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, 0xa0c8}, // 500 Series HD Audio 31 { 0x8086, 0x4dc8}, // JasperLake HD Audio 32 { 0x8086, 0x43c8}, // Tiger Lake-H HD Audio 33 { 0x8086, 0xa171}, // CM238 HD Audio 34 { 0x8086, 0x3198}, // GeminiLake HD Audio 35 }; 36 37 38 static bool 39 supports_device(pci_info &info) 40 { 41 for (size_t i = 0; i < B_COUNT_OF(kSupportedDevices); i++) { 42 if (info.vendor_id == kSupportedDevices[i].vendor 43 && info.device_id == kSupportedDevices[i].device) { 44 return true; 45 } 46 } 47 return false; 48 } 49 50 51 extern "C" status_t 52 init_hardware(void) 53 { 54 pci_info info; 55 long i; 56 57 if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPci) != B_OK) 58 return ENODEV; 59 60 for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK; i++) { 61 if ((info.class_base == PCI_multimedia 62 && info.class_sub == PCI_hd_audio) 63 || supports_device(info)) { 64 put_module(B_PCI_MODULE_NAME); 65 return B_OK; 66 } 67 } 68 69 put_module(B_PCI_MODULE_NAME); 70 return ENODEV; 71 } 72 73 74 extern "C" status_t 75 init_driver(void) 76 { 77 char path[B_PATH_NAME_LENGTH]; 78 pci_info info; 79 long i; 80 81 if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPci) != B_OK) 82 return ENODEV; 83 84 gNumCards = 0; 85 86 for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK 87 && gNumCards < MAX_CARDS; i++) { 88 if ((info.class_base == PCI_multimedia 89 && info.class_sub == PCI_hd_audio) 90 || supports_device(info)) { 91 #ifdef __HAIKU__ 92 if ((*gPci->reserve_device)(info.bus, info.device, info.function, 93 "hda", &gCards[gNumCards]) < B_OK) { 94 dprintf("HDA: Failed to reserve PCI:%d:%d:%d\n", 95 info.bus, info.device, info.function); 96 continue; 97 } 98 #endif 99 memset(&gCards[gNumCards], 0, sizeof(hda_controller)); 100 gCards[gNumCards].pci_info = info; 101 gCards[gNumCards].opened = 0; 102 sprintf(path, DEVFS_PATH_FORMAT, gNumCards); 103 gCards[gNumCards++].devfs_path = strdup(path); 104 105 dprintf("HDA: Detected controller @ PCI:%d:%d:%d, IRQ:%d, " 106 "type %04x/%04x (%04x/%04x)\n", 107 info.bus, info.device, info.function, 108 info.u.h0.interrupt_line, info.vendor_id, info.device_id, 109 info.u.h0.subsystem_vendor_id, info.u.h0.subsystem_id); 110 } 111 } 112 113 if (gNumCards == 0) { 114 put_module(B_PCI_MODULE_NAME); 115 return ENODEV; 116 } 117 118 if (get_module(B_PCI_X86_MODULE_NAME, (module_info**)&gPCIx86Module) 119 != B_OK) { 120 gPCIx86Module = NULL; 121 } 122 123 return B_OK; 124 } 125 126 127 extern "C" void 128 uninit_driver(void) 129 { 130 for (uint32 i = 0; i < gNumCards; i++) { 131 #ifdef __HAIKU__ 132 (*gPci->unreserve_device)(gCards[i].pci_info.bus, 133 gCards[i].pci_info.device, gCards[i].pci_info.function, "hda", 134 &gCards[i]); 135 #endif 136 free((void*)gCards[i].devfs_path); 137 gCards[i].devfs_path = NULL; 138 } 139 140 put_module(B_PCI_MODULE_NAME); 141 if (gPCIx86Module != NULL) { 142 put_module(B_PCI_X86_MODULE_NAME); 143 gPCIx86Module = NULL; 144 } 145 } 146 147 148 extern "C" const char** 149 publish_devices(void) 150 { 151 static const char* devs[MAX_CARDS + 1]; 152 uint32 i; 153 154 for (i = 0; i < gNumCards; i++) 155 devs[i] = gCards[i].devfs_path; 156 157 devs[i] = NULL; 158 159 return devs; 160 } 161 162 163 extern "C" device_hooks* 164 find_device(const char* name) 165 { 166 return &gDriverHooks; 167 } 168