Home | History | Annotate | Line # | Download | only in isa
i82365_isa.c revision 1.1.2.2
      1  1.1.2.2  marc #define PCICISADEBUG
      2  1.1.2.2  marc 
      3  1.1.2.1  marc #include <sys/types.h>
      4  1.1.2.1  marc #include <sys/param.h>
      5  1.1.2.1  marc #include <sys/systm.h>
      6  1.1.2.1  marc #include <sys/device.h>
      7  1.1.2.1  marc #include <sys/extent.h>
      8  1.1.2.1  marc #include <sys/malloc.h>
      9  1.1.2.1  marc 
     10  1.1.2.1  marc #include <vm/vm.h>
     11  1.1.2.1  marc 
     12  1.1.2.1  marc #include <machine/bus.h>
     13  1.1.2.1  marc #include <machine/intr.h>
     14  1.1.2.1  marc 
     15  1.1.2.1  marc #include <dev/isa/isareg.h>
     16  1.1.2.1  marc #include <dev/isa/isavar.h>
     17  1.1.2.1  marc 
     18  1.1.2.1  marc #include <dev/pcmcia/pcmciareg.h>
     19  1.1.2.1  marc #include <dev/pcmcia/pcmciavar.h>
     20  1.1.2.1  marc #include <dev/pcmcia/pcmciachip.h>
     21  1.1.2.1  marc 
     22  1.1.2.1  marc #include <dev/ic/i82365reg.h>
     23  1.1.2.1  marc #include <dev/ic/i82365var.h>
     24  1.1.2.1  marc 
     25  1.1.2.2  marc #ifdef PCICISADEBUG
     26  1.1.2.2  marc int	pcicisa_debug = 0 /* XXX */;
     27  1.1.2.2  marc #define DPRINTF(arg) if (pcicisa_debug) printf arg;
     28  1.1.2.2  marc #else
     29  1.1.2.2  marc #define DPRINTF(arg)
     30  1.1.2.2  marc #endif
     31  1.1.2.2  marc 
     32  1.1.2.1  marc int pcic_isa_probe __P((struct device *, void *, void *));
     33  1.1.2.1  marc void pcic_isa_attach __P((struct device *, struct device *, void *));
     34  1.1.2.1  marc 
     35  1.1.2.1  marc void *pcic_isa_chip_intr_establish __P((pcmcia_chipset_handle_t,
     36  1.1.2.1  marc 					struct pcmcia_function *, int,
     37  1.1.2.1  marc 					int (*)(void *), void *));
     38  1.1.2.1  marc void pcic_isa_chip_intr_disestablish __P((pcmcia_chipset_handle_t, void *));
     39  1.1.2.1  marc 
     40  1.1.2.1  marc struct cfattach pcic_isa_ca = {
     41  1.1.2.1  marc 	sizeof(struct pcic_softc), pcic_isa_probe, pcic_isa_attach
     42  1.1.2.1  marc };
     43  1.1.2.1  marc 
     44  1.1.2.1  marc static struct pcmcia_chip_functions pcic_isa_functions = {
     45  1.1.2.1  marc     pcic_chip_mem_alloc,
     46  1.1.2.1  marc     pcic_chip_mem_free,
     47  1.1.2.1  marc     pcic_chip_mem_map,
     48  1.1.2.1  marc     pcic_chip_mem_unmap,
     49  1.1.2.1  marc 
     50  1.1.2.1  marc     pcic_chip_io_alloc,
     51  1.1.2.1  marc     pcic_chip_io_free,
     52  1.1.2.1  marc     pcic_chip_io_map,
     53  1.1.2.1  marc     pcic_chip_io_unmap,
     54  1.1.2.1  marc 
     55  1.1.2.1  marc     pcic_isa_chip_intr_establish,
     56  1.1.2.1  marc     pcic_isa_chip_intr_disestablish,
     57  1.1.2.1  marc 
     58  1.1.2.1  marc     pcic_chip_socket_enable,
     59  1.1.2.1  marc     pcic_chip_socket_disable,
     60  1.1.2.1  marc };
     61  1.1.2.1  marc 
     62  1.1.2.1  marc int
     63  1.1.2.1  marc pcic_isa_probe(parent, match, aux)
     64  1.1.2.1  marc 	struct device *parent;
     65  1.1.2.1  marc 	void *match, *aux;
     66  1.1.2.1  marc {
     67  1.1.2.1  marc     struct isa_attach_args *ia = aux;
     68  1.1.2.1  marc     bus_space_tag_t iot = ia->ia_iot;
     69  1.1.2.1  marc     bus_space_handle_t ioh, memh;
     70  1.1.2.1  marc     int val, found;
     71  1.1.2.1  marc 
     72  1.1.2.1  marc     if (bus_space_map(iot, ia->ia_iobase, PCIC_IOSIZE, 0, &ioh))
     73  1.1.2.1  marc 	return (0);
     74  1.1.2.1  marc 
     75  1.1.2.1  marc     if (ia->ia_msize == -1)
     76  1.1.2.1  marc 	ia->ia_msize = PCIC_MEMSIZE;
     77  1.1.2.1  marc 
     78  1.1.2.1  marc     if (bus_space_map(ia->ia_memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
     79  1.1.2.1  marc 	return (0);
     80  1.1.2.1  marc 
     81  1.1.2.1  marc     found = 0;
     82  1.1.2.1  marc 
     83  1.1.2.1  marc     /* this could be done with a loop, but it would violate the
     84  1.1.2.1  marc        abstraction */
     85  1.1.2.1  marc 
     86  1.1.2.1  marc     bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SA+PCIC_IDENT);
     87  1.1.2.1  marc 
     88  1.1.2.1  marc     val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
     89  1.1.2.1  marc 
     90  1.1.2.1  marc     if (pcic_ident_ok(val))
     91  1.1.2.1  marc 	found++;
     92  1.1.2.1  marc 
     93  1.1.2.1  marc 
     94  1.1.2.1  marc     bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SB+PCIC_IDENT);
     95  1.1.2.1  marc 
     96  1.1.2.1  marc     val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
     97  1.1.2.1  marc 
     98  1.1.2.1  marc     if (pcic_ident_ok(val))
     99  1.1.2.1  marc 	found++;
    100  1.1.2.1  marc 
    101  1.1.2.1  marc 
    102  1.1.2.1  marc     bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SA+PCIC_IDENT);
    103  1.1.2.1  marc 
    104  1.1.2.1  marc     val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
    105  1.1.2.1  marc 
    106  1.1.2.1  marc     if (pcic_ident_ok(val))
    107  1.1.2.1  marc 	found++;
    108  1.1.2.1  marc 
    109  1.1.2.1  marc 
    110  1.1.2.1  marc     bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SB+PCIC_IDENT);
    111  1.1.2.1  marc 
    112  1.1.2.1  marc     val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
    113  1.1.2.1  marc 
    114  1.1.2.1  marc     if (pcic_ident_ok(val))
    115  1.1.2.1  marc 	found++;
    116  1.1.2.1  marc 
    117  1.1.2.1  marc 
    118  1.1.2.1  marc     bus_space_unmap(iot, ioh, PCIC_IOSIZE);
    119  1.1.2.1  marc     bus_space_unmap(ia->ia_memt, memh, ia->ia_msize);
    120  1.1.2.1  marc 
    121  1.1.2.1  marc     if (!found)
    122  1.1.2.1  marc 	return(0);
    123  1.1.2.1  marc 
    124  1.1.2.1  marc     ia->ia_iosize = PCIC_IOSIZE;
    125  1.1.2.1  marc 
    126  1.1.2.1  marc     return(1);
    127  1.1.2.1  marc }
    128  1.1.2.1  marc 
    129  1.1.2.2  marc #ifndef PCIC_ISA_ALLOC_IOBASE
    130  1.1.2.2  marc #define PCIC_ISA_ALLOC_IOBASE 0
    131  1.1.2.2  marc #endif
    132  1.1.2.2  marc 
    133  1.1.2.2  marc #ifndef PCIC_ISA_ALLOC_IOSIZE
    134  1.1.2.2  marc #define PCIC_ISA_ALLOC_IOSIZE 0
    135  1.1.2.2  marc #endif
    136  1.1.2.2  marc 
    137  1.1.2.2  marc int pcic_isa_alloc_iobase = PCIC_ISA_ALLOC_IOBASE;
    138  1.1.2.2  marc int pcic_isa_alloc_iosize = PCIC_ISA_ALLOC_IOSIZE;
    139  1.1.2.2  marc 
    140  1.1.2.1  marc void
    141  1.1.2.1  marc pcic_isa_attach(parent, self, aux)
    142  1.1.2.1  marc      struct device *parent, *self;
    143  1.1.2.1  marc      void *aux;
    144  1.1.2.1  marc {
    145  1.1.2.1  marc     struct pcic_softc *sc = (void *)self;
    146  1.1.2.1  marc     struct isa_attach_args *ia = aux;
    147  1.1.2.1  marc     isa_chipset_tag_t ic = ia->ia_ic;
    148  1.1.2.1  marc     bus_space_tag_t iot = ia->ia_iot;
    149  1.1.2.1  marc     bus_space_tag_t memt = ia->ia_memt;
    150  1.1.2.1  marc     bus_space_handle_t ioh;
    151  1.1.2.1  marc     bus_space_handle_t memh;
    152  1.1.2.2  marc     bus_space_handle_t ioh_high;
    153  1.1.2.2  marc     int i, iobuswidth, tmp1, tmp2;
    154  1.1.2.1  marc 
    155  1.1.2.1  marc     /* Map i/o space. */
    156  1.1.2.1  marc     if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh))
    157  1.1.2.1  marc 	panic("pcic_isa_attach: can't map i/o space");
    158  1.1.2.1  marc 
    159  1.1.2.1  marc     /* Map mem space. */
    160  1.1.2.1  marc     if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
    161  1.1.2.1  marc 	panic("pcic_isa_attach: can't map i/o space");
    162  1.1.2.1  marc 
    163  1.1.2.1  marc     sc->membase = ia->ia_maddr;
    164  1.1.2.1  marc     sc->subregionmask = (1<<(ia->ia_msize/PCIC_MEM_PAGESIZE))-1;
    165  1.1.2.1  marc 
    166  1.1.2.1  marc     sc->intr_est = ic;
    167  1.1.2.1  marc     sc->pct = (pcmcia_chipset_tag_t) &pcic_isa_functions;
    168  1.1.2.1  marc 
    169  1.1.2.1  marc     sc->iot = iot;
    170  1.1.2.1  marc     sc->ioh = ioh;
    171  1.1.2.1  marc     sc->memt = memt;
    172  1.1.2.1  marc     sc->memh = memh;
    173  1.1.2.1  marc 
    174  1.1.2.1  marc     /* allocate an irq.  it will be used by both controllers.  I could
    175  1.1.2.1  marc        use two different interrupts, but interrupts are relatively
    176  1.1.2.1  marc        scarce, shareable, and for PCIC controllers, very infrequent. */
    177  1.1.2.1  marc 
    178  1.1.2.1  marc     if ((sc->irq = ia->ia_irq) == IRQUNK) {
    179  1.1.2.1  marc 	/* XXX CHECK RETURN VALUE */
    180  1.1.2.1  marc 	(void) isa_intr_alloc(ic,
    181  1.1.2.1  marc 			      PCIC_CSC_INTR_IRQ_VALIDMASK,
    182  1.1.2.1  marc 			      IST_EDGE, &sc->irq);
    183  1.1.2.1  marc 	printf(": using irq %d", sc->irq);
    184  1.1.2.1  marc     }
    185  1.1.2.1  marc 
    186  1.1.2.1  marc     printf("\n");
    187  1.1.2.1  marc 
    188  1.1.2.1  marc     pcic_attach(sc);
    189  1.1.2.1  marc 
    190  1.1.2.2  marc     /* figure out how wide the isa bus is.  Do this by checking if
    191  1.1.2.2  marc        the pcic controller is mirrored 0x400 above where we expect it
    192  1.1.2.2  marc        to be. */
    193  1.1.2.2  marc 
    194  1.1.2.2  marc     iobuswidth = 12;
    195  1.1.2.2  marc 
    196  1.1.2.2  marc     /* Map i/o space. */
    197  1.1.2.2  marc     if (bus_space_map(iot, ia->ia_iobase+0x400, ia->ia_iosize, 0, &ioh_high))
    198  1.1.2.2  marc 	panic("pcic_isa_attach: can't map high i/o space");
    199  1.1.2.2  marc 
    200  1.1.2.2  marc     for (i=0; i<PCIC_NSLOTS; i++) {
    201  1.1.2.2  marc 	if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) {
    202  1.1.2.2  marc 	    /* read the ident flags from the normal space
    203  1.1.2.2  marc 	       and from the mirror, and compare them */
    204  1.1.2.2  marc 
    205  1.1.2.2  marc 	    bus_space_write_1(iot, ioh, PCIC_REG_INDEX,
    206  1.1.2.2  marc 			      sc->handle[i].sock+PCIC_IDENT);
    207  1.1.2.2  marc 	    tmp1 = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
    208  1.1.2.2  marc 
    209  1.1.2.2  marc 	    bus_space_write_1(iot, ioh_high, PCIC_REG_INDEX,
    210  1.1.2.2  marc 			      sc->handle[i].sock+PCIC_IDENT);
    211  1.1.2.2  marc 	    tmp2 = bus_space_read_1(iot, ioh_high, PCIC_REG_DATA);
    212  1.1.2.2  marc 
    213  1.1.2.2  marc 	    if (tmp1 == tmp2)
    214  1.1.2.2  marc 		iobuswidth = 10;
    215  1.1.2.2  marc 	}
    216  1.1.2.2  marc     }
    217  1.1.2.2  marc 
    218  1.1.2.2  marc     bus_space_free(iot, ioh_high, ia->ia_iosize);
    219  1.1.2.2  marc 
    220  1.1.2.2  marc /* XXX mycroft recommends I/O space range 0x400-0xfff .  I should put
    221  1.1.2.2  marc    this in a header somewhere */
    222  1.1.2.2  marc 
    223  1.1.2.2  marc /* XXX some hardware doesn't seem to grok addresses in 0x400 range--
    224  1.1.2.2  marc    apparently missing a bit or more of address lines.
    225  1.1.2.2  marc    (e.g. CIRRUS_PD672X with Linksys EthernetCard ne2000 clone in TI
    226  1.1.2.2  marc    TravelMate 5000--not clear which is at fault)
    227  1.1.2.2  marc 
    228  1.1.2.2  marc    Add a kludge to detect 10 bit wide buses and deal with them, and
    229  1.1.2.2  marc    also a config file option to override the probe. */
    230  1.1.2.2  marc 
    231  1.1.2.2  marc     if (iobuswidth == 10) {
    232  1.1.2.2  marc 	sc->iobase = 0x300;
    233  1.1.2.2  marc 	sc->iosize = 0x0ff;
    234  1.1.2.2  marc     } else {
    235  1.1.2.2  marc 	sc->iobase = 0x400;
    236  1.1.2.2  marc 	sc->iosize = 0xbff;
    237  1.1.2.2  marc     }
    238  1.1.2.2  marc 
    239  1.1.2.2  marc     DPRINTF(("%s: bus_space_alloc range 0x%04lx-0x%04lx (probed)\n",
    240  1.1.2.2  marc 	     sc->dev.dv_xname, (long) sc->iobase,
    241  1.1.2.2  marc 	     (long) sc->iobase+sc->iosize));
    242  1.1.2.2  marc 
    243  1.1.2.2  marc     if (pcic_isa_alloc_iobase && pcic_isa_alloc_iosize) {
    244  1.1.2.2  marc 	sc->iobase = pcic_isa_alloc_iobase;
    245  1.1.2.2  marc 	sc->iosize = pcic_isa_alloc_iosize;
    246  1.1.2.2  marc 
    247  1.1.2.2  marc 	DPRINTF(("%s: bus_space_alloc range 0x%04lx-0x%04lx (config override)\n",
    248  1.1.2.2  marc 		 sc->dev.dv_xname, (long) sc->iobase,
    249  1.1.2.2  marc 		 (long) sc->iobase+sc->iosize));
    250  1.1.2.2  marc     }
    251  1.1.2.2  marc 
    252  1.1.2.1  marc     sc->ih = isa_intr_establish(ic, sc->irq, IST_EDGE, IPL_TTY, pcic_intr, sc);
    253  1.1.2.1  marc 
    254  1.1.2.1  marc     pcic_attach_sockets(sc);
    255  1.1.2.1  marc }
    256  1.1.2.1  marc 
    257  1.1.2.1  marc /* allow patching or kernel option file override of available IRQs.
    258  1.1.2.1  marc    Useful if order of probing would screw up other devices, or if PCIC
    259  1.1.2.1  marc    hardware/cards have trouble with certain interrupt lines. */
    260  1.1.2.1  marc 
    261  1.1.2.1  marc #ifndef PCIC_INTR_ALLOC_MASK
    262  1.1.2.1  marc #define	PCIC_INTR_ALLOC_MASK	0xffff
    263  1.1.2.1  marc #endif
    264  1.1.2.1  marc 
    265  1.1.2.1  marc int	pcic_intr_alloc_mask = PCIC_INTR_ALLOC_MASK;
    266  1.1.2.1  marc 
    267  1.1.2.1  marc void *
    268  1.1.2.1  marc pcic_isa_chip_intr_establish(pch, pf, ipl, fct, arg)
    269  1.1.2.1  marc      pcmcia_chipset_handle_t pch;
    270  1.1.2.1  marc      struct pcmcia_function *pf;
    271  1.1.2.1  marc      int ipl;
    272  1.1.2.1  marc      int (*fct)(void *);
    273  1.1.2.1  marc      void *arg;
    274  1.1.2.1  marc {
    275  1.1.2.1  marc     struct pcic_handle *h = (struct pcic_handle *) pch;
    276  1.1.2.1  marc     int irq, ist;
    277  1.1.2.1  marc     void *ih;
    278  1.1.2.1  marc     int reg;
    279  1.1.2.1  marc 
    280  1.1.2.1  marc     if (pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)
    281  1.1.2.1  marc 	ist = IST_LEVEL;
    282  1.1.2.1  marc     else if (pf->cfe->flags & PCMCIA_CFE_IRQPULSE)
    283  1.1.2.1  marc 	ist = IST_PULSE;
    284  1.1.2.1  marc     else
    285  1.1.2.1  marc 	ist = IST_LEVEL;
    286  1.1.2.1  marc 
    287  1.1.2.1  marc     if (isa_intr_alloc(h->sc->intr_est,
    288  1.1.2.1  marc     		       PCIC_INTR_IRQ_VALIDMASK & pcic_intr_alloc_mask,
    289  1.1.2.1  marc     		       ist, &irq))
    290  1.1.2.1  marc 	return(NULL);
    291  1.1.2.1  marc     if (!(ih = isa_intr_establish(h->sc->intr_est, irq, ist, ipl, fct, arg)))
    292  1.1.2.1  marc 	return(NULL);
    293  1.1.2.1  marc 
    294  1.1.2.1  marc     reg = pcic_read(h, PCIC_INTR);
    295  1.1.2.1  marc     reg &= ~PCIC_INTR_IRQ_MASK;
    296  1.1.2.1  marc     reg |= irq;
    297  1.1.2.1  marc     pcic_write(h, PCIC_INTR, reg);
    298  1.1.2.1  marc 
    299  1.1.2.2  marc     h->ih_irq = irq;
    300  1.1.2.2  marc 
    301  1.1.2.1  marc     printf("%s: card irq %d\n", h->pcmcia->dv_xname, irq);
    302  1.1.2.1  marc 
    303  1.1.2.1  marc     return(ih);
    304  1.1.2.1  marc }
    305  1.1.2.1  marc 
    306  1.1.2.1  marc void pcic_isa_chip_intr_disestablish(pch, ih)
    307  1.1.2.1  marc      pcmcia_chipset_handle_t pch;
    308  1.1.2.1  marc      void *ih;
    309  1.1.2.1  marc {
    310  1.1.2.1  marc     struct pcic_handle *h = (struct pcic_handle *) pch;
    311  1.1.2.1  marc     int reg;
    312  1.1.2.2  marc 
    313  1.1.2.2  marc     h->ih_irq = 0;
    314  1.1.2.1  marc 
    315  1.1.2.1  marc     reg = pcic_read(h, PCIC_INTR);
    316  1.1.2.1  marc     reg &= ~(PCIC_INTR_IRQ_MASK|PCIC_INTR_ENABLE);
    317  1.1.2.1  marc     pcic_write(h, PCIC_INTR, reg);
    318  1.1.2.1  marc 
    319  1.1.2.1  marc     isa_intr_disestablish(h->sc->intr_est, ih);
    320  1.1.2.1  marc }
    321