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