dec21140A ethernet driver for virtualpc, contributed by nicolas tittley.
[minix.git] / drivers / amddev / amddev.c
blobd4ce79b3319bca173a0f21ef6d11489d389ca27b
1 /*
2 amddev.c
4 Driver for the AMD Device Exclusion Vector (DEV)
5 */
7 #define _SYSTEM
8 #define _MINIX
10 #include <minix/config.h>
11 #include <minix/type.h>
13 #include <errno.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <sys/vm_i386.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 <ibm/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(int index);
57 static int do_add_phys(message *m);
58 static int do_del_phys(message *m);
59 static int do_add4pci(message *m);
60 static void add_range(u32_t busaddr, u32_t size);
61 static void del_range(u32_t busaddr, u32_t size);
62 static void do_pm_notify(message *m);
63 static void report_exceptions(void);
65 /* SEF functions and variables. */
66 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
67 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
69 int main(void)
71 int r;
72 message m;
74 /* SEF local startup. */
75 sef_local_startup();
77 for(;;)
79 report_exceptions();
81 r= sef_receive(ANY, &m);
82 if (r != OK)
83 panic(__FILE__, "sef_receive failed", r);
84 if (is_notify(m.m_type)) {
85 if (_ENDPOINT_P(m.m_source) == PM_PROC_NR) {
86 do_pm_notify(&m);
87 continue;
90 else if (m.m_type == IOMMU_MAP) {
91 r= do_add4pci(&m);
92 m.m_type= r;
93 send(m.m_source, &m);
94 continue;
96 printf("amddev: got message from %d\n", m.m_source);
100 /*===========================================================================*
101 * sef_local_startup *
102 *===========================================================================*/
103 PRIVATE void sef_local_startup()
105 /* Register init callbacks. */
106 sef_setcb_init_fresh(sef_cb_init_fresh);
107 sef_setcb_init_lu(sef_cb_init_fresh);
108 sef_setcb_init_restart(sef_cb_init_fresh);
110 /* Register live update callbacks. */
111 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
112 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
114 /* Let SEF perform startup. */
115 sef_startup();
118 /*===========================================================================*
119 * sef_cb_init_fresh *
120 *===========================================================================*/
121 PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
123 /* Initialize the amddev driver. */
124 int r, n_maps, n_domains, revision;
125 u16_t flags;
126 u32_t bits;
128 printf("amddev: starting\n");
130 r= find_dev(&dev_devind, &dev_capptr);
131 if (!r)
132 return r;
133 flags= pci_attr_r16(dev_devind, dev_capptr+CAP_SD_INFO);
134 printf("amddev`init: flags = 0x%x\n", flags);
136 bits= read_reg(DEVF_CAP, 0);
137 n_maps= ((bits & DEVF_CAP_MAPS_MASK) >> DEVF_CAP_MAPS_SHIFT);
138 n_domains= ((bits & DEVF_CAP_DOMS_MASK) >> DEVF_CAP_DOMS_SHIFT);
139 revision= ((bits & DEVF_CAP_REV_MASK) >> DEVF_CAP_REV_SHIFT);
140 printf("amddev`init: DEVF_CAP = 0x%x (%d maps, %d domains, rev 0x%x)\n",
141 bits, n_maps, n_domains, revision);
143 printf("status = 0x%x, addr-lo = 0x%x, addr-hi = 0x%x\n",
144 read_reg(DEVF_ERR_STATUS, 0),
145 read_reg(DEVF_ERR_ADDR_LO, 0),
146 read_reg(DEVF_ERR_ADDR_HI, 0));
148 init_domain(0);
149 init_map(0);
150 #if 0
151 init_domain(1);
152 #endif
154 write_reg(DEVF_CR, 0, 0x10 | 0x8 | 0x4 | 1);
156 printf("after write: DEVF_CR: 0x%x\n", read_reg(DEVF_CR, 0));
158 return(OK);
161 /* Returns 0 if no device found, or 1 if a device is found. */
162 static int find_dev(devindp, capaddrp)
163 int *devindp;
164 u8_t *capaddrp;
166 int r, devind, first;
167 u8_t capptr, type, next, subtype;
168 u16_t vid, did, status;
170 pci_init();
172 first= 1;
173 for(;;)
175 if (first)
177 first= 0;
178 r= pci_first_dev(&devind, &vid, &did);
179 if (!r)
181 printf("amddev`find_dev: no first dev\n");
182 return 0;
185 else
187 r= pci_next_dev(&devind, &vid, &did);
188 if (!r)
190 printf("amddev`find_dev: no next dev\n");
191 return 0;
195 printf("amddev`find_dev: got devind %d, vid 0x%x, did 0x%x\n",
196 devind, vid, did);
198 /* Check capabilities bit in the device status register */
199 status= pci_attr_r16(devind, PCI_SR);
200 if (!(status & PSR_CAPPTR))
201 continue;
203 capptr= (pci_attr_r8(devind, PCI_CAPPTR) & PCI_CP_MASK);
204 while (capptr != 0)
206 type = pci_attr_r8(devind, capptr+CAP_TYPE);
207 next= (pci_attr_r8(devind, capptr+CAP_NEXT) &
208 PCI_CP_MASK);
209 if (type == CAP_T_SECURE_DEV)
211 printf(
212 "amddev`find_dev: found secure device\n");
213 subtype= (pci_attr_r8(devind, capptr+
214 CAP_SD_INFO) & CAP_SD_SUBTYPE_MASK);
215 if (subtype == CAP_T_SD_DEV)
217 printf("amddev`find_dev: AMD DEV\n");
218 pci_reserve(devind);
219 *devindp= devind;
220 *capaddrp= capptr;
221 return 1;
224 capptr= next;
227 return 0;
230 static u32_t read_reg(int function, int index)
232 pci_attr_w32(dev_devind, dev_capptr + DEV_OP, ((function <<
233 DEV_OP_FUNC_SHIFT) | index));
234 return pci_attr_r32(dev_devind, dev_capptr + DEV_DATA);
237 static void write_reg(int function, int index, u32_t value)
239 pci_attr_w32(dev_devind, dev_capptr + DEV_OP, ((function <<
240 DEV_OP_FUNC_SHIFT) | index));
241 pci_attr_w32(dev_devind, dev_capptr + DEV_DATA, value);
244 static void init_domain(int index)
246 size_t size, memsize;
247 phys_bytes busaddr;
249 size= 0x100000 / 8;
250 table= alloc_contig(size, AC_ALIGN4K, &busaddr);
251 if (table == NULL)
252 panic("AMDDEV","malloc failed", NO_NUM);
253 if (index == 0)
255 memset(table, 0, size);
256 memsize= 0x37000 / 8;
257 printf("memsize = 0x%x / 8\n", memsize*8);
258 memset(table, 0xff, memsize);
260 else
262 memset(table, 0xff, size);
263 memset(table, 0x00, size);
266 printf("init_domain: busaddr = %p\n", busaddr);
268 write_reg(DEVF_BASE_HI, index, 0);
269 write_reg(DEVF_BASE_LO, index, busaddr | 3);
271 printf("after write: DEVF_BASE_LO: 0x%x\n",
272 read_reg(DEVF_BASE_LO, index));
275 static void init_map(int index)
277 u32_t v, dom, busno, unit0, unit1;
279 dom= 1;
280 busno= 7;
281 unit1= 9;
282 unit0= 9;
283 v= (dom << 26) | (dom << 20) | (busno << 12) |
284 (0 << 11) | (unit1 << 6) |
285 (0 << 5) | (unit0 << 0);
286 write_reg(DEVF_MAP, index, v);
288 printf("after write: DEVF_MAP: 0x%x\n", read_reg(DEVF_MAP, index));
291 #if 0
292 static int do_add(message *m)
294 int r;
295 endpoint_t proc;
296 vir_bytes start;
297 size_t size;
298 phys_bytes busaddr;
300 proc= m->m_source;
301 start= m->m2_l1;
302 size= m->m2_l2;
304 #if 0
305 printf("amddev`do_add: got request for 0x%x@0x%x from %d\n",
306 size, start, proc);
307 #endif
309 if (start % I386_PAGE_SIZE)
311 printf("amddev`do_add: bad start 0x%x from proc %d\n",
312 start, proc);
313 return EINVAL;
315 if (size % I386_PAGE_SIZE)
317 printf("amddev`do_add: bad size 0x%x from proc %d\n",
318 size, proc);
319 return EINVAL;
321 r= sys_umap(proc, VM_D, (vir_bytes)start, size, &busaddr);
322 if (r != OK)
324 printf("amddev`do_add: umap failed for 0x%x@0x%x, proc %d\n",
325 size, start, proc);
326 return r;
328 add_range(busaddr, size);
331 #endif
333 static int do_add_phys(message *m)
335 int i;
336 phys_bytes start;
337 size_t size;
339 start= m->m2_l1;
340 size= m->m2_l2;
342 #if 0
343 printf("amddev`do_add_phys: got request for 0x%x@0x%x\n",
344 size, start);
345 #endif
347 if (start % I386_PAGE_SIZE)
349 printf("amddev`do_add_phys: bad start 0x%x\n", start);
350 return EINVAL;
352 if (size % I386_PAGE_SIZE)
354 printf("amddev`do_add_phys: bad size 0x%x\n", size);
355 return EINVAL;
357 add_range(start, size);
359 write_reg(DEVF_CR, 0, 0x10);
360 for (i= 0; i<1000000; i++)
362 if (read_reg(DEVF_CR, 0) & 0x10)
363 continue;
364 return OK;
366 return EBUSY;
369 static int do_del_phys(message *m)
371 phys_bytes start;
372 size_t size;
374 start= m->m2_l1;
375 size= m->m2_l2;
377 #if 0
378 printf("amddev`do_del_phys: got request for 0x%x@0x%x\n",
379 size, start);
380 #endif
382 if (start % I386_PAGE_SIZE)
384 printf("amddev`do_del_phys: bad start 0x%x\n", start);
385 return EINVAL;
387 if (size % I386_PAGE_SIZE)
389 printf("amddev`do_del_phys: bad size 0x%x\n", size);
390 return EINVAL;
392 del_range(start, size);
394 write_reg(DEVF_CR, 0, 0x10);
396 return OK;
399 static int do_add4pci(message *m)
401 int r, pci_bus, pci_dev, pci_func;
402 endpoint_t proc;
403 vir_bytes start;
404 size_t size;
405 phys_bytes busaddr;
407 proc= m->m_source;
408 start= m->m2_l1;
409 size= m->m2_l2;
410 pci_bus= m->m1_i1;
411 pci_dev= m->m1_i2;
412 pci_func= m->m1_i3;
414 printf(
415 "amddev`do_add4pci: got request for 0x%x@0x%x from %d for pci dev %u.%u.%u\n",
416 size, start, proc, pci_bus, pci_dev, pci_func);
418 if (start % I386_PAGE_SIZE)
420 printf("amddev`do_add4pci: bad start 0x%x from proc %d\n",
421 start, proc);
422 return EINVAL;
424 if (size % I386_PAGE_SIZE)
426 printf("amddev`do_add4pci: bad size 0x%x from proc %d\n",
427 size, proc);
428 return EINVAL;
431 printf("amddev`do_add4pci: should check with PCI\n");
433 r= sys_umap(proc, VM_D, (vir_bytes)start, size, &busaddr);
434 if (r != OK)
436 printf(
437 "amddev`do_add4pci: umap failed for 0x%x@0x%x, proc %d: %d\n",
438 size, start, proc, r);
439 return r;
442 r= adddma(proc, start, size);
443 if (r != 0)
445 r= -errno;
446 printf(
447 "amddev`do_add4pci: adddma failed for 0x%x@0x%x, proc %d: %d\n",
448 size, start, proc, r);
449 return r;
452 add_range(busaddr, size);
454 return OK;
458 static void add_range(u32_t busaddr, u32_t size)
460 u32_t o, bit;
462 #if 0
463 printf("add_range: mapping 0x%x@0x%x\n", size, busaddr);
464 #endif
466 for (o= 0; o<size; o += I386_PAGE_SIZE)
468 bit= (busaddr+o)/I386_PAGE_SIZE;
469 table[bit/8] &= ~(1 << (bit % 8));
473 static void del_range(u32_t busaddr, u32_t size)
475 u32_t o, bit;
477 #if 0
478 printf("del_range: mapping 0x%x@0x%x\n", size, busaddr);
479 #endif
481 for (o= 0; o<size; o += I386_PAGE_SIZE)
483 bit= (busaddr+o)/I386_PAGE_SIZE;
484 table[bit/8] |= (1 << (bit % 8));
488 static void do_pm_notify(message *m)
490 int r;
491 endpoint_t proc_e;
492 phys_bytes base, size;
494 if (m->m_source != PM_PROC_NR)
496 printf("amddev`do_pm_notify: notify not from PM (from %d)\n",
497 m->m_source);
498 return;
501 for (;;)
503 r= getdma(&proc_e, &base, &size);
504 if (r == -1)
506 if (errno != -EAGAIN)
508 printf(
509 "amddev`do_pm_notify: getdma failed: %d\n",
510 errno);
512 break;
515 printf(
516 "amddev`do_pm_notify: deleting 0x%x@0x%x for proc %d\n",
517 size, base, proc_e);
518 del_range(base, size);
519 r= deldma(proc_e, base, size);
520 if (r == -1)
522 printf("amddev`do_pm_notify: deldma failed: %d\n",
523 errno);
524 break;
529 static void report_exceptions(void)
531 u32_t status;
533 status= read_reg(DEVF_ERR_STATUS, 0);
534 if (!(status & 0x80000000))
535 return;
536 printf("amddev: status = 0x%x, addr-lo = 0x%x, addr-hi = 0x%x\n",
537 status, read_reg(DEVF_ERR_ADDR_LO, 0),
538 read_reg(DEVF_ERR_ADDR_HI, 0));
539 write_reg(DEVF_ERR_STATUS, 0, 0);