2 ** Copyright 2007, Marcus Overhagen. All rights reserved.
3 ** Copyright 2002/03, Thomas Kurschel. All rights reserved.
4 ** Distributed under the terms of the Haiku License.
8 Part of Open IDE bus manager
12 As the IDE bus manager is an SCSI to IDE translater, it
13 has to know a bit more about connected devices then a standard
14 SIM. This file contains device detection and classification.
17 #include "ide_internal.h"
23 #include <ByteOrder.h>
25 #define TRACE(x...) dprintf("IDE: " x)
27 /** cleanup links devices on one bus when <device> is deleted */
30 cleanup_device_links(ide_device_info
*device
)
32 ide_bus_info
*bus
= device
->bus
;
34 TRACE("cleanup_device_links: device %p\n", device
);
36 bus
->devices
[device
->is_device1
] = NULL
;
38 if (device
->other_device
) {
39 if (device
->other_device
!= device
) {
40 device
->other_device
->other_device
= device
->other_device
;
41 bus
->first_device
= device
->other_device
;
43 bus
->first_device
= NULL
;
46 device
->other_device
= NULL
;
50 /** destroy device info */
53 destroy_device(ide_device_info
*device
)
55 TRACE("destroy_device: device %p\n", device
);
58 device
->exec_io
= NULL
;
59 cancel_timer(&device
->reconnect_timer
.te
);
61 scsi
->free_dpc(device
->reconnect_timeout_dpc
);
63 cleanup_device_links(device
);
65 destroy_qreq_array(device
);
67 uninit_synced_pc(&device
->reconnect_timeout_synced_pc
);
73 /** setup links between the devices on one bus */
76 setup_device_links(ide_bus_info
*bus
, ide_device_info
*device
)
78 TRACE("setup_device_links: bus %p, device %p\n", bus
, device
);
81 bus
->devices
[device
->is_device1
] = device
;
83 device
->other_device
= device
;
85 if (device
->is_device1
) {
86 if (bus
->devices
[0]) {
87 device
->other_device
= bus
->devices
[0];
88 bus
->devices
[0]->other_device
= device
;
91 if (bus
->devices
[1]) {
92 device
->other_device
= bus
->devices
[1];
93 bus
->devices
[1]->other_device
= device
;
97 if (bus
->first_device
== NULL
)
98 bus
->first_device
= device
;
102 /** create device info */
104 static ide_device_info
*
105 create_device(ide_bus_info
*bus
, bool is_device1
)
107 ide_device_info
*device
;
109 TRACE("create_device: bus %p, device-number %d\n", bus
, is_device1
);
111 device
= (ide_device_info
*)malloc(sizeof(*device
));
115 memset(device
, 0, sizeof(*device
));
117 device
->is_device1
= is_device1
;
118 device
->target_id
= is_device1
;
120 setup_device_links(bus
, device
);
122 device
->DMA_failures
= 0;
123 device
->CQ_failures
= 0;
124 device
->num_failed_send
= 0;
126 device
->combined_sense
= 0;
128 device
->num_running_reqs
= 0;
130 device
->reconnect_timer
.device
= device
;
132 init_synced_pc(&device
->reconnect_timeout_synced_pc
,
133 reconnect_timeout_worker
);
135 if (scsi
->alloc_dpc(&device
->reconnect_timeout_dpc
) != B_OK
)
138 device
->total_sectors
= 0;
142 destroy_device(device
);
146 #if B_HOST_IS_LENDIAN
148 #define B_BENDIAN_TO_HOST_MULTI(v, n) do { \
149 size_t __swap16_multi_n = (n); \
150 uint16 *__swap16_multi_v = (v); \
152 while( __swap16_multi_n ) { \
153 *__swap16_multi_v = B_SWAP_INT16(*__swap16_multi_v); \
154 __swap16_multi_v++; \
155 __swap16_multi_n--; \
161 #define B_BENDIAN_TO_HOST_MULTI(v, n)
166 /** prepare infoblock for further use, i.e. fix endianess */
169 prep_infoblock(ide_device_info
*device
)
171 ide_device_infoblock
*infoblock
= &device
->infoblock
;
173 B_BENDIAN_TO_HOST_MULTI((uint16
*)infoblock
->serial_number
,
174 sizeof(infoblock
->serial_number
) / 2);
176 B_BENDIAN_TO_HOST_MULTI( (uint16
*)infoblock
->firmware_version
,
177 sizeof(infoblock
->firmware_version
) / 2);
179 B_BENDIAN_TO_HOST_MULTI( (uint16
*)infoblock
->model_number
,
180 sizeof(infoblock
->model_number
) / 2);
182 infoblock
->LBA_total_sectors
= B_LENDIAN_TO_HOST_INT32(infoblock
->LBA_total_sectors
);
183 infoblock
->LBA48_total_sectors
= B_LENDIAN_TO_HOST_INT64(infoblock
->LBA48_total_sectors
);
187 /** read info block of ATA or ATAPI device */
190 scan_device_int(ide_device_info
*device
, bool atapi
)
192 ide_bus_info
*bus
= device
->bus
;
195 TRACE("scan_device_int: device %p, atapi %d\n", device
, atapi
);
197 device
->tf_param_mask
= 0;
198 device
->tf
.write
.command
= atapi
? IDE_CMD_IDENTIFY_PACKET_DEVICE
199 : IDE_CMD_IDENTIFY_DEVICE
;
201 // initialize device selection flags,
202 // this is the only place where this bit gets initialized in the task file
203 if (bus
->controller
->read_command_block_regs(bus
->channel_cookie
, &device
->tf
,
204 ide_mask_device_head
) != B_OK
) {
205 TRACE("scan_device_int: read_command_block_regs failed\n");
209 device
->tf
.lba
.device
= device
->is_device1
;
211 if (!send_command(device
, NULL
, atapi
? false : true, 20, ide_state_sync_waiting
)) {
212 TRACE("scan_device_int: send_command failed\n");
216 // do a short wait first - if there's no device at all we could wait forever
217 // ToDo: have a look at this; if it times out (when the time is too short),
218 // the kernel seems to crash a little later)!
219 TRACE("scan_device_int: waiting 100ms...\n");
220 if (acquire_sem_etc(bus
->sync_wait_sem
, 1, B_RELATIVE_TIMEOUT
, 100000) == B_TIMED_OUT
) {
223 TRACE("scan_device_int: no fast response to inquiry\n");
225 // check the busy flag - if it's still set, there's probably no device
228 status
= bus
->controller
->get_altstatus(bus
->channel_cookie
);
229 cont
= (status
& ide_status_bsy
) == ide_status_bsy
;
233 TRACE("scan_device_int: status %#04x\n", status
);
236 TRACE("scan_device_int: busy bit not set after 100ms - probably noone there\n");
237 // no reaction -> abort waiting
238 cancel_irq_timeout(bus
);
240 // timeout or irq may have been fired, reset semaphore just is case
241 acquire_sem_etc(bus
->sync_wait_sem
, 1, B_RELATIVE_TIMEOUT
, 0);
243 TRACE("scan_device_int: aborting because busy bit not set\n");
247 TRACE("scan_device_int: busy bit set, give device more time\n");
249 // there is something, so wait for it
250 acquire_sem(bus
->sync_wait_sem
);
252 TRACE("scan_device_int: got a fast response\n");
254 // cancel the timeout manually; usually this is done by wait_for_sync(), but
255 // we've used the wait semaphore directly
256 cancel_irq_timeout(bus
);
258 if (bus
->sync_wait_timeout
) {
259 TRACE("scan_device_int: aborting on sync_wait_timeout\n");
263 ide_wait(device
, ide_status_drq
, ide_status_bsy
, true, 1000);
265 status
= bus
->controller
->get_altstatus(bus
->channel_cookie
);
267 if ((status
& ide_status_err
) != 0) {
268 // if there's no device, all bits including the error bit are set
269 TRACE("scan_device_int: error bit set - no device or wrong type (status: %#04x)\n", status
);
274 bus
->controller
->read_pio(bus
->channel_cookie
, (uint16
*)&device
->infoblock
,
275 sizeof(device
->infoblock
) / sizeof(uint16
), false);
277 if (!wait_for_drqdown(device
)) {
278 TRACE("scan_device_int: wait_for_drqdown failed\n");
282 TRACE("scan_device_int: device found\n");
284 prep_infoblock(device
);
289 /** scan one device */
292 scan_device_worker(ide_bus_info
*bus
, void *arg
)
294 int is_device1
= (int)arg
;
295 ide_device_info
*device
;
297 TRACE("scan_device_worker: bus %p, device-number %d\n", bus
, is_device1
);
299 // forget everything we know about the device;
300 // don't care about peripheral drivers using this device
301 // as the device info is only used by us and not published
302 // directly or indirectly to the SCSI bus manager
303 if (bus
->devices
[is_device1
])
304 destroy_device(bus
->devices
[is_device1
]);
306 device
= create_device(bus
, is_device1
);
308 // reset status so we can see what goes wrong during detection
309 device
->subsys_status
= SCSI_REQ_CMP
;
311 if (scan_device_int(device
, false)) {
312 if (!prep_ata(device
))
314 } else if (device
->subsys_status
!= SCSI_TID_INVALID
315 && scan_device_int(device
, true)) {
316 // only try ATAPI if there is at least some device
317 // (see send_command - this error code must be unique!)
318 if (!prep_atapi(device
))
323 bus
->state
= ide_state_idle
;
324 release_sem(bus
->scan_device_sem
);
328 destroy_device(device
);
330 bus
->state
= ide_state_idle
;
331 release_sem(bus
->scan_device_sem
);