diff options
Diffstat (limited to 'drivers/ide/ide-floppy.c')
-rw-r--r-- | drivers/ide/ide-floppy.c | 156 |
1 files changed, 64 insertions, 92 deletions
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 317ec62c33d4..7ae662334835 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -61,50 +61,6 @@ | |||
61 | */ | 61 | */ |
62 | #define IDEFLOPPY_PC_DELAY (HZ/20) /* default delay for ZIP 100 (50ms) */ | 62 | #define IDEFLOPPY_PC_DELAY (HZ/20) /* default delay for ZIP 100 (50ms) */ |
63 | 63 | ||
64 | /* Error code returned in rq->errors to the higher part of the driver. */ | ||
65 | #define IDEFLOPPY_ERROR_GENERAL 101 | ||
66 | |||
67 | /* | ||
68 | * Used to finish servicing a request. For read/write requests, we will call | ||
69 | * ide_end_request to pass to the next buffer. | ||
70 | */ | ||
71 | static int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs) | ||
72 | { | ||
73 | struct ide_disk_obj *floppy = drive->driver_data; | ||
74 | struct request *rq = drive->hwif->rq; | ||
75 | int error; | ||
76 | |||
77 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | ||
78 | |||
79 | switch (uptodate) { | ||
80 | case 0: | ||
81 | error = IDEFLOPPY_ERROR_GENERAL; | ||
82 | break; | ||
83 | |||
84 | case 1: | ||
85 | error = 0; | ||
86 | break; | ||
87 | |||
88 | default: | ||
89 | error = uptodate; | ||
90 | } | ||
91 | |||
92 | if (error) | ||
93 | floppy->failed_pc = NULL; | ||
94 | /* Why does this happen? */ | ||
95 | if (!rq) | ||
96 | return 0; | ||
97 | if (!blk_special_request(rq)) { | ||
98 | /* our real local end request function */ | ||
99 | ide_end_request(drive, uptodate, nsecs); | ||
100 | return 0; | ||
101 | } | ||
102 | rq->errors = error; | ||
103 | /* fixme: need to move this local also */ | ||
104 | ide_end_drive_cmd(drive, 0, 0); | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static void idefloppy_update_buffers(ide_drive_t *drive, | 64 | static void idefloppy_update_buffers(ide_drive_t *drive, |
109 | struct ide_atapi_pc *pc) | 65 | struct ide_atapi_pc *pc) |
110 | { | 66 | { |
@@ -112,22 +68,23 @@ static void idefloppy_update_buffers(ide_drive_t *drive, | |||
112 | struct bio *bio = rq->bio; | 68 | struct bio *bio = rq->bio; |
113 | 69 | ||
114 | while ((bio = rq->bio) != NULL) | 70 | while ((bio = rq->bio) != NULL) |
115 | ide_floppy_end_request(drive, 1, 0); | 71 | ide_complete_rq(drive, 0, ide_rq_bytes(rq)); |
116 | } | 72 | } |
117 | 73 | ||
118 | static void ide_floppy_callback(ide_drive_t *drive, int dsc) | 74 | static int ide_floppy_callback(ide_drive_t *drive, int dsc) |
119 | { | 75 | { |
120 | struct ide_disk_obj *floppy = drive->driver_data; | 76 | struct ide_disk_obj *floppy = drive->driver_data; |
121 | struct ide_atapi_pc *pc = drive->pc; | 77 | struct ide_atapi_pc *pc = drive->pc; |
78 | struct request *rq = pc->rq; | ||
122 | int uptodate = pc->error ? 0 : 1; | 79 | int uptodate = pc->error ? 0 : 1; |
123 | 80 | ||
124 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | 81 | ide_debug_log(IDE_DBG_FUNC, "enter"); |
125 | 82 | ||
126 | if (floppy->failed_pc == pc) | 83 | if (drive->failed_pc == pc) |
127 | floppy->failed_pc = NULL; | 84 | drive->failed_pc = NULL; |
128 | 85 | ||
129 | if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 || | 86 | if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 || |
130 | (pc->rq && blk_pc_request(pc->rq))) | 87 | (rq && blk_pc_request(rq))) |
131 | uptodate = 1; /* FIXME */ | 88 | uptodate = 1; /* FIXME */ |
132 | else if (pc->c[0] == GPCMD_REQUEST_SENSE) { | 89 | else if (pc->c[0] == GPCMD_REQUEST_SENSE) { |
133 | u8 *buf = pc->buf; | 90 | u8 *buf = pc->buf; |
@@ -139,19 +96,22 @@ static void ide_floppy_callback(ide_drive_t *drive, int dsc) | |||
139 | floppy->progress_indication = buf[15] & 0x80 ? | 96 | floppy->progress_indication = buf[15] & 0x80 ? |
140 | (u16)get_unaligned((u16 *)&buf[16]) : 0x10000; | 97 | (u16)get_unaligned((u16 *)&buf[16]) : 0x10000; |
141 | 98 | ||
142 | if (floppy->failed_pc) | 99 | if (drive->failed_pc) |
143 | ide_debug_log(IDE_DBG_PC, "pc = %x, ", | 100 | ide_debug_log(IDE_DBG_PC, "pc = %x", |
144 | floppy->failed_pc->c[0]); | 101 | drive->failed_pc->c[0]); |
145 | 102 | ||
146 | ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x," | 103 | ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x," |
147 | "ascq = %x\n", floppy->sense_key, | 104 | "ascq = %x", floppy->sense_key, |
148 | floppy->asc, floppy->ascq); | 105 | floppy->asc, floppy->ascq); |
149 | } else | 106 | } else |
150 | printk(KERN_ERR PFX "Error in REQUEST SENSE itself - " | 107 | printk(KERN_ERR PFX "Error in REQUEST SENSE itself - " |
151 | "Aborting request!\n"); | 108 | "Aborting request!\n"); |
152 | } | 109 | } |
153 | 110 | ||
154 | ide_floppy_end_request(drive, uptodate, 0); | 111 | if (blk_special_request(rq)) |
112 | rq->errors = uptodate ? 0 : IDE_DRV_ERROR_GENERAL; | ||
113 | |||
114 | return uptodate; | ||
155 | } | 115 | } |
156 | 116 | ||
157 | static void ide_floppy_report_error(struct ide_disk_obj *floppy, | 117 | static void ide_floppy_report_error(struct ide_disk_obj *floppy, |
@@ -170,14 +130,15 @@ static void ide_floppy_report_error(struct ide_disk_obj *floppy, | |||
170 | 130 | ||
171 | } | 131 | } |
172 | 132 | ||
173 | static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, | 133 | static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive, |
174 | struct ide_atapi_pc *pc) | 134 | struct ide_cmd *cmd, |
135 | struct ide_atapi_pc *pc) | ||
175 | { | 136 | { |
176 | struct ide_disk_obj *floppy = drive->driver_data; | 137 | struct ide_disk_obj *floppy = drive->driver_data; |
177 | 138 | ||
178 | if (floppy->failed_pc == NULL && | 139 | if (drive->failed_pc == NULL && |
179 | pc->c[0] != GPCMD_REQUEST_SENSE) | 140 | pc->c[0] != GPCMD_REQUEST_SENSE) |
180 | floppy->failed_pc = pc; | 141 | drive->failed_pc = pc; |
181 | 142 | ||
182 | /* Set the current packet command */ | 143 | /* Set the current packet command */ |
183 | drive->pc = pc; | 144 | drive->pc = pc; |
@@ -186,18 +147,18 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, | |||
186 | if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR)) | 147 | if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR)) |
187 | ide_floppy_report_error(floppy, pc); | 148 | ide_floppy_report_error(floppy, pc); |
188 | /* Giving up */ | 149 | /* Giving up */ |
189 | pc->error = IDEFLOPPY_ERROR_GENERAL; | 150 | pc->error = IDE_DRV_ERROR_GENERAL; |
190 | 151 | ||
191 | floppy->failed_pc = NULL; | 152 | drive->failed_pc = NULL; |
192 | drive->pc_callback(drive, 0); | 153 | drive->pc_callback(drive, 0); |
193 | return ide_stopped; | 154 | return ide_stopped; |
194 | } | 155 | } |
195 | 156 | ||
196 | ide_debug_log(IDE_DBG_FUNC, "%s: Retry #%d\n", __func__, pc->retries); | 157 | ide_debug_log(IDE_DBG_FUNC, "retry #%d", pc->retries); |
197 | 158 | ||
198 | pc->retries++; | 159 | pc->retries++; |
199 | 160 | ||
200 | return ide_issue_pc(drive); | 161 | return ide_issue_pc(drive, cmd); |
201 | } | 162 | } |
202 | 163 | ||
203 | void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) | 164 | void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) |
@@ -242,8 +203,7 @@ static void idefloppy_create_rw_cmd(ide_drive_t *drive, | |||
242 | int blocks = rq->nr_sectors / floppy->bs_factor; | 203 | int blocks = rq->nr_sectors / floppy->bs_factor; |
243 | int cmd = rq_data_dir(rq); | 204 | int cmd = rq_data_dir(rq); |
244 | 205 | ||
245 | ide_debug_log(IDE_DBG_FUNC, "%s: block: %d, blocks: %d\n", __func__, | 206 | ide_debug_log(IDE_DBG_FUNC, "block: %d, blocks: %d", block, blocks); |
246 | block, blocks); | ||
247 | 207 | ||
248 | ide_init_pc(pc); | 208 | ide_init_pc(pc); |
249 | pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10; | 209 | pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10; |
@@ -285,34 +245,34 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, | |||
285 | { | 245 | { |
286 | struct ide_disk_obj *floppy = drive->driver_data; | 246 | struct ide_disk_obj *floppy = drive->driver_data; |
287 | ide_hwif_t *hwif = drive->hwif; | 247 | ide_hwif_t *hwif = drive->hwif; |
248 | struct ide_cmd cmd; | ||
288 | struct ide_atapi_pc *pc; | 249 | struct ide_atapi_pc *pc; |
289 | 250 | ||
290 | ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, " | 251 | if (drive->debug_mask & IDE_DBG_RQ) |
291 | "errors: %d\n", | 252 | blk_dump_rq_flags(rq, (rq->rq_disk |
292 | __func__, rq->rq_disk ? rq->rq_disk->disk_name : "?", | 253 | ? rq->rq_disk->disk_name |
293 | rq->cmd[0], rq->cmd_type, rq->errors); | 254 | : "dev?")); |
294 | |||
295 | ide_debug_log(IDE_DBG_FUNC, "%s: sector: %ld, nr_sectors: %ld, " | ||
296 | "current_nr_sectors: %d\n", | ||
297 | __func__, (long)rq->sector, rq->nr_sectors, | ||
298 | rq->current_nr_sectors); | ||
299 | 255 | ||
300 | if (rq->errors >= ERROR_MAX) { | 256 | if (rq->errors >= ERROR_MAX) { |
301 | if (floppy->failed_pc) | 257 | if (drive->failed_pc) { |
302 | ide_floppy_report_error(floppy, floppy->failed_pc); | 258 | ide_floppy_report_error(floppy, drive->failed_pc); |
303 | else | 259 | drive->failed_pc = NULL; |
260 | } else | ||
304 | printk(KERN_ERR PFX "%s: I/O error\n", drive->name); | 261 | printk(KERN_ERR PFX "%s: I/O error\n", drive->name); |
305 | 262 | ||
306 | ide_floppy_end_request(drive, 0, 0); | 263 | if (blk_special_request(rq)) { |
307 | return ide_stopped; | 264 | rq->errors = 0; |
265 | ide_complete_rq(drive, 0, blk_rq_bytes(rq)); | ||
266 | return ide_stopped; | ||
267 | } else | ||
268 | goto out_end; | ||
308 | } | 269 | } |
309 | if (blk_fs_request(rq)) { | 270 | if (blk_fs_request(rq)) { |
310 | if (((long)rq->sector % floppy->bs_factor) || | 271 | if (((long)rq->sector % floppy->bs_factor) || |
311 | (rq->nr_sectors % floppy->bs_factor)) { | 272 | (rq->nr_sectors % floppy->bs_factor)) { |
312 | printk(KERN_ERR PFX "%s: unsupported r/w rq size\n", | 273 | printk(KERN_ERR PFX "%s: unsupported r/w rq size\n", |
313 | drive->name); | 274 | drive->name); |
314 | ide_floppy_end_request(drive, 0, 0); | 275 | goto out_end; |
315 | return ide_stopped; | ||
316 | } | 276 | } |
317 | pc = &floppy->queued_pc; | 277 | pc = &floppy->queued_pc; |
318 | idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block); | 278 | idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block); |
@@ -323,21 +283,33 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, | |||
323 | idefloppy_blockpc_cmd(floppy, pc, rq); | 283 | idefloppy_blockpc_cmd(floppy, pc, rq); |
324 | } else { | 284 | } else { |
325 | blk_dump_rq_flags(rq, PFX "unsupported command in queue"); | 285 | blk_dump_rq_flags(rq, PFX "unsupported command in queue"); |
326 | ide_floppy_end_request(drive, 0, 0); | 286 | goto out_end; |
327 | return ide_stopped; | ||
328 | } | 287 | } |
329 | 288 | ||
289 | memset(&cmd, 0, sizeof(cmd)); | ||
290 | |||
291 | if (rq_data_dir(rq)) | ||
292 | cmd.tf_flags |= IDE_TFLAG_WRITE; | ||
293 | |||
294 | cmd.rq = rq; | ||
295 | |||
330 | if (blk_fs_request(rq) || pc->req_xfer) { | 296 | if (blk_fs_request(rq) || pc->req_xfer) { |
331 | ide_init_sg_cmd(drive, rq); | 297 | ide_init_sg_cmd(&cmd, rq->nr_sectors << 9); |
332 | ide_map_sg(drive, rq); | 298 | ide_map_sg(drive, &cmd); |
333 | } | 299 | } |
334 | 300 | ||
335 | pc->sg = hwif->sg_table; | 301 | pc->sg = hwif->sg_table; |
336 | pc->sg_cnt = hwif->sg_nents; | 302 | pc->sg_cnt = cmd.sg_nents; |
337 | 303 | ||
338 | pc->rq = rq; | 304 | pc->rq = rq; |
339 | 305 | ||
340 | return idefloppy_issue_pc(drive, pc); | 306 | return ide_floppy_issue_pc(drive, &cmd, pc); |
307 | out_end: | ||
308 | drive->failed_pc = NULL; | ||
309 | if (blk_fs_request(rq) == 0 && rq->errors == 0) | ||
310 | rq->errors = -EIO; | ||
311 | ide_complete_rq(drive, -EIO, ide_rq_bytes(rq)); | ||
312 | return ide_stopped; | ||
341 | } | 313 | } |
342 | 314 | ||
343 | /* | 315 | /* |
@@ -438,8 +410,9 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) | |||
438 | length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]); | 410 | length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]); |
439 | 411 | ||
440 | ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, " | 412 | ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, " |
441 | "%d sector size\n", | 413 | "%d sector size", |
442 | i, blocks * length / 1024, blocks, length); | 414 | i, blocks * length / 1024, |
415 | blocks, length); | ||
443 | 416 | ||
444 | if (i) | 417 | if (i) |
445 | continue; | 418 | continue; |
@@ -495,8 +468,8 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) | |||
495 | "in drive\n", drive->name); | 468 | "in drive\n", drive->name); |
496 | break; | 469 | break; |
497 | } | 470 | } |
498 | ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d\n", | 471 | ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d", |
499 | pc.buf[desc_start + 4] & 0x03); | 472 | pc.buf[desc_start + 4] & 0x03); |
500 | } | 473 | } |
501 | 474 | ||
502 | /* Clik! disk does not support get_flexible_disk_page */ | 475 | /* Clik! disk does not support get_flexible_disk_page */ |
@@ -575,6 +548,5 @@ const struct ide_disk_ops ide_atapi_disk_ops = { | |||
575 | .init_media = ide_floppy_init_media, | 548 | .init_media = ide_floppy_init_media, |
576 | .set_doorlock = ide_set_media_lock, | 549 | .set_doorlock = ide_set_media_lock, |
577 | .do_request = ide_floppy_do_request, | 550 | .do_request = ide_floppy_do_request, |
578 | .end_request = ide_floppy_end_request, | ||
579 | .ioctl = ide_floppy_ioctl, | 551 | .ioctl = ide_floppy_ioctl, |
580 | }; | 552 | }; |