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