Commit 3793c9b9 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.2.5

parent 98c4b45f
VERSION = 1
PATCHLEVEL = 2
SUBLEVEL = 4
SUBLEVEL = 5
ARCH = i386
......
......@@ -124,15 +124,15 @@ COMPILING the kernel:
floppy.
If you boot Linux from the hard drive, chances are you use LILO which
uses the kernel image as specified in the file /etc/lilo/config. The
uses the kernel image as specified in the file /etc/lilo.conf. The
kernel image file is usually /vmlinuz, or /zImage, or /etc/zImage.
To use the new kernel, copy the new image over the old one (save a
backup of the original!). Then, you MUST RERUN LILO to update the
loading map!! If you don't, you won't be able to boot the new kernel
image.
Reinstalling LILO is usually a matter of running /etc/lilo/install.
You may wish to edit /etc/lilo/config to specify an entry for your
Reinstalling LILO is usually a matter of running /sbin/lilo.
You may wish to edit /etc/lilo.conf to specify an entry for your
old kernel image (say, /vmlinux.old) in case the new one does not
work. See the LILO docs for more information.
......
......@@ -169,20 +169,40 @@ static inline struct request * get_request(int n, int dev)
/*
* wait until a free request in the first N entries is available.
* NOTE: interrupts must be disabled on the way in, and will still
* be disabled on the way out.
*/
static inline struct request * get_request_wait(int n, int dev)
static struct request * __get_request_wait(int n, int dev)
{
register struct request *req;
struct wait_queue wait = { current, NULL };
while ((req = get_request(n, dev)) == NULL) {
add_wait_queue(&wait_for_request, &wait);
for (;;) {
unplug_device(MAJOR(dev)+blk_dev);
sleep_on(&wait_for_request);
current->state = TASK_UNINTERRUPTIBLE;
cli();
req = get_request(n, dev);
sti();
if (req)
break;
schedule();
}
remove_wait_queue(&wait_for_request, &wait);
current->state = TASK_RUNNING;
return req;
}
static inline struct request * get_request_wait(int n, int dev)
{
register struct request *req;
cli();
req = get_request(n, dev);
sti();
if (req)
return req;
return __get_request_wait(n, dev);
}
/* RO fail safe mechanism */
static long ro_bits[MAX_BLKDEV][8];
......@@ -303,9 +323,7 @@ static void make_request(int major,int rw, struct buffer_head * bh)
*/
max_req = (rw == READ) ? NR_REQUEST : ((NR_REQUEST*2)/3);
/* big loop: look for a free request. */
repeat:
/* look for a free request. */
cli();
/* The scsi disk drivers and the IDE driver completely remove the request
......@@ -363,23 +381,17 @@ static void make_request(int major,int rw, struct buffer_head * bh)
/* find an unused request. */
req = get_request(max_req, bh->b_dev);
sti();
/* if no request available: if rw_ahead, forget it; otherwise try again. */
if (! req) {
/* if no request available: if rw_ahead, forget it; otherwise try again blocking.. */
if (!req) {
if (rw_ahead) {
sti();
unlock_buffer(bh);
return;
}
unplug_device(major+blk_dev);
sleep_on(&wait_for_request);
sti();
goto repeat;
req = __get_request_wait(max_req, bh->b_dev);
}
/* we found a request. */
sti();
/* fill up the request-info, and add it to the queue */
req->cmd = rw;
req->errors = 0;
......@@ -410,9 +422,7 @@ void ll_rw_page(int rw, int dev, int page, char * buffer)
printk("Can't page to read-only device 0x%X\n",dev);
return;
}
cli();
req = get_request_wait(NR_REQUEST, dev);
sti();
/* fill up the request-info, and add it to the queue */
req->cmd = rw;
req->errors = 0;
......@@ -533,9 +543,7 @@ void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buf)
for (i=0; i<nb; i++, buf += buffersize)
{
cli();
req = get_request_wait(NR_REQUEST, dev);
sti();
req->cmd = rw;
req->errors = 0;
req->sector = (b[i] * buffersize) >> 9;
......
Wed Apr 12 08:06:16 1995 Theodore Y. Ts'o <tytso@localhost>
* serial.c (do_serial_hangup, do_softint, check_modem_status,
rs_init): Hangups are now scheduled via a separate tqueue
structure in the async_struct structure, tqueue_hangup.
This task is pushed on to the tq_schedule queue, so that
it is processed syncronously by the scheduler.
Sat Feb 18 12:13:51 1995 Theodore Y. Ts'o (tytso@rt-11)
* tty_io.c (disassociate_ctty, tty_open, tty_ioctl): Clear
......
......@@ -468,7 +468,8 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
#ifdef SERIAL_DEBUG_OPEN
printk("scheduling hangup...");
#endif
rs_sched_event(info, RS_EVENT_HANGUP);
queue_task_irq_off(&info->tqueue_hangup,
&tq_scheduler);
}
}
if (info->flags & ASYNC_CTS_FLOW) {
......@@ -722,12 +723,6 @@ static void do_softint(void *private_)
if (!tty)
return;
if (clear_bit(RS_EVENT_HANGUP, &info->event)) {
tty_hangup(tty);
wake_up_interruptible(&info->open_wait);
info->flags &= ~(ASYNC_NORMAL_ACTIVE|
ASYNC_CALLOUT_ACTIVE);
}
if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
......@@ -736,6 +731,28 @@ static void do_softint(void *private_)
}
}
/*
* This routine is called from the scheduler tqueue when the interrupt
* routine has signalled that a hangup has occured. The path of
* hangup processing is:
*
* serial interrupt routine -> (scheduler tqueue) ->
* do_serial_hangup() -> tty->hangup() -> rs_hangup()
*
*/
static void do_serial_hangup(void *private_)
{
struct async_struct *info = (struct async_struct *) private_;
struct tty_struct *tty;
tty = info->tty;
if (!tty)
return;
tty_hangup(tty);
}
/*
* This subroutine is called when the RS_TIMER goes off. It is used
* by the serial driver to handle ports that do not have an interrupt
......@@ -2615,6 +2632,8 @@ long rs_init(long kmem_start)
info->blocked_open = 0;
info->tqueue.routine = do_softint;
info->tqueue.data = info;
info->tqueue_hangup.routine = do_serial_hangup;
info->tqueue_hangup.data = info;
info->callout_termios =callout_driver.init_termios;
info->normal_termios = serial_driver.init_termios;
info->open_wait = 0;
......
......@@ -913,7 +913,7 @@ lance_rx(struct device *dev)
lp->rx_ring[entry].base &= 0x03ffffff;
} else {
/* Malloc up new buffer, compatible with net-2e. */
short pkt_len = lp->rx_ring[entry].msg_length;
short pkt_len = (lp->rx_ring[entry].msg_length & 0xfff)-4;
struct sk_buff *skb;
skb = alloc_skb(pkt_len, GFP_ATOMIC);
......
#define rw_bugfix
/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
/*
Written 1992-94 by Donald Becker.
......@@ -375,6 +376,7 @@ ne_block_output(struct device *dev, int count,
{
int retries = 0;
int nic_base = NE_BASE;
unsigned long flags;
/* Round the count up for word writes. Do we need to do this?
What effect will an odd byte count have on the 8390?
......@@ -415,8 +417,13 @@ ne_block_output(struct device *dev, int count,
race condition will munge the remote byte count values, and then
the ne2k will hang the machine by holding I/O CH RDY because it
expects more data. Hopefully fixes the lockups. -- Paul Gortmaker.
Use save_flags/cli/restore_flags rather than cli/sti to avoid risk
of accidentally enabling interrupts which were disabled when we
were entered. Dave Platt <dplatt@3do.com>
*/
save_flags(flags);
cli();
outb_p(count & 0xff, nic_base + EN0_RCNTLO);
outb_p(count >> 8, nic_base + EN0_RCNTHI);
......@@ -429,7 +436,7 @@ ne_block_output(struct device *dev, int count,
} else {
outsb(NE_BASE + NE_DATAPORT, buf, count);
}
sti();
restore_flags(flags);
#ifdef CONFIG_NE_SANITY
/* This was for the ALPHA version only, but enough people have
......
......@@ -71,7 +71,7 @@ struct net_local
extern int wavelan_probe(device *); /* See Space.c */
static char *version = "wavelan.c:v6 22/2/95\n";
static char *version = "wavelan.c:v7 95/4/8\n";
/*
* Entry point forward declarations.
......@@ -508,6 +508,9 @@ wavelan_hardware_reset(device *dev)
ac_cfg_t cfg;
ac_ias_t ias;
if (wavelan_debug > 0)
printk("%s: ->wavelan_hardware_reset(dev=0x%x)\n", dev->name, (unsigned int)dev);
ioaddr = dev->base_addr;
lp = (net_local *)dev->priv;
......@@ -565,7 +568,12 @@ wavelan_hardware_reset(device *dev)
}
if (i <= 0)
{
printk("%s: wavelan_hardware_reset(): iscp_busy timeout.\n", dev->name);
if (wavelan_debug > 0)
printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name);
return -1;
}
for (i = 15; i > 0; i--)
{
......@@ -578,7 +586,12 @@ wavelan_hardware_reset(device *dev)
}
if (i <= 0)
{
printk("%s: wavelan_hardware_reset(): status: expected 0x%02x, got 0x%02x.\n", dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status);
if (wavelan_debug > 0)
printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name);
return -1;
}
wavelan_ack(dev);
......@@ -588,12 +601,18 @@ wavelan_hardware_reset(device *dev)
obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
if (wavelan_synchronous_cmd(dev, "diag()") == -1)
{
if (wavelan_debug > 0)
printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name);
return -1;
}
obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
if (cb.ac_status & AC_SFLD_FAIL)
{
printk("%s: wavelan_hardware_reset(): i82586 Self Test failed.\n", dev->name);
if (wavelan_debug > 0)
printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name);
return -1;
}
......@@ -654,7 +673,12 @@ wavelan_hardware_reset(device *dev)
obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cfg, sizeof(cfg));
if (wavelan_synchronous_cmd(dev, "reset()-configure") == -1)
{
if (wavelan_debug > 0)
printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name);
return -1;
}
memset(&ias, 0x00, sizeof(ias));
ias.ias_h.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_ia_setup);
......@@ -663,19 +687,24 @@ wavelan_hardware_reset(device *dev)
obram_write(ioaddr, OFFSET_CU, (unsigned char *)&ias, sizeof(ias));
if (wavelan_synchronous_cmd(dev, "reset()-address") == -1)
{
if (wavelan_debug > 0)
printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name);
return -1;
}
wavelan_ints_on(dev);
if (wavelan_debug > 4)
{
wavelan_scb_show(ioaddr);
printk("%s: Initialized WaveLAN.\n", dev->name);
}
wavelan_ru_start(dev);
wavelan_cu_start(dev);
if (wavelan_debug > 0)
printk("%s: <-wavelan_hardware_reset(): 0\n", dev->name);
return 0;
}
......@@ -708,6 +737,7 @@ int
wavelan_probe(device *dev)
{
int i;
int r;
short base_addr;
static unsigned short iobase[] =
{
......@@ -721,10 +751,17 @@ wavelan_probe(device *dev)
0x390,
};
if (wavelan_debug > 0)
printk("%s: ->wavelan_probe(dev=0x%x (base_addr=0x%x))\n", dev->name, (unsigned int)dev, (unsigned int)dev->base_addr);
#if STRUCT_CHECK == 1
if (wavelan_struct_check() != (char *)0)
{
printk("%s: structure/compiler botch: \"%s\"\n", dev->name, wavelan_struct_check());
if (wavelan_debug > 0)
printk("%s: <-wavelan_probe(): ENODEV\n", dev->name);
return ENODEV;
}
#endif /* STRUCT_CHECK == 1 */
......@@ -732,16 +769,25 @@ wavelan_probe(device *dev)
base_addr = dev->base_addr;
if (base_addr < 0)
{
/*
* Don't probe at all.
*/
if (wavelan_debug > 0)
printk("%s: <-wavelan_probe(): ENXIO\n", dev->name);
return ENXIO;
}
if (base_addr > 0x100)
{
/*
* Check a single specified location.
*/
return wavelan_probe1(dev, base_addr);
r = wavelan_probe1(dev, base_addr);
if (wavelan_debug > 0)
printk("%s: <-wavelan_probe(): %d\n", dev->name, r);
return r;
}
for (i = 0; i < nels(iobase); i++)
{
......@@ -749,9 +795,16 @@ wavelan_probe(device *dev)
continue;
if (wavelan_probe1(dev, iobase[i]) == 0)
{
if (wavelan_debug > 0)
printk("%s: <-wavelan_probe(): 0\n", dev->name);
return 0;
}
}
if (wavelan_debug > 0)
printk("%s: <-wavelan_probe(): ENODEV\n", dev->name);
return ENODEV;
}
......@@ -764,6 +817,9 @@ wavelan_probe1(device *dev, unsigned short ioaddr)
int i;
net_local *lp;
if (wavelan_debug > 0)
printk("%s: ->wavelan_probe1(dev=0x%x, ioaddr=0x%x)\n", dev->name, (unsigned int)dev, ioaddr);
wavelan_reset(ioaddr);
psa_read(ioaddr, HACR_DEFAULT, 0, (unsigned char *)&psa, sizeof(psa));
......@@ -780,13 +836,19 @@ wavelan_probe1(device *dev, unsigned short ioaddr)
||
psa.psa_univ_mac_addr[2] != SA_ADDR2
)
{
if (wavelan_debug > 0)
printk("%s: <-wavelan_probe1(): ENODEV\n", dev->name);
return ENODEV;
}
printk("%s: WaveLAN at %#x,", dev->name, ioaddr);
if ((irq = wavelan_map_irq(ioaddr, psa.psa_int_req_no)) == -1)
{
printk(" could not wavelan_map_irq(0x%x, %d).\n", ioaddr, psa.psa_int_req_no);
if (wavelan_debug > 0)
printk("%s: <-wavelan_probe1(): EAGAIN\n", dev->name);
return EAGAIN;
}
......@@ -871,7 +933,7 @@ wavelan_probe1(device *dev, unsigned short ioaddr)
printk("\n");
if (wavelan_debug)
if (wavelan_debug > 0)
printk(version);
dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL);
......@@ -915,6 +977,9 @@ wavelan_probe1(device *dev, unsigned short ioaddr)
dev->mtu = WAVELAN_MTU;
if (wavelan_debug > 0)
printk("%s: <-wavelan_probe1(): 0\n", dev->name);
return 0;
}
......@@ -1074,12 +1139,21 @@ wavelan_open(device *dev)
{
unsigned short ioaddr;
net_local *lp;
unsigned long x;
int r;
if (wavelan_debug > 0)
printk("%s: ->wavelan_open(dev=0x%x)\n", dev->name, (unsigned int)dev);
ioaddr = dev->base_addr;
lp = (net_local *)dev->priv;
if (dev->irq == 0)
{
if (wavelan_debug > 0)
printk("%s: <-wavelan_open(): -ENXIO\n", dev->name);
return -ENXIO;
}
if
(
......@@ -1092,23 +1166,35 @@ wavelan_open(device *dev)
)
{
irq2dev_map[dev->irq] = (device *)0;
if (wavelan_debug > 0)
printk("%s: <-wavelan_open(): -EAGAIN\n", dev->name);
return -EAGAIN;
}
if (wavelan_hardware_reset(dev) == -1)
x = wavelan_splhi();
if ((r = wavelan_hardware_reset(dev)) != -1)
{
dev->interrupt = 0;
dev->start = 1;
}
wavelan_splx(x);
if (r == -1)
{
free_irq(dev->irq);
irq2dev_map[dev->irq] = (device *)0;
if (wavelan_debug > 0)
printk("%s: <-wavelan_open(): -EAGAIN(2)\n", dev->name);
return -EAGAIN;
}
dev->interrupt = 0;
dev->start = 1;
#if defined(MODULE)
MOD_INC_USE_COUNT;
#endif /* defined(MODULE) */
if (wavelan_debug > 0)
printk("%s: <-wavelan_open(): 0\n", dev->name);
return 0;
}
......@@ -1438,7 +1524,7 @@ wavelan_receive(device *dev)
}
#endif /* 0 */
if (wavelan_debug > 0)
if (wavelan_debug > 5)
{
unsigned char addr[WAVELAN_ADDR_SIZE];
unsigned short ltype;
......@@ -1723,14 +1809,14 @@ wavelan_interrupt(int irq, struct pt_regs *regs)
* This will clear it -- ignored for now.
*/
mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status, sizeof(dce_status));
if (wavelan_debug > 4)
if (wavelan_debug > 0)
printk("%s: warning: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n", dev->name, dce_status);
}
if ((hasr & HASR_82586_INTR) == 0)
{
dev->interrupt = 0;
if (wavelan_debug > 4)
if (wavelan_debug > 0)
printk("%s: warning: wavelan_interrupt() but (hasr & HASR_82586_INTR) == 0.\n", dev->name);
return;
}
......@@ -1746,7 +1832,7 @@ wavelan_interrupt(int irq, struct pt_regs *regs)
set_chan_attn(ioaddr, lp->hacr);
if (wavelan_debug > 4)
if (wavelan_debug > 5)
printk("%s: interrupt, status 0x%04x.\n", dev->name, status);
if ((status & SCB_ST_CX) == SCB_ST_CX)
......@@ -1804,6 +1890,9 @@ wavelan_close(device *dev)
net_local *lp;
unsigned short scb_cmd;
if (wavelan_debug > 0)
printk("%s: ->wavelan_close(dev=0x%x)\n", dev->name, (unsigned int)dev);
ioaddr = dev->base_addr;
lp = (net_local *)dev->priv;
......@@ -1831,6 +1920,9 @@ wavelan_close(device *dev)
MOD_DEC_USE_COUNT;
#endif /* defined(MODULE) */
if (wavelan_debug > 0)
printk("%s: <-wavelan_close(): 0\n", dev->name);
return 0;
}
......@@ -1856,6 +1948,9 @@ wavelan_set_multicast_list(device *dev, int num_addrs, void *addrs)
net_local *lp;
unsigned long x;
if (wavelan_debug > 0)
printk("%s: ->wavelan_set_multicast_list(dev=0x%x, num_addrs=%d, addrs=0x%x)\n", dev->name, (unsigned int)dev, num_addrs, (unsigned int)addrs);
lp = (net_local *)dev->priv;
switch (num_addrs)
......@@ -1888,6 +1983,9 @@ wavelan_set_multicast_list(device *dev, int num_addrs, void *addrs)
*/
break;
}
if (wavelan_debug > 0)
printk("%s: <-wavelan_set_multicast_list()\n", dev->name);
}
/*
......@@ -2330,6 +2428,7 @@ wavelan_local_show(device *dev)
* Matthew Geier (matthew@cs.usyd.edu.au),
* Remo di Giovanni (remo@cs.usyd.edu.au),
* Eckhard Grah (grah@wrcs1.urz.uni-wuppertal.de),
* Vipul Gupta (vgupta@cs.binghamton.edu),
* Mark Hagan (mhagan@wtcpost.daytonoh.NCR.COM),
* Tim Nicholson (tim@cs.usyd.edu.au),
* Ian Parkin (ian@cs.usyd.edu.au),
......
......@@ -86,9 +86,11 @@ SCSI_OBJS := $(SCSI_OBJS) buslogic.o
SCSI_SRCS := $(SCSI_SRCS) buslogic.c
endif
SCSI_SRCS := $(SCSI_SRCS) eata_dma.c
ifdef CONFIG_SCSI_EATA_DMA
SCSI_OBJS := $(SCSI_OBJS) eata_dma.o
SCSI_SRCS := $(SCSI_SRCS) eata_dma.c
else
SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) eata_dma.o
endif
ifdef CONFIG_SCSI_U14_34F
......
......@@ -56,16 +56,18 @@
* BT-747D - 747S + differential termination.
* BT-757S - 747S + WIDE SCSI.
* BT-757D - 747D + WIDE SCSI.
* BT-445S - VESA bus-master FAST SCSI with active termination and floppy
* support.
* BT-445S - VESA bus-master FAST SCSI with active termination
* and floppy support.
* BT-445C - 445S + enhanced BIOS & firmware options.
* BT-946C - PCI bus-master FAST SCSI. (??? Nothing else known.)
* BT-946C - PCI bus-master FAST SCSI.
* BT-956C - PCI bus-master FAST/WIDE SCSI.
*
* ??? I believe other boards besides the 445 now have a "C" model, but I
* have no facts on them.
*
* This driver SHOULD support all of these boards. It has only been tested
* with a 747S and 445S.
* with a 747S, 445S, 946C, and 956C; there is no PCI-specific support as
* yet.
*
* Should you require further information on any of these boards, BusLogic
* can be reached at (408)492-9090. Their BBS # is (408)492-1984 (maybe BBS
......@@ -118,7 +120,7 @@
The test is believed to fail on at least some AMI BusLogic clones. */
/* #define BIOS_TRANSLATION_OVERRIDE BIOS_TRANSLATION_BIG */
#define BUSLOGIC_VERSION "1.14"
#define BUSLOGIC_VERSION "1.15"
/* Not a random value - if this is too large, the system hangs for a long time
waiting for something to happen if a board is not installed. */
......@@ -137,11 +139,13 @@
/* Since the SG list is malloced, we have to limit the length. */
#define BUSLOGIC_MAX_SG (BUSLOGIC_SG_MALLOC / sizeof (struct chain))
/* ??? Arbitrary. If we can dynamically allocate the mailbox arrays, I may
bump up this number. */
#define BUSLOGIC_MAILBOXES 16
/* Since the host adapters have room to buffer 32 commands internally, there
is some virtue in setting BUSLOGIC_MAILBOXES to 32. The maximum value
appears to be 255, since the Count parameter to the Initialize Extended
Mailbox command is limited to one byte. */
#define BUSLOGIC_MAILBOXES 32
#define BUSLOGIC_CMDLUN 4 /* ??? Arbitrary */
#define BUSLOGIC_CMDLUN 4 /* Arbitrary, but seems to work well. */
/* BusLogic boards can be configured for quite a number of port addresses (six
to be exact), but I generally do not want the driver poking around at
......@@ -165,8 +169,8 @@ static unsigned short bases[7] = {
struct hostdata {
unsigned int bus_type;
unsigned int bios_translation: 1; /* BIOS mapping (for compatibility) */
size_t last_mbi_used;
size_t last_mbo_used;
int last_mbi_used;
int last_mbo_used;
char model[7];
char firmware_rev[6];
Scsi_Cmnd *sc[BUSLOGIC_MAILBOXES];
......@@ -425,174 +429,131 @@ const char *buslogic_info(struct Scsi_Host *shpnt)
return "BusLogic SCSI driver " BUSLOGIC_VERSION;
}
/* A "high" level interrupt handler. */
/*
This is a major rewrite of the interrupt handler to support the newer
and faster PCI cards. While the previous interrupt handler was supposed
to handle multiple incoming becoming available mailboxes during the same
interrupt, my testing showed that in practice only a single mailbox was
ever made available. With the 946C and 956C, multiple incoming mailboxes
being ready for processing during a single interrupt occurs much more
frequently, and so care must be taken to avoid race conditions managing
the Host Adapter Interrupt Register, which can lead to lost interrupts.
Leonard N. Zubkoff, 23-Mar-95
*/
static void buslogic_interrupt(int irq, struct pt_regs * regs)
{
void (*my_done)(Scsi_Cmnd *) = NULL;
int errstatus, mbistatus = MBX_NOT_IN_USE, number_serviced, found;
size_t mbi, mbo = 0;
int mbi, saved_mbo[BUSLOGIC_MAILBOXES];
int base, interrupt_flags, found, i;
struct Scsi_Host *shpnt;
Scsi_Cmnd *sctmp;
unsigned long flags;
int base, flag;
int needs_restart;
struct mailbox *mb;
struct ccb *ccb;
shpnt = host[irq - 9];
if (!shpnt)
panic("buslogic_interrupt: NULL SCSI host entry");
if (shpnt == NULL)
panic("buslogic_interrupt: NULL SCSI host entry");
mb = HOSTDATA(shpnt)->mb;
ccb = HOSTDATA(shpnt)->ccbs;
base = shpnt->io_port;
#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
flag = inb(INTERRUPT(base));
buslogic_printk("");
if (!(flag & INTV))
printk("no interrupt? ");
if (flag & IMBL)
printk("IMBL ");
if (flag & MBOR)
printk("MBOR ");
if (flag & CMDC)
printk("CMDC ");
if (flag & RSTS)
printk("RSTS ");
printk("status %02X\n", inb(STATUS(base)));
#endif
/*
This interrupt handler is now specified to use the SA_INTERRUPT
protocol, so interrupts are inhibited on entry until explicitly
allowed again. Read the Host Adapter Interrupt Register, and
complain if there is no pending interrupt being signaled.
*/
number_serviced = 0;
needs_restart = 0;
interrupt_flags = inb(INTERRUPT(base));
for (;;) {
flag = inb(INTERRUPT(base));
/* Check for unusual interrupts. If any of these happen, we should
probably do something special, but for now just printing a message
is sufficient. A SCSI reset detected is something that we really
need to deal with in some way. */
if (flag & (MBOR | CMDC | RSTS)) {
buslogic_printk("unusual flag:");
if (flag & MBOR)
printk(" MBOR");
if (flag & CMDC)
printk(" CMDC");
if (flag & RSTS) {
needs_restart = 1;
printk(" RSTS");
}
printk("\n");
}
if (!(interrupt_flags & INTV))
{
buslogic_printk("interrupt received, but INTV not set\n");
return;
}
INTR_RESET(base);
/*
Reset the Host Adapter Interrupt Register. It appears to be
important that this is only done once per interrupt to avoid
losing interrupts under heavy loads.
*/
save_flags(flags);
cli();
INTR_RESET(base);
mbi = HOSTDATA(shpnt)->last_mbi_used + 1;
if (mbi >= 2 * BUSLOGIC_MAILBOXES)
mbi = BUSLOGIC_MAILBOXES;
if (interrupt_flags & RSTS)
{
restart(shpnt);
return;
}
/* I use the "found" variable as I like to keep cli/sti pairs at the
same block level. Debugging dropped sti's is no fun... */
/*
With interrupts still inhibited, scan through the incoming mailboxes
in strict round robin fashion saving the status information and
then freeing the mailbox. A second pass over the completed commands
will be made separately to complete their processing.
*/
found = FALSE;
do {
if (mb[mbi].status != MBX_NOT_IN_USE) {
found = TRUE;
break;
}
mbi++;
if (mbi >= 2 * BUSLOGIC_MAILBOXES)
mbi = BUSLOGIC_MAILBOXES;
} while (mbi != HOSTDATA(shpnt)->last_mbi_used);
if (found) {
mbo = (struct ccb *)mb[mbi].ccbptr - ccb;
mbistatus = mb[mbi].status;
mb[mbi].status = MBX_NOT_IN_USE;
HOSTDATA(shpnt)->last_mbi_used = mbi;
}
mbi = HOSTDATA(shpnt)->last_mbi_used + 1;
if (mbi >= 2*BUSLOGIC_MAILBOXES)
mbi = BUSLOGIC_MAILBOXES;
restore_flags(flags);
found = 0;
if (!found) {
/* Hmm, no mail. Must have read it the last time around. */
if (!number_serviced && !needs_restart)
buslogic_printk("interrupt received, but no mail.\n");
/* We detected a reset. Restart all pending commands for devices
that use the hard reset option. */
if (needs_restart)
restart(shpnt);
return;
}
while (mb[mbi].status != MBX_NOT_IN_USE && found < BUSLOGIC_MAILBOXES)
{
int mbo = (struct ccb *)mb[mbi].ccbptr - ccb;
int result = 0;
#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
if (ccb[mbo].tarstat || ccb[mbo].hastat)
buslogic_printk("returning %08X (status %d).\n",
((int)ccb[mbo].hastat << 16) | ccb[mbo].tarstat,
mb[mbi].status);
#endif
saved_mbo[found++] = mbo;
if (mbistatus == MBX_COMPLETION_NOT_FOUND)
continue;
if (mb[mbi].status != MBX_COMPLETION_OK)
result = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
buslogic_printk("...done %u %u\n", mbo, mbi);
#endif
HOSTDATA(shpnt)->sc[mbo]->result = result;
sctmp = HOSTDATA(shpnt)->sc[mbo];
mb[mbi].status = MBX_NOT_IN_USE;
if (!sctmp || !sctmp->scsi_done) {
buslogic_printk("unexpected interrupt.\n");
buslogic_printk("tarstat=%02X, hastat=%02X id=%d lun=%d ccb#=%u\n",
ccb[mbo].tarstat, ccb[mbo].hastat,
ccb[mbo].id, ccb[mbo].lun, mbo);
return;
}
HOSTDATA(shpnt)->last_mbi_used = mbi;
my_done = sctmp->scsi_done;
if (sctmp->host_scribble)
scsi_free(sctmp->host_scribble, BUSLOGIC_SG_MALLOC);
/* ??? more error checking left out here */
if (mbistatus != MBX_COMPLETION_OK) {
/* ??? This is surely wrong, but I don't know what's right. */
errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
} else
errstatus = 0;
#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
if (errstatus)
buslogic_printk("error: %04X %04X\n",
ccb[mbo].hastat, ccb[mbo].tarstat);
if (status_byte(ccb[mbo].tarstat) == CHECK_CONDITION) {
size_t i;
buslogic_printk("sense:");
for (i = 0; i < sizeof sctmp->sense_buffer; i++)
printk(" %02X", sctmp->sense_buffer[i]);
printk("\n");
}
if (++mbi >= 2*BUSLOGIC_MAILBOXES)
mbi = BUSLOGIC_MAILBOXES;
}
if (errstatus)
buslogic_printk("returning %08X.\n", errstatus);
#endif
/*
With interrupts no longer inhibited, iterate over the completed
commands freeing resources and calling the completion routines.
Since we exit upon completion of this loop, there is no need to
inhibit interrupts before exit, as this will be handled by the
fast interrupt assembly code we return to.
*/
sctmp->result = errstatus;
HOSTDATA(shpnt)->sc[mbo] = NULL; /* This effectively frees up
the mailbox slot, as far as
queuecommand is
concerned. */
my_done(sctmp);
number_serviced++;
}
sti();
for (i = 0; i < found; i++)
{
int mbo = saved_mbo[i];
sctmp = HOSTDATA(shpnt)->sc[mbo];
/*
First, free any storage allocated for a scatter/gather
data segment list.
*/
if (sctmp->host_scribble)
scsi_free(sctmp->host_scribble, BUSLOGIC_SG_MALLOC);
/*
Next, call the SCSI command completion handler.
*/
sctmp->scsi_done(sctmp);
/*
Finally, mark the SCSI Command as completed so it may be reused
for another command by buslogic_queuecommand.
*/
HOSTDATA(shpnt)->sc[mbo] = NULL;
}
}
/* ??? Why does queuecommand return a value? scsi.c never looks at it... */
int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *))
{
......@@ -605,9 +566,10 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *))
int bufflen = scpnt->request_bufflen;
int mbo;
unsigned long flags;
struct mailbox *mb;
struct ccb *ccb;
struct Scsi_Host *shpnt = scpnt->host;
struct mailbox *mb = HOSTDATA(shpnt)->mb;
struct ccb *ccb;
#if (BUSLOGIC_DEBUG & BD_COMMAND)
if (target > 1) {
......@@ -651,9 +613,6 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *))
}
#endif
mb = HOSTDATA(shpnt)->mb;
ccb = HOSTDATA(shpnt)->ccbs;
/* Use the outgoing mailboxes in a round-robin fashion, because this
is how the host adapter will scan for them. */
......@@ -693,12 +652,14 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *))
buslogic_printk("sending command (%d %08X)...", mbo, done);
#endif
ccb = &HOSTDATA(shpnt)->ccbs[mbo];
/* This gets trashed for some reason */
mb[mbo].ccbptr = &ccb[mbo];
mb[mbo].ccbptr = ccb;
memset(&ccb[mbo], 0, sizeof (struct ccb));
memset(ccb, 0, sizeof (struct ccb));
ccb[mbo].cdblen = scpnt->cmd_len; /* SCSI Command Descriptor
ccb->cdblen = scpnt->cmd_len; /* SCSI Command Descriptor
Block Length */
direction = 0;
......@@ -707,14 +668,14 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *))
else if (*cmd == WRITE_10 || *cmd == WRITE_6)
direction = 16;
memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
memcpy(ccb->cdb, cmd, ccb->cdblen);
if (scpnt->use_sg) {
struct scatterlist *sgpnt;
struct chain *cptr;
size_t i;
ccb[mbo].op = CCB_OP_INIT_SG; /* SCSI Initiator Command
ccb->op = CCB_OP_INIT_SG; /* SCSI Initiator Command
w/scatter-gather */
scpnt->host_scribble
= (unsigned char *)scsi_malloc(BUSLOGIC_SG_MALLOC);
......@@ -735,8 +696,8 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *))
cptr[i].dataptr = sgpnt[i].address;
cptr[i].datalen = sgpnt[i].length;
}
ccb[mbo].datalen = scpnt->use_sg * sizeof (struct chain);
ccb[mbo].dataptr = cptr;
ccb->datalen = scpnt->use_sg * sizeof (struct chain);
ccb->dataptr = cptr;
#if (BUSLOGIC_DEBUG & BD_COMMAND)
{
unsigned char *ptr;
......@@ -749,27 +710,26 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *))
}
#endif
} else {
ccb[mbo].op = CCB_OP_INIT; /* SCSI Initiator Command */
ccb->op = CCB_OP_INIT; /* SCSI Initiator Command */
scpnt->host_scribble = NULL;
CHECK_DMA_ADDR(shpnt->unchecked_isa_dma, buff, goto baddma);
ccb[mbo].datalen = bufflen;
ccb[mbo].dataptr = buff;
ccb->datalen = bufflen;
ccb->dataptr = buff;
}
ccb[mbo].id = target;
ccb[mbo].lun = lun;
ccb[mbo].dir = direction;
ccb[mbo].rsalen = sizeof scpnt->sense_buffer;
ccb[mbo].senseptr = scpnt->sense_buffer;
ccb[mbo].linkptr = NULL;
ccb[mbo].commlinkid = 0;
ccb->id = target;
ccb->lun = lun;
ccb->dir = direction;
ccb->rsalen = sizeof scpnt->sense_buffer;
ccb->senseptr = scpnt->sense_buffer;
/* ccbcontrol, commlinkid, and linkptr are 0 due to above memset. */
#if (BUSLOGIC_DEBUG & BD_COMMAND)
{
size_t i;
buslogic_printk("sending...");
for (i = 0; i < sizeof ccb[mbo] - 10; i++)
printk(" %02X", ((unsigned char *)&ccb[mbo])[i]);
for (i = 0; i < sizeof(struct ccb) - 10; i++)
printk(" %02X", ((unsigned char *)ccb)[i]);
printk("\n");
}
#endif
......@@ -1255,7 +1215,8 @@ int buslogic_detect(Scsi_Host_Template *tpnt)
save_flags(flags);
cli();
if (request_irq(irq, buslogic_interrupt, 0, "buslogic")) {
if (request_irq(irq, buslogic_interrupt,
SA_INTERRUPT, "buslogic")) {
buslogic_printk("unable to allocate IRQ for "
"BusLogic controller.\n");
restore_flags(flags);
......
......@@ -44,13 +44,14 @@
* Thanks also to Greg Hosler who did a lot of testing and *
* found quite a number of bugs during the development. *
************************************************************
* last change: 95/02/13 OS: Linux 1.1.91 or higher *
* last change: 95/04/10 OS: Linux 1.2.00 or higher *
************************************************************/
/* Look in eata_dma.h for configuration and revision information */
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
#endif
#include <linux/kernel.h>
......@@ -61,6 +62,7 @@
#include <linux/in.h>
#include <linux/bios32.h>
#include <linux/pci.h>
#include <asm/types.h>
#include <asm/io.h>
#include <asm/dma.h>
#include "../block/blk.h"
......@@ -87,10 +89,13 @@ static unchar reg_IRQ[] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static unchar reg_IRQL[] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static struct eata_sp status[MAXIRQ]; /* Statuspacket array */
static struct eata_sp *status = 0; /* Statuspacket array */
static void *dma_scratch = 0;
static uint internal_command_finished = TRUE;
static unchar HBA_interpret = FALSE;
static u32 fake_int_base;
static u32 fake_int_result;
static struct geom_emul geometry; /* Drive 1 & 2 geometry */
static ulong int_counter = 0;
......@@ -101,6 +106,14 @@ void eata_scsi_done (Scsi_Cmnd * SCpnt)
return;
}
void eata_fake_int_handler(s32 irq, struct pt_regs * regs)
{
fake_int_result = inb(fake_int_base + HA_RSTATUS);
DBG(DBG_INTR3, printk("eata_fake_int_handler called irq%ld base %#lx res %#lx\n",
irq, fake_int_base, fake_int_result));
return;
}
#if EATA_DMA_PROC
#include "eata_dma_proc.c"
#endif
......@@ -109,6 +122,9 @@ int eata_release(struct Scsi_Host *sh)
{
if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq);
else reg_IRQ[sh->irq]--;
scsi_init_free((void *)status, 512);
if (SD(sh)->channel == 0) {
if (sh->dma_channel != 0xff) free_dma(sh->dma_channel);
if (sh->io_port && sh->n_io_port)
......@@ -125,7 +141,7 @@ const char *eata_info(struct Scsi_Host *host)
void eata_int_handler(int irq, struct pt_regs * regs)
{
uint i, result;
uint i, result = 0;
uint hba_stat, scsi_stat, eata_stat;
Scsi_Cmnd *cmd;
struct eata_ccb *cp;
......@@ -183,21 +199,25 @@ void eata_int_handler(int irq, struct pt_regs * regs)
eata_stat, hba_stat));
switch (hba_stat) {
case 0x00: /* NO Error */
case HA_NO_ERROR: /* NO Error */
if (scsi_stat == CONDITION_GOOD
&& cmd->device->type == TYPE_DISK
&& (HD(cmd)->t_state[cmd->target] == RESET))
result = DID_BUS_BUSY << 16;
else if (scsi_stat == GOOD)
HD(cmd)->t_state[cmd->target] = FALSE;
else if (scsi_stat == CHECK_CONDITION
&& cmd->device->type == TYPE_DISK
&& (cmd->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
result = DID_BUS_BUSY << 16;
else
result = DID_OK << 16;
if (scsi_stat == GOOD)
HD(cmd)->t_state[cmd->target] = FALSE;
HD(cmd)->t_timeout[cmd->target] = 0;
HD(cmd)->t_timeout[cmd->target] = FALSE;
break;
case 0x01: /* Selection Timeout */
case HA_ERR_SEL_TO: /* Selection Timeout */
result = DID_BAD_TARGET << 16;
break;
case 0x02: /* Command Timeout */
case HA_ERR_CMD_TO: /* Command Timeout */
if (HD(cmd)->t_timeout[cmd->target] > 1)
result = DID_ERROR << 16;
else {
......@@ -205,7 +225,8 @@ void eata_int_handler(int irq, struct pt_regs * regs)
HD(cmd)->t_timeout[cmd->target]++;
}
break;
case 0x03: /* SCSI Bus Reset Received */
case HA_ERR_RESET: /* SCSI Bus Reset Received */
case HA_INIT_POWERUP: /* Initial Controller Power-up */
if (cmd->device->type != TYPE_TAPE)
result = DID_BUS_BUSY << 16;
else
......@@ -214,23 +235,19 @@ void eata_int_handler(int irq, struct pt_regs * regs)
for (i = 0; i < MAXTARGET; i++)
HD(cmd)->t_state[i] = RESET;
break;
case 0x07: /* Bus Parity Error */
case 0x0c: /* Controller Ram Parity */
case 0x04: /* Initial Controller Power-up */
case 0x05: /* Unexpected Bus Phase */
case 0x06: /* Unexpected Bus Free */
case 0x08: /* SCSI Hung */
case 0x09: /* Unexpected Message Reject */
case 0x0a: /* SCSI Bus Reset Stuck */
case 0x0b: /* Auto Request-Sense Failed */
case HA_UNX_BUSPHASE: /* Unexpected Bus Phase */
case HA_UNX_BUS_FREE: /* Unexpected Bus Free */
case HA_BUS_PARITY: /* Bus Parity Error */
case HA_SCSI_HUNG: /* SCSI Hung */
case HA_UNX_MSGRJCT: /* Unexpected Message Reject */
case HA_RESET_STUCK: /* SCSI Bus Reset Stuck */
case HA_RSENSE_FAIL: /* Auto Request-Sense Failed */
case HA_PARITY_ERR: /* Controller Ram Parity */
default:
result = DID_ERROR << 16;
break;
}
cmd->result = result | scsi_stat;
if (in_scan_scsis && scsi_stat == CHECK_CONDITION &&
(cmd->sense_buffer[2] & 0xf) == UNIT_ATTENTION)
cmd->result |= (DRIVER_SENSE << 24);
cmd->result = result | (scsi_stat << 1);
#if DBG_INTR2
if (scsi_stat || result || hba_stat || eata_stat != 0x50)
......@@ -262,14 +279,14 @@ inline uint eata_send_command(ulong addr, uint base, unchar command)
while (inb(base + HA_RAUXSTAT) & HA_ABUSY)
if (--loop == 0)
return(TRUE);
return(FALSE);
outb(addr & 0x000000ff, base + HA_WDMAADDR);
outb((addr & 0x0000ff00) >> 8, base + HA_WDMAADDR + 1);
outb((addr & 0x00ff0000) >> 16, base + HA_WDMAADDR + 2);
outb((addr & 0xff000000) >> 24, base + HA_WDMAADDR + 3);
outb(command, base + HA_WCOMMAND);
return(FALSE);
return(TRUE);
}
int eata_queue(Scsi_Cmnd * cmd, void *(done) (Scsi_Cmnd *))
......@@ -337,10 +354,10 @@ int eata_queue(Scsi_Cmnd * cmd, void *(done) (Scsi_Cmnd *))
case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE:
case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
case WRITE_6: case WRITE_10: case WRITE_VERIFY:
case 0x3f: case 0x41: case 0xb1:
case 0xb0: case 0xb2: case 0xaa:
case 0xae: case 0x24: case 0x38:
case 0x3d: case 0xb6:
case UPDATE_BLOCK: case WRITE_LONG: case WRITE_SAME:
case SEARCH_HIGH_12: case SEARCH_EQUAL_12: case SEARCH_LOW_12:
case WRITE_12: case WRITE_VERIFY_12: case SET_WINDOW:
case MEDIUM_SCAN: case SEND_VOLUME_TAG:
case 0xea: /* alternate number for WRITE LONG */
cp->DataOut = TRUE; /* Output mode */
break;
......@@ -376,7 +393,7 @@ int eata_queue(Scsi_Cmnd * cmd, void *(done) (Scsi_Cmnd *))
cp->cp_lun = cmd->lun;
cp->cp_dispri = TRUE;
cp->cp_identify = TRUE;
memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
memcpy(cp->cp_cdb, cmd->cmnd, cmd->cmd_len);
cp->cp_statDMA = htonl((ulong) &(hd->sp));
......@@ -384,7 +401,7 @@ int eata_queue(Scsi_Cmnd * cmd, void *(done) (Scsi_Cmnd *))
cp->cmd = cmd;
cmd->host_scribble = (char *)&hd->ccb[y];
if(eata_send_command((ulong) cp, (uint) sh->base, EATA_CMD_DMA_SEND_CP)) {
if(eata_send_command((ulong) cp, (uint) sh->base, EATA_CMD_DMA_SEND_CP) == FALSE) {
cmd->result = DID_ERROR << 16;
printk("eata_queue target %d, pid %ld, HBA busy, returning DID_ERROR, done.\n",
cmd->target, cmd->pid);
......@@ -494,8 +511,10 @@ int eata_reset(Scsi_Cmnd * cmd)
DBG(DBG_ABNORM && DBG_DELAY, DEL2(500));
return (SCSI_RESET_ERROR);
}
for (z = 0; z < MAXTARGET; z++)
for (z = 0; z < MAXTARGET; z++) {
HD(cmd)->t_state[z] = RESET;
HD(cmd)->t_timeout[z] = FALSE;
}
for (x = 0; x < cmd->host->can_queue; x++) {
......@@ -577,16 +596,21 @@ char * get_board_data(ulong base, uint irq, uint id)
{
struct eata_ccb cp;
struct eata_sp sp;
static char buff[256];
static char *buff;
u32 i;
buff = dma_scratch;
memset(&cp, 0, sizeof(struct eata_ccb));
memset(buff, 0, sizeof(buff));
memset(&sp, 0, sizeof(struct eata_sp));
memset(buff, 0, 256);
cp.DataIn = TRUE;
cp.Interpret = TRUE; /* Interpret command */
cp.cp_datalen = htonl(255);
cp.cp_dataDMA = htonl((long)buff);
cp.cp_dataDMA = htonl((s32)buff);
cp.cp_viraddr = &cp;
cp.cp_id = id;
cp.cp_lun = 0;
......@@ -600,9 +624,21 @@ char * get_board_data(ulong base, uint irq, uint id)
cp.cp_statDMA = htonl((ulong) &sp);
eata_send_command((ulong) &cp, (uint) base, EATA_CMD_DMA_SEND_CP);
while (!(inb(base + HA_RAUXSTAT) & HA_AIRQ));
if(inb((uint) base + HA_RSTATUS) & 1)
fake_int_base = base;
fake_int_result = 0;
eata_send_command((u32) &cp, (u32) base, EATA_CMD_DMA_SEND_CP);
i = jiffies + 300;
while (!fake_int_result && jiffies <= i)
/* nothing */;
DBG(DBG_INTR3, printk("fake_int_result: %#lx hbastat %#lx scsistat %#lx,"
" buff %p sp %p\n",
fake_int_result, (u32) (sp.hba_stat & 0x7f),
(u32) sp.scsi_stat, buff, &sp));
if (jiffies > i || (fake_int_result & 1))
return (NULL);
else
return (buff);
......@@ -610,7 +646,6 @@ char * get_board_data(ulong base, uint irq, uint id)
int check_blink_state(long base)
{
uint ret = 0;
uint loops = 10;
ulong blinkindicator = 0x42445054;
ulong state = 0x12345678;
......@@ -621,10 +656,13 @@ int check_blink_state(long base)
state = inl((uint) base + 1);
}
DBG(DBG_BLINK, printk("Did Blink check. Status: %d\n",
(state == oldstate) && (state == blinkindicator)));
if ((state == oldstate) && (state == blinkindicator))
ret = 1;
DBG(DBG_BLINK, printk("Did Blink check. Status: %d\n", ret));
return (ret);
return(TRUE);
else
return (FALSE);
}
int get_conf_PIO(struct eata_register *base, struct get_conf *buf)
......@@ -632,8 +670,14 @@ int get_conf_PIO(struct eata_register *base, struct get_conf *buf)
ulong loop = R_LIMIT;
ushort *p;
if(check_region((uint)base, 9))
u8 warning = FALSE;
if(check_region((int) base, 9)) {
if ((int)base == 0x1f0 || (int)base == 0x170) {
warning = 1;
} else
return (FALSE);
}
memset(buf, 0, sizeof(struct get_conf));
......@@ -665,11 +709,15 @@ int get_conf_PIO(struct eata_register *base, struct get_conf *buf)
while (inb((uint) base + HA_RSTATUS) & HA_SDRQ)
inw((uint) base + HA_RDATA);
if (warning == TRUE)
printk("Warning: HBA with IO on 0x%p dectected,\n"
" this IO space is already allocated, probably by the IDE driver.\n"
" This might lead to problems.", base);
return (TRUE);
}
} else {
printk("eata_dma: get_conf_PIO, error during transfer for HBA at %lx",
(long)base);
DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer "
"for HBA at %lx\n", (long)base));
}
return (FALSE);
}
......@@ -701,42 +749,14 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
DBG(DBG_REGISTER, print_config(gc));
if (!gc->DMA_support) {
printk("HBA at %#.8lx doesn't support DMA. Sorry\n",base);
return (FALSE);
}
if ((buff = get_board_data((uint)base, gc->IRQ, gc->scsi_id[3])) == NULL){
printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (ulong) base);
return (FALSE);
}
if(gc->HAA_valid == FALSE || ntohl(gc->len) <= 0x1e)
gc->MAX_CHAN = 0;
if(strncmp("PM2322", &buff[16], 6) && strncmp("PM3021", &buff[16], 6)
&& strncmp("PM3222", &buff[16], 6) && strncmp("PM3224", &buff[16], 6))
if(gc->HAA_valid == FALSE || ntohl(gc->len) < 0x22)
gc->MAX_CHAN = 0;
/* if gc->DMA_valid it must be a PM2011 and we have to register it */
dma_channel = 0xff;
if (gc->DMA_valid) {
if (request_dma(dma_channel = (8 - gc->DMA_channel) & 7, "DPT_PM2011")) {
printk("Unable to allocate DMA channel %d for HBA PM2011.\n",
dma_channel);
return (FALSE);
}
}
if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */
if (!request_irq(gc->IRQ, eata_int_handler, SA_INTERRUPT, "EATA-DMA")){
if (!request_irq(gc->IRQ, (void *) eata_fake_int_handler, SA_INTERRUPT, "eata_dma")){
reg_IRQ[gc->IRQ] += (gc->MAX_CHAN+1);
if (!gc->IRQ_TR)
reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */
/* We free it again so we can do a get_conf_dma and
* allocate the interrupt again later */
free_irq(gc->IRQ);
} else {
printk("Couldn't allocate IRQ %d, Sorry.", gc->IRQ);
return (FALSE);
......@@ -750,7 +770,47 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
reg_IRQ[gc->IRQ] += (gc->MAX_CHAN+1);
}
request_region(base, 9, "eata_dma");
/* if gc->DMA_valid it must be an ISA HBA and we have to register it */
dma_channel = 0xff;
if (gc->DMA_valid) {
if (request_dma(dma_channel = (8 - gc->DMA_channel) & 7, "eata_dma")) {
printk("Unable to allocate DMA channel %d for ISA HBA at %#.4lx.\n",
dma_channel, base);
reg_IRQ[gc->IRQ] -= (gc->MAX_CHAN+1);
if (reg_IRQ[gc->IRQ] == 0)
free_irq(gc->IRQ);
if (!gc->IRQ_TR)
reg_IRQL[gc->IRQ] = FALSE;
return (FALSE);
}
}
buff = get_board_data(base, gc->IRQ, gc->scsi_id[3]);
if (buff == NULL) {
if (gc->DMA_support == FALSE)
printk("HBA at %#.4lx doesn't support DMA. Sorry\n", base);
else
printk("HBA at %#.4lx didn't react on INQUIRY. Sorry.\n", base);
if (gc->DMA_valid)
free_dma(dma_channel);
reg_IRQ[gc->IRQ] -= (gc->MAX_CHAN+1);
if (reg_IRQ[gc->IRQ] == 0)
free_irq(gc->IRQ);
if (!gc->IRQ_TR)
reg_IRQL[gc->IRQ] = FALSE;
return (FALSE);
}
if (gc->DMA_support == FALSE && buff != NULL)
printk("HBA %.12sat %#.4lx doesn't set the DMA_support flag correctly.\n",
&buff[16], base);
request_region(base, 9, "eata_dma"); /* We already checked the
* availability, so this could
* only fail if we're on
* 0x1f0 or 0x170.
*/
if(ntohs(gc->queuesiz) == 0) {
gc->queuesiz = ntohs(64);
......@@ -769,6 +829,18 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
for (i = 0; i <= gc->MAX_CHAN; i++) {
sh = scsi_register(tpnt, size);
if(sh == NULL) {
if (gc->DMA_valid)
free_dma(dma_channel);
reg_IRQ[gc->IRQ] -= 1;
if (reg_IRQ[gc->IRQ] == 0)
free_irq(gc->IRQ);
if (!gc->IRQ_TR)
reg_IRQL[gc->IRQ] = FALSE;
return (FALSE);
}
hd = SD(sh);
memset(hd->ccb, 0, (sizeof(struct eata_ccb) * ntohs(gc->queuesiz)) /
......@@ -808,8 +880,10 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
if (gc->OCS_enabled == TRUE) {
sh->cmd_per_lun = sh->can_queue/C_P_L_DIV;
#if 0 /* The memory management seems to be more stable now */
if (sh->cmd_per_lun > C_P_L_CURRENT_MAX)
sh->cmd_per_lun = C_P_L_CURRENT_MAX;
#endif
} else {
sh->cmd_per_lun = 1;
}
......@@ -940,7 +1014,7 @@ void find_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt)
{
#ifndef CONFIG_PCI
printk("Kernel PCI support not enabled. Skipping.\n");
printk("Kernel PCI support not enabled. Skipping scan for PCI HBAs.\n");
#else
unchar pci_bus, pci_device_fn;
......@@ -1041,14 +1115,12 @@ int eata_detect(Scsi_Host_Template * tpnt)
geometry.drv[0].trans = geometry.drv[1].trans = 0;
printk("EATA (Extended Attachment) driver version: %d.%d%s\n"
"developed in co-operation with DPT\n"
"(c) 1993-95 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de\n",
VER_MAJOR, VER_MINOR, VER_SUB);
DBG((DBG_PROBE && DBG_DELAY)|| DPT_DEBUG,
printk("Using lots of delays to let you read the debugging output\n"));
status = scsi_init_malloc(512, GFP_ATOMIC | GFP_DMA);
dma_scratch = scsi_init_malloc(512, GFP_ATOMIC | GFP_DMA);
find_PCI(&gc, tpnt);
for (i = 0; i < MAXEISA; i++) {
......@@ -1064,23 +1136,40 @@ int eata_detect(Scsi_Host_Template * tpnt)
}
for (i = 0; i <= MAXIRQ; i++)
if (reg_IRQ[i])
if (reg_IRQ[i]){
free_irq(i);
request_irq(i, eata_int_handler, SA_INTERRUPT, "EATA-DMA");
}
HBA_ptr = first_HBA;
if (registered_HBAs != 0) {
printk("EATA (Extended Attachment) driver version: %d.%d%s\n"
"developed in co-operation with DPT\n"
"(c) 1993-95 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de\n",
VER_MAJOR, VER_MINOR, VER_SUB);
printk("Registered HBAs:\n");
printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: DMA: Ch: ID: Pr: QS: SG: CPL:\n");
for (i = 1; i <= registered_HBAs; i++) {
printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4x %2d %2x %d %d %d %2d %2d %2d\n",
printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4lx %2d",
HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision,
SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P')?
"PCI ":(SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA ",
(uint) HBA_ptr->base, HBA_ptr->irq, HBA_ptr->dma_channel,
SD(HBA_ptr)->channel, HBA_ptr->this_id, SD(HBA_ptr)->primary,
(u32) HBA_ptr->base, HBA_ptr->irq);
if(HBA_ptr->dma_channel != 0xff)
printk(" %2x ", HBA_ptr->dma_channel);
else
printk(" %s", "BMST");
printk(" %d %d %c %2d %2d %2d\n", SD(HBA_ptr)->channel,
HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE)?'Y':'N',
HBA_ptr->can_queue, HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun);
HBA_ptr = SD(HBA_ptr)->next;
}
} else
scsi_init_free((void *)status, 512);
scsi_init_free((void *)dma_scratch, 512);
DBG(DPT_DEBUG,DELAY(1200));
return (registered_HBAs);
......
......@@ -2,7 +2,7 @@
* Header file for eata_dma.c Linux EATA-DMA SCSI driver *
* (c) 1993,94,95 Michael Neuffer *
*********************************************************
* last change: 95/02/13 *
* last change: 95/04/10 *
********************************************************/
......@@ -11,7 +11,7 @@
#define VER_MAJOR 2
#define VER_MINOR 3
#define VER_SUB "1a"
#define VER_SUB "5r"
/************************************************************************
* Here you can configure your drives that are using a non-standard *
......@@ -61,6 +61,7 @@
#define DBG_QUEUE 0 /* Trace command queueing. */
#define DBG_INTR 0 /* Trace interrupt service routine. */
#define DBG_INTR2 0 /* Trace interrupt service routine. */
#define DBG_INTR3 0 /* Trace interrupt service routine. */
#define DBG_PROC 0 /* Debug proc-fs related statistics */
#define DBG_REGISTER 0 /* */
#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort)*/
......@@ -125,13 +126,15 @@ int eata_release(struct Scsi_Host *);
#define SG_SIZE 64
#define C_P_L_CURRENT_MAX 10 /* Until this limit in the mm is removed
#define C_P_L_CURRENT_MAX 16 /* Until this limit in the mm is removed
* Kernels < 1.1.86 died horrible deaths
* if you used values >2. The memory management
* since pl1.1.86 seems to cope with up to 10
* queued commands per device.
* Since 1.2.0 the memory management seems to
* have no more problems......
*/
#define C_P_L_DIV 4 /* 1 <= C_P_L_DIV <= 8
#define C_P_L_DIV 3 /* 1 <= C_P_L_DIV <= 8
* You can use this parameter to fine-tune
* the driver. Depending on the number of
* devices and their speed and ability to queue
......@@ -201,6 +204,24 @@ int eata_release(struct Scsi_Host *);
#define HA_SBUSY 0x80 /* drive busy */
#define HA_SDRDY HA_SSC+HA_SREADY+HA_SDRQ
#define HA_NO_ERROR 0x00
#define HA_ERR_SEL_TO 0x01
#define HA_ERR_CMD_TO 0x02
#define HA_ERR_RESET 0x03
#define HA_INIT_POWERUP 0x04
#define HA_UNX_BUSPHASE 0x05
#define HA_UNX_BUS_FREE 0x06
#define HA_BUS_PARITY 0x07
#define HA_SCSI_HUNG 0x08
#define HA_UNX_MSGRJCT 0x09
#define HA_RESET_STUCK 0x0a
#define HA_RSENSE_FAIL 0x0b
#define HA_PARITY_ERR 0x0c
#define HA_CP_ABORT_NA 0x0d
#define HA_CP_ABORTED 0x0e
#define HA_CP_RESET_NA 0x0f
#define HA_CP_RESET 0x10
/**********************************************
* Message definitions *
**********************************************/
......
......@@ -387,7 +387,8 @@ void scan_scsis (struct Scsi_Host * shpnt)
if(SCpnt->result) {
if ((driver_byte(SCpnt->result) & DRIVER_SENSE) &&
if (((driver_byte(SCpnt->result) & DRIVER_SENSE) ||
(status_byte(SCpnt->result) & CHECK_CONDITION)) &&
((SCpnt->sense_buffer[0] & 0x70) >> 4) == 7) {
if (SCpnt->sense_buffer[2] &0xe0)
continue; /* No devices here... */
......
......@@ -50,6 +50,7 @@
#define SEND_DIAGNOSTIC 0x1d
#define ALLOW_MEDIUM_REMOVAL 0x1e
#define SET_WINDOW 0x24
#define READ_CAPACITY 0x25
#define READ_10 0x28
#define WRITE_10 0x2a
......@@ -65,16 +66,26 @@
#define SYNCHRONIZE_CACHE 0x35
#define LOCK_UNLOCK_CACHE 0x36
#define READ_DEFECT_DATA 0x37
#define MEDIUM_SCAN 0x38
#define COMPARE 0x39
#define COPY_VERIFY 0x3a
#define WRITE_BUFFER 0x3b
#define READ_BUFFER 0x3c
#define UPDATE_BLOCK 0x3d
#define READ_LONG 0x3e
#define WRITE_LONG 0x3f
#define CHANGE_DEFINITION 0x40
#define WRITE_SAME 0x41
#define LOG_SELECT 0x4c
#define LOG_SENSE 0x4d
#define MODE_SELECT_10 0x55
#define MODE_SENSE_10 0x5a
#define WRITE_12 0xaa
#define WRITE_VERIFY_12 0xae
#define SEARCH_HIGH_12 0xb0
#define SEARCH_EQUAL_12 0xb1
#define SEARCH_LOW_12 0xb2
#define SEND_VOLUME_TAG 0xb6
extern void scsi_make_blocked_list(void);
extern volatile int in_scan_scsis;
......
......@@ -358,8 +358,8 @@ static void do_sd_request (void)
unsigned long flags;
int flag = 0;
save_flags(flags);
while (1==1){
save_flags(flags);
cli();
if (CURRENT != NULL && CURRENT->dev == -1) {
restore_flags(flags);
......@@ -387,12 +387,10 @@ static void do_sd_request (void)
/*
* The following restore_flags leads to latency problems. FIXME.
* Using a "sti()" gets rid of the latency problems but causes
* race conditions and crashes.
*/
#if 0
restore_flags(flags);
#else
sti();
#endif
/* This is a performance enhancement. We dig down into the request list and
try and find a queueable request (i.e. device not busy, and host able to
......@@ -404,7 +402,6 @@ static void do_sd_request (void)
if (!SCpnt && sd_template.nr_dev > 1){
struct request *req1;
req1 = NULL;
save_flags(flags);
cli();
req = CURRENT;
while(req){
......
......@@ -1063,8 +1063,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
SCpnt->request.dev = dev;
scsi_do_cmd (SCpnt,
(void *) cmd, (STp->buffer)->b_data,
(STp->buffer)->buffer_size,
st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
bytes, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
/* this must be done with interrupts off */
......
......@@ -79,7 +79,7 @@ static int parse_options(char *options, struct iso9660_options * popt)
popt->rock = 'y';
popt->cruft = 'n';
popt->unhide = 'n';
popt->conversion = 'a';
popt->conversion = 'b'; /* default: no conversion */
popt->blocksize = 1024;
popt->mode = S_IRUGO;
popt->gid = 0;
......
......@@ -7,8 +7,8 @@
/* limits */
#define MAX_CHRDEV 32
#define MAX_BLKDEV 32
#define MAX_CHRDEV 64
#define MAX_BLKDEV 64
/*
* assignments
......
......@@ -140,6 +140,7 @@ struct async_struct {
int xmit_tail;
int xmit_cnt;
struct tq_struct tqueue;
struct tq_struct tqueue_hangup;
struct termios normal_termios;
struct termios callout_termios;
struct wait_queue *open_wait;
......@@ -160,7 +161,6 @@ struct async_struct {
* time, instead of at rs interrupt time.
*/
#define RS_EVENT_WRITE_WAKEUP 0
#define RS_EVENT_HANGUP 1
/*
* Multiport serial configuration structure --- internal structure
......
......@@ -57,7 +57,7 @@ typedef struct tq_struct * task_queue;
#define DECLARE_TASK_QUEUE(q) task_queue q = &tq_last
extern struct tq_struct tq_last;
extern task_queue tq_timer, tq_immediate;
extern task_queue tq_timer, tq_immediate, tq_scheduler;
#ifdef INCLUDE_INLINE_FUNCS
struct tq_struct tq_last = {
......
......@@ -41,8 +41,10 @@
#include <linux/tcp.h>
#include "../net/inet/protocol.h"
#include "../net/inet/arp.h"
#if defined(CONFIG_PPP) || defined(CONFIG_SLIP)
#include "../drivers/net/slhc.h"
#endif
#endif
#ifdef CONFIG_PCI
#include <linux/pci.h>
#endif
......@@ -209,6 +211,7 @@ struct symbol_table symbol_table = {
X(del_timer),
X(tq_timer),
X(tq_immediate),
X(tq_scheduler),
X(tq_last),
X(timer_active),
X(timer_table),
......@@ -273,11 +276,13 @@ struct symbol_table symbol_table = {
#ifdef CONFIG_INET
X(inet_add_protocol),
X(inet_del_protocol),
#if defined(CONFIG_PPP) || defined(CONFIG_SLIP)
X(slhc_init),
X(slhc_free),
X(slhc_remember),
X(slhc_compress),
X(slhc_uncompress),
#endif
#endif
/* Device callback registration */
X(register_netdevice_notifier),
......@@ -323,6 +328,8 @@ struct symbol_table symbol_table = {
X(scsi_register),
X(scsi_unregister),
X(scsicam_bios_param),
X(scsi_init_malloc),
X(scsi_init_free),
X(print_command),
#endif
/* Added to make file system as module */
......
......@@ -45,6 +45,7 @@ int tickadj = 500/HZ; /* microsecs */
DECLARE_TASK_QUEUE(tq_timer);
DECLARE_TASK_QUEUE(tq_immediate);
DECLARE_TASK_QUEUE(tq_scheduler);
/*
* phase-lock loop variables
......@@ -119,6 +120,7 @@ asmlinkage void schedule(void)
printk("Aiee: scheduling in interrupt\n");
intr_count = 0;
}
run_task_queue(&tq_scheduler);
cli();
ticks = itimer_ticks;
itimer_ticks = 0;
......
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