diff options
author | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 1998-09-11 07:53:59 +0000 |
---|---|---|
committer | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 1998-09-11 07:53:59 +0000 |
commit | 84653f6d81c53fefc2b1e764149dd303ee17b3c3 (patch) | |
tree | 31189913070caf9e6e9e3d0fb5dbb5703524af5f | |
parent | fbb2fdc115860d5370e6ba3c47655fc3b1739c66 (diff) |
Added support for Intel 82365SL PCIC controllers and clones from NetBSD.
-rw-r--r-- | sys/dev/ic/i82365.c | 1151 | ||||
-rw-r--r-- | sys/dev/ic/i82365reg.h | 547 | ||||
-rw-r--r-- | sys/dev/ic/i82365var.h | 169 |
3 files changed, 1643 insertions, 224 deletions
diff --git a/sys/dev/ic/i82365.c b/sys/dev/ic/i82365.c new file mode 100644 index 00000000000..2c5a75f9f09 --- /dev/null +++ b/sys/dev/ic/i82365.c @@ -0,0 +1,1151 @@ +/* $OpenBSD: i82365.c,v 1.1 1998/09/11 07:53:57 fgsch Exp $ */ +/* $NetBSD: i82365.c,v 1.10 1998/06/09 07:36:55 thorpej Exp $ */ + +/* + * Copyright (c) 1997 Marc Horowitz. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Marc Horowitz. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#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/pcmcia/pcmciareg.h> +#include <dev/pcmcia/pcmciavar.h> + +#include <dev/ic/i82365reg.h> +#include <dev/ic/i82365var.h> + +#ifdef PCICDEBUG +int pcic_debug = 1; +#define DPRINTF(arg) if (pcic_debug) printf arg; +#else +#define DPRINTF(arg) +#endif + +#define PCIC_VENDOR_UNKNOWN 0 +#define PCIC_VENDOR_I82365SLR0 1 +#define PCIC_VENDOR_I82365SLR1 2 +#define PCIC_VENDOR_CIRRUS_PD6710 3 +#define PCIC_VENDOR_CIRRUS_PD672X 4 + +/* + * Individual drivers will allocate their own memory and io regions. Memory + * regions must be a multiple of 4k, aligned on a 4k boundary. + */ + +#define PCIC_MEM_ALIGN PCIC_MEM_PAGESIZE + +void pcic_attach_socket __P((struct pcic_handle *)); +void pcic_init_socket __P((struct pcic_handle *)); + +int pcic_submatch __P((struct device *, void *, void *)); +int pcic_print __P((void *arg, const char *pnp)); +int pcic_intr_socket __P((struct pcic_handle *)); + +void pcic_attach_card __P((struct pcic_handle *)); +void pcic_detach_card __P((struct pcic_handle *)); + +void pcic_chip_do_mem_map __P((struct pcic_handle *, int)); +void pcic_chip_do_io_map __P((struct pcic_handle *, int)); + +static void pcic_wait_ready __P((struct pcic_handle *)); + +struct cfdriver pcic_cd = { + NULL, "pcic", DV_DULL +}; + +int +pcic_ident_ok(ident) + int ident; +{ + /* this is very empirical and heuristic */ + + if ((ident == 0) || (ident == 0xff) || (ident & PCIC_IDENT_ZERO)) + return (0); + + if ((ident & PCIC_IDENT_IFTYPE_MASK) != PCIC_IDENT_IFTYPE_MEM_AND_IO) { +#ifdef DIAGNOSTIC + printf("pcic: does not support memory and I/O cards, " + "ignored (ident=%0x)\n", ident); +#endif + return (0); + } + return (1); +} + +int +pcic_vendor(h) + struct pcic_handle *h; +{ + int reg; + + /* + * the chip_id of the cirrus toggles between 11 and 00 after a write. + * weird. + */ + + pcic_write(h, PCIC_CIRRUS_CHIP_INFO, 0); + reg = pcic_read(h, -1); + + if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == + PCIC_CIRRUS_CHIP_INFO_CHIP_ID) { + reg = pcic_read(h, -1); + if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == 0) { + if (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS) + return (PCIC_VENDOR_CIRRUS_PD672X); + else + return (PCIC_VENDOR_CIRRUS_PD6710); + } + } + /* XXX how do I identify the GD6729? */ + + reg = pcic_read(h, PCIC_IDENT); + + if ((reg & PCIC_IDENT_REV_MASK) == PCIC_IDENT_REV_I82365SLR0) + return (PCIC_VENDOR_I82365SLR0); + else + return (PCIC_VENDOR_I82365SLR1); + + return (PCIC_VENDOR_UNKNOWN); +} + +char * +pcic_vendor_to_string(vendor) + int vendor; +{ + switch (vendor) { + case PCIC_VENDOR_I82365SLR0: + return ("Intel 82365SL Revision 0"); + case PCIC_VENDOR_I82365SLR1: + return ("Intel 82365SL Revision 1"); + case PCIC_VENDOR_CIRRUS_PD6710: + return ("Cirrus PD6710"); + case PCIC_VENDOR_CIRRUS_PD672X: + return ("Cirrus PD672X"); + } + + return ("Unknown controller"); +} + +void +pcic_attach(sc) + struct pcic_softc *sc; +{ + int vendor, count, i, reg; + + /* now check for each controller/socket */ + + /* + * this could be done with a loop, but it would violate the + * abstraction + */ + + count = 0; + + DPRINTF(("pcic ident regs:")); + + sc->handle[0].sc = sc; + sc->handle[0].sock = C0SA; + if (pcic_ident_ok(reg = pcic_read(&sc->handle[0], PCIC_IDENT))) { + sc->handle[0].flags = PCIC_FLAG_SOCKETP; + count++; + } else { + sc->handle[0].flags = 0; + } + + DPRINTF((" 0x%02x", reg)); + + sc->handle[1].sc = sc; + sc->handle[1].sock = C0SB; + if (pcic_ident_ok(reg = pcic_read(&sc->handle[1], PCIC_IDENT))) { + sc->handle[1].flags = PCIC_FLAG_SOCKETP; + count++; + } else { + sc->handle[1].flags = 0; + } + + DPRINTF((" 0x%02x", reg)); + + sc->handle[2].sc = sc; + sc->handle[2].sock = C1SA; + if (pcic_ident_ok(reg = pcic_read(&sc->handle[2], PCIC_IDENT))) { + sc->handle[2].flags = PCIC_FLAG_SOCKETP; + count++; + } else { + sc->handle[2].flags = 0; + } + + DPRINTF((" 0x%02x", reg)); + + sc->handle[3].sc = sc; + sc->handle[3].sock = C1SB; + if (pcic_ident_ok(reg = pcic_read(&sc->handle[3], PCIC_IDENT))) { + sc->handle[3].flags = PCIC_FLAG_SOCKETP; + count++; + } else { + sc->handle[3].flags = 0; + } + + DPRINTF((" 0x%02x\n", reg)); + + if (count == 0) + panic("pcic_attach: attach found no sockets"); + + /* establish the interrupt */ + + /* XXX block interrupts? */ + + for (i = 0; i < PCIC_NSLOTS; i++) { +#if 0 + /* + * this should work, but w/o it, setting tty flags hangs at + * boot time. + */ + if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) +#endif + { + pcic_write(&sc->handle[i], PCIC_CSC_INTR, 0); + pcic_read(&sc->handle[i], PCIC_CSC); + } + } + + if ((sc->handle[0].flags & PCIC_FLAG_SOCKETP) || + (sc->handle[1].flags & PCIC_FLAG_SOCKETP)) { + vendor = pcic_vendor(&sc->handle[0]); + + printf("%s: controller 0 (%s) has ", sc->dev.dv_xname, + pcic_vendor_to_string(vendor)); + + if ((sc->handle[0].flags & PCIC_FLAG_SOCKETP) && + (sc->handle[1].flags & PCIC_FLAG_SOCKETP)) + printf("sockets A and B\n"); + else if (sc->handle[0].flags & PCIC_FLAG_SOCKETP) + printf("socket A only\n"); + else + printf("socket B only\n"); + + if (sc->handle[0].flags & PCIC_FLAG_SOCKETP) + sc->handle[0].vendor = vendor; + if (sc->handle[1].flags & PCIC_FLAG_SOCKETP) + sc->handle[1].vendor = vendor; + } + if ((sc->handle[2].flags & PCIC_FLAG_SOCKETP) || + (sc->handle[3].flags & PCIC_FLAG_SOCKETP)) { + vendor = pcic_vendor(&sc->handle[2]); + + printf("%s: controller 1 (%s) has ", sc->dev.dv_xname, + pcic_vendor_to_string(vendor)); + + if ((sc->handle[2].flags & PCIC_FLAG_SOCKETP) && + (sc->handle[3].flags & PCIC_FLAG_SOCKETP)) + printf("sockets A and B\n"); + else if (sc->handle[2].flags & PCIC_FLAG_SOCKETP) + printf("socket A only\n"); + else + printf("socket B only\n"); + + if (sc->handle[2].flags & PCIC_FLAG_SOCKETP) + sc->handle[2].vendor = vendor; + if (sc->handle[3].flags & PCIC_FLAG_SOCKETP) + sc->handle[3].vendor = vendor; + } +} + +void +pcic_attach_sockets(sc) + struct pcic_softc *sc; +{ + int i; + + for (i = 0; i < PCIC_NSLOTS; i++) + if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) + pcic_attach_socket(&sc->handle[i]); +} + +void +pcic_attach_socket(h) + struct pcic_handle *h; +{ + struct pcmciabus_attach_args paa; + + /* initialize the rest of the handle */ + + h->memalloc = 0; + h->ioalloc = 0; + h->ih_irq = 0; + + /* now, config one pcmcia device per socket */ + + paa.pct = (pcmcia_chipset_tag_t) h->sc->pct; + paa.pch = (pcmcia_chipset_handle_t) h; + paa.iobase = h->sc->iobase; + paa.iosize = h->sc->iosize; + + h->pcmcia = config_found_sm(&h->sc->dev, &paa, pcic_print, + pcic_submatch); + + /* if there's actually a pcmcia device attached, initialize the slot */ + + if (h->pcmcia) + pcic_init_socket(h); +} + +void +pcic_init_socket(h) + struct pcic_handle *h; +{ + int reg; + + /* set up the card to interrupt on card detect */ + + pcic_write(h, PCIC_CSC_INTR, (h->sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) | + PCIC_CSC_INTR_CD_ENABLE); + pcic_write(h, PCIC_INTR, 0); + pcic_read(h, PCIC_CSC); + + /* unsleep the cirrus controller */ + + if ((h->vendor == PCIC_VENDOR_CIRRUS_PD6710) || + (h->vendor == PCIC_VENDOR_CIRRUS_PD672X)) { + reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2); + if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) { + DPRINTF(("%s: socket %02x was suspended\n", + h->sc->dev.dv_xname, h->sock)); + reg &= ~PCIC_CIRRUS_MISC_CTL_2_SUSPEND; + pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg); + } + } + /* if there's a card there, then attach it. */ + + reg = pcic_read(h, PCIC_IF_STATUS); + + if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) == + PCIC_IF_STATUS_CARDDETECT_PRESENT) + pcic_attach_card(h); +} + +int +pcic_submatch(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct pcmciabus_attach_args *paa = aux; + struct pcic_handle *h = (struct pcic_handle *) paa->pch; + + switch (h->sock) { + case C0SA: + if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] != + -1 /* PCICCF_CONTROLLER_DEFAULT */ && + cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 0) + return 0; + if (cf->cf_loc[1 /* PCICCF_SOCKET */] != + -1 /* PCICCF_SOCKET_DEFAULT */ && + cf->cf_loc[1 /* PCICCF_SOCKET */] != 0) + return 0; + + break; + case C0SB: + if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] != + -1 /* PCICCF_CONTROLLER_DEFAULT */ && + cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 0) + return 0; + if (cf->cf_loc[1 /* PCICCF_SOCKET */] != + -1 /* PCICCF_SOCKET_DEFAULT */ && + cf->cf_loc[1 /* PCICCF_SOCKET */] != 1) + return 0; + + break; + case C1SA: + if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] != + -1 /* PCICCF_CONTROLLER_DEFAULT */ && + cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 1) + return 0; + if (cf->cf_loc[1 /* PCICCF_SOCKET */] != + -1 /* PCICCF_SOCKET_DEFAULT */ && + cf->cf_loc[1 /* PCICCF_SOCKET */] != 0) + return 0; + + break; + case C1SB: + if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] != + -1 /* PCICCF_CONTROLLER_DEFAULT */ && + cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 1) + return 0; + if (cf->cf_loc[1 /* PCICCF_SOCKET */] != + -1 /* PCICCF_SOCKET_DEFAULT */ && + cf->cf_loc[1 /* PCICCF_SOCKET */] != 1) + return 0; + + break; + default: + panic("unknown pcic socket"); + } + + return ((*cf->cf_attach->ca_match)(parent, cf, aux)); +} + +int +pcic_print(arg, pnp) + void *arg; + const char *pnp; +{ + struct pcmciabus_attach_args *paa = arg; + struct pcic_handle *h = (struct pcic_handle *) paa->pch; + + /* Only "pcmcia"s can attach to "pcic"s... easy. */ + if (pnp) + printf("pcmcia at %s", pnp); + + switch (h->sock) { + case C0SA: + printf(" controller 0 socket 0"); + break; + case C0SB: + printf(" controller 0 socket 1"); + break; + case C1SA: + printf(" controller 1 socket 0"); + break; + case C1SB: + printf(" controller 1 socket 1"); + break; + default: + panic("unknown pcic socket"); + } + + return (UNCONF); +} + +int +pcic_intr(arg) + void *arg; +{ + struct pcic_softc *sc = arg; + int i, ret = 0; + + DPRINTF(("%s: intr\n", sc->dev.dv_xname)); + + for (i = 0; i < PCIC_NSLOTS; i++) + if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) + ret += pcic_intr_socket(&sc->handle[i]); + + return (ret ? 1 : 0); +} + +int +pcic_intr_socket(h) + struct pcic_handle *h; +{ + int cscreg; + + cscreg = pcic_read(h, PCIC_CSC); + + cscreg &= (PCIC_CSC_GPI | + PCIC_CSC_CD | + PCIC_CSC_READY | + PCIC_CSC_BATTWARN | + PCIC_CSC_BATTDEAD); + + if (cscreg & PCIC_CSC_GPI) { + DPRINTF(("%s: %02x GPI\n", h->sc->dev.dv_xname, h->sock)); + } + if (cscreg & PCIC_CSC_CD) { + int statreg; + + statreg = pcic_read(h, PCIC_IF_STATUS); + + DPRINTF(("%s: %02x CD %x\n", h->sc->dev.dv_xname, h->sock, + statreg)); + + /* + * XXX This should probably schedule something to happen + * after the interrupt handler completes + */ + + if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == + PCIC_IF_STATUS_CARDDETECT_PRESENT) { + if (!(h->flags & PCIC_FLAG_CARDP)) + pcic_attach_card(h); + } else { + if (h->flags & PCIC_FLAG_CARDP) + pcic_detach_card(h); + } + } + if (cscreg & PCIC_CSC_READY) { + DPRINTF(("%s: %02x READY\n", h->sc->dev.dv_xname, h->sock)); + /* shouldn't happen */ + } + if (cscreg & PCIC_CSC_BATTWARN) { + DPRINTF(("%s: %02x BATTWARN\n", h->sc->dev.dv_xname, h->sock)); + } + if (cscreg & PCIC_CSC_BATTDEAD) { + DPRINTF(("%s: %02x BATTDEAD\n", h->sc->dev.dv_xname, h->sock)); + } + return (cscreg ? 1 : 0); +} + +void +pcic_attach_card(h) + struct pcic_handle *h; +{ + if (h->flags & PCIC_FLAG_CARDP) + panic("pcic_attach_card: already attached"); + + /* call the MI attach function */ + + pcmcia_card_attach(h->pcmcia); + + h->flags |= PCIC_FLAG_CARDP; +} + +void +pcic_detach_card(h) + struct pcic_handle *h; +{ + if (!(h->flags & PCIC_FLAG_CARDP)) + panic("pcic_attach_card: already detached"); + + h->flags &= ~PCIC_FLAG_CARDP; + + /* call the MI attach function */ + + pcmcia_card_detach(h->pcmcia); + + /* disable card detect resume and configuration reset */ + + /* power down the socket */ + + pcic_write(h, PCIC_PWRCTL, 0); + + /* reset the card */ + + pcic_write(h, PCIC_INTR, 0); +} + +int +pcic_chip_mem_alloc(pch, size, pcmhp) + pcmcia_chipset_handle_t pch; + bus_size_t size; + struct pcmcia_mem_handle *pcmhp; +{ + struct pcic_handle *h = (struct pcic_handle *) pch; + bus_space_handle_t memh; + bus_addr_t addr; + bus_size_t sizepg; + int i, mask, mhandle; + + /* out of sc->memh, allocate as many pages as necessary */ + + /* convert size to PCIC pages */ + sizepg = (size + (PCIC_MEM_ALIGN - 1)) / PCIC_MEM_ALIGN; + + mask = (1 << sizepg) - 1; + + addr = 0; /* XXX gcc -Wuninitialized */ + mhandle = 0; /* XXX gcc -Wuninitialized */ + + for (i = 0; i < (PCIC_MEM_PAGES + 1 - sizepg); i++) { + if ((h->sc->subregionmask & (mask << i)) == (mask << i)) { + if (bus_space_subregion(h->sc->memt, h->sc->memh, + i * PCIC_MEM_PAGESIZE, + sizepg * PCIC_MEM_PAGESIZE, &memh)) + return (1); + mhandle = mask << i; + addr = h->sc->membase + (i * PCIC_MEM_PAGESIZE); + h->sc->subregionmask &= ~(mhandle); + break; + } + } + + if (i == (PCIC_MEM_PAGES + 1 - size)) + return (1); + + DPRINTF(("pcic_chip_mem_alloc bus addr 0x%lx+0x%lx\n", (u_long) addr, + (u_long) size)); + + pcmhp->memt = h->sc->memt; + pcmhp->memh = memh; + pcmhp->addr = addr; + pcmhp->size = size; + pcmhp->mhandle = mhandle; + pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE; + + return (0); +} + +void +pcic_chip_mem_free(pch, pcmhp) + pcmcia_chipset_handle_t pch; + struct pcmcia_mem_handle *pcmhp; +{ + struct pcic_handle *h = (struct pcic_handle *) pch; + + h->sc->subregionmask |= pcmhp->mhandle; +} + +static struct mem_map_index_st { + int sysmem_start_lsb; + int sysmem_start_msb; + int sysmem_stop_lsb; + int sysmem_stop_msb; + int cardmem_lsb; + int cardmem_msb; + int memenable; +} mem_map_index[] = { + { + PCIC_SYSMEM_ADDR0_START_LSB, + PCIC_SYSMEM_ADDR0_START_MSB, + PCIC_SYSMEM_ADDR0_STOP_LSB, + PCIC_SYSMEM_ADDR0_STOP_MSB, + PCIC_CARDMEM_ADDR0_LSB, + PCIC_CARDMEM_ADDR0_MSB, + PCIC_ADDRWIN_ENABLE_MEM0, + }, + { + PCIC_SYSMEM_ADDR1_START_LSB, + PCIC_SYSMEM_ADDR1_START_MSB, + PCIC_SYSMEM_ADDR1_STOP_LSB, + PCIC_SYSMEM_ADDR1_STOP_MSB, + PCIC_CARDMEM_ADDR1_LSB, + PCIC_CARDMEM_ADDR1_MSB, + PCIC_ADDRWIN_ENABLE_MEM1, + }, + { + PCIC_SYSMEM_ADDR2_START_LSB, + PCIC_SYSMEM_ADDR2_START_MSB, + PCIC_SYSMEM_ADDR2_STOP_LSB, + PCIC_SYSMEM_ADDR2_STOP_MSB, + PCIC_CARDMEM_ADDR2_LSB, + PCIC_CARDMEM_ADDR2_MSB, + PCIC_ADDRWIN_ENABLE_MEM2, + }, + { + PCIC_SYSMEM_ADDR3_START_LSB, + PCIC_SYSMEM_ADDR3_START_MSB, + PCIC_SYSMEM_ADDR3_STOP_LSB, + PCIC_SYSMEM_ADDR3_STOP_MSB, + PCIC_CARDMEM_ADDR3_LSB, + PCIC_CARDMEM_ADDR3_MSB, + PCIC_ADDRWIN_ENABLE_MEM3, + }, + { + PCIC_SYSMEM_ADDR4_START_LSB, + PCIC_SYSMEM_ADDR4_START_MSB, + PCIC_SYSMEM_ADDR4_STOP_LSB, + PCIC_SYSMEM_ADDR4_STOP_MSB, + PCIC_CARDMEM_ADDR4_LSB, + PCIC_CARDMEM_ADDR4_MSB, + PCIC_ADDRWIN_ENABLE_MEM4, + }, +}; + +void +pcic_chip_do_mem_map(h, win) + struct pcic_handle *h; + int win; +{ + int reg; + + pcic_write(h, mem_map_index[win].sysmem_start_lsb, + (h->mem[win].addr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff); + pcic_write(h, mem_map_index[win].sysmem_start_msb, + ((h->mem[win].addr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) & + PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK)); + +#if 0 + /* XXX do I want 16 bit all the time? */ + PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT; +#endif + + pcic_write(h, mem_map_index[win].sysmem_stop_lsb, + ((h->mem[win].addr + h->mem[win].size) >> + PCIC_SYSMEM_ADDRX_SHIFT) & 0xff); + pcic_write(h, mem_map_index[win].sysmem_stop_msb, + (((h->mem[win].addr + h->mem[win].size) >> + (PCIC_SYSMEM_ADDRX_SHIFT + 8)) & + PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) | + PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2); + + pcic_write(h, mem_map_index[win].cardmem_lsb, + (h->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff); + pcic_write(h, mem_map_index[win].cardmem_msb, + ((h->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) & + PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) | + ((h->mem[win].kind == PCMCIA_MEM_ATTR) ? + PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0)); + + reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); + reg |= (mem_map_index[win].memenable | PCIC_ADDRWIN_ENABLE_MEMCS16); + pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); + +#ifdef PCICDEBUG + { + int r1, r2, r3, r4, r5, r6; + + r1 = pcic_read(h, mem_map_index[win].sysmem_start_msb); + r2 = pcic_read(h, mem_map_index[win].sysmem_start_lsb); + r3 = pcic_read(h, mem_map_index[win].sysmem_stop_msb); + r4 = pcic_read(h, mem_map_index[win].sysmem_stop_lsb); + r5 = pcic_read(h, mem_map_index[win].cardmem_msb); + r6 = pcic_read(h, mem_map_index[win].cardmem_lsb); + + DPRINTF(("pcic_chip_do_mem_map window %d: %02x%02x %02x%02x " + "%02x%02x\n", win, r1, r2, r3, r4, r5, r6)); + } +#endif +} + +int +pcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp) + pcmcia_chipset_handle_t pch; + int kind; + bus_addr_t card_addr; + bus_size_t size; + struct pcmcia_mem_handle *pcmhp; + bus_addr_t *offsetp; + int *windowp; +{ + struct pcic_handle *h = (struct pcic_handle *) pch; + bus_addr_t busaddr; + long card_offset; + int i, win; + + win = -1; + for (i = 0; i < (sizeof(mem_map_index) / sizeof(mem_map_index[0])); + i++) { + if ((h->memalloc & (1 << i)) == 0) { + win = i; + h->memalloc |= (1 << i); + break; + } + } + + if (win == -1) + return (1); + + *windowp = win; + + /* XXX this is pretty gross */ + + if (h->sc->memt != pcmhp->memt) + panic("pcic_chip_mem_map memt is bogus"); + + busaddr = pcmhp->addr; + + /* + * compute the address offset to the pcmcia address space for the + * pcic. this is intentionally signed. The masks and shifts below + * will cause TRT to happen in the pcic registers. Deal with making + * sure the address is aligned, and return the alignment offset. + */ + + *offsetp = card_addr % PCIC_MEM_ALIGN; + card_addr -= *offsetp; + + DPRINTF(("pcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr " + "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size, + (u_long) card_addr)); + + /* + * include the offset in the size, and decrement size by one, since + * the hw wants start/stop + */ + size += *offsetp - 1; + + card_offset = (((long) card_addr) - ((long) busaddr)); + + h->mem[win].addr = busaddr; + h->mem[win].size = size; + h->mem[win].offset = card_offset; + h->mem[win].kind = kind; + + pcic_chip_do_mem_map(h, win); + + return (0); +} + +void +pcic_chip_mem_unmap(pch, window) + pcmcia_chipset_handle_t pch; + int window; +{ + struct pcic_handle *h = (struct pcic_handle *) pch; + int reg; + + if (window >= (sizeof(mem_map_index) / sizeof(mem_map_index[0]))) + panic("pcic_chip_mem_unmap: window out of range"); + + reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); + reg &= ~mem_map_index[window].memenable; + pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); + + h->memalloc &= ~(1 << window); +} + +int +pcic_chip_io_alloc(pch, start, size, align, pcihp) + pcmcia_chipset_handle_t pch; + bus_addr_t start; + bus_size_t size; + bus_size_t align; + struct pcmcia_io_handle *pcihp; +{ + struct pcic_handle *h = (struct pcic_handle *) pch; + bus_space_tag_t iot; + bus_space_handle_t ioh; + bus_addr_t ioaddr; + int flags = 0; + + /* + * Allocate some arbitrary I/O space. + */ + + iot = h->sc->iot; + + if (start) { + ioaddr = start; + if (bus_space_map(iot, start, size, 0, &ioh)) + return (1); + DPRINTF(("pcic_chip_io_alloc map port %lx+%lx\n", + (u_long) ioaddr, (u_long) size)); + } else { + flags |= PCMCIA_IO_ALLOCATED; + if (bus_space_alloc(iot, h->sc->iobase, + h->sc->iobase + h->sc->iosize, size, align, 0, 0, + &ioaddr, &ioh)) + return (1); + DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n", + (u_long) ioaddr, (u_long) size)); + } + + pcihp->iot = iot; + pcihp->ioh = ioh; + pcihp->addr = ioaddr; + pcihp->size = size; + pcihp->flags = flags; + + return (0); +} + +void +pcic_chip_io_free(pch, pcihp) + pcmcia_chipset_handle_t pch; + struct pcmcia_io_handle *pcihp; +{ + bus_space_tag_t iot = pcihp->iot; + bus_space_handle_t ioh = pcihp->ioh; + bus_size_t size = pcihp->size; + + if (pcihp->flags & PCMCIA_IO_ALLOCATED) + bus_space_free(iot, ioh, size); + else + bus_space_unmap(iot, ioh, size); +} + + +static struct io_map_index_st { + int start_lsb; + int start_msb; + int stop_lsb; + int stop_msb; + int ioenable; + int ioctlmask; + int ioctlbits[3]; /* indexed by PCMCIA_WIDTH_* */ +} io_map_index[] = { + { + PCIC_IOADDR0_START_LSB, + PCIC_IOADDR0_START_MSB, + PCIC_IOADDR0_STOP_LSB, + PCIC_IOADDR0_STOP_MSB, + PCIC_ADDRWIN_ENABLE_IO0, + PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT | + PCIC_IOCTL_IO0_IOCS16SRC_MASK | PCIC_IOCTL_IO0_DATASIZE_MASK, + { + PCIC_IOCTL_IO0_IOCS16SRC_CARD, + PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | + PCIC_IOCTL_IO0_DATASIZE_8BIT, + PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | + PCIC_IOCTL_IO0_DATASIZE_16BIT, + }, + }, + { + PCIC_IOADDR1_START_LSB, + PCIC_IOADDR1_START_MSB, + PCIC_IOADDR1_STOP_LSB, + PCIC_IOADDR1_STOP_MSB, + PCIC_ADDRWIN_ENABLE_IO1, + PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT | + PCIC_IOCTL_IO1_IOCS16SRC_MASK | PCIC_IOCTL_IO1_DATASIZE_MASK, + { + PCIC_IOCTL_IO1_IOCS16SRC_CARD, + PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE | + PCIC_IOCTL_IO1_DATASIZE_8BIT, + PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE | + PCIC_IOCTL_IO1_DATASIZE_16BIT, + }, + }, +}; + +void +pcic_chip_do_io_map(h, win) + struct pcic_handle *h; + int win; +{ + int reg; + + DPRINTF(("pcic_chip_do_io_map win %d addr %lx size %lx width %d\n", + win, (long) h->io[win].addr, (long) h->io[win].size, + h->io[win].width * 8)); + + pcic_write(h, io_map_index[win].start_lsb, h->io[win].addr & 0xff); + pcic_write(h, io_map_index[win].start_msb, + (h->io[win].addr >> 8) & 0xff); + + pcic_write(h, io_map_index[win].stop_lsb, + (h->io[win].addr + h->io[win].size - 1) & 0xff); + pcic_write(h, io_map_index[win].stop_msb, + ((h->io[win].addr + h->io[win].size - 1) >> 8) & 0xff); + + reg = pcic_read(h, PCIC_IOCTL); + reg &= ~io_map_index[win].ioctlmask; + reg |= io_map_index[win].ioctlbits[h->io[win].width]; + pcic_write(h, PCIC_IOCTL, reg); + + reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); + reg |= io_map_index[win].ioenable; + pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); +} + +int +pcic_chip_io_map(pch, width, offset, size, pcihp, windowp) + pcmcia_chipset_handle_t pch; + int width; + bus_addr_t offset; + bus_size_t size; + struct pcmcia_io_handle *pcihp; + int *windowp; +{ + struct pcic_handle *h = (struct pcic_handle *) pch; + bus_addr_t ioaddr = pcihp->addr + offset; + int i, win; +#ifdef PCICDEBUG + static char *width_names[] = { "auto", "io8", "io16" }; +#endif + + /* XXX Sanity check offset/size. */ + + win = -1; + for (i = 0; i < (sizeof(io_map_index) / sizeof(io_map_index[0])); i++) { + if ((h->ioalloc & (1 << i)) == 0) { + win = i; + h->ioalloc |= (1 << i); + break; + } + } + + if (win == -1) + return (1); + + *windowp = win; + + /* XXX this is pretty gross */ + + if (h->sc->iot != pcihp->iot) + panic("pcic_chip_io_map iot is bogus"); + + DPRINTF(("pcic_chip_io_map window %d %s port %lx+%lx\n", + win, width_names[width], (u_long) ioaddr, (u_long) size)); + + /* XXX wtf is this doing here? */ + + printf(" port 0x%lx", (u_long) ioaddr); + if (size > 1) + printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1); + + h->io[win].addr = ioaddr; + h->io[win].size = size; + h->io[win].width = width; + + pcic_chip_do_io_map(h, win); + + return (0); +} + +void +pcic_chip_io_unmap(pch, window) + pcmcia_chipset_handle_t pch; + int window; +{ + struct pcic_handle *h = (struct pcic_handle *) pch; + int reg; + + if (window >= (sizeof(io_map_index) / sizeof(io_map_index[0]))) + panic("pcic_chip_io_unmap: window out of range"); + + reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); + reg &= ~io_map_index[window].ioenable; + pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); + + h->ioalloc &= ~(1 << window); +} + +static void +pcic_wait_ready(h) + struct pcic_handle *h; +{ + int i; + + for (i = 0; i < 10000; i++) { + if (pcic_read(h, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY) + return; + delay(500); +#ifdef PCICDEBUG + if (pcic_debug) { + if ((i>5000) && (i%100 == 99)) + printf("."); + } +#endif + } + +#ifdef DIAGNOSTIC + printf("pcic_wait_ready ready never happened\n"); +#endif +} + +void +pcic_chip_socket_enable(pch) + pcmcia_chipset_handle_t pch; +{ + struct pcic_handle *h = (struct pcic_handle *) pch; + int cardtype, reg, win; + + /* this bit is mostly stolen from pcic_attach_card */ + + /* power down the socket to reset it, clear the card reset pin */ + + pcic_write(h, PCIC_PWRCTL, 0); + + /* + * wait 300ms until power fails (Tpf). Then, wait 100ms since + * we are changing Vcc (Toff). + */ + delay((300 + 100) * 1000); + + /* power up the socket */ + + pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_PWR_ENABLE); + + /* + * wait 100ms until power raise (Tpr) and 20ms to become + * stable (Tsu(Vcc)). + */ + delay((100 + 20) * 1000); + + pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_PWR_ENABLE | PCIC_PWRCTL_OE); + +#if 0 + /* + * hold RESET at least 10us. + */ + delay(10); +#else + /* + * at least one card i've tested needs this. -fgsch + */ + delay(250 * 1000); +#endif + + /* clear the reset flag */ + + pcic_write(h, PCIC_INTR, PCIC_INTR_RESET); + + /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */ + + delay(20000); + + /* wait for the chip to finish initializing */ + + pcic_wait_ready(h); + + /* zero out the address windows */ + + pcic_write(h, PCIC_ADDRWIN_ENABLE, 0); + + /* set the card type */ + + cardtype = pcmcia_card_gettype(h->pcmcia); + + reg = pcic_read(h, PCIC_INTR); + reg &= ~PCIC_INTR_CARDTYPE_MASK; + reg |= ((cardtype == PCMCIA_IFTYPE_IO) ? + PCIC_INTR_CARDTYPE_IO : + PCIC_INTR_CARDTYPE_MEM); + reg |= h->ih_irq; + pcic_write(h, PCIC_INTR, reg); + + DPRINTF(("%s: pcic_chip_socket_enable %02x cardtype %s %02x\n", + h->sc->dev.dv_xname, h->sock, + ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), reg)); + + /* reinstall all the memory and io mappings */ + + for (win = 0; win < PCIC_MEM_WINS; win++) + if (h->memalloc & (1 << win)) + pcic_chip_do_mem_map(h, win); + + for (win = 0; win < PCIC_IO_WINS; win++) + if (h->ioalloc & (1 << win)) + pcic_chip_do_io_map(h, win); +} + +void +pcic_chip_socket_disable(pch) + pcmcia_chipset_handle_t pch; +{ + struct pcic_handle *h = (struct pcic_handle *) pch; + + DPRINTF(("pcic_chip_socket_disable\n")); + + /* power down the socket */ + + pcic_write(h, PCIC_PWRCTL, 0); + + /* + * wait 300ms until power fails (Tpf). + */ + delay(300 * 1000); +} diff --git a/sys/dev/ic/i82365reg.h b/sys/dev/ic/i82365reg.h index d574d332d8d..e9daa79c6a2 100644 --- a/sys/dev/ic/i82365reg.h +++ b/sys/dev/ic/i82365reg.h @@ -1,234 +1,333 @@ -/* $OpenBSD: i82365reg.h,v 1.4 1996/10/31 01:01:31 niklas Exp $ */ +/* $OpenBSD: i82365reg.h,v 1.5 1998/09/11 07:53:57 fgsch Exp $ */ +/* $NetBSD: i82365reg.h,v 1.2 1997/10/16 23:18:18 thorpej Exp $ */ -#ifndef __82365_H__ -#define __82365_H__ - -/*********************************************************************** - * 82365.h -- information necessary for direct manipulation of PCMCIA - * cards and controllers +/* + * Copyright (c) 1997 Marc Horowitz. All rights reserved. * - * Support is included for Intel 82365SL PCIC controllers and clones - * thereof. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Marc Horowitz. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - ***********************************************************************/ + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ /* - * data structures used to store information about PCIC sockets and - * PCMCIA cards, and functions to manipulate them + * All information is from the intel 82365sl PC Card Interface Controller + * (PCIC) data sheet, marked "preliminary". Order number 290423-002, January + * 1993. */ -#define MAX_CONFIGS 12 /* config table entries */ -#define MAX_IOADDRS 2 /* i/o port ranges */ -#define MAX_MEMS 4 /* memory ranges */ -#define MAX_SOCKS 8 /* pcic sockets */ + +#define PCIC_IOSIZE 2 + +#define PCIC_REG_INDEX 0 +#define PCIC_REG_DATA 1 /* - * PCIC Registers - * Each register is given a name, and most of the bits are named too. - * I should really name them all. - * - * Finally, since the banks can be addressed with a regular syntax, - * some macros are provided for that purpose. + * The PCIC allows two chips to share the same address. In order not to run + * afoul of the netbsd device model, this driver will treat those chips as + * the same device. */ -#define PCIC_BASE 0x03e0 /* base adddress of pcic register set */ -#define PCIC_NPORTS 2 /* pcic takes 2 ports */ - -/* First, all the registers */ -#define PCIC_ID_REV 0x00 /* Identification and Revision */ -#define PCIC_STATUS 0x01 /* Interface Status */ -#define PCIC_POWER 0x02 /* Power and RESETDRV control */ -#define PCIC_INT_GEN 0x03 /* Interrupt and General Control */ -#define PCIC_STAT_CHG 0x04 /* Card Status Change */ -#define PCIC_STAT_INT 0x05 /* Card Status Change Interrupt Config */ -#define PCIC_ADDRWINE 0x06 /* Address Window Enable */ -#define PCIC_IOCTL 0x07 /* I/O Control */ -#define PCIC_IO0_STL 0x08 /* I/O Address 0 Start Low Byte */ -#define PCIC_IO0_STH 0x09 /* I/O Address 0 Start High Byte */ -#define PCIC_IO0_SPL 0x0a /* I/O Address 0 Stop Low Byte */ -#define PCIC_IO0_SPH 0x0b /* I/O Address 0 Stop High Byte */ -#define PCIC_IO1_STL 0x0c /* I/O Address 1 Start Low Byte */ -#define PCIC_IO1_STH 0x0d /* I/O Address 1 Start High Byte */ -#define PCIC_IO1_SPL 0x0e /* I/O Address 1 Stop Low Byte */ -#define PCIC_IO1_SPH 0x0f /* I/O Address 1 Stop High Byte */ -#define PCIC_SM0_STL 0x10 /* System Memory Address 0 Mapping Start Low Byte */ -#define PCIC_SM0_STH 0x11 /* System Memory Address 0 Mapping Start High Byte */ -#define PCIC_SM0_SPL 0x12 /* System Memory Address 0 Mapping Stop Low Byte */ -#define PCIC_SM0_SPH 0x13 /* System Memory Address 0 Mapping Stop High Byte */ -#define PCIC_CM0_L 0x14 /* Card Memory Offset Address 0 Low Byte */ -#define PCIC_CM0_H 0x15 /* Card Memory Offset Address 0 High Byte */ -#define PCIC_CDGC 0x16 /* Card Detect and General Control */ -#define PCIC_RES17 0x17 /* Reserved */ -#define PCIC_SM1_STL 0x18 /* System Memory Address 1 Mapping Start Low Byte */ -#define PCIC_SM1_STH 0x19 /* System Memory Address 1 Mapping Start High Byte */ -#define PCIC_SM1_SPL 0x1a /* System Memory Address 1 Mapping Stop Low Byte */ -#define PCIC_SM1_SPH 0x1b /* System Memory Address 1 Mapping Stop High Byte */ -#define PCIC_CM1_L 0x1c /* Card Memory Offset Address 1 Low Byte */ -#define PCIC_CM1_H 0x1d /* Card Memory Offset Address 1 High Byte */ -#define PCIC_RES1E 0x1e /* Reserved */ -#define PCIC_RES1F 0x1f /* Reserved */ -#define PCIC_SM2_STL 0x20 /* System Memory Address 2 Mapping Start Low Byte */ -#define PCIC_SM2_STH 0x21 /* System Memory Address 2 Mapping Start High Byte */ -#define PCIC_SM2_SPL 0x22 /* System Memory Address 2 Mapping Stop Low Byte */ -#define PCIC_SM2_SPH 0x23 /* System Memory Address 2 Mapping Stop High Byte */ -#define PCIC_CM2_L 0x24 /* Card Memory Offset Address 2 Low Byte */ -#define PCIC_CM2_H 0x25 /* Card Memory Offset Address 2 High Byte */ -#define PCIC_RES26 0x26 /* Reserved */ -#define PCIC_RES27 0x27 /* Reserved */ -#define PCIC_SM3_STL 0x28 /* System Memory Address 3 Mapping Start Low Byte */ -#define PCIC_SM3_STH 0x29 /* System Memory Address 3 Mapping Start High Byte */ -#define PCIC_SM3_SPL 0x2a /* System Memory Address 3 Mapping Stop Low Byte */ -#define PCIC_SM3_SPH 0x2b /* System Memory Address 3 Mapping Stop High Byte */ -#define PCIC_CM3_L 0x2c /* Card Memory Offset Address 3 Low Byte */ -#define PCIC_CM3_H 0x2d /* Card Memory Offset Address 3 High Byte */ -#define PCIC_RES2E 0x2e /* Reserved */ -#define PCIC_RES2F 0x2f /* Reserved */ -#define PCIC_SM4_STL 0x30 /* System Memory Address 4 Mapping Start Low Byte */ -#define PCIC_SM4_STH 0x31 /* System Memory Address 4 Mapping Start High Byte */ -#define PCIC_SM4_SPL 0x32 /* System Memory Address 4 Mapping Stop Low Byte */ -#define PCIC_SM4_SPH 0x33 /* System Memory Address 4 Mapping Stop High Byte */ -#define PCIC_CM4_L 0x34 /* Card Memory Offset Address 4 Low Byte */ -#define PCIC_CM4_H 0x35 /* Card Memory Offset Address 4 High Byte */ -#define PCIC_RES36 0x36 /* Reserved */ -#define PCIC_RES37 0x37 /* Reserved */ -#define PCIC_RES38 0x38 /* Reserved */ -#define PCIC_RES39 0x39 /* Reserved */ -#define PCIC_RES3A 0x3a /* Reserved */ -#define PCIC_RES3B 0x3b /* Reserved */ -#define PCIC_RES3C 0x3c /* Reserved */ -#define PCIC_RES3D 0x3d /* Reserved */ -#define PCIC_RES3E 0x3e /* Reserved */ -#define PCIC_RES3F 0x3f /* Reserved */ - -#define PCIC_STATUSBITS \ - "\020\010VPP\07POWER\06READY\05WPROT\04DET1\03DET2\02VOL1\01VOL2" - -/* Now register bits, ordered by reg # */ - -/* For Identification and Revision (PCIC_ID_REV) */ -#define PCIC_INTEL0 0x82 /* Intel 82365SL Rev. 0; Both Memory and I/O */ -#define PCIC_INTEL1 0x83 /* Intel 82365SL Rev. 1; Both Memory and I/O */ -#define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */ -#define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */ -#define PCIC_146FC6 0x84 /* VL82C146FC6; Both Memory and I/O */ -#define PCIC_146FC7 0x85 /* VL82C146FC7; Both Memory and I/O */ - -/* For Interface Status register (PCIC_STATUS) */ -#define PCIC_VPPV 0x80 /* Vpp_valid */ -#define PCIC_POW 0x40 /* PC Card power active */ -#define PCIC_READY 0x20 /* Ready/~Busy */ -#define PCIC_MWP 0x10 /* Memory Write Protect */ -#define PCIC_CD 0x0C /* Both card detect bits */ -#define PCIC_BVD 0x03 /* Both Battery Voltage Detect bits */ - -/* For the Power and RESETDRV register (PCIC_POWER) */ -#define PCIC_OUTENA 0x80 /* Output Enable */ -#define PCIC_DISRST 0x40 /* Disable RESETDRV */ -#define PCIC_APSENA 0x20 /* Auto Pwer Switch Enable */ -#define PCIC_VCC5V 0x10 /* PC Card Power 5V Enable */ -#define PCIC_VCC3V 0x08 /* PC Card Power 3V Enable */ -#define PCIC_VPP12V 0x02 /* PC Card Power VPP 12V Enable */ -#define PCIC_VPP5V 0x01 /* PC Card Power VPP 5V Enable */ - -/* For the Interrupt and General Control register (PCIC_INT_GEN) */ -#define PCIC_INT_MASK 0x0f -#define PCIC_INT_FLAGMASK 0x0f -#define PCIC_INTR_ENA 0x10 /* clr bit means CSC interrupt goes via IRQ */ -#define PCIC_CARDTYPE 0x20 /* Card Type 0 = memory, 1 = I/O */ -#define PCIC_IOCARD 0x20 -#define PCIC_MEMCARD 0x00 -#define PCIC_CARDRESET 0x40 /* Card reset 0 = Reset, 1 = Normal */ -#define PCIC_RINGIND 0x80 - -/* For the Card Status Change register (PCIC_STAT_CHG) */ -#define PCIC_GPICH 0x10 /* General Purpose Input (GPI) Change */ -#define PCIC_CDTCH 0x08 /* Card Detect Change */ -#define PCIC_RDYCH 0x04 /* Ready Change */ -#define PCIC_BATWRN 0x02 /* Battery Warning */ -#define PCIC_BATDED 0x01 /* Battery Dead */ -#define PCIC_STCH 0x01 /* Status Change */ - -/* For the Card Status Change interrupt config register (PCIC_STAT_INT) */ -#define PCIC_CDT_ENA 0x08 /* Card Detect Enable */ -#define PCIC_RDY_ENA 0x04 /* Ready Enable */ -#define PCIC_BATWRN_ENA 0x02 /* Battery Warning */ -#define PCIC_BATDED_ENA 0x01 /* Battery Dead */ -#define PCIC_ST_ENA 0x01 /* Status Change */ - -/* For the Address Window Enable Register (PCIC_ADDRWINE) */ -#define PCIC_SM0_EN 0x01 /* Memory Window 0 Enable */ -#define PCIC_SM1_EN 0x02 /* Memory Window 1 Enable */ -#define PCIC_SM2_EN 0x04 /* Memory Window 2 Enable */ -#define PCIC_SM3_EN 0x08 /* Memory Window 3 Enable */ -#define PCIC_SM4_EN 0x10 /* Memory Window 4 Enable */ -#define PCIC_MEMCS16 0x20 /* ~MEMCS16 Decode A23-A12 */ -#define PCIC_IO0_EN 0x40 /* I/O Window 0 Enable */ -#define PCIC_IO1_EN 0x80 /* I/O Window 1 Enable */ - -/* For the I/O Control Register (PCIC_IOCTL) */ -#define PCIC_IO0_16BIT 0x01 /* I/O to this segment is 16 bit */ -#define PCIC_IO0_CS16 0x02 /* I/O cs16 source is the card */ -#define PCIC_IO0_0WS 0x04 /* zero wait states added on 8 bit cycles */ -#define PCIC_IO0_WS 0x08 /* Wait states added for 16 bit cycles */ -#define PCIC_IO1_16BIT 0x10 /* I/O to this segment is 16 bit */ -#define PCIC_IO1_CS16 0x20 /* I/O cs16 source is the card */ -#define PCIC_IO1_0WS 0x40 /* zero wait states added on 8 bit cycles */ -#define PCIC_IO1_WS 0x80 /* Wait states added for 16 bit cycles */ - -/* For the various I/O and Memory windows */ -#define PCIC_ADDR_LOW 0 -#define PCIC_ADDR_HIGH 1 -#define PCIC_START 0x00 /* Start of mapping region */ -#define PCIC_END 0x02 /* End of mapping region */ -#define PCIC_MOFF 0x04 /* Card Memory Mapping region offset */ -#define PCIC_IO0 0x08 /* I/O Address 0 */ -#define PCIC_IO1 0x0c /* I/O Address 1 */ -#define PCIC_SM0 0x10 /* System Memory Address 0 Mapping */ -#define PCIC_SM1 0x18 /* System Memory Address 1 Mapping */ -#define PCIC_SM2 0x20 /* System Memory Address 2 Mapping */ -#define PCIC_SM3 0x28 /* System Memory Address 3 Mapping */ -#define PCIC_SM4 0x30 /* System Memory Address 4 Mapping */ - -/* For System Memory Window start registers - (PCIC_SMx|PCIC_START|PCIC_ADDR_HIGH) */ -#define PCIC_ZEROWS 0x40 /* Zero wait states */ -#define PCIC_DATA16 0x80 /* Data width is 16 bits */ - -/* For System Memory Window stop registers - (PCIC_SMx|PCIC_END|PCIC_ADDR_HIGH) */ -#define PCIC_MW0 0x40 /* Wait state bit 0 */ -#define PCIC_MW1 0x80 /* Wait state bit 1 */ - -/* For System Memory Window offset registers - (PCIC_SMx|PCIC_MOFF|PCIC_ADDR_HIGH) */ -#define PCIC_REG 0x40 /* Attribute/Common select (why called Reg?) */ -#define PCIC_WP 0x80 /* Write-protect this window */ - -/* For Card Detect and General Control register (PCIC_CDGC) */ -#define PCIC_16_DL_INH 0x01 /* 16-bit memory delay inhibit */ -#define PCIC_CNFG_RST_EN 0x02 /* configuration reset enable */ -#define PCIC_GPI_EN 0x04 /* General Purpose Input (GPI) Enable */ -#define PCIC_GPI_TRANS 0x08 /* GPI Transition Control */ -#define PCIC_CDRES_EN 0x10 /* card detect resume enable */ -#define PCIC_SW_CD_INT 0x20 /* s/w card detect interrupt */ - -/* structure for ioctl */ -struct pcic_register { - u_char addr; - u_char val; -}; -struct pcic_regs { - u_short chip_vers; -#define PCMICA_CHIP_82365_0 1 -#define PCMICA_CHIP_82365_1 2 -#define PCMICA_CHIP_IBM_1 3 -#define PCMICA_CHIP_IBM_2 4 -#define PCMICA_CHIP_146FC6 5 -#define PCMICA_CHIP_146FC7 6 - u_short cnt; - struct pcic_register reg[128]; -}; -/* DON'T ADD ANYTHING AFTER THIS #endif */ -#endif /* __82365_H__ */ -#ifndef __82365_H__ -#define __82365_H__ -#endif +#define PCIC_CHIP0_BASE 0x00 +#define PCIC_CHIP1_BASE 0x80 + +/* Each PCIC chip can drive two sockets */ + +#define PCIC_SOCKETA_INDEX 0x00 +#define PCIC_SOCKETB_INDEX 0x40 + +/* general setup registers */ + +#define PCIC_IDENT 0x00 /* RO */ +#define PCIC_IDENT_IFTYPE_MASK 0xC0 +#define PCIC_IDENT_IFTYPE_IO_ONLY 0x00 +#define PCIC_IDENT_IFTYPE_MEM_ONLY 0x40 +#define PCIC_IDENT_IFTYPE_MEM_AND_IO 0x80 +#define PCIC_IDENT_IFTYPE_RESERVED 0xC0 +#define PCIC_IDENT_ZERO 0x30 +#define PCIC_IDENT_REV_MASK 0x0F +#define PCIC_IDENT_REV_I82365SLR0 0x02 +#define PCIC_IDENT_REV_I82365SLR1 0x03 + +#define PCIC_IF_STATUS 0x01 /* RO */ +#define PCIC_IF_STATUS_GPI 0x80 /* General Purpose Input */ +#define PCIC_IF_STATUS_POWERACTIVE 0x40 +#define PCIC_IF_STATUS_READY 0x20 /* really READY/!BUSY */ +#define PCIC_IF_STATUS_MEM_WP 0x10 +#define PCIC_IF_STATUS_CARDDETECT_MASK 0x0C +#define PCIC_IF_STATUS_CARDDETECT_PRESENT 0x0C +#define PCIC_IF_STATUS_BATTERY_MASK 0x03 +#define PCIC_IF_STATUS_BATTERY_DEAD1 0x00 +#define PCIC_IF_STATUS_BATTERY_DEAD2 0x01 +#define PCIC_IF_STATUS_BATTERY_WARNING 0x02 +#define PCIC_IF_STATUS_BATTERY_GOOD 0x03 + +#define PCIC_PWRCTL 0x02 /* RW */ +#define PCIC_PWRCTL_OE 0x80 /* output enable */ +#define PCIC_PWRCTL_DISABLE_RESETDRV 0x40 +#define PCIC_PWRCTL_AUTOSWITCH_ENABLE 0x20 +#define PCIC_PWRCTL_PWR_ENABLE 0x10 +#define PCIC_PWRCTL_VPP2_MASK 0x0C +/* XXX these are a little unclear from the data sheet */ +#define PCIC_PWRCTL_VPP2_RESERVED 0x0C +#define PCIC_PWRCTL_VPP2_EN1 0x08 +#define PCIC_PWRCTL_VPP2_EN0 0x04 +#define PCIC_PWRCTL_VPP2_ENX 0x00 +#define PCIC_PWRCTL_VPP1_MASK 0x03 +/* XXX these are a little unclear from the data sheet */ +#define PCIC_PWRCTL_VPP1_RESERVED 0x03 +#define PCIC_PWRCTL_VPP1_EN1 0x02 +#define PCIC_PWRCTL_VPP1_EN0 0x01 +#define PCIC_PWRCTL_VPP1_ENX 0x00 + +#define PCIC_CSC 0x04 /* RW */ +#define PCIC_CSC_ZERO 0xE0 +#define PCIC_CSC_GPI 0x10 +#define PCIC_CSC_CD 0x08 /* Card Detect Change */ +#define PCIC_CSC_READY 0x04 +#define PCIC_CSC_BATTWARN 0x02 +#define PCIC_CSC_BATTDEAD 0x01 /* for memory cards */ +#define PCIC_CSC_RI 0x01 /* for i/o cards */ + +#define PCIC_ADDRWIN_ENABLE 0x06 /* RW */ +#define PCIC_ADDRWIN_ENABLE_IO1 0x80 +#define PCIC_ADDRWIN_ENABLE_IO0 0x40 +#define PCIC_ADDRWIN_ENABLE_MEMCS16 0x20 /* rtfds if you care */ +#define PCIC_ADDRWIN_ENABLE_MEM4 0x10 +#define PCIC_ADDRWIN_ENABLE_MEM3 0x08 +#define PCIC_ADDRWIN_ENABLE_MEM2 0x04 +#define PCIC_ADDRWIN_ENABLE_MEM1 0x02 +#define PCIC_ADDRWIN_ENABLE_MEM0 0x01 + +#define PCIC_CARD_DETECT 0x16 /* RW */ +#define PCIC_CARD_DETECT_RESERVED 0xC0 +#define PCIC_CARD_DETECT_SW_INTR 0x20 +#define PCIC_CARD_DETECT_RESUME_ENABLE 0x10 +#define PCIC_CARD_DETECT_GPI_TRANSCTL 0x08 +#define PCIC_CARD_DETECT_GPI_ENABLE 0x04 +#define PCIC_CARD_DETECT_CFGRST_ENABLE 0x02 +#define PCIC_CARD_DETECT_MEMDLY_INHIBIT 0x01 + +/* interrupt registers */ + +#define PCIC_INTR 0x03 /* RW */ +#define PCIC_INTR_RI_ENABLE 0x80 +#define PCIC_INTR_RESET 0x40 /* active low (zero) */ +#define PCIC_INTR_CARDTYPE_MASK 0x20 +#define PCIC_INTR_CARDTYPE_IO 0x20 +#define PCIC_INTR_CARDTYPE_MEM 0x00 +#define PCIC_INTR_ENABLE 0x10 +#define PCIC_INTR_IRQ_MASK 0x0F +#define PCIC_INTR_IRQ_SHIFT 0 +#define PCIC_INTR_IRQ_NONE 0x00 +#define PCIC_INTR_IRQ_RESERVED1 0x01 +#define PCIC_INTR_IRQ_RESERVED2 0x02 +#define PCIC_INTR_IRQ3 0x03 +#define PCIC_INTR_IRQ4 0x04 +#define PCIC_INTR_IRQ5 0x05 +#define PCIC_INTR_IRQ_RESERVED6 0x06 +#define PCIC_INTR_IRQ7 0x07 +#define PCIC_INTR_IRQ_RESERVED8 0x08 +#define PCIC_INTR_IRQ9 0x09 +#define PCIC_INTR_IRQ10 0x0A +#define PCIC_INTR_IRQ11 0x0B +#define PCIC_INTR_IRQ12 0x0C +#define PCIC_INTR_IRQ_RESERVED13 0x0D +#define PCIC_INTR_IRQ14 0x0E +#define PCIC_INTR_IRQ15 0x0F + +#define PCIC_INTR_IRQ_VALIDMASK 0xDEB8 /* 1101 1110 1011 1000 */ + +#define PCIC_CSC_INTR 0x05 /* RW */ +#define PCIC_CSC_INTR_IRQ_MASK 0xF0 +#define PCIC_CSC_INTR_IRQ_SHIFT 4 +#define PCIC_CSC_INTR_IRQ_NONE 0x00 +#define PCIC_CSC_INTR_IRQ_RESERVED1 0x10 +#define PCIC_CSC_INTR_IRQ_RESERVED2 0x20 +#define PCIC_CSC_INTR_IRQ3 0x30 +#define PCIC_CSC_INTR_IRQ4 0x40 +#define PCIC_CSC_INTR_IRQ5 0x50 +#define PCIC_CSC_INTR_IRQ_RESERVED6 0x60 +#define PCIC_CSC_INTR_IRQ7 0x70 +#define PCIC_CSC_INTR_IRQ_RESERVED8 0x80 +#define PCIC_CSC_INTR_IRQ9 0x90 +#define PCIC_CSC_INTR_IRQ10 0xA0 +#define PCIC_CSC_INTR_IRQ11 0xB0 +#define PCIC_CSC_INTR_IRQ12 0xC0 +#define PCIC_CSC_INTR_IRQ_RESERVED13 0xD0 +#define PCIC_CSC_INTR_IRQ14 0xE0 +#define PCIC_CSC_INTR_IRQ15 0xF0 +#define PCIC_CSC_INTR_CD_ENABLE 0x08 +#define PCIC_CSC_INTR_READY_ENABLE 0x04 +#define PCIC_CSC_INTR_BATTWARN_ENABLE 0x02 +#define PCIC_CSC_INTR_BATTDEAD_ENABLE 0x01 /* for memory cards */ +#define PCIC_CSC_INTR_RI_ENABLE 0x01 /* for I/O cards */ + +#define PCIC_CSC_INTR_IRQ_VALIDMASK 0xDEB8 /* 1101 1110 1011 1000 */ + +/* I/O registers */ + +#define PCIC_IO_WINS 2 + +#define PCIC_IOCTL 0x07 /* RW */ +#define PCIC_IOCTL_IO1_WAITSTATE 0x80 +#define PCIC_IOCTL_IO1_ZEROWAIT 0x40 +#define PCIC_IOCTL_IO1_IOCS16SRC_MASK 0x20 +#define PCIC_IOCTL_IO1_IOCS16SRC_CARD 0x20 +#define PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE 0x00 +#define PCIC_IOCTL_IO1_DATASIZE_MASK 0x10 +#define PCIC_IOCTL_IO1_DATASIZE_16BIT 0x10 +#define PCIC_IOCTL_IO1_DATASIZE_8BIT 0x00 +#define PCIC_IOCTL_IO0_WAITSTATE 0x08 +#define PCIC_IOCTL_IO0_ZEROWAIT 0x04 +#define PCIC_IOCTL_IO0_IOCS16SRC_MASK 0x02 +#define PCIC_IOCTL_IO0_IOCS16SRC_CARD 0x02 +#define PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE 0x00 +#define PCIC_IOCTL_IO0_DATASIZE_MASK 0x01 +#define PCIC_IOCTL_IO0_DATASIZE_16BIT 0x01 +#define PCIC_IOCTL_IO0_DATASIZE_8BIT 0x00 + +#define PCIC_IOADDR0_START_LSB 0x08 +#define PCIC_IOADDR0_START_MSB 0x09 +#define PCIC_IOADDR0_STOP_LSB 0x0A +#define PCIC_IOADDR0_STOP_MSB 0x0B +#define PCIC_IOADDR1_START_LSB 0x0C +#define PCIC_IOADDR1_START_MSB 0x0D +#define PCIC_IOADDR1_STOP_LSB 0x0E +#define PCIC_IOADDR1_STOP_MSB 0x0F + +/* memory registers */ + +/* + * memory window addresses refer to bits A23-A12 of the ISA system memory + * address. This is a shift of 12 bits. The LSB contains A19-A12, and the + * MSB contains A23-A20, plus some other bits. + */ + +#define PCIC_MEM_WINS 5 + +#define PCIC_MEM_SHIFT 12 +#define PCIC_MEM_PAGESIZE (1<<PCIC_MEM_SHIFT) + +#define PCIC_SYSMEM_ADDRX_SHIFT PCIC_MEM_SHIFT +#define PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_MASK 0x80 +#define PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT 0x80 +#define PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_8BIT 0x00 +#define PCIC_SYSMEM_ADDRX_START_MSB_ZEROWAIT 0x40 +#define PCIC_SYSMEM_ADDRX_START_MSB_SCRATCH_MASK 0x30 +#define PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK 0x0F + +#define PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT_MASK 0xC0 +#define PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT0 0x00 +#define PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT1 0x40 +#define PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2 0x80 +#define PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT3 0xC0 +#define PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK 0x0F + +/* + * The card side of a memory mapping consists of bits A19-A12 of the card + * memory address in the LSB, and A25-A20 plus some other bits in the MSB. + * Again, the shift is 12 bits. + */ + +#define PCIC_CARDMEM_ADDRX_SHIFT PCIC_MEM_SHIFT +#define PCIC_CARDMEM_ADDRX_MSB_WP 0x80 +#define PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_MASK 0x40 +#define PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR 0x40 +#define PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_COMMON 0x00 +#define PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK 0x3F + +#define PCIC_SYSMEM_ADDR0_START_LSB 0x10 +#define PCIC_SYSMEM_ADDR0_START_MSB 0x11 +#define PCIC_SYSMEM_ADDR0_STOP_LSB 0x12 +#define PCIC_SYSMEM_ADDR0_STOP_MSB 0x13 + +#define PCIC_CARDMEM_ADDR0_LSB 0x14 +#define PCIC_CARDMEM_ADDR0_MSB 0x15 + +/* #define PCIC_RESERVED 0x17 */ + +#define PCIC_SYSMEM_ADDR1_START_LSB 0x18 +#define PCIC_SYSMEM_ADDR1_START_MSB 0x19 +#define PCIC_SYSMEM_ADDR1_STOP_LSB 0x1A +#define PCIC_SYSMEM_ADDR1_STOP_MSB 0x1B + +#define PCIC_CARDMEM_ADDR1_LSB 0x1C +#define PCIC_CARDMEM_ADDR1_MSB 0x1D + +#define PCIC_SYSMEM_ADDR2_START_LSB 0x20 +#define PCIC_SYSMEM_ADDR2_START_MSB 0x21 +#define PCIC_SYSMEM_ADDR2_STOP_LSB 0x22 +#define PCIC_SYSMEM_ADDR2_STOP_MSB 0x23 + +#define PCIC_CARDMEM_ADDR2_LSB 0x24 +#define PCIC_CARDMEM_ADDR2_MSB 0x25 + +/* #define PCIC_RESERVED 0x26 */ +/* #define PCIC_RESERVED 0x27 */ + +#define PCIC_SYSMEM_ADDR3_START_LSB 0x28 +#define PCIC_SYSMEM_ADDR3_START_MSB 0x29 +#define PCIC_SYSMEM_ADDR3_STOP_LSB 0x2A +#define PCIC_SYSMEM_ADDR3_STOP_MSB 0x2B + +#define PCIC_CARDMEM_ADDR3_LSB 0x2C +#define PCIC_CARDMEM_ADDR3_MSB 0x2D + +/* #define PCIC_RESERVED 0x2E */ +/* #define PCIC_RESERVED 0x2F */ + +#define PCIC_SYSMEM_ADDR4_START_LSB 0x30 +#define PCIC_SYSMEM_ADDR4_START_MSB 0x31 +#define PCIC_SYSMEM_ADDR4_STOP_LSB 0x32 +#define PCIC_SYSMEM_ADDR4_STOP_MSB 0x33 + +#define PCIC_CARDMEM_ADDR4_LSB 0x34 +#define PCIC_CARDMEM_ADDR4_MSB 0x35 + +/* #define PCIC_RESERVED 0x36 */ +/* #define PCIC_RESERVED 0x37 */ +/* #define PCIC_RESERVED 0x38 */ +/* #define PCIC_RESERVED 0x39 */ +/* #define PCIC_RESERVED 0x3A */ +/* #define PCIC_RESERVED 0x3B */ +/* #define PCIC_RESERVED 0x3C */ +/* #define PCIC_RESERVED 0x3D */ +/* #define PCIC_RESERVED 0x3E */ +/* #define PCIC_RESERVED 0x3F */ + +/* vendor-specific registers */ + +#define PCIC_INTEL_GLOBAL_CTL 0x1E /* RW */ +#define PCIC_INTEL_GLOBAL_CTL_RESERVED 0xF0 +#define PCIC_INTEL_GLOBAL_CTL_IRQ14PULSE_ENABLE 0x08 +#define PCIC_INTEL_GLOBAL_CTL_EXPLICIT_CSC_ACK 0x04 +#define PCIC_INTEL_GLOBAL_CTL_IRQLEVEL_ENABLE 0x02 +#define PCIC_INTEL_GLOBAL_CTL_POWERDOWN 0x01 + +#define PCIC_CIRRUS_MISC_CTL_2 0x1E +#define PCIC_CIRRUS_MISC_CTL_2_SUSPEND 0x04 + +#define PCIC_CIRRUS_CHIP_INFO 0x1F +#define PCIC_CIRRUS_CHIP_INFO_CHIP_ID 0xC0 +#define PCIC_CIRRUS_CHIP_INFO_SLOTS 0x20 +#define PCIC_CIRRUS_CHIP_INFO_REV 0x1F diff --git a/sys/dev/ic/i82365var.h b/sys/dev/ic/i82365var.h new file mode 100644 index 00000000000..7c96d40f90a --- /dev/null +++ b/sys/dev/ic/i82365var.h @@ -0,0 +1,169 @@ +/* $OpenBSD: i82365var.h,v 1.1 1998/09/11 07:53:58 fgsch Exp $ */ +/* $NetBSD: i82365var.h,v 1.4 1998/05/23 18:32:29 matt Exp $ */ + +/* + * Copyright (c) 1997 Marc Horowitz. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Marc Horowitz. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/device.h> + +#include <dev/pcmcia/pcmciareg.h> +#include <dev/pcmcia/pcmciachip.h> + +#include <dev/ic/i82365reg.h> + +struct pcic_handle { + struct pcic_softc *sc; + int vendor; + int sock; + int flags; + int memalloc; + struct { + bus_addr_t addr; + bus_size_t size; + long offset; + int kind; + } mem[PCIC_MEM_WINS]; + int ioalloc; + struct { + bus_addr_t addr; + bus_size_t size; + int width; + } io[PCIC_IO_WINS]; + int ih_irq; + struct device *pcmcia; +}; + +#define PCIC_FLAG_SOCKETP 0x0001 +#define PCIC_FLAG_CARDP 0x0002 + +#define C0SA PCIC_CHIP0_BASE+PCIC_SOCKETA_INDEX +#define C0SB PCIC_CHIP0_BASE+PCIC_SOCKETB_INDEX +#define C1SA PCIC_CHIP1_BASE+PCIC_SOCKETA_INDEX +#define C1SB PCIC_CHIP1_BASE+PCIC_SOCKETB_INDEX + +/* + * This is sort of arbitrary. It merely needs to be "enough". It can be + * overridden in the conf file, anyway. + */ + +#define PCIC_MEM_PAGES 4 +#define PCIC_MEMSIZE PCIC_MEM_PAGES*PCIC_MEM_PAGESIZE + +#define PCIC_NSLOTS 4 + +struct pcic_softc { + struct device dev; + + bus_space_tag_t memt; + bus_space_handle_t memh; + bus_space_tag_t iot; + bus_space_handle_t ioh; + + /* XXX isa_chipset_tag_t, pci_chipset_tag_t, etc. */ + void *intr_est; + + pcmcia_chipset_tag_t pct; + + /* this needs to be large enough to hold PCIC_MEM_PAGES bits */ + int subregionmask; + + /* used by memory window mapping functions */ + bus_addr_t membase; + + /* + * used by io window mapping functions. These can actually overlap + * with another pcic, since the underlying extent mapper will deal + * with individual allocations. This is here to deal with the fact + * that different busses have different real widths (different pc + * hardware seems to use 10 or 12 bits for the I/O bus). + */ + bus_addr_t iobase; + bus_addr_t iosize; + + int irq; + void *ih; + + struct pcic_handle handle[PCIC_NSLOTS]; +}; + + +int pcic_ident_ok __P((int)); +int pcic_vendor __P((struct pcic_handle *)); +char *pcic_vendor_to_string __P((int)); + +void pcic_attach __P((struct pcic_softc *)); +void pcic_attach_sockets __P((struct pcic_softc *)); +int pcic_intr __P((void *arg)); + +static inline int pcic_read __P((struct pcic_handle *, int)); +static inline void pcic_write __P((struct pcic_handle *, int, int)); + +int pcic_chip_mem_alloc __P((pcmcia_chipset_handle_t, bus_size_t, + struct pcmcia_mem_handle *)); +void pcic_chip_mem_free __P((pcmcia_chipset_handle_t, + struct pcmcia_mem_handle *)); +int pcic_chip_mem_map __P((pcmcia_chipset_handle_t, int, bus_addr_t, + bus_size_t, struct pcmcia_mem_handle *, bus_addr_t *, int *)); +void pcic_chip_mem_unmap __P((pcmcia_chipset_handle_t, int)); + +int pcic_chip_io_alloc __P((pcmcia_chipset_handle_t, bus_addr_t, + bus_size_t, bus_size_t, struct pcmcia_io_handle *)); +void pcic_chip_io_free __P((pcmcia_chipset_handle_t, + struct pcmcia_io_handle *)); +int pcic_chip_io_map __P((pcmcia_chipset_handle_t, int, bus_addr_t, + bus_size_t, struct pcmcia_io_handle *, int *)); +void pcic_chip_io_unmap __P((pcmcia_chipset_handle_t, int)); + +void pcic_chip_socket_enable __P((pcmcia_chipset_handle_t)); +void pcic_chip_socket_disable __P((pcmcia_chipset_handle_t)); + +static __inline int pcic_read __P((struct pcic_handle *, int)); +static __inline int +pcic_read(h, idx) + struct pcic_handle *h; + int idx; +{ + if (idx != -1) + bus_space_write_1(h->sc->iot, h->sc->ioh, PCIC_REG_INDEX, + h->sock + idx); + return (bus_space_read_1(h->sc->iot, h->sc->ioh, PCIC_REG_DATA)); +} + +static __inline void pcic_write __P((struct pcic_handle *, int, int)); +static __inline void +pcic_write(h, idx, data) + struct pcic_handle *h; + int idx; + int data; +{ + if (idx != -1) + bus_space_write_1(h->sc->iot, h->sc->ioh, PCIC_REG_INDEX, + h->sock + idx); + bus_space_write_1(h->sc->iot, h->sc->ioh, PCIC_REG_DATA, (data)); +} |