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 21 const device_info kSupportedDevices[] = { 22 { 0x1002, 0x4380, "ATI SB600" }, 23 { 0x1002, 0x4390, "ATI SB700/800" }, 24 { 0x1002, 0x4391, "ATI IXP700" }, 25 { 0x1002, 0x4392, "ATI SB700/800" }, 26 { 0x1002, 0x4393, "ATI SB700/800" }, 27 { 0x1002, 0x4394, "ATI SB700/800" }, 28 { 0x1002, 0x4395, "ATI SB700/800" }, 29 { 0x1039, 0x1184, "SiS 966" }, 30 { 0x1039, 0x1185, "SiS 966" }, 31 { 0x1039, 0x0186, "SiS 968" }, 32 { 0x10b9, 0x5288, "Acer Labs M5288" }, 33 { 0x10de, 0x044c, "NVIDIA MCP65" }, 34 { 0x10de, 0x044d, "NVIDIA MCP65" }, 35 { 0x10de, 0x044e, "NVIDIA MCP65" }, 36 { 0x10de, 0x044f, "NVIDIA MCP65" }, 37 { 0x10de, 0x045c, "NVIDIA MCP65" }, 38 { 0x10de, 0x045d, "NVIDIA MCP65" }, 39 { 0x10de, 0x045e, "NVIDIA MCP65" }, 40 { 0x10de, 0x045f, "NVIDIA MCP65" }, 41 { 0x10de, 0x0550, "NVIDIA MCP67" }, 42 { 0x10de, 0x0551, "NVIDIA MCP67" }, 43 { 0x10de, 0x0552, "NVIDIA MCP67" }, 44 { 0x10de, 0x0553, "NVIDIA MCP67" }, 45 { 0x10de, 0x0554, "NVIDIA MCP67" }, 46 { 0x10de, 0x0555, "NVIDIA MCP67" }, 47 { 0x10de, 0x0556, "NVIDIA MCP67" }, 48 { 0x10de, 0x0557, "NVIDIA MCP67" }, 49 { 0x10de, 0x0558, "NVIDIA MCP67" }, 50 { 0x10de, 0x0559, "NVIDIA MCP67" }, 51 { 0x10de, 0x055a, "NVIDIA MCP67" }, 52 { 0x10de, 0x055b, "NVIDIA MCP67" }, 53 { 0x10de, 0x07f0, "NVIDIA MCP73" }, 54 { 0x10de, 0x07f1, "NVIDIA MCP73" }, 55 { 0x10de, 0x07f2, "NVIDIA MCP73" }, 56 { 0x10de, 0x07f3, "NVIDIA MCP73" }, 57 { 0x10de, 0x07f4, "NVIDIA MCP73" }, 58 { 0x10de, 0x07f5, "NVIDIA MCP73" }, 59 { 0x10de, 0x07f6, "NVIDIA MCP73" }, 60 { 0x10de, 0x07f7, "NVIDIA MCP73" }, 61 { 0x10de, 0x07f8, "NVIDIA MCP73" }, 62 { 0x10de, 0x07f9, "NVIDIA MCP73" }, 63 { 0x10de, 0x07fa, "NVIDIA MCP73" }, 64 { 0x10de, 0x07fb, "NVIDIA MCP73" }, 65 { 0x10de, 0x0ad0, "NVIDIA MCP77" }, 66 { 0x10de, 0x0ad1, "NVIDIA MCP77" }, 67 { 0x10de, 0x0ad2, "NVIDIA MCP77" }, 68 { 0x10de, 0x0ad3, "NVIDIA MCP77" }, 69 { 0x10de, 0x0ad4, "NVIDIA MCP77" }, 70 { 0x10de, 0x0ad5, "NVIDIA MCP77" }, 71 { 0x10de, 0x0ad6, "NVIDIA MCP77" }, 72 { 0x10de, 0x0ad7, "NVIDIA MCP77" }, 73 { 0x10de, 0x0ad8, "NVIDIA MCP77" }, 74 { 0x10de, 0x0ad9, "NVIDIA MCP77" }, 75 { 0x10de, 0x0ada, "NVIDIA MCP77" }, 76 { 0x10de, 0x0adb, "NVIDIA MCP77" }, 77 { 0x1106, 0x3349, "VIA VT8251" }, 78 { 0x1106, 0x6287, "VIA VT8251" }, 79 { 0x11ab, 0x6145, "Marvell 6145" }, 80 { 0x197b, 0x2360, "JMicron JMB360" }, 81 { 0x197b, 0x2361, "JMicron JMB361" }, 82 { 0x197b, 0x2362, "JMicron JMB362" }, 83 { 0x197b, 0x2363, "JMicron JMB363" }, 84 { 0x197b, 0x2366, "JMicron JMB366" }, 85 { 0x8086, 0x2652, "Intel ICH6R" }, 86 { 0x8086, 0x2653, "Intel ICH6-M" }, 87 { 0x8086, 0x2681, "Intel 63xxESB" }, 88 { 0x8086, 0x2682, "Intel ESB2" }, 89 { 0x8086, 0x2683, "Intel ESB2" }, 90 { 0x8086, 0x27c1, "Intel ICH7R (AHCI mode)" }, 91 { 0x8086, 0x27c3, "Intel ICH7R (RAID mode)" }, 92 { 0x8086, 0x27c5, "Intel ICH7-M (AHCI mode)" }, 93 { 0x8086, 0x27c6, "Intel ICH7-M DH (RAID mode)" }, 94 { 0x8086, 0x2821, "Intel ICH8 (AHCI mode)" }, 95 { 0x8086, 0x2822, "Intel ICH8R / ICH9 (RAID mode)" }, 96 { 0x8086, 0x2824, "Intel ICH8 (AHCI mode)" }, 97 { 0x8086, 0x2829, "Intel ICH8M (AHCI mode)" }, 98 { 0x8086, 0x282a, "Intel ICH8M (RAID mode)" }, 99 { 0x8086, 0x2922, "Intel ICH9 (AHCI mode)" }, 100 { 0x8086, 0x2923, "Intel ICH9 (AHCI mode)" }, 101 { 0x8086, 0x2924, "Intel ICH9" }, 102 { 0x8086, 0x2925, "Intel ICH9" }, 103 { 0x8086, 0x2927, "Intel ICH9" }, 104 { 0x8086, 0x2929, "Intel ICH9M" }, 105 { 0x8086, 0x292a, "Intel ICH9M" }, 106 { 0x8086, 0x292b, "Intel ICH9M" }, 107 { 0x8086, 0x292c, "Intel ICH9M" }, 108 { 0x8086, 0x292f, "Intel ICH9M" }, 109 { 0x8086, 0x294d, "Intel ICH9" }, 110 { 0x8086, 0x294e, "Intel ICH9M" }, 111 {} 112 }; 113 114 115 status_t 116 get_device_info(uint16 vendorID, uint16 deviceID, const char **name, 117 uint32 *flags) 118 { 119 const device_info *info; 120 for (info = kSupportedDevices; info->vendor; info++) { 121 if (info->vendor == vendorID && info->device == deviceID) { 122 if (name) 123 *name = info->name; 124 if (flags) 125 *flags = info->flags; 126 return B_OK; 127 } 128 } 129 return B_ERROR; 130 } 131 132 133 static status_t 134 register_sim(device_node_handle parent) 135 { 136 int32 id = gDeviceManager->create_id(AHCI_ID_GENERATOR); 137 if (id < 0) 138 return id; 139 140 { 141 device_attr attrs[] = { 142 { B_DRIVER_MODULE, B_STRING_TYPE, 143 { string: AHCI_SIM_MODULE_NAME }}, 144 { B_DRIVER_FIXED_CHILD, B_STRING_TYPE, 145 { string: SCSI_FOR_SIM_MODULE_NAME }}, 146 147 { SCSI_DESCRIPTION_CONTROLLER_NAME, B_STRING_TYPE, 148 { string: AHCI_DEVICE_MODULE_NAME }}, 149 { B_BLOCK_DEVICE_MAX_BLOCKS_ITEM, B_UINT32_TYPE, { ui32: 255 }}, 150 { AHCI_ID_ITEM, B_UINT32_TYPE, { ui32: id }}, 151 { PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE, 152 { string: AHCI_ID_GENERATOR }}, 153 { PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { ui32: id }}, 154 155 { NULL } 156 }; 157 158 device_node_handle node; 159 status_t status = gDeviceManager->register_device(parent, attrs, NULL, 160 &node); 161 if (status < B_OK) 162 gDeviceManager->free_id(AHCI_ID_GENERATOR, id); 163 164 return status; 165 } 166 } 167 168 169 // #pragma mark - 170 171 172 static float 173 ahci_supports_device(device_node_handle parent, bool *_noConnection) 174 { 175 uint8 baseClass, subClass, classAPI; 176 uint16 vendorID; 177 uint16 deviceID; 178 bool isPCI; 179 const char *name; 180 char *bus; 181 182 TRACE("ahci_supports_device\n"); 183 184 if (gDeviceManager->get_attr_string(parent, B_DRIVER_BUS, &bus, false) < B_OK) 185 return 0.0f; 186 isPCI = !strcmp(bus, "pci"); 187 free(bus); 188 if (!isPCI) 189 return 0.0f; 190 191 if (gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_BASE_CLASS_ID_ITEM, &baseClass, false) < B_OK 192 || gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_SUB_CLASS_ID_ITEM, &subClass, false) < B_OK 193 || gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_API_ID_ITEM, &classAPI, false) < B_OK 194 || gDeviceManager->get_attr_uint16(parent, PCI_DEVICE_VENDOR_ID_ITEM, &vendorID, false) < B_OK 195 || gDeviceManager->get_attr_uint16(parent, PCI_DEVICE_DEVICE_ID_ITEM, &deviceID, false) < B_OK) 196 return 0.0f; 197 198 if (get_device_info(vendorID, deviceID, &name, NULL) < B_OK) { 199 if (baseClass != PCI_mass_storage || subClass != PCI_sata || classAPI != PCI_sata_ahci) 200 return 0.0f; 201 TRACE("generic AHCI controller found! vendor 0x%04x, device 0x%04x\n", vendorID, deviceID); 202 return 0.8f; 203 } 204 205 if (vendorID == PCI_VENDOR_JMICRON) { 206 // JMicron uses the same device ID for SATA and PATA controllers, 207 // check if BAR5 exists to determine if it's a AHCI controller 208 uint8 bus, device, function; 209 pci_info info; 210 pci_module_info *pci; 211 size_t size = 0; 212 int i; 213 gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_BUS_ITEM, &bus, false); 214 gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_DEVICE_ITEM, &device, false); 215 gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_FUNCTION_ITEM, &function, false); 216 get_module(B_PCI_MODULE_NAME, (module_info **)&pci); 217 for (i = 0; B_OK == pci->get_nth_pci_info(i, &info); i++) { 218 if (info.bus == bus && info.device == device && info.function == function) { 219 size = info.u.h0.base_register_sizes[5]; 220 break; 221 } 222 } 223 put_module(B_PCI_MODULE_NAME); 224 if (size == 0) 225 return 0.0f; 226 } 227 228 TRACE("AHCI controller %s found!\n", name); 229 return 1.0f; 230 } 231 232 233 static status_t 234 ahci_register_device(device_node_handle parent) 235 { 236 device_node_handle node; 237 status_t status; 238 239 device_attr attrs[] = { 240 // info about ourself and our consumer 241 { B_DRIVER_MODULE, B_STRING_TYPE, { string: AHCI_DEVICE_MODULE_NAME }}, 242 243 { SCSI_DEVICE_MAX_TARGET_COUNT, B_UINT32_TYPE, 244 { ui32: 33 }}, 245 246 // DMA properties 247 // data must be word-aligned; 248 { B_BLOCK_DEVICE_DMA_ALIGNMENT, B_UINT32_TYPE, 249 { ui32: 1 }}, 250 // one S/G block must not cross 64K boundary 251 { B_BLOCK_DEVICE_DMA_BOUNDARY, B_UINT32_TYPE, 252 { ui32: 0xffff }}, 253 // max size of S/G block is 16 bits with zero being 64K 254 { B_BLOCK_DEVICE_MAX_SG_BLOCK_SIZE, B_UINT32_TYPE, 255 { ui32: 0x10000 }}, 256 // see definition of MAX_SG_COUNT 257 { B_BLOCK_DEVICE_MAX_SG_BLOCKS, B_UINT32_TYPE, 258 { ui32: 32 /* whatever... */ }}, 259 { NULL } 260 }; 261 262 TRACE("ahci_register_device\n"); 263 264 status = gDeviceManager->register_device(parent, attrs, 265 NULL, &node); 266 if (status < B_OK) 267 return status; 268 269 // TODO: register SIM for every controller we find! 270 return register_sim(node); 271 } 272 273 274 static status_t 275 ahci_init_driver(device_node_handle node, void *userCookie, void **_cookie) 276 { 277 pci_device *_userCookie = userCookie; 278 pci_device pciDevice; 279 device_node_handle parent; 280 status_t status; 281 282 TRACE("ahci_init_driver, userCookie %p\n", userCookie); 283 284 parent = gDeviceManager->get_parent(node); 285 286 // initialize parent (the bus) to get the PCI interface and device 287 status = gDeviceManager->init_driver(parent, NULL, 288 (driver_module_info **)&gPCI, (void **)&pciDevice); 289 if (status != B_OK) 290 return status; 291 292 TRACE("ahci_init_driver: gPCI %p, pciDevice %p\n", gPCI, pciDevice); 293 294 gDeviceManager->put_device_node(parent); 295 296 *_userCookie = pciDevice; 297 *_cookie = node; 298 return B_OK; 299 } 300 301 302 static status_t 303 ahci_uninit_driver(void *cookie) 304 { 305 device_node_handle node = cookie; 306 device_node_handle parent; 307 308 TRACE("ahci_uninit_driver, cookie %p\n", cookie); 309 310 parent = gDeviceManager->get_parent(node); 311 gDeviceManager->uninit_driver(parent); 312 gDeviceManager->put_device_node(parent); 313 return B_OK; 314 } 315 316 317 static void 318 ahci_device_removed(device_node_handle node, void *cookie) 319 { 320 TRACE("ahci_device_removed, cookie %p\n", cookie); 321 } 322 323 324 static void 325 ahci_device_cleanup(device_node_handle node) 326 { 327 TRACE("ahci_device_cleanup\n"); 328 } 329 330 331 static void 332 ahci_get_supported_paths(const char ***_busses, const char ***_devices) 333 { 334 static const char *kBus[] = { "pci", NULL }; 335 static const char *kDevice[] = { "drivers/dev/disk/sata", NULL }; 336 337 TRACE("ahci_get_supported_paths\n"); 338 339 *_busses = kBus; 340 *_devices = kDevice; 341 } 342 343 344 static status_t 345 std_ops(int32 op, ...) 346 { 347 switch (op) { 348 case B_MODULE_INIT: 349 case B_MODULE_UNINIT: 350 return B_OK; 351 352 default: 353 return B_ERROR; 354 } 355 } 356 357 358 driver_module_info sAHCIDevice = { 359 { 360 AHCI_DEVICE_MODULE_NAME, 361 0, 362 std_ops 363 }, 364 ahci_supports_device, 365 ahci_register_device, 366 ahci_init_driver, 367 ahci_uninit_driver, 368 ahci_device_removed, 369 ahci_device_cleanup, 370 ahci_get_supported_paths, 371 }; 372 373 374 module_dependency module_dependencies[] = { 375 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, 376 // { B_PCI_MODULE_NAME, (module_info **)&gPCI }, 377 { SCSI_FOR_SIM_MODULE_NAME, (module_info **)&gSCSI }, 378 {} 379 }; 380 381 382 module_info *modules[] = { 383 (module_info *)&sAHCIDevice, 384 (module_info *)&gAHCISimInterface, 385 NULL 386 }; 387