summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files3
-rw-r--r--sys/pccard/i82365.h41
-rw-r--r--sys/pccard/pccard.c133
-rw-r--r--sys/pccard/pccard_nbk.c110
-rw-r--r--sys/pccard/pcic.c1177
-rw-r--r--sys/pccard/pcic_pci.c4
-rw-r--r--sys/pccard/slot.h13
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);