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
));
256 ReplyMsg(&io
->io_Message
);
261 * Simulate page inquiries for disk attachments.
263 static BYTE
ahci_scsi_page_inquiry(struct ahci_port
*ap
, struct ata_port
*at
, struct SCSICmd
*scsi
)
266 struct scsi_vpd_supported_page_list list
;
267 struct scsi_vpd_unit_serial_number serno
;
275 cdb
= (APTR
)scsi
->scsi_Command
;
277 switch(cdb
->inquiry
.page_code
) {
278 case SVPD_SUPPORTED_PAGE_LIST
:
280 page
.list
.device
= T_DIRECT
;
281 page
.list
.page_code
= SVPD_SUPPORTED_PAGE_LIST
;
282 page
.list
.list
[i
++] = SVPD_SUPPORTED_PAGE_LIST
;
283 page
.list
.list
[i
++] = SVPD_UNIT_SERIAL_NUMBER
;
284 page
.list
.length
= i
;
285 len
= offsetof(struct scsi_vpd_supported_page_list
, list
[3]);
287 case SVPD_UNIT_SERIAL_NUMBER
:
289 j
= sizeof(at
->at_identify
.serial
);
290 for (i
= 0; i
< j
&& at
->at_identify
.serial
[i
] == ' '; ++i
)
292 while (j
> i
&& at
->at_identify
.serial
[j
-1] == ' ')
294 page
.serno
.device
= T_DIRECT
;
295 page
.serno
.page_code
= SVPD_UNIT_SERIAL_NUMBER
;
296 page
.serno
.length
= j
- i
;
297 CopyMem(at
->at_identify
.serial
+ i
,
298 page
.serno
.serial_num
, j
- i
);
299 len
= offsetof(struct scsi_vpd_unit_serial_number
,
307 if (len
> scsi
->scsi_Length
)
308 return IOERR_BADLENGTH
;
310 memset(scsi
->scsi_Data
+ len
, 0, scsi
->scsi_Length
- len
);
311 CopyMem(&page
, scsi
->scsi_Data
, len
);
312 scsi
->scsi_Actual
= len
;
319 * Convert the SCSI command to an ata_xfer command in xa
320 * for ATA_PORT_T_DISK operations. Set the completion function
321 * to convert the response back, then dispatch to the OpenBSD AHCI
324 * AHCI DISK commands only support a limited command set, and we
325 * fake additional commands to make it play nice.
327 * Return TRUE if no need to wait for a reply
329 BOOL
ahci_scsi_disk_io(struct IORequest
*io
, struct SCSICmd
*scsi
)
331 struct cam_sim
*unit
= (struct cam_sim
*)io
->io_Unit
;
332 struct ahci_port
*ap
= unit
->sim_Port
;
333 struct ata_port
*at
= ap
->ap_ata
[0];
335 struct ata_fis_h2d
*fis
;
337 struct scsi_inquiry_data inquiry_data
;
338 struct scsi_read_capacity_data read_capacity_data
;
339 } *rdata
= (APTR
)scsi
->scsi_Command
;
340 ULONG rdata_len
= scsi
->scsi_CmdLength
;
345 scsi_cdb_t cdb
= (APTR
)scsi
->scsi_Command
;
347 xa
= ahci_ata_get_xfer(ap
, at
);
349 switch(cdb
->generic
.opcode
) {
350 case SCSI_REQUEST_SENSE
:
352 * Auto-sense everything, so explicit sense requests
355 io
->io_Error
= HFERR_BadStatus
;
361 * Inquiry supported features
363 * [opcode, byte2, page_code, length, control]
365 if (cdb
->inquiry
.byte2
& SI_EVPD
) {
366 io
->io_Error
= ahci_scsi_page_inquiry(ap
, at
, scsi
);
368 memset(rdata
, 0, rdata_len
);
369 if (rdata_len
< SHORT_INQUIRY_LENGTH
) {
370 io
->io_Error
= IOERR_BADLENGTH
;
373 if (rdata_len
> sizeof(rdata
->inquiry_data
))
374 rdata_len
= sizeof(rdata
->inquiry_data
);
375 rdata
->inquiry_data
.device
= T_DIRECT
;
376 /* Mark as removable if ATA has the 'removable' tag */
377 rdata
->inquiry_data
.dev_qual2
= (at
->at_identify
.config
? 0x80 : 0);
378 rdata
->inquiry_data
.version
= SCSI_REV_SPC2
;
379 rdata
->inquiry_data
.response_format
= 2;
380 rdata
->inquiry_data
.additional_length
= 32;
383 * Use the vendor specific area to set the TRIM status
385 if (at
->at_identify
.support_dsm
) {
386 rdata
->inquiry_data
.vendor_specific
[0] =
387 at
->at_identify
.support_dsm
&ATA_SUPPORT_DSM_TRIM
;
388 rdata
->inquiry_data
.vendor_specific
[1] =
389 at
->at_identify
.max_dsm_blocks
;
391 CopyMem("SATA ", rdata
->inquiry_data
.vendor
, 8);
392 CopyMem(at
->at_identify
.model
,
393 rdata
->inquiry_data
.product
,
394 sizeof(rdata
->inquiry_data
.product
));
395 CopyMem(at
->at_identify
.firmware
,
396 rdata
->inquiry_data
.revision
,
397 sizeof(rdata
->inquiry_data
.revision
));
400 case SCSI_DA_READ_CAPACITY
:
402 if (rdata_len
< sizeof(rdata
->read_capacity_data
)) {
403 io
->io_Error
= IOERR_BADLENGTH
;
407 capacity
= at
->at_capacity
;
409 memset(rdata
, 0, rdata_len
);
410 rdata_len
= sizeof(rdata
->read_capacity_data
);
411 if (capacity
> 0xFFFFFFFFU
)
412 capacity
= 0xFFFFFFFFU
;
413 memset(&rdata
->read_capacity_data
, 0, rdata_len
);
414 scsi_ulto4b((u_int32_t
)capacity
- 1,
415 rdata
->read_capacity_data
.addr
);
416 scsi_ulto4b(512, rdata
->read_capacity_data
.length
);
418 case SCSI_DA_SYNCHRONIZE_CACHE
:
420 * Synchronize cache. Specification says this can take
421 * greater then 30 seconds so give it at least 45.
424 fis
->flags
= ATA_H2D_FLAGS_CMD
;
425 fis
->command
= ATA_C_FLUSH_CACHE
;
427 if (xa
->timeout
< 45000)
431 xa
->complete
= ahci_io_complete
;
433 case SCSI_TEST_UNIT_READY
:
435 * Just silently return success
441 switch(cdb
->generic
.opcode
) {
443 lba
= scsi_3btoul(cdb
->rw_6
.addr
) & 0x1FFFFF;
444 count
= cdb
->rw_6
.length
? cdb
->rw_6
.length
: 0x100;
445 xa
->flags
= ATA_F_READ
;
447 case SCSI_DA_READ_10
:
448 lba
= scsi_4btoul(cdb
->rw_10
.addr
);
449 count
= scsi_2btoul(cdb
->rw_10
.length
);
450 xa
->flags
= ATA_F_READ
;
452 case SCSI_DA_READ_12
:
453 lba
= scsi_4btoul(cdb
->rw_12
.addr
);
454 count
= scsi_4btoul(cdb
->rw_12
.length
);
455 xa
->flags
= ATA_F_READ
;
457 case SCSI_DA_READ_16
:
458 lba
= scsi_8btou64(cdb
->rw_16
.addr
);
459 count
= scsi_4btoul(cdb
->rw_16
.length
);
460 xa
->flags
= ATA_F_READ
;
462 case SCSI_DA_WRITE_6
:
463 lba
= scsi_3btoul(cdb
->rw_6
.addr
) & 0x1FFFFF;
464 count
= cdb
->rw_6
.length
? cdb
->rw_6
.length
: 0x100;
465 xa
->flags
= ATA_F_WRITE
;
467 case SCSI_DA_WRITE_10
:
468 lba
= scsi_4btoul(cdb
->rw_10
.addr
);
469 count
= scsi_2btoul(cdb
->rw_10
.length
);
470 xa
->flags
= ATA_F_WRITE
;
472 case SCSI_DA_WRITE_12
:
473 lba
= scsi_4btoul(cdb
->rw_12
.addr
);
474 count
= scsi_4btoul(cdb
->rw_12
.length
);
475 xa
->flags
= ATA_F_WRITE
;
477 case SCSI_DA_WRITE_16
:
478 lba
= scsi_8btou64(cdb
->rw_16
.addr
);
479 count
= scsi_4btoul(cdb
->rw_16
.length
);
480 xa
->flags
= ATA_F_WRITE
;
483 io
->io_Error
= IOERR_NOCMD
;
491 fis
->flags
= ATA_H2D_FLAGS_CMD
;
492 fis
->lba_low
= (u_int8_t
)lba
;
493 fis
->lba_mid
= (u_int8_t
)(lba
>> 8);
494 fis
->lba_high
= (u_int8_t
)(lba
>> 16);
495 fis
->device
= ATA_H2D_DEVICE_LBA
;
498 * NCQ only for direct-attached disks, do not currently
499 * try to use NCQ with port multipliers.
501 if (at
->at_ncqdepth
> 1 &&
502 ap
->ap_type
== ATA_PORT_T_DISK
&&
503 (ap
->ap_sc
->sc_cap
& AHCI_REG_CAP_SNCQ
)) {
505 * Use NCQ - always uses 48 bit addressing
507 xa
->flags
|= ATA_F_NCQ
;
508 fis
->command
= (xa
->flags
& ATA_F_WRITE
) ?
509 ATA_C_WRITE_FPDMA
: ATA_C_READ_FPDMA
;
510 fis
->lba_low_exp
= (u_int8_t
)(lba
>> 24);
511 fis
->lba_mid_exp
= (u_int8_t
)(lba
>> 32);
512 fis
->lba_high_exp
= (u_int8_t
)(lba
>> 40);
513 fis
->sector_count
= xa
->tag
<< 3;
514 fis
->features
= (u_int8_t
)count
;
515 fis
->features_exp
= (u_int8_t
)(count
>> 8);
516 } else if (count
> 0x100 || lba
> 0x0FFFFFFFU
) {
520 fis
->command
= (xa
->flags
& ATA_F_WRITE
) ?
521 ATA_C_WRITEDMA_EXT
: ATA_C_READDMA_EXT
;
522 fis
->lba_low_exp
= (u_int8_t
)(lba
>> 24);
523 fis
->lba_mid_exp
= (u_int8_t
)(lba
>> 32);
524 fis
->lba_high_exp
= (u_int8_t
)(lba
>> 40);
525 fis
->sector_count
= (u_int8_t
)count
;
526 fis
->sector_count_exp
= (u_int8_t
)(count
>> 8);
531 * NOTE: 256 sectors is supported, stored as 0.
533 fis
->command
= (xa
->flags
& ATA_F_WRITE
) ?
534 ATA_C_WRITEDMA
: ATA_C_READDMA
;
535 fis
->device
|= (u_int8_t
)(lba
>> 24) & 0x0F;
536 fis
->sector_count
= (u_int8_t
)count
;
539 xa
->data
= scsi
->scsi_Data
;
540 xa
->datalen
= scsi
->scsi_Length
;
541 xa
->complete
= ahci_io_complete
;
542 xa
->timeout
= 1000; /* milliseconds */
544 if (xa
->timeout
> 10000) /* XXX - debug */
551 * If the request is still in progress the xa and FIS have
552 * been set up (except for the PM target), and must be dispatched.
553 * Otherwise the request was completed.
556 io
->io_Flags
&= ~IOF_QUICK
;
557 KKASSERT(xa
->complete
!= NULL
);
558 xa
->atascsi_private
= io
;
559 ahci_os_lock_port(ap
);
560 xa
->fis
->flags
|= at
->at_target
;
562 ahci_os_unlock_port(ap
);
564 IOStdReq(io
)->io_Actual
= sizeof(*scsi
);
565 ahci_ata_put_xfer(xa
);
572 * Convert the SCSI command in ccb to an ata_xfer command in xa
573 * for ATA_PORT_T_ATAPI operations. Set the completion function
574 * to convert the response back, then dispatch to the OpenBSD AHCI
577 BOOL
ahci_scsi_atapi_io(struct IORequest
*io
, struct SCSICmd
*scsi
)
579 struct cam_sim
*unit
= (struct cam_sim
*)io
->io_Unit
;
580 struct ahci_port
*ap
= unit
->sim_Port
;
581 struct ata_port
*at
= ap
->ap_ata
[0];
583 struct ata_fis_h2d
*fis
;
586 uint32_t offset
, len
;
589 if (scsi
->scsi_Flags
& SCSIF_READ
) {
590 flags
= ATA_F_PACKET
| ATA_F_READ
;
592 flags
= ATA_F_PACKET
| ATA_F_WRITE
;
596 * Special handling to get the rfis back into host memory while
597 * still allowing the chip to run commands in parallel to
598 * ATAPI devices behind a PM.
600 if (scsi
->scsi_Flags
& (SCSIF_AUTOSENSE
| SCSIF_OLDAUTOSENSE
))
601 flags
|= ATA_F_AUTOSENSE
;
604 * The command has to fit in the packet command buffer.
606 if (scsi
->scsi_CmdLength
< 6 || scsi
->scsi_CmdLength
> 16) {
607 io
->io_Error
= IOERR_NOCMD
;
612 * Initialize the XA and FIS. It is unclear how much of
613 * this has to mimic the equivalent ATA command.
615 * XXX not passing NULL at for direct attach!
617 xa
= ahci_ata_get_xfer(ap
, at
);
619 io
->io_Error
= IOERR_UNITBUSY
;
624 fis
->flags
= ATA_H2D_FLAGS_CMD
| at
->at_target
;
625 fis
->command
= ATA_C_PACKET
;
626 fis
->device
= ATA_H2D_DEVICE_LBA
;
627 fis
->sector_count
= xa
->tag
<< 3;
628 if (flags
& (ATA_F_READ
| ATA_F_WRITE
)) {
629 if (flags
& ATA_F_WRITE
) {
630 fis
->features
= ATA_H2D_FEATURES_DMA
|
631 ATA_H2D_FEATURES_DIR_WRITE
;
633 fis
->features
= ATA_H2D_FEATURES_DMA
|
634 ATA_H2D_FEATURES_DIR_READ
;
640 fis
->control
= ATA_FIS_CONTROL_4BIT
;
643 xa
->data
= scsi
->scsi_Data
;
644 xa
->datalen
= scsi
->scsi_Length
;
645 xa
->timeout
= 1000; /* milliseconds */
648 * Copy the cdb to the packetcmd buffer in the FIS using a
649 * convenient pointer in the xa.
651 * Zero-out any trailing bytes in case the ATAPI device cares.
653 cdbs
= (void *)scsi
->scsi_Command
;
654 CopyMem(cdbs
, xa
->packetcmd
, scsi
->scsi_CmdLength
);
655 if (scsi
->scsi_CmdLength
< 16)
656 memset(xa
->packetcmd
+ scsi
->scsi_CmdLength
, 0, 16 - scsi
->scsi_CmdLength
);
659 kprintf("opcode %d cdb_len %d dxfer_len %d\n",
660 cdbs
->generic
.opcode
,
661 scsi
->scsi_CmdLength
, scsi
->scsi_Length
);
665 * Some ATAPI commands do not actually follow the SCSI standard.
667 cdbd
= (void *)xa
->packetcmd
;
669 switch(cdbd
->generic
.opcode
) {
670 case SCSI_REQUEST_SENSE
:
672 * Force SENSE requests to the ATAPI sense length.
674 * It is unclear if this is needed or not.
676 if (cdbd
->sense
.length
== SSD_FULL_SIZE
) {
678 kprintf("%s: Shortening sense request\n",
681 cdbd
->sense
.length
= offsetof(struct scsi_sense_data
,
687 * Some ATAPI devices can't handle long inquiry lengths,
688 * don't ask me why. Truncate the inquiry length.
690 if (cdbd
->inquiry
.page_code
== 0 &&
691 cdbd
->inquiry
.length
> SHORT_INQUIRY_LENGTH
) {
692 cdbd
->inquiry
.length
= SHORT_INQUIRY_LENGTH
;
696 case SCSI_DA_WRITE_6
:
697 offset
= (cdbd
->rw_6
.addr
[0] << 16) |
698 (cdbd
->rw_6
.addr
[1] << 8) |
699 (cdbd
->rw_6
.addr
[2]);
700 len
= cdbd
->rw_6
.length
? cdbd
->rw_6
.length
: 0x100;
702 * Convert *_6 to *_10 commands. Most ATAPI devices
703 * cannot handle the SCSI READ_6 and WRITE_6 commands.
705 cdbd
->rw_10
.opcode
|= 0x20;
706 cdbd
->rw_10
.control
= cdbs
->rw_6
.control
;
707 cdbd
->rw_10
.byte2
= 0;
708 cdbd
->rw_10
.reserved
= 0;
710 cdbd
->rw_10
.addr
[0] = (offset
>> 24) & 0xff;
711 cdbd
->rw_10
.addr
[1] = (offset
>> 16) & 0xff;
712 cdbd
->rw_10
.addr
[2] = (offset
>> 8) & 0xff;
713 cdbd
->rw_10
.addr
[3] = (offset
>> 0) & 0xff;
715 cdbd
->rw_10
.length
[0] = (len
>> 8) & 0xff;
716 cdbd
->rw_10
.length
[1] = (len
>> 0) & 0xff;
725 io
->io_Flags
&= ~IOF_QUICK
;
726 xa
->complete
= ahci_io_complete
;
727 xa
->atascsi_private
= io
;
728 ahci_os_lock_port(ap
);
730 ahci_os_unlock_port(ap
);