etc/services - sync with NetBSD-8
[minix.git] / minix / drivers / bus / pci / main.c
bloba21080a627b49748b1b995a039162db5ead33ae2
1 #include <sys/types.h>
3 #include <dev/pci/pciio.h>
5 #include <minix/chardriver.h>
6 #include <minix/driver.h>
7 #include <minix/rs.h>
9 #include "pci.h"
11 int debug = 0;
12 struct pci_acl pci_acl[NR_DRIVERS];
14 /*======================================================================*
15 * Helpers *
16 *======================================================================*/
17 static struct rs_pci *
18 find_acl(int endpoint)
20 int i;
22 /* Find ACL entry for caller */
23 for (i= 0; i<NR_DRIVERS; i++)
25 if (!pci_acl[i].inuse)
26 continue;
27 if (pci_acl[i].acl.rsp_endpoint == endpoint)
28 return &pci_acl[i].acl;
30 return NULL;
33 static void
34 reply(message *mp, int result)
36 int r;
37 message m;
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);
45 static void
46 do_init(message *mp)
48 int r;
50 #if DEBUG
51 printf("PCI: do_init: called by '%d'\n", mp->m_source);
52 #endif
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);
61 static void
62 do_first_dev(message *mp)
64 int r, devind;
65 u16_t vid, did;
66 struct rs_pci *aclp;
68 aclp= find_acl(mp->m_source);
70 if (!aclp && debug)
71 printf("PCI: do_first_dev: no acl for caller %d\n",
72 mp->m_source);
74 r= _pci_first_dev(aclp, &devind, &vid, &did);
75 if (r == 1)
77 mp->m1_i1= devind;
78 mp->m1_i2= vid;
79 mp->m1_i3= did;
81 mp->m_type= r;
82 r= ipc_send(mp->m_source, mp);
83 if (r != 0)
85 printf("PCI: do_first_dev: unable to send to %d: %d\n",
86 mp->m_source, r);
90 static void
91 do_next_dev(message *mp)
93 int r, devind;
94 u16_t vid, did;
95 struct rs_pci *aclp;
97 devind= mp->m1_i1;
98 aclp= find_acl(mp->m_source);
100 r= _pci_next_dev(aclp, &devind, &vid, &did);
101 if (r == 1)
103 mp->m1_i1= devind;
104 mp->m1_i2= vid;
105 mp->m1_i3= did;
107 mp->m_type= r;
108 r= ipc_send(mp->m_source, mp);
109 if (r != 0)
111 printf("PCI: do_next_dev: unable to send to %d: %d\n",
112 mp->m_source, r);
116 static void
117 do_find_dev(message *mp)
119 int r, devind;
120 u8_t bus, dev, func;
122 bus= mp->m1_i1;
123 dev= mp->m1_i2;
124 func= mp->m1_i3;
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)
133 printf("PCI: do_find_dev: unable to send to %d: %d\n",
134 mp->m_source, r);
138 static void
139 do_ids(message *mp)
141 int r, devind;
142 u16_t vid, did;
144 devind= mp->m1_i1;
146 r= _pci_ids(devind, &vid, &did);
147 if (r != OK)
149 printf("pci:do_ids: failed for devind %d: %d\n",
150 devind, r);
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)
159 printf("PCI: do_ids: unable to send to %d: %d\n",
160 mp->m_source, r);
164 static void
165 do_dev_name(message *mp)
167 int r, name_len, len;
168 u16_t vid, did;
169 cp_grant_id_t name_gid;
170 const char *name;
172 vid= mp->m7_i1;
173 did= mp->m7_i2;
174 name_len= mp->m7_i3;
175 name_gid= mp->m7_i4;
177 name= _pci_dev_name(vid, did);
178 if (name == NULL)
180 /* No name */
181 r= ENOENT;
183 else
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);
192 mp->m_type= r;
193 r= ipc_send(mp->m_source, mp);
194 if (r != 0)
196 printf("PCI: do_dev_name: unable to send to %d: %d\n",
197 mp->m_source, r);
201 static void
202 do_slot_name(message *mp)
204 int r, devind, name_len, len;
205 cp_grant_id_t gid;
206 char *name;
208 devind= mp->m1_i1;
209 name_len= mp->m1_i2;
210 gid= mp->m1_i3;
212 r= _pci_slot_name(devind, &name);
213 if (r != OK)
215 printf("pci:do_slot_name_s: failed for devind %d: %d\n",
216 devind, r);
219 if (r == OK)
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);
228 mp->m_type= r;
229 r= ipc_send(mp->m_source, mp);
230 if (r != 0)
232 printf("PCI: do_slot_name: unable to send to %d: %d\n",
233 mp->m_source, r);
237 static void
238 do_set_acl(message *mp)
240 int i, r, gid;
242 if (mp->m_source != RS_PROC_NR)
244 printf("PCI: do_set_acl: not from RS\n");
245 reply(mp, EPERM);
246 return;
249 for (i= 0; i<NR_DRIVERS; i++)
251 if (!pci_acl[i].inuse)
252 break;
254 if (i >= NR_DRIVERS)
256 printf("PCI: do_set_acl: table is full\n");
257 reply(mp, ENOMEM);
258 return;
261 gid= mp->m1_i1;
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)
267 printf("PCI: do_set_acl: safecopyfrom failed\n");
268 reply(mp, r);
269 return;
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,
277 reply(mp, OK);
280 static void
281 do_del_acl(message *mp)
283 int i, proc_nr;
285 if (mp->m_source != RS_PROC_NR)
287 printf("do_del_acl: not from RS\n");
288 reply(mp, EPERM);
289 return;
292 proc_nr= mp->m1_i1;
294 for (i= 0; i<NR_DRIVERS; i++)
296 if (!pci_acl[i].inuse)
297 continue;
298 if (pci_acl[i].acl.rsp_endpoint == proc_nr)
299 break;
302 if (i >= NR_DRIVERS)
304 printf("do_del_acl: nothing found for %d\n", proc_nr);
305 reply(mp, EINVAL);
306 return;
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
315 /* Also release all devices held by this process */
316 _pci_release(proc_nr);
318 reply(mp, OK);
321 static void
322 do_reserve(message *mp)
324 struct rs_pci *aclp;
325 int r, devind;
327 devind= mp->m1_i1;
329 aclp= find_acl(mp->m_source);
331 mp->m_type= _pci_reserve(devind, mp->m_source, aclp);
332 r= ipc_send(mp->m_source, mp);
333 if (r != 0)
335 printf("do_reserve: unable to send to %d: %d\n",
336 mp->m_source, r);
340 static void
341 do_attr_r8(message *mp)
343 int r, devind, port;
344 u8_t v;
346 devind= mp->m2_i1;
347 port= mp->m2_i2;
349 r= _pci_attr_r8(devind, port, &v);
350 if (r != OK)
352 printf(
353 "pci:do_attr_r8: pci_attr_r8(%d, %d, ...) failed: %d\n",
354 devind, port, r);
356 mp->m2_l1= v;
357 mp->m_type= r;
358 r= ipc_send(mp->m_source, mp);
359 if (r != 0)
361 printf("do_attr_r8: unable to send to %d: %d\n",
362 mp->m_source, r);
366 static void
367 do_attr_r16(message *mp)
369 int r, devind, port;
370 u16_t v;
372 devind= mp->m2_i1;
373 port= mp->m2_i2;
375 r= _pci_attr_r16(devind, port, &v);
376 if (r != OK)
378 printf(
379 "pci:do_attr_r16: pci_attr_r16(%d, %d, ...) failed: %d\n",
380 devind, port, r);
382 mp->m2_l1= v;
383 mp->m_type= OK;
384 r= ipc_send(mp->m_source, mp);
385 if (r != 0)
387 printf("do_attr_r16: unable to send to %d: %d\n",
388 mp->m_source, r);
392 static void
393 do_attr_r32(message *mp)
395 int r, devind, port;
396 u32_t v;
398 devind= mp->m2_i1;
399 port= mp->m2_i2;
401 r= _pci_attr_r32(devind, port, &v);
402 if (r != OK)
404 printf(
405 "pci:do_attr_r32: pci_attr_r32(%d, %d, ...) failed: %d\n",
406 devind, port, r);
408 mp->m2_l1= v;
409 mp->m_type= OK;
410 r= ipc_send(mp->m_source, mp);
411 if (r != 0)
413 printf("do_attr_r32: unable to send to %d: %d\n",
414 mp->m_source, r);
418 static void
419 do_attr_w8(message *mp)
421 int r, devind, port;
422 u8_t v;
424 devind= mp->m2_i1;
425 port= mp->m2_i2;
426 v= mp->m2_l1;
428 _pci_attr_w8(devind, port, v);
429 mp->m_type= OK;
430 r= ipc_send(mp->m_source, mp);
431 if (r != 0)
433 printf("do_attr_w8: unable to send to %d: %d\n",
434 mp->m_source, r);
438 static void
439 do_attr_w16(message *mp)
441 int r, devind, port;
442 u16_t v;
444 devind= mp->m2_i1;
445 port= mp->m2_i2;
446 v= mp->m2_l1;
448 _pci_attr_w16(devind, port, v);
449 mp->m_type= OK;
450 r= ipc_send(mp->m_source, mp);
451 if (r != 0)
453 printf("do_attr_w16: unable to send to %d: %d\n",
454 mp->m_source, r);
458 static void
459 do_attr_w32(message *mp)
461 int r, devind, port;
462 u32_t v;
464 devind= mp->m2_i1;
465 port= mp->m2_i2;
466 v= mp->m2_l1;
468 _pci_attr_w32(devind, port, v);
469 mp->m_type= OK;
470 r= ipc_send(mp->m_source, mp);
471 if (r != 0)
473 printf("do_attr_w32: unable to send to %d: %d\n",
474 mp->m_source, r);
478 static void
479 do_get_bar(message *mp)
481 int r, devind, port, ioflag;
482 u32_t base, size;
484 devind= mp->m_lsys_pci_busc_get_bar.devind;
485 port= mp->m_lsys_pci_busc_get_bar.port;
487 mp->m_type= _pci_get_bar(devind, port, &base, &size, &ioflag);
489 if (mp->m_type == OK)
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;
496 r= ipc_send(mp->m_source, mp);
497 if (r != 0)
499 printf("do_get_bar: unable to send to %d: %d\n",
500 mp->m_source, r);
504 static void
505 do_rescan_bus(message *mp)
507 int r, busnr;
509 busnr= mp->m2_i1;
511 _pci_rescan_bus(busnr);
512 mp->m_type= OK;
513 r= ipc_send(mp->m_source, mp);
514 if (r != 0)
516 printf("do_rescan_bus: unable to send to %d: %d\n",
517 mp->m_source, r);
521 /*======================================================================*
522 * CharDriver Callbacks *
523 *======================================================================*/
524 static int
525 pci_open(devminor_t UNUSED(minor), int UNUSED(access),
526 endpoint_t UNUSED(user_endpt))
528 return OK;
531 static int
532 pci_close(devminor_t UNUSED(minor))
534 return OK;
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)
541 int devind;
542 int r = ENOTTY;
544 switch(request)
546 case PCI_IOC_BDF_CFGREAD:
548 struct pciio_bdf_cfgreg bdf;
550 if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&bdf,
551 sizeof(bdf))) != OK)
552 break;
554 r = _pci_find_dev(bdf.bus, bdf.device, bdf.function, &devind);
555 if (r != 1) {
556 r = EINVAL;
557 break;
560 if ((r = _pci_attr_r32(devind, bdf.cfgreg.reg,
561 &bdf.cfgreg.val)) != OK)
562 break;
564 r = sys_safecopyto(endpt, grant, 0, (vir_bytes)&bdf,
565 sizeof(bdf));
566 break;
568 case PCI_IOC_BDF_CFGWRITE:
570 struct pciio_bdf_cfgreg bdf;
572 if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&bdf,
573 sizeof(bdf))) != OK)
574 break;
576 r = _pci_find_dev(bdf.bus, bdf.device, bdf.function, &devind);
577 if (r != 1) {
578 r = EINVAL;
579 break;
582 _pci_attr_w32(devind, bdf.cfgreg.reg, bdf.cfgreg.val);
583 r = OK;
584 break;
586 case PCI_IOC_BUSINFO:
587 break;
588 case PCI_IOC_MAP:
590 struct pciio_map map;
591 struct minix_mem_range mr;
593 if ((r = sys_safecopyfrom(endpt, grant, 0,
594 (vir_bytes)&map, sizeof(map))) != OK)
595 break;
597 #if 1
598 mr.mr_base = map.phys_offset;
599 mr.mr_limit = map.phys_offset + map.size - 1;
601 r = sys_privctl(user_endpt, SYS_PRIV_ADD_MEM, &mr);
602 if (r != OK)
604 break;
606 #endif
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;
614 case PCI_IOC_UNMAP:
616 struct pciio_map map;
618 if ((r = sys_safecopyfrom(endpt, grant, 0,
619 (vir_bytes)&map, sizeof(map))) != OK)
620 break;
622 r = vm_unmap_phys(user_endpt, map.vaddr, map.size);
623 break;
625 case PCI_IOC_RESERVE:
627 struct pciio_acl acl;
629 if ((r = sys_safecopyfrom(endpt, grant, 0,
630 (vir_bytes)&acl, sizeof(acl))) != OK)
631 break;
633 r = _pci_find_dev(acl.bus, acl.device, acl.function, &devind);
634 if (r != 1) {
635 r = EINVAL;
636 break;
639 r = _pci_grant_access(devind, user_endpt);
640 break;
642 case PCI_IOC_RELEASE:
644 struct pciio_acl acl;
646 if ((r = sys_safecopyfrom(endpt, grant, 0,
647 (vir_bytes)&acl, sizeof(acl))) != OK)
648 break;
650 r = _pci_find_dev(acl.bus, acl.device, acl.function, &devind);
651 if (r != 1) {
652 r = EINVAL;
653 break;
656 _pci_release(endpt);
657 r = OK;
659 break;
661 case PCI_IOC_CFGREAD:
662 case PCI_IOC_CFGWRITE:
663 default:
664 r = ENOTTY;
666 return r;
669 static void
670 pci_other(message *m, int ipc_status)
672 switch(m->m_type)
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;
699 static struct chardriver driver =
701 .cdr_open = pci_open,
702 .cdr_close = pci_close,
703 .cdr_ioctl = pci_ioctl,
704 .cdr_other = pci_other,
707 /*======================================================================*
708 * SEF Callbacks *
709 *======================================================================*/
710 /* NOTE: sef_cb_init is in pci.c. */
711 static void
712 sef_local_startup(void)
715 * Register init callbacks. Use the same function for all event types
717 sef_setcb_init_fresh(sef_cb_init);
718 sef_setcb_init_restart(sef_cb_init);
720 /* Let SEF perform startup. */
721 sef_startup();
724 /*======================================================================*
725 * main *
726 *======================================================================*/
728 main(void)
731 * Perform initialization.
733 sef_local_startup();
736 * Run the main loop.
738 chardriver_task(&driver);
739 return OK;