2000-11-21 19:06:00

by Michel Salim

[permalink] [raw]
Subject: i82365 PCI-PCMCIA bridge still not working in 2.4.0-test11

/lib/modules/2.4.0-test11/pcmcia/i82365.o: init_module: No such device
ds: no socket drivers loaded!
/lib/modules/2.4.0-test11/pcmcia/ds.o: init_module: Operation not permitted


Attachments:
log (253.00 B)
errmsg (177.00 B)
Download all attachments

2000-11-22 11:16:16

by David Woodhouse

[permalink] [raw]
Subject: Re: i82365 PCI-PCMCIA bridge still not working in 2.4.0-test11


[email protected] said:
> Installed kernel 2.4.0-test11 on my Debian Woody box today. Had no
> problem apart from getting PCMCIA to work. I have a PCI-PCMCIA adapter
> on my desktop PC, using the Cirrus Logic CL6729 chipset;

Linus got a bit carried away when stripping out all the CardBus support
from i82365, and took out the support for PCI-PCMCIA bridges too.

Try this snapshot of my development tree, or use lspci to find the IO
address of the device and specify that to the existing module.

Index: drivers/pcmcia/cirrus.h
===================================================================
RCS file: /net/passion/inst/cvs/linux/drivers/pcmcia/Attic/cirrus.h,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 cirrus.h
--- drivers/pcmcia/cirrus.h 2000/06/07 10:38:28 1.1.2.2
+++ drivers/pcmcia/cirrus.h 2000/11/22 10:37:31
@@ -48,6 +48,11 @@
#define PD67_EXT_INDEX 0x2e /* Extension index */
#define PD67_EXT_DATA 0x2f /* Extension data */

+#define pd67_ext_get(s, r) \
+ (i365_set(s, PD67_EXT_INDEX, r), i365_get(s, PD67_EXT_DATA))
+#define pd67_ext_set(s, r, v) \
+ (i365_set(s, PD67_EXT_INDEX, r), i365_set(s, PD67_EXT_DATA, v))
+
/* PD6722 extension registers -- indexed in PD67_EXT_INDEX */
#define PD67_DATA_MASK0 0x01 /* Data mask 0 */
#define PD67_DATA_MASK1 0x02 /* Data mask 1 */
@@ -119,6 +124,10 @@
#define PD67_EC1_INV_CARD_IRQ 0x08
#define PD67_EC1_INV_MGMT_IRQ 0x10
#define PD67_EC1_PULLUP_CTL 0x20
+
+/* Fields in PD67_EXTERN_DATA */
+#define PD67_EXD_VS1(s) (0x01 << ((s)<<1))
+#define PD67_EXD_VS2(s) (0x02 << ((s)<<1))

/* Fields in PD67_MISC_CTL_3 */
#define PD67_MC3_IRQ_MASK 0x03
Index: drivers/pcmcia/cs.c
===================================================================
RCS file: /net/passion/inst/cvs/linux/drivers/pcmcia/Attic/cs.c,v
retrieving revision 1.1.2.28
diff -u -r1.1.2.28 cs.c
--- drivers/pcmcia/cs.c 2000/11/10 14:56:32 1.1.2.28
+++ drivers/pcmcia/cs.c 2000/11/22 10:37:33
@@ -416,12 +416,10 @@
{
int i;

- for (i = 0; i < sockets; i++) {
+ for (i = sockets-1; i >= 0; i-- ) {
socket_info_t *socket = socket_table[i];
if (socket->ss_entry == ss_entry)
- pcmcia_unregister_socket (socket);
- else
- i++;
+ pcmcia_unregister_socket (socket);
}
} /* unregister_ss_entry */

Index: drivers/pcmcia/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
--- drivers/pcmcia/i82365.c 2000/11/17 09:35:49 1.1.2.15
+++ drivers/pcmcia/i82365.c 2000/11/22 10:37:36
@@ -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: drivers/pcmcia/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
--- drivers/pcmcia/i82365.h 2000/06/07 10:38:28 1.1.2.2
+++ drivers/pcmcia/i82365.h 2000/11/22 10:37:36
@@ -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


2000-11-23 01:36:18

by Michel Salim

[permalink] [raw]
Subject: Re: i82365 PCI-PCMCIA bridge still not working in 2.4.0-test11

Thanks for the patch... but it does not quite work. It applies cleanly,
but upon booting the patched kernel, the machine freezes completely upon
PCMCIA initialisation (it got to the point where the init script said
'Loading modules' then nothing). CTRL+ALT+DEL does not work, either.

Anyone got a clue? Would love to help debug this if someone would just
walk me through it.

Michel

David Woodhouse wrote:

> [email protected] said:
>
>> Installed kernel 2.4.0-test11 on my Debian Woody box today. Had no
>> problem apart from getting PCMCIA to work. I have a PCI-PCMCIA adapter
>> on my desktop PC, using the Cirrus Logic CL6729 chipset;
>
>
> Linus got a bit carried away when stripping out all the CardBus support
> from i82365, and took out the support for PCI-PCMCIA bridges too.
>
> Try this snapshot of my development tree, or use lspci to find the IO
> address of the device and specify that to the existing module.
>