xref: /netbsd-src/sys/arch/sun3/sun3/obio.c (revision 4b30c543a0b21e3ba94f2c569e9a82b4fdb2075f)
1 #include "sys/systm.h"
2 #include "sys/device.h"
3 
4 #include "machine/autoconf.h"
5 #include "machine/obio.h"
6 #include "machine/pte.h"
7 #include "machine/param.h"
8 #include "machine/mon.h"
9 #include "machine/isr.h"
10 
11 #define ALL 0xFF
12 
13 unsigned char *interrupt_reg = NULL;
14 vm_offset_t eeprom_va = NULL;
15 vm_offset_t memerr_va = NULL;
16 
17 static struct obio_internal {
18     vm_offset_t *obio_internal_va;
19     vm_offset_t obio_addr;
20     unsigned char obio_cpu_mask;
21     unsigned int obio_size;
22     int obio_rw;
23 } obio_internal_dev[] = {
24     {&eeprom_va,                     OBIO_EEPROM,   ALL, OBIO_EEPROM_SIZE  ,1},
25     {(vm_offset_t *) &interrupt_reg, OBIO_INTERREG, ALL, OBIO_INTERREG_SIZE,1},
26     {&memerr_va,                     OBIO_MEMERR,   ALL, OBIO_MEMERR_SIZE  ,1},
27     {NULL,                           0,               0, 0                 ,0}
28 /*  {&ecc_va, OBIO_MEMERR,  ALL, OBIO_MEMERR_SIZE },        */
29 };
30 
31 extern void obioattach __P((struct device *, struct device *, void *));
32 
33 struct obio_softc {
34     struct device obio_dev;
35 };
36 
37 struct cfdriver obiocd =
38 { NULL, "obio", always_match, obioattach, DV_DULL,
39       sizeof(struct obio_softc), 0};
40 
41 void obio_print(addr, level)
42      caddr_t addr;
43      int level;
44 {
45     printf(" addr 0x%x", addr);
46     if (level >=0)
47 	printf(" level %d", level);
48 }
49 
50 void obioattach(parent, self, args)
51      struct device *parent;
52      struct device *self;
53      void *args;
54 {
55     struct cfdata *new_match;
56 
57     printf("\n");
58     while (1) {
59 	new_match = config_search(NULL, self, NULL);
60 	if (!new_match) break;
61 	config_attach(self, new_match, NULL, NULL);
62     }
63 }
64 
65 /*
66  * this routine "configures" any internal OBIO devices which must be
67  * accessible before the mainline OBIO autoconfiguration as part of
68  * configure().
69  *
70  * In reality this maps in a few control registers.  VA space is allocated
71  * out of the high_segment...
72  *
73  */
74 void obio_internal_configure()
75 {
76     struct obio_internal *oip;
77     extern unsigned char cpu_machine_id;
78     vm_offset_t va, high_segment_alloc(), pte_proto,obio_pa;
79     int npages;
80 
81     for (oip = obio_internal_dev; oip->obio_internal_va; oip++) {
82 	if ((cpu_machine_id & oip->obio_cpu_mask) == 0) continue;
83 	npages = PA_PGNUM(sun3_round_page(oip->obio_size));
84 	va = high_segment_alloc(npages);
85 	if (!va)
86 	   mon_panic("obio_internal_configure: short pages for internal devs");
87 	*oip->obio_internal_va = va;
88 	pte_proto = PG_VALID|PG_SYSTEM|PG_NC|MAKE_PGTYPE(PG_OBIO);
89 	if (oip->obio_rw)
90 	    pte_proto |= PG_WRITE;
91 	obio_pa = oip->obio_addr;
92 	for (; npages != 0; npages--, va += NBPG, obio_pa += NBPG)
93 	    set_pte(va, pte_proto | PA_PGNUM(obio_pa));
94     }
95 }
96 
97 caddr_t obio_alloc(obio_addr, obio_size, obio_flags)
98      caddr_t obio_addr;
99      int obio_size;
100      int obio_flags;
101 {
102     int npages;
103     vm_offset_t va, high_segment_alloc(), obio_pa, obio_va, pte_proto;
104 
105     npages = PA_PGNUM(sun3_round_page(obio_size));
106     if (!npages)
107 	panic("obio_alloc: attempt to allocate 0 pages for obio");
108     va = high_segment_alloc(npages);
109     if (!va)
110 	va = (vm_offset_t) obio_vm_alloc(npages);
111     if (!va)
112 	panic("obio_alloc: unable to allocate va for obio mapping");
113     pte_proto = PG_VALID|PG_SYSTEM|MAKE_PGTYPE(PG_OBIO);
114     if ((obio_flags & OBIO_CACHE) == 0)
115 	pte_proto |= PG_NC;
116     if (obio_flags & OBIO_WRITE)
117 	pte_proto |= PG_WRITE;
118     obio_va = va;
119     obio_pa = (vm_offset_t) obio_addr;
120     for (; npages ; npages--, obio_va += NBPG, obio_pa += NBPG)
121 	set_pte(obio_va, pte_proto | PA_PGNUM(obio_pa));
122     return (caddr_t) va;
123 }
124 
125