]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ata/ata-queue.c
This commit was generated by cvs2svn to compensate for changes in r151937,
[FreeBSD/FreeBSD.git] / sys / dev / ata / ata-queue.c
1 /*-
2  * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification, immediately at the beginning of the file.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include "opt_ata.h"
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/ata.h>
36 #include <sys/kernel.h>
37 #include <sys/bio.h>
38 #include <sys/bus.h>
39 #include <sys/conf.h>
40 #include <sys/sema.h>
41 #include <sys/taskqueue.h>
42 #include <vm/uma.h>
43 #include <machine/bus.h>
44 #include <sys/rman.h>
45 #include <dev/ata/ata-all.h>
46 #include <ata_if.h>
47
48 /* prototypes */
49 static void ata_completed(void *, int);
50 static void ata_sort_queue(struct ata_channel *ch, struct ata_request *request);
51 static char *ata_skey2str(u_int8_t);
52
53 void
54 ata_queue_request(struct ata_request *request)
55 {
56     struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
57
58     /* mark request as virgin (this might be a ATA_R_REQUEUE) */
59     request->result = request->status = request->error = 0;
60     callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED);
61
62     if (!request->callback && !(request->flags & ATA_R_REQUEUE))
63         sema_init(&request->done, 0, "ATA request done");
64
65     /* in ATA_STALL_QUEUE state we call HW directly (used only during reinit) */
66     if ((ch->state & ATA_STALL_QUEUE) && (request->flags & ATA_R_CONTROL)) {
67         mtx_lock(&ch->state_mtx);
68         ch->running = request;
69         if (ch->hw.begin_transaction(request) == ATA_OP_FINISHED) {
70             ch->running = NULL;
71             if (!request->callback) 
72                 sema_destroy(&request->done);
73             mtx_unlock(&ch->state_mtx);
74             return;
75         }
76         mtx_unlock(&ch->state_mtx);
77     }
78     /* otherwise put request on the locked queue at the specified location */
79     else  {
80         mtx_lock(&ch->queue_mtx);
81         if (request->flags & ATA_R_AT_HEAD)
82             TAILQ_INSERT_HEAD(&ch->ata_queue, request, chain);
83         else if (request->flags & ATA_R_ORDERED)
84             ata_sort_queue(ch, request);
85         else
86             TAILQ_INSERT_TAIL(&ch->ata_queue, request, chain);
87         mtx_unlock(&ch->queue_mtx);
88         ATA_DEBUG_RQ(request, "queued");
89         ata_start(ch->dev);
90     }
91
92     /* if this is a requeued request callback/sleep we're done */
93     if (request->flags & ATA_R_REQUEUE)
94         return;
95
96     /* if this is not a callback wait until request is completed */
97     if (!request->callback) {
98         ATA_DEBUG_RQ(request, "wait for completition");
99         while (sema_timedwait(&request->done, request->timeout * hz * 4)) {
100             device_printf(request->dev,
101                 "req=%p %s semaphore timeout !! DANGER Will Robinson !!\n",
102                       request, ata_cmd2str(request));
103             ata_start(ch->dev);
104         }
105         sema_destroy(&request->done);
106     }
107 }
108
109 int
110 ata_controlcmd(device_t dev, u_int8_t command, u_int16_t feature,
111                u_int64_t lba, u_int16_t count)
112 {
113     struct ata_request *request = ata_alloc_request();
114     int error = ENOMEM;
115
116     if (request) {
117         request->dev = dev;
118         request->u.ata.command = command;
119         request->u.ata.lba = lba;
120         request->u.ata.count = count;
121         request->u.ata.feature = feature;
122         request->flags = ATA_R_CONTROL;
123         request->timeout = 1;
124         request->retries = 0;
125         ata_queue_request(request);
126         error = request->result;
127         ata_free_request(request);
128     }
129     return error;
130 }
131
132 int
133 ata_atapicmd(device_t dev, u_int8_t *ccb, caddr_t data,
134              int count, int flags, int timeout)
135 {
136     struct ata_request *request = ata_alloc_request();
137     struct ata_device *atadev = device_get_softc(dev);
138     int error = ENOMEM;
139
140     if (request) {
141         request->dev = dev;
142         if ((atadev->param.config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12)
143             bcopy(ccb, request->u.atapi.ccb, 12);
144         else
145             bcopy(ccb, request->u.atapi.ccb, 16);
146         request->data = data;
147         request->bytecount = count;
148         request->transfersize = min(request->bytecount, 65534);
149         request->flags = flags | ATA_R_ATAPI;
150         request->timeout = timeout;
151         request->retries = 0;
152         ata_queue_request(request);
153         error = request->result;
154         ata_free_request(request);
155     }
156     return error;
157 }
158
159 void
160 ata_start(device_t dev)
161 {
162     struct ata_channel *ch = device_get_softc(dev);
163     struct ata_request *request;
164     struct ata_composite *cptr;
165     int dependencies = 0;
166
167     /* if we have a request on the queue try to get it running */
168     mtx_lock(&ch->queue_mtx);
169     if ((request = TAILQ_FIRST(&ch->ata_queue))) {
170
171         /* we need the locking function to get the lock for this channel */
172         if (ATA_LOCKING(dev, ATA_LF_LOCK) == ch->unit) {
173
174             /* check for composite dependencies */
175             if ((cptr = request->composite)) {
176                 mtx_lock(&cptr->lock);
177                 if ((request->flags & ATA_R_WRITE) &&
178                     (cptr->wr_depend & cptr->rd_done) != cptr->wr_depend) {
179                     dependencies = 1;
180                 }
181                 mtx_unlock(&cptr->lock);
182             }
183
184             /* check we are in the right state and has no dependencies */
185             mtx_lock(&ch->state_mtx);
186             if (ch->state == ATA_IDLE && !dependencies) {
187                 ATA_DEBUG_RQ(request, "starting");
188                 TAILQ_REMOVE(&ch->ata_queue, request, chain);
189                 ch->running = request;
190                 ch->state = ATA_ACTIVE;
191
192                 /* if we are the freezing point release it */
193                 if (ch->freezepoint == request)
194                     ch->freezepoint = NULL;
195
196                 if (ch->hw.begin_transaction(request) == ATA_OP_FINISHED) {
197                     ch->running = NULL;
198                     ch->state = ATA_IDLE;
199                     mtx_unlock(&ch->state_mtx);
200                     mtx_unlock(&ch->queue_mtx);
201                     ATA_LOCKING(dev, ATA_LF_UNLOCK);
202                     ata_finish(request);
203                     return;
204                 }
205             }
206             mtx_unlock(&ch->state_mtx);
207         }
208     }
209     mtx_unlock(&ch->queue_mtx);
210 }
211
212 void
213 ata_finish(struct ata_request *request)
214 {
215     struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
216
217     /*
218      * if in ATA_STALL_QUEUE state or request has ATA_R_DIRECT flags set
219      * we need to call ata_complete() directly here (no taskqueue involvement)
220      */
221     if ((ch->state & ATA_STALL_QUEUE) || (request->flags & ATA_R_DIRECT)) {
222         ATA_DEBUG_RQ(request, "finish directly");
223         ata_completed(request, 0);
224     }
225     else {
226         /* put request on the proper taskqueue for completition */
227         if (request->bio && !(request->flags & (ATA_R_THREAD | ATA_R_TIMEOUT))){
228             ATA_DEBUG_RQ(request, "finish bio_taskqueue");
229             bio_taskqueue(request->bio, (bio_task_t *)ata_completed, request);
230         }
231         else {
232             TASK_INIT(&request->task, 0, ata_completed, request);
233             ATA_DEBUG_RQ(request, "finish taskqueue_swi");
234             taskqueue_enqueue(taskqueue_swi, &request->task);
235         }
236     }
237 }
238
239 static void
240 ata_completed(void *context, int dummy)
241 {
242     struct ata_request *request = (struct ata_request *)context;
243     struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
244     struct ata_device *atadev = device_get_softc(request->dev);
245     struct ata_composite *composite;
246
247     ATA_DEBUG_RQ(request, "completed entered");
248
249     /* if we had a timeout, reinit channel and deal with the falldown */
250     if (request->flags & ATA_R_TIMEOUT) {
251         /*
252          * if reinit succeeds and the device doesn't get detached and
253          * there are retries left we reinject this request
254          */
255         if (!ata_reinit(ch->dev) && !request->result &&
256             (request->retries-- > 0)) {
257             if (!(request->flags & ATA_R_QUIET)) {
258                 device_printf(request->dev,
259                               "TIMEOUT - %s retrying (%d retr%s left)",
260                               ata_cmd2str(request), request->retries,
261                               request->retries == 1 ? "y" : "ies");
262                 if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
263                     printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
264                 printf("\n");
265             }
266             request->flags &= ~(ATA_R_TIMEOUT | ATA_R_DEBUG);
267             request->flags |= (ATA_R_AT_HEAD | ATA_R_REQUEUE);
268             ATA_DEBUG_RQ(request, "completed reinject");
269             ata_queue_request(request);
270             return;
271         }
272
273         /* ran out of good intentions so finish with error */
274         if (!request->result) {
275             if (!(request->flags & ATA_R_QUIET)) {
276                 if (request->dev) {
277                     device_printf(request->dev, "FAILURE - %s timed out",
278                                   ata_cmd2str(request));
279                     if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
280                         printf(" LBA=%llu",
281                                (unsigned long long)request->u.ata.lba);
282                     printf("\n");
283                 }
284             }
285             request->result = EIO;
286         }
287     }
288     else {
289         /* if this is a soft ECC error warn about it */
290         /* XXX SOS we could do WARF here */
291         if ((request->status & (ATA_S_CORR | ATA_S_ERROR)) == ATA_S_CORR) {
292             device_printf(request->dev,
293                           "WARNING - %s soft error (ECC corrected)",
294                           ata_cmd2str(request));
295             if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
296                 printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
297             printf("\n");
298         }
299
300         /* if this is a UDMA CRC error we reinject if there are retries left */
301         if (request->flags & ATA_R_DMA && request->error & ATA_E_ICRC) {
302             if (request->retries-- > 0) {
303                 device_printf(request->dev,
304                               "WARNING - %s UDMA ICRC error (retrying request)",
305                               ata_cmd2str(request));
306                 if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
307                     printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
308                 printf("\n");
309                 request->flags |= (ATA_R_AT_HEAD | ATA_R_REQUEUE);
310                 ata_queue_request(request);
311                 return;
312             }
313         }
314     }
315
316     switch (request->flags & ATA_R_ATAPI) {
317
318     /* ATA errors */
319     default:
320         if (!request->result && request->status & ATA_S_ERROR) {
321             if (!(request->flags & ATA_R_QUIET)) {
322                 device_printf(request->dev,
323                               "FAILURE - %s status=%b error=%b", 
324                               ata_cmd2str(request),
325                               request->status, "\20\10BUSY\7READY\6DMA_READY"
326                               "\5DSC\4DRQ\3CORRECTABLE\2INDEX\1ERROR",
327                               request->error, "\20\10ICRC\7UNCORRECTABLE"
328                               "\6MEDIA_CHANGED\5NID_NOT_FOUND"
329                               "\4MEDIA_CHANGE_REQEST"
330                               "\3ABORTED\2NO_MEDIA\1ILLEGAL_LENGTH");
331                 if ((request->flags & ATA_R_DMA) &&
332                     (request->dmastat & ATA_BMSTAT_ERROR))
333                     printf(" dma=0x%02x", request->dmastat);
334                 if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
335                     printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
336                 printf("\n");
337             }
338             request->result = EIO;
339         }
340         break;
341
342     /* ATAPI errors */
343     case ATA_R_ATAPI:
344         /* skip if result already set */
345         if (request->result)
346             break;
347
348         /* if we have a sensekey -> request sense from device */
349         if (request->error & ATA_SK_MASK &&
350             request->u.atapi.ccb[0] != ATAPI_REQUEST_SENSE) {
351             static u_int8_t ccb[16] = { ATAPI_REQUEST_SENSE, 0, 0, 0,
352                                         sizeof(struct atapi_sense),
353                                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
354
355             request->u.atapi.sense_key = request->error;
356             request->u.atapi.sense_cmd = request->u.atapi.ccb[0];
357             bcopy(ccb, request->u.atapi.ccb, 16);
358             request->data = (caddr_t)&request->u.atapi.sense_data;
359             request->bytecount = sizeof(struct atapi_sense);
360             request->donecount = 0;
361             request->transfersize = sizeof(struct atapi_sense);
362             request->timeout = 5;
363             request->flags &= (ATA_R_ATAPI | ATA_R_QUIET);
364             request->flags |= (ATA_R_READ | ATA_R_AT_HEAD | ATA_R_REQUEUE);
365             ATA_DEBUG_RQ(request, "autoissue request sense");
366             ata_queue_request(request);
367             return;
368         }
369
370         switch (request->u.atapi.sense_key & ATA_SK_MASK) {
371         case ATA_SK_RECOVERED_ERROR:
372             device_printf(request->dev, "WARNING - %s recovered error\n",
373                           ata_cmd2str(request));
374             /* FALLTHROUGH */
375
376         case ATA_SK_NO_SENSE:
377             request->result = 0;
378             break;
379
380         case ATA_SK_NOT_READY: 
381             request->result = EBUSY;
382             break;
383
384         case ATA_SK_UNIT_ATTENTION:
385             atadev->flags |= ATA_D_MEDIA_CHANGED;
386             request->result = EIO;
387             break;
388
389         default:
390             request->result = EIO;
391             if (request->flags & ATA_R_QUIET)
392                 break;
393
394             device_printf(request->dev,
395                           "FAILURE - %s %s asc=0x%02x ascq=0x%02x ",
396                           ata_cmd2str(request), ata_skey2str(
397                           (request->u.atapi.sense_key & ATA_SK_MASK) >> 4),
398                           request->u.atapi.sense_data.asc,
399                           request->u.atapi.sense_data.ascq);
400             if (request->u.atapi.sense_data.sksv)
401                 printf("sks=0x%02x 0x%02x 0x%02x ",
402                        request->u.atapi.sense_data.sk_specific,
403                        request->u.atapi.sense_data.sk_specific1,
404                        request->u.atapi.sense_data.sk_specific2);
405             printf("error=%b\n",
406                    (request->u.atapi.sense_key & ATA_E_MASK),
407                    "\20\4MEDIA_CHANGE_REQUEST\3ABORTED"
408                    "\2NO_MEDIA\1ILLEGAL_LENGTH");
409         }
410
411         if ((request->u.atapi.sense_key ?
412              request->u.atapi.sense_key : request->error) & ATA_E_MASK)
413             request->result = EIO;
414     }
415
416     ATA_DEBUG_RQ(request, "completed callback/wakeup");
417
418     /* if we are part of a composite operation update progress */
419     if ((composite = request->composite)) {
420         int index = 0;
421
422         mtx_lock(&composite->lock);
423         if (request->flags & ATA_R_READ)
424             composite->rd_done |= (1 << request->this);
425         if (request->flags & ATA_R_WRITE)
426             composite->wr_done |= (1 << request->this);
427
428         if (composite->wr_depend &&
429             (composite->rd_done & composite->wr_depend)==composite->wr_depend &&
430             (composite->wr_needed & (~composite->wr_done))) {
431             index = ((composite->wr_needed & (~composite->wr_done))) - 1;
432         }
433         mtx_unlock(&composite->lock);
434         if (index)
435             ata_start(device_get_parent(composite->request[index]->dev));
436     }
437
438     /* get results back to the initiator */
439     if (request->callback)
440         (request->callback)(request);
441     else
442         sema_post(&request->done);
443
444     ata_start(ch->dev);
445 }
446
447 void
448 ata_timeout(struct ata_request *request)
449 {
450     struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
451
452     //request->flags |= ATA_R_DEBUG;
453     ATA_DEBUG_RQ(request, "timeout");
454
455     /*
456      * if we have an ATA_ACTIVE request running, we flag the request 
457      * ATA_R_TIMEOUT so ata_finish will handle it correctly
458      * also NULL out the running request so we wont loose 
459      * the race with an eventual interrupt arriving late
460      */
461     if (ch->state == ATA_ACTIVE) {
462         request->flags |= ATA_R_TIMEOUT;
463         ch->running = NULL;
464         mtx_unlock(&ch->state_mtx);
465         ATA_LOCKING(ch->dev, ATA_LF_UNLOCK);
466         ata_finish(request);
467     }
468     else {
469         mtx_unlock(&ch->state_mtx);
470     }
471 }
472
473 void
474 ata_fail_requests(device_t dev)
475 {
476     struct ata_channel *ch = device_get_softc(device_get_parent(dev));
477     struct ata_request *request;
478
479     /* do we have any outstanding request to care about ?*/
480     mtx_lock(&ch->state_mtx);
481     if ((request = ch->running) && (!dev || request->dev == dev)) {
482         callout_stop(&request->callout);
483         ch->running = NULL;
484     }
485     else
486         request = NULL;
487     mtx_unlock(&ch->state_mtx);
488     if (request)  {
489         request->result = ENXIO;
490         ata_finish(request);
491     }
492
493     /* fail all requests queued on this channel for device dev if !NULL */
494     mtx_lock(&ch->queue_mtx);
495     while ((request = TAILQ_FIRST(&ch->ata_queue))) {
496         if (!dev || request->dev == dev) {
497             TAILQ_REMOVE(&ch->ata_queue, request, chain);
498             mtx_unlock(&ch->queue_mtx);
499             request->result = ENXIO;
500             ata_finish(request);
501             mtx_lock(&ch->queue_mtx);
502         }
503     }
504     mtx_unlock(&ch->queue_mtx);
505 }
506
507 static u_int64_t
508 ata_get_lba(struct ata_request *request)
509 {
510     if (request->flags & ATA_R_ATAPI) {
511         switch (request->u.atapi.ccb[0]) {
512         case ATAPI_READ_BIG:
513         case ATAPI_WRITE_BIG:
514         case ATAPI_READ_CD:
515             return (request->u.atapi.ccb[5]) | (request->u.atapi.ccb[4]<<8) |
516                    (request->u.atapi.ccb[3]<<16)|(request->u.atapi.ccb[2]<<24);
517         case ATAPI_READ:
518         case ATAPI_WRITE:
519             return (request->u.atapi.ccb[4]) | (request->u.atapi.ccb[3]<<8) |
520                    (request->u.atapi.ccb[2]<<16);
521         default:
522             return 0;
523         }
524     }
525     else
526         return request->u.ata.lba;
527 }
528
529 static void
530 ata_sort_queue(struct ata_channel *ch, struct ata_request *request)
531 {
532     struct ata_request *this, *next;
533
534     this = TAILQ_FIRST(&ch->ata_queue);
535
536     /* if the queue is empty just insert */
537     if (!this) {
538         if (request->composite)
539             ch->freezepoint = request;
540         TAILQ_INSERT_TAIL(&ch->ata_queue, request, chain);
541         return;
542     }
543
544     /* dont sort frozen parts of the queue */
545     if (ch->freezepoint)
546         this = ch->freezepoint;
547         
548     /* if position is less than head we add after tipping point */
549     if (ata_get_lba(request) < ata_get_lba(this)) {
550         while ((next = TAILQ_NEXT(this, chain))) {
551
552             /* have we reached the tipping point */
553             if (ata_get_lba(next) < ata_get_lba(this)) {
554
555                 /* sort the insert */
556                 do {
557                     if (ata_get_lba(request) < ata_get_lba(next))
558                         break;
559                     this = next;
560                 } while ((next = TAILQ_NEXT(this, chain)));
561                 break;
562             }
563             this = next;
564         }
565     }
566
567     /* we are after head so sort the insert before tipping point */
568     else {
569         while ((next = TAILQ_NEXT(this, chain))) {
570             if (ata_get_lba(next) < ata_get_lba(this) ||
571                 ata_get_lba(request) < ata_get_lba(next))
572                 break;
573             this = next;
574         }
575     }
576
577     if (request->composite)
578         ch->freezepoint = request;
579     TAILQ_INSERT_AFTER(&ch->ata_queue, this, request, chain);
580 }
581
582 char *
583 ata_cmd2str(struct ata_request *request)
584 {
585     static char buffer[20];
586
587     if (request->flags & ATA_R_ATAPI) {
588         switch (request->u.atapi.sense_key ?
589                 request->u.atapi.sense_cmd : request->u.atapi.ccb[0]) {
590         case 0x00: return ("TEST_UNIT_READY");
591         case 0x01: return ("REZERO");
592         case 0x03: return ("REQUEST_SENSE");
593         case 0x04: return ("FORMAT");
594         case 0x08: return ("READ");
595         case 0x0a: return ("WRITE");
596         case 0x10: return ("WEOF");
597         case 0x11: return ("SPACE");
598         case 0x12: return ("INQUIRY");
599         case 0x15: return ("MODE_SELECT");
600         case 0x19: return ("ERASE");
601         case 0x1a: return ("MODE_SENSE");
602         case 0x1b: return ("START_STOP");
603         case 0x1e: return ("PREVENT_ALLOW");
604         case 0x23: return ("ATAPI_READ_FORMAT_CAPACITIES");
605         case 0x25: return ("READ_CAPACITY");
606         case 0x28: return ("READ_BIG");
607         case 0x2a: return ("WRITE_BIG");
608         case 0x2b: return ("LOCATE");
609         case 0x34: return ("READ_POSITION");
610         case 0x35: return ("SYNCHRONIZE_CACHE");
611         case 0x3b: return ("WRITE_BUFFER");
612         case 0x3c: return ("READ_BUFFER");
613         case 0x42: return ("READ_SUBCHANNEL");
614         case 0x43: return ("READ_TOC");
615         case 0x45: return ("PLAY_10");
616         case 0x47: return ("PLAY_MSF");
617         case 0x48: return ("PLAY_TRACK");
618         case 0x4b: return ("PAUSE");
619         case 0x51: return ("READ_DISK_INFO");
620         case 0x52: return ("READ_TRACK_INFO");
621         case 0x53: return ("RESERVE_TRACK");
622         case 0x54: return ("SEND_OPC_INFO");
623         case 0x55: return ("MODE_SELECT_BIG");
624         case 0x58: return ("REPAIR_TRACK");
625         case 0x59: return ("READ_MASTER_CUE");
626         case 0x5a: return ("MODE_SENSE_BIG");
627         case 0x5b: return ("CLOSE_TRACK/SESSION");
628         case 0x5c: return ("READ_BUFFER_CAPACITY");
629         case 0x5d: return ("SEND_CUE_SHEET");
630         case 0xa1: return ("BLANK_CMD");
631         case 0xa3: return ("SEND_KEY");
632         case 0xa4: return ("REPORT_KEY");
633         case 0xa5: return ("PLAY_12");
634         case 0xa6: return ("LOAD_UNLOAD");
635         case 0xad: return ("READ_DVD_STRUCTURE");
636         case 0xb4: return ("PLAY_CD");
637         case 0xbb: return ("SET_SPEED");
638         case 0xbd: return ("MECH_STATUS");
639         case 0xbe: return ("READ_CD");
640         case 0xff: return ("POLL_DSC");
641         }
642     }
643     else {
644         switch (request->u.ata.command) {
645         case 0x00: return ("NOP");
646         case 0x08: return ("DEVICE_RESET");
647         case 0x20: return ("READ");
648         case 0x24: return ("READ48");
649         case 0x25: return ("READ_DMA48");
650         case 0x26: return ("READ_DMA_QUEUED48");
651         case 0x29: return ("READ_MUL48");
652         case 0x30: return ("WRITE");
653         case 0x34: return ("WRITE48");
654         case 0x35: return ("WRITE_DMA48");
655         case 0x36: return ("WRITE_DMA_QUEUED48");
656         case 0x39: return ("WRITE_MUL48");
657         case 0x70: return ("SEEK");
658         case 0xa0: return ("PACKET_CMD");
659         case 0xa1: return ("ATAPI_IDENTIFY");
660         case 0xa2: return ("SERVICE");
661         case 0xc0: return ("CFA ERASE");
662         case 0xc4: return ("READ_MUL");
663         case 0xc5: return ("WRITE_MUL");
664         case 0xc6: return ("SET_MULTI");
665         case 0xc7: return ("READ_DMA_QUEUED");
666         case 0xc8: return ("READ_DMA");
667         case 0xca: return ("WRITE_DMA");
668         case 0xcc: return ("WRITE_DMA_QUEUED");
669         case 0xe6: return ("SLEEP");
670         case 0xe7: return ("FLUSHCACHE");
671         case 0xea: return ("FLUSHCACHE48");
672         case 0xec: return ("ATA_IDENTIFY");
673         case 0xef:
674             switch (request->u.ata.feature) {
675             case 0x03: return ("SETFEATURES SET TRANSFER MODE");
676             case 0x02: return ("SETFEATURES ENABLE WCACHE");
677             case 0x82: return ("SETFEATURES DISABLE WCACHE");
678             case 0xaa: return ("SETFEATURES ENABLE RCACHE");
679             case 0x55: return ("SETFEATURES DISABLE RCACHE");
680             }
681             sprintf(buffer, "SETFEATURES 0x%02x", request->u.ata.feature);
682             return buffer;
683         }
684     }
685     sprintf(buffer, "unknown CMD (0x%02x)", request->u.ata.command);
686     return buffer;
687 }
688
689 static char *
690 ata_skey2str(u_int8_t skey)
691 {
692     switch (skey) {
693     case 0x00: return ("NO SENSE");
694     case 0x01: return ("RECOVERED ERROR");
695     case 0x02: return ("NOT READY");
696     case 0x03: return ("MEDIUM ERROR");
697     case 0x04: return ("HARDWARE ERROR");
698     case 0x05: return ("ILLEGAL REQUEST");
699     case 0x06: return ("UNIT ATTENTION");
700     case 0x07: return ("DATA PROTECT");
701     case 0x08: return ("BLANK CHECK");
702     case 0x09: return ("VENDOR SPECIFIC");
703     case 0x0a: return ("COPY ABORTED");
704     case 0x0b: return ("ABORTED COMMAND");
705     case 0x0c: return ("EQUAL");
706     case 0x0d: return ("VOLUME OVERFLOW");
707     case 0x0e: return ("MISCOMPARE");
708     case 0x0f: return ("RESERVED");
709     default: return("UNKNOWN");
710     }
711 }