Home | History | Annotate | Line # | Download | only in isa
ast.c revision 1.7
      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: ast.c,v 1.7 1994/04/07 06:50:15 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/isavar.h>
     20 
     21 struct ast_softc {
     22 	struct device sc_dev;
     23 	struct intrhand sc_ih;
     24 
     25 	u_short sc_iobase;
     26 	int sc_alive;		/* mask of slave units attached */
     27 	void *sc_slaves[4];	/* com device unit numbers */
     28 };
     29 
     30 int astprobe();
     31 void astattach();
     32 int astintr __P((struct ast_softc *));
     33 
     34 struct cfdriver astcd = {
     35 	NULL, "ast", astprobe, astattach, DV_TTY, sizeof(struct ast_softc)
     36 };
     37 
     38 int
     39 astprobe(parent, self, aux)
     40 	struct device *parent, *self;
     41 	void *aux;
     42 {
     43 	struct isa_attach_args *ia = aux;
     44 
     45 	/*
     46 	 * Do the normal com probe for the first UART and assume
     47 	 * its presence means there is a multiport board there.
     48 	 * XXX Needs more robustness.
     49 	 */
     50 	ia->ia_iosize = 4 * 8;
     51 	return comprobe1(ia->ia_iobase);
     52 }
     53 
     54 struct ast_attach_args {
     55 	u_short aa_iobase;
     56 	int aa_slave;
     57 };
     58 
     59 int
     60 astsubmatch(parent, self, aux)
     61 	struct device *parent, *self;
     62 	void *aux;
     63 {
     64 	struct ast_softc *sc = (void *)parent;
     65 	struct ast_attach_args *aa = aux;
     66 	struct cfdata *cf = self->dv_cfdata;
     67 	int found, frobbed = 0;
     68 #ifdef NEWCONFIG
     69 
     70 #define cf_slave cf_loc[6]
     71 	if (cf->cf_slave != -1 && cf->cf_slave != aa->aa_slave)
     72 		return 0;
     73 	if (cf->cf_iobase == IOBASEUNK) {
     74 		frobbed = 1;
     75 		cf->cf_iobase = aa->aa_iobase;
     76 	}
     77 #undef cf_slave
     78 #else
     79 	struct isa_device *id = (void *)cf->cf_loc;
     80 
     81 	if (id->id_physid != -1 && id->id_physid != aa->aa_slave)
     82 		return 0;
     83 	if (id->id_iobase == 0) {
     84 		frobbed = 1;
     85 		id->id_iobase = aa->aa_iobase;
     86 	}
     87 #endif
     88 	found = isasubmatch(parent, self, aux);
     89 	if (found) {
     90 		sc->sc_slaves[aa->aa_slave] = self;
     91 		sc->sc_alive |= 1 << aa->aa_slave;
     92 	}
     93 	/*
     94 	 * If we changed the iobase, we have to set it back now, because it
     95 	 * might be a clone device, and the iobase wouldn't get set properly on
     96 	 * the next iteration.
     97 	 */
     98 #ifdef NEWCONFIG
     99 	if (frobbed)
    100 		cf->cf_iobase = IOBASEUNK;
    101 #else
    102 	if (frobbed)
    103 		id->id_iobase = 0;
    104 #endif
    105 	return found;
    106 }
    107 
    108 void
    109 astattach(parent, self, aux)
    110 	struct device *parent, *self;
    111 	void *aux;
    112 {
    113 	struct ast_softc *sc = (void *)self;
    114 	struct isa_attach_args *ia = aux;
    115 	struct ast_attach_args aa;
    116 
    117 	/*
    118 	 * Enable the master interrupt.
    119 	 */
    120 	sc->sc_iobase = ia->ia_iobase;
    121 	outb(sc->sc_iobase | 0x1f, 0x80);
    122 	printf("\n");
    123 
    124 	for (aa.aa_slave = 0, aa.aa_iobase = sc->sc_iobase;
    125 	    aa.aa_slave < 4;
    126 	    aa.aa_slave++, aa.aa_iobase += 8)
    127 		config_search(astsubmatch, self, &aa);
    128 
    129 	sc->sc_ih.ih_fun = astintr;
    130 	sc->sc_ih.ih_arg = sc;
    131 	sc->sc_ih.ih_level = IPL_TTY;
    132 	intr_establish(ia->ia_irq, &sc->sc_ih);
    133 }
    134 
    135 int
    136 astintr(sc)
    137 	struct ast_softc *sc;
    138 {
    139 	u_short iobase = sc->sc_iobase;
    140 	int alive = sc->sc_alive;
    141 	int bits;
    142 
    143 	bits = inb(iobase | 0x1f) & alive;
    144 	if (bits == alive)
    145 		return 0;
    146 
    147 	do {
    148 #define	TRY(n) \
    149 		if ((bits & (1 << (n))) == 0) \
    150 			comintr(sc->sc_slaves[n]);
    151 		TRY(0);
    152 		TRY(1);
    153 		TRY(2);
    154 		TRY(3);
    155 #undef TRY
    156 		bits = inb(iobase | 0x1f) & alive;
    157  	} while (bits != alive);
    158 
    159 	return 1;
    160 }
    161