xref: /haiku/src/add-ons/kernel/drivers/audio/ac97/sis7018/Driver.cpp (revision 830f67ef991407f287dbc1238aa5f5906d90c991)
1 /*
2  *	SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver.
3  *	Copyright (c) 2002, 2008-2011 S.Zharski <imker@gmx.li>
4  *	Distributed under the terms of the MIT license.
5  *
6  */
7 
8 
9 #include "Driver.h"
10 
11 #include <kernel_cpp.h>
12 #include <string.h>
13 
14 #include "Device.h"
15 #include "Settings.h"
16 
17 
18 int32 api_version = B_CUR_DRIVER_API_VERSION;
19 
20 size_t gNumCards = 0;
21 Device *gDevices[MAX_DEVICES] = { 0 };
22 char *gDeviceNames[MAX_DEVICES + 1] = { 0 };
23 pci_module_info *gPCI = NULL;
24 
25 
26 static Device::Info cardInfos[] = {
27 	{ SiS7018, "SiS 7018" },
28 	{ ALi5451, "ALi M5451" },
29 	{ TridentDX, "Trident DX" },
30 	{ TridentNX, "Trident NX" }
31 };
32 
33 
34 status_t
35 init_hardware()
36 {
37 	dprintf("sis7018:init_hardware:ver:%s\n", kVersion);
38 	status_t result = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI);
39 	if (result < B_OK) {
40 		return ENOSYS;
41 	}
42 
43 	pci_info info = {0};
44 	for (long i = 0; B_OK == (*gPCI->get_nth_pci_info)(i, &info); i++) {
45 		for (size_t idx = 0; idx < B_COUNT_OF(cardInfos); idx++) {
46 			if (info.vendor_id == cardInfos[idx].VendorId() &&
47 				info.device_id == cardInfos[idx].DeviceId())
48 			{
49 				put_module(B_PCI_MODULE_NAME);
50 				return B_OK;
51 			}
52 		}
53 	}
54 
55 	put_module(B_PCI_MODULE_NAME);
56 	return ENODEV;
57 }
58 
59 
60 status_t
61 init_driver()
62 {
63 	status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI);
64 	if (status < B_OK) {
65 		return ENOSYS;
66 	}
67 
68 	load_settings();
69 
70 	pci_info info = { 0 };
71 	for (long i = 0; B_OK == (*gPCI->get_nth_pci_info)(i, &info); i++) {
72 		for (size_t idx = 0; idx < B_COUNT_OF(cardInfos); idx++) {
73 			if (info.vendor_id == cardInfos[idx].VendorId() &&
74 				info.device_id == cardInfos[idx].DeviceId())
75 			{
76 				if (gNumCards == MAX_DEVICES) {
77 					ERROR("Skipped:%s [%#06x:%#06x]\n", cardInfos[idx].Name(),
78 						cardInfos[idx].VendorId(), cardInfos[idx].DeviceId());
79 					break;
80 				}
81 
82 				Device* device = new(std::nothrow) Device(cardInfos[idx], info);
83 				if (device == 0) {
84 					return ENODEV;
85 				}
86 
87 				status_t status = device->InitCheck();
88 				if (status < B_OK) {
89 					delete device;
90 					break;
91 				}
92 
93 				status = device->Setup();
94 				if (status < B_OK) {
95 					delete device;
96 					break;
97 				}
98 
99 				char name[32] = {0};
100 				sprintf(name, "audio/hmulti/%s/%ld",
101 								cardInfos[idx].Name(), gNumCards);
102 				gDeviceNames[gNumCards] = strdup(name);
103 				gDevices[gNumCards++] = device;
104 
105 				TRACE("Found:%s [%#06x:%#06x]\n", cardInfos[idx].Name(),
106 						cardInfos[idx].VendorId(), cardInfos[idx].DeviceId());
107 			}
108 		}
109 	}
110 
111 	if (gNumCards == 0) {
112 		put_module(B_PCI_MODULE_NAME);
113 		return ENODEV;
114 	}
115 
116 	return B_OK;
117 }
118 
119 
120 void
121 uninit_driver()
122 {
123 	for (size_t i = 0; i < MAX_DEVICES; i++) {
124 		if (gDevices[i]) {
125 			delete gDevices[i];
126 			gDevices[i] = NULL;
127 		}
128 
129 		free(gDeviceNames[i]);
130 		gDeviceNames[i] = NULL;
131 	}
132 
133 	put_module(B_PCI_MODULE_NAME);
134 
135 	release_settings();
136 }
137 
138 
139 static status_t
140 SiS7018_open(const char *name, uint32 flags, void **cookie)
141 {
142 	status_t status = ENODEV;
143 	*cookie = NULL;
144 	for (size_t i = 0; i < MAX_DEVICES; i++) {
145 		if (gDeviceNames[i] && !strcmp(gDeviceNames[i], name)) {
146 			status = gDevices[i]->Open(flags);
147 			*cookie = gDevices[i];
148 		}
149 	}
150 
151 	return status;
152 }
153 
154 
155 static status_t
156 SiS7018_read(void *cookie, off_t position, void *buffer, size_t *numBytes)
157 {
158 	Device *device = (Device *)cookie;
159 	return device->Read((uint8 *)buffer, numBytes);
160 }
161 
162 
163 static status_t
164 SiS7018_write(void *cookie, off_t position,
165 							const void *buffer, size_t *numBytes)
166 {
167 	Device *device = (Device *)cookie;
168 	return device->Write((const uint8 *)buffer, numBytes);
169 }
170 
171 
172 static status_t
173 SiS7018_control(void *cookie, uint32 op, void *buffer, size_t length)
174 {
175 	Device *device = (Device *)cookie;
176 	return device->Control(op, buffer, length);
177 }
178 
179 
180 static status_t
181 SiS7018_close(void *cookie)
182 {
183 	Device *device = (Device *)cookie;
184 	return device->Close();
185 }
186 
187 
188 static status_t
189 SiS7018_free(void *cookie)
190 {
191 	Device *device = (Device *)cookie;
192 	return device->Free();
193 }
194 
195 
196 const char **
197 publish_devices()
198 {
199 	for (size_t i = 0; i < MAX_DEVICES; i++) {
200 		if (gDevices[i] == NULL)
201 			continue;
202 
203 		if (gDeviceNames[i])
204 			TRACE("%s\n", gDeviceNames[i]);
205 	}
206 
207 	return (const char **)&gDeviceNames[0];
208 }
209 
210 
211 device_hooks *
212 find_device(const char *name)
213 {
214 	static device_hooks deviceHooks = {
215 		SiS7018_open,
216 		SiS7018_close,
217 		SiS7018_free,
218 		SiS7018_control,
219 		SiS7018_read,
220 		SiS7018_write,
221 		NULL,				// select
222 		NULL				// deselect
223 	};
224 
225 	return &deviceHooks;
226 }
227 
228