1 /* 2 * Multi-port serial card interrupt demuxing support. 3 * Roland McGrath 3/20/94 4 * The author disclaims copyright and places this file in the public domain. 5 * 6 * Modified by: Charles Hannum, 3/22/94 7 * 8 * $Id: rtfps.c,v 1.1 1994/08/07 10:45:53 mycroft Exp $ 9 */ 10 11 #include <sys/param.h> 12 #include <sys/device.h> 13 14 #include <machine/pio.h> 15 16 #ifndef NEWCONFIG 17 #include <i386/isa/isa_device.h> 18 #endif 19 #include <i386/isa/icu.h> 20 #include <i386/isa/isavar.h> 21 22 struct rtfps_softc { 23 struct device sc_dev; 24 struct intrhand sc_ih; 25 26 u_short sc_iobase; 27 u_short sc_irq; 28 int sc_alive; /* mask of slave units attached */ 29 void *sc_slaves[4]; /* com device unit numbers */ 30 }; 31 32 int rtfpsprobe(); 33 void rtfpsattach(); 34 int rtfpsintr __P((struct rtfps_softc *)); 35 void rt_resetintr __P((/*u_short*/)); 36 37 struct cfdriver rtfpscd = { 38 NULL, "rtfps", rtfpsprobe, rtfpsattach, DV_TTY, sizeof(struct rtfps_softc) 39 }; 40 41 int 42 rtfpsprobe(parent, self, aux) 43 struct device *parent, *self; 44 void *aux; 45 { 46 struct isa_attach_args *ia = aux; 47 48 /* 49 * Do the normal com probe for the first UART and assume 50 * its presence means there is a multiport board there. 51 * XXX Needs more robustness. 52 */ 53 ia->ia_iosize = 4 * 8; 54 return comprobe1(ia->ia_iobase); 55 } 56 57 struct rtfps_attach_args { 58 u_short ra_iobase; 59 int ra_slave; 60 }; 61 62 int 63 rtfpssubmatch(parent, self, aux) 64 struct device *parent, *self; 65 void *aux; 66 { 67 struct rtfps_softc *sc = (void *)parent; 68 struct rtfps_attach_args *aa = aux; 69 struct cfdata *cf = self->dv_cfdata; 70 int found, frobbed = 0; 71 #ifdef NEWCONFIG 72 73 #define cf_slave cf_loc[6] 74 if (cf->cf_slave != -1 && cf->cf_slave != aa->ra_slave) 75 return 0; 76 if (cf->cf_iobase == IOBASEUNK) { 77 frobbed = 1; 78 cf->cf_iobase = aa->ra_iobase; 79 } 80 #undef cf_slave 81 #else 82 struct isa_device *id = (void *)cf->cf_loc; 83 84 if (id->id_physid != -1 && id->id_physid != aa->ra_slave) 85 return 0; 86 if (id->id_iobase == 0) { 87 frobbed = 1; 88 id->id_iobase = aa->ra_iobase; 89 } 90 #endif 91 found = isasubmatch(parent, self, aux); 92 if (found) { 93 sc->sc_slaves[aa->ra_slave] = self; 94 sc->sc_alive |= 1 << aa->ra_slave; 95 } 96 /* 97 * If we changed the iobase, we have to set it back now, because it 98 * might be a clone device, and the iobase wouldn't get set properly on 99 * the next iteration. 100 */ 101 #ifdef NEWCONFIG 102 if (frobbed) 103 cf->cf_iobase = IOBASEUNK; 104 #else 105 if (frobbed) 106 id->id_iobase = 0; 107 #endif 108 return found; 109 } 110 111 void 112 rtfpsattach(parent, self, aux) 113 struct device *parent, *self; 114 void *aux; 115 { 116 struct rtfps_softc *sc = (void *)self; 117 struct isa_attach_args *ia = aux; 118 struct rtfps_attach_args aa; 119 120 sc->sc_iobase = ia->ia_iobase; 121 sc->sc_irq = ia->ia_irq; 122 123 rt_resetintr(ia->ia_irq); 124 125 printf("\n"); 126 127 for (aa.ra_slave = 0, aa.ra_iobase = sc->sc_iobase; 128 aa.ra_slave < 4; 129 aa.ra_slave++, aa.ra_iobase += 8) 130 config_search(rtfpssubmatch, self, &aa); 131 132 sc->sc_ih.ih_fun = rtfpsintr; 133 sc->sc_ih.ih_arg = sc; 134 sc->sc_ih.ih_level = IPL_TTY; 135 intr_establish(ia->ia_irq, &sc->sc_ih); 136 } 137 138 int 139 rtfpsintr(sc) 140 struct rtfps_softc *sc; 141 { 142 u_short iobase = sc->sc_iobase; 143 int alive = sc->sc_alive; 144 145 rt_resetintr(sc->sc_irq); 146 147 #define TRY(n) \ 148 if (alive & (1 << (n))) \ 149 comintr(sc->sc_slaves[n]); 150 TRY(0); 151 TRY(1); 152 TRY(2); 153 TRY(3); 154 #undef TRY 155 156 return 1; 157 } 158 159 void 160 rt_resetintr(irq) 161 u_short irq; 162 { 163 164 switch (irq) { 165 case IRQ9: 166 outb(0x2f2, 0); 167 break; 168 case IRQ10: 169 outb(0x6f2, 0); 170 break; 171 case IRQ11: 172 outb(0x6f3, 0); 173 break; 174 default: 175 panic("rt_resetintr: invalid irq"); 176 } 177 } 178