Commit 0a07c5b5 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/tmp3
parents c3e9a7f3 fed61014
This diff is collapsed.
...@@ -465,10 +465,17 @@ t2_init_arch(void) ...@@ -465,10 +465,17 @@ t2_init_arch(void)
*(vulp)T2_HAE_1 = 0; mb(); /* Sparse MEM HAE */ *(vulp)T2_HAE_1 = 0; mb(); /* Sparse MEM HAE */
*(vulp)T2_HAE_2 = 0; mb(); /* Sparse I/O HAE */ *(vulp)T2_HAE_2 = 0; mb(); /* Sparse I/O HAE */
*(vulp)T2_HAE_3 = 0; mb(); /* Config Space HAE */ *(vulp)T2_HAE_3 = 0; mb(); /* Config Space HAE */
#if 0
/* !!! DO NOT EVER TOUCH THIS !!! */ /*
*(vulp)T2_HAE_4 = 0; mb(); /* Dense MEM HAE */ * We also now zero out HAE_4, the dense memory HAE, so that
#endif * we need not account for its "offset" when accessing dense
* memory resources which we allocated in our normal way. This
* HAE would need to stay untouched were we to keep the SRM
* resource settings.
*
* Thus we can now run standard X servers on SABLE/LYNX. :-)
*/
*(vulp)T2_HAE_4 = 0; mb();
} }
void void
......
...@@ -270,7 +270,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -270,7 +270,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct thread_info *childti = p->thread_info; struct thread_info *childti = p->thread_info;
struct pt_regs * childregs; struct pt_regs * childregs;
struct switch_stack * childstack, *stack; struct switch_stack * childstack, *stack;
unsigned long stack_offset; unsigned long stack_offset, settls;
stack_offset = PAGE_SIZE - sizeof(struct pt_regs); stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
if (!(regs->ps & 8)) if (!(regs->ps & 8))
...@@ -279,6 +279,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -279,6 +279,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
(stack_offset + PAGE_SIZE + (long) childti); (stack_offset + PAGE_SIZE + (long) childti);
*childregs = *regs; *childregs = *regs;
settls = regs->r20;
childregs->r0 = 0; childregs->r0 = 0;
childregs->r19 = 0; childregs->r19 = 0;
childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
...@@ -292,14 +293,16 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -292,14 +293,16 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childti->pcb.flags = 1; /* set FEN, clear everything else */ childti->pcb.flags = 1; /* set FEN, clear everything else */
/* Set a new TLS for the child thread? Peek back into the /* Set a new TLS for the child thread? Peek back into the
syscall arguments that we saved on syscall entry. */ syscall arguments that we saved on syscall entry. Oops,
except we'd have clobbered it with the parent/child set
of r20. Read the saved copy. */
/* Note: if CLONE_SETTLS is not set, then we must inherit the /* Note: if CLONE_SETTLS is not set, then we must inherit the
value from the parent, which will have been set by the block value from the parent, which will have been set by the block
copy in dup_task_struct. This is non-intuitive, but is copy in dup_task_struct. This is non-intuitive, but is
required for proper operation in the case of a threaded required for proper operation in the case of a threaded
application calling fork. */ application calling fork. */
if (clone_flags & CLONE_SETTLS) if (clone_flags & CLONE_SETTLS)
childti->pcb.unique = regs->r20; childti->pcb.unique = settls;
return 0; return 0;
} }
......
...@@ -284,7 +284,6 @@ mca_nmi_hook(void) ...@@ -284,7 +284,6 @@ mca_nmi_hook(void)
{ {
__u8 dumpval __attribute__((unused)) = inb(0xf823); __u8 dumpval __attribute__((unused)) = inb(0xf823);
__u8 swnmi __attribute__((unused)) = inb(0xf813); __u8 swnmi __attribute__((unused)) = inb(0xf813);
extern void show_stack(unsigned long *);
/* FIXME: assume dump switch pressed */ /* FIXME: assume dump switch pressed */
/* check to see if the dump switch was pressed */ /* check to see if the dump switch was pressed */
...@@ -302,7 +301,7 @@ mca_nmi_hook(void) ...@@ -302,7 +301,7 @@ mca_nmi_hook(void)
} }
} }
printk(KERN_ERR "VOYAGER: Dump switch pressed, printing CPU%d tracebacks\n", smp_processor_id()); printk(KERN_ERR "VOYAGER: Dump switch pressed, printing CPU%d tracebacks\n", smp_processor_id());
show_stack(NULL); show_stack(NULL, NULL);
show_state(); show_state();
} }
......
...@@ -115,6 +115,8 @@ _start: ...@@ -115,6 +115,8 @@ _start:
nop nop
#endif #endif
#ifdef CONFIG_ROMFS_FS
/* /*
* Move ROM filesystem above bss :-) * Move ROM filesystem above bss :-)
*/ */
...@@ -135,6 +137,11 @@ _copy_romfs: ...@@ -135,6 +137,11 @@ _copy_romfs:
move.l %d0, -(%a1) move.l %d0, -(%a1)
cmp.l %a0, %a2 /* Check if at end */ cmp.l %a0, %a2 /* Check if at end */
bne _copy_romfs bne _copy_romfs
#else /* CONFIG_ROMFS_FS */
lea.l _ebss, %a1
move.l %a1, _ramstart
#endif /* CONFIG_ROMFS_FS */
/* /*
* Zero out the bss region. * Zero out the bss region.
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/param.h> #include <linux/param.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/coldfire.h> #include <asm/coldfire.h>
#include <asm/mcfpit.h> #include <asm/mcfpit.h>
......
...@@ -102,7 +102,10 @@ void config_BSP(char *commandp, int size) ...@@ -102,7 +102,10 @@ void config_BSP(char *commandp, int size)
{ {
mcf_setimr(MCFSIM_IMR_MASKALL); mcf_setimr(MCFSIM_IMR_MASKALL);
#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ #if defined(CONFIG_BOOTPARAM)
strncpy(commandp, CONFIG_BOOTPARAM_STRING, size);
commandp[size-1] = 0;
#elif defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \ defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \
defined(CONFIG_CLEOPATRA) defined(CONFIG_CLEOPATRA)
/* Copy command line from FLASH to local buffer... */ /* Copy command line from FLASH to local buffer... */
......
...@@ -36,6 +36,7 @@ void __init prom_init(void *cif_handler, void *cif_stack) ...@@ -36,6 +36,7 @@ void __init prom_init(void *cif_handler, void *cif_stack)
int ints[3]; int ints[3];
int node; int node;
int i = 0; int i = 0;
int bufadjust;
prom_vers = PROM_P1275; prom_vers = PROM_P1275;
...@@ -63,9 +64,19 @@ void __init prom_init(void *cif_handler, void *cif_stack) ...@@ -63,9 +64,19 @@ void __init prom_init(void *cif_handler, void *cif_stack)
if (strncmp (buffer, "OBP ", 4)) if (strncmp (buffer, "OBP ", 4))
goto strange_version; goto strange_version;
/* Version field is expected to be 'OBP xx.yy.zz date...' */ /*
* Version field is expected to be 'OBP xx.yy.zz date...'
* However, Sun can't stick to this format very well, so
* we need to check for 'OBP xx.yy.zz date...' and adjust
* accordingly. -spot
*/
if (strncmp (buffer, "OBP ", 5))
bufadjust = 4;
else
bufadjust = 5;
p = buffer + 4; p = buffer + bufadjust;
while (p && isdigit(*p) && i < 3) { while (p && isdigit(*p) && i < 3) {
ints[i++] = simple_strtoul(p, NULL, 0); ints[i++] = simple_strtoul(p, NULL, 0);
if ((p = strchr(p, '.')) != NULL) if ((p = strchr(p, '.')) != NULL)
...@@ -77,7 +88,7 @@ void __init prom_init(void *cif_handler, void *cif_stack) ...@@ -77,7 +88,7 @@ void __init prom_init(void *cif_handler, void *cif_stack)
prom_rev = ints[1]; prom_rev = ints[1];
prom_prev = (ints[0] << 16) | (ints[1] << 8) | ints[2]; prom_prev = (ints[0] << 16) | (ints[1] << 8) | ints[2];
printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + 4); printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + bufadjust);
prom_meminit(); prom_meminit();
......
...@@ -703,7 +703,8 @@ static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_ ...@@ -703,7 +703,8 @@ static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_
*/ */
pciirq = dev->irq; pciirq = dev->irq;
if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { /* Is it an "IDE storage" device in non-PCI mode? */
if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 5) != 5) {
if (noisy) if (noisy)
printk(KERN_INFO "%s: not 100%% native mode: " printk(KERN_INFO "%s: not 100%% native mode: "
"will probe irqs later\n", d->name); "will probe irqs later\n", d->name);
......
This diff is collapsed.
...@@ -231,18 +231,6 @@ static const lookup_t service_table[] = { ...@@ -231,18 +231,6 @@ static const lookup_t service_table[] = {
======================================================================*/ ======================================================================*/
static int register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info)
{
int error;
if (handler && !try_module_get(s->ss_entry->owner))
return -ENODEV;
error = s->ss_entry->register_callback(s, handler, info);
if (!handler)
module_put(s->ss_entry->owner);
return error;
}
static int get_socket_status(struct pcmcia_socket *s, int *val) static int get_socket_status(struct pcmcia_socket *s, int *val)
{ {
return s->ss_entry->get_status(s, val); return s->ss_entry->get_status(s, val);
...@@ -363,6 +351,7 @@ static int pcmcia_add_socket(struct class_device *class_dev) ...@@ -363,6 +351,7 @@ static int pcmcia_add_socket(struct class_device *class_dev)
wait_for_completion(&socket->thread_done); wait_for_completion(&socket->thread_done);
BUG_ON(!socket->thread); BUG_ON(!socket->thread);
pcmcia_parse_events(socket, SS_DETECT);
return 0; return 0;
} }
...@@ -723,6 +712,9 @@ static int socket_insert(struct pcmcia_socket *skt) ...@@ -723,6 +712,9 @@ static int socket_insert(struct pcmcia_socket *skt)
{ {
int ret; int ret;
if (!try_module_get(skt->owner))
return CS_NO_CARD;
ret = socket_setup(skt, setup_delay); ret = socket_setup(skt, setup_delay);
if (ret == CS_SUCCESS) { if (ret == CS_SUCCESS) {
#ifdef CONFIG_CARDBUS #ifdef CONFIG_CARDBUS
...@@ -733,8 +725,10 @@ static int socket_insert(struct pcmcia_socket *skt) ...@@ -733,8 +725,10 @@ static int socket_insert(struct pcmcia_socket *skt)
#endif #endif
send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
skt->socket.flags &= ~SS_DEBOUNCED; skt->socket.flags &= ~SS_DEBOUNCED;
} else } else {
socket_shutdown(skt); socket_shutdown(skt);
module_put(skt->owner);
}
return ret; return ret;
} }
...@@ -778,14 +772,55 @@ static int socket_resume(struct pcmcia_socket *skt) ...@@ -778,14 +772,55 @@ static int socket_resume(struct pcmcia_socket *skt)
send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW); send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
} }
skt->socket.flags &= ~SS_DEBOUNCED; skt->socket.flags &= ~SS_DEBOUNCED;
} else } else {
unsigned int old_state = skt->state;
socket_shutdown(skt); socket_shutdown(skt);
if (old_state & SOCKET_PRESENT)
module_put(skt->owner);
}
skt->state &= ~SOCKET_SUSPEND; skt->state &= ~SOCKET_SUSPEND;
return CS_SUCCESS; return CS_SUCCESS;
} }
static void socket_remove(struct pcmcia_socket *skt)
{
socket_shutdown(skt);
module_put(skt->owner);
}
/*
* Process a socket card detect status change.
*
* If we don't have a card already present, delay the detect event for
* about 20ms (to be on the safe side) before reading the socket status.
*
* Some i82365-based systems send multiple SS_DETECT events during card
* insertion, and the "card present" status bit seems to bounce. This
* will probably be true with GPIO-based card detection systems after
* the product has aged.
*/
static void socket_detect_change(struct pcmcia_socket *skt)
{
if (!(skt->state & SOCKET_SUSPEND)) {
int status;
if (!(skt->state & SOCKET_PRESENT)) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(cs_to_timeout(2));
}
get_socket_status(skt, &status);
if ((skt->state & SOCKET_PRESENT) &&
!(status & SS_DETECT))
socket_remove(skt);
if (!(skt->state & SOCKET_PRESENT) &&
(status & SS_DETECT))
socket_insert(skt);
}
}
static int pccardd(void *__skt) static int pccardd(void *__skt)
{ {
struct pcmcia_socket *skt = __skt; struct pcmcia_socket *skt = __skt;
...@@ -809,17 +844,8 @@ static int pccardd(void *__skt) ...@@ -809,17 +844,8 @@ static int pccardd(void *__skt)
if (events) { if (events) {
down(&skt->skt_sem); down(&skt->skt_sem);
if (events & SS_DETECT && !(skt->state & SOCKET_SUSPEND)) { if (events & SS_DETECT)
int status; socket_detect_change(skt);
get_socket_status(skt, &status);
if ((skt->state & SOCKET_PRESENT) &&
!(status & SS_DETECT))
socket_shutdown(skt);
if (!(skt->state & SOCKET_PRESENT) &&
(status & SS_DETECT))
socket_insert(skt);
}
if (events & SS_BATDEAD) if (events & SS_BATDEAD)
send_event(skt, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW); send_event(skt, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW);
if (events & SS_BATWARN) if (events & SS_BATWARN)
...@@ -839,21 +865,17 @@ static int pccardd(void *__skt) ...@@ -839,21 +865,17 @@ static int pccardd(void *__skt)
} }
remove_wait_queue(&skt->thread_wait, &wait); remove_wait_queue(&skt->thread_wait, &wait);
socket_shutdown(skt);
complete_and_exit(&skt->thread_done, 0); complete_and_exit(&skt->thread_done, 0);
} }
static void parse_events(void *info, u_int events) void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
{ {
struct pcmcia_socket *s = info;
spin_lock(&s->thread_lock); spin_lock(&s->thread_lock);
s->thread_events |= events; s->thread_events |= events;
spin_unlock(&s->thread_lock); spin_unlock(&s->thread_lock);
wake_up(&s->thread_wait); wake_up(&s->thread_wait);
} /* parse_events */ } /* pcmcia_parse_events */
/*====================================================================== /*======================================================================
...@@ -1114,9 +1136,6 @@ int pcmcia_deregister_client(client_handle_t handle) ...@@ -1114,9 +1136,6 @@ int pcmcia_deregister_client(client_handle_t handle)
handle->event_handler = NULL; handle->event_handler = NULL;
} }
if (--s->real_clients == 0)
register_callback(s, NULL, NULL);
return CS_SUCCESS; return CS_SUCCESS;
} /* deregister_client */ } /* deregister_client */
...@@ -1531,11 +1550,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) ...@@ -1531,11 +1550,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
if (client == NULL) if (client == NULL)
return CS_OUT_OF_RESOURCE; return CS_OUT_OF_RESOURCE;
if (++s->real_clients == 1) {
register_callback(s, &parse_events, s);
parse_events(s, SS_DETECT);
}
*handle = client; *handle = client;
client->state &= ~CLIENT_UNBOUND; client->state &= ~CLIENT_UNBOUND;
client->Socket = s; client->Socket = s;
...@@ -2213,7 +2227,7 @@ int pcmcia_eject_card(client_handle_t handle, client_req_t *req) ...@@ -2213,7 +2227,7 @@ int pcmcia_eject_card(client_handle_t handle, client_req_t *req)
if (ret != 0) if (ret != 0)
break; break;
socket_shutdown(skt); socket_remove(skt);
ret = CS_SUCCESS; ret = CS_SUCCESS;
} while (0); } while (0);
up(&skt->skt_sem); up(&skt->skt_sem);
...@@ -2504,6 +2518,7 @@ EXPORT_SYMBOL(pcmcia_write_memory); ...@@ -2504,6 +2518,7 @@ EXPORT_SYMBOL(pcmcia_write_memory);
EXPORT_SYMBOL(dead_socket); EXPORT_SYMBOL(dead_socket);
EXPORT_SYMBOL(CardServices); EXPORT_SYMBOL(CardServices);
EXPORT_SYMBOL(MTDHelperEntry); EXPORT_SYMBOL(MTDHelperEntry);
EXPORT_SYMBOL(pcmcia_parse_events);
struct class pcmcia_socket_class = { struct class pcmcia_socket_class = {
.name = "pcmcia_socket", .name = "pcmcia_socket",
......
...@@ -64,10 +64,8 @@ static struct pci_driver i82092aa_pci_drv = { ...@@ -64,10 +64,8 @@ static struct pci_driver i82092aa_pci_drv = {
/* the pccard structure and its functions */ /* the pccard structure and its functions */
static struct pccard_operations i82092aa_operations = { static struct pccard_operations i82092aa_operations = {
.owner = THIS_MODULE,
.init = i82092aa_init, .init = i82092aa_init,
.suspend = i82092aa_suspend, .suspend = i82092aa_suspend,
.register_callback = i82092aa_register_callback,
.get_status = i82092aa_get_status, .get_status = i82092aa_get_status,
.get_socket = i82092aa_get_socket, .get_socket = i82092aa_get_socket,
.set_socket = i82092aa_set_socket, .set_socket = i82092aa_set_socket,
...@@ -85,12 +83,6 @@ struct socket_info { ...@@ -85,12 +83,6 @@ struct socket_info {
3 = operational card */ 3 = operational card */
int io_base; /* base io address of the socket */ int io_base; /* base io address of the socket */
unsigned int pending_events; /* Pending events on this interface */
void (*handler)(void *info, u_int events);
/* callback to the driver of the card */
void *info; /* to be passed to the handler */
struct pcmcia_socket socket; struct pcmcia_socket socket;
struct pci_dev *dev; /* The PCI device for the socket */ struct pci_dev *dev; /* The PCI device for the socket */
}; };
...@@ -142,6 +134,7 @@ static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_devic ...@@ -142,6 +134,7 @@ static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_devic
sockets[i].socket.map_size = 0x1000; sockets[i].socket.map_size = 0x1000;
sockets[i].socket.irq_mask = 0; sockets[i].socket.irq_mask = 0;
sockets[i].socket.pci_irq = dev->irq; sockets[i].socket.pci_irq = dev->irq;
sockets[i].socket.owner = THIS_MODULE;
sockets[i].number = i; sockets[i].number = i;
...@@ -324,23 +317,6 @@ static int to_cycles(int ns) ...@@ -324,23 +317,6 @@ static int to_cycles(int ns)
/* Interrupt handler functionality */ /* Interrupt handler functionality */
static void i82092aa_bh(void *dummy)
{
unsigned int events;
int i;
for (i=0; i < socket_count; i++) {
events = xchg(&(sockets[i].pending_events),0);
printk("events = %x \n",events);
if (sockets[i].handler)
sockets[i].handler(sockets[i].info, events);
}
}
static DECLARE_WORK(i82092aa_task, i82092aa_bh, NULL);
static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs) static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
{ {
int i; int i;
...@@ -367,8 +343,7 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs) ...@@ -367,8 +343,7 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
csc = indirect_read(i,I365_CSC); /* card status change register */ csc = indirect_read(i,I365_CSC); /* card status change register */
if ((csc==0) || /* no events on this socket */ if (csc==0) /* no events on this socket */
(sockets[i].handler==NULL)) /* no way to handle events */
continue; continue;
handled = 1; handled = 1;
events = 0; events = 0;
...@@ -389,8 +364,7 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs) ...@@ -389,8 +364,7 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
} }
if (events) { if (events) {
sockets[i].pending_events |= events; pcmcia_parse_events(&sockets[i].socket, events);
schedule_work(&i82092aa_task);
} }
active |= events; active |= events;
} }
...@@ -475,16 +449,6 @@ static int i82092aa_suspend(struct pcmcia_socket *sock) ...@@ -475,16 +449,6 @@ static int i82092aa_suspend(struct pcmcia_socket *sock)
return retval; return retval;
} }
static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info)
{
unsigned int sock = container_of(socket, struct socket_info, socket)->number;
enter("i82092aa_register_callback");
sockets[sock].handler = handler;
sockets[sock].info = info;
leave("i82092aa_register_callback");
return 0;
} /* i82092aa_register_callback */
static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value) static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value)
{ {
unsigned int sock = container_of(socket, struct socket_info, socket)->number; unsigned int sock = container_of(socket, struct socket_info, socket)->number;
......
...@@ -35,7 +35,6 @@ static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_ma ...@@ -35,7 +35,6 @@ static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_ma
static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem); static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem);
static int i82092aa_init(struct pcmcia_socket *socket); static int i82092aa_init(struct pcmcia_socket *socket);
static int i82092aa_suspend(struct pcmcia_socket *socket); static int i82092aa_suspend(struct pcmcia_socket *socket);
static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info);
#endif #endif
...@@ -164,8 +164,6 @@ struct i82365_socket { ...@@ -164,8 +164,6 @@ struct i82365_socket {
ioaddr_t ioaddr; ioaddr_t ioaddr;
u_short psock; u_short psock;
u_char cs_irq, intr; u_char cs_irq, intr;
void (*handler)(void *info, u_int events);
void *info;
union { union {
cirrus_state_t cirrus; cirrus_state_t cirrus;
vg46x_state_t vg46x; vg46x_state_t vg46x;
...@@ -863,35 +861,6 @@ static void __init isa_probe(void) ...@@ -863,35 +861,6 @@ static void __init isa_probe(void)
/*====================================================================*/ /*====================================================================*/
static u_int pending_events[8];
static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
static void pcic_bh(void *dummy)
{
u_int events;
int i;
for (i=0; i < sockets; i++) {
spin_lock_irq(&pending_event_lock);
events = pending_events[i];
pending_events[i] = 0;
spin_unlock_irq(&pending_event_lock);
/*
SS_DETECT events need a small delay here. The reason for this is that
the "is there a card" electronics need time to see the card after the
"we have a card coming in" electronics have seen it.
*/
if (events & SS_DETECT)
mdelay(4);
if (socket[i].handler)
socket[i].handler(socket[i].info, events);
}
}
static DECLARE_WORK(pcic_task, pcic_bh, NULL);
static unsigned long last_detect_jiffies;
static irqreturn_t pcic_interrupt(int irq, void *dev, static irqreturn_t pcic_interrupt(int irq, void *dev,
struct pt_regs *regs) struct pt_regs *regs)
{ {
...@@ -911,26 +880,12 @@ static irqreturn_t pcic_interrupt(int irq, void *dev, ...@@ -911,26 +880,12 @@ static irqreturn_t pcic_interrupt(int irq, void *dev,
handled = 1; handled = 1;
ISA_LOCK(i, flags); ISA_LOCK(i, flags);
csc = i365_get(i, I365_CSC); csc = i365_get(i, I365_CSC);
if ((csc == 0) || (!socket[i].handler) || if ((csc == 0) || (i365_get(i, I365_IDENT) & 0x70)) {
(i365_get(i, I365_IDENT) & 0x70)) {
ISA_UNLOCK(i, flags); ISA_UNLOCK(i, flags);
continue; continue;
} }
events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0; events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
/* Several sockets will send multiple "new card detected"
events in rapid succession. However, the rest of the pcmcia expects
only one such event. We just ignore these events by having a
timeout */
if (events) {
if ((jiffies - last_detect_jiffies)<(HZ/20))
events = 0;
last_detect_jiffies = jiffies;
}
if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD) if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)
events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
else { else {
...@@ -941,12 +896,9 @@ static irqreturn_t pcic_interrupt(int irq, void *dev, ...@@ -941,12 +896,9 @@ static irqreturn_t pcic_interrupt(int irq, void *dev,
ISA_UNLOCK(i, flags); ISA_UNLOCK(i, flags);
DEBUG(2, "i82365: socket %d event 0x%02x\n", i, events); DEBUG(2, "i82365: socket %d event 0x%02x\n", i, events);
if (events) { if (events)
spin_lock(&pending_event_lock); pcmcia_parse_events(&socket[i].socket, events);
pending_events[i] |= events;
spin_unlock(&pending_event_lock);
schedule_work(&pcic_task);
}
active |= events; active |= events;
} }
if (!active) break; if (!active) break;
...@@ -968,16 +920,6 @@ static void pcic_interrupt_wrapper(u_long data) ...@@ -968,16 +920,6 @@ static void pcic_interrupt_wrapper(u_long data)
/*====================================================================*/ /*====================================================================*/
static int pcic_register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info)
{
unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
socket[sock].handler = handler;
socket[sock].info = info;
return 0;
} /* pcic_register_callback */
/*====================================================================*/
static int i365_get_status(u_short sock, u_int *value) static int i365_get_status(u_short sock, u_int *value)
{ {
u_int status; u_int status;
...@@ -1400,10 +1342,8 @@ static int pcic_suspend(struct pcmcia_socket *sock) ...@@ -1400,10 +1342,8 @@ static int pcic_suspend(struct pcmcia_socket *sock)
} }
static struct pccard_operations pcic_operations = { static struct pccard_operations pcic_operations = {
.owner = THIS_MODULE,
.init = pcic_init, .init = pcic_init,
.suspend = pcic_suspend, .suspend = pcic_suspend,
.register_callback = pcic_register_callback,
.get_status = pcic_get_status, .get_status = pcic_get_status,
.get_socket = pcic_get_socket, .get_socket = pcic_get_socket,
.set_socket = pcic_set_socket, .set_socket = pcic_set_socket,
...@@ -1464,6 +1404,7 @@ static int __init init_i82365(void) ...@@ -1464,6 +1404,7 @@ static int __init init_i82365(void)
for (i = 0; i < sockets; i++) { for (i = 0; i < sockets; i++) {
socket[i].socket.dev.dev = &i82365_device.dev; socket[i].socket.dev.dev = &i82365_device.dev;
socket[i].socket.ss_entry = &pcic_operations; socket[i].socket.ss_entry = &pcic_operations;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i; socket[i].number = i;
ret = pcmcia_register_socket(&socket[i].socket); ret = pcmcia_register_socket(&socket[i].socket);
if (ret && i--) { if (ret && i--) {
......
...@@ -38,15 +38,13 @@ ...@@ -38,15 +38,13 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/workqueue.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/version.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -263,29 +261,27 @@ static int sa1100_pcmcia_suspend(struct pcmcia_socket *sock) ...@@ -263,29 +261,27 @@ static int sa1100_pcmcia_suspend(struct pcmcia_socket *sock)
return ret; return ret;
} }
static spinlock_t status_lock = SPIN_LOCK_UNLOCKED;
/* sa1100_pcmcia_task_handler() /* sa1100_check_status()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * ^^^^^^^^^^^^^^^^^^^^^
* Processes serviceable socket events using the "eventd" thread context.
*
* Event processing (specifically, the invocation of the Card Services event
* callback) occurs in this thread rather than in the actual interrupt
* handler due to the use of scheduling operations in the PCMCIA core.
*/ */
static void sa1100_pcmcia_task_handler(void *data) static void sa1100_check_status(struct sa1100_pcmcia_socket *skt)
{ {
struct sa1100_pcmcia_socket *skt = data;
unsigned int events; unsigned int events;
DEBUG(4, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__); DEBUG(4, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__);
do { do {
unsigned int status; unsigned int status;
unsigned long flags;
status = sa1100_pcmcia_skt_state(skt); status = sa1100_pcmcia_skt_state(skt);
spin_lock_irqsave(&status_lock, flags);
events = (status ^ skt->status) & skt->cs_state.csc_mask; events = (status ^ skt->status) & skt->cs_state.csc_mask;
skt->status = status; skt->status = status;
spin_unlock_irqrestore(&status_lock, flags);
DEBUG(2, "events: %s%s%s%s%s%s\n", DEBUG(2, "events: %s%s%s%s%s%s\n",
events == 0 ? "<NONE>" : "", events == 0 ? "<NONE>" : "",
...@@ -295,8 +291,8 @@ static void sa1100_pcmcia_task_handler(void *data) ...@@ -295,8 +291,8 @@ static void sa1100_pcmcia_task_handler(void *data)
events & SS_BATWARN ? "BATWARN " : "", events & SS_BATWARN ? "BATWARN " : "",
events & SS_STSCHG ? "STSCHG " : ""); events & SS_STSCHG ? "STSCHG " : "");
if (events && skt->handler != NULL) if (events)
skt->handler(skt->handler_info, events); pcmcia_parse_events(&skt->socket, events);
} while (events); } while (events);
} }
...@@ -311,7 +307,7 @@ static void sa1100_pcmcia_poll_event(unsigned long dummy) ...@@ -311,7 +307,7 @@ static void sa1100_pcmcia_poll_event(unsigned long dummy)
mod_timer(&skt->poll_timer, jiffies + SA1100_PCMCIA_POLL_PERIOD); mod_timer(&skt->poll_timer, jiffies + SA1100_PCMCIA_POLL_PERIOD);
schedule_work(&skt->work); sa1100_check_status(skt);
} }
...@@ -330,44 +326,11 @@ static irqreturn_t sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *r ...@@ -330,44 +326,11 @@ static irqreturn_t sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *r
DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq); DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
schedule_work(&skt->work); sa1100_check_status(skt);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/* sa1100_pcmcia_register_callback()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Implements the register_callback() operation for the in-kernel
* PCMCIA service (formerly SS_RegisterCallback in Card Services). If
* the function pointer `handler' is not NULL, remember the callback
* location in the state for `sock', and increment the usage counter
* for the driver module. (The callback is invoked from the interrupt
* service routine, sa1100_pcmcia_interrupt(), to notify Card Services
* of interesting events.) Otherwise, clear the callback pointer in the
* socket state and decrement the module usage count.
*
* Returns: 0
*/
static int
sa1100_pcmcia_register_callback(struct pcmcia_socket *sock,
void (*handler)(void *, unsigned int),
void *info)
{
struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
if (handler) {
if (!try_module_get(skt->ops->owner))
return -ENODEV;
skt->handler_info = info;
skt->handler = handler;
} else {
skt->handler = NULL;
module_put(skt->ops->owner);
}
return 0;
}
/* sa1100_pcmcia_get_status() /* sa1100_pcmcia_get_status()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
...@@ -655,10 +618,8 @@ static CLASS_DEVICE_ATTR(status, S_IRUGO, show_status, NULL); ...@@ -655,10 +618,8 @@ static CLASS_DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
static struct pccard_operations sa11xx_pcmcia_operations = { static struct pccard_operations sa11xx_pcmcia_operations = {
.owner = THIS_MODULE,
.init = sa1100_pcmcia_sock_init, .init = sa1100_pcmcia_sock_init,
.suspend = sa1100_pcmcia_suspend, .suspend = sa1100_pcmcia_suspend,
.register_callback = sa1100_pcmcia_register_callback,
.get_status = sa1100_pcmcia_get_status, .get_status = sa1100_pcmcia_get_status,
.get_socket = sa1100_pcmcia_get_socket, .get_socket = sa1100_pcmcia_get_socket,
.set_socket = sa1100_pcmcia_set_socket, .set_socket = sa1100_pcmcia_set_socket,
...@@ -765,10 +726,9 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -765,10 +726,9 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
memset(skt, 0, sizeof(*skt)); memset(skt, 0, sizeof(*skt));
skt->socket.ss_entry = &sa11xx_pcmcia_operations; skt->socket.ss_entry = &sa11xx_pcmcia_operations;
skt->socket.owner = ops->owner;
skt->socket.dev.dev = dev; skt->socket.dev.dev = dev;
INIT_WORK(&skt->work, sa1100_pcmcia_task_handler, skt);
init_timer(&skt->poll_timer); init_timer(&skt->poll_timer);
skt->poll_timer.function = sa1100_pcmcia_poll_event; skt->poll_timer.function = sa1100_pcmcia_poll_event;
skt->poll_timer.data = (unsigned long)skt; skt->poll_timer.data = (unsigned long)skt;
......
...@@ -59,8 +59,6 @@ struct sa1100_pcmcia_socket { ...@@ -59,8 +59,6 @@ struct sa1100_pcmcia_socket {
unsigned int status; unsigned int status;
socket_state_t cs_state; socket_state_t cs_state;
void (*handler)(void *, unsigned int);
void *handler_info;
unsigned short spd_io[MAX_IO_WIN]; unsigned short spd_io[MAX_IO_WIN];
unsigned short spd_mem[MAX_WIN]; unsigned short spd_mem[MAX_WIN];
...@@ -75,7 +73,6 @@ struct sa1100_pcmcia_socket { ...@@ -75,7 +73,6 @@ struct sa1100_pcmcia_socket {
unsigned int irq_state; unsigned int irq_state;
struct timer_list poll_timer; struct timer_list poll_timer;
struct work_struct work;
}; };
struct pcmcia_low_level { struct pcmcia_low_level {
......
...@@ -116,8 +116,6 @@ static struct pccard_operations tcic_operations; ...@@ -116,8 +116,6 @@ static struct pccard_operations tcic_operations;
struct tcic_socket { struct tcic_socket {
u_short psock; u_short psock;
void (*handler)(void *info, u_int events);
void *info;
u_char last_sstat; u_char last_sstat;
u_char id; u_char id;
struct pcmcia_socket socket; struct pcmcia_socket socket;
...@@ -433,10 +431,9 @@ static int __init init_tcic(void) ...@@ -433,10 +431,9 @@ static int __init init_tcic(void)
for (i = 0; i < sock; i++) { for (i = 0; i < sock; i++) {
if ((i == ignore) || is_active(i)) continue; if ((i == ignore) || is_active(i)) continue;
socket_table[sockets].psock = i; socket_table[sockets].psock = i;
socket_table[sockets].handler = NULL;
socket_table[sockets].info = NULL;
socket_table[sockets].id = get_tcic_id(); socket_table[sockets].id = get_tcic_id();
socket_table[sockets].socket.owner = THIS_MODULE;
/* only 16-bit cards, memory windows must be size-aligned */ /* only 16-bit cards, memory windows must be size-aligned */
/* No PCI or CardBus support */ /* No PCI or CardBus support */
socket_table[sockets].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN; socket_table[sockets].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN;
...@@ -558,26 +555,6 @@ static void __exit exit_tcic(void) ...@@ -558,26 +555,6 @@ static void __exit exit_tcic(void)
/*====================================================================*/ /*====================================================================*/
static u_int pending_events[2];
static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
static void tcic_bh(void *dummy)
{
u_int events;
int i;
for (i=0; i < sockets; i++) {
spin_lock_irq(&pending_event_lock);
events = pending_events[i];
pending_events[i] = 0;
spin_unlock_irq(&pending_event_lock);
if (socket_table[i].handler)
socket_table[i].handler(socket_table[i].info, events);
}
}
static DECLARE_WORK(tcic_task, tcic_bh, NULL);
static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs) static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs)
{ {
int i, quick = 0; int i, quick = 0;
...@@ -605,7 +582,7 @@ static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs) ...@@ -605,7 +582,7 @@ static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs)
tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR); tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR);
quick = 1; quick = 1;
} }
if ((latch == 0) || (socket_table[psock].handler == NULL)) if (latch == 0)
continue; continue;
events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0; events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0;
events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0; events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
...@@ -617,10 +594,7 @@ static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs) ...@@ -617,10 +594,7 @@ static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs)
events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0; events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
} }
if (events) { if (events) {
spin_lock(&pending_event_lock); pcmcia_parse_events(&socket_table[i].socket, events);
pending_events[i] |= events;
spin_unlock(&pending_event_lock);
schedule_work(&tcic_task);
} }
} }
...@@ -645,16 +619,6 @@ static void tcic_timer(u_long data) ...@@ -645,16 +619,6 @@ static void tcic_timer(u_long data)
/*====================================================================*/ /*====================================================================*/
static int tcic_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
{
u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
socket_table[psock].handler = handler;
socket_table[psock].info = info;
return 0;
} /* tcic_register_callback */
/*====================================================================*/
static int tcic_get_status(struct pcmcia_socket *sock, u_int *value) static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
{ {
u_short psock = container_of(sock, struct tcic_socket, socket)->psock; u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
...@@ -915,10 +879,8 @@ static int tcic_suspend(struct pcmcia_socket *sock) ...@@ -915,10 +879,8 @@ static int tcic_suspend(struct pcmcia_socket *sock)
} }
static struct pccard_operations tcic_operations = { static struct pccard_operations tcic_operations = {
.owner = THIS_MODULE,
.init = tcic_init, .init = tcic_init,
.suspend = tcic_suspend, .suspend = tcic_suspend,
.register_callback = tcic_register_callback,
.get_status = tcic_get_status, .get_status = tcic_get_status,
.get_socket = tcic_get_socket, .get_socket = tcic_get_socket,
.set_socket = tcic_set_socket, .set_socket = tcic_set_socket,
......
...@@ -250,7 +250,6 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) ...@@ -250,7 +250,6 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
if (state->flags & SS_DEBOUNCED) { if (state->flags & SS_DEBOUNCED) {
/* The insertion debounce period has ended. Clear any pending insertion events */ /* The insertion debounce period has ended. Clear any pending insertion events */
socket->events &= ~SS_DETECT;
state->flags &= ~SS_DEBOUNCED; /* SS_DEBOUNCED is oneshot */ state->flags &= ~SS_DEBOUNCED; /* SS_DEBOUNCED is oneshot */
} }
yenta_set_power(socket, state); yenta_set_power(socket, state);
...@@ -420,19 +419,6 @@ static unsigned int yenta_events(struct yenta_socket *socket) ...@@ -420,19 +419,6 @@ static unsigned int yenta_events(struct yenta_socket *socket)
} }
static void yenta_bh(void *data)
{
struct yenta_socket *socket = data;
unsigned int events;
spin_lock_irq(&socket->event_lock);
events = socket->events;
socket->events = 0;
spin_unlock_irq(&socket->event_lock);
if (socket->handler)
socket->handler(socket->info, events);
}
static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
unsigned int events; unsigned int events;
...@@ -440,10 +426,7 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -440,10 +426,7 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
events = yenta_events(socket); events = yenta_events(socket);
if (events) { if (events) {
spin_lock(&socket->event_lock); pcmcia_parse_events(&socket->socket, events);
socket->events |= events;
spin_unlock(&socket->event_lock);
schedule_work(&socket->tq_task);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
return IRQ_NONE; return IRQ_NONE;
...@@ -771,21 +754,9 @@ static void yenta_close(struct pci_dev *dev) ...@@ -771,21 +754,9 @@ static void yenta_close(struct pci_dev *dev)
} }
static int yenta_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
{
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
socket->handler = handler;
socket->info = info;
return 0;
}
static struct pccard_operations yenta_socket_operations = { static struct pccard_operations yenta_socket_operations = {
.owner = THIS_MODULE,
.init = yenta_init, .init = yenta_init,
.suspend = yenta_suspend, .suspend = yenta_suspend,
.register_callback = yenta_register_callback,
.get_status = yenta_get_status, .get_status = yenta_get_status,
.get_socket = yenta_get_socket, .get_socket = yenta_get_socket,
.set_socket = yenta_set_socket, .set_socket = yenta_set_socket,
...@@ -860,11 +831,11 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i ...@@ -860,11 +831,11 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
socket->socket.ss_entry = &yenta_socket_operations; socket->socket.ss_entry = &yenta_socket_operations;
socket->socket.dev.dev = &dev->dev; socket->socket.dev.dev = &dev->dev;
socket->socket.driver_data = socket; socket->socket.driver_data = socket;
socket->socket.owner = THIS_MODULE;
/* prepare struct yenta_socket */ /* prepare struct yenta_socket */
socket->dev = dev; socket->dev = dev;
pci_set_drvdata(dev, socket); pci_set_drvdata(dev, socket);
spin_lock_init(&socket->event_lock);
/* /*
* Do some basic sanity checking.. * Do some basic sanity checking..
...@@ -907,8 +878,6 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i ...@@ -907,8 +878,6 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
/* We must finish initialization here */ /* We must finish initialization here */
INIT_WORK(&socket->tq_task, yenta_bh, socket);
if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) { if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) {
/* No IRQ or request_irq failed. Poll */ /* No IRQ or request_irq failed. Poll */
socket->cb_irq = 0; /* But zero is a valid IRQ number. */ socket->cb_irq = 0; /* But zero is a valid IRQ number. */
......
...@@ -99,11 +99,6 @@ struct yenta_socket { ...@@ -99,11 +99,6 @@ struct yenta_socket {
struct pci_dev *dev; struct pci_dev *dev;
int cb_irq, io_irq; int cb_irq, io_irq;
void *base; void *base;
void (*handler)(void *, unsigned int);
void *info;
spinlock_t event_lock;
unsigned int events;
struct work_struct tq_task;
struct timer_list poll_timer; struct timer_list poll_timer;
struct pcmcia_socket socket; struct pcmcia_socket socket;
......
...@@ -133,7 +133,6 @@ ...@@ -133,7 +133,6 @@
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include "scsi.h" #include "scsi.h"
...@@ -564,8 +563,7 @@ NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, Scsi_Cmnd *SCp, ...@@ -564,8 +563,7 @@ NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, Scsi_Cmnd *SCp,
{ {
if(SCp->sc_data_direction != SCSI_DATA_NONE && if(SCp->sc_data_direction != SCSI_DATA_NONE &&
SCp->sc_data_direction != SCSI_DATA_UNKNOWN) { SCp->sc_data_direction != SCSI_DATA_UNKNOWN) {
enum dma_data_direction direction = enum dma_data_direction direction = SCp->sc_data_direction;
(enum dma_data_direction)scsi_to_pci_dma_dir(SCp->sc_data_direction);
if(SCp->use_sg) { if(SCp->use_sg) {
dma_unmap_sg(hostdata->dev, SCp->buffer, dma_unmap_sg(hostdata->dev, SCp->buffer,
SCp->use_sg, direction); SCp->use_sg, direction);
...@@ -1842,7 +1840,7 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) ...@@ -1842,7 +1840,7 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *))
} }
/* now build the scatter gather list */ /* now build the scatter gather list */
direction = (enum dma_data_direction)scsi_to_pci_dma_dir(SCp->sc_data_direction); direction = SCp->sc_data_direction;
if(move_ins != 0) { if(move_ins != 0) {
int i; int i;
int sg_count; int sg_count;
...@@ -2039,8 +2037,15 @@ NCR_700_init(void) ...@@ -2039,8 +2037,15 @@ NCR_700_init(void)
return 0; return 0;
} }
/* NULL exit routine to keep modutils happy */
STATIC void __exit
NCR_700_exit(void)
{
}
EXPORT_SYMBOL(NCR_700_detect); EXPORT_SYMBOL(NCR_700_detect);
EXPORT_SYMBOL(NCR_700_release); EXPORT_SYMBOL(NCR_700_release);
EXPORT_SYMBOL(NCR_700_intr); EXPORT_SYMBOL(NCR_700_intr);
module_init(NCR_700_init); module_init(NCR_700_init);
module_exit(NCR_700_exit);
...@@ -978,26 +978,16 @@ config SCSI_ZALON ...@@ -978,26 +978,16 @@ config SCSI_ZALON
used on the add-in Bluefish, Barracuda & Shrike SCSI cards. used on the add-in Bluefish, Barracuda & Shrike SCSI cards.
Say Y here if you have one of these machines or cards. Say Y here if you have one of these machines or cards.
config SCSI_NCR53C8XX config SCSI_NCR_Q720
tristate "NCR53C8XX SCSI support" tristate "NCR Quad 720 MCA SCSI support"
depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI_ZALON!=y && SCSI depends on MCA && SCSI
---help--- help
This is the BSD ncr driver adapted to Linux for the NCR53C8XX family This is a driver for the MicroChannel Quad 720 card produced by
of PCI-SCSI controllers. This driver supports parity checking, NCR and commonly used in 345x/35xx/4100 class machines. It always
tagged command queuing and fast synchronous data transfers up to 80 tries to negotiate sync and uses tag command queueing.
MB/s with wide FAST-40 LVD devices and controllers.
Recent versions of the 53C8XX chips are better supported by the
option "SYM53C8XX SCSI support", below.
Note: there is yet another driver for the 53c8xx family of
controllers ("NCR53c7,8xx SCSI support" above). If you want to use
them both, you need to say M to both and build them as modules, but
only one may be active at a time. If you have a 53c8xx board, you
probably do not want to use the "NCR53c7,8xx SCSI support".
Please read <file:Documentation/scsi/ncr53c8xx.txt> for more Unless you have an NCR manufactured machine, the chances are that
information. you do not have this SCSI card, so say N.
config SCSI_SYM53C8XX config SCSI_SYM53C8XX
tristate "SYM53C8XX SCSI support" tristate "SYM53C8XX SCSI support"
...@@ -1027,8 +1017,8 @@ config SCSI_SYM53C8XX ...@@ -1027,8 +1017,8 @@ config SCSI_SYM53C8XX
information. information.
config SCSI_NCR53C8XX_DEFAULT_TAGS config SCSI_NCR53C8XX_DEFAULT_TAGS
int "default tagged command queue depth" int " default tagged command queue depth"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720)
default "8" default "8"
---help--- ---help---
"Tagged command queuing" is a feature of SCSI-2 which improves "Tagged command queuing" is a feature of SCSI-2 which improves
...@@ -1053,8 +1043,8 @@ config SCSI_NCR53C8XX_DEFAULT_TAGS ...@@ -1053,8 +1043,8 @@ config SCSI_NCR53C8XX_DEFAULT_TAGS
There is no safe option other than using good SCSI devices. There is no safe option other than using good SCSI devices.
config SCSI_NCR53C8XX_MAX_TAGS config SCSI_NCR53C8XX_MAX_TAGS
int "maximum number of queued commands" int " maximum number of queued commands"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720)
default "32" default "32"
---help--- ---help---
This option allows you to specify the maximum number of commands This option allows you to specify the maximum number of commands
...@@ -1070,8 +1060,8 @@ config SCSI_NCR53C8XX_MAX_TAGS ...@@ -1070,8 +1060,8 @@ config SCSI_NCR53C8XX_MAX_TAGS
There is no safe option and the default answer is recommended. There is no safe option and the default answer is recommended.
config SCSI_NCR53C8XX_SYNC config SCSI_NCR53C8XX_SYNC
int "synchronous transfers frequency in MHz" int " synchronous transfers frequency in MHz"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720)
default "20" default "20"
---help--- ---help---
The SCSI Parallel Interface-2 Standard defines 5 classes of transfer The SCSI Parallel Interface-2 Standard defines 5 classes of transfer
...@@ -1104,8 +1094,8 @@ config SCSI_NCR53C8XX_SYNC ...@@ -1104,8 +1094,8 @@ config SCSI_NCR53C8XX_SYNC
terminations and SCSI conformant devices. terminations and SCSI conformant devices.
config SCSI_NCR53C8XX_PROFILE config SCSI_NCR53C8XX_PROFILE
bool "enable profiling" bool " enable profiling"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720)
help help
This option allows you to enable profiling information gathering. This option allows you to enable profiling information gathering.
These statistics are not very accurate due to the low frequency These statistics are not very accurate due to the low frequency
...@@ -1115,8 +1105,8 @@ config SCSI_NCR53C8XX_PROFILE ...@@ -1115,8 +1105,8 @@ config SCSI_NCR53C8XX_PROFILE
The normal answer therefore is N. The normal answer therefore is N.
config SCSI_NCR53C8XX_IOMAPPED config SCSI_NCR53C8XX_IOMAPPED
bool "use normal IO" bool " use normal IO"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX) && !SCSI_ZALON depends on SCSI_SYM53C8XX && !(SCSI_ZALON || SCSI_NCR_Q720)
help help
If you say Y here, the driver will use normal IO, as opposed to If you say Y here, the driver will use normal IO, as opposed to
memory mapped IO. Memory mapped IO has less latency than normal IO memory mapped IO. Memory mapped IO has less latency than normal IO
...@@ -1128,8 +1118,8 @@ config SCSI_NCR53C8XX_IOMAPPED ...@@ -1128,8 +1118,8 @@ config SCSI_NCR53C8XX_IOMAPPED
related problems. related problems.
config SCSI_NCR53C8XX_PQS_PDS config SCSI_NCR53C8XX_PQS_PDS
bool "include support for the NCR PQS/PDS SCSI card" bool " include support for the NCR PQS/PDS SCSI card"
depends on (SCSI_NCR53C8XX || SCSI_SYM53C8XX) && SCSI_SYM53C8XX depends on SCSI_SYM53C8XX
help help
Say Y here if you have a special SCSI adapter produced by NCR Say Y here if you have a special SCSI adapter produced by NCR
corporation called a PCI Quad SCSI or PCI Dual SCSI. You do not need corporation called a PCI Quad SCSI or PCI Dual SCSI. You do not need
...@@ -1140,8 +1130,8 @@ config SCSI_NCR53C8XX_PQS_PDS ...@@ -1140,8 +1130,8 @@ config SCSI_NCR53C8XX_PQS_PDS
The common answer here is N, but answering Y is safe. The common answer here is N, but answering Y is safe.
config SCSI_NCR53C8XX_NO_DISCONNECT config SCSI_NCR53C8XX_NO_DISCONNECT
bool "not allow targets to disconnect" bool " not allow targets to disconnect"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) && SCSI_NCR53C8XX_DEFAULT_TAGS=0 depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0
help help
This option is only provided for safety if you suspect some SCSI This option is only provided for safety if you suspect some SCSI
device of yours to not support properly the target-disconnect device of yours to not support properly the target-disconnect
...@@ -1150,8 +1140,8 @@ config SCSI_NCR53C8XX_NO_DISCONNECT ...@@ -1150,8 +1140,8 @@ config SCSI_NCR53C8XX_NO_DISCONNECT
than 1 device on a SCSI bus. The normal answer therefore is N. than 1 device on a SCSI bus. The normal answer therefore is N.
config SCSI_NCR53C8XX_SYMBIOS_COMPAT config SCSI_NCR53C8XX_SYMBIOS_COMPAT
bool "assume boards are SYMBIOS compatible (EXPERIMENTAL)" bool " assume boards are SYMBIOS compatible (EXPERIMENTAL)"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) && EXPERIMENTAL depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720 ) && EXPERIMENTAL
---help--- ---help---
This option allows you to enable some features depending on GPIO This option allows you to enable some features depending on GPIO
wiring. These General Purpose Input/Output pins can be used for wiring. These General Purpose Input/Output pins can be used for
......
...@@ -68,6 +68,7 @@ obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o ...@@ -68,6 +68,7 @@ obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o
obj-$(CONFIG_SCSI_GENERIC_NCR5380_MMIO) += g_NCR5380_mmio.o obj-$(CONFIG_SCSI_GENERIC_NCR5380_MMIO) += g_NCR5380_mmio.o
obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o
obj-$(CONFIG_SCSI_NCR_D700) += NCR_D700.o 53c700.o obj-$(CONFIG_SCSI_NCR_D700) += NCR_D700.o 53c700.o
obj-$(CONFIG_SCSI_NCR_Q720) += NCR_Q720_mod.o
obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o
obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas.o
obj-$(CONFIG_SCSI_QLOGIC_ISP) += qlogicisp.o obj-$(CONFIG_SCSI_QLOGIC_ISP) += qlogicisp.o
...@@ -81,7 +82,6 @@ obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o ...@@ -81,7 +82,6 @@ obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o
obj-$(CONFIG_SCSI_DTC3280) += dtc.o obj-$(CONFIG_SCSI_DTC3280) += dtc.o
obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/ obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/
obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
obj-$(CONFIG_SCSI_NCR53C8XX) += ncr53c8xx.o
obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o
obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o
obj-$(CONFIG_SCSI_7000FASST) += wd7000.o obj-$(CONFIG_SCSI_7000FASST) += wd7000.o
...@@ -133,7 +133,17 @@ sd_mod-objs := sd.o ...@@ -133,7 +133,17 @@ sd_mod-objs := sd.o
sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o
initio-objs := ini9100u.o i91uscsi.o initio-objs := ini9100u.o i91uscsi.o
a100u2w-objs := inia100.o i60uscsi.o a100u2w-objs := inia100.o i60uscsi.o
ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
:= -DCONFIG_NCR53C8XX_PREFETCH \
-DCONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS \
-DCONFIG_SCSI_NCR53C8XX_NO_NVRAM \
-DSCSI_NCR_BIG_ENDIAN -DSIMULATED_INTFLY
ncr53c8xx-flags-$(CONFIG_SCSI_NCR_Q720) \
:= -DCONFIG_SCSI_NCR53C8XX_NO_NVRAM \
-DSIMULATED_INTFLY
CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
zalon7xx-objs := zalon.o ncr53c8xx.o zalon7xx-objs := zalon.o ncr53c8xx.o
NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o
cpqfc-objs := cpqfcTSinit.o cpqfcTScontrol.o cpqfcTSi2c.o \ cpqfc-objs := cpqfcTSinit.o cpqfcTScontrol.o cpqfcTSi2c.o \
cpqfcTSworker.o cpqfcTStrigger.o cpqfcTSworker.o cpqfcTStrigger.o
......
/* -*- mode: c; c-basic-offset: 8 -*- */
/* NCR Quad 720 MCA SCSI Driver
*
* Copyright (C) 2003 by James.Bottomley@HansenPartnership.com
*/
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mca.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/io.h>
#include "scsi.h"
#include "hosts.h"
#include "ncr53c8xx.h"
#include "NCR_Q720.h"
static ncr_chip q720_chip __initdata = {
.device_id = PSEUDO_720_ID,
.revision_id = 0x0f,
.name = "720",
.burst_max = 3,
.offset_max = 8,
.nr_divisor = 4,
.features = FE_WIDE | FE_DIFF | FE_VARCLK,
};
MODULE_AUTHOR("James Bottomley");
MODULE_DESCRIPTION("NCR Quad 720 SCSI Driver");
MODULE_LICENSE("GPL");
#define NCR_Q720_VERSION "0.9"
/* We needs this helper because we have up to four hosts per struct device */
struct NCR_Q720_private {
struct device *dev;
__u32 mem_base;
__u32 phys_mem_base;
__u32 mem_size;
__u8 irq;
__u8 siops;
__u8 irq_enable;
struct Scsi_Host *hosts[4];
};
Scsi_Host_Template NCR_Q720_tpnt = {
.module = THIS_MODULE,
.proc_name = "NCR_Q720",
};
static irqreturn_t
NCR_Q720_intr(int irq, void *data, struct pt_regs * regs)
{
struct NCR_Q720_private *p = (struct NCR_Q720_private *)data;
__u8 sir = (readb(p->mem_base + 0x0d) & 0xf0) >> 4;
__u8 siop;
sir |= ~p->irq_enable;
if(sir == 0xff)
return IRQ_NONE;
while((siop = ffz(sir)) < p->siops) {
sir |= 1<<siop;
ncr53c8xx_intr(irq, p->hosts[siop], regs);
}
return IRQ_HANDLED;
}
static int __init
NCR_Q720_probe_one(struct NCR_Q720_private *p, int siop,
int irq, int slot, __u32 paddr, __u32 vaddr)
{
ncr_device device;
__u8 scsi_id;
static int unit = 0;
__u8 scsr1 = readb(vaddr + NCR_Q720_SCSR_OFFSET + 1);
__u8 differential = readb(vaddr + NCR_Q720_SCSR_OFFSET) & 0x20;
__u8 version;
scsi_id = scsr1 >> 4;
/* enable burst length 16 (FIXME: should allow this) */
scsr1 |= 0x02;
/* force a siop reset */
scsr1 |= 0x04;
writeb(scsr1, vaddr + NCR_Q720_SCSR_OFFSET + 1);
udelay(10);
version = readb(vaddr + 0x18) >> 4;
memset(&device, 0, sizeof(ncr_device));
/* Initialise ncr_device structure with items required by ncr_attach. */
device.chip = q720_chip;
device.chip.revision_id = version;
device.host_id = scsi_id;
device.dev = p->dev;
device.slot.base = paddr;
device.slot.base_c = paddr;
device.slot.base_v = vaddr;
device.slot.irq = irq;
device.differential = differential ? 2 : 0;
printk("Q720 probe unit %d (siop%d) at 0x%lx, diff = %d, vers = %d\n", unit, siop,
(unsigned long)paddr, differential, version);
p->hosts[siop] = ncr_attach(&NCR_Q720_tpnt, unit++, &device);
if (!p->hosts[siop])
goto fail;
p->irq_enable |= (1<<siop);
scsr1 = readb(vaddr + NCR_Q720_SCSR_OFFSET + 1);
/* clear the disable interrupt bit */
scsr1 &= ~0x01;
writeb(scsr1, vaddr + NCR_Q720_SCSR_OFFSET + 1);
scsi_add_host(p->hosts[siop], p->dev);
return 0;
fail:
return -ENODEV;
}
/* Detect a Q720 card. Note, because of the setup --- the chips are
* essentially connectecd to the MCA bus independently, it is easier
* to set them up as two separate host adapters, rather than one
* adapter with two channels */
static int __init
NCR_Q720_probe(struct device *dev)
{
struct NCR_Q720_private *p;
static int banner = 1;
struct mca_device *mca_dev = to_mca_device(dev);
int slot = mca_dev->slot;
int found = 0;
int irq, i, siops;
__u8 pos2, pos4, asr2, asr9, asr10;
__u16 io_base;
__u32 base_addr, mem_size;
__u32 mem_base;
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (!p)
return -ENOMEM;
memset(p, 0, sizeof(*p));
pos2 = mca_device_read_pos(mca_dev, 2);
/* enable device */
pos2 |= NCR_Q720_POS2_BOARD_ENABLE | NCR_Q720_POS2_INTERRUPT_ENABLE;
mca_device_write_pos(mca_dev, 2, pos2);
io_base = (pos2 & NCR_Q720_POS2_IO_MASK) << NCR_Q720_POS2_IO_SHIFT;
if(banner) {
printk(KERN_NOTICE "NCR Q720: Driver Version " NCR_Q720_VERSION "\n"
"NCR Q720: Copyright (c) 2003 by James.Bottomley@HansenPartnership.com\n"
"NCR Q720:\n");
banner = 0;
}
io_base = mca_device_transform_ioport(mca_dev, io_base);
/* OK, this is phase one of the bootstrap, we now know the
* I/O space base address. All the configuration registers
* are mapped here (including pos) */
/* sanity check I/O mapping */
i = inb(io_base) | (inb(io_base+1)<<8);
if(i != NCR_Q720_MCA_ID) {
printk(KERN_ERR "NCR_Q720, adapter failed to I/O map registers correctly at 0x%x(0x%x)\n", io_base, i);
return -ENODEV;
}
/* Phase II, find the ram base and memory map the board register */
pos4 = inb(io_base + 4);
/* enable streaming data */
pos4 |= 0x01;
outb(pos4, io_base + 4);
base_addr = (pos4 & 0x7e) << 20;
base_addr += (pos4 & 0x80) << 23;
asr10 = inb(io_base + 0x12);
base_addr += (asr10 & 0x80) << 24;
base_addr += (asr10 & 0x70) << 23;
/* OK, got the base addr, now we need to find the ram size,
* enable and map it */
asr9 = inb(io_base + 0x11);
i = (asr9 & 0xc0) >> 6;
if(i == 0)
mem_size = 1024;
else
mem_size = 1 << (19 + i);
/* enable the sram mapping */
asr9 |= 0x20;
/* disable the rom mapping */
asr9 &= ~0x10;
outb(asr9, io_base + 0x11);
if(!request_mem_region(base_addr, mem_size, "NCR_Q720")) {
printk(KERN_ERR "NCR_Q720: Failed to claim memory region 0x%lx\n-0x%lx",
(unsigned long)base_addr,
(unsigned long)(base_addr + mem_size));
goto out_free;
}
mem_base = (__u32)ioremap(base_addr, mem_size);
/* now also enable accesses in asr 2 */
asr2 = inb(io_base + 0x0a);
asr2 |= 0x01;
outb(asr2, io_base + 0x0a);
/* get the number of SIOPs (this should be 2 or 4) */
siops = ((asr2 & 0xe0) >> 5) + 1;
/* sanity check mapping (again) */
i = readw(mem_base);
if(i != NCR_Q720_MCA_ID) {
printk(KERN_ERR "NCR_Q720, adapter failed to memory map registers correctly at 0x%lx(0x%x)\n", (unsigned long)base_addr, i);
goto out_release;
}
irq = readb(mem_base + 5) & 0x0f;
/* now do the bus related transforms */
irq = mca_device_transform_irq(mca_dev, irq);
printk(KERN_NOTICE "NCR Q720: found in slot %d irq = %d mem base = 0x%lx siops = %d\n", slot, irq, (unsigned long)base_addr, siops);
printk(KERN_NOTICE "NCR Q720: On board ram %dk\n", mem_size/1024);
p->dev = dev;
p->mem_base = mem_base;
p->phys_mem_base = base_addr;
p->mem_size = mem_size;
p->irq = irq;
p->siops = siops;
if (request_irq(irq, NCR_Q720_intr, SA_SHIRQ, "NCR_Q720", p)) {
printk(KERN_ERR "NCR_Q720: request irq %d failed\n", irq);
goto out_release;
}
/* disable all the siop interrupts */
for(i = 0; i < siops; i++) {
__u32 reg_scsr1 = mem_base + NCR_Q720_CHIP_REGISTER_OFFSET
+ i*NCR_Q720_SIOP_SHIFT + NCR_Q720_SCSR_OFFSET + 1;
__u8 scsr1 = readb(reg_scsr1);
scsr1 |= 0x01;
writeb(scsr1, reg_scsr1);
}
/* plumb in all 720 chips */
for (i = 0; i < siops; i++) {
__u32 siop_v_base = mem_base + NCR_Q720_CHIP_REGISTER_OFFSET
+ i*NCR_Q720_SIOP_SHIFT;
__u32 siop_p_base = base_addr + NCR_Q720_CHIP_REGISTER_OFFSET
+ i*NCR_Q720_SIOP_SHIFT;
__u16 port = io_base + NCR_Q720_CHIP_REGISTER_OFFSET
+ i*NCR_Q720_SIOP_SHIFT;
int err;
outb(0xff, port + 0x40);
outb(0x07, port + 0x41);
if ((err = NCR_Q720_probe_one(p, i, irq, slot,
siop_p_base, siop_v_base)) != 0)
printk("Q720: SIOP%d: probe failed, error = %d\n",
i, err);
else
found++;
}
if (!found) {
kfree(p);
return -ENODEV;
}
mca_device_set_claim(mca_dev, 1);
strlcpy(dev->name, "NCR_Q720", sizeof(dev->name));
dev_set_drvdata(dev, p);
return 0;
out_release:
iounmap((void *)mem_base);
release_mem_region(base_addr, mem_size);
out_free:
kfree(p);
return -ENODEV;
}
static void __exit
NCR_Q720_remove_one(struct Scsi_Host *host)
{
scsi_remove_host(host);
ncr53c8xx_release(host);
}
static int __exit
NCR_Q720_remove(struct device *dev)
{
struct NCR_Q720_private *p = dev_get_drvdata(dev);
int i;
for (i = 0; i < p->siops; i++)
if(p->hosts[i])
NCR_Q720_remove_one(p->hosts[i]);
iounmap((void *)p->mem_base);
release_mem_region(p->phys_mem_base, p->mem_size);
free_irq(p->irq, p);
kfree(p);
return 0;
}
static short NCR_Q720_id_table[] = { NCR_Q720_MCA_ID, 0 };
struct mca_driver NCR_Q720_driver = {
.id_table = NCR_Q720_id_table,
.driver = {
.name = "NCR_Q720",
.bus = &mca_bus_type,
.probe = NCR_Q720_probe,
.remove = __devexit_p(NCR_Q720_remove),
},
};
static int __init
NCR_Q720_init(void)
{
return mca_register_driver(&NCR_Q720_driver);
}
static void __exit
NCR_Q720_exit(void)
{
mca_unregister_driver(&NCR_Q720_driver);
//scsi_sysfs_release_attributes(&NCR_Q720_driver_template);
}
module_init(NCR_Q720_init);
module_exit(NCR_Q720_exit);
/* -*- mode: c; c-basic-offset: 8 -*- */
/* NCR Quad 720 MCA SCSI Driver
*
* Copyright (C) 2003 by James.Bottomley@HansenPartnership.com
*/
#ifndef _NCR_Q720_H
#define _NCR_Q720_H
/* The MCA identifier */
#define NCR_Q720_MCA_ID 0x0720
#define NCR_Q720_CLOCK_MHZ 30
#define NCR_Q720_POS2_BOARD_ENABLE 0x01
#define NCR_Q720_POS2_INTERRUPT_ENABLE 0x02
#define NCR_Q720_POS2_PARITY_DISABLE 0x04
#define NCR_Q720_POS2_IO_MASK 0xf8
#define NCR_Q720_POS2_IO_SHIFT 8
#define NCR_Q720_CHIP_REGISTER_OFFSET 0x200
#define NCR_Q720_SCSR_OFFSET 0x070
#define NCR_Q720_SIOP_SHIFT 0x080
#endif
This diff is collapsed.
This diff is collapsed.
...@@ -12,11 +12,6 @@ ...@@ -12,11 +12,6 @@
#include <linux/types.h> #include <linux/types.h>
/* Eisa Enhanced mode operation - slot locating and addressing */
#define MINEISA 1 /* I don't have an EISA Spec to know these ranges, so I */
#define MAXEISA 8 /* Just took my machine's specifications. Adjust to fit. */
/* I just saw an ad, and bumped this from 6 to 8 */
#define SLOTBASE(x) ((x << 12) + 0xc80)
#define SLOTSIZE 0x5c #define SLOTSIZE 0x5c
/* EISA configuration registers & values */ /* EISA configuration registers & values */
...@@ -152,11 +147,6 @@ struct ecb { /* Enhanced Control Block 6.1 */ ...@@ -152,11 +147,6 @@ struct ecb { /* Enhanced Control Block 6.1 */
#define AHA1740CMD_RINQ 0x0a /* Read Host Adapter Inquiry Data */ #define AHA1740CMD_RINQ 0x0a /* Read Host Adapter Inquiry Data */
#define AHA1740CMD_TARG 0x10 /* Target SCSI Command */ #define AHA1740CMD_TARG 0x10 /* Target SCSI Command */
static int aha1740_detect(Scsi_Host_Template *);
static int aha1740_command(Scsi_Cmnd *);
static int aha1740_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
static int aha1740_biosparam(struct scsi_device *, struct block_device *, sector_t, int *);
#define AHA1740_ECBS 32 #define AHA1740_ECBS 32
#define AHA1740_SCATTER 16 #define AHA1740_SCATTER 16
#define AHA1740_CMDLUN 1 #define AHA1740_CMDLUN 1
......
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/pci.h>
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Features Features
......
...@@ -82,6 +82,13 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) ...@@ -82,6 +82,13 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
sht->info ? sht->info(shost) : sht->name); sht->info ? sht->info(shost) : sht->name);
error = scsi_sysfs_add_host(shost, dev); error = scsi_sysfs_add_host(shost, dev);
if (!shost->can_queue) {
printk(KERN_ERR "%s: can_queue = 0 no longer supported\n",
sht->name);
error = -EINVAL;
}
if (!error) { if (!error) {
scsi_proc_host_add(shost); scsi_proc_host_add(shost);
scsi_scan_host(shost); scsi_scan_host(shost);
...@@ -187,7 +194,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) ...@@ -187,7 +194,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
shost->use_blk_tcq = sht->use_blk_tcq; shost->use_blk_tcq = sht->use_blk_tcq;
shost->highmem_io = sht->highmem_io; shost->highmem_io = sht->highmem_io;
if (!sht->max_host_blocked) if (sht->max_host_blocked)
shost->max_host_blocked = sht->max_host_blocked; shost->max_host_blocked = sht->max_host_blocked;
else else
shost->max_host_blocked = SCSI_DEFAULT_HOST_BLOCKED; shost->max_host_blocked = SCSI_DEFAULT_HOST_BLOCKED;
......
...@@ -26,29 +26,9 @@ ...@@ -26,29 +26,9 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/types.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
struct scsi_driver {
struct module *owner;
struct device_driver gendrv;
int (*init_command)(struct scsi_cmnd *);
void (*rescan)(struct device *);
};
#define to_scsi_driver(drv) \
container_of((drv), struct scsi_driver, gendrv)
extern int scsi_register_driver(struct device_driver *);
#define scsi_unregister_driver(drv) \
driver_unregister(drv);
extern int scsi_register_interface(struct class_interface *);
#define scsi_unregister_interface(intf) \
class_interface_unregister(intf)
/** /**
* scsi_find_device - find a device given the host * scsi_find_device - find a device given the host
* @shost: SCSI host pointer * @shost: SCSI host pointer
......
...@@ -2379,7 +2379,6 @@ static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, ...@@ -2379,7 +2379,6 @@ static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start,
{ {
int len = 0; int len = 0;
int i, id, lun, host_index; int i, id, lun, host_index;
struct Scsi_Host *shpnt;
unsigned long flags; unsigned long flags;
int max_pun; int max_pun;
...@@ -2452,11 +2451,6 @@ static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, ...@@ -2452,11 +2451,6 @@ static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start,
return len; return len;
} }
static void ibmmca_scsi_setup(char *str, int *ints)
{
internal_ibmmca_scsi_setup(str, ints);
}
static int option_setup(char *str) static int option_setup(char *str)
{ {
int ints[IM_MAX_HOSTS]; int ints[IM_MAX_HOSTS];
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
/* Interfaces to the midlevel Linux SCSI driver */ /* Interfaces to the midlevel Linux SCSI driver */
static int ibmmca_detect (Scsi_Host_Template *); static int ibmmca_detect (Scsi_Host_Template *);
static int ibmmca_release (struct Scsi_Host *); static int ibmmca_release (struct Scsi_Host *);
static int ibmmca_command (Scsi_Cmnd *);
static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
static int ibmmca_abort (Scsi_Cmnd *); static int ibmmca_abort (Scsi_Cmnd *);
static int ibmmca_host_reset (Scsi_Cmnd *); static int ibmmca_host_reset (Scsi_Cmnd *);
......
...@@ -7009,10 +7009,10 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr ) ...@@ -7009,10 +7009,10 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr )
* are guaranteed to be < 4G. * are guaranteed to be < 4G.
*/ */
if ( IPS_ENABLE_DMA64 && IPS_HAS_ENH_SGLIST(ha) && if ( IPS_ENABLE_DMA64 && IPS_HAS_ENH_SGLIST(ha) &&
!pci_set_dma_mask(ha->pcidev, (u64)0xffffffffffffffff)) { !pci_set_dma_mask(ha->pcidev, 0xffffffffffffffffULL)) {
(ha)->flags |= IPS_HA_ENH_SG; (ha)->flags |= IPS_HA_ENH_SG;
} else { } else {
if ( pci_set_dma_mask(ha->pcidev, (u64)0xffffffff) != 0 ) { if ( pci_set_dma_mask(ha->pcidev, 0xffffffffULL) != 0 ) {
printk(KERN_WARNING "Unable to set DMA Mask\n"); printk(KERN_WARNING "Unable to set DMA Mask\n");
return ips_abort_init(ha, index); return ips_abort_init(ha, index);
} }
......
...@@ -76,6 +76,7 @@ static struct parisc_driver lasi700_driver = { ...@@ -76,6 +76,7 @@ static struct parisc_driver lasi700_driver = {
.name = "Lasi SCSI", .name = "Lasi SCSI",
.id_table = lasi700_scsi_tbl, .id_table = lasi700_scsi_tbl,
.probe = lasi700_driver_callback, .probe = lasi700_driver_callback,
.remove = __devexit_p(lasi700_driver_remove),
}; };
static int __init static int __init
...@@ -97,12 +98,6 @@ lasi700_driver_callback(struct parisc_device *dev) ...@@ -97,12 +98,6 @@ lasi700_driver_callback(struct parisc_device *dev)
} }
memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
if (!request_mem_region(base, 64, dev->dev.name)) {
printk(KERN_ERR "%s: Failed to claim memory region\n",
dev->dev.name);
goto out_kfree;
}
hostdata->dev = &dev->dev; hostdata->dev = &dev->dev;
dma_set_mask(&dev->dev, 0xffffffffUL); dma_set_mask(&dev->dev, 0xffffffffUL);
hostdata->base = base; hostdata->base = base;
...@@ -122,7 +117,7 @@ lasi700_driver_callback(struct parisc_device *dev) ...@@ -122,7 +117,7 @@ lasi700_driver_callback(struct parisc_device *dev)
host = NCR_700_detect(&lasi700_template, hostdata); host = NCR_700_detect(&lasi700_template, hostdata);
if (!host) if (!host)
goto out_release_mem_region; goto out_kfree;
host->irq = dev->irq; host->irq = dev->irq;
if (request_irq(dev->irq, NCR_700_intr, SA_SHIRQ, if (request_irq(dev->irq, NCR_700_intr, SA_SHIRQ,
...@@ -132,33 +127,33 @@ lasi700_driver_callback(struct parisc_device *dev) ...@@ -132,33 +127,33 @@ lasi700_driver_callback(struct parisc_device *dev)
goto out_put_host; goto out_put_host;
} }
dev_set_drvdata(&dev->dev, host);
scsi_add_host(host, &dev->dev); scsi_add_host(host, &dev->dev);
return 0; return 0;
out_put_host: out_put_host:
scsi_host_put(host); scsi_host_put(host);
out_release_mem_region:
release_mem_region(base, 64);
out_kfree: out_kfree:
kfree(hostdata); kfree(hostdata);
return 1; return -ENODEV;
} }
#if 0 static int __exit
static int lasi700_driver_remove(struct parisc_device *dev)
lasi700_release(struct Scsi_Host *host)
{ {
struct D700_Host_Parameters *hostdata = struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
(struct D700_Host_Parameters *)host->hostdata[0]; struct NCR_700_Host_Parameters *hostdata =
(struct NCR_700_Host_Parameters *)host->hostdata[0];
scsi_remove_host(host);
NCR_700_release(host); NCR_700_release(host);
kfree(hostdata);
free_irq(host->irq, host); free_irq(host->irq, host);
release_mem_region(host->base, 64); kfree(hostdata);
unregister_parisc_driver(&lasi700_driver);
return 1; return 0;
} }
#endif
static int __init static int __init
lasi700_init(void) lasi700_init(void)
...@@ -166,4 +161,12 @@ lasi700_init(void) ...@@ -166,4 +161,12 @@ lasi700_init(void)
return register_parisc_driver(&lasi700_driver); return register_parisc_driver(&lasi700_driver);
} }
static void __exit
lasi700_exit(void)
{
unregister_parisc_driver(&lasi700_driver);
scsi_sysfs_release_attributes(&lasi700_template);
}
module_init(lasi700_init); module_init(lasi700_init);
module_exit(lasi700_exit);
...@@ -25,9 +25,8 @@ ...@@ -25,9 +25,8 @@
#ifndef _LASI700_H #ifndef _LASI700_H
#define _LASI700_H #define _LASI700_H
static int lasi700_detect(Scsi_Host_Template *);
static int lasi700_driver_callback(struct parisc_device *dev); static int lasi700_driver_callback(struct parisc_device *dev);
static int lasi700_release(struct Scsi_Host *host); static int lasi700_driver_remove(struct parisc_device *dev);
#define LASI_710_SVERSION 0x082 #define LASI_710_SVERSION 0x082
#define LASI_700_SVERSION 0x071 #define LASI_700_SVERSION 0x071
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/pci.h>
#include <scsi/scsicam.h> #include <scsi/scsicam.h>
#include "scsi.h" #include "scsi.h"
......
This diff is collapsed.
...@@ -42,6 +42,79 @@ ...@@ -42,6 +42,79 @@
#ifndef NCR53C8XX_H #ifndef NCR53C8XX_H
#define NCR53C8XX_H #define NCR53C8XX_H
/*
** Define the BSD style u_int32 and u_int64 type.
** Are in fact u_int32_t and u_int64_t :-)
*/
typedef u32 u_int32;
typedef u64 u_int64;
typedef u_long vm_offset_t;
#include "sym53c8xx_defs.h" #include "sym53c8xx_defs.h"
/*==========================================================
**
** Structures used by the detection routine to transmit
** device configuration to the attach function.
**
**==========================================================
*/
typedef struct {
int bus;
u_char device_fn;
u_long base;
u_long base_2;
u_long io_port;
u_long base_c;
u_long base_2_c;
u_long base_v;
u_long base_2_v;
int irq;
/* port and reg fields to use INB, OUTB macros */
u_long base_io;
volatile struct ncr_reg *reg;
} ncr_slot;
/*==========================================================
**
** Structure used to store the NVRAM content.
**
**==========================================================
*/
typedef struct {
int type;
#define SCSI_NCR_SYMBIOS_NVRAM (1)
#define SCSI_NCR_TEKRAM_NVRAM (2)
#ifdef SCSI_NCR_NVRAM_SUPPORT
union {
Symbios_nvram Symbios;
Tekram_nvram Tekram;
} data;
#endif
} ncr_nvram;
/*==========================================================
**
** Structure used by detection routine to save data on
** each detected board for attach.
**
**==========================================================
*/
typedef struct {
struct device *dev;
ncr_slot slot;
ncr_chip chip;
ncr_nvram *nvram;
u_char host_id;
#ifdef SCSI_NCR_PQS_PDS_SUPPORT
u_char pqs_pds;
#endif
__u8 differential;
int attach_done;
} ncr_device;
extern struct Scsi_Host *ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device);
extern int ncr53c8xx_release(struct Scsi_Host *host);
irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs);
#endif /* NCR53C8XX_H */ #endif /* NCR53C8XX_H */
...@@ -283,7 +283,6 @@ static const char *nsp32_info(struct Scsi_Host *); ...@@ -283,7 +283,6 @@ static const char *nsp32_info(struct Scsi_Host *);
static int nsp32_eh_abort(Scsi_Cmnd *); static int nsp32_eh_abort(Scsi_Cmnd *);
static int nsp32_eh_bus_reset(Scsi_Cmnd *); static int nsp32_eh_bus_reset(Scsi_Cmnd *);
static int nsp32_eh_host_reset(Scsi_Cmnd *); static int nsp32_eh_host_reset(Scsi_Cmnd *);
static int nsp32_reset(Scsi_Cmnd *, unsigned int);
static int nsp32_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int); static int nsp32_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
static int __devinit nsp32_probe(struct pci_dev *, const struct pci_device_id *); static int __devinit nsp32_probe(struct pci_dev *, const struct pci_device_id *);
static void __devexit nsp32_remove(struct pci_dev *); static void __devexit nsp32_remove(struct pci_dev *);
...@@ -1854,18 +1853,6 @@ static const char *nsp32_info(struct Scsi_Host *shpnt) ...@@ -1854,18 +1853,6 @@ static const char *nsp32_info(struct Scsi_Host *shpnt)
} }
/*
* error handler
*/
static int nsp32_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
{
nsp32_dbg(NSP32_DEBUG_BUSRESET, "SCpnt=0x%p why=%d\n", SCpnt, reset_flags);
nsp32_eh_bus_reset(SCpnt);
return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
}
static int nsp32_eh_abort(Scsi_Cmnd *SCpnt) static int nsp32_eh_abort(Scsi_Cmnd *SCpnt)
{ {
nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
......
...@@ -63,6 +63,7 @@ const char * osst_version = "0.99.0"; ...@@ -63,6 +63,7 @@ const char * osst_version = "0.99.0";
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
#include <scsi/scsi_driver.h>
#include <scsi/scsi_ioctl.h> #include <scsi/scsi_ioctl.h>
#define ST_KILOBYTE 1024 #define ST_KILOBYTE 1024
......
...@@ -139,7 +139,7 @@ struct scsi_request *scsi_allocate_request(struct scsi_device *sdev) ...@@ -139,7 +139,7 @@ struct scsi_request *scsi_allocate_request(struct scsi_device *sdev)
sreq->sr_device = sdev; sreq->sr_device = sdev;
sreq->sr_host = sdev->host; sreq->sr_host = sdev->host;
sreq->sr_magic = SCSI_REQ_MAGIC; sreq->sr_magic = SCSI_REQ_MAGIC;
sreq->sr_data_direction = SCSI_DATA_UNKNOWN; sreq->sr_data_direction = DMA_BIDIRECTIONAL;
} }
return sreq; return sreq;
......
...@@ -24,54 +24,6 @@ ...@@ -24,54 +24,6 @@
#include <scsi/scsi_tcq.h> #include <scsi/scsi_tcq.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
/*
* These are the values that the SCpnt->sc_data_direction and
* SRpnt->sr_data_direction can take. These need to be set
* The SCSI_DATA_UNKNOWN value is essentially the default.
* In the event that the command creator didn't bother to
* set a value, you will see SCSI_DATA_UNKNOWN.
*/
#define SCSI_DATA_UNKNOWN 0
#define SCSI_DATA_WRITE 1
#define SCSI_DATA_READ 2
#define SCSI_DATA_NONE 3
#ifdef CONFIG_PCI
#include <linux/pci.h>
#if ((SCSI_DATA_UNKNOWN == PCI_DMA_BIDIRECTIONAL) && (SCSI_DATA_WRITE == PCI_DMA_TODEVICE) && (SCSI_DATA_READ == PCI_DMA_FROMDEVICE) && (SCSI_DATA_NONE == PCI_DMA_NONE))
#define scsi_to_pci_dma_dir(scsi_dir) ((int)(scsi_dir))
#else
extern __inline__ int scsi_to_pci_dma_dir(unsigned char scsi_dir)
{
if (scsi_dir == SCSI_DATA_UNKNOWN)
return PCI_DMA_BIDIRECTIONAL;
if (scsi_dir == SCSI_DATA_WRITE)
return PCI_DMA_TODEVICE;
if (scsi_dir == SCSI_DATA_READ)
return PCI_DMA_FROMDEVICE;
return PCI_DMA_NONE;
}
#endif
#endif
#if defined(CONFIG_SBUS) && !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
#include <asm/sbus.h>
#if ((SCSI_DATA_UNKNOWN == SBUS_DMA_BIDIRECTIONAL) && (SCSI_DATA_WRITE == SBUS_DMA_TODEVICE) && (SCSI_DATA_READ == SBUS_DMA_FROMDEVICE) && (SCSI_DATA_NONE == SBUS_DMA_NONE))
#define scsi_to_sbus_dma_dir(scsi_dir) ((int)(scsi_dir))
#else
extern __inline__ int scsi_to_sbus_dma_dir(unsigned char scsi_dir)
{
if (scsi_dir == SCSI_DATA_UNKNOWN)
return SBUS_DMA_BIDIRECTIONAL;
if (scsi_dir == SCSI_DATA_WRITE)
return SBUS_DMA_TODEVICE;
if (scsi_dir == SCSI_DATA_READ)
return SBUS_DMA_FROMDEVICE;
return SBUS_DMA_NONE;
}
#endif
#endif
/* /*
* Some defs, in case these are not defined elsewhere. * Some defs, in case these are not defined elsewhere.
*/ */
...@@ -227,6 +179,21 @@ extern int scsi_sysfs_modify_sdev_attribute(struct device_attribute ***dev_attrs ...@@ -227,6 +179,21 @@ extern int scsi_sysfs_modify_sdev_attribute(struct device_attribute ***dev_attrs
extern int scsi_sysfs_modify_shost_attribute(struct class_device_attribute ***class_attrs, extern int scsi_sysfs_modify_shost_attribute(struct class_device_attribute ***class_attrs,
struct class_device_attribute *attr); struct class_device_attribute *attr);
/*
* Legacy dma direction interfaces.
*
* This assumes the pci/sbus dma mapping flags have the same numercial
* values as the generic dma-mapping ones. Currently they have but there's
* no way to check. Better don't use these interfaces!
*/
#define SCSI_DATA_UNKNOWN (DMA_BIDIRECTIONAL)
#define SCSI_DATA_WRITE (DMA_TO_DEVICE)
#define SCSI_DATA_READ (DMA_FROM_DEVICE)
#define SCSI_DATA_NONE (DMA_NONE)
#define scsi_to_pci_dma_dir(scsi_dir) ((int)(scsi_dir))
#define scsi_to_sbus_dma_dir(scsi_dir) ((int)(scsi_dir))
/* /*
* This is the crap from the old error handling code. We have it in a special * This is the crap from the old error handling code. We have it in a special
* place so that we can more easily delete it later on. * place so that we can more easily delete it later on.
......
...@@ -532,14 +532,14 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout) ...@@ -532,14 +532,14 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
static int scsi_request_sense(struct scsi_cmnd *scmd) static int scsi_request_sense(struct scsi_cmnd *scmd)
{ {
static unsigned char generic_sense[6] = static unsigned char generic_sense[6] =
{REQUEST_SENSE, 0, 0, 0, 254, 0}; {REQUEST_SENSE, 0, 0, 0, 252, 0};
unsigned char *scsi_result; unsigned char *scsi_result;
int saved_result; int saved_result;
int rtn; int rtn;
memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense)); memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense));
scsi_result = kmalloc(254, GFP_ATOMIC | (scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0); scsi_result = kmalloc(252, GFP_ATOMIC | (scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0);
if (unlikely(!scsi_result)) { if (unlikely(!scsi_result)) {
...@@ -555,14 +555,14 @@ static int scsi_request_sense(struct scsi_cmnd *scmd) ...@@ -555,14 +555,14 @@ static int scsi_request_sense(struct scsi_cmnd *scmd)
* address (db). 0 is not a valid sense code. * address (db). 0 is not a valid sense code.
*/ */
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer)); memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
memset(scsi_result, 0, 254); memset(scsi_result, 0, 252);
saved_result = scmd->result; saved_result = scmd->result;
scmd->request_buffer = scsi_result; scmd->request_buffer = scsi_result;
scmd->request_bufflen = 254; scmd->request_bufflen = 252;
scmd->use_sg = 0; scmd->use_sg = 0;
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
scmd->sc_data_direction = SCSI_DATA_READ; scmd->sc_data_direction = DMA_FROM_DEVICE;
scmd->underflow = 0; scmd->underflow = 0;
rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT); rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
...@@ -742,7 +742,7 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd) ...@@ -742,7 +742,7 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd)
scmd->use_sg = 0; scmd->use_sg = 0;
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
scmd->underflow = 0; scmd->underflow = 0;
scmd->sc_data_direction = SCSI_DATA_NONE; scmd->sc_data_direction = DMA_NONE;
rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT); rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
...@@ -1338,7 +1338,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) ...@@ -1338,7 +1338,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
if (unlikely(!sreq)) { if (unlikely(!sreq)) {
printk(KERN_ERR "%s: request allocate failed," printk(KERN_ERR "%s: request allocate failed,"
"prevent media removal cmd not sent", __FUNCTION__); "prevent media removal cmd not sent\n", __FUNCTION__);
return; return;
} }
...@@ -1348,7 +1348,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) ...@@ -1348,7 +1348,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
sreq->sr_cmnd[3] = 0; sreq->sr_cmnd[3] = 0;
sreq->sr_cmnd[4] = SCSI_REMOVAL_PREVENT; sreq->sr_cmnd[4] = SCSI_REMOVAL_PREVENT;
sreq->sr_cmnd[5] = 0; sreq->sr_cmnd[5] = 0;
sreq->sr_data_direction = SCSI_DATA_NONE; sreq->sr_data_direction = DMA_NONE;
sreq->sr_bufflen = 0; sreq->sr_bufflen = 0;
sreq->sr_buffer = NULL; sreq->sr_buffer = NULL;
sreq->sr_allowed = 5; sreq->sr_allowed = 5;
...@@ -1723,7 +1723,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag) ...@@ -1723,7 +1723,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
scmd->cmd_len = 0; scmd->cmd_len = 0;
scmd->sc_data_direction = SCSI_DATA_UNKNOWN; scmd->sc_data_direction = DMA_BIDIRECTIONAL;
scmd->sc_request = NULL; scmd->sc_request = NULL;
scmd->sc_magic = SCSI_CMND_MAGIC; scmd->sc_magic = SCSI_CMND_MAGIC;
......
...@@ -104,7 +104,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, ...@@ -104,7 +104,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
return -ENOMEM; return -ENOMEM;
} }
sreq->sr_data_direction = SCSI_DATA_NONE; sreq->sr_data_direction = DMA_NONE;
scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result)); SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result));
...@@ -258,19 +258,19 @@ int scsi_ioctl_send_command(struct scsi_device *sdev, ...@@ -258,19 +258,19 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
return -ENOMEM; return -ENOMEM;
memset(buf, 0, buf_needed); memset(buf, 0, buf_needed);
if (inlen == 0) { if (inlen == 0) {
data_direction = SCSI_DATA_READ; data_direction = DMA_FROM_DEVICE;
} else if (outlen == 0 ) { } else if (outlen == 0 ) {
data_direction = SCSI_DATA_WRITE; data_direction = DMA_TO_DEVICE;
} else { } else {
/* /*
* Can this ever happen? * Can this ever happen?
*/ */
data_direction = SCSI_DATA_UNKNOWN; data_direction = DMA_BIDIRECTIONAL;
} }
} else { } else {
buf = NULL; buf = NULL;
data_direction = SCSI_DATA_NONE; data_direction = DMA_NONE;
} }
/* /*
...@@ -322,7 +322,7 @@ int scsi_ioctl_send_command(struct scsi_device *sdev, ...@@ -322,7 +322,7 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
} }
sreq = scsi_allocate_request(sdev); sreq = scsi_allocate_request(sdev);
if (sreq) { if (!sreq) {
result = -EINTR; result = -EINTR;
goto error; goto error;
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
#include <scsi/scsi_driver.h>
#include "scsi_priv.h" #include "scsi_priv.h"
#include "scsi_logging.h" #include "scsi_logging.h"
...@@ -1094,14 +1095,17 @@ static inline int scsi_host_queue_ready(struct request_queue *q, ...@@ -1094,14 +1095,17 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
return 0; return 0;
} }
} }
if (!list_empty(&sdev->starved_entry))
return 0;
if ((shost->can_queue > 0 && shost->host_busy >= shost->can_queue) || if ((shost->can_queue > 0 && shost->host_busy >= shost->can_queue) ||
shost->host_blocked || shost->host_self_blocked) { shost->host_blocked || shost->host_self_blocked) {
if (list_empty(&sdev->starved_entry))
list_add_tail(&sdev->starved_entry, &shost->starved_list); list_add_tail(&sdev->starved_entry, &shost->starved_list);
return 0; return 0;
} }
/* We're OK to process the command, so we can't be starved */
if (!list_empty(&sdev->starved_entry))
list_del_init(&sdev->starved_entry);
return 1; return 1;
} }
...@@ -1128,6 +1132,7 @@ static void scsi_request_fn(struct request_queue *q) ...@@ -1128,6 +1132,7 @@ static void scsi_request_fn(struct request_queue *q)
* the host is no longer able to accept any more requests. * the host is no longer able to accept any more requests.
*/ */
while (!blk_queue_plugged(q)) { while (!blk_queue_plugged(q)) {
int rtn;
/* /*
* get next queueable request. We do this early to make sure * get next queueable request. We do this early to make sure
* that the request is fully prepared even if we cannot * that the request is fully prepared even if we cannot
...@@ -1181,8 +1186,17 @@ static void scsi_request_fn(struct request_queue *q) ...@@ -1181,8 +1186,17 @@ static void scsi_request_fn(struct request_queue *q)
/* /*
* Dispatch the command to the low-level driver. * Dispatch the command to the low-level driver.
*/ */
scsi_dispatch_cmd(cmd); rtn = scsi_dispatch_cmd(cmd);
spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock);
if(rtn) {
/* we're refusing the command; because of
* the way locks get dropped, we need to
* check here if plugging is required */
if(sdev->device_busy == 0)
blk_plug_device(q);
break;
}
} }
return; return;
...@@ -1203,6 +1217,8 @@ static void scsi_request_fn(struct request_queue *q) ...@@ -1203,6 +1217,8 @@ static void scsi_request_fn(struct request_queue *q)
blk_queue_end_tag(q, req); blk_queue_end_tag(q, req);
__elv_add_request(q, req, 0, 0); __elv_add_request(q, req, 0, 0);
sdev->device_busy--; sdev->device_busy--;
if(sdev->device_busy == 0)
blk_plug_device(q);
} }
u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost)
...@@ -1336,3 +1352,127 @@ void scsi_exit_queue(void) ...@@ -1336,3 +1352,127 @@ void scsi_exit_queue(void)
kmem_cache_destroy(sgp->slab); kmem_cache_destroy(sgp->slab);
} }
} }
/**
* __scsi_mode_sense - issue a mode sense, falling back from 10 to
* six bytes if necessary.
* @sreq: SCSI request to fill in with the MODE_SENSE
* @dbd: set if mode sense will allow block descriptors to be returned
* @modepage: mode page being requested
* @buffer: request buffer (may not be smaller than eight bytes)
* @len: length of request buffer.
* @timeout: command timeout
* @retries: number of retries before failing
* @data: returns a structure abstracting the mode header data
*
* Returns zero if unsuccessful, or the header offset (either 4
* or 8 depending on whether a six or ten byte command was
* issued) if successful.
**/
int
__scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage,
unsigned char *buffer, int len, int timeout, int retries,
struct scsi_mode_data *data) {
unsigned char cmd[12];
int use_10_for_ms;
int header_length;
memset(data, 0, sizeof(*data));
memset(&cmd[0], 0, 12);
cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */
cmd[2] = modepage;
retry:
use_10_for_ms = sreq->sr_device->use_10_for_ms;
if (use_10_for_ms) {
if (len < 8)
len = 8;
cmd[0] = MODE_SENSE_10;
cmd[8] = len;
header_length = 8;
} else {
if (len < 4)
len = 4;
cmd[0] = MODE_SENSE;
cmd[4] = len;
header_length = 4;
}
sreq->sr_cmd_len = 0;
sreq->sr_sense_buffer[0] = 0;
sreq->sr_sense_buffer[2] = 0;
sreq->sr_data_direction = DMA_FROM_DEVICE;
memset(buffer, 0, len);
scsi_wait_req(sreq, cmd, buffer, len, timeout, retries);
/* This code looks awful: what it's doing is making sure an
* ILLEGAL REQUEST sense return identifies the actual command
* byte as the problem. MODE_SENSE commands can return
* ILLEGAL REQUEST if the code page isn't supported */
if (use_10_for_ms && ! scsi_status_is_good(sreq->sr_result) &&
(driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
sreq->sr_sense_buffer[2] == ILLEGAL_REQUEST &&
(sreq->sr_sense_buffer[4] & 0x40) == 0x40 &&
sreq->sr_sense_buffer[5] == 0 &&
sreq->sr_sense_buffer[6] == 0 ) {
sreq->sr_device->use_10_for_ms = 0;
goto retry;
}
if(scsi_status_is_good(sreq->sr_result)) {
data->header_length = header_length;
if(use_10_for_ms) {
data->length = buffer[0]*256 + buffer[1];
data->medium_type = buffer[2];
data->device_specific = buffer[3];
data->longlba = buffer[4] & 0x01;
data->block_descriptor_length = buffer[6]*256
+ buffer[7];
} else {
data->length = buffer[0];
data->medium_type = buffer[1];
data->device_specific = buffer[3];
data->block_descriptor_length = buffer[4];
}
}
return sreq->sr_result;
}
/**
* scsi_mode_sense - issue a mode sense, falling back from 10 to
* six bytes if necessary.
* @sdev: scsi device to send command to.
* @dbd: set if mode sense will disable block descriptors in the return
* @modepage: mode page being requested
* @buffer: request buffer (may not be smaller than eight bytes)
* @len: length of request buffer.
* @timeout: command timeout
* @retries: number of retries before failing
*
* Returns zero if unsuccessful, or the header offset (either 4
* or 8 depending on whether a six or ten byte command was
* issued) if successful.
**/
int
scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
unsigned char *buffer, int len, int timeout, int retries,
struct scsi_mode_data *data)
{
struct scsi_request *sreq = scsi_allocate_request(sdev);
int ret;
if (!sreq)
return -1;
ret = __scsi_mode_sense(sreq, dbd, modepage, buffer, len,
timeout, retries, data);
scsi_release_request(sreq);
return ret;
}
This diff is collapsed.
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <asm/dma.h> #include <asm/dma.h>
#include "scsi.h" #include "scsi.h"
#include <scsi/scsi_driver.h>
#include <scsi/scsi_ioctl.h> #include <scsi/scsi_ioctl.h>
#include "hosts.h" #include "hosts.h"
#include "scsi_logging.h" #include "scsi_logging.h"
...@@ -86,6 +87,9 @@ EXPORT_SYMBOL(scsi_add_device); ...@@ -86,6 +87,9 @@ EXPORT_SYMBOL(scsi_add_device);
EXPORT_SYMBOL(scsi_remove_device); EXPORT_SYMBOL(scsi_remove_device);
EXPORT_SYMBOL(scsi_set_device_offline); EXPORT_SYMBOL(scsi_set_device_offline);
EXPORT_SYMBOL(__scsi_mode_sense);
EXPORT_SYMBOL(scsi_mode_sense);
/* /*
* This symbol is for the highlevel drivers (e.g. sg) only. * This symbol is for the highlevel drivers (e.g. sg) only.
*/ */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#define SEAGATE_H #define SEAGATE_H
static int seagate_st0x_detect(Scsi_Host_Template *); static int seagate_st0x_detect(Scsi_Host_Template *);
static int seagate_st0x_command(Scsi_Cmnd *);
static int seagate_st0x_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int seagate_st0x_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
static int seagate_st0x_abort(Scsi_Cmnd *); static int seagate_st0x_abort(Scsi_Cmnd *);
......
...@@ -64,6 +64,7 @@ static int sg_version_num = 30529; /* 2 digits for each component */ ...@@ -64,6 +64,7 @@ static int sg_version_num = 30529; /* 2 digits for each component */
#include <linux/blk.h> #include <linux/blk.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
#include <scsi/scsi_driver.h>
#include <scsi/scsi_ioctl.h> #include <scsi/scsi_ioctl.h>
#include <scsi/sg.h> #include <scsi/sg.h>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment