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