Various patches against v2.1.13

Paul Gortmaker (Paul.Gortmaker@anu.edu.au)
Mon, 25 Nov 1996 05:19:25 +1100 (EST)


Here is a few odds n ends for v2.1.14 (or whatever). It contains:

o Updated NE2000 driver that supports the Winbond and Compex PCI
cards in addition to the RealTek cards. Module will auto-detect
PCI cards as well.

o Driver for the Racal-Interlan ES3210 EISA cards (new).

o Strip IDE functionality from hd.c so it is a generic ST-506/wd1006
hard disk driver. Use ide-disk.c if you want all the bells and whistles.

o Tweak vga.c to minimize possibility of seeing text flash on right
hand of screen during heavy scrolling on console.

o Various minor documentation updates, tag a couple of annoying printk()
with KERN_INFO, etc.

Figured I'd better offload this little lot before v2.1 diverges to
the point where I'd have to start hand applying them.

Paul.

diff -ur /tmp/linux-2113/Documentation/00-INDEX linux/Documentation/00-INDEX
--- /tmp/linux-2113/Documentation/00-INDEX Thu Jun 6 21:57:43 1996
+++ linux/Documentation/00-INDEX Sun Nov 24 17:24:17 1996
@@ -1,8 +1,8 @@
This is a brief list of all the files in ./linux/Documentation and what
they contain. If you add a documentation file, please list it here in
-alphabetical order as well. Note that subdirectories have their own
-index files too.
- Thanks -- Paul.
+alphabetical order as well, or risk being hunted down like a rabid dog.
+Note that subdirectories have their own index files too.
+ Thanks -- Paul G.

00-INDEX
- this file.
@@ -14,6 +14,8 @@
- how the boss likes the C code in the kernel to look.
Configure.help
- text file that is used for help when you run "make config"
+IO-mapping.txt
+ - how to access I/O mapped memory from within device drivers.
SMP.txt
- notes, and "To Fix" list for multi-processor Linux. (see smp.tex)
cdrom/
@@ -24,6 +26,8 @@
- plain ASCII listing of all the nodes in /dev/ with major minor #'s
digiboard.txt
- info on the Digiboard PC/X{i,e,eve} multiport boards.
+exception.txt
+ - how linux v2.1 handles exceptions without verify_area etc.
filesystems/
- directory with info on the various filesystems that Linux supports.
ide.txt
@@ -38,6 +42,10 @@
- info on the in-kernel binary support for Java(tm)
locks.txt
- info on file locking implementations, flock() vs. fcntl(), etc.
+logo.gif
+ - Full colour GIF image of Linux logo (penguin)
+logo.txt
+ - Info on creator of above logo & site to get additional images from.
magic-number.txt
- list of magic numbers used to mark/protect kernel data structures.
mandatory.txt
@@ -66,4 +74,7 @@
- info on the Unicode character/font mapping used in Linux.
watchdog.txt
- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
+xterm-linux.xpm
+ - XPM image of penguin logo (see logo.txt) sitting on an xterm.
+

diff -ur /tmp/linux-2113/Documentation/Configure.help linux/Documentation/Configure.help
--- /tmp/linux-2113/Documentation/Configure.help Mon Nov 25 02:11:07 1996
+++ linux/Documentation/Configure.help Mon Nov 25 02:10:14 1996
@@ -2501,6 +2501,19 @@
Multiple-Ethernet-mini-HOWTO, available from
sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.

+Racal-Interlan EISA ES3210 support
+CONFIG_ES3210
+ If you have a network (ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available via ftp (user: anonymous) in
+ sunsite.unc.edu:/pub/Linux/docs/HOWTO. This driver is also available
+ as a module ( = code which can be inserted in and removed from the
+ running kernel whenever you want). If you want to compile it as a
+ module, say M here and read Documentation/modules.txt as well as
+ Documentation/networking/net-modules.txt. If you plan to use more
+ than one network card under linux, read the
+ Multiple-Ethernet-mini-HOWTO, available from
+ sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
+
Apricot Xen-II on board ethernet
CONFIG_APRICOT
If you have a network (ethernet) controller of this type, say Y and
diff -ur /tmp/linux-2113/drivers/block/hd.c linux/drivers/block/hd.c
--- /tmp/linux-2113/drivers/block/hd.c Mon Oct 28 23:29:19 1996
+++ linux/drivers/block/hd.c Sun Nov 24 17:02:27 1996
@@ -17,11 +17,15 @@
*
* IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
* and general streamlining by Mark Lord.
+ *
+ * Removed 99% of above. Use Mark's ide driver for those options.
+ * This is now a lightweight ST-506 driver. (Paul Gortmaker)
+ *
*/
-
-#define DEFAULT_MULT_COUNT 0 /* set to 0 to disable multiple mode at boot */
-#define DEFAULT_UNMASK_INTR 0 /* set to 0 to *NOT* unmask irq's more often */
-
+
+/* Uncomment the following if you want verbose error reports. */
+/* #define VERBOSE_ERRORS */
+
#include <asm/irq.h>
#include <linux/errno.h>
#include <linux/signal.h>
@@ -73,16 +77,13 @@
*/
struct hd_i_struct {
unsigned int head,sect,cyl,wpcom,lzone,ctl;
- };
-static struct hd_driveid *hd_ident_info[MAX_HD] = {0, };
+};

#ifdef HD_TYPE
static struct hd_i_struct hd_info[] = { HD_TYPE };
-struct hd_i_struct bios_info[] = { HD_TYPE };
static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
#else
static struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
-struct hd_i_struct bios_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
static int NR_HD = 0;
#endif

@@ -115,14 +116,14 @@

if (ints[0] != 3)
return;
- if (bios_info[0].head != 0)
+ if (hd_info[0].head != 0)
hdind=1;
- bios_info[hdind].head = hd_info[hdind].head = ints[2];
- bios_info[hdind].sect = hd_info[hdind].sect = ints[3];
- bios_info[hdind].cyl = hd_info[hdind].cyl = ints[1];
- bios_info[hdind].wpcom = hd_info[hdind].wpcom = 0;
- bios_info[hdind].lzone = hd_info[hdind].lzone = ints[1];
- bios_info[hdind].ctl = hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
+ hd_info[hdind].head = ints[2];
+ hd_info[hdind].sect = ints[3];
+ hd_info[hdind].cyl = ints[1];
+ hd_info[hdind].wpcom = 0;
+ hd_info[hdind].lzone = ints[1];
+ hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
NR_HD = hdind+1;
}

@@ -134,6 +135,7 @@
devc = CURRENT ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?';
save_flags (flags);
sti();
+#ifdef VERBOSE_ERRORS
printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff);
if (stat & BUSY_STAT) printk("Busy ");
if (stat & READY_STAT) printk("DriveReady ");
@@ -164,6 +166,15 @@
}
printk("\n");
}
+#else
+ printk("hd%c: %s: status=0x%02x.\n", devc, msg, stat & 0xff);
+ if ((stat & ERR_STAT) == 0) {
+ hd_error = 0;
+ } else {
+ hd_error = inb(HD_ERROR);
+ printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff);
+ }
+#endif /* verbose errors */
restore_flags (flags);
}

@@ -246,113 +257,6 @@
}

static void hd_request (void);
-static unsigned int identified [MAX_HD] = {0,}; /* 1 = drive ID already displayed */
-static unsigned int unmask_intr [MAX_HD] = {0,}; /* 1 = unmask IRQs during I/O */
-static unsigned int max_mult [MAX_HD] = {0,}; /* max sectors for MultMode */
-static unsigned int mult_req [MAX_HD] = {0,}; /* requested MultMode count */
-static unsigned int mult_count [MAX_HD] = {0,}; /* currently enabled MultMode count */
-static struct request WCURRENT;
-
-static void fixstring (unsigned char *s, int bytecount)
-{
- unsigned char *p, *end = &s[bytecount &= ~1]; /* bytecount must be even */
-
- /* convert from big-endian to little-endian */
- for (p = end ; p != s;) {
- unsigned short *pp = (unsigned short *) (p -= 2);
- *pp = (*pp >> 8) | (*pp << 8);
- }
-
- /* strip leading blanks */
- while (s != end && *s == ' ')
- ++s;
-
- /* compress internal blanks and strip trailing blanks */
- while (s != end && *s) {
- if (*s++ != ' ' || (s != end && *s && *s != ' '))
- *p++ = *(s-1);
- }
-
- /* wipe out trailing garbage */
- while (p != end)
- *p++ = '\0';
-}
-
-static void identify_intr(void)
-{
- unsigned int dev = DEVICE_NR(CURRENT->rq_dev);
- unsigned short stat = inb_p(HD_STATUS);
- struct hd_driveid *id = hd_ident_info[dev];
-
- if (unmask_intr[dev])
- sti();
- if (stat & (BUSY_STAT|ERR_STAT)) {
- printk (" hd%c: non-IDE device, %dMB, CHS=%d/%d/%d\n", dev+'a',
- hd_info[dev].cyl*hd_info[dev].head*hd_info[dev].sect / 2048,
- hd_info[dev].cyl, hd_info[dev].head, hd_info[dev].sect);
- if (id != NULL) {
- hd_ident_info[dev] = NULL;
- kfree_s (id, 512);
- }
- } else {
- insw(HD_DATA, id, 256); /* get ID info */
- max_mult[dev] = id->max_multsect;
- if ((id->field_valid&1) && id->cur_cyls && id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
- /*
- * Extract the physical drive geometry for our use.
- * Note that we purposely do *not* update the bios_info.
- * This way, programs that use it (like fdisk) will
- * still have the same logical view as the BIOS does,
- * which keeps the partition table from being screwed.
- */
- hd_info[dev].cyl = id->cur_cyls;
- hd_info[dev].head = id->cur_heads;
- hd_info[dev].sect = id->cur_sectors;
- }
- fixstring (id->serial_no, sizeof(id->serial_no));
- fixstring (id->fw_rev, sizeof(id->fw_rev));
- fixstring (id->model, sizeof(id->model));
- printk (" hd%c: %.40s, %dMB w/%dKB Cache, CHS=%d/%d/%d, MaxMult=%d\n",
- dev+'a', id->model, id->cyls*id->heads*id->sectors/2048,
- id->buf_size/2, bios_info[dev].cyl, bios_info[dev].head,
- bios_info[dev].sect, id->max_multsect);
- /*
- * Early model Quantum drives go weird at this point,
- * but doing a recalibrate seems to "fix" them.
- * (Doing a full reset confuses some other model Quantums)
- */
- if (!strncmp(id->model, "QUANTUM", 7))
- special_op[dev] = recalibrate[dev] = 1;
- }
-#if (HD_DELAY > 0)
- last_req = read_timer();
-#endif
- hd_request();
- return;
-}
-
-static void set_multmode_intr(void)
-{
- unsigned int dev = DEVICE_NR(CURRENT->rq_dev), stat = inb_p(HD_STATUS);
-
- if (unmask_intr[dev])
- sti();
- if (stat & (BUSY_STAT|ERR_STAT)) {
- mult_req[dev] = mult_count[dev] = 0;
- dump_status("set multmode failed", stat);
- } else {
- if ((mult_count[dev] = mult_req[dev]))
- printk (" hd%c: enabled %d-sector multiple mode\n",
- dev+'a', mult_count[dev]);
- else
- printk (" hd%c: disabled multiple mode\n", dev+'a');
- }
-#if (HD_DELAY > 0)
- last_req = read_timer();
-#endif
- hd_request();
- return;
-}

static int drive_busy(void)
{
@@ -398,17 +302,6 @@
}
if (++i < NR_HD) {
special_op[i] = recalibrate[i] = 1;
- if (unmask_intr[i]) {
- unmask_intr[i] = DEFAULT_UNMASK_INTR;
- printk("hd%c: reset irq-unmasking to %d\n",i+'a',
- DEFAULT_UNMASK_INTR);
- }
- if (mult_req[i] || mult_count[i]) {
- mult_count[i] = 0;
- mult_req[i] = DEFAULT_MULT_COUNT;
- printk("hd%c: reset multiple mode to %d\n",i+'a',
- DEFAULT_MULT_COUNT);
- }
hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
if (reset)
@@ -471,11 +364,8 @@

static void read_intr(void)
{
- unsigned int dev = DEVICE_NR(CURRENT->rq_dev);
- int i, retries = 100000, msect = mult_count[dev], nsect;
+ int i, retries = 100000;

- if (unmask_intr[dev])
- sti(); /* permit other IRQs during xfer */
do {
i = (unsigned) inb_p(HD_STATUS);
if (i & BUSY_STAT)
@@ -490,28 +380,20 @@
hd_request();
return;
ok_to_read:
- if (msect) {
- if ((nsect = CURRENT->current_nr_sectors) > msect)
- nsect = msect;
- msect -= nsect;
- } else
- nsect = 1;
- insw(HD_DATA,CURRENT->buffer,nsect<<8);
- CURRENT->sector += nsect;
- CURRENT->buffer += nsect<<9;
+ insw(HD_DATA,CURRENT->buffer,256);
+ CURRENT->sector++;
+ CURRENT->buffer += 512;
CURRENT->errors = 0;
- i = (CURRENT->nr_sectors -= nsect);
-
+ i = --CURRENT->nr_sectors;
+ --CURRENT->current_nr_sectors;
#ifdef DEBUG
- printk("hd%c: read: sectors(%ld-%ld), remaining=%ld, buffer=0x%08lx\n",
- dev+'a', CURRENT->sector, CURRENT->sector+nsect,
- CURRENT->nr_sectors, (unsigned long) CURRENT->buffer+(nsect<<9));
+ printk("hd%c: read: sector %ld, remaining = %ld, buffer=0x%08lx\n",
+ dev+'a', CURRENT->sector, CURRENT->nr_sectors,
+ (unsigned long) CURRENT->buffer+512));
#endif
- if ((CURRENT->current_nr_sectors -= nsect) <= 0)
+ if (CURRENT->current_nr_sectors <= 0)
end_request(1);
if (i > 0) {
- if (msect)
- goto ok_to_read;
SET_INTR(&read_intr);
return;
}
@@ -524,66 +406,11 @@
return;
}

-static inline void multwrite (unsigned int dev)
-{
- unsigned int mcount = mult_count[dev];
-
- while (mcount--) {
- outsw(HD_DATA,WCURRENT.buffer,256);
- if (!--WCURRENT.nr_sectors)
- return;
- WCURRENT.buffer += 512;
- if (!--WCURRENT.current_nr_sectors) {
- WCURRENT.bh = WCURRENT.bh->b_reqnext;
- if (WCURRENT.bh == NULL)
- panic("buffer list corrupted\n");
- WCURRENT.current_nr_sectors = WCURRENT.bh->b_size>>9;
- WCURRENT.buffer = WCURRENT.bh->b_data;
- }
- }
-}
-
-static void multwrite_intr(void)
-{
- int i;
- unsigned int dev = DEVICE_NR(WCURRENT.rq_dev);
-
- if (unmask_intr[dev])
- sti();
- if (OK_STATUS(i=inb_p(HD_STATUS))) {
- if (i & DRQ_STAT) {
- if (WCURRENT.nr_sectors) {
- multwrite(dev);
- SET_INTR(&multwrite_intr);
- return;
- }
- } else {
- if (!WCURRENT.nr_sectors) { /* all done? */
- for (i = CURRENT->nr_sectors; i > 0;){
- i -= CURRENT->current_nr_sectors;
- end_request(1);
- }
-#if (HD_DELAY > 0)
- last_req = read_timer();
-#endif
- if (CURRENT)
- hd_request();
- return;
- }
- }
- }
- dump_status("multwrite_intr", i);
- bad_rw_intr();
- hd_request();
-}
-
static void write_intr(void)
{
int i;
int retries = 100000;

- if (unmask_intr[DEVICE_NR(WCURRENT.rq_dev)])
- sti();
do {
i = (unsigned) inb_p(HD_STATUS);
if (i & BUSY_STAT)
@@ -660,17 +487,6 @@
hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
return reset;
}
- if (!identified[dev]) {
- identified[dev] = 1;
- unmask_intr[dev] = DEFAULT_UNMASK_INTR;
- mult_req[dev] = DEFAULT_MULT_COUNT;
- hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr);
- return reset;
- }
- if (mult_req[dev] != mult_count[dev]) {
- hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr);
- return reset;
- }
if (hd_info[dev].head > 16) {
printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
end_request(0);
@@ -686,10 +502,8 @@
*
* Interrupts are still masked (by default) whenever we are exchanging
* data/cmds with a drive, because some drives seem to have very poor
- * tolerance for latency during I/O. For devices which don't suffer from
- * that problem (most don't), the unmask_intr[] flag can be set to unmask
- * other interrupts during data/cmd transfers (by defining DEFAULT_UNMASK_INTR
- * to 1, or by using "hdparm -u1 /dev/hd?" from the shell).
+ * tolerance for latency during I/O. The IDE driver has support to unmask
+ * interrupts for non-broken hardware, so use that driver if required.
*/
static void hd_request(void)
{
@@ -738,31 +552,21 @@
dev+'a', (CURRENT->cmd == READ)?"read":"writ",
cyl, head, sec, nsect, (unsigned long) CURRENT->buffer);
#endif
- if (!unmask_intr[dev])
- cli();
if (CURRENT->cmd == READ) {
- unsigned int cmd = mult_count[dev] > 1 ? WIN_MULTREAD : WIN_READ;
- hd_out(dev,nsect,sec,head,cyl,cmd,&read_intr);
+ hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
if (reset)
goto repeat;
return;
}
if (CURRENT->cmd == WRITE) {
- if (mult_count[dev])
- hd_out(dev,nsect,sec,head,cyl,WIN_MULTWRITE,&multwrite_intr);
- else
- hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
+ hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
if (reset)
goto repeat;
if (wait_DRQ()) {
bad_rw_intr();
goto repeat;
}
- if (mult_count[dev]) {
- WCURRENT = *CURRENT;
- multwrite(dev);
- } else
- outsw(HD_DATA,CURRENT->buffer,256);
+ outsw(HD_DATA,CURRENT->buffer,256);
return;
}
panic("unknown hd-command");
@@ -780,7 +584,6 @@
{
struct hd_geometry *loc = (struct hd_geometry *) arg;
int dev, err;
- unsigned long flags;

if ((!inode) || !(inode->i_rdev))
return -EINVAL;
@@ -793,11 +596,11 @@
err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
if (err)
return err;
- put_user(bios_info[dev].head,
+ put_user(hd_info[dev].head,
(char *) &loc->heads);
- put_user(bios_info[dev].sect,
+ put_user(hd_info[dev].sect,
(char *) &loc->sectors);
- put_user(bios_info[dev].cyl,
+ put_user(hd_info[dev].cyl,
(short *) &loc->cylinders);
put_user(hd[MINOR(inode->i_rdev)].start_sect,
(long *) &loc->start);
@@ -830,57 +633,6 @@
case BLKRRPART: /* Re-read partition tables */
return revalidate_hddisk(inode->i_rdev, 1);

- case HDIO_SET_UNMASKINTR:
- if (!suser()) return -EACCES;
- if ((arg > 1) || (MINOR(inode->i_rdev) & 0x3F))
- return -EINVAL;
- unmask_intr[dev] = arg;
- return 0;
-
- case HDIO_GET_UNMASKINTR:
- if (!arg) return -EINVAL;
- err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
- if (err)
- return err;
- put_user(unmask_intr[dev], (long *) arg);
- return 0;
-
- case HDIO_GET_MULTCOUNT:
- if (!arg) return -EINVAL;
- err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
- if (err)
- return err;
- put_user(mult_count[dev], (long *) arg);
- return 0;
-
- case HDIO_SET_MULTCOUNT:
- if (!suser()) return -EACCES;
- if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
- save_flags(flags);
- cli(); /* a prior request might still be in progress */
- if (arg > max_mult[dev])
- err = -EINVAL; /* out of range for device */
- else if (mult_req[dev] != mult_count[dev]) {
- special_op[dev] = 1;
- err = -EBUSY; /* busy, try again */
- } else {
- mult_req[dev] = arg;
- special_op[dev] = 1;
- err = 0;
- }
- restore_flags(flags);
- return err;
-
- case HDIO_GET_IDENTITY:
- if (!arg) return -EINVAL;
- if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
- if (hd_ident_info[dev] == NULL) return -ENOMSG;
- err = verify_area(VERIFY_WRITE, (char *) arg, sizeof(struct hd_driveid));
- if (err)
- return err;
- copy_to_user((char *)arg, (char *) hd_ident_info[dev], sizeof(struct hd_driveid));
- return 0;
-
RO_IOCTLS(inode->i_rdev,arg);
default:
return -EINVAL;
@@ -926,7 +678,7 @@
hd, /* hd struct */
hd_sizes, /* block sizes */
0, /* number */
- (void *) bios_info, /* internal */
+ NULL, /* internal use, not presently used */
NULL /* next */
};

@@ -953,21 +705,21 @@
*/
static void hd_geninit(struct gendisk *ignored)
{
- int i;
+ int drive;

#ifdef __i386__
if (!NR_HD) {
extern struct drive_info drive_info;
unsigned char *BIOS = (unsigned char *) &drive_info;
- int cmos_disks, drive;
+ int cmos_disks;

for (drive=0 ; drive<2 ; drive++) {
- bios_info[drive].cyl = hd_info[drive].cyl = *(unsigned short *) BIOS;
- bios_info[drive].head = hd_info[drive].head = *(2+BIOS);
- bios_info[drive].wpcom = hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
- bios_info[drive].ctl = hd_info[drive].ctl = *(8+BIOS);
- bios_info[drive].lzone = hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
- bios_info[drive].sect = hd_info[drive].sect = *(14+BIOS);
+ hd_info[drive].cyl = *(unsigned short *) BIOS;
+ hd_info[drive].head = *(2+BIOS);
+ hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
+ hd_info[drive].ctl = *(8+BIOS);
+ hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
+ hd_info[drive].sect = *(14+BIOS);
#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp
if (hd_info[drive].cyl && NR_HD == drive)
NR_HD++;
@@ -1004,20 +756,12 @@
NR_HD = 1;
}
#endif /* __i386__ */
- i = NR_HD;
- while (i-- > 0) {
- /*
- * The newer E-IDE BIOSs handle drives larger than 1024
- * cylinders by increasing the number of logical heads
- * to keep the number of logical cylinders below the
- * sacred INT13 limit of 1024 (10 bits). If that is
- * what's happening here, we'll find out and correct
- * it later when "identifying" the drive.
- */
- hd[i<<6].nr_sects = bios_info[i].head *
- bios_info[i].sect * bios_info[i].cyl;
- hd_ident_info[i] = (struct hd_driveid *) kmalloc(512,GFP_KERNEL);
- special_op[i] = 1;
+ for (drive=0 ; drive < NR_HD ; drive++) {
+ hd[drive<<6].nr_sects = hd_info[drive].head *
+ hd_info[drive].sect * hd_info[drive].cyl;
+ printk ("hd%c: %ldMB, CHS=%d/%d/%d\n", drive+'a',
+ hd[drive<<6].nr_sects / 2048, hd_info[drive].cyl,
+ hd_info[drive].head, hd_info[drive].sect);
}
if (NR_HD) {
if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
@@ -1030,7 +774,8 @@
}
hd_gendisk.nr_real = NR_HD;

- for(i=0;i<(MAX_HD << 6);i++) hd_blocksizes[i] = 1024;
+ for(drive=0; drive < (MAX_HD << 6); drive++)
+ hd_blocksizes[drive] = 1024;
blksize_size[MAJOR_NR] = hd_blocksizes;
}

@@ -1063,7 +808,7 @@

#define DEVICE_BUSY busy[target]
#define USAGE access_count[target]
-#define CAPACITY (bios_info[target].head*bios_info[target].sect*bios_info[target].cyl)
+#define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl)
/* We assume that the the bios parameters do not change, so the disk capacity
will not change */
#undef MAYBE_REINIT
diff -ur /tmp/linux-2113/drivers/char/Config.in linux/drivers/char/Config.in
--- /tmp/linux-2113/drivers/char/Config.in Thu Aug 1 22:43:04 1996
+++ linux/drivers/char/Config.in Mon Nov 25 03:49:42 1996
@@ -27,7 +27,9 @@
fi
fi

-bool 'Support for user misc device modules' CONFIG_UMISC
+if [ "$CONFIG_MODULES" = "y" ]; then
+ bool 'Support for user misc device modules' CONFIG_UMISC
+fi

bool 'QIC-02 tape support' CONFIG_QIC02_TAPE
if [ "$CONFIG_QIC02_TAPE" = "y" ]; then
diff -ur /tmp/linux-2113/drivers/char/vga.c linux/drivers/char/vga.c
--- /tmp/linux-2113/drivers/char/vga.c Mon Oct 28 23:29:23 1996
+++ linux/drivers/char/vga.c Sun Nov 24 23:39:50 1996
@@ -33,6 +33,10 @@
* because it causes screen to flicker, by Mitja Horvat
* 5-May-96 <mitja.horvat@guest.arnes.si>
*
+ * Use 2 outw instead of 4 outb_p to reduce erroneous text
+ * flashing on RHS of screen during heavy console scrolling .
+ * Oct 1996, Paul Gortmaker.
+ *
*/

#include <linux/sched.h>
@@ -67,6 +71,29 @@
#define dac_reg (0x3c8)
#define dac_val (0x3c9)

+/*
+ * By replacing the four outb_p with two back to back outw, we can reduce
+ * the window of opportunity to see text mislocated to the RHS of the
+ * console during heavy scrolling activity. However there is the remote
+ * possibility that some pre-dinosaur hardware won't like the back to back
+ * I/O. Since the Xservers get away with it, we should be able to as well.
+ */
+static inline void write_vga(unsigned char reg, unsigned int val)
+{
+#ifndef SLOW_VGA
+ unsigned int v1, v2;
+
+ v1 = reg + (val & 0xff00);
+ v2 = reg + 1 + ((val << 8) & 0xff00);
+ outw(v1, video_port_reg);
+ outw(v2, video_port_reg);
+#else
+ outb_p(reg, video_port_reg);
+ outb_p(val >> 8, video_port_val);
+ outb_p(reg+1, video_port_reg);
+ outb_p(val & 0xff, video_port_val);
+#endif
+}

void
set_palette (void)
@@ -94,10 +121,7 @@

save_flags(flags); cli();
__origin = offset;
- outb_p(12, video_port_reg);
- outb_p(offset >> 8, video_port_val);
- outb_p(13, video_port_reg);
- outb_p(offset, video_port_val);
+ write_vga(12, offset);
restore_flags(flags);
}

@@ -110,10 +134,7 @@
/* This is inefficient, we could just put the cursor at 0xffff,
but perhaps the delays due to the inefficiency are useful for
some hardware... */
- outb_p(14, video_port_reg);
- outb_p(0xff&((video_mem_term-video_mem_base)>>9), video_port_val);
- outb_p(15, video_port_reg);
- outb_p(0xff&((video_mem_term-video_mem_base)>>1), video_port_val);
+ write_vga(14, (video_mem_term - video_mem_base)>>1);
}

void
@@ -127,10 +148,7 @@
__set_origin(__real_origin);
save_flags(flags); cli();
if (deccm) {
- outb_p(14, video_port_reg);
- outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
- outb_p(15, video_port_reg);
- outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
+ write_vga(14, (pos - video_mem_base)>>1);
} else
hide_cursor();
restore_flags(flags);
diff -ur /tmp/linux-2113/drivers/net/Config.in linux/drivers/net/Config.in
--- /tmp/linux-2113/drivers/net/Config.in Sun Nov 24 17:35:54 1996
+++ linux/drivers/net/Config.in Mon Nov 25 03:07:01 1996
@@ -73,6 +73,7 @@
tristate 'DECchip Tulip (dc21x4x) PCI support' CONFIG_DEC_ELCP
tristate 'Digi Intl. RightSwitch SE-X support' CONFIG_DGRS
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Racal-Interlan EISA ES3210 support (EXPERIMENTAL)' CONFIG_ES3210
bool 'Zenith Z-Note support (EXPERIMENTAL)' CONFIG_ZNET
fi
fi
diff -ur /tmp/linux-2113/drivers/net/Makefile linux/drivers/net/Makefile
--- /tmp/linux-2113/drivers/net/Makefile Sun Nov 24 17:35:54 1996
+++ linux/drivers/net/Makefile Sun Nov 24 16:50:12 1996
@@ -156,6 +156,17 @@
endif
endif

+ifeq ($(CONFIG_ES3210),y)
+L_OBJS += es3210.o
+CONFIG_8390_BUILTIN = y
+else
+ ifeq ($(CONFIG_ES3210),m)
+ CONFIG_8390_MODULE = y
+ M_OBJS += es3210.o
+ endif
+endif
+
+
ifeq ($(CONFIG_PLIP),y)
L_OBJS += plip.o
else
diff -ur /tmp/linux-2113/drivers/net/es3210.c linux/drivers/net/es3210.c
--- /tmp/linux-2113/drivers/net/es3210.c Thu Jan 1 00:00:00 1970
+++ linux/drivers/net/es3210.c Mon Nov 25 02:48:43 1996
@@ -0,0 +1,438 @@
+/*
+ es3210.c
+
+ Linux driver for Racal-Interlan ES3210 EISA Network Adapter
+
+ Copyright (C) 1996, Paul Gortmaker.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License, incorporated herein by reference.
+
+ Information and Code Sources:
+
+ 1) The existing myriad of Linux 8390 drivers written by Donald Becker.
+
+ 2) Once again Russ Nelson's asm packet driver provided additional info.
+
+ 3) Info for getting IRQ and sh-mem gleaned from the EISA cfg files.
+ Too bad it doesn't work -- see below.
+
+ The ES3210 is an EISA shared memory NS8390 implementation. Note
+ that all memory copies to/from the board must be 32bit transfers.
+ Which rules out using eth_io_copy_and_sum() in this driver.
+
+ Apparently there are two slightly different revisions of the
+ card, since there are two distinct EISA cfg files (!rii0101.cfg
+ and !rii0102.cfg) One has media select in the cfg file and the
+ other doesn't. Hopefully this will work with either.
+
+ That is about all I can tell you about it, having never actually
+ even seen one of these cards. :) Try http://www.interlan.com
+ if you want more info.
+
+ Thanks go to Mark Salazar for testing v0.02 of this driver.
+
+ Bugs, to-fix, etc:
+
+ 1) The EISA cfg ports that are *supposed* to have the IRQ and shared
+ mem values just read 0xff all the time. Hrrmpf. Apparently the
+ same happens with the packet driver as the code for reading
+ these registers is disabled there. In the meantime, boot with:
+ ether=<IRQ>,0,0x<shared_mem_addr>,eth0 to override the IRQ and
+ shared memory detection. (The i/o port detection is okay.)
+
+ 2) Module support currently untested. Probably works though.
+
+*/
+
+static const char *version =
+ "es3210.c: Driver revision v0.03, 14/09/96\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include "8390.h"
+
+int es_probe(struct device *dev);
+int es_probe1(struct device *dev, int ioaddr);
+
+static int es_open(struct device *dev);
+static int es_close_card(struct device *dev);
+
+static void es_reset_8390(struct device *dev);
+
+static void es_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
+static void es_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset);
+static void es_block_output(struct device *dev, int count, const unsigned char *buf, const start_page);
+
+#define ES_START_PG 0x00 /* First page of TX buffer */
+#define ES_STOP_PG 0x40 /* Last page +1 of RX ring */
+
+#define ES_IO_EXTENT 0x37 /* The cfg file says 0xc90 -> 0xcc7 */
+#define ES_ID_PORT 0xc80 /* Same for all EISA cards */
+#define ES_SA_PROM 0xc90 /* Start of e'net addr. */
+#define ES_RESET_PORT 0xc84 /* From the packet driver source */
+#define ES_NIC_OFFSET 0xca0 /* Hello, the 8390 is *here* */
+
+#define ES_ADDR0 0x02 /* 3 byte vendor prefix */
+#define ES_ADDR1 0x07
+#define ES_ADDR2 0x01
+
+/*
+ * Two card revisions. EISA ID's are always rev. minor, rev. major,, and
+ * then the three vendor letters stored in 5 bits each, with an "a" = 1.
+ * For eg: "rii" = 10010 01001 01001 = 0x4929, which is how the EISA
+ * config utility determines automagically what config file(s) to use.
+ */
+#define ES_EISA_ID1 0x01012949 /* !rii0101.cfg */
+#define ES_EISA_ID2 0x02012949 /* !rii0102.cfg */
+
+#define ES_CFG1 0xcc0 /* IOPORT(1) --> IOPORT(6) in cfg file */
+#define ES_CFG2 0xcc1
+#define ES_CFG3 0xcc2
+#define ES_CFG4 0xcc3
+#define ES_CFG5 0xcc4
+#define ES_CFG6 0xc84 /* NB: 0xc84 is also "reset" port. */
+
+/*
+ * You can OR any of the following bits together and assign it
+ * to ES_DEBUG to get verbose driver info during operation.
+ * Some of these don't do anything yet.
+ */
+
+#define ES_D_PROBE 0x01
+#define ES_D_RX_PKT 0x02
+#define ES_D_TX_PKT 0x04
+#define ED_D_IRQ 0x08
+
+#define ES_DEBUG 0
+
+static unsigned char lo_irq_map[] = {3, 4, 5, 6, 7, 9, 10};
+static unsigned char hi_irq_map[] = {11, 12, 0, 14, 0, 0, 0, 15};
+
+/*
+ * Probe for the card. The best way is to read the EISA ID if it
+ * is known. Then we check the prefix of the station address
+ * PROM for a match against the Racal-Interlan assigned value.
+ */
+
+int es_probe(struct device *dev)
+{
+ unsigned short ioaddr = dev->base_addr;
+
+ if (ioaddr > 0x1ff) /* Check a single specified location. */
+ return es_probe1(dev, ioaddr);
+ else if (ioaddr > 0) /* Don't probe at all. */
+ return ENXIO;
+
+ if (!EISA_bus) {
+#if ES_DEBUG & ES_D_PROBE
+ printk("es3210.c: Not EISA bus. Not probing high ports.\n");
+#endif
+ return ENXIO;
+ }
+
+ /* EISA spec allows for up to 16 slots, but 8 is typical. */
+ for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
+ if (check_region(ioaddr + ES_SA_PROM, ES_IO_EXTENT))
+ continue;
+ if (es_probe1(dev, ioaddr) == 0)
+ return 0;
+ }
+
+ return ENODEV;
+}
+
+int es_probe1(struct device *dev, int ioaddr)
+{
+ int i;
+ unsigned long eisa_id;
+
+#if ES_DEBUG & ES_D_PROBE
+ printk("es3210.c: probe at %#x, ID %#8x\n", ioaddr, inl(ioaddr + ES_ID_PORT));
+ printk("es3210.c: config regs: %#x %#x %#x %#x %#x %#x\n",
+ inb(ioaddr + ES_CFG1), inb(ioaddr + ES_CFG2), inb(ioaddr + ES_CFG3),
+ inb(ioaddr + ES_CFG4), inb(ioaddr + ES_CFG5), inb(ioaddr + ES_CFG6));
+#endif
+
+
+/* Check the EISA ID of the card. */
+ eisa_id = inl(ioaddr + ES_ID_PORT);
+ if ((eisa_id != ES_EISA_ID1) && (eisa_id != ES_EISA_ID2)) {
+ return ENODEV;
+ }
+
+/* Check the Racal vendor ID as well. */
+ if (inb(ioaddr + ES_SA_PROM + 0) != ES_ADDR0
+ || inb(ioaddr + ES_SA_PROM + 1) != ES_ADDR1
+ || inb(ioaddr + ES_SA_PROM + 2) != ES_ADDR2 ) {
+ printk("es3210.c: card not found");
+ for(i = 0; i < ETHER_ADDR_LEN; i++)
+ printk(" %02x", inb(ioaddr + ES_SA_PROM + i));
+ printk(" (invalid prefix).\n");
+ return ENODEV;
+ }
+
+ /* We should have a "dev" from Space.c or the static module table. */
+ if (dev == NULL) {
+ printk("es3210.c: Passed a NULL device.\n");
+ dev = init_etherdev(0, 0);
+ }
+
+ printk("es3210.c: ES3210 rev. %ld at %#x, node", eisa_id>>24, ioaddr);
+ for(i = 0; i < ETHER_ADDR_LEN; i++)
+ printk(" %02x", (dev->dev_addr[i] = inb(ioaddr + ES_SA_PROM + i)));
+
+ /* Snarf the interrupt now. */
+ if (dev->irq == 0) {
+ unsigned char hi_irq = inb(ioaddr + ES_CFG2) & 0x07;
+ unsigned char lo_irq = inb(ioaddr + ES_CFG1) & 0xfe;
+
+ if (hi_irq != 0) {
+ dev->irq = hi_irq_map[hi_irq - 1];
+ } else {
+ int i = 0;
+ while (lo_irq > (1<<i)) i++;
+ dev->irq = lo_irq_map[i];
+ }
+ printk(" using IRQ %d", dev->irq);
+#if ES_DEBUG & ES_D_PROBE
+ printk("es3210.c: hi_irq %#x, lo_irq %#x, dev->irq = %d\n",
+ hi_irq, lo_irq, dev->irq);
+#endif
+ } else {
+ if (dev->irq == 2)
+ dev->irq = 9; /* Doh! */
+ printk(" assigning IRQ %d", dev->irq);
+ }
+
+ if (request_irq(dev->irq, ei_interrupt, 0, "es3210", NULL)) {
+ printk (" unable to get IRQ %d.\n", dev->irq);
+ return EAGAIN;
+ }
+
+ if (dev->mem_start == 0) {
+ unsigned char mem_enabled = inb(ioaddr + ES_CFG2) & 0xc0;
+ unsigned char mem_bits = inb(ioaddr + ES_CFG3) & 0x07;
+
+ if (mem_enabled != 0x80) {
+ printk(" shared mem disabled - giving up\n");
+ free_irq(dev->irq, NULL);
+ return -ENXIO;
+ }
+ dev->mem_start = 0xC0000 + mem_bits*0x4000;
+ printk(" using ");
+ } else {
+ printk(" assigning ");
+ }
+
+ dev->mem_end = dev->rmem_end = dev->mem_start
+ + (ES_STOP_PG - ES_START_PG)*256;
+ dev->rmem_start = dev->mem_start + TX_PAGES*256;
+
+ printk("mem %#lx-%#lx\n", dev->mem_start, dev->mem_end-1);
+
+ /* Allocate dev->priv and fill in 8390 specific dev fields. */
+ if (ethdev_init(dev)) {
+ printk (" unable to allocate memory for dev->priv.\n");
+ free_irq(dev->irq, NULL);
+ return -ENOMEM;
+ }
+
+#if ES_DEBUG & ES_D_PROBE
+ if (inb(ioaddr + ES_CFG5))
+ printk("es3210: Warning - DMA channel enabled, but not used here.\n");
+#endif
+ /* Note, point at the 8390, and not the card... */
+ dev->base_addr = ioaddr + ES_NIC_OFFSET;
+ request_region(ioaddr + ES_SA_PROM, ES_IO_EXTENT, "es3210");
+
+
+ ei_status.name = "ES3210";
+ ei_status.tx_start_page = ES_START_PG;
+ ei_status.rx_start_page = ES_START_PG + TX_PAGES;
+ ei_status.stop_page = ES_STOP_PG;
+ ei_status.word16 = 1;
+
+ if (ei_debug > 0)
+ printk(version);
+
+ ei_status.reset_8390 = &es_reset_8390;
+ ei_status.block_input = &es_block_input;
+ ei_status.block_output = &es_block_output;
+ ei_status.get_8390_hdr = &es_get_8390_hdr;
+
+ dev->open = &es_open;
+ dev->stop = &es_close_card;
+ NS8390_init(dev, 0);
+ return 0;
+}
+
+/*
+ * Reset as per the packet driver method. Judging by the EISA cfg
+ * file, this just toggles the "Board Enable" bits (bit 2 and 0).
+ */
+
+static void es_reset_8390(struct device *dev)
+{
+ unsigned short ioaddr = dev->base_addr;
+ unsigned long end;
+
+ outb(0x04, ioaddr + ES_RESET_PORT);
+ if (ei_debug > 1) printk("%s: resetting the ES3210...", dev->name);
+
+ end = jiffies + 2*HZ/100;
+ while ((signed)(end - jiffies) > 0) continue;
+
+ ei_status.txing = 0;
+ outb(0x01, ioaddr + ES_RESET_PORT);
+ if (ei_debug > 1) printk("reset done\n");
+
+ return;
+}
+
+/*
+ * Note: In the following three functions is the implicit assumption
+ * that the associated memcpy will only use "rep; movsl" as long as
+ * we keep the counts as some multiple of doublewords. This is a
+ * requirement of the hardware, and also prevents us from using
+ * eth_io_copy_and_sum() since we can't guarantee it will limit
+ * itself to doubleword access.
+ */
+
+/*
+ * Grab the 8390 specific header. Similar to the block_input routine, but
+ * we don't need to be concerned with ring wrap as the header will be at
+ * the start of a page, so we optimize accordingly. (A single doubleword.)
+ */
+
+static void
+es_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+ unsigned long hdr_start = dev->mem_start + ((ring_page - ES_START_PG)<<8);
+ memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+ hdr->count = (hdr->count + 3) & ~3; /* Round up allocation. */
+}
+
+/*
+ * Block input and output are easy on shared memory ethercards, the only
+ * complication is when the ring buffer wraps. The count will already
+ * be rounded up to a doubleword value via es_get_8390_hdr() above.
+ */
+
+static void es_block_input(struct device *dev, int count, struct sk_buff *skb,
+ int ring_offset)
+{
+ unsigned long xfer_start = dev->mem_start + ring_offset - (ES_START_PG<<8);
+
+ if (xfer_start + count > dev->rmem_end) {
+ /* Packet wraps over end of ring buffer. */
+ int semi_count = dev->rmem_end - xfer_start;
+ memcpy_fromio(skb->data, xfer_start, semi_count);
+ count -= semi_count;
+ memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+ } else {
+ /* Packet is in one chunk. */
+ memcpy_fromio(skb->data, xfer_start, count);
+ }
+}
+
+static void es_block_output(struct device *dev, int count,
+ const unsigned char *buf, int start_page)
+{
+ unsigned long shmem = dev->mem_start + ((start_page - ES_START_PG)<<8);
+
+ count = (count + 3) & ~3; /* Round up to doubleword */
+ memcpy_toio(shmem, buf, count);
+}
+
+static int es_open(struct device *dev)
+{
+ ei_open(dev);
+
+ MOD_INC_USE_COUNT;
+
+ return 0;
+}
+
+static int es_close_card(struct device *dev)
+{
+
+ if (ei_debug > 1)
+ printk("%s: Shutting down ethercard.\n", dev->name);
+
+ ei_close(dev);
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+}
+
+#ifdef MODULE
+#define MAX_ES_CARDS 4 /* Max number of ES3210 cards per module */
+#define NAMELEN 8 /* # of chars for storing dev->name */
+static char namelist[NAMELEN * MAX_ES_CARDS] = { 0, };
+static struct device dev_ac32[MAX_ES_CARDS] = {
+ {
+ NULL, /* assign a chunk of namelist[] below */
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0, 0, NULL, NULL
+ },
+};
+
+static int io[MAX_ES_CARDS] = { 0, };
+static int irq[MAX_ES_CARDS] = { 0, };
+static int mem[MAX_ES_CARDS] = { 0, };
+
+int
+init_module(void)
+{
+ int this_dev, found = 0;
+
+ for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) {
+ struct device *dev = &dev_ac32[this_dev];
+ dev->name = namelist+(NAMELEN*this_dev);
+ dev->irq = irq[this_dev];
+ dev->base_addr = io[this_dev];
+ dev->mem_start = mem[this_dev]; /* Currently ignored by driver */
+ dev->init = es_probe;
+ /* Default is to only install one card. */
+ if (io[this_dev] == 0 && this_dev != 0) break;
+ if (register_netdev(dev) != 0) {
+ printk(KERN_WARNING "es3210.c: No es3210 card found (i/o = 0x%x).\n", io[this_dev]);
+ if (found != 0) return 0; /* Got at least one. */
+ return -ENXIO;
+ }
+ found++;
+ }
+
+ return 0;
+}
+
+void
+cleanup_module(void)
+{
+ int this_dev;
+
+ for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) {
+ struct device *dev = &dev_ac32[this_dev];
+ if (dev->priv != NULL) {
+ kfree(dev->priv);
+ dev->priv = NULL;
+ free_irq(dev->irq, NULL);
+ irq2dev_map[dev->irq] = NULL;
+ release_region(dev->base_addr, ES_IO_EXTENT);
+ unregister_netdev(dev);
+ }
+ }
+}
+#endif /* MODULE */
+
diff -ur /tmp/linux-2113/drivers/net/ne.c linux/drivers/net/ne.c
--- /tmp/linux-2113/drivers/net/ne.c Tue Oct 8 03:27:59 1996
+++ linux/drivers/net/ne.c Sun Nov 24 15:14:24 1996
@@ -24,6 +24,7 @@
Paul Gortmaker : multiple card support for module users.
Paul Gortmaker : Support for PCI ne2k clones, similar to lance.c
Paul Gortmaker : Allow users with bad cards to avoid full probe.
+ Paul Gortmaker : PCI probe changes, more PCI cards supported.

*/

@@ -61,12 +62,21 @@
/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
/* #define PACKETBUF_MEMSIZE 0x40 */

-/* ---- No user-serviceable parts below ---- */
-
/* A zero-terminated list of I/O addresses to be probed. */
static unsigned int netcard_portlist[] =
{ 0x300, 0x280, 0x320, 0x340, 0x360, 0};

+#ifdef CONFIG_PCI
+/* Ack! People are making PCI ne2000 clones! Oh the horror, the horror... */
+static struct { unsigned short vendor, dev_id;}
+pci_clone_list[] = {
+ {PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8029},
+ {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940},
+ {PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_RL2000},
+ {0,}
+};
+#endif
+
#ifdef SUPPORT_NE_BAD_CLONES
/* A list of bad clones that we none-the-less recognize. */
static struct { const char *name8, *name16; unsigned char SAprefix[4];}
@@ -80,10 +90,14 @@
{"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}}, /* Outlaw 4-Dimension cards. */
{"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */
{"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
+ {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
+ {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
{0,}
};
#endif

+/* ---- No user-serviceable parts below ---- */
+
#define NE_BASE (dev->base_addr)
#define NE_CMD 0x00
#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */
@@ -100,6 +114,9 @@

int ne_probe(struct device *dev);
static int ne_probe1(struct device *dev, int ioaddr);
+#ifdef CONFIG_PCI
+static int ne_probe_pci(struct device *dev);
+#endif

static int ne_open(struct device *dev);
static int ne_close(struct device *dev);
@@ -139,9 +156,12 @@
{"ne", ne_probe1, NE_IO_EXTENT, netcard_portlist};
#else

-/* Note that this probe only picks up one card at a time, even for multiple
- PCI ne2k cards. Use "ether=0,0,eth1" if you have a second PCI ne2k card.
- This keeps things consistent regardless of the bus type of the card. */
+/*
+ * Note that at boot, this probe only picks up one card at a time, even for
+ * multiple PCI ne2k cards. Use "ether=0,0,eth1" if you have a second PCI
+ * ne2k card. This keeps things consistent regardless of the bus type of
+ * the card.
+ */

int ne_probe(struct device *dev)
{
@@ -154,40 +174,13 @@
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;

+#ifdef CONFIG_PCI
/* Then look for any installed PCI clones */
-#if defined(CONFIG_PCI)
- if (pcibios_present()) {
- int pci_index;
- for (pci_index = 0; pci_index < 8; pci_index++) {
- unsigned char pci_bus, pci_device_fn;
- unsigned int pci_ioaddr;
-
- /* Currently only Realtek are making PCI ne2k clones. */
- if (pcibios_find_device (PCI_VENDOR_ID_REALTEK,
- PCI_DEVICE_ID_REALTEK_8029, pci_index,
- &pci_bus, &pci_device_fn) != 0)
- break; /* OK, now try to probe for std. ISA card */
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq_line);
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &pci_ioaddr);
- /* Strip the I/O address out of the returned value */
- pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
- /* Avoid already found cards from previous ne_probe() calls */
- if (check_region(pci_ioaddr, NE_IO_EXTENT))
- continue;
- printk("ne.c: PCI BIOS reports ne2000 clone at i/o %#x, irq %d.\n",
- pci_ioaddr, pci_irq_line);
- if (ne_probe1(dev, pci_ioaddr) != 0) { /* Shouldn't happen. */
- printk(KERN_ERR "ne.c: Probe of PCI card at %#x failed.\n", pci_ioaddr);
- break; /* Hrmm, try to probe for ISA card... */
- }
- pci_irq_line = 0;
- return 0;
- }
- }
-#endif /* defined(CONFIG_PCI) */
+ if (pcibios_present() && (ne_probe_pci(dev) == 0))
+ return 0;
+#endif

+#ifndef MODULE
/* Last resort. The semi-risky ISA auto-probe. */
for (i = 0; netcard_portlist[i]; i++) {
int ioaddr = netcard_portlist[i];
@@ -196,11 +189,55 @@
if (ne_probe1(dev, ioaddr) == 0)
return 0;
}
+#endif

return ENODEV;
}
#endif

+#ifdef CONFIG_PCI
+static int ne_probe_pci(struct device *dev)
+{
+ int i;
+
+ for (i = 0; pci_clone_list[i].vendor != 0; i++) {
+ unsigned char pci_bus, pci_device_fn;
+ unsigned int pci_ioaddr;
+ int pci_index;
+
+ for (pci_index = 0; pci_index < 8; pci_index++) {
+ if (pcibios_find_device (pci_clone_list[i].vendor,
+ pci_clone_list[i].dev_id, pci_index,
+ &pci_bus, &pci_device_fn) != 0)
+ break; /* No more of these type of cards */
+ pcibios_read_config_dword(pci_bus, pci_device_fn,
+ PCI_BASE_ADDRESS_0, &pci_ioaddr);
+ /* Strip the I/O address out of the returned value */
+ pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
+ /* Avoid already found cards from previous calls */
+ if (check_region(pci_ioaddr, NE_IO_EXTENT))
+ continue;
+ pcibios_read_config_byte(pci_bus, pci_device_fn,
+ PCI_INTERRUPT_LINE, &pci_irq_line);
+ break; /* Beauty -- got a valid card. */
+ }
+ if (pci_irq_line == 0) continue; /* Try next PCI ID */
+ printk("ne.c: PCI BIOS reports %s %s at i/o %#x, irq %d.\n",
+ pci_strvendor(pci_clone_list[i].vendor),
+ pci_strdev(pci_clone_list[i].vendor, pci_clone_list[i].dev_id),
+ pci_ioaddr, pci_irq_line);
+ if (ne_probe1(dev, pci_ioaddr) != 0) { /* Shouldn't happen. */
+ printk(KERN_ERR "ne.c: Probe of PCI card at %#x failed.\n", pci_ioaddr);
+ pci_irq_line = 0;
+ return -ENXIO;
+ }
+ pci_irq_line = 0;
+ return 0;
+ }
+ return -ENODEV;
+}
+#endif /* CONFIG_PCI */
+
static int ne_probe1(struct device *dev, int ioaddr)
{
int i;
@@ -308,8 +345,8 @@
for (i = 0; i < 16; i++)
SA_prom[i] = SA_prom[i+i];

- if (pci_irq_line)
- wordlength = 2; /* Catch broken cards mentioned above. */
+ if (pci_irq_line || ioaddr >= 0x400)
+ wordlength = 2; /* Catch broken PCI cards mentioned above. */

if (wordlength == 2) {
/* We must set the 8390 for word mode. */
@@ -359,9 +396,8 @@

}

- if (pci_irq_line) {
+ if (pci_irq_line)
dev->irq = pci_irq_line;
- }

if (dev->irq < 2) {
autoirq_setup(0);
@@ -694,8 +730,9 @@

static int io[MAX_NE_CARDS] = { 0, };
static int irq[MAX_NE_CARDS] = { 0, };
+static int bad[MAX_NE_CARDS] = { 0, }; /* 0xbad = bad sig or no reset ack */

-/* This is set up so that no autoprobe takes place. We can't guarantee
+/* This is set up so that no ISA autoprobe takes place. We can't guarantee
that the ne2k probe is the last 8390 based probe to take place (as it
is at boot) and so the probe will get confused by any other 8390 cards.
ISA device autoprobes on a running machine are not recommended anyway. */
@@ -709,19 +746,20 @@
struct device *dev = &dev_ne[this_dev];
dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
+ dev->mem_end = bad[this_dev];
dev->base_addr = io[this_dev];
dev->init = ne_probe;
- if (io[this_dev] == 0) {
- if (this_dev != 0) break; /* only complain once */
- printk(KERN_NOTICE "ne.c: Module autoprobing not allowed. Append \"io=0xNNN\" value(s).\n");
- return -EPERM;
- }
- if (register_netdev(dev) != 0) {
- printk(KERN_WARNING "ne.c: No NE*000 card found (i/o = 0x%x).\n", io[this_dev]);
- if (found != 0) return 0; /* Got at least one. */
- return -ENXIO;
+ if (register_netdev(dev) == 0) {
+ found++;
+ continue;
}
- found++;
+ if (found != 0) /* Got at least one. */
+ return 0;
+ if (io[this_dev] != 0)
+ printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
+ else
+ printk(KERN_NOTICE "ne.c: No PCI cards found. Use \"io=0xNNN\" value(s) for ISA cards.\n");
+ return -ENXIO;
}

return 0;
diff -ur /tmp/linux-2113/drivers/pci/pci.c linux/drivers/pci/pci.c
--- /tmp/linux-2113/drivers/pci/pci.c Mon Nov 25 02:11:13 1996
+++ linux/drivers/pci/pci.c Mon Nov 25 02:10:25 1996
@@ -117,6 +117,7 @@
DEVICE( BUSLOGIC, BUSLOGIC_MULTIMASTER, "MultiMaster"),
DEVICE( BUSLOGIC, BUSLOGIC_FLASHPOINT, "FlashPoint"),
DEVICE( OAK, OAK_OTI107, "OTI107"),
+ DEVICE( WINBOND2, WINBOND2_89C940,"NE2000-PCI"),
DEVICE( PROMISE, PROMISE_5300, "DC5030"),
DEVICE( N9, N9_I128, "Imagine 128"),
DEVICE( N9, N9_I128_2, "Imagine 128v2"),
@@ -197,6 +198,7 @@
DEVICE( ZEITNET, ZEITNET_1225, "1225"),
DEVICE( SPECIALIX, SPECIALIX_XIO, "XIO/SIO host"),
DEVICE( SPECIALIX, SPECIALIX_RIO, "RIO host"),
+ DEVICE( COMPEX, COMPEX_RL2000, "ReadyLink 2000"),
DEVICE( RP, RP8OCTA, "RocketPort 8 Oct"),
DEVICE( RP, RP8INTF, "RocketPort 8 Intf"),
DEVICE( RP, RP16INTF, "RocketPort 16 Intf"),
@@ -479,6 +481,7 @@
case PCI_VENDOR_ID_SGS: return "SGS Thomson";
case PCI_VENDOR_ID_BUSLOGIC: return "BusLogic";
case PCI_VENDOR_ID_OAK: return "OAK";
+ case PCI_VENDOR_ID_WINBOND2: return "Winbond";
case PCI_VENDOR_ID_PROMISE: return "Promise Technology";
case PCI_VENDOR_ID_N9: return "Number Nine";
case PCI_VENDOR_ID_UMC: return "UMC";
@@ -516,6 +519,7 @@
case PCI_VENDOR_ID_TOSHIBA: return "Toshiba";
case PCI_VENDOR_ID_ZEITNET: return "ZeitNet";
case PCI_VENDOR_ID_SPECIALIX: return "Specialix";
+ case PCI_VENDOR_ID_COMPEX: return "Compex";
case PCI_VENDOR_ID_RP: return "Comtrol";
case PCI_VENDOR_ID_CYCLADES: return "Cyclades";
case PCI_VENDOR_ID_SYMPHONY: return "Symphony";
diff -ur /tmp/linux-2113/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- /tmp/linux-2113/drivers/scsi/sr.c Mon Nov 25 03:14:33 1996
+++ linux/drivers/scsi/sr.c Mon Nov 25 03:15:04 1996
@@ -315,7 +315,7 @@
}

if (SCpnt->sense_buffer[2] == NOT_READY) {
- printk("CD-ROM not ready. Make sure you have a disc in the drive.\n");
+ printk(KERN_INFO "CD-ROM not ready. Make sure you have a disc in the drive.\n");
SCpnt = end_scsi_request(SCpnt, 0, this_count);
requeue_sr_request(SCpnt); /* Do next request */
return;
diff -ur /tmp/linux-2113/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- /tmp/linux-2113/drivers/scsi/sr_ioctl.c Mon Nov 25 02:11:15 1996
+++ linux/drivers/scsi/sr_ioctl.c Mon Nov 25 02:10:26 1996
@@ -63,7 +63,7 @@
printk("Disc change detected.\n");
break;
case NOT_READY: /* This happens if there is no disc in drive */
- printk("CDROM not ready. Make sure there is a disc in the drive.\n");
+ printk(KERN_INFO "CDROM not ready. Make sure there is a disc in the drive.\n");
break;
case ILLEGAL_REQUEST:
printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n");
diff -ur /tmp/linux-2113/fs/buffer.c linux/fs/buffer.c
--- /tmp/linux-2113/fs/buffer.c Sun Nov 24 17:35:19 1996
+++ linux/fs/buffer.c Sun Nov 24 17:32:14 1996
@@ -17,6 +17,7 @@
*/

/* Some bdflush() changes for the dynamic ramdisk - Paul Gortmaker, 12/94 */
+/* Start bdflush() with kernel_thread not syscall - Paul Gortmaker, 12/95 */

#include <linux/sched.h>
#include <linux/kernel.h>
diff -ur /tmp/linux-2113/include/linux/pci.h linux/include/linux/pci.h
--- /tmp/linux-2113/include/linux/pci.h Mon Nov 25 02:11:19 1996
+++ linux/include/linux/pci.h Mon Nov 25 02:10:31 1996
@@ -349,6 +349,10 @@
#define PCI_VENDOR_ID_OAK 0x104e
#define PCI_DEVICE_ID_OAK_OTI107 0x0107

+/* Winbond have two vendor ID! See 0x10ad as well */
+#define PCI_VENDOR_ID_WINBOND2 0x1050
+#define PCI_DEVICE_ID_WINBOND2_89C940 0x0940
+
#define PCI_VENDOR_ID_PROMISE 0x105a
#define PCI_DEVICE_ID_PROMISE_5300 0x5300

@@ -504,6 +508,9 @@
#define PCI_VENDOR_ID_SPECIALIX 0x11cb
#define PCI_DEVICE_ID_SPECIALIX_XIO 0x4000
#define PCI_DEVICE_ID_SPECIALIX_RIO 0x8000
+
+#define PCI_VENDOR_ID_COMPEX 0x11f6
+#define PCI_DEVICE_ID_COMPEX_RL2000 0x1401

#define PCI_VENDOR_ID_RP 0x11fe
#define PCI_DEVICE_ID_RP8OCTA 0x0001
diff -ur /tmp/linux-2113/net/netsyms.c linux/net/netsyms.c
--- /tmp/linux-2113/net/netsyms.c Mon Nov 25 02:11:24 1996
+++ linux/net/netsyms.c Mon Nov 25 02:10:37 1996
@@ -44,10 +44,11 @@
#include <linux/net_alias.h>
#endif

-#if defined(CONFIG_ULTRA) || defined(CONFIG_WD80x3) || \
- defined(CONFIG_EL2) || defined(CONFIG_NE2000) || \
- defined(CONFIG_E2100) || defined(CONFIG_HPLAN_PLUS) || \
- defined(CONFIG_HPLAN) || defined(CONFIG_AC3200)
+#if defined(CONFIG_ULTRA) || defined(CONFIG_WD80x3) || \
+ defined(CONFIG_EL2) || defined(CONFIG_NE2000) || \
+ defined(CONFIG_E2100) || defined(CONFIG_HPLAN_PLUS) || \
+ defined(CONFIG_HPLAN) || defined(CONFIG_AC3200) || \
+ defined(CONFIG_ES3210)
#include "../drivers/net/8390.h"
#endif

@@ -189,7 +190,8 @@
#if defined(CONFIG_ULTRA) || defined(CONFIG_WD80x3) || \
defined(CONFIG_EL2) || defined(CONFIG_NE2000) || \
defined(CONFIG_E2100) || defined(CONFIG_HPLAN_PLUS) || \
- defined(CONFIG_HPLAN) || defined(CONFIG_AC3200)
+ defined(CONFIG_HPLAN) || defined(CONFIG_AC3200) || \
+ defined(CONFIG_ES3210)
/* If 8390 NIC support is built in, we will need these. */
X(ei_open),
X(ei_close),