2 * Copyright (C) 2012, The AROS Development Team. All rights reserved.
3 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
5 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
8 #include <exec/errors.h>
9 #include <devices/scsidisk.h>
10 #include <devices/trackdisk.h>
11 #include <scsi/commands.h>
12 #include <scsi/values.h>
15 #include "ahci_scsi.h"
20 #define offsetof(TYPE, MEMBER) ((IPTR) &((TYPE *)0)->MEMBER)
21 #define container_of(ptr, type, member) ({ \
22 const typeof(((type *)0)->member) *__mptr = (ptr); \
23 (type *)((char *)__mptr - offsetof(type, member)); })
26 static inline UQUAD
scsi_8btou64(UBYTE
*addr
)
31 for (i
= 0; i
< 8; i
++, res
<<= 8, res
|= *(addr
++));
35 static inline ULONG
scsi_4btoul(UBYTE
*addr
)
40 for (i
= 0; i
< 4; i
++, res
<<= 8, res
|= *(addr
++));
44 static inline ULONG
scsi_3btoul(UBYTE
*addr
)
49 for (i
= 0; i
< 3; i
++, res
<<= 8, res
|= *(addr
++));
53 static inline ULONG
scsi_2btoul(UBYTE
*addr
)
58 for (i
= 0; i
< 2; i
++, res
<<= 8, res
|= *(addr
++));
62 static inline void scsi_ulto4b(ULONG val
, UBYTE
*addr
)
65 for (i
= 3; i
>= 0; i
--, val
>>= 8)
70 * Construct dummy sense data for disks, and ATAPI devices
71 * that do not support extended status
73 * In the io_complete, there should a REQUEST SENSE command
76 static void ahci_ata_sense(struct ata_xfer
*xa
,
77 struct scsi_sense_data
*sense_data
)
79 struct ata_fis_d2h
*rfis
= &xa
->rfis
;
80 UBYTE asc
= 0, asq
= 0, key
= 0;
82 if ((rfis
->status
& ATA_D2H_STATUS_BSY
)) {
83 key
= SSD_KEY_ABORTED_COMMAND
;
85 /* Decode error bits */
86 switch (rfis
->error
& 0xff) {
87 case ATA_D2H_ERROR_BBK
|ATA_D2H_ERROR_UNK
|ATA_D2H_ERROR_IDNF
:
88 case ATA_D2H_ERROR_BBK
|ATA_D2H_ERROR_UNK
|ATA_D2H_ERROR_IDNF
|ATA_D2H_ERROR_AMNF
:
89 /* Device busy, aborted command */
90 case ATA_D2H_ERROR_ABRT
:
92 key
= SSD_KEY_ABORTED_COMMAND
;
93 asc
= 0x00; asq
= 0x00; /* no additional sense code */
95 case ATA_D2H_ERROR_UNK
|ATA_D2H_ERROR_MC
|ATA_D2H_ERROR_AMNF
:
97 key
= SSD_KEY_HARDWARE_ERROR
;
98 asc
= 0x44; asq
= 0x00; /* internal target failure */
100 case ATA_D2H_ERROR_BBK
|ATA_D2H_ERROR_ABRT
:
101 /* Data partiy error */
102 key
= SSD_KEY_ABORTED_COMMAND
;
103 asc
= 0x4b; asq
= 0x00; /* data phase error */
105 case ATA_D2H_ERROR_MC
:
107 key
= SSD_KEY_NOT_READY
;
108 asc
= 0x3a; asq
= 0x00; /* medium not present */
110 case ATA_D2H_ERROR_MCR
:
111 /* Media change request */
112 key
= SSD_KEY_NOT_READY
;
113 asc
= 0x04; asq
= 0x03; /* manual intervention required */
115 case ATA_D2H_ERROR_MC
|ATA_D2H_ERROR_IDNF
|ATA_D2H_ERROR_ABRT
|ATA_D2H_ERROR_TK0NF
|ATA_D2H_ERROR_AMNF
:
116 case ATA_D2H_ERROR_MCR
|ATA_D2H_ERROR_AMNF
:
117 /* Unit offline or not ready */
118 key
= SSD_KEY_NOT_READY
;
119 asc
= 0x04; asq
= 0x00; /* unknown reason */
121 case ATA_D2H_ERROR_AMNF
:
122 /* No address mark found */
123 key
= SSD_KEY_MEDIUM_ERROR
;
124 asc
= 0x31; asq
= 0x00; /* medium format corrupted */
126 case ATA_D2H_ERROR_TK0NF
:
127 /* Track 0 not found */
128 key
= SSD_KEY_HARDWARE_ERROR
;
129 asc
= 0x02; asq
= 0x00; /* no seek complete */
131 case ATA_D2H_ERROR_IDNF
:
132 /* Sector not found */
133 key
= SSD_KEY_ILLEGAL_REQUEST
;
134 asc
= 0x21; asq
= 0x00; /* LBA out of range */
136 case ATA_D2H_ERROR_BBK
:
137 /* Bad block (now defined as interface CRC in ATA8-ACS) */
138 key
= SSD_KEY_ABORTED_COMMAND
;
139 asc
= 0x47; asq
= 0x00; /* SCSI partity error */
141 case ATA_D2H_ERROR_UNK
:
143 key
= SSD_KEY_MEDIUM_ERROR
;
144 if ((xa
->fis
->flags
& ATA_H2D_FEATURES_DIR
) == ATA_H2D_FEATURES_DIR_WRITE
) {
145 asc
= 0x10; asq
= 0x00; /* write fault */
147 asc
= 0x11; asq
= 0x00; /* read fault */
151 D(bug("ahci.device: No sense translation for ATA Error 0x%02x\n", rfis
->error
));
152 switch (rfis
->status
) {
153 case ATA_D2H_STATUS_DF
:
154 key
= SSD_KEY_HARDWARE_ERROR
;
155 asc
= 0x44; asq
= 0x00; /* Internal target failure */
157 case ATA_D2H_STATUS_DRQ
:
158 key
= SSD_KEY_ABORTED_COMMAND
;
159 asc
= 0x4B; asq
= 0x00; /* Data phase error */
161 case ATA_D2H_STATUS_CORR
:
162 if ((xa
->fis
->flags
& ATA_H2D_FEATURES_DIR
) == ATA_H2D_FEATURES_DIR_WRITE
) {
163 key
= SSD_KEY_RECOVERED_ERROR
;
164 asc
= 0x0c; asq
= 0x01; /* Recovered write with realloc */
166 key
= SSD_KEY_RECOVERED_ERROR
;
167 asc
= 0x18; asq
= 0x02; /* Recovered read with realloc */
171 D(bug("ahci.device: No sense translation for ATA Status 0x%02x\n", rfis
->status
));
172 key
= SSD_KEY_ABORTED_COMMAND
;
179 memset(sense_data
, 0, sizeof(sense_data
));
181 sense_data
->error_code
= SSD_ERRCODE_VALID
| SSD_CURRENT_ERROR
;
183 sense_data
->flags
= ((rfis
->error
& 0xF0) >> 4) | key
;
184 if (rfis
->error
& ATA_D2H_ERROR_AMNF
)
185 sense_data
->flags
|= SSD_ILI
;
186 sense_data
->add_sense_code
= asc
;
187 sense_data
->add_sense_qual
= asq
;
190 static void ahci_io_complete(struct ata_xfer
*xa
)
192 struct IORequest
*io
= xa
->atascsi_private
;
193 const int sense_length
= offsetof(struct scsi_sense_data
, extra_bytes
[0]);
194 struct cam_sim
*unit
= (struct cam_sim
*)io
->io_Unit
;
198 if (io
->io_Command
== HD_SCSICMD
) {
199 struct SCSICmd
*scsi
= IOStdReq(io
)->io_Data
;
200 scsi
->scsi_Status
= SCSI_GOOD
;
201 scsi
->scsi_Actual
= xa
->datalen
;
202 IOStdReq(io
)->io_Actual
= sizeof(*scsi
);
204 IOStdReq(io
)->io_Actual
= xa
->datalen
;
208 if (io
->io_Command
== HD_SCSICMD
) {
209 struct SCSICmd
*scsi
= IOStdReq(io
)->io_Data
;
210 D(bug("Error on HD_SCSICMD\n"));
211 scsi
->scsi_Status
= SCSI_CHECK_CONDITION
;
212 scsi
->scsi_Actual
= 0;
213 IOStdReq(io
)->io_Actual
= sizeof(*scsi
);
214 if (scsi
->scsi_Flags
& (SCSIF_AUTOSENSE
| SCSIF_OLDAUTOSENSE
)) {
215 D(bug("SCSIF_AUTOSENSE desired\n"));
216 if (scsi
->scsi_SenseData
&& scsi
->scsi_SenseLength
>= sense_length
) {
217 ahci_ata_sense(xa
, (void *)scsi
->scsi_SenseData
);
218 scsi
->scsi_SenseActual
= sense_length
;
219 D(bug("SCSI Sense: KCQ = 0x%02x 0x%02x 0x%02x\n",
220 scsi
->scsi_SenseData
[2],
221 scsi
->scsi_SenseData
[12],
222 scsi
->scsi_SenseData
[13]));
226 io
->io_Error
= TDERR_SeekError
;
227 IOStdReq(io
)->io_Actual
= 0;
231 if (io
->io_Command
== HD_SCSICMD
) {
232 struct SCSICmd
*scsi
= IOStdReq(io
)->io_Data
;
233 scsi
->scsi_Status
= SCSI_BUSY
;
234 scsi
->scsi_Actual
= 0;
235 IOStdReq(io
)->io_Actual
= sizeof(*scsi
);
237 io
->io_Error
= IOERR_UNITBUSY
;
238 IOStdReq(io
)->io_Actual
= 0;
242 io
->io_Error
= IOERR_NOCMD
;
246 ahci_ata_put_xfer(xa
);
248 ObtainSemaphore(&unit
->sim_Lock
);
249 Remove(&io
->io_Message
.mn_Node
);
250 ReleaseSemaphore(&unit
->sim_Lock
);
252 ASSERT(!(io
->io_Flags
& IOF_QUICK
));
254 D(bug("[AHCI%02ld] IO %p Final, io_Flags = %d, io_Error = %d\n", unit
->sim_Unit
, io
, io
->io_Flags
, io
->io_Error
));
255 ReplyMsg(&io
->io_Message
);
260 * Simulate page inquiries for disk attachments.
262 static BYTE
ahci_scsi_page_inquiry(struct ahci_port
*ap
, struct ata_port
*at
, struct SCSICmd
*scsi
)
265 struct scsi_vpd_supported_page_list list
;
266 struct scsi_vpd_unit_serial_number serno
;
274 cdb
= (APTR
)scsi
->scsi_Command
;
276 switch(cdb
->inquiry
.page_code
) {
277 case SVPD_SUPPORTED_PAGE_LIST
:
279 page
.list
.device
= T_DIRECT
;
280 page
.list
.page_code
= SVPD_SUPPORTED_PAGE_LIST
;
281 page
.list
.list
[i
++] = SVPD_SUPPORTED_PAGE_LIST
;
282 page
.list
.list
[i
++] = SVPD_UNIT_SERIAL_NUMBER
;
283 page
.list
.length
= i
;
284 len
= offsetof(struct scsi_vpd_supported_page_list
, list
[3]);
286 case SVPD_UNIT_SERIAL_NUMBER
:
288 j
= sizeof(at
->at_identify
.serial
);
289 for (i
= 0; i
< j
&& at
->at_identify
.serial
[i
] == ' '; ++i
)
291 while (j
> i
&& at
->at_identify
.serial
[j
-1] == ' ')
293 page
.serno
.device
= T_DIRECT
;
294 page
.serno
.page_code
= SVPD_UNIT_SERIAL_NUMBER
;
295 page
.serno
.length
= j
- i
;
296 CopyMem(at
->at_identify
.serial
+ i
,
297 page
.serno
.serial_num
, j
- i
);
298 len
= offsetof(struct scsi_vpd_unit_serial_number
,
306 if (len
> scsi
->scsi_Length
)
307 return IOERR_BADLENGTH
;
309 memset(scsi
->scsi_Data
+ len
, 0, scsi
->scsi_Length
- len
);
310 CopyMem(&page
, scsi
->scsi_Data
, len
);
311 scsi
->scsi_Actual
= len
;
318 * Convert the SCSI command to an ata_xfer command in xa
319 * for ATA_PORT_T_DISK operations. Set the completion function
320 * to convert the response back, then dispatch to the OpenBSD AHCI
323 * AHCI DISK commands only support a limited command set, and we
324 * fake additional commands to make it play nice.
326 * Return TRUE if no need to wait for a reply
328 BOOL
ahci_scsi_disk_io(struct IORequest
*io
, struct SCSICmd
*scsi
)
330 struct cam_sim
*unit
= (struct cam_sim
*)io
->io_Unit
;
331 struct ahci_port
*ap
= unit
->sim_Port
;
332 struct ata_port
*at
= ap
->ap_ata
[0];
334 struct ata_fis_h2d
*fis
;
336 struct scsi_inquiry_data inquiry_data
;
337 struct scsi_read_capacity_data read_capacity_data
;
338 } *rdata
= (APTR
)scsi
->scsi_Command
;
339 ULONG rdata_len
= scsi
->scsi_CmdLength
;
344 scsi_cdb_t cdb
= (APTR
)scsi
->scsi_Command
;
346 xa
= ahci_ata_get_xfer(ap
, at
);
348 switch(cdb
->generic
.opcode
) {
349 case SCSI_REQUEST_SENSE
:
351 * Auto-sense everything, so explicit sense requests
354 io
->io_Error
= HFERR_BadStatus
;
360 * Inquiry supported features
362 * [opcode, byte2, page_code, length, control]
364 if (cdb
->inquiry
.byte2
& SI_EVPD
) {
365 io
->io_Error
= ahci_scsi_page_inquiry(ap
, at
, scsi
);
367 memset(rdata
, 0, rdata_len
);
368 if (rdata_len
< SHORT_INQUIRY_LENGTH
) {
369 io
->io_Error
= IOERR_BADLENGTH
;
372 if (rdata_len
> sizeof(rdata
->inquiry_data
))
373 rdata_len
= sizeof(rdata
->inquiry_data
);
374 rdata
->inquiry_data
.device
= T_DIRECT
;
375 /* Mark as removable if ATA has the 'removable' tag */
376 rdata
->inquiry_data
.dev_qual2
= (at
->at_identify
.config
? 0x80 : 0);
377 rdata
->inquiry_data
.version
= SCSI_REV_SPC2
;
378 rdata
->inquiry_data
.response_format
= 2;
379 rdata
->inquiry_data
.additional_length
= 32;
382 * Use the vendor specific area to set the TRIM status
384 if (at
->at_identify
.support_dsm
) {
385 rdata
->inquiry_data
.vendor_specific
[0] =
386 at
->at_identify
.support_dsm
&ATA_SUPPORT_DSM_TRIM
;
387 rdata
->inquiry_data
.vendor_specific
[1] =
388 at
->at_identify
.max_dsm_blocks
;
390 CopyMem("SATA ", rdata
->inquiry_data
.vendor
, 8);
391 CopyMem(at
->at_identify
.model
,
392 rdata
->inquiry_data
.product
,
393 sizeof(rdata
->inquiry_data
.product
));
394 CopyMem(at
->at_identify
.firmware
,
395 rdata
->inquiry_data
.revision
,
396 sizeof(rdata
->inquiry_data
.revision
));
399 case SCSI_DA_READ_CAPACITY
:
401 if (rdata_len
< sizeof(rdata
->read_capacity_data
)) {
402 io
->io_Error
= IOERR_BADLENGTH
;
406 capacity
= at
->at_capacity
;
408 memset(rdata
, 0, rdata_len
);
409 rdata_len
= sizeof(rdata
->read_capacity_data
);
410 if (capacity
> 0xFFFFFFFFU
)
411 capacity
= 0xFFFFFFFFU
;
412 memset(&rdata
->read_capacity_data
, 0, rdata_len
);
413 scsi_ulto4b((u_int32_t
)capacity
- 1,
414 rdata
->read_capacity_data
.addr
);
415 scsi_ulto4b(512, rdata
->read_capacity_data
.length
);
417 case SCSI_DA_SYNCHRONIZE_CACHE
:
419 * Synchronize cache. Specification says this can take
420 * greater then 30 seconds so give it at least 45.
423 fis
->flags
= ATA_H2D_FLAGS_CMD
;
424 fis
->command
= ATA_C_FLUSH_CACHE
;
426 if (xa
->timeout
< 45000)
430 xa
->complete
= ahci_io_complete
;
432 case SCSI_TEST_UNIT_READY
:
434 * Just silently return success
440 switch(cdb
->generic
.opcode
) {
442 lba
= scsi_3btoul(cdb
->rw_6
.addr
) & 0x1FFFFF;
443 count
= cdb
->rw_6
.length
? cdb
->rw_6
.length
: 0x100;
444 xa
->flags
= ATA_F_READ
;
446 case SCSI_DA_READ_10
:
447 lba
= scsi_4btoul(cdb
->rw_10
.addr
);
448 count
= scsi_2btoul(cdb
->rw_10
.length
);
449 xa
->flags
= ATA_F_READ
;
451 case SCSI_DA_READ_12
:
452 lba
= scsi_4btoul(cdb
->rw_12
.addr
);
453 count
= scsi_4btoul(cdb
->rw_12
.length
);
454 xa
->flags
= ATA_F_READ
;
456 case SCSI_DA_READ_16
:
457 lba
= scsi_8btou64(cdb
->rw_16
.addr
);
458 count
= scsi_4btoul(cdb
->rw_16
.length
);
459 xa
->flags
= ATA_F_READ
;
461 case SCSI_DA_WRITE_6
:
462 lba
= scsi_3btoul(cdb
->rw_6
.addr
) & 0x1FFFFF;
463 count
= cdb
->rw_6
.length
? cdb
->rw_6
.length
: 0x100;
464 xa
->flags
= ATA_F_WRITE
;
466 case SCSI_DA_WRITE_10
:
467 lba
= scsi_4btoul(cdb
->rw_10
.addr
);
468 count
= scsi_2btoul(cdb
->rw_10
.length
);
469 xa
->flags
= ATA_F_WRITE
;
471 case SCSI_DA_WRITE_12
:
472 lba
= scsi_4btoul(cdb
->rw_12
.addr
);
473 count
= scsi_4btoul(cdb
->rw_12
.length
);
474 xa
->flags
= ATA_F_WRITE
;
476 case SCSI_DA_WRITE_16
:
477 lba
= scsi_8btou64(cdb
->rw_16
.addr
);
478 count
= scsi_4btoul(cdb
->rw_16
.length
);
479 xa
->flags
= ATA_F_WRITE
;
482 io
->io_Error
= IOERR_NOCMD
;
490 fis
->flags
= ATA_H2D_FLAGS_CMD
;
491 fis
->lba_low
= (u_int8_t
)lba
;
492 fis
->lba_mid
= (u_int8_t
)(lba
>> 8);
493 fis
->lba_high
= (u_int8_t
)(lba
>> 16);
494 fis
->device
= ATA_H2D_DEVICE_LBA
;
497 * NCQ only for direct-attached disks, do not currently
498 * try to use NCQ with port multipliers.
500 if (at
->at_ncqdepth
> 1 &&
501 ap
->ap_type
== ATA_PORT_T_DISK
&&
502 (ap
->ap_sc
->sc_cap
& AHCI_REG_CAP_SNCQ
)) {
504 * Use NCQ - always uses 48 bit addressing
506 xa
->flags
|= ATA_F_NCQ
;
507 fis
->command
= (xa
->flags
& ATA_F_WRITE
) ?
508 ATA_C_WRITE_FPDMA
: ATA_C_READ_FPDMA
;
509 fis
->lba_low_exp
= (u_int8_t
)(lba
>> 24);
510 fis
->lba_mid_exp
= (u_int8_t
)(lba
>> 32);
511 fis
->lba_high_exp
= (u_int8_t
)(lba
>> 40);
512 fis
->sector_count
= xa
->tag
<< 3;
513 fis
->features
= (u_int8_t
)count
;
514 fis
->features_exp
= (u_int8_t
)(count
>> 8);
515 } else if (count
> 0x100 || lba
> 0x0FFFFFFFU
) {
519 fis
->command
= (xa
->flags
& ATA_F_WRITE
) ?
520 ATA_C_WRITEDMA_EXT
: ATA_C_READDMA_EXT
;
521 fis
->lba_low_exp
= (u_int8_t
)(lba
>> 24);
522 fis
->lba_mid_exp
= (u_int8_t
)(lba
>> 32);
523 fis
->lba_high_exp
= (u_int8_t
)(lba
>> 40);
524 fis
->sector_count
= (u_int8_t
)count
;
525 fis
->sector_count_exp
= (u_int8_t
)(count
>> 8);
530 * NOTE: 256 sectors is supported, stored as 0.
532 fis
->command
= (xa
->flags
& ATA_F_WRITE
) ?
533 ATA_C_WRITEDMA
: ATA_C_READDMA
;
534 fis
->device
|= (u_int8_t
)(lba
>> 24) & 0x0F;
535 fis
->sector_count
= (u_int8_t
)count
;
538 xa
->data
= scsi
->scsi_Data
;
539 xa
->datalen
= scsi
->scsi_Length
;
540 xa
->complete
= ahci_io_complete
;
541 xa
->timeout
= 1000; /* milliseconds */
543 if (xa
->timeout
> 10000) /* XXX - debug */
550 * If the request is still in progress the xa and FIS have
551 * been set up (except for the PM target), and must be dispatched.
552 * Otherwise the request was completed.
555 io
->io_Flags
&= ~IOF_QUICK
;
556 KKASSERT(xa
->complete
!= NULL
);
557 xa
->atascsi_private
= io
;
558 ahci_os_lock_port(ap
);
559 xa
->fis
->flags
|= at
->at_target
;
561 ahci_os_unlock_port(ap
);
563 IOStdReq(io
)->io_Actual
= sizeof(*scsi
);
564 ahci_ata_put_xfer(xa
);
571 * Convert the SCSI command in ccb to an ata_xfer command in xa
572 * for ATA_PORT_T_ATAPI operations. Set the completion function
573 * to convert the response back, then dispatch to the OpenBSD AHCI
576 BOOL
ahci_scsi_atapi_io(struct IORequest
*io
, struct SCSICmd
*scsi
)
578 struct cam_sim
*unit
= (struct cam_sim
*)io
->io_Unit
;
579 struct ahci_port
*ap
= unit
->sim_Port
;
580 struct ata_port
*at
= ap
->ap_ata
[0];
582 struct ata_fis_h2d
*fis
;
585 uint32_t offset
, len
;
588 if (scsi
->scsi_Flags
& SCSIF_READ
) {
589 flags
= ATA_F_PACKET
| ATA_F_READ
;
591 flags
= ATA_F_PACKET
| ATA_F_WRITE
;
595 * Special handling to get the rfis back into host memory while
596 * still allowing the chip to run commands in parallel to
597 * ATAPI devices behind a PM.
599 if (scsi
->scsi_Flags
& (SCSIF_AUTOSENSE
| SCSIF_OLDAUTOSENSE
))
600 flags
|= ATA_F_AUTOSENSE
;
603 * The command has to fit in the packet command buffer.
605 if (scsi
->scsi_CmdLength
< 6 || scsi
->scsi_CmdLength
> 16) {
606 io
->io_Error
= IOERR_NOCMD
;
611 * Initialize the XA and FIS. It is unclear how much of
612 * this has to mimic the equivalent ATA command.
614 * XXX not passing NULL at for direct attach!
616 xa
= ahci_ata_get_xfer(ap
, at
);
618 io
->io_Error
= IOERR_UNITBUSY
;
623 fis
->flags
= ATA_H2D_FLAGS_CMD
| at
->at_target
;
624 fis
->command
= ATA_C_PACKET
;
625 fis
->device
= ATA_H2D_DEVICE_LBA
;
626 fis
->sector_count
= xa
->tag
<< 3;
627 if (flags
& (ATA_F_READ
| ATA_F_WRITE
)) {
628 if (flags
& ATA_F_WRITE
) {
629 fis
->features
= ATA_H2D_FEATURES_DMA
|
630 ATA_H2D_FEATURES_DIR_WRITE
;
632 fis
->features
= ATA_H2D_FEATURES_DMA
|
633 ATA_H2D_FEATURES_DIR_READ
;
639 fis
->control
= ATA_FIS_CONTROL_4BIT
;
642 xa
->data
= scsi
->scsi_Data
;
643 xa
->datalen
= scsi
->scsi_Length
;
644 xa
->timeout
= 1000; /* milliseconds */
647 * Copy the cdb to the packetcmd buffer in the FIS using a
648 * convenient pointer in the xa.
650 * Zero-out any trailing bytes in case the ATAPI device cares.
652 cdbs
= (void *)scsi
->scsi_Command
;
653 CopyMem(cdbs
, xa
->packetcmd
, scsi
->scsi_CmdLength
);
654 if (scsi
->scsi_CmdLength
< 16)
655 memset(xa
->packetcmd
+ scsi
->scsi_CmdLength
, 0, 16 - scsi
->scsi_CmdLength
);
658 kprintf("opcode %d cdb_len %d dxfer_len %d\n",
659 cdbs
->generic
.opcode
,
660 scsi
->scsi_CmdLength
, scsi
->scsi_Length
);
664 * Some ATAPI commands do not actually follow the SCSI standard.
666 cdbd
= (void *)xa
->packetcmd
;
668 switch(cdbd
->generic
.opcode
) {
669 case SCSI_REQUEST_SENSE
:
671 * Force SENSE requests to the ATAPI sense length.
673 * It is unclear if this is needed or not.
675 if (cdbd
->sense
.length
== SSD_FULL_SIZE
) {
677 kprintf("%s: Shortening sense request\n",
680 cdbd
->sense
.length
= offsetof(struct scsi_sense_data
,
686 * Some ATAPI devices can't handle long inquiry lengths,
687 * don't ask me why. Truncate the inquiry length.
689 if (cdbd
->inquiry
.page_code
== 0 &&
690 cdbd
->inquiry
.length
> SHORT_INQUIRY_LENGTH
) {
691 cdbd
->inquiry
.length
= SHORT_INQUIRY_LENGTH
;
695 case SCSI_DA_WRITE_6
:
696 offset
= (cdbd
->rw_6
.addr
[0] << 16) |
697 (cdbd
->rw_6
.addr
[1] << 8) |
698 (cdbd
->rw_6
.addr
[2]);
699 len
= cdbd
->rw_6
.length
? cdbd
->rw_6
.length
: 0x100;
701 * Convert *_6 to *_10 commands. Most ATAPI devices
702 * cannot handle the SCSI READ_6 and WRITE_6 commands.
704 cdbd
->rw_10
.opcode
|= 0x20;
705 cdbd
->rw_10
.control
= cdbs
->rw_6
.control
;
706 cdbd
->rw_10
.byte2
= 0;
707 cdbd
->rw_10
.reserved
= 0;
709 cdbd
->rw_10
.addr
[0] = (offset
>> 24) & 0xff;
710 cdbd
->rw_10
.addr
[1] = (offset
>> 16) & 0xff;
711 cdbd
->rw_10
.addr
[2] = (offset
>> 8) & 0xff;
712 cdbd
->rw_10
.addr
[3] = (offset
>> 0) & 0xff;
714 cdbd
->rw_10
.length
[0] = (len
>> 8) & 0xff;
715 cdbd
->rw_10
.length
[1] = (len
>> 0) & 0xff;
724 io
->io_Flags
&= ~IOF_QUICK
;
725 xa
->complete
= ahci_io_complete
;
726 xa
->atascsi_private
= io
;
727 ahci_os_lock_port(ap
);
729 ahci_os_unlock_port(ap
);