root/drivers/block/swim.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_swim_mode
  2. get_swim_mode
  3. swim_select
  4. swim_action
  5. swim_readbit
  6. swim_drive
  7. swim_motor
  8. swim_eject
  9. swim_head
  10. swim_step
  11. swim_track00
  12. swim_seek
  13. swim_track
  14. floppy_eject
  15. swim_read_sector
  16. floppy_read_sectors
  17. swim_queue_rq
  18. get_floppy_geometry
  19. setup_medium
  20. floppy_open
  21. floppy_unlocked_open
  22. floppy_release
  23. floppy_ioctl
  24. floppy_getgeo
  25. floppy_check_events
  26. floppy_revalidate
  27. floppy_find
  28. swim_add_floppy
  29. swim_floppy_init
  30. swim_probe
  31. swim_remove
  32. swim_init
  33. swim_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Driver for SWIM (Sander Woz Integrated Machine) floppy controller
   4  *
   5  * Copyright (C) 2004,2008 Laurent Vivier <Laurent@lvivier.info>
   6  *
   7  * based on Alastair Bridgewater SWIM analysis, 2001
   8  * based on SWIM3 driver (c) Paul Mackerras, 1996
   9  * based on netBSD IWM driver (c) 1997, 1998 Hauke Fath.
  10  *
  11  * 2004-08-21 (lv) - Initial implementation
  12  * 2008-10-30 (lv) - Port to 2.6
  13  */
  14 
  15 #include <linux/module.h>
  16 #include <linux/fd.h>
  17 #include <linux/slab.h>
  18 #include <linux/blk-mq.h>
  19 #include <linux/mutex.h>
  20 #include <linux/hdreg.h>
  21 #include <linux/kernel.h>
  22 #include <linux/delay.h>
  23 #include <linux/platform_device.h>
  24 
  25 #include <asm/mac_via.h>
  26 
  27 #define CARDNAME "swim"
  28 
  29 struct sector_header {
  30         unsigned char side;
  31         unsigned char track;
  32         unsigned char sector;
  33         unsigned char size;
  34         unsigned char crc0;
  35         unsigned char crc1;
  36 } __attribute__((packed));
  37 
  38 #define DRIVER_VERSION "Version 0.2 (2008-10-30)"
  39 
  40 #define REG(x)  unsigned char x, x ## _pad[0x200 - 1];
  41 
  42 struct swim {
  43         REG(write_data)
  44         REG(write_mark)
  45         REG(write_CRC)
  46         REG(write_parameter)
  47         REG(write_phase)
  48         REG(write_setup)
  49         REG(write_mode0)
  50         REG(write_mode1)
  51 
  52         REG(read_data)
  53         REG(read_mark)
  54         REG(read_error)
  55         REG(read_parameter)
  56         REG(read_phase)
  57         REG(read_setup)
  58         REG(read_status)
  59         REG(read_handshake)
  60 } __attribute__((packed));
  61 
  62 #define swim_write(base, reg, v)        out_8(&(base)->write_##reg, (v))
  63 #define swim_read(base, reg)            in_8(&(base)->read_##reg)
  64 
  65 /* IWM registers */
  66 
  67 struct iwm {
  68         REG(ph0L)
  69         REG(ph0H)
  70         REG(ph1L)
  71         REG(ph1H)
  72         REG(ph2L)
  73         REG(ph2H)
  74         REG(ph3L)
  75         REG(ph3H)
  76         REG(mtrOff)
  77         REG(mtrOn)
  78         REG(intDrive)
  79         REG(extDrive)
  80         REG(q6L)
  81         REG(q6H)
  82         REG(q7L)
  83         REG(q7H)
  84 } __attribute__((packed));
  85 
  86 #define iwm_write(base, reg, v)         out_8(&(base)->reg, (v))
  87 #define iwm_read(base, reg)             in_8(&(base)->reg)
  88 
  89 /* bits in phase register */
  90 
  91 #define SEEK_POSITIVE   0x070
  92 #define SEEK_NEGATIVE   0x074
  93 #define STEP            0x071
  94 #define MOTOR_ON        0x072
  95 #define MOTOR_OFF       0x076
  96 #define INDEX           0x073
  97 #define EJECT           0x077
  98 #define SETMFM          0x171
  99 #define SETGCR          0x175
 100 
 101 #define RELAX           0x033
 102 #define LSTRB           0x008
 103 
 104 #define CA_MASK         0x077
 105 
 106 /* Select values for swim_select and swim_readbit */
 107 
 108 #define READ_DATA_0     0x074
 109 #define ONEMEG_DRIVE    0x075
 110 #define SINGLE_SIDED    0x076
 111 #define DRIVE_PRESENT   0x077
 112 #define DISK_IN         0x170
 113 #define WRITE_PROT      0x171
 114 #define TRACK_ZERO      0x172
 115 #define TACHO           0x173
 116 #define READ_DATA_1     0x174
 117 #define GCR_MODE        0x175
 118 #define SEEK_COMPLETE   0x176
 119 #define TWOMEG_MEDIA    0x177
 120 
 121 /* Bits in handshake register */
 122 
 123 #define MARK_BYTE       0x01
 124 #define CRC_ZERO        0x02
 125 #define RDDATA          0x04
 126 #define SENSE           0x08
 127 #define MOTEN           0x10
 128 #define ERROR           0x20
 129 #define DAT2BYTE        0x40
 130 #define DAT1BYTE        0x80
 131 
 132 /* bits in setup register */
 133 
 134 #define S_INV_WDATA     0x01
 135 #define S_3_5_SELECT    0x02
 136 #define S_GCR           0x04
 137 #define S_FCLK_DIV2     0x08
 138 #define S_ERROR_CORR    0x10
 139 #define S_IBM_DRIVE     0x20
 140 #define S_GCR_WRITE     0x40
 141 #define S_TIMEOUT       0x80
 142 
 143 /* bits in mode register */
 144 
 145 #define CLFIFO          0x01
 146 #define ENBL1           0x02
 147 #define ENBL2           0x04
 148 #define ACTION          0x08
 149 #define WRITE_MODE      0x10
 150 #define HEDSEL          0x20
 151 #define MOTON           0x80
 152 
 153 /*----------------------------------------------------------------------------*/
 154 
 155 enum drive_location {
 156         INTERNAL_DRIVE = 0x02,
 157         EXTERNAL_DRIVE = 0x04,
 158 };
 159 
 160 enum media_type {
 161         DD_MEDIA,
 162         HD_MEDIA,
 163 };
 164 
 165 struct floppy_state {
 166 
 167         /* physical properties */
 168 
 169         enum drive_location location;   /* internal or external drive */
 170         int              head_number;   /* single- or double-sided drive */
 171 
 172         /* media */
 173 
 174         int              disk_in;
 175         int              ejected;
 176         enum media_type  type;
 177         int              write_protected;
 178 
 179         int              total_secs;
 180         int              secpercyl;
 181         int              secpertrack;
 182 
 183         /* in-use information */
 184 
 185         int             track;
 186         int             ref_count;
 187 
 188         struct gendisk *disk;
 189         struct blk_mq_tag_set tag_set;
 190 
 191         /* parent controller */
 192 
 193         struct swim_priv *swd;
 194 };
 195 
 196 enum motor_action {
 197         OFF,
 198         ON,
 199 };
 200 
 201 enum head {
 202         LOWER_HEAD = 0,
 203         UPPER_HEAD = 1,
 204 };
 205 
 206 #define FD_MAX_UNIT     2
 207 
 208 struct swim_priv {
 209         struct swim __iomem *base;
 210         spinlock_t lock;
 211         int floppy_count;
 212         struct floppy_state unit[FD_MAX_UNIT];
 213 };
 214 
 215 extern int swim_read_sector_header(struct swim __iomem *base,
 216                                    struct sector_header *header);
 217 extern int swim_read_sector_data(struct swim __iomem *base,
 218                                  unsigned char *data);
 219 
 220 static DEFINE_MUTEX(swim_mutex);
 221 static inline void set_swim_mode(struct swim __iomem *base, int enable)
 222 {
 223         struct iwm __iomem *iwm_base;
 224         unsigned long flags;
 225 
 226         if (!enable) {
 227                 swim_write(base, mode0, 0xf8);
 228                 return;
 229         }
 230 
 231         iwm_base = (struct iwm __iomem *)base;
 232         local_irq_save(flags);
 233 
 234         iwm_read(iwm_base, q7L);
 235         iwm_read(iwm_base, mtrOff);
 236         iwm_read(iwm_base, q6H);
 237 
 238         iwm_write(iwm_base, q7H, 0x57);
 239         iwm_write(iwm_base, q7H, 0x17);
 240         iwm_write(iwm_base, q7H, 0x57);
 241         iwm_write(iwm_base, q7H, 0x57);
 242 
 243         local_irq_restore(flags);
 244 }
 245 
 246 static inline int get_swim_mode(struct swim __iomem *base)
 247 {
 248         unsigned long flags;
 249 
 250         local_irq_save(flags);
 251 
 252         swim_write(base, phase, 0xf5);
 253         if (swim_read(base, phase) != 0xf5)
 254                 goto is_iwm;
 255         swim_write(base, phase, 0xf6);
 256         if (swim_read(base, phase) != 0xf6)
 257                 goto is_iwm;
 258         swim_write(base, phase, 0xf7);
 259         if (swim_read(base, phase) != 0xf7)
 260                 goto is_iwm;
 261         local_irq_restore(flags);
 262         return 1;
 263 is_iwm:
 264         local_irq_restore(flags);
 265         return 0;
 266 }
 267 
 268 static inline void swim_select(struct swim __iomem *base, int sel)
 269 {
 270         swim_write(base, phase, RELAX);
 271 
 272         via1_set_head(sel & 0x100);
 273 
 274         swim_write(base, phase, sel & CA_MASK);
 275 }
 276 
 277 static inline void swim_action(struct swim __iomem *base, int action)
 278 {
 279         unsigned long flags;
 280 
 281         local_irq_save(flags);
 282 
 283         swim_select(base, action);
 284         udelay(1);
 285         swim_write(base, phase, (LSTRB<<4) | LSTRB);
 286         udelay(1);
 287         swim_write(base, phase, (LSTRB<<4) | ((~LSTRB) & 0x0F));
 288         udelay(1);
 289 
 290         local_irq_restore(flags);
 291 }
 292 
 293 static inline int swim_readbit(struct swim __iomem *base, int bit)
 294 {
 295         int stat;
 296 
 297         swim_select(base, bit);
 298 
 299         udelay(10);
 300 
 301         stat = swim_read(base, handshake);
 302 
 303         return (stat & SENSE) == 0;
 304 }
 305 
 306 static inline void swim_drive(struct swim __iomem *base,
 307                               enum drive_location location)
 308 {
 309         if (location == INTERNAL_DRIVE) {
 310                 swim_write(base, mode0, EXTERNAL_DRIVE); /* clear drive 1 bit */
 311                 swim_write(base, mode1, INTERNAL_DRIVE); /* set drive 0 bit */
 312         } else if (location == EXTERNAL_DRIVE) {
 313                 swim_write(base, mode0, INTERNAL_DRIVE); /* clear drive 0 bit */
 314                 swim_write(base, mode1, EXTERNAL_DRIVE); /* set drive 1 bit */
 315         }
 316 }
 317 
 318 static inline void swim_motor(struct swim __iomem *base,
 319                               enum motor_action action)
 320 {
 321         if (action == ON) {
 322                 int i;
 323 
 324                 swim_action(base, MOTOR_ON);
 325 
 326                 for (i = 0; i < 2*HZ; i++) {
 327                         swim_select(base, RELAX);
 328                         if (swim_readbit(base, MOTOR_ON))
 329                                 break;
 330                         current->state = TASK_INTERRUPTIBLE;
 331                         schedule_timeout(1);
 332                 }
 333         } else if (action == OFF) {
 334                 swim_action(base, MOTOR_OFF);
 335                 swim_select(base, RELAX);
 336         }
 337 }
 338 
 339 static inline void swim_eject(struct swim __iomem *base)
 340 {
 341         int i;
 342 
 343         swim_action(base, EJECT);
 344 
 345         for (i = 0; i < 2*HZ; i++) {
 346                 swim_select(base, RELAX);
 347                 if (!swim_readbit(base, DISK_IN))
 348                         break;
 349                 current->state = TASK_INTERRUPTIBLE;
 350                 schedule_timeout(1);
 351         }
 352         swim_select(base, RELAX);
 353 }
 354 
 355 static inline void swim_head(struct swim __iomem *base, enum head head)
 356 {
 357         /* wait drive is ready */
 358 
 359         if (head == UPPER_HEAD)
 360                 swim_select(base, READ_DATA_1);
 361         else if (head == LOWER_HEAD)
 362                 swim_select(base, READ_DATA_0);
 363 }
 364 
 365 static inline int swim_step(struct swim __iomem *base)
 366 {
 367         int wait;
 368 
 369         swim_action(base, STEP);
 370 
 371         for (wait = 0; wait < HZ; wait++) {
 372 
 373                 current->state = TASK_INTERRUPTIBLE;
 374                 schedule_timeout(1);
 375 
 376                 swim_select(base, RELAX);
 377                 if (!swim_readbit(base, STEP))
 378                         return 0;
 379         }
 380         return -1;
 381 }
 382 
 383 static inline int swim_track00(struct swim __iomem *base)
 384 {
 385         int try;
 386 
 387         swim_action(base, SEEK_NEGATIVE);
 388 
 389         for (try = 0; try < 100; try++) {
 390 
 391                 swim_select(base, RELAX);
 392                 if (swim_readbit(base, TRACK_ZERO))
 393                         break;
 394 
 395                 if (swim_step(base))
 396                         return -1;
 397         }
 398 
 399         if (swim_readbit(base, TRACK_ZERO))
 400                 return 0;
 401 
 402         return -1;
 403 }
 404 
 405 static inline int swim_seek(struct swim __iomem *base, int step)
 406 {
 407         if (step == 0)
 408                 return 0;
 409 
 410         if (step < 0) {
 411                 swim_action(base, SEEK_NEGATIVE);
 412                 step = -step;
 413         } else
 414                 swim_action(base, SEEK_POSITIVE);
 415 
 416         for ( ; step > 0; step--) {
 417                 if (swim_step(base))
 418                         return -1;
 419         }
 420 
 421         return 0;
 422 }
 423 
 424 static inline int swim_track(struct floppy_state *fs,  int track)
 425 {
 426         struct swim __iomem *base = fs->swd->base;
 427         int ret;
 428 
 429         ret = swim_seek(base, track - fs->track);
 430 
 431         if (ret == 0)
 432                 fs->track = track;
 433         else {
 434                 swim_track00(base);
 435                 fs->track = 0;
 436         }
 437 
 438         return ret;
 439 }
 440 
 441 static int floppy_eject(struct floppy_state *fs)
 442 {
 443         struct swim __iomem *base = fs->swd->base;
 444 
 445         swim_drive(base, fs->location);
 446         swim_motor(base, OFF);
 447         swim_eject(base);
 448 
 449         fs->disk_in = 0;
 450         fs->ejected = 1;
 451 
 452         return 0;
 453 }
 454 
 455 static inline int swim_read_sector(struct floppy_state *fs,
 456                                    int side, int track,
 457                                    int sector, unsigned char *buffer)
 458 {
 459         struct swim __iomem *base = fs->swd->base;
 460         unsigned long flags;
 461         struct sector_header header;
 462         int ret = -1;
 463         short i;
 464 
 465         swim_track(fs, track);
 466 
 467         swim_write(base, mode1, MOTON);
 468         swim_head(base, side);
 469         swim_write(base, mode0, side);
 470 
 471         local_irq_save(flags);
 472         for (i = 0; i < 36; i++) {
 473                 ret = swim_read_sector_header(base, &header);
 474                 if (!ret && (header.sector == sector)) {
 475                         /* found */
 476 
 477                         ret = swim_read_sector_data(base, buffer);
 478                         break;
 479                 }
 480         }
 481         local_irq_restore(flags);
 482 
 483         swim_write(base, mode0, MOTON);
 484 
 485         if ((header.side != side)  || (header.track != track) ||
 486              (header.sector != sector))
 487                 return 0;
 488 
 489         return ret;
 490 }
 491 
 492 static blk_status_t floppy_read_sectors(struct floppy_state *fs,
 493                                int req_sector, int sectors_nb,
 494                                unsigned char *buffer)
 495 {
 496         struct swim __iomem *base = fs->swd->base;
 497         int ret;
 498         int side, track, sector;
 499         int i, try;
 500 
 501 
 502         swim_drive(base, fs->location);
 503         for (i = req_sector; i < req_sector + sectors_nb; i++) {
 504                 int x;
 505                 track = i / fs->secpercyl;
 506                 x = i % fs->secpercyl;
 507                 side = x / fs->secpertrack;
 508                 sector = x % fs->secpertrack + 1;
 509 
 510                 try = 5;
 511                 do {
 512                         ret = swim_read_sector(fs, side, track, sector,
 513                                                 buffer);
 514                         if (try-- == 0)
 515                                 return BLK_STS_IOERR;
 516                 } while (ret != 512);
 517 
 518                 buffer += ret;
 519         }
 520 
 521         return 0;
 522 }
 523 
 524 static blk_status_t swim_queue_rq(struct blk_mq_hw_ctx *hctx,
 525                                   const struct blk_mq_queue_data *bd)
 526 {
 527         struct floppy_state *fs = hctx->queue->queuedata;
 528         struct swim_priv *swd = fs->swd;
 529         struct request *req = bd->rq;
 530         blk_status_t err;
 531 
 532         if (!spin_trylock_irq(&swd->lock))
 533                 return BLK_STS_DEV_RESOURCE;
 534 
 535         blk_mq_start_request(req);
 536 
 537         if (!fs->disk_in || rq_data_dir(req) == WRITE) {
 538                 err = BLK_STS_IOERR;
 539                 goto out;
 540         }
 541 
 542         do {
 543                 err = floppy_read_sectors(fs, blk_rq_pos(req),
 544                                           blk_rq_cur_sectors(req),
 545                                           bio_data(req->bio));
 546         } while (blk_update_request(req, err, blk_rq_cur_bytes(req)));
 547         __blk_mq_end_request(req, err);
 548 
 549         err = BLK_STS_OK;
 550 out:
 551         spin_unlock_irq(&swd->lock);
 552         return err;
 553 
 554 }
 555 
 556 static struct floppy_struct floppy_type[4] = {
 557         {    0,  0, 0,  0, 0, 0x00, 0x00, 0x00, 0x00, NULL }, /* no testing   */
 558         {  720,  9, 1, 80, 0, 0x2A, 0x02, 0xDF, 0x50, NULL }, /* 360KB SS 3.5"*/
 559         { 1440,  9, 2, 80, 0, 0x2A, 0x02, 0xDF, 0x50, NULL }, /* 720KB 3.5"   */
 560         { 2880, 18, 2, 80, 0, 0x1B, 0x00, 0xCF, 0x6C, NULL }, /* 1.44MB 3.5"  */
 561 };
 562 
 563 static int get_floppy_geometry(struct floppy_state *fs, int type,
 564                                struct floppy_struct **g)
 565 {
 566         if (type >= ARRAY_SIZE(floppy_type))
 567                 return -EINVAL;
 568 
 569         if (type)
 570                 *g = &floppy_type[type];
 571         else if (fs->type == HD_MEDIA) /* High-Density media */
 572                 *g = &floppy_type[3];
 573         else if (fs->head_number == 2) /* double-sided */
 574                 *g = &floppy_type[2];
 575         else
 576                 *g = &floppy_type[1];
 577 
 578         return 0;
 579 }
 580 
 581 static void setup_medium(struct floppy_state *fs)
 582 {
 583         struct swim __iomem *base = fs->swd->base;
 584 
 585         if (swim_readbit(base, DISK_IN)) {
 586                 struct floppy_struct *g;
 587                 fs->disk_in = 1;
 588                 fs->write_protected = swim_readbit(base, WRITE_PROT);
 589 
 590                 if (swim_track00(base))
 591                         printk(KERN_ERR
 592                                 "SWIM: cannot move floppy head to track 0\n");
 593 
 594                 swim_track00(base);
 595 
 596                 fs->type = swim_readbit(base, TWOMEG_MEDIA) ?
 597                         HD_MEDIA : DD_MEDIA;
 598                 fs->head_number = swim_readbit(base, SINGLE_SIDED) ? 1 : 2;
 599                 get_floppy_geometry(fs, 0, &g);
 600                 fs->total_secs = g->size;
 601                 fs->secpercyl = g->head * g->sect;
 602                 fs->secpertrack = g->sect;
 603                 fs->track = 0;
 604         } else {
 605                 fs->disk_in = 0;
 606         }
 607 }
 608 
 609 static int floppy_open(struct block_device *bdev, fmode_t mode)
 610 {
 611         struct floppy_state *fs = bdev->bd_disk->private_data;
 612         struct swim __iomem *base = fs->swd->base;
 613         int err;
 614 
 615         if (fs->ref_count == -1 || (fs->ref_count && mode & FMODE_EXCL))
 616                 return -EBUSY;
 617 
 618         if (mode & FMODE_EXCL)
 619                 fs->ref_count = -1;
 620         else
 621                 fs->ref_count++;
 622 
 623         swim_write(base, setup, S_IBM_DRIVE  | S_FCLK_DIV2);
 624         udelay(10);
 625         swim_drive(base, fs->location);
 626         swim_motor(base, ON);
 627         swim_action(base, SETMFM);
 628         if (fs->ejected)
 629                 setup_medium(fs);
 630         if (!fs->disk_in) {
 631                 err = -ENXIO;
 632                 goto out;
 633         }
 634 
 635         set_capacity(fs->disk, fs->total_secs);
 636 
 637         if (mode & FMODE_NDELAY)
 638                 return 0;
 639 
 640         if (mode & (FMODE_READ|FMODE_WRITE)) {
 641                 check_disk_change(bdev);
 642                 if ((mode & FMODE_WRITE) && fs->write_protected) {
 643                         err = -EROFS;
 644                         goto out;
 645                 }
 646         }
 647         return 0;
 648 out:
 649         if (fs->ref_count < 0)
 650                 fs->ref_count = 0;
 651         else if (fs->ref_count > 0)
 652                 --fs->ref_count;
 653 
 654         if (fs->ref_count == 0)
 655                 swim_motor(base, OFF);
 656         return err;
 657 }
 658 
 659 static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
 660 {
 661         int ret;
 662 
 663         mutex_lock(&swim_mutex);
 664         ret = floppy_open(bdev, mode);
 665         mutex_unlock(&swim_mutex);
 666 
 667         return ret;
 668 }
 669 
 670 static void floppy_release(struct gendisk *disk, fmode_t mode)
 671 {
 672         struct floppy_state *fs = disk->private_data;
 673         struct swim __iomem *base = fs->swd->base;
 674 
 675         mutex_lock(&swim_mutex);
 676         if (fs->ref_count < 0)
 677                 fs->ref_count = 0;
 678         else if (fs->ref_count > 0)
 679                 --fs->ref_count;
 680 
 681         if (fs->ref_count == 0)
 682                 swim_motor(base, OFF);
 683         mutex_unlock(&swim_mutex);
 684 }
 685 
 686 static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
 687                         unsigned int cmd, unsigned long param)
 688 {
 689         struct floppy_state *fs = bdev->bd_disk->private_data;
 690         int err;
 691 
 692         if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
 693                         return -EPERM;
 694 
 695         switch (cmd) {
 696         case FDEJECT:
 697                 if (fs->ref_count != 1)
 698                         return -EBUSY;
 699                 mutex_lock(&swim_mutex);
 700                 err = floppy_eject(fs);
 701                 mutex_unlock(&swim_mutex);
 702                 return err;
 703 
 704         case FDGETPRM:
 705                 if (copy_to_user((void __user *) param, (void *) &floppy_type,
 706                                  sizeof(struct floppy_struct)))
 707                         return -EFAULT;
 708                 return 0;
 709         }
 710         return -ENOTTY;
 711 }
 712 
 713 static int floppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 714 {
 715         struct floppy_state *fs = bdev->bd_disk->private_data;
 716         struct floppy_struct *g;
 717         int ret;
 718 
 719         ret = get_floppy_geometry(fs, 0, &g);
 720         if (ret)
 721                 return ret;
 722 
 723         geo->heads = g->head;
 724         geo->sectors = g->sect;
 725         geo->cylinders = g->track;
 726 
 727         return 0;
 728 }
 729 
 730 static unsigned int floppy_check_events(struct gendisk *disk,
 731                                         unsigned int clearing)
 732 {
 733         struct floppy_state *fs = disk->private_data;
 734 
 735         return fs->ejected ? DISK_EVENT_MEDIA_CHANGE : 0;
 736 }
 737 
 738 static int floppy_revalidate(struct gendisk *disk)
 739 {
 740         struct floppy_state *fs = disk->private_data;
 741         struct swim __iomem *base = fs->swd->base;
 742 
 743         swim_drive(base, fs->location);
 744 
 745         if (fs->ejected)
 746                 setup_medium(fs);
 747 
 748         if (!fs->disk_in)
 749                 swim_motor(base, OFF);
 750         else
 751                 fs->ejected = 0;
 752 
 753         return !fs->disk_in;
 754 }
 755 
 756 static const struct block_device_operations floppy_fops = {
 757         .owner           = THIS_MODULE,
 758         .open            = floppy_unlocked_open,
 759         .release         = floppy_release,
 760         .ioctl           = floppy_ioctl,
 761         .getgeo          = floppy_getgeo,
 762         .check_events    = floppy_check_events,
 763         .revalidate_disk = floppy_revalidate,
 764 };
 765 
 766 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 767 {
 768         struct swim_priv *swd = data;
 769         int drive = (*part & 3);
 770 
 771         if (drive >= swd->floppy_count)
 772                 return NULL;
 773 
 774         *part = 0;
 775         return get_disk_and_module(swd->unit[drive].disk);
 776 }
 777 
 778 static int swim_add_floppy(struct swim_priv *swd, enum drive_location location)
 779 {
 780         struct floppy_state *fs = &swd->unit[swd->floppy_count];
 781         struct swim __iomem *base = swd->base;
 782 
 783         fs->location = location;
 784 
 785         swim_drive(base, location);
 786 
 787         swim_motor(base, OFF);
 788 
 789         fs->type = HD_MEDIA;
 790         fs->head_number = 2;
 791 
 792         fs->ref_count = 0;
 793         fs->ejected = 1;
 794 
 795         swd->floppy_count++;
 796 
 797         return 0;
 798 }
 799 
 800 static const struct blk_mq_ops swim_mq_ops = {
 801         .queue_rq = swim_queue_rq,
 802 };
 803 
 804 static int swim_floppy_init(struct swim_priv *swd)
 805 {
 806         int err;
 807         int drive;
 808         struct swim __iomem *base = swd->base;
 809 
 810         /* scan floppy drives */
 811 
 812         swim_drive(base, INTERNAL_DRIVE);
 813         if (swim_readbit(base, DRIVE_PRESENT) &&
 814             !swim_readbit(base, ONEMEG_DRIVE))
 815                 swim_add_floppy(swd, INTERNAL_DRIVE);
 816         swim_drive(base, EXTERNAL_DRIVE);
 817         if (swim_readbit(base, DRIVE_PRESENT) &&
 818             !swim_readbit(base, ONEMEG_DRIVE))
 819                 swim_add_floppy(swd, EXTERNAL_DRIVE);
 820 
 821         /* register floppy drives */
 822 
 823         err = register_blkdev(FLOPPY_MAJOR, "fd");
 824         if (err) {
 825                 printk(KERN_ERR "Unable to get major %d for SWIM floppy\n",
 826                        FLOPPY_MAJOR);
 827                 return -EBUSY;
 828         }
 829 
 830         spin_lock_init(&swd->lock);
 831 
 832         for (drive = 0; drive < swd->floppy_count; drive++) {
 833                 struct request_queue *q;
 834 
 835                 swd->unit[drive].disk = alloc_disk(1);
 836                 if (swd->unit[drive].disk == NULL) {
 837                         err = -ENOMEM;
 838                         goto exit_put_disks;
 839                 }
 840 
 841                 q = blk_mq_init_sq_queue(&swd->unit[drive].tag_set, &swim_mq_ops,
 842                                                 2, BLK_MQ_F_SHOULD_MERGE);
 843                 if (IS_ERR(q)) {
 844                         err = PTR_ERR(q);
 845                         goto exit_put_disks;
 846                 }
 847 
 848                 swd->unit[drive].disk->queue = q;
 849                 blk_queue_bounce_limit(swd->unit[drive].disk->queue,
 850                                 BLK_BOUNCE_HIGH);
 851                 swd->unit[drive].disk->queue->queuedata = &swd->unit[drive];
 852                 swd->unit[drive].swd = swd;
 853         }
 854 
 855         for (drive = 0; drive < swd->floppy_count; drive++) {
 856                 swd->unit[drive].disk->flags = GENHD_FL_REMOVABLE;
 857                 swd->unit[drive].disk->major = FLOPPY_MAJOR;
 858                 swd->unit[drive].disk->first_minor = drive;
 859                 sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive);
 860                 swd->unit[drive].disk->fops = &floppy_fops;
 861                 swd->unit[drive].disk->events = DISK_EVENT_MEDIA_CHANGE;
 862                 swd->unit[drive].disk->private_data = &swd->unit[drive];
 863                 set_capacity(swd->unit[drive].disk, 2880);
 864                 add_disk(swd->unit[drive].disk);
 865         }
 866 
 867         blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
 868                             floppy_find, NULL, swd);
 869 
 870         return 0;
 871 
 872 exit_put_disks:
 873         unregister_blkdev(FLOPPY_MAJOR, "fd");
 874         do {
 875                 struct gendisk *disk = swd->unit[drive].disk;
 876 
 877                 if (disk) {
 878                         if (disk->queue) {
 879                                 blk_cleanup_queue(disk->queue);
 880                                 disk->queue = NULL;
 881                         }
 882                         blk_mq_free_tag_set(&swd->unit[drive].tag_set);
 883                         put_disk(disk);
 884                 }
 885         } while (drive--);
 886         return err;
 887 }
 888 
 889 static int swim_probe(struct platform_device *dev)
 890 {
 891         struct resource *res;
 892         struct swim __iomem *swim_base;
 893         struct swim_priv *swd;
 894         int ret;
 895 
 896         res = platform_get_resource(dev, IORESOURCE_MEM, 0);
 897         if (!res) {
 898                 ret = -ENODEV;
 899                 goto out;
 900         }
 901 
 902         if (!request_mem_region(res->start, resource_size(res), CARDNAME)) {
 903                 ret = -EBUSY;
 904                 goto out;
 905         }
 906 
 907         swim_base = (struct swim __iomem *)res->start;
 908         if (!swim_base) {
 909                 ret = -ENOMEM;
 910                 goto out_release_io;
 911         }
 912 
 913         /* probe device */
 914 
 915         set_swim_mode(swim_base, 1);
 916         if (!get_swim_mode(swim_base)) {
 917                 printk(KERN_INFO "SWIM device not found !\n");
 918                 ret = -ENODEV;
 919                 goto out_release_io;
 920         }
 921 
 922         /* set platform driver data */
 923 
 924         swd = kzalloc(sizeof(struct swim_priv), GFP_KERNEL);
 925         if (!swd) {
 926                 ret = -ENOMEM;
 927                 goto out_release_io;
 928         }
 929         platform_set_drvdata(dev, swd);
 930 
 931         swd->base = swim_base;
 932 
 933         ret = swim_floppy_init(swd);
 934         if (ret)
 935                 goto out_kfree;
 936 
 937         return 0;
 938 
 939 out_kfree:
 940         kfree(swd);
 941 out_release_io:
 942         release_mem_region(res->start, resource_size(res));
 943 out:
 944         return ret;
 945 }
 946 
 947 static int swim_remove(struct platform_device *dev)
 948 {
 949         struct swim_priv *swd = platform_get_drvdata(dev);
 950         int drive;
 951         struct resource *res;
 952 
 953         blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
 954 
 955         for (drive = 0; drive < swd->floppy_count; drive++) {
 956                 del_gendisk(swd->unit[drive].disk);
 957                 blk_cleanup_queue(swd->unit[drive].disk->queue);
 958                 blk_mq_free_tag_set(&swd->unit[drive].tag_set);
 959                 put_disk(swd->unit[drive].disk);
 960         }
 961 
 962         unregister_blkdev(FLOPPY_MAJOR, "fd");
 963 
 964         /* eject floppies */
 965 
 966         for (drive = 0; drive < swd->floppy_count; drive++)
 967                 floppy_eject(&swd->unit[drive]);
 968 
 969         res = platform_get_resource(dev, IORESOURCE_MEM, 0);
 970         if (res)
 971                 release_mem_region(res->start, resource_size(res));
 972 
 973         kfree(swd);
 974 
 975         return 0;
 976 }
 977 
 978 static struct platform_driver swim_driver = {
 979         .probe  = swim_probe,
 980         .remove = swim_remove,
 981         .driver   = {
 982                 .name   = CARDNAME,
 983         },
 984 };
 985 
 986 static int __init swim_init(void)
 987 {
 988         printk(KERN_INFO "SWIM floppy driver %s\n", DRIVER_VERSION);
 989 
 990         return platform_driver_register(&swim_driver);
 991 }
 992 module_init(swim_init);
 993 
 994 static void __exit swim_exit(void)
 995 {
 996         platform_driver_unregister(&swim_driver);
 997 }
 998 module_exit(swim_exit);
 999 
1000 MODULE_DESCRIPTION("Driver for SWIM floppy controller");
1001 MODULE_LICENSE("GPL");
1002 MODULE_AUTHOR("Laurent Vivier <laurent@lvivier.info>");
1003 MODULE_ALIAS_BLOCKDEV_MAJOR(FLOPPY_MAJOR);

/* [<][>][^][v][top][bottom][index][help] */