aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-atapi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-11 16:22:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-11 16:22:33 -0400
commit5c3c4d9b5810c9aabd8c05219c62ca088aa83eb0 (patch)
treef1122247e0b6d6269588702738df9c46061e280d /drivers/ide/ide-atapi.c
parentead9d23d803ea3a73766c3cb27bf7563ac8d7266 (diff)
parent92f1f8fd8040e7b50a67a850a935509bb01201bb (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6: (71 commits) ide: Remove ide_spin_wait_hwgroup() and use special requests instead ide: move IDE{FLOPPY,TAPE}_WAIT_CMD defines to <linux/ide.h> ide: add ide_do_test_unit_ready() helper ide: add ide_do_start_stop() helper ide: add ide_set_media_lock() helper ide-floppy: move floppy ioctls handling to ide-floppy_ioctl.c ide-floppy: ->{srfp,wp} -> IDE_AFLAG_{SRFP,WP} ide: add ide_queue_pc_tail() helper ide: add ide_queue_pc_head() helper ide: add ide_init_pc() helper ide-tape: add ide_tape_set_media_lock() helper ide-floppy: add ide_floppy_set_media_lock() helper ide: add ide_io_buffers() helper ide-scsi: cleanup ide_scsi_io_buffers() ide-floppy: remove MODE_SENSE_* defines ide-{floppy,tape}: remove packet command stack ide-{floppy,tape}: remove request stack ide-generic: handle probing of legacy io-ports v5 ide-floppy: use scatterlists for pio transfers ide-tape: remove idetape_init_rq() ...
Diffstat (limited to 'drivers/ide/ide-atapi.c')
-rw-r--r--drivers/ide/ide-atapi.c236
1 files changed, 216 insertions, 20 deletions
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index adf04f99cdeb..608c5bade929 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -14,12 +14,201 @@
14#define debug_log(fmt, args...) do {} while (0) 14#define debug_log(fmt, args...) do {} while (0)
15#endif 15#endif
16 16
17/*
18 * Check whether we can support a device,
19 * based on the ATAPI IDENTIFY command results.
20 */
21int ide_check_atapi_device(ide_drive_t *drive, const char *s)
22{
23 u16 *id = drive->id;
24 u8 gcw[2], protocol, device_type, removable, drq_type, packet_size;
25
26 *((u16 *)&gcw) = id[ATA_ID_CONFIG];
27
28 protocol = (gcw[1] & 0xC0) >> 6;
29 device_type = gcw[1] & 0x1F;
30 removable = (gcw[0] & 0x80) >> 7;
31 drq_type = (gcw[0] & 0x60) >> 5;
32 packet_size = gcw[0] & 0x03;
33
34#ifdef CONFIG_PPC
35 /* kludge for Apple PowerBook internal zip */
36 if (drive->media == ide_floppy && device_type == 5 &&
37 !strstr((char *)&id[ATA_ID_PROD], "CD-ROM") &&
38 strstr((char *)&id[ATA_ID_PROD], "ZIP"))
39 device_type = 0;
40#endif
41
42 if (protocol != 2)
43 printk(KERN_ERR "%s: %s: protocol (0x%02x) is not ATAPI\n",
44 s, drive->name, protocol);
45 else if ((drive->media == ide_floppy && device_type != 0) ||
46 (drive->media == ide_tape && device_type != 1))
47 printk(KERN_ERR "%s: %s: invalid device type (0x%02x)\n",
48 s, drive->name, device_type);
49 else if (removable == 0)
50 printk(KERN_ERR "%s: %s: the removable flag is not set\n",
51 s, drive->name);
52 else if (drive->media == ide_floppy && drq_type == 3)
53 printk(KERN_ERR "%s: %s: sorry, DRQ type (0x%02x) not "
54 "supported\n", s, drive->name, drq_type);
55 else if (packet_size != 0)
56 printk(KERN_ERR "%s: %s: packet size (0x%02x) is not 12 "
57 "bytes\n", s, drive->name, packet_size);
58 else
59 return 1;
60 return 0;
61}
62EXPORT_SYMBOL_GPL(ide_check_atapi_device);
63
64/* PIO data transfer routine using the scatter gather table. */
65int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
66 unsigned int bcount, int write)
67{
68 ide_hwif_t *hwif = drive->hwif;
69 const struct ide_tp_ops *tp_ops = hwif->tp_ops;
70 xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
71 struct scatterlist *sg = pc->sg;
72 char *buf;
73 int count, done = 0;
74
75 while (bcount) {
76 count = min(sg->length - pc->b_count, bcount);
77
78 if (PageHighMem(sg_page(sg))) {
79 unsigned long flags;
80
81 local_irq_save(flags);
82 buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
83 xf(drive, NULL, buf + pc->b_count, count);
84 kunmap_atomic(buf - sg->offset, KM_IRQ0);
85 local_irq_restore(flags);
86 } else {
87 buf = sg_virt(sg);
88 xf(drive, NULL, buf + pc->b_count, count);
89 }
90
91 bcount -= count;
92 pc->b_count += count;
93 done += count;
94
95 if (pc->b_count == sg->length) {
96 if (!--pc->sg_cnt)
97 break;
98 pc->sg = sg = sg_next(sg);
99 pc->b_count = 0;
100 }
101 }
102
103 if (bcount) {
104 printk(KERN_ERR "%s: %d leftover bytes, %s\n", drive->name,
105 bcount, write ? "padding with zeros"
106 : "discarding data");
107 ide_pad_transfer(drive, write, bcount);
108 }
109
110 return done;
111}
112EXPORT_SYMBOL_GPL(ide_io_buffers);
113
114void ide_init_pc(struct ide_atapi_pc *pc)
115{
116 memset(pc, 0, sizeof(*pc));
117 pc->buf = pc->pc_buf;
118 pc->buf_size = IDE_PC_BUFFER_SIZE;
119}
120EXPORT_SYMBOL_GPL(ide_init_pc);
121
122/*
123 * Generate a new packet command request in front of the request queue, before
124 * the current request, so that it will be processed immediately, on the next
125 * pass through the driver.
126 */
127void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
128 struct ide_atapi_pc *pc, struct request *rq)
129{
130 blk_rq_init(NULL, rq);
131 rq->cmd_type = REQ_TYPE_SPECIAL;
132 rq->cmd_flags |= REQ_PREEMPT;
133 rq->buffer = (char *)pc;
134 rq->rq_disk = disk;
135 memcpy(rq->cmd, pc->c, 12);
136 if (drive->media == ide_tape)
137 rq->cmd[13] = REQ_IDETAPE_PC1;
138 ide_do_drive_cmd(drive, rq);
139}
140EXPORT_SYMBOL_GPL(ide_queue_pc_head);
141
142/*
143 * Add a special packet command request to the tail of the request queue,
144 * and wait for it to be serviced.
145 */
146int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
147 struct ide_atapi_pc *pc)
148{
149 struct request *rq;
150 int error;
151
152 rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
153 rq->cmd_type = REQ_TYPE_SPECIAL;
154 rq->buffer = (char *)pc;
155 memcpy(rq->cmd, pc->c, 12);
156 if (drive->media == ide_tape)
157 rq->cmd[13] = REQ_IDETAPE_PC1;
158 error = blk_execute_rq(drive->queue, disk, rq, 0);
159 blk_put_request(rq);
160
161 return error;
162}
163EXPORT_SYMBOL_GPL(ide_queue_pc_tail);
164
165int ide_do_test_unit_ready(ide_drive_t *drive, struct gendisk *disk)
166{
167 struct ide_atapi_pc pc;
168
169 ide_init_pc(&pc);
170 pc.c[0] = TEST_UNIT_READY;
171
172 return ide_queue_pc_tail(drive, disk, &pc);
173}
174EXPORT_SYMBOL_GPL(ide_do_test_unit_ready);
175
176int ide_do_start_stop(ide_drive_t *drive, struct gendisk *disk, int start)
177{
178 struct ide_atapi_pc pc;
179
180 ide_init_pc(&pc);
181 pc.c[0] = START_STOP;
182 pc.c[4] = start;
183
184 if (drive->media == ide_tape)
185 pc.flags |= PC_FLAG_WAIT_FOR_DSC;
186
187 return ide_queue_pc_tail(drive, disk, &pc);
188}
189EXPORT_SYMBOL_GPL(ide_do_start_stop);
190
191int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on)
192{
193 struct ide_atapi_pc pc;
194
195 if (drive->atapi_flags & IDE_AFLAG_NO_DOORLOCK)
196 return 0;
197
198 ide_init_pc(&pc);
199 pc.c[0] = ALLOW_MEDIUM_REMOVAL;
200 pc.c[4] = on;
201
202 return ide_queue_pc_tail(drive, disk, &pc);
203}
204EXPORT_SYMBOL_GPL(ide_set_media_lock);
205
17/* TODO: unify the code thus making some arguments go away */ 206/* TODO: unify the code thus making some arguments go away */
18ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, 207ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
19 ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, 208 ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry,
20 void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *), 209 void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *),
21 void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *), 210 void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *),
22 void (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int)) 211 int (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int))
23{ 212{
24 ide_hwif_t *hwif = drive->hwif; 213 ide_hwif_t *hwif = drive->hwif;
25 struct request *rq = hwif->hwgroup->rq; 214 struct request *rq = hwif->hwgroup->rq;
@@ -41,7 +230,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
41 230
42 if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { 231 if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
43 if (hwif->dma_ops->dma_end(drive) || 232 if (hwif->dma_ops->dma_end(drive) ||
44 (drive->media == ide_tape && !scsi && (stat & ERR_STAT))) { 233 (drive->media == ide_tape && !scsi && (stat & ATA_ERR))) {
45 if (drive->media == ide_floppy && !scsi) 234 if (drive->media == ide_floppy && !scsi)
46 printk(KERN_ERR "%s: DMA %s error\n", 235 printk(KERN_ERR "%s: DMA %s error\n",
47 drive->name, rq_data_dir(pc->rq) 236 drive->name, rq_data_dir(pc->rq)
@@ -56,7 +245,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
56 } 245 }
57 246
58 /* No more interrupts */ 247 /* No more interrupts */
59 if ((stat & DRQ_STAT) == 0) { 248 if ((stat & ATA_DRQ) == 0) {
60 debug_log("Packet command completed, %d bytes transferred\n", 249 debug_log("Packet command completed, %d bytes transferred\n",
61 pc->xferred); 250 pc->xferred);
62 251
@@ -65,10 +254,10 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
65 local_irq_enable_in_hardirq(); 254 local_irq_enable_in_hardirq();
66 255
67 if (drive->media == ide_tape && !scsi && 256 if (drive->media == ide_tape && !scsi &&
68 (stat & ERR_STAT) && rq->cmd[0] == REQUEST_SENSE) 257 (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE)
69 stat &= ~ERR_STAT; 258 stat &= ~ATA_ERR;
70 259
71 if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) { 260 if ((stat & ATA_ERR) || (pc->flags & PC_FLAG_DMA_ERROR)) {
72 /* Error detected */ 261 /* Error detected */
73 debug_log("%s: I/O error\n", drive->name); 262 debug_log("%s: I/O error\n", drive->name);
74 263
@@ -95,7 +284,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
95cmd_finished: 284cmd_finished:
96 pc->error = 0; 285 pc->error = 0;
97 if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && 286 if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) &&
98 (stat & SEEK_STAT) == 0) { 287 (stat & ATA_DSC) == 0) {
99 dsc_handle(drive); 288 dsc_handle(drive);
100 return ide_stopped; 289 return ide_stopped;
101 } 290 }
@@ -117,17 +306,18 @@ cmd_finished:
117 /* Get the number of bytes to transfer on this interrupt. */ 306 /* Get the number of bytes to transfer on this interrupt. */
118 ide_read_bcount_and_ireason(drive, &bcount, &ireason); 307 ide_read_bcount_and_ireason(drive, &bcount, &ireason);
119 308
120 if (ireason & CD) { 309 if (ireason & ATAPI_COD) {
121 printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__); 310 printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
122 return ide_do_reset(drive); 311 return ide_do_reset(drive);
123 } 312 }
124 313
125 if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) { 314 if (((ireason & ATAPI_IO) == ATAPI_IO) ==
315 !!(pc->flags & PC_FLAG_WRITING)) {
126 /* Hopefully, we will never get here */ 316 /* Hopefully, we will never get here */
127 printk(KERN_ERR "%s: We wanted to %s, but the device wants us " 317 printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
128 "to %s!\n", drive->name, 318 "to %s!\n", drive->name,
129 (ireason & IO) ? "Write" : "Read", 319 (ireason & ATAPI_IO) ? "Write" : "Read",
130 (ireason & IO) ? "Read" : "Write"); 320 (ireason & ATAPI_IO) ? "Read" : "Write");
131 return ide_do_reset(drive); 321 return ide_do_reset(drive);
132 } 322 }
133 323
@@ -171,9 +361,14 @@ cmd_finished:
171 361
172 if ((drive->media == ide_floppy && !scsi && !pc->buf) || 362 if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
173 (drive->media == ide_tape && !scsi && pc->bh) || 363 (drive->media == ide_tape && !scsi && pc->bh) ||
174 (scsi && pc->sg)) 364 (scsi && pc->sg)) {
175 io_buffers(drive, pc, bcount, !!(pc->flags & PC_FLAG_WRITING)); 365 int done = io_buffers(drive, pc, bcount,
176 else 366 !!(pc->flags & PC_FLAG_WRITING));
367
368 /* FIXME: don't do partial completions */
369 if (drive->media == ide_floppy && !scsi)
370 ide_end_request(drive, 1, done >> 9);
371 } else
177 xferfunc(drive, NULL, pc->cur_pos, bcount); 372 xferfunc(drive, NULL, pc->cur_pos, bcount);
178 373
179 /* Update the current position */ 374 /* Update the current position */
@@ -205,7 +400,8 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
205{ 400{
206 int retries = 100; 401 int retries = 100;
207 402
208 while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) { 403 while (retries-- && ((ireason & ATAPI_COD) == 0 ||
404 (ireason & ATAPI_IO))) {
209 printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " 405 printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
210 "a packet command, retrying\n", drive->name); 406 "a packet command, retrying\n", drive->name);
211 udelay(100); 407 udelay(100);
@@ -214,8 +410,8 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
214 printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " 410 printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
215 "a packet command, ignoring\n", 411 "a packet command, ignoring\n",
216 drive->name); 412 drive->name);
217 ireason |= CD; 413 ireason |= ATAPI_COD;
218 ireason &= ~IO; 414 ireason &= ~ATAPI_IO;
219 } 415 }
220 } 416 }
221 417
@@ -231,7 +427,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
231 ide_startstop_t startstop; 427 ide_startstop_t startstop;
232 u8 ireason; 428 u8 ireason;
233 429
234 if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) { 430 if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) {
235 printk(KERN_ERR "%s: Strange, packet command initiated yet " 431 printk(KERN_ERR "%s: Strange, packet command initiated yet "
236 "DRQ isn't asserted\n", drive->name); 432 "DRQ isn't asserted\n", drive->name);
237 return startstop; 433 return startstop;
@@ -241,7 +437,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
241 if (drive->media == ide_tape && !drive->scsi) 437 if (drive->media == ide_tape && !drive->scsi)
242 ireason = ide_wait_ireason(drive, ireason); 438 ireason = ide_wait_ireason(drive, ireason);
243 439
244 if ((ireason & CD) == 0 || (ireason & IO)) { 440 if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
245 printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing " 441 printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
246 "a packet command\n", drive->name); 442 "a packet command\n", drive->name);
247 return ide_do_reset(drive); 443 return ide_do_reset(drive);
@@ -303,7 +499,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
303 499
304 /* Issue the packet command */ 500 /* Issue the packet command */
305 if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { 501 if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
306 ide_execute_command(drive, WIN_PACKETCMD, handler, 502 ide_execute_command(drive, ATA_CMD_PACKET, handler,
307 timeout, NULL); 503 timeout, NULL);
308 return ide_started; 504 return ide_started;
309 } else { 505 } else {