[BACK]Return to i82365_isa.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / isa

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/dev/isa/i82365_isa.c between version 1.1 and 1.1.2.3

version 1.1, 1997/08/28 23:00:53 version 1.1.2.3, 1997/10/16 02:57:10
Line 0 
Line 1 
   /*      $NetBSD$        */
   
   #define PCICISADEBUG
   
   #include <sys/types.h>
   #include <sys/param.h>
   #include <sys/systm.h>
   #include <sys/device.h>
   #include <sys/extent.h>
   #include <sys/malloc.h>
   
   #include <vm/vm.h>
   
   #include <machine/bus.h>
   #include <machine/intr.h>
   
   #include <dev/isa/isareg.h>
   #include <dev/isa/isavar.h>
   
   #include <dev/pcmcia/pcmciareg.h>
   #include <dev/pcmcia/pcmciavar.h>
   #include <dev/pcmcia/pcmciachip.h>
   
   #include <dev/ic/i82365reg.h>
   #include <dev/ic/i82365var.h>
   
   #ifdef PCICISADEBUG
   int     pcicisa_debug = 0 /* XXX */ ;
   #define DPRINTF(arg) if (pcicisa_debug) printf arg;
   #else
   #define DPRINTF(arg)
   #endif
   
   int     pcic_isa_probe __P((struct device *, void *, void *));
   void    pcic_isa_attach __P((struct device *, struct device *, void *));
   
   void    *pcic_isa_chip_intr_establish __P((pcmcia_chipset_handle_t,
               struct pcmcia_function *, int, int (*) (void *), void *));
   void    pcic_isa_chip_intr_disestablish __P((pcmcia_chipset_handle_t, void *));
   
   struct cfattach pcic_isa_ca = {
           sizeof(struct pcic_softc), pcic_isa_probe, pcic_isa_attach
   };
   
   static struct pcmcia_chip_functions pcic_isa_functions = {
           pcic_chip_mem_alloc,
           pcic_chip_mem_free,
           pcic_chip_mem_map,
           pcic_chip_mem_unmap,
   
           pcic_chip_io_alloc,
           pcic_chip_io_free,
           pcic_chip_io_map,
           pcic_chip_io_unmap,
   
           pcic_isa_chip_intr_establish,
           pcic_isa_chip_intr_disestablish,
   
           pcic_chip_socket_enable,
           pcic_chip_socket_disable,
   };
   
   int
   pcic_isa_probe(parent, match, aux)
           struct device *parent;
           void *match, *aux;
   {
           struct isa_attach_args *ia = aux;
           bus_space_tag_t iot = ia->ia_iot;
           bus_space_handle_t ioh, memh;
           int val, found;
   
           if (bus_space_map(iot, ia->ia_iobase, PCIC_IOSIZE, 0, &ioh))
                   return (0);
   
           if (ia->ia_msize == -1)
                   ia->ia_msize = PCIC_MEMSIZE;
   
           if (bus_space_map(ia->ia_memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
                   return (0);
   
           found = 0;
   
           /*
            * this could be done with a loop, but it would violate the
            * abstraction
            */
   
           bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SA + PCIC_IDENT);
   
           val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
   
           if (pcic_ident_ok(val))
                   found++;
   
   
           bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SB + PCIC_IDENT);
   
           val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
   
           if (pcic_ident_ok(val))
                   found++;
   
   
           bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SA + PCIC_IDENT);
   
           val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
   
           if (pcic_ident_ok(val))
                   found++;
   
   
           bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SB + PCIC_IDENT);
   
           val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
   
           if (pcic_ident_ok(val))
                   found++;
   
   
           bus_space_unmap(iot, ioh, PCIC_IOSIZE);
           bus_space_unmap(ia->ia_memt, memh, ia->ia_msize);
   
           if (!found)
                   return (0);
   
           ia->ia_iosize = PCIC_IOSIZE;
   
           return (1);
   }
   
   #ifndef PCIC_ISA_ALLOC_IOBASE
   #define PCIC_ISA_ALLOC_IOBASE 0
   #endif
   
   #ifndef PCIC_ISA_ALLOC_IOSIZE
   #define PCIC_ISA_ALLOC_IOSIZE 0
   #endif
   
   int     pcic_isa_alloc_iobase = PCIC_ISA_ALLOC_IOBASE;
   int     pcic_isa_alloc_iosize = PCIC_ISA_ALLOC_IOSIZE;
   
   void
   pcic_isa_attach(parent, self, aux)
           struct device *parent, *self;
           void *aux;
   {
           struct pcic_softc *sc = (void *) self;
           struct isa_attach_args *ia = aux;
           isa_chipset_tag_t ic = ia->ia_ic;
           bus_space_tag_t iot = ia->ia_iot;
           bus_space_tag_t memt = ia->ia_memt;
           bus_space_handle_t ioh;
           bus_space_handle_t memh;
           bus_space_handle_t ioh_high;
           int i, iobuswidth, tmp1, tmp2;
   
           /* Map i/o space. */
           if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh))
                   panic("pcic_isa_attach: can't map i/o space");
   
           /* Map mem space. */
           if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
                   panic("pcic_isa_attach: can't map i/o space");
   
           sc->membase = ia->ia_maddr;
           sc->subregionmask = (1 << (ia->ia_msize / PCIC_MEM_PAGESIZE)) - 1;
   
           sc->intr_est = ic;
           sc->pct = (pcmcia_chipset_tag_t) & pcic_isa_functions;
   
           sc->iot = iot;
           sc->ioh = ioh;
           sc->memt = memt;
           sc->memh = memh;
   
           /*
            * allocate an irq.  it will be used by both controllers.  I could
            * use two different interrupts, but interrupts are relatively
            * scarce, shareable, and for PCIC controllers, very infrequent.
            */
   
           if ((sc->irq = ia->ia_irq) == IRQUNK) {
                   /* XXX CHECK RETURN VALUE */
                   (void) isa_intr_alloc(ic, PCIC_CSC_INTR_IRQ_VALIDMASK,
                       IST_EDGE, &sc->irq);
                   printf(": using irq %d", sc->irq);
           }
           printf("\n");
   
           pcic_attach(sc);
   
           /*
            * figure out how wide the isa bus is.  Do this by checking if the
            * pcic controller is mirrored 0x400 above where we expect it to be.
            */
   
           iobuswidth = 12;
   
           /* Map i/o space. */
           if (bus_space_map(iot, ia->ia_iobase + 0x400, ia->ia_iosize, 0,
               &ioh_high))
                   panic("pcic_isa_attach: can't map high i/o space");
   
           for (i = 0; i < PCIC_NSLOTS; i++) {
                   if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) {
                           /*
                            * read the ident flags from the normal space and
                            * from the mirror, and compare them
                            */
   
                           bus_space_write_1(iot, ioh, PCIC_REG_INDEX,
                               sc->handle[i].sock + PCIC_IDENT);
                           tmp1 = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
   
                           bus_space_write_1(iot, ioh_high, PCIC_REG_INDEX,
                               sc->handle[i].sock + PCIC_IDENT);
                           tmp2 = bus_space_read_1(iot, ioh_high, PCIC_REG_DATA);
   
                           if (tmp1 == tmp2)
                                   iobuswidth = 10;
                   }
           }
   
           bus_space_free(iot, ioh_high, ia->ia_iosize);
   
           /*
            * XXX mycroft recommends I/O space range 0x400-0xfff .  I should put
            * this in a header somewhere
            */
   
           /*
            * XXX some hardware doesn't seem to grok addresses in 0x400 range--
            * apparently missing a bit or more of address lines. (e.g.
            * CIRRUS_PD672X with Linksys EthernetCard ne2000 clone in TI
            * TravelMate 5000--not clear which is at fault)
            *
            * Add a kludge to detect 10 bit wide buses and deal with them,
            * and also a config file option to override the probe.
            */
   
           if (iobuswidth == 10) {
                   sc->iobase = 0x300;
                   sc->iosize = 0x0ff;
           } else {
                   sc->iobase = 0x400;
                   sc->iosize = 0xbff;
           }
   
           DPRINTF(("%s: bus_space_alloc range 0x%04lx-0x%04lx (probed)\n",
               sc->dev.dv_xname, (long) sc->iobase,
               (long) sc->iobase + sc->iosize));
   
           if (pcic_isa_alloc_iobase && pcic_isa_alloc_iosize) {
                   sc->iobase = pcic_isa_alloc_iobase;
                   sc->iosize = pcic_isa_alloc_iosize;
   
                   DPRINTF(("%s: bus_space_alloc range 0x%04lx-0x%04lx "
                       "(config override)\n", sc->dev.dv_xname, (long) sc->iobase,
                       (long) sc->iobase + sc->iosize));
           }
           sc->ih = isa_intr_establish(ic, sc->irq, IST_EDGE, IPL_TTY,
               pcic_intr, sc);
   
           pcic_attach_sockets(sc);
   }
   
   /*
    * allow patching or kernel option file override of available IRQs. Useful if
    * order of probing would screw up other devices, or if PCIC hardware/cards
    * have trouble with certain interrupt lines.
    */
   
   #ifndef PCIC_INTR_ALLOC_MASK
   #define PCIC_INTR_ALLOC_MASK    0xffff
   #endif
   
   int     pcic_intr_alloc_mask = PCIC_INTR_ALLOC_MASK;
   
   void *
   pcic_isa_chip_intr_establish(pch, pf, ipl, fct, arg)
           pcmcia_chipset_handle_t pch;
           struct pcmcia_function *pf;
           int ipl;
           int (*fct) __P((void *));
           void *arg;
   {
           struct pcic_handle *h = (struct pcic_handle *) pch;
           int irq, ist;
           void *ih;
           int reg;
   
           if (pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)
                   ist = IST_LEVEL;
           else if (pf->cfe->flags & PCMCIA_CFE_IRQPULSE)
                   ist = IST_PULSE;
           else
                   ist = IST_LEVEL;
   
           if (isa_intr_alloc(h->sc->intr_est,
               PCIC_INTR_IRQ_VALIDMASK & pcic_intr_alloc_mask, ist, &irq))
                   return (NULL);
           if ((ih = isa_intr_establish(h->sc->intr_est, irq, ist, ipl,
               fct, arg)) == NULL)
                   return (NULL);
   
           reg = pcic_read(h, PCIC_INTR);
           reg &= ~PCIC_INTR_IRQ_MASK;
           reg |= irq;
           pcic_write(h, PCIC_INTR, reg);
   
           h->ih_irq = irq;
   
           printf("%s: card irq %d\n", h->pcmcia->dv_xname, irq);
   
           return (ih);
   }
   
   void
   pcic_isa_chip_intr_disestablish(pch, ih)
           pcmcia_chipset_handle_t pch;
           void *ih;
   {
           struct pcic_handle *h = (struct pcic_handle *) pch;
           int reg;
   
           h->ih_irq = 0;
   
           reg = pcic_read(h, PCIC_INTR);
           reg &= ~(PCIC_INTR_IRQ_MASK | PCIC_INTR_ENABLE);
           pcic_write(h, PCIC_INTR, reg);
   
           isa_intr_disestablish(h->sc->intr_est, ih);
   }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.1.2.3

CVSweb <webmaster@jp.NetBSD.org>