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
- Lines: 234
- Date:
Thu Sep 7 09:13:00 2000
- Orig file:
v2.4.0-test7/linux/drivers/pcmcia/cs.c
- Orig date:
Wed Aug 23 18:36:38 2000
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)