]> Zhao Yanbai Git Server - minix.git/commitdiff
Initial version of Cardbus support with the TI1225 Cardbus controler.
authorPhilip Homburg <philip@cs.vu.nl>
Thu, 12 Jan 2006 14:47:48 +0000 (14:47 +0000)
committerPhilip Homburg <philip@cs.vu.nl>
Thu, 12 Jan 2006 14:47:48 +0000 (14:47 +0000)
drivers/Makefile
drivers/ti1225/Makefile [new file with mode: 0644]
drivers/ti1225/i82365.h [new file with mode: 0644]
drivers/ti1225/ti1225.c [new file with mode: 0644]
drivers/ti1225/ti1225.h [new file with mode: 0644]

index 29431b9347451df4cd6523cfacd37b971a264949..218ed63eb5bd9b27c348be94493ed325fa59fddb 100644 (file)
@@ -32,6 +32,7 @@ all install depend clean:
        cd ./sb16 && $(MAKE) $@
        cd ./lance && $(MAKE) $@
        cd ./pci && $(MAKE) $@
+       cd ./ti1225 && $(MAKE) $@
 
 image:
        cd ./libdriver && $(MAKE) build
diff --git a/drivers/ti1225/Makefile b/drivers/ti1225/Makefile
new file mode 100644 (file)
index 0000000..7d511ba
--- /dev/null
@@ -0,0 +1,40 @@
+# Makefile for the Texas Instruments PCI1225 PC Card controller driver (ti1225)
+DRIVER = ti1225
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+CC =   exec cc
+CFLAGS = -I$i
+LDFLAGS = -i 
+LIBS = -lsys -lsysutil -ltimers
+
+OBJ = ti1225.o
+
+# build local binary
+all build:     $(DRIVER)
+$(DRIVER):     $(OBJ) 
+       $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+       install -S 4096 $(DRIVER)
+
+# install with other drivers
+install:       /usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):   $(DRIVER)
+       install -o root -cs $? $@
+
+# clean up local files
+clean:
+       rm -f *.o *.bak $(DRIVER)
+
+depend: 
+       /usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
diff --git a/drivers/ti1225/i82365.h b/drivers/ti1225/i82365.h
new file mode 100644 (file)
index 0000000..09bfd54
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+i82365.h
+
+Created:       May 1995 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+#ifndef I82365_H
+#define I82365_H
+
+/* The default I/O ports used by a i82365 are the following: */
+#define I365_INDEX     0x3E0
+#define I365_DATA      0x3E1
+
+/* The index register is used to select one of the following registers: */
+#define I365_REVISION          0x00    /* IDREG */
+#define                I365R_ID_MASK           0xC0
+#define                        I365R_ID_IO             0x00
+#define                        I365R_ID_MEM            0x40
+#define                        I365R_ID_MEM_IO         0x80
+#define                I365R_RES_MASK          0x30
+#define                I365R_REV_MASK          0x0F
+
+#define I365_IF_STAT           0x01    /* ISTAT */
+#define                        I365IS_GPI              0x80
+#define                        CL6722IS_VPPVALID       0x80
+#define                        I365IS_POWER            0x40
+#define                        I365IS_READY            0x20
+#define                        I365IS_WRTPROT          0x10
+#define                I365IS_CARD_MASK        0x0C
+#define                        I365IS_CARD_ABSENT      0x00
+#define                        I365IS_CARD_PART_0      0x04
+#define                        I365IS_CARD_PART_1      0x08
+#define                        I365IS_CARD_PRESENT     0x0C
+#define                I365IS_BAT_MASK         0x03
+#define                        I365IS_BAT_LOST_0       0x00
+#define                        I365IS_BAT_LOW          0x01
+#define                        I365IS_BAT_LOST_1       0x02
+#define                        I365IS_BAT_OKAY         0x03
+
+#define I365_PWR_CTL           0x02    /* PCTRL */
+#define                I365PC_CARD_EN          0x80
+#define                        I365PC_NORESET          0x40
+#define                        CL6722PC_COMPAT_0       0x40
+#define                I365PC_AUTO_PWR         0x20
+#define                        I365PC_Vcc_MASK         0x18
+#define                                I365PC_Vcc_NC           0x00
+#define                                I365PC_Vcc_Reserved     0x08
+#define                                I365PC_Vcc_5            0x10
+#define                                I365PC_Vcc_33           0x18
+#define                CL6722PC_Vcc_PWR        0x10
+#define                CL6722PC_COMPAT_1       0x08
+#define        I365PC_Vpp_MASK         0x03
+#define                I365PC_Vpp_NC           0x00
+#define                CL6722PC_Vpp_ZERO_0     0x00
+#define                I365PC_Vpp_5            0x01
+#define                CL6722PC_Vpp_Vcc        0x01
+#define                I365PC_Vpp_12           0x02
+#define                I365PC_Vpp_Reserved     0x03
+#define                CL6722PC_Vpp_ZERO_1     0x03
+
+#define I365_INT_GEN_CTL       0x03
+#define                I365IGC_RING_IND        0x80
+#define                I365IGC_RESET           0x40
+#define                I365IGC_CARD_IS_IO      0x20
+#define                I365IGC_EN_MNG_INT      0x10
+#define        I365IGC_IRQ_MASK        0x0F
+
+#define I365_CRD_STAT_CHG      0x04    /* CSTCH */
+#define                I365CSC_GPI             0x10
+#define                I365CSC_CARD_DETECT     0x08
+#define                I365CSC_READY           0x04
+#define                I365CSC_BAT_WARN        0x02
+#define                I365CSC_BAT_DEAD        0x01
+
+#define I365_MNG_INT_CONF      0x05
+#define                I365MIC_IRQ_MASK        0xF0
+#define                I365MIC_CARD_DETECT     0x08
+#define                I365MIC_READY           0x04
+#define                I365MIC_BAT_WARN        0x02
+#define                I365MIC_BAT_DEAD        0x01
+
+#define I365_MAP_ENABLE                0x06    /* ADWEN */
+#define                I365ME_IO_MAP_0         0x40
+#define                I365ME_MEM_MAP_0        0x01
+
+#define I365_IO_WND_CTL                0x07
+#define                I365IWC_AUTO_1          0x80
+#define                CL6722IWC_TIMING_1      0x80
+#define                I365IWC_0WS_1           0x40
+#define                I365IWC_AUTO_SIZE_1     0x20
+#define                I365IWC_IO_SIZE_1       0x10
+#define                I365IWC_WAIT_0          0x08
+#define                I365IWC_0WS_0           0x04
+#define                CL6722IWC_TIMING_0      0x08
+#define                I365IWC_AUTO_SIZE_0     0x02
+#define                I365IWC_IO_SIZE_0       0x01
+
+#define I365_IO_0_START_LOW    0x08
+#define I365_IO_0_START_HIGH   0x09
+#define I365_IO_0_END_LOW      0x0A
+#define I365_IO_0_END_HIGH     0x0B
+#define I365_IO_1_START_LOW    0x0C
+#define I365_IO_1_START_HIGH   0x0D
+#define I365_IO_1_END_LOW      0x0E
+#define I365_IO_1_END_HIGH     0x0F
+
+#define I365_MEM_0_START_LOW   0x10
+#define I365_MEM_0_START_HIGH  0x11
+#define I365_MEM_0_END_LOW     0x12
+#define I365_MEM_0_END_HIGH    0x13
+#define I365_MEM_0_OFF_LOW     0x14
+#define I365_MEM_0_OFF_HIGH    0x15
+
+#define CL6722_MISC_CTL_1      0x16
+#define CL6722_FIFO_CTL                0x17
+
+#define I365_MEM_1_START_LOW   0x18
+#define I365_MEM_1_START_HIGH  0x19
+#define I365_MEM_1_END_LOW     0x1A
+#define I365_MEM_1_END_HIGH    0x1B
+#define I365_MEM_1_OFF_LOW     0x1C
+#define I365_MEM_1_OFF_HIGH    0x1D
+
+#define CL6722_MISC_CTL_2      0x1E
+#define CL6722_CHIP_INFO       0x1F
+#define                CL6722CI_ID_MASK        0xC0
+
+#define I365_MEM_2_START_LOW   0x20
+#define I365_MEM_2_START_HIGH  0x21
+#define I365_MEM_2_END_LOW     0x22
+#define I365_MEM_2_END_HIGH    0x23
+#define I365_MEM_2_OFF_LOW     0x24
+#define I365_MEM_2_OFF_HIGH    0x25
+
+#define CL6722_ATA_CONTROL     0x26    /* CPAGE */
+#define I365_RESERVED          0x27
+
+#define I365_MEM_3_START_LOW   0x28
+#define I365_MEM_3_START_HIGH  0x29
+#define I365_MEM_3_END_LOW     0x2A
+#define I365_MEM_3_END_HIGH    0x2B
+#define I365_MEM_3_OFF_LOW     0x2C
+#define I365_MEM_3_OFF_HIGH    0x2D
+
+#define CL6722_EXT_INDEX       0x2E    /* CSCTRL */
+#define CL6722_EXT_DATA                0x2F
+
+#define I365_MEM_4_START_LOW   0x30
+#define I365_MEM_4_START_HIGH  0x31
+#define I365_MEM_4_END_LOW     0x32
+#define I365_MEM_4_END_HIGH    0x33
+#define I365_MEM_4_OFF_LOW     0x34
+#define I365_MEM_4_OFF_HIGH    0x35
+
+#define CL6722_IO_0_OFF_LOW    0x36
+#define CL6722_IO_0_OFF_HIGH   0x37
+#define CL6722_IO_1_OFF_LOW    0x38
+#define CL6722_IO_1_OFF_HIGH   0x39
+
+#define I365_SETUP_TIM_0       0x3A
+#define I365_CMD_TIM_0         0x3B
+#define I365_RECOV_TIM_0       0x3C
+#define I365_SETUP_TIM_1       0x3D
+#define I365_CMD_TIM_1         0x3E
+#define I365_RECOV_TIM_1       0x3F
+
+#endif /* I82365_H */
diff --git a/drivers/ti1225/ti1225.c b/drivers/ti1225/ti1225.c
new file mode 100644 (file)
index 0000000..225169c
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ti1225.c
+
+Created:       Dec 2005 by Philip Homburg
+*/
+
+#include "../drivers.h"
+#include <ibm/pci.h>
+#include <sys/vm.h>
+
+#include "ti1225.h"
+#include "i82365.h"
+
+/* The use of interrupts is not yet ready for prime time */
+#define USE_INTS       0
+
+#define MICROS_TO_TICKS(m)  (((m)*HZ/1000000)+1)
+
+#define NR_PORTS 2
+
+PRIVATE struct port
+{
+       unsigned p_flags;
+       int p_devind;
+       u8_t p_cb_busnr;
+       u16_t p_exca_port;
+#if USE_INTS
+       int p_irq;
+       int p_hook;
+#endif
+       char *base_ptr;
+       volatile struct csr *csr_ptr;
+
+       char buffer[2*PAGE_SIZE];
+} ports[NR_PORTS];
+
+#define PF_PRESENT     1
+
+struct pcitab
+{
+       u16_t vid;
+       u16_t did;
+       int checkclass;
+};
+
+PRIVATE struct pcitab pcitab_ti[]=
+{
+       { 0x104C, 0xAC1C, 0 },          /* TI PCI1225 */
+
+       { 0x0000, 0x0000, 0 }
+};
+PRIVATE char *progname;
+PRIVATE int debug;
+
+FORWARD _PROTOTYPE( void init, (void)                                  );
+FORWARD _PROTOTYPE( void hw_init, (struct port *pp)                    );
+FORWARD _PROTOTYPE( void map_regs, (struct port *pp, u32_t base)       );
+FORWARD _PROTOTYPE( void do_int, (struct port *pp)                     );
+FORWARD _PROTOTYPE( u8_t read_exca, (struct port *pp, int socket, int reg) );
+FORWARD _PROTOTYPE( void do_outb, (port_t port, u8_t value)            );
+FORWARD _PROTOTYPE( u8_t do_inb, (port_t port)                         );
+FORWARD _PROTOTYPE( void micro_delay, (unsigned long usecs)            );
+
+int main(int argc, char *argv[])
+{
+       int c, r;
+       message m;
+
+       (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
+
+       debug= 0;
+       while (c= getopt(argc, argv, "d?"), c != -1)
+       {
+               switch(c)
+               {
+               case '?': panic("ti1225", "Usage: ti1225 [-d]", NO_NUM);
+               case 'd': debug++; break;
+               default: panic("ti1225", "getopt failed", NO_NUM);
+               }
+       }
+
+       init();
+
+       for (;;)
+       {
+               r= receive(ANY, &m);
+               if (r != OK)
+                       panic("ti1225", "receive failed", r);
+               printf("ti1225: got message %u from %d\n",
+                       m.m_type, m.m_source);
+       }
+       return 0;
+}
+
+PRIVATE void init()
+{
+       int i, r, first, devind, port;
+       u16_t vid, did;
+
+       pci_init1(progname);
+
+       first= 1;
+       port= 0;
+       for (;;)
+       {
+               if (first)
+               {
+                       first= 0;
+                       r= pci_first_dev(&devind, &vid, &did);
+               }
+               else
+                       r= pci_next_dev(&devind, &vid, &did);
+               if (r != 1)
+                       break;
+
+               for (i= 0; pcitab_ti[i].vid != 0; i++)
+               {
+                       if (pcitab_ti[i].vid != vid)
+                               continue;
+                       if (pcitab_ti[i].did != did)
+                               continue;
+                       if (pcitab_ti[i].checkclass)
+                       {
+                               panic("ti1225",
+                               "fxp_probe: class check not implemented",
+                                       NO_NUM);
+                       }
+                       break;
+               }
+               if (pcitab_ti[i].vid == 0)
+                       continue;
+
+               pci_reserve(devind);
+
+               if (debug)
+                       printf("ti1225: found device %04x/%04x\n", vid, did);
+               ports[port].p_devind= devind;
+               ports[port].p_flags |= PF_PRESENT;
+               port++;
+               if (port >= NR_PORTS)
+                       break;
+       }
+
+       for (i= 0; i<NR_PORTS; i++)
+       {
+               if (!(ports[i].p_flags & PF_PRESENT))
+                       continue;
+               hw_init(&ports[i]);
+       }
+}
+
+PRIVATE void hw_init(pp)
+struct port *pp;
+{
+       int i, r, devind, irq, socket;
+       u8_t v8;
+       u16_t v16;
+       u32_t v32;
+
+       devind= pp->p_devind;
+       if (debug)
+               printf("hw_init: devind = %d\n", devind);
+
+       if (debug)
+       {
+               v16= pci_attr_r16(devind, PCI_CR);
+               printf("ti1225: command register 0x%x\n", v16);
+       }
+
+       v32= pci_attr_r32(devind, TI_CB_BASEADDR);
+       if (debug)
+               printf("ti1225: Cardbus/ExCA base address 0x%x\n", v32);
+       map_regs(pp, v32);
+       pp->csr_ptr= (struct csr *)pp->base_ptr;
+
+       if (debug)
+       {
+               v8= pci_attr_r8(devind, TI_PCI_BUS_NR);
+               printf("ti1225: PCI bus number %d\n", v8);
+       }
+       v8= pci_attr_r8(devind, TI_CB_BUS_NR);
+       pp->p_cb_busnr= v8;
+       if (debug)
+       {
+               printf("ti1225: CardBus bus number %d\n", v8);
+               v8= pci_attr_r8(devind, TI_SO_BUS_NR);
+               printf("ti1225: Subordinate bus number %d\n", v8);
+       }
+
+#if USE_INTS
+       irq= pci_attr_r8(devind, PCI_ILR);
+       pp->p_irq= irq;
+       printf("ti1225 using IRQ %d\n", irq);
+#endif
+
+       v32= pci_attr_r32(devind, TI_LEGACY_BA);
+       v32 &= ~1;
+       if (debug)
+       {
+               printf("ti1225: PC Card 16-bit legacy-mode base address 0x%x\n",
+                       v32);
+       }
+
+       if (v32 == 0)
+               panic("ti1225", "bad lagacy-mode base address 0x%x\n", v32);
+       pp->p_exca_port= v32;
+
+       if (debug)
+       {
+               v32= pci_attr_r32(devind, TI_MF_ROUTE);
+               printf("ti1225: Multifunction routing 0x%08x\n", v32);
+       }
+
+#if USE_INTS
+       pp->p_hook = pp->p_irq;
+       r= sys_irqsetpolicy(pp->p_irq, 0, &pp->p_hook);
+       if (r != OK)
+               panic("ti1225","sys_irqsetpolicy failed", r);
+#endif
+
+       /* Clear CBB_BC_INTEXCA */
+       v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
+       if (debug)
+               printf("ti1225: Bridge control 0x%04x\n", v16);
+       v16 &= ~CBB_BC_INTEXCA;
+       pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
+
+       if (debug)
+       {
+               v32= pci_attr_r32(devind, TI_SYSCTRL);
+               printf("ti1225: System Control Register 0x%08x\n", v32);
+
+               v8= pci_attr_r8(devind, TI_CARD_CTRL);
+               printf("ti1225: Card Control 0x%02x\n", v8);
+
+               v8= pci_attr_r8(devind, TI_DEV_CTRL);
+               printf("ti1225: Device Control 0x%02x\n", v8);
+       }
+
+       /* Enable socket interrupts */
+       pp->csr_ptr->csr_mask |= CM_PWRMASK | CM_CDMASK | CM_CSTSMASK;
+
+       do_int(pp);
+
+#if USE_INTS
+       r= sys_irqenable(&pp->p_hook);
+       if (r != OK)
+               panic("ti1225","unable enable interrupts", r);
+#endif
+}
+
+PRIVATE void map_regs(pp, base)
+struct port *pp;
+u32_t base;
+{
+       int r;
+       vir_bytes buf_base;
+
+       buf_base= (vir_bytes)pp->buffer;
+       if (buf_base % PAGE_SIZE)
+               buf_base += PAGE_SIZE-(buf_base % PAGE_SIZE);
+       pp->base_ptr= (char *)buf_base;
+       if (debug)
+       {
+               printf("ti1225: map_regs: using %p for %p\n",
+                       pp->base_ptr, pp->buffer);
+       }
+
+       /* Clear low order bits in base */
+       base &= ~(u32_t)0xF;
+
+       r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)pp->base_ptr,
+               PAGE_SIZE, (phys_bytes)base);
+       if (r != OK)
+               panic("ti1225", "map_regs: sys_vm_map failed", r);
+}
+
+PRIVATE void do_int(pp)
+struct port *pp;
+{
+       int i, r, devind, vcc_5v, vcc_3v, vcc_Xv, vcc_Yv,
+               socket_5v, socket_3v, socket_Xv, socket_Yv;
+       clock_t t0, t1;
+       u32_t csr_event, csr_present, csr_control;
+       u8_t v8;
+       u16_t v16;
+
+       devind= pp->p_devind;
+       v8= pci_attr_r8(devind, TI_CARD_CTRL);
+       if (v8 & TI_CCR_IFG)
+       {
+               printf("ti1225: got functional interrupt\n", v8);
+               pci_attr_w8(devind, TI_CARD_CTRL, v8);
+       }
+
+       if (debug)
+       {
+               printf("Socket event: 0x%x\n", pp->csr_ptr->csr_event);
+               printf("Socket mask: 0x%x\n", pp->csr_ptr->csr_mask);
+       }
+
+       csr_present= pp->csr_ptr->csr_present;
+       csr_control= pp->csr_ptr->csr_control;
+
+       if ((csr_present & (CP_CDETECT1|CP_CDETECT2)) != 0)
+       {
+               if (debug)
+                       printf("do_int: no card present\n");
+               return;
+       }
+       if (csr_present & CP_BADVCCREQ)
+       {
+               printf("do_int: Bad Vcc request\n");
+               /* return; */
+       }
+       if (csr_present & CP_DATALOST)
+       {
+               /* Do we care? */
+               if (debug)
+                       printf("do_int: Data lost\n");
+               /* return; */
+       }
+       if (csr_present & CP_NOTACARD)
+       {
+               printf("do_int: Not a card\n");
+               return;
+       }
+       if (debug)
+       {
+               if (csr_present & CP_CBCARD)
+                       printf("do_int: Cardbus card detected\n");
+               if (csr_present & CP_16BITCARD)
+                       printf("do_int: 16-bit card detected\n");
+       }
+       if (csr_present & CP_PWRCYCLE)
+       {
+               if (debug)
+                       printf("do_int: powered up\n");
+               return;
+       }
+       vcc_5v= !!(csr_present & CP_5VCARD);
+       vcc_3v= !!(csr_present & CP_3VCARD);
+       vcc_Xv= !!(csr_present & CP_XVCARD);
+       vcc_Yv= !!(csr_present & CP_YVCARD);
+       if (debug)
+       {
+               printf("do_int: card supports:%s%s%s%s\n",
+                       vcc_5v ? " 5V" : "", vcc_3v ? " 3V" : "",
+                       vcc_Xv ? " X.X V" : "", vcc_Yv ? " Y.Y V" : "");
+       }
+       socket_5v= !!(csr_present & CP_5VSOCKET);
+       socket_3v= !!(csr_present & CP_3VSOCKET);
+       socket_Xv= !!(csr_present & CP_XVSOCKET);
+       socket_Yv= !!(csr_present & CP_YVSOCKET);
+       if (debug)
+       {
+               printf("do_int: socket supports:%s%s%s%s\n",
+                       socket_5v ? " 5V" : "", socket_3v ? " 3V" : "",
+                       socket_Xv ? " X.X V" : "", socket_Yv ? " Y.Y V" : "");
+       }
+       if (vcc_5v && socket_5v)
+       {
+               csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_5V;
+               pp->csr_ptr->csr_control= csr_control;
+               if (debug)
+                       printf("do_int: applying 5V\n");
+       }
+       else if (vcc_3v && socket_3v)
+       {
+               csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_3V;
+               pp->csr_ptr->csr_control= csr_control;
+               if (debug)
+                       printf("do_int: applying 3V\n");
+       }
+       else if (vcc_Xv && socket_Xv)
+       {
+               csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_XV;
+               pp->csr_ptr->csr_control= csr_control;
+               printf("do_int: applying X.X V\n");
+       }
+       else if (vcc_Yv && socket_Yv)
+       {
+               csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_YV;
+               pp->csr_ptr->csr_control= csr_control;
+               printf("do_int: applying Y.Y V\n");
+       }
+       else
+       {
+               printf("do_int: socket and card are not compatible\n");
+               return;
+       }
+
+       csr_event= pp->csr_ptr->csr_event;
+       if (csr_event)
+       {
+               if (debug)
+                       printf("clearing socket event\n");
+               pp->csr_ptr->csr_event= csr_event;
+               if (debug)
+               {
+                       printf("Socket event (cleared): 0x%x\n",
+                               pp->csr_ptr->csr_event);
+               }
+       }
+
+       devind= pp->p_devind;
+       v8= pci_attr_r8(devind, TI_CARD_CTRL);
+       if (v8 & TI_CCR_IFG)
+       {
+               printf("ti1225: got functional interrupt\n", v8);
+               pci_attr_w8(devind, TI_CARD_CTRL, v8);
+       }
+
+       if (debug)
+       {
+               v8= pci_attr_r8(devind, TI_CARD_CTRL);
+               printf("TI_CARD_CTRL: 0x%02x\n", v8);
+       }
+
+       getuptime(&t0);
+       do {
+               csr_present= pp->csr_ptr->csr_present;
+               if (csr_present & CP_PWRCYCLE)
+                       break;
+       } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
+
+       if (!(csr_present & CP_PWRCYCLE))
+       {
+               printf("do_int: not powered up?\n");
+               return;
+       }
+
+       /* Reset device */
+       v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
+       v16 |= CBB_BC_CRST;
+       pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
+
+       /* Wait one microsecond. Is this correct? What are the specs? */
+       micro_delay(1);
+
+       /* Clear CBB_BC_CRST */
+       v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
+       v16 &= ~CBB_BC_CRST;
+       pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
+
+       /* Wait one microsecond after clearing the reset line. Is this
+        * correct? What are the specs?
+        */
+       micro_delay(1);
+
+       pci_rescan_bus(pp->p_cb_busnr);
+
+#if USE_INTS
+       r= sys_irqenable(&pp->p_hook);
+       if (r != OK)
+               panic("ti1225","unable enable interrupts", r);
+#endif
+
+}
+
+PRIVATE u8_t read_exca(pp, socket, reg)
+struct port *pp;
+int socket;
+int reg;
+{
+       u16_t port;
+
+       port= pp->p_exca_port;
+       if (port == 0)
+               panic("ti1225", "read_exca: bad port", NO_NUM);
+       do_outb(port, socket * 0x40 + reg);
+       return do_inb(port+1);
+}
+
+PRIVATE u8_t do_inb(port_t port)
+{
+       int r;
+       u32_t value;
+
+       r= sys_inb(port, &value);
+       if (r != OK)
+               panic("ti1225","sys_inb failed", r);
+       return value;
+}
+
+PRIVATE void do_outb(port_t port, u8_t value)
+{
+       int r;
+
+       r= sys_outb(port, value);
+       if (r != OK)
+               panic("ti1225","sys_outb failed", r);
+}
+
+PRIVATE void micro_delay(unsigned long usecs)
+{
+       tickdelay(MICROS_TO_TICKS(usecs));
+}
+
diff --git a/drivers/ti1225/ti1225.h b/drivers/ti1225/ti1225.h
new file mode 100644 (file)
index 0000000..261adf2
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ti1225.h
+
+Created:       Dec 2005 by Philip Homburg
+*/
+
+/* PCI attribute space registers */
+#define TI_CB_BASEADDR 0x10
+#define TI_PCI_BUS_NR  0x18
+#define TI_CB_BUS_NR   0x19
+#define TI_SO_BUS_NR   0x1A
+#define TI_LEGACY_BA   0x44
+#define TI_SYSCTRL     0x80
+#define TI_MF_ROUTE    0x8C
+#define TI_CARD_CTRL   0x91
+#define                TI_CCR_IFG      0x01
+#define TI_DEV_CTRL    0x92
+
+/* CardBus Socket Registers */
+struct csr
+{
+/*00*/ u32_t csr_event;
+/*04*/ u32_t csr_mask;
+/*08*/ u32_t csr_present;
+/*0C*/ u32_t csr_force_event;
+/*10*/ u32_t csr_control;
+/*14*/ u32_t csr_res0;
+/*18*/ u32_t csr_res1;
+/*1C*/ u32_t csr_res2;
+/*20*/ u32_t csr_power;
+};
+
+/* csr_mask */
+#define CM_PWRMASK     0x00000008
+#define CM_CDMASK      0x00000006
+#define CM_CSTSMASK    0x00000001
+
+/* csr_present */
+#define CP_YVSOCKET    0x80000000
+#define CP_XVSOCKET    0x40000000
+#define CP_3VSOCKET    0x20000000
+#define CP_5VSOCKET    0x10000000
+#define CP_YVCARD      0x00002000
+#define CP_XVCARD      0x00001000
+#define CP_3VCARD      0x00000800
+#define CP_5VCARD      0x00000400
+#define CP_BADVCCREQ   0x00000200
+#define CP_DATALOST    0x00000100
+#define CP_NOTACARD    0x00000080
+#define CP_IREQCINT    0x00000040
+#define CP_CBCARD      0x00000020
+#define CP_16BITCARD   0x00000010
+#define CP_PWRCYCLE    0x00000008
+#define CP_CDETECT2    0x00000004
+#define CP_CDETECT1    0x00000002
+#define CP_CARDSTS     0x00000001
+
+/* csr_control */
+#define CC_VCCCTRL     0x00000070
+#define        CC_VCC_OFF      0x00000000
+#define        CC_VCC_5V       0x00000020
+#define        CC_VCC_3V       0x00000030
+#define        CC_VCC_XV       0x00000040
+#define        CC_VCC_YV       0x00000050
+#define CC_VPPCTRL     0x00000007
+#define        CC_VPP_OFF      0x00000000
+#define        CC_VPP_12V      0x00000001
+#define        CC_VPP_5V       0x00000002
+#define        CC_VPP_3V       0x00000003
+#define        CC_VPP_XV       0x00000004
+#define        CC_VPP_YV       0x00000005