@@ -795,6+795,14 @@ S: Molenbaan 29 S: B2240 Zandhoven
S: Belgium
+N: Martin Schulze
+E: joey@infodrom.north.de
+D: Random Linux Hacker, Linux Promoter
+D: CD-List, Books-List, Ex-FAQ
+D: Linux-Support, -Mailbox, -Stammtisch
+D: several improvements to system programs
+S: Oldenburg, Germany
+
N: Darren Senn
E: sinster@scintilla.santa-clara.ca.us
D: Whatever I notice needs doing (so far: itimers, /proc)
@@ -959,7+967,6 @@ S: 205 Gray Street NE S: Wilson, North Carolina 27893
S: USA
-
N: Marco van Wieringen
E: mvw@mercury.mcs.nl.mugnet.org
D: Author of acct and quota
VERSION = 1
PATCHLEVEL = 3
-SUBLEVEL = 17
+SUBLEVEL = 18
ARCH = i386
@@ -222,10+222,8 @@ repeat: goto repeat;
}
/* this is a hack for non-kernel-mapped video buffers and similar */
- if (page < high_memory) {
- page += addr & ~PAGE_MASK;
- *(unsigned long *) page = data;
- }
+ if (page < high_memory)
+ *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
/* this should also re-instate whatever read-only mode there was before */
*pgtable = pte_mkdirty(mk_pte(page, vma->vm_page_prot));
@@ -173,10+173,8 @@ repeat: goto repeat;
}
/* this is a hack for non-kernel-mapped video buffers and similar */
- if (page < high_memory) {
- page += addr & ~PAGE_MASK;
- *(unsigned long *) page = data;
- }
+ if (page < high_memory)
+ *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
/* this should also re-instate whatever read-only mode there was before */
*pgtable = pte_mkdirty(mk_pte(page, vma->vm_page_prot));
@@ -130,8+130,7 @@ void setup_arch(char **cmdline_p, request_region(0x70,0x10,"rtc");
request_region(0x80,0x20,"dma page reg");
request_region(0xc0,0x20,"dma2");
- request_region(0xf0,0x2,"npu");
- request_region(0xf8,0x8,"npu");
+ request_region(0xf0,0x10,"npu");
}
int get_cpuinfo(char * buffer)
-$Id: README.aztcd,v 1.50 1995/07/29 20:33:35 root Exp root $
+$Id: README.aztcd,v 1.60 1995/08/09 12:37:46 root Exp root $
Readme-File README.aztcd
for Aztech CD-ROM CDA268-01A, ORCHID CD-3110, OKANO/WEARNES CDD110
CD-ROM Driver
- Version 1.5 and newer
+ Version 1.6 and newer
(for other drives see 6.-8.)
NOTE: THIS DRIVER WILL WORK WITH THE CD-ROM DRIVES LISTED, WHICH HAVE
@@ -73,7+73,8 @@ CD-ROM drive at the base address specified in aztcd.h at compile time. This address can be overwritten by boot parameter aztcd=....You should reboot and
start Linux with boot parameter aztcd=<base address>, e.g. aztcd=0x320. If
you do not know the base address, start your PC with DOS and look at the boot
-message of your CD-ROM's DOS driver.
+message of your CD-ROM's DOS driver. If that still does not help, use boot
+parameter aztcd=<base address>,0x79 , this tells aztcd to try a little harder.
If the message looks correct, as user 'root' you should be able to mount the
drive by
@@ -181,11+182,10 @@ configured and mail me (see 6.) the appropriate information. 5. KNOWN PROBLEMS, FUTURE DEVELOPMENTS
5.1 MULTISESSION SUPPORT
I have now (July 1995) started support of multisession CDs. Unfortunately I
-do neither have a multisession CD nor use appropriate applications, so I can
-program, but will not test it :-(. If you'd like to help me, please contact
-me. As of version 1.4 you can enable the multisession support in aztcd.h by
-setting AZT_MULTISESSION to 1. As I have not tested it, I don't know, if it
-works ...
+do only have one multisession CD and no appropriate applications, so I can
+program, but testing is a little too less :-(. If you'd like to help me,
+please contact me. As of version 1.4 you can enable the multisession support
+in aztcd.h by setting AZT_MULTISESSION to 1.
5.2 STATUS RECOGNITION
The drive status recognition does not work correctly in all cases. Changing
@@ -497,7+497,7 @@ APPENDIX: Source code of cdplay.c
Copyright 1994, 1995 Werner Zimmermann (zimmerma@rz.fht-esslingen.de)
-This programm originally was written to test the audio functions of the
+This program originally was written to test the audio functions of the
AZTECH.CDROM-driver, but it should work with every CD-ROM drive. Before
using it, you should set a symlink from /dev/cdrom to your real CDROM
device.
@@ -545,7+545,7 @@ int main(void) } azt;
struct cdrom_volctrl volctrl;
- printf("\nMini-Audio CD-Player V0.7 (C) 1994,1995 W.Zimmermann\n");
+ printf("\nMini-Audio CD-Player V0.71 (C) 1994,1995 W.Zimmermann\n");
handle=open("/dev/cdrom",O_RDWR);
ioctl(handle,CDROMRESUME);
@@ -675,7+675,7 @@ int main(void) }
break;
case 'a': cmd=CDROMPLAYMSF;
- printf("Adress (min:sec:frame) ");
+ printf("Address (min:sec:frame) ");
scanf("%d:%d:%d",&arg1,&arg2,&arg3);
msf.cdmsf_min0 =arg1;
msf.cdmsf_sec0 =arg2;
@@ -686,12+686,12 @@ int main(void) msf.cdmsf_sec1=00;
msf.cdmsf_frame1=00;
if (ioctl(handle,cmd,&msf))
- { printf("Drive error or invalid adress\n");
+ { printf("Drive error or invalid address\n");
}
break;
#ifdef AZT_PRIVATE_IOCTLS /*not supported by every CDROM driver*/
case 'd': cmd=CDROMREADCOOKED;
- printf("Adress (min:sec:frame) ");
+ printf("Address (min:sec:frame) ");
scanf("%d:%d:%d",&arg1,&arg2,&arg3);
azt.msf.cdmsf_min0 =arg1;
azt.msf.cdmsf_sec0 =arg2;
@@ -699,7+699,7 @@ int main(void) if (azt.msf.cdmsf_sec0 > 59) azt.msf.cdmsf_sec0 =59;
if (azt.msf.cdmsf_frame0> 74) azt.msf.cdmsf_frame0=74;
if (ioctl(handle,cmd,&azt.msf))
- { printf("Drive error, invalid adress or unsupported command\n");
+ { printf("Drive error, invalid address or unsupported command\n");
}
k=0;
getchar();
@@ -724,7+724,7 @@ int main(void) }
break;
case 'w': cmd=CDROMREADRAW;
- printf("Adress (min:sec:frame) ");
+ printf("Address (min:sec:frame) ");
scanf("%d:%d:%d",&arg1,&arg2,&arg3);
azt.msf.cdmsf_min0 =arg1;
azt.msf.cdmsf_sec0 =arg2;
@@ -732,7+732,7 @@ int main(void) if (azt.msf.cdmsf_sec0 > 59) azt.msf.cdmsf_sec0 =59;
if (azt.msf.cdmsf_frame0> 74) azt.msf.cdmsf_frame0=74;
if (ioctl(handle,cmd,&azt))
- { printf("Drive error, invalid adress or unsupported command\n");
+ { printf("Drive error, invalid address or unsupported command\n");
}
k=0;
for (i=0;i<147;i++)
-#define AZT_VERSION "1.50"
-/* $Id: aztcd.c,v 1.50 1995/07/28 16:43:59 root Exp root $
+#define AZT_VERSION "1.60"
+/* $Id: aztcd.c,v 1.60 1995/08/09 12:37:38 root Exp root $
linux/drivers/block/aztcd.c - AztechCD268 CDROM driver
Copyright (C) 1994,1995 Werner Zimmermann (zimmerma@rz.fht-esslingen.de)
sometimes DOSEMU may hang for 30 seconds or so. A fully functional ver-
sion needs an update of Dosemu0.60's cdrom.c, which will come with the
next revision of Dosemu.
- Also Soundwave32 support no works.
+ Also Soundwave32 support now works.
Werner Zimmermann, May 22, 95
V1.30 Auto-eject feature. Inspired by Franc Racis (racis@psu.edu)
Werner Zimmermann, July 4, 95
XA, but still untested. Heavy modifications to drive status de-
tection.
Werner Zimmermann, July 25, 95
+ V1.60 XA support now should work. Speeded up drive recognition in cases,
+ where no drive is installed.
+ Werner Zimmermann, August 8, 1995
NOTE:
Points marked with ??? are questionable !
*/
@@ -193,7+196,6 @@ static int aztPresent = 0;
#define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA)
#define AZT_BUF_SIZ 16
-#define CD_XA_HEAD_SUBHEAD CD_XA_HEAD+8
static volatile int azt_transfer_is_active=0;
@@ -254,7+256,6 @@ static char aztTocUpToDate = 0; static void azt_transfer(void);
static void azt_poll(void);
static void azt_invalidate_buffers(void);
-static void do_aztcd_request(void);
static void azt_hsg2msf(long hsg, struct msf *msf);
static void azt_bin2bcd(unsigned char *p);
static int azt_bcd2bin(unsigned char bcd);
@@ -439,7+440,7 @@ static int sendAztCmd(int cmd, struct azt_Play_msf *params) int retry;
#ifdef AZT_DEBUG
- printk("start=%02x:%02x:%02x end=%02x:%02x:%02x\n", \
+ printk("aztcd: play start=%02x:%02x:%02x end=%02x:%02x:%02x\n", \
params->start.min, params->start.sec, params->start.frame, \
params->end.min, params->end.sec, params->end.frame);
#endif
@@ -633,7+634,7 @@ static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsi aztAudioStatus = CDROM_AUDIO_PLAY;
break;
#if AZT_MULTISESSION
- case CDROMMULTISESSION: /*multisession support -- not tested ???*/
+ case CDROMMULTISESSION: /*multisession support -- experimental*/
{ struct cdrom_multisession ms;
#ifdef AZT_DEBUG
printk("aztcd ioctl MULTISESSION\n");
@@ -656,12+657,12 @@ static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsi memcpy_tofs((void*) arg, &ms, sizeof(struct cdrom_multisession));
#ifdef AZT_DEBUG
if (ms.addr_format == CDROM_MSF)
- printk("aztcd multisession %d, %02x:%02x.%02x [%02x:%02x.%02x])\n",
+ printk("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n",
ms.xa_flag, ms.addr.msf.minute, ms.addr.msf.second,
ms.addr.msf.frame, DiskInfo.lastTrack.min,
DiskInfo.lastTrack.sec, DiskInfo.lastTrack.frame);
else
- printk("atzcd multisession %d, 0x%08x [%02x:%02x.%02x])\n",
+ printk("atzcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n",
ms.xa_flag, ms.addr.lba, DiskInfo.lastTrack.min,
DiskInfo.lastTrack.sec, DiskInfo.lastTrack.frame);
#endif
@@ -870,24+871,26 @@ azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame); azt_Play.end.min = msf.cdmsf_min1;
azt_Play.end.sec = msf.cdmsf_sec1;
azt_Play.end.frame = msf.cdmsf_frame1;
- if (cmd==CDROMREADCOOKED)
- { sendAztCmd(ACMD_PLAY_READ, &azt_Play);
+ if (cmd==CDROMREADRAW)
+ { if (DiskInfo.xa)
+ { return -1; /*XA Disks can't be read raw*/
+ }
+ else
+ { if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play)) return -1;
+ DTEN_LOW;
+ insb(DATA_PORT,buf,CD_FRAMESIZE_RAW);
+ memcpy_tofs((void *) arg, &buf, CD_FRAMESIZE_RAW);
+ }
+ }
+ else /*CDROMREADCOOKED*/
+ { if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) return -1;
DTEN_LOW;
insb(DATA_PORT,buf,CD_FRAMESIZE);
memcpy_tofs((void *) arg, &buf, CD_FRAMESIZE);
}
- else /*CDROMREADRAW*/
- { sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play);
- DTEN_LOW;
- insb(DATA_PORT,buf,CD_FRAMESIZE_RAW);
- memcpy_tofs((void *) arg, &buf, CD_FRAMESIZE_RAW);
- }
}
break;
#endif /*end of incompatible code*/
- case CDROMREADMODE0: /*set read data in mode 0, does not work with my drive*/
- printk ("aztcd Status %x\n", getAztStatus());
- return aztSetDiskType(AZT_MODE_0);
case CDROMREADMODE1: /*set read data in mode 1*/
return aztSetDiskType(AZT_MODE_1);
case CDROMREADMODE2: /*set read data in mode 2*/
@@ -1239,15+1242,7 @@ static void azt_poll(void) }
else
{ if (azt_read_mode==AZT_MODE_2)
- { if (DiskInfo.xa) /*With XA disks skip head and tail*/
- { unsigned char tmp_buf[CD_XA_TAIL];
- insb(DATA_PORT, tmp_buf , CD_XA_HEAD_SUBHEAD);
- insb(DATA_PORT, azt_buf + CD_FRAMESIZE * azt_buf_in, CD_FRAMESIZE);
- insb(DATA_PORT, tmp_buf , CD_XA_TAIL);
- }
- else
- { insb(DATA_PORT, azt_buf + CD_FRAMESIZE_RAW * azt_buf_in, CD_FRAMESIZE_RAW);
- }
+ { insb(DATA_PORT, azt_buf + CD_FRAMESIZE_RAW * azt_buf_in, CD_FRAMESIZE_RAW);
}
else
{ insb(DATA_PORT, azt_buf + CD_FRAMESIZE * azt_buf_in, CD_FRAMESIZE);
@@ -1417,25+1412,24 @@ int aztcd_open(struct inode *ip, struct file *fp) }
if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) /*no disk in drive or changed*/
- { printk("aztcd: No Disk in Drive or Disk Changed?\n");
+ { printk("aztcd: Disk Changed or No Disk in Drive?\n");
/* return -EIO;
*/ }
if (aztUpdateToc() < 0) return -EIO;
-/* Detect XA disks. XA disks will be read in raw mode, others not
- --> must set read command to read raw --> to be done ???
-*/ if (aztSetDiskType(DiskInfo.xa ? AZT_MODE_2 : AZT_MODE_1)) return -EIO;
- if (DiskInfo.xa) printk("aztcd: XA support not yet tested - please mail 'zimmerma@rz.fht-esslingen.de'\n");
+ /* XA detection was already done in aztGetToc */
+ if (DiskInfo.xa)
+ { printk("aztcd: XA support experimental - mail results to zimmerma@rz.fht-esslingen.de\n");
+ }
/* audio detection was already done in aztGetToc */
if (DiskInfo.audio)
{ printk(("aztcd: Audio-CD found\n"));
}
else
- { printk("aztcd: %s%s CD-ROM found\n",
- DiskInfo.xa ? "XA " : "",
- DiskInfo.multi ? "Multi Session" : "Single Session");
+ { printk("aztcd: %sCD-ROM found\n",
+ DiskInfo.xa ? "XA " : "");
}
}
++azt_open_count;
@@ -1546,45+1540,65 @@ int init_module(void) inb(CMD_PORT);
inb(CMD_PORT);
outb(ACMD_GET_VERSION,CMD_PORT); /*Try to get version info*/
- STEN_LOW;
- if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK? If not, reset and try again*/
- { printk("aztcd: drive reset - please wait\n");
- for (count=0;count<50;count++)
- { inb(STATUS_PORT); /*removing all data from earlier tries*/
- inb(DATA_PORT);
- }
- outb(POLLED,MODE_PORT); /*???*/
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_SOFT_RESET,CMD_PORT); /*send reset*/
- STEN_LOW;
- if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK?*/
- { printk("aztcd: no AZTECH CD-ROM drive found\n");
+
+/* STEN_LOW - special implementation for drive recognition
+*/ aztTimeOutCount=0;
+ do { aztIndatum=inb(STATUS_PORT);
+ aztTimeOutCount++;
+ if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break;
+ } while (aztIndatum&AFL_STATUS);
+
+ if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK? If not, reset and try again*/
+ {
+#ifndef MODULE
+ if (azt_cont!=0x79)
+ { printk("aztcd: no AZTECH CD-ROM drive found-Try boot parameter aztcd=<BaseAddress>,0x79\n");
+ return (mem_start);
+ }
+#else
+ if (0)
+ {
+ }
+#endif
+ else
+ { printk("aztcd: drive reset - please wait\n");
+ for (count=0;count<50;count++)
+ { inb(STATUS_PORT); /*removing all data from earlier tries*/
+ inb(DATA_PORT);
+ }
+ outb(POLLED,MODE_PORT); /*???*/
+ inb(CMD_PORT);
+ inb(CMD_PORT);
+ outb(ACMD_SOFT_RESET,CMD_PORT); /*send reset*/
+ STEN_LOW;
+ if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK?*/
+ { printk("aztcd: no AZTECH CD-ROM drive found\n");
#ifndef MODULE
- return (mem_start);
+ return (mem_start);
#else
- return -EIO;
+ return -EIO;
#endif
- }
- for (count = 0; count < AZT_TIMEOUT; count++); /* delay a bit */
- if ((st=getAztStatus())==-1)
- { printk("aztcd: Drive Status Error Status=%x\n",st);
+ }
+ for (count = 0; count < AZT_TIMEOUT; count++); /* delay a bit */
+ if ((st=getAztStatus())==-1)
+ { printk("aztcd: Drive Status Error Status=%x\n",st);
#ifndef MODULE
- return (mem_start);
+ return (mem_start);
#else
- return -EIO;
+ return -EIO;
#endif
- }
+ }
#ifdef AZT_DEBUG
- printk("aztcd: Status = %x\n",st);
+ printk("aztcd: Status = %x\n",st);
#endif
- outb(POLLED,MODE_PORT); /*???*/
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_GET_VERSION,CMD_PORT); /*GetVersion*/
- STEN_LOW;
- OP_OK;
- }
+ outb(POLLED,MODE_PORT); /*???*/
+ inb(CMD_PORT);
+ inb(CMD_PORT);
+ outb(ACMD_GET_VERSION,CMD_PORT); /*GetVersion*/
+ STEN_LOW;
+ OP_OK;
+ }
+ }
azt_init_end=1;
STEN_LOW;
result[0]=inb(DATA_PORT); /*reading in a null byte???*/
@@ -1612,7+1626,7 @@ int init_module(void) else /*OTHERS or none*/
{ printk("aztcd: : unknown drive or firmware version detected\n");
printk(" azt may not run stable, if you want to try anyhow,\n");
- printk(" boot with: aztcd=base_address,0x79\n");
+ printk(" boot with: aztcd=<BaseAddress>,0x79\n");
if ((azt_cont!=0x79))
{ printk("aztcd: FirmwareVersion=");
for (count=1;count<5;count++) printk("%c",result[count]);
@@ -1872,14+1886,16 @@ static int aztGetToc()
Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
-/*support for XA and multisession CDs not yet working ???*/
- DiskInfo.multi = 0; /*how to get this info ???*/
- if (!DiskInfo.multi) DiskInfo.lastTrack.sec=2;
+ /*support for multisession CDs is done automatically with Aztech drives,
+ we don't have to take care about TOC redirection */
+ DiskInfo.multi = 0;
+ DiskInfo.lastTrack.min = Toc[DiskInfo.last].diskTime.min;
+ DiskInfo.lastTrack.sec = Toc[DiskInfo.last].diskTime.sec;
+ DiskInfo.lastTrack.frame= Toc[DiskInfo.last].diskTime.frame;
+
+ /*try to detect XA disks*/
i = getAztStatus();
- DiskInfo.xa = i & AST_MODE; /* I doubt this will work ??? */
- DiskInfo.lastTrack.min =Toc[DiskInfo.last].diskTime.min;
- DiskInfo.lastTrack.sec =Toc[DiskInfo.last].diskTime.sec;
- DiskInfo.lastTrack.frame=Toc[DiskInfo.last].diskTime.frame;
+ DiskInfo.xa = i & AST_MODE; /* XA info sometimes unreliable ??? */
/*try to detect audio disks; with my Aztech drive there is no audio
status bit, so I use the copy protection bit of the first track. If
@@ -186,7+186,6 @@ static char mcdVersion; static void mcd_transfer(void);
static void mcd_poll(void);
static void mcd_invalidate_buffers(void);
-static void do_mcd_request(void);
static void hsg2msf(long hsg, struct msf *msf);
static void bin2bcd(unsigned char *p);
static int bcd2bin(unsigned char bcd);
@@ -148,9+148,7 @@ static void do_load(void) }
/* Try ext2 */
- if (nblocks == -1 && (ext2sb->s_magic ==
- EXT2_PRE_02B_MAGIC ||
- ext2sb->s_magic == EXT2_SUPER_MAGIC))
+ if (nblocks == -1 && ext2sb->s_magic == EXT2_SUPER_MAGIC)
{
printk("RAMDISK: Ext2 filesystem found at block %d\n",
block);
@@ -1180,8+1180,7 @@ unsigned long kbd_init(unsigned long kmem_start)
bh_base[KEYBOARD_BH].routine = kbd_bh;
request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard");
- request_region(0x60,1,"kbd");
- request_region(0x64,1,"kbd");
+ request_region(0x60,16,"kbd");
#ifdef __alpha__
/* enable keyboard interrupts, PC/AT mode */
kb_wait();
* Copyright (C) 1993 by Nigel Gamble (added interrupt code)
* Copyright (C) 1994 by Alan Cox (Modularised it)
* LPCAREFUL, LPABORT, LPGETSTATUS added by Chris Metcalf, metcalf@lcs.mit.edu
+ * Statistics and support for slow printers by Rob Janssen, rob@knoware.nl
*/
#ifdef MODULE
#include <linux/malloc.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <asm/segment.h>
* if you have more than 3 printers, remember to increase LP_NO
*/
struct lp_struct lp_table[] = {
- { 0x3bc, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
- { 0x378, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
- { 0x278, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
+ { 0x3bc, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
+ { 0x378, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
+ { 0x278, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
};
#define LP_NO 3
@@ -54,33+56,24 @@ struct lp_struct lp_table[] = { /*
* All my debugging code assumes that you debug with only one printer at
* a time. RWWH
+ * Debug info moved into stats area, so this is no longer true (Rob Janssen)
*/
#undef LP_DEBUG
static int lp_reset(int minor)
{
- int testvalue;
- unsigned char command;
-
- command = LP_PSELECP | LP_PINITP;
-
- /* reset value */
- outb_p(0, LP_C(minor));
- for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
- ;
- outb_p(command, LP_C(minor));
+ outb_p(LP_PSELECP, LP_C(minor));
+ udelay(LP_DELAY);
+ outb_p(LP_PSELECP | LP_PINITP, LP_C(minor));
return LP_S(minor);
}
-#ifdef LP_DEBUG
-static int lp_max_count = 1;
-#endif
-
-static int lp_char_polled(char lpchar, int minor)
+static inline int lp_char_polled(char lpchar, int minor)
{
- int status = 0, wait = 0;
+ int status, wait = 0;
unsigned long count = 0;
+ struct lp_stats *stats;
do {
status = LP_S(minor);
@@ -93,13+86,9 @@ static int lp_char_polled(char lpchar, int minor) return 0;
/* we timed out, and the character was /not/ printed */
}
-#ifdef LP_DEBUG
- if (count > lp_max_count) {
- printk("lp success after %d counts.\n",count);
- lp_max_count=count;
- }
-#endif
outb_p(lpchar, LP_B(minor));
+ stats = &LP_STAT(minor);
+ stats->chars++;
/* must wait before taking strobe high, and after taking strobe
low, according spec. Some printers need it, others don't. */
while(wait != LP_WAIT(minor)) wait++;
@@ -108,58+97,76 @@ static int lp_char_polled(char lpchar, int minor) while(wait) wait--;
/* take strobe low */
outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
+ /* update waittime statistics */
+ if (count > stats->maxwait) {
+#ifdef LP_DEBUG
+ printk(KERN_DEBUG "lp%d success after %d counts.\n",minor,count);
+#endif
+ stats->maxwait = count;
+ }
+ count *= 256;
+ wait = (count > stats->meanwait)? count - stats->meanwait :
+ stats->meanwait - count;
+ stats->meanwait = (255*stats->meanwait + count + 128) / 256;
+ stats->mdev = ((127 * stats->mdev) + wait + 64) / 128;
return 1;
}
-static int lp_char_interrupt(char lpchar, int minor)
+static inline int lp_char_interrupt(char lpchar, int minor)
{
- int wait = 0;
+ int wait;
+ unsigned long count = 0;
unsigned char status;
+ struct lp_stats *stats;
-
- if (!((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
- || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
- || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)) {
-
+ do {
+ if ((status = LP_S(minor)) & LP_PBUSY) {
if (!LP_CAREFUL_READY(minor, status))
return 0;
outb_p(lpchar, LP_B(minor));
+ stats = &LP_STAT(minor);
+ stats->chars++;
/* must wait before taking strobe high, and after taking strobe
low, according spec. Some printers need it, others don't. */
+ wait = 0;
while(wait != LP_WAIT(minor)) wait++;
/* control port takes strobe high */
outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
while(wait) wait--;
/* take strobe low */
outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
+ /* update waittime statistics */
+ if (count) {
+ if (count > stats->maxwait)
+ stats->maxwait = count;
+ count *= 256;
+ wait = (count > stats->meanwait)? count - stats->meanwait :
+ stats->meanwait - count;
+ stats->meanwait = (255*stats->meanwait + count + 128) / 256;
+ stats->mdev = ((127 * stats->mdev) + wait + 64) / 128;
+ }
return 1;
- }
+ }
+ } while (count++ < LP_CHAR(minor));
return 0;
}
-#ifdef LP_DEBUG
- unsigned int lp_total_chars = 0;
- unsigned int lp_last_call = 0;
-#endif
-
static void lp_interrupt(int irq, struct pt_regs *regs)
{
struct lp_struct *lp = &lp_table[0];
- struct lp_struct *lp_end = &lp_table[LP_NO];
while (irq != lp->irq) {
- if (++lp >= lp_end)
+ if (++lp >= &lp_table[LP_NO])
return;
}
wake_up(&lp->lp_wait_q);
}
-static int lp_write_interrupt(struct inode * inode, struct file * file, const char * buf, int count)
+static inline int lp_write_interrupt(unsigned int minor, const char * buf, int count)
{
- unsigned int minor = MINOR(inode->i_rdev);
unsigned long copy_size;
unsigned long total_bytes_written = 0;
unsigned long bytes_written;
@@ -175,8+182,11 @@ static int lp_write_interrupt(struct inode * inode, struct file * file, const ch if (lp_char_interrupt(lp->lp_buffer[bytes_written], minor)) {
--copy_size;
++bytes_written;
+ lp_table[minor].runchars++;
} else {
int rc = total_bytes_written + bytes_written;
+ if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
+ LP_STAT(minor).maxrun = lp_table[minor].runchars;
status = LP_S(minor);
if ((status & LP_POUTPA)) {
printk(KERN_INFO "lp%d out of paper\n", minor);
@@ -191,6+201,7 @@ static int lp_write_interrupt(struct inode * inode, struct file * file, const ch if (LP_F(minor) & LP_ABORT)
return rc?rc:-EIO;
}
+ LP_STAT(minor).sleeps++;
cli();
outb_p((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor)));
status = LP_S(minor);
@@ -200,6+211,7 @@ static int lp_write_interrupt(struct inode * inode, struct file * file, const ch sti();
continue;
}
+ lp_table[minor].runchars=0;
current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
interruptible_sleep_on(&lp->lp_wait_q);
outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
@@ -222,34+234,24 @@ static int lp_write_interrupt(struct inode * inode, struct file * file, const ch return total_bytes_written;
}
-static int lp_write_polled(struct inode * inode, struct file * file,
- const char * buf, int count)
+static inline int lp_write_polled(unsigned int minor, const char * buf, int count)
{
- int retval;
- unsigned int minor = MINOR(inode->i_rdev);
+ int retval,status;
char c;
- const char *temp = buf;
-
-#ifdef LP_DEBUG
- if (jiffies-lp_last_call > LP_TIME(minor)) {
- lp_total_chars = 0;
- lp_max_count = 1;
- }
- lp_last_call = jiffies;
-#endif
+ const char *temp;
temp = buf;
while (count > 0) {
c = get_user(temp);
retval = lp_char_polled(c, minor);
/* only update counting vars if character was printed */
- if (retval) { count--; temp++;
-#ifdef LP_DEBUG
- lp_total_chars++;
-#endif
- }
- if (!retval) { /* if printer timed out */
- int status = LP_S(minor);
+ if (retval) {
+ count--; temp++;
+ lp_table[minor].runchars++;
+ } else { /* if printer timed out */
+ if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
+ LP_STAT(minor).maxrun = lp_table[minor].runchars;
+ status = LP_S(minor);
if (status & LP_POUTPA) {
printk(KERN_INFO "lp%d out of paper\n", minor);
@@ -284,11+286,12 @@ static int lp_write_polled(struct inode * inode, struct file * file, else
return -EINTR;
}
+ LP_STAT(minor).sleeps++;
#ifdef LP_DEBUG
- printk("lp sleeping at %d characters for %d jiffies\n",
- lp_total_chars, LP_TIME(minor));
- lp_total_chars=0;
+ printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n",
+ minor,lp_table[minor].runchars, LP_TIME(minor));
#endif
+ lp_table[minor].runchars=0;
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + LP_TIME(minor);
schedule();
@@ -299,10+302,16 @@ static int lp_write_polled(struct inode * inode, struct file * file,
static int lp_write(struct inode * inode, struct file * file, const char * buf, int count)
{
- if (LP_IRQ(MINOR(inode->i_rdev)))
- return lp_write_interrupt(inode, file, buf, count);
+ unsigned int minor = MINOR(inode->i_rdev);
+
+ if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
+ lp_table[minor].runchars = 0;
+ lp_table[minor].lastcall = jiffies;
+
+ if (LP_IRQ(minor))
+ return lp_write_interrupt(minor, buf, count);
else
- return lp_write_polled(inode, file, buf, count);
+ return lp_write_polled(minor, buf, count);
}
static int lp_lseek(struct inode * inode, struct file * file,
@@ -392,7+401,7 @@ static int lp_ioctl(struct inode *inode, struct file *file, int retval = 0;
#ifdef LP_DEBUG
- printk("lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
+ printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
#endif
if (minor >= LP_NO)
return -ENODEV;
@@ -489,6+498,17 @@ static int lp_ioctl(struct inode *inode, struct file *file, case LPRESET:
lp_reset(minor);
break;
+ case LPGETSTATS:
+ retval = verify_area(VERIFY_WRITE, (void *) arg,
+ sizeof(struct lp_stats));
+ if (retval)
+ return retval;
+ else {
+ memcpy_tofs((int *) arg, &LP_STAT(minor), sizeof(struct lp_stats));
+ if (suser())
+ memset(&LP_STAT(minor), 0, sizeof(struct lp_stats));
+ }
+ break;
default:
retval = -EINVAL;
}
@@ -517,8+537,9 @@ long lp_init(long kmem_start) #endif
{
int offset = 0;
- unsigned int testvalue = 0;
+ unsigned int testvalue;
int count = 0;
+ int base,size;
if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) {
printk("lp: unable to get major %d\n", LP_MAJOR);
@@ -530,18+551,19 @@ long lp_init(long kmem_start) }
/* take on all known port values */
for (offset = 0; offset < LP_NO; offset++) {
- if (check_region(LP_B(offset), 3))
+ base = LP_B(offset);
+ size = (base == 0x3bc)? 3 : 8;
+ if (check_region(base, size))
continue;
/* write to port & read back to check */
- outb_p( LP_DUMMY, LP_B(offset));
- for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
- ;
- testvalue = inb_p(LP_B(offset));
+ outb_p( LP_DUMMY, base);
+ udelay(LP_DELAY);
+ testvalue = inb_p(base);
if (testvalue == LP_DUMMY) {
LP_F(offset) |= LP_EXIST;
lp_reset(offset);
- printk("lp%d at 0x%04x, ", offset,LP_B(offset));
- request_region(LP_B(offset), 3, "lp");
+ printk("lp%d at 0x%04x, ", offset,base);
+ request_region(base, size, "lp");
if (LP_IRQ(offset))
printk("(irq = %d)\n", LP_IRQ(offset));
else
@@ -559,6+581,7 @@ long lp_init(long kmem_start) return kmem_start;
#endif
}
+ int base,size;
#ifdef MODULE
void cleanup_module(void)
@@ -1785,21+1785,37 @@ static int set_multiport_struct(struct async_struct * info,
multi->port_monitor = new_multi.port_monitor;
+ if (multi->port1)
+ release_region(multi->port1,1);
multi->port1 = new_multi.port1;
multi->mask1 = new_multi.mask1;
multi->match1 = new_multi.match1;
+ if (multi->port1)
+ request_region(multi->port1,1,"serial(multiport1)");
+ if (multi->port2)
+ release_region(multi->port2,1);
multi->port2 = new_multi.port2;
multi->mask2 = new_multi.mask2;
multi->match2 = new_multi.match2;
+ if (multi->port2)
+ request_region(multi->port2,1,"serial(multiport2)");
+ if (multi->port3)
+ release_region(multi->port3,1);
multi->port3 = new_multi.port3;
multi->mask3 = new_multi.mask3;
multi->match3 = new_multi.match3;
+ if (multi->port3)
+ request_region(multi->port3,1,"serial(multiport3)");
+ if (multi->port4)
+ release_region(multi->port4,1);
multi->port4 = new_multi.port4;
multi->mask4 = new_multi.mask4;
multi->match4 = new_multi.match4;
+ if (multi->port4)
+ request_region(multi->port4,1,"serial(multiport4)");
now_multi = (multi->port1 != 0);
@@ -473,7+473,7 @@ static struct device el2_drv = static struct device el2pio_drv =
{"3c503pio", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el2_pio_probe };
-int io = 0;
+int io = 0x300;
int irq = 0;
static int no_pio = 1;
@@ -485,6+485,9 @@ int init_module(void) el2pio_drv.base_addr = io;
el2pio_drv.irq = irq;
+ if (io == 0)
+ printk("3c503: You should not use auto-probing with insmod!\n");
+
rc2 = 0;
no_pio = 1;
rc1 = register_netdev(&el2_drv);
@@ -1462,11+1462,13 @@ char kernel_version[] = UTS_RELEASE; static struct device dev_3c505 = {
" " /*"3c505"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, elplus_probe };
-int io = 0;
+int io = 0x300;
int irq = 0;
int init_module(void)
{
+ if (io == 0)
+ printk("3c505: You should not use auto-probing with insmod!\n");
dev_3c505.base_addr = io;
dev_3c505.irq = irq;
if (register_netdev(&dev_3c505) != 0) {
@@ -888,11+888,13 @@ char kernel_version[] = UTS_RELEASE; static struct device dev_3c507 = {
" " /*"3c507"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el16_probe };
-int io = 0;
+int io = 0x300;
int irq = 0;
int init_module(void)
{
+ if (io == 0)
+ printk("3c507: You should not use auto-probing with insmod!\n");
dev_3c507.base_addr = io;
dev_3c507.irq = irq;
if (register_netdev(&dev_3c507) != 0) {
@@ -171,6+171,14 @@ int el3_probe(struct device *dev) ID_PORT. We find cards past the first by setting the 'current_tag'
on cards as they are found. Cards with their tag set will not
respond to subsequent ID sequences. */
+
+ if (check_region(ID_PORT,1)) {
+ static int once = 1;
+ if (once) printk("3c509: Somebody has reserved 0x%x, can't do ID_PORT lookup, nor card auto-probing\n",ID_PORT);
+ once = 0;
+ return -ENODEV;
+ }
+
outb(0x00, ID_PORT);
outb(0x00, ID_PORT);
for(i = 0; i < 255; i++) {
@@ -698,9+706,17 @@ char kernel_version[] = UTS_RELEASE; static struct device dev_3c509 = {
" " /*"3c509"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el3_probe };
+int io = 0;
+int irq = 0;
+
int
init_module(void)
{
+ dev_3c509.base_addr = io;
+ dev_3c509.irq = irq;
+ if (!EISA_bus) {
+ printk("3c509: WARNING! Module load-time probing works reliably only for EISA-bus!\n");
+ }
if (register_netdev(&dev_3c509) != 0)
return -EIO;
return 0;
@@ -84,12+84,12 @@ static const char *version = #ifdef EI_DEBUG
int ei_debug = EI_DEBUG;
#else
-int ei_debug = 0;
+int ei_debug = 1;
#endif
-#ifdef EI_NOPINGPONG
-static int ei_pingpong = 0;
-#else
+#ifdef EI_PINGPONG
static int ei_pingpong = 1;
+#else
+static int ei_pingpong = 0;
#endif
/* Max number of packets received at one Intr.
@@ -145,10+145,12 @@ Windows: See DOS :) Trumpet Winsock works fine with either the Novell or LAN Manager and Windows for Workgroups: These programs use protocols that
are incompatible with the internet standard. They try to pretend
the cards are ethernet, and confuse everyone else on the network.
- However, v1.90 ALPHA and later of the Linux ARCnet driver support
- this protocol via the 'arc0w' device. After setting up arc0 as
- usual, ifconfig and set up routes to your WfWg-protocol hosts
- through arc0w.
+ However, v1.93 ALPHA and later of the Linux ARCnet driver support
+ this protocol via the 'arc0e' device. After setting up arc0 as
+ usual, ifconfig and set up routes to your ethernet-encap hosts
+ through arc0e. There may be non-Microsoft products that support
+ this protocol as well, so it was changed in 1.93 ALPHA from arc0w
+ to arc0e.
Using the freeware Samba server and clients for Linux, you can now
interface quite nicely with TCP/IP-based WfWg or Lan Manager
@@ -2,12+2,34 @@ Wed 2-Aug-95 <matti.aarnio@utu.fi>
Linux network driver modules
- This is a potpourri of INSMOD-time(*) configuration
- options (if exist) and their default values of various
- modules on Linux network drivers collection.
-
- Do NOT mistake this to "README.modules" at the top-level
- directory!
+ Do not mistake this to "README.modules" at the top-level
+ directory! That document tells about modules in general, while
+ this one tells only about network device driver modules.
+
+ This is a potpourri of INSMOD-time(*) configuration options
+ (if such exists) and their default values of various modules
+ on Linux network drivers collection.
+
+ Some modules have also hidden (= non-documented) tunable values.
+ Choice of not documenting them is based on general belief, that
+ the less user needs to know, the better. (There are things that
+ driver developer can use, others should not confuse themselves.)
+
+ In many cases it is highly preferred that insmod:ing is done
+ ONLY with defining an explicite address for the card, AND BY
+ NOT USING AUTO-PROBING!
+
+ Now most cards have some explicitely defined base address, they
+ are compiled with (to avoid auto-probing, among other things).
+ If that compiled value does not match your actual configuration,
+ do use "io=0xXXX" -parameter for the insmod, and give there
+ a value matching your environment.
+
+ If you are adventureous, you can ask the driver to autoprobe
+ by using "io=0" parameter, however it is potentially dangerous
+ thing to do in a live system. (If you don't know where the
+ card is located, you can try autoprobing, and after possible
+ crash recovery, insmod with proper IO-address..)
--------------------------
(*) "INSMOD-time" means when you load module with
@@ -22,29+44,29 @@ Wed 2-Aug-95 <matti.aarnio@utu.fi> (Probes ports: 0x280, 0x300)
3c503.c:
- io = 0
+ io = 0x300
irq = 0
(Probes ports: 0x300, 0x310, 0x330, 0x350, 0x250, 0x280, 0x2A0, 0x2E0)
3c505.c:
- io = 0
+ io = 0x300
irq = 0
(Probes ports: 0x300, 0x280, 0x310)
3c507.c:
- io = 0
+ io = 0x300
irq = 0
(Probes ports: 0x300, 0x320, 0x340, 0x280)
3c509.c:
- No parameters (autoprobes)
- (EISA, and MCA probes in addition to ISA-probes;
- ISA probing via PCMCIA AutoConfig (or similar)
- via port 0x100.)
+ io = 0
+ irq = 0
+ ( Module load-time probing Works reliably only on EISA, ISA ID-PROBE
+ IS NOT RELIABLE! Compile this driver statically into kernel for
+ now, if you need it auto-probing on an ISA-bus machine. )
8390.c:
- ei_debug = 0
- ei_pingpong = 1 (If no Rx/Tx PINGPONG is desired, set to zero)
+ (No public options, several other modules need this one)
ac3200.c:
io = 0
@@ -60,6+82,7 @@ arcnet.c: irqnum = 0
shmem = 0
num = 0
+ DO SET THESE MANUALLY AT INSMOD!
(When probing, looks at the following possible addresses:
Suggested ones:
0x300, 0x2E0, 0x2F0, 0x2D0
@@ -70,7+93,7 @@ arcnet.c: 0x380, 0x390, 0x3A0, 0x3E0, 0x3F0 )
at1700.c:
- io = 0
+ io = 0x260
irq = 0
(Probes ports: 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300)
@@ -107,17+130,17 @@ dummy.c: No options
e2100.c:
- io = 0
+ io = 0x300
irq = 0
(Probes ports: 0x300, 0x280, 0x380, 0x220)
eepro.c:
- io = 0
+ io = 0x200
irq = 0
(Probes ports: 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0x360)
eexpress.c:
- io = 0
+ io = 0x300
irq = 0
(Probes ports: 0x300, 0x270, 0x320, 0x340)
@@ -135,14+158,13 @@ ewrk3.c: 0x300, 0x340, 0x360, 0x380, 0x3A0, 0x3C0)
hp-plus.c:
- io = 0
+ io = 0x200
irq = 0
(Probes ports: 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340)
hp.c:
- io = 0
+ io = 0x300
irq = 0
- ne8390_rw_bugfix = 0
(Probes ports: 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240)
hp100.c:
@@ -152,7+174,7 @@ hp100.c: in increments of 0x020)
ibmtr.c:
- io = 0
+ io = 0xA20
(Probes ports: 0xA20, 0xA24 -- Ok, 0x220, 0x224, but IBM style..)
lance.c: *Not modularized*
@@ -162,10+184,8 @@ lance.c: *Not modularized* loopback.c: *Static kernel component*
ne.c:
- io = 0
+ io = 0x300
irq = 0
- config_ne_sanity = 0
- ne8390_rw_bugfix = 0;
(Probes ports: 0x300, 0x280, 0x320, 0x340, 0x360)
net_init.c: *Static kernel component*
@@ -205,7+225,7 @@ slip.c:
smc-ultra.c:
- io = 0
+ io = 0x200
irq = 0
(Probes ports: 0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380)
@@ -220,7+240,7 @@ wavelan.c: irq = 0 (Not honoured, if changed..)
wd.c:
- io = 0
+ io = 0x300
irq = 0
mem = 0 (Force shared-memory on address 0xC8000, or whatever..)
(Probes ports: 0x300, 0x280, 0x380, 0x240,
**********************
+ v1.93 ALPHA (95/08/10)
+ - Should work with both 1.2.x and 1.3.x now. (I hope)
+ - Renamed arc0w ("Windows" protocol) to arc0e ("Ethernet-Encap")
+ because the protocol used isn't necessarily limited to
+ Microsoft.
+
v1.92 ALPHA (95/07/11)
- Fixes to make things work with kernel 1.3.x. Completely broke
1.2.x support. Oops? 1.2.x users keep using 1.91 ALPHA until I
v1.91 ALPHA (95/07/02)
- Oops. Exception packets hit us again! I remembered to test
- them in Windows-protocol mode, but due to the many various
+ them in ethernet-protocol mode, but due to the many various
changes they broke in RFC1201 instead. All fixed.
- A long-standing bug with "exception" packets not setting
protocol_id properly has been corrected. This would have caused
IRQ.
- Initial support for "multiprotocol" ARCnet (this involved a LOT
of reorganizing!). Added an arc0w device, which allows us to
- talk to "Windows" ARCnet TCP/IP protocol. To use it, ifconfig
- arc0 and arc0w (in that order). For now, Windows-protocol
+ talk to ethernet-over-ARCnet TCP/IP protocol. To use it, ifconfig
+ arc0 and arc0w (in that order). For now, ethernet-protocol
hosts should have routes through arc0w - eventually I hope to
make things more automatic.
v1.11 ALPHA (95/06/07)
If someone sends me information, I'll try to implement it.
- Remove excess lock variables that are probably not necessary
anymore due to the changes in Linux 1.2.9.
+ - Dump Linux 1.2 and properly use the extended 1.3.x skb functions.
+ - Problems forwarding from arc0e to arc0 in 1.3.x? (it may be a
+ general kernel bug, though, since I heard other people complaining
+ about forwarding problems on ethernet cards)
+ - D_SKB doesn't work right on 1.3.x kernels.
Sources:
*/
static const char *version =
- "arcnet.c:v1.92 ALPHA 95/07/11 Avery Pennarun <apenwarr@foxnet.net>\n";
-
+ "arcnet.c:v1.93 ALPHA 95/08/10 Avery Pennarun <apenwarr@foxnet.net>\n";
+
/**************************************************************************/
/* Define this if you want to detect network reconfigurations.
@@ -156,11+167,19 @@ static const char *version =
#include <linux/config.h>
+#include <linux/version.h>
+
#ifdef MODULE
#include <linux/module.h>
-#include <linux/version.h>
#endif /* MODULE */
+
+/* are we Linux 1.2.x? */
+#if LINUX_VERSION_CODE < 0x10300
+#define LINUX12
+#endif
+
+
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
@@ -229,11+248,11 @@ extern struct device *irq2dev_map[16];
/* Some useful multiprotocol macros */
#define TBUSY lp->adev->tbusy \
- =lp->wdev->tbusy
+ =lp->edev->tbusy
#define IF_TBUSY (lp->adev->tbusy \
- || lp->wdev->tbusy)
+ || lp->edev->tbusy)
#define START lp->adev->start \
- =lp->wdev->start
+ =lp->edev->start
/* The number of low I/O ports used by the ethercard. */
@@ -416,7+435,7 @@ struct arcnet_local { struct Outgoing outgoing; /* packet currently being sent */
struct device *adev; /* RFC1201 protocol device */
- struct device *wdev; /* Windows protocol device */
+ struct device *edev; /* Ethernet-Encap device */
};
@@ -426,7+445,7 @@ extern int arcnet_probe(struct device *dev); static int arcnet_memprobe(struct device *dev,u_char *addr);
static int arcnet_ioprobe(struct device *dev, short ioaddr);
#endif
-static int arcnetW_init(struct device *dev);
+static int arcnetE_init(struct device *dev);
static int arcnet_open(struct device *dev);
static int arcnet_close(struct device *dev);
@@ -438,7+457,7 @@ static void arcnetA_prepare_tx(struct device *dev,struct ClientData *hdr, short length,char *data);
static void arcnetA_go_tx(struct device *dev);
-static int arcnetW_send_packet(struct sk_buff *skb, struct device *dev);
+static int arcnetE_send_packet(struct sk_buff *skb, struct device *dev);
static void arcnet_interrupt(int irq,struct pt_regs *regs);
static void arcnet_inthandler(struct device *dev);
@@ -446,15+465,21 @@ static void arcnet_inthandler(struct device *dev); static void arcnet_rx(struct device *dev,int recbuf);
static void arcnetA_rx(struct device *dev,struct ClientData *arcsoft,
int length,u_char saddr, u_char daddr);
-static void arcnetW_rx(struct device *dev,u_char *arcsoft,
+static void arcnetE_rx(struct device *dev,u_char *arcsoft,
int length,u_char saddr, u_char daddr);
static struct enet_statistics *arcnet_get_stats(struct device *dev);
static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
- /* annoying functions for header/arp/etc building */
-int arcnetA_header(struct sk_buff *skb,struct device *dev,unsigned short type,
- void *daddr,void *saddr,unsigned len);
+ /* functions for header/arp/etc building */
+#ifdef LINUX12
+int arcnetA_header(unsigned char *buff,struct device *dev,
+ unsigned short type,void *daddr,void *saddr,unsigned len,
+ struct sk_buff *skb);
+#else
+int arcnetA_header(struct sk_buff *skb,struct device *dev,
+ unsigned short type,void *daddr,void *saddr,unsigned len);
+#endif
int arcnetA_rebuild_header(void *eth,struct device *dev,unsigned long raddr,
struct sk_buff *skb);
unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev);
@@ -652,6+677,10 @@ arcnet_probe(struct device *dev)
dev->hard_header=arcnetA_header;
dev->rebuild_header=arcnetA_rebuild_header;
+
+ #ifdef LINUX12
+ dev->type_trans=arcnetA_type_trans;
+ #endif
return 0;
}
@@ -886,21+915,21 @@ int arcnet_reset(struct device *dev) return 0;
}
-static int arcnetW_init(struct device *dev)
+static int arcnetE_init(struct device *dev)
{
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- ether_setup(lp->wdev);
+ ether_setup(lp->edev);
dev->dev_addr[0]=0;
dev->dev_addr[5]=lp->arcnum;
dev->mtu=493; /* MTU is small because of missing packet splitting */
- lp->wdev->open=NULL;
- lp->wdev->stop=NULL;
- lp->wdev->hard_start_xmit=arcnetW_send_packet;
+ lp->edev->open=NULL;
+ lp->edev->stop=NULL;
+ lp->edev->hard_start_xmit=arcnetE_send_packet;
BUGLVL(D_EXTRA)
- printk("%s: ARCnet \"Windows\" protocol initialized.\n",
- lp->wdev->name);
+ printk("%s: ARCnet \"Ethernet-Encap\" protocol initialized.\n",
+ lp->edev->name);
return 0;
}
@@ -953,13+982,13 @@ arcnet_open(struct device *dev) printk("%s: ARCnet RFC1201 protocol initialized.\n",
lp->adev->name);
- /* Initialize the Windows protocol driver */
- lp->wdev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
- memcpy(lp->wdev,dev,sizeof(struct device));
- lp->wdev->name=(char *)kmalloc(10,GFP_KERNEL);
- sprintf(lp->wdev->name,"%sw",dev->name);
- lp->wdev->init=arcnetW_init;
- register_netdev(lp->wdev);
+ /* Initialize the ethernet-encap protocol driver */
+ lp->edev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
+ memcpy(lp->edev,dev,sizeof(struct device));
+ lp->edev->name=(char *)kmalloc(10,GFP_KERNEL);
+ sprintf(lp->edev->name,"%se",dev->name);
+ lp->edev->init=arcnetE_init;
+ register_netdev(lp->edev);
/* we're started */
START=1;
@@ -992,13+1021,13 @@ arcnet_close(struct device *dev) /* do NOT free lp->adev!! It's static! */
lp->adev=NULL;
- /* free the Windows protocol device */
- lp->wdev->start=0;
- lp->wdev->priv=NULL;
- unregister_netdev(lp->wdev);
- kfree(lp->wdev->name);
- kfree(lp->wdev);
- lp->wdev=NULL;
+ /* free the ethernet-encap protocol device */
+ lp->edev->start=0;
+ lp->edev->priv=NULL;
+ unregister_netdev(lp->edev);
+ kfree(lp->edev->name);
+ kfree(lp->edev);
+ lp->edev=NULL;
/* Update the statistics here. */
@@ -1408,15+1437,15 @@ arcnetA_go_tx(struct device *dev) }
-/* Called by the kernel in order to transmit a "Windows" packet.
+/* Called by the kernel in order to transmit an ethernet-type packet.
*/
static int
-arcnetW_send_packet(struct sk_buff *skb, struct device *dev)
+arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
{
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
BUGLVL(D_DURING)
- printk("%s: in arcnetW_send_packet (skb=%p)\n",dev->name,skb);
+ printk("%s: in arcnetE_send_packet (skb=%p)\n",dev->name,skb);
if (IF_TBUSY)
{
@@ -1457,8+1486,8 @@ arcnetW_send_packet(struct sk_buff *skb, struct device *dev)
if (length>XMTU)
{
- printk("arcnet: MTU for %s and %s must be <= 493 for Windows protocol.\n",
- lp->adev->name,lp->wdev->name);
+ printk("arcnet: MTU for %s and %s must be <= 493 for ethernet encap.\n",
+ lp->adev->name,lp->edev->name);
printk("arcnet: transmit aborted.\n");
dev_kfree_skb(skb,FREE_WRITE);
@@ -1827,7+1856,7 @@ arcnet_rx(struct device *dev,int recbuf) length,saddr,daddr);
break;
case ARC_P_MS_TCPIP:
- arcnetW_rx(dev,arcsoft,length,saddr,daddr);
+ arcnetE_rx(dev,arcsoft,length,saddr,daddr);
break;
default:
printk("arcnet: received unknown protocol %d (%Xh)\n",
@@ -1853,6+1882,11 @@ arcnet_rx(struct device *dev,int recbuf) }
+ /* clean out the page to make debugging make more sense :) */
+ BUGLVL(D_DURING)
+ memset((void *)arcpacket->raw,0x42,512);
+
+
/* If any worth-while packets have been received, a mark_bh(NET_BH)
* has been done by netif_rx and Linux will handle them after we
* return.
@@ -1972,7+2006,9 @@ arcnetA_rx(struct device *dev,struct ClientData *arcsoft, printk("\n");
}
- skb->protocol=arcnetA_type_trans(skb,dev);
+ #ifndef LINUX12
+ skb->protocol=arcnetA_type_trans(skb,dev);
+ #endif
netif_rx(skb);
lp->stats.rx_packets++;
@@ -2136,8+2172,11 @@ arcnetA_rx(struct device *dev,struct ClientData *arcsoft, printk("\n");
}
- skb->protocol=arcnetA_type_trans(skb,dev);
-
+
+ #ifndef LINUX12
+ skb->protocol=arcnetA_type_trans(skb,dev);
+ #endif
+
netif_rx(skb);
lp->stats.rx_packets++;
}
@@ -2145,17+2184,17 @@ arcnetA_rx(struct device *dev,struct ClientData *arcsoft, }
-/* Packet receiver for non-standard Windows-style packets
+/* Packet receiver for non-standard ethernet-style packets
*/
static void
-arcnetW_rx(struct device *dev,u_char *arcsoft,
+arcnetE_rx(struct device *dev,u_char *arcsoft,
int length,u_char saddr, u_char daddr)
{
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
struct sk_buff *skb;
BUGLVL(D_DURING)
- printk("arcnet: it's a Windows packet (length=%d)\n",
+ printk("arcnet: it's an ethernet-encap packet (length=%d)\n",
length);
skb = alloc_skb(length, GFP_ATOMIC);
@@ -2166,7+2205,7 @@ arcnetW_rx(struct device *dev,u_char *arcsoft, }
skb->len = length;
- skb->dev = lp->wdev;
+ skb->dev = lp->edev;
memcpy(skb->data,(u_char *)arcsoft+1,length-1);
@@ -2184,7+2223,9 @@ arcnetW_rx(struct device *dev,u_char *arcsoft, printk("\n");
}
- skb->protocol=eth_type_trans(skb,dev);
+ #ifndef LINUX12
+ skb->protocol=eth_type_trans(skb,dev);
+ #endif
netif_rx(skb);
lp->stats.rx_packets++;
@@ -2235,11+2276,21 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs) * saddr=NULL means use device source address (always will anyway)
* daddr=NULL means leave destination address (eg unresolved arp)
*/
-int arcnetA_header(struct sk_buff *skb,struct device *dev,unsigned short type,
- void *daddr,void *saddr,unsigned len)
+#ifdef LINUX12
+int arcnetA_header(unsigned char *buff,struct device *dev,
+ unsigned short type,void *daddr,void *saddr,unsigned len,
+ struct sk_buff *skb)
+#else
+int arcnetA_header(struct sk_buff *skb,struct device *dev,
+ unsigned short type,void *daddr,void *saddr,unsigned len)
+#endif
{
struct ClientData *head = (struct ClientData *)
+#ifdef LINUX12
+ buff;
+#else
skb_push(skb,dev->hard_header_len);
+#endif
/* struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);*/
/* set the protocol ID according to RFC-1201 */
@@ -2350,9+2401,11 @@ unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev) struct ClientData *head = (struct ClientData *) skb->data;
struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
+#ifndef LINUX12
/* Pull off the arcnet header. */
skb->mac.raw=skb->data;
skb_pull(skb,dev->hard_header_len);
+#endif
if (head->daddr==0)
skb->pkt_type=PACKET_BROADCAST;
@@ -2409,6+2462,9 @@ int num=0; /* number of device (ie for 0 for arc0, 1 for arc1...) */ int
init_module(void)
{
+ if (io == 0)
+ printk("arcnet: You should not use auto-probing with insmod!\n");
+
sprintf(thiscard.name,"arc%d",num);
thiscard.base_addr=io;
@@ -57,8+57,6 @@ static const char *version = #include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-extern struct device *init_etherdev(struct device *dev, int sizeof_private,
- unsigned long *mem_startp);
/* This unusual address order is used to verify the CONFIG register. */
static int at1700_probe_list[] =
@@ -634,11+632,13 @@ char kernel_version[] = UTS_RELEASE; static struct device dev_at1700 = {
" " /*"at1700"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, at1700_probe };
-int io = 0;
+int io = 0x260;
int irq = 0;
int init_module(void)
{
+ if (io == 0)
+ printk("at1700: You should not use auto-probing with insmod!\n");
dev_at1700.base_addr = io;
dev_at1700.irq = irq;
if (register_netdev(&dev_at1700) != 0) {
@@ -1829,6+1829,8 @@ static int io=0x200; /* Or use the irq= io= options to insmod */ int
init_module(void)
{
+ if (io == 0)
+ printk("depca: You should not use auto-probing with insmod!\n");
thisDepca.irq=irq;
thisDepca.base_addr=io;
if (register_netdev(&thisDepca) != 0)
@@ -359,11+359,13 @@ char kernel_version[] = UTS_RELEASE; static struct device dev_e2100 = {
" " /*"e2100"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, e2100_probe };
-int io = 0;
+int io = 0x300;
int irq = 0;
int init_module(void)
{
+ if (io == 0)
+ printk("e2100: You should not use auto-probing with insmod!\n");
dev_e2100.base_addr = io;
dev_e2100.irq = irq;
if (register_netdev(&dev_e2100) != 0) {
@@ -103,8+103,7 @@ static const char *version = #include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-extern struct device *init_etherdev(struct device *dev, int sizeof_private,
- unsigned long *mem_startp);
+
/* First, a few definitions that the brave might change. */
/* A zero-terminated list of I/O addresses to be probed. */
@@ -1137,12+1136,14 @@ char kernel_version[] = UTS_RELEASE; static struct device dev_eepro = {
" " /*"eepro"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, eepro_probe };
-int io = 0;
+int io = 0x200;
int irq = 0;
int
init_module(void)
{
+ if (io == 0)
+ printk("eepro: You should not use auto-probing with insmod!\n");
dev_eepro.base_addr = io;
dev_eepro.irq = irq;
@@ -1006,12+1006,14 @@ static struct device dev_eexpress = { " " /*"eexpress"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe };
-int irq=0;
+int irq=0x300;
int io=0;
int
init_module(void)
{
+ if (io == 0)
+ printk("eexpress: You should not use auto-probing with insmod!\n");
dev_eexpress.base_addr=io;
dev_eexpress.irq=irq;
if (register_netdev(&dev_eexpress) != 0)
@@ -39,8+39,6 @@ static const char *version =
#include "8390.h"
-extern struct device *init_etherdev(struct device *dev, int sizeof_private,
- unsigned long *mem_startp);
/* A zero-terminated list of I/O addresses to be probed. */
static unsigned int hpplus_portlist[] =
@@ -372,11+370,13 @@ char kernel_version[] = UTS_RELEASE; static struct device dev_hp = {
" " /*"hp"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, hp_plus_probe };
-int io = 0;
+int io = 0x200;
int irq = 0;
int init_module(void)
{
+ if (io == 0)
+ printk("HP-plus: You should not use auto-probing with insmod!\n");
dev_hp.base_addr = io;
dev_hp.irq = irq;
if (register_netdev(&dev_hp) != 0) {
@@ -72,9+72,6 @@ static void hp_init_card(struct device *dev); /* My default is IRQ5 0 1 2 3 4 5 6 7 8 9 10 11 */
static char irqmap[16] = { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0};
-/* NE2000, et.al. bug-fix code */
-static int ne8390_rw_bugfix = 0;
-
\f
/* Probe for an HP LAN adaptor.
Also initialize the card and fill in STATION_ADDR with the station
@@ -275,19+272,19 @@ hp_block_output(struct device *dev, int count, /* We should already be in page 0, but to be safe... */
outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base);
- if (ne8390_rw_bugfix) {
- /* Handle the read-before-write bug the same way as the
- Crynwr packet driver -- the NatSemi method doesn't work. */
- outb_p(0x42, nic_base + EN0_RCNTLO);
- outb_p(0, nic_base + EN0_RCNTHI);
- outb_p(0xff, nic_base + EN0_RSARLO);
- outb_p(0x00, nic_base + EN0_RSARHI);
+#ifdef NE8390_RW_BUGFIX
+ /* Handle the read-before-write bug the same way as the
+ Crynwr packet driver -- the NatSemi method doesn't work. */
+ outb_p(0x42, nic_base + EN0_RCNTLO);
+ outb_p(0, nic_base + EN0_RCNTHI);
+ outb_p(0xff, nic_base + EN0_RSARLO);
+ outb_p(0x00, nic_base + EN0_RSARHI);
#define NE_CMD 0x00
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- /* Make certain that the dummy read has occurred. */
- inb_p(0x61);
- inb_p(0x61);
- }
+ outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+ /* Make certain that the dummy read has occurred. */
+ inb_p(0x61);
+ inb_p(0x61);
+#endif
outb_p(count & 0xff, nic_base + EN0_RCNTLO);
outb_p(count >> 8, nic_base + EN0_RCNTHI);
@@ -333,11+330,13 @@ char kernel_version[] = UTS_RELEASE; static struct device dev_hp = {
" " /*"hp"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, hp_probe };
-int io = 0;
+int io = 300;
int irq = 0;
int init_module(void)
{
+ if (io == 0)
+ printk("hp: You should not use auto-probing with insmod!\n");
dev_hp.base_addr = io;
dev_hp.irq = irq;
if (register_netdev(&dev_hp) != 0) {
@@ -1135,6+1135,8 @@ static struct device dev_hp100 = {
int init_module( void )
{
+ if (hp100_port == 0 && !EISA_bus)
+ printk("HP100: You should not use auto-probing with insmod!\n");
if ( hp100_port > 0 )
dev_hp100.base_addr = hp100_port;
if ( register_netdev( &dev_hp100 ) != 0 )
@@ -1201,10+1201,12 @@ char kernel_version[] = UTS_RELEASE; static struct device dev_ibmtr = {
" " /*"ibmtr"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, tok_probe };
-int io = 0;
+int io = 0xa20;
int init_module(void)
{
+ if (io == 0)
+ printk("ibmtr: You should not use auto-probing with insmod!\n");
dev_ibmtr.base_addr = io;
dev_ibmtr.irq = 0;
if (register_netdev(&dev_ibmtr) != 0) {
@@ -51,19+51,9 @@ static const char *version =
/* Do we perform extra sanity checks on stuff ? */
/* #define CONFIG_NE_SANITY */
-#ifdef CONFIG_NE_SANITY
-static int config_ne_sanity = 1;
-#else
-static int config_ne_sanity = 0;
-#endif
/* Do we implement the read before write bugfix ? */
/* #define CONFIG_NE_RW_BUGFIX */
-#ifdef CONFIG_NE_RW_BUGFIX
-static int ne8390_rw_bugfix = 1;
-#else
-static int ne8390_rw_bugfix = 0;
-#endif
/* ---- No user-serviceable parts below ---- */
@@ -388,8+378,9 @@ static int ne_block_input(struct device *dev, int count, char *buf, int ring_offset)
{
int nic_base = dev->base_addr;
- /* CONFIG_NE_SANITY */
+#ifdef CONFIG_NE_SANITY
int xfer_count = count;
+#endif
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
@@ -411,19+402,20 @@ ne_block_input(struct device *dev, int count, char *buf, int ring_offset) insw(NE_BASE + NE_DATAPORT,buf,count>>1);
if (count & 0x01) {
buf[count-1] = inb(NE_BASE + NE_DATAPORT);
- /* CONFIG_NE_SANITY */
+#ifdef CONFIG_NE_SANITY
xfer_count++;
+#endif
}
} else {
insb(NE_BASE + NE_DATAPORT, buf, count);
}
+#ifdef CONFIG_NE_SANITY
/* This was for the ALPHA version only, but enough people have
been encountering problems so it is still here. If you see
this message you either 1) have a slightly incompatible clone
or 2) have noise/speed problems with your bus. */
- if (config_ne_sanity &&
- ei_debug > 1) { /* DMA termination address check... */
+ if (ei_debug > 1) { /* DMA termination address check... */
int addr, tries = 20;
do {
/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
@@ -439,6+431,7 @@ ne_block_input(struct device *dev, int count, char *buf, int ring_offset) "%#4.4x (expected) vs. %#4.4x (actual).\n",
dev->name, ring_offset + xfer_count, addr);
}
+#endif
outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
ei_status.dmaing &= ~0x01;
return ring_offset + count;
@@ -450,8+443,9 @@ ne_block_output(struct device *dev, int count, {
int nic_base = NE_BASE;
unsigned long dma_start;
- /* CONFIG_NE_SANITY */
+#ifdef CONFIG_NE_SANITY
int retries = 0;
+#endif
/* Round the count up for word writes. Do we need to do this?
What effect will an odd byte count have on the 8390?
@@ -472,23+466,25 @@ ne_block_output(struct device *dev, int count, /* We should already be in page 0, but to be safe... */
outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+#ifdef CONFIG_NE_SANITY
retry:
+#endif
- if (ne8390_rw_bugfix) {
- /* Handle the read-before-write bug the same way as the
- Crynwr packet driver -- the NatSemi method doesn't work.
- Actually this doesn't always work either, but if you have
- problems with your NEx000 this is better than nothing! */
- outb_p(0x42, nic_base + EN0_RCNTLO);
- outb_p(0x00, nic_base + EN0_RCNTHI);
- outb_p(0x42, nic_base + EN0_RSARLO);
- outb_p(0x00, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- /* Make certain that the dummy read has occurred. */
- SLOW_DOWN_IO;
- SLOW_DOWN_IO;
- SLOW_DOWN_IO;
- }
+#ifdef NE8390_RW_BUGFIX
+ /* Handle the read-before-write bug the same way as the
+ Crynwr packet driver -- the NatSemi method doesn't work.
+ Actually this doesn't always work either, but if you have
+ problems with your NEx000 this is better than nothing! */
+ outb_p(0x42, nic_base + EN0_RCNTLO);
+ outb_p(0x00, nic_base + EN0_RCNTHI);
+ outb_p(0x42, nic_base + EN0_RSARLO);
+ outb_p(0x00, nic_base + EN0_RSARHI);
+ outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+ /* Make certain that the dummy read has occurred. */
+ SLOW_DOWN_IO;
+ SLOW_DOWN_IO;
+ SLOW_DOWN_IO;
+#endif
outb_p(ENISR_RDC, nic_base + EN0_ISR);
@@ -507,10+503,10 @@ ne_block_output(struct device *dev, int count,
dma_start = jiffies;
+#ifdef CONFIG_NE_SANITY
/* This was for the ALPHA version only, but enough people have
been encountering problems so it is still here. */
- if (config_ne_sanity &&
- ei_debug > 1) { /* DMA termination address check... */
+ if (ei_debug > 1) { /* DMA termination address check... */
int addr, tries = 20;
do {
int high = inb_p(nic_base + EN0_RSARHI);
@@ -527,6+523,7 @@ ne_block_output(struct device *dev, int count, goto retry;
}
}
+#endif
while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
@@ -546,11+543,13 @@ char kernel_version[] = UTS_RELEASE; static struct device dev_ne2000 = {
" " /*"ne2000"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ne_probe };
-int io = 0;
+int io = 0x300;
int irq = 0;
int init_module(void)
{
+ if (io == 0)
+ printk("ne: You should not use auto-probing with insmod!\n");
dev_ne2000.base_addr = io;
dev_ne2000.irq = irq;
if (register_netdev(&dev_ne2000) != 0)
@@ -312,8+312,6 @@ void unregister_netdev(struct device *dev) save_flags(flags);
cli();
- printk("unregister_netdev: device ");
-
if (dev == NULL)
{
printk("was NULL\n");
@@ -333,11+331,10 @@ void unregister_netdev(struct device *dev) if (d && (d->next == dev))
{
d->next = dev->next;
- printk("'%s' unlinked\n", dev->name);
}
else
{
- printk("'%s' not found\n", dev->name);
+ printk("unregister_netdev: '%s' not found\n", dev->name);
restore_flags(flags);
return;
}
@@ -207,7+207,7 @@ plip_init(struct device *dev) struct net_local *nl;
/* Check region before the probe */
- if (check_region(PAR_DATA(dev), 3) < 0)
+ if (check_region(PAR_DATA(dev), (PAR_DATA(dev) == 0x3bc)? 4 : 8) < 0)
return -ENODEV;
/* Check that there is something at base_addr. */
@@ -244,7+244,7 @@ plip_init(struct device *dev) " Please set IRQ by ifconfig.\n", irq);
}
- request_region(PAR_DATA(dev), 3, dev->name);
+ request_region(PAR_DATA(dev), (PAR_DATA(dev) == 0x3bc)? 4 : 8, dev->name);
/* Fill in the generic fields of the device structure. */
ether_setup(dev);
@@ -1082,19+1082,19 @@ cleanup_module(void) {
if (dev_plip0.priv) {
unregister_netdev(&dev_plip0);
- release_region(PAR_DATA(&dev_plip0), 3);
+ release_region(PAR_DATA(&dev_plip0), (PAR_DATA(&dev_plip0) == 0x3bc)? 4 : 8);
kfree_s(dev_plip0.priv, sizeof(struct net_local));
dev_plip0.priv = NULL;
}
if (dev_plip1.priv) {
unregister_netdev(&dev_plip1);
- release_region(PAR_DATA(&dev_plip1), 3);
+ release_region(PAR_DATA(&dev_plip1), (PAR_DATA(&dev_plip1) == 0x3bc)? 4 : 8);
kfree_s(dev_plip1.priv, sizeof(struct net_local));
dev_plip1.priv = NULL;
}
if (dev_plip2.priv) {
unregister_netdev(&dev_plip2);
- release_region(PAR_DATA(&dev_plip2), 3);
+ release_region(PAR_DATA(&dev_plip2), (PAR_DATA(&dev_plip2) == 0x3bc)? 4 : 8);
kfree_s(dev_plip2.priv, sizeof(struct net_local));
dev_plip2.priv = NULL;
}
@@ -1175,8+1175,8 @@ slip_init_ctrl_dev(struct device *dummy) * now needs to be unregistered.
*/
#ifndef MODULE
- printk("SLIP: Unregistering bootstrap device "
- "'slip_proto' - slip OK\n");
+/* printk("SLIP: Unregistering bootstrap device "
+ "'slip_proto' - slip OK\n");*/
unregister_netdev(dummy);
#endif
return status;
@@ -328,11+328,13 @@ char kernel_version[] = UTS_RELEASE; static struct device dev_ultra = {
" " /*"smc-ultra"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ultra_probe };
-int io = 0;
+int io = 0x200;
int irq = 0;
int init_module(void)
{
+ if (io == 0)
+ printk("smc-ultra: You should not use auto-probing with insmod!\n");
dev_ultra.base_addr = io;
dev_ultra.irq = irq;
if (register_netdev(&dev_ultra) != 0) {
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
*/
-static char *version = "tulip.c:v0.05 1/20/95 becker@cesdis.gsfc.nasa.gov\n";
+static const char *version = "tulip.c:v0.05 1/20/95 becker@cesdis.gsfc.nasa.gov\n";
#ifdef MODULE
#include <linux/module.h>
@@ -40,10+40,6 @@ static char *version = "tulip.c:v0.05 1/20/95 becker@cesdis.gsfc.nasa.gov\n"; #include <linux/etherdevice.h>
#include <linux/skbuff.h>
-/* This will be in linux/etherdevice.h someday. */
-struct device *init_etherdev(struct device *dev, int sizeof_private,
- unsigned long *mem_startp);
-
/* The total size is unusually large: The 21040 aligns each of its 16
longword-wide registers on a quadword boundary. */
#define TULIP_TOTAL_SIZE 0x80
@@ -757,6+753,11 @@ int irq = 0;
int init_module(void)
{
+ printk("tulip: Sorry, modularization is not completed\n");
+ return -EIO;
+#if 0
+ if (io == 0)
+ printk("tulip: You should not use auto-probing with insmod!\n");
dev_tulip.base_addr = io;
dev_tulip.irq = irq;
if (register_netdev(&dev_tulip) != 0) {
@@ -764,6+765,7 @@ int init_module(void) return -EIO;
}
return 0;
+#endif
}
void
@@ -839,8+839,8 @@ wavelan_probe(device *dev) if (wavelan_debug > 0)
printk("%s: <-wavelan_probe(): 0\n", dev->name);
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_WAVELAN, wavelan_get_info,
- 7, "wavelan" });
+ { PROC_NET_WAVELAN, 7, "wavelan",
+ wavelan_get_info });
return 0;
}
@@ -400,12+400,14 @@ char kernel_version[] = UTS_RELEASE; static struct device dev_wd80x3 = {
" " /*"wd80x3"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, wd_probe };
-int io = 0;
+int io = 0x300;
int irq = 0;
int mem = 0;
int init_module(void)
{
+ if (io == 0)
+ printk("wd: You should not use auto-probing with insmod!\n");
dev_wd80x3.base_addr = io;
dev_wd80x3.irq = irq;
dev_wd80x3.mem_start = mem;
@@ -421,6+423,11 @@ cleanup_module(void) printk("wd80x3: device busy, remove delayed\n");
else
{
+ int ioaddr = dev_wd80x3.base_addr - WD_NIC_OFFSET;
+
+ free_irq(dev_wd80x3.irq);
+ release_region(ioaddr, WD_IO_EXTENT);
+
unregister_netdev(&dev_wd80x3);
}
}
-Changelog for version 3.0
--------------------------
+Changelog for version 3.0.1
+---------------------------
+
+Since 3.0
+- Some important bug fixes.
+- select() for /dev/dsp and /dev/audio (Linux only).
+(To use select() with read, you have to call read() to start
+the recording. Calling write() kills recording immediately so
+use select() carefully when you are writing a half duplex app.
+Full duplex mode is not implemented yet.) Select works also with
+/dev/sequencer and /dev/music. Maybe with /dev/midi## too.
Since 3.0-beta2
- Minor fixes.
@@ -7,22+7,13 @@ sites). It contains much more information than this file. * about configuring various cards. *
*****************************************************************
-VoxWare v3.0 release notes
---------------------------
+VoxWare v3.0.1 release notes
+----------------------------
This version is the final v3.0. All features I have planned to
include in v3.0 are there but some of them are completely untested
(see experimental.txt).
-NOTE! This Linux only distribution doesn't contain files required
- for other operating systems than Linux. They are distributed
- in file VoxWare-3.0.tar.gz which is available from
- sunsite.unc.edu:pub/Linux/kernel/sound (or pub/Linux/Incoming).
-
- Also some utilities for SoundScape, PSS and AudioTriX cards
- have been removed. They are available in VoxWare-3.0.tar.gz and
- in snd-util-3.0.tar.gz (when I have time to release it).
-
*** GUS MAX enhancements *****************************************************
Recording with GUS MAX works now. The configuration program asks
two DMA channels for GUS MAX. You have to use two different 16 bit
@@ -178,7+169,8 @@ Sponsors etc. The following companies have greatly helped development of this driver
in form of a free copy of their product:
-Novell Inc, UnixWare personal edition + SDK
+Novell, Inc. UnixWare personal edition + SDK
+The Santa Cruz Operation, Inc. A SCO OpenServer + SDK
Ensoniq Corp, a SoundScape card and extensive amount of assistance
MediaTriX Peripherals Inc, a AudioTriX Pro card + SDK
@@ -202,6+194,8 @@ If you have some problems =========================
Read the sound HOWTO (sunsite.unc.edu:/pub/Linux/docs/...?).
+Also look at the home page (http://personal.eunet.fi/pp/voxware). It may
+contain info about some recent bug fixes.
It's likely that you have some problems when trying to use the sound driver
first time. Soundcards don't have standard configuration so there are no
@@ -249,6+243,13 @@ In general the printout of of /dev/sndstat should tell what is the problem. It's possible that there are bugs in the sound driver but 99% of the problems
reported to me are caused by somehow incorrect setup during "make config".
+For owners of TI TM4000M notebooks
+----------------------------------
+
+There appears to be some kind of conflict between the sound support
+(MV Jazz), mouse port and VoxWare. You could try to configure kernel
+with the C&T 82C710 mouse port support disabled.
+
Hannu
Regards,
@@ -109,7+109,7 @@ PSS based cards (AD1848 + ADSP-2115 + Echo ESC614 ASIC) MediaTriX AudioTriX Pro
The ATP card is built around a CS4231 codec and a OPL4 synthesizer
chips. The OPL4 mode is supported by a microcontroller running a
- General MIDI emulator. There is also SB 1.5 playback mode.
+ General MIDI emulator. There is also a SB 1.5 compatible playback mode.
Ensoniq SoundScape and compatibles
Ensoniq has designed a soundcard architecture based on the
@@ -128,6+128,39 @@ Audio Excell DSP16 Support for this card is made by Riccardo Faccetti
(riccardo@cdc8g5.cdc.polimi.it). See aedsp16.c for more info.
+Jumpers and software configuration
+----------------------------------
+
+Some of the earliest soundcards were jumper configurable. You have to
+configure VoxWare to configure VoxWare use I/O, IRQ and DMA settings
+that match the jumpers. Just few 8 bit cards are fully jumper
+configurable (SB 1.x/2.x, SB Pro and clones).
+Some cards made by Aztech have an EEPROM which contains the
+config info. These cards behave much like hardware jumpered cards.
+
+Most cards have jumper for the base I/O address but other parameters
+are software configurable. Sometimes there are few other jumpers too.
+
+Latest cards are fully software configurable or they are PnP ISA
+compatible. There are no jumpers on the board.
+
+VoxWare handles software configurable cards automaticly. Just configure
+the driver to use I/O, IRQ and DMA settings which are known to work.
+You could usually use the same values than with DOS and/or Windows.
+Using different settings is possible but not recommended since it may cause
+some trouble (for example when warm booting from an OS to another or
+when installing new hardware to the machine).
+
+VoxWare sets the soft configurable parameters of the card automaticly
+during boot. Usually you don't need to run any extra initialization
+programs when booting Linux but there are some exceptions. See the
+card specific instructions (below) for more info.
+
+The drawback of software configuration is that the driver needs to know
+how the card must be initialized. It cannot initialize unknown cards
+even if they are otherwise compatible with some other cards (like SB,
+MPU401 or Windows Sound System).
+
What if your card was not listed above?
---------------------------------------
@@ -495,7+528,7 @@ AudioTriX Pro -------------
You have to enable the OPL3 and SB (not SB Pro or SB16) drivers in addition
-to the native AudioTriX driver. You don't need to enable MSS or MPU drivers.
+to the native AudioTriX driver. Don't enable MSS or MPU drivers.
Configuring ATP is little bit tricky since it uses so many I/O, IRQ and
DMA numbers. Using the same values than with DOS/Win is a good idea. Don't
@@ -608,6+641,10 @@ contact me if you have a soundcard which uses these chips. Some MAD16 based cards may cause feedback, whistle or terrible noise if the
line3 mixer channel is turned too high.
+If you have a MAD16 card which have an OPL4 (FM + Wave table) synthesizer
+chip (_not_ an OPL3), you have to apped line containing #define MAD16_OPL4
+to the file linux/dirvers/sound/local.h (after running make config).
+
MV Jazz (ProSonic)
------------------
* The CS4231 which is used in the GUS MAX and some other cards is
* upwards compatible with AD1848 and this driver is able to drive it.
*
+ * CS4231A and AD1845 are upward compatible with CS4231. However
+ * the new features of these chips are different.
+ *
+ * CS4232 is a PnP audio chip which contains a CS4231A.
+ *
* Copyright by Hannu Savolainen 1994, 1995
*
* Redistribution and use in source and binary forms, with or without
@@ -1039,7+1044,7 @@ ad1848_halt (int dev) OUTB (0, io_Status (devc)); /* Clear interrupt status */
ad_leave_MCE (devc);
- DMAbuf_reset_dma (dev);
+ /* DMAbuf_reset_dma (dev); */
}
int
@@ -1181,17+1186,46 @@ ad1848_detect (int io_base) if ((ad_read (devc, 25) & 0xe7) == (tmp1 & 0xe7))
{
/*
- * It's a CS4231
+ * It's at least CS4231
*/
devc->chip_name = "CS4231";
-
#ifdef MOZART_PORT
if (devc->base != MOZART_PORT + 4)
#endif
devc->mode = 2;
+ /*
+ * It could be an AD1845 or CS4231A as well.
+ * CS4231 and AD1845 report the same revision info in I25
+ * while the CS4231A reports different.
+ */
+ if ((ad_read (devc, 25) & 0xe7) == 0xa0)
+ {
+ devc->chip_name = "CS4231A";
+ }
+ else if ((ad_read (devc, 25) & 0xe7) == 0x80)
+ {
+ /*
+ * It must be a CS4231 or AD1845. The register I23 of
+ * CS4231 is undefined and it appears to be read only.
+ * AD1845 uses I23 for setting sample rate. Assume
+ * the chip is AD1845 if I23 is changeable.
+ */
+
+ unsigned char tmp = ad_read (devc, 23);
+
+ ad_write (devc, 23, ~tmp);
+ if (ad_read (devc, 23) != tmp) /* AD1845 ? */
+ {
+ devc->chip_name = "AD1845";
+ }
+
+ ad_write (devc, 23, tmp); /* Restore */
+ }
+
+ /* Otherwise behave just as if the chip is a CS4231 */
}
ad_write (devc, 25, tmp1); /* Restore bits */
}
@@ -410,9+410,6 @@ audio_ioctl (int dev, struct fileinfo *file, if (err < 0)
return err;
- if (wr_buff_no[dev] != -1)
- info.bytes += wr_buff_ptr[dev];
-
IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info));
return 0;
}
@@ -478,7+475,7 @@ audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) break;
case SEL_OUT:
- if (audio_mode[dev] != AM_WRITE) /* Wrong direction */
+ if (audio_mode[dev] == AM_READ) /* Wrong direction */
return 0;
if (wr_buff_no[dev] != -1)
@@ -489,14+489,46 @@ DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) case SNDCTL_DSP_GETOSPACE:
if (!local)
return RET_ERROR (EINVAL);
+ else
+ {
+ audio_buf_info *info = (audio_buf_info *) arg;
- {
- audio_buf_info *info = (audio_buf_info *) arg;
+ if (!(dmap->flags & DMA_ALLOC_DONE))
+ reorganize_buffers (dev);
- info->fragments = dmap->qlen;
- info->fragsize = dmap->fragment_size;
- info->bytes = dmap->qlen * dmap->fragment_size;
- }
+ if (cmd == SNDCTL_DSP_GETISPACE)
+ info->fragments = dmap->qlen;
+ else
+ {
+ if (!space_in_queue (dev))
+ info->fragments = 0;
+ else
+ {
+ info->fragments = dmap->nbufs - dmap->qlen;
+ if (audio_devs[dev]->local_qlen)
+ {
+ int tmp = audio_devs[dev]->local_qlen (dev);
+
+ if (tmp & info->fragments)
+ tmp--; /*
+ * This buffer has been counted twice
+ */
+ info->fragments -= tmp;
+ }
+ }
+ }
+
+ if (info->fragments < 0)
+ info->fragments = 0;
+ else if (info->fragments > dmap->nbufs)
+ info->fragments = dmap->nbufs;
+
+ info->fragsize = dmap->fragment_size;
+ info->bytes = info->fragments * dmap->fragment_size;
+
+ if (cmd == SNDCTL_DSP_GETISPACE && dmap->qlen)
+ info->bytes -= dmap->counts[dmap->qhead];
+ }
return 0;
default:
@@ -511,7+543,7 @@ space_in_queue (int dev) int len, max, tmp;
struct dma_buffparms *dmap = audio_devs[dev]->dmap;
- if (dmap->qlen == dmap->nbufs) /* No space at all */
+ if (dmap->qlen >= dmap->nbufs) /* No space at all */
return 0;
/*
@@ -929,6+961,7 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait switch (sel_type)
{
case SEL_IN:
+
if (dmap->dma_mode != DMODE_INPUT)
return 0;
@@ -945,10+978,14 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait
case SEL_OUT:
if (dmap->dma_mode == DMODE_INPUT)
- return 0;
+ {
+ return 0;
+ }
if (dmap->dma_mode == DMODE_NONE)
- return 1;
+ {
+ return 1;
+ }
if (!space_in_queue (dev))
{
+#define MAD16_OPL4 /* Disable this if you have problems with OPL3 */
/*
* sound/mad16.c
*
* 0x01 - joystick disabled
*
* CD-ROM type selection (select just one):
+ * 0x00 - none
* 0x02 - Sony 31A
* 0x04 - Mitsumi
- * 0x06 - Panasonic
- * 0x08 - Secondary IDE
- * 0x0a - Primary IDE
+ * 0x06 - Panasonic (type "LaserMate", not "SoundBlaster")
+ * 0x08 - Secondary IDE (address 0x170)
+ * 0x0a - Primary IDE (address 0x1F0)
*
* For example Mitsumi with joystick disabled = 0x04|0x01 = 0x05
+ * For example LaserMate (for use with sbpcd) plus joystick = 0x06
*
+ * MAD16_CDSEL:
* This defaults to CD I/O 0x340, no IRQ and DMA3
* (DMA5 with Mitsumi or IDE). If you like to change these, define
* MAD16_CDSEL with the following bits:
* or
* CD-ROM DMA (Mitsumi or IDE): 0x00=DMA5, 0x01=DMA6, 0x02=DMA7 or 0x03=disabled
*
+ * For use with sbpcd, address 0x340, set MAD16_CDSEL to 0x03 or 0x23.
+ *
* Copyright by Hannu Savolainen 1995
*
* Redistribution and use in source and binary forms, with or without
@@ -84,8+90,8 @@ static int already_initialized = 0; * only until the next I/O read or write.
*/
-#define MC1_PORT 0xf8d
-#define MC2_PORT 0xf8e
+#define MC1_PORT 0xf8d /* SB address, CDROM interface type, joystick */
+#define MC2_PORT 0xf8e /* CDROM address, IRQ, DMA, plus OPL4 bit */
#define MC3_PORT 0xf8f
#define PASSWD_REG 0xf8f
#define MC4_PORT 0xf90
@@ -236,9+242,9 @@ probe_mad16 (struct address_info *hw_config) }
else
{
- unsigned char model;
+ unsigned char model;
- if (((model=mad_read (MC3_PORT)) & 0x03) == 0x03)
+ if (((model = mad_read (MC3_PORT)) & 0x03) == 0x03)
{
printk ("mad16.c: Mozart detected???\n");
board_type = MOZART;
@@ -277,6+283,8 @@ probe_mad16 (struct address_info *hw_config) /*
* Set optional CD-ROM and joystick settings.
*/
+#define MAD16_CONF 0x06
+#define MAD16_CDSEL 0x03
#ifdef MAD16_CONF
tmp |= ((MAD16_CONF) & 0x0f); /* CD-ROM and joystick bits */
attach_mad16_mpu (long mem_start, struct address_info *hw_config)
{
-#ifdef EXCLUDE_MIDI
- return mem_start;
-#else
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
if (!already_initialized)
return mem_start;
return attach_mpu401 (mem_start, hw_config);
+#else
+ return mem_start;
#endif
}
int
probe_mad16_mpu (struct address_info *hw_config)
{
-#ifdef EXCLUDE_MIDI
- return 0;
-#else
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
static int mpu_attached = 0;
static int valid_ports[] =
{0x330, 0x320, 0x310, 0x300};
@@ -365,7+371,7 @@ probe_mad16_mpu (struct address_info *hw_config) return 0;
}
- tmp = 0x80; /* MPU-401 enable */
+ tmp = 0x83; /* MPU-401 enable */
/*
* Set the MPU base bits
@@ -403,12+409,12 @@ probe_mad16_mpu (struct address_info *hw_config) tmp |= i << 3;
break;
}
-
- tmp |= 0x03; /* ???????? */
- mad_write (MC6_PORT, tmp); /* Write MPU401 config */
}
+ mad_write (MC6_PORT, tmp); /* Write MPU401 config */
return probe_mpu401 (hw_config);
+#else
+ return 0;
#endif
}
@@ -96,7+96,7 @@ struct mpu_config
#define OUTPUT_READY 0x40
#define INPUT_AVAIL 0x80
-#define MPU_ACK 0xF7
+#define MPU_ACK 0xFE
#define MPU_RESET 0xFF
#define UART_MODE_ON 0x3F
ok = 0;
for (timeout = 50000; timeout > 0 && !ok; timeout--)
if (input_avail (devc->base))
- {
- if (mpu_input_scanner (devc, read_data (devc->base)) == MPU_ACK)
- ok = 1;
- }
+ if (devc->opened && devc->mode == MODE_SYNTH)
+ {
+ if (mpu_input_scanner (devc, read_data (devc->base)) == MPU_ACK)
+ ok = 1;
+ }
+ else
+ { /* Device is not currently open. Use simplier method */
+ if (read_data (devc->base) == MPU_ACK)
+ ok = 1;
+ }
if (!ok)
{
@@ -680,7+686,7 @@ retry: if (!ok)
{
RESTORE_INTR (flags);
- /* printk ("MPU: No response(%d) to command (0x%x)\n", i, (int) cmd->cmd); */
+ /* printk ("MPU: No response(%d) to command (0x%x)\n", i, (int) cmd->cmd); */
return RET_ERROR (EIO);
}
}
@@ -1219,6+1225,7 @@ probe_mpu401 (struct address_info *hw_config) tmp_devc.base = hw_config->io_base;
tmp_devc.irq = hw_config->irq;
tmp_devc.initialized = 0;
+ tmp_devc.opened = 0;
#if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_MPU401)
/*
@@ -1094,7+1094,7 @@ opl3_bender (int dev, int voice, int value) if (voice < 0 || voice >= nr_voices)
return;
- bend_pitch (dev, voice, value);
+ bend_pitch (dev, voice, value - 8192);
}
static int
#include <linux/malloc.h>
#include <linux/string.h>
-#include "linux/soundcard.h"
+#include <linux/soundcard.h>
typedef char snd_rw_buf;
@@ -155,7+155,7 @@ struct snd_wait { */
#define ACTIVATE_TIMER(name, proc, time) \
- {name.expires = jiffies+(time); \
+ {name.expires = time; \
add_timer (&name);}
#define INB inb
@@ -57,7+57,7 @@ static char *pas_model_names[] = /*
* to support other than the default base address
*/
-extern void mix_write (unsigned char data, int ioaddr);
+extern void mix_write (unsigned char data, int ioaddr);
unsigned char
pas_read (int ioaddr)
@@ -99,10+99,8 @@ pasintr (INT_HANDLER_PARMS (irq, dummy)) if (status & I_S_MIDI_IRQ)
{
#ifndef EXCLUDE_MIDI
-#ifdef EXCLUDE_PRO_MIDI
pas_midi_interrupt ();
#endif
-#endif
status &= ~I_S_MIDI_IRQ;
}
@@ -253,7+251,7 @@ config_pas_hw (struct address_info *hw_config) * 17.897 kHz
*/
#if 1
- pas_write (8, PRESCALE_DIVIDER);
+ pas_write (8, PRESCALE_DIVIDER);
#else
if (pas_model == PAS_16 || pas_model == PAS_16D)
pas_write (8, PRESCALE_DIVIDER);
@@ -264,7+262,7 @@ config_pas_hw (struct address_info *hw_config) mix_write (P_M_MV508_ADDRESS | 5, PARALLEL_MIXER);
mix_write (5, PARALLEL_MIXER);
-#if !defined(EXCLUDE_SB_EMULATION) || !defined(EXCLUDE_SB)
+#if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB)
{
struct address_info *sb_config;
@@ -396,10+394,8 @@ attach_pas_card (long mem_start, struct address_info *hw_config) #endif
#ifndef EXCLUDE_MIDI
-#ifdef EXCLUDE_PRO_MIDI
mem_start = pas_midi_init (mem_start);
#endif
-#endif
pas_init_mixer ();
}
@@ -395,10+395,10 @@ probe_pss_mpu (struct address_info *hw_config) break; /* No more input */
}
-#ifdef EXCLUDE_MIDI
- return 0;
-#else
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
return probe_mpu401 (hw_config);
+#else
+ return 0
#endif
}
@@ -662,7+662,7 @@ attach_pss_mpu (long mem_start, struct address_info *hw_config) int prev_devs;
long ret;
-#ifndef EXCLUDE_MIDI
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
prev_devs = num_midis;
ret = attach_mpu401 (mem_start, hw_config);
@@ -436,7+436,7 @@ sb16_dsp_halt (int dev) sb_dsp_command01 (0xda);
sb_dsp_command01 (0xd0);
}
- DMAbuf_reset_dma (dev);
+ /* DMAbuf_reset_dma (dev); */
}
static void
@@ -1139,6+1139,13 @@ sb_dsp_init (long mem_start, struct address_info *hw_config) }
}
+ if (sbc_major == 0)
+ {
+ printk ("\n\nFailed to get SB version (%x) - possible I/O conflict\n\n",
+ INB (DSP_DATA_AVAIL));
+ sbc_major = 1;
+ }
+
if (sbc_major == 2 || sbc_major == 3)
sb_duplex_midi = 1;
@@ -1818,7+1818,7 @@ note_to_freq (int note_num) 369998, 391998, 415306, 440000, 466162, 493880
};
-#define BASE_OCTAVE 4
+#define BASE_OCTAVE 5
octave = note_num / 12;
note = note_num % 12;
#include "soundvers.h"
#if !defined(PSS_MPU_BASE) && defined(EXCLUDE_SSCAPE) && \
- defined(EXCLUDE_TRIX) && !defined(MAD16_MPU_BASE)
+ defined(EXCLUDE_TRIX) && !defined(MAD16_MPU_BASE)
#define EXCLUDE_MPU_EMU
#endif
@@ -58,8+58,8 @@ put_status (char *s) {
int l;
- for (l = 0; l < 256 && s[l]; l++); /*
- * l=strnlen(s,256);
+ for (l = 0; l < 256, s[l]; l++); /*
+ * l=strlen(s);
*/
if (status_len + l >= 4000)
@@ -115,10+115,17 @@ init_status (void)
status_ptr = 0;
+#ifdef SOUND_UNAME_A
+ put_status ("VoxWare Sound Driver:" SOUND_VERSION_STRING
+ " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY ",\n"
+ SOUND_UNAME_A ")"
+ "\n");
+#else
put_status ("VoxWare Sound Driver:" SOUND_VERSION_STRING
" (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")"
"\n");
+#endif
if (!put_status ("Config options: "))
return;
-#define SOUND_VERSION_STRING "3.0-950728"
+#define SOUND_VERSION_STRING "3.0.1-950812"
@@ -88,11+88,11 @@ trix_set_wss_port (struct address_info *hw_config) if (kilroy_was_here) /* Already initialized */
return 0;
- kilroy_was_here = 1;
-
if (trix_read (0x15) != 0x71) /* No asic signature */
return 0;
+ kilroy_was_here = 1;
+
/*
* Disable separate wave playback and recording DMA channels since
* the driver doesn't support duplex mode yet.
@@ -276,12+276,17 @@ attach_trix_sb (long mem_start, struct address_info *hw_config) long
attach_trix_mpu (long mem_start, struct address_info *hw_config)
{
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
return attach_mpu401 (mem_start, hw_config);
+#else
+ return mem_start;
+#endif
}
int
probe_trix_mpu (struct address_info *hw_config)
{
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
unsigned char conf;
static char irq_bits[] =
{-1, -1, -1, 1, 2, 3, -1, 4, -1, 5};
@@ -326,6+331,9 @@ probe_trix_mpu (struct address_info *hw_config) mpu_initialized = 1;
return probe_mpu401 (hw_config);
+#else
+ return 0;
+#endif
}
#endif
Changes from version 0.5a to version 0.5b
=========================================
+ - Some cleanups in the code.
- More consistency checks on directories.
- The ext2.diff patch from Tom May <ftom@netcom.com> has been
integrated. This patch replaces expensive "/" and "%" with
@@ -128,48+128,6 @@ static struct super_operations ext2_sops = { ext2_remount
};
-#ifdef EXT2FS_PRE_02B_COMPAT
-
-static int convert_pre_02b_fs (struct super_block * sb,
- struct buffer_head * bh)
-{
- struct ext2_super_block * es;
- struct ext2_old_group_desc old_group_desc [BLOCK_SIZE / sizeof (struct ext2_old_group_desc)];
- struct ext2_group_desc * gdp;
- struct buffer_head * bh2;
- int groups_count;
- int i;
-
- es = (struct ext2_super_block *) bh->b_data;
- bh2 = bread (sb->s_dev, 2, BLOCK_SIZE);
- if (!bh2) {
- printk ("Cannot read descriptor blocks while converting !\n");
- return 0;
- }
- memcpy (old_group_desc, bh2->b_data, BLOCK_SIZE);
- groups_count = (sb->u.ext2_sb.s_blocks_count -
- sb->u.ext2_sb.s_first_data_block +
- (EXT2_BLOCK_SIZE(sb) * 8) - 1) /
- (EXT2_BLOCK_SIZE(sb) * 8);
- memset (bh2->b_data, 0, BLOCK_SIZE);
- gdp = (struct ext2_group_desc *) bh2->b_data;
- for (i = 0; i < groups_count; i++) {
- gdp[i].bg_block_bitmap = old_group_desc[i].bg_block_bitmap;
- gdp[i].bg_inode_bitmap = old_group_desc[i].bg_inode_bitmap;
- gdp[i].bg_inode_table = old_group_desc[i].bg_inode_table;
- gdp[i].bg_free_blocks_count = old_group_desc[i].bg_free_blocks_count;
- gdp[i].bg_free_inodes_count = old_group_desc[i].bg_free_inodes_count;
- }
- mark_buffer_dirty(bh2, 1);
- brelse (bh2);
- es->s_magic = EXT2_SUPER_MAGIC;
- mark_buffer_dirty(bh, 1);
- sb->s_magic = EXT2_SUPER_MAGIC;
- return 1;
-}
-
-#endif
-
/*
* This function has been shamelessly adapted from the msdos fs
*/
@@ -403,9+361,6 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, int dev = sb->s_dev;
int db_count;
int i, j;
-#ifdef EXT2FS_PRE_02B_COMPAT
- int fs_converted = 0;
-#endif
set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
@@ -429,11+384,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, es = (struct ext2_super_block *) bh->b_data;
sb->u.ext2_sb.s_es = es;
sb->s_magic = es->s_magic;
- if (sb->s_magic != EXT2_SUPER_MAGIC
-#ifdef EXT2FS_PRE_02B_COMPAT
- && sb->s_magic != EXT2_PRE_02B_MAGIC
-#endif
- ) {
+ if (sb->s_magic != EXT2_SUPER_MAGIC) {
sb->s_dev = 0;
unlock_super (sb);
brelse (bh);
@@ -500,39+451,6 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, log2 (EXT2_INODES_PER_BLOCK(sb));
sb->u.ext2_sb.s_desc_per_block_bits =
log2 (EXT2_DESC_PER_BLOCK(sb));
-#ifdef EXT2FS_PRE_02B_COMPAT
- if (sb->s_magic == EXT2_PRE_02B_MAGIC) {
- if (es->s_blocks_count > 262144) {
- /*
- * fs > 256 MB can't be converted
- */
- sb->s_dev = 0;
- unlock_super (sb);
- brelse (bh);
- printk ("EXT2-fs: trying to mount a pre-0.2b file"
- "system which cannot be converted\n");
- return NULL;
- }
- printk ("EXT2-fs: mounting a pre 0.2b file system, "
- "will try to convert the structure\n");
- if (!(sb->s_flags & MS_RDONLY)) {
- sb->s_dev = 0;
- unlock_super (sb);
- brelse (bh);
- printk ("EXT2-fs: cannot convert a read-only fs\n");
- return NULL;
- }
- if (!convert_pre_02b_fs (sb, bh)) {
- sb->s_dev = 0;
- unlock_super (sb);
- brelse (bh);
- printk ("EXT2-fs: conversion failed !!!\n");
- return NULL;
- }
- printk ("EXT2-fs: conversion succeeded !!!\n");
- fs_converted = 1;
- }
-#endif
if (sb->s_magic != EXT2_SUPER_MAGIC) {
sb->s_dev = 0;
unlock_super (sb);
@@ -652,13+570,6 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, printk ("EXT2-fs: get root inode failed\n");
return NULL;
}
-#ifdef EXT2FS_PRE_02B_COMPAT
- if (fs_converted) {
- for (i = 0; i < db_count; i++)
- mark_buffer_dirty(sb->u.ext2_sb.s_group_desc[i], 1);
- sb->s_dirt = 1;
- }
-#endif
ext2_setup_super (sb, es);
return sb;
}
@@ -51,18+51,18 @@ struct inode_operations proc_base_inode_operations = { };
static struct proc_dir_entry base_dir[] = {
- { PROC_PID_INO, NULL, 1, "." },
- { PROC_ROOT_INO, NULL, 2, ".." },
- { PROC_PID_MEM, NULL, 3, "mem" },
- { PROC_PID_CWD, NULL, 3, "cwd" },
- { PROC_PID_ROOT, NULL, 4, "root" },
- { PROC_PID_EXE, NULL, 3, "exe" },
- { PROC_PID_FD, NULL, 2, "fd" },
- { PROC_PID_ENVIRON, NULL, 7, "environ" },
- { PROC_PID_CMDLINE, NULL, 7, "cmdline" },
- { PROC_PID_STAT, NULL, 4, "stat" },
- { PROC_PID_STATM, NULL, 5, "statm" },
- { PROC_PID_MAPS, NULL, 4, "maps" }
+ { PROC_PID_INO, 1, "." },
+ { PROC_ROOT_INO, 2, ".." },
+ { PROC_PID_MEM, 3, "mem" },
+ { PROC_PID_CWD, 3, "cwd" },
+ { PROC_PID_ROOT, 4, "root" },
+ { PROC_PID_EXE, 3, "exe" },
+ { PROC_PID_FD, 2, "fd" },
+ { PROC_PID_ENVIRON, 7, "environ" },
+ { PROC_PID_CMDLINE, 7, "cmdline" },
+ { PROC_PID_STAT, 4, "stat" },
+ { PROC_PID_STATM, 5, "statm" },
+ { PROC_PID_MAPS, 4, "maps" }
};
#define NR_BASE_DIRENTRY ((sizeof (base_dir))/(sizeof (base_dir[0])))
@@ -82,6+82,7 @@ int proc_match(int len,const char * name,struct proc_dir_entry * de) static int proc_lookupbase(struct inode * dir,const char * name, int len,
struct inode ** result)
{
+ struct proc_dir_entry * de = NULL;
unsigned int pid, ino;
int i;
@@ -94,17+95,20 @@ static int proc_lookupbase(struct inode * dir,const char * name, int len, }
ino = dir->i_ino;
pid = ino >> 16;
- i = NR_BASE_DIRENTRY;
- while (i-- > 0 && !proc_match(len,name,base_dir+i))
- /* nothing */;
- if (i < 0) {
+ for (i = 0; i < NR_BASE_DIRENTRY; i++) {
+ if (!proc_match(len, name, base_dir+i))
+ continue;
+ de = base_dir+i;
+ break;
+ }
+ if (!de) {
iput(dir);
return -ENOENT;
}
- if (base_dir[i].low_ino == 1)
+ if (de->low_ino == 1)
ino = 1;
else
- ino = (pid << 16) + base_dir[i].low_ino;
+ ino = (pid << 16) + de->low_ino;
for (i = 0 ; i < NR_TASKS ; i++)
if (task[i] && task[i]->pid == pid)
break;
@@ -117,6+121,7 @@ static int proc_lookupbase(struct inode * dir,const char * name, int len, return -ENOENT;
}
iput(dir);
+ (*result)->u.generic_ip = de;
return 0;
}
@@ -205,7+205,7 @@ void proc_read_inode(struct inode * inode) case PROC_NET:
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
inode->i_nlink = 2;
- inode->i_op = &proc_net_inode_operations;
+ inode->i_op = &proc_netdir_inode_operations;
break;
case PROC_SCSI:
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
#include <linux/config.h>
#include <linux/mm.h>
-/* forward references */
-static int proc_readnet(struct inode * inode, struct file * file,
- char * buf, int count);
-static int proc_readnetdir(struct inode *, struct file *,
- void *, filldir_t filldir);
-static int proc_lookupnet(struct inode *,const char *,int,struct inode **);
-
-static struct file_operations proc_net_operations = {
- NULL, /* lseek - default */
- proc_readnet, /* read - bad */
- NULL, /* write - bad */
- proc_readnetdir, /* readdir */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* no special release code */
- NULL /* can't fsync */
-};
-
-/*
- * proc directories can do almost nothing..
- */
-struct inode_operations proc_net_inode_operations = {
- &proc_net_operations, /* default net directory file-ops */
- NULL, /* create */
- proc_lookupnet, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
-
-#define NR_MAX_PROC_NET_DIR 100
-static struct proc_dir_entry *net_dir[NR_MAX_PROC_NET_DIR] = {
- NULL,
-};
-
-static int nr_net_direntry = 0;
+static struct proc_dir_entry *net_dir = NULL;
int proc_net_register(struct proc_dir_entry *dp)
{
- int i;
-
- for (i = 0; net_dir[i] != NULL; ++i ) ;
-
- if (i >= NR_MAX_PROC_NET_DIR)
- return -ENOMEM;
-
- net_dir[i] = dp;
- net_dir[i+1] = NULL; /* Just make sure.. */
- ++nr_net_direntry;
- return i;
+ dp->next = net_dir;
+ net_dir = dp;
+ return 0;
}
int proc_net_unregister(int ino)
{
- int i;
- for (i = 0; net_dir[i] != NULL && i < nr_net_direntry; ++i)
- if (net_dir[i]->low_ino == ino) {
- for ( ; net_dir[i] != NULL; ++i )
- net_dir[i] = net_dir[i+1];
- --nr_net_direntry;
- return 0;
- }
- return -ENOENT;
-}
+ struct proc_dir_entry **p = &net_dir, *dp;
+
+ while ((dp = *p) != NULL) {
+ if (dp->low_ino == ino) {
+ *p = dp->next;
+ dp->next = NULL;
+ return 0;
+ }
+ p = &dp->next;
+ }
+ return -EINVAL;
+}
static int dir_get_info(char * a, char ** b, off_t d, int e, int f)
{
@@ -120,8+68,8 @@ static int dir_get_info(char * a, char ** b, off_t d, int e, int f) void proc_net_init(void)
{
static struct proc_dir_entry
- nd_thisdir = { PROC_NET, dir_get_info, 1, "." },
- nd_rootdir = { PROC_ROOT_INO, dir_get_info, 1, ".." };
+ nd_thisdir = { PROC_NET, 1, ".", dir_get_info },
+ nd_rootdir = { PROC_ROOT_INO, 2, "..", dir_get_info };
static int already = 0;
if (already) return;
@@ -135,7+83,7 @@ void proc_net_init(void) static int proc_lookupnet(struct inode * dir,const char * name, int len,
struct inode ** result)
{
- struct proc_dir_entry **de;
+ struct proc_dir_entry *de;
*result = NULL;
if (!dir)
@@ -144,13+92,18 @@ static int proc_lookupnet(struct inode * dir,const char * name, int len, iput(dir);
return -ENOENT;
}
- for (de = net_dir ; (*de)->name ; de++) {
- if (!proc_match(len, name, *de))
+ for (de = net_dir ; de ; de = de->next) {
+ struct inode * inode;
+ if (!proc_match(len, name, de))
continue;
- *result = iget(dir->i_sb, (*de)->low_ino);
+ inode = iget(dir->i_sb, de->low_ino);
iput(dir);
- if (!*result)
+ if (!inode)
return -ENOENT;
+ inode->u.generic_ip = de;
+ if (de->fill_inode)
+ de->fill_inode(inode);
+ *result = inode;
return 0;
}
iput(dir);
@@ -162,16+115,29 @@ static int proc_readnetdir(struct inode * inode, struct file * filp, {
struct proc_dir_entry * de;
unsigned int ino;
+ int i;
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
ino = inode->i_ino;
- while (((unsigned) filp->f_pos) < nr_net_direntry) {
- de = net_dir[filp->f_pos];
- if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino) < 0)
+ de = net_dir;
+ i = filp->f_pos;
+ for (;;) {
+ if (!de)
+ return 0;
+ if (!i)
break;
- filp->f_pos++;
+ de = de->next;
+ i--;
}
+
+ do {
+ if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino) < 0)
+ return 0;
+ filp->f_pos++;
+ de = de->next;
+ } while (de);
+
return 0;
}
@@ -182,22+148,14 @@ static int proc_readnet(struct inode * inode, struct file * file, char * buf, int count)
{
char * page;
- unsigned int ino;
int bytes=count;
- int i;
int copied=0;
char *start;
struct proc_dir_entry * dp;
if (count < 0)
return -EINVAL;
- ino = inode->i_ino;
- for (i = 0; ;i++) {
- if (i >= NR_MAX_PROC_NET_DIR || (dp = net_dir[i]) == NULL)
- return -EBADF;
- if (dp->low_ino == ino)
- break;
- }
+ dp = (struct proc_dir_entry *) inode->u.generic_ip;
if (!(page = (char*) __get_free_page(GFP_KERNEL)))
return -ENOMEM;
@@ -233,3+191,71 @@ static int proc_readnet(struct inode * inode, struct file * file, free_page((unsigned long) page);
return copied;
}
+
+static struct file_operations proc_net_operations = {
+ NULL, /* lseek - default */
+ proc_readnet, /* read - bad */
+ NULL, /* write - bad */
+ NULL, /* readdir */
+ NULL, /* select - default */
+ NULL, /* ioctl - default */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
+};
+
+/*
+ * proc directories can do almost nothing..
+ */
+struct inode_operations proc_net_inode_operations = {
+ &proc_net_operations, /* default net file-ops */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL /* permission */
+};
+
+static struct file_operations proc_netdir_operations = {
+ NULL, /* lseek - default */
+ NULL, /* read - bad */
+ NULL, /* write - bad */
+ proc_readnetdir, /* readdir */
+ NULL, /* select - default */
+ NULL, /* ioctl - default */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
+};
+
+/*
+ * proc directories can do almost nothing..
+ */
+struct inode_operations proc_netdir_inode_operations = {
+ &proc_netdir_operations, /* default net directory file-ops */
+ NULL, /* create */
+ proc_lookupnet, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL /* permission */
+};
@@ -52,34+52,34 @@ struct inode_operations proc_root_inode_operations = { };
static struct proc_dir_entry root_dir[] = {
- { PROC_ROOT_INO, NULL, 1, "." },
- { PROC_ROOT_INO, NULL, 2, ".." },
- { PROC_LOADAVG, NULL, 7, "loadavg" },
- { PROC_UPTIME, NULL, 6, "uptime" },
- { PROC_MEMINFO, NULL, 7, "meminfo" },
- { PROC_KMSG, NULL, 4, "kmsg" },
- { PROC_VERSION, NULL, 7, "version" },
+ { PROC_ROOT_INO, 1, "." },
+ { PROC_ROOT_INO, 2, ".." },
+ { PROC_LOADAVG, 7, "loadavg" },
+ { PROC_UPTIME, 6, "uptime" },
+ { PROC_MEMINFO, 7, "meminfo" },
+ { PROC_KMSG, 4, "kmsg" },
+ { PROC_VERSION, 7, "version" },
#ifdef CONFIG_PCI
- { PROC_PCI, NULL, 3, "pci" },
+ { PROC_PCI, 3, "pci" },
#endif
- { PROC_CPUINFO, NULL, 7, "cpuinfo" },
- { PROC_SELF, NULL, 4, "self" }, /* will change inode # */
- { PROC_NET, NULL, 3, "net" },
- { PROC_SCSI, NULL, 4, "scsi" },
+ { PROC_CPUINFO, 7, "cpuinfo" },
+ { PROC_SELF, 4, "self" }, /* will change inode # */
+ { PROC_NET, 3, "net" },
+ { PROC_SCSI, 4, "scsi" },
#ifdef CONFIG_DEBUG_MALLOC
- { PROC_MALLOC, NULL, 6, "malloc" },
+ { PROC_MALLOC, 6, "malloc" },
#endif
- { PROC_KCORE, NULL, 5, "kcore" },
- { PROC_MODULES, NULL, 7, "modules" },
- { PROC_STAT, NULL, 4, "stat" },
- { PROC_DEVICES, NULL, 7, "devices" },
- { PROC_INTERRUPTS, NULL, 10,"interrupts" },
- { PROC_FILESYSTEMS, NULL, 11,"filesystems" },
- { PROC_KSYMS, NULL, 5, "ksyms" },
- { PROC_DMA, NULL, 3, "dma" },
- { PROC_IOPORTS, NULL, 7, "ioports"},
+ { PROC_KCORE, 5, "kcore" },
+ { PROC_MODULES, 7, "modules" },
+ { PROC_STAT, 4, "stat" },
+ { PROC_DEVICES, 7, "devices" },
+ { PROC_INTERRUPTS, 10,"interrupts" },
+ { PROC_FILESYSTEMS, 11,"filesystems" },
+ { PROC_KSYMS, 5, "ksyms" },
+ { PROC_DMA, 3, "dma" },
+ { PROC_IOPORTS, 7, "ioports" },
#ifdef CONFIG_PROFILE
- { PROC_PROFILE, NULL, 7, "profile"},
+ { PROC_PROFILE, 7, "profile" },
#endif
};
@@ -88,6+88,7 @@ static struct proc_dir_entry root_dir[] = { static int proc_lookuproot(struct inode * dir,const char * name, int len,
struct inode ** result)
{
+ struct proc_dir_entry * de = NULL;
unsigned int pid, c;
int i, ino;
@@ -98,11+99,14 @@ static int proc_lookuproot(struct inode * dir,const char * name, int len, iput(dir);
return -ENOENT;
}
- i = NR_ROOT_DIRENTRY;
- while (i-- > 0 && !proc_match(len,name,root_dir+i))
- /* nothing */;
- if (i >= 0) {
- ino = root_dir[i].low_ino;
+ for (i = 0; i < NR_ROOT_DIRENTRY; i++) {
+ if (!proc_match(len,name,root_dir+i))
+ continue;
+ de = root_dir + i;
+ break;
+ }
+ if (de) {
+ ino = de->low_ino;
if (ino == PROC_ROOT_INO) {
*result = dir;
return 0;
@@ -139,6+143,7 @@ static int proc_lookuproot(struct inode * dir,const char * name, int len, return -ENOENT;
}
iput(dir);
+ (*result)->u.generic_ip = de;
return 0;
}
@@ -84,10+84,10 @@ struct proc_dir_entry scsi_dir[PROC_SCSI_FILE - PROC_SCSI_SCSI + 3]; struct proc_dir_entry scsi_hba_dir[(PROC_SCSI_LAST - PROC_SCSI_FILE) * 4];
static struct proc_dir_entry scsi_dir2[] = {
- { PROC_SCSI, NULL, 1, "." },
- { PROC_ROOT_INO, NULL, 2, ".." },
- { PROC_SCSI_NOT_PRESENT, NULL, 11, "not.present" },
- { 0, NULL, 0, NULL }
+ { PROC_SCSI, 1, "." },
+ { PROC_ROOT_INO, 2, ".." },
+ { PROC_SCSI_NOT_PRESENT, 11, "not.present" },
+ { 0, 0, NULL }
};
inline static uint count_dir_entries(uint inode, uint *num)
-/* $Id: aztcd.h,v 1.50 1995/07/29 20:31:32 root Exp $
+/* $Id: aztcd.h,v 1.60 1995/08/09 12:38:12 root Exp root $
*
* Definitions for a AztechCD268 CD-ROM interface
* Copyright (C) 1994, 1995 Werner Zimmermann
*/
#ifdef AZT_SW32
-#define AZT_SW32_BASE_ADDR 0x220 /*I/O port base adress of your soundcard*/
+#define AZT_SW32_BASE_ADDR 0x220 /*I/O port base address of your soundcard*/
#endif
/* Set this to 1, if you want your tray to be locked, set to 0 to prevent tray
/*
* some fix numbers
*/
-#define CD_MINS 74 /* max. minutes per CD */
-#define CD_SECS 60 /* seconds per minute */
-#define CD_FRAMES 75 /* frames per second */
-#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */
-#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */
-#define CD_FRAMESIZE 2048 /* bytes per frame, cooked mode */
-#define CD_FRAMESIZE_RAW0 2336 /* bytes per frame, "raw" mode */
-#define CD_FRAMESIZE_XA 2340 /* bytes per frame, "xa" mode */
-#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */
-#define CD_FRAMESIZE_SUB 96 /* subchannel data size */
-#define CD_BLOCK_OFFSET 150 /* offset of first logical frame */
-#define CD_XA_HEAD 12 /* header size of XA frame */
-#define CD_XA_TAIL 280 /* tail size of XA frame */
-
+#define CD_MINS 74 /* max. minutes per CD */
+#define CD_SECS 60 /* seconds per minute */
+#define CD_FRAMES 75 /* frames per second */
+#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */
+#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */
+#define CD_FRAMESIZE 2048 /* bytes per frame, cooked mode */
+#define CD_FRAMESIZE_RAW0 2336 /* bytes per frame, "raw" mode */
+#define CD_FRAMESIZE_XA 2340 /* bytes per frame, "xa" mode */
+#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */
+#define CD_FRAMESIZE_SUB 96 /* subchannel data size */
+#define CD_BLOCK_OFFSET 150 /* offset of first logical frame */
+#define CD_XA_HEAD 12 /* header size of XA frame */
+#define CD_XA_TAIL 280 /* tail size of XA frame */
+#define CD_XA_SYNC_HEAD (CD_XA_HEAD+12)/* sync bytes + header of XA frame */
/*
*
* For IOCTL calls, we will commandeer byte 0x53, or 'S'.
@@ -424,8+424,7 @@ struct cdrom_multisession #define CDROMVOLREAD 0x5313 /* let the drive tell its volume setting */
/* (struct cdrom_volctrl) */
-#define CDROMREADMODE0 0x5314 /*read data in audio mode*/
-#define CDROMREADRAW 0x5315 /*read data in raw mode*/
-#define CDROMREADCOOKED 0x5316 /*read data in cooked mode*/
+#define CDROMREADRAW 0x5314 /*read data in raw mode*/
+#define CDROMREADCOOKED 0x5315 /*read data in cooked mode*/
#endif _LINUX_CDROM_H
#undef EXT2FS_DEBUG
/*
- * Define EXT2FS_DEBUG_CACHE to produce cache debug messages
- */
-#undef EXT2FS_DEBUG_CACHE
-
-/*
- * Define EXT2FS_CHECK_CACHE to add some checks to the name cache code
- */
-#undef EXT2FS_CHECK_CACHE
-
-/*
- * Define EXT2FS_PRE_02B_COMPAT to convert ext 2 fs prior to 0.2b
- */
-#undef EXT2FS_PRE_02B_COMPAT
-
-/*
* Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
*/
#define EXT2_PREALLOCATE
/*
* The second extended file system version
*/
-#define EXT2FS_DATE "95/07/02"
+#define EXT2FS_DATE "95/08/09"
#define EXT2FS_VERSION "0.5b"
/*
/*
* The second extended file system magic number
*/
-#define EXT2_PRE_02B_MAGIC 0xEF51
#define EXT2_SUPER_MAGIC 0xEF53
/*
@@ -151,15+135,6 @@ struct ext2_acl_entry /* Access Control List Entry */ /*
* Structure of a blocks group descriptor
*/
-struct ext2_old_group_desc
-{
- __u32 bg_block_bitmap; /* Blocks bitmap block */
- __u32 bg_inode_bitmap; /* Inodes bitmap block */
- __u32 bg_inode_table; /* Inodes table block */
- __u16 bg_free_blocks_count; /* Free blocks count */
- __u16 bg_free_inodes_count; /* Free inodes count */
-};
-
struct ext2_group_desc
{
__u32 bg_block_bitmap; /* Blocks bitmap block */
@@ -362,12+337,25 @@ struct ext2_super_block { __u32 s_reserved[235]; /* Padding to the end of the block */
};
+/*
+ * Codes for operating systems
+ */
#define EXT2_OS_LINUX 0
#define EXT2_OS_HURD 1
#define EXT2_OS_MASIX 2
+#define EXT2_OS_FREEBSD 3
+#define EXT2_OS_LITES 4
+
+/*
+ * Revision levels
+ */
+#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
-#define EXT2_CURRENT_REV 0
+#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
+/*
+ * Default values for user and/or group using reserved blocks
+ */
#define EXT2_DEF_RESUID 0
#define EXT2_DEF_RESGID 0
@@ -163,6+163,7 @@ extern void ip_acct_cnt(struct iphdr *, struct device *, struct ip_fw *); extern int ip_acct_ctl(int, void *, int);
#endif
extern int ip_fw_chk(struct iphdr *, struct device *rif,struct ip_fw *, int, int);
+extern void ip_fw_init(void);
#endif /* KERNEL */
#ifdef CONFIG_IP_MASQUERADE
FALSE to ignore error. Default is ignore. */
#define LPGETSTATUS 0x060b /* return LP_S(minor) */
#define LPRESET 0x060c /* reset printer */
+#define LPGETSTATS 0x060d /* get statistics (struct lp_stats) */
/* timeout for printk'ing a timeout, in jiffies (100ths of a second).
This is also used for re-checking error conditions if LP_ABORT is
#define LP_WAIT(minor) lp_table[(minor)].wait /* strobe wait */
#define LP_IRQ(minor) lp_table[(minor)].irq /* interrupt # */
/* 0 means polled */
+#define LP_STAT(minor) lp_table[(minor)].stats /* statistics area */
#define LP_BUFFER_SIZE 256
+struct lp_stats {
+ unsigned long chars;
+ unsigned long sleeps;
+ unsigned int maxrun;
+ unsigned int maxwait;
+ unsigned int meanwait;
+ unsigned int mdev;
+};
+
struct lp_struct {
int base;
unsigned int irq;
@@ -97,6+108,10 @@ struct lp_struct { unsigned int wait;
struct wait_queue *lp_wait_q;
char *lp_buffer;
+ unsigned int lastcall;
+ unsigned int runchars;
+ unsigned int waittime;
+ struct lp_stats stats;
};
/*
@@ -123,11+138,11 @@ struct lp_struct { * base + 2
* accessed with LP_C(minor)
*/
-#define LP_PINTEN 0x10
+#define LP_PINTEN 0x10 /* high to read data in or-ed with data out */
#define LP_PSELECP 0x08 /* inverted output, active low */
#define LP_PINITP 0x04 /* unchanged output, active low */
#define LP_PAUTOLF 0x02 /* inverted output, active low */
-#define LP_PSTROBE 0x01 /* inverted output, active low */
+#define LP_PSTROBE 0x01 /* short high output on raising edge */
/*
* the value written to ports to test existence. PC-style ports will
@@ -137,10+152,10 @@ struct lp_struct { #define LP_DUMMY 0x00
/*
- * This is the port delay time. Your mileage may vary.
- * It is used only in the lp_init() routine.
+ * This is the port delay time, in microseconds.
+ * It is used only in the lp_init() and lp_reset() routine.
*/
-#define LP_DELAY 150000
+#define LP_DELAY 50
/*
* function prototypes
@@ -116,11+116,28 @@ enum scsi_directory_inos {
#define PROC_SUPER_MAGIC 0x9fa0
+/*
+ * This is not completely implemented yet. The idea is to
+ * create a in-memory tree (like the actual /proc filesystem
+ * tree) of these proc_dir_entries, so that we can dynamically
+ * add new files to /proc.
+ *
+ * The "next" pointer creates a linked list of one /proc directory,
+ * while parent/subdir create the directory structure (every
+ * /proc file has a parent, but "subdir" is NULL for all
+ * non-directory entries).
+ *
+ * "get_info" is called at "read", while "fill_inode" is used to
+ * fill in file type/protection/owner information specific to the
+ * particular /proc file.
+ */
struct proc_dir_entry {
unsigned short low_ino;
- int (*get_info)(char *, char **, off_t, int, int);
unsigned short namelen;
- const char * name;
+ const char *name;
+ int (*get_info)(char *, char **, off_t, int, int);
+ void (*fill_inode)(struct inode *);
+ struct proc_dir_entry *next, *parent, *subdir;
};
extern struct super_block *proc_read_super(struct super_block *,void *,int);
@@ -136,6+153,7 @@ extern int proc_net_unregister(int); extern struct inode_operations proc_root_inode_operations;
extern struct inode_operations proc_base_inode_operations;
extern struct inode_operations proc_net_inode_operations;
+extern struct inode_operations proc_netdir_inode_operations;
extern struct inode_operations proc_scsi_inode_operations;
extern struct inode_operations proc_mem_inode_operations;
extern struct inode_operations proc_array_inode_operations;
@@ -91,7+91,7 @@ struct nr_neigh { extern struct nr_parms_struct nr_default;
extern int nr_rx_frame(struct sk_buff *, struct device *);
extern void nr_destroy_socket(struct sock *);
-extern int nr_get_info(char *, char **, off_t, int);
+extern int nr_get_info(char *, char **, off_t, int, int);
/* nr_dev.c */
extern int nr_rx_ip(struct sk_buff *, struct device *);
@@ -119,8+119,8 @@ extern struct device *nr_dev_get(ax25_address *); extern int nr_rt_ioctl(unsigned int, void *);
extern void nr_link_failed(ax25_address *, struct device *);
extern int nr_route_frame(struct sk_buff *, ax25_cb *);
-extern int nr_nodes_get_info(char *, char **, off_t, int);
-extern int nr_neigh_get_info(char *, char **, off_t, int);
+extern int nr_nodes_get_info(char *, char **, off_t, int, int);
+extern int nr_neigh_get_info(char *, char **, off_t, int, int);
/* nr_subr.c */
extern void nr_clear_queues(struct sock *);
@@ -33,7+33,7 @@ struct rtable unsigned long rt_mask;
unsigned long rt_gateway;
unsigned short rt_flags;
- unsigned short rt_metric;
+ short rt_metric;
unsigned int rt_refcnt;
unsigned long rt_use;
unsigned short rt_mss;
@@ -45,7+45,7 @@ struct rtable
extern void ip_rt_flush(struct device *dev);
extern void ip_rt_add(short flags, unsigned long addr, unsigned long mask,
- unsigned long gw, struct device *dev, unsigned short mss, unsigned long window, unsigned short irtt, unsigned char metric);
+ unsigned long gw, struct device *dev, unsigned short mss, unsigned long window, unsigned short irtt, short metric);
extern struct rtable *ip_rt_route(unsigned long daddr, struct options *opt, unsigned long *src_addr);
extern struct rtable *ip_rt_local(unsigned long daddr, struct options *opt, unsigned long *src_addr);
extern int rt_get_info(char * buffer, char **start, off_t offset, int length, int dummy);
#include <linux/igmp.h>
-#define SOCK_ARRAY_SIZE 256 /* Think big (also on some systems a byte is faster */
+/* Think big (also on some systems a byte is faster) */
+#define SOCK_ARRAY_SIZE 256
/*
@@ -177,8+178,8 @@ struct sock { #endif
/*
- * This is where all the private (optional) areas that dont overlap will eventually live
- * for now just AF_UNIX is here.
+ * This is where all the private (optional) areas that don't
+ * overlap will eventually live. For now just AF_UNIX is here.
*/
union
@@ -187,57+188,59 @@ struct sock { } protinfo;
/* IP 'private area' or will be eventually */
- int ip_ttl; /* TTL setting */
- int ip_tos; /* TOS */
- struct tcphdr dummy_th;
- struct timer_list keepalive_timer; /* TCP keepalive hack */
- struct timer_list retransmit_timer; /* TCP retransmit timer */
- struct timer_list ack_timer; /* TCP delayed ack timer */
- int ip_xmit_timeout; /* Why the timeout is running */
- struct rtable *ip_route_cache; /* Cached output route */
- unsigned long ip_route_stamp; /* Route cache stamp */
- unsigned long ip_route_daddr; /* Target address */
- unsigned long ip_route_saddr; /* Source address */
- int ip_route_local; /* State of locality flag */
- unsigned long ip_hcache_stamp; /* Header cache stamp */
- unsigned long *ip_hcache_ver; /* Pointer to version of cache */
- char ip_hcache_data[16]; /* Cached header */
- int ip_hcache_state; /* Have we a cached header */
- unsigned char ip_option_len; /* Length of IP options */
- unsigned char ip_option_flen; /* Second fragment option length */
- unsigned char ip_opt_next_strict; /* Next hop is strict route */
- unsigned long ip_opt_next_hop; /* Next hop if forced */
- unsigned char *ip_opt_ptr[2]; /* IP option pointers */
+ int ip_ttl; /* TTL setting */
+ int ip_tos; /* TOS */
+ struct tcphdr dummy_th;
+ struct timer_list keepalive_timer; /* TCP keepalive hack */
+ struct timer_list retransmit_timer; /* TCP retransmit timer */
+ struct timer_list ack_timer; /* TCP delayed ack timer */
+ int ip_xmit_timeout; /* Why the timeout is running */
+ struct rtable *ip_route_cache; /* Cached output route */
+ unsigned long ip_route_stamp; /* Route cache stamp */
+ unsigned long ip_route_daddr; /* Target address */
+ unsigned long ip_route_saddr; /* Source address */
+ int ip_route_local; /* State of locality flag */
+ unsigned long ip_hcache_stamp; /* Header cache stamp */
+ unsigned long *ip_hcache_ver; /* Pointer to version of cache */
+ char ip_hcache_data[16]; /* Cached header */
+ int ip_hcache_state; /* Have we a cached header */
+ unsigned char ip_option_len; /* Length of IP options */
+ unsigned char ip_option_flen; /* Second fragment option length */
+ unsigned char ip_opt_next_strict; /* Next hop is strict route */
+ unsigned long ip_opt_next_hop; /* Next hop if forced */
+ unsigned char *ip_opt_ptr[2]; /* IP option pointers */
#ifdef CONFIG_IP_MULTICAST
- int ip_mc_ttl; /* Multicasting TTL */
- int ip_mc_loop; /* Loopback */
- char ip_mc_name[MAX_ADDR_LEN]; /* Multicast device name */
- struct ip_mc_socklist *ip_mc_list; /* Group array */
+ int ip_mc_ttl; /* Multicasting TTL */
+ int ip_mc_loop; /* Loopback */
+ char ip_mc_name[MAX_ADDR_LEN];/* Multicast device name */
+ struct ip_mc_socklist *ip_mc_list; /* Group array */
#endif
/* This part is used for the timeout functions (timer.c). */
- int timeout; /* What are we waiting for? */
- struct timer_list timer; /* This is the TIME_WAIT/receive timer when we are doing IP */
- struct timeval stamp;
+ int timeout; /* What are we waiting for? */
+ struct timer_list timer; /* This is the TIME_WAIT/receive timer
+ * when we are doing IP
+ */
+ struct timeval stamp;
/* identd */
- struct socket *socket;
+ struct socket *socket;
/* Callbacks */
- void (*state_change)(struct sock *sk);
- void (*data_ready)(struct sock *sk,int bytes);
- void (*write_space)(struct sock *sk);
- void (*error_report)(struct sock *sk);
+ void (*state_change)(struct sock *sk);
+ void (*data_ready)(struct sock *sk,int bytes);
+ void (*write_space)(struct sock *sk);
+ void (*error_report)(struct sock *sk);
};
struct proto {
struct sk_buff * (*wmalloc)(struct sock *sk,
- unsigned long size, int force,
- int priority);
+ unsigned long size, int force,
+ int priority);
struct sk_buff * (*rmalloc)(struct sock *sk,
- unsigned long size, int force,
- int priority);
+ unsigned long size, int force,
+ int priority);
void (*wfree)(struct sock *sk, struct sk_buff *skb);
void (*rfree)(struct sock *sk, struct sk_buff *skb);
unsigned long (*rspace)(struct sock *sk);
@@ -248,9+251,9 @@ struct proto { int (*write)(struct sock *sk, const unsigned char *to,
int len, int nonblock, unsigned flags);
int (*sendto)(struct sock *sk,
- const unsigned char *from, int len, int noblock,
- unsigned flags, struct sockaddr_in *usin,
- int addr_len);
+ const unsigned char *from, int len,
+ int noblock, unsigned flags,
+ struct sockaddr_in *usin, int addr_len);
int (*recvfrom)(struct sock *sk,
unsigned char *from, int len, int noblock,
unsigned flags, struct sockaddr_in *usin,
@@ -259,9+262,10 @@ struct proto { unsigned long saddr,
unsigned long daddr,
struct device **dev, int type,
- struct options *opt, int len, int tos, int ttl);
+ struct options *opt, int len,
+ int tos, int ttl);
int (*connect)(struct sock *sk,
- struct sockaddr_in *usin, int addr_len);
+ struct sockaddr_in *usin, int addr_len);
struct sock * (*accept) (struct sock *sk, int flags);
void (*queue_xmit)(struct sock *sk,
struct device *dev, struct sk_buff *skb,
@@ -280,9+284,9 @@ struct proto { int (*init)(struct sock *sk);
void (*shutdown)(struct sock *sk, int how);
int (*setsockopt)(struct sock *sk, int level, int optname,
- char *optval, int optlen);
+ char *optval, int optlen);
int (*getsockopt)(struct sock *sk, int level, int optname,
- char *optval, int *option);
+ char *optval, int *option);
unsigned short max_header;
unsigned long retransmits;
char name[32];
@@ -298,9+302,13 @@ struct proto { #define TIME_DESTROY 4
#define TIME_DONE 5 /* used to absorb those last few packets */
#define TIME_PROBE0 6
-#define SOCK_DESTROY_TIME 1000 /* about 10 seconds */
+/* about 10 seconds */
+#define SOCK_DESTROY_TIME (10*HZ)
+
+
+/* Sockets 0-1023 can't be bound too unless you are superuser */
+#define PROT_SOCK 1024
-#define PROT_SOCK 1024 /* Sockets 0-1023 can't be bound too unless you are superuser */
#define SHUTDOWN_MASK 3
#define RCV_SHUTDOWN 1
@@ -308,7+316,8 @@ struct proto {
extern void destroy_sock(struct sock *sk);
-extern unsigned short get_new_socknum(struct proto *, unsigned short);
+extern unsigned short get_new_socknum(struct proto *,
+ unsigned short);
extern void put_sock(unsigned short, struct sock *);
extern void release_sock(struct sock *sk);
extern struct sock *get_sock(struct proto *, unsigned short,
@@ -326,22+335,32 @@ extern struct sk_buff *sock_wmalloc(struct sock *sk, extern struct sk_buff *sock_rmalloc(struct sock *sk,
unsigned long size, int force,
int priority);
-extern void sock_wfree(struct sock *sk, struct sk_buff *skb);
-extern void sock_rfree(struct sock *sk, struct sk_buff *skb);
+extern void sock_wfree(struct sock *sk,
+ struct sk_buff *skb);
+extern void sock_rfree(struct sock *sk,
+ struct sk_buff *skb);
extern unsigned long sock_rspace(struct sock *sk);
extern unsigned long sock_wspace(struct sock *sk);
-extern int sock_setsockopt(struct sock *sk,int level,int op,char *optval,int optlen);
+extern int sock_setsockopt(struct sock *sk, int level,
+ int op, char *optval,
+ int optlen);
-extern int sock_getsockopt(struct sock *sk,int level,int op,char *optval,int *optlen);
-extern struct sk_buff *sock_alloc_send_skb(struct sock *skb, unsigned long size, int noblock, int *errcode);
+extern int sock_getsockopt(struct sock *sk, int level,
+ int op, char *optval,
+ int *optlen);
+extern struct sk_buff *sock_alloc_send_skb(struct sock *skb,
+ unsigned long size,
+ int noblock,
+ int *errcode);
/*
- * Queue a received datagram if it will fit. Stream and sequenced protocols
- * can't normally use this as they need to fit buffers in and play with them.
+ * Queue a received datagram if it will fit. Stream and sequenced
+ * protocols can't normally use this as they need to fit buffers in
+ * and play with them.
*
- * Inlined as its very short and called for pretty much every packet ever
- * received.
+ * Inlined as its very short and called for pretty much every
+ * packet ever received.
*/
extern __inline__ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
@@ -363,9+382,9 @@ extern __inline__ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) /* declarations from timer.c */
extern struct sock *timer_base;
-void delete_timer (struct sock *);
-void reset_timer (struct sock *, int, unsigned long);
-void net_timer (unsigned long);
+extern void delete_timer (struct sock *);
+extern void reset_timer (struct sock *, int, unsigned long);
+extern void net_timer (unsigned long);
/* Enable debug/info messages */
@@ -436,7+436,7 @@ asmlinkage unsigned long sys_brk(unsigned long brk) freepages = buffermem >> 12;
freepages += nr_free_pages;
freepages += nr_swap_pages;
- freepages -= (high_memory - 0x100000) >> 16;
+ freepages -= MAP_NR(high_memory) >> 4;
freepages -= (newbrk-oldbrk) >> 12;
if (freepages < 0)
return current->mm->brk;
@@ -62,8+62,10 @@ char * strncat(char *dest, const char *src, size_t count) while (*dest)
dest++;
while ((*dest++ = *src++)) {
- if (--count == 0)
+ if (--count == 0) {
+ *dest = '\0';
break;
+ }
}
}
@@ -154,14+154,21 @@ o Minor bug fixes [IN]
------->>>> 1.3.16 <<<--------
-o Missing patches for device change in TCP [IN]
-o Device locking [IN]
+o Missing patches for device change in TCP [TESTED]
+o Device locking [TESTED]
o Infinite slip devices [IN]
o New AF_UNIX sockets [IN]
o Sendmsg/recvmsg (for some stuff only) [IN]
-o Device unload loopholes fixed [IN]
+o Device unload loopholes fixed [TESTED]
o Extra firewall abilities [IN]
-o Appletalk node probe bug fix [IN]
+o Appletalk node probe bug fix [TESTED]
+
+------->>>> 1.3.18 <<<<---------
+
+o AF_UNIX debugging [IN]
+o TCP explode on SWS bug fix [IN]
+o John Naylor's ARP hwtype fix [IN]
+o Datagram select matches BSD semantics [IN]
o Finish merging the bridge code
@@ -1865,11+1865,11 @@ void atalk_proto_init(struct net_proto *pro) aarp_proto_init();
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_ATALK, atalk_get_info, 9, "appletalk" });
+ { PROC_NET_ATALK, 9, "appletalk", atalk_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_AT_ROUTE, atalk_rt_get_info, 11,"atalk_route" });
+ { PROC_NET_AT_ROUTE, 11,"atalk_route", atalk_rt_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_ATIF, atalk_if_get_info, 11,"atalk_iface" });
+ { PROC_NET_ATIF, 11,"atalk_iface", atalk_if_get_info });
printk("Appletalk BETA 0.11 for Linux NET3.030\n");
}
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/notifier.h>
+#include <linux/proc_fs.h>
#include <net/ip.h>
#include <net/arp.h>
@@ -2031,11+2032,11 @@ void ax25_proto_init(struct net_proto *pro) register_netdevice_notifier(&ax25_dev_notifier);
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_AX25_ROUTE, ax25_rt_get_info, 10, "ax25_route" });
+ { PROC_NET_AX25_ROUTE, 10, "ax25_route", ax25_rt_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_AX25, ax25_get_info, 4, "ax25" });
+ { PROC_NET_AX25, 4, "ax25", ax25_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_AX25_CALLS, ax25_cs_get_info, 10, "ax25_calls" });
+ { PROC_NET_AX25_CALLS, 10, "ax25_calls", ax25_cs_get_info });
printk("GW4PTS/G4KLX AX.25 for Linux. Version 0.30 ALPHA for Linux NET3.030 (Linux 1.3.0)\n");
}
* Alan Cox : Fixed write select of non IP protocol crash.
* Florian La Roche: Changed for my new skbuff handling.
* Darryl Miles : Fixed non-blocking SOCK_SEQPACKET.
+ * Linus Torvalds : BSD semantic fixes.
*
* Note:
* A lot of this will change when the protocol/socket separation
@@ -1321,7+1321,7 @@ void dev_init(void) }
}
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_DEV, dev_get_info, 3, "dev" });
+ { PROC_NET_DEV, 3, "dev", dev_get_info });
}
@@ -1601,21+1601,26 @@ void inet_proto_init(struct net_proto *pro) */
ip_init();
+#if defined(CONFIG_IP_ACCT)||defined(CONFIG_IP_FIREWALL)|| \
+ defined(CONFIG_IP_MASQUERADE)
+ ip_fw_init();
+#endif
+
#ifdef CONFIG_INET_RARP
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_RARP, rarp_get_info, 4, "rarp"});
+ { PROC_NET_RARP, 4, "rarp", rarp_get_info });
rarp_ioctl_hook = rarp_ioctl;
#endif
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_RAW, raw_get_info, 3, "raw" });
+ { PROC_NET_RAW, 3, "raw", raw_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_SNMP, snmp_get_info, 4, "snmp" });
+ { PROC_NET_SNMP, 4, "snmp", snmp_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_SOCKSTAT, afinet_get_info, 8, "sockstat" });
+ { PROC_NET_SOCKSTAT, 8, "sockstat", afinet_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_TCP, tcp_get_info, 3, "tcp" });
+ { PROC_NET_TCP, 3, "tcp", tcp_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_UDP, udp_get_info, 3, "udp" });
+ { PROC_NET_UDP, 3, "udp", udp_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_ROUTE, rt_get_info, 5, "route" });
+ { PROC_NET_ROUTE, 5, "route", rt_get_info });
}
* Alan Cox : Don't proxy across hardware types!
* Jonathan Naylor : Added support for NET/ROM.
* Mike Shaver : RFC1122 checks.
+ * Jonathan Naylor : Only lookup the hardware address for
+ * the correct hardware type.
*/
/* RFC1122 Status:
@@ -160,7+162,7 @@ enum proxy {
/* Forward declarations. */
static void arp_check_expire (unsigned long);
-static struct arp_table *arp_lookup(u32 paddr, enum proxy proxy);
+static struct arp_table *arp_lookup(u32 paddr, enum proxy proxy, unsigned short type);
static struct timer_list arp_timer =
@@ -953,7+955,7 @@ int arp_find(unsigned char *haddr, u32 paddr, struct device *dev, /*
* Find an entry
*/
- entry = arp_lookup(paddr, PROXY_NONE);
+ entry = arp_lookup(paddr, PROXY_NONE, dev->type);
if (entry != NULL) /* It exists */
{
@@ -1126,13+1128,14 @@ int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy * for proxy entries, otherwise the netmask will be used
*/
-static struct arp_table *arp_lookup(u32 paddr, enum proxy proxy)
+static struct arp_table *arp_lookup(u32 paddr, enum proxy proxy, unsigned short type)
{
struct arp_table *entry;
unsigned long hash = HASH(paddr);
for (entry = arp_tables[hash]; entry != NULL; entry = entry->next)
- if (entry->ip == paddr) break;
+ if (entry->ip == paddr && entry->htype == type)
+ break;
/* it's possibly a proxy entry (with a netmask) */
if (!entry && proxy != PROXY_NONE)
@@ -1186,7+1189,7 @@ int arp_find_cache(unsigned char *dp, u32 daddr, struct device *dev) return 1;
default:
- entry=arp_lookup(daddr, PROXY_NONE);
+ entry=arp_lookup(daddr, PROXY_NONE, dev->type);
if(entry)
{
memcpy(dp,entry->ha, ETH_ALEN);
@@ -1277,7+1280,7 @@ static int arp_req_set(struct arpreq *req) /*
* Find the entry
*/
- entry = arp_lookup(ip, PROXY_EXACT);
+ entry = arp_lookup(ip, PROXY_EXACT, htype);
if (entry && (entry->flags & ATF_PUBL) != (r.arp_flags & ATF_PUBL))
{
sti();
@@ -1358,7+1361,7 @@ static int arp_req_get(struct arpreq *req)
si = (struct sockaddr_in *) &r.arp_pa;
cli();
- entry = arp_lookup(si->sin_addr.s_addr,PROXY_ANY);
+ entry = arp_lookup(si->sin_addr.s_addr, PROXY_ANY, r.arp_ha.sa_family);
if (entry == NULL)
{
@@ -1458,6+1461,6 @@ void arp_init (void) register_netdevice_notifier(&arp_dev_notifier);
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_ARP, arp_get_info, 3, "arp" });
+ { PROC_NET_ARP, 3, "arp", arp_get_info });
}
* Alan Cox : Fixed multicast (by popular demand 8))
* Alan Cox : Fixed forwarding (by even more popular demand 8))
* Alan Cox : Fixed SNMP statistics [I think]
+ * Gerhard Koerting : IP fragmentation forwarding fix
*
*
*
@@ -987,6+988,7 @@ void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int i */
iph = (struct iphdr *)(skb2->h.raw/*+dev->hard_header_len*/);
iph->frag_off = htons((offset >> 3));
+ skb2->ip_hdr = iph;
/*
* Added AC : If we are fragmenting a fragment thats not the
* last fragment then keep MF on each bit
@@ -2819,7+2821,7 @@ void ip_init(void)
#ifdef CONFIG_IP_MULTICAST
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_IGMP, ip_mc_procinfo, 4, "igmp"});
+ { PROC_NET_IGMP, 4, "igmp", ip_mc_procinfo });
#endif
}
@@ -1551,16+1551,16 @@ void ip_fw_init(void) {
#ifdef CONFIG_IP_ACCT
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_IPACCT, ip_acct_procinfo, 7, "ip_acct"});
+ { PROC_NET_IPACCT, 7, "ip_acct", ip_acct_procinfo });
#endif
#ifdef CONFIG_IP_FIREWALL
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_IPFWBLK, ip_fw_blk_procinfo, 8, "ip_block"});
+ { PROC_NET_IPFWBLK, 8, "ip_block", ip_fw_blk_procinfo });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_IPFWFWD, ip_fw_fwd_procinfo, 10, "ip_forward"});
+ { PROC_NET_IPFWFWD, 10, "ip_forward", ip_fw_fwd_procinfo });
#endif
#ifdef CONFIG_IP_MASQUERADE
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_IPMSQHST, ip_msqhst_procinfo, 13, "ip_masquerade"});
+ { PROC_NET_IPMSQHST, 13, "ip_masquerade", ip_msqhst_procinfo });
#endif
}
rarp_init(void)
{
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_RARP, rarp_get_info, 4, "rarp"});
+ { PROC_NET_RARP, 4, "rarp", rarp_get_info });
rarp_ioctl_hook = rarp_ioctl;
}
* Alan Cox : TCP irtt support.
* Jonathan Naylor : Added Metric support.
* Miquel van Smoorenburg : BSD API fixes.
+ * Miquel van Smoorenburg : Metrics.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -73,9+74,11 @@ static struct rtable *rt_loopback = NULL;
/*
* Remove a routing table entry.
+ * Should we return a status value here ?
*/
-static void rt_del(unsigned long dst, char *devname)
+static void rt_del(unsigned long dst, unsigned long mask,
+ char *devname, unsigned long gtw, short rt_flags, short metric)
{
struct rtable *r, **rp;
unsigned long flags;
@@ -91,9+94,16 @@ static void rt_del(unsigned long dst, char *devname) cli();
while((r = *rp) != NULL)
{
- /* Make sure both the destination and the device match */
- if ( r->rt_dst != dst ||
- (devname != NULL && strcmp((r->rt_dev)->name,devname) != 0) )
+ /*
+ * Make sure the destination and netmask match.
+ * metric, gateway and device are also checked
+ * if they were specified.
+ */
+ if (r->rt_dst != dst ||
+ (mask && r->rt_mask != mask) ||
+ (gtw && r->rt_gateway != gtw) ||
+ (metric >= 0 && r->rt_metric != metric) ||
+ (devname && strcmp((r->rt_dev)->name,devname) != 0) )
{
rp = &r->rt_next;
continue;
@@ -211,11+221,13 @@ static inline struct device * get_gw_dev(unsigned long gw) */
void ip_rt_add(short flags, unsigned long dst, unsigned long mask,
- unsigned long gw, struct device *dev, unsigned short mtu, unsigned long window, unsigned short irtt, unsigned char metric)
+ unsigned long gw, struct device *dev, unsigned short mtu,
+ unsigned long window, unsigned short irtt, short metric)
{
struct rtable *r, *rt;
struct rtable **rp;
unsigned long cpuflags;
+ int duplicate = 0;
/*
* A host is a unique machine and has no network bits.
@@ -320,6+332,12 @@ void ip_rt_add(short flags, unsigned long dst, unsigned long mask, rp = &r->rt_next;
continue;
}
+ if (r->rt_metric != metric && r->rt_gateway != gw)
+ {
+ duplicate = 1;
+ rp = &r->rt_next;
+ continue;
+ }
*rp = r->rt_next;
if (rt_loopback == r)
rt_loopback = NULL;
@@ -332,8+350,22 @@ void ip_rt_add(short flags, unsigned long dst, unsigned long mask,
rp = &rt_base;
while ((r = *rp) != NULL) {
- if ((r->rt_mask & mask) != mask)
+ /*
+ * When adding a duplicate route, add it before
+ * the route with a higher metric.
+ */
+ if (duplicate &&
+ r->rt_dst == dst &&
+ r->rt_mask == mask &&
+ r->rt_metric > metric)
break;
+ else
+ /*
+ * Otherwise, just add it before the
+ * route with a higher generality.
+ */
+ if ((r->rt_mask & mask) != mask)
+ break;
rp = &r->rt_next;
}
rt->rt_next = r;
@@ -381,7+413,7 @@ static int rt_new(struct rtentry *r) char * devname;
struct device * dev = NULL;
unsigned long flags, daddr, mask, gw;
- unsigned char metric;
+ short metric;
/*
* If a device is specified find it.
@@ -489,17+521,26 @@ static int rt_new(struct rtentry *r) static int rt_kill(struct rtentry *r)
{
struct sockaddr_in *trg;
+ struct sockaddr_in *msk;
+ struct sockaddr_in *gtw;
char *devname;
int err;
trg = (struct sockaddr_in *) &r->rt_dst;
+ msk = (struct sockaddr_in *) &r->rt_genmask;
+ gtw = (struct sockaddr_in *) &r->rt_gateway;
if ((devname = r->rt_dev) != NULL)
{
err = getname(devname, &devname);
if (err)
return err;
}
- rt_del(trg->sin_addr.s_addr, devname);
+ /*
+ * metric can become negative here if it wasn't filled in
+ * but that's a fortunate accident; we really use that in rt_del.
+ */
+ rt_del(trg->sin_addr.s_addr, msk->sin_addr.s_addr, devname,
+ gtw->sin_addr.s_addr, r->rt_flags, r->rt_metric - 1);
if ( devname != NULL )
putname(devname);
return 0;
#include <linux/interrupt.h>
#include <net/p8022.h>
#include <net/psnap.h>
+#include <linux/proc_fs.h>
#ifdef CONFIG_IPX
/* Configuration Variables */
@@ -1969,11+1970,11 @@ void ipx_proto_init(struct net_proto *pro) register_netdevice_notifier(&ipx_dev_notifier);
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_IPX, ipx_get_info, 3, "ipx" });
+ { PROC_NET_IPX, 3, "ipx", ipx_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_IPX_INTERFACE, ipx_interface_get_info, 13,"ipx_interface"});
+ { PROC_NET_IPX_INTERFACE, 13, "ipx_interface", ipx_interface_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_IPX_ROUTE, ipx_rt_get_info 9, "ipx_route" });
+ { PROC_NET_IPX_ROUTE, 9, "ipx_route", ipx_rt_get_info });
printk("Swansea University Computer Society IPX 0.31 for NET3.030\n");
printk("IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
#include <net/ip.h>
#include <net/arp.h>
+#include <linux/proc_fs.h>
+
/************************************************************************\
* *
* Handlers for the socket list *
@@ -1391,11+1393,11 @@ void nr_proto_init(struct net_proto *pro) nr_default.window = NR_DEFAULT_WINDOW;
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_NR, nr_get_info, 2, "nr" });
+ { PROC_NET_NR, 2, "nr", nr_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_NR_NEIGH, nr_neigh_get_info, 8, "nr_neigh" });
+ { PROC_NET_NR_NEIGH, 8, "nr_neigh", nr_neigh_get_info });
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_NR_NODES, nr_nodes_get_info, 8, "nr_nodes" });
+ { PROC_NET_NR_NODES, 8, "nr_nodes", nr_nodes_get_info });
}
@@ -80,10+80,6 @@ static int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
static int sock_fasync(struct inode *inode, struct file *filp, int on);
-extern int proc_net_register(struct proc_dir_entry *);
-extern int proc_net_unregister(int);
-
-
/*
* Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * Fixes:
+ * Linus Torvalds : Assorted bug cures.
*/
#include <linux/config.h>
#include <linux/malloc.h>
#include <asm/segment.h>
#include <linux/skbuff.h>
-/*#include <linux/netprotocol.h>*/
#include <linux/netdevice.h>
#include <net/sock.h>
#include <net/tcp.h>
@@ -1015,7+1017,7 @@ void unix_proto_init(struct net_proto *pro) printk("NET3: Unix domain sockets 0.07 BETA for Linux NET3.030.\n");
sock_register(unix_proto_ops.family, &unix_proto_ops);
proc_net_register(&(struct proc_dir_entry)
- { PROC_NET_UNIX, unix_get_info, 4, "unix" });
+ { PROC_NET_UNIX, 4, "unix", unix_get_info });
}
/*
* Local variables: