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