1 /* $NetBSD: rtfps.c,v 1.7 1994/11/18 22:25:19 mycroft Exp $ */ 2 3 /* 4 * Multi-port serial card interrupt demuxing support. 5 * Roland McGrath 3/20/94 6 * The author disclaims copyright and places this file in the public domain. 7 * 8 * Modified by: Charles Hannum, 3/22/94 9 */ 10 11 #include <sys/param.h> 12 #include <sys/device.h> 13 14 #include <machine/pio.h> 15 16 #include <i386/isa/isavar.h> 17 18 struct rtfps_softc { 19 struct device sc_dev; 20 struct intrhand sc_ih; 21 22 int sc_iobase; 23 int sc_irqport; 24 int sc_alive; /* mask of slave units attached */ 25 void *sc_slaves[4]; /* com device unit numbers */ 26 }; 27 28 int rtfpsprobe(); 29 void rtfpsattach(); 30 int rtfpsintr __P((struct rtfps_softc *)); 31 32 struct cfdriver rtfpscd = { 33 NULL, "rtfps", rtfpsprobe, rtfpsattach, DV_TTY, sizeof(struct rtfps_softc), 1 34 }; 35 36 int 37 rtfpsprobe(parent, self, aux) 38 struct device *parent, *self; 39 void *aux; 40 { 41 struct isa_attach_args *ia = aux; 42 43 /* 44 * Do the normal com probe for the first UART and assume 45 * its presence means there is a multiport board there. 46 * XXX Needs more robustness. 47 */ 48 ia->ia_iosize = 4 * 8; 49 return comprobe1(ia->ia_iobase); 50 } 51 52 struct rtfps_attach_args { 53 int ra_slave; 54 }; 55 56 int 57 rtfpssubmatch(parent, match, aux) 58 struct device *parent; 59 void *match, *aux; 60 { 61 struct rtfps_softc *sc = (void *)parent; 62 struct device *self = match; 63 struct isa_attach_args *ia = aux; 64 struct rtfps_attach_args *ra = ia->ia_aux; 65 struct cfdata *cf = self->dv_cfdata; 66 67 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ra->ra_slave) 68 return (0); 69 return ((*cf->cf_driver->cd_match)(parent, match, ia)); 70 } 71 72 int 73 rtfpsprint(aux, rtfps) 74 void *aux; 75 char *rtfps; 76 { 77 struct isa_attach_args *ia = aux; 78 struct rtfps_attach_args *ra = ia->ia_aux; 79 80 printf(" slave %d", ra->ra_slave); 81 } 82 83 void 84 rtfpsattach(parent, self, aux) 85 struct device *parent, *self; 86 void *aux; 87 { 88 struct rtfps_softc *sc = (void *)self; 89 struct isa_attach_args *ia = aux; 90 struct rtfps_attach_args ra; 91 struct isa_attach_args isa; 92 static int irqport[] = { 93 IOBASEUNK, IOBASEUNK, IOBASEUNK, IOBASEUNK, 94 IOBASEUNK, IOBASEUNK, IOBASEUNK, IOBASEUNK, 95 IOBASEUNK, 0x2f2, 0x6f2, 0x6f3, 96 IOBASEUNK, IOBASEUNK, IOBASEUNK, IOBASEUNK 97 }; 98 99 sc->sc_iobase = ia->ia_iobase; 100 101 if (ia->ia_irq >= 16 || irqport[ia->ia_irq] == IOBASEUNK) 102 panic("rtfpsattach: invalid irq"); 103 sc->sc_irqport = irqport[ia->ia_irq]; 104 105 outb(sc->sc_irqport, 0); 106 107 printf("\n"); 108 109 isa.ia_aux = &ra; 110 for (ra.ra_slave = 0; ra.ra_slave < 4; ra.ra_slave++) { 111 void *match; 112 isa.ia_iobase = sc->sc_iobase + 8 * ra.ra_slave; 113 isa.ia_iosize = 0x666; 114 isa.ia_irq = IRQUNK; 115 isa.ia_drq = DRQUNK; 116 isa.ia_msize = 0; 117 if ((match = config_search(rtfpssubmatch, self, &isa)) != 0) { 118 sc->sc_slaves[ra.ra_slave] = match; 119 sc->sc_alive |= 1 << ra.ra_slave; 120 config_attach(self, match, &isa, rtfpsprint); 121 } 122 } 123 124 sc->sc_ih.ih_fun = rtfpsintr; 125 sc->sc_ih.ih_arg = sc; 126 sc->sc_ih.ih_level = IPL_TTY; 127 intr_establish(ia->ia_irq, &sc->sc_ih); 128 } 129 130 int 131 rtfpsintr(sc) 132 struct rtfps_softc *sc; 133 { 134 int iobase = sc->sc_iobase; 135 int alive = sc->sc_alive; 136 137 outb(sc->sc_irqport, 0); 138 139 #define TRY(n) \ 140 if (alive & (1 << (n))) \ 141 comintr(sc->sc_slaves[n]); 142 TRY(0); 143 TRY(1); 144 TRY(2); 145 TRY(3); 146 #undef TRY 147 148 return (1); 149 } 150