patch-2.4.0-test8 linux/drivers/pcmcia/cs.c

Next file: linux/drivers/pcmcia/cs_internal.h
Previous file: linux/drivers/pcmcia/cistpl.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test7/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
@@ -2,7 +2,7 @@
 
     PCMCIA Card Services -- core services
 
-    cs.c 1.249 2000/02/10 23:26:11
+    cs.c 1.267 2000/08/30 22:07:31
     
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -15,7 +15,7 @@
     rights and limitations under the License.
 
     The initial developer of the original code is David A. Hinds
-    <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
+    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
@@ -66,7 +66,7 @@
 int pc_debug = PCMCIA_DEBUG;
 MODULE_PARM(pc_debug, "i");
 static const char *version =
-"cs.c 1.249 2000/02/10 23:26:11 (David Hinds)";
+"cs.c 1.267 2000/08/30 22:07:31 (David Hinds)";
 #endif
 
 #ifdef CONFIG_PCI
@@ -93,7 +93,7 @@
 static const char *release = "Linux PCMCIA Card Services " CS_RELEASE;
 static const char *options = "options: " OPTIONS;
 
-MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
 MODULE_DESCRIPTION("Linux PCMCIA Card Services " CS_RELEASE
 		   "\n  options:" OPTIONS);
 
@@ -303,7 +303,7 @@
     
 ======================================================================*/
 
-static void setup_socket(socket_info_t *);
+static int setup_socket(socket_info_t *);
 static void shutdown_socket(socket_info_t *);
 static void reset_socket(socket_info_t *);
 static void unreset_socket(socket_info_t *);
@@ -490,9 +490,12 @@
     free_regions(&s->c_region);
 } /* shutdown_socket */
 
-static void setup_socket(socket_info_t *s)
+/*
+ * Return zero if we think the card isn't actually present
+ */
+static int setup_socket(socket_info_t *s)
 {
-	int val;
+	int val, ret;
 	int setup_timeout = 100;
 
 	/* Wait for "not pending" */
@@ -506,7 +509,8 @@
 		}
 		printk(KERN_NOTICE "cs: socket %p voltage interrogation"
 			" timed out\n", s);
-		return;
+		ret = 0;
+		goto out;
 	}
 
 	if (val & SS_DETECT) {
@@ -531,8 +535,13 @@
 		set_socket(s, &s->socket);
 		msleep(vcc_settle);
 		reset_socket(s);
-	} else
+		ret = 1;
+	} else {
 		DEBUG(0, "cs: setup_socket(%p): no card!\n", s);
+		ret = 0;
+	}
+out:
+	return ret;
 } /* setup_socket */
 
 /*======================================================================
@@ -569,7 +578,7 @@
 		get_socket_status(s, &val);
 		if (val & SS_READY)
 			break;
-		DEBUG(2, "cs: socket %ld not ready yet\n", i);
+		DEBUG(2, "cs: socket %d not ready yet\n", s->sock);
 		if (--setup_timeout) {
 			msleep(unreset_check);
 			continue;
@@ -673,7 +682,8 @@
 		msleep(resume_delay);
 	    else
 		msleep(setup_delay);
-	    setup_socket(s);
+	    if (setup_socket(s) == 0)
+		s->state &= ~SOCKET_SETUP_PENDING;
 	}
     }
     if (events & SS_BATDEAD)
@@ -773,6 +783,13 @@
 	      *base, align);
 	align = 0;
     }
+    /* Check for an already-allocated window that must conflict with
+       what was asked for.  It is a hack because it does not catch all
+       potential conflicts, just the most obvious ones. */
+    for (i = 0; i < MAX_IO_WIN; i++)
+	if ((s->io[i].NumPorts != 0) &&
+	    ((s->io[i].BasePort & (align-1)) == *base))
+	    return 1;
     for (i = 0; i < MAX_IO_WIN; i++) {
 	if (s->io[i].NumPorts == 0) {
 	    if (find_io_region(base, num, align, name) == 0) {
@@ -1408,7 +1425,8 @@
 	if ((status & SS_DETECT) &&
 	    !(s->state & SOCKET_SETUP_PENDING)) {
 	    s->state |= SOCKET_SETUP_PENDING;
-	    setup_socket(s);
+	    if (setup_socket(s) == 0)
+		    s->state &= ~SOCKET_SETUP_PENDING;
 	}
     }
 
@@ -1676,11 +1694,13 @@
 	write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
     }
     if (req->Present & PRESENT_OPTION) {
-	if (s->functions == 1)
+	if (s->functions == 1) {
 	    c->Option = req->ConfigIndex & COR_CONFIG_MASK;
-	else {
+	} else {
 	    c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
-	    c->Option |= COR_FUNC_ENA|COR_ADDR_DECODE|COR_IREQ_ENA;
+	    c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
+	    if (req->Present & PRESENT_IOBASE_0)
+		c->Option |= COR_ADDR_DECODE;
 	}
 	if (c->state & CONFIG_IRQ_REQ)
 	    if (!(c->irq.Attributes & IRQ_FORCED_PULSE))
@@ -1829,8 +1849,8 @@
     if (c->state & CONFIG_IRQ_REQ)
 	return CS_IN_USE;
     
-    /* Short cut: if the interrupt is PCI, there are no options */
-    if (s->cap.irq_mask == (1 << s->cap.pci_irq))
+    /* Short cut: if there are no ISA interrupts, then it is PCI */
+    if (!s->cap.irq_mask)
 	irq = s->cap.pci_irq;
 #ifdef CONFIG_ISA
     else if (s->irq.AssignedIRQ != 0) {
@@ -1845,7 +1865,6 @@
 	ret = CS_IN_USE;
 	if (req->IRQInfo1 & IRQ_INFO2_VALID) {
 	    mask = req->IRQInfo2 & s->cap.irq_mask;
-	    mask &= ~(1 << s->cap.pci_irq);
 	    for (try = 0; try < 2; try++) {
 		for (irq = 0; irq < 32; irq++)
 		    if ((mask >> irq) & 1) {
@@ -1910,11 +1929,12 @@
 	     req->Size : s->cap.map_size);
     if (req->Size & (s->cap.map_size-1))
 	return CS_BAD_SIZE;
-    if (req->Base & (align-1))
+    if ((req->Base && (s->cap.features & SS_CAP_STATIC_MAP)) ||
+	(req->Base & (align-1)))
 	return CS_BAD_BASE;
     if (req->Base)
 	align = 0;
-    
+
     /* Allocate system memory window */
     for (w = 0; w < MAX_WIN; w++)
 	if (!(s->state & SOCKET_WIN_REQ(w))) break;
@@ -1928,13 +1948,13 @@
     win->sock = s;
     win->base = req->Base;
     win->size = req->Size;
-	
-    if (find_mem_region(&win->base, win->size, align,
+
+    if (!(s->cap.features & SS_CAP_STATIC_MAP) &&
+	find_mem_region(&win->base, win->size, align,
 			(req->Attributes & WIN_MAP_BELOW_1MB) ||
 			!(s->cap.features & SS_CAP_PAGE_REGS),
 			(*handle)->dev_info))
 	return CS_IN_USE;
-    req->Base = win->base;
     (*handle)->state |= CLIENT_WIN_REQ(w);
 
     /* Configure the socket controller */
@@ -1949,14 +1969,15 @@
 	win->ctl.flags |= MAP_16BIT;
     if (req->Attributes & WIN_USE_WAIT)
 	win->ctl.flags |= MAP_USE_WAIT;
-    win->ctl.sys_start = req->Base;
-    win->ctl.sys_stop = req->Base + req->Size-1;
+    win->ctl.sys_start = win->base;
+    win->ctl.sys_stop = win->base + win->size-1;
     win->ctl.card_start = 0;
     if (set_mem_map(s, &win->ctl) != 0)
 	return CS_BAD_ARGS;
     s->state |= SOCKET_WIN_REQ(w);
 
     /* Return window handle */
+    req->Base = win->ctl.sys_start;
     *wh = win;
     
     return CS_SUCCESS;
@@ -2096,9 +2117,7 @@
 	s->state |= SOCKET_SETUP_PENDING;
 	spin_unlock_irqrestore(&s->lock, flags);
 	get_socket_status(s, &status);
-	if (status & SS_DETECT)
-	    setup_socket(s);
-	else {
+	if ((status & SS_DETECT) == 0 || (setup_socket(s) == 0)) {
 	    s->state &= ~SOCKET_SETUP_PENDING;
 	    return CS_NO_CARD;
 	}
@@ -2168,7 +2187,7 @@
 {
 
 #ifdef PCMCIA_DEBUG
-    if (pc_debug > 1) {
+    if (pc_debug > 2) {
 	int i;
 	for (i = 0; i < SERVICE_COUNT; i++)
 	    if (service_table[i].key == func) break;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)