home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC-Online 1996 May
/
PCOnline_05_1996.bin
/
linux
/
source
/
kernel-s
/
v1.2
/
patch-1.008
/
patch-1.2.5
Wrap
Text File
|
1995-04-12
|
60KB
|
1,935 lines
diff -u --recursive --new-file v1.2.4/linux/Makefile linux/Makefile
--- v1.2.4/linux/Makefile Sun Apr 9 11:59:55 1995
+++ linux/Makefile Wed Apr 12 15:25:52 1995
@@ -1,6 +1,6 @@
VERSION = 1
PATCHLEVEL = 2
-SUBLEVEL = 4
+SUBLEVEL = 5
ARCH = i386
diff -u --recursive --new-file v1.2.4/linux/README linux/README
--- v1.2.4/linux/README Sun Apr 9 11:59:55 1995
+++ linux/README Wed Apr 12 08:12:14 1995
@@ -124,15 +124,15 @@
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.
diff -u --recursive --new-file v1.2.4/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v1.2.4/linux/drivers/block/ll_rw_blk.c Sun Apr 9 11:59:56 1995
+++ linux/drivers/block/ll_rw_blk.c Mon Apr 10 11:22:45 1995
@@ -169,20 +169,40 @@
/*
* 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 @@
*/
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 @@
/* 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 @@
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 @@
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;
diff -u --recursive --new-file v1.2.4/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog
--- v1.2.4/linux/drivers/char/ChangeLog Thu Mar 9 20:37:34 1995
+++ linux/drivers/char/ChangeLog Wed Apr 12 21:24:17 1995
@@ -1,3 +1,11 @@
+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
diff -u --recursive --new-file v1.2.4/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v1.2.4/linux/drivers/char/serial.c Thu Feb 23 13:31:40 1995
+++ linux/drivers/char/serial.c Wed Apr 12 21:24:17 1995
@@ -468,7 +468,8 @@
#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 @@
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)
@@ -737,6 +732,28 @@
}
/*
+ * 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
* (irq=0). This doesn't work very well for 16450's, but gives barely
@@ -2615,6 +2632,8 @@
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;
diff -u --recursive --new-file v1.2.4/linux/drivers/net/lance.c linux/drivers/net/lance.c
--- v1.2.4/linux/drivers/net/lance.c Fri Jan 20 11:34:39 1995
+++ linux/drivers/net/lance.c Sun Apr 9 10:38:29 1995
@@ -913,7 +913,7 @@
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);
diff -u --recursive --new-file v1.2.4/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- v1.2.4/linux/drivers/net/ne.c Sun Apr 9 11:59:56 1995
+++ linux/drivers/net/ne.c Wed Apr 12 13:16:11 1995
@@ -1,3 +1,4 @@
+#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 @@
{
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 @@
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 @@
} 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
diff -u --recursive --new-file v1.2.4/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c
--- v1.2.4/linux/drivers/net/wavelan.c Wed Feb 22 16:25:04 1995
+++ linux/drivers/net/wavelan.c Tue Apr 11 07:45:38 1995
@@ -71,7 +71,7 @@
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 @@
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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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 @@
wavelan_probe(device *dev)
{
int i;
+ int r;
short base_addr;
static unsigned short iobase[] =
{
@@ -721,10 +751,17 @@
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 @@
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 @@
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 @@
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 @@
||
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 @@
printk("\n");
- if (wavelan_debug)
+ if (wavelan_debug > 0)
printk(version);
dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL);
@@ -915,6 +977,9 @@
dev->mtu = WAVELAN_MTU;
+ if (wavelan_debug > 0)
+ printk("%s: <-wavelan_probe1(): 0\n", dev->name);
+
return 0;
}
@@ -1074,12 +1139,21 @@
{
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 @@
)
{
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 @@
}
#endif /* 0 */
- if (wavelan_debug > 0)
+ if (wavelan_debug > 5)
{
unsigned char addr[WAVELAN_ADDR_SIZE];
unsigned short ltype;
@@ -1723,14 +1809,14 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
*/
break;
}
+
+ if (wavelan_debug > 0)
+ printk("%s: <-wavelan_set_multicast_list()\n", dev->name);
}
/*
@@ -2330,6 +2428,7 @@
* 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),
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v1.2.4/linux/drivers/scsi/Makefile Tue Apr 4 09:05:34 1995
+++ linux/drivers/scsi/Makefile Tue Apr 11 07:56:24 1995
@@ -86,9 +86,11 @@
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
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/buslogic.c linux/drivers/scsi/buslogic.c
--- v1.2.4/linux/drivers/scsi/buslogic.c Mon Jan 23 10:38:29 1995
+++ linux/drivers/scsi/buslogic.c Wed Apr 12 08:12:14 1995
@@ -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 @@
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 @@
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));
+ /*
+ 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.
+ */
+
+ interrupt_flags = inb(INTERRUPT(base));
+
+ if (!(interrupt_flags & INTV))
+ {
+ buslogic_printk("interrupt received, but INTV not set\n");
+ return;
+ }
+
+ /*
+ 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.
+ */
- 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
-
- number_serviced = 0;
- needs_restart = 0;
-
- 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");
- }
-
- INTR_RESET(base);
-
- save_flags(flags);
- cli();
-
- mbi = HOSTDATA(shpnt)->last_mbi_used + 1;
- if (mbi >= 2 * BUSLOGIC_MAILBOXES)
- mbi = BUSLOGIC_MAILBOXES;
-
- /* 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... */
-
- 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;
- }
-
- restore_flags(flags);
-
- 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;
- }
-
-#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
-
- if (mbistatus == MBX_COMPLETION_NOT_FOUND)
- continue;
-
-#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
- buslogic_printk("...done %u %u\n", mbo, mbi);
-#endif
+ INTR_RESET(base);
+ if (interrupt_flags & RSTS)
+ {
+ restart(shpnt);
+ return;
+ }
+
+ /*
+ 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.
+ */
+
+ mbi = HOSTDATA(shpnt)->last_mbi_used + 1;
+ if (mbi >= 2*BUSLOGIC_MAILBOXES)
+ mbi = BUSLOGIC_MAILBOXES;
+
+ found = 0;
+
+ while (mb[mbi].status != MBX_NOT_IN_USE && found < BUSLOGIC_MAILBOXES)
+ {
+ int mbo = (struct ccb *)mb[mbi].ccbptr - ccb;
+ int result = 0;
+
+ saved_mbo[found++] = mbo;
+
+ if (mb[mbi].status != MBX_COMPLETION_OK)
+ result = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
+
+ HOSTDATA(shpnt)->sc[mbo]->result = result;
+
+ mb[mbi].status = MBX_NOT_IN_USE;
+
+ HOSTDATA(shpnt)->last_mbi_used = mbi;
+
+ if (++mbi >= 2*BUSLOGIC_MAILBOXES)
+ mbi = BUSLOGIC_MAILBOXES;
+ }
+
+ /*
+ 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.
+ */
+
+ sti();
+
+ for (i = 0; i < found; i++)
+ {
+ int mbo = saved_mbo[i];
sctmp = HOSTDATA(shpnt)->sc[mbo];
-
- 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;
- }
-
- my_done = sctmp->scsi_done;
+ /*
+ First, free any storage allocated for a scatter/gather
+ data segment list.
+ */
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 (errstatus)
- buslogic_printk("returning %08X.\n", errstatus);
-#endif
-
- 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++;
- }
+ 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 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 @@
}
#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 @@
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 @@
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 @@
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 @@
}
#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 @@
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);
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c
--- v1.2.4/linux/drivers/scsi/eata_dma.c Tue Feb 14 08:02:58 1995
+++ linux/drivers/scsi/eata_dma.c Wed Apr 12 21:03:23 1995
@@ -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 @@
{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 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
int check_blink_state(long base)
{
- uint ret = 0;
uint loops = 10;
ulong blinkindicator = 0x42445054;
ulong state = 0x12345678;
@@ -621,10 +656,13 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{
#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 @@
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 @@
}
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);
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/eata_dma.h linux/drivers/scsi/eata_dma.h
--- v1.2.4/linux/drivers/scsi/eata_dma.h Tue Feb 14 08:02:58 1995
+++ linux/drivers/scsi/eata_dma.h Tue Apr 11 07:56:25 1995
@@ -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 @@
#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
@@ -200,6 +203,24 @@
#define HA_SREADY 0x40 /* drive ready */
#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 *
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.2.4/linux/drivers/scsi/scsi.c Wed Mar 29 06:52:58 1995
+++ linux/drivers/scsi/scsi.c Wed Apr 12 21:03:23 1995
@@ -387,7 +387,8 @@
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... */
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v1.2.4/linux/drivers/scsi/scsi.h Wed Mar 29 06:52:59 1995
+++ linux/drivers/scsi/scsi.h Tue Apr 11 07:56:25 1995
@@ -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;
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v1.2.4/linux/drivers/scsi/sd.c Sun Feb 19 11:33:13 1995
+++ linux/drivers/scsi/sd.c Mon Apr 10 08:31:51 1995
@@ -358,8 +358,8 @@
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 @@
/*
* 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 @@
if (!SCpnt && sd_template.nr_dev > 1){
struct request *req1;
req1 = NULL;
- save_flags(flags);
cli();
req = CURRENT;
while(req){
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v1.2.4/linux/drivers/scsi/st.c Sun Apr 9 11:59:57 1995
+++ linux/drivers/scsi/st.c Sun Apr 9 12:50:58 1995
@@ -1063,8 +1063,7 @@
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 */
diff -u --recursive --new-file v1.2.4/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v1.2.4/linux/fs/isofs/inode.c Wed Feb 22 08:15:14 1995
+++ linux/fs/isofs/inode.c Sun Apr 9 10:04:42 1995
@@ -79,7 +79,7 @@
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;
diff -u --recursive --new-file v1.2.4/linux/include/linux/major.h linux/include/linux/major.h
--- v1.2.4/linux/include/linux/major.h Thu Feb 23 13:31:40 1995
+++ linux/include/linux/major.h Tue Apr 11 08:03:29 1995
@@ -7,8 +7,8 @@
/* limits */
-#define MAX_CHRDEV 32
-#define MAX_BLKDEV 32
+#define MAX_CHRDEV 64
+#define MAX_BLKDEV 64
/*
* assignments
diff -u --recursive --new-file v1.2.4/linux/include/linux/serial.h linux/include/linux/serial.h
--- v1.2.4/linux/include/linux/serial.h Mon Feb 20 21:29:53 1995
+++ linux/include/linux/serial.h Wed Apr 12 21:24:17 1995
@@ -140,6 +140,7 @@
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 @@
* time, instead of at rs interrupt time.
*/
#define RS_EVENT_WRITE_WAKEUP 0
-#define RS_EVENT_HANGUP 1
/*
* Multiport serial configuration structure --- internal structure
diff -u --recursive --new-file v1.2.4/linux/include/linux/tqueue.h linux/include/linux/tqueue.h
--- v1.2.4/linux/include/linux/tqueue.h Wed Dec 28 16:38:30 1994
+++ linux/include/linux/tqueue.h Wed Apr 12 21:24:17 1995
@@ -57,7 +57,7 @@
#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 = {
diff -u --recursive --new-file v1.2.4/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.2.4/linux/kernel/ksyms.c Sun Apr 9 11:59:57 1995
+++ linux/kernel/ksyms.c Wed Apr 12 21:24:17 1995
@@ -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 @@
X(del_timer),
X(tq_timer),
X(tq_immediate),
+ X(tq_scheduler),
X(tq_last),
X(timer_active),
X(timer_table),
@@ -273,12 +276,14 @@
#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),
X(unregister_netdevice_notifier),
@@ -323,6 +328,8 @@
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 */
diff -u --recursive --new-file v1.2.4/linux/kernel/sched.c linux/kernel/sched.c
--- v1.2.4/linux/kernel/sched.c Sun Apr 9 11:59:57 1995
+++ linux/kernel/sched.c Wed Apr 12 21:24:17 1995
@@ -45,6 +45,7 @@
DECLARE_TASK_QUEUE(tq_timer);
DECLARE_TASK_QUEUE(tq_immediate);
+DECLARE_TASK_QUEUE(tq_scheduler);
/*
* phase-lock loop variables
@@ -119,6 +120,7 @@
printk("Aiee: scheduling in interrupt\n");
intr_count = 0;
}
+ run_task_queue(&tq_scheduler);
cli();
ticks = itimer_ticks;
itimer_ticks = 0;