ide-floppy.c 14.4 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
2 3
 * IDE ATAPI floppy driver.
 *
4 5 6
 * Copyright (C) 1996-1999  Gadi Oxman <gadio@netvision.net.il>
 * Copyright (C) 2000-2002  Paul Bristow <paul@paulbristow.net>
 * Copyright (C) 2005       Bartlomiej Zolnierkiewicz
7
 *
Linus Torvalds's avatar
Linus Torvalds committed
8 9 10 11 12 13
 * This driver supports the following IDE floppy drives:
 *
 * LS-120/240 SuperDisk
 * Iomega Zip 100/250
 * Iomega PC Card Clik!/PocketZip
 *
14 15
 * For a historical changelog see
 * Documentation/ide/ChangeLog.ide-floppy.1996-2002
Linus Torvalds's avatar
Linus Torvalds committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29
 */

#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
#include <linux/cdrom.h>
#include <linux/ide.h>
30
#include <linux/hdreg.h>
Linus Torvalds's avatar
Linus Torvalds committed
31
#include <linux/bitops.h>
32
#include <linux/mutex.h>
33
#include <linux/scatterlist.h>
Linus Torvalds's avatar
Linus Torvalds committed
34

35 36
#include <scsi/scsi_ioctl.h>

Linus Torvalds's avatar
Linus Torvalds committed
37
#include <asm/byteorder.h>
38 39
#include <linux/uaccess.h>
#include <linux/io.h>
Linus Torvalds's avatar
Linus Torvalds committed
40 41
#include <asm/unaligned.h>

42 43
#include "ide-floppy.h"

Linus Torvalds's avatar
Linus Torvalds committed
44
/*
45 46
 * After each failed packet command we issue a request sense command and retry
 * the packet command IDEFLOPPY_MAX_PC_RETRIES times.
Linus Torvalds's avatar
Linus Torvalds committed
47 48 49
 */
#define IDEFLOPPY_MAX_PC_RETRIES	3

50
/* format capacities descriptor codes */
Linus Torvalds's avatar
Linus Torvalds committed
51 52 53 54 55
#define CAPACITY_INVALID	0x00
#define CAPACITY_UNFORMATTED	0x01
#define CAPACITY_CURRENT	0x02
#define CAPACITY_NO_CARTRIDGE	0x03

56 57 58 59 60
/*
 * The following delay solves a problem with ATAPI Zip 100 drive where BSY bit
 * was apparently being deasserted before the unit was ready to receive data.
 */
#define IDEFLOPPY_PC_DELAY	(HZ/20)	/* default delay for ZIP 100 (50ms) */
Linus Torvalds's avatar
Linus Torvalds committed
61

62
static int ide_floppy_callback(ide_drive_t *drive, int dsc)
Linus Torvalds's avatar
Linus Torvalds committed
63
{
64
	struct ide_disk_obj *floppy = drive->driver_data;
65
	struct ide_atapi_pc *pc = drive->pc;
66
	struct request *rq = pc->rq;
67
	int uptodate = pc->error ? 0 : 1;
Linus Torvalds's avatar
Linus Torvalds committed
68

69
	ide_debug_log(IDE_DBG_FUNC, "enter");
70

71 72
	if (drive->failed_pc == pc)
		drive->failed_pc = NULL;
73

74
	if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 ||
75
	    rq->cmd_type == REQ_TYPE_BLOCK_PC)
76 77
		uptodate = 1; /* FIXME */
	else if (pc->c[0] == GPCMD_REQUEST_SENSE) {
78 79

		u8 *buf = bio_data(rq->bio);
80

81 82 83 84 85 86
		if (!pc->error) {
			floppy->sense_key = buf[2] & 0x0F;
			floppy->asc = buf[12];
			floppy->ascq = buf[13];
			floppy->progress_indication = buf[15] & 0x80 ?
				(u16)get_unaligned((u16 *)&buf[16]) : 0x10000;
87

88
			if (drive->failed_pc)
89
				ide_debug_log(IDE_DBG_PC, "pc = %x",
90
					      drive->failed_pc->c[0]);
91

92
			ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x,"
93
				      "ascq = %x", floppy->sense_key,
94
				      floppy->asc, floppy->ascq);
95
		} else
96 97
			printk(KERN_ERR PFX "Error in REQUEST SENSE itself - "
			       "Aborting request!\n");
98
	}
Linus Torvalds's avatar
Linus Torvalds committed
99

100
	if (rq->cmd_type == REQ_TYPE_DRV_PRIV)
101
		rq->errors = uptodate ? 0 : IDE_DRV_ERROR_GENERAL;
102 103

	return uptodate;
Linus Torvalds's avatar
Linus Torvalds committed
104 105
}

106
static void ide_floppy_report_error(struct ide_disk_obj *floppy,
107
				    struct ide_atapi_pc *pc)
Linus Torvalds's avatar
Linus Torvalds committed
108
{
109
	/* suppress error messages resulting from Medium not present */
Linus Torvalds's avatar
Linus Torvalds committed
110 111 112
	if (floppy->sense_key == 0x02 &&
	    floppy->asc       == 0x3a &&
	    floppy->ascq      == 0x00)
113 114
		return;

115
	printk(KERN_ERR PFX "%s: I/O error, pc = %2x, key = %2x, "
116 117 118 119
			"asc = %2x, ascq = %2x\n",
			floppy->drive->name, pc->c[0], floppy->sense_key,
			floppy->asc, floppy->ascq);

Linus Torvalds's avatar
Linus Torvalds committed
120 121
}

122 123 124
static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive,
					   struct ide_cmd *cmd,
					   struct ide_atapi_pc *pc)
Linus Torvalds's avatar
Linus Torvalds committed
125
{
126
	struct ide_disk_obj *floppy = drive->driver_data;
Linus Torvalds's avatar
Linus Torvalds committed
127

128
	if (drive->failed_pc == NULL &&
129
	    pc->c[0] != GPCMD_REQUEST_SENSE)
130
		drive->failed_pc = pc;
131

Linus Torvalds's avatar
Linus Torvalds committed
132
	/* Set the current packet command */
133
	drive->pc = pc;
Linus Torvalds's avatar
Linus Torvalds committed
134

135
	if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
136 137
		unsigned int done = blk_rq_bytes(drive->hwif->rq);

138
		if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
139
			ide_floppy_report_error(floppy, pc);
140

141
		/* Giving up */
142
		pc->error = IDE_DRV_ERROR_GENERAL;
143

144
		drive->failed_pc = NULL;
145
		drive->pc_callback(drive, 0);
146
		ide_complete_rq(drive, -EIO, done);
Linus Torvalds's avatar
Linus Torvalds committed
147 148 149
		return ide_stopped;
	}

150
	ide_debug_log(IDE_DBG_FUNC, "retry #%d", pc->retries);
Linus Torvalds's avatar
Linus Torvalds committed
151 152 153

	pc->retries++;

154
	return ide_issue_pc(drive, cmd);
Linus Torvalds's avatar
Linus Torvalds committed
155 156
}

157
void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
Linus Torvalds's avatar
Linus Torvalds committed
158
{
159
	ide_init_pc(pc);
160
	pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES;
Linus Torvalds's avatar
Linus Torvalds committed
161 162
	pc->c[7] = 255;
	pc->c[8] = 255;
163
	pc->req_xfer = 255;
Linus Torvalds's avatar
Linus Torvalds committed
164 165
}

166
/* A mode sense command is used to "sense" floppy parameters. */
167
void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
Linus Torvalds's avatar
Linus Torvalds committed
168
{
169
	u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
170

171
	ide_init_pc(pc);
172
	pc->c[0] = GPCMD_MODE_SENSE_10;
Linus Torvalds's avatar
Linus Torvalds committed
173
	pc->c[1] = 0;
174
	pc->c[2] = page_code;
Linus Torvalds's avatar
Linus Torvalds committed
175 176

	switch (page_code) {
177 178 179 180 181 182 183
	case IDEFLOPPY_CAPABILITIES_PAGE:
		length += 12;
		break;
	case IDEFLOPPY_FLEXIBLE_DISK_PAGE:
		length += 32;
		break;
	default:
184
		printk(KERN_ERR PFX "unsupported page code in %s\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
185
	}
186
	put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
187
	pc->req_xfer = length;
Linus Torvalds's avatar
Linus Torvalds committed
188 189
}

190
static void idefloppy_create_rw_cmd(ide_drive_t *drive,
191
				    struct ide_atapi_pc *pc, struct request *rq,
192
				    unsigned long sector)
Linus Torvalds's avatar
Linus Torvalds committed
193
{
194
	struct ide_disk_obj *floppy = drive->driver_data;
Linus Torvalds's avatar
Linus Torvalds committed
195
	int block = sector / floppy->bs_factor;
196
	int blocks = blk_rq_sectors(rq) / floppy->bs_factor;
Linus Torvalds's avatar
Linus Torvalds committed
197 198
	int cmd = rq_data_dir(rq);

199
	ide_debug_log(IDE_DBG_FUNC, "block: %d, blocks: %d", block, blocks);
Linus Torvalds's avatar
Linus Torvalds committed
200

201
	ide_init_pc(pc);
202 203
	pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10;
	put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
204
	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
205

206 207
	memcpy(rq->cmd, pc->c, 12);

Linus Torvalds's avatar
Linus Torvalds committed
208
	pc->rq = rq;
209
	if (cmd == WRITE)
210
		pc->flags |= PC_FLAG_WRITING;
211

212
	pc->flags |= PC_FLAG_DMA_OK;
Linus Torvalds's avatar
Linus Torvalds committed
213 214
}

215
static void idefloppy_blockpc_cmd(struct ide_disk_obj *floppy,
216
		struct ide_atapi_pc *pc, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
217
{
218
	ide_init_pc(pc);
Linus Torvalds's avatar
Linus Torvalds committed
219
	memcpy(pc->c, rq->cmd, sizeof(pc->c));
220
	pc->rq = rq;
221
	if (blk_rq_bytes(rq)) {
222
		pc->flags |= PC_FLAG_DMA_OK;
223 224 225
		if (rq_data_dir(rq) == WRITE)
			pc->flags |= PC_FLAG_WRITING;
	}
Linus Torvalds's avatar
Linus Torvalds committed
226 227
}

228 229
static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
					     struct request *rq, sector_t block)
Linus Torvalds's avatar
Linus Torvalds committed
230
{
231
	struct ide_disk_obj *floppy = drive->driver_data;
232
	struct ide_cmd cmd;
233
	struct ide_atapi_pc *pc;
Linus Torvalds's avatar
Linus Torvalds committed
234

235 236
	ide_debug_log(IDE_DBG_FUNC, "enter, cmd: 0x%x\n", rq->cmd[0]);

237 238 239 240
	if (drive->debug_mask & IDE_DBG_RQ)
		blk_dump_rq_flags(rq, (rq->rq_disk
					? rq->rq_disk->disk_name
					: "dev?"));
Linus Torvalds's avatar
Linus Torvalds committed
241 242

	if (rq->errors >= ERROR_MAX) {
243
		if (drive->failed_pc) {
244
			ide_floppy_report_error(floppy, drive->failed_pc);
245 246
			drive->failed_pc = NULL;
		} else
247 248
			printk(KERN_ERR PFX "%s: I/O error\n", drive->name);

249
		if (rq->cmd_type == REQ_TYPE_DRV_PRIV) {
250
			rq->errors = 0;
251
			ide_complete_rq(drive, 0, blk_rq_bytes(rq));
252 253 254
			return ide_stopped;
		} else
			goto out_end;
Linus Torvalds's avatar
Linus Torvalds committed
255
	}
256 257 258

	switch (rq->cmd_type) {
	case REQ_TYPE_FS:
259 260
		if (((long)blk_rq_pos(rq) % floppy->bs_factor) ||
		    (blk_rq_sectors(rq) % floppy->bs_factor)) {
261 262
			printk(KERN_ERR PFX "%s: unsupported r/w rq size\n",
				drive->name);
263
			goto out_end;
Linus Torvalds's avatar
Linus Torvalds committed
264
		}
265
		pc = &floppy->queued_pc;
266
		idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block);
267
		break;
268
	case REQ_TYPE_DRV_PRIV:
269
	case REQ_TYPE_ATA_SENSE:
270
		pc = (struct ide_atapi_pc *)rq->special;
271 272
		break;
	case REQ_TYPE_BLOCK_PC:
273
		pc = &floppy->queued_pc;
274
		idefloppy_blockpc_cmd(floppy, pc, rq);
275 276
		break;
	default:
277
		BUG();
278
	}
Linus Torvalds's avatar
Linus Torvalds committed
279

280 281
	ide_prep_sense(drive, rq);

282 283
	memset(&cmd, 0, sizeof(cmd));

284
	if (rq_data_dir(rq))
285 286 287
		cmd.tf_flags |= IDE_TFLAG_WRITE;

	cmd.rq = rq;
288

289
	if (rq->cmd_type == REQ_TYPE_FS || blk_rq_bytes(rq)) {
290
		ide_init_sg_cmd(&cmd, blk_rq_bytes(rq));
291
		ide_map_sg(drive, &cmd);
292
	}
293

Linus Torvalds's avatar
Linus Torvalds committed
294
	pc->rq = rq;
295

296
	return ide_floppy_issue_pc(drive, &cmd, pc);
297 298
out_end:
	drive->failed_pc = NULL;
299
	if (rq->cmd_type != REQ_TYPE_FS && rq->errors == 0)
300
		rq->errors = -EIO;
301
	ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
302
	return ide_stopped;
Linus Torvalds's avatar
Linus Torvalds committed
303 304 305
}

/*
306 307
 * Look at the flexible disk page parameters. We ignore the CHS capacity
 * parameters and use the LBA parameters instead.
Linus Torvalds's avatar
Linus Torvalds committed
308
 */
309 310
static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive,
					     struct ide_atapi_pc *pc)
Linus Torvalds's avatar
Linus Torvalds committed
311
{
312
	struct ide_disk_obj *floppy = drive->driver_data;
313
	struct gendisk *disk = floppy->disk;
314
	u8 *page, buf[40];
Linus Torvalds's avatar
Linus Torvalds committed
315
	int capacity, lba_capacity;
316 317
	u16 transfer_rate, sector_size, cyls, rpm;
	u8 heads, sectors;
Linus Torvalds's avatar
Linus Torvalds committed
318

319
	ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
320

321
	if (ide_queue_pc_tail(drive, disk, pc, buf, pc->req_xfer)) {
322
		printk(KERN_ERR PFX "Can't get flexible disk page params\n");
Linus Torvalds's avatar
Linus Torvalds committed
323 324
		return 1;
	}
325

326
	if (buf[3] & 0x80)
327
		drive->dev_flags |= IDE_DFLAG_WP;
328
	else
329
		drive->dev_flags &= ~IDE_DFLAG_WP;
330

331
	set_disk_ro(disk, !!(drive->dev_flags & IDE_DFLAG_WP));
332

333
	page = &buf[8];
334

335 336 337 338 339 340
	transfer_rate = be16_to_cpup((__be16 *)&buf[8 + 2]);
	sector_size   = be16_to_cpup((__be16 *)&buf[8 + 6]);
	cyls          = be16_to_cpup((__be16 *)&buf[8 + 8]);
	rpm           = be16_to_cpup((__be16 *)&buf[8 + 28]);
	heads         = buf[8 + 4];
	sectors       = buf[8 + 5];
341 342 343 344

	capacity = cyls * heads * sectors * sector_size;

	if (memcmp(page, &floppy->flexible_disk_page, 32))
345
		printk(KERN_INFO PFX "%s: %dkB, %d/%d/%d CHS, %d kBps, "
Linus Torvalds's avatar
Linus Torvalds committed
346
				"%d sector size, %d rpm\n",
347 348 349 350 351 352 353
				drive->name, capacity / 1024, cyls, heads,
				sectors, transfer_rate / 8, sector_size, rpm);

	memcpy(&floppy->flexible_disk_page, page, 32);
	drive->bios_cyl = cyls;
	drive->bios_head = heads;
	drive->bios_sect = sectors;
Linus Torvalds's avatar
Linus Torvalds committed
354
	lba_capacity = floppy->blocks * floppy->block_size;
355

Linus Torvalds's avatar
Linus Torvalds committed
356
	if (capacity < lba_capacity) {
357
		printk(KERN_NOTICE PFX "%s: The disk reports a capacity of %d "
Linus Torvalds's avatar
Linus Torvalds committed
358 359
			"bytes, but the drive only handles %d\n",
			drive->name, lba_capacity, capacity);
360 361
		floppy->blocks = floppy->block_size ?
			capacity / floppy->block_size : 0;
362
		drive->capacity64 = floppy->blocks * floppy->bs_factor;
Linus Torvalds's avatar
Linus Torvalds committed
363
	}
364

Linus Torvalds's avatar
Linus Torvalds committed
365 366 367 368
	return 0;
}

/*
369 370
 * Determine if a media is present in the floppy drive, and if so, its LBA
 * capacity.
Linus Torvalds's avatar
Linus Torvalds committed
371
 */
372
static int ide_floppy_get_capacity(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
373
{
374
	struct ide_disk_obj *floppy = drive->driver_data;
375
	struct gendisk *disk = floppy->disk;
376
	struct ide_atapi_pc pc;
377
	u8 *cap_desc;
378
	u8 pc_buf[256], header_len, desc_cnt;
379 380
	int i, rc = 1, blocks, length;

381 382
	ide_debug_log(IDE_DBG_FUNC, "enter");

Linus Torvalds's avatar
Linus Torvalds committed
383 384
	drive->bios_cyl = 0;
	drive->bios_head = drive->bios_sect = 0;
385 386
	floppy->blocks = 0;
	floppy->bs_factor = 1;
387
	drive->capacity64 = 0;
Linus Torvalds's avatar
Linus Torvalds committed
388

389
	ide_floppy_create_read_capacity_cmd(&pc);
390
	if (ide_queue_pc_tail(drive, disk, &pc, pc_buf, pc.req_xfer)) {
391
		printk(KERN_ERR PFX "Can't get floppy parameters\n");
Linus Torvalds's avatar
Linus Torvalds committed
392 393
		return 1;
	}
394 395
	header_len = pc_buf[3];
	cap_desc = &pc_buf[4];
396 397 398 399 400
	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */

	for (i = 0; i < desc_cnt; i++) {
		unsigned int desc_start = 4 + i*8;

401 402
		blocks = be32_to_cpup((__be32 *)&pc_buf[desc_start]);
		length = be16_to_cpup((__be16 *)&pc_buf[desc_start + 6]);
403

404
		ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, "
405 406 407
					     "%d sector size",
					     i, blocks * length / 1024,
					     blocks, length);
Linus Torvalds's avatar
Linus Torvalds committed
408

409 410 411 412 413
		if (i)
			continue;
		/*
		 * the code below is valid only for the 1st descriptor, ie i=0
		 */
Linus Torvalds's avatar
Linus Torvalds committed
414

415
		switch (pc_buf[desc_start + 4] & 0x03) {
Linus Torvalds's avatar
Linus Torvalds committed
416 417
		/* Clik! drive returns this instead of CAPACITY_CURRENT */
		case CAPACITY_UNFORMATTED:
418
			if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
419
				/*
Linus Torvalds's avatar
Linus Torvalds committed
420 421 422 423 424 425
				 * If it is not a clik drive, break out
				 * (maintains previous driver behaviour)
				 */
				break;
		case CAPACITY_CURRENT:
			/* Normal Zip/LS-120 disks */
426
			if (memcmp(cap_desc, &floppy->cap_desc, 8))
427 428 429 430
				printk(KERN_INFO PFX "%s: %dkB, %d blocks, %d "
				       "sector size\n",
				       drive->name, blocks * length / 1024,
				       blocks, length);
431 432
			memcpy(&floppy->cap_desc, cap_desc, 8);

Linus Torvalds's avatar
Linus Torvalds committed
433
			if (!length || length % 512) {
434 435
				printk(KERN_NOTICE PFX "%s: %d bytes block size"
				       " not supported\n", drive->name, length);
Linus Torvalds's avatar
Linus Torvalds committed
436
			} else {
437 438 439 440
				floppy->blocks = blocks;
				floppy->block_size = length;
				floppy->bs_factor = length / 512;
				if (floppy->bs_factor != 1)
441 442 443 444
					printk(KERN_NOTICE PFX "%s: Warning: "
					       "non 512 bytes block size not "
					       "fully supported\n",
					       drive->name);
445 446
				drive->capacity64 =
					floppy->blocks * floppy->bs_factor;
447
				rc = 0;
Linus Torvalds's avatar
Linus Torvalds committed
448 449 450 451 452 453 454
			}
			break;
		case CAPACITY_NO_CARTRIDGE:
			/*
			 * This is a KERN_ERR so it appears on screen
			 * for the user to see
			 */
455 456
			printk(KERN_ERR PFX "%s: No disk in drive\n",
			       drive->name);
Linus Torvalds's avatar
Linus Torvalds committed
457 458
			break;
		case CAPACITY_INVALID:
459
			printk(KERN_ERR PFX "%s: Invalid capacity for disk "
Linus Torvalds's avatar
Linus Torvalds committed
460 461 462
				"in drive\n", drive->name);
			break;
		}
463
		ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d",
464
					     pc_buf[desc_start + 4] & 0x03);
Linus Torvalds's avatar
Linus Torvalds committed
465 466 467
	}

	/* Clik! disk does not support get_flexible_disk_page */
468
	if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
469
		(void) ide_floppy_get_flexible_disk_page(drive, &pc);
Linus Torvalds's avatar
Linus Torvalds committed
470 471 472 473

	return rc;
}

474
static void ide_floppy_setup(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
475
{
476
	struct ide_disk_obj *floppy = drive->driver_data;
477
	u16 *id = drive->id;
478

479
	drive->pc_callback	 = ide_floppy_callback;
480

Linus Torvalds's avatar
Linus Torvalds committed
481
	/*
482 483
	 * We used to check revisions here. At this point however I'm giving up.
	 * Just assume they are all broken, its easier.
Linus Torvalds's avatar
Linus Torvalds committed
484
	 *
485 486 487 488
	 * The actual reason for the workarounds was likely a driver bug after
	 * all rather than a firmware bug, and the workaround below used to hide
	 * it. It should be fixed as of version 1.9, but to be on the safe side
	 * we'll leave the limitation below for the 2.2.x tree.
Linus Torvalds's avatar
Linus Torvalds committed
489
	 */
490
	if (strstarts((char *)&id[ATA_ID_PROD], "IOMEGA ZIP 100 ATAPI")) {
491
		drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE;
Linus Torvalds's avatar
Linus Torvalds committed
492
		/* This value will be visible in the /proc/ide/hdx/settings */
493
		drive->pc_delay = IDEFLOPPY_PC_DELAY;
494
		blk_queue_max_hw_sectors(drive->queue, 64);
Linus Torvalds's avatar
Linus Torvalds committed
495 496 497
	}

	/*
498 499 500
	 * Guess what? The IOMEGA Clik! drive also needs the above fix. It makes
	 * nasty clicking noises without it, so please don't remove this.
	 */
501
	if (strstarts((char *)&id[ATA_ID_PROD], "IOMEGA Clik!")) {
502
		blk_queue_max_hw_sectors(drive->queue, 64);
503
		drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE;
504
		/* IOMEGA Clik! drives do not support lock/unlock commands */
505
		drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
Linus Torvalds's avatar
Linus Torvalds committed
506 507
	}

508
	(void) ide_floppy_get_capacity(drive);
509 510

	ide_proc_register_driver(drive, floppy->driver);
511 512

	drive->dev_flags |= IDE_DFLAG_ATTACH;
Linus Torvalds's avatar
Linus Torvalds committed
513
}
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542

static void ide_floppy_flush(ide_drive_t *drive)
{
}

static int ide_floppy_init_media(ide_drive_t *drive, struct gendisk *disk)
{
	int ret = 0;

	if (ide_do_test_unit_ready(drive, disk))
		ide_do_start_stop(drive, disk, 1);

	ret = ide_floppy_get_capacity(drive);

	set_capacity(disk, ide_gd_capacity(drive));

	return ret;
}

const struct ide_disk_ops ide_atapi_disk_ops = {
	.check		= ide_check_atapi_device,
	.get_capacity	= ide_floppy_get_capacity,
	.setup		= ide_floppy_setup,
	.flush		= ide_floppy_flush,
	.init_media	= ide_floppy_init_media,
	.set_doorlock	= ide_set_media_lock,
	.do_request	= ide_floppy_do_request,
	.ioctl		= ide_floppy_ioctl,
};