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