2 * Copyright 2008, Marcus Overhagen. All rights reserved.
3 * Distributed under the terms of the MIT License.
9 #include "sata_request.h"
10 #include "scsi_cmds.h"
13 #define FIS_TYPE_REGISTER_HOST_TO_DEVICE 0x27
16 sata_request::sata_request()
20 fCompletionSem(create_sem(0, "sata completion")),
28 sata_request::sata_request(scsi_ccb
* ccb
)
40 sata_request::~sata_request()
42 if (fCompletionSem
>= 0)
43 delete_sem(fCompletionSem
);
48 sata_request::SetData(void* data
, size_t dataSize
)
57 sata_request::SetATACommand(uint8 command
)
59 memset(fFis
, 0, sizeof(fFis
));
60 fFis
[0] = FIS_TYPE_REGISTER_HOST_TO_DEVICE
;
68 sata_request::SetATA28Command(uint8 command
, uint32 lba
, uint8 sectorCount
)
70 SetATACommand(command
);
72 fFis
[5] = (lba
>> 8) & 0xff;
73 fFis
[6] = (lba
>> 16) & 0xff;
74 fFis
[7] = 0x40 | ((lba
>> 24) & 0x0f);
76 fFis
[12] = sectorCount
& 0xff;
81 sata_request::SetATA48Command(uint8 command
, uint64 lba
, uint16 sectorCount
)
83 SetATACommand(command
);
85 fFis
[5] = (lba
>> 8) & 0xff;
86 fFis
[6] = (lba
>> 16) & 0xff;
89 fFis
[8] = (lba
>> 24) & 0xff;
90 fFis
[9] = (lba
>> 32) & 0xff;
91 fFis
[10] = (lba
>> 40) & 0xff;
92 fFis
[12] = sectorCount
& 0xff;
93 fFis
[13] = (sectorCount
>> 8) & 0xff;
98 sata_request::SetFeature(uint16 feature
)
100 fFis
[3] = (uint8
)(feature
& 0xff);
101 fFis
[11] = (uint8
)(feature
>> 8);
106 sata_request::SetATAPICommand(size_t transferLength
)
111 if (transferLength
== 0)
113 else if (transferLength
> 0xfffe)
114 transferLength
= 0xfffe;
115 fFis
[5] = transferLength
& 0xff;
116 fFis
[6] = (transferLength
>> 8) & 0xff;
122 sata_request::Finish(int tfd
, size_t bytesTransfered
)
124 if ((tfd
& (ATA_STATUS_ERROR
| ATA_STATUS_DEVICE_FAULT
)) != 0) {
125 uint8 status
= tfd
& 0xff;
126 uint8 error
= (tfd
>> 8) & 0xff;
128 if (!IsTestUnitReady()) {
129 dprintf("ahci: sata_request::finish ATA command 0x%02x failed:"
130 " status 0x%02x, error 0x%02x\n", fFis
[2], status
, error
);
135 fCcb
->data_resid
= fCcb
->data_length
- bytesTransfered
;
136 fCcb
->device_status
= SCSI_STATUS_GOOD
;
137 fCcb
->subsys_status
= SCSI_REQ_CMP
;
138 if (tfd
& (ATA_STATUS_ERROR
| ATA_STATUS_DEVICE_FAULT
)) {
139 fCcb
->subsys_status
= SCSI_REQ_CMP_ERR
;
141 if (!IsTestUnitReady()) {
142 dprintf("ahci: sata_request::finish ATAPI packet %02x %02x "
143 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x "
144 "%02x %02x %02x %02x (len %d)\n",
145 fCcb
->cdb
[0], fCcb
->cdb
[1], fCcb
->cdb
[2], fCcb
->cdb
[3],
146 fCcb
->cdb
[4], fCcb
->cdb
[5], fCcb
->cdb
[6], fCcb
->cdb
[7],
147 fCcb
->cdb
[8], fCcb
->cdb
[9], fCcb
->cdb
[10],
148 fCcb
->cdb
[11], fCcb
->cdb
[12], fCcb
->cdb
[13],
149 fCcb
->cdb
[14], fCcb
->cdb
[15], fCcb
->cdb_length
);
152 fCcb
->device_status
= SCSI_STATUS_CHECK_CONDITION
;
154 // TODO ATA error handling goes here
156 // TODO check ABORT bit if this is useful
157 if ((tfd >> 8) & 0x04) { // ABRT
158 fCcb->subsys_status = SCSI_REQ_ABORTED;
160 fCcb->device_status = SCSI_STATUS_CHECK_CONDITION;
161 fCcb->subsys_status |= SCSI_AUTOSNS_VALID;
162 fCcb->sense_resid = 0; //FIXME
163 scsi_sense *sense = (scsi_sense *)fCcb->sense;
164 sense->error_code = SCSIS_CURR_ERROR;
165 sense->sense_key = error >> 4;
172 gSCSI
->finished(fCcb
, 1);
175 fCompletionStatus
= tfd
;
176 release_sem(fCompletionSem
);
182 sata_request::Abort()
184 dprintf("ahci: sata_request::abort called for command 0x%02x\n", fFis
[2]);
186 fCcb
->subsys_status
= SCSI_REQ_ABORTED
;
187 gSCSI
->finished(fCcb
, 1);
190 fCompletionStatus
= ATA_STATUS_ERROR
;
191 release_sem(fCompletionSem
);
197 sata_request::WaitForCompletion()
199 ASSERT(fCcb
== NULL
);
200 acquire_sem(fCompletionSem
);
205 sata_request::CompletionStatus()
207 ASSERT(fCcb
== NULL
);
208 return fCompletionStatus
;