1*5d831176SLionel Sambuc #include <sys/types.h>
2*5d831176SLionel Sambuc
3*5d831176SLionel Sambuc #include <dev/pci/pciio.h>
4*5d831176SLionel Sambuc
5*5d831176SLionel Sambuc #include <minix/chardriver.h>
66e7bb628SLionel Sambuc #include <minix/driver.h>
76e7bb628SLionel Sambuc #include <minix/rs.h>
8433d6423SLionel Sambuc
9433d6423SLionel Sambuc #include "pci.h"
10433d6423SLionel Sambuc
116e7bb628SLionel Sambuc int debug = 0;
12433d6423SLionel Sambuc struct pci_acl pci_acl[NR_DRIVERS];
13433d6423SLionel Sambuc
14*5d831176SLionel Sambuc /*======================================================================*
15*5d831176SLionel Sambuc * Helpers *
16*5d831176SLionel Sambuc *======================================================================*/
176e7bb628SLionel Sambuc static struct rs_pci *
find_acl(int endpoint)186e7bb628SLionel Sambuc find_acl(int endpoint)
196e7bb628SLionel Sambuc {
206e7bb628SLionel Sambuc int i;
216e7bb628SLionel Sambuc
226e7bb628SLionel Sambuc /* Find ACL entry for caller */
236e7bb628SLionel Sambuc for (i= 0; i<NR_DRIVERS; i++)
246e7bb628SLionel Sambuc {
256e7bb628SLionel Sambuc if (!pci_acl[i].inuse)
266e7bb628SLionel Sambuc continue;
276e7bb628SLionel Sambuc if (pci_acl[i].acl.rsp_endpoint == endpoint)
286e7bb628SLionel Sambuc return &pci_acl[i].acl;
296e7bb628SLionel Sambuc }
306e7bb628SLionel Sambuc return NULL;
316e7bb628SLionel Sambuc }
326e7bb628SLionel Sambuc
336e7bb628SLionel Sambuc static void
reply(message * mp,int result)346e7bb628SLionel Sambuc reply(message *mp, int result)
356e7bb628SLionel Sambuc {
366e7bb628SLionel Sambuc int r;
376e7bb628SLionel Sambuc message m;
386e7bb628SLionel Sambuc
396e7bb628SLionel Sambuc m.m_type= result;
406e7bb628SLionel Sambuc r= ipc_send(mp->m_source, &m);
416e7bb628SLionel Sambuc if (r != 0)
426e7bb628SLionel Sambuc printf("reply: unable to send to %d: %d\n", mp->m_source, r);
436e7bb628SLionel Sambuc }
446e7bb628SLionel Sambuc
456e7bb628SLionel Sambuc static void
do_init(message * mp)466e7bb628SLionel Sambuc do_init(message *mp)
47433d6423SLionel Sambuc {
48433d6423SLionel Sambuc int r;
49433d6423SLionel Sambuc
50433d6423SLionel Sambuc #if DEBUG
51433d6423SLionel Sambuc printf("PCI: do_init: called by '%d'\n", mp->m_source);
52433d6423SLionel Sambuc #endif
53433d6423SLionel Sambuc
54433d6423SLionel Sambuc mp->m_type= 0;
55433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
56433d6423SLionel Sambuc if (r != 0)
57433d6423SLionel Sambuc printf("PCI: do_init: unable to send to %d: %d\n",
58433d6423SLionel Sambuc mp->m_source, r);
59433d6423SLionel Sambuc }
60433d6423SLionel Sambuc
616e7bb628SLionel Sambuc static void
do_first_dev(message * mp)626e7bb628SLionel Sambuc do_first_dev(message *mp)
63433d6423SLionel Sambuc {
64433d6423SLionel Sambuc int r, devind;
65433d6423SLionel Sambuc u16_t vid, did;
66433d6423SLionel Sambuc struct rs_pci *aclp;
67433d6423SLionel Sambuc
68433d6423SLionel Sambuc aclp= find_acl(mp->m_source);
69433d6423SLionel Sambuc
70433d6423SLionel Sambuc if (!aclp && debug)
71433d6423SLionel Sambuc printf("PCI: do_first_dev: no acl for caller %d\n",
72433d6423SLionel Sambuc mp->m_source);
73433d6423SLionel Sambuc
746e7bb628SLionel Sambuc r= _pci_first_dev(aclp, &devind, &vid, &did);
75433d6423SLionel Sambuc if (r == 1)
76433d6423SLionel Sambuc {
77433d6423SLionel Sambuc mp->m1_i1= devind;
78433d6423SLionel Sambuc mp->m1_i2= vid;
79433d6423SLionel Sambuc mp->m1_i3= did;
80433d6423SLionel Sambuc }
81433d6423SLionel Sambuc mp->m_type= r;
82433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
83433d6423SLionel Sambuc if (r != 0)
84433d6423SLionel Sambuc {
85433d6423SLionel Sambuc printf("PCI: do_first_dev: unable to send to %d: %d\n",
86433d6423SLionel Sambuc mp->m_source, r);
87433d6423SLionel Sambuc }
88433d6423SLionel Sambuc }
89433d6423SLionel Sambuc
906e7bb628SLionel Sambuc static void
do_next_dev(message * mp)916e7bb628SLionel Sambuc do_next_dev(message *mp)
92433d6423SLionel Sambuc {
93433d6423SLionel Sambuc int r, devind;
94433d6423SLionel Sambuc u16_t vid, did;
95433d6423SLionel Sambuc struct rs_pci *aclp;
96433d6423SLionel Sambuc
97433d6423SLionel Sambuc devind= mp->m1_i1;
98433d6423SLionel Sambuc aclp= find_acl(mp->m_source);
99433d6423SLionel Sambuc
1006e7bb628SLionel Sambuc r= _pci_next_dev(aclp, &devind, &vid, &did);
101433d6423SLionel Sambuc if (r == 1)
102433d6423SLionel Sambuc {
103433d6423SLionel Sambuc mp->m1_i1= devind;
104433d6423SLionel Sambuc mp->m1_i2= vid;
105433d6423SLionel Sambuc mp->m1_i3= did;
106433d6423SLionel Sambuc }
107433d6423SLionel Sambuc mp->m_type= r;
108433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
109433d6423SLionel Sambuc if (r != 0)
110433d6423SLionel Sambuc {
111433d6423SLionel Sambuc printf("PCI: do_next_dev: unable to send to %d: %d\n",
112433d6423SLionel Sambuc mp->m_source, r);
113433d6423SLionel Sambuc }
114433d6423SLionel Sambuc }
115433d6423SLionel Sambuc
1166e7bb628SLionel Sambuc static void
do_find_dev(message * mp)1176e7bb628SLionel Sambuc do_find_dev(message *mp)
118433d6423SLionel Sambuc {
119433d6423SLionel Sambuc int r, devind;
120433d6423SLionel Sambuc u8_t bus, dev, func;
121433d6423SLionel Sambuc
122433d6423SLionel Sambuc bus= mp->m1_i1;
123433d6423SLionel Sambuc dev= mp->m1_i2;
124433d6423SLionel Sambuc func= mp->m1_i3;
125433d6423SLionel Sambuc
1266e7bb628SLionel Sambuc r= _pci_find_dev(bus, dev, func, &devind);
127433d6423SLionel Sambuc if (r == 1)
128433d6423SLionel Sambuc mp->m1_i1= devind;
129433d6423SLionel Sambuc mp->m_type= r;
130433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
131433d6423SLionel Sambuc if (r != 0)
132433d6423SLionel Sambuc {
133433d6423SLionel Sambuc printf("PCI: do_find_dev: unable to send to %d: %d\n",
134433d6423SLionel Sambuc mp->m_source, r);
135433d6423SLionel Sambuc }
136433d6423SLionel Sambuc }
137433d6423SLionel Sambuc
1386e7bb628SLionel Sambuc static void
do_ids(message * mp)1396e7bb628SLionel Sambuc do_ids(message *mp)
140433d6423SLionel Sambuc {
141433d6423SLionel Sambuc int r, devind;
142433d6423SLionel Sambuc u16_t vid, did;
143433d6423SLionel Sambuc
144433d6423SLionel Sambuc devind= mp->m1_i1;
145433d6423SLionel Sambuc
1466e7bb628SLionel Sambuc r= _pci_ids(devind, &vid, &did);
147433d6423SLionel Sambuc if (r != OK)
148433d6423SLionel Sambuc {
149433d6423SLionel Sambuc printf("pci:do_ids: failed for devind %d: %d\n",
150433d6423SLionel Sambuc devind, r);
151433d6423SLionel Sambuc }
152433d6423SLionel Sambuc
153433d6423SLionel Sambuc mp->m1_i1= vid;
154433d6423SLionel Sambuc mp->m1_i2= did;
155433d6423SLionel Sambuc mp->m_type= r;
156433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
157433d6423SLionel Sambuc if (r != 0)
158433d6423SLionel Sambuc {
159433d6423SLionel Sambuc printf("PCI: do_ids: unable to send to %d: %d\n",
160433d6423SLionel Sambuc mp->m_source, r);
161433d6423SLionel Sambuc }
162433d6423SLionel Sambuc }
163433d6423SLionel Sambuc
1646e7bb628SLionel Sambuc static void
do_dev_name(message * mp)1656e7bb628SLionel Sambuc do_dev_name(message *mp)
166433d6423SLionel Sambuc {
167433d6423SLionel Sambuc int r, name_len, len;
168433d6423SLionel Sambuc u16_t vid, did;
169433d6423SLionel Sambuc cp_grant_id_t name_gid;
1706e7bb628SLionel Sambuc const char *name;
171433d6423SLionel Sambuc
172433d6423SLionel Sambuc vid= mp->m7_i1;
173433d6423SLionel Sambuc did= mp->m7_i2;
174433d6423SLionel Sambuc name_len= mp->m7_i3;
175433d6423SLionel Sambuc name_gid= mp->m7_i4;
176433d6423SLionel Sambuc
1776e7bb628SLionel Sambuc name= _pci_dev_name(vid, did);
178433d6423SLionel Sambuc if (name == NULL)
179433d6423SLionel Sambuc {
180433d6423SLionel Sambuc /* No name */
181433d6423SLionel Sambuc r= ENOENT;
182433d6423SLionel Sambuc }
183433d6423SLionel Sambuc else
184433d6423SLionel Sambuc {
185433d6423SLionel Sambuc len= strlen(name)+1;
186433d6423SLionel Sambuc if (len > name_len)
187433d6423SLionel Sambuc len= name_len;
188433d6423SLionel Sambuc r= sys_safecopyto(mp->m_source, name_gid, 0, (vir_bytes)name,
189433d6423SLionel Sambuc len);
190433d6423SLionel Sambuc }
191433d6423SLionel Sambuc
192433d6423SLionel Sambuc mp->m_type= r;
193433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
194433d6423SLionel Sambuc if (r != 0)
195433d6423SLionel Sambuc {
196433d6423SLionel Sambuc printf("PCI: do_dev_name: unable to send to %d: %d\n",
197433d6423SLionel Sambuc mp->m_source, r);
198433d6423SLionel Sambuc }
199433d6423SLionel Sambuc }
200433d6423SLionel Sambuc
2016e7bb628SLionel Sambuc static void
do_slot_name(message * mp)2026e7bb628SLionel Sambuc do_slot_name(message *mp)
203433d6423SLionel Sambuc {
204433d6423SLionel Sambuc int r, devind, name_len, len;
205433d6423SLionel Sambuc cp_grant_id_t gid;
206433d6423SLionel Sambuc char *name;
207433d6423SLionel Sambuc
208433d6423SLionel Sambuc devind= mp->m1_i1;
209433d6423SLionel Sambuc name_len= mp->m1_i2;
210433d6423SLionel Sambuc gid= mp->m1_i3;
211433d6423SLionel Sambuc
2126e7bb628SLionel Sambuc r= _pci_slot_name(devind, &name);
213433d6423SLionel Sambuc if (r != OK)
214433d6423SLionel Sambuc {
215433d6423SLionel Sambuc printf("pci:do_slot_name_s: failed for devind %d: %d\n",
216433d6423SLionel Sambuc devind, r);
217433d6423SLionel Sambuc }
218433d6423SLionel Sambuc
219433d6423SLionel Sambuc if (r == OK)
220433d6423SLionel Sambuc {
221433d6423SLionel Sambuc len= strlen(name)+1;
222433d6423SLionel Sambuc if (len > name_len)
223433d6423SLionel Sambuc len= name_len;
224433d6423SLionel Sambuc r= sys_safecopyto(mp->m_source, gid, 0,
225433d6423SLionel Sambuc (vir_bytes)name, len);
226433d6423SLionel Sambuc }
227433d6423SLionel Sambuc
228433d6423SLionel Sambuc mp->m_type= r;
229433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
230433d6423SLionel Sambuc if (r != 0)
231433d6423SLionel Sambuc {
232433d6423SLionel Sambuc printf("PCI: do_slot_name: unable to send to %d: %d\n",
233433d6423SLionel Sambuc mp->m_source, r);
234433d6423SLionel Sambuc }
235433d6423SLionel Sambuc }
236433d6423SLionel Sambuc
2376e7bb628SLionel Sambuc static void
do_set_acl(message * mp)2386e7bb628SLionel Sambuc do_set_acl(message *mp)
239433d6423SLionel Sambuc {
240433d6423SLionel Sambuc int i, r, gid;
241433d6423SLionel Sambuc
242433d6423SLionel Sambuc if (mp->m_source != RS_PROC_NR)
243433d6423SLionel Sambuc {
244433d6423SLionel Sambuc printf("PCI: do_set_acl: not from RS\n");
245433d6423SLionel Sambuc reply(mp, EPERM);
246433d6423SLionel Sambuc return;
247433d6423SLionel Sambuc }
248433d6423SLionel Sambuc
249433d6423SLionel Sambuc for (i= 0; i<NR_DRIVERS; i++)
250433d6423SLionel Sambuc {
251433d6423SLionel Sambuc if (!pci_acl[i].inuse)
252433d6423SLionel Sambuc break;
253433d6423SLionel Sambuc }
254433d6423SLionel Sambuc if (i >= NR_DRIVERS)
255433d6423SLionel Sambuc {
256433d6423SLionel Sambuc printf("PCI: do_set_acl: table is full\n");
257433d6423SLionel Sambuc reply(mp, ENOMEM);
258433d6423SLionel Sambuc return;
259433d6423SLionel Sambuc }
260433d6423SLionel Sambuc
261433d6423SLionel Sambuc gid= mp->m1_i1;
262433d6423SLionel Sambuc
263433d6423SLionel Sambuc r= sys_safecopyfrom(mp->m_source, gid, 0, (vir_bytes)&pci_acl[i].acl,
264433d6423SLionel Sambuc sizeof(pci_acl[i].acl));
265433d6423SLionel Sambuc if (r != OK)
266433d6423SLionel Sambuc {
267433d6423SLionel Sambuc printf("PCI: do_set_acl: safecopyfrom failed\n");
268433d6423SLionel Sambuc reply(mp, r);
269433d6423SLionel Sambuc return;
270433d6423SLionel Sambuc }
271433d6423SLionel Sambuc pci_acl[i].inuse= 1;
272433d6423SLionel Sambuc if(debug)
273433d6423SLionel Sambuc printf("PCI: do_acl: setting ACL for %d ('%s') at entry %d\n",
274433d6423SLionel Sambuc pci_acl[i].acl.rsp_endpoint, pci_acl[i].acl.rsp_label,
275433d6423SLionel Sambuc i);
276433d6423SLionel Sambuc
277433d6423SLionel Sambuc reply(mp, OK);
278433d6423SLionel Sambuc }
279433d6423SLionel Sambuc
2806e7bb628SLionel Sambuc static void
do_del_acl(message * mp)2816e7bb628SLionel Sambuc do_del_acl(message *mp)
282433d6423SLionel Sambuc {
283433d6423SLionel Sambuc int i, proc_nr;
284433d6423SLionel Sambuc
285433d6423SLionel Sambuc if (mp->m_source != RS_PROC_NR)
286433d6423SLionel Sambuc {
287433d6423SLionel Sambuc printf("do_del_acl: not from RS\n");
288433d6423SLionel Sambuc reply(mp, EPERM);
289433d6423SLionel Sambuc return;
290433d6423SLionel Sambuc }
291433d6423SLionel Sambuc
292433d6423SLionel Sambuc proc_nr= mp->m1_i1;
293433d6423SLionel Sambuc
294433d6423SLionel Sambuc for (i= 0; i<NR_DRIVERS; i++)
295433d6423SLionel Sambuc {
296433d6423SLionel Sambuc if (!pci_acl[i].inuse)
297433d6423SLionel Sambuc continue;
298433d6423SLionel Sambuc if (pci_acl[i].acl.rsp_endpoint == proc_nr)
299433d6423SLionel Sambuc break;
300433d6423SLionel Sambuc }
301433d6423SLionel Sambuc
302433d6423SLionel Sambuc if (i >= NR_DRIVERS)
303433d6423SLionel Sambuc {
304433d6423SLionel Sambuc printf("do_del_acl: nothing found for %d\n", proc_nr);
305433d6423SLionel Sambuc reply(mp, EINVAL);
306433d6423SLionel Sambuc return;
307433d6423SLionel Sambuc }
308433d6423SLionel Sambuc
309433d6423SLionel Sambuc pci_acl[i].inuse= 0;
310433d6423SLionel Sambuc #if 0
311433d6423SLionel Sambuc printf("do_acl: deleting ACL for %d ('%s') at entry %d\n",
312433d6423SLionel Sambuc pci_acl[i].acl.rsp_endpoint, pci_acl[i].acl.rsp_label, i);
313433d6423SLionel Sambuc #endif
314433d6423SLionel Sambuc
315433d6423SLionel Sambuc /* Also release all devices held by this process */
3166e7bb628SLionel Sambuc _pci_release(proc_nr);
317433d6423SLionel Sambuc
318433d6423SLionel Sambuc reply(mp, OK);
319433d6423SLionel Sambuc }
320433d6423SLionel Sambuc
3216e7bb628SLionel Sambuc static void
do_reserve(message * mp)3226e7bb628SLionel Sambuc do_reserve(message *mp)
323433d6423SLionel Sambuc {
324433d6423SLionel Sambuc struct rs_pci *aclp;
325433d6423SLionel Sambuc int r, devind;
326433d6423SLionel Sambuc
327433d6423SLionel Sambuc devind= mp->m1_i1;
328433d6423SLionel Sambuc
329433d6423SLionel Sambuc aclp= find_acl(mp->m_source);
330433d6423SLionel Sambuc
3316e7bb628SLionel Sambuc mp->m_type= _pci_reserve(devind, mp->m_source, aclp);
332433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
333433d6423SLionel Sambuc if (r != 0)
334433d6423SLionel Sambuc {
335433d6423SLionel Sambuc printf("do_reserve: unable to send to %d: %d\n",
336433d6423SLionel Sambuc mp->m_source, r);
337433d6423SLionel Sambuc }
338433d6423SLionel Sambuc }
339433d6423SLionel Sambuc
3406e7bb628SLionel Sambuc static void
do_attr_r8(message * mp)3416e7bb628SLionel Sambuc do_attr_r8(message *mp)
342433d6423SLionel Sambuc {
343433d6423SLionel Sambuc int r, devind, port;
344433d6423SLionel Sambuc u8_t v;
345433d6423SLionel Sambuc
346433d6423SLionel Sambuc devind= mp->m2_i1;
347433d6423SLionel Sambuc port= mp->m2_i2;
348433d6423SLionel Sambuc
3496e7bb628SLionel Sambuc r= _pci_attr_r8(devind, port, &v);
350433d6423SLionel Sambuc if (r != OK)
351433d6423SLionel Sambuc {
352433d6423SLionel Sambuc printf(
3536e7bb628SLionel Sambuc "pci:do_attr_r8: pci_attr_r8(%d, %d, ...) failed: %d\n",
354433d6423SLionel Sambuc devind, port, r);
355433d6423SLionel Sambuc }
356433d6423SLionel Sambuc mp->m2_l1= v;
357433d6423SLionel Sambuc mp->m_type= r;
358433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
359433d6423SLionel Sambuc if (r != 0)
360433d6423SLionel Sambuc {
361433d6423SLionel Sambuc printf("do_attr_r8: unable to send to %d: %d\n",
362433d6423SLionel Sambuc mp->m_source, r);
363433d6423SLionel Sambuc }
364433d6423SLionel Sambuc }
365433d6423SLionel Sambuc
3666e7bb628SLionel Sambuc static void
do_attr_r16(message * mp)3676e7bb628SLionel Sambuc do_attr_r16(message *mp)
368433d6423SLionel Sambuc {
369433d6423SLionel Sambuc int r, devind, port;
3706e7bb628SLionel Sambuc u16_t v;
371433d6423SLionel Sambuc
372433d6423SLionel Sambuc devind= mp->m2_i1;
373433d6423SLionel Sambuc port= mp->m2_i2;
374433d6423SLionel Sambuc
3756e7bb628SLionel Sambuc r= _pci_attr_r16(devind, port, &v);
3766e7bb628SLionel Sambuc if (r != OK)
3776e7bb628SLionel Sambuc {
3786e7bb628SLionel Sambuc printf(
3796e7bb628SLionel Sambuc "pci:do_attr_r16: pci_attr_r16(%d, %d, ...) failed: %d\n",
3806e7bb628SLionel Sambuc devind, port, r);
3816e7bb628SLionel Sambuc }
382433d6423SLionel Sambuc mp->m2_l1= v;
383433d6423SLionel Sambuc mp->m_type= OK;
384433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
385433d6423SLionel Sambuc if (r != 0)
386433d6423SLionel Sambuc {
387433d6423SLionel Sambuc printf("do_attr_r16: unable to send to %d: %d\n",
388433d6423SLionel Sambuc mp->m_source, r);
389433d6423SLionel Sambuc }
390433d6423SLionel Sambuc }
391433d6423SLionel Sambuc
3926e7bb628SLionel Sambuc static void
do_attr_r32(message * mp)3936e7bb628SLionel Sambuc do_attr_r32(message *mp)
394433d6423SLionel Sambuc {
395433d6423SLionel Sambuc int r, devind, port;
396433d6423SLionel Sambuc u32_t v;
397433d6423SLionel Sambuc
398433d6423SLionel Sambuc devind= mp->m2_i1;
399433d6423SLionel Sambuc port= mp->m2_i2;
400433d6423SLionel Sambuc
4016e7bb628SLionel Sambuc r= _pci_attr_r32(devind, port, &v);
402433d6423SLionel Sambuc if (r != OK)
403433d6423SLionel Sambuc {
404433d6423SLionel Sambuc printf(
4056e7bb628SLionel Sambuc "pci:do_attr_r32: pci_attr_r32(%d, %d, ...) failed: %d\n",
406433d6423SLionel Sambuc devind, port, r);
407433d6423SLionel Sambuc }
408433d6423SLionel Sambuc mp->m2_l1= v;
409433d6423SLionel Sambuc mp->m_type= OK;
410433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
411433d6423SLionel Sambuc if (r != 0)
412433d6423SLionel Sambuc {
413433d6423SLionel Sambuc printf("do_attr_r32: unable to send to %d: %d\n",
414433d6423SLionel Sambuc mp->m_source, r);
415433d6423SLionel Sambuc }
416433d6423SLionel Sambuc }
417433d6423SLionel Sambuc
4186e7bb628SLionel Sambuc static void
do_attr_w8(message * mp)4196e7bb628SLionel Sambuc do_attr_w8(message *mp)
420433d6423SLionel Sambuc {
421433d6423SLionel Sambuc int r, devind, port;
422433d6423SLionel Sambuc u8_t v;
423433d6423SLionel Sambuc
424433d6423SLionel Sambuc devind= mp->m2_i1;
425433d6423SLionel Sambuc port= mp->m2_i2;
426433d6423SLionel Sambuc v= mp->m2_l1;
427433d6423SLionel Sambuc
4286e7bb628SLionel Sambuc _pci_attr_w8(devind, port, v);
429433d6423SLionel Sambuc mp->m_type= OK;
430433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
431433d6423SLionel Sambuc if (r != 0)
432433d6423SLionel Sambuc {
433433d6423SLionel Sambuc printf("do_attr_w8: unable to send to %d: %d\n",
434433d6423SLionel Sambuc mp->m_source, r);
435433d6423SLionel Sambuc }
436433d6423SLionel Sambuc }
437433d6423SLionel Sambuc
4386e7bb628SLionel Sambuc static void
do_attr_w16(message * mp)4396e7bb628SLionel Sambuc do_attr_w16(message *mp)
440433d6423SLionel Sambuc {
441433d6423SLionel Sambuc int r, devind, port;
442433d6423SLionel Sambuc u16_t v;
443433d6423SLionel Sambuc
444433d6423SLionel Sambuc devind= mp->m2_i1;
445433d6423SLionel Sambuc port= mp->m2_i2;
446433d6423SLionel Sambuc v= mp->m2_l1;
447433d6423SLionel Sambuc
4486e7bb628SLionel Sambuc _pci_attr_w16(devind, port, v);
449433d6423SLionel Sambuc mp->m_type= OK;
450433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
451433d6423SLionel Sambuc if (r != 0)
452433d6423SLionel Sambuc {
453433d6423SLionel Sambuc printf("do_attr_w16: unable to send to %d: %d\n",
454433d6423SLionel Sambuc mp->m_source, r);
455433d6423SLionel Sambuc }
456433d6423SLionel Sambuc }
457433d6423SLionel Sambuc
4586e7bb628SLionel Sambuc static void
do_attr_w32(message * mp)4596e7bb628SLionel Sambuc do_attr_w32(message *mp)
460433d6423SLionel Sambuc {
461433d6423SLionel Sambuc int r, devind, port;
462433d6423SLionel Sambuc u32_t v;
463433d6423SLionel Sambuc
464433d6423SLionel Sambuc devind= mp->m2_i1;
465433d6423SLionel Sambuc port= mp->m2_i2;
466433d6423SLionel Sambuc v= mp->m2_l1;
467433d6423SLionel Sambuc
4686e7bb628SLionel Sambuc _pci_attr_w32(devind, port, v);
469433d6423SLionel Sambuc mp->m_type= OK;
470433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
471433d6423SLionel Sambuc if (r != 0)
472433d6423SLionel Sambuc {
473433d6423SLionel Sambuc printf("do_attr_w32: unable to send to %d: %d\n",
474433d6423SLionel Sambuc mp->m_source, r);
475433d6423SLionel Sambuc }
476433d6423SLionel Sambuc }
477433d6423SLionel Sambuc
4786e7bb628SLionel Sambuc static void
do_get_bar(message * mp)4796e7bb628SLionel Sambuc do_get_bar(message *mp)
480433d6423SLionel Sambuc {
481433d6423SLionel Sambuc int r, devind, port, ioflag;
482433d6423SLionel Sambuc u32_t base, size;
483433d6423SLionel Sambuc
484433d6423SLionel Sambuc devind= mp->m_lsys_pci_busc_get_bar.devind;
485433d6423SLionel Sambuc port= mp->m_lsys_pci_busc_get_bar.port;
486433d6423SLionel Sambuc
4876e7bb628SLionel Sambuc mp->m_type= _pci_get_bar(devind, port, &base, &size, &ioflag);
488433d6423SLionel Sambuc
489433d6423SLionel Sambuc if (mp->m_type == OK)
490433d6423SLionel Sambuc {
491433d6423SLionel Sambuc mp->m_pci_lsys_busc_get_bar.base= base;
492433d6423SLionel Sambuc mp->m_pci_lsys_busc_get_bar.size= size;
493433d6423SLionel Sambuc mp->m_pci_lsys_busc_get_bar.flags= ioflag;
494433d6423SLionel Sambuc }
495433d6423SLionel Sambuc
496433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
497433d6423SLionel Sambuc if (r != 0)
498433d6423SLionel Sambuc {
499433d6423SLionel Sambuc printf("do_get_bar: unable to send to %d: %d\n",
500433d6423SLionel Sambuc mp->m_source, r);
501433d6423SLionel Sambuc }
502433d6423SLionel Sambuc }
503433d6423SLionel Sambuc
5046e7bb628SLionel Sambuc static void
do_rescan_bus(message * mp)5056e7bb628SLionel Sambuc do_rescan_bus(message *mp)
506433d6423SLionel Sambuc {
507433d6423SLionel Sambuc int r, busnr;
508433d6423SLionel Sambuc
509433d6423SLionel Sambuc busnr= mp->m2_i1;
510433d6423SLionel Sambuc
5116e7bb628SLionel Sambuc _pci_rescan_bus(busnr);
512433d6423SLionel Sambuc mp->m_type= OK;
513433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp);
514433d6423SLionel Sambuc if (r != 0)
515433d6423SLionel Sambuc {
516433d6423SLionel Sambuc printf("do_rescan_bus: unable to send to %d: %d\n",
517433d6423SLionel Sambuc mp->m_source, r);
518433d6423SLionel Sambuc }
519433d6423SLionel Sambuc }
520433d6423SLionel Sambuc
521*5d831176SLionel Sambuc /*======================================================================*
522*5d831176SLionel Sambuc * CharDriver Callbacks *
523*5d831176SLionel Sambuc *======================================================================*/
524*5d831176SLionel Sambuc static int
pci_open(devminor_t UNUSED (minor),int UNUSED (access),endpoint_t UNUSED (user_endpt))525*5d831176SLionel Sambuc pci_open(devminor_t UNUSED(minor), int UNUSED(access),
526*5d831176SLionel Sambuc endpoint_t UNUSED(user_endpt))
527*5d831176SLionel Sambuc {
528*5d831176SLionel Sambuc return OK;
529*5d831176SLionel Sambuc }
530*5d831176SLionel Sambuc
531*5d831176SLionel Sambuc static int
pci_close(devminor_t UNUSED (minor))532*5d831176SLionel Sambuc pci_close(devminor_t UNUSED(minor))
533*5d831176SLionel Sambuc {
534*5d831176SLionel Sambuc return OK;
535*5d831176SLionel Sambuc }
536*5d831176SLionel Sambuc
537*5d831176SLionel Sambuc static int
pci_ioctl(devminor_t minor,unsigned long request,endpoint_t endpt,cp_grant_id_t grant,int flags,endpoint_t user_endpt,cdev_id_t id)538*5d831176SLionel Sambuc pci_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
539*5d831176SLionel Sambuc cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id)
540*5d831176SLionel Sambuc {
541*5d831176SLionel Sambuc int devind;
542*5d831176SLionel Sambuc int r = ENOTTY;
543*5d831176SLionel Sambuc
544*5d831176SLionel Sambuc switch(request)
545*5d831176SLionel Sambuc {
546*5d831176SLionel Sambuc case PCI_IOC_BDF_CFGREAD:
547*5d831176SLionel Sambuc {
548*5d831176SLionel Sambuc struct pciio_bdf_cfgreg bdf;
549*5d831176SLionel Sambuc
550*5d831176SLionel Sambuc if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&bdf,
551*5d831176SLionel Sambuc sizeof(bdf))) != OK)
552*5d831176SLionel Sambuc break;
553*5d831176SLionel Sambuc
554*5d831176SLionel Sambuc r = _pci_find_dev(bdf.bus, bdf.device, bdf.function, &devind);
555*5d831176SLionel Sambuc if (r != 1) {
556*5d831176SLionel Sambuc r = EINVAL;
557*5d831176SLionel Sambuc break;
558*5d831176SLionel Sambuc }
559*5d831176SLionel Sambuc
560*5d831176SLionel Sambuc if ((r = _pci_attr_r32(devind, bdf.cfgreg.reg,
561*5d831176SLionel Sambuc &bdf.cfgreg.val)) != OK)
562*5d831176SLionel Sambuc break;
563*5d831176SLionel Sambuc
564*5d831176SLionel Sambuc r = sys_safecopyto(endpt, grant, 0, (vir_bytes)&bdf,
565*5d831176SLionel Sambuc sizeof(bdf));
566*5d831176SLionel Sambuc break;
567*5d831176SLionel Sambuc }
568*5d831176SLionel Sambuc case PCI_IOC_BDF_CFGWRITE:
569*5d831176SLionel Sambuc {
570*5d831176SLionel Sambuc struct pciio_bdf_cfgreg bdf;
571*5d831176SLionel Sambuc
572*5d831176SLionel Sambuc if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&bdf,
573*5d831176SLionel Sambuc sizeof(bdf))) != OK)
574*5d831176SLionel Sambuc break;
575*5d831176SLionel Sambuc
576*5d831176SLionel Sambuc r = _pci_find_dev(bdf.bus, bdf.device, bdf.function, &devind);
577*5d831176SLionel Sambuc if (r != 1) {
578*5d831176SLionel Sambuc r = EINVAL;
579*5d831176SLionel Sambuc break;
580*5d831176SLionel Sambuc }
581*5d831176SLionel Sambuc
582*5d831176SLionel Sambuc _pci_attr_w32(devind, bdf.cfgreg.reg, bdf.cfgreg.val);
583*5d831176SLionel Sambuc r = OK;
584*5d831176SLionel Sambuc break;
585*5d831176SLionel Sambuc }
586*5d831176SLionel Sambuc case PCI_IOC_BUSINFO:
587*5d831176SLionel Sambuc break;
588*5d831176SLionel Sambuc case PCI_IOC_MAP:
589*5d831176SLionel Sambuc {
590*5d831176SLionel Sambuc struct pciio_map map;
591*5d831176SLionel Sambuc struct minix_mem_range mr;
592*5d831176SLionel Sambuc
593*5d831176SLionel Sambuc if ((r = sys_safecopyfrom(endpt, grant, 0,
594*5d831176SLionel Sambuc (vir_bytes)&map, sizeof(map))) != OK)
595*5d831176SLionel Sambuc break;
596*5d831176SLionel Sambuc
597*5d831176SLionel Sambuc #if 1
598*5d831176SLionel Sambuc mr.mr_base = map.phys_offset;
599*5d831176SLionel Sambuc mr.mr_limit = map.phys_offset + map.size - 1;
600*5d831176SLionel Sambuc
601*5d831176SLionel Sambuc r = sys_privctl(user_endpt, SYS_PRIV_ADD_MEM, &mr);
602*5d831176SLionel Sambuc if (r != OK)
603*5d831176SLionel Sambuc {
604*5d831176SLionel Sambuc break;
605*5d831176SLionel Sambuc }
606*5d831176SLionel Sambuc #endif
607*5d831176SLionel Sambuc
608*5d831176SLionel Sambuc map.vaddr_ret = vm_map_phys(user_endpt,
609*5d831176SLionel Sambuc (void *)map.phys_offset, map.size);
610*5d831176SLionel Sambuc r = sys_safecopyto(endpt, grant, 0, (vir_bytes)&map,
611*5d831176SLionel Sambuc sizeof(map));
612*5d831176SLionel Sambuc break;
613*5d831176SLionel Sambuc }
614*5d831176SLionel Sambuc case PCI_IOC_UNMAP:
615*5d831176SLionel Sambuc {
616*5d831176SLionel Sambuc struct pciio_map map;
617*5d831176SLionel Sambuc
618*5d831176SLionel Sambuc if ((r = sys_safecopyfrom(endpt, grant, 0,
619*5d831176SLionel Sambuc (vir_bytes)&map, sizeof(map))) != OK)
620*5d831176SLionel Sambuc break;
621*5d831176SLionel Sambuc
622*5d831176SLionel Sambuc r = vm_unmap_phys(user_endpt, map.vaddr, map.size);
623*5d831176SLionel Sambuc break;
624*5d831176SLionel Sambuc }
625*5d831176SLionel Sambuc case PCI_IOC_RESERVE:
626*5d831176SLionel Sambuc {
627*5d831176SLionel Sambuc struct pciio_acl acl;
628*5d831176SLionel Sambuc
629*5d831176SLionel Sambuc if ((r = sys_safecopyfrom(endpt, grant, 0,
630*5d831176SLionel Sambuc (vir_bytes)&acl, sizeof(acl))) != OK)
631*5d831176SLionel Sambuc break;
632*5d831176SLionel Sambuc
633*5d831176SLionel Sambuc r = _pci_find_dev(acl.bus, acl.device, acl.function, &devind);
634*5d831176SLionel Sambuc if (r != 1) {
635*5d831176SLionel Sambuc r = EINVAL;
636*5d831176SLionel Sambuc break;
637*5d831176SLionel Sambuc }
638*5d831176SLionel Sambuc
639*5d831176SLionel Sambuc r = _pci_grant_access(devind, user_endpt);
640*5d831176SLionel Sambuc break;
641*5d831176SLionel Sambuc }
642*5d831176SLionel Sambuc case PCI_IOC_RELEASE:
643*5d831176SLionel Sambuc {
644*5d831176SLionel Sambuc struct pciio_acl acl;
645*5d831176SLionel Sambuc
646*5d831176SLionel Sambuc if ((r = sys_safecopyfrom(endpt, grant, 0,
647*5d831176SLionel Sambuc (vir_bytes)&acl, sizeof(acl))) != OK)
648*5d831176SLionel Sambuc break;
649*5d831176SLionel Sambuc
650*5d831176SLionel Sambuc r = _pci_find_dev(acl.bus, acl.device, acl.function, &devind);
651*5d831176SLionel Sambuc if (r != 1) {
652*5d831176SLionel Sambuc r = EINVAL;
653*5d831176SLionel Sambuc break;
654*5d831176SLionel Sambuc }
655*5d831176SLionel Sambuc
656*5d831176SLionel Sambuc _pci_release(endpt);
657*5d831176SLionel Sambuc r = OK;
658*5d831176SLionel Sambuc
659*5d831176SLionel Sambuc break;
660*5d831176SLionel Sambuc }
661*5d831176SLionel Sambuc case PCI_IOC_CFGREAD:
662*5d831176SLionel Sambuc case PCI_IOC_CFGWRITE:
663*5d831176SLionel Sambuc default:
664*5d831176SLionel Sambuc r = ENOTTY;
665*5d831176SLionel Sambuc }
666*5d831176SLionel Sambuc return r;
667*5d831176SLionel Sambuc }
668*5d831176SLionel Sambuc
669*5d831176SLionel Sambuc static void
pci_other(message * m,int ipc_status)670*5d831176SLionel Sambuc pci_other(message *m, int ipc_status)
671*5d831176SLionel Sambuc {
672*5d831176SLionel Sambuc switch(m->m_type)
673*5d831176SLionel Sambuc {
674*5d831176SLionel Sambuc case BUSC_PCI_INIT: do_init(m); break;
675*5d831176SLionel Sambuc case BUSC_PCI_FIRST_DEV: do_first_dev(m); break;
676*5d831176SLionel Sambuc case BUSC_PCI_NEXT_DEV: do_next_dev(m); break;
677*5d831176SLionel Sambuc case BUSC_PCI_FIND_DEV: do_find_dev(m); break;
678*5d831176SLionel Sambuc case BUSC_PCI_IDS: do_ids(m); break;
679*5d831176SLionel Sambuc case BUSC_PCI_RESERVE: do_reserve(m); break;
680*5d831176SLionel Sambuc case BUSC_PCI_ATTR_R8: do_attr_r8(m); break;
681*5d831176SLionel Sambuc case BUSC_PCI_ATTR_R16: do_attr_r16(m); break;
682*5d831176SLionel Sambuc case BUSC_PCI_ATTR_R32: do_attr_r32(m); break;
683*5d831176SLionel Sambuc case BUSC_PCI_ATTR_W8: do_attr_w8(m); break;
684*5d831176SLionel Sambuc case BUSC_PCI_ATTR_W16: do_attr_w16(m); break;
685*5d831176SLionel Sambuc case BUSC_PCI_ATTR_W32: do_attr_w32(m); break;
686*5d831176SLionel Sambuc case BUSC_PCI_RESCAN: do_rescan_bus(m); break;
687*5d831176SLionel Sambuc case BUSC_PCI_DEV_NAME_S: do_dev_name(m); break;
688*5d831176SLionel Sambuc case BUSC_PCI_SLOT_NAME_S: do_slot_name(m); break;
689*5d831176SLionel Sambuc case BUSC_PCI_SET_ACL: do_set_acl(m); break;
690*5d831176SLionel Sambuc case BUSC_PCI_DEL_ACL: do_del_acl(m); break;
691*5d831176SLionel Sambuc case BUSC_PCI_GET_BAR: do_get_bar(m); break;
692*5d831176SLionel Sambuc default:
693*5d831176SLionel Sambuc printf("PCI: unhandled message from %d, type %d\n",
694*5d831176SLionel Sambuc m->m_source, m->m_type);
695*5d831176SLionel Sambuc break;
696*5d831176SLionel Sambuc }
697*5d831176SLionel Sambuc }
698*5d831176SLionel Sambuc
699*5d831176SLionel Sambuc static struct chardriver driver =
700*5d831176SLionel Sambuc {
701*5d831176SLionel Sambuc .cdr_open = pci_open,
702*5d831176SLionel Sambuc .cdr_close = pci_close,
703*5d831176SLionel Sambuc .cdr_ioctl = pci_ioctl,
704*5d831176SLionel Sambuc .cdr_other = pci_other,
705*5d831176SLionel Sambuc };
706*5d831176SLionel Sambuc
707*5d831176SLionel Sambuc /*======================================================================*
708*5d831176SLionel Sambuc * SEF Callbacks *
709*5d831176SLionel Sambuc *======================================================================*/
710*5d831176SLionel Sambuc /* NOTE: sef_cb_init is in pci.c. */
711*5d831176SLionel Sambuc static void
sef_local_startup(void)712*5d831176SLionel Sambuc sef_local_startup(void)
713*5d831176SLionel Sambuc {
714*5d831176SLionel Sambuc /*
715*5d831176SLionel Sambuc * Register init callbacks. Use the same function for all event types
716*5d831176SLionel Sambuc */
717*5d831176SLionel Sambuc sef_setcb_init_fresh(sef_cb_init);
718*5d831176SLionel Sambuc sef_setcb_init_restart(sef_cb_init);
719*5d831176SLionel Sambuc
720*5d831176SLionel Sambuc /* Let SEF perform startup. */
721*5d831176SLionel Sambuc sef_startup();
722*5d831176SLionel Sambuc }
723*5d831176SLionel Sambuc
724*5d831176SLionel Sambuc /*======================================================================*
725*5d831176SLionel Sambuc * main *
726*5d831176SLionel Sambuc *======================================================================*/
7276e7bb628SLionel Sambuc int
main(void)7286e7bb628SLionel Sambuc main(void)
729433d6423SLionel Sambuc {
730*5d831176SLionel Sambuc /*
731*5d831176SLionel Sambuc * Perform initialization.
732*5d831176SLionel Sambuc */
7336e7bb628SLionel Sambuc sef_local_startup();
7346e7bb628SLionel Sambuc
735*5d831176SLionel Sambuc /*
736*5d831176SLionel Sambuc * Run the main loop.
737*5d831176SLionel Sambuc */
738*5d831176SLionel Sambuc chardriver_task(&driver);
739*5d831176SLionel Sambuc return OK;
740433d6423SLionel Sambuc }
741