diff options
| -rw-r--r-- | sys/conf/files | 3 | ||||
| -rw-r--r-- | sys/pccard/i82365.h | 41 | ||||
| -rw-r--r-- | sys/pccard/pccard.c | 133 | ||||
| -rw-r--r-- | sys/pccard/pccard_nbk.c | 110 | ||||
| -rw-r--r-- | sys/pccard/pcic.c | 1177 | ||||
| -rw-r--r-- | sys/pccard/pcic_pci.c | 4 | ||||
| -rw-r--r-- | sys/pccard/slot.h | 13 |
7 files changed, 489 insertions, 992 deletions
diff --git a/sys/conf/files b/sys/conf/files index 508e607401a1..540cd29e174d 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -914,7 +914,8 @@ pccard/pccard.c optional card pccard/pccard_beep.c optional card pccard/pccard_nbk.c optional card pccard/pcic.c optional pcic card -pccard/pcic_pci.c optional pcic pci +pccard/pcic_isa.c optional pcic isa card +pccard/pcic_pci.c optional pcic pci card pci/agp.c optional agp pci/agp_intel.c optional agp pci/agp_via.c optional agp diff --git a/sys/pccard/i82365.h b/sys/pccard/i82365.h index e8ef822813c6..633923f86758 100644 --- a/sys/pccard/i82365.h +++ b/sys/pccard/i82365.h @@ -8,6 +8,7 @@ * Updated 3/3/95 to include Cirrus Logic stuff. *------------------------------------------------------------------------- * + * Copyright (c) 2001 M. Warner Losh. All rights reserved. * Copyright (c) 1995 Andrew McRae. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,7 +36,7 @@ * $FreeBSD$ */ -#define PCIC_I82365 0 /* Intel chip */ +#define PCIC_I82365 0 /* Intel i82365SL-A/B or clone */ #define PCIC_IBM 1 /* IBM clone */ #define PCIC_VLSI 2 /* VLSI chip */ #define PCIC_PD672X 3 /* Cirrus logic 672x */ @@ -44,11 +45,10 @@ #define PCIC_VG465 6 /* Vadem 465 */ #define PCIC_VG468 7 /* Vadem 468 */ #define PCIC_VG469 8 /* Vadem 469 */ -#define PCIC_RF5C396 9 /* Ricoh RF5C396 */ -#define PCIC_IBM_KING 10 /* IBM KING PCMCIA Controller */ -#define PCIC_PC98 11 /* NEC PC98 PCMCIA Controller */ -/* These last ones aren't in normal freebsd */ -#define PCIC_TI1130 12 /* TI PCI1130 CardBus */ +#define PCIC_RF5C296 9 /* Ricoh RF5C296 */ +#define PCIC_RF5C396 10 /* Ricoh RF5C396 */ +#define PCIC_IBM_KING 11 /* IBM KING PCMCIA Controller */ +#define PCIC_I82365SL_DF 12 /* Intel i82365sl-DF step */ /* * Address of the controllers. Each controller can manage @@ -61,10 +61,10 @@ * identify the port number, and the lower 6 bits * select one of the 64 possible data registers. */ -#define PCIC_INDEX_0 0x3e0 /* index reg, chips 0 and 1 */ -#define PCIC_DATA_0 (PCIC_INDEX_0 + 1) /* data reg, chips 0 and 1 */ -#define PCIC_INDEX_1 (PCIC_INDEX_0 + 2) /* index reg, chips 2 and 3 */ -#define PCIC_DATA_1 (PCIC_INDEX_1 + 1) /* data reg, chips 2 and 3 */ +#define PCIC_INDEX 0 /* Index register */ +#define PCIC_DATA 1 /* Data register */ +#define PCIC_NPORT 2 /* Number of ports */ +#define PCIC_PORT_0 0x3e0 /* index reg, chips 0 and 1 */ /* * Register index addresses. @@ -86,8 +86,10 @@ #define PCIC_MISC2 0x1e /* PD672x: Misc control register 2 per chip */ #define PCIC_CLCHIP 0x1f /* PD67xx: Chip I/D */ #define PCIC_CVSR 0x2f /* Vadem: Voltage select register */ +#define PCIC_RICOH_MCR2 0x2f /* Ricoh: Mode Control Register 2 */ #define PCIC_VMISC 0x3a /* Vadem: Misc control register */ +#define PCIC_RICOH_ID 0x3a /* Ricoh: ID register */ #define PCIC_TIME_SETUP0 0x3a #define PCIC_TIME_CMD0 0x3b @@ -103,6 +105,7 @@ /* 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_INTEL2 0x84 /* Intel 82365SL step D */ #define PCIC_VLSI82C146 0x84 /* VLSI 82C146 */ #define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */ #define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */ @@ -123,6 +126,7 @@ #define PCIC_PCPWRE 0x10 /* PC Card Power Enable */ #define PCIC_VCC 0x18 /* Vcc control bits */ #define PCIC_VCC_5V 0x10 /* 5 volts */ +#define PCIC_VCC_ON 0x10 /* Turn on VCC on some chips. */ #define PCIC_VCC_3V 0x18 /* 3 volts */ #define PCIC_VCC_5V_KING 0x14 /* 5 volts for KING PCIC */ #define PCIC_VPP 0x03 /* Vpp control bits */ @@ -208,6 +212,8 @@ #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 */ +#define PCIC_VS1STAT 0x40 /* 0 VS1# low, 1 VS1# high */ +#define PCIC_VS2STAT 0x80 /* 0 VS2# low, 1 VS2# high */ /* CL-PD67[12]x: For 3.3V cards, etc. (PCIC_MISC1) */ #define PCIC_MISC1_5V_DETECT 0x01 /* PD6710 only */ @@ -239,9 +245,16 @@ #define PCIC_CVSR_VS_XX 0x02 /* X.XV when available */ #define PCIC_CVSR_VS_33 0x03 /* 3.3V */ +/* Ricoh: Misc Control Register 2 (PCIC_RICOH_MCR2) */ +#define PCIC_MCR2_VCC_33 0x01 /* 3.3V */ + /* Vadem: misc register (PCIC_VMISC) */ #define PCIC_VADEMREV 0x40 +/* Ricoh: ID register values (PCIC_RICOH_ID) */ +#define PCIC_RID_296 0x32 +#define PCIC_RID_396 0xb2 + /* * Mask of allowable interrupts. * @@ -254,11 +267,11 @@ * * For NEC PC98 machines, irq 3, 5, 6, 9, 10, 11, 12, 13 are allowed. * These correspond to the C-BUS signals INT 0, 1, 2, 3, 41, 42, 5, 6 - * respectively. This is with the desktop C-BUS addin card. I don't - * know if this corresponds to laptop usage or not. + * respectively. This is with the desktop C-BUS addin card. * - * I'm not sure the proper way to map these interrupts, but it looks - * like pc98 is a subset of ibm-at so no actual mapping is required. + * Hiroshi TSUKADA-san writes in FreeBSD98-testers that cbus IRQ + * 6 is routed to the IRQ 7 pin of the pcic in pc98 cbus based + * cards. I do not know how pc98 laptop models are wired. */ #ifdef PC98 #define PCIC_INT_MASK_ALLOWED 0x3E68 /* PC98 */ diff --git a/sys/pccard/pccard.c b/sys/pccard/pccard.c index 92d62bf5f87c..069dda6fcf79 100644 --- a/sys/pccard/pccard.c +++ b/sys/pccard/pccard.c @@ -39,9 +39,9 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> +#include <sys/sysctl.h> #include <sys/proc.h> #include <sys/select.h> -#include <sys/sysctl.h> #include <sys/conf.h> #include <sys/uio.h> #include <sys/poll.h> @@ -50,7 +50,6 @@ #include <pccard/cardinfo.h> #include <pccard/driver.h> -#include <pccard/pcic.h> #include <pccard/slot.h> #include <pccard/pccard_nbk.h> @@ -71,14 +70,14 @@ static void disable_slot(struct slot *); static void disable_slot_to(struct slot *); static void power_off_slot(void *); -static struct slot *pccard_slots[MAXSLOT]; /* slot entries */ - /* * The driver interface for read/write uses a block * of memory in the ISA I/O memory space allocated via * an ioctl setting. + * + * Now that we have different bus attachments, we should really + * use a better algorythm to allocate memory. */ -/* XXX this should be in pcic */ static unsigned long pccard_mem; /* Physical memory */ static unsigned char *pccard_kmem; /* Kernel virtual address */ static struct resource *pccard_mem_res; @@ -123,6 +122,8 @@ power_off_slot(void *arg) * the interrupt unitl after disable runs so that we can get rid * rid of the interrupt before it becomes unsafe to touch the * device. + * + * XXX In current, the spl stuff is a nop. */ s = splhigh(); /* Power off the slot. */ @@ -138,7 +139,6 @@ power_off_slot(void *arg) static void disable_slot(struct slot *slt) { - /* XXX Need to store pccarddev in slt. */ device_t pccarddev; device_t *kids; int nkids; @@ -150,7 +150,7 @@ disable_slot(struct slot *slt) * driver is accessing the device and it is removed, then * all bets are off... */ - pccarddev = devclass_get_device(pccard_devclass, slt->slotnum); + pccarddev = slt->dev; device_get_children(pccarddev, &kids, &nkids); for (i = 0; i < nkids; i++) { if ((ret = device_delete_child(pccarddev, kids[i])) != 0) @@ -175,31 +175,26 @@ disable_slot_to(struct slot *slt) } /* - * pccard_alloc_slot - Called from controller probe - * routine, this function allocates a new PC-CARD slot - * and initialises the data structures using the data provided. - * It returns the allocated structure to the probe routine - * to allow the controller specific data to be initialised. + * pccard_init_slot - Initialize the slot controller and attach various + * things to it. We also make the device for it. We create the device that + * will be exported to devfs. */ struct slot * -pccard_alloc_slot(struct slot_ctrl *ctrl) +pccard_init_slot(device_t dev, struct slot_ctrl *ctrl) { - struct slot *slt; - int slotno; - - for (slotno = 0; slotno < MAXSLOT; slotno++) - if (pccard_slots[slotno] == 0) - break; - if (slotno == MAXSLOT) - return (0); - - MALLOC(slt, struct slot *, sizeof(*slt), M_DEVBUF, M_WAITOK | M_ZERO); - make_dev(&crd_cdevsw, slotno, 0, 0, 0600, "card%d", slotno); + int slotno; + struct slot *slt; + + slt = PCCARD_DEVICE2SOFTC(dev); + slotno = device_get_unit(dev); + slt->dev = dev; + slt->d = make_dev(&crd_cdevsw, slotno, 0, 0, 0600, "card%d", slotno); + slt->d->si_drv1 = slt; slt->ctrl = ctrl; slt->slotnum = slotno; - pccard_slots[slotno] = slt; callout_handle_init(&slt->insert_ch); callout_handle_init(&slt->poff_ch); + return (slt); } @@ -215,7 +210,7 @@ allocate_driver(struct slot *slt, struct dev_desc *desc) int err, irq = 0; device_t child; - pccarddev = devclass_get_device(pccard_devclass, slt->slotnum); + pccarddev = slt->dev; irq = ffs(desc->irqmask) - 1; MALLOC(devi, struct pccard_devinfo *, sizeof(*devi), M_DEVBUF, M_WAITOK | M_ZERO); @@ -329,12 +324,9 @@ pccard_event(struct slot *slt, enum card_event event) static int crdopen(dev_t dev, int oflags, int devtype, struct proc *p) { - struct slot *slt; + struct slot *slt = PCCARD_DEV2SOFTC(dev); - if (minor(dev) >= MAXSLOT) - return (ENXIO); - slt = pccard_slots[minor(dev)]; - if (slt == 0) + if (slt == NULL) return (ENXIO); if (slt->rwmem == 0) slt->rwmem = MDF_ATTR; @@ -358,7 +350,7 @@ crdclose(dev_t dev, int fflag, int devtype, struct proc *p) static int crdread(dev_t dev, struct uio *uio, int ioflag) { - struct slot *slt = pccard_slots[minor(dev)]; + struct slot *slt = PCCARD_DEV2SOFTC(dev); struct mem_desc *mp, oldmap; unsigned char *p; unsigned int offs; @@ -375,7 +367,7 @@ crdread(dev_t dev, struct uio *uio, int ioflag) return (EBUSY); mp = &slt->mem[win]; oldmap = *mp; - mp->flags = slt->rwmem|MDF_ACTIVE; + mp->flags = slt->rwmem | MDF_ACTIVE; while (uio->uio_resid && error == 0) { mp->card = uio->uio_offset; mp->size = PCCARD_MEMSIZE; @@ -404,7 +396,7 @@ crdread(dev_t dev, struct uio *uio, int ioflag) static int crdwrite(dev_t dev, struct uio *uio, int ioflag) { - struct slot *slt = pccard_slots[minor(dev)]; + struct slot *slt = PCCARD_DEV2SOFTC(dev); struct mem_desc *mp, oldmap; unsigned char *p; unsigned int offs; @@ -421,7 +413,7 @@ crdwrite(dev_t dev, struct uio *uio, int ioflag) return (EBUSY); mp = &slt->mem[win]; oldmap = *mp; - mp->flags = slt->rwmem|MDF_ACTIVE; + mp->flags = slt->rwmem | MDF_ACTIVE; while (uio->uio_resid && error == 0) { mp->card = uio->uio_offset; mp->size = PCCARD_MEMSIZE; @@ -447,18 +439,13 @@ crdioctl_sresource(dev_t dev, caddr_t data) { struct pccard_resource *pr; struct resource *r; - device_t pcicdev; - int i; - int rid = 1; - int err; + int flags; + int rid = 0; + device_t bridgedev; pr = (struct pccard_resource *)data; pr->resource_addr = ~0ul; - /* - * pccard_devclass does not have soft_c - * so we use pcic_devclass - */ - pcicdev = devclass_get_device(pcic_devclass, 0); + bridgedev = PCCARD_DEV2SOFTC(dev)->dev; switch(pr->type) { default: return (EINVAL); @@ -467,20 +454,12 @@ crdioctl_sresource(dev_t dev, caddr_t data) case SYS_RES_IOPORT: break; } - for (i = pr->min; i + pr->size - 1 <= pr->max; i++) { - /* already allocated to pcic? */ - if (bus_get_resource_start(pcicdev, pr->type, 0) == i) - continue; - err = bus_set_resource(pcicdev, pr->type, rid, i, pr->size); - if (err != 0) - continue; - r = bus_alloc_resource(pcicdev, pr->type, &rid, 0ul, ~0ul, - pr->size, 0); - if (r == NULL) - continue; + flags = rman_make_alignment_flags(pr->size); + r = bus_alloc_resource(bridgedev, pr->type, &rid, pr->min, pr->max, + pr->size, flags); + if (r != NULL) { pr->resource_addr = (u_long)rman_get_start(r); - bus_release_resource(pcicdev, pr->type, rid, r); - return (0); + bus_release_resource(bridgedev, pr->type, rid, r); } return (0); } @@ -492,13 +471,14 @@ crdioctl_sresource(dev_t dev, caddr_t data) static int crdioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) { - struct slot *slt = pccard_slots[minor(dev)]; + u_int32_t addr; + int err; + struct io_desc *ip; struct mem_desc *mp; - struct io_desc *ip; - device_t pcicdev; - int s, err; - int pwval; - u_int32_t addr; + device_t pccarddev; + int pwval; + int s; + struct slot *slt = PCCARD_DEV2SOFTC(dev); if (slt == 0 && cmd != PIOCRWMEM) return (ENXIO); @@ -598,18 +578,15 @@ crdioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) */ if (*(unsigned long *)data & (PCCARD_MEMSIZE-1)) return (EINVAL); - pcicdev = devclass_get_device(pcic_devclass, 0); + pccarddev = PCCARD_DEV2SOFTC(dev)->dev; pccard_mem_rid = 0; addr = *(unsigned long *)data; if (pccard_mem_res) - bus_release_resource(pcicdev, SYS_RES_MEMORY, + bus_release_resource(pccarddev, SYS_RES_MEMORY, pccard_mem_rid, pccard_mem_res); - pccard_mem_res = bus_alloc_resource(pcicdev, SYS_RES_MEMORY, + pccard_mem_res = bus_alloc_resource(pccarddev, SYS_RES_MEMORY, &pccard_mem_rid, addr, addr, PCCARD_MEMSIZE, - RF_ACTIVE); -#ifdef NOT_YET_XXX - | rman_make_alignment_flags(PCCARD_MEMSIZE)); -#endif + RF_ACTIVE | rman_make_alignment_flags(PCCARD_MEMSIZE)); if (pccard_mem_res == NULL) return (EINVAL); pccard_mem = rman_get_start(pccard_mem_res); @@ -668,9 +645,9 @@ crdioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) static int crdpoll(dev_t dev, int events, struct proc *p) { - int s; - struct slot *slt = pccard_slots[minor(dev)]; - int revents = 0; + int revents = 0; + int s; + struct slot *slt = PCCARD_DEV2SOFTC(dev); if (events & (POLLIN | POLLRDNORM)) revents |= events & (POLLIN | POLLRDNORM); @@ -693,19 +670,13 @@ crdpoll(dev_t dev, int events, struct proc *p) return (revents); } -static struct slot * -pccard_dev2slot(device_t dev) -{ - return pccard_slots[device_get_unit(dev)]; -} - /* * APM hooks for suspending and resuming. */ int pccard_suspend(device_t dev) { - struct slot *slt = pccard_dev2slot(dev); + struct slot *slt = PCCARD_DEVICE2SOFTC(dev); /* This code stolen from pccard_event:card_removed */ if (slt->state == filled) { @@ -728,7 +699,7 @@ pccard_suspend(device_t dev) int pccard_resume(device_t dev) { - struct slot *slt = pccard_dev2slot(dev); + struct slot *slt = PCCARD_DEVICE2SOFTC(dev); if (pcic_resume_reset) slt->ctrl->resume(slt); diff --git a/sys/pccard/pccard_nbk.c b/sys/pccard/pccard_nbk.c index d799754bf0a4..0f8fa252fad6 100644 --- a/sys/pccard/pccard_nbk.c +++ b/sys/pccard/pccard_nbk.c @@ -1,6 +1,5 @@ /* - * Copyright (c) 1999, M. Warner Losh. - * All rights reserved. + * Copyright (c) 1999, 2001 M. Warner Losh. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -53,14 +52,22 @@ #include <sys/systm.h> #include <sys/module.h> #include <sys/kernel.h> -#include <sys/queue.h> #include <sys/select.h> +#include <sys/sysctl.h> +#include <sys/queue.h> #include <sys/types.h> #include <sys/bus.h> #include <machine/bus.h> #include <machine/resource.h> +/* XXX Shouldn't reach into the MD code here */ +#ifdef PC98 +#include <pc98/pc98/pc98.h> +#else +#include <i386/isa/isa.h> +#endif + #include <pccard/cardinfo.h> #include <pccard/slot.h> @@ -78,7 +85,17 @@ devclass_t pccard_devclass; #define PCCARD_DEVINFO(d) (struct pccard_devinfo *) device_get_ivars(d) -#if NOT_YET_XXX +SYSCTL_NODE(_machdep, OID_AUTO, pccard, CTLFLAG_RW, 0, "pccard"); + +static u_long mem_start = IOM_BEGIN; +static u_long mem_end = IOM_END; + +SYSCTL_ULONG(_machdep_pccard, OID_AUTO, mem_start, CTLFLAG_RW, + &mem_start, 0, ""); +SYSCTL_ULONG(_machdep_pccard, OID_AUTO, mem_end, CTLFLAG_RW, + &mem_end, 0, ""); + +#ifdef NOT_YET_XXX /* * glue for NEWCARD/OLDCARD compat layer */ @@ -98,8 +115,14 @@ pccard_compat_do_attach(device_t bus, device_t dev) static int pccard_probe(device_t dev) { - device_set_desc(dev, "PC Card bus -- kludge version"); - return 0; + device_set_desc(dev, "PC Card bus (classic)"); + return (0); +} + +static int +pccard_attach(device_t dev) +{ + return (0); } static void @@ -167,21 +190,21 @@ pccard_set_resource(device_t dev, device_t child, int type, int rid, if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY && type != SYS_RES_IRQ && type != SYS_RES_DRQ) - return EINVAL; + return (EINVAL); if (rid < 0) - return EINVAL; + return (EINVAL); if (type == SYS_RES_IOPORT && rid >= PCCARD_NPORT) - return EINVAL; + return (EINVAL); if (type == SYS_RES_MEMORY && rid >= PCCARD_NMEM) - return EINVAL; + return (EINVAL); if (type == SYS_RES_IRQ && rid >= PCCARD_NIRQ) - return EINVAL; + return (EINVAL); if (type == SYS_RES_DRQ && rid >= PCCARD_NDRQ) - return EINVAL; + return (EINVAL); resource_list_add(rl, type, rid, start, start + count - 1, count); - return 0; + return (0); } static int @@ -194,14 +217,14 @@ pccard_get_resource(device_t dev, device_t child, int type, int rid, rle = resource_list_find(rl, type, rid); if (!rle) - return ENOENT; + return (ENOENT); if (startp) *startp = rle->start; if (countp) *countp = rle->count; - return 0; + return (0); } static void @@ -218,7 +241,7 @@ pccard_alloc_resource(device_t bus, device_t child, int type, int *rid, { /* * Consider adding a resource definition. We allow rid 0 for - * irq, 0-3 for memory and 0-1 for ports + * irq, 0-4 for memory and 0-1 for ports */ int passthrough = (device_get_parent(child) != bus); int isdefault; @@ -228,34 +251,34 @@ pccard_alloc_resource(device_t bus, device_t child, int type, int *rid, struct resource *res; if (start == 0 && end == ~0 && type == SYS_RES_MEMORY && count != 1) { - start = 0xd0000; - end = 0xdffff; + start = mem_start; + end = mem_end; } isdefault = (start == 0UL && end == ~0UL); if (!passthrough && !isdefault) { rle = resource_list_find(rl, type, *rid); if (!rle) { if (*rid < 0) - return 0; + return (NULL); switch (type) { case SYS_RES_IRQ: if (*rid >= PCCARD_NIRQ) - return 0; + return (NULL); break; case SYS_RES_DRQ: if (*rid >= PCCARD_NDRQ) - return 0; + return (NULL); break; case SYS_RES_MEMORY: if (*rid >= PCCARD_NMEM) - return 0; + return (NULL); break; case SYS_RES_IOPORT: if (*rid >= PCCARD_NPORT) - return 0; + return (NULL); break; default: - return 0; + return (NULL); } resource_list_add(rl, type, *rid, start, end, count); } @@ -271,7 +294,7 @@ pccard_release_resource(device_t bus, device_t child, int type, int rid, { struct pccard_devinfo *devi = PCCARD_DEVINFO(child); struct resource_list *rl = &devi->resources; - return resource_list_release(rl, bus, child, type, rid, r); + return (resource_list_release(rl, bus, child, type, rid, r)); } static int @@ -282,48 +305,46 @@ pccard_read_ivar(device_t bus, device_t child, int which, u_char *result) switch (which) { case PCCARD_IVAR_ETHADDR: bcopy(devi->misc, result, ETHER_ADDR_LEN); - return 0; + return (0); } - return ENOENT; + return (ENOENT); } -/* Pass card requests up to pcic. This may mean a bad design XXX */ - static int pccard_set_res_flags(device_t bus, device_t child, int restype, int rid, u_long value) { - return CARD_SET_RES_FLAGS(device_get_parent(bus), child, restype, - rid, value); + return (CARD_SET_RES_FLAGS(device_get_parent(bus), child, restype, + rid, value)); } static int pccard_get_res_flags(device_t bus, device_t child, int restype, int rid, u_long *value) { - return CARD_GET_RES_FLAGS(device_get_parent(bus), child, restype, - rid, value); + return (CARD_GET_RES_FLAGS(device_get_parent(bus), child, restype, + rid, value)); } static int pccard_set_memory_offset(device_t bus, device_t child, int rid, u_int32_t offset) { - return CARD_SET_MEMORY_OFFSET(device_get_parent(bus), child, rid, - offset); + return (CARD_SET_MEMORY_OFFSET(device_get_parent(bus), child, rid, + offset)); } static int pccard_get_memory_offset(device_t bus, device_t child, int rid, u_int32_t *offset) { - return CARD_GET_MEMORY_OFFSET(device_get_parent(bus), child, rid, - offset); + return (CARD_GET_MEMORY_OFFSET(device_get_parent(bus), child, rid, + offset)); } #ifdef NOT_YET_XXX static int -pccard_get_function(device_t bus, device_t child, int *function) +pccard_get_function_num(device_t bus, device_t child, int *function) { *function = 0; return (0); @@ -347,14 +368,14 @@ const struct pccard_product * pccard_product_lookup(device_t dev, const struct pccard_product *tab, size_t ent_size, pccard_product_match_fn matchfn) { - return NULL; + return (NULL); } #endif static device_method_t pccard_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pccard_probe), - DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_attach, pccard_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, pccard_suspend), DEVMETHOD(device_resume, pccard_resume), @@ -379,23 +400,22 @@ static device_method_t pccard_methods[] = { DEVMETHOD(card_set_memory_offset, pccard_set_memory_offset), DEVMETHOD(card_get_memory_offset, pccard_get_memory_offset), #ifdef NOT_YET_XXX - DEVMETHOD(card_get_function, pccard_get_function), + DEVMETHOD(card_get_function, pccard_get_function_num), DEVMETHOD(card_activate_function, pccard_activate_function), DEVMETHOD(card_deactivate_function, pccard_deactivate_function), DEVMETHOD(card_compat_do_probe, pccard_compat_do_probe), DEVMETHOD(card_compat_do_attach, pccard_compat_do_attach), #endif - { 0, 0 } }; static driver_t pccard_driver = { "pccard", pccard_methods, - 1, /* no softc */ + sizeof(struct slot) }; DRIVER_MODULE(pccard, pcic, pccard_driver, pccard_devclass, 0, 0); -DRIVER_MODULE(pccard, pc98pcic, pccard_driver, pccard_devclass, 0, 0); -DRIVER_MODULE(pccard, cbb, pccard_driver, pccard_devclass, 0, 0); +DRIVER_MODULE(pccard, mecia, pccard_driver, pccard_devclass, 0, 0); +DRIVER_MODULE(pccard, tcic, pccard_driver, pccard_devclass, 0, 0); MODULE_VERSION(pccard, 1); diff --git a/sys/pccard/pcic.c b/sys/pccard/pcic.c index cce51561af00..1b586aa5b696 100644 --- a/sys/pccard/pcic.c +++ b/sys/pccard/pcic.c @@ -2,6 +2,7 @@ * Intel PCIC or compatible Controller driver *------------------------------------------------------------------------- * + * Copyright (c) 2001 M. Warner Losh. All rights reserved. * Copyright (c) 1995 Andrew McRae. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,135 +32,81 @@ #include <sys/param.h> #include <sys/bus.h> +#include <sys/select.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/module.h> -#include <sys/select.h> -#include <machine/clock.h> #include <pccard/i82365.h> +#include <pccard/pcic_pci.h> #include <pccard/cardinfo.h> #include <pccard/slot.h> -#ifdef PC98 -#include <pccard/pcic98reg.h> -#ifndef PCIC98_IOBASE -#define PCIC98_IOBASE 0x80d0 -#endif -#endif /* PC98 */ +#include <pccard/pcicvar.h> /* Get pnp IDs */ #include <isa/isavar.h> #include <dev/pcic/i82365reg.h> +#include <dev/pccard/pccardvar.h> #include "card_if.h" /* * Prototypes for interrupt handler. */ -static driver_intr_t pcicintr; static int pcic_ioctl(struct slot *, int, caddr_t); static int pcic_power(struct slot *); static void pcic_mapirq(struct slot *, int); static timeout_t pcic_reset; static void pcic_resume(struct slot *); static void pcic_disable(struct slot *); -static timeout_t pcictimeout; -static struct callout_handle pcictimeout_ch - = CALLOUT_HANDLE_INITIALIZER(&pcictimeout_ch); static int pcic_memory(struct slot *, int); static int pcic_io(struct slot *, int); -#ifdef PC98 -/* local functions for PC-98 Original PC-Card controller */ -static int pcic98_power(struct slot *); -static void pcic98_mapirq(struct slot *, int); -static int pcic98_memory(struct slot *, int); -static int pcic98_io(struct slot *, int); -static timeout_t pcic98_reset; -static void pcic98_disable(struct slot *); -static void pcic98_resume(struct slot *); -#endif /* PC98 */ - -/* - * Per-slot data table. - */ -static struct pcic_slot { - int slotnum; /* My slot number */ - int index; /* Index register */ - int data; /* Data register */ - int offset; /* Offset value for index */ - char controller; /* Device type */ - char revision; /* Device Revision */ - struct slot *slt; /* Back ptr to slot */ - u_char (*getb)(struct pcic_slot *, int); - void (*putb)(struct pcic_slot *, int, u_char); - u_char *regs; /* Pointer to regs in mem */ -} pcic_slots[PCIC_MAX_SLOTS]; - -static struct slot_ctrl cinfo; - -static struct isa_pnp_id pcic_ids[] = { - {PCIC_PNP_ACTIONTEC, NULL}, /* AEI0218 */ - {PCIC_PNP_IBM3765, NULL}, /* IBM3765 */ - {PCIC_PNP_82365, NULL}, /* PNP0E00 */ - {PCIC_PNP_CL_PD6720, NULL}, /* PNP0E01 */ - {PCIC_PNP_VLSI_82C146, NULL}, /* PNP0E02 */ - {PCIC_PNP_82365_CARDBUS, NULL}, /* PNP0E03 */ - {PCIC_PNP_SCM_SWAPBOX, NULL}, /* SCM0469 */ - {0} -}; - -static int validunits = 0; -#ifdef PC98 -static u_char pcic98_last_reg1; -#endif /* PC98 */ -#define GET_UNIT(d) *(int *)device_get_softc(d) -#define SET_UNIT(d,u) *(int *)device_get_softc(d) = (u) +devclass_t pcic_devclass; -static char *bridges[] = -{ - "Intel i82365", - "IBM PCIC", - "VLSI 82C146", - "Cirrus logic 672x", - "Cirrus logic 6710", - "Vadem 365", - "Vadem 465", - "Vadem 468", - "Vadem 469", - "Ricoh RF5C396", - "IBM KING PCMCIA Controller", - "PC-98 Original" +static struct slot_ctrl pcic_cinfo = { + pcic_mapirq, + pcic_memory, + pcic_io, + pcic_reset, + pcic_disable, + pcic_power, + pcic_ioctl, + pcic_resume, + PCIC_MEM_WIN, + PCIC_IO_WIN }; /* - * Internal inline functions for accessing the PCIC. - */ -/* * Read a register from the PCIC. */ -static __inline unsigned char -getb1(struct pcic_slot *sp, int reg) +unsigned char +pcic_getb_io(struct pcic_slot *sp, int reg) { - outb(sp->index, sp->offset + reg); - return inb(sp->data); + bus_space_write_1(sp->bst, sp->bsh, PCIC_INDEX, sp->offset + reg); + return (bus_space_read_1(sp->bst, sp->bsh, PCIC_DATA)); } /* * Write a register on the PCIC */ -static __inline void -putb1(struct pcic_slot *sp, int reg, unsigned char val) +void +pcic_putb_io(struct pcic_slot *sp, int reg, unsigned char val) { - outb(sp->index, sp->offset + reg); - outb(sp->data, val); + /* + * Many datasheets recommend using outw rather than outb to save + * a microsecond. Maybe we should do this, but we'd likely only + * save 20-30us on card activation. + */ + bus_space_write_1(sp->bst, sp->bsh, PCIC_INDEX, sp->offset + reg); + bus_space_write_1(sp->bst, sp->bsh, PCIC_DATA, val); } /* * Clear bit(s) of a register. */ -static __inline void -clrb(struct pcic_slot *sp, int reg, unsigned char mask) +__inline void +pcic_clrb(struct pcic_slot *sp, int reg, unsigned char mask) { sp->putb(sp, reg, sp->getb(sp, reg) & ~mask); } @@ -167,8 +114,8 @@ clrb(struct pcic_slot *sp, int reg, unsigned char mask) /* * Set bit(s) of a register */ -static __inline void -setb(struct pcic_slot *sp, int reg, unsigned char mask) +__inline void +pcic_setb(struct pcic_slot *sp, int reg, unsigned char mask) { sp->putb(sp, reg, sp->getb(sp, reg) | mask); } @@ -177,13 +124,53 @@ setb(struct pcic_slot *sp, int reg, unsigned char mask) * Write a 16 bit value to 2 adjacent PCIC registers */ static __inline void -putw(struct pcic_slot *sp, int reg, unsigned short word) +pcic_putw(struct pcic_slot *sp, int reg, unsigned short word) { sp->putb(sp, reg, word & 0xFF); sp->putb(sp, reg + 1, (word >> 8) & 0xff); } /* + * pc98 cbus cards introduce a slight wrinkle here. They route the irq7 pin + * from the pcic chip to INT 2 on the cbus. INT 2 is normally mapped to + * irq 6 on the pc98 architecture, so if we get a request for irq 6 + * lie to the hardware and say it is 7. All the other usual mappings for + * cbus INT into irq space are the same as the rest of the system. + */ +static __inline int +host_irq_to_pcic(int irq) +{ +#ifdef PC98 + if (irq == 6) + irq = 7; +#endif + return (irq); +} + +/* + * Free up resources allocated so far. + */ +void +pcic_dealloc(device_t dev) +{ + struct pcic_softc *sc; + + sc = (struct pcic_softc *) device_get_softc(dev); + if (sc->slot_poll) + untimeout(sc->slot_poll, sc, sc->timeout_ch); + if (sc->iores) + bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, + sc->iores); + if (sc->memres) + bus_release_resource(dev, SYS_RES_MEMORY, sc->memrid, + sc->memres); + if (sc->ih) + bus_teardown_intr(dev, sc->irqres, sc->ih); + if (sc->irqres) + bus_release_resource(dev, SYS_RES_IRQ, sc->irqrid, sc->irqres); +} + +/* * entry point from main code to map/unmap memory context. */ static int @@ -193,6 +180,10 @@ pcic_memory(struct slot *slt, int win) struct mem_desc *mp = &slt->mem[win]; int reg = win * PCIC_MEMSIZE + PCIC_MEMBASE; + if (win < 0 || win >= slt->ctrl->maxmem) { + printf("Illegal PCIC MEMORY window request %d\n", win); + return (ENXIO); + } if (mp->flags & MDF_ACTIVE) { unsigned long sys_addr = (uintptr_t)(void *)mp->start >> 12; /* @@ -200,36 +191,36 @@ pcic_memory(struct slot *slt, int win) * The values are all stored as the upper 12 bits of the * 24 bit address i.e everything is allocated as 4 Kb chunks. */ - putw(sp, reg, sys_addr & 0xFFF); - putw(sp, reg+2, (sys_addr + (mp->size >> 12) - 1) & 0xFFF); - putw(sp, reg+4, ((mp->card >> 12) - sys_addr) & 0x3FFF); + pcic_putw(sp, reg, sys_addr & 0xFFF); + pcic_putw(sp, reg+2, (sys_addr + (mp->size >> 12) - 1) & 0xFFF); + pcic_putw(sp, reg+4, ((mp->card >> 12) - sys_addr) & 0x3FFF); /* * Each 16 bit register has some flags in the upper bits. */ if (mp->flags & MDF_16BITS) - setb(sp, reg+1, PCIC_DATA16); + pcic_setb(sp, reg+1, PCIC_DATA16); if (mp->flags & MDF_ZEROWS) - setb(sp, reg+1, PCIC_ZEROWS); + pcic_setb(sp, reg+1, PCIC_ZEROWS); if (mp->flags & MDF_WS0) - setb(sp, reg+3, PCIC_MW0); + pcic_setb(sp, reg+3, PCIC_MW0); if (mp->flags & MDF_WS1) - setb(sp, reg+3, PCIC_MW1); + pcic_setb(sp, reg+3, PCIC_MW1); if (mp->flags & MDF_ATTR) - setb(sp, reg+5, PCIC_REG); + pcic_setb(sp, reg+5, PCIC_REG); if (mp->flags & MDF_WP) - setb(sp, reg+5, PCIC_WP); + pcic_setb(sp, reg+5, PCIC_WP); /* * Enable the memory window. By experiment, we need a delay. */ - setb(sp, PCIC_ADDRWINE, (1<<win) | PCIC_MEMCS16); + pcic_setb(sp, PCIC_ADDRWINE, (1<<win) | PCIC_MEMCS16); DELAY(50); } else { - clrb(sp, PCIC_ADDRWINE, 1<<win); - putw(sp, reg, 0); - putw(sp, reg+2, 0); - putw(sp, reg+4, 0); + pcic_clrb(sp, PCIC_ADDRWINE, 1<<win); + pcic_putw(sp, reg, 0); + pcic_putw(sp, reg+2, 0); + pcic_putw(sp, reg+4, 0); } - return(0); + return (0); } /* @@ -256,13 +247,14 @@ pcic_io(struct slot *slt, int win) reg = PCIC_IO1; break; default: - panic("Illegal PCIC I/O window request!"); + printf("Illegal PCIC I/O window request %d\n", win); + return (ENXIO); } if (ip->flags & IODF_ACTIVE) { unsigned char x, ioctlv; - putw(sp, reg, ip->start); - putw(sp, reg+2, ip->start+ip->size-1); + pcic_putw(sp, reg, ip->start); + pcic_putw(sp, reg+2, ip->start+ip->size-1); x = 0; if (ip->flags & IODF_ZEROWS) x |= PCIC_IO_0WS; @@ -288,335 +280,88 @@ pcic_io(struct slot *slt, int win) break; } DELAY(100); - setb(sp, PCIC_ADDRWINE, mask); + pcic_setb(sp, PCIC_ADDRWINE, mask); DELAY(100); } else { - clrb(sp, PCIC_ADDRWINE, mask); + pcic_clrb(sp, PCIC_ADDRWINE, mask); DELAY(100); - putw(sp, reg, 0); - putw(sp, reg + 2, 0); + pcic_putw(sp, reg, 0); + pcic_putw(sp, reg + 2, 0); } - return(0); + return (0); } -/* - * Look for an Intel PCIC (or compatible). - * For each available slot, allocate a PC-CARD slot. - */ - -/* - * VLSI 82C146 has incompatibilities about the I/O address of slot 1. - * Assume it's the only PCIC whose vendor ID is 0x84, - * contact Warner Losh <imp@freebsd.org> if correct. - */ -static int -pcic_probe(device_t dev) +static void +pcic_do_mgt_irq(struct pcic_slot *sp, int irq) { - int slotnum, validslots = 0; - struct slot *slt; - struct pcic_slot *sp; - unsigned char c; - int error; - struct resource *r; - int rid; - static int maybe_vlsi = 0; - - /* Check isapnp ids */ - error = ISA_PNP_PROBE(device_get_parent(dev), dev, pcic_ids); - if (error == ENXIO) - return (ENXIO); - - /* - * Initialise controller information structure. - */ - cinfo.mapirq = pcic_mapirq; - cinfo.mapmem = pcic_memory; - cinfo.mapio = pcic_io; - cinfo.ioctl = pcic_ioctl; - cinfo.power = pcic_power; - cinfo.reset = pcic_reset; - cinfo.disable = pcic_disable; - cinfo.resume = pcic_resume; - cinfo.maxmem = PCIC_MEM_WIN; - cinfo.maxio = PCIC_IO_WIN; - - if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0) - bus_set_resource(dev, SYS_RES_IOPORT, 0, PCIC_INDEX0, 2); - rid = 0; - r = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); - if (!r) { - if (bootverbose) - device_printf(dev, "Cannot get I/O range\n"); - return ENOMEM; - } - - sp = &pcic_slots[validunits * PCIC_CARD_SLOTS]; - for (slotnum = 0; slotnum < PCIC_CARD_SLOTS; slotnum++, sp++) { - /* - * Initialise the PCIC slot table. - */ - sp->getb = getb1; - sp->putb = putb1; - sp->index = rman_get_start(r); - sp->data = sp->index + 1; - sp->offset = slotnum * PCIC_SLOT_SIZE; - /* - * XXX - Screwed up slot 1 on the VLSI chips. According to - * the Linux PCMCIA code from David Hinds, working chipsets - * return 0x84 from their (correct) ID ports, while the broken - * ones would need to be probed at the new offset we set after - * we assume it's broken. - */ - if (slotnum == 1 && maybe_vlsi && - sp->getb(sp, PCIC_ID_REV) != PCIC_VLSI82C146) { - sp->index += 4; - sp->data += 4; - sp->offset = PCIC_SLOT_SIZE << 1; - } - /* - * see if there's a PCMCIA controller here - * Intel PCMCIA controllers use 0x82 and 0x83 - * IBM clone chips use 0x88 and 0x89, apparently - */ - c = sp->getb(sp, PCIC_ID_REV); - sp->revision = -1; - switch(c) { - /* - * 82365 or clones. - */ - case PCIC_INTEL0: - case PCIC_INTEL1: - sp->controller = PCIC_I82365; - sp->revision = c & 1; - /* - * Now check for VADEM chips. - */ - outb(sp->index, 0x0E); /* Unlock VADEM's extra regs */ - outb(sp->index, 0x37); - setb(sp, PCIC_VMISC, PCIC_VADEMREV); - c = sp->getb(sp, PCIC_ID_REV); - if (c & 0x08) { - switch (sp->revision = c & 7) { - case 1: - sp->controller = PCIC_VG365; - break; - case 2: - sp->controller = PCIC_VG465; - break; - case 3: - sp->controller = PCIC_VG468; - break; - default: - sp->controller = PCIC_VG469; - break; - } - clrb(sp, PCIC_VMISC, PCIC_VADEMREV); - } - - /* - * Check for RICOH RF5C396 PCMCIA Controller - */ - c = sp->getb(sp, 0x3a); - if (c == 0xb2) { - sp->controller = PCIC_RF5C396; - } + u_int32_t reg; - break; - /* - * VLSI chips. - */ - case PCIC_VLSI82C146: - sp->controller = PCIC_VLSI; - maybe_vlsi = 1; - break; - case PCIC_IBM1: - case PCIC_IBM2: - sp->controller = PCIC_IBM; - sp->revision = c & 1; - break; - case PCIC_IBM3: - sp->controller = PCIC_IBM_KING; - sp->revision = c & 1; - break; - default: - continue; - } - /* - * Check for Cirrus logic chips. - */ - sp->putb(sp, PCIC_CLCHIP, 0); - c = sp->getb(sp, PCIC_CLCHIP); - if ((c & PCIC_CLC_TOGGLE) == PCIC_CLC_TOGGLE) { - c = sp->getb(sp, PCIC_CLCHIP); - if ((c & PCIC_CLC_TOGGLE) == 0) { - if (c & PCIC_CLC_DUAL) - sp->controller = PCIC_PD672X; - else - sp->controller = PCIC_PD6710; - sp->revision = 8 - ((c & 0x1F) >> 2); - } - } - device_set_desc(dev, bridges[(int) sp->controller]); - /* - * OK it seems we have a PCIC or lookalike. - * Allocate a slot and initialise the data structures. - */ - validslots++; - sp->slotnum = slotnum + validunits * PCIC_CARD_SLOTS; - slt = pccard_alloc_slot(&cinfo); - if (slt == 0) - continue; - slt->cdata = sp; - sp->slt = slt; - /* - * Modem cards send the speaker audio (dialing noises) - * to the host's speaker. Cirrus Logic PCIC chips must - * enable this. There is also a Low Power Dynamic Mode bit - * that claims to reduce power consumption by 30%, so - * enable it and hope for the best. - */ - if (sp->controller == PCIC_PD672X) { - setb(sp, PCIC_MISC1, PCIC_MISC1_SPEAKER); - setb(sp, PCIC_MISC2, PCIC_LPDM_EN); - } - } - bus_release_resource(dev, SYS_RES_IOPORT, rid, r); - if (validslots != 0) - return (0); -#ifdef PC98 - sp = &pcic_slots[validunits * PCIC_CARD_SLOTS]; - if (inb(PCIC98_REG0) != 0xff) { - sp->controller = PCIC_PC98; - sp->revision = 0; - cinfo.mapmem = pcic98_memory; - cinfo.mapio = pcic98_io; - cinfo.power = pcic98_power; - cinfo.mapirq = pcic98_mapirq; - cinfo.reset = pcic98_reset; - cinfo.disable = pcic98_disable; - cinfo.resume = pcic98_resume; - cinfo.maxmem = 1; -#if 0 - cinfo.maxio = 1; -#else - cinfo.maxio = 2; /* fake for UE2212 LAN card */ -#endif - validslots++; - slt = pccard_alloc_slot(&cinfo); - slt->cdata = sp; - sp->slt = slt; - /* XXX need to allocated the port resources */ - device_set_desc(dev, "MECIA PC98 Original PCMCIA Controller"); + if (sp->sc->csc_route == pci_parallel) { +#ifdef NOT_YET_XXX + reg = CB_SM_CD; + bus_space_write_4(sp->bst, sp->bsh, CB_SOCKET_MASK, reg); +#endif + } else { + /* Management IRQ changes */ + pcic_clrb(sp, PCIC_INT_GEN, PCIC_INTR_ENA); + irq = host_irq_to_pcic(irq); + sp->putb(sp, PCIC_STAT_INT, (irq << 4) | 0x8); } -#endif /* PC98 */ - return(validslots ? 0 : ENXIO); -} - -static void -do_mgt_irq(struct pcic_slot *sp, int irq) -{ - /* Management IRQ changes */ - clrb(sp, PCIC_INT_GEN, PCIC_INTR_ENA); - sp->putb(sp, PCIC_STAT_INT, (irq << 4) | 0xF); } -static int +int pcic_attach(device_t dev) { - void *ih; - int rid; - struct resource *r; - int irq; - int error; + int i; + device_t kid; + struct pcic_softc *sc; + struct slot *slt; struct pcic_slot *sp; - int i; - int stat; + int stat; - SET_UNIT(dev, validunits); - sp = &pcic_slots[GET_UNIT(dev) * PCIC_CARD_SLOTS]; + sc = (struct pcic_softc *) device_get_softc(dev); + callout_handle_init(&sc->timeout_ch); + sp = &sc->slots[0]; for (i = 0; i < PCIC_CARD_SLOTS; i++, sp++) { - if (sp->slt) - device_add_child(dev, NULL, -1); - } - validunits++; - - rid = 0; - r = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); - if (!r) { - return ENXIO; - } - - irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0); - if (irq == 0) { - /* See if the user has requested a specific IRQ */ - if (!getenv_int("machdep.pccard.pcic_irq", &irq)) - irq = 0; - } - rid = 0; - r = 0; - if (irq > 0) { - r = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq, - irq, 1, RF_ACTIVE); - } - if (r && ((1 << (rman_get_start(r))) & PCIC_INT_MASK_ALLOWED) == 0) { - device_printf(dev, - "Hardware does not support irq %d, trying polling.\n", - irq); - bus_release_resource(dev, SYS_RES_IRQ, rid, r); - r = 0; - irq = 0; - } - if (r) { - error = bus_setup_intr(dev, r, INTR_TYPE_MISC, - pcicintr, (void *) GET_UNIT(dev), &ih); - if (error) { - bus_release_resource(dev, SYS_RES_IRQ, rid, r); - return error; + if (!sp->slt) + continue; + sp->slt = 0; + kid = device_add_child(dev, NULL, -1); + if (kid == NULL) { + device_printf(dev, "Can't add pccard bus slot %d", i); + return (ENXIO); } - irq = rman_get_start(r); - device_printf(dev, "management irq %d\n", irq); - } else { - irq = 0; - } - if (irq == 0) { - pcictimeout_ch = timeout(pcictimeout, (void *) GET_UNIT(dev), - hz/2); - device_printf(dev, "Polling mode\n"); + device_probe_and_attach(kid); + slt = pccard_init_slot(kid, &pcic_cinfo); + if (slt == 0) { + device_printf(dev, "Can't get pccard info slot %d", i); + return (ENXIO); + } + sc->slotmask |= (1 << i); + slt->cdata = sp; + sp->slt = slt; + sp->sc = sc; } - sp = &pcic_slots[GET_UNIT(dev) * PCIC_CARD_SLOTS]; + sp = &sc->slots[0]; for (i = 0; i < PCIC_CARD_SLOTS; i++, sp++) { if (sp->slt == NULL) continue; -#ifdef PC98 - if (sp->controller == PCIC_PC98) { - pcic98_last_reg1 = inb(PCIC98_REG1); - if (pcic98_last_reg1 & PCIC98_CARDEXIST) { - /* PCMCIA card exist */ - sp->slt->laststate = sp->slt->state = filled; - pccard_event(sp->slt, card_inserted); - } else { - sp->slt->laststate = sp->slt->state = empty; - } - } else -#endif /* PC98 */ - { - do_mgt_irq(sp, irq); - - /* Check for changes */ - setb(sp, PCIC_POWER, PCIC_PCPWRE| PCIC_DISRST); - stat = sp->getb(sp, PCIC_STATUS); - if (bootverbose) - printf("stat is %x\n", stat); - if ((stat & PCIC_CD) != PCIC_CD) { - sp->slt->laststate = sp->slt->state = empty; - } else { - sp->slt->laststate = sp->slt->state = filled; - pccard_event(sp->slt, card_inserted); - } + pcic_do_mgt_irq(sp, sc->irq); + sp->slt->irq = sc->irq; + + /* Check for changes */ + pcic_setb(sp, PCIC_POWER, PCIC_PCPWRE | PCIC_DISRST); + stat = sp->getb(sp, PCIC_STATUS); + if (bootverbose) + printf("stat is %x\n", stat); + if ((stat & PCIC_CD) != PCIC_CD) { + sp->slt->laststate = sp->slt->state = empty; + } else { + sp->slt->laststate = sp->slt->state = filled; + pccard_event(sp->slt, card_inserted); } - sp->slt->irq = irq; } return (bus_generic_attach(dev)); @@ -632,7 +377,7 @@ pcic_ioctl(struct slot *slt, int cmd, caddr_t data) switch(cmd) { default: - return(ENOTTY); + return (ENOTTY); /* * Get/set PCIC registers */ @@ -645,7 +390,7 @@ pcic_ioctl(struct slot *slt, int cmd, caddr_t data) ((struct pcic_reg *)data)->value); break; } - return(0); + return (0); } /* @@ -655,69 +400,106 @@ pcic_ioctl(struct slot *slt, int cmd, caddr_t data) static int pcic_power(struct slot *slt) { - unsigned char reg = PCIC_DISRST|PCIC_PCPWRE; + unsigned char c; + unsigned char reg = PCIC_DISRST | PCIC_PCPWRE; struct pcic_slot *sp = slt->cdata; + struct pcic_softc *sc = sp->sc; - switch(sp->controller) { - case PCIC_PD672X: - case PCIC_PD6710: - case PCIC_VG365: - case PCIC_VG465: - case PCIC_VG468: - case PCIC_VG469: - case PCIC_RF5C396: - case PCIC_VLSI: - case PCIC_IBM_KING: - case PCIC_I82365: - switch(slt->pwr.vpp) { - default: - return(EINVAL); - case 0: - break; - case 50: - case 33: - reg |= PCIC_VPP_5V; - break; - case 120: - reg |= PCIC_VPP_12V; + if (sc->flags & (PCIC_DF_POWER | PCIC_AB_POWER)) { + /* + * Look at the VS[12]# bits on the card. If VS1 is clear + * then we should apply 3.3 volts. + */ + c = sp->getb(sp, PCIC_CDGC); + if ((c & PCIC_VS1STAT) == 0) + slt->pwr.vcc = 33; + } + + /* + * XXX Note: The Vpp controls varies quit a bit between bridge chips + * and the following might not be right in all cases. The Linux + * code and wildboar code bases are more complex. However, most + * applications want vpp == vcc and the following code does appear + * to do that for all bridge sets. + */ + switch(slt->pwr.vpp) { + default: + return (EINVAL); + case 0: + break; + case 50: + case 33: + reg |= PCIC_VPP_5V; + break; + case 120: + reg |= PCIC_VPP_12V; + break; + } + + if (slt->pwr.vcc) + reg |= PCIC_VCC_ON; /* Turn on Vcc */ + switch(slt->pwr.vcc) { + default: + return (EINVAL); + case 0: + break; + case 33: + /* + * The wildboar code has comments that state that + * the IBM KING controller doesn't support 3.3V + * on the "IBM Smart PC card drive". The code + * intemates that's the only place they have seen + * it used and that there's a boatload of issues + * with it. I'm not even sure this is right because + * the only docs I've been able to find say this is for + * 5V power. Of course, this "doc" is just code comments + * so who knows for sure. + */ + if (sc->flags & PCIC_KING_POWER) { + reg |= PCIC_VCC_5V_KING; break; } - switch(slt->pwr.vcc) { - default: - return(EINVAL); - case 0: + if (sc->flags & PCIC_VG_POWER) { + pcic_setb(sp, PCIC_CVSR, PCIC_CVSR_VS); break; - case 33: - if (sp->controller == PCIC_IBM_KING) { - reg |= PCIC_VCC_5V_KING; - break; - } - reg |= PCIC_VCC_3V; - if (sp->controller == PCIC_VG468 || - sp->controller == PCIC_VG469 || - sp->controller == PCIC_VG465 || - sp->controller == PCIC_VG365) - setb(sp, PCIC_CVSR, PCIC_CVSR_VS); - else if (sp->controller == PCIC_PD6710 || - sp->controller == PCIC_PD672X) - setb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33); + } + if (sc->flags & PCIC_PD_POWER) { + pcic_setb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33); break; - case 50: - if (sp->controller == PCIC_IBM_KING) { - reg |= PCIC_VCC_5V_KING; - break; - } - reg |= PCIC_VCC_5V; - if (sp->controller == PCIC_VG468 || - sp->controller == PCIC_VG469 || - sp->controller == PCIC_VG465 || - sp->controller == PCIC_VG365) - clrb(sp, PCIC_CVSR, PCIC_CVSR_VS); - else if (sp->controller == PCIC_PD6710 || - sp->controller == PCIC_PD672X) - clrb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33); + } + if (sc->flags & PCIC_RICOH_POWER) { + pcic_setb(sp, PCIC_RICOH_MCR2, PCIC_MCR2_VCC_33); break; } + + /* + * Technically, The A, B, C stepping didn't support + * the 3.3V cards. However, many cardbus bridges are + * identified as B step cards by our probe routine, so + * we do both. It won't hurt the A, B, C bridges that + * don't support this bit since it is one of the + * reserved bits. + */ + if (sc->flags & (PCIC_AB_POWER | PCIC_DF_POWER)) + reg |= PCIC_VCC_3V; + break; + case 50: + if (sc->flags & PCIC_KING_POWER) + reg |= PCIC_VCC_5V_KING; + /* + * For all of the variant power schemes for 3.3V go + * ahead and turn off the 3.3V enable bit. For all + * bridges, the setting the Vcc on bit does the rest. + * Note that we don't have to turn off the 3.3V bit + * for the '365 step D since with the reg assigments + * to this point it doesn't get turned on. + */ + if (sc->flags & PCIC_VG_POWER) + pcic_clrb(sp, PCIC_CVSR, PCIC_CVSR_VS); + if (sc->flags & PCIC_PD_POWER) + pcic_clrb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33); + if (sc->flags & PCIC_RICOH_POWER) + pcic_clrb(sp, PCIC_RICOH_MCR2, PCIC_MCR2_VCC_33); break; } sp->putb(sp, PCIC_POWER, reg); @@ -727,15 +509,20 @@ pcic_power(struct slot *slt) sp->putb(sp, PCIC_POWER, reg); DELAY(100*1000); } - /* Some chips are smarter than us it seems, so if we weren't - * allowed to use 5V, try 3.3 instead + + /* + * Some chipsets will attempt to preclude us from supplying + * 5.0V to cards that only handle 3.3V. We seem to need to + * try 3.3V to paper over some power handling issues in other + * parts of the system. I suspect they are in the pccard bus + * driver, but may be in pccardd as well. */ if (!(sp->getb(sp, PCIC_STATUS) & PCIC_POW) && slt->pwr.vcc == 50) { slt->pwr.vcc = 33; slt->pwr.vpp = 0; return (pcic_power(slt)); } - return(0); + return (0); } /* @@ -747,8 +534,11 @@ static void pcic_mapirq(struct slot *slt, int irq) { struct pcic_slot *sp = slt->cdata; + if (sp->sc->csc_route == pci_parallel) + return; + irq = host_irq_to_pcic(irq); if (irq == 0) - clrb(sp, PCIC_INT_GEN, 0xF); + pcic_clrb(sp, PCIC_INT_GEN, 0xF); else sp->putb(sp, PCIC_INT_GEN, (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq); @@ -767,18 +557,18 @@ pcic_reset(void *chan) case 0: /* Something funny happended on the way to the pub... */ return; case 1: /* Assert reset */ - clrb(sp, PCIC_INT_GEN, PCIC_CARDRESET); + pcic_clrb(sp, PCIC_INT_GEN, PCIC_CARDRESET); slt->insert_seq = 2; - timeout(cinfo.reset, (void *)slt, hz/4); + timeout(pcic_reset, (void *)slt, hz/4); return; case 2: /* Deassert it again */ - setb(sp, PCIC_INT_GEN, PCIC_CARDRESET|PCIC_IOCARD); + pcic_setb(sp, PCIC_INT_GEN, PCIC_CARDRESET | PCIC_IOCARD); slt->insert_seq = 3; - timeout(cinfo.reset, (void *)slt, hz/4); + timeout(pcic_reset, (void *)slt, hz/4); return; case 3: /* Wait if card needs more time */ if (!sp->getb(sp, PCIC_STATUS) & PCIC_READY) { - timeout(cinfo.reset, (void *)slt, hz/10); + timeout(pcic_reset, (void *)slt, hz/10); return; } } @@ -807,71 +597,6 @@ pcic_disable(struct slot *slt) } /* - * PCIC timer. If the controller doesn't have a free IRQ to use - * or if interrupt steering doesn't work, poll the controller for - * insertion/removal events. - */ -static void -pcictimeout(void *chan) -{ - pcicintr(chan); - pcictimeout_ch = timeout(pcictimeout, chan, hz/2); -} - -/* - * PCIC Interrupt handler. - * Check each slot in turn, and read the card status change - * register. If this is non-zero, then a change has occurred - * on this card, so send an event to the main code. - */ -static void -pcicintr(void *arg) -{ - int slot, s; - unsigned char chg; - int unit = (int) arg; - struct pcic_slot *sp = &pcic_slots[unit * PCIC_CARD_SLOTS]; - - s = splhigh(); -#ifdef PC98 - if (sp->controller == PCIC_PC98) { - u_char reg1; - /* Check for a card in this slot */ - reg1 = inb(PCIC98_REG1); - if ((pcic98_last_reg1 ^ reg1) & PCIC98_CARDEXIST) { - pcic98_last_reg1 = reg1; - if (reg1 & PCIC98_CARDEXIST) - pccard_event(sp->slt, card_inserted); - else - pccard_event(sp->slt, card_removed); - } - } else -#endif /* PC98 */ - { - for (slot = 0; slot < PCIC_CARD_SLOTS; slot++, sp++) { - if (sp->slt && - (chg = sp->getb(sp, PCIC_STAT_CHG)) != 0) { - if (bootverbose) - printf("Slot %d chg = 0x%x\n", slot, - chg); - if (chg & PCIC_CDTCH) { - if ((sp->getb(sp, PCIC_STATUS) & - PCIC_CD) == PCIC_CD) { - pccard_event(sp->slt, - card_inserted); - } else { - pccard_event(sp->slt, - card_removed); - cinfo.disable(sp->slt); - } - } - } - } - } - splx(s); -} - -/* * pcic_resume - Suspend/resume support for PCIC */ static void @@ -879,251 +604,24 @@ pcic_resume(struct slot *slt) { struct pcic_slot *sp = slt->cdata; - do_mgt_irq(sp, slt->irq); + pcic_do_mgt_irq(sp, slt->irq); if (sp->controller == PCIC_PD672X) { - setb(sp, PCIC_MISC1, PCIC_MISC1_SPEAKER); - setb(sp, PCIC_MISC2, PCIC_LPDM_EN); + pcic_setb(sp, PCIC_MISC1, PCIC_MISC1_SPEAKER); + pcic_setb(sp, PCIC_MISC2, PCIC_LPDM_EN); } } -#ifdef PC98 -/* - * local functions for PC-98 Original PC-Card controller - */ -#define PCIC98_ALWAYS_128MAPPING 1 /* trick for using UE2212 */ - -int pcic98_mode = 0; /* almost the same as the value in PCIC98_REG2 */ - -static unsigned char reg_winsel = PCIC98_UNMAPWIN; -static unsigned short reg_pagofs = 0; - -static int -pcic98_memory(struct slot *slt, int win) -{ - struct mem_desc *mp = &slt->mem[win]; - unsigned char x; - - if (mp->flags & MDF_ACTIVE) { - /* slot = 0, window = 0, sys_addr = 0xda000, length = 8KB */ - if ((unsigned long)mp->start != 0xda000) { - printf( - "sys_addr must be 0xda000. requested address = %p\n", - mp->start); - return(EINVAL); - } - - /* omajinai ??? */ - outb(PCIC98_REG0, 0); - x = inb(PCIC98_REG1); - x &= 0xfc; - x |= 0x02; - outb(PCIC98_REG1, x); - reg_winsel = inb(PCIC98_REG_WINSEL); - reg_pagofs = inw(PCIC98_REG_PAGOFS); - outb(PCIC98_REG_WINSEL, PCIC98_MAPWIN); - outw(PCIC98_REG_PAGOFS, (mp->card >> 13)); /* 8KB */ - - if (mp->flags & MDF_ATTR) { - outb(PCIC98_REG7, inb(PCIC98_REG7) | PCIC98_ATTRMEM); - }else{ - outb(PCIC98_REG7, inb(PCIC98_REG7) & (~PCIC98_ATTRMEM)); - } - - outb(PCIC98_REG_WINSEL, PCIC98_MAPWIN); -#if 0 - if ((mp->flags & MDF_16BITS) == 1) { /* 16bit */ - outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_8BIT)); - }else{ /* 8bit */ - outb(PCIC98_REG2, inb(PCIC98_REG2) | PCIC98_8BIT); - } -#endif - } else { /* !(mp->flags & MDF_ACTIVE) */ - outb(PCIC98_REG0, 0); - x = inb(PCIC98_REG1); - x &= 0xfc; - x |= 0x02; - outb(PCIC98_REG1, x); -#if 0 - outb(PCIC98_REG_WINSEL, PCIC98_UNMAPWIN); - outw(PCIC98_REG_PAGOFS, 0); -#else - outb(PCIC98_REG_WINSEL, reg_winsel); - outw(PCIC98_REG_PAGOFS, reg_pagofs); -#endif - } - return 0; -} - -static int -pcic98_io(struct slot *slt, int win) -{ - struct io_desc *ip = &slt->io[win]; - unsigned char x; - unsigned short cardbase; - u_short ofst; - - if (win != 0) { - /* ignore for UE2212 */ - printf( - "pcic98:Illegal PCIC I/O window(%d) request! Ignored.\n", win); -/* return(EINVAL);*/ - return 0; - } - - if (ip->flags & IODF_ACTIVE) { - x = inb(PCIC98_REG2) & 0x0f; -#if 0 - if (! (ip->flags & IODF_CS16)) - x |= PCIC98_8BIT; -#else - if (! (ip->flags & IODF_16BIT)) { - x |= PCIC98_8BIT; - pcic98_mode |= PCIC98_8BIT; - } -#endif - - ofst = ip->start & 0xf; - cardbase = ip->start & ~0xf; -#ifndef PCIC98_ALWAYS_128MAPPING - if (ip->size + ofst > 16) -#endif - { /* 128bytes mapping */ - x |= PCIC98_MAP128; - pcic98_mode |= PCIC98_MAP128; - ofst |= ((cardbase & 0x70) << 4); - cardbase &= ~0x70; - } - - x |= PCIC98_MAPIO; - outb(PCIC98_REG2, x); - - outw(PCIC98_REG4, PCIC98_IOBASE); /* 98side I/O base */ - outw(PCIC98_REG5, cardbase); /* card side I/O base */ - - if (bootverbose) { - printf("pcic98: I/O mapped 0x%04x(98) -> " - "0x%04x(Card) and width %d bytes\n", - PCIC98_IOBASE+ofst, ip->start, ip->size); - printf("pcic98: reg2=0x%02x reg3=0x%02x reg7=0x%02x\n", - inb(PCIC98_REG2), inb(PCIC98_REG3), - inb(PCIC98_REG7)); - printf("pcic98: mode=%d\n", pcic98_mode); - } - - ip->start = PCIC98_IOBASE + ofst; - } else { - outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_MAPIO)); - pcic98_mode = 0; - } - return 0; -} - -static int -pcic98_power(struct slot *slt) -{ - unsigned char reg; - - reg = inb(PCIC98_REG7) & (~PCIC98_VPP12V); - switch(slt->pwr.vpp) { - default: - return(EINVAL); - case 50: - break; - case 120: - reg |= PCIC98_VPP12V; - break; - } - outb(PCIC98_REG7, reg); - DELAY(100*1000); - - reg = inb(PCIC98_REG2) & (~PCIC98_VCC3P3V); - switch(slt->pwr.vcc) { - default: - return(EINVAL); - case 33: - reg |= PCIC98_VCC3P3V; - break; - case 50: - break; - } - outb(PCIC98_REG2, reg); - DELAY(100*1000); - return 0; -} - -static void -pcic98_mapirq(struct slot *slt, int irq) -{ - u_char x; - - switch (irq) { - case 3: - x = PCIC98_INT0; - break; - case 5: - x = PCIC98_INT1; - break; - case 6: - x = PCIC98_INT2; - break; - case 10: - x = PCIC98_INT4; - break; - case 12: - x = PCIC98_INT5; - break; - case 0: /* disable */ - x = PCIC98_INTDISABLE; - break; - default: - printf("pcic98: illegal irq %d\n", irq); - return; - } -#ifdef PCIC_DEBUG - printf("pcic98: irq=%d mapped.\n", irq); -#endif - outb(PCIC98_REG3, x); -} - -static void -pcic98_reset(void *chan) -{ - struct slot *slt = chan; - - outb(PCIC98_REG0, 0); - outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_MAPIO)); - outb(PCIC98_REG3, PCIC98_INTDISABLE); -#if 0 -/* pcic98_reset() is called after pcic98_power() */ - outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_VCC3P3V)); - outb(PCIC98_REG7, inb(PCIC98_REG7) & (~PCIC98_VPP12V)); -#endif - outb(PCIC98_REG1, 0); - - selwakeup(&slt->selp); -} - -static void -pcic98_disable(struct slot *slt) -{ - /* null function */ -} - -static void -pcic98_resume(struct slot *slt) -{ - /* XXX PCIC98 How ? */ -} -#endif /* PC98 */ -/* end of local functions for PC-98 Original PC-Card controller */ - -static int +int pcic_activate_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { struct pccard_devinfo *devi = device_get_ivars(child); int err; + if (dev != device_get_parent(device_get_parent(child)) || devi == NULL) + return (bus_generic_activate_resource(dev, child, type, + rid, r)); + switch (type) { case SYS_RES_IOPORT: { struct io_desc *ip; @@ -1137,9 +635,9 @@ pcic_activate_resource(device_t dev, device_t child, int type, int rid, ip->flags |= IODF_ACTIVE; ip->start = rman_get_start(r); ip->size = rman_get_end(r) - rman_get_start(r) + 1; - err = cinfo.mapio(devi->slt, rid); + err = pcic_io(devi->slt, rid); if (err) - return err; + return (err); break; } case SYS_RES_IRQ: @@ -1152,38 +650,41 @@ pcic_activate_resource(device_t dev, device_t child, int type, int rid, case SYS_RES_MEMORY: { struct mem_desc *mp; if (rid >= NUM_MEM_WINDOWS) - return EINVAL; + return (EINVAL); mp = &devi->slt->mem[rid]; mp->flags |= MDF_ACTIVE; mp->start = (caddr_t) rman_get_start(r); mp->size = rman_get_end(r) - rman_get_start(r) + 1; - err = cinfo.mapmem(devi->slt, rid); + err = pcic_memory(devi->slt, rid); if (err) - return err; + return (err); break; } default: break; } err = bus_generic_activate_resource(dev, child, type, rid, r); - return err; + return (err); } -static int +int pcic_deactivate_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { struct pccard_devinfo *devi = device_get_ivars(child); int err; + if (dev != device_get_parent(device_get_parent(child)) || devi == NULL) + return (bus_generic_deactivate_resource(dev, child, type, + rid, r)); + switch (type) { case SYS_RES_IOPORT: { struct io_desc *ip = &devi->slt->io[rid]; ip->flags &= ~IODF_ACTIVE; - err = cinfo.mapio(devi->slt, rid); - if (err) { - return err; - } + err = pcic_io(devi->slt, rid); + if (err) + return (err); break; } case SYS_RES_IRQ: @@ -1191,26 +692,29 @@ pcic_deactivate_resource(device_t dev, device_t child, int type, int rid, case SYS_RES_MEMORY: { struct mem_desc *mp = &devi->slt->mem[rid]; mp->flags &= ~(MDF_ACTIVE | MDF_ATTR); - err = cinfo.mapmem(devi->slt, rid); - if (err) { - return err; - } + err = pcic_memory(devi->slt, rid); + if (err) + return (err); break; } default: break; } err = bus_generic_deactivate_resource(dev, child, type, rid, r); - return err; + return (err); } -static int +int pcic_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_intr_t *intr, void *arg, void **cookiep) { + struct pcic_softc *sc = device_get_softc(dev); struct pccard_devinfo *devi = device_get_ivars(child); int err; + if (sc->csc_route == pci_parallel && (flags & INTR_TYPE_FAST)) + return (EINVAL); + if (((1 << rman_get_start(irq)) & PCIC_INT_MASK_ALLOWED) == 0) { device_printf(dev, "Hardware does not support irq %ld.\n", rman_get_start(irq)); @@ -1220,24 +724,24 @@ pcic_setup_intr(device_t dev, device_t child, struct resource *irq, err = bus_generic_setup_intr(dev, child, irq, flags, intr, arg, cookiep); if (err == 0) - cinfo.mapirq(devi->slt, rman_get_start(irq)); + pcic_mapirq(devi->slt, rman_get_start(irq)); else device_printf(dev, "Error %d irq %ld\n", err, rman_get_start(irq)); return (err); } -static int +int pcic_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie) { struct pccard_devinfo *devi = device_get_ivars(child); - cinfo.mapirq(devi->slt, 0); + pcic_mapirq(devi->slt, 0); return (bus_generic_teardown_intr(dev, child, irq, cookie)); } -static int +int pcic_set_res_flags(device_t bus, device_t child, int restype, int rid, u_long value) { @@ -1248,17 +752,20 @@ pcic_set_res_flags(device_t bus, device_t child, int restype, int rid, case SYS_RES_MEMORY: { struct mem_desc *mp = &devi->slt->mem[rid]; switch (value) { - case 0: + case PCCARD_A_MEM_COM: mp->flags &= ~MDF_ATTR; break; - case 1: + case PCCARD_A_MEM_ATTR: mp->flags |= MDF_ATTR; break; - case 2: + case PCCARD_A_MEM_8BIT: mp->flags &= ~MDF_16BITS; break; + case PCCARD_A_MEM_16BIT: + mp->flags |= MDF_16BITS; + break; } - err = cinfo.mapmem(devi->slt, rid); + err = pcic_memory(devi->slt, rid); break; } default: @@ -1267,7 +774,7 @@ pcic_set_res_flags(device_t bus, device_t child, int restype, int rid, return (err); } -static int +int pcic_get_res_flags(device_t bus, device_t child, int restype, int rid, u_long *value) { @@ -1291,20 +798,23 @@ pcic_get_res_flags(device_t bus, device_t child, int restype, int rid, default: err = EOPNOTSUPP; } - return (0); + return (err); } -static int -pcic_set_memory_offset(device_t bus, device_t child, int rid, u_int32_t offset) +int +pcic_set_memory_offset(device_t bus, device_t child, int rid, u_int32_t offset, + u_int32_t *deltap) { struct pccard_devinfo *devi = device_get_ivars(child); struct mem_desc *mp = &devi->slt->mem[rid]; mp->card = offset; - return (cinfo.mapmem(devi->slt, rid)); + if (deltap) + *deltap = 0; /* XXX BAD XXX */ + return (pcic_memory(devi->slt, rid)); } -static int +int pcic_get_memory_offset(device_t bus, device_t child, int rid, u_int32_t *offset) { struct pccard_devinfo *devi = device_get_ivars(child); @@ -1318,39 +828,22 @@ pcic_get_memory_offset(device_t bus, device_t child, int rid, u_int32_t *offset) return (0); } -static device_method_t pcic_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, pcic_probe), - DEVMETHOD(device_attach, pcic_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_activate_resource, pcic_activate_resource), - DEVMETHOD(bus_deactivate_resource, pcic_deactivate_resource), - DEVMETHOD(bus_setup_intr, pcic_setup_intr), - DEVMETHOD(bus_teardown_intr, pcic_teardown_intr), - - /* Card interface */ - DEVMETHOD(card_set_res_flags, pcic_set_res_flags), - DEVMETHOD(card_get_res_flags, pcic_get_res_flags), - DEVMETHOD(card_set_memory_offset, pcic_set_memory_offset), - DEVMETHOD(card_get_memory_offset, pcic_get_memory_offset), - - { 0, 0 } -}; - -devclass_t pcic_devclass; +struct resource * +pcic_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct pcic_softc *sc = device_get_softc(dev); -static driver_t pcic_driver = { - "pcic", - pcic_methods, - sizeof(int) -}; + /* + * If we're routing via pci, we can share. + */ + if (sc->func_route == pci_parallel && type == SYS_RES_IRQ) { + if (bootverbose) + device_printf(child, "Forcing IRQ to %d\n", sc->irq); + start = end = sc->irq; + flags |= RF_SHAREABLE; + } -DRIVER_MODULE(pcic, isa, pcic_driver, pcic_devclass, 0, 0); + return (bus_generic_alloc_resource(dev, child, type, rid, start, end, + count, flags)); +} diff --git a/sys/pccard/pcic_pci.c b/sys/pccard/pcic_pci.c index 1bbe672dc353..6588881c139c 100644 --- a/sys/pccard/pcic_pci.c +++ b/sys/pccard/pcic_pci.c @@ -151,7 +151,7 @@ pd6832_legacy_init(device_t dev) * sequentially. We only initialize the first socket's legacy port, * the other is a dummy. */ - io_port = PCIC_INDEX_0 + num6832 * CLPD6832_NUM_REGS; + io_port = PCIC_PORT_0 + num6832 * CLPD6832_NUM_REGS; if (unit == 0) pci_write_config(dev, CLPD6832_LEGACY_16BIT_IOADDR, io_port & ~CLPD6832_LEGACY_16BIT_IOENABLE, 4); @@ -288,7 +288,7 @@ generic_cardbus_attach(device_t dev) iobase = pci_read_config(dev, CB_PCI_LEGACY16_IOADDR, 2) & ~CB_PCI_LEGACY16_IOENABLE; if (!iobase) { - iobase = PCIC_INDEX_0 | CB_PCI_LEGACY16_IOENABLE; + iobase = PCIC_PORT_0 | CB_PCI_LEGACY16_IOENABLE; pci_write_config(dev, CB_PCI_LEGACY16_IOADDR, iobase, 2); iobase = pci_read_config(dev, CB_PCI_LEGACY16_IOADDR, 2) & ~CB_PCI_LEGACY16_IOENABLE; diff --git a/sys/pccard/slot.h b/sys/pccard/slot.h index f34066baeeaa..9374355a76a4 100644 --- a/sys/pccard/slot.h +++ b/sys/pccard/slot.h @@ -70,12 +70,6 @@ struct slot_ctrl { /* suspend/resume support */ int maxmem; /* Number of allowed memory windows */ int maxio; /* Number of allowed I/O windows */ - - /* - * The rest is maintained by the mainline PC-CARD code. - */ - struct slot_ctrl *next; /* Allows linked list of controllers */ - int slots; /* Slots available */ }; /* @@ -118,11 +112,16 @@ struct slot { struct slot_ctrl *ctrl; /* Per-controller data */ void *cdata; /* Controller specific data */ int pwr_off_pending;/* Power status of slot */ + device_t dev; /* Config system device. */ + dev_t d; /* fs device */ }; +#define PCCARD_DEVICE2SOFTC(d) ((struct slot *) device_get_softc(d)) +#define PCCARD_DEV2SOFTC(d) ((struct slot *) (d)->si_drv1) + enum card_event { card_removed, card_inserted }; -struct slot *pccard_alloc_slot(struct slot_ctrl *); +struct slot *pccard_init_slot(device_t, struct slot_ctrl *); void pccard_event(struct slot *, enum card_event); int pccard_suspend(device_t); int pccard_resume(device_t); |
