aboutsummaryrefslogtreecommitdiff
path: root/sys/pccard
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2001-09-04 04:47:58 +0000
committerWarner Losh <imp@FreeBSD.org>2001-09-04 04:47:58 +0000
commit592823383b253d289c1c861a014b4807886d8953 (patch)
treedebe7561bea176c6e277b8af756d91eb8d3640e5 /sys/pccard
parent4ea024db92720d19e3d640ff68a0b97a5be39c02 (diff)
downloadsrc-592823383b253d289c1c861a014b4807886d8953.tar.gz
src-592823383b253d289c1c861a014b4807886d8953.zip
Move to using a chip function + function pointers to deal with the
function and csc interrupt routing path (eg, ISA or PCI) so that we can more easily switch between the two. When we don't have a card ISR, put the function interrupt into ISA mode. This effectively masks the interrupt since it happens once, and not again until we have an ISR. This should help hangs, and might help people that unwisely update the kernel w/o updating pccardd. This is done at mapirq time. Force CL-PD6729/30 to use ISA interrupt routing and maybe even detect the number of pccard slots properly (this is still WIP). We aren't going to support PCI interrupts for this release. A future release should support them, however. Shibata-san's 3.3V fixes are not included. Add a hack which should, in i386, rewrite IRQ 0 cardbus bridges to be IRQ 255, which should cause interrupts to be routed. This is mostly untested since my one tester disappeared after reporting nothing changed. Implement, but do not use, a power method called cardbus. It looked like a great way to get around the 3.3V problem, but it seems that you can only use it to power cardbus cards (I get no CIS when I enable it, so maybe we're programming things bogusly). GC the intr and argp stuff from the slot database. Improve the ToPIC support with the power hacks that Nakagawa-san published in FreeBSD Press and that Hiroyuki Aizu-san ported to -stable. The ToPIC hacks were for 3.3V support in ToPIC 100, but it looks like the '97 also has identical registers, so use them too. Add some #defines for the cardbus power stuff. Finally implement making CSC on the Ricoh chips ISA or PCI. This will allow polling mode to work on vaios, I think. Add some minor debugging. This should likely be cleaned up or put behing a bootverbose. Some of this work, and earlier work, was influanced by Chiharu Shibata-san's power handing patches posted to bsd-nomads:15866. MFC: Soon, if possible.
Notes
Notes: svn path=/head/; revision=82928
Diffstat (limited to 'sys/pccard')
-rw-r--r--sys/pccard/pcic.c118
-rw-r--r--sys/pccard/pcic_isa.c31
-rw-r--r--sys/pccard/pcic_pci.c588
-rw-r--r--sys/pccard/pcic_pci.h26
-rw-r--r--sys/pccard/pcicvar.h30
5 files changed, 634 insertions, 159 deletions
diff --git a/sys/pccard/pcic.c b/sys/pccard/pcic.c
index 793c4455349c..c1ce023d82a0 100644
--- a/sys/pccard/pcic.c
+++ b/sys/pccard/pcic.c
@@ -84,7 +84,8 @@ SYSCTL_NODE(_hw, OID_AUTO, pcic, CTLFLAG_RD, 0, "PCIC parameters");
int pcic_override_irq = 0;
TUNABLE_INT("machdep.pccard.pcic_irq", &pcic_override_irq);
TUNABLE_INT("hw.pcic.irq", &pcic_override_irq);
-SYSCTL_INT(_hw_pcic, OID_AUTO, irq, CTLFLAG_RD, &pcic_override_irq, 0,
+SYSCTL_INT(_hw_pcic, OID_AUTO, irq, CTLFLAG_RD,
+ &pcic_override_irq, 0,
"Override the IRQ configured by the config system for all pcic devices");
/*
@@ -472,6 +473,69 @@ pcic_ioctl(struct slot *slt, int cmd, caddr_t data)
}
/*
+ * pcic_cardbus_power
+ *
+ * Power the card up, as specified, using the cardbus power
+ * registers to control power. Microsoft recommends that cardbus
+ * vendors support powering the card via cardbus registers because
+ * there is no standard for 3.3V cards. Since at least a few of the
+ * cardbus bridges have minor issues with power via the ExCA registers,
+ * go ahead and do it all via cardbus registers.
+ *
+ * An expamination of the code will show the relative
+ * ease that we do Vpp as well.
+ *
+ * Too bad it appears to not work.
+ */
+static int
+pcic_cardbus_power(struct pcic_slot *sp, struct slot *slt)
+{
+ uint32_t reg;
+
+ /*
+ * Preserve the clock stop bit of the socket power register.
+ */
+ reg = bus_space_read_4(sp->bst, sp->bsh, CB_SOCKET_POWER);
+ printf("old value 0x%x\n", reg);
+ reg &= CB_SP_CLKSTOP;
+
+ switch(slt->pwr.vpp) {
+ default:
+ return (EINVAL);
+ case 0:
+ reg |= CB_SP_VPP_0V;
+ break;
+ case 33:
+ reg |= CB_SP_VPP_3V;
+ break;
+ case 50:
+ reg |= CB_SP_VPP_5V;
+ break;
+ case 120:
+ reg |= CB_SP_VPP_12V;
+ break;
+ }
+
+ switch(slt->pwr.vcc) {
+ default:
+ return (EINVAL);
+ case 0:
+ reg |= CB_SP_VCC_0V;
+ break;
+ case 33:
+ reg |= CB_SP_VCC_3V;
+ break;
+ case 50:
+ reg |= CB_SP_VCC_5V;
+ break;
+ }
+ printf("Setting power reg to 0x%x", reg);
+ bus_space_write_4(sp->bst, sp->bsh, CB_SOCKET_POWER, reg);
+
+ return (EIO);
+}
+
+/*
* pcic_power - Enable the power of the slot according to
* the parameters in the power structure(s).
*/
@@ -483,7 +547,13 @@ pcic_power(struct slot *slt)
struct pcic_slot *sp = slt->cdata;
struct pcic_softc *sc = sp->sc;
- if (sc->flags & (PCIC_DF_POWER | PCIC_AB_POWER)) {
+ /*
+ * Cardbus power registers are completely different.
+ */
+ if (sc->flags & PCIC_CARDBUS_POWER)
+ return (pcic_cardbus_power(sp, slt));
+
+ if (sc->flags & PCIC_DF_POWER) {
/*
* Look at the VS[12]# bits on the card. If VS1 is clear
* then we should apply 3.3 volts.
@@ -549,16 +619,7 @@ pcic_power(struct slot *slt)
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))
+ if (sc->flags & PCIC_DF_POWER)
reg |= PCIC_VCC_3V;
break;
case 50:
@@ -612,14 +673,8 @@ static void
pcic_mapirq(struct slot *slt, int irq)
{
struct pcic_slot *sp = slt->cdata;
- if (sp->sc->csc_route == pcic_iw_pci)
- return;
- irq = host_irq_to_pcic(irq);
- if (irq == 0)
- pcic_clrb(sp, PCIC_INT_GEN, 0xF);
- else
- sp->putb(sp, PCIC_INT_GEN,
- (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq);
+
+ sp->sc->chip->map_irq(sp, irq);
}
/*
@@ -631,20 +686,27 @@ pcic_reset(void *chan)
struct slot *slt = chan;
struct pcic_slot *sp = slt->cdata;
+ printf("reset %d\n", slt->insert_seq);
switch (slt->insert_seq) {
case 0: /* Something funny happended on the way to the pub... */
return;
case 1: /* Assert reset */
pcic_clrb(sp, PCIC_INT_GEN, PCIC_CARDRESET);
+ printf("int is %x stat is %x\n", sp->getb(sp, PCIC_INT_GEN),
+ sp->getb(sp, PCIC_STATUS));
slt->insert_seq = 2;
timeout(pcic_reset, (void *)slt, hz/4);
return;
case 2: /* Deassert it again */
pcic_setb(sp, PCIC_INT_GEN, PCIC_CARDRESET | PCIC_IOCARD);
+ printf("int is %x stat is %x\n", sp->getb(sp, PCIC_INT_GEN),
+ sp->getb(sp, PCIC_STATUS));
slt->insert_seq = 3;
timeout(pcic_reset, (void *)slt, hz/4);
return;
case 3: /* Wait if card needs more time */
+ printf("int is %x stat is %x\n", sp->getb(sp, PCIC_INT_GEN),
+ sp->getb(sp, PCIC_STATUS));
if (!sp->getb(sp, PCIC_STATUS) & PCIC_READY) {
timeout(pcic_reset, (void *)slt, hz/10);
return;
@@ -670,7 +732,8 @@ pcic_disable(struct slot *slt)
{
struct pcic_slot *sp = slt->cdata;
- pcic_clrb(sp, PCIC_INT_GEN, 0xf | PCIC_CARDTYPE | PCIC_CARDRESET);
+ pcic_clrb(sp, PCIC_INT_GEN, PCIC_CARDTYPE | PCIC_CARDRESET);
+ pcic_mapirq(slt, 0);
sp->putb(sp, PCIC_POWER, 0);
}
@@ -1013,3 +1076,16 @@ pcic_isa_intr1(void *arg)
splx(s);
return (0);
}
+
+int
+pcic_isa_mapirq(struct pcic_slot *sp, int irq)
+{
+ irq = host_irq_to_pcic(irq);
+ sp->sc->chip->func_intr_way(sp, pcic_iw_isa);
+ if (irq == 0)
+ pcic_clrb(sp, PCIC_INT_GEN, 0xF);
+ else
+ sp->putb(sp, PCIC_INT_GEN,
+ (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq);
+ return (0);
+}
diff --git a/sys/pccard/pcic_isa.c b/sys/pccard/pcic_isa.c
index ce39f2605b38..e20eedfc388b 100644
--- a/sys/pccard/pcic_isa.c
+++ b/sys/pccard/pcic_isa.c
@@ -75,6 +75,16 @@ static struct {
{ "Intel i82365SL-DF", PCIC_DF_POWER}
};
+static pcic_intr_way_t pcic_isa_intr_way;
+static pcic_init_t pcic_isa_init;
+
+struct pcic_chip pcic_isa_chip = {
+ pcic_isa_intr_way,
+ pcic_isa_intr_way,
+ pcic_isa_mapirq,
+ pcic_isa_init
+};
+
/*
* Look for an Intel PCIC (or compatible).
* For each available slot, allocate a PC-CARD slot.
@@ -291,6 +301,7 @@ pcic_isa_attach(device_t dev)
sc->iores = r;
sc->csc_route = pcic_iw_isa;
sc->func_route = pcic_iw_isa;
+ sc->chip = &pcic_isa_chip;
rid = 0;
r = NULL;
@@ -331,6 +342,26 @@ pcic_isa_attach(device_t dev)
return (pcic_attach(dev));
}
+/*
+ * ISA cards can only do ISA interrupts. There's no need to do
+ * anything but check args for sanity.
+ */
+static int
+pcic_isa_intr_way(struct pcic_slot *sp, enum pcic_intr_way iw)
+{
+ if (iw != pcic_iw_isa)
+ return (EINVAL);
+ return (0);
+}
+
+/*
+ * No speicial initialization is necesary for ISA cards.
+ */
+static void
+pcic_isa_init(device_t dev)
+{
+}
+
static device_method_t pcic_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pcic_isa_probe),
diff --git a/sys/pccard/pcic_pci.c b/sys/pccard/pcic_pci.c
index 205e7268f5af..199afdcef94b 100644
--- a/sys/pccard/pcic_pci.c
+++ b/sys/pccard/pcic_pci.c
@@ -90,13 +90,95 @@ always require this, while builtin bridges need it less often");
typedef void (*init_t)(device_t);
static void pcic_pci_cardbus_init(device_t);
-static void pcic_pci_oz67xx_init(device_t);
-static void pcic_pci_oz68xx_init(device_t);
-static void pcic_pci_pd67xx_init(device_t);
-static void pcic_pci_pd683x_init(device_t);
-static void pcic_pci_ricoh_init(device_t);
-static void pcic_pci_ti_init(device_t);
-static void pcic_pci_topic_init(device_t);
+static pcic_intr_mapirq_t pcic_pci_gen_mapirq;
+
+static pcic_intr_way_t pcic_pci_oz67xx_func;
+static pcic_intr_way_t pcic_pci_oz67xx_csc;
+static pcic_init_t pcic_pci_oz67xx_init;
+
+static pcic_intr_way_t pcic_pci_oz68xx_func;
+static pcic_intr_way_t pcic_pci_oz68xx_csc;
+static pcic_init_t pcic_pci_oz68xx_init;
+
+static pcic_intr_way_t pcic_pci_pd67xx_func;
+static pcic_intr_way_t pcic_pci_pd67xx_csc;
+static pcic_init_t pcic_pci_pd67xx_init;
+
+static pcic_intr_way_t pcic_pci_pd68xx_func;
+static pcic_intr_way_t pcic_pci_pd68xx_csc;
+static pcic_init_t pcic_pci_pd68xx_init;
+
+static pcic_intr_way_t pcic_pci_ricoh_func;
+static pcic_intr_way_t pcic_pci_ricoh_csc;
+static pcic_init_t pcic_pci_ricoh_init;
+
+static pcic_intr_way_t pcic_pci_ti113x_func;
+static pcic_intr_way_t pcic_pci_ti113x_csc;
+static pcic_init_t pcic_pci_ti_init;
+
+static pcic_intr_way_t pcic_pci_ti12xx_func;
+static pcic_intr_way_t pcic_pci_ti12xx_csc;
+
+static pcic_intr_way_t pcic_pci_topic_func;
+static pcic_intr_way_t pcic_pci_topic_csc;
+static pcic_init_t pcic_pci_topic_init;
+
+static struct pcic_chip pcic_pci_oz67xx_chip = {
+ pcic_pci_oz67xx_func,
+ pcic_pci_oz67xx_csc,
+ pcic_pci_gen_mapirq,
+ pcic_pci_oz67xx_init
+};
+
+static struct pcic_chip pcic_pci_oz68xx_chip = {
+ pcic_pci_oz68xx_func,
+ pcic_pci_oz68xx_csc,
+ pcic_pci_gen_mapirq,
+ pcic_pci_oz68xx_init
+};
+
+static struct pcic_chip pcic_pci_pd67xx_chip = {
+ pcic_pci_pd67xx_func,
+ pcic_pci_pd67xx_csc,
+ pcic_pci_gen_mapirq,
+ pcic_pci_pd67xx_init
+};
+
+static struct pcic_chip pcic_pci_pd68xx_chip = {
+ pcic_pci_pd68xx_func,
+ pcic_pci_pd68xx_csc,
+ pcic_pci_gen_mapirq,
+ pcic_pci_pd68xx_init
+};
+
+static struct pcic_chip pcic_pci_ricoh_chip = {
+ pcic_pci_ricoh_func,
+ pcic_pci_ricoh_csc,
+ pcic_pci_gen_mapirq,
+ pcic_pci_ricoh_init
+};
+
+static struct pcic_chip pcic_pci_ti113x_chip = {
+ pcic_pci_ti113x_func,
+ pcic_pci_ti113x_csc,
+ pcic_pci_gen_mapirq,
+ pcic_pci_ti_init
+};
+
+static struct pcic_chip pcic_pci_ti12xx_chip = {
+ pcic_pci_ti12xx_func,
+ pcic_pci_ti12xx_csc,
+ pcic_pci_gen_mapirq,
+ pcic_pci_ti_init
+};
+
+static struct pcic_chip pcic_pci_topic_chip = {
+ pcic_pci_topic_func,
+ pcic_pci_topic_csc,
+ pcic_pci_gen_mapirq,
+ pcic_pci_topic_init
+};
+
struct pcic_pci_table
{
@@ -104,113 +186,113 @@ struct pcic_pci_table
const char *descr;
int type;
u_int32_t flags;
- init_t init;
+ struct pcic_chip *chip;
} pcic_pci_devs[] = {
{ PCI_DEVICE_ID_PCIC_CLPD6729,
"Cirrus Logic PD6729/6730 PC-Card Controller",
- PCIC_PD672X, PCIC_PD_POWER, pcic_pci_pd67xx_init },
+ PCIC_PD672X, PCIC_PD_POWER, &pcic_pci_pd67xx_chip },
{ PCI_DEVICE_ID_PCIC_CLPD6832,
"Cirrus Logic PD6832 PCI-CardBus Bridge",
- PCIC_PD672X, PCIC_PD_POWER, pcic_pci_pd683x_init },
+ PCIC_PD672X, PCIC_PD_POWER, &pcic_pci_pd68xx_chip },
{ PCI_DEVICE_ID_PCIC_CLPD6833,
"Cirrus Logic PD6833 PCI-CardBus Bridge",
- PCIC_PD672X, PCIC_PD_POWER, pcic_pci_pd683x_init },
+ PCIC_PD672X, PCIC_PD_POWER, &pcic_pci_pd68xx_chip },
{ PCI_DEVICE_ID_PCIC_OZ6729,
"O2micro OZ6729 PC-Card Bridge",
- PCIC_I82365, PCIC_AB_POWER, pcic_pci_oz67xx_init },
+ PCIC_I82365, PCIC_AB_POWER, &pcic_pci_oz67xx_chip },
{ PCI_DEVICE_ID_PCIC_OZ6730,
"O2micro OZ6730 PC-Card Bridge",
- PCIC_I82365, PCIC_AB_POWER, pcic_pci_oz67xx_init },
+ PCIC_I82365, PCIC_AB_POWER, &pcic_pci_oz67xx_chip },
{ PCI_DEVICE_ID_PCIC_OZ6832,
"O2micro 6832/6833 PCI-Cardbus Bridge",
- PCIC_I82365, PCIC_AB_POWER, pcic_pci_oz68xx_init },
+ PCIC_I82365, PCIC_AB_POWER, &pcic_pci_oz68xx_chip },
{ PCI_DEVICE_ID_PCIC_OZ6860,
"O2micro 6860/6836 PCI-Cardbus Bridge",
- PCIC_I82365, PCIC_AB_POWER, pcic_pci_oz68xx_init },
+ PCIC_I82365, PCIC_AB_POWER, &pcic_pci_oz68xx_chip },
{ PCI_DEVICE_ID_PCIC_OZ6872,
"O2micro 6812/6872 PCI-Cardbus Bridge",
- PCIC_I82365, PCIC_AB_POWER, pcic_pci_oz68xx_init },
+ PCIC_I82365, PCIC_AB_POWER, &pcic_pci_oz68xx_chip },
{ PCI_DEVICE_ID_RICOH_RL5C465,
"Ricoh RL5C465 PCI-CardBus Bridge",
- PCIC_RF5C296, PCIC_RICOH_POWER, pcic_pci_ricoh_init },
+ PCIC_RF5C296, PCIC_RICOH_POWER, &pcic_pci_ricoh_chip },
{ PCI_DEVICE_ID_RICOH_RL5C475,
"Ricoh RL5C475 PCI-CardBus Bridge",
- PCIC_RF5C296, PCIC_RICOH_POWER, pcic_pci_ricoh_init },
+ PCIC_RF5C296, PCIC_RICOH_POWER, &pcic_pci_ricoh_chip },
{ PCI_DEVICE_ID_RICOH_RL5C476,
"Ricoh RL5C476 PCI-CardBus Bridge",
- PCIC_RF5C296, PCIC_RICOH_POWER, pcic_pci_ricoh_init },
+ PCIC_RF5C296, PCIC_RICOH_POWER, &pcic_pci_ricoh_chip },
{ PCI_DEVICE_ID_RICOH_RL5C477,
"Ricoh RL5C477 PCI-CardBus Bridge",
- PCIC_RF5C296, PCIC_RICOH_POWER, pcic_pci_ricoh_init },
+ PCIC_RF5C296, PCIC_RICOH_POWER, &pcic_pci_ricoh_chip },
{ PCI_DEVICE_ID_RICOH_RL5C478,
"Ricoh RL5C478 PCI-CardBus Bridge",
- PCIC_RF5C296, PCIC_RICOH_POWER, pcic_pci_ricoh_init },
+ PCIC_RF5C296, PCIC_RICOH_POWER, &pcic_pci_ricoh_chip },
{ PCI_DEVICE_ID_PCIC_TI1031,
"TI PCI-1031 PCI-PCMCIA Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti113x_chip },
{ PCI_DEVICE_ID_PCIC_TI1130,
"TI PCI-1130 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti113x_chip },
{ PCI_DEVICE_ID_PCIC_TI1131,
"TI PCI-1131 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti113x_chip },
{ PCI_DEVICE_ID_PCIC_TI1210,
"TI PCI-1210 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI1211,
"TI PCI-1211 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI1220,
"TI PCI-1220 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI1221,
"TI PCI-1221 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI1225,
"TI PCI-1225 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI1250,
"TI PCI-1250 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI1251,
"TI PCI-1251 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI1251B,
"TI PCI-1251B PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI1410,
"TI PCI-1410 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI1420,
"TI PCI-1420 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI1450,
"TI PCI-1450 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI1451,
"TI PCI-1451 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI4410,
"TI PCI-4410 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI4450,
"TI PCI-4450 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_PCIC_TI4451,
"TI PCI-4451 PCI-CardBus Bridge",
- PCIC_I82365SL_DF, PCIC_DF_POWER, pcic_pci_ti_init },
+ PCIC_I82365SL_DF, PCIC_DF_POWER, &pcic_pci_ti12xx_chip },
{ PCI_DEVICE_ID_TOSHIBA_TOPIC95,
"Toshiba ToPIC95 PCI-CardBus Bridge",
- PCIC_I82365, PCIC_AB_POWER, pcic_pci_topic_init },
+ PCIC_I82365, PCIC_AB_POWER, &pcic_pci_topic_chip },
{ PCI_DEVICE_ID_TOSHIBA_TOPIC95B,
"Toshiba ToPIC95B PCI-CardBus Bridge",
- PCIC_I82365, PCIC_AB_POWER, pcic_pci_topic_init },
+ PCIC_I82365, PCIC_AB_POWER, &pcic_pci_topic_chip },
{ PCI_DEVICE_ID_TOSHIBA_TOPIC97,
"Toshiba ToPIC97 PCI-CardBus Bridge",
- PCIC_I82365, PCIC_AB_POWER, pcic_pci_topic_init },
+ PCIC_I82365, PCIC_DF_POWER, &pcic_pci_topic_chip },
{ PCI_DEVICE_ID_TOSHIBA_TOPIC100,
"Toshiba ToPIC100 PCI-CardBus Bridge",
- PCIC_I82365, PCIC_AB_POWER, pcic_pci_topic_init },
+ PCIC_I82365, PCIC_DF_POWER, &pcic_pci_topic_chip },
{ 0, NULL, 0, 0, NULL }
};
@@ -246,6 +328,46 @@ pcic_pci_lookup(u_int32_t devid, struct pcic_pci_table *tbl)
return (NULL);
}
+/*
+ * The standard way to control fuction interrupts is via bit 7 in the BCR
+ * register. Some data sheets indicate that this is just for "intterupts"
+ * while others are clear that it is for function interrupts. When this
+ * bit is set, function interrupts are routed via the ExCA register. When
+ * this bit is clear, they are routed via the PCI bus, usually via the int
+ * in the INTPIN register.
+ */
+static int
+pcic_pci_gen_func(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ u_int16_t bcr;
+
+ bcr = pci_read_config(sp->sc->dev, CB_PCI_BRIDGE_CTRL, 2);
+ if (way == pcic_iw_pci)
+ bcr &= ~CB_BCR_INT_EXCA;
+ else
+ bcr |= CB_BCR_INT_EXCA;
+ pci_write_config(sp->sc->dev, CB_PCI_BRIDGE_CTRL, bcr, 2);
+ return (0);
+}
+
+
+/*
+ * The O2micro OZ67xx chips functions.
+ */
+static int
+pcic_pci_oz67xx_func(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ return (pcic_pci_gen_func(sp, way));
+}
+
+static int
+pcic_pci_oz67xx_csc(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ /* XXX */
+ return (0);
+}
+
+
static void
pcic_pci_oz67xx_init(device_t dev)
{
@@ -256,6 +378,22 @@ pcic_pci_oz67xx_init(device_t dev)
pcic_pci_cardbus_init(dev);
}
+/*
+ * The O2micro OZ68xx chips functions.
+ */
+static int
+pcic_pci_oz68xx_func(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ return (pcic_pci_gen_func(sp, way));
+}
+
+static int
+pcic_pci_oz68xx_csc(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ /* XXX */
+ return (0);
+}
+
static void
pcic_pci_oz68xx_init(device_t dev)
{
@@ -266,6 +404,24 @@ pcic_pci_oz68xx_init(device_t dev)
pcic_pci_cardbus_init(dev);
}
+/*
+ * The Cirrus Logic PD6729/30. These are weird beasts, so be careful.
+ */
+static int
+pcic_pci_pd67xx_func(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ /* XXX */
+ return (0);
+}
+
+static int
+pcic_pci_pd67xx_csc(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ /* XXX */
+ return (0);
+}
+
+
static void
pcic_pci_pd67xx_init(device_t dev)
{
@@ -276,50 +432,88 @@ pcic_pci_pd67xx_init(device_t dev)
}
/*
- * Set up the CL-PD6832
+ * Set up the CL-PD6832 and 6833.
*/
-static void
-pcic_pci_pd683x_init(device_t dev)
+static int
+pcic_pci_pd68xx_func(struct pcic_slot *sp, enum pcic_intr_way way)
{
- struct pcic_softc *sc = device_get_softc(dev);
+ return (pcic_pci_gen_func(sp, way));
+}
+
+static int
+pcic_pci_pd68xx_csc(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ struct pcic_softc *sc = sp->sc;
+ device_t dev = sc->dev;
u_int32_t device_id = pci_get_devid(dev);
u_long bcr;
u_long cm1;
/*
- * CLPD6832 management interrupt enable bit is bit 11 (MGMT_IRQ_ENA)
- * in bridge control register(offset 0x3d).
- * When this bit is turned on, card status change interrupt sets
- * on ISA IRQ interrupt.
- * Bit 7 controls the function interrupts and appears to be stanard.
+ * CLPD6832 management interrupt enable bit is bit 11
+ * (MGMT_IRQ_ENA) in bridge control register(offset 0x3d).
+ * When on, card status interrupts are ISA controlled by
+ * the ExCA register 0x05.
*
- * The CLPD6833 does things differently. It has bit 7, but not bit
- * 11. Bit 11's functionality appears to be in the "Configuration
+ * The CLPD6833 does things differently. It doesn't have bit
+ * 11 in the bridge control register. Instead, this
+ * functionality appears to be in the "Configuration
* Miscellaneous 1" register bit 1.
*/
- bcr = pci_read_config(dev, CB_PCI_BRIDGE_CTRL, 2);
if (device_id == PCI_DEVICE_ID_PCIC_CLPD6832) {
- if (sc->csc_route == pcic_iw_pci)
+ bcr = pci_read_config(dev, CB_PCI_BRIDGE_CTRL, 2);
+ if (way == pcic_iw_pci)
bcr &= ~CLPD6832_BCR_MGMT_IRQ_ENA;
else
bcr |= CLPD6832_BCR_MGMT_IRQ_ENA;
+ pci_write_config(dev, CB_PCI_BRIDGE_CTRL, bcr, 2);
}
- if (sc->func_route == pcic_iw_pci)
- bcr &= ~CB_BCR_INT_EXCA;
- else
- bcr |= CB_BCR_INT_EXCA;
- pci_write_config(dev, CB_PCI_BRIDGE_CTRL, bcr, 2);
if (device_id == PCI_DEVICE_ID_PCIC_CLPD6833) {
cm1 = pci_read_config(dev, CLPD6833_CFG_MISC_1, 4);
- if (sc->csc_route == pcic_iw_pci)
+ if (way == pcic_iw_pci)
cm1 &= ~CLPD6833_CM1_MGMT_EXCA_ENA;
else
cm1 |= CLPD6833_CM1_MGMT_EXCA_ENA;
pci_write_config(dev, CLPD6833_CFG_MISC_1, cm1, 4);
}
+ return (0);
+}
+
+static void
+pcic_pci_pd68xx_init(device_t dev)
+{
pcic_pci_cardbus_init(dev);
}
+static int
+pcic_pci_ricoh_func(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ return (pcic_pci_gen_func(sp, way));
+}
+
+static int
+pcic_pci_ricoh_csc(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ struct pcic_softc *sc = sp->sc;
+ device_t dev = sc->dev;
+ u_int16_t mcr2;
+
+ /*
+ * For CSC interrupts via ISA, we can't do that exactly.
+ * However, we can disable INT# routing, which is usually what
+ * we want. This is bit 7 in the field. Note, bit 6 looks
+ * interesting, but appears to be unnecessary.
+ */
+ mcr2 = pci_read_config(dev, R5C47X_MISC_CONTROL_REGISTER_2, 2);
+ if (way == pcic_iw_pci)
+ mcr2 &= ~R5C47X_MCR2_CSC_TO_INTX_DISABLE;
+ else
+ mcr2 |= R5C47X_MCR2_CSC_TO_INTX_DISABLE;
+ pci_write_config(dev, R5C47X_MISC_CONTROL_REGISTER_2, mcr2, 2);
+
+ return (0);
+}
+
static void
pcic_pci_ricoh_init(device_t dev)
{
@@ -343,6 +537,88 @@ pcic_pci_ricoh_init(device_t dev)
}
/*
+ * TI 1030, 1130, and 1131.
+ */
+static int
+pcic_pci_ti113x_func(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ u_int32_t cardcntl;
+ device_t dev = sp->sc->dev;
+
+ /*
+ * The TI-1130 (and 1030 and 1131) have a different interrupt
+ * routing control than the newer cards. assume we're not
+ * routing PCI, but enable as necessary when we find someone
+ * uses PCI interrupts. In order to get any pci interrupts,
+ * PCI_IRQ_ENA (bit 5) must be set. If either PCI_IREQ (bit
+ * 4) or PCI_CSC (bit 3) are set, then set bit 5 at the same
+ * time, since setting them enables the PCI interrupt routing.
+ *
+ * It also appears necessary to set the function routing bit
+ * in the bridge control register, but cardbus_init does that
+ * for us.
+ */
+ cardcntl = pci_read_config(dev, TI113X_PCI_CARD_CONTROL, 1);
+ if (way == pcic_iw_pci)
+ cardcntl |= TI113X_CARDCNTL_PCI_IREQ;
+ else
+ cardcntl &= ~TI113X_CARDCNTL_PCI_IREQ;
+ if (cardcntl & (TI113X_CARDCNTL_PCI_IREQ | TI113X_CARDCNTL_PCI_CSC))
+ cardcntl &= ~TI113X_CARDCNTL_PCI_IRQ_ENA;
+ else
+ cardcntl |= TI113X_CARDCNTL_PCI_IRQ_ENA;
+ pci_write_config(dev, TI113X_PCI_CARD_CONTROL, cardcntl, 1);
+
+ return (pcic_pci_gen_func(sp, way));
+}
+
+static int
+pcic_pci_ti113x_csc(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ u_int32_t cardcntl;
+ device_t dev = sp->sc->dev;
+
+ /*
+ * The TI-1130 (and 1030 and 1131) have a different interrupt
+ * routing control than the newer cards. assume we're not
+ * routing PCI, but enable as necessary when we find someone
+ * uses PCI interrupts. In order to get any pci interrupts,
+ * PCI_IRQ_ENA (bit 5) must be set. If either PCI_IREQ (bit
+ * 4) or PCI_CSC (bit 3) are set, then set bit 5 at the same
+ * time, since setting them enables the PCI interrupt routing.
+ *
+ * It also appears necessary to set the function routing bit
+ * in the bridge control register, but cardbus_init does that
+ * for us.
+ */
+ cardcntl = pci_read_config(dev, TI113X_PCI_CARD_CONTROL, 1);
+ if (way == pcic_iw_pci)
+ cardcntl |= TI113X_CARDCNTL_PCI_CSC;
+ else
+ cardcntl &= ~TI113X_CARDCNTL_PCI_CSC;
+ if (cardcntl & (TI113X_CARDCNTL_PCI_IREQ | TI113X_CARDCNTL_PCI_CSC))
+ cardcntl &= ~TI113X_CARDCNTL_PCI_IRQ_ENA;
+ else
+ cardcntl |= TI113X_CARDCNTL_PCI_IRQ_ENA;
+ pci_write_config(dev, TI113X_PCI_CARD_CONTROL, cardcntl, 1);
+
+ return (0);
+}
+
+static int
+pcic_pci_ti12xx_func(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ return (pcic_pci_gen_func(sp, way));
+}
+
+static int
+pcic_pci_ti12xx_csc(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ /* XXX */
+ return (0);
+}
+
+/*
* TI PCI-CardBus Host Adapter specific function code.
* This function is separated from pcic_pci_attach().
* Takeshi Shibagaki(shiba@jp.freebsd.org).
@@ -363,30 +639,6 @@ pcic_pci_ti_init(device_t dev)
if (ti113x) {
device_printf(dev, "TI113X PCI Config Reg: ");
-
- /*
- * The TI-1130 (and 1030 and 1131) have a different
- * interrupt routing control than the newer cards.
- * assume we're not routing PCI, but enable as necessary
- * when we find someone uses PCI interrupts. In order to
- * get any pci interrupts, PCI_IRQ_ENA (bit 5) must
- * be set. If either PCI_IREQ (bit 4) or PCI_CSC (bit 3)
- * are set, then set bit 5 at the same time, since setting
- * them enables the PCI interrupt routing.
- */
- cardcntl &= ~TI113X_CARDCNTL_PCI_IRQ_ENA;
- if (sc->func_route == pcic_iw_pci)
- cardcntl |= TI113X_CARDCNTL_PCI_IRQ_ENA |
- TI113X_CARDCNTL_PCI_IREQ;
- else
- cardcntl &= ~TI113X_CARDCNTL_PCI_IREQ;
- if (sc->csc_route == pcic_iw_pci)
- cardcntl |= TI113X_CARDCNTL_PCI_IRQ_ENA |
- TI113X_CARDCNTL_PCI_CSC;
- else
- cardcntl &= ~TI113X_CARDCNTL_PCI_CSC;
- pci_write_config(dev, TI113X_PCI_CARD_CONTROL, cardcntl, 1);
- cardcntl = pci_read_config(dev, TI113X_PCI_CARD_CONTROL, 1);
if (syscntl & TI113X_SYSCNTL_CLKRUN_ENA) {
if (syscntl & TI113X_SYSCNTL_CLKRUN_SEL)
printf("[clkrun irq 12]");
@@ -415,11 +667,11 @@ pcic_pci_ti_init(device_t dev)
*/
pci_write_config(dev, TI12XX_PCI_MULTIMEDIA_CONTROL, 0, 4);
}
- /*
- * Default card control register setting is PCI interrupt.
- * The method of this code switches PCI INT and ISA IRQ by bit
- * 7 of Bridge Control Register(Offset:0x3e,0x13e).
- * Takeshi Shibagaki(shiba@jp.freebsd.org)
+ /*
+ * Special code for the Orinoco cards (and a few others). They
+ * seem to need this special code to make them work only over pci
+ * interrupts. Sadly, doing this code also causes problems for
+ * many laptops, so we have to make it controlled by a tunable.
*/
if (sc->func_route == pcic_iw_pci) {
if (pcic_init_routing) {
@@ -457,46 +709,65 @@ pcic_pci_ti_init(device_t dev)
pcic_pci_cardbus_init(dev);
}
+/*
+ * Code for TOPIC chips
+ */
+static int
+pcic_pci_topic_func(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+ return (pcic_pci_gen_func(sp, way));
+}
+
+static int
+pcic_pci_topic_csc(struct pcic_slot *sp, enum pcic_intr_way way)
+{
+
+ return (0);
+}
+
static void
pcic_pci_topic_init(device_t dev)
{
- /*
- * This is almost certainly incomplete.
- */
- device_printf(dev, "Warning: Toshiba ToPIC chips may not work\n");
+ struct pcic_softc *sc = device_get_softc(dev);
+ u_int32_t device_id;
+
+ device_id = pci_get_devid(dev);
+ if (device_id == PCI_DEVICE_ID_TOSHIBA_TOPIC100 ||
+ device_id == PCI_DEVICE_ID_TOSHIBA_TOPIC97) {
+ /*
+ * We need to enable voltage sense and 3V cards explicitly
+ * in the bridge. The datasheets I have for both the
+ * ToPIC 97 and 100 both lists these ports. Without
+ * datasheets for the ToPIC95s, I can't tell if we need
+ * to do it there or not.
+ */
+ pcic_setb(&sc->slots[0], PCIC_TOPIC_FCR,
+ PCIC_FCR_3V_EN | PCIC_FCR_VS_EN);
+ }
pcic_pci_cardbus_init(dev);
}
static void
pcic_pci_cardbus_init(device_t dev)
{
+ struct pcic_softc *sc = device_get_softc(dev);
u_int16_t brgcntl;
int unit;
- struct pcic_softc *sc = device_get_softc(dev);
unit = device_get_unit(dev);
- if (sc->func_route == pcic_iw_pci) {
- /* Use INTA for routing function interrupts via pci bus */
- brgcntl = pci_read_config(dev, CB_PCI_BRIDGE_CTRL, 2);
- brgcntl &= ~CB_BCR_INT_EXCA;
- brgcntl |= CB_BCR_WRITE_POST_EN | CB_BCR_MASTER_ABORT;
- pci_write_config(dev, CB_PCI_BRIDGE_CTRL, brgcntl, 2);
- } else {
- /* Output ISA IRQ indicated in ExCA register(0x03). */
- brgcntl = pci_read_config(dev, CB_PCI_BRIDGE_CTRL, 2);
- brgcntl |= CB_BCR_INT_EXCA;
- pci_write_config(dev, CB_PCI_BRIDGE_CTRL, brgcntl, 2);
- }
+ brgcntl = pci_read_config(dev, CB_PCI_BRIDGE_CTRL, 2);
+ brgcntl |= CB_BCR_WRITE_POST_EN | CB_BCR_MASTER_ABORT;
+ pci_write_config(dev, CB_PCI_BRIDGE_CTRL, brgcntl, 2);
/* Turn off legacy address */
pci_write_config(dev, CB_PCI_LEGACY16_IOADDR, 0, 2);
/*
- * Write zeros into the remaining BARs. This seems to turn off
- * the pci configuration of these things and make the cardbus
- * bridge use the values for memory programmed into the pcic
- * registers.
+ * Write zeros into the remaining memory I/O windows. This
+ * seems to turn off the pci configuration of these things and
+ * make the cardbus bridge use the values for memory
+ * programmed into the pcic registers.
*/
pci_write_config(dev, CB_PCI_MEMBASE0, 0, 4);
pci_write_config(dev, CB_PCI_MEMLIMIT0, 0, 4);
@@ -507,6 +778,13 @@ pcic_pci_cardbus_init(device_t dev)
pci_write_config(dev, CB_PCI_IOBASE1, 0, 4);
pci_write_config(dev, CB_PCI_IOLIMIT1, 0, 4);
+ /*
+ * Force the function interrupts to be pulse rather than
+ * edge triggered.
+ */
+ sc->chip->func_intr_way(&sc->slots[0], pcic_iw_isa);
+ sc->chip->csc_intr_way(&sc->slots[0], sc->csc_route);
+
return;
}
@@ -584,10 +862,14 @@ pcic_pci_intr(void *arg)
sc->cd_pending = 1;
} else {
sc->cd_present = 0;
- sp->intr = NULL;
pccard_event(sp->slt, card_removed);
}
}
+ if (event & CB_SE_POWER)
+ device_printf(sc->dev, "Power interrupt\n");
+ if (stat & CB_SS_BADVCC)
+ device_printf(sc->dev, "BAD Vcc request\n");
+
/* Ack the interrupt */
bus_space_write_4(sp->bst, sp->bsh, 0, event);
}
@@ -659,9 +941,24 @@ pcic_pci_probe(device_t dev)
* This so we get the interrupt number in the probe message.
* We only need to route interrupts when we're doing pci
* parallel interrupt routing.
+ *
+ * Note: The CLPD6729 is a special case. See its init function
+ * for an explaination of ISA vs PCI interrupts.
*/
- if (pcic_intr_path == pcic_iw_pci) {
+ if (pcic_intr_path == pcic_iw_pci &&
+ device_id != PCI_DEVICE_ID_PCIC_CLPD6729) {
rid = 0;
+#ifdef __i386__
+ /*
+ * IRQ 0 is invalid on x86, but not other platforms.
+ * If we have irq 0, then write 255 to force a new, non-
+ * bogus one to be assigned.
+ */
+ if (pci_get_irq(dev) == 0) {
+ pci_set_irq(dev, 255);
+ pci_write_config(dev, PCIR_INTLINE, 255, 1);
+ }
+#endif
res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
RF_ACTIVE);
if (res)
@@ -721,6 +1018,7 @@ pcic_pci_attach(device_t dev)
u_int32_t stat;
struct pcic_pci_table *itm;
int rid;
+ int i;
struct resource *r = NULL;
int error;
u_long irq = 0;
@@ -745,15 +1043,32 @@ pcic_pci_attach(device_t dev)
&sc->iorid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
if (sc->iores == NULL)
return (ENOMEM);
- sp->getb = pcic_getb_io;
- sp->putb = pcic_putb_io;
sp->bst = rman_get_bustag(sc->iores);
sp->bsh = rman_get_bushandle(sc->iores);
- sp->offset = pci_get_function(dev) * PCIC_SLOT_SIZE;
sp->controller = PCIC_PD672X;
sp->revision = 0;
sc->flags = PCIC_PD_POWER;
itm = pcic_pci_lookup(device_id, &pcic_pci_devs[0]);
+ for (i = 0; i < 2; i++) {
+ sp[i].getb = pcic_getb_io;
+ sp[i].putb = pcic_putb_io;
+ sp[i].offset = i * PCIC_SLOT_SIZE;
+ sp[i].controller = PCIC_PD672X;
+ printf("ID is 0x%x\n", sp[i].getb(sp, PCIC_ID_REV));
+ if ((sp[i].getb(sp, PCIC_ID_REV) & 0xc0) == 0x80)
+ sp[i].slt = (struct slot *) 1;
+ }
+ /*
+ * We only support isa at this time. These cards can be
+ * wired up as either ISA cards *OR* PCI cards (well, weird
+ * hybrids are possible, but not seen in the wild). Since it
+ * is an either or thing, we assume ISA since all laptops that
+ * we supported in 4.3 and earlier work.
+ */
+ sc->csc_route = pcic_iw_isa;
+ sc->func_route = pcic_iw_isa;
+ if (itm)
+ sc->flags = itm->flags;
} else {
sc->memrid = CB_PCI_SOCKET_BASE;
sc->memres = bus_alloc_resource(dev, SYS_RES_MEMORY,
@@ -769,18 +1084,22 @@ pcic_pci_attach(device_t dev)
if (itm != NULL) {
sp->controller = itm->type;
sp->revision = 0;
- sc->flags = itm->flags;
+ sc->flags = itm->flags;
} else {
/* By default, assume we're a D step compatible */
sp->controller = PCIC_I82365SL_DF;
sp->revision = 0;
sc->flags = PCIC_DF_POWER;
}
+ /* sc->flags = PCIC_CARDBUS_POWER; */
+ sp->slt = (struct slot *) 1;
+ sc->csc_route = pcic_intr_path;
+ sc->func_route = pcic_intr_path;
+ stat = bus_space_read_4(sp->bst, sp->bsh, CB_SOCKET_STATE);
+ sc->cd_present = (stat & CB_SS_CD) == 0;
}
sc->dev = dev;
- sc->csc_route = pcic_intr_path;
- sc->func_route = pcic_intr_path;
- sp->slt = (struct slot *) 1;
+ sc->chip = itm->chip;
if (sc->csc_route == pcic_iw_pci) {
rid = 0;
@@ -808,6 +1127,8 @@ pcic_pci_attach(device_t dev)
pcic_dealloc(dev);
return (ENXIO);
}
+ device_printf(dev,
+ "Management interrupt on ISA IRQ %ld\n", irq);
intr = pcic_isa_intr;
} else {
sc->slot_poll = pcic_timeout;
@@ -821,10 +1142,9 @@ pcic_pci_attach(device_t dev)
* Initialize AFTER we figure out what kind of interrupt we're
* going to be using, if any.
*/
- if (itm && itm->init)
- itm->init(dev);
- else
- pcic_pci_cardbus_init(dev);
+ if (!sc->chip)
+ panic("Bug: sc->chip not set!\n");
+ sc->chip->init(dev);
/*
* Now install the interrupt handler, if necessary.
@@ -839,9 +1159,6 @@ pcic_pci_attach(device_t dev)
return (error);
}
}
-
- stat = bus_space_read_4(sp->bst, sp->bsh, CB_SOCKET_STATE);
- sc->cd_present = (stat & CB_SS_CD) == 0;
return (pcic_attach(dev));
}
@@ -887,6 +1204,21 @@ pcic_pci_get_memory(device_t dev)
return (0);
}
+static int
+pcic_pci_gen_mapirq(struct pcic_slot *sp, int irq)
+{
+ /*
+ * If we're doing ISA interrupt routing, then just go to the
+ * generic ISA routine. Also, irq 0 means turn off the interrupts
+ * at the bridge. We do this by making the interrupts edge
+ * triggered rather then level.
+ */
+ if (sp->sc->func_route == pcic_iw_isa || irq == 0)
+ return (pcic_isa_mapirq(sp, irq));
+
+ return (sp->sc->chip->func_intr_way(sp, pcic_iw_pci));
+}
+
static device_method_t pcic_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pcic_pci_probe),
diff --git a/sys/pccard/pcic_pci.h b/sys/pccard/pcic_pci.h
index 928f4786e690..38a9c86bfbbb 100644
--- a/sys/pccard/pcic_pci.h
+++ b/sys/pccard/pcic_pci.h
@@ -91,6 +91,13 @@
#define TI113X_ExCA_IO_OFFSET1 0x38 /* Offset of I/O window */
#define TI113X_ExCA_MEM_WINDOW_PAGE 0x3C /* Memory Window Page */
+/*
+ * Ricoh R5C47[5678] parts have these registers. Maybe the 46x also use
+ * them, but I can't find out for sure without datasheets...
+ */
+#define R5C47X_MISC_CONTROL_REGISTER_2 0xa0
+#define R5C47X_MCR2_CSC_TO_INTX_DISABLE 0x0010 /* Bit 7 */
+
/* sanpei */
/* For Bridge Control register (CB_PCI_BRIDGE_CTRL) */
@@ -140,12 +147,14 @@
#define CB_SOCKET_MASK 0x04
#define CB_SOCKET_STATE 0x08
#define CB_SOCKET_FORCE 0x0c
-#define CB_SOCKET_CONTROL 0x10
-#define CB_SOCKET_POWER 0x14
+#define CB_SOCKET_POWER 0x10
#define CB_EXCA_OFFSET 0x800 /* Offset for ExCA registers */
#define CB_SE_CD 0x6 /* Socket Event Card detect */
+#define CB_SE_POWER 0x8
+
#define CB_SM_CD 0x6 /* Socket MASK Card detect */
+#define CB_SM_POWER 0x8
#define CB_SS_CARDSTS 0x00000001 /* Card Status Change */
#define CB_SS_CD1 0x00000002 /* Card Detect 1 */
@@ -166,3 +175,16 @@
#define CB_SS_3VSOCK 0x20000000 /* 3.3 V Socket */
#define CB_SS_XVSOCK 0x40000000 /* X.X V Socket */
#define CB_SS_YVSOCK 0x80000000 /* Y.Y V Socket */
+
+#define CB_SP_CLKSTOP 0x80 /* Cardbus clock stop protocol */
+#define CB_SP_VCC_0V 0x00
+#define CB_SP_VCC_5V 0x20
+#define CB_SP_VCC_3V 0x30
+#define CB_SP_VCC_XV 0x40
+#define CB_SP_VCC_YV 0x50
+#define CB_SP_VPP_0V 0x00
+#define CB_SP_VPP_12V 0x01
+#define CB_SP_VPP_5V 0x02
+#define CB_SP_VPP_3V 0x03
+#define CB_SP_VPP_XV 0x04
+#define CB_SP_VPP_YV 0x05
diff --git a/sys/pccard/pcicvar.h b/sys/pccard/pcicvar.h
index 04626efb9d67..154860df269c 100644
--- a/sys/pccard/pcicvar.h
+++ b/sys/pccard/pcicvar.h
@@ -37,8 +37,6 @@ struct pcic_slot {
void (*putb)(struct pcic_slot *, int, u_int8_t);
bus_space_tag_t bst;
bus_space_handle_t bsh;
- driver_intr_t *intr;
- void *argp;
};
enum pcic_intr_way { pcic_iw_isa = 1, pcic_iw_pci = 2 };
@@ -47,12 +45,14 @@ struct pcic_softc
{
u_int32_t slotmask;/* Mask of valid slots */
u_int32_t flags; /* Interesting flags */
-#define PCIC_AB_POWER 0x00000001 /* Use old A/B step power */
-#define PCIC_DF_POWER 0x00000002 /* Uses DF step regs */
-#define PCIC_PD_POWER 0x00000004 /* Uses CL-PD regs */
-#define PCIC_VG_POWER 0x00000008 /* Uses VG power regs */
-#define PCIC_KING_POWER 0x00000010 /* Uses IBM KING regs */
-#define PCIC_RICOH_POWER 0x0000020 /* Uses the ricoh power regs */
+#define PCIC_AB_POWER 0x00000001 /* Use old A/B step power */
+#define PCIC_DF_POWER 0x00000002 /* Uses DF step regs */
+#define PCIC_PD_POWER 0x00000004 /* Uses CL-PD regs */
+#define PCIC_VG_POWER 0x00000008 /* Uses VG power regs */
+#define PCIC_KING_POWER 0x00000010 /* Uses IBM KING regs */
+#define PCIC_RICOH_POWER 0x00000020 /* Uses the ricoh power regs */
+#define PCIC_CARDBUS_POWER 0x00000040 /* Cardbus power regs */
+
enum pcic_intr_way csc_route; /* How to route csc interrupts */
enum pcic_intr_way func_route; /* How to route function ints */
int iorid; /* Rid of I/O region */
@@ -70,6 +70,19 @@ struct pcic_softc
int cd_pending; /* debounce timeout active */
int cd_present; /* debounced card-present state */
struct callout_handle cd_ch; /* handle for pcic_cd_insert */
+ struct pcic_chip *chip;
+};
+
+typedef int (pcic_intr_way_t)(struct pcic_slot *, enum pcic_intr_way);
+typedef int (pcic_intr_mapirq_t)(struct pcic_slot *, int irq);
+typedef void (pcic_init_t)(device_t);
+
+struct pcic_chip
+{
+ pcic_intr_way_t *func_intr_way;
+ pcic_intr_way_t *csc_intr_way;
+ pcic_intr_mapirq_t *map_irq;
+ pcic_init_t *init;
};
extern devclass_t pcic_devclass;
@@ -92,6 +105,7 @@ int pcic_get_res_flags(device_t bus, device_t child, int restype, int rid,
unsigned char pcic_getb_io(struct pcic_slot *sp, int reg);
driver_intr_t pcic_isa_intr;
int pcic_isa_intr1(void *);
+pcic_intr_mapirq_t pcic_isa_mapirq;
void pcic_putb_io(struct pcic_slot *sp, int reg, unsigned char val);
int pcic_set_memory_offset(device_t bus, device_t child, int rid,
u_int32_t offset