Blame view

drivers/ide/ide-floppy.c 14.4 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
  #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>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
  #include <linux/cdrom.h>
  #include <linux/ide.h>
3ceca727f   Bartlomiej Zolnierkiewicz   ide: include <lin...
29
  #include <linux/hdreg.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  #include <linux/bitops.h>
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
31
  #include <linux/mutex.h>
b98b3409a   Borislav Petkov   ide-floppy: use s...
32
  #include <linux/scatterlist.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

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

03a2faaea   Bartlomiej Zolnierkiewicz   ide: return reque...
56
  static int ide_floppy_callback(ide_drive_t *drive, int dsc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
58
  	struct ide_disk_obj *floppy = drive->driver_data;
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
59
  	struct ide_atapi_pc *pc = drive->pc;
313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
60
  	struct request *rq = pc->rq;
81f493823   Borislav Petkov   ide-floppy: merge...
61
  	int uptodate = pc->error ? 0 : 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62

088b1b886   Borislav Petkov   ide: improve debu...
63
  	ide_debug_log(IDE_DBG_FUNC, "enter");
bcc77d9cc   Borislav Petkov   ide-floppy: clean...
64

5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
65
66
  	if (drive->failed_pc == pc)
  		drive->failed_pc = NULL;
dd2e9a032   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
67

81f493823   Borislav Petkov   ide-floppy: merge...
68
  	if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 ||
f17bfe79e   Jiri Slaby   IDE: ide-floppy, ...
69
  	    rq->cmd_type == REQ_TYPE_BLOCK_PC)
81f493823   Borislav Petkov   ide-floppy: merge...
70
71
  		uptodate = 1; /* FIXME */
  	else if (pc->c[0] == GPCMD_REQUEST_SENSE) {
ae3a8387b   Borislav Petkov   ide-atapi: use lo...
72
73
  
  		u8 *buf = bio_data(rq->bio);
a6ff2d3b0   Borislav Petkov   ide-floppy: remov...
74

81f493823   Borislav Petkov   ide-floppy: merge...
75
76
77
78
79
80
  		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...
81

5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
82
  			if (drive->failed_pc)
088b1b886   Borislav Petkov   ide: improve debu...
83
  				ide_debug_log(IDE_DBG_PC, "pc = %x",
5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
84
  					      drive->failed_pc->c[0]);
bcc77d9cc   Borislav Petkov   ide-floppy: clean...
85

7b3557262   Borislav Petkov   ide-floppy: conve...
86
  			ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x,"
088b1b886   Borislav Petkov   ide: improve debu...
87
  				      "ascq = %x", floppy->sense_key,
7b3557262   Borislav Petkov   ide-floppy: conve...
88
  				      floppy->asc, floppy->ascq);
81f493823   Borislav Petkov   ide-floppy: merge...
89
  		} else
7b3557262   Borislav Petkov   ide-floppy: conve...
90
91
92
  			printk(KERN_ERR PFX "Error in REQUEST SENSE itself - "
  			       "Aborting request!
  ");
81f493823   Borislav Petkov   ide-floppy: merge...
93
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94

33659ebba   Christoph Hellwig   block: remove wra...
95
  	if (rq->cmd_type == REQ_TYPE_SPECIAL)
313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
96
  		rq->errors = uptodate ? 0 : IDE_DRV_ERROR_GENERAL;
03a2faaea   Bartlomiej Zolnierkiewicz   ide: return reque...
97
98
  
  	return uptodate;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  }
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
100
  static void ide_floppy_report_error(struct ide_disk_obj *floppy,
8e5551239   Borislav Petkov   ide-floppy: conve...
101
  				    struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  {
25985edce   Lucas De Marchi   Fix common misspe...
103
  	/* suppress error messages resulting from Medium not present */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
  	if (floppy->sense_key == 0x02 &&
  	    floppy->asc       == 0x3a &&
  	    floppy->ascq      == 0x00)
d652c1380   Borislav Petkov   ide-floppy: mv id...
107
  		return;
7b3557262   Borislav Petkov   ide-floppy: conve...
108
  	printk(KERN_ERR PFX "%s: I/O error, pc = %2x, key = %2x, "
d652c1380   Borislav Petkov   ide-floppy: mv id...
109
110
111
112
  			"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
113
  }
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
114
115
116
  static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive,
  					   struct ide_cmd *cmd,
  					   struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
118
  	struct ide_disk_obj *floppy = drive->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119

5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
120
  	if (drive->failed_pc == NULL &&
30d670993   Borislav Petkov   ide-floppy: conve...
121
  	    pc->c[0] != GPCMD_REQUEST_SENSE)
5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
122
  		drive->failed_pc = pc;
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
123

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

757ced898   Borislav Petkov   ide-floppy: remov...
127
  	if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
eb6a61bb9   Tejun Heo   ide-atapi,tape,fl...
128
  		unsigned int done = blk_rq_bytes(drive->hwif->rq);
6e5fa7b88   Borislav Petkov   ide-floppy: remov...
129
  		if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
757ced898   Borislav Petkov   ide-floppy: remov...
130
  			ide_floppy_report_error(floppy, pc);
eb6a61bb9   Tejun Heo   ide-atapi,tape,fl...
131

757ced898   Borislav Petkov   ide-floppy: remov...
132
  		/* Giving up */
c152cc1a9   Bartlomiej Zolnierkiewicz   ide: use ->end_re...
133
  		pc->error = IDE_DRV_ERROR_GENERAL;
757ced898   Borislav Petkov   ide-floppy: remov...
134

5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
135
  		drive->failed_pc = NULL;
b14c72127   Bartlomiej Zolnierkiewicz   ide: drop dsc_han...
136
  		drive->pc_callback(drive, 0);
eb6a61bb9   Tejun Heo   ide-atapi,tape,fl...
137
  		ide_complete_rq(drive, -EIO, done);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
  		return ide_stopped;
  	}
088b1b886   Borislav Petkov   ide: improve debu...
140
  	ide_debug_log(IDE_DBG_FUNC, "retry #%d", pc->retries);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
  
  	pc->retries++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143

b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
144
  	return ide_issue_pc(drive, cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  }
0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
146
  void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
148
  	ide_init_pc(pc);
30d670993   Borislav Petkov   ide-floppy: conve...
149
  	pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
  	pc->c[7] = 255;
  	pc->c[8] = 255;
8e5551239   Borislav Petkov   ide-floppy: conve...
152
  	pc->req_xfer = 255;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  }
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
154
  /* A mode sense command is used to "sense" floppy parameters. */
0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
155
  void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
  {
24a5d7033   Borislav Petkov   ide-floppy: remov...
157
  	u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
158

7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
159
  	ide_init_pc(pc);
30d670993   Borislav Petkov   ide-floppy: conve...
160
  	pc->c[0] = GPCMD_MODE_SENSE_10;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  	pc->c[1] = 0;
4de4b9e14   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
162
  	pc->c[2] = page_code;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
  
  	switch (page_code) {
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
165
166
167
168
169
170
171
  	case IDEFLOPPY_CAPABILITIES_PAGE:
  		length += 12;
  		break;
  	case IDEFLOPPY_FLEXIBLE_DISK_PAGE:
  		length += 32;
  		break;
  	default:
7b3557262   Borislav Petkov   ide-floppy: conve...
172
173
  		printk(KERN_ERR PFX "unsupported page code in %s
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
  	}
8f6224308   Borislav Petkov   ide-floppy: repla...
175
  	put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
8e5551239   Borislav Petkov   ide-floppy: conve...
176
  	pc->req_xfer = length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  }
7b3557262   Borislav Petkov   ide-floppy: conve...
178
  static void idefloppy_create_rw_cmd(ide_drive_t *drive,
8e5551239   Borislav Petkov   ide-floppy: conve...
179
  				    struct ide_atapi_pc *pc, struct request *rq,
ae7e8ddc3   Borislav Petkov   ide-floppy: remov...
180
  				    unsigned long sector)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
182
  	struct ide_disk_obj *floppy = drive->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  	int block = sector / floppy->bs_factor;
9780e2dd8   Tejun Heo   ide: convert to r...
184
  	int blocks = blk_rq_sectors(rq) / floppy->bs_factor;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
  	int cmd = rq_data_dir(rq);
088b1b886   Borislav Petkov   ide: improve debu...
186
  	ide_debug_log(IDE_DBG_FUNC, "block: %d, blocks: %d", block, blocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187

7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
188
  	ide_init_pc(pc);
ae7e8ddc3   Borislav Petkov   ide-floppy: remov...
189
190
  	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...
191
  	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
ae7e8ddc3   Borislav Petkov   ide-floppy: remov...
192

20cd93be6   Borislav Petkov   ide-floppy: pass ...
193
  	memcpy(rq->cmd, pc->c, 12);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
  	pc->rq = rq;
7b6d91dae   Christoph Hellwig   block: unify flag...
195
  	if (rq->cmd_flags & REQ_WRITE)
6e5fa7b88   Borislav Petkov   ide-floppy: remov...
196
  		pc->flags |= PC_FLAG_WRITING;
19f52a784   Borislav Petkov   ide-atapi: remove...
197

5e3310958   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
198
  	pc->flags |= PC_FLAG_DMA_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  }
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
200
  static void idefloppy_blockpc_cmd(struct ide_disk_obj *floppy,
8e5551239   Borislav Petkov   ide-floppy: conve...
201
  		struct ide_atapi_pc *pc, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
203
  	ide_init_pc(pc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
  	memcpy(pc->c, rq->cmd, sizeof(pc->c));
3d6392cfb   Jens Axboe   bsg: support for ...
205
  	pc->rq = rq;
34b7d2c95   Tejun Heo   ide: cleanup rq->...
206
  	if (blk_rq_bytes(rq)) {
5e3310958   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
207
  		pc->flags |= PC_FLAG_DMA_OK;
8968932e5   Tejun Heo   ide-floppy: block...
208
209
210
  		if (rq_data_dir(rq) == WRITE)
  			pc->flags |= PC_FLAG_WRITING;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  }
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
212
213
  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
214
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
215
  	struct ide_disk_obj *floppy = drive->driver_data;
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
216
  	struct ide_cmd cmd;
8e5551239   Borislav Petkov   ide-floppy: conve...
217
  	struct ide_atapi_pc *pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218

349d12a1f   Bartlomiej Zolnierkiewicz   ide-floppy: use i...
219
220
  	ide_debug_log(IDE_DBG_FUNC, "enter, cmd: 0x%x
  ", rq->cmd[0]);
088b1b886   Borislav Petkov   ide: improve debu...
221
222
223
224
  	if (drive->debug_mask & IDE_DBG_RQ)
  		blk_dump_rq_flags(rq, (rq->rq_disk
  					? rq->rq_disk->disk_name
  					: "dev?"));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
  
  	if (rq->errors >= ERROR_MAX) {
313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
227
  		if (drive->failed_pc) {
5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
228
  			ide_floppy_report_error(floppy, drive->failed_pc);
313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
229
230
  			drive->failed_pc = NULL;
  		} else
7b3557262   Borislav Petkov   ide-floppy: conve...
231
232
  			printk(KERN_ERR PFX "%s: I/O error
  ", drive->name);
33659ebba   Christoph Hellwig   block: remove wra...
233
  		if (rq->cmd_type == REQ_TYPE_SPECIAL) {
6902a5331   Bartlomiej Zolnierkiewicz   ide: pass error v...
234
  			rq->errors = 0;
f974b196f   Bartlomiej Zolnierkiewicz   ide: pass number ...
235
  			ide_complete_rq(drive, 0, blk_rq_bytes(rq));
313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
236
237
238
  			return ide_stopped;
  		} else
  			goto out_end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
  	}
33659ebba   Christoph Hellwig   block: remove wra...
240
241
242
  
  	switch (rq->cmd_type) {
  	case REQ_TYPE_FS:
9780e2dd8   Tejun Heo   ide: convert to r...
243
244
  		if (((long)blk_rq_pos(rq) % floppy->bs_factor) ||
  		    (blk_rq_sectors(rq) % floppy->bs_factor)) {
7b3557262   Borislav Petkov   ide-floppy: conve...
245
246
247
  			printk(KERN_ERR PFX "%s: unsupported r/w rq size
  ",
  				drive->name);
313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
248
  			goto out_end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
  		}
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
250
  		pc = &floppy->queued_pc;
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
251
  		idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block);
33659ebba   Christoph Hellwig   block: remove wra...
252
253
254
  		break;
  	case REQ_TYPE_SPECIAL:
  	case REQ_TYPE_SENSE:
ac0b0113d   Tejun Heo   ide-atapi: don't ...
255
  		pc = (struct ide_atapi_pc *)rq->special;
33659ebba   Christoph Hellwig   block: remove wra...
256
257
  		break;
  	case REQ_TYPE_BLOCK_PC:
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
258
  		pc = &floppy->queued_pc;
3d6392cfb   Jens Axboe   bsg: support for ...
259
  		idefloppy_blockpc_cmd(floppy, pc, rq);
33659ebba   Christoph Hellwig   block: remove wra...
260
261
  		break;
  	default:
2c7eaa43c   Bartlomiej Zolnierkiewicz   ide: BUG() on unk...
262
  		BUG();
33659ebba   Christoph Hellwig   block: remove wra...
263
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264

068753203   Borislav Petkov   ide-atapi: conver...
265
  	ide_prep_sense(drive, rq);
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
266
  	memset(&cmd, 0, sizeof(cmd));
229816941   Bartlomiej Zolnierkiewicz   ide: pass command...
267
  	if (rq_data_dir(rq))
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
268
269
270
  		cmd.tf_flags |= IDE_TFLAG_WRITE;
  
  	cmd.rq = rq;
229816941   Bartlomiej Zolnierkiewicz   ide: pass command...
271

33659ebba   Christoph Hellwig   block: remove wra...
272
  	if (rq->cmd_type == REQ_TYPE_FS || blk_rq_bytes(rq)) {
dfb7e621f   Borislav Petkov   ide-atapi: switch...
273
  		ide_init_sg_cmd(&cmd, blk_rq_bytes(rq));
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
274
  		ide_map_sg(drive, &cmd);
3eb76c1cc   Borislav Petkov   ide-floppy: do no...
275
  	}
b98b3409a   Borislav Petkov   ide-floppy: use s...
276

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
  	pc->rq = rq;
5d41893c0   Bartlomiej Zolnierkiewicz   ide: add PC_FLAG_...
278

b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
279
  	return ide_floppy_issue_pc(drive, &cmd, pc);
313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
280
281
  out_end:
  	drive->failed_pc = NULL;
33659ebba   Christoph Hellwig   block: remove wra...
282
  	if (rq->cmd_type != REQ_TYPE_FS && rq->errors == 0)
89f78b326   Bartlomiej Zolnierkiewicz   ide: move rq->err...
283
  		rq->errors = -EIO;
5e955245d   Bartlomiej Zolnierkiewicz   ide: always kill ...
284
  	ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
285
  	return ide_stopped;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
288
  }
  
  /*
8e81bbba7   Borislav Petkov   ide-floppy: remov...
289
290
   * 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
291
   */
07bd3f473   Linus Torvalds   ide-floppy: alloc...
292
293
  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
294
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
295
  	struct ide_disk_obj *floppy = drive->driver_data;
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
296
  	struct gendisk *disk = floppy->disk;
d9a683076   Borislav Petkov   ide-floppy/ide_fl...
297
  	u8 *page, buf[40];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
  	int capacity, lba_capacity;
8e81bbba7   Borislav Petkov   ide-floppy: remov...
299
300
  	u16 transfer_rate, sector_size, cyls, rpm;
  	u8 heads, sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301

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

d9a683076   Borislav Petkov   ide-floppy/ide_fl...
304
  	if (ide_queue_pc_tail(drive, disk, pc, buf, pc->req_xfer)) {
7b3557262   Borislav Petkov   ide-floppy: conve...
305
306
  		printk(KERN_ERR PFX "Can't get flexible disk page params
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
  		return 1;
  	}
49cac39e7   Bartlomiej Zolnierkiewicz   ide-floppy: ->{sr...
309

d9a683076   Borislav Petkov   ide-floppy/ide_fl...
310
  	if (buf[3] & 0x80)
da167876b   Bartlomiej Zolnierkiewicz   ide: IDE_AFLAG_WP...
311
  		drive->dev_flags |= IDE_DFLAG_WP;
49cac39e7   Bartlomiej Zolnierkiewicz   ide-floppy: ->{sr...
312
  	else
da167876b   Bartlomiej Zolnierkiewicz   ide: IDE_AFLAG_WP...
313
  		drive->dev_flags &= ~IDE_DFLAG_WP;
49cac39e7   Bartlomiej Zolnierkiewicz   ide-floppy: ->{sr...
314

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

d9a683076   Borislav Petkov   ide-floppy/ide_fl...
317
  	page = &buf[8];
8e81bbba7   Borislav Petkov   ide-floppy: remov...
318

d9a683076   Borislav Petkov   ide-floppy/ide_fl...
319
320
321
322
323
324
  	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];
8e81bbba7   Borislav Petkov   ide-floppy: remov...
325
326
327
328
  
  	capacity = cyls * heads * sectors * sector_size;
  
  	if (memcmp(page, &floppy->flexible_disk_page, 32))
7b3557262   Borislav Petkov   ide-floppy: conve...
329
  		printk(KERN_INFO PFX "%s: %dkB, %d/%d/%d CHS, %d kBps, "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
331
  				"%d sector size, %d rpm
  ",
8e81bbba7   Borislav Petkov   ide-floppy: remov...
332
333
334
335
336
337
338
  				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
339
  	lba_capacity = floppy->blocks * floppy->block_size;
8e81bbba7   Borislav Petkov   ide-floppy: remov...
340

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
  	if (capacity < lba_capacity) {
7b3557262   Borislav Petkov   ide-floppy: conve...
342
  		printk(KERN_NOTICE PFX "%s: The disk reports a capacity of %d "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
345
  			"bytes, but the drive only handles %d
  ",
  			drive->name, lba_capacity, capacity);
8e81bbba7   Borislav Petkov   ide-floppy: remov...
346
347
  		floppy->blocks = floppy->block_size ?
  			capacity / floppy->block_size : 0;
6f84083bb   Bartlomiej Zolnierkiewicz   ide-floppy: use d...
348
  		drive->capacity64 = floppy->blocks * floppy->bs_factor;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
  	}
6f84083bb   Bartlomiej Zolnierkiewicz   ide-floppy: use d...
350

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
  /*
194ec0c07   Borislav Petkov   ide-floppy: remov...
354
355
   * Determine if a media is present in the floppy drive, and if so, its LBA
   * capacity.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
   */
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
357
  static int ide_floppy_get_capacity(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
  {
0df962777   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
359
  	struct ide_disk_obj *floppy = drive->driver_data;
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
360
  	struct gendisk *disk = floppy->disk;
8e5551239   Borislav Petkov   ide-floppy: conve...
361
  	struct ide_atapi_pc pc;
194ec0c07   Borislav Petkov   ide-floppy: remov...
362
  	u8 *cap_desc;
41fa9f863   Bartlomiej Zolnierkiewicz   ide: decrease siz...
363
  	u8 pc_buf[256], header_len, desc_cnt;
194ec0c07   Borislav Petkov   ide-floppy: remov...
364
  	int i, rc = 1, blocks, length;
349d12a1f   Bartlomiej Zolnierkiewicz   ide-floppy: use i...
365
  	ide_debug_log(IDE_DBG_FUNC, "enter");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
367
  	drive->bios_cyl = 0;
  	drive->bios_head = drive->bios_sect = 0;
fdb77da4c   Alan Cox   ide-floppy: Fix u...
368
369
  	floppy->blocks = 0;
  	floppy->bs_factor = 1;
6f84083bb   Bartlomiej Zolnierkiewicz   ide-floppy: use d...
370
  	drive->capacity64 = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371

0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
372
  	ide_floppy_create_read_capacity_cmd(&pc);
b13345f39   Borislav Petkov   ide-atapi: add a ...
373
  	if (ide_queue_pc_tail(drive, disk, &pc, pc_buf, pc.req_xfer)) {
7b3557262   Borislav Petkov   ide-floppy: conve...
374
375
  		printk(KERN_ERR PFX "Can't get floppy parameters
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
  		return 1;
  	}
b13345f39   Borislav Petkov   ide-atapi: add a ...
378
379
  	header_len = pc_buf[3];
  	cap_desc = &pc_buf[4];
194ec0c07   Borislav Petkov   ide-floppy: remov...
380
381
382
383
  	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
  
  	for (i = 0; i < desc_cnt; i++) {
  		unsigned int desc_start = 4 + i*8;
b13345f39   Borislav Petkov   ide-atapi: add a ...
384
385
  		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...
386

7b3557262   Borislav Petkov   ide-floppy: conve...
387
  		ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, "
088b1b886   Borislav Petkov   ide: improve debu...
388
389
390
  					     "%d sector size",
  					     i, blocks * length / 1024,
  					     blocks, length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391

194ec0c07   Borislav Petkov   ide-floppy: remov...
392
393
394
395
396
  		if (i)
  			continue;
  		/*
  		 * the code below is valid only for the 1st descriptor, ie i=0
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397

b13345f39   Borislav Petkov   ide-atapi: add a ...
398
  		switch (pc_buf[desc_start + 4] & 0x03) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
  		/* Clik! drive returns this instead of CAPACITY_CURRENT */
  		case CAPACITY_UNFORMATTED:
ea68d270f   Borislav Petkov   ide-floppy: conve...
401
  			if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
402
  				/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
406
407
408
  				 * 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...
409
  			if (memcmp(cap_desc, &floppy->cap_desc, 8))
7b3557262   Borislav Petkov   ide-floppy: conve...
410
411
412
413
414
  				printk(KERN_INFO PFX "%s: %dkB, %d blocks, %d "
  				       "sector size
  ",
  				       drive->name, blocks * length / 1024,
  				       blocks, length);
194ec0c07   Borislav Petkov   ide-floppy: remov...
415
  			memcpy(&floppy->cap_desc, cap_desc, 8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
  			if (!length || length % 512) {
7b3557262   Borislav Petkov   ide-floppy: conve...
417
418
419
  				printk(KERN_NOTICE PFX "%s: %d bytes block size"
  				       " not supported
  ", drive->name, length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
  			} else {
194ec0c07   Borislav Petkov   ide-floppy: remov...
421
422
423
424
  				floppy->blocks = blocks;
  				floppy->block_size = length;
  				floppy->bs_factor = length / 512;
  				if (floppy->bs_factor != 1)
7b3557262   Borislav Petkov   ide-floppy: conve...
425
426
427
428
429
  					printk(KERN_NOTICE PFX "%s: Warning: "
  					       "non 512 bytes block size not "
  					       "fully supported
  ",
  					       drive->name);
6f84083bb   Bartlomiej Zolnierkiewicz   ide-floppy: use d...
430
431
  				drive->capacity64 =
  					floppy->blocks * floppy->bs_factor;
194ec0c07   Borislav Petkov   ide-floppy: remov...
432
  				rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
437
438
439
  			}
  			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...
440
441
442
  			printk(KERN_ERR PFX "%s: No disk in drive
  ",
  			       drive->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
444
  			break;
  		case CAPACITY_INVALID:
7b3557262   Borislav Petkov   ide-floppy: conve...
445
  			printk(KERN_ERR PFX "%s: Invalid capacity for disk "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
447
448
449
  				"in drive
  ", drive->name);
  			break;
  		}
088b1b886   Borislav Petkov   ide: improve debu...
450
  		ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d",
b13345f39   Borislav Petkov   ide-atapi: add a ...
451
  					     pc_buf[desc_start + 4] & 0x03);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452
453
454
  	}
  
  	/* Clik! disk does not support get_flexible_disk_page */
ea68d270f   Borislav Petkov   ide-floppy: conve...
455
  	if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
07bd3f473   Linus Torvalds   ide-floppy: alloc...
456
  		(void) ide_floppy_get_flexible_disk_page(drive, &pc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
  	return rc;
  }
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
460
  static void ide_floppy_setup(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
  {
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
462
  	struct ide_disk_obj *floppy = drive->driver_data;
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
463
  	u16 *id = drive->id;
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
464

85e39035c   Bartlomiej Zolnierkiewicz   ide: add ->pc_{up...
465
  	drive->pc_callback	 = ide_floppy_callback;
3ad6776cc   Borislav Petkov   ide-floppy: remov...
466

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
  	/*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
468
469
  	 * 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
470
  	 *
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
471
472
473
474
  	 * 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
475
  	 */
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
476
  	if (!strncmp((char *)&id[ATA_ID_PROD], "IOMEGA ZIP 100 ATAPI", 20)) {
ea68d270f   Borislav Petkov   ide-floppy: conve...
477
  		drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
  		/* This value will be visible in the /proc/ide/hdx/settings */
baf08f0be   Bartlomiej Zolnierkiewicz   ide: make ide_tra...
479
  		drive->pc_delay = IDEFLOPPY_PC_DELAY;
086fa5ff0   Martin K. Petersen   block: Rename blk...
480
  		blk_queue_max_hw_sectors(drive->queue, 64);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
  	}
  
  	/*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
484
485
486
  	 * 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->...
487
  	if (strncmp((char *)&id[ATA_ID_PROD], "IOMEGA Clik!", 11) == 0) {
086fa5ff0   Martin K. Petersen   block: Rename blk...
488
  		blk_queue_max_hw_sectors(drive->queue, 64);
ea68d270f   Borislav Petkov   ide-floppy: conve...
489
  		drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE;
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
490
  		/* IOMEGA Clik! drives do not support lock/unlock commands */
42619d35c   Bartlomiej Zolnierkiewicz   ide: remove IDE_A...
491
  		drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
  	}
194ec0c07   Borislav Petkov   ide-floppy: remov...
493
  	(void) ide_floppy_get_capacity(drive);
1e874f448   Bartlomiej Zolnierkiewicz   ide: call ide_pro...
494
495
  
  	ide_proc_register_driver(drive, floppy->driver);
ae9f9f073   Bartlomiej Zolnierkiewicz   ide-{disk,floppy}...
496
497
  
  	drive->dev_flags |= IDE_DFLAG_ATTACH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
  }
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
  
  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,
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
526
527
  	.ioctl		= ide_floppy_ioctl,
  };