1 /* 2 * Copyright 2007, Marcus Overhagen. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include "ahci_controller.h" 7 8 #include <KernelExport.h> 9 #include <string.h> 10 #include <new> 11 12 #define TRACE(a...) dprintf("\33[34mahci:\33[0m " a) 13 //#define FLOW(a...) dprintf("ahci: " a) 14 #define FLOW(a...) 15 16 17 pci_device_module_info *gPCI; 18 scsi_for_sim_interface *gSCSI; 19 20 21 // #pragma mark - SIM module interface 22 23 24 //! execute request 25 static void 26 ahci_scsi_io(scsi_sim_cookie cookie, scsi_ccb *request) 27 { 28 FLOW("ahci_scsi_io, cookie %p, path_id %u, target_id %u, target_lun %u\n", 29 cookie, request->path_id, request->target_id, request->target_lun); 30 static_cast<AHCIController *>(cookie)->ExecuteRequest(request); 31 } 32 33 34 //! abort request 35 static uchar 36 ahci_abort_io(scsi_sim_cookie cookie, scsi_ccb *request) 37 { 38 TRACE("ahci_abort_io, cookie %p\n", cookie); 39 return static_cast<AHCIController *>(cookie)->AbortRequest(request); 40 } 41 42 43 static uchar 44 ahci_reset_device(scsi_sim_cookie cookie, uchar targetID, uchar targetLUN) 45 { 46 TRACE("ahci_reset_device, cookie %p\n", cookie); 47 return static_cast<AHCIController *>(cookie)->ResetDevice(targetID, targetLUN); 48 } 49 50 51 //! terminate request 52 static uchar 53 ahci_terminate_io(scsi_sim_cookie cookie, scsi_ccb *request) 54 { 55 TRACE("ahci_terminate_io, cookie %p\n", cookie); 56 return static_cast<AHCIController *>(cookie)->TerminateRequest(request); 57 } 58 59 60 //! get information about bus 61 static uchar 62 ahci_path_inquiry(scsi_sim_cookie cookie, scsi_path_inquiry *info) 63 { 64 TRACE("ahci_path_inquiry, cookie %p\n", cookie); 65 66 memset(info, 0, sizeof(*info)); 67 info->version_num = 1; 68 // supports tagged requests and soft reset 69 info->hba_inquiry = 0; // SCSI_PI_TAG_ABLE | SCSI_PI_SOFT_RST; 70 // controller is 32, devices are 0 to 31 71 info->initiator_id = 32; 72 // adapter command queue size 73 info->hba_queue_size = 1; 74 75 return SCSI_REQ_CMP; 76 } 77 78 79 //! this is called immediately before the SCSI bus manager scans the bus 80 static uchar 81 ahci_scan_bus(scsi_sim_cookie cookie) 82 { 83 TRACE("ahci_scan_bus, cookie %p\n", cookie); 84 85 return SCSI_REQ_CMP; 86 } 87 88 89 static uchar 90 ahci_reset_bus(scsi_sim_cookie cookie) 91 { 92 TRACE("ahci_reset_bus, cookie %p\n", cookie); 93 94 return SCSI_REQ_CMP; 95 } 96 97 98 /*! Get restrictions of one device 99 (used for non-SCSI transport protocols and bug fixes) 100 */ 101 static void 102 ahci_get_restrictions(scsi_sim_cookie cookie, uchar targetID, bool *isATAPI, 103 bool *noAutoSense, uint32 *maxBlocks) 104 { 105 TRACE("ahci_get_restrictions, cookie %p\n", cookie); 106 107 *isATAPI = false; 108 *noAutoSense = false; 109 *maxBlocks = 256; 110 } 111 112 113 static status_t 114 ahci_ioctl(scsi_sim_cookie cookie, uint8 targetID, uint32 op, void *buffer, 115 size_t length) 116 { 117 TRACE("ahci_ioctl, cookie %p\n", cookie); 118 return B_BAD_VALUE; 119 } 120 121 122 // #pragma mark - 123 124 125 static status_t 126 ahci_sim_init_bus(device_node_handle node, void *userCookie, void **_cookie) 127 { 128 pci_device_info *pciDevice; 129 device_node_handle parent; 130 AHCIController *controller; 131 status_t status; 132 133 TRACE("ahci_sim_init_bus: userCookie %p\n", userCookie); 134 135 TRACE("ahci_sim_init_bus: gPCI %p\n", gPCI); 136 137 // initialize parent (the bus) to get the PCI device 138 parent = gDeviceManager->get_parent(node); 139 status = gDeviceManager->init_driver(parent, &pciDevice, NULL, NULL); 140 gDeviceManager->put_device_node(parent); 141 if (status != B_OK) 142 return status; 143 144 TRACE("ahci_sim_init_bus: pciDevice %p\n", pciDevice); 145 146 controller = new(std::nothrow) AHCIController(node, pciDevice); 147 if (!controller) 148 return B_NO_MEMORY; 149 status = controller->Init(); 150 if (status < B_OK) { 151 delete controller; 152 return status; 153 } 154 155 *_cookie = controller; 156 TRACE("cookie = %p\n", *_cookie); 157 return B_OK; 158 } 159 160 161 static status_t 162 ahci_sim_uninit_bus(void *cookie) 163 { 164 TRACE("ahci_sim_uninit_bus, cookie %p\n", cookie); 165 AHCIController *controller = static_cast<AHCIController *>(cookie); 166 167 device_node_handle parent = gDeviceManager->get_parent( 168 controller->DeviceNode()); 169 170 controller->Uninit(); 171 delete controller; 172 173 gDeviceManager->uninit_driver(parent); 174 gDeviceManager->put_device_node(parent); 175 176 return B_OK; 177 } 178 179 180 static void 181 ahci_sim_bus_removed(device_node_handle node, void *cookie) 182 { 183 TRACE("ahci_sim_bus_removed, cookie %p\n", cookie); 184 } 185 186 187 static status_t 188 std_ops(int32 op, ...) 189 { 190 switch (op) { 191 case B_MODULE_INIT: 192 case B_MODULE_UNINIT: 193 return B_OK; 194 195 default: 196 return B_ERROR; 197 } 198 } 199 200 201 scsi_sim_interface gAHCISimInterface = { 202 { 203 { 204 AHCI_SIM_MODULE_NAME, 205 0, 206 std_ops 207 }, 208 NULL, // supported devices 209 NULL, // register node 210 ahci_sim_init_bus, 211 ahci_sim_uninit_bus, 212 ahci_sim_bus_removed, 213 NULL, // device cleanup 214 NULL, // get supported paths 215 }, 216 ahci_scsi_io, 217 ahci_abort_io, 218 ahci_reset_device, 219 ahci_terminate_io, 220 ahci_path_inquiry, 221 ahci_scan_bus, 222 ahci_reset_bus, 223 ahci_get_restrictions, 224 ahci_ioctl 225 }; 226 227