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