diff --git a/sys/pccard/i82365.h b/sys/pccard/i82365.h index 633923f8675..41afe8c82e1 100644 --- a/sys/pccard/i82365.h +++ b/sys/pccard/i82365.h @@ -138,7 +138,7 @@ #define PCIC_IOCARD 0x20 #define PCIC_MEMCARD 0x00 #define PCIC_CARDRESET 0x40 /* Card reset 0 = Reset, 1 = Normal */ -#define PCIC_INTR_ENA 0x10 /* Interrupt enable */ +#define PCIC_INTR_ENA 0x10 /* PCI CSC Interrupt enable */ /* For the Card Status Change register (PCIC_STAT_CHG) */ #define PCIC_CDTCH 0x08 /* Card Detect Change */ @@ -146,6 +146,14 @@ #define PCIC_BATWRN 0x02 /* Battery Warning */ #define PCIC_BATDED 0x01 /* Battery Dead */ +/* For the Card status change interrupt PCIC_STAT_INT */ +#define PCIC_CSCSELECT 0xf0 /* CSCSELECT */ +#define PCIC_SI_IRQ_SHIFT 4 +#define PCIC_CDEN 0x8 +#define PCIC_READYEN 0x4 +#define PCIC_BATWARNEN 0x2 +#define PCIC_BATDEADEN 0x1 + /* * For the Address Window Enable Register (PCIC_ADDRWINE) * The lower 6 bits contain enable bits for the memory diff --git a/sys/pccard/pcic.c b/sys/pccard/pcic.c index 2b2b4daec7a..a716e0a062a 100644 --- a/sys/pccard/pcic.c +++ b/sys/pccard/pcic.c @@ -308,13 +308,34 @@ pcic_do_mgt_irq(struct pcic_slot *sp, int irq) u_int32_t reg; if (sp->sc->csc_route == pci_parallel) { + /* Do the PCI side of things: Enable the Card Change int */ reg = CB_SM_CD; bus_space_write_4(sp->bst, sp->bsh, CB_SOCKET_MASK, reg); + /* + * TI Chips need us to set the following. We tell the + * controller to route things via PCI interrupts. Also + * we clear the interrupt number in the STAT_INT register + * as well. The TI-12xx and newer chips require one or the + * other of these to happen, depending on what is set in the + * diagnostic register. I do both on the theory that other + * chips might need one or the other and that no harm will + * come from it. If there is harm, then I'll make it a bit + * in the tables. + */ + pcic_setb(sp, PCIC_INT_GEN, PCIC_INTR_ENA); + pcic_clrb(sp, PCIC_STAT_INT, PCIC_CSCSELECT); } else { /* Management IRQ changes */ + /* + * The PCIC_INTR_ENA bit means either "tie the function + * and csc interrupts together" or "Route csc interrupts + * via PCI" or "Reserved". In any case, we want to clear + * it since we're using ISA interrupts. + */ pcic_clrb(sp, PCIC_INT_GEN, PCIC_INTR_ENA); irq = host_irq_to_pcic(irq); - sp->putb(sp, PCIC_STAT_INT, (irq << 4) | 0x8); + sp->putb(sp, PCIC_STAT_INT, (irq << PCIC_SI_IRQ_SHIFT) | + PCIC_CDEN); } } @@ -629,7 +650,7 @@ pcic_disable(struct slot *slt) struct pcic_slot *sp = slt->cdata; sp->putb(sp, PCIC_INT_GEN, 0); - sp->putb(sp, PCIC_POWER, 0); +/* sp->putb(sp, PCIC_POWER, 0); */ } /* diff --git a/sys/pccard/pcic_pci.c b/sys/pccard/pcic_pci.c index 03145854896..fdb16f9d686 100644 --- a/sys/pccard/pcic_pci.c +++ b/sys/pccard/pcic_pci.c @@ -247,10 +247,10 @@ pcic_pci_pd6832_init(device_t dev) static void pcic_pci_ti_init(device_t dev) { - u_long syscntl,devcntl,cardcntl; - u_int32_t device_id = pci_get_devid(dev); + u_int32_t syscntl, diagctl, devcntl, cardcntl; + u_int32_t device_id = pci_get_devid(dev); struct pcic_softc *sc = device_get_softc(dev); - int ti113x = (device_id == PCI_DEVICE_ID_PCIC_TI1031) || + int ti113x = (device_id == PCI_DEVICE_ID_PCIC_TI1031) || (device_id == PCI_DEVICE_ID_PCIC_TI1130) || (device_id == PCI_DEVICE_ID_PCIC_TI1131); @@ -258,9 +258,12 @@ pcic_pci_ti_init(device_t dev) devcntl = pci_read_config(dev, TI113X_PCI_DEVICE_CONTROL, 1); cardcntl = pci_read_config(dev, TI113X_PCI_CARD_CONTROL, 1); - switch(ti113x){ + switch (ti113x) { case 0 : device_printf(dev, "TI12XX PCI Config Reg: "); + diagctl = pci_read_config(dev, TI12XX_PCI_DIAGNOSTIC, 1); + diagctl |= TI12XX_DIAG_CSC_INTR; + pci_write_config(dev, TI12XX_PCI_DIAGNOSTIC, diagctl, 1); break; case 1 : device_printf(dev, "TI113X PCI Config Reg: "); @@ -305,7 +308,7 @@ pcic_pci_ti_init(device_t dev) printf("[speaker enable]"); if (syscntl & TI113X_SYSCNTL_PWRSAVINGS) printf("[pwr save]"); - switch (devcntl & TI113X_DEVCNTL_INTR_MASK) { + switch(devcntl & TI113X_DEVCNTL_INTR_MASK){ case TI113X_DEVCNTL_INTR_ISA : printf("[CSC parallel isa irq]"); break; @@ -436,10 +439,21 @@ pcic_pci_intr(void *arg) bus_space_write_4(sp->bst, sp->bsh, 0, 0xffffffff); } + /* + * TI chips also require us to read the old ExCA register for + * card status change when we route CSC via PCI! So, we go ahead + * and read it to clear the bits. Maybe we should check the status + * ala the ISA interrupt handler, but those changes should be caught + * in the CD change. + */ + sp->getb(sp, PCIC_STAT_CHG); + /* Now call children interrupts if any */ stat = bus_space_read_4(sp->bst, sp->bsh, CB_SOCKET_STATE); - if (sp->intr && (stat & CB_SS_CD) == 0) - sp->intr(sp->argp); + if ((stat & CB_SS_CD) == 0) { + if (sp->intr != NULL) + sp->intr(sp->argp); + } } /* diff --git a/sys/pccard/pcic_pci.h b/sys/pccard/pcic_pci.h index 221a8df3d32..1b55716dd5a 100644 --- a/sys/pccard/pcic_pci.h +++ b/sys/pccard/pcic_pci.h @@ -46,6 +46,7 @@ #define TI113X_PCI_CARD_CONTROL 0x91 /* Card Control */ #define TI113X_PCI_DEVICE_CONTROL 0x92 /* Device Control */ #define TI113X_PCI_BUFFER_CONTROL 0x93 /* Buffer Control */ +#define TI12XX_PCI_DIAGNOSTIC 0x93 /* Diagnostic register */ #define TI113X_PCI_SOCKET_DMA0 0x94 /* Socket DMA Register 0 */ #define TI113X_PCI_SOCKET_DMA1 0x98 /* Socket DMA Register 1 */ @@ -80,6 +81,10 @@ #define TI113X_DEVCNTL_INTR_SERIAL 0x04u /* TI12XX specific code */ #define TI12XX_DEVCNTL_INTR_ALLSERIAL 0x06u + +/* Diagnostic register (misnamed) TI12XX_PCI_DIAGNOSTIC == 0x93 */ +#define TI12XX_DIAG_CSC_INTR 0x20 /* see datasheet */ + /* Texas Instruments PCI-1130/1131 CardBus Controller */ #define TI113X_ExCA_IO_OFFSET0 0x36 /* Offset of I/O window */ #define TI113X_ExCA_IO_OFFSET1 0x38 /* Offset of I/O window */