--- linux246-orig/drivers/ide/ide-floppy.c Fri Feb 9 20:30:23 2001 +++ linux/drivers/ide/ide-floppy.c Sat Jul 14 12:07:40 2001 @@ -1,7 +1,8 @@ /* - * linux/drivers/ide/ide-floppy.c Version 0.9 Jul 4, 1999 + * linux/drivers/ide/ide-floppy.c Version 0.96 Jan 7, 2001 * * Copyright (C) 1996 - 1999 Gadi Oxman + * Copyright (C) 2000 - 2001 Paul Bristow */ /* @@ -10,6 +11,12 @@ * The driver currently doesn't have any fancy features, just the bare * minimum read/write support. * + * This driver supports the following IDE floppy drives: + * + * LS-120 SuperDisk + * Iomega Zip 100/250 + * Iomega PC Card Clik!/PocketZip + * * Many thanks to Lode Leroy , who tested so many * ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive. * @@ -29,9 +36,20 @@ * Ver 0.9 Jul 4 99 Fix a bug which might have caused the number of * bytes requested on each interrupt to be zero. * Thanks to for pointing this out. + * Ver 0.91 Dec 11 99 Added IOMEGA Clik! drive support by + * + * Ver 0.92 Oct 22 00 Paul Bristow became official maintainer for this + * driver. Included Powerbook internal zip kludge. + * Ver 0.93 Oct 24 00 Fixed bugs for Clik! drive + * no disk on insert and disk change now works + * Ver 0.94 Oct 27 00 Tidied up to remove strstr(Clik) everywhere + * Ver 0.95 Nov 7 00 Brought across to kernel 2.4 + * Ver 0.96 Jan 7 01 Actually in line with release version of 2.4.0 + * including set_bit patch from Rusty Russel + * */ -#define IDEFLOPPY_VERSION "0.9" +#define IDEFLOPPY_VERSION "0.96" #include #include @@ -45,7 +63,7 @@ #include #include #include -#include +#include #include #include @@ -56,12 +74,14 @@ #include #include + /* * The following are used to debug the driver. */ -#define IDEFLOPPY_DEBUG_LOG 0 #define IDEFLOPPY_DEBUG_INFO 0 #define IDEFLOPPY_DEBUG_BUGS 1 +/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */ +#define IDEFLOPPY_DEBUG( fmt, args... ) /* * Some drives require a longer irq timeout. @@ -104,7 +124,7 @@ byte *current_position; /* Pointer into the above buffer */ void (*callback) (ide_drive_t *); /* Called when this packet command is completed */ byte pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE]; /* Temporary buffer */ - unsigned long flags; /* Status/Action bit flags: long for set_bit */ + unsigned long flags; /* Status/Action bit flags : long for set_bit() */ } idefloppy_pc_t; /* @@ -181,6 +201,7 @@ u8 reserved30[2]; } idefloppy_flexible_disk_page_t; + /* * Format capacity */ @@ -237,7 +258,7 @@ idefloppy_flexible_disk_page_t flexible_disk_page; /* Copy of the flexible disk page */ int wp; /* Write protect */ - unsigned int flags; /* Status/Action flags */ + unsigned long flags; /* Status/Action flags : long for set_bit() */ } idefloppy_floppy_t; /* @@ -246,6 +267,8 @@ #define IDEFLOPPY_DRQ_INTERRUPT 0 /* DRQ interrupt device */ #define IDEFLOPPY_MEDIA_CHANGED 1 /* Media may have changed */ #define IDEFLOPPY_USE_READ12 2 /* Use READ12/WRITE12 or READ10/WRITE10 */ +#define IDEFLOPPY_CLIK_DRIVE 3 /* Avoid commands not supported in Clik drive */ +#define IDEFLOPPY_POWERBOOK_ZIP 4 /* Kludge for Apple Powerbook Zip drive */ /* * ATAPI floppy drive packet commands @@ -621,9 +644,7 @@ struct request *rq = hwgroup->rq; int error; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_end_request\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "Reached idefloppy_end_request\n"); switch (uptodate) { case 0: error = IDEFLOPPY_ERROR_GENERAL; break; @@ -746,21 +767,19 @@ idefloppy_floppy_t *floppy = drive->driver_data; floppy->sense_key = result->sense_key; floppy->asc = result->asc; floppy->ascq = result->ascq; -#if IDEFLOPPY_DEBUG_LOG - if (floppy->failed_pc) - printk (KERN_INFO "ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq); - else - printk (KERN_INFO "ide-floppy: sense key = %x, asc = %x, ascq = %x\n",result->sense_key,result->asc,result->ascq); -#endif /* IDEFLOPPY_DEBUG_LOG */ + if (floppy->failed_pc) { + IDEFLOPPY_DEBUG("ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq); + } + else { + IDEFLOPPY_DEBUG("ide-floppy: sense key = %x, asc = %x, ascq = %x\n",result->sense_key,result->asc,result->ascq); + } } static void idefloppy_request_sense_callback (ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_request_sense_callback\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_request_sense_callback\n"); if (!floppy->pc->error) { idefloppy_analyze_error (drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer); idefloppy_end_request (1,HWGROUP (drive)); @@ -777,9 +796,7 @@ { idefloppy_floppy_t *floppy = drive->driver_data; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_callback\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_pc_callback\n"); idefloppy_end_request (floppy->pc->error ? 0:1, HWGROUP(drive)); } @@ -840,9 +857,7 @@ struct request *rq = pc->rq; unsigned int temp; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n"); #ifdef CONFIG_BLK_DEV_IDEDMA if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { @@ -852,26 +867,20 @@ pc->actually_transferred=pc->request_transfer; idefloppy_update_buffers (drive, pc); } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: DMA finished\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: DMA finished\n"); } #endif /* CONFIG_BLK_DEV_IDEDMA */ status.all = GET_STAT(); /* Clear the interrupt */ if (!status.b.drq) { /* No more interrupts */ -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "Packet command completed, %d bytes transferred\n", pc->actually_transferred); clear_bit (PC_DMA_IN_PROGRESS, &pc->flags); ide__sti(); /* local CPU only */ if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */ -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: %s: I/O error\n",drive->name); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: %s: I/O error\n",drive->name); rq->errors++; if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { printk (KERN_ERR "ide-floppy: I/O error in request sense command\n"); @@ -915,9 +924,7 @@ ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); return ide_started; } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_NOTICE "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n"); } } if (test_bit (PC_WRITING, &pc->flags)) { @@ -983,7 +990,7 @@ * a legitimate error code was received. */ if (!test_bit (PC_ABORT, &pc->flags)) { - printk (KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", + IDEFLOPPY_DEBUG( "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", drive->name, pc->c[0], floppy->sense_key, floppy->asc, floppy->ascq); pc->error = IDEFLOPPY_ERROR_GENERAL; /* Giving up */ } @@ -991,9 +998,7 @@ pc->callback(drive); return ide_stopped; } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Retry number - %d\n",pc->retries); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "Retry number - %d\n",pc->retries); pc->retries++; pc->actually_transferred=0; /* We haven't transferred any data yet */ @@ -1034,9 +1039,7 @@ static void idefloppy_rw_callback (ide_drive_t *drive) { -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_rw_callback\n"); idefloppy_end_request(1, HWGROUP(drive)); return; @@ -1044,9 +1047,7 @@ static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent) { -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: creating prevent removal command, prevent = %d\n", prevent); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: creating prevent removal command, prevent = %d\n", prevent); idefloppy_init_pc (pc); pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD; @@ -1106,10 +1107,8 @@ int block = sector / floppy->bs_factor; int blocks = rq->nr_sectors / floppy->bs_factor; -#if IDEFLOPPY_DEBUG_LOG - printk ("create_rw1%d_cmd: block == %d, blocks == %d\n", + IDEFLOPPY_DEBUG( "create_rw1%d_cmd: block == %d, blocks == %d\n", 2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags), block, blocks); -#endif /* IDEFLOPPY_DEBUG_LOG */ idefloppy_init_pc (pc); if (test_bit (IDEFLOPPY_USE_READ12, &floppy->flags)) { @@ -1139,10 +1138,8 @@ idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t *pc; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); - printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); + IDEFLOPPY_DEBUG( "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); if (rq->errors >= ERROR_MAX) { if (floppy->failed_pc != NULL) @@ -1235,6 +1232,7 @@ return 0; } + /* * Determine if a media is present in the floppy drive, and if so, * its LBA capacity. @@ -1263,48 +1261,68 @@ for (i = 0; i < descriptors; i++, descriptor++) { blocks = descriptor->blocks = ntohl (descriptor->blocks); length = descriptor->length = ntohs (descriptor->length); - if (!i && descriptor->dc == CAPACITY_CURRENT) { - if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) { - printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size, %s \n", - drive->name, blocks * length / 1024, blocks, length, - drive->using_dma ? ", DMA":""); - } - floppy->capacity = *descriptor; + if (!i) { + switch (descriptor->dc) { + case CAPACITY_UNFORMATTED: /* Clik! drive returns this instead of CAPACITY_CURRENT */ + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) + break; /* If it is not a clik drive, break out (maintains previous driver behaviour) */ + case CAPACITY_CURRENT: /* Normal Zip/LS-120 disks */ + if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) + printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size\n", drive->name, blocks * length / 1024, blocks, length); + floppy->capacity = *descriptor; if (!length || length % 512) - printk (KERN_ERR "%s: %d bytes block size not supported\n", drive->name, length); + printk (KERN_NOTICE "%s: %d bytes block size not supported\n", drive->name, length); else { floppy->blocks = blocks; floppy->block_size = length; if ((floppy->bs_factor = length / 512) != 1) printk (KERN_NOTICE "%s: warning: non 512 bytes block size not fully supported\n", drive->name); - rc = 0; - } + rc = 0; + } + break; + case CAPACITY_NO_CARTRIDGE: + /* This is a KERN_ERR so it appears on screen for the user to see */ + printk (KERN_ERR "%s: No disk in drive\n", drive->name); + break; + case CAPACITY_INVALID: + printk (KERN_ERR "%s: Invalid capacity for disk in drive\n", drive->name); + break; } -#if IDEFLOPPY_DEBUG_INFO - if (!i) printk (KERN_INFO "Descriptor 0 Code: %d\n", descriptor->dc); - printk (KERN_INFO "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length); -#endif /* IDEFLOPPY_DEBUG_INFO */ } + if (!i) { + IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n", descriptor->dc); + } + IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length); + } + + /* Clik! disk does not support get_flexible_disk_page */ + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) (void) idefloppy_get_flexible_disk_page (drive); + drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor; return rc; } + /* * Our special ide-floppy ioctl's. * - * Currently there aren't any ioctl's. + * Supports eject command */ static int idefloppy_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { idefloppy_pc_t pc; + idefloppy_floppy_t *floppy = drive->driver_data; if (cmd == CDROMEJECT) { if (drive->usage > 1) return -EBUSY; + /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */ + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd (&pc, 0); (void) idefloppy_queue_pc_tail (drive, &pc); + } idefloppy_create_start_stop_cmd (&pc, 2); (void) idefloppy_queue_pc_tail (drive, &pc); return 0; @@ -1320,20 +1338,24 @@ idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t pc; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_open\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "Reached idefloppy_open\n"); MOD_INC_USE_COUNT; if (drive->usage == 1) { + IDEFLOPPY_DEBUG( "Testing if unit is ready...\n"); idefloppy_create_test_unit_ready_cmd(&pc); if (idefloppy_queue_pc_tail(drive, &pc)) { + IDEFLOPPY_DEBUG( "Not ready, issuing start command\n"); idefloppy_create_start_stop_cmd (&pc, 1); (void) idefloppy_queue_pc_tail (drive, &pc); + } else + { + IDEFLOPPY_DEBUG( "Yes unit is ready\n"); } if (idefloppy_get_capacity (drive)) { drive->usage--; MOD_DEC_USE_COUNT; + IDEFLOPPY_DEBUG( "I/O Error Getting Capacity\n"); return -EIO; } if (floppy->wp && (filp->f_mode & 2)) { @@ -1342,8 +1364,11 @@ return -EROFS; } set_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); + /* IOMEGA Clik! drives do not support lock/unlock commands - no room for mechanism */ + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd (&pc, 1); (void) idefloppy_queue_pc_tail (drive, &pc); + } check_disk_change(inode->i_rdev); } return 0; @@ -1352,16 +1377,18 @@ static void idefloppy_release (struct inode *inode, struct file *filp, ide_drive_t *drive) { idefloppy_pc_t pc; + idefloppy_floppy_t *floppy = drive->driver_data; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_release\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "Reached idefloppy_release\n"); if (!drive->usage) { invalidate_buffers (inode->i_rdev); + /* IOMEGA Clik! drives do not support lock/unlock commands */ + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd (&pc, 0); (void) idefloppy_queue_pc_tail (drive, &pc); } + } MOD_DEC_USE_COUNT; } @@ -1559,6 +1586,17 @@ for (i = 0; i < 1 << PARTN_BITS; i++) max_sectors[major][minor + i] = 64; } + /* + * Guess what? The IOMEGA Clik! drive also needs the + * above fix. It makes nasty clicking noises without + * it, so please don't remove this. + */ + if (strcmp(drive->id->model, "IOMEGA Clik! 40 CZ ATAPI") == 0) + { + for (i = 0; i < 1 << PARTN_BITS; i++) + max_sectors[major][minor + i] = 64; + set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags); + } (void) idefloppy_get_capacity (drive); idefloppy_add_settings(drive); @@ -1597,6 +1635,7 @@ #endif /* CONFIG_PROC_FS */ + /* * IDE subdriver functions, registered with ide.c */ @@ -1629,6 +1668,7 @@ NULL }; + /* * idefloppy_init will register the driver for each floppy. */ @@ -1665,12 +1705,16 @@ return 0; } + #ifdef MODULE +/* Initialisation code for loading the driver as a modules */ int init_module (void) { return idefloppy_init (); } + +/* Cleanup code for removing the driver module */ void cleanup_module (void) { ide_drive_t *drive;