1#include <KernelExport.h>
2#include <Drivers.h>
3#include <Errors.h>
4#include <OS.h>
5#include <PCI.h>
6#include <malloc.h>
7#include <string.h>
8#include <stdio.h>
9
10#include "lala.h"
11
12#define MAX_DEVICES 8
13
14int32 			api_version = B_CUR_DRIVER_API_VERSION;
15
16sem_id			drv_sem;
17char *			drv_path[MAX_DEVICES + 1];
18audio_drv_t *	drv_data[MAX_DEVICES];
19int				drv_open_count[MAX_DEVICES];
20void *			drv_cookie[MAX_DEVICES];
21int				drv_count;
22
23pci_module_info *pcimodule;
24
25extern driver_info_t driver_info;
26
27status_t
28init_hardware(void)
29{
30	dprintf("init_hardware\n");
31	return B_OK;
32}
33
34
35status_t
36init_driver(void)
37{
38	struct pci_info info;
39	struct pci_info *pciinfo = &info;
40	int pciindex;
41	int devindex;
42
43	dprintf("init_driver\n");
44	dprintf("driver base name '%s'\n", driver_info.basename);
45
46	if (get_module(B_PCI_MODULE_NAME, (module_info **) &pcimodule) < 0) {
47		return B_ERROR;
48	}
49
50	drv_sem = create_sem(1, "drv_sem");
51
52	drv_count = 0;
53
54	for (pciindex = 0; B_OK == pcimodule->get_nth_pci_info(pciindex, pciinfo); pciindex++) {
55//		dprintf("Checking PCI device, vendor 0x%04x, id 0x%04x, bus 0x%02x, dev 0x%02x, func 0x%02x, rev 0x%02x, api 0x%02x, sub 0x%02x, base 0x%02x\n",
56//			pciinfo->vendor_id, pciinfo->device_id, pciinfo->bus, pciinfo->device, pciinfo->function,
57//			pciinfo->revision, pciinfo->class_api, pciinfo->class_sub, pciinfo->class_base);
58
59		for (devindex = 0; driver_info.pci_id_table[devindex].vendor != 0; devindex++) {
60			if (driver_info.pci_id_table[devindex].vendor != -1 && driver_info.pci_id_table[devindex].vendor != pciinfo->vendor_id)
61				continue;
62			if (driver_info.pci_id_table[devindex].device != -1 && driver_info.pci_id_table[devindex].device != pciinfo->device_id)
63				continue;
64			if (driver_info.pci_id_table[devindex].revision != -1 && driver_info.pci_id_table[devindex].revision != pciinfo->revision)
65				continue;
66			if (driver_info.pci_id_table[devindex].class != -1 && driver_info.pci_id_table[devindex].class != pciinfo->class_base)
67				continue;
68			if (driver_info.pci_id_table[devindex].subclass != -1 && driver_info.pci_id_table[devindex].subclass != pciinfo->class_sub)
69				continue;
70			if (pciinfo->header_type == 0) {
71				if (driver_info.pci_id_table[devindex].subsystem_vendor != -1 && driver_info.pci_id_table[devindex].subsystem_vendor != pciinfo->u.h0.subsystem_vendor_id)
72					continue;
73				if (driver_info.pci_id_table[devindex].subsystem_device != -1 && driver_info.pci_id_table[devindex].subsystem_device != pciinfo->u.h0.subsystem_id)
74					continue;
75			}
76
77			dprintf("found device '%s'\n", driver_info.pci_id_table[devindex].name);
78
79			drv_path[drv_count] = (char *) malloc(strlen(driver_info.basename) + 5);
80			sprintf(drv_path[drv_count], "%s/%d", driver_info.basename, drv_count + 1);
81
82			drv_data[drv_count] = (audio_drv_t *) malloc(sizeof(audio_drv_t));
83			drv_data[drv_count]->pci 		= pcimodule;
84			drv_data[drv_count]->bus		= pciinfo->bus;
85			drv_data[drv_count]->device		= pciinfo->device;
86			drv_data[drv_count]->function	= pciinfo->function;
87			drv_data[drv_count]->name		= driver_info.pci_id_table[devindex].name;
88			drv_data[drv_count]->param		= driver_info.pci_id_table[devindex].param;
89			drv_open_count[drv_count]		= 0;
90
91			drv_count++;
92			break;
93		}
94		if (drv_count == MAX_DEVICES)
95			break;
96	}
97
98	drv_path[drv_count + 1] = NULL;
99
100	return B_OK;
101}
102
103void
104uninit_driver(void)
105{
106	int i;
107	dprintf("uninit_driver\n");
108
109	for (i = 0; i < drv_count; i++) {
110		free(drv_path[i]);
111		free(drv_data[i]);
112	}
113	delete_sem(drv_sem);
114}
115
116static status_t
117driver_open(const char *name, uint32 flags, void** cookie)
118{
119	int index;
120	status_t res;
121
122	acquire_sem(drv_sem);
123
124	for (index = 0; index < drv_count; index++) {
125		if (0 == strcmp(drv_path[index], name))
126			break;
127	}
128	if (index == drv_count) { // name not found
129		release_sem(drv_sem);
130		return B_ERROR;
131	}
132	*cookie = (void *) index;
133
134	if (drv_open_count[index] == 0) {
135		res = driver_info.attach(drv_data[index], &drv_cookie[index]);
136		drv_open_count[index] = (res == B_OK) ? 1 : 0;
137	} else {
138		res = B_OK;
139		drv_open_count[index]++;
140	}
141
142	release_sem(drv_sem);
143
144	return res;
145}
146
147static status_t
148driver_close(void* cookie)
149{
150	dprintf("close\n");
151	return B_OK;
152}
153
154static status_t
155driver_free(void* cookie)
156{
157	int index;
158	status_t res;
159
160	dprintf("free\n");
161
162	index = (int) cookie;
163
164	acquire_sem(drv_sem);
165
166	drv_open_count[index]--;
167
168	if (drv_open_count[index] == 0)
169		res = driver_info.detach(drv_data[index], drv_cookie[index]);
170	else
171		res = B_OK;
172
173	release_sem(drv_sem);
174
175	return res;
176}
177
178static status_t
179driver_control(void* cookie, uint32 op, void* arg, size_t len)
180{
181	return B_OK;
182}
183
184static status_t
185driver_read(void* cookie, off_t position, void *buf, size_t* num_bytes)
186{
187	*num_bytes = 0;
188	return B_IO_ERROR;
189}
190
191static status_t
192driver_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes)
193{
194	*num_bytes = 0;
195	return B_IO_ERROR;
196}
197
198device_hooks driver_hooks = {
199	driver_open,
200	driver_close,
201	driver_free,
202	driver_control,
203	driver_read,
204	driver_write
205};
206
207const char **
208publish_devices(void)
209{
210	dprintf("publish_devices\n");
211	return (const char **) drv_path;
212}
213
214device_hooks*
215find_device(const char* name)
216{
217	dprintf("find_device\n");
218	return &driver_hooks;
219}
220
221