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 extern "C" status_t 22 init_hardware(void) 23 { 24 pci_info info; 25 long i; 26 27 if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPci) != B_OK) 28 return ENODEV; 29 30 for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK; i++) { 31 if (info.class_base == PCI_multimedia 32 && info.class_sub == PCI_hd_audio) { 33 put_module(B_PCI_MODULE_NAME); 34 return B_OK; 35 } 36 } 37 38 put_module(B_PCI_MODULE_NAME); 39 return ENODEV; 40 } 41 42 43 extern "C" status_t 44 init_driver(void) 45 { 46 char path[B_PATH_NAME_LENGTH]; 47 pci_info info; 48 long i; 49 50 if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPci) != B_OK) 51 return ENODEV; 52 53 gNumCards = 0; 54 55 for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK 56 && gNumCards < MAX_CARDS; i++) { 57 if (info.class_base == PCI_multimedia 58 && info.class_sub == PCI_hd_audio) { 59 #ifdef __HAIKU__ 60 if ((*gPci->reserve_device)(info.bus, info.device, info.function, 61 "hda", &gCards[gNumCards]) < B_OK) { 62 dprintf("HDA: Failed to reserve PCI:%d:%d:%d\n", 63 info.bus, info.device, info.function); 64 continue; 65 } 66 #endif 67 memset(&gCards[gNumCards], 0, sizeof(hda_controller)); 68 gCards[gNumCards].pci_info = info; 69 gCards[gNumCards].opened = 0; 70 sprintf(path, DEVFS_PATH_FORMAT, gNumCards); 71 gCards[gNumCards++].devfs_path = strdup(path); 72 73 dprintf("HDA: Detected controller @ PCI:%d:%d:%d, IRQ:%d, " 74 "type %04x/%04x (%04x/%04x)\n", 75 info.bus, info.device, info.function, 76 info.u.h0.interrupt_line, info.vendor_id, info.device_id, 77 info.u.h0.subsystem_vendor_id, info.u.h0.subsystem_id); 78 } 79 } 80 81 if (gNumCards == 0) { 82 put_module(B_PCI_MODULE_NAME); 83 return ENODEV; 84 } 85 86 if (get_module(B_PCI_X86_MODULE_NAME, (module_info**)&gPCIx86Module) 87 != B_OK) { 88 gPCIx86Module = NULL; 89 } 90 91 return B_OK; 92 } 93 94 95 extern "C" void 96 uninit_driver(void) 97 { 98 for (uint32 i = 0; i < gNumCards; i++) { 99 #ifdef __HAIKU__ 100 (*gPci->unreserve_device)(gCards[i].pci_info.bus, 101 gCards[i].pci_info.device, gCards[i].pci_info.function, "hda", 102 &gCards[i]); 103 #endif 104 free((void*)gCards[i].devfs_path); 105 gCards[i].devfs_path = NULL; 106 } 107 108 put_module(B_PCI_MODULE_NAME); 109 if (gPCIx86Module != NULL) { 110 put_module(B_PCI_X86_MODULE_NAME); 111 gPCIx86Module = NULL; 112 } 113 } 114 115 116 extern "C" const char** 117 publish_devices(void) 118 { 119 static const char* devs[MAX_CARDS + 1]; 120 uint32 i; 121 122 for (i = 0; i < gNumCards; i++) 123 devs[i] = gCards[i].devfs_path; 124 125 devs[i] = NULL; 126 127 return devs; 128 } 129 130 131 extern "C" device_hooks* 132 find_device(const char* name) 133 { 134 return &gDriverHooks; 135 } 136