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
next prev parent reply other threads:[~2001-02-04 10:53 UTC|newest]
Thread overview: 112+ 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
[not found] <3A711BB1.C5B8BCFB@megapathdsl.net>
[not found] ` <3A711CB1.62757B52@megapathdsl.net>
[not found] ` <20010131200621.F29731@sonic.net>
[not found] ` <3A78E3EC.8050605@megapathdsl.net>
[not found] ` <20010202183642.F30100@sonic.net>
2001-02-03 7:28 ` Miles Lane
2001-02-03 10:07 ` Jeff Garzik
2001-02-04 0:00 ` Miles Lane
2001-02-05 1:14 ` Jeff Garzik
2001-02-05 2:43 ` Miles Lane
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.