Blame view

drivers/ide/ide-floppy.c 15.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
d3f208488   Borislav Petkov   ide-floppy: clean...
2
3
   * IDE ATAPI floppy driver.
   *
59bca8cc9   Bartlomiej Zolnierkiewicz   ide: update/add m...
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
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
7
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
   *
d3f208488   Borislav Petkov   ide-floppy: clean...
14
15
   * For a historical changelog see
   * Documentation/ide/ChangeLog.ide-floppy.1996-2002
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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/slab.h>
  #include <linux/cdrom.h>
  #include <linux/ide.h>
3ceca727f   Bartlomiej Zolnierkiewicz   ide: include <lin...
30
  #include <linux/hdreg.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  #include <linux/bitops.h>
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
32
  #include <linux/mutex.h>
b98b3409a   Borislav Petkov   ide-floppy: use s...
33
  #include <linux/scatterlist.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34

89636af25   Bartlomiej Zolnierkiewicz   ide: add support ...
35
  #include <scsi/scsi_ioctl.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  #include <asm/byteorder.h>
7e8b163b2   Borislav Petkov   ide-floppy: inclu...
37
38
39
  #include <linux/irq.h>
  #include <linux/uaccess.h>
  #include <linux/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  #include <asm/unaligned.h>
0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
41
  #include "ide-floppy.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  /*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
43
44
   * After each failed packet command we issue a request sense command and retry
   * the packet command IDEFLOPPY_MAX_PC_RETRIES times.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
   */
  #define IDEFLOPPY_MAX_PC_RETRIES	3
194ec0c07   Borislav Petkov   ide-floppy: remov...
47
  /* format capacities descriptor codes */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
51
  #define CAPACITY_INVALID	0x00
  #define CAPACITY_UNFORMATTED	0x01
  #define CAPACITY_CURRENT	0x02
  #define CAPACITY_NO_CARTRIDGE	0x03
baf08f0be   Bartlomiej Zolnierkiewicz   ide: make ide_tra...
52
53
54
55
56
  /*
   * 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) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57

0571c7a4f   Borislav Petkov   ide-floppy: fix m...
58
  /* Error code returned in rq->errors to the higher part of the driver. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
  #define	IDEFLOPPY_ERROR_GENERAL		101
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
  /*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
61
62
   * Used to finish servicing a request. For read/write requests, we will call
   * ide_end_request to pass to the next buffer.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
   */
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
64
  static int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
66
  	struct ide_disk_obj *floppy = drive->driver_data;
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
67
  	struct request *rq = drive->hwif->rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
  	int error;
7b3557262   Borislav Petkov   ide-floppy: conve...
69
70
  	ide_debug_log(IDE_DBG_FUNC, "Call %s
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
  
  	switch (uptodate) {
7b3557262   Borislav Petkov   ide-floppy: conve...
73
74
75
76
77
78
79
80
81
82
  	case 0:
  		error = IDEFLOPPY_ERROR_GENERAL;
  		break;
  
  	case 1:
  		error = 0;
  		break;
  
  	default:
  		error = uptodate;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  	}
7b3557262   Borislav Petkov   ide-floppy: conve...
84

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
87
88
89
  	if (error)
  		floppy->failed_pc = NULL;
  	/* Why does this happen? */
  	if (!rq)
  		return 0;
4aff5e233   Jens Axboe   [PATCH] Split str...
90
  	if (!blk_special_request(rq)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
94
95
96
97
98
99
  		/* our real local end request function */
  		ide_end_request(drive, uptodate, nsecs);
  		return 0;
  	}
  	rq->errors = error;
  	/* fixme: need to move this local also */
  	ide_end_drive_cmd(drive, 0, 0);
  	return 0;
  }
8e5551239   Borislav Petkov   ide-floppy: conve...
100
101
  static void idefloppy_update_buffers(ide_drive_t *drive,
  				struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
104
105
106
  {
  	struct request *rq = pc->rq;
  	struct bio *bio = rq->bio;
  
  	while ((bio = rq->bio) != NULL)
c84d9bbe7   Bartlomiej Zolnierkiewicz   ide-floppy: facto...
107
  		ide_floppy_end_request(drive, 1, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  }
b14c72127   Bartlomiej Zolnierkiewicz   ide: drop dsc_han...
109
  static void ide_floppy_callback(ide_drive_t *drive, int dsc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
111
  	struct ide_disk_obj *floppy = drive->driver_data;
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
112
  	struct ide_atapi_pc *pc = drive->pc;
81f493823   Borislav Petkov   ide-floppy: merge...
113
  	int uptodate = pc->error ? 0 : 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114

7b3557262   Borislav Petkov   ide-floppy: conve...
115
116
  	ide_debug_log(IDE_DBG_FUNC, "Call %s
  ", __func__);
bcc77d9cc   Borislav Petkov   ide-floppy: clean...
117

dd2e9a032   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
118
119
  	if (floppy->failed_pc == pc)
  		floppy->failed_pc = NULL;
81f493823   Borislav Petkov   ide-floppy: merge...
120
121
122
123
  	if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 ||
  	    (pc->rq && blk_pc_request(pc->rq)))
  		uptodate = 1; /* FIXME */
  	else if (pc->c[0] == GPCMD_REQUEST_SENSE) {
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
124
  		u8 *buf = pc->buf;
a6ff2d3b0   Borislav Petkov   ide-floppy: remov...
125

81f493823   Borislav Petkov   ide-floppy: merge...
126
127
128
129
130
131
  		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;
a6ff2d3b0   Borislav Petkov   ide-floppy: remov...
132

81f493823   Borislav Petkov   ide-floppy: merge...
133
  			if (floppy->failed_pc)
7b3557262   Borislav Petkov   ide-floppy: conve...
134
135
  				ide_debug_log(IDE_DBG_PC, "pc = %x, ",
  					      floppy->failed_pc->c[0]);
bcc77d9cc   Borislav Petkov   ide-floppy: clean...
136

7b3557262   Borislav Petkov   ide-floppy: conve...
137
138
139
140
  			ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x,"
  				      "ascq = %x
  ", floppy->sense_key,
  				      floppy->asc, floppy->ascq);
81f493823   Borislav Petkov   ide-floppy: merge...
141
  		} else
7b3557262   Borislav Petkov   ide-floppy: conve...
142
143
144
  			printk(KERN_ERR PFX "Error in REQUEST SENSE itself - "
  			       "Aborting request!
  ");
81f493823   Borislav Petkov   ide-floppy: merge...
145
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146

c84d9bbe7   Bartlomiej Zolnierkiewicz   ide-floppy: facto...
147
  	ide_floppy_end_request(drive, uptodate, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
  }
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
149
  static void ide_floppy_report_error(struct ide_disk_obj *floppy,
8e5551239   Borislav Petkov   ide-floppy: conve...
150
  				    struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  {
d652c1380   Borislav Petkov   ide-floppy: mv id...
152
  	/* supress error messages resulting from Medium not present */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
  	if (floppy->sense_key == 0x02 &&
  	    floppy->asc       == 0x3a &&
  	    floppy->ascq      == 0x00)
d652c1380   Borislav Petkov   ide-floppy: mv id...
156
  		return;
7b3557262   Borislav Petkov   ide-floppy: conve...
157
  	printk(KERN_ERR PFX "%s: I/O error, pc = %2x, key = %2x, "
d652c1380   Borislav Petkov   ide-floppy: mv id...
158
159
160
161
  			"asc = %2x, ascq = %2x
  ",
  			floppy->drive->name, pc->c[0], floppy->sense_key,
  			floppy->asc, floppy->ascq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  }
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
163
  static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
8e5551239   Borislav Petkov   ide-floppy: conve...
164
  		struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
166
  	struct ide_disk_obj *floppy = drive->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
  	if (floppy->failed_pc == NULL &&
30d670993   Borislav Petkov   ide-floppy: conve...
169
  	    pc->c[0] != GPCMD_REQUEST_SENSE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  		floppy->failed_pc = pc;
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
171

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  	/* Set the current packet command */
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
173
  	drive->pc = pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174

757ced898   Borislav Petkov   ide-floppy: remov...
175
  	if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
6e5fa7b88   Borislav Petkov   ide-floppy: remov...
176
  		if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
757ced898   Borislav Petkov   ide-floppy: remov...
177
178
179
  			ide_floppy_report_error(floppy, pc);
  		/* Giving up */
  		pc->error = IDEFLOPPY_ERROR_GENERAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
  		floppy->failed_pc = NULL;
b14c72127   Bartlomiej Zolnierkiewicz   ide: drop dsc_han...
181
  		drive->pc_callback(drive, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
  		return ide_stopped;
  	}
7b3557262   Borislav Petkov   ide-floppy: conve...
184
185
  	ide_debug_log(IDE_DBG_FUNC, "%s: Retry #%d
  ", __func__, pc->retries);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
  
  	pc->retries++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188

28ad91db7   Borislav Petkov   ide-atapi: remove...
189
  	return ide_issue_pc(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  }
0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
191
  void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
193
  	ide_init_pc(pc);
30d670993   Borislav Petkov   ide-floppy: conve...
194
  	pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
  	pc->c[7] = 255;
  	pc->c[8] = 255;
8e5551239   Borislav Petkov   ide-floppy: conve...
197
  	pc->req_xfer = 255;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  }
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
199
  /* A mode sense command is used to "sense" floppy parameters. */
0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
200
  void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  {
24a5d7033   Borislav Petkov   ide-floppy: remov...
202
  	u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
203

7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
204
  	ide_init_pc(pc);
30d670993   Borislav Petkov   ide-floppy: conve...
205
  	pc->c[0] = GPCMD_MODE_SENSE_10;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
  	pc->c[1] = 0;
4de4b9e14   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
207
  	pc->c[2] = page_code;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
  
  	switch (page_code) {
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
210
211
212
213
214
215
216
  	case IDEFLOPPY_CAPABILITIES_PAGE:
  		length += 12;
  		break;
  	case IDEFLOPPY_FLEXIBLE_DISK_PAGE:
  		length += 32;
  		break;
  	default:
7b3557262   Borislav Petkov   ide-floppy: conve...
217
218
  		printk(KERN_ERR PFX "unsupported page code in %s
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
  	}
8f6224308   Borislav Petkov   ide-floppy: repla...
220
  	put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
8e5551239   Borislav Petkov   ide-floppy: conve...
221
  	pc->req_xfer = length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  }
7b3557262   Borislav Petkov   ide-floppy: conve...
223
  static void idefloppy_create_rw_cmd(ide_drive_t *drive,
8e5551239   Borislav Petkov   ide-floppy: conve...
224
  				    struct ide_atapi_pc *pc, struct request *rq,
ae7e8ddc3   Borislav Petkov   ide-floppy: remov...
225
  				    unsigned long sector)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
227
  	struct ide_disk_obj *floppy = drive->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
230
  	int block = sector / floppy->bs_factor;
  	int blocks = rq->nr_sectors / floppy->bs_factor;
  	int cmd = rq_data_dir(rq);
7b3557262   Borislav Petkov   ide-floppy: conve...
231
232
233
  	ide_debug_log(IDE_DBG_FUNC, "%s: block: %d, blocks: %d
  ", __func__,
  		      block, blocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234

7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
235
  	ide_init_pc(pc);
ae7e8ddc3   Borislav Petkov   ide-floppy: remov...
236
237
  	pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10;
  	put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
8f6224308   Borislav Petkov   ide-floppy: repla...
238
  	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
ae7e8ddc3   Borislav Petkov   ide-floppy: remov...
239

20cd93be6   Borislav Petkov   ide-floppy: pass ...
240
  	memcpy(rq->cmd, pc->c, 12);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
  	pc->rq = rq;
b98b3409a   Borislav Petkov   ide-floppy: use s...
242
  	pc->b_count = 0;
4aff5e233   Jens Axboe   [PATCH] Split str...
243
  	if (rq->cmd_flags & REQ_RW)
6e5fa7b88   Borislav Petkov   ide-floppy: remov...
244
  		pc->flags |= PC_FLAG_WRITING;
8e5551239   Borislav Petkov   ide-floppy: conve...
245
246
  	pc->buf = NULL;
  	pc->req_xfer = pc->buf_size = blocks * floppy->block_size;
5e3310958   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
247
  	pc->flags |= PC_FLAG_DMA_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
  }
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
249
  static void idefloppy_blockpc_cmd(struct ide_disk_obj *floppy,
8e5551239   Borislav Petkov   ide-floppy: conve...
250
  		struct ide_atapi_pc *pc, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
252
  	ide_init_pc(pc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  	memcpy(pc->c, rq->cmd, sizeof(pc->c));
3d6392cfb   Jens Axboe   bsg: support for ...
254
  	pc->rq = rq;
b98b3409a   Borislav Petkov   ide-floppy: use s...
255
  	pc->b_count = 0;
3d6392cfb   Jens Axboe   bsg: support for ...
256
  	if (rq->data_len && rq_data_dir(rq) == WRITE)
6e5fa7b88   Borislav Petkov   ide-floppy: remov...
257
  		pc->flags |= PC_FLAG_WRITING;
8e5551239   Borislav Petkov   ide-floppy: conve...
258
  	pc->buf = rq->data;
3d6392cfb   Jens Axboe   bsg: support for ...
259
  	if (rq->bio)
5e3310958   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
260
  		pc->flags |= PC_FLAG_DMA_OK;
3d6392cfb   Jens Axboe   bsg: support for ...
261
262
263
264
  	/*
  	 * possibly problematic, doesn't look like ide-floppy correctly
  	 * handled scattered requests if dma fails...
  	 */
8e5551239   Borislav Petkov   ide-floppy: conve...
265
  	pc->req_xfer = pc->buf_size = rq->data_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
  }
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
267
268
  static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
  					     struct request *rq, sector_t block)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
270
  	struct ide_disk_obj *floppy = drive->driver_data;
b98b3409a   Borislav Petkov   ide-floppy: use s...
271
  	ide_hwif_t *hwif = drive->hwif;
8e5551239   Borislav Petkov   ide-floppy: conve...
272
  	struct ide_atapi_pc *pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273

7b3557262   Borislav Petkov   ide-floppy: conve...
274
275
276
277
278
  	ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, "
  		      "errors: %d
  ",
  		      __func__, rq->rq_disk ? rq->rq_disk->disk_name : "?",
  		      rq->cmd[0], rq->cmd_type, rq->errors);
b98b3409a   Borislav Petkov   ide-floppy: use s...
279

7b3557262   Borislav Petkov   ide-floppy: conve...
280
281
282
283
284
  	ide_debug_log(IDE_DBG_FUNC, "%s: sector: %ld, nr_sectors: %ld, "
  		      "current_nr_sectors: %d
  ",
  		      __func__, (long)rq->sector, rq->nr_sectors,
  		      rq->current_nr_sectors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
  
  	if (rq->errors >= ERROR_MAX) {
d652c1380   Borislav Petkov   ide-floppy: mv id...
287
288
  		if (floppy->failed_pc)
  			ide_floppy_report_error(floppy, floppy->failed_pc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
  		else
7b3557262   Borislav Petkov   ide-floppy: conve...
290
291
  			printk(KERN_ERR PFX "%s: I/O error
  ", drive->name);
c84d9bbe7   Bartlomiej Zolnierkiewicz   ide-floppy: facto...
292
  		ide_floppy_end_request(drive, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
  		return ide_stopped;
  	}
4aff5e233   Jens Axboe   [PATCH] Split str...
295
  	if (blk_fs_request(rq)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
  		if (((long)rq->sector % floppy->bs_factor) ||
  		    (rq->nr_sectors % floppy->bs_factor)) {
7b3557262   Borislav Petkov   ide-floppy: conve...
298
299
300
  			printk(KERN_ERR PFX "%s: unsupported r/w rq size
  ",
  				drive->name);
c84d9bbe7   Bartlomiej Zolnierkiewicz   ide-floppy: facto...
301
  			ide_floppy_end_request(drive, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
  			return ide_stopped;
  		}
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
304
  		pc = &floppy->queued_pc;
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
305
  		idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block);
4aff5e233   Jens Axboe   [PATCH] Split str...
306
  	} else if (blk_special_request(rq)) {
8e5551239   Borislav Petkov   ide-floppy: conve...
307
  		pc = (struct ide_atapi_pc *) rq->buffer;
4aff5e233   Jens Axboe   [PATCH] Split str...
308
  	} else if (blk_pc_request(rq)) {
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
309
  		pc = &floppy->queued_pc;
3d6392cfb   Jens Axboe   bsg: support for ...
310
  		idefloppy_blockpc_cmd(floppy, pc, rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
  	} else {
7b3557262   Borislav Petkov   ide-floppy: conve...
312
  		blk_dump_rq_flags(rq, PFX "unsupported command in queue");
c84d9bbe7   Bartlomiej Zolnierkiewicz   ide-floppy: facto...
313
  		ide_floppy_end_request(drive, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
  		return ide_stopped;
  	}
3eb76c1cc   Borislav Petkov   ide-floppy: do no...
316
317
318
319
  	if (blk_fs_request(rq) || pc->req_xfer) {
  		ide_init_sg_cmd(drive, rq);
  		ide_map_sg(drive, rq);
  	}
b98b3409a   Borislav Petkov   ide-floppy: use s...
320
321
322
  
  	pc->sg = hwif->sg_table;
  	pc->sg_cnt = hwif->sg_nents;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
  	pc->rq = rq;
5d41893c0   Bartlomiej Zolnierkiewicz   ide: add PC_FLAG_...
324

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
328
  	return idefloppy_issue_pc(drive, pc);
  }
  
  /*
8e81bbba7   Borislav Petkov   ide-floppy: remov...
329
330
   * Look at the flexible disk page parameters. We ignore the CHS capacity
   * parameters and use the LBA parameters instead.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
   */
07bd3f473   Linus Torvalds   ide-floppy: alloc...
332
333
  static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive,
  					     struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
335
  	struct ide_disk_obj *floppy = drive->driver_data;
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
336
  	struct gendisk *disk = floppy->disk;
8e81bbba7   Borislav Petkov   ide-floppy: remov...
337
  	u8 *page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
  	int capacity, lba_capacity;
8e81bbba7   Borislav Petkov   ide-floppy: remov...
339
340
  	u16 transfer_rate, sector_size, cyls, rpm;
  	u8 heads, sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341

07bd3f473   Linus Torvalds   ide-floppy: alloc...
342
  	ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
8e81bbba7   Borislav Petkov   ide-floppy: remov...
343

07bd3f473   Linus Torvalds   ide-floppy: alloc...
344
  	if (ide_queue_pc_tail(drive, disk, pc)) {
7b3557262   Borislav Petkov   ide-floppy: conve...
345
346
  		printk(KERN_ERR PFX "Can't get flexible disk page params
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
348
  		return 1;
  	}
49cac39e7   Bartlomiej Zolnierkiewicz   ide-floppy: ->{sr...
349

07bd3f473   Linus Torvalds   ide-floppy: alloc...
350
  	if (pc->buf[3] & 0x80)
da167876b   Bartlomiej Zolnierkiewicz   ide: IDE_AFLAG_WP...
351
  		drive->dev_flags |= IDE_DFLAG_WP;
49cac39e7   Bartlomiej Zolnierkiewicz   ide-floppy: ->{sr...
352
  	else
da167876b   Bartlomiej Zolnierkiewicz   ide: IDE_AFLAG_WP...
353
  		drive->dev_flags &= ~IDE_DFLAG_WP;
49cac39e7   Bartlomiej Zolnierkiewicz   ide-floppy: ->{sr...
354

da167876b   Bartlomiej Zolnierkiewicz   ide: IDE_AFLAG_WP...
355
  	set_disk_ro(disk, !!(drive->dev_flags & IDE_DFLAG_WP));
49cac39e7   Bartlomiej Zolnierkiewicz   ide-floppy: ->{sr...
356

07bd3f473   Linus Torvalds   ide-floppy: alloc...
357
  	page = &pc->buf[8];
8e81bbba7   Borislav Petkov   ide-floppy: remov...
358

07bd3f473   Linus Torvalds   ide-floppy: alloc...
359
360
361
362
363
364
  	transfer_rate = be16_to_cpup((__be16 *)&pc->buf[8 + 2]);
  	sector_size   = be16_to_cpup((__be16 *)&pc->buf[8 + 6]);
  	cyls          = be16_to_cpup((__be16 *)&pc->buf[8 + 8]);
  	rpm           = be16_to_cpup((__be16 *)&pc->buf[8 + 28]);
  	heads         = pc->buf[8 + 4];
  	sectors       = pc->buf[8 + 5];
8e81bbba7   Borislav Petkov   ide-floppy: remov...
365
366
367
368
  
  	capacity = cyls * heads * sectors * sector_size;
  
  	if (memcmp(page, &floppy->flexible_disk_page, 32))
7b3557262   Borislav Petkov   ide-floppy: conve...
369
  		printk(KERN_INFO PFX "%s: %dkB, %d/%d/%d CHS, %d kBps, "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
  				"%d sector size, %d rpm
  ",
8e81bbba7   Borislav Petkov   ide-floppy: remov...
372
373
374
375
376
377
378
  				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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
  	lba_capacity = floppy->blocks * floppy->block_size;
8e81bbba7   Borislav Petkov   ide-floppy: remov...
380

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
  	if (capacity < lba_capacity) {
7b3557262   Borislav Petkov   ide-floppy: conve...
382
  		printk(KERN_NOTICE PFX "%s: The disk reports a capacity of %d "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
384
385
  			"bytes, but the drive only handles %d
  ",
  			drive->name, lba_capacity, capacity);
8e81bbba7   Borislav Petkov   ide-floppy: remov...
386
387
  		floppy->blocks = floppy->block_size ?
  			capacity / floppy->block_size : 0;
6f84083bb   Bartlomiej Zolnierkiewicz   ide-floppy: use d...
388
  		drive->capacity64 = floppy->blocks * floppy->bs_factor;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  	}
6f84083bb   Bartlomiej Zolnierkiewicz   ide-floppy: use d...
390

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
392
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  /*
194ec0c07   Borislav Petkov   ide-floppy: remov...
394
395
   * Determine if a media is present in the floppy drive, and if so, its LBA
   * capacity.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
   */
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
397
  static int ide_floppy_get_capacity(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
399
  	struct ide_disk_obj *floppy = drive->driver_data;
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
400
  	struct gendisk *disk = floppy->disk;
8e5551239   Borislav Petkov   ide-floppy: conve...
401
  	struct ide_atapi_pc pc;
194ec0c07   Borislav Petkov   ide-floppy: remov...
402
403
404
  	u8 *cap_desc;
  	u8 header_len, desc_cnt;
  	int i, rc = 1, blocks, length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
  	drive->bios_cyl = 0;
  	drive->bios_head = drive->bios_sect = 0;
fdb77da4c   Alan Cox   ide-floppy: Fix u...
407
408
  	floppy->blocks = 0;
  	floppy->bs_factor = 1;
6f84083bb   Bartlomiej Zolnierkiewicz   ide-floppy: use d...
409
  	drive->capacity64 = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410

0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
411
  	ide_floppy_create_read_capacity_cmd(&pc);
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
412
  	if (ide_queue_pc_tail(drive, disk, &pc)) {
7b3557262   Borislav Petkov   ide-floppy: conve...
413
414
  		printk(KERN_ERR PFX "Can't get floppy parameters
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
  		return 1;
  	}
8e5551239   Borislav Petkov   ide-floppy: conve...
417
418
  	header_len = pc.buf[3];
  	cap_desc = &pc.buf[4];
194ec0c07   Borislav Petkov   ide-floppy: remov...
419
420
421
422
  	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
  
  	for (i = 0; i < desc_cnt; i++) {
  		unsigned int desc_start = 4 + i*8;
85ae98a3d   Harvey Harrison   ide: endian annot...
423
424
  		blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
  		length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
194ec0c07   Borislav Petkov   ide-floppy: remov...
425

7b3557262   Borislav Petkov   ide-floppy: conve...
426
427
428
429
  		ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, "
  			      "%d sector size
  ",
  			      i, blocks * length / 1024, blocks, length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430

194ec0c07   Borislav Petkov   ide-floppy: remov...
431
432
433
434
435
  		if (i)
  			continue;
  		/*
  		 * the code below is valid only for the 1st descriptor, ie i=0
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436

8e5551239   Borislav Petkov   ide-floppy: conve...
437
  		switch (pc.buf[desc_start + 4] & 0x03) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
  		/* Clik! drive returns this instead of CAPACITY_CURRENT */
  		case CAPACITY_UNFORMATTED:
ea68d270f   Borislav Petkov   ide-floppy: conve...
440
  			if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
441
  				/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
443
444
445
446
447
  				 * If it is not a clik drive, break out
  				 * (maintains previous driver behaviour)
  				 */
  				break;
  		case CAPACITY_CURRENT:
  			/* Normal Zip/LS-120 disks */
194ec0c07   Borislav Petkov   ide-floppy: remov...
448
  			if (memcmp(cap_desc, &floppy->cap_desc, 8))
7b3557262   Borislav Petkov   ide-floppy: conve...
449
450
451
452
453
  				printk(KERN_INFO PFX "%s: %dkB, %d blocks, %d "
  				       "sector size
  ",
  				       drive->name, blocks * length / 1024,
  				       blocks, length);
194ec0c07   Borislav Petkov   ide-floppy: remov...
454
  			memcpy(&floppy->cap_desc, cap_desc, 8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
  			if (!length || length % 512) {
7b3557262   Borislav Petkov   ide-floppy: conve...
456
457
458
  				printk(KERN_NOTICE PFX "%s: %d bytes block size"
  				       " not supported
  ", drive->name, length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
  			} else {
194ec0c07   Borislav Petkov   ide-floppy: remov...
460
461
462
463
  				floppy->blocks = blocks;
  				floppy->block_size = length;
  				floppy->bs_factor = length / 512;
  				if (floppy->bs_factor != 1)
7b3557262   Borislav Petkov   ide-floppy: conve...
464
465
466
467
468
  					printk(KERN_NOTICE PFX "%s: Warning: "
  					       "non 512 bytes block size not "
  					       "fully supported
  ",
  					       drive->name);
6f84083bb   Bartlomiej Zolnierkiewicz   ide-floppy: use d...
469
470
  				drive->capacity64 =
  					floppy->blocks * floppy->bs_factor;
194ec0c07   Borislav Petkov   ide-floppy: remov...
471
  				rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
474
475
476
477
478
  			}
  			break;
  		case CAPACITY_NO_CARTRIDGE:
  			/*
  			 * This is a KERN_ERR so it appears on screen
  			 * for the user to see
  			 */
7b3557262   Borislav Petkov   ide-floppy: conve...
479
480
481
  			printk(KERN_ERR PFX "%s: No disk in drive
  ",
  			       drive->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
  			break;
  		case CAPACITY_INVALID:
7b3557262   Borislav Petkov   ide-floppy: conve...
484
  			printk(KERN_ERR PFX "%s: Invalid capacity for disk "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
486
487
488
  				"in drive
  ", drive->name);
  			break;
  		}
7b3557262   Borislav Petkov   ide-floppy: conve...
489
490
491
  		ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d
  ",
  			      pc.buf[desc_start + 4] & 0x03);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
493
494
  	}
  
  	/* Clik! disk does not support get_flexible_disk_page */
ea68d270f   Borislav Petkov   ide-floppy: conve...
495
  	if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
07bd3f473   Linus Torvalds   ide-floppy: alloc...
496
  		(void) ide_floppy_get_flexible_disk_page(drive, &pc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
499
  	return rc;
  }
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
500
  static void ide_floppy_setup(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
  {
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
502
  	struct ide_disk_obj *floppy = drive->driver_data;
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
503
  	u16 *id = drive->id;
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
504

85e39035c   Bartlomiej Zolnierkiewicz   ide: add ->pc_{up...
505
506
507
  	drive->pc_callback	 = ide_floppy_callback;
  	drive->pc_update_buffers = idefloppy_update_buffers;
  	drive->pc_io_buffers	 = ide_io_buffers;
3ad6776cc   Borislav Petkov   ide-floppy: remov...
508

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
  	/*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
510
511
  	 * We used to check revisions here. At this point however I'm giving up.
  	 * Just assume they are all broken, its easier.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512
  	 *
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
513
514
515
516
  	 * 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.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
  	 */
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
518
  	if (!strncmp((char *)&id[ATA_ID_PROD], "IOMEGA ZIP 100 ATAPI", 20)) {
ea68d270f   Borislav Petkov   ide-floppy: conve...
519
  		drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
  		/* This value will be visible in the /proc/ide/hdx/settings */
baf08f0be   Bartlomiej Zolnierkiewicz   ide: make ide_tra...
521
  		drive->pc_delay = IDEFLOPPY_PC_DELAY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
523
524
525
  		blk_queue_max_sectors(drive->queue, 64);
  	}
  
  	/*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
526
527
528
  	 * Guess what? The IOMEGA Clik! drive also needs the above fix. It makes
  	 * nasty clicking noises without it, so please don't remove this.
  	 */
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
529
  	if (strncmp((char *)&id[ATA_ID_PROD], "IOMEGA Clik!", 11) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
  		blk_queue_max_sectors(drive->queue, 64);
ea68d270f   Borislav Petkov   ide-floppy: conve...
531
  		drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE;
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
532
  		/* IOMEGA Clik! drives do not support lock/unlock commands */
42619d35c   Bartlomiej Zolnierkiewicz   ide: remove IDE_A...
533
  		drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
  	}
194ec0c07   Borislav Petkov   ide-floppy: remov...
535
  	(void) ide_floppy_get_capacity(drive);
1e874f448   Bartlomiej Zolnierkiewicz   ide: call ide_pro...
536
537
  
  	ide_proc_register_driver(drive, floppy->driver);
ae9f9f073   Bartlomiej Zolnierkiewicz   ide-{disk,floppy}...
538
539
  
  	drive->dev_flags |= IDE_DFLAG_ATTACH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
  }
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
  
  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,
  	.end_request	= ide_floppy_end_request,
  	.ioctl		= ide_floppy_ioctl,
  };