xref: /minix/minix/drivers/bus/pci/main.c (revision 7f5f010b)
1 /*
2 main.c
3 */
4 
5 #include "pci.h"
6 
7 struct pci_acl pci_acl[NR_DRIVERS];
8 
9 static void do_init(message *mp);
10 static void do_first_dev(message *mp);
11 static void do_next_dev(message *mp);
12 static void do_find_dev(message *mp);
13 static void do_ids(message *mp);
14 static void do_dev_name_s(message *mp);
15 static void do_slot_name_s(message *mp);
16 static void do_set_acl(message *mp);
17 static void do_del_acl(message *mp);
18 static void do_reserve(message *mp);
19 static void do_attr_r8(message *mp);
20 static void do_attr_r16(message *mp);
21 static void do_attr_r32(message *mp);
22 static void do_attr_w8(message *mp);
23 static void do_attr_w16(message *mp);
24 static void do_attr_w32(message *mp);
25 static void do_get_bar(message *mp);
26 static void do_rescan_bus(message *mp);
27 static void reply(message *mp, int result);
28 static struct rs_pci *find_acl(int endpoint);
29 
30 extern int debug;
31 
32 /* SEF functions and variables. */
33 static void sef_local_startup(void);
34 
35 int main(void)
36 {
37 	int r;
38 	message m;
39 	int ipc_status;
40 
41 	/* SEF local startup. */
42 	sef_local_startup();
43 
44 	for(;;)
45 	{
46 		r= driver_receive(ANY, &m, &ipc_status);
47 		if (r < 0)
48 		{
49 			printf("PCI: driver_receive failed: %d\n", r);
50 			break;
51 		}
52 
53 		if (is_ipc_notify(ipc_status)) {
54 			printf("PCI: got notify from %d\n", m.m_source);
55 
56 			/* done, get a new message */
57 			continue;
58 		}
59 
60 		switch(m.m_type)
61 		{
62 		case BUSC_PCI_INIT: do_init(&m); break;
63 		case BUSC_PCI_FIRST_DEV: do_first_dev(&m); break;
64 		case BUSC_PCI_NEXT_DEV: do_next_dev(&m); break;
65 		case BUSC_PCI_FIND_DEV: do_find_dev(&m); break;
66 		case BUSC_PCI_IDS: do_ids(&m); break;
67 		case BUSC_PCI_RESERVE: do_reserve(&m); break;
68 		case BUSC_PCI_ATTR_R8: do_attr_r8(&m); break;
69 		case BUSC_PCI_ATTR_R16: do_attr_r16(&m); break;
70 		case BUSC_PCI_ATTR_R32: do_attr_r32(&m); break;
71 		case BUSC_PCI_ATTR_W8: do_attr_w8(&m); break;
72 		case BUSC_PCI_ATTR_W16: do_attr_w16(&m); break;
73 		case BUSC_PCI_ATTR_W32: do_attr_w32(&m); break;
74 		case BUSC_PCI_RESCAN: do_rescan_bus(&m); break;
75 		case BUSC_PCI_DEV_NAME_S: do_dev_name_s(&m); break;
76 		case BUSC_PCI_SLOT_NAME_S: do_slot_name_s(&m); break;
77 		case BUSC_PCI_SET_ACL: do_set_acl(&m); break;
78 		case BUSC_PCI_DEL_ACL: do_del_acl(&m); break;
79 		case BUSC_PCI_GET_BAR: do_get_bar(&m); break;
80 		default:
81 			printf("PCI: got message from %d, type %d\n",
82 				m.m_source, m.m_type);
83 			break;
84 		}
85 	}
86 
87 	return 0;
88 }
89 
90 /*===========================================================================*
91  *			       sef_local_startup			     *
92  *===========================================================================*/
93 static void sef_local_startup()
94 {
95   /* Register init callbacks. */
96   sef_setcb_init_fresh(sef_cb_init_fresh);
97   sef_setcb_init_lu(sef_cb_init_fresh);
98   sef_setcb_init_restart(sef_cb_init_fresh);
99 
100   /* Register live update callbacks. */
101   sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
102   sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
103 
104   /* Let SEF perform startup. */
105   sef_startup();
106 }
107 
108 static void do_init(mp)
109 message *mp;
110 {
111 	int r;
112 
113 #if DEBUG
114 	printf("PCI: do_init: called by '%d'\n", mp->m_source);
115 #endif
116 
117 	mp->m_type= 0;
118 	r= ipc_send(mp->m_source, mp);
119 	if (r != 0)
120 		printf("PCI: do_init: unable to send to %d: %d\n",
121 			mp->m_source, r);
122 }
123 
124 static void do_first_dev(message *mp)
125 {
126 	int r, devind;
127 	u16_t vid, did;
128 	struct rs_pci *aclp;
129 
130 	aclp= find_acl(mp->m_source);
131 
132 	if (!aclp && debug)
133 		printf("PCI: do_first_dev: no acl for caller %d\n",
134 			mp->m_source);
135 
136 	r= pci_first_dev_a(aclp, &devind, &vid, &did);
137 	if (r == 1)
138 	{
139 		mp->m1_i1= devind;
140 		mp->m1_i2= vid;
141 		mp->m1_i3= did;
142 	}
143 	mp->m_type= r;
144 	r= ipc_send(mp->m_source, mp);
145 	if (r != 0)
146 	{
147 		printf("PCI: do_first_dev: unable to send to %d: %d\n",
148 			mp->m_source, r);
149 	}
150 }
151 
152 static void do_next_dev(message *mp)
153 {
154 	int r, devind;
155 	u16_t vid, did;
156 	struct rs_pci *aclp;
157 
158 	devind= mp->m1_i1;
159 	aclp= find_acl(mp->m_source);
160 
161 	r= pci_next_dev_a(aclp, &devind, &vid, &did);
162 	if (r == 1)
163 	{
164 		mp->m1_i1= devind;
165 		mp->m1_i2= vid;
166 		mp->m1_i3= did;
167 	}
168 	mp->m_type= r;
169 	r= ipc_send(mp->m_source, mp);
170 	if (r != 0)
171 	{
172 		printf("PCI: do_next_dev: unable to send to %d: %d\n",
173 			mp->m_source, r);
174 	}
175 }
176 
177 static void do_find_dev(mp)
178 message *mp;
179 {
180 	int r, devind;
181 	u8_t bus, dev, func;
182 
183 	bus= mp->m1_i1;
184 	dev= mp->m1_i2;
185 	func= mp->m1_i3;
186 
187 	r= pci_find_dev(bus, dev, func, &devind);
188 	if (r == 1)
189 		mp->m1_i1= devind;
190 	mp->m_type= r;
191 	r= ipc_send(mp->m_source, mp);
192 	if (r != 0)
193 	{
194 		printf("PCI: do_find_dev: unable to send to %d: %d\n",
195 			mp->m_source, r);
196 	}
197 }
198 
199 static void do_ids(mp)
200 message *mp;
201 {
202 	int r, devind;
203 	u16_t vid, did;
204 
205 	devind= mp->m1_i1;
206 
207 	r= pci_ids_s(devind, &vid, &did);
208 	if (r != OK)
209 	{
210 		printf("pci:do_ids: failed for devind %d: %d\n",
211 			devind, r);
212 	}
213 
214 	mp->m1_i1= vid;
215 	mp->m1_i2= did;
216 	mp->m_type= r;
217 	r= ipc_send(mp->m_source, mp);
218 	if (r != 0)
219 	{
220 		printf("PCI: do_ids: unable to send to %d: %d\n",
221 			mp->m_source, r);
222 	}
223 }
224 
225 static void do_dev_name_s(mp)
226 message *mp;
227 {
228 	int r, name_len, len;
229 	u16_t vid, did;
230 	cp_grant_id_t name_gid;
231 	char *name;
232 
233 	vid= mp->m7_i1;
234 	did= mp->m7_i2;
235 	name_len= mp->m7_i3;
236 	name_gid= mp->m7_i4;
237 
238 	name= pci_dev_name(vid, did);
239 	if (name == NULL)
240 	{
241 		/* No name */
242 		r= ENOENT;
243 	}
244 	else
245 	{
246 		len= strlen(name)+1;
247 		if (len > name_len)
248 			len= name_len;
249 		r= sys_safecopyto(mp->m_source, name_gid, 0, (vir_bytes)name,
250 			len);
251 	}
252 
253 	mp->m_type= r;
254 	r= ipc_send(mp->m_source, mp);
255 	if (r != 0)
256 	{
257 		printf("PCI: do_dev_name: unable to send to %d: %d\n",
258 			mp->m_source, r);
259 	}
260 }
261 
262 static void do_slot_name_s(mp)
263 message *mp;
264 {
265 	int r, devind, name_len, len;
266 	cp_grant_id_t gid;
267 	char *name;
268 
269 	devind= mp->m1_i1;
270 	name_len= mp->m1_i2;
271 	gid= mp->m1_i3;
272 
273 	r= pci_slot_name_s(devind, &name);
274 	if (r != OK)
275 	{
276 		printf("pci:do_slot_name_s: failed for devind %d: %d\n",
277 			devind, r);
278 	}
279 
280 	if (r == OK)
281 	{
282 		len= strlen(name)+1;
283 		if (len > name_len)
284 			len= name_len;
285 		r= sys_safecopyto(mp->m_source, gid, 0,
286 			(vir_bytes)name, len);
287 	}
288 
289 	mp->m_type= r;
290 	r= ipc_send(mp->m_source, mp);
291 	if (r != 0)
292 	{
293 		printf("PCI: do_slot_name: unable to send to %d: %d\n",
294 			mp->m_source, r);
295 	}
296 }
297 
298 static void do_set_acl(mp)
299 message *mp;
300 {
301 	int i, r, gid;
302 
303 	if (mp->m_source != RS_PROC_NR)
304 	{
305 		printf("PCI: do_set_acl: not from RS\n");
306 		reply(mp, EPERM);
307 		return;
308 	}
309 
310 	for (i= 0; i<NR_DRIVERS; i++)
311 	{
312 		if (!pci_acl[i].inuse)
313 			break;
314 	}
315 	if (i >= NR_DRIVERS)
316 	{
317 		printf("PCI: do_set_acl: table is full\n");
318 		reply(mp, ENOMEM);
319 		return;
320 	}
321 
322 	gid= mp->m1_i1;
323 
324 	r= sys_safecopyfrom(mp->m_source, gid, 0, (vir_bytes)&pci_acl[i].acl,
325 		sizeof(pci_acl[i].acl));
326 	if (r != OK)
327 	{
328 		printf("PCI: do_set_acl: safecopyfrom failed\n");
329 		reply(mp, r);
330 		return;
331 	}
332 	pci_acl[i].inuse= 1;
333 	if(debug)
334 	  printf("PCI: do_acl: setting ACL for %d ('%s') at entry %d\n",
335 		pci_acl[i].acl.rsp_endpoint, pci_acl[i].acl.rsp_label,
336 		i);
337 
338 	reply(mp, OK);
339 }
340 
341 static void do_del_acl(message *mp)
342 {
343 	int i, proc_nr;
344 
345 	if (mp->m_source != RS_PROC_NR)
346 	{
347 		printf("do_del_acl: not from RS\n");
348 		reply(mp, EPERM);
349 		return;
350 	}
351 
352 	proc_nr= mp->m1_i1;
353 
354 	for (i= 0; i<NR_DRIVERS; i++)
355 	{
356 		if (!pci_acl[i].inuse)
357 			continue;
358 		if (pci_acl[i].acl.rsp_endpoint == proc_nr)
359 			break;
360 	}
361 
362 	if (i >= NR_DRIVERS)
363 	{
364 		printf("do_del_acl: nothing found for %d\n", proc_nr);
365 		reply(mp, EINVAL);
366 		return;
367 	}
368 
369 	pci_acl[i].inuse= 0;
370 #if 0
371 	printf("do_acl: deleting ACL for %d ('%s') at entry %d\n",
372 		pci_acl[i].acl.rsp_endpoint, pci_acl[i].acl.rsp_label, i);
373 #endif
374 
375 	/* Also release all devices held by this process */
376 	pci_release(proc_nr);
377 
378 	reply(mp, OK);
379 }
380 
381 static void do_reserve(message *mp)
382 {
383 	struct rs_pci *aclp;
384 	int r, devind;
385 
386 	devind= mp->m1_i1;
387 
388 	aclp= find_acl(mp->m_source);
389 
390 	mp->m_type= pci_reserve_a(devind, mp->m_source, aclp);
391 	r= ipc_send(mp->m_source, mp);
392 	if (r != 0)
393 	{
394 		printf("do_reserve: unable to send to %d: %d\n",
395 			mp->m_source, r);
396 	}
397 }
398 
399 static void do_attr_r8(mp)
400 message *mp;
401 {
402 	int r, devind, port;
403 	u8_t v;
404 
405 	devind= mp->m2_i1;
406 	port= mp->m2_i2;
407 
408 	r= pci_attr_r8_s(devind, port, &v);
409 	if (r != OK)
410 	{
411 		printf(
412 		"pci:do_attr_r8: pci_attr_r8_s(%d, %d, ...) failed: %d\n",
413 			devind, port, r);
414 	}
415 	mp->m2_l1= v;
416 	mp->m_type= r;
417 	r= ipc_send(mp->m_source, mp);
418 	if (r != 0)
419 	{
420 		printf("do_attr_r8: unable to send to %d: %d\n",
421 			mp->m_source, r);
422 	}
423 }
424 
425 static void do_attr_r16(mp)
426 message *mp;
427 {
428 	int r, devind, port;
429 	u32_t v;
430 
431 	devind= mp->m2_i1;
432 	port= mp->m2_i2;
433 
434 	v= pci_attr_r16(devind, port);
435 	mp->m2_l1= v;
436 	mp->m_type= OK;
437 	r= ipc_send(mp->m_source, mp);
438 	if (r != 0)
439 	{
440 		printf("do_attr_r16: unable to send to %d: %d\n",
441 			mp->m_source, r);
442 	}
443 }
444 
445 static void do_attr_r32(mp)
446 message *mp;
447 {
448 	int r, devind, port;
449 	u32_t v;
450 
451 	devind= mp->m2_i1;
452 	port= mp->m2_i2;
453 
454 	r= pci_attr_r32_s(devind, port, &v);
455 	if (r != OK)
456 	{
457 		printf(
458 		"pci:do_attr_r32: pci_attr_r32_s(%d, %d, ...) failed: %d\n",
459 			devind, port, r);
460 	}
461 	mp->m2_l1= v;
462 	mp->m_type= OK;
463 	r= ipc_send(mp->m_source, mp);
464 	if (r != 0)
465 	{
466 		printf("do_attr_r32: unable to send to %d: %d\n",
467 			mp->m_source, r);
468 	}
469 }
470 
471 static void do_attr_w8(mp)
472 message *mp;
473 {
474 	int r, devind, port;
475 	u8_t v;
476 
477 	devind= mp->m2_i1;
478 	port= mp->m2_i2;
479 	v= mp->m2_l1;
480 
481 	pci_attr_w8(devind, port, v);
482 	mp->m_type= OK;
483 	r= ipc_send(mp->m_source, mp);
484 	if (r != 0)
485 	{
486 		printf("do_attr_w8: unable to send to %d: %d\n",
487 			mp->m_source, r);
488 	}
489 }
490 
491 static void do_attr_w16(mp)
492 message *mp;
493 {
494 	int r, devind, port;
495 	u16_t v;
496 
497 	devind= mp->m2_i1;
498 	port= mp->m2_i2;
499 	v= mp->m2_l1;
500 
501 	pci_attr_w16(devind, port, v);
502 	mp->m_type= OK;
503 	r= ipc_send(mp->m_source, mp);
504 	if (r != 0)
505 	{
506 		printf("do_attr_w16: unable to send to %d: %d\n",
507 			mp->m_source, r);
508 	}
509 }
510 
511 static void do_attr_w32(mp)
512 message *mp;
513 {
514 	int r, devind, port;
515 	u32_t v;
516 
517 	devind= mp->m2_i1;
518 	port= mp->m2_i2;
519 	v= mp->m2_l1;
520 
521 	pci_attr_w32(devind, port, v);
522 	mp->m_type= OK;
523 	r= ipc_send(mp->m_source, mp);
524 	if (r != 0)
525 	{
526 		printf("do_attr_w32: unable to send to %d: %d\n",
527 			mp->m_source, r);
528 	}
529 }
530 
531 static void do_get_bar(mp)
532 message *mp;
533 {
534 	int r, devind, port, ioflag;
535 	u32_t base, size;
536 
537 	devind= mp->m_lsys_pci_busc_get_bar.devind;
538 	port= mp->m_lsys_pci_busc_get_bar.port;
539 
540 	mp->m_type= pci_get_bar_s(devind, port, &base, &size, &ioflag);
541 
542 	if (mp->m_type == OK)
543 	{
544 		mp->m_pci_lsys_busc_get_bar.base= base;
545 		mp->m_pci_lsys_busc_get_bar.size= size;
546 		mp->m_pci_lsys_busc_get_bar.flags= ioflag;
547 	}
548 
549 	r= ipc_send(mp->m_source, mp);
550 	if (r != 0)
551 	{
552 		printf("do_get_bar: unable to send to %d: %d\n",
553 			mp->m_source, r);
554 	}
555 }
556 
557 static void do_rescan_bus(mp)
558 message *mp;
559 {
560 	int r, busnr;
561 
562 	busnr= mp->m2_i1;
563 
564 	pci_rescan_bus(busnr);
565 	mp->m_type= OK;
566 	r= ipc_send(mp->m_source, mp);
567 	if (r != 0)
568 	{
569 		printf("do_rescan_bus: unable to send to %d: %d\n",
570 			mp->m_source, r);
571 	}
572 }
573 
574 
575 static void reply(mp, result)
576 message *mp;
577 int result;
578 {
579 	int r;
580 	message m;
581 
582 	m.m_type= result;
583 	r= ipc_send(mp->m_source, &m);
584 	if (r != 0)
585 		printf("reply: unable to send to %d: %d\n", mp->m_source, r);
586 }
587 
588 
589 static struct rs_pci *find_acl(endpoint)
590 int endpoint;
591 {
592 	int i;
593 
594 	/* Find ACL entry for caller */
595 	for (i= 0; i<NR_DRIVERS; i++)
596 	{
597 		if (!pci_acl[i].inuse)
598 			continue;
599 		if (pci_acl[i].acl.rsp_endpoint == endpoint)
600 			return &pci_acl[i].acl;
601 	}
602 	return NULL;
603 }
604