rtfps.c revision 1.5
1/* $NetBSD: rtfps.c,v 1.5 1994/11/07 09:03:51 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 u_short sc_iobase; 23 u_short 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 *)); 31void rt_resetintr __P((/*u_short*/)); 32 33struct cfdriver rtfpscd = { 34 NULL, "rtfps", rtfpsprobe, rtfpsattach, DV_TTY, sizeof(struct rtfps_softc), 1 35}; 36 37int 38rtfpsprobe(parent, self, aux) 39 struct device *parent, *self; 40 void *aux; 41{ 42 struct isa_attach_args *ia = aux; 43 44 /* 45 * Do the normal com probe for the first UART and assume 46 * its presence means there is a multiport board there. 47 * XXX Needs more robustness. 48 */ 49 ia->ia_iosize = 4 * 8; 50 return comprobe1(ia->ia_iobase); 51} 52 53struct rtfps_attach_args { 54 int ra_slave; 55}; 56 57int 58rtfpssubmatch(parent, match, aux) 59 struct device *parent; 60 void *match, *aux; 61{ 62 struct rtfps_softc *sc = (void *)parent; 63 struct device *self = match; 64 struct isa_attach_args *ia = aux; 65 struct rtfps_attach_args *ra = ia->ia_aux; 66 struct cfdata *cf = self->dv_cfdata; 67 68 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ra->ra_slave) 69 return (0); 70 return ((*cf->cf_driver->cd_match)(parent, match, ia)); 71} 72 73int 74rtfpsprint(aux, rtfps) 75 void *aux; 76 char *rtfps; 77{ 78 struct isa_attach_args *ia = aux; 79 struct rtfps_attach_args *ra = ia->ia_aux; 80 81 printf(" slave %d", ra->ra_slave); 82} 83 84void 85rtfpsattach(parent, self, aux) 86 struct device *parent, *self; 87 void *aux; 88{ 89 struct rtfps_softc *sc = (void *)self; 90 struct isa_attach_args *ia = aux; 91 struct rtfps_attach_args ra; 92 struct isa_attach_args isa; 93 static u_short irqport[] = { 94 -1, -1, -1, -1, 95 -1, -1, -1, -1, 96 -1, 0x2f2, 0x6f2, 0x6f3, 97 -1, -1, -1, -1 98 }; 99 100 sc->sc_iobase = ia->ia_iobase; 101 102 if (ia->ia_irq >= 16 || irqport[ia->ia_irq] == (u_short)-1) 103 panic("rtfpsattach: invalid irq"); 104 sc->sc_irqport = irqport[ia->ia_irq]; 105 106 outb(sc->sc_irqport, 0); 107 108 printf("\n"); 109 110 isa.ia_aux = &ra; 111 for (ra.ra_slave = 0; ra.ra_slave < 4; ra.ra_slave++) { 112 void *match; 113 isa.ia_iobase = sc->sc_iobase + 8 * ra.ra_slave; 114 isa.ia_iosize = 0x666; 115 isa.ia_irq = IRQUNK; 116 isa.ia_drq = DRQUNK; 117 isa.ia_msize = 0; 118 if ((match = config_search(rtfpssubmatch, self, &isa)) != 0) { 119 sc->sc_slaves[ra.ra_slave] = match; 120 sc->sc_alive |= 1 << ra.ra_slave; 121 config_attach(self, match, &isa, rtfpsprint); 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 u_short 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