linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Woodhouse <dwmw2@infradead.org>
To: linux-hotplug@vger.kernel.org
Subject: Re: Adding PCMCIA support to the kernel tree -- developers needed.
Date: Sun, 04 Feb 2001 10:53:06 +0000	[thread overview]
Message-ID: <marc-linux-hotplug-98140443518951@msgid-missing> (raw)
In-Reply-To: <marc-linux-hotplug-98118528107653@msgid-missing>

On Sat, 3 Feb 2001, Miles Lane wrote:

> Well, would care to elaborate on what the PCI mess is, exactly?  

Er... I seem to have lied about the patch being attached. 

Index: i82365.c
=================================RCS file: /net/passion/inst/cvs/linux/drivers/pcmcia/Attic/i82365.c,v
retrieving revision 1.1.2.15
diff -u -r1.1.2.15 i82365.c
--- i82365.c	2000/11/17 09:35:49	1.1.2.15
+++ i82365.c	2000/11/19 17:31:07
@@ -142,6 +142,18 @@
 MODULE_PARM(wakeup, "i");
 #endif
 
+#ifdef CONFIG_PCI
+static int pci_irq_list[8] = { 0 };	/* PCI interrupt assignments */
+static int do_pci_probe = 1;		/* Scan for PCI bridges? */
+static int fast_pci = -1;
+static int irq_mode = -1;		/* Override BIOS routing? */
+
+MODULE_PARM(pci_irq_list, "1-8i");
+MODULE_PARM(do_pci_probe, "i");
+MODULE_PARM(fast_pci, "i");
+MODULE_PARM(irq_mode, "i");
+#endif
+
 MODULE_PARM(do_scan, "i");
 MODULE_PARM(poll_interval, "i");
 MODULE_PARM(cycle_time, "i");
@@ -153,11 +165,27 @@
 MODULE_PARM(setup_time, "i");
 MODULE_PARM(cmd_time, "i");
 MODULE_PARM(recov_time, "i");
+#if defined(CONFIG_ISA) && defined(CONFIG_PCI)
+int pci_csc = 1;		/* PCI card status irqs? */
+int pci_int = 1;		/* PCI IO card irqs? */
+MODULE_PARM(pci_csc, "i");
+MODULE_PARM(pci_int, "i");
+#elif defined(CONFIG_ISA) && !defined(CONFIG_PCI)
+#define pci_csc		0
+#define pci_int		0
+#elif !defined(CONFIG_ISA) && defined(CONFIG_PCI)
+#define pci_csc		0
+#define pci_int		1		/* We must use PCI irq's */
+#else
+#error "No bus architectures defined!"
+#endif
 
+
 /*==================================*/
 
 typedef struct cirrus_state_t {
     u_char		misc1, misc2;
+    u_char		ectl1;
     u_char		timer[6];
 } cirrus_state_t;
 
@@ -165,6 +193,17 @@
     u_char		ctl, ema;
 } vg46x_state_t;
 
+typedef struct o2micro_state_t {
+    u_char		mode_a;		/* O2_MODE_A */
+    u_char		mode_b;		/* O2_MODE_B */
+    u_char		mode_c;		/* O2_MODE_C */
+    u_char		mode_d;		/* O2_MODE_D */
+    u_char		mhpg;		/* O2_MHPG_DMA */
+    u_char		fifo;		/* O2_FIFO_ENA */
+    u_char		mode_e;		/* O2_MODE_E */
+} o2micro_state_t;
+
+
 typedef struct socket_info_t {
     u_short		type, flags;
     socket_cap_t	cap;
@@ -176,9 +215,15 @@
 #ifdef CONFIG_PROC_FS
     struct proc_dir_entry *proc;
 #endif
+    u_char		pci_irq_code;
+    u_char		revision;
+#ifdef CONFIG_PCI
+    struct pci_dev	*dev;
+#endif
     union {
 	cirrus_state_t		cirrus;
 	vg46x_state_t		vg46x;
+	o2micro_state_t		o2micro;
     } state;
 } socket_info_t;
 
@@ -216,6 +261,18 @@
     IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469,
     IS_PD6710, IS_PD672X, IS_VT83C469,
 #endif
+#ifdef CONFIG_PCI
+    /*
+     * There are many cards which were supported by the i82365 driver
+     * in the standalone package, but which are not listed here.
+     * This is because they are CardBus-capable and hence now supported
+     * by the Yenta driver.
+     */
+    IS_I82092AA, IS_OM82C092G, 			/* Intel 82092-based */
+    IS_PD6729, IS_PD6730, 			/* Cirrus */
+    IS_OZ6729, IS_OZ6730, 			/* O2Micro  */
+    IS_UNK_PCI
+#endif
 } pcic_id;
 
 /* Flags for classifying groups of controllers */
@@ -251,7 +308,86 @@
     { "Cirrus PD672x", IS_CIRRUS },
     { "VIA VT83C469", IS_CIRRUS|IS_VIA },
 #endif
+#ifdef CONFIG_PCI
+    { "Intel 82092AA", IS_PCI },
+    { "Omega Micro 82C092G", IS_PCI },
+    { "Cirrus PD6729", IS_CIRRUS|IS_PCI },
+    { "Cirrus PD6730", IS_CIRRUS|IS_PCI },
+    { "O2Micro OZ6729", IS_O2MICRO|IS_PCI|IS_VG_PWR },
+    { "O2Micro OZ6730", IS_O2MICRO|IS_PCI|IS_VG_PWR },
+    { "Unknown", IS_PCI|IS_UNKNOWN },
+#endif
+};
+
+#ifdef CONFIG_PCI
+static struct pci_device_id i82365_pci_ids[] = {
+	{	
+		vendor: PCI_VENDOR_ID_INTEL,
+		device: PCI_DEVICE_ID_INTEL_82092AA_0,
+		subvendor: PCI_ANY_ID,
+		subdevice: PCI_ANY_ID,
+		class: 0, class_mask: 0,
+		driver_data: IS_I82092AA
+	}, {
+		vendor: PCI_VENDOR_ID_OMEGA,
+		device: PCI_DEVICE_ID_OMEGA_82C092G,
+		subvendor: PCI_ANY_ID,
+		subdevice: PCI_ANY_ID,
+		class: 0, class_mask: 0,
+		driver_data: IS_OM82C092G
+	}, {
+		vendor: PCI_VENDOR_ID_CIRRUS,
+		device: PCI_DEVICE_ID_CIRRUS_6729,
+		subvendor: PCI_ANY_ID,
+		subdevice: PCI_ANY_ID,
+		class: 0, class_mask: 0,
+		driver_data: IS_PD6729
+	}, {
+		vendor: PCI_VENDOR_ID_CIRRUS,
+		device: PCI_ANY_ID,
+		subvendor: PCI_ANY_ID,
+		subdevice: PCI_ANY_ID,
+		class: PCI_CLASS_BRIDGE_PCMCIA,
+		class_mask: 0xffff,
+		driver_data: IS_PD6730
+	}, {
+		vendor: PCI_VENDOR_ID_O2,
+		device: PCI_DEVICE_ID_O2_6729,
+		subvendor: PCI_ANY_ID,
+		subdevice: PCI_ANY_ID,
+		class: 0, class_mask: 0,
+		driver_data: IS_OZ6729
+	}, {
+		vendor: PCI_VENDOR_ID_O2,
+		device: PCI_DEVICE_ID_O2_6730,
+		subvendor: PCI_ANY_ID,
+		subdevice: PCI_ANY_ID,
+		class: 0, class_mask: 0,
+		driver_data: IS_OZ6730
+	}, {
+		vendor: PCI_ANY_ID,
+		device: PCI_ANY_ID,
+		subvendor: PCI_ANY_ID,
+		subdevice: PCI_ANY_ID,
+		class: PCI_CLASS_BRIDGE_PCMCIA,
+		class_mask: 0xffff,
+		driver_data: IS_UNK_PCI
+	},
+	{ /* Terminating entry */ }
+};
+
+static int i82365_pci_probe(struct pci_dev *dev, const struct pci_device_id *id);
+static void i82365_pci_remove(struct pci_dev *dev);
+
+static struct pci_driver i82365_pci_drv = {
+	name:		"i82365",
+	id_table:	i82365_pci_ids,
+	probe:		i82365_pci_probe,
+	remove:		i82365_pci_remove,
+	suspend:	NULL,
+	resume:		NULL
 };
+#endif
 
 #define PCIC_COUNT	(sizeof(pcic)/sizeof(pcic_t))
 
@@ -315,6 +451,22 @@
     i365_set(sock, reg+1, data >> 8);
 }
 
+#ifdef CONFIG_PCI
+
+static int __init get_pci_irq(u_short s)
+{
+    socket_info_t *t = &socket[s];
+    u8 irq;
+
+    irq = t->dev->irq;
+    if ((irq = 0) && (pci_csc || pci_int))
+	irq = pci_irq_list[t - socket];
+    if (irq >= NR_IRQS) irq = 0;
+    t->cap.pci_irq = irq;
+    return irq;
+}
+
+#endif
 /*===================================
 
     Code to save and restore global state information for Cirrus
@@ -384,6 +536,23 @@
 	if (p->misc2 & PD67_MC2_FREQ_BYPASS)
 	    strcat(buf, " [freq bypass]");
 	}
+#ifdef CONFIG_PCI
+    } else {
+	p->misc1 &= ~PD67_MC1_MEDIA_ENA;
+	p->misc1 &= ~(PD67_MC1_PULSE_MGMT | PD67_MC1_PULSE_IRQ);
+	p->ectl1 &= ~(PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ);
+	flip(p->misc2, PD67_MC2_FAST_PCI, fast_pci);
+	if (p->misc2 & PD67_MC2_IRQ15_RI)
+	    mask &= (t->type = IS_PD6730) ? ~0x0400 : ~0x8000;
+	if ((irq_mode = 1) && get_pci_irq(s)) {
+	    /* Configure PD6729 bridge for PCI interrupts */
+	    p->ectl1 |= PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ;
+	    t->pci_irq_code = 3; /* PCI INTA = "irq 3" */
+	    buf += strlen(buf);
+	    sprintf(buf, " [pci irq %d]", t->cap.pci_irq);
+	    mask = 0;
+	}
+#endif
     }
     if (!(t->flags & IS_VIA)) {
 	if (setup_time >= 0)
@@ -459,7 +628,79 @@
 
 #endif
 
+/*===================================
+
+    Code to save and restore global state information for O2Micro
+    controllers, and to set and report global configuration options.
+    
+===================================*/
+
+#ifdef CONFIG_PCI
+
+static void __init o2micro_get_state(u_short s)
+{
+    o2micro_state_t *p = &socket[s].state.o2micro;
+
+    if (((socket[s].revision & 0xff) = 0x34) || 
+	((socket[s].revision & 0xff) = 0x62)) {
+	p->mode_a = i365_get(s, O2_MODE_A_2);
+	p->mode_b = i365_get(s, O2_MODE_B_2);
+    } else {
+	p->mode_a = i365_get(s, O2_MODE_A);
+	p->mode_b = i365_get(s, O2_MODE_B);
+    }
+    p->mode_c = i365_get(s, O2_MODE_C);
+    p->mode_d = i365_get(s, O2_MODE_D);
+}
+
+static void o2micro_set_state(u_short s)
+{
+    o2micro_state_t *p = &socket[s].state.o2micro;
+
+    if (((socket[s].revision & 0xff) = 0x34) || 
+	((socket[s].revision & 0xff) = 0x62)) {
+	i365_set(s, O2_MODE_A_2, p->mode_a);
+	i365_set(s, O2_MODE_B_2, p->mode_b);
+    } else {
+	i365_set(s, O2_MODE_A, p->mode_a);
+	i365_set(s, O2_MODE_B, p->mode_b);
+    }
+    i365_set(s, O2_MODE_C, p->mode_c);
+    i365_set(s, O2_MODE_D, p->mode_d);
+}
+
+static u_int __init o2micro_set_opts(u_short s, char *buf)
+{
+    o2micro_state_t *p = &socket[s].state.o2micro;
+    u_int mask = 0xffff;
 
+    p->mode_b = (p->mode_b & ~O2_MODE_B_IDENT) | O2_MODE_B_ID_CSTEP;
+    flip(p->mode_b, O2_MODE_B_IRQ15_RI, has_ring);
+    p->mode_c &= ~(O2_MODE_C_ZVIDEO | O2_MODE_C_DREQ_MASK);
+
+    if (p->mode_b & O2_MODE_B_IRQ15_RI) {
+	mask &= ~0x8000;
+	strcat(buf, " [ring]");
+    }
+    if (irq_mode != -1)
+	p->mode_d = irq_mode;
+    if (p->mode_d & O2_MODE_D_ISA_IRQ) {
+	strcat(buf, " [pci+isa]");
+    } else {
+	switch (p->mode_d & O2_MODE_D_IRQ_MODE) {
+	case O2_MODE_D_IRQ_PCPCI:
+	    strcat(buf, " [pc/pci]"); break;
+	case O2_MODE_D_IRQ_PCIWAY:
+	    strcat(buf, " [pci/way]"); break;
+	case O2_MODE_D_IRQ_PCI:
+	    strcat(buf, " [pci only]"); mask = 0; break;
+	}
+    }
+    return mask;
+}
+
+#endif
+
 /*===================================
 
     Generic routines to get and set controller options
@@ -475,6 +716,10 @@
     else if (t->flags & IS_VADEM)
 	vg46x_get_state(s);
 #endif
+#ifdef CONFIG_PCI
+    else if (t->flags & IS_O2MICRO)
+	o2micro_get_state(s);
+#endif
 }
 
 static void set_bridge_state(u_short s)
@@ -491,6 +736,10 @@
     if (t->flags & IS_VADEM)
 	vg46x_set_state(s);
 #endif
+#ifdef CONFIG_PCI
+    if (t->flags & IS_O2MICRO)
+	o2micro_set_state(s);
+#endif
 }
 
 static u_int __init set_bridge_opts(u_short s, u_short ns)
@@ -512,6 +761,10 @@
 	else if (socket[i].flags & IS_VADEM)
 	    m = vg46x_set_opts(i, buf);
 #endif
+#ifdef CONFIG_PCI
+	else if (socket[i].flags & IS_O2MICRO)
+	    m = o2micro_set_opts(s+i, buf);
+#endif
 	set_bridge_state(i);
 	printk(KERN_INFO "    host opts [%d]:%s\n", i,
 	       (*buf) ? buf : " none");
@@ -535,12 +788,15 @@
     DEBUG(2, "-> hit on irq %d\n", irq);
 }
 
-static u_int __init test_irq(u_short sock, int irq)
+static u_int __init test_irq(u_short sock, int irq, int pci)
 {
-    DEBUG(2, "  testing ISA irq %d\n", irq);
+    int csc = (pci) ? 0 : irq;
+
+    DEBUG(2, "  testing %s irq %d\n", pci?"PCI":"ISA", irq);
     if (request_irq(irq, irq_count, 0, "scan", irq_count) != 0)
 	return 1;
-    irq_hits = 0; irq_sock = sock;
+    irq_hits = 0;
+    irq_sock = sock;
     __set_current_state(TASK_UNINTERRUPTIBLE);
     schedule_timeout(HZ/100);
     if (irq_hits) {
@@ -550,7 +806,7 @@
     }
 
     /* Generate one interrupt */
-    i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (irq << 4));
+    i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (csc << 4));
     i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);
     udelay(1000);
 
@@ -560,7 +816,10 @@
     i365_set(sock, I365_CSCINT, 0);
     DEBUG(2, "    hits = %d\n", irq_hits);
     
-    return (irq_hits != 1);
+    if (pci)
+	    return (irq_hits = 0);
+    else
+	    return (irq_hits != 1);
 }
 
 #ifdef CONFIG_ISA
@@ -580,10 +839,10 @@
 	set_bridge_state(sock);
 	i365_set(sock, I365_CSCINT, 0);
 	for (i = 0; i < 16; i++)
-	    if ((mask0 & (1 << i)) && (test_irq(sock, i) = 0))
+	    if ((mask0 & (1 << i)) && (test_irq(sock, i, 0) = 0))
 		mask1 |= (1 << i);
 	for (i = 0; i < 16; i++)
-	    if ((mask1 & (1 << i)) && (test_irq(sock, i) != 0))
+	    if ((mask1 & (1 << i)) && (test_irq(sock, i, 0) != 0))
 		mask1 ^= (1 << i);
     }
     
@@ -611,6 +870,22 @@
 
 #endif /* CONFIG_ISA */
 
+#ifdef CONFIG_PCI
+static int __init pci_scan(u_short sock)
+{
+    socket_info_t *t = &socket[sock];
+
+    /* for PCI-to-PCMCIA bridges, just check for wedged irq */
+    irq_sock = sock; irq_hits = 0;
+    if (request_irq(t->cap.pci_irq, irq_count, 0, "scan", irq_count))
+	    return 1;
+    udelay(50);
+    free_irq(t->cap.pci_irq, irq_count);
+    DEBUG(2,"pci_scan: %d hits on IRQ %d\n", irq_hits, t->cap.pci_irq);
+    return (!irq_hits);
+}
+#endif /* CONFIG_PCI */
+
 /*==================================*/
 
 /* Time conversion functions */
@@ -629,7 +904,7 @@
 
 #ifdef CONFIG_ISA
 
-static int __init identify(u_short port, u_short sock)
+static int __init isa_identify(u_short port, u_short sock)
 {
     u_char val;
     int type = -1;
@@ -741,8 +1016,17 @@
     
     if (base = 0) printk("\n");
     printk(KERN_INFO "  %s", pcic[type].name);
-    printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
-	       t->ioaddr, t->psock*0x40);
+#ifdef CONFIG_PCI
+    if (t->flags & IS_UNKNOWN)
+	    printk(" [%04x %04x]", t->dev->vendor, t->dev->device);
+    printk(" rev %02x", t->revision);
+    if (t->flags & IS_PCI)
+	    printk(" PCI-to-PCMCIA at slot %02x:%02x, port %#x",
+		   t->dev->bus->number, PCI_SLOT(t->dev->devfn), t->ioaddr);
+    else
+#endif
+	    printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
+		   t->ioaddr, t->psock*0x40);
     printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : ""));
 
 #ifdef CONFIG_ISA
@@ -754,13 +1038,27 @@
 	    mask |= (1<<irq_list[i]);
 #endif
     mask &= I365_MASK & set_bridge_opts(base, ns);
+#ifdef CONFIG_PCI
+    /* Can we use PCI interrupts for card status changes? */
+    if (pci_csc || pci_int) {
+	for (i = base; i < base + ns; i++)
+		if (!socket[i].cap.pci_irq || test_irq(i, socket[i].cap.pci_irq, 1)) break;
+	use_pci = (i=ns);
+    }
+#endif
 #ifdef CONFIG_ISA
     /* Scan for ISA interrupts */
     mask = isa_scan(base, mask);
-#else
-    printk(KERN_INFO "    PCI card interrupts,");
+#endif
+
+#ifdef CONFIG_PCI
+    if (!mask)
+	printk(KERN_INFO "    %s card interrupts,",
+	       (use_pci && pci_int) ? "PCI" : "*NO*");
+    if (use_pci && pci_csc)
+	printk(" PCI status changes\n");
 #endif
-        
+  
 #ifdef CONFIG_ISA
     /* Poll if only two interrupts available */
     if (!use_pci && !poll_interval) {
@@ -770,7 +1068,8 @@
 	    poll_interval = HZ;
     }
     /* Only try an ISA cs_irq if this is the first controller */
-    if (!use_pci && !grab_irq && (cs_irq || !poll_interval)) {
+    if (!(use_pci && pci_csc) && !grab_irq &&
+	(cs_irq || !poll_interval)) {
 	/* Avoid irq 12 unless it is explicitly requested */
 	u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
 	for (cs_irq = 15; cs_irq > 0; cs_irq--)
@@ -785,7 +1084,7 @@
     }
 #endif
     
-    if (!use_pci && !isa_irq) {
+    if (!(use_pci && pci_csc) && !isa_irq) {
 	if (poll_interval = 0)
 	    poll_interval = HZ;
 	printk(" polling interval = %d ms\n",
@@ -798,6 +1097,8 @@
 	t[i].cap.features |= SS_CAP_PCCARD;
 	t[i].cap.map_size = 0x1000;
 	t[i].cap.irq_mask = mask;
+	if (!use_pci)
+	    t[i].cap.pci_irq = 0;
 	t[i].cs_irq = isa_irq;
     }
 
@@ -819,13 +1120,13 @@
 	return;
     }
 
-    id = identify(i365_base, 0);
-    if ((id = IS_I82365DF) && (identify(i365_base, 1) != id)) {
+    id = isa_identify(i365_base, 0);
+    if ((id = IS_I82365DF) && (isa_identify(i365_base, 1) != id)) {
 	for (i = 0; i < 4; i++) {
 	    if (i = ignore) continue;
 	    port = i365_base + ((i & 1) << 2) + ((i & 2) << 1);
 	    sock = (i & 1) << 1;
-	    if (identify(port, sock) = IS_I82365DF) {
+	    if (isa_identify(port, sock) = IS_I82365DF) {
 		add_socket(port, sock, IS_VLSI);
 		add_pcic(1, IS_VLSI);
 	    }
@@ -834,12 +1135,12 @@
 	for (i = 0; i < (extra_sockets ? 8 : 4); i += 2) {
 	    port = i365_base + 2*(i>>2);
 	    sock = (i & 3);
-	    id = identify(port, sock);
+	    id = isa_identify(port, sock);
 	    if (id < 0) continue;
 
 	    for (j = ns = 0; j < 2; j++) {
 		/* Does the socket exist? */
-		if ((ignore = i+j) || (identify(port, sock+j) < 0))
+		if ((ignore = i+j) || (isa_identify(port, sock+j) < 0))
 		    continue;
 		/* Check for bad socket decode */
 		for (k = 0; k <= sockets; k++)
@@ -857,6 +1158,47 @@
 
 #endif
 
+#ifdef CONFIG_PCI
+static void pcic_interrupt(int irq, void *dev,
+			   struct pt_regs *regs);
+
+static int i82365_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+    socket_info_t *s = &socket[sockets];
+    int type = id->driver_data;
+    unsigned long addr;
+    int ns;
+ 
+    dev->driver_data = (void *)sockets;
+    printk("i82365_pci_probe\n");
+
+    if (pci_enable_device(dev))
+	return -EIO;
+    
+    addr = dev->resource[0].start & ~1;
+    for (ns=0; ns < ((type = IS_I82092AA) ? 4 : 2); ns++) {
+	s[ns].dev = dev;
+	s[ns].cap.pci_irq = dev->irq;
+	pci_read_config_byte(dev, PCI_REVISION_ID, &s[ns].revision);
+	add_socket(addr, ns, type);
+    }
+
+    add_pcic(ns, type);
+    if (pci_csc && s[0].cap.pci_irq)
+	request_irq(dev->irq, pcic_interrupt, SA_SHIRQ, "i82365", pcic_interrupt);
+    return 0;
+
+}
+static void i82365_pci_remove(struct pci_dev *dev)
+{
+    u_short s = (u_short)dev->driver_data;
+    
+    if (pci_csc && socket[s].cap.pci_irq)
+	free_irq(dev->irq, pcic_interrupt);
+}
+
+#endif
+
 /*==================================*/
 
 static u_int pending_events[8];
@@ -980,6 +1322,20 @@
     *value |= (status & I365_CS_READY) ? SS_READY : 0;
     *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
 
+#ifdef CONFIG_PCI
+    if (socket[sock].flags & IS_O2MICRO) {
+	status = i365_get(sock, O2_MODE_B);
+	*value |= (status & O2_MODE_B_VS1) ? 0 : SS_3VCARD;
+	*value |= (status & O2_MODE_B_VS2) ? 0 : SS_XVCARD;
+    } else if (socket[sock].type = IS_PD6729) {
+	status = pd67_ext_get(sock + (1-socket[sock].psock), PD67_EXTERN_DATA);
+	*value |= (status & PD67_EXD_VS1(socket[sock].psock)) ? 0 : SS_3VCARD;
+	*value |= (status & PD67_EXD_VS2(socket[sock].psock)) ? 0 : SS_XVCARD;
+    }
+    /* For now, ignore cards with unsupported voltage keys */
+    if (*value & SS_XVCARD)
+	*value &= ~(SS_DETECT|SS_3VCARD|SS_XVCARD);
+#endif
 #ifdef CONFIG_ISA
     if (socket[sock].type = IS_VG469) {
 	status = i365_get(sock, VG469_VSENSE);
@@ -1044,7 +1400,13 @@
     reg = i365_get(sock, I365_INTCTL);
     state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
     if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;
-    state->io_irq = reg & I365_IRQ_MASK;
+
+#ifdef CONFIG_PCI
+    if (socket[sock].cap.pci_irq)
+	    state->io_irq = socket[sock].cap.pci_irq;
+    else
+#endif
+	    state->io_irq = reg & I365_IRQ_MASK;
     
     /* speaker control */
     if (t->flags & IS_CIRRUS) {
@@ -1084,8 +1446,8 @@
     set_bridge_state(sock);
     
     /* IO card, RESET flag, IO interrupt */
-    reg = t->intr;
-    if (state->io_irq != t->cap.pci_irq) reg |= state->io_irq;
+    reg = t->intr | ((state->io_irq = t->cap.pci_irq) ?
+		     t->pci_irq_code : state->io_irq);
     reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
     reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
     i365_set(sock, I365_INTCTL, reg);
@@ -1164,7 +1526,7 @@
     }
     
     /* Card status change interrupt mask */
-    reg = t->cs_irq << 4;
+    reg =  (t->cap.pci_irq ? t->pci_irq_code : t->cs_irq) << 4;
     if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
     if (state->flags & SS_IOCARD) {
 	if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
@@ -1261,6 +1623,13 @@
     mem->card_start = ((u_int)(i & 0x3fff) << 12) + mem->sys_start;
     mem->card_start &= 0x3ffffff;
     
+#ifdef CONFIG_PCI
+    /* Take care of high byte, for PCI controllers */
+    if (socket[sock].type = IS_PD6729) {
+	i365_set(sock, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
+	addr = i365_get(sock, PD67_EXT_DATA) << 24;
+    }
+#endif
     DEBUG(1, "i82365: GetMemMap(%d, %d) = %#2.2x, %d ns, %#5.5lx-%#5."
 	  "5lx, %#5.5x\n", sock, mem->map, mem->flags, mem->speed,
 	  mem->sys_start, mem->sys_stop, mem->card_start);
@@ -1290,6 +1659,13 @@
     if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
 	i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
     
+#ifdef CONFIG_PCI
+    /* Take care of high byte, for PCI controllers */
+    if (socket[sock].type = IS_PD6729) {
+	i365_set(sock, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
+	i365_set(sock, PD67_EXT_DATA, (mem->sys_start >> 24));
+    }
+#endif
     base = I365_MEM(map);
     i = (mem->sys_start >> 12) & 0x0fff;
     if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
@@ -1332,6 +1708,12 @@
     char *p = buf;
     p += sprintf(p, "type:     %s\npsock:    %d\n",
 		 pcic[s->type].name, s->psock);
+#ifdef CONFIG_PCI
+    if (s->flags & (IS_PCI))
+	p += sprintf(p, "bus:      %02x\ndevfn:    %02x.%1x\n",
+		     s->dev->bus->number, PCI_SLOT(s->dev->devfn),
+		     PCI_FUNC(s->dev->devfn));
+#endif
     return (p - buf);
 }
 
@@ -1361,6 +1743,26 @@
     return (p - buf);
 }
 
+#ifdef CONFIG_PCI
+static int proc_read_pci(char *buf, char **start, off_t pos,
+			  int count, int *eof, void *data)
+{
+    struct pci_dev *dev = ((socket_info_t *)data)->dev;
+    char *p = buf;
+    u_int a, b, c, d;
+    int i;
+    
+    for (i = 0; i < 0xc0; i += 0x10) {
+	pci_read_config_dword(dev, i, &a);
+	pci_read_config_dword(dev, i+4, &b);
+	pci_read_config_dword(dev, i+8, &c);
+	pci_read_config_dword(dev, i+12, &d);
+	p += sprintf(p, "%08x %08x %08x %08x\n", a, b, c, d);
+    }
+    return (p - buf);
+}
+#endif
+
 static void pcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
 {
     socket_info_t *s = &socket[sock];
@@ -1370,15 +1772,26 @@
 
     create_proc_read_entry("info", 0, base, proc_read_info, s);
     create_proc_read_entry("exca", 0, base, proc_read_exca, s);
+#ifdef CONFIG_PCI
+    if (s->flags & IS_PCI)
+	create_proc_read_entry("pci", 0, base, proc_read_pci, s);
+#endif
     s->proc = base;
 }
 
 static void pcic_proc_remove(u_short sock)
 {
     struct proc_dir_entry *base = socket[sock].proc;
-    if (base = NULL) return;
+
+    if (base = NULL) 
+	return;
+
     remove_proc_entry("info", base);
     remove_proc_entry("exca", base);
+#ifdef CONFIG_PCI
+    if (socket[sock].flags & IS_PCI)
+	remove_proc_entry("pci", base);
+#endif
 }
 
 #else
@@ -1523,12 +1936,19 @@
     printk(KERN_INFO "Intel PCIC probe: ");
     sockets = 0;
 
+#ifdef CONFIG_PCI
+    if (do_pci_probe)
+	pci_register_driver (&i82365_pci_drv);
+#endif
 #ifdef CONFIG_ISA
     isa_probe();
 #endif
-
     if (sockets = 0) {
 	printk("not found.\n");
+#ifdef CONFIG_PCI
+	if (do_pci_probe)
+	    pci_unregister_driver (&i82365_pci_drv);
+#endif
 	return -ENODEV;
     }
 
@@ -1537,7 +1957,7 @@
     if (grab_irq != 0)
 	request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
 #endif
-    
+
     if (register_ss_entry(sockets, &pcic_operations) != 0)
 	printk(KERN_NOTICE "i82365: register_ss_entry() failed\n");
 
@@ -1567,6 +1987,11 @@
     if (grab_irq != 0)
 	free_irq(cs_irq, pcic_interrupt);
 #endif
+#ifdef CONFIG_PCI
+    if (do_pci_probe)
+	pci_unregister_driver (&i82365_pci_drv);
+#endif
+
     for (i = 0; i < sockets; i++) {
 	/* Turn off all interrupt sources! */
 	i365_set(i, I365_CSCINT, 0);
Index: i82365.h
=================================RCS file: /net/passion/inst/cvs/linux/drivers/pcmcia/Attic/i82365.h,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 i82365.h
--- i82365.h	2000/06/07 10:38:28	1.1.2.2
+++ i82365.h	2000/11/19 17:31:07
@@ -132,4 +132,9 @@
 
 #define I365_REG(slot, reg)	(((slot) << 6) + reg)
 
+#define  O2_MODE_D_IRQ_MODE     0x03
+#define  O2_MODE_D_IRQ_PCPCI    0x00
+#define  O2_MODE_D_IRQ_PCIWAY   0x02
+#define  O2_MODE_D_IRQ_PCI      0x03
+
 #endif /* _LINUX_I82365_H */
-- 
dwmw2



_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

  parent reply	other threads:[~2001-02-04 10:53 UTC|newest]

Thread overview: 107+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-02-03  7:28 Adding PCMCIA support to the kernel tree -- developers needed Miles Lane
2001-02-03 10:07 ` Jeff Garzik
2001-02-03 19:27 ` David Woodhouse
2001-02-03 23:59 ` Miles Lane
2001-02-04  0:00 ` David Hinds
2001-02-04  0:05 ` David Woodhouse
2001-02-04  1:19 ` David Brownell
2001-02-04  1:58 ` Miles Lane
2001-02-04  3:26 ` Keith Owens
2001-02-04  5:59 ` Miles Lane
2001-02-04  8:56 ` David Hinds
2001-02-04  9:55 ` David Woodhouse
2001-02-04 10:00 ` David Woodhouse
2001-02-04 10:10 ` Oliver Neukum
2001-02-04 10:53 ` David Woodhouse [this message]
2001-02-04 11:37 ` David Woodhouse
2001-02-04 17:34 ` David Hinds
2001-02-04 18:02 ` Miles Lane
2001-02-04 18:16 ` Oliver Neukum
2001-02-04 18:54 ` Miles Lane
2001-02-05  1:14 ` Jeff Garzik
2001-02-05  1:56 ` David Brownell
2001-02-05  2:43 ` Miles Lane
2001-02-05  8:42 ` Miles Lane
2001-02-05 10:01 ` Keith Owens
2001-02-05 10:13 ` Keith Owens
2001-02-05 23:43 ` David Woodhouse
2001-02-05 23:45 ` David Woodhouse
2001-02-05 23:59 ` Oliver Neukum
2001-02-06  0:27 ` Miles Lane
2001-02-06  1:10 ` David Brownell
2001-02-06  1:40 ` David Brownell
2001-02-06  6:55 ` Miles Lane
2001-02-06  7:11 ` David Woodhouse
2001-02-06  7:58 ` David Hinds
2001-02-06  8:02 ` David Hinds
2001-02-06  8:13 ` David Hinds
2001-02-06  9:51 ` Oliver Neukum
2001-02-06 13:46 ` Andrew Morton
2001-02-06 15:15 ` Jeff Garzik
2001-02-06 15:20 ` David Woodhouse
2001-02-06 15:33 ` Oliver Neukum
2001-02-06 15:35 ` David Woodhouse
2001-02-06 15:54 ` Oliver Neukum
2001-02-06 16:43 ` Jeff Garzik
2001-02-06 18:56 ` David Brownell
2001-02-06 19:22 ` David Brownell
2001-02-06 19:31 ` David Brownell
2001-02-06 22:09 ` Adam J. Richter
2001-02-06 22:10 ` Andrew Morton
2001-02-06 22:50 ` Oliver Neukum
2001-02-06 23:07 ` Andrew Morton
2001-02-06 23:12 ` Andrew Morton
2001-02-06 23:14 ` Andrew Morton
2001-02-06 23:20 ` David Woodhouse
2001-02-06 23:30 ` Oliver Neukum
2001-02-06 23:34 ` Oliver Neukum
2001-02-06 23:36 ` Andrew Morton
2001-02-07  1:33 ` David Brownell
2001-02-07  2:11 ` Miles Lane
2001-02-07  2:38 ` Adam J. Richter
2001-02-07  9:02 ` Oliver Neukum
2001-02-07  9:09 ` Vojtech Pavlik
2001-02-07  9:10 ` David Woodhouse
2001-02-07  9:35 ` Oliver Neukum
2001-02-07  9:37 ` Vojtech Pavlik
2001-02-07  9:57 ` Oliver Neukum
2001-02-07 10:11 ` Vojtech Pavlik
2001-02-07 10:27 ` David Woodhouse
2001-02-07 10:29 ` Oliver Neukum
2001-02-07 10:30 ` David Woodhouse
2001-02-07 14:45 ` Oliver Neukum
2001-02-07 15:19 ` Adam J. Richter
2001-02-07 16:11 ` Oliver Neukum
2001-02-07 17:37 ` Miles Lane
2001-02-07 17:48 ` Vojtech Pavlik
2001-02-07 18:24 ` David Brownell
2001-02-07 18:42 ` David Brownell
2001-02-07 18:47 ` David Brownell
2001-02-07 18:47 ` Oliver Neukum
2001-02-07 19:00 ` David Brownell
2001-02-07 19:29 ` Vojtech Pavlik
2001-02-07 19:59 ` Miles Lane
2001-02-07 21:02 ` Oliver Neukum
2001-02-07 21:14 ` David Brownell
2001-02-07 22:43 ` Oliver Neukum
2001-02-08  7:22 ` Miles Lane
2001-02-08  9:29 ` Adam J. Richter
2001-02-08 10:24 ` Oliver Neukum
2001-02-08 12:47 ` Andrew Morton
2001-02-08 13:22 ` Oliver Neukum
2001-02-08 13:49 ` Andrew Morton
2001-02-08 14:07 ` Oliver Neukum
2001-02-08 15:00 ` Vojtech Pavlik
2001-02-08 15:10 ` Vojtech Pavlik
2001-02-08 15:13 ` Vojtech Pavlik
2001-02-09  7:42 ` Vojtech Pavlik
2001-02-09 11:48 ` Oliver Neukum
2001-02-09 12:45 ` Vojtech Pavlik
2001-02-09 13:09 ` Oliver Neukum
2001-02-09 14:15 ` David Brownell
2001-02-09 15:45 ` Vojtech Pavlik
2001-02-26 17:47 ` David Brownell
2001-02-26 21:45 ` Chris Brand
2001-02-27  7:56 ` David Hinds
2001-02-28 16:56 ` David Brownell
2001-02-28 17:32 ` David Hinds

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=marc-linux-hotplug-98140443518951@msgid-missing \
    --to=dwmw2@infradead.org \
    --cc=linux-hotplug@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).