Improve the process for GNU tools
[minix3.git] / minix / drivers / iommu / amddev / amddev.c
blobb5d61927f3cb7930382437508f4a17b6b83d3d9d
1 /*
2 amddev.c
4 Driver for the AMD Device Exclusion Vector (DEV)
5 */
7 #include <minix/driver.h>
8 #include <minix/config.h>
9 #include <minix/type.h>
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <machine/vm.h>
17 #include <machine/vmparam.h>
18 #include <signal.h>
19 #include <minix/com.h>
20 #include <minix/const.h>
21 #include <minix/ipc.h>
22 #include <minix/syslib.h>
23 #include <minix/sysutil.h>
24 #include <minix/endpoint.h>
25 #include <machine/pci.h>
27 /* Offsets from capability pointer */
28 #define DEV_OP 4 /* Selects control/status register to access */
29 #define DEV_OP_FUNC_SHIFT 8 /* Function part in OP reg. */
30 #define DEV_DATA 8 /* Read/write to access reg. selected */
32 /* Functions */
33 #define DEVF_BASE_LO 0
34 #define DEVF_BASE_HI 1
35 #define DEVF_MAP 2
36 #define DEVF_CAP 3
37 #define DEVF_CAP_MAPS_MASK 0x00ff0000
38 #define DEVF_CAP_MAPS_SHIFT 16
39 #define DEVF_CAP_DOMS_MASK 0x0000ff00
40 #define DEVF_CAP_DOMS_SHIFT 8
41 #define DEVF_CAP_REV_MASK 0x000000ff
42 #define DEVF_CAP_REV_SHIFT 0
43 #define DEVF_CR 4
44 #define DEVF_ERR_STATUS 5
45 #define DEVF_ERR_ADDR_LO 6
46 #define DEVF_ERR_ADDR_HI 7
48 static int dev_devind;
49 static u8_t dev_capptr;
50 static u8_t *table;
52 static int find_dev(int *devindp, u8_t *capaddrp);
53 static u32_t read_reg(int function, int index);
54 static void write_reg(int function, int index, u32_t value);
55 static void init_domain(int index);
56 static void init_map(unsigned int ix);
57 static int do_add4pci(const message *m);
58 static void add_range(phys_bytes busaddr, phys_bytes size);
59 #if 0
60 static void del_range(phys_bytes busaddr, phys_bytes size);
61 static void sef_cb_signal_handler(int signo);
62 #endif
63 static void report_exceptions(void);
65 /* SEF functions and variables. */
66 static void sef_local_startup(void);
67 static int sef_cb_init_fresh(int type, sef_init_info_t *info);
69 int main(void)
71 int r;
72 message m;
73 int ipc_status;
75 /* SEF local startup. */
76 sef_local_startup();
78 for(;;)
80 report_exceptions();
82 r= driver_receive(ANY, &m, &ipc_status);
83 if (r != OK)
84 panic("driver_receive failed: %d", r);
85 if (m.m_type == IOMMU_MAP) {
86 r= do_add4pci(&m);
87 m.m_type= r;
88 ipc_send(m.m_source, &m);
89 continue;
91 printf("amddev: got message from %d\n", m.m_source);
95 /*===========================================================================*
96 * sef_local_startup *
97 *===========================================================================*/
98 static void sef_local_startup()
100 /* Register init callbacks. */
101 sef_setcb_init_fresh(sef_cb_init_fresh);
102 sef_setcb_init_lu(sef_cb_init_fresh);
103 sef_setcb_init_restart(sef_cb_init_fresh);
105 #if 0
106 /* Register signal callbacks. */
107 sef_setcb_signal_handler(sef_cb_signal_handler);
108 #endif
110 /* Let SEF perform startup. */
111 sef_startup();
114 /*===========================================================================*
115 * sef_cb_init_fresh *
116 *===========================================================================*/
117 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
119 /* Initialize the amddev driver. */
120 int r, n_maps, n_domains, revision;
121 u16_t flags;
122 u32_t bits;
124 printf("amddev: starting\n");
126 r= find_dev(&dev_devind, &dev_capptr);
127 if (!r)
128 return r;
129 flags= pci_attr_r16(dev_devind, dev_capptr+CAP_SD_INFO);
130 printf("amddev`init: flags = 0x%x\n", flags);
132 bits= read_reg(DEVF_CAP, 0);
133 n_maps= ((bits & DEVF_CAP_MAPS_MASK) >> DEVF_CAP_MAPS_SHIFT);
134 n_domains= ((bits & DEVF_CAP_DOMS_MASK) >> DEVF_CAP_DOMS_SHIFT);
135 revision= ((bits & DEVF_CAP_REV_MASK) >> DEVF_CAP_REV_SHIFT);
136 printf("amddev`init: DEVF_CAP = 0x%x (%d maps, %d domains, rev 0x%x)\n",
137 bits, n_maps, n_domains, revision);
139 printf("status = 0x%x, addr-lo = 0x%x, addr-hi = 0x%x\n",
140 read_reg(DEVF_ERR_STATUS, 0),
141 read_reg(DEVF_ERR_ADDR_LO, 0),
142 read_reg(DEVF_ERR_ADDR_HI, 0));
144 init_domain(0);
145 init_map(0);
146 #if 0
147 init_domain(1);
148 #endif
150 write_reg(DEVF_CR, 0, 0x10 | 0x8 | 0x4 | 1);
152 printf("after write: DEVF_CR: 0x%x\n", read_reg(DEVF_CR, 0));
154 return(OK);
158 #if 0
159 /*===========================================================================*
160 * sef_cb_signal_handler *
161 *===========================================================================*/
162 static void sef_cb_signal_handler(int signo)
164 int r;
165 endpoint_t proc_e;
166 phys_bytes base, size;
168 /* Only check for termination signal, ignore anything else. */
169 if (signo != SIGTERM) return;
171 for (;;)
173 r= vm_getdma(&proc_e, &base, &size);
174 if (r == -1)
176 if (errno != -EAGAIN)
178 printf(
179 "amddev: vm_getdma failed: %d\n",
180 errno);
182 break;
185 printf(
186 "amddev: deleting 0x%lx@0x%lx for proc %d\n",
187 size, base, proc_e);
188 del_range(base, size);
189 r= vm_deldma(proc_e, base, size);
190 if (r == -1)
192 printf("amddev: vm_deldma failed: %d\n",
193 errno);
194 break;
198 #endif
200 /* Returns 0 if no device found, or 1 if a device is found. */
201 static int find_dev(devindp, capaddrp)
202 int *devindp;
203 u8_t *capaddrp;
205 int r, devind, first;
206 u8_t capptr, type, next, subtype;
207 u16_t vid, did, status;
209 pci_init();
211 first= 1;
212 for(;;)
214 if (first)
216 first= 0;
217 r= pci_first_dev(&devind, &vid, &did);
218 if (!r)
220 printf("amddev`find_dev: no first dev\n");
221 return 0;
224 else
226 r= pci_next_dev(&devind, &vid, &did);
227 if (!r)
229 printf("amddev`find_dev: no next dev\n");
230 return 0;
234 printf("amddev`find_dev: got devind %d, vid 0x%x, did 0x%x\n",
235 devind, vid, did);
237 /* Check capabilities bit in the device status register */
238 status= pci_attr_r16(devind, PCI_SR);
239 if (!(status & PSR_CAPPTR))
240 continue;
242 capptr= (pci_attr_r8(devind, PCI_CAPPTR) & PCI_CP_MASK);
243 while (capptr != 0)
245 type = pci_attr_r8(devind, capptr+CAP_TYPE);
246 next= (pci_attr_r8(devind, capptr+CAP_NEXT) &
247 PCI_CP_MASK);
248 if (type == CAP_T_SECURE_DEV)
250 printf(
251 "amddev`find_dev: found secure device\n");
252 subtype= (pci_attr_r8(devind, capptr+
253 CAP_SD_INFO) & CAP_SD_SUBTYPE_MASK);
254 if (subtype == CAP_T_SD_DEV)
256 printf("amddev`find_dev: AMD DEV\n");
257 pci_reserve(devind);
258 *devindp= devind;
259 *capaddrp= capptr;
260 return 1;
263 capptr= next;
266 return 0;
269 static u32_t read_reg(int function, int index)
271 pci_attr_w32(dev_devind, dev_capptr + DEV_OP, ((function <<
272 DEV_OP_FUNC_SHIFT) | index));
273 return pci_attr_r32(dev_devind, dev_capptr + DEV_DATA);
276 static void write_reg(int function, int index, u32_t value)
278 pci_attr_w32(dev_devind, dev_capptr + DEV_OP, ((function <<
279 DEV_OP_FUNC_SHIFT) | index));
280 pci_attr_w32(dev_devind, dev_capptr + DEV_DATA, value);
283 static void init_domain(int index)
285 size_t size, memsize;
286 phys_bytes busaddr;
288 size= 0x100000 / 8;
289 table= alloc_contig(size, AC_ALIGN4K, &busaddr);
290 if (table == NULL)
291 panic("malloc failed");
292 if (index == 0)
294 memset(table, 0, size);
295 memsize= 0x37000 / 8;
296 printf("memsize = 0x%x / 8\n", memsize*8);
297 memset(table, 0xff, memsize);
299 else
301 memset(table, 0xff, size);
302 memset(table, 0x00, size);
305 printf("init_domain: busaddr = 0x%lx\n", busaddr);
307 write_reg(DEVF_BASE_HI, index, 0);
308 write_reg(DEVF_BASE_LO, index, busaddr | 3);
310 printf("after write: DEVF_BASE_LO: 0x%x\n",
311 read_reg(DEVF_BASE_LO, index));
314 static void init_map(unsigned int ix)
316 u32_t v, dom, busno, unit0, unit1;
318 dom= 1;
319 busno= 7;
320 unit1= 9;
321 unit0= 9;
322 v= (dom << 26) | (dom << 20) | (busno << 12) |
323 (0 << 11) | (unit1 << 6) |
324 (0 << 5) | (unit0 << 0);
325 write_reg(DEVF_MAP, ix, v);
327 printf("after write: DEVF_MAP: 0x%x\n", read_reg(DEVF_MAP, ix));
330 #if 0
331 static int do_add(message *m)
333 int r;
334 endpoint_t proc;
335 vir_bytes start;
336 size_t size;
337 phys_bytes busaddr;
339 proc= m->m_source;
340 start= m->m2_l1;
341 size= m->m2_l2;
343 #if 0
344 printf("amddev`do_add: got request for 0x%x@0x%x from %d\n",
345 size, start, proc);
346 #endif
348 if (start % PAGE_SIZE)
350 printf("amddev`do_add: bad start 0x%x from proc %d\n",
351 start, proc);
352 return EINVAL;
354 if (size % PAGE_SIZE)
356 printf("amddev`do_add: bad size 0x%x from proc %d\n",
357 size, proc);
358 return EINVAL;
360 r= sys_umap_remote(proc, SELF, VM_D, (vir_bytes)start, size, &busaddr);
361 if (r != OK)
363 printf("amddev`do_add: umap failed for 0x%x@0x%x, proc %d\n",
364 size, start, proc);
365 return r;
367 add_range(busaddr, size);
370 #endif
374 static int do_add4pci(const message *m)
376 int r, pci_bus, pci_dev, pci_func;
377 endpoint_t proc;
378 vir_bytes start;
379 size_t size;
380 phys_bytes busaddr;
382 proc= m->m_source;
383 start= m->m2_l1;
384 size= m->m2_l2;
385 pci_bus= m->m1_i1;
386 pci_dev= m->m1_i2;
387 pci_func= m->m1_i3;
389 printf(
390 "amddev`do_add4pci: got request for 0x%x@0x%lx from %d for pci dev %u.%u.%u\n",
391 size, start, proc, pci_bus, pci_dev, pci_func);
393 if (start % PAGE_SIZE)
395 printf("amddev`do_add4pci: bad start 0x%lx from proc %d\n",
396 start, proc);
397 return EINVAL;
399 if (size % PAGE_SIZE)
401 printf("amddev`do_add4pci: bad size 0x%x from proc %d\n",
402 size, proc);
403 return EINVAL;
406 printf("amddev`do_add4pci: should check with PCI\n");
408 r= sys_umap_remote(proc, SELF, VM_D, (vir_bytes)start, size, &busaddr);
409 if (r != OK)
411 printf(
412 "amddev`do_add4pci: umap failed for 0x%x@0x%lx, proc %d: %d\n",
413 size, start, proc, r);
414 return r;
417 #if 0
418 r= vm_adddma(proc, start, size);
419 if (r != 0)
421 r= -errno;
422 printf("amddev`do_add4pci: vm_adddma failed for 0x%x@0x%lx, "
423 "proc %d: %d\n", size, start, proc, r);
424 return r;
426 #endif
428 add_range(busaddr, size);
430 return OK;
434 static void add_range(phys_bytes busaddr, phys_bytes size)
436 phys_bytes o;
438 #if 0
439 printf("add_range: mapping 0x%x@0x%x\n", size, busaddr);
440 #endif
442 for (o= 0; o<size; o += PAGE_SIZE)
444 u32_t bit= (busaddr+o)/PAGE_SIZE;
445 table[bit/8] &= ~(1U << (bit % 8));
449 #if 0
450 static void del_range(phys_bytes busaddr, phys_bytes size)
452 phys_bytes o;
454 #if 0
455 printf("del_range: mapping 0x%x@0x%x\n", size, busaddr);
456 #endif
458 for (o= 0; o<size; o += PAGE_SIZE)
460 u32_t bit= (busaddr+o)/PAGE_SIZE;
461 table[bit/8] |= (1 << (bit % 8));
464 #endif
466 static void report_exceptions(void)
468 u32_t status;
470 status= read_reg(DEVF_ERR_STATUS, 0);
471 if (!(status & 0x80000000))
472 return;
473 printf("amddev: status = 0x%x, addr-lo = 0x%x, addr-hi = 0x%x\n",
474 status, read_reg(DEVF_ERR_ADDR_LO, 0),
475 read_reg(DEVF_ERR_ADDR_HI, 0));
476 write_reg(DEVF_ERR_STATUS, 0, 0);