1 /* 2 * Copyright 2007-2008, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ithamar Adema, ithamar AT unet DOT nl 7 */ 8 9 10 #include "driver.h" 11 12 13 int32 api_version = B_CUR_DRIVER_API_VERSION; 14 15 hda_controller gCards[MAX_CARDS]; 16 uint32 gNumCards; 17 pci_module_info* gPci; 18 pci_x86_module_info* gPCIx86Module; 19 20 21 static struct { 22 uint16 vendor; 23 uint16 device; 24 } kSupportedDevices[] = { 25 { 0x8086, 0xa170}, // 100 Series HD Audio 26 { 0x8086, 0x9d71}, // 200 Series HD Audio 27 { 0x8086, 0xa348}, // 300 Series cAVS 28 { 0x8086, 0x9dc8}, // 300 Series HD Audio 29 { 0x8086, 0x06c8}, // 400 Series cAVS 30 { 0x8086, 0x02c8}, // 400 Series HD Audio 31 { 0x8086, 0xa0c8}, // 500 Series HD Audio 32 { 0x8086, 0x51c8}, // 600 Series HD Audio 33 { 0x8086, 0x4dc8}, // JasperLake HD Audio 34 { 0x8086, 0x43c8}, // Tiger Lake-H HD Audio 35 { 0x8086, 0xa171}, // CM238 HD Audio 36 { 0x8086, 0x3198}, // GeminiLake HD Audio 37 }; 38 39 40 static bool 41 supports_device(pci_info &info) 42 { 43 for (size_t i = 0; i < B_COUNT_OF(kSupportedDevices); i++) { 44 if (info.vendor_id == kSupportedDevices[i].vendor 45 && info.device_id == kSupportedDevices[i].device) { 46 return true; 47 } 48 } 49 return false; 50 } 51 52 53 extern "C" status_t 54 init_hardware(void) 55 { 56 pci_info info; 57 long i; 58 59 if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPci) != B_OK) 60 return ENODEV; 61 62 for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK; i++) { 63 if ((info.class_base == PCI_multimedia 64 && info.class_sub == PCI_hd_audio) 65 || supports_device(info)) { 66 put_module(B_PCI_MODULE_NAME); 67 return B_OK; 68 } 69 } 70 71 put_module(B_PCI_MODULE_NAME); 72 return ENODEV; 73 } 74 75 76 extern "C" status_t 77 init_driver(void) 78 { 79 char path[B_PATH_NAME_LENGTH]; 80 pci_info info; 81 long i; 82 83 if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPci) != B_OK) 84 return ENODEV; 85 86 gNumCards = 0; 87 88 for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK 89 && gNumCards < MAX_CARDS; i++) { 90 if ((info.class_base == PCI_multimedia 91 && info.class_sub == PCI_hd_audio) 92 || supports_device(info)) { 93 #ifdef __HAIKU__ 94 if ((*gPci->reserve_device)(info.bus, info.device, info.function, 95 "hda", &gCards[gNumCards]) < B_OK) { 96 dprintf("HDA: Failed to reserve PCI:%d:%d:%d\n", 97 info.bus, info.device, info.function); 98 continue; 99 } 100 #endif 101 memset(&gCards[gNumCards], 0, sizeof(hda_controller)); 102 gCards[gNumCards].pci_info = info; 103 gCards[gNumCards].opened = 0; 104 sprintf(path, DEVFS_PATH_FORMAT, gNumCards); 105 gCards[gNumCards++].devfs_path = strdup(path); 106 107 dprintf("HDA: Detected controller @ PCI:%d:%d:%d, IRQ:%d, " 108 "type %04x/%04x (%04x/%04x)\n", 109 info.bus, info.device, info.function, 110 info.u.h0.interrupt_line, info.vendor_id, info.device_id, 111 info.u.h0.subsystem_vendor_id, info.u.h0.subsystem_id); 112 } 113 } 114 115 if (gNumCards == 0) { 116 put_module(B_PCI_MODULE_NAME); 117 return ENODEV; 118 } 119 120 if (get_module(B_PCI_X86_MODULE_NAME, (module_info**)&gPCIx86Module) 121 != B_OK) { 122 gPCIx86Module = NULL; 123 } 124 125 return B_OK; 126 } 127 128 129 extern "C" void 130 uninit_driver(void) 131 { 132 for (uint32 i = 0; i < gNumCards; i++) { 133 #ifdef __HAIKU__ 134 (*gPci->unreserve_device)(gCards[i].pci_info.bus, 135 gCards[i].pci_info.device, gCards[i].pci_info.function, "hda", 136 &gCards[i]); 137 #endif 138 free((void*)gCards[i].devfs_path); 139 gCards[i].devfs_path = NULL; 140 } 141 142 put_module(B_PCI_MODULE_NAME); 143 if (gPCIx86Module != NULL) { 144 put_module(B_PCI_X86_MODULE_NAME); 145 gPCIx86Module = NULL; 146 } 147 } 148 149 150 extern "C" const char** 151 publish_devices(void) 152 { 153 static const char* devs[MAX_CARDS + 1]; 154 uint32 i; 155 156 for (i = 0; i < gNumCards; i++) 157 devs[i] = gCards[i].devfs_path; 158 159 devs[i] = NULL; 160 161 return devs; 162 } 163 164 165 extern "C" device_hooks* 166 find_device(const char* name) 167 { 168 return &gDriverHooks; 169 } 170