xref: /haiku/src/add-ons/kernel/drivers/audio/hda/driver.cpp (revision cbe0a0c436162d78cc3f92a305b64918c839d079)
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