*/
#define IDEFLOPPY_PC_BUFFER_SIZE 256
-/*
- * In various places in the driver, we need to allocate storage for packet
- * commands and requests, which will remain valid while we leave the driver to
- * wait for an interrupt or a timeout event.
- */
-#define IDEFLOPPY_PC_STACK (10 + IDEFLOPPY_MAX_PC_RETRIES)
-
/* format capacities descriptor codes */
#define CAPACITY_INVALID 0x00
#define CAPACITY_UNFORMATTED 0x01
struct ide_atapi_pc *pc;
/* Last failed packet command */
struct ide_atapi_pc *failed_pc;
- /* Packet command stack */
- struct ide_atapi_pc pc_stack[IDEFLOPPY_PC_STACK];
- /* Next free packet command storage space */
- int pc_stack_index;
- struct request rq_stack[IDEFLOPPY_PC_STACK];
- /* We implement a circular array */
- int rq_stack_index;
+ /* used for blk_{fs,pc}_request() requests */
+ struct ide_atapi_pc queued_pc;
+
+ struct ide_atapi_pc request_sense_pc;
+ struct request request_sense_rq;
/* Last error information */
u8 sense_key, asc, ascq;
#define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */
-/* Defines for the MODE SENSE command */
-#define MODE_SENSE_CURRENT 0x00
-#define MODE_SENSE_CHANGEABLE 0x01
-#define MODE_SENSE_DEFAULT 0x02
-#define MODE_SENSE_SAVED 0x03
-
/* IOCTLs used in low-level formatting. */
#define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600
#define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601
return 0;
}
-static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
- unsigned int bcount, int direction)
-{
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_tp_ops *tp_ops = hwif->tp_ops;
- xfer_func_t *xf = direction ? tp_ops->output_data : tp_ops->input_data;
- struct scatterlist *sg = pc->sg;
- char *buf;
- int count, done = 0;
-
- while (bcount) {
- count = min(sg->length - pc->b_count, bcount);
- if (PageHighMem(sg_page(sg))) {
- unsigned long flags;
-
- local_irq_save(flags);
- buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
- xf(drive, NULL, buf + pc->b_count, count);
- kunmap_atomic(buf - sg->offset, KM_IRQ0);
- local_irq_restore(flags);
- } else {
- buf = sg_virt(sg);
- xf(drive, NULL, buf + pc->b_count, count);
- }
- bcount -= count;
- pc->b_count += count;
- done += count;
-
- if (pc->b_count == sg->length) {
- if (!--pc->sg_cnt)
- break;
- pc->sg = sg = sg_next(sg);
- pc->b_count = 0;
- }
- }
-
- idefloppy_end_request(drive, 1, done >> 9);
-
- if (bcount) {
- printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n",
- drive->name, __func__, bcount);
- ide_pad_transfer(drive, direction, bcount);
- }
-}
-
static void idefloppy_update_buffers(ide_drive_t *drive,
struct ide_atapi_pc *pc)
{
ide_do_drive_cmd(drive, rq);
}
-static struct ide_atapi_pc *idefloppy_next_pc_storage(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
-
- if (floppy->pc_stack_index == IDEFLOPPY_PC_STACK)
- floppy->pc_stack_index = 0;
- return (&floppy->pc_stack[floppy->pc_stack_index++]);
-}
-
-static struct request *idefloppy_next_rq_storage(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
-
- if (floppy->rq_stack_index == IDEFLOPPY_PC_STACK)
- floppy->rq_stack_index = 0;
- return (&floppy->rq_stack[floppy->rq_stack_index++]);
-}
-
static void ide_floppy_callback(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
*/
static void idefloppy_retry_pc(ide_drive_t *drive)
{
- struct ide_atapi_pc *pc;
- struct request *rq;
+ struct ide_floppy_obj *floppy = drive->driver_data;
+ struct request *rq = &floppy->request_sense_rq;
+ struct ide_atapi_pc *pc = &floppy->request_sense_pc;
(void)ide_read_error(drive);
- pc = idefloppy_next_pc_storage(drive);
- rq = idefloppy_next_rq_storage(drive);
idefloppy_create_request_sense_cmd(pc);
idefloppy_queue_pc_head(drive, pc, rq);
}
return ide_pc_intr(drive, floppy->pc, idefloppy_pc_intr,
IDEFLOPPY_WAIT_CMD, NULL, idefloppy_update_buffers,
- idefloppy_retry_pc, NULL, ide_floppy_io_buffers);
+ idefloppy_retry_pc, NULL, ide_io_buffers);
}
/*
/* A mode sense command is used to "sense" floppy parameters. */
static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc,
- u8 page_code, u8 type)
+ u8 page_code)
{
u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
idefloppy_init_pc(pc);
pc->c[0] = GPCMD_MODE_SENSE_10;
pc->c[1] = 0;
- pc->c[2] = page_code + (type << 6);
+ pc->c[2] = page_code;
switch (page_code) {
case IDEFLOPPY_CAPABILITIES_PAGE:
idefloppy_end_request(drive, 0, 0);
return ide_stopped;
}
- pc = idefloppy_next_pc_storage(drive);
+ pc = &floppy->queued_pc;
idefloppy_create_rw_cmd(floppy, pc, rq, block);
} else if (blk_special_request(rq)) {
pc = (struct ide_atapi_pc *) rq->buffer;
} else if (blk_pc_request(rq)) {
- pc = idefloppy_next_pc_storage(drive);
+ pc = &floppy->queued_pc;
idefloppy_blockpc_cmd(floppy, pc, rq);
} else {
blk_dump_rq_flags(rq,
u16 transfer_rate, sector_size, cyls, rpm;
u8 heads, sectors;
- idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE,
- MODE_SENSE_CURRENT);
+ idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
if (idefloppy_queue_pc_tail(drive, &pc)) {
printk(KERN_ERR "ide-floppy: Can't get flexible disk page"
struct ide_atapi_pc pc;
floppy->srfp = 0;
- idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE,
- MODE_SENSE_CURRENT);
+ idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE);
pc.flags |= PC_FLAG_SUPPRESS_ERROR;
+
if (idefloppy_queue_pc_tail(drive, &pc))
return 1;
u8 gcw[2];
*((u16 *)&gcw) = id[ATA_ID_CONFIG];
- floppy->pc = floppy->pc_stack;
+
drive->pc_callback = ide_floppy_callback;
if (((gcw[0] & 0x60) >> 5) == 1)
#endif
};
+static void ide_floppy_set_media_lock(ide_drive_t *drive, int on)
+{
+ struct ide_atapi_pc pc;
+
+ /* IOMEGA Clik! drives do not support lock/unlock commands */
+ if ((drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE) == 0) {
+ idefloppy_create_prevent_cmd(&pc, on);
+ (void)idefloppy_queue_pc_tail(drive, &pc);
+ }
+}
+
static int idefloppy_open(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
ret = -EROFS;
goto out_put_floppy;
}
+
drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
- /* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
- idefloppy_create_prevent_cmd(&pc, 1);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
+ ide_floppy_set_media_lock(drive, 1);
check_disk_change(inode->i_bdev);
} else if (drive->atapi_flags & IDE_AFLAG_FORMAT_IN_PROGRESS) {
ret = -EBUSY;
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ide_floppy_obj *floppy = ide_floppy_g(disk);
ide_drive_t *drive = floppy->drive;
- struct ide_atapi_pc pc;
debug_log("Reached %s\n", __func__);
if (floppy->openers == 1) {
- /* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
- idefloppy_create_prevent_cmd(&pc, 0);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
-
+ ide_floppy_set_media_lock(drive, 0);
drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
}
unsigned long arg, unsigned int cmd)
{
idefloppy_floppy_t *floppy = drive->driver_data;
+ int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0;
if (floppy->openers > 1)
return -EBUSY;
- /* The IOMEGA Clik! Drive doesn't support this command -
- * no room for an eject mechanism */
- if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
- int prevent = arg ? 1 : 0;
-
- if (cmd == CDROMEJECT)
- prevent = 0;
-
- idefloppy_create_prevent_cmd(pc, prevent);
- (void) idefloppy_queue_pc_tail(floppy->drive, pc);
- }
+ ide_floppy_set_media_lock(drive, prevent);
if (cmd == CDROMEJECT) {
idefloppy_create_start_stop_cmd(pc, 2);