xref: /minix/minix/drivers/bus/pci/main.c (revision 9f988b79)
1 #include <sys/types.h>
2 
3 #include <dev/pci/pciio.h>
4 
5 #include <minix/chardriver.h>
6 #include <minix/driver.h>
7 #include <minix/rs.h>
8 
9 #include "pci.h"
10 
11 int debug = 0;
12 struct pci_acl pci_acl[NR_DRIVERS];
13 
14 /*======================================================================*
15  *				Helpers					*
16  *======================================================================*/
17 static struct rs_pci *
18 find_acl(int endpoint)
19 {
20 	int i;
21 
22 	/* Find ACL entry for caller */
23 	for (i= 0; i<NR_DRIVERS; i++)
24 	{
25 		if (!pci_acl[i].inuse)
26 			continue;
27 		if (pci_acl[i].acl.rsp_endpoint == endpoint)
28 			return &pci_acl[i].acl;
29 	}
30 	return NULL;
31 }
32 
33 static void
34 reply(message *mp, int result)
35 {
36 	int r;
37 	message m;
38 
39 	m.m_type= result;
40 	r= ipc_send(mp->m_source, &m);
41 	if (r != 0)
42 		printf("reply: unable to send to %d: %d\n", mp->m_source, r);
43 }
44 
45 static void
46 do_init(message *mp)
47 {
48 	int r;
49 
50 #if DEBUG
51 	printf("PCI: do_init: called by '%d'\n", mp->m_source);
52 #endif
53 
54 	mp->m_type= 0;
55 	r= ipc_send(mp->m_source, mp);
56 	if (r != 0)
57 		printf("PCI: do_init: unable to send to %d: %d\n",
58 			mp->m_source, r);
59 }
60 
61 static void
62 do_first_dev(message *mp)
63 {
64 	int r, devind;
65 	u16_t vid, did;
66 	struct rs_pci *aclp;
67 
68 	aclp= find_acl(mp->m_source);
69 
70 	if (!aclp && debug)
71 		printf("PCI: do_first_dev: no acl for caller %d\n",
72 			mp->m_source);
73 
74 	r= _pci_first_dev(aclp, &devind, &vid, &did);
75 	if (r == 1)
76 	{
77 		mp->m1_i1= devind;
78 		mp->m1_i2= vid;
79 		mp->m1_i3= did;
80 	}
81 	mp->m_type= r;
82 	r= ipc_send(mp->m_source, mp);
83 	if (r != 0)
84 	{
85 		printf("PCI: do_first_dev: unable to send to %d: %d\n",
86 			mp->m_source, r);
87 	}
88 }
89 
90 static void
91 do_next_dev(message *mp)
92 {
93 	int r, devind;
94 	u16_t vid, did;
95 	struct rs_pci *aclp;
96 
97 	devind= mp->m1_i1;
98 	aclp= find_acl(mp->m_source);
99 
100 	r= _pci_next_dev(aclp, &devind, &vid, &did);
101 	if (r == 1)
102 	{
103 		mp->m1_i1= devind;
104 		mp->m1_i2= vid;
105 		mp->m1_i3= did;
106 	}
107 	mp->m_type= r;
108 	r= ipc_send(mp->m_source, mp);
109 	if (r != 0)
110 	{
111 		printf("PCI: do_next_dev: unable to send to %d: %d\n",
112 			mp->m_source, r);
113 	}
114 }
115 
116 static void
117 do_find_dev(message *mp)
118 {
119 	int r, devind;
120 	u8_t bus, dev, func;
121 
122 	bus= mp->m1_i1;
123 	dev= mp->m1_i2;
124 	func= mp->m1_i3;
125 
126 	r= _pci_find_dev(bus, dev, func, &devind);
127 	if (r == 1)
128 		mp->m1_i1= devind;
129 	mp->m_type= r;
130 	r= ipc_send(mp->m_source, mp);
131 	if (r != 0)
132 	{
133 		printf("PCI: do_find_dev: unable to send to %d: %d\n",
134 			mp->m_source, r);
135 	}
136 }
137 
138 static void
139 do_ids(message *mp)
140 {
141 	int r, devind;
142 	u16_t vid, did;
143 
144 	devind= mp->m1_i1;
145 
146 	r= _pci_ids(devind, &vid, &did);
147 	if (r != OK)
148 	{
149 		printf("pci:do_ids: failed for devind %d: %d\n",
150 			devind, r);
151 	}
152 
153 	mp->m1_i1= vid;
154 	mp->m1_i2= did;
155 	mp->m_type= r;
156 	r= ipc_send(mp->m_source, mp);
157 	if (r != 0)
158 	{
159 		printf("PCI: do_ids: unable to send to %d: %d\n",
160 			mp->m_source, r);
161 	}
162 }
163 
164 static void
165 do_dev_name(message *mp)
166 {
167 	int r, name_len, len;
168 	u16_t vid, did;
169 	cp_grant_id_t name_gid;
170 	const char *name;
171 
172 	vid= mp->m7_i1;
173 	did= mp->m7_i2;
174 	name_len= mp->m7_i3;
175 	name_gid= mp->m7_i4;
176 
177 	name= _pci_dev_name(vid, did);
178 	if (name == NULL)
179 	{
180 		/* No name */
181 		r= ENOENT;
182 	}
183 	else
184 	{
185 		len= strlen(name)+1;
186 		if (len > name_len)
187 			len= name_len;
188 		r= sys_safecopyto(mp->m_source, name_gid, 0, (vir_bytes)name,
189 			len);
190 	}
191 
192 	mp->m_type= r;
193 	r= ipc_send(mp->m_source, mp);
194 	if (r != 0)
195 	{
196 		printf("PCI: do_dev_name: unable to send to %d: %d\n",
197 			mp->m_source, r);
198 	}
199 }
200 
201 static void
202 do_slot_name(message *mp)
203 {
204 	int r, devind, name_len, len;
205 	cp_grant_id_t gid;
206 	char *name;
207 
208 	devind= mp->m1_i1;
209 	name_len= mp->m1_i2;
210 	gid= mp->m1_i3;
211 
212 	r= _pci_slot_name(devind, &name);
213 	if (r != OK)
214 	{
215 		printf("pci:do_slot_name_s: failed for devind %d: %d\n",
216 			devind, r);
217 	}
218 
219 	if (r == OK)
220 	{
221 		len= strlen(name)+1;
222 		if (len > name_len)
223 			len= name_len;
224 		r= sys_safecopyto(mp->m_source, gid, 0,
225 			(vir_bytes)name, len);
226 	}
227 
228 	mp->m_type= r;
229 	r= ipc_send(mp->m_source, mp);
230 	if (r != 0)
231 	{
232 		printf("PCI: do_slot_name: unable to send to %d: %d\n",
233 			mp->m_source, r);
234 	}
235 }
236 
237 static void
238 do_set_acl(message *mp)
239 {
240 	int i, r, gid;
241 
242 	if (mp->m_source != RS_PROC_NR)
243 	{
244 		printf("PCI: do_set_acl: not from RS\n");
245 		reply(mp, EPERM);
246 		return;
247 	}
248 
249 	for (i= 0; i<NR_DRIVERS; i++)
250 	{
251 		if (!pci_acl[i].inuse)
252 			break;
253 	}
254 	if (i >= NR_DRIVERS)
255 	{
256 		printf("PCI: do_set_acl: table is full\n");
257 		reply(mp, ENOMEM);
258 		return;
259 	}
260 
261 	gid= mp->m1_i1;
262 
263 	r= sys_safecopyfrom(mp->m_source, gid, 0, (vir_bytes)&pci_acl[i].acl,
264 		sizeof(pci_acl[i].acl));
265 	if (r != OK)
266 	{
267 		printf("PCI: do_set_acl: safecopyfrom failed\n");
268 		reply(mp, r);
269 		return;
270 	}
271 	pci_acl[i].inuse= 1;
272 	if(debug)
273 	  printf("PCI: do_acl: setting ACL for %d ('%s') at entry %d\n",
274 		pci_acl[i].acl.rsp_endpoint, pci_acl[i].acl.rsp_label,
275 		i);
276 
277 	reply(mp, OK);
278 }
279 
280 static void
281 do_del_acl(message *mp)
282 {
283 	int i, proc_nr;
284 
285 	if (mp->m_source != RS_PROC_NR)
286 	{
287 		printf("do_del_acl: not from RS\n");
288 		reply(mp, EPERM);
289 		return;
290 	}
291 
292 	proc_nr= mp->m1_i1;
293 
294 	for (i= 0; i<NR_DRIVERS; i++)
295 	{
296 		if (!pci_acl[i].inuse)
297 			continue;
298 		if (pci_acl[i].acl.rsp_endpoint == proc_nr)
299 			break;
300 	}
301 
302 	if (i >= NR_DRIVERS)
303 	{
304 		printf("do_del_acl: nothing found for %d\n", proc_nr);
305 		reply(mp, EINVAL);
306 		return;
307 	}
308 
309 	pci_acl[i].inuse= 0;
310 #if 0
311 	printf("do_acl: deleting ACL for %d ('%s') at entry %d\n",
312 		pci_acl[i].acl.rsp_endpoint, pci_acl[i].acl.rsp_label, i);
313 #endif
314 
315 	/* Also release all devices held by this process */
316 	_pci_release(proc_nr);
317 
318 	reply(mp, OK);
319 }
320 
321 static void
322 do_reserve(message *mp)
323 {
324 	struct rs_pci *aclp;
325 	int r, devind;
326 
327 	devind= mp->m1_i1;
328 
329 	aclp= find_acl(mp->m_source);
330 
331 	mp->m_type= _pci_reserve(devind, mp->m_source, aclp);
332 	r= ipc_send(mp->m_source, mp);
333 	if (r != 0)
334 	{
335 		printf("do_reserve: unable to send to %d: %d\n",
336 			mp->m_source, r);
337 	}
338 }
339 
340 static void
341 do_attr_r8(message *mp)
342 {
343 	int r, devind, port;
344 	u8_t v;
345 
346 	devind= mp->m2_i1;
347 	port= mp->m2_i2;
348 
349 	r= _pci_attr_r8(devind, port, &v);
350 	if (r != OK)
351 	{
352 		printf(
353 		"pci:do_attr_r8: pci_attr_r8(%d, %d, ...) failed: %d\n",
354 			devind, port, r);
355 	}
356 	mp->m2_l1= v;
357 	mp->m_type= r;
358 	r= ipc_send(mp->m_source, mp);
359 	if (r != 0)
360 	{
361 		printf("do_attr_r8: unable to send to %d: %d\n",
362 			mp->m_source, r);
363 	}
364 }
365 
366 static void
367 do_attr_r16(message *mp)
368 {
369 	int r, devind, port;
370 	u16_t v;
371 
372 	devind= mp->m2_i1;
373 	port= mp->m2_i2;
374 
375 	r= _pci_attr_r16(devind, port, &v);
376 	if (r != OK)
377 	{
378 		printf(
379 		"pci:do_attr_r16: pci_attr_r16(%d, %d, ...) failed: %d\n",
380 			devind, port, r);
381 	}
382 	mp->m2_l1= v;
383 	mp->m_type= OK;
384 	r= ipc_send(mp->m_source, mp);
385 	if (r != 0)
386 	{
387 		printf("do_attr_r16: unable to send to %d: %d\n",
388 			mp->m_source, r);
389 	}
390 }
391 
392 static void
393 do_attr_r32(message *mp)
394 {
395 	int r, devind, port;
396 	u32_t v;
397 
398 	devind= mp->m2_i1;
399 	port= mp->m2_i2;
400 
401 	r= _pci_attr_r32(devind, port, &v);
402 	if (r != OK)
403 	{
404 		printf(
405 		"pci:do_attr_r32: pci_attr_r32(%d, %d, ...) failed: %d\n",
406 			devind, port, r);
407 	}
408 	mp->m2_l1= v;
409 	mp->m_type= OK;
410 	r= ipc_send(mp->m_source, mp);
411 	if (r != 0)
412 	{
413 		printf("do_attr_r32: unable to send to %d: %d\n",
414 			mp->m_source, r);
415 	}
416 }
417 
418 static void
419 do_attr_w8(message *mp)
420 {
421 	int r, devind, port;
422 	u8_t v;
423 
424 	devind= mp->m2_i1;
425 	port= mp->m2_i2;
426 	v= mp->m2_l1;
427 
428 	_pci_attr_w8(devind, port, v);
429 	mp->m_type= OK;
430 	r= ipc_send(mp->m_source, mp);
431 	if (r != 0)
432 	{
433 		printf("do_attr_w8: unable to send to %d: %d\n",
434 			mp->m_source, r);
435 	}
436 }
437 
438 static void
439 do_attr_w16(message *mp)
440 {
441 	int r, devind, port;
442 	u16_t v;
443 
444 	devind= mp->m2_i1;
445 	port= mp->m2_i2;
446 	v= mp->m2_l1;
447 
448 	_pci_attr_w16(devind, port, v);
449 	mp->m_type= OK;
450 	r= ipc_send(mp->m_source, mp);
451 	if (r != 0)
452 	{
453 		printf("do_attr_w16: unable to send to %d: %d\n",
454 			mp->m_source, r);
455 	}
456 }
457 
458 static void
459 do_attr_w32(message *mp)
460 {
461 	int r, devind, port;
462 	u32_t v;
463 
464 	devind= mp->m2_i1;
465 	port= mp->m2_i2;
466 	v= mp->m2_l1;
467 
468 	_pci_attr_w32(devind, port, v);
469 	mp->m_type= OK;
470 	r= ipc_send(mp->m_source, mp);
471 	if (r != 0)
472 	{
473 		printf("do_attr_w32: unable to send to %d: %d\n",
474 			mp->m_source, r);
475 	}
476 }
477 
478 static void
479 do_get_bar(message *mp)
480 {
481 	int r, devind, port, ioflag;
482 	u32_t base, size;
483 
484 	devind= mp->m_lsys_pci_busc_get_bar.devind;
485 	port= mp->m_lsys_pci_busc_get_bar.port;
486 
487 	mp->m_type= _pci_get_bar(devind, port, &base, &size, &ioflag);
488 
489 	if (mp->m_type == OK)
490 	{
491 		mp->m_pci_lsys_busc_get_bar.base= base;
492 		mp->m_pci_lsys_busc_get_bar.size= size;
493 		mp->m_pci_lsys_busc_get_bar.flags= ioflag;
494 	}
495 
496 	r= ipc_send(mp->m_source, mp);
497 	if (r != 0)
498 	{
499 		printf("do_get_bar: unable to send to %d: %d\n",
500 			mp->m_source, r);
501 	}
502 }
503 
504 static void
505 do_rescan_bus(message *mp)
506 {
507 	int r, busnr;
508 
509 	busnr= mp->m2_i1;
510 
511 	_pci_rescan_bus(busnr);
512 	mp->m_type= OK;
513 	r= ipc_send(mp->m_source, mp);
514 	if (r != 0)
515 	{
516 		printf("do_rescan_bus: unable to send to %d: %d\n",
517 			mp->m_source, r);
518 	}
519 }
520 
521 /*======================================================================*
522  *			CharDriver Callbacks				*
523  *======================================================================*/
524 static int
525 pci_open(devminor_t UNUSED(minor), int UNUSED(access),
526 	endpoint_t UNUSED(user_endpt))
527 {
528 	return OK;
529 }
530 
531 static int
532 pci_close(devminor_t UNUSED(minor))
533 {
534 	return OK;
535 }
536 
537 static int
538 pci_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
539 	cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id)
540 {
541 	int devind;
542 	int r = ENOTTY;
543 
544 	switch(request)
545 	{
546 	case PCI_IOC_BDF_CFGREAD:
547 	{
548 		struct pciio_bdf_cfgreg bdf;
549 
550 		if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&bdf,
551 				sizeof(bdf))) != OK)
552 			break;
553 
554 		r = _pci_find_dev(bdf.bus, bdf.device, bdf.function, &devind);
555 		if (r != 1) {
556 			r = EINVAL;
557 			break;
558 		}
559 
560 		if ((r = _pci_attr_r32(devind, bdf.cfgreg.reg,
561 					&bdf.cfgreg.val)) != OK)
562 			break;
563 
564 		r = sys_safecopyto(endpt, grant, 0, (vir_bytes)&bdf,
565 			sizeof(bdf));
566 		break;
567 	}
568 	case PCI_IOC_BDF_CFGWRITE:
569 	{
570 		struct pciio_bdf_cfgreg bdf;
571 
572 		if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&bdf,
573 				sizeof(bdf))) != OK)
574 			break;
575 
576 		r = _pci_find_dev(bdf.bus, bdf.device, bdf.function, &devind);
577 		if (r != 1) {
578 			r = EINVAL;
579 			break;
580 		}
581 
582 		_pci_attr_w32(devind, bdf.cfgreg.reg, bdf.cfgreg.val);
583 		r = OK;
584 		break;
585 	}
586 	case PCI_IOC_BUSINFO:
587 		break;
588 	case PCI_IOC_MAP:
589 	{
590 		struct pciio_map map;
591 		struct minix_mem_range mr;
592 
593 		if ((r = sys_safecopyfrom(endpt, grant, 0,
594 				(vir_bytes)&map, sizeof(map))) != OK)
595 			break;
596 
597 #if 1
598 		mr.mr_base = map.phys_offset;
599 		mr.mr_limit = map.phys_offset + map.size - 1;
600 
601 		r = sys_privctl(user_endpt, SYS_PRIV_ADD_MEM, &mr);
602 		if (r != OK)
603 		{
604 			break;
605 		}
606 #endif
607 
608 		map.vaddr_ret = vm_map_phys(user_endpt,
609 			(void *)map.phys_offset, map.size);
610 		r = sys_safecopyto(endpt, grant, 0, (vir_bytes)&map,
611 			sizeof(map));
612 		break;
613 	}
614 	case PCI_IOC_UNMAP:
615 	{
616 		struct pciio_map map;
617 
618 		if ((r = sys_safecopyfrom(endpt, grant, 0,
619 				(vir_bytes)&map, sizeof(map))) != OK)
620 			break;
621 
622 		r = vm_unmap_phys(user_endpt, map.vaddr, map.size);
623 		break;
624 	}
625 	case PCI_IOC_RESERVE:
626 	{
627 		struct pciio_acl acl;
628 
629 		if ((r = sys_safecopyfrom(endpt, grant, 0,
630 				(vir_bytes)&acl, sizeof(acl))) != OK)
631 			break;
632 
633 		r = _pci_find_dev(acl.bus, acl.device, acl.function, &devind);
634 		if (r != 1) {
635 			r = EINVAL;
636 			break;
637 		}
638 
639 		r = _pci_grant_access(devind, user_endpt);
640 		break;
641 	}
642 	case PCI_IOC_RELEASE:
643 	{
644 		struct pciio_acl acl;
645 
646 		if ((r = sys_safecopyfrom(endpt, grant, 0,
647 				(vir_bytes)&acl, sizeof(acl))) != OK)
648 			break;
649 
650 		r = _pci_find_dev(acl.bus, acl.device, acl.function, &devind);
651 		if (r != 1) {
652 			r = EINVAL;
653 			break;
654 		}
655 
656 		_pci_release(endpt);
657 		r = OK;
658 
659 		break;
660 	}
661 	case PCI_IOC_CFGREAD:
662 	case PCI_IOC_CFGWRITE:
663 	default:
664 		r = ENOTTY;
665 	}
666 	return r;
667 }
668 
669 static void
670 pci_other(message *m, int ipc_status)
671 {
672 	switch(m->m_type)
673 	{
674 	case BUSC_PCI_INIT: do_init(m); break;
675 	case BUSC_PCI_FIRST_DEV: do_first_dev(m); break;
676 	case BUSC_PCI_NEXT_DEV: do_next_dev(m); break;
677 	case BUSC_PCI_FIND_DEV: do_find_dev(m); break;
678 	case BUSC_PCI_IDS: do_ids(m); break;
679 	case BUSC_PCI_RESERVE: do_reserve(m); break;
680 	case BUSC_PCI_ATTR_R8: do_attr_r8(m); break;
681 	case BUSC_PCI_ATTR_R16: do_attr_r16(m); break;
682 	case BUSC_PCI_ATTR_R32: do_attr_r32(m); break;
683 	case BUSC_PCI_ATTR_W8: do_attr_w8(m); break;
684 	case BUSC_PCI_ATTR_W16: do_attr_w16(m); break;
685 	case BUSC_PCI_ATTR_W32: do_attr_w32(m); break;
686 	case BUSC_PCI_RESCAN: do_rescan_bus(m); break;
687 	case BUSC_PCI_DEV_NAME_S: do_dev_name(m); break;
688 	case BUSC_PCI_SLOT_NAME_S: do_slot_name(m); break;
689 	case BUSC_PCI_SET_ACL: do_set_acl(m); break;
690 	case BUSC_PCI_DEL_ACL: do_del_acl(m); break;
691 	case BUSC_PCI_GET_BAR: do_get_bar(m); break;
692 	default:
693 		printf("PCI: unhandled message from %d, type %d\n",
694 			m->m_source, m->m_type);
695 		break;
696 	}
697 }
698 
699 static struct chardriver driver =
700 {
701 	.cdr_open	= pci_open,
702 	.cdr_close	= pci_close,
703 	.cdr_ioctl	= pci_ioctl,
704 	.cdr_other	= pci_other,
705 };
706 
707 /*======================================================================*
708  *			SEF Callbacks					*
709  *======================================================================*/
710 /* NOTE: sef_cb_init is in pci.c. */
711 static void
712 sef_local_startup(void)
713 {
714 	/*
715 	 * Register init callbacks. Use the same function for all event types
716 	 */
717 	sef_setcb_init_fresh(sef_cb_init);
718 	sef_setcb_init_restart(sef_cb_init);
719 
720 	/* Let SEF perform startup. */
721 	sef_startup();
722 }
723 
724 /*======================================================================*
725  *				main					*
726  *======================================================================*/
727 int
728 main(void)
729 {
730 	/*
731 	 * Perform initialization.
732 	 */
733 	sef_local_startup();
734 
735 	/*
736 	 * Run the main loop.
737 	 */
738 	chardriver_task(&driver);
739 	return OK;
740 }
741