1 /* 2 * Copyright 2007, Marcus Overhagen. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include "ahci_defs.h" 7 8 #include <stdlib.h> 9 #include <string.h> 10 11 #include <block_io.h> 12 13 14 #define TRACE(a...) dprintf("\33[35mahci:\33[0m " a) 15 #define FLOW(a...) dprintf("ahci: " a) 16 17 #define AHCI_ID_GENERATOR "ahci/id" 18 #define AHCI_ID_ITEM "ahci/id" 19 20 device_manager_info *gDeviceManager; 21 22 23 static status_t 24 register_sim(device_node_handle parent) 25 { 26 int32 id = gDeviceManager->create_id(AHCI_ID_GENERATOR); 27 if (id < 0) 28 return id; 29 30 { 31 device_attr attrs[] = { 32 { B_DRIVER_MODULE, B_STRING_TYPE, 33 { string: AHCI_SIM_MODULE_NAME }}, 34 { B_DRIVER_FIXED_CHILD, B_STRING_TYPE, 35 { string: SCSI_FOR_SIM_MODULE_NAME }}, 36 37 { SCSI_DESCRIPTION_CONTROLLER_NAME, B_STRING_TYPE, 38 { string: AHCI_DEVICE_MODULE_NAME }}, 39 { B_BLOCK_DEVICE_MAX_BLOCKS_ITEM, B_UINT32_TYPE, { ui32: 255 }}, 40 { AHCI_ID_ITEM, B_UINT32_TYPE, { ui32: id }}, 41 { PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE, 42 { string: AHCI_ID_GENERATOR }}, 43 { PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { ui32: id }}, 44 45 { NULL } 46 }; 47 48 device_node_handle node; 49 status_t status = gDeviceManager->register_device(parent, attrs, NULL, 50 &node); 51 if (status < B_OK) 52 gDeviceManager->free_id(AHCI_ID_GENERATOR, id); 53 54 return status; 55 } 56 } 57 58 59 // #pragma mark - 60 61 62 static float 63 ahci_supports_device(device_node_handle parent, bool *_noConnection) 64 { 65 uint8 baseClass, subClass, classAPI; 66 uint16 vendorID; 67 uint16 deviceID; 68 char *bus; 69 70 TRACE("ahci_supports_device\n"); 71 72 if (gDeviceManager->get_attr_string(parent, B_DRIVER_BUS, &bus, 73 false) != B_OK 74 || gDeviceManager->get_attr_uint8(parent, 75 PCI_DEVICE_BASE_CLASS_ID_ITEM, &baseClass, false) != B_OK 76 || gDeviceManager->get_attr_uint8(parent, 77 PCI_DEVICE_SUB_CLASS_ID_ITEM, &subClass, false) != B_OK 78 || gDeviceManager->get_attr_uint8(parent, 79 PCI_DEVICE_API_ID_ITEM, &classAPI, false) != B_OK 80 || gDeviceManager->get_attr_uint16(parent, 81 PCI_DEVICE_VENDOR_ID_ITEM, &vendorID, false) != B_OK 82 || gDeviceManager->get_attr_uint16(parent, 83 PCI_DEVICE_DEVICE_ID_ITEM, &deviceID, false) != B_OK) 84 return B_ERROR; 85 86 #if 1 87 if (strcmp(bus, "pci") || baseClass != PCI_mass_storage 88 || subClass != PCI_sata || classAPI != PCI_sata_ahci) { 89 free(bus); 90 return 0.0f; 91 } 92 #else 93 if (strcmp(bus, "pci") || baseClass != PCI_mass_storage 94 || subClass != PCI_ide) { 95 free(bus); 96 return 0.0; 97 } 98 #endif 99 100 TRACE("controller found! vendor 0x%04x, device 0x%04x\n", 101 vendorID, deviceID); 102 103 free(bus); 104 return 0.5; 105 } 106 107 108 static status_t 109 ahci_register_device(device_node_handle parent) 110 { 111 device_node_handle node; 112 status_t status; 113 114 device_attr attrs[] = { 115 // info about ourself and our consumer 116 { B_DRIVER_MODULE, B_STRING_TYPE, { string: AHCI_DEVICE_MODULE_NAME }}, 117 118 { SCSI_DEVICE_MAX_TARGET_COUNT, B_UINT32_TYPE, 119 { ui32: 33 }}, 120 121 // DMA properties 122 // data must be word-aligned; 123 { B_BLOCK_DEVICE_DMA_ALIGNMENT, B_UINT32_TYPE, 124 { ui32: 1 }}, 125 // one S/G block must not cross 64K boundary 126 { B_BLOCK_DEVICE_DMA_BOUNDARY, B_UINT32_TYPE, 127 { ui32: 0xffff }}, 128 // max size of S/G block is 16 bits with zero being 64K 129 { B_BLOCK_DEVICE_MAX_SG_BLOCK_SIZE, B_UINT32_TYPE, 130 { ui32: 0x10000 }}, 131 // see definition of MAX_SG_COUNT 132 { B_BLOCK_DEVICE_MAX_SG_BLOCKS, B_UINT32_TYPE, 133 { ui32: 32 /* whatever... */ }}, 134 { NULL } 135 }; 136 137 TRACE("ahci_register_device\n"); 138 139 status = gDeviceManager->register_device(parent, attrs, 140 NULL, &node); 141 if (status < B_OK) 142 return status; 143 144 // TODO: register SIM for every controller we find! 145 return register_sim(node); 146 } 147 148 149 static status_t 150 ahci_init_driver(device_node_handle node, void *userCookie, void **_cookie) 151 { 152 pci_device *_userCookie = userCookie; 153 pci_device pciDevice; 154 device_node_handle parent; 155 status_t status; 156 157 TRACE("ahci_init_driver, userCookie %p\n", userCookie); 158 159 parent = gDeviceManager->get_parent(node); 160 161 // initialize parent (the bus) to get the PCI interface and device 162 status = gDeviceManager->init_driver(parent, NULL, 163 (driver_module_info **)&gPCI, (void **)&pciDevice); 164 if (status != B_OK) 165 return status; 166 167 gDeviceManager->put_device_node(parent); 168 169 *_userCookie = pciDevice; 170 *_cookie = node; 171 return B_OK; 172 } 173 174 175 static status_t 176 ahci_uninit_driver(void *cookie) 177 { 178 device_node_handle node = cookie; 179 device_node_handle parent; 180 181 TRACE("ahci_uninit_driver, cookie %p\n", cookie); 182 183 parent = gDeviceManager->get_parent(node); 184 gDeviceManager->uninit_driver(parent); 185 gDeviceManager->put_device_node(parent); 186 return B_OK; 187 } 188 189 190 static void 191 ahci_device_removed(device_node_handle node, void *cookie) 192 { 193 TRACE("ahci_device_removed, cookie %p\n", cookie); 194 } 195 196 197 static void 198 ahci_device_cleanup(device_node_handle node) 199 { 200 TRACE("ahci_device_cleanup\n"); 201 } 202 203 204 static void 205 ahci_get_supported_paths(const char ***_busses, const char ***_devices) 206 { 207 static const char *kBus[] = { "pci", NULL }; 208 static const char *kDevice[] = { "drivers/dev/disk/sata", NULL }; 209 210 TRACE("ahci_get_supported_paths\n"); 211 212 *_busses = kBus; 213 *_devices = kDevice; 214 } 215 216 217 static status_t 218 std_ops(int32 op, ...) 219 { 220 switch (op) { 221 case B_MODULE_INIT: 222 case B_MODULE_UNINIT: 223 return B_OK; 224 225 default: 226 return B_ERROR; 227 } 228 } 229 230 231 driver_module_info sAHCIDevice = { 232 { 233 AHCI_DEVICE_MODULE_NAME, 234 0, 235 std_ops 236 }, 237 ahci_supports_device, 238 ahci_register_device, 239 ahci_init_driver, 240 ahci_uninit_driver, 241 ahci_device_removed, 242 ahci_device_cleanup, 243 ahci_get_supported_paths, 244 }; 245 246 module_dependency module_dependencies[] = { 247 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, 248 { SCSI_FOR_SIM_MODULE_NAME, (module_info **)&gSCSI }, 249 {} 250 }; 251 252 module_info *modules[] = { 253 (module_info *)&sAHCIDevice, 254 (module_info *)&gAHCISimInterface, 255 NULL 256 }; 257