rtfps.c revision 1.8
1/* $NetBSD: rtfps.c,v 1.8 1995/01/02 22:27:47 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 18struct 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 28int rtfpsprobe(); 29void rtfpsattach(); 30int rtfpsintr __P((struct rtfps_softc *)); 31 32struct cfdriver rtfpscd = { 33 NULL, "rtfps", rtfpsprobe, rtfpsattach, DV_TTY, sizeof(struct rtfps_softc) 34}; 35 36int 37rtfpsprobe(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 52struct rtfps_attach_args { 53 int ra_slave; 54}; 55 56int 57rtfpssubmatch(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 72int 73rtfpsprint(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 83void 84rtfpsattach(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 struct cfdata *cf; 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 ((cf = config_search(rtfpssubmatch, self, &isa)) != 0) { 118 config_attach(self, cf, &isa, rtfpsprint); 119 sc->sc_slaves[ra.ra_slave] = 120 cf->cf_driver->cd_devs[cf->cf_unit]; 121 sc->sc_alive |= 1 << ra.ra_slave; 122 } 123 } 124 125 sc->sc_ih.ih_fun = rtfpsintr; 126 sc->sc_ih.ih_arg = sc; 127 sc->sc_ih.ih_level = IPL_TTY; 128 intr_establish(ia->ia_irq, &sc->sc_ih); 129} 130 131int 132rtfpsintr(sc) 133 struct rtfps_softc *sc; 134{ 135 int iobase = sc->sc_iobase; 136 int alive = sc->sc_alive; 137 138 outb(sc->sc_irqport, 0); 139 140#define TRY(n) \ 141 if (alive & (1 << (n))) \ 142 comintr(sc->sc_slaves[n]); 143 TRY(0); 144 TRY(1); 145 TRY(2); 146 TRY(3); 147#undef TRY 148 149 return (1); 150} 151