1/* 2 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch. 3 * Copyright 2008, Marcus Overhagen. 4 * Copyright 2004-2008, Axel D��rfler, axeld@pinc-software.de. 5 * Copyright 2002-2003, Thomas Kurschel. 6 * 7 * Distributed under the terms of the MIT License. 8 */ 9 10#include "ATAPrivate.h" 11 12 13scsi_for_sim_interface *gSCSIModule = NULL; 14device_manager_info *gDeviceManager = NULL; 15 16 17static status_t 18ata_sim_init_bus(device_node *node, void **cookie) 19{ 20 ATAChannel *channel = new(std::nothrow) ATAChannel(node); 21 if (channel == NULL) 22 return B_NO_MEMORY; 23 24 status_t result = channel->InitCheck(); 25 if (result != B_OK) { 26 TRACE_ERROR("failed to set up ata channel object\n"); 27 delete channel; 28 return result; 29 } 30 31 *cookie = channel; 32 return B_OK; 33} 34 35 36static void 37ata_sim_uninit_bus(void *cookie) 38{ 39 ATAChannel *channel = (ATAChannel *)cookie; 40 delete channel; 41} 42 43 44static void 45ata_sim_bus_removed(void *cookie) 46{ 47 ATAChannel *channel = (ATAChannel *)cookie; 48 if (channel->Bus() != NULL) { 49 gSCSIModule->block_bus(channel->Bus()); 50 channel->SetBus(NULL); 51 } 52} 53 54 55static void 56ata_sim_set_scsi_bus(scsi_sim_cookie cookie, scsi_bus bus) 57{ 58 ATAChannel *channel = (ATAChannel *)cookie; 59 channel->SetBus(bus); 60 channel->ScanBus(); 61} 62 63 64static void 65ata_sim_scsi_io(scsi_sim_cookie cookie, scsi_ccb *ccb) 66{ 67 ATAChannel *channel = (ATAChannel *)cookie; 68 if (channel->Bus() == NULL) { 69 ccb->subsys_status = SCSI_NO_HBA; 70 gSCSIModule->finished(ccb, 1); 71 return; 72 } 73 74 if (channel->ExecuteIO(ccb) == B_BUSY) 75 gSCSIModule->requeue(ccb, true); 76} 77 78 79static uchar 80ata_sim_abort(scsi_sim_cookie cookie, scsi_ccb *ccb) 81{ 82 ATAChannel *channel = (ATAChannel *)cookie; 83 if (channel->Bus() == NULL) 84 return SCSI_NO_HBA; 85 86 // aborting individual commands is not possible 87 return SCSI_REQ_CMP; 88} 89 90 91static uchar 92ata_sim_reset_device(scsi_sim_cookie cookie, uchar targetId, uchar targetLun) 93{ 94 ATAChannel *channel = (ATAChannel *)cookie; 95 if (channel->Bus() == NULL) 96 return SCSI_NO_HBA; 97 98 // TODO: implement 99 return SCSI_REQ_INVALID; 100} 101 102 103static uchar 104ata_sim_term_io(scsi_sim_cookie cookie, scsi_ccb *ccb) 105{ 106 ATAChannel *channel = (ATAChannel *)cookie; 107 if (channel->Bus() == NULL) 108 return SCSI_NO_HBA; 109 110 // we don't terminate commands, ignore 111 return SCSI_REQ_CMP; 112} 113 114 115static uchar 116ata_sim_path_inquiry(scsi_sim_cookie cookie, scsi_path_inquiry *info) 117{ 118 ATAChannel *channel = (ATAChannel *)cookie; 119 if (channel->Bus() == NULL) 120 return SCSI_NO_HBA; 121 122 channel->PathInquiry(info); 123 return SCSI_REQ_CMP; 124} 125 126 127static uchar 128ata_sim_rescan_bus(scsi_sim_cookie cookie) 129{ 130 // TODO: implement 131 return SCSI_REQ_CMP; 132} 133 134 135static uchar 136ata_sim_reset_bus(scsi_sim_cookie cookie) 137{ 138 ATAChannel *channel = (ATAChannel *)cookie; 139 if (channel->Bus() == NULL) 140 return SCSI_NO_HBA; 141 142 //channel->Reset(); 143 panic("asking for trouble"); 144 return SCSI_REQ_CMP; 145} 146 147 148static void 149ata_sim_get_restrictions(scsi_sim_cookie cookie, uchar targetID, 150 bool *isATAPI, bool *noAutoSense, uint32 *maxBlocks) 151{ 152 ATAChannel *channel = (ATAChannel *)cookie; 153 channel->GetRestrictions(targetID, isATAPI, noAutoSense, maxBlocks); 154} 155 156 157static status_t 158ata_sim_control(scsi_sim_cookie cookie, uchar targetID, uint32 op, void *buffer, 159 size_t length) 160{ 161 ATAChannel *channel = (ATAChannel *)cookie; 162 return channel->Control(targetID, op, buffer, length); 163} 164 165 166status_t 167ata_channel_added(device_node *parent) 168{ 169 const char *controllerName; 170 if (gDeviceManager->get_attr_string(parent, 171 ATA_CONTROLLER_CONTROLLER_NAME_ITEM, &controllerName, true) != B_OK) { 172 TRACE_ERROR("controller name missing\n"); 173 return B_ERROR; 174 } 175 176 int32 channelID = gDeviceManager->create_id(ATA_CHANNEL_ID_GENERATOR); 177 if (channelID < 0) { 178 TRACE_ERROR("out of channel ids\n"); 179 return B_ERROR; 180 } 181 182 device_attr attributes[] = { 183 { 184 B_DEVICE_FIXED_CHILD, B_STRING_TYPE, 185 { .string = SCSI_FOR_SIM_MODULE_NAME } 186 }, 187 188 { 189 SCSI_DESCRIPTION_CONTROLLER_NAME, B_STRING_TYPE, 190 { .string = controllerName } 191 }, 192 193 // maximum number of blocks per transmission: 194 // - ATAPI uses packets, i.e. normal SCSI limits apply 195 // but I'm not sure about controller restrictions 196 // - ATA allows up to 256 blocks for LBA28 and 65535 for LBA48 197 // to fix specific drive bugs use ATAChannel::GetRestrictions() 198 { B_DMA_MAX_TRANSFER_BLOCKS, B_UINT32_TYPE, { .ui32 = 0xffff } }, 199 { ATA_CHANNEL_ID_ITEM, B_UINT32_TYPE, { .ui32 = (uint32)channelID } }, 200 { NULL } 201 }; 202 203 return gDeviceManager->register_node(parent, ATA_SIM_MODULE_NAME, 204 attributes, NULL, NULL); 205} 206 207 208status_t 209ata_interrupt_handler(void *cookie, uint8 status) 210{ 211 ATAChannel *channel = (ATAChannel *)cookie; 212 return channel->Interrupt(status); 213} 214 215 216static status_t 217std_ops(int32 op, ...) 218{ 219 switch (op) { 220 case B_MODULE_INIT: 221 case B_MODULE_UNINIT: 222 return B_OK; 223 224 default: 225 break; 226 } 227 228 return B_ERROR; 229} 230 231 232scsi_sim_interface ata_sim_module = { 233 { 234 { 235 ATA_SIM_MODULE_NAME, 236 0, 237 std_ops 238 }, 239 240 NULL, // supported devices 241 NULL, // register node 242 ata_sim_init_bus, 243 ata_sim_uninit_bus, 244 NULL, // register child devices 245 NULL, // rescan 246 ata_sim_bus_removed, 247 NULL, // suspend 248 NULL, // resume 249 }, 250 251 ata_sim_set_scsi_bus, 252 ata_sim_scsi_io, 253 ata_sim_abort, 254 ata_sim_reset_device, 255 ata_sim_term_io, 256 ata_sim_path_inquiry, 257 ata_sim_rescan_bus, 258 ata_sim_reset_bus, 259 ata_sim_get_restrictions, 260 ata_sim_control 261}; 262 263ata_for_controller_interface ata_for_controller_module = { 264 { 265 { 266 ATA_FOR_CONTROLLER_MODULE_NAME, 267 0, 268 &std_ops 269 }, 270 271 NULL, // supported devices 272 ata_channel_added, 273 NULL, 274 NULL, 275 NULL 276 }, 277 278 ata_interrupt_handler 279}; 280 281 282module_dependency module_dependencies[] = { 283 { SCSI_FOR_SIM_MODULE_NAME, (module_info **)&gSCSIModule }, 284 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, 285 {} 286}; 287 288module_info *modules[] = { 289 (module_info *)&ata_for_controller_module, 290 (module_info *)&ata_sim_module, 291 NULL 292}; 293