Commit e7bcec37 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.84

parent 0fd8b35e
......@@ -953,6 +953,13 @@ S: 1507 145th Place SE #B5
S: Bellevue, Washington 98007
S: USA
N: Werner Zimmermann
E: zimmerma@rz.fht-esslingen.de
D: CDROM driver "aztcd" (Aztech/Okano/Orchid/Wearnes)
S: Flandernstrasse 101
S: D-73732 Esslingen
S: Germany
N: Leonard N. Zubkoff
E: lnz@dandelion.com
D: XFree86 and BusLogic driver additions
......
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 83
SUBLEVEL = 84
ARCH = i386
......
......@@ -8,11 +8,11 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/version.h>
#include <linux/mm.h>
#include <asm/system.h>
#include <asm/console.h>
#include <asm/hwrpb.h>
#include <asm/page.h>
#include <stdarg.h>
......
......@@ -60,11 +60,18 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
* we can handle it..
*/
good_area:
if (!(vma->vm_page_prot & PAGE_USER))
goto bad_area;
if (mmcsr) {
if (!(vma->vm_page_prot & (PAGE_RW | PAGE_COW)))
if (cause < 0) {
if (!(vma->vm_flags & VM_EXEC))
goto bad_area;
} else if (!cause) {
if (!(vma->vm_flags & VM_READ))
goto bad_area;
} else {
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
}
if (mmcsr) {
do_wp_page(vma, address, cause > 0);
return;
}
......
......@@ -38,10 +38,10 @@ extern void show_net_buffers(void);
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
*/
unsigned long __bad_pagetable(void)
struct pte * __bad_pagetable(void)
{
memset((void *) EMPTY_PGT, 0, PAGE_SIZE);
return EMPTY_PGT;
return (struct pte *) EMPTY_PGT;
}
unsigned long __bad_page(void)
......
......@@ -9,6 +9,7 @@ bool 'Kernel math emulation' CONFIG_MATH_EMULATION n
bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD y
bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506 y
if [ "$CONFIG_ST506" = "y" ]; then
comment 'Please see block/drivers/README.ide for help/info on IDE drives'
bool ' Use old (reliable) disk-only driver for primary i/f' CONFIG_BLK_DEV_HD y
if [ "$CONFIG_BLK_DEV_HD" = "y" ]; then
bool ' Include new IDE driver for secondary i/f support' CONFIG_BLK_DEV_IDE n
......
......@@ -65,7 +65,7 @@ unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exe
mpnt->vm_task = current;
mpnt->vm_start = PAGE_MASK & (unsigned long) p;
mpnt->vm_end = TASK_SIZE;
mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY;
mpnt->vm_page_prot = PAGE_COPY;
mpnt->vm_flags = VM_STACK_FLAGS;
mpnt->vm_ops = NULL;
mpnt->vm_inode = NULL;
......
......@@ -37,7 +37,7 @@ asmlinkage int sys_idle(void)
/* Map out the low memory: it's no longer needed */
for (i = 0 ; i < 768 ; i++)
swapper_pg_dir[i] = 0;
pgd_clear(swapper_pg_dir + i);
/* endless idle loop with no priority at all */
current->counter = -100;
......
......@@ -84,23 +84,30 @@ static inline int put_stack_long(struct task_struct *task, int offset,
*/
static unsigned long get_long(struct vm_area_struct * vma, unsigned long addr)
{
pgd_t * pgdir;
pte_t * pgtable;
unsigned long page;
repeat:
page = *PAGE_DIR_OFFSET(vma->vm_task, addr);
if (page & PAGE_PRESENT) {
page &= PAGE_MASK;
page += PAGE_PTR(addr);
page = *((unsigned long *) page);
pgdir = PAGE_DIR_OFFSET(vma->vm_task, addr);
if (pgd_none(*pgdir)) {
do_no_page(vma, addr, 0);
goto repeat;
}
if (pgd_bad(*pgdir)) {
printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
pgd_clear(pgdir);
return 0;
}
if (!(page & PAGE_PRESENT)) {
pgtable = (pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir));
if (!pte_present(*pgtable)) {
do_no_page(vma, addr, 0);
goto repeat;
}
page = pte_page(*pgtable);
/* this is a hack for non-kernel-mapped video buffers and similar */
if (page >= high_memory)
return 0;
page &= PAGE_MASK;
page += addr & ~PAGE_MASK;
return *(unsigned long *) page;
}
......@@ -117,39 +124,40 @@ static unsigned long get_long(struct vm_area_struct * vma, unsigned long addr)
static void put_long(struct vm_area_struct * vma, unsigned long addr,
unsigned long data)
{
unsigned long page, pte = 0;
int readonly = 0;
pgd_t *pgdir;
pte_t *pgtable;
unsigned long page;
repeat:
page = *PAGE_DIR_OFFSET(vma->vm_task, addr);
if (page & PAGE_PRESENT) {
page &= PAGE_MASK;
page += PAGE_PTR(addr);
pte = page;
page = *((unsigned long *) page);
pgdir = PAGE_DIR_OFFSET(vma->vm_task, addr);
if (!pgd_present(*pgdir)) {
do_no_page(vma, addr, 1);
goto repeat;
}
if (!(page & PAGE_PRESENT)) {
do_no_page(vma, addr, 0 /* PAGE_RW */);
if (pgd_bad(*pgdir)) {
printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
pgd_clear(pgdir);
return;
}
pgtable = (pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir));
if (!pte_present(*pgtable)) {
do_no_page(vma, addr, 1);
goto repeat;
}
if (!(page & PAGE_RW)) {
if (!(page & PAGE_COW))
readonly = 1;
do_wp_page(vma, addr, PAGE_RW | PAGE_PRESENT);
page = pte_page(*pgtable);
if (!pte_write(*pgtable)) {
do_wp_page(vma, addr, 1);
goto repeat;
}
/* this is a hack for non-kernel-mapped video buffers and similar */
if (page >= high_memory)
return;
if (page < high_memory) {
page += addr & ~PAGE_MASK;
*(unsigned long *) page = data;
}
/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
*(unsigned long *) pte |= (PAGE_DIRTY|PAGE_COW);
page &= PAGE_MASK;
page += addr & ~PAGE_MASK;
*(unsigned long *) page = data;
if (readonly) {
*(unsigned long *) pte &=~ (PAGE_RW|PAGE_COW);
invalidate();
}
/* this should also re-instate whatever read-only mode there was before */
*pgtable = pte_mkdirty(mk_pte(page, vma->vm_page_prot));
invalidate();
}
static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
......
......@@ -67,20 +67,24 @@ asmlinkage struct pt_regs * save_v86_state(struct vm86_regs * regs)
static void mark_screen_rdonly(struct task_struct * tsk)
{
unsigned long tmp;
unsigned long *pg_table;
if ((tmp = tsk->tss.cr3) != 0) {
tmp = *(unsigned long *) tmp;
if (tmp & PAGE_PRESENT) {
tmp &= PAGE_MASK;
pg_table = (0xA0000 >> PAGE_SHIFT) + (unsigned long *) tmp;
tmp = 32;
while (tmp--) {
if (PAGE_PRESENT & *pg_table)
*pg_table &= ~PAGE_RW;
pg_table++;
}
pgd_t *pg_dir;
pg_dir = PAGE_DIR_OFFSET(tsk, 0);
if (!pgd_none(*pg_dir)) {
pte_t *pg_table;
int i;
if (pgd_bad(*pg_dir)) {
printk("vm86: bad page table directory entry %08lx\n", pgd_val(*pg_dir));
pgd_clear(pg_dir);
return;
}
pg_table = (pte_t *) pgd_page(*pg_dir);
pg_table += 0xA0000 >> PAGE_SHIFT;
for (i = 0 ; i < 32 ; i++) {
if (pte_present(*pg_table))
*pg_table = pte_wrprotect(*pg_table);
pg_table++;
}
}
}
......
......@@ -25,6 +25,11 @@ extern void die_if_kernel(char *,struct pt_regs *,long);
* This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate
* routines.
*
* error_code:
* bit 0 == 0 means no page found, 1 means protection fault
* bit 1 == 0 means read, 1 means write
* bit 2 == 0 means kernel, 1 means user-mode
*/
asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
{
......@@ -50,24 +55,36 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
* we can handle it..
*/
good_area:
/*
* was it a write?
*/
if (error_code & 2) {
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
} else {
/* read with protection fault? */
if (error_code & 1)
goto bad_area;
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
}
/*
* Did it hit the DOS screen memory VA from vm86 mode?
*/
if (regs->eflags & VM_MASK) {
unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT;
if (bit < 32)
current->tss.screen_bitmap |= 1 << bit;
}
if (!(vma->vm_page_prot & PAGE_USER))
goto bad_area;
if (error_code & PAGE_PRESENT) {
if (!(vma->vm_page_prot & (PAGE_RW | PAGE_COW)))
goto bad_area;
if (error_code & 1) {
#ifdef CONFIG_TEST_VERIFY_AREA
if (regs->cs == KERNEL_CS)
printk("WP fault at %08x\n", regs->eip);
#endif
do_wp_page(vma, address, error_code & PAGE_RW);
do_wp_page(vma, address, error_code & 2);
return;
}
do_no_page(vma, address, error_code & PAGE_RW);
do_no_page(vma, address, error_code & 2);
return;
/*
......@@ -75,7 +92,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
* Fix it, but check if it's kernel or user first..
*/
bad_area:
if (error_code & PAGE_USER) {
if (error_code & 4) {
current->tss.cr2 = address;
current->tss.error_code = error_code;
current->tss.trap_no = 14;
......@@ -85,17 +102,19 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
/*
* Oops. The kernel tried to access some bad page. We'll have to
* terminate things with extreme prejudice.
*
* First we check if it was the bootup rw-test, though..
*/
if (wp_works_ok < 0 && address == TASK_SIZE && (error_code & PAGE_PRESENT)) {
if (wp_works_ok < 0 && address == TASK_SIZE && (error_code & 1)) {
wp_works_ok = 1;
pg0[0] = PAGE_SHARED;
pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
invalidate();
printk("This processor honours the WP bit even when in supervisor mode. Good.\n");
return;
}
if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE) {
printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
pg0[0] = PAGE_SHARED;
pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
} else
printk(KERN_ALERT "Unable to handle kernel paging request");
printk(" at virtual address %08lx\n",address);
......@@ -104,7 +123,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
current->tss.cr3, page);
page = ((unsigned long *) page)[address >> 22];
printk(KERN_ALERT "*pde = %08lx\n", page);
if (page & PAGE_PRESENT) {
if (page & 1) {
page &= PAGE_MASK;
address &= 0x003ff000;
page = ((unsigned long *) page)[address >> PAGE_SHIFT];
......
......@@ -36,19 +36,19 @@ extern void show_net_buffers(void);
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
*/
unsigned long __bad_pagetable(void)
pte_t * __bad_pagetable(void)
{
extern char empty_bad_page_table[PAGE_SIZE];
__asm__ __volatile__("cld ; rep ; stosl":
:"a" (BAD_PAGE + PAGE_TABLE),
:"a" (pte_val(BAD_PAGE)),
"D" ((long) empty_bad_page_table),
"c" (PTRS_PER_PAGE)
:"di","cx");
return (unsigned long) empty_bad_page_table;
return (pte_t *) empty_bad_page_table;
}
unsigned long __bad_page(void)
pte_t __bad_page(void)
{
extern char empty_bad_page[PAGE_SIZE];
......@@ -57,7 +57,7 @@ unsigned long __bad_page(void)
"D" ((long) empty_bad_page),
"c" (PTRS_PER_PAGE)
:"di","cx");
return (unsigned long) empty_bad_page;
return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED));
}
unsigned long __zero_page(void)
......@@ -111,8 +111,8 @@ extern unsigned long free_area_init(unsigned long, unsigned long);
*/
unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
{
unsigned long * pg_dir;
unsigned long * pg_table;
pgd_t * pg_dir;
pte_t * pg_table;
unsigned long tmp;
unsigned long address;
......@@ -129,20 +129,22 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
address = 0;
pg_dir = swapper_pg_dir;
while (address < end_mem) {
tmp = *(pg_dir + 768); /* at virtual addr 0xC0000000 */
if (!tmp) {
tmp = start_mem | PAGE_TABLE;
*(pg_dir + 768) = tmp;
/* map the memory at virtual addr 0xC0000000 */
if (pgd_none(pg_dir[768])) {
pgd_set(pg_dir+768, (pte_t *) start_mem);
start_mem += PAGE_SIZE;
}
*pg_dir = tmp; /* also map it in at 0x0000000 for init */
pg_table = (pte_t *) pgd_page(pg_dir[768]);
/* also map it tempoarily at 0x0000000 for init */
pgd_set(pg_dir+768, pg_table);
pgd_set(pg_dir, pg_table);
pg_dir++;
pg_table = (unsigned long *) (tmp & PAGE_MASK);
for (tmp = 0 ; tmp < PTRS_PER_PAGE ; tmp++,pg_table++) {
if (address < end_mem)
*pg_table = address | PAGE_SHARED;
*pg_table = mk_pte(address, PAGE_SHARED);
else
*pg_table = 0;
pte_clear(pg_table);
address += PAGE_SIZE;
}
}
......@@ -208,7 +210,7 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
datapages << (PAGE_SHIFT-10));
/* test if the WP bit is honoured in supervisor mode */
wp_works_ok = -1;
pg0[0] = PAGE_READONLY;
pg0[0] = pte_val(mk_pte(0, PAGE_READONLY));
invalidate();
__asm__ __volatile__("movb 0,%%al ; movb %%al,0": : :"ax", "memory");
pg0[0] = 0;
......
......@@ -45,7 +45,7 @@ old kernel, in order to reboot if something goes wrong!
2. INSTALLATION
If you received this software as a standalone package AZTECH.CDROM.Vxx.tgz
(xx=version number) and not included in the standard Linux kernel, read the
file AZTECH.CDROM.Vxx.README included in that package to install it. The
file AZTECH.CDROM.README included in that package to install it. The
standalone package's home is 'ftp.gwdg.de : pub/linux/cdrom/drivers/aztech'.
The driver consists of a header file 'aztcd.h', which normally should reside
in /usr/include/linux and the source code 'aztcd.c', which normally resides in
......@@ -62,13 +62,12 @@ see the following message while Linux boots:
Aztech CD-ROM Init: <drive type> detected
Aztech CD-ROM Init: End
If the message looks different and you are sure to have a supported drive,
it may have a different base address. The Aztech driver does have an 'auto-
detection feature', which looks for the 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.
it may have a different base address. The Aztech driver does look for the
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.
If the message looks correct, as user 'root' you should be able to mount the
drive by
......@@ -146,13 +145,12 @@ Please send detailed bug reports and bug fixes via EMail to
zimmerma@rz.fht-esslingen.de
I also would like to get positive feedback. Please inform me, if you have
positive test results. Please include a description of your CD-ROM drive
type and interface card, the exact firmware message during Linux bootup,
the version number of the AZTECH-CDROM-driver and the Linux kernel version.
Also a description of your system's other hardware could be of interest,
especially microprocessor type, clock frequency, other interface cards such
as soundcards, ethernet adapter, game cards etc..
Please include a description of your CD-ROM drive type and interface card,
the exact firmware message during Linux bootup, the version number of the
AZTECH-CDROM-driver and the Linux kernel version. Also a description of your
system's other hardware could be of interest, especially microprocessor type,
clock frequency, other interface cards such as soundcards, ethernet adapter,
game cards etc..
I will try to collect the reports and make the necessary modifications from
time to time. I may also come back to you directly with some bug fixes and
......@@ -172,12 +170,12 @@ snail mail address for such 'stuff' is
7. OTHER DRIVES
The following drives ORCHID CDS3110, OKANO CDD110 and WEARNES nearly look
the same as AZTECH CDA268-01A, especially they seem to use the same command
codes. So it should be simple to make the AZTECH driver work with these drives.
codes. So it was quite simple to make the AZTECH driver work with these drives.
Unfortuntately I do not have any of these drives available, so I can't test
it. I've got reports, that it works with ORCHID CDS3110 and Game-Wave32
sound cards and also with WEARNES CDD110 in some different combinations. In
some installations, it seems necessary to initialize the drive with the DOS
Unfortuntately I do not have any of these drives available, so I couldn't test
it myself. But I've got reports, that it works with ORCHID CDS3110 and Game-
Wave32 sound cards and also with WEARNES CDD110 in some different combinations.
In some installations, it seems necessary to initialize the drive with the DOS
driver before (especially if combined with a sound card) and then do a warm
boot (CTRL-ALT-RESET) or start Linux from DOS, e.g. with 'loadlin'.
......@@ -350,8 +348,8 @@ great job in analyzing the command structure of various CD-ROM drives, this
work would not have been possible. E.Moenkeberg was also a great help in
making the software 'kernel ready' and in answering many of the CDROM-related
questions in the newsgroups. He really is *the* Linux CD-ROM guru. Thanks
also to Ruediger Helsch, Unifix, and to all the guys on the Internet, who
collected valuable technical information about CDROMs.
also to all the guys on the Internet, who collected valuable technical
information about CDROMs.
Joe Nardone (nardone@clark.net) was a patient tester even for my first
trial, which was more than slow, and made suggestions for code improvement.
......@@ -462,7 +460,7 @@ int main(void)
unsigned char buf[2336];
} azt;
printf("\nMini-Audio CD-Player V0.5 (C) 1994 W.Zimmermann\n");
printf("\nMini-Audio CD-Player V0.5 (C) 1994,1995 W.Zimmermann\n");
handle=open("/dev/cdrom",O_RDWR);
ioctl(handle,CDROMRESUME);
......@@ -608,7 +606,7 @@ int main(void)
{ printf("Drive error or invalid adress\n");
}
break;
#ifdef AZT_PRIVATE_IOCTLS
#ifdef AZT_PRIVATE_IOCTLS /*not supported by every CDROM driver*/
case 'd': cmd=CDROMREADMODE1;
printf("Adress (min:sec:frame) ");
scanf("%d:%d:%d",&arg1,&arg2,&arg3);
......@@ -618,7 +616,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 or invalid adress\n");
{ printf("Drive error, invalid adress or unsupported command\n");
}
k=0;
getchar();
......@@ -651,7 +649,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 or invalid adress\n");
{ printf("Drive error, invalid adress or unsupported command\n");
}
k=0;
for (i=0;i<146;i++)
......
This Readme file describes the floppy driver.
FAQ list:
=========
A FAQ list may be found in the fdutils package (see below), and also
at ftp.imag.fr:pub/Linux/ZLIBC/floppy/FAQ
Lilo config options (Thinkpad users, read this)
===============================================
The floppy driver is configured using the 'floppy=' option in
lilo. This option can be typed at the boot prompt, or entered in the
lilo configuration file.
Example: If your kernel is called linux-72, type the following line
at the lilo boot prompt (if you have a thinkpad):
linux-72 floppy=thinkpad
You may also enter the following line in /etc/lilo.conf, in the description
of linux-72:
append = "floppy=thinkpad"
Several floppy related options may be given, example:
linux-72 floppy=daring floppy=two_fdc
append = "floppy=daring floppy=two_fdc"
If you give options both in the lilo config file and on the boot
prompt, the option strings of both places are concatenated, the boot
prompt options coming last. That's why there are also options to
restore the default behaviour.
The floppy related options include:
floppy=<mask>,allowed_drive_mask
Sets the bitmask of allowed drives to <mask>. By default, only units
0 and 1 of each floppy controller are allowed. This is done because
certain non-standard hardware (ASUS PCI motherboards) mess up the
keyboard when accessing units 2 or 3.
floppy=two_fdc
Tells the floppy driver that you have two floppy controllers. The
second floppy controller is assumed to be at io address 0x370.
floppy=thinkpad
Tells the floppy driver that you have a Thinkpad. Thinkpads use an
inverted convention for the disk change line.
Supporting utilities and additional documentation:
==================================================
Additional parameters of the floppy driver can be configured at run
time. Utilities which do this can be found in the fdutils
package. This package also contains a new version of mtools which
allows to access high capacity disks (up to 1992K on a high density 3
1/2 disk!). It also contains additional documentation about the floppy
driver. It can be found at:
ftp.imag.fr:pub/Linux/ZLIBC/fdutils/fdutils-4.0.src.tar.gz
sunsite.unc.edu:/pub/Linux/system/Misc/fdutils-4.0.src.tar.gz
tsx-11.mit.edu:/pub/linux/sources/sbin/fdutils-4.0.src.tar.gz
Alpha patches to these utilities are at:
ftp.imag.fr:pub/Linux/ZLIBC/fdutils/ALPHA
All patches contained in this directory are directly against the base
version, i.e. DON'T APPLY THEM ON TOP OF EACH OTHER. Only apply the
most recent one.
Alpha patches for the floppy driver:
====================================
You may find ALPHA patches of the driver itself in
ftp.imag.fr:pub/Linux/ZLIBC/floppy/ALPHA. These patches are named
fdp<kernel-version>-<day><month>.diff.gz
WARNING: These _are_ ALPHA, and may introduce new problems! Some
problems may only show up on certain hardware, or when trying weirdo
things. So don't be misled by people claiming they are stable and
should really be BETA. What works for one person, may not work for
somebody else at all. This directory contains a RELEASES file
describing the features of some of these patches.
If after some testing these patches prove to be sufficiently stable,
they'll move into ftp.imag.fr:pub/Linux/ZLIBC/floppy/BETA.
You may find quick&dirty fixes to the driver in
ftp.imag.fr:pub/Linux/ZLIBC/QDF. These patches are named
fdp<kernel-version>-<day><month>.diff
These patches fix only the most obvious problems, or provide trivial
enhancements. The main objective is to keep these patches small and
local, in order to keep the probability of introducing new problems as
small as possible. However, they may not attack the root of the
problem but only cure the symptoms. This directory contains a RELEASES
file describing the features of these patches.
The ALPHA, BETA and QDF directories are removed, and replaced by a
README file when they get empty due to integration of the patches into
the stock kernel. You may still find patches to old kernels in
ftp.imag.fr:pub/Linux/ZLIBC/obsolete
Reporting problems about the floppy driver
==========================================
If you have a question or a bug report about the floppy driver, mail
me at Alain.Knaff@imag.fr. If you post to the news, use preferably one
of the groups comp.os.linux.help (for questions) or
comp.os.linux.hardware (for bug reports). As the volume in these
groups is rather high, be sure to include the word "floppy" (or
"FLOPPY") in the subject line.
Be sure to read the FAQ before mailing/posting any bug reports!
Alain
......@@ -18,7 +18,7 @@ Major features of ide.c & ide-cd.c:
- optional (compile time) support for 32-bit VLB data transfers
- support for IDE multiple (block) mode (same as hd.c)
- support for interrupt unmasking during I/O (better than hd.c)
- auto detection/use of multiple (block) mode settings from BIOS
- compile flag for auto detection/use of multiple mode setting from BIOS
- improved handshaking and error detection/recovery
- can co-exist with hd.c to control only the secondary interface
......@@ -96,10 +96,54 @@ mlord@bnr.ca
snyder@fnald0.fnal.gov
================================================================================
How To Use *Big* IDE drives with Linux/DOS
Some Terminology
----------------
IDE = Integrated Drive Electonics, meaning that each drive has a built-in
controller, which is why an "IDE interface card" is not a "controller card".
IDE drives are designed to attach almost directly to the ISA bus of an AT-style
computer. The typcial IDE interface card merely provides I/O port address
decoding and tri-state buffers, although several newer localbus cards go much
beyond the basics. When purchasing a localbus IDE interface, avoid cards with
an onboard BIOS and those which require special drivers. Instead, look for a
card which uses hardware switches/jumpers to select the interface timing speed,
to allow much faster data transfers than the original 8Mhz ISA bus allows.
ATA = AT (the old IBM 286 computer) Attachment Interface, a draft American
National Standard for connecting hard drives to PCs. This is the official
name for "IDE".
The latest standards define some enhancements, known as the ATA-2 spec,
which grew out of vendor-specific "Enhanced IDE" (EIDE) implementations.
ATAPI = ATA Packet Interface, a new protocol for controlling the drives,
similar to SCSI protocols, created at the same time as the ATA2 standard.
ATAPI is currently used for controlling CDROM and TAPE devices, and will
likely also soon be used for Floppy drives, removeable R/W cartridges,
and for high capacity hard disk drives.
How To Use *Big* ATA/IDE drives with Linux
------------------------------------------
All IDE drives larger than 504MB ("528Meg") use a "physical" geometry which
has more than 1024 cylinders. This presents two problems to most systems:
The ATA Interface spec for IDE disk drives allows a total of 28 bits
(8 bits for sector, 16 bits for cylinder, and 4 bits for head) for addressing
individual disk sectors of 512 bytes each (in "Linear Block Address" (LBA)
mode, there is still only a total of 28 bits available in the hardware).
This "limits" the capacity of an IDE drive to no more than 128GB (Giga-bytes). All current day IDE drives are somewhat smaller than this upper limit, and
within a few years, ATAPI disk drives will raise the limit considerably.
All IDE disk drives "suffer" from a "16-heads" limitation: the hardware has
only a four bit field for head selection, restricting the number of "physical"
heads to 16 or less. Since the BIOS usually has a 63 sectors/track limit,
this means that all IDE drivers larger than 504MB (528Meg) must use a "physical"
geometry with more than 1024 cylinders.
(1024cyls * 16heads * 63sects * 512bytes/sector) / (1024 * 1024) == 504MB
(Some BIOSs (and controllers with onboard BIOS) pretend to allow "32" or "64"
heads per drive (discussed below), but can only do so by playing games with
the real (hidden) geometry, which is always limited to 16 or fewer heads).
This presents two problems to most systems:
1. The INT13 interface to the BIOS only allows 10-bits for cylinder
addresses, giving a limit of 1024cyls for programs which use it.
......@@ -182,6 +226,11 @@ by doing the following after installing slackware (or whatever):
5. Create a symlink for LILO to use with: ln -s /dos/boot /boot
6. Re-run LILO with: lilo
A danger with this approach is that whenever an MS-DOS "defragmentation"
program is run (like Norton "speeddisk"), it may move the Linux boot
files around, confusing LILO and making the (Linux) system unbootable.
Be sure to keep a "boot floppy" kernel at hand for such circumstances.
If you "don't do DOS", then partition as you please, but remember to create
a small partition to hold the /boot directory (and vmlinuz) as described above
such that they stay within the first 1024 cylinders.
......
#define AZT_VERSION "V0.72"
/* $Id: aztcd.c,v 0.72 1995/01/13 15:21:09 root Exp root $
#define AZT_VERSION "V0.8"
/* $Id: aztcd.c,v 0.80 1995/01/21 19:54:53 root Exp $
linux/drivers/block/aztcd.c - AztechCD268 CDROM driver
Copyright (C) 1994,1995 Werner Zimmermann (zimmerma@rz.fht-esslingen.de)
......@@ -90,7 +90,10 @@
W.Zimmermann, Jan. 8, 1995
V0.72 Some more modifications for adaption to the standard kernel.
W.Zimmermann, Jan. 16, 1995
V0.80 aztcd is now part of the standard kernel since version 1.1.83.
Modified the SET_TIMER and CLEAR_TIMER macros to comply with
the new timer scheme.
W.Zimmermann, Jan. 21, 1995
NOTE:
Points marked with ??? are questionable !
*/
......@@ -110,11 +113,7 @@
#include <asm/io.h>
#include <asm/segment.h>
#ifdef CONFIG_AZTCD
#define MAJOR_NR AZTECH_CDROM_MAJOR
#else
#define MAJOR_NR MITSUMI_CDROM_MAJOR /*use Mitsumi major number, if Aztech*/
#endif /*major number is not configured*/
#include "blk.h"
#include <linux/aztcd.h>
......@@ -128,7 +127,6 @@ static int aztPresent = 0;
#define AZT_TEST4 /* QUICK_LOOP-counter */
#define AZT_TEST5 /* port(1) state */
#define AZT_DEBUG
#define AZT_PRIVATE_IOCTLS /*incompatible ioctls*/
#endif
#define CURRENT_VALID \
......@@ -176,6 +174,7 @@ static char azt_init_end = 0;
static int AztTimeout, AztTries;
static struct wait_queue *azt_waitq = NULL;
static struct timer_list delay_timer = { NULL, NULL, 0, 0, NULL };
static struct azt_DiskInfo DiskInfo;
static struct azt_Toc Toc[MAX_TRACKS];
......@@ -1208,6 +1207,7 @@ static void aztcd_release(struct inode * inode, struct file * file)
azt_invalidate_buffers();
sync_dev(inode->i_rdev); /*??? isn't it a read only dev?*/
invalidate_buffers(inode -> i_rdev);
CLEAR_TIMER;
}
return;
}
......
......@@ -92,6 +92,8 @@
#include <linux/config.h>
#ifdef CONFIG_BLK_DEV_FD
#ifndef FD_MODULE
/* the following is the mask of allowed drives. By default units 2 and
* 3 of both floppy controllers are disabled, because switching on the
......@@ -108,7 +110,6 @@ static int FDC2=-1;
#define MODULE_AWARE_DRIVER
#ifdef CONFIG_BLK_DEV_FD
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
......@@ -989,7 +990,7 @@ static void fdc_specify(void)
/* TODO: lock this in via LOCK during initialization */
output_byte(FD_CONFIGURE);
output_byte(0);
output_byte(0x1A); /* FIFO on, polling off, 10 byte threshold */
output_byte(0x2A); /* FIFO on, polling off, 10 byte threshold */
output_byte(0); /* precompensation from track 0 upwards */
if ( FDCS->reset ){
FDCS->has_fifo=0;
......@@ -1708,9 +1709,10 @@ static void failure_and_wakeup(void)
static int next_valid_format(void)
{
int probed_format;
probed_format = DRS->probed_format;
while(1){
probed_format = DRS->probed_format;
if ( probed_format > N_DRIVE ||
if ( probed_format >= 8 ||
! DP->autodetect[probed_format] ){
DRS->probed_format = 0;
return 1;
......
/*
* linux/drivers/block/ide.c Version 3.8 January 12, 1995
* linux/drivers/block/ide.c Version 3.10 January 21, 1995
*
* Copyright (C) 1994, 1995 Linus Torvalds & authors (see below)
*/
......@@ -95,6 +95,11 @@
* Version 3.8 fixed byte-swapping for confused Mitsumi cdrom drives
* update of ide-cd.c from Scott, allows blocksize=1024
* cdrom probe fixes, inspired by jprang@uni-duisburg.de
* Version 3.9 don't use LBA if lba_capacity looks funny
* correct the drive capacity calculations
* fix probing for old Seagates without HD_ALTSTATUS
* fix byte-ordering for some NEC cdrom drives
* Version 3.10 disable multiple mode by default; was causing trouble
*
* To do:
* - special 32-bit controller-type detection & support
......@@ -102,6 +107,7 @@
* - figure out how to support oddball "intelligent" caching cards
*/
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
......@@ -110,7 +116,6 @@
#include <linux/kernel.h>
#include <linux/hdreg.h>
#include <linux/genhd.h>
#include <linux/config.h>
#include <linux/malloc.h>
#include <linux/string.h>
#include <linux/major.h>
......@@ -130,8 +135,8 @@
#include <asm/io.h>
#undef REALLY_FAST_IO /* define if ide ports are perfect */
#undef INITIAL_MULT_COUNT /* define to override status quo */
#define INITIAL_MULT_COUNT 0 /* undef to use BIOS setting on entry */
/* or non-zero to enable block mode */
#ifndef VLB_32BIT_IDE /* 0 for safety, 1 for 32-bit chipset:*/
#define VLB_32BIT_IDE 0 /* Winbond 83759F or OPTi 82C621 */
#endif
......@@ -1567,7 +1572,11 @@ static void fixstring (byte *s, int bytecount, int byteswap)
*p++ = '\0';
}
static unsigned long fix_lba_capacity (struct hd_driveid *id)
static int lba_capacity_is_ok (struct hd_driveid *id)
/*
* Returns: 1 if lba_capacity looks sensible
* 0 otherwise
*/
{
unsigned long lba_sects = id->lba_capacity;
unsigned long chs_sects = id->cyls * id->heads * id->sectors;
......@@ -1575,15 +1584,15 @@ static unsigned long fix_lba_capacity (struct hd_driveid *id)
/* perform a rough sanity check on lba_sects: within 10% is "okay" */
if ((lba_sects - chs_sects) < _10_percent)
return lba_sects;
return 1; /* lba_capacity is good */
/* some drives have the word order reversed */
lba_sects = (lba_sects << 16) | (lba_sects >> 16);
if ((lba_sects - chs_sects) < _10_percent)
return (id->lba_capacity = lba_sects);
/* play it safe and assume lba capacity is the same as chs capacity */
return chs_sects;
if ((lba_sects - chs_sects) < _10_percent) {
id->lba_capacity = lba_sects; /* fix it */
return 1; /* lba_capacity is (now) good */
}
return 0; /* lba_capacity value is bad */
}
static unsigned long probe_mem_start; /* used by drive/irq probing routines */
......@@ -1591,6 +1600,7 @@ static unsigned long probe_mem_start; /* used by drive/irq probing routines */
static void do_identify (ide_dev_t *dev)
{
int bswap;
unsigned short model01;
struct hd_driveid *id;
unsigned long capacity, check;
......@@ -1601,16 +1611,23 @@ static void do_identify (ide_dev_t *dev)
/*
* Non-ATAPI drives seem to always use big-endian string ordering.
* Most ATAPI cdrom drives, such as the NEC, Vertos, and some Mitsumi
* models, use little-endian. But other Mitsumi models appear to use
* big-endian, confusing the issue. We try to take all of this into
* consideration, "knowing" that Mitsumi drive names begin with "FX".
* Most ATAPI cdrom drives, such as the Vertos, and some NEC and Mitsumi
* models, use little-endian. But some NEC/Mitsumi revisions appear to
* use big-endian, confusing the issue. We try to take all of this
* into consideration, "knowing" that Mitsumi drive model names begin
* with "FX" and NEC drive model names begin with "NE".
*/
bswap = 1;
if (id->model[0] != 'X' || id->model[1] != 'F') {
if ((id->model[0] == 'F' && id->model[1] == 'X') || (id->config & 0x8000))
bswap = 0;
}
#define PAIR(hi,lo) ((unsigned short)((hi<<8)|(lo&0xff)))
model01 = PAIR(id->model[0],id->model[1]);
if (model01 == PAIR('N','E') || model01 == PAIR('F','X'))
bswap = 0; /* little endian NEC or Mitsumi */
else if (model01 == PAIR('E','N') || model01 == PAIR('X','F'))
bswap = 1; /* big endian NEC or Mitsumi */
else if ((id->config & 0x8000) || dev->type == cdrom)
bswap = 0; /* all other ATAPI drives */
else
bswap = 1; /* all other non-ATAPI drives */
#undef PAIR
fixstring (id->model, sizeof(id->model), bswap);
fixstring (id->fw_rev, sizeof(id->fw_rev), bswap);
fixstring (id->serial_no, sizeof(id->serial_no), bswap);
......@@ -1636,17 +1653,15 @@ static void do_identify (ide_dev_t *dev)
return;
}
/*
* Gather up the geometry info.
*/
dev->type = disk;
/* Extract geometry if we did not already have one for the drive */
if (!dev->present) {
dev->present = 1;
dev->cyl = dev->bios_cyl = id->cyls;
dev->head = dev->bios_head = id->heads;
dev->sect = dev->bios_sect = id->sectors;
}
capacity = BIOS_SECTORS(dev); /* default value */
/* Handle logical geometry translation by the drive */
if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads
&& (id->cur_heads <= 16) && id->cur_sectors)
{
......@@ -1670,22 +1685,23 @@ static void do_identify (ide_dev_t *dev)
if (check == capacity) /* was it swapped? */
*((int *)&id->cur_capacity0) = capacity; /* fix it */
}
if (id->capability & 2) { /* use LBA if the drive supports it */
capacity = fix_lba_capacity(id);
dev->select.b.lba = 1;
if (!dev->head || dev->head > 16) {
dev->cyl = id->cyls; /* WIN_SPECIFY needs a valid */
dev->head = id->heads; /* geometry or it fails. */
dev->sect = id->sectors;
}
/* Use physical geometry if what we have still makes no sense */
if ((!dev->head || dev->head > 16) && id->heads && id->heads <= 16) {
dev->cyl = id->cyls;
dev->head = id->heads;
dev->sect = id->sectors;
}
/* Correct the number of cyls if the bios value is too small */
if (dev->sect == dev->bios_sect && dev->head == dev->bios_head) {
if (dev->cyl > dev->bios_cyl) {
if (dev->cyl > dev->bios_cyl)
dev->bios_cyl = dev->cyl;
if (!(id->capability & 2)) /* if NOT using LBA */
capacity = BIOS_SECTORS(dev);
}
}
/* Determine capacity, and use LBA if the drive properly supports it */
if ((id->capability & 2) && lba_capacity_is_ok(id)) {
dev->select.b.lba = 1;
capacity = id->lba_capacity;
} else {
capacity = dev->cyl * dev->head * dev->sect;
}
ide_capacity[DEV_HWIF][dev->select.b.drive] = capacity;
......@@ -1693,17 +1709,18 @@ static void do_identify (ide_dev_t *dev)
dev->name, id->model, capacity/2048L, id->buf_size/2,
dev->select.b.lba ? "LBA, " : "",
dev->bios_cyl, dev->bios_head, dev->bios_sect);
/* Keep current multiplemode setting, if any (from DOS/BIOS) */
if (id->max_multsect) {
/*
* Keep current multiplemode setting, if any (from DOS/BIOS):
*/
if ((id->multsect_valid & 1) && id->multsect)
dev->mult_count = id->multsect; /* current setting */
#ifdef INITIAL_MULT_COUNT
if (INITIAL_MULT_COUNT <= id->max_multsect)
dev->mult_req = INITIAL_MULT_COUNT;
else
dev->mult_req = INITIAL_MULT_COUNT;
#if INITIAL_MULT_COUNT
/* use specified value, or maximum, whichever is less */
if (INITIAL_MULT_COUNT > id->max_multsect)
dev->mult_req = id->max_multsect;
#endif
#else /* use existing setting from DOS/BIOS: */
if (dev->mult_count <= id->max_multsect) /* valid? */
dev->mult_req = dev->mult_count; /* keep it */
......@@ -1729,7 +1746,7 @@ static int try_to_identify (ide_dev_t *dev, byte cmd)
* 2 device aborted the command (refused to identify itself)
*/
{
int rc;
int hd_status, rc;
unsigned long timeout;
#if PROBE_FOR_IRQS
int irqs = 0;
......@@ -1744,18 +1761,23 @@ static int try_to_identify (ide_dev_t *dev, byte cmd)
}
#endif /* PROBE_FOR_IRQS */
delay_10ms(); /* take a deep breath */
if (IN_BYTE(HD_ALTSTATUS,DEV_HWIF) == IN_BYTE(HD_STATUS,DEV_HWIF))
hd_status = HD_ALTSTATUS; /* use non-intrusive polling */
else
hd_status = HD_STATUS; /* an ancient Seagate drive */
OUT_BYTE(cmd,HD_COMMAND); /* ask drive for ID */
delay_10ms(); /* wait for BUSY_STAT */
timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
for (timeout += jiffies; IN_BYTE(HD_ALTSTATUS,DEV_HWIF) & BUSY_STAT;) {
if (timeout < jiffies) {
timeout += jiffies;
do {
if (jiffies > timeout) {
#if PROBE_FOR_IRQS
if (!irq_probed[DEV_HWIF])
(void) probe_irq_off(irqs);
#endif /* PROBE_FOR_IRQS */
return 1; /* drive timed-out */
}
}
delay_10ms(); /* give drive a breather */
} while (IN_BYTE(hd_status,DEV_HWIF) & BUSY_STAT);
delay_10ms(); /* wait for IRQ and DRQ_STAT */
if (OK_STAT(GET_STAT(DEV_HWIF),DRQ_STAT,BAD_RW_STAT)) {
cli(); /* some systems need this */
......@@ -1821,7 +1843,8 @@ static int do_probe (ide_dev_t *dev, byte cmd)
if ((rc = try_to_identify(dev, cmd))) /* send cmd and wait */
rc = try_to_identify(dev, cmd); /* failed: try again */
if (rc == 1)
printk("%s: no response\n", dev->name);
printk("%s: no response (status = 0x%02x)\n",
dev->name, GET_STAT(DEV_HWIF));
OUT_BYTE(dev->ctl|2,HD_CMD); /* disable device irq */
delay_10ms();
(void) GET_STAT(DEV_HWIF); /* ensure drive irq is clear */
......
......@@ -87,7 +87,13 @@ static int mmap_mem(struct inode * inode, struct file * file, struct vm_area_str
{
if (vma->vm_offset & ~PAGE_MASK)
return -ENXIO;
#ifdef __i386__
#if 0 && defined(__i386__)
/*
* hmm.. This disables high-memory caching, as the XFree86 team wondered
* about that at one time. It doesn't seem to make a difference, though:
* the surround logic should disable caching for the high device addresses
* anyway.
*/
if (x86 > 3 && vma->vm_offset >= high_memory)
vma->vm_page_prot |= PAGE_PCD;
#endif
......@@ -163,7 +169,7 @@ static int read_zero(struct inode * node,struct file * file,char * buf,int count
static int mmap_zero(struct inode * inode, struct file * file, struct vm_area_struct * vma)
{
if (vma->vm_page_prot & PAGE_RW)
if (vma->vm_flags & VM_SHARED)
return -EINVAL;
if (zeromap_page_range(vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
......
......@@ -166,6 +166,9 @@ endif
ifdef CONFIG_APRICOT
NETDRV_OBJS := $(NETDRV_OBJS) apricot.o
endif
ifdef CONFIG_DEC_ELCP
NETDRV_OBJS := $(NETDRV_OBJS) tulip.o
endif
ifdef CONFIG_8390
NETDRV_OBJS := $(NETDRV_OBJS) 8390.o
......
......@@ -16,20 +16,20 @@
straight-forward Fujitsu MB86965 implementation.
Sources:
The Fujitsu MB86695 datasheet.
The Fujitsu MB86965 datasheet.
After the initial version of this driver was written Gerry Sockins of
After the initial version of this driver was written Gerry Sawkins of
ATI provided their EEPROM configuration code header file.
Thanks to NIIBE Yutaka <gniibe@mri.co.jp> for bug fixes.
Bugs:
The MB86695 has a design flaw that makes all probes unreliable. Not
The MB86965 has a design flaw that makes all probes unreliable. Not
only is it difficult to detect, it also moves around in I/O space in
response to inb()s from other device probes!
*/
static char *version =
"at1700.c:v1.10 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
"at1700.c:v1.12 1/18/95 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include <linux/config.h>
......@@ -70,7 +70,6 @@ typedef unsigned char uchar;
/* Information that need to be kept for each board. */
struct net_local {
struct enet_statistics stats;
long open_time; /* Useless example local info. */
uint tx_started:1; /* Number of packet on the Tx queue. */
uchar tx_queue; /* Number of packet on the Tx queue. */
ushort tx_queue_len; /* Current length of the Tx queue. */
......@@ -207,7 +206,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
/* Grab the region so that we can find another board if the IRQ request
fails. */
request_region(ioaddr, AT1700_IO_EXTENT,"at1700");
request_region(ioaddr, AT1700_IO_EXTENT, "at1700");
printk("%s: AT1700 found at %#3x, IRQ %d, address ", dev->name,
ioaddr, irq);
......@@ -345,12 +344,14 @@ static int net_open(struct device *dev)
/* Switch to register bank 2 for the run-time registers. */
outb(0xe8, ioaddr + CONFIG_1);
lp->tx_started = 0;
lp->tx_queue = 0;
lp->tx_queue_len = 0;
/* Turn on Rx interrupts, leave Tx interrupts off until packet Tx. */
outb(0x00, ioaddr + TX_INTR);
outb(0x81, ioaddr + RX_INTR);
lp->open_time = jiffies;
dev->tbusy = 0;
dev->interrupt = 0;
dev->start = 1;
......@@ -385,6 +386,9 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
outw(0x8100, ioaddr + TX_INTR);
dev->tbusy=0;
dev->trans_start = jiffies;
lp->tx_started = 0;
lp->tx_queue = 0;
lp->tx_queue_len = 0;
}
/* If some higher layer thinks we've missed an tx-done interrupt
......@@ -492,6 +496,7 @@ net_rx(struct device *dev)
while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
ushort status = inw(ioaddr + DATAPORT);
ushort pkt_len = inw(ioaddr + DATAPORT);
if (net_debug > 4)
printk("%s: Rxing packet mode %02x status %04x.\n",
......@@ -510,13 +515,14 @@ net_rx(struct device *dev)
if (status & 0x02) lp->stats.rx_crc_errors++;
if (status & 0x01) lp->stats.rx_over_errors++;
} else {
ushort pkt_len = inw(ioaddr + DATAPORT);
/* Malloc up new buffer. */
struct sk_buff *skb;
if (pkt_len > 1550) {
printk("%s: The AT1700 claimed a very large packet, size %d.\n",
dev->name, pkt_len);
/* Prime the FIFO and then flush the packet. */
inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
outb(0x05, ioaddr + 14);
lp->stats.rx_errors++;
break;
......@@ -525,6 +531,8 @@ net_rx(struct device *dev)
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet (len %d).\n",
dev->name, pkt_len);
/* Prime the FIFO and then flush the packet. */
inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
outb(0x05, ioaddr + 14);
lp->stats.rx_dropped++;
break;
......@@ -533,15 +541,6 @@ net_rx(struct device *dev)
skb->dev = dev;
insw(ioaddr + DATAPORT, skb->data, (pkt_len + 1) >> 1);
if (net_debug > 5) {
int i;
printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);
for (i = 0; i < 14; i++)
printk(" %02x", skb->data[i]);
printk(".\n");
}
netif_rx(skb);
lp->stats.rx_packets++;
}
......@@ -574,8 +573,6 @@ static int net_close(struct device *dev)
struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
lp->open_time = 0;
dev->tbusy = 1;
dev->start = 0;
......
This diff is collapsed.
......@@ -68,7 +68,7 @@
0) have a copy of the loadable modules code installed on your system.
1) copy ewrk3.c from the /linux/drivers/net directory to your favourite
temporary directory.
2) edit the source code near line 1340 to reflect the I/O address and
2) edit the source code near line 1830 to reflect the I/O address and
IRQ you're using.
3) compile ewrk3.c, but include -DMODULE in the command line to ensure
that the correct bits are compiled (see end of source code).
......@@ -78,7 +78,7 @@
6) run the net startup bits for your new eth?? interface manually
(usually /etc/rc.inet[12] at boot time).
7) enjoy!
[Alan Cox: Changed this so you can insmod ewrk3.o irq=x io=y]
Note that autoprobing is not allowed in loadable modules - the system is
......@@ -121,11 +121,12 @@
0.24 31-oct-94 Added uid checks in some ioctls
0.30 1-nov-94 BETA code release
0.31 5-dec-94 Added check/snarf_region code.
0.32 16-jan-95 Broadcast packet fix
=========================================================================
*/
static char *version = "ewrk3.c:v0.31 12/5/94 davies@wanton.lkg.dec.com\n";
static char *version = "ewrk3.c:v0.32 1/16/95 davies@wanton.lkg.dec.com\n";
#include <stdarg.h>
#include <linux/kernel.h>
......@@ -195,6 +196,7 @@ static int ewrk3_debug = 1;
#define EWRK3_IO_BASE 0x100 /* Start address for probe search */
#define EWRK3_IOP_INC 0x20 /* I/O address increment */
#define EWRK3_TOTAL_SIZE 0x20 /* required I/O address space */
#define EWRK3_IO_SEARCH 0x007dff7f /* probe search mask */
static long mem_chkd = EWRK3_IO_SEARCH; /* holds which I/O addrs should be */
/* checked, for multi-EWRK3 case */
......@@ -212,9 +214,8 @@ static long mem_chkd = EWRK3_IO_SEARCH; /* holds which I/O addrs should be */
#define EISA_SLOT_INC 0x1000
#endif
#ifndef CRC_POLYNOMIAL
#define CRC_POLYNOMIAL 0x04c11db7 /* Ethernet CRC polynomial */
#endif /* CRC_POLYNOMIAL */
#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */
#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
/*
** EtherWORKS 3 shared memory window sizes
......@@ -349,10 +350,11 @@ int ewrk3_probe(struct device *dev)
if (base_addr > 0x0ff) { /* Check a single specified location. */
if (!autoprobed) { /* Module or fixed location */
if (!check_region(base_addr, EWRK3_IOP_INC)) {
if (!check_region(base_addr, EWRK3_TOTAL_SIZE)) {
if (((mem_chkd >> ((base_addr - EWRK3_IO_BASE)/ EWRK3_IOP_INC))&0x01)==1) {
if (DevicePresent(base_addr) == 0) { /* Is EWRK3 really here? */
request_region(base_addr, EWRK3_IOP_INC,"ewrk3"); /* Register I/O region */
/* Register I/O Region */
request_region(base_addr, EWRK3_IOP_INC, "ewrk3");
status = ewrk3_hw_init(dev, base_addr);
} else {
printk("ewrk3_probe(): No device found\n");
......@@ -1239,20 +1241,19 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
/*
** Calculate the hash code and update the logical address filter
** from a list of ethernet multicast addresses.
** Derived from a 'C' program in the AMD data book:
** "Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE)",
** Pub #17781, Rev. A, May 1993
** Little endian crc one liner from Matt Thomas, DEC.
**
** Note that when clearing the table, the broadcast bit must remain asserted
** to receive broadcast messages.
*/
static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs, char *multicast_table)
{
struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
int iobase = dev->base_addr;
char j, ctrl, bit, octet;
int i, iobase = dev->base_addr;
char j, bit, byte;
short *p = (short *) multicast_table;
unsigned short hashcode;
int i;
long int crc, poly = (long int) CRC_POLYNOMIAL;
u_short hashcode;
u_long crc, poly = CRC_POLYNOMIAL_LE;
while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */
......@@ -1272,48 +1273,49 @@ static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs, c
i++;
}
}
} else if (num_addrs == 0) {
} else {
/* Clear table except for broadcast bit */
if (lp->shmem_length == IO_ONLY) {
for (i=0; i<(HASH_TABLE_LEN >> 3); i++) {
for (i=0; i<(HASH_TABLE_LEN >> 4) - 1; i++) {
outb(0x00, EWRK3_DATA);
}
outb(0x80, EWRK3_DATA); i++; /* insert the broadcast bit */
for (; i<(HASH_TABLE_LEN >> 3); i++) {
outb(0x00, EWRK3_DATA);
}
} else {
memset(multicast_table, 0, (HASH_TABLE_LEN >> 3));
*(multicast_table + (HASH_TABLE_LEN >> 4) - 1) = 0x80;
}
} else {
/* Update table */
for (i=0;i<num_addrs;i++) { /* for each address in the list */
if (((char) *(addrs+ETH_ALEN*i) & 0x01) == 1) {/* multicast address? */
crc = (long int) 0xffffffff; /* init CRC for each address */
for (octet=0;octet<ETH_ALEN;octet++) { /* for each address octet */
for(j=0;j<8;j++) { /* process each address bit */
bit = (((char)* (addrs+ETH_ALEN*i+octet)) >> j) & 0x01;
ctrl = ((crc < 0) ? 1 : 0); /* shift the control bit */
crc <<= 1; /* shift the CRC */
if (bit ^ ctrl) { /* (bit) XOR (control bit) */
crc ^= poly; /* (CRC) XOR (polynomial) */
}
if ((*addrs & 0x01) == 1) { /* multicast address? */
crc = 0xffffffff; /* init CRC for each address */
for (byte=0;byte<ETH_ALEN;byte++) { /* for each address byte */
/* process each address bit */
for (bit = *addrs++,j=0;j<8;j++, bit>>=1) {
crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0);
}
}
hashcode = ((crc >>= 23) & 0x01); /* hashcode is 9 MSb of CRC ... */
for (j=0;j<8;j++) { /* ... in reverse order. */
hashcode <<= 1;
crc >>= 1;
hashcode |= (crc & 0x01);
}
octet = hashcode >> 3; /* bit[3-8] -> octet in filter */
/* bit[0-2] -> bit in octet */
hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */
byte = hashcode >> 3; /* bit[3-8] -> byte in filter */
bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */
if (lp->shmem_length == IO_ONLY) {
unsigned char tmp;
outw((short)((long)multicast_table) + octet, EWRK3_PIR1);
outw((short)((long)multicast_table) + byte, EWRK3_PIR1);
tmp = inb(EWRK3_DATA);
tmp |= (1 << (hashcode & 0x07));
outw((short)((long)multicast_table) + octet, EWRK3_PIR1);
tmp |= bit;
outw((short)((long)multicast_table) + byte, EWRK3_PIR1);
outb(tmp, EWRK3_DATA);
} else {
multicast_table[octet] |= (1 << (hashcode & 0x07));
multicast_table[byte] |= bit;
}
} else { /* skip this address */
addrs += ETH_ALEN;
}
}
}
......@@ -1337,13 +1339,13 @@ static struct device *isa_probe(struct device *dev)
iobase += EWRK3_IOP_INC, i++) {
if (tmp & 0x01) {
/* Anything else registered here? */
if (!check_region(iobase, EWRK3_IOP_INC)) {
if (!check_region(iobase, EWRK3_TOTAL_SIZE)) {
if (DevicePresent(iobase) == 0) {
/*
** Device found. Mark its (I/O) location for future reference. Only 24
** EtherWORKS devices can exist between 0x100 and 0x3e0.
*/
request_region(iobase, EWRK3_IOP_INC,"ewrk3");
request_region(iobase, EWRK3_IOP_INC, "ewrk3");
if (num_ewrk3s > 0) { /* only gets here in autoprobe */
dev = alloc_device(dev, iobase);
} else {
......@@ -1379,14 +1381,14 @@ static struct device *eisa_probe(struct device *dev)
for (status = -ENODEV, i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) {
/* Anything else registered here? */
if (!check_region(iobase, EWRK3_IOP_INC)) {
if (!check_region(iobase, EWRK3_TOTAL_SIZE)) {
if (DevicePresent(iobase) == 0) {
/*
** Device found. Mark its slot location for future reference. Only 7
** EtherWORKS devices can exist in EISA space....
*/
mem_chkd |= (0x01 << (i + 24));
request_region(iobase, EWRK3_IOP_INC,"ewrk3");
request_region(iobase, EWRK3_IOP_INC, "ewrk3");
if (num_ewrk3s > 0) { /* only gets here in autoprobe */
dev = alloc_device(dev, iobase);
} else {
......@@ -1827,7 +1829,6 @@ static struct device thisEthwrk = {
0x300, 5, /* I/O address, IRQ */
0, 0, 0, NULL, ewrk3_probe };
int io=0x300; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
int irq=5; /* or use the insmod io= irq= options */
......
/* lance.c: An AMD LANCE ethernet driver for linux. */
/*
Written 1993-94 by Donald Becker.
Written 1993,1994,1995 by Donald Becker.
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
......@@ -15,7 +15,7 @@
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
*/
static char *version = "lance.c:v1.06 11/29/94 becker@cesdis.gsfc.nasa.gov\n";
static char *version = "lance.c:v1.07 1/18/95 becker@cesdis.gsfc.nasa.gov\n";
#include <linux/config.h>
#include <linux/kernel.h>
......@@ -188,7 +188,8 @@ struct lance_init_block {
};
struct lance_private {
char devname[8];
char *name;
void *pad;
/* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
struct lance_rx_head rx_ring[RX_RING_SIZE];
struct lance_tx_head tx_ring[TX_RING_SIZE];
......@@ -263,7 +264,8 @@ unsigned long lance_init(unsigned long mem_start, unsigned long mem_end)
for (pci_index = 0; pci_index < 8; pci_index++) {
unsigned char pci_bus, pci_device_fn;
unsigned long pci_ioaddr;
unsigned short pci_command;
if (pcibios_find_device (AMD_VENDOR_ID, AMD_DEVICE_ID, pci_index,
&pci_bus, &pci_device_fn) != 0)
break;
......@@ -273,6 +275,18 @@ unsigned long lance_init(unsigned long mem_start, unsigned long mem_end)
PCI_BASE_ADDRESS_0, &pci_ioaddr);
/* Remove I/O space marker in bit 0. */
pci_ioaddr &= ~3;
/* PCI Spec 2.1 states that it is either the driver or PCI card's
* responsibility to set the PCI Master Enable Bit if needed.
* (From Mark Stockton <marks@schooner.sys.hou.compaq.com>)
*/
pcibios_read_config_word(pci_bus, pci_device_fn,
PCI_COMMAND, &pci_command);
if ( ! (pci_command & PCI_COMMAND_MASTER)) {
printk("PCI Master Bit has not been set. Setting...\n");
pci_command |= PCI_COMMAND_MASTER;
pcibios_write_config_word(pci_bus, pci_device_fn,
PCI_COMMAND, pci_command);
}
printk("Found PCnet/PCI at %#lx, irq %d (mem_start is %#lx).\n",
pci_ioaddr, pci_irq_line, mem_start);
mem_start = lance_probe1(pci_ioaddr, mem_start);
......@@ -300,6 +314,7 @@ unsigned long lance_probe1(int ioaddr, unsigned long mem_start)
struct lance_private *lp;
short dma_channels; /* Mark spuriously-busy DMA channels */
int i, reset_val, lance_version;
char *chipname;
/* Flags for specific chips or boards. */
unsigned char hpJ2405A = 0; /* HP ISA adaptor */
int hp_builtin = 0; /* HP on-board ethernet. */
......@@ -357,7 +372,8 @@ unsigned long lance_probe1(int ioaddr, unsigned long mem_start)
+ PKT_BUF_SZ*(RX_RING_SIZE + TX_RING_SIZE),
&mem_start);
printk("%s: %s at %#3x,", dev->name, chip_table[lance_version].name, ioaddr);
chipname = chip_table[lance_version].name;
printk("%s: %s at %#3x,", dev->name, chipname, ioaddr);
/* There is a 16 byte station address PROM at the base address.
The first six bytes are the station address. */
......@@ -365,11 +381,12 @@ unsigned long lance_probe1(int ioaddr, unsigned long mem_start)
printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
dev->base_addr = ioaddr;
request_region(ioaddr, LANCE_TOTAL_SIZE,"lance");
request_region(ioaddr, LANCE_TOTAL_SIZE, chip_table[lance_version].name);
/* Make certain the data structures used by the LANCE are aligned. */
dev->priv = (void *)(((int)dev->priv + 7) & ~7);
lp = (struct lance_private *)dev->priv;
lp->name = chipname;
lp->rx_buffs = (long)dev->priv + sizeof(struct lance_private);
lp->tx_bounce_buffs = (char (*)[PKT_BUF_SZ])
(lp->rx_buffs + PKT_BUF_SZ*RX_RING_SIZE);
......@@ -464,7 +481,7 @@ unsigned long lance_probe1(int ioaddr, unsigned long mem_start)
if (dev->dma == 4) {
printk(", no DMA needed.\n");
} else if (dev->dma) {
if (request_dma(dev->dma, "lance")) {
if (request_dma(dev->dma, chipname)) {
printk("DMA %d allocation failed.\n", dev->dma);
return mem_start;
} else
......@@ -480,7 +497,7 @@ unsigned long lance_probe1(int ioaddr, unsigned long mem_start)
if (test_bit(dma, &dma_channels))
continue;
outw(0x7f04, ioaddr+LANCE_DATA); /* Clear the memory error bits. */
if (request_dma(dma, "lance"))
if (request_dma(dma, chipname))
continue;
set_dma_mode(dma, DMA_MODE_CASCADE);
enable_dma(dma);
......@@ -534,7 +551,7 @@ lance_open(struct device *dev)
int i;
if (dev->irq == 0 ||
request_irq(dev->irq, &lance_interrupt, 0, "lance")) {
request_irq(dev->irq, &lance_interrupt, 0, lp->name)) {
return -EAGAIN;
}
......@@ -587,7 +604,11 @@ lance_open(struct device *dev)
while (i++ < 100)
if (inw(ioaddr+LANCE_DATA) & 0x0100)
break;
outw(0x0142, ioaddr+LANCE_DATA);
/*
* We used to clear the InitDone bit, 0x0100, here but Mark Stockton
* reports that doing so triggers a bug in the '974.
*/
outw(0x0042, ioaddr+LANCE_DATA);
if (lance_debug > 2)
printk("%s: LANCE open after %d ticks, init block %#x csr0 %4.4x.\n",
......
......@@ -40,8 +40,9 @@
Given that almost all of these functions are handled in the current
socket-based scheme, putting ethercard devices in /dev/ seems pointless.
[Removed all support for /dev network devices. When someone adds streams then
by magic we get them, but otherwise they are un-needed and a space waste]
[Removed all support for /dev network devices. When someone adds
streams then by magic we get them, but otherwise they are un-needed
and a space waste]
*/
/* The list of used and available "eth" slots (for "eth0", "eth1", etc.) */
......@@ -51,7 +52,7 @@ static struct device *ethdev_index[MAX_ETH_CARDS];
unsigned long lance_init(unsigned long mem_start, unsigned long mem_end);
unsigned long pi_init(unsigned long mem_start, unsigned long mem_end);
unsigned long apricot_init(unsigned long mem_start, unsigned long mem_end);
unsigned long dec21040_init(unsigned long mem_start, unsigned long mem_end);
/*
net_dev_init() is our network device initialization routine.
......@@ -62,11 +63,17 @@ unsigned long apricot_init(unsigned long mem_start, unsigned long mem_end);
unsigned long net_dev_init (unsigned long mem_start, unsigned long mem_end)
{
#if defined(CONFIG_LANCE) /* Note this is _not_ CONFIG_AT1500. */
/* Network device initialization for devices that must allocate
low-memory or contiguous DMA buffers.
*/
#if defined(CONFIG_LANCE)
mem_start = lance_init(mem_start, mem_end);
#endif
#if defined(CONFIG_PI)
mem_start = pi_init(mem_start, mem_end);
#endif
#if defined(CONFIG_DEC_ELCP)
mem_start = dec21040_init(mem_start, mem_end);
#endif
return mem_start;
}
......@@ -82,14 +89,33 @@ unsigned long net_dev_init (unsigned long mem_start, unsigned long mem_end)
*/
struct device *
init_etherdev(struct device *dev, int sizeof_private, unsigned long *mem_startp)
init_etherdev(struct device *dev, int sizeof_priv, unsigned long *mem_startp)
{
int new_device = 0;
int i;
/* Use an existing correctly named device in Space.c:dev_base. */
if (dev == NULL) {
int alloc_size = sizeof(struct device) + sizeof("eth%d ")
+ sizeof_private + 3;
+ sizeof_priv + 3;
struct device *cur_dev;
char pname[8]; /* Putative name for the device. */
for (i = 0; i < MAX_ETH_CARDS; ++i)
if (ethdev_index[i] == NULL) {
sprintf(pname, "eth%d", i);
for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next)
if (strcmp(pname, cur_dev->name) == 0) {
dev = cur_dev;
dev->init = NULL;
if (mem_startp && *mem_startp ) {
dev->priv = (void*) *mem_startp;
*mem_startp += sizeof_priv + 3;
} else
dev->priv = kmalloc(sizeof_priv + 3, GFP_KERNEL);
goto found;
}
}
alloc_size &= ~3; /* Round to dword boundary. */
......@@ -99,12 +125,14 @@ init_etherdev(struct device *dev, int sizeof_private, unsigned long *mem_startp)
} else
dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL);
memset(dev, 0, alloc_size);
if (sizeof_private)
if (sizeof_priv)
dev->priv = (void *) (dev + 1);
dev->name = sizeof_private + (char *)(dev + 1);
dev->name = sizeof_priv + (char *)(dev + 1);
new_device = 1;
}
found: /* From the double loop above. */
if (dev->name &&
((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
for (i = 0; i < MAX_ETH_CARDS; ++i)
......@@ -115,7 +143,7 @@ init_etherdev(struct device *dev, int sizeof_private, unsigned long *mem_startp)
}
}
ether_setup(dev); /* should this be called here? */
ether_setup(dev); /* Hmmm, should this be called here? */
if (new_device) {
/* Append the device to the device queue. */
......
/* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
/*
Written 1993-94 by Donald Becker.
Written 1993,1994,1995 by Donald Becker.
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
......@@ -12,12 +12,33 @@
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This is a driver for the SMC Ultra ethercard.
This is a driver for the SMC Ultra and SMC EtherEZ ethercards.
This driver uses the cards in the 8390-compatible, shared memory mode.
Most of the run-time complexity is handled by the generic code in
8390.c. The code in this file is responsible for
ultra_probe() Detecting and initializing the card.
ultra_probe1()
ultra_open() The card-specific details of starting, stopping
ultra_reset_8390() and resetting the 8390 NIC core.
ultra_close()
ultra_block_input() Routines for reading and writing blocks of
ultra_block_output() packet buffer memory.
This driver enables the shared memory only when doing the actual data
transfers to avoid a bug in early version of the card that corrupted
data transferred by a AHA1542.
This driver does not support the programmed-I/O data transfer mode of
the EtherEZ. That support (if available) is smc-ez.c. Nor does it
use the non-8390-compatible "Altego" mode. (No support currently planned.)
*/
static char *version =
"smc-ultra.c:v1.11 11/21/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
"smc-ultra.c:v1.12 1/18/95 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include <linux/kernel.h>
#include <linux/sched.h>
......@@ -93,10 +114,13 @@ int ultra_probe1(struct device *dev, int ioaddr)
char *model_name;
unsigned char eeprom_irq = 0;
/* Values from various config regs. */
unsigned char num_pages, irqreg, addr, reg4 = inb(ioaddr + 4) & 0x7f;
unsigned char num_pages, irqreg, addr;
unsigned char idreg = inb(ioaddr + 7);
unsigned char reg4 = inb(ioaddr + 4) & 0x7f;
/* Check the ID nibble. */
if ((inb(ioaddr + 7) & 0xF0) != 0x20)
if ((idreg & 0xF0) != 0x20 /* SMC Ultra */
&& (idreg & 0xF0) != 0x40) /* SMC EtherEZ */
return ENODEV;
/* Select the station address register set. */
......@@ -110,7 +134,9 @@ int ultra_probe1(struct device *dev, int ioaddr)
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct ei_device), 0);
printk("%s: SMC Ultra at %#3x,", dev->name, ioaddr);
model_name = (idreg & 0xF0) == 0x20 ? "SMC Ultra" : "SMC EtherEZ";
printk("%s: %s at %#3x,", dev->name, model_name, ioaddr);
for (i = 0; i < 6; i++)
printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i));
......@@ -128,8 +154,6 @@ int ultra_probe1(struct device *dev, int ioaddr)
can find the card after a warm boot. */
outb(reg4, ioaddr + 4);
model_name = "SMC Ultra";
if (dev->irq < 2) {
unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
int irq;
......@@ -146,8 +170,8 @@ int ultra_probe1(struct device *dev, int ioaddr)
}
/* OK, were are certain this is going to work. Setup the device. */
request_region(ioaddr, 32,"smc-ultra");
/* OK, we are certain this is going to work. Setup the device. */
request_region(ioaddr, 32, model_name);
/* The 8390 isn't at the base address, so fake the offset */
dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
......@@ -192,7 +216,7 @@ ultra_open(struct device *dev)
{
int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
if (request_irq(dev->irq, ei_interrupt, 0, "SMC Ultra"))
if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name))
return -EAGAIN;
outb(ULTRA_MEMENB, ioaddr); /* Enable memory, 16 bit mode. */
......
This diff is collapsed.
......@@ -52,9 +52,11 @@ SCSI_OBJS := $(SCSI_OBJS) sg.o
SCSI_SRCS := $(SCSI_SRCS) sg.c
endif
SCSI_SRCS := $(SCSI_SRCS) qlogic.c
ifdef CONFIG_SCSI_QLOGIC
SCSI_OBJS := $(SCSI_OBJS) qlogic.o
SCSI_SRCS := $(SCSI_SRCS) qlogic.c
else
SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) qlogic.o
endif
ifdef CONFIG_SCSI_AHA152X
......
This diff is collapsed.
......@@ -2,7 +2,7 @@
#define _AHA152X_H
/*
* $Id: aha152x.h,v 1.6 1994/11/24 21:35:38 root Exp root $
* $Id: aha152x.h,v 1.8 1995/01/21 22:11:07 root Exp root $
*/
#if defined(__KERNEL__)
......@@ -22,7 +22,7 @@ int aha152x_biosparam(Disk *, int, int*);
(unless we support more than 1 cmd_per_lun this should do) */
#define AHA152X_MAXQUEUE 7
#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.6 $"
#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.8 $"
/* Initial value of Scsi_Host entry */
#define AHA152X { /* next */ NULL, \
......
This diff is collapsed.
......@@ -2,7 +2,7 @@
* Header file for eata_dma.c Linux EATA-DMA SCSI driver *
* (c) 1993,94,95 Michael Neuffer *
*********************************************************
* last change: 95/01/15 *
* last change: 95/01/16 *
********************************************************/
......@@ -16,7 +16,7 @@
#define VER_MAJOR 2
#define VER_MINOR 1
#define VER_SUB "0g"
#define VER_SUB "0h"
/************************************************************************
* Here you can configure your drives that are using a non-standard *
......@@ -49,7 +49,7 @@
* Debug options. *
* Enable DEBUG and whichever options you require. *
************************************************************************/
#define DEBUG 1 /* Enable debug code. */
#define DEBUG_EATA 1 /* Enable debug code. */
#define DPT_DEBUG 0 /* Bobs special */
#define DBG_DELAY 0 /* Build in delays so debug messages can be
* be read before they vanish of the top of
......@@ -64,10 +64,11 @@
#define DBG_COM 0 /* Trace command call */
#define DBG_QUEUE 0 /* Trace command queueing. */
#define DBG_INTR 0 /* Trace interrupt service routine. */
#define DBG_INTR2 0 /* Trace interrupt service routine. */
#define DBG_REGISTER 0 /* */
#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort)*/
#if DEBUG
#if DEBUG_EATA
#define DBG(x, y) if ((x)) {y;}
#else
#define DBG(x, y)
......@@ -91,7 +92,7 @@
0, /* sg_tablesize */ \
0, /* cmd_per_lun */ \
0, /* present */ \
0, /* True if ISA */ \
1, /* True if ISA */ \
ENABLE_CLUSTERING }
int eata_detect(Scsi_Host_Template *);
......@@ -121,21 +122,19 @@ int eata_reset(Scsi_Cmnd *);
#define MAXIRQ 16
#define MAXTARGET 8
/* PCI Bus And Device Limitations */
#define MAX_PCI_DEVICES 32 /* Maximum # Of Devices Per Bus */
#define MAX_METHOD_2 16 /* Max Devices For Method 2 */
#define MAX_PCI_BUS 16 /* Maximum # Of Busses Allowed */
#define MAX_PCI_DEVICES 32 /* Maximum # Of Devices Per Bus */
#define MAX_METHOD_2 16 /* Max Devices For Method 2 */
#define MAX_PCI_BUS 16 /* Maximum # Of Busses Allowed */
#define SG_SIZE 64
#define C_P_L_DIV 8 /* 1 <= C_P_L_DIV <= 8 */
#define C_P_L_CURRENT_MAX 2 /* Until this limit is removed */
#define SG_SIZE 64
#define C_P_L_DIV 32
#define FREE 0
#define USED 1
#define TIMEOUT 2
#define RESET 4
#define LOCKED 8
#define FREE 0
#define USED 1
#define TIMEOUT 2
#define RESET 4
#define LOCKED 8
#define HD(cmd) ((hostdata *)&(cmd->host->hostdata))
#define CD(cmd) ((struct eata_ccb *)(cmd->host_scribble))
......@@ -335,6 +334,7 @@ typedef struct hstd{
char vendor[9];
char name[18];
char revision[6];
char EATA_revision;
unchar bustype; /* bustype of HBA */
unchar channel; /* no. of scsi channel */
unchar state; /* state of HBA */
......@@ -388,4 +388,6 @@ typedef struct emul_pp {
struct lun_map lunmap[4];
}emulpp;
#endif /* _EATA_H */
/*
* This file is in2000.c, written and
* Copyright (C) 1993 Brad McLean
* Last edit 08/25/94 WDE
* Last edit 1/19/95 TZ
* Disclaimer:
* Note: This is ugly. I know it, I wrote it, but my whole
* focus was on getting the damn thing up and out quickly.
......@@ -49,6 +49,9 @@
*
* 1/7/95 Fix from Peter Lu (swift@world.std.com) for datalen vs. dataptr
* logic, much more stable under load.
*
* 1/19/95 (zerucha@shell.portal.com) Added module and biosparam support for
* larger SCSI hard drives (untested).
*/
#include <linux/kernel.h>
......@@ -684,5 +687,33 @@ int in2000_biosparam(Disk * disk, int dev, int* iinfo)
iinfo[0] = 64;
iinfo[1] = 32;
iinfo[2] = size >> 11;
/* This should approximate the large drive handling that the DOS ASPI manager
uses. Drives very near the boundaries may not be handled correctly (i.e.
near 2.0 Gb and 4.0 Gb) */
if (iinfo[2] > 1024) {
iinfo[0] = 64;
iinfo[1] = 63;
iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]);
}
if (iinfo[2] > 1024) {
iinfo[0] = 128;
iinfo[1] = 63;
iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]);
}
if (iinfo[2] > 1024) {
iinfo[0] = 255;
iinfo[1] = 63;
iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]);
if (iinfo[2] > 1023)
iinfo[2] = 1023;
}
return 0;
}
#ifdef MODULE
/* Eventually this will go into an include file, but this will be later */
Scsi_Host_Template driver_template = IN2000;
#include "scsi_module.c"
#endif
......@@ -14,7 +14,7 @@
Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994
(you can reference it, but it is incomplete and inaccurate in places)
Version 0.38a
Version 0.38b
This also works with loadable SCSI as a module. Check configuration
options QL_INT_ACTIVE_HIGH and QL_TURBO_PDMA for PCMCIA usage (which
......@@ -25,6 +25,9 @@
*/
/*----------------------------------------------------------------*/
/* Configuration */
/* Set this if you are using the PCMCIA adapter - it will automatically
take care of several settings */
#define QL_PCMCIA 0
/* Set the following to 2 to use normal interrupt (active high/totempole-
tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open
......@@ -69,6 +72,15 @@
cause the deassertion to be early by 1/2 clock. Bits 5&4 control
the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */
/* Option Synchronization */
#if QL_PCMCIA
#undef QL_INT_ACTIVE_HIGH
#undef QL_TURBO_PDMA
#define QL_INT_ACTIVE_HIGH 0
#define QL_TURBO_PDMA 0
#endif
/*----------------------------------------------------------------*/
#include "../block/blk.h" /* to get disk capacity */
......@@ -118,6 +130,8 @@ static void ql_zap(void);
void ql_zap()
{
int x;
unsigned long flags;
save_flags( flags );
cli();
x = inb(qbase + 0xd);
REG0;
......@@ -125,7 +139,7 @@ int x;
outb(2, qbase + 3); /* reset chip */
if (x & 0x80)
REG1;
sti();
restore_flags( flags );
}
/*----------------------------------------------------------------*/
......@@ -228,8 +242,11 @@ int i,k;
static void ql_icmd(Scsi_Cmnd * cmd)
{
unsigned int i;
unsigned long flags;
qabort = 0;
save_flags( flags );
cli();
REG0;
/* clearing of interrupts and the fifo is needed */
......@@ -274,7 +291,7 @@ unsigned int i;
outb(cmd->cmnd[i], qbase + 2);
qlcmd = cmd;
outb(0x41, qbase + 3); /* select and send command */
sti();
restore_flags( flags );
}
/*----------------------------------------------------------------*/
/* process scsi command - usually after interrupt */
......@@ -464,6 +481,7 @@ int qlogic_detect(Scsi_Host_Template * host)
int i, j; /* these are only used by IRQ detect */
int qltyp; /* type of chip */
struct Scsi_Host *hreg; /* registered host structure */
unsigned long flags;
/* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself decodes the
address - I check 230 first since MIDI cards are typically at 330
......@@ -479,8 +497,10 @@ struct Scsi_Host *hreg; /* registered host structure */
*/
for (qbase = 0x230; qbase < 0x430; qbase += 0x100) {
#ifndef PCMCIA
if( check_region( qbase , 0x10 ) )
continue;
#endif
REG1;
if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 )
&& ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) )
......@@ -506,6 +526,7 @@ struct Scsi_Host *hreg; /* registered host structure */
#endif
#if QL_USE_IRQ
/* IRQ probe - toggle pin and check request pending */
save_flags( flags );
cli();
i = 0xffff;
j = 3;
......@@ -525,17 +546,19 @@ struct Scsi_Host *hreg; /* registered host structure */
i >>= 1, qlirq++; /* should check for exactly 1 on */
if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, SA_INTERRUPT, "qlogic"))
host->can_queue = 1;
sti();
restore_flags( flags );
#endif
#ifndef PCMCIA
request_region( qbase , 0x10 ,"qlogic");
#endif
hreg = scsi_register( host , 0 ); /* no host data */
hreg->io_port = qbase;
hreg->n_io_port = 16;
if( qlirq != -1 )
hreg->irq = qlirq;
sprintf(qinfo, "Qlogic Driver version 0.38a, chip %02X at %03X, IRQ %d", qltyp, qbase, qlirq);
sprintf(qinfo, "Qlogic Driver version 0.38b, chip %02X at %03X, IRQ %d, Opts:%d%d",
qltyp, qbase, qlirq, QL_INT_ACTIVE_HIGH, QL_TURBO_PDMA );
host->name = qinfo;
return 1;
......
......@@ -93,7 +93,6 @@ static void ad1848_start_input (int dev, unsigned long buf, int count, int i
static int ad1848_prepare_for_IO (int dev, int bsize, int bcount);
static void ad1848_reset (int dev);
static void ad1848_halt (int dev);
void ad1848_interrupt (int dev, struct pt_regs * regs);
static int
ad_read (ad1848_info * devc, int reg)
......
......@@ -128,7 +128,7 @@ gusintr (int irq, struct pt_regs * regs)
#ifndef EXCLUDE_GUSMAX
if (have_gus_max)
ad1848_interrupt (irq);
ad1848_interrupt (irq, regs);
#endif
while (1)
......
......@@ -225,7 +225,7 @@ void sound_timer_interrupt(void);
/* From ad1848.c */
void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture);
int ad1848_detect (int io_base);
void ad1848_interrupt (int dev);
void ad1848_interrupt (int dev, struct pt_regs *regs);
long attach_ms_sound(long mem_start, struct address_info * hw_config);
int probe_ms_sound(struct address_info *hw_config);
......
......@@ -84,7 +84,7 @@ unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exe
mpnt->vm_task = current;
mpnt->vm_start = PAGE_MASK & (unsigned long) p;
mpnt->vm_end = TASK_SIZE;
mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY;
mpnt->vm_page_prot = PAGE_COPY;
#ifdef VM_STACK_FLAGS
mpnt->vm_flags = VM_STACK_FLAGS;
mpnt->vm_pte = 0;
......
......@@ -305,7 +305,7 @@ unsigned long * create_tables(char * p,int argc,int envc,int ibcs)
mpnt->vm_task = current;
mpnt->vm_start = PAGE_MASK & (unsigned long) p;
mpnt->vm_end = TASK_SIZE;
mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY;
mpnt->vm_page_prot = PAGE_COPY;
mpnt->vm_flags = VM_STACK_FLAGS;
mpnt->vm_ops = NULL;
mpnt->vm_offset = 0;
......
......@@ -88,7 +88,7 @@ struct vm_operations_struct msdos_file_mmap = {
*/
int msdos_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma)
{
if (vma->vm_page_prot & PAGE_RW) /* only PAGE_COW or read-only supported now */
if (vma->vm_flags & VM_SHARED) /* only PAGE_COW or read-only supported now */
return -EINVAL;
if (vma->vm_offset & (inode->i_sb->s_blocksize - 1))
return -EINVAL;
......@@ -105,3 +105,4 @@ int msdos_mmap(struct inode * inode, struct file * file, struct vm_area_struct *
return 0;
}
......@@ -33,13 +33,13 @@ static inline int get_max_filename(unsigned long address)
if (get_fs() == KERNEL_DS)
return 0;
vma = find_vma(current, address);
if (!vma || vma->vm_start > address || !(vma->vm_page_prot & PAGE_USER))
if (!vma || vma->vm_start > address || !(vma->vm_flags & VM_READ))
return -EFAULT;
address = vma->vm_end - address;
if (address > PAGE_SIZE)
return 0;
if (vma->vm_next && vma->vm_next->vm_start == vma->vm_end &&
(vma->vm_next->vm_page_prot & PAGE_USER))
(vma->vm_next->vm_flags & VM_READ))
return 0;
return address;
}
......
......@@ -92,7 +92,7 @@ struct vm_operations_struct nfs_file_mmap = {
/* This is used for a general mmap of a nfs file */
int nfs_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma)
{
if (vma->vm_page_prot & PAGE_RW) /* only PAGE_COW or read-only supported now */
if (vma->vm_flags & VM_SHARED) /* only PAGE_COW or read-only supported now */
return -EINVAL;
if (!inode->i_sb || !S_ISREG(inode->i_mode))
return -EACCES;
......
......@@ -334,21 +334,23 @@ static struct task_struct ** get_task(pid_t pid)
static unsigned long get_phys_addr(struct task_struct ** p, unsigned long ptr)
{
unsigned long page;
pgd_t *dir;
pte_t *table, pte;
if (!p || !*p || ptr >= TASK_SIZE)
return 0;
page = *PAGE_DIR_OFFSET(*p,ptr);
if (!(page & PAGE_PRESENT))
dir = PAGE_DIR_OFFSET(*p,ptr);
if (pgd_none(*dir))
return 0;
if (pgd_bad(*dir)) {
printk("bad page directory entry %08lx\n", pgd_val(*dir));
return 0;
page &= PAGE_MASK;
page += PAGE_PTR(ptr);
page = *(unsigned long *) page;
if (!(page & PAGE_PRESENT))
}
table = (pte_t *) (pgd_page(*dir) + PAGE_PTR(ptr));
pte = *table;
if (!pte_present(pte))
return 0;
page &= PAGE_MASK;
page += ptr & ~PAGE_MASK;
return page;
return pte_page(pte) + (ptr & ~PAGE_MASK);
}
static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer)
......@@ -511,9 +513,10 @@ static int get_stat(int pid, char * buffer)
static int get_statm(int pid, char * buffer)
{
struct task_struct ** p = get_task(pid);
int i, tpag;
pgd_t *pagedir;
pte_t *pte;
int i, j, tpag;
int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
unsigned long ptbl, *buf, *pte, *pagedir, map_nr;
if (!p || !*p)
return 0;
......@@ -521,15 +524,21 @@ static int get_statm(int pid, char * buffer)
if ((*p)->state != TASK_ZOMBIE) {
pagedir = PAGE_DIR_OFFSET(*p, 0);
for (i = 0; i < 0x300; ++i) {
if ((ptbl = pagedir[i]) == 0) {
if (pgd_none(pagedir[i])) {
tpag -= PTRS_PER_PAGE;
continue;
}
buf = (unsigned long *)(ptbl & PAGE_MASK);
for (pte = buf; pte < (buf + PTRS_PER_PAGE); ++pte) {
if (*pte != 0) {
if (pgd_bad(pagedir[i])) {
printk("bad page table dir %08lx\n", pgd_val(pagedir[i]));
pgd_clear(pagedir+i);
tpag -= PTRS_PER_PAGE;
continue;
}
pte = (pte_t *) pgd_page(pagedir[i]);
for (j = 0; j < PTRS_PER_PAGE; j++, pte++) {
if (!pte_none(*pte)) {
++size;
if (*pte & 1) {
if (pte_present(*pte)) {
++resident;
if (tpag > 0)
++trs;
......@@ -537,13 +546,12 @@ static int get_statm(int pid, char * buffer)
++drs;
if (i >= 15 && i < 0x2f0) {
++lrs;
if (*pte & 0x40)
if (pte_dirty(*pte))
++dt;
else
--drs;
}
map_nr = MAP_NR(*pte);
if (map_nr < (high_memory / PAGE_SIZE) && mem_map[map_nr] > 1)
if (pte_page(*pte) < high_memory && mem_map[MAP_NR(pte_page(*pte))] > 1)
++share;
}
}
......
......@@ -24,10 +24,12 @@
static int mem_read(struct inode * inode, struct file * file,char * buf, int count)
{
pgd_t *pgdir;
pte_t pte;
char * page;
struct task_struct * tsk;
unsigned long addr, pid;
char *tmp;
unsigned long pte, page;
int i;
if (count < 0)
......@@ -47,20 +49,22 @@ static int mem_read(struct inode * inode, struct file * file,char * buf, int cou
while (count > 0) {
if (current->signal & ~current->blocked)
break;
pte = *PAGE_DIR_OFFSET(tsk,addr);
if (!(pte & PAGE_PRESENT))
pgdir = PAGE_DIR_OFFSET(tsk,addr);
if (pgd_none(*pgdir))
break;
pte &= PAGE_MASK;
pte += PAGE_PTR(addr);
page = *(unsigned long *) pte;
if (!(page & 1))
if (pgd_bad(*pgdir)) {
printk("Bad page dir entry %08lx\n", pgd_val(*pgdir));
pgd_clear(pgdir);
break;
page &= PAGE_MASK;
page += addr & ~PAGE_MASK;
}
pte = *(pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir));
if (!pte_present(pte))
break;
page = (char *) pte_page(pte) + (addr & ~PAGE_MASK);
i = PAGE_SIZE-(addr & ~PAGE_MASK);
if (i > count)
i = count;
memcpy_tofs(tmp,(void *) page,i);
memcpy_tofs(tmp, page, i);
addr += i;
tmp += i;
count -= i;
......@@ -73,10 +77,12 @@ static int mem_read(struct inode * inode, struct file * file,char * buf, int cou
static int mem_write(struct inode * inode, struct file * file,char * buf, int count)
{
pgd_t * pgdir;
pte_t * pte;
char * page;
struct task_struct * tsk;
unsigned long addr, pid;
char *tmp;
unsigned long pte, page;
int i;
if (count < 0)
......@@ -96,24 +102,24 @@ static int mem_write(struct inode * inode, struct file * file,char * buf, int co
while (count > 0) {
if (current->signal & ~current->blocked)
break;
pte = *PAGE_DIR_OFFSET(tsk,addr);
if (!(pte & PAGE_PRESENT))
pgdir = PAGE_DIR_OFFSET(tsk,addr);
if (pgd_none(*pgdir))
break;
pte &= PAGE_MASK;
pte += PAGE_PTR(addr);
page = *(unsigned long *) pte;
if (!(page & PAGE_PRESENT))
if (pgd_bad(*pgdir)) {
printk("Bad page dir entry %08lx\n", pgd_val(*pgdir));
pgd_clear(pgdir);
break;
if (!(page & 2)) {
do_wp_page(0,addr,current,0);
continue;
}
page &= PAGE_MASK;
page += addr & ~PAGE_MASK;
pte = *(pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir));
if (!pte_present(pte))
break;
if (!pte_write(pte))
break;
page = (char *) pte_page(pte) + (addr & ~PAGE_MASK);
i = PAGE_SIZE-(addr & ~PAGE_MASK);
if (i > count)
i = count;
memcpy_fromfs((void *) page,tmp,i);
memcpy_fromfs(page, tmp, i);
addr += i;
tmp += i;
count -= i;
......@@ -142,93 +148,112 @@ static int mem_lseek(struct inode * inode, struct file * file, off_t offset, int
}
}
int
mem_mmap(struct inode * inode, struct file * file,
/*
* This isn't really reliable by any means..
*/
int mem_mmap(struct inode * inode, struct file * file,
struct vm_area_struct * vma)
{
struct task_struct *tsk;
unsigned long *src_table, *dest_table, stmp, dtmp;
struct vm_area_struct *src_vma = 0;
int i;
/* Get the source's task information */
tsk = NULL;
for (i = 1 ; i < NR_TASKS ; i++)
if (task[i] && task[i]->pid == (inode->i_ino >> 16)) {
tsk = task[i];
src_vma = task[i]->mm->mmap;
break;
}
if (!tsk)
return -EACCES;
/* Ensure that we have a valid source area. (Has to be mmap'ed and
have valid page information.) We can't map shared memory at the
moment because working out the vm_area_struct & nattach stuff isn't
worth it. */
stmp = vma->vm_offset;
while (stmp < vma->vm_offset + (vma->vm_end - vma->vm_start)) {
while (src_vma && stmp > src_vma->vm_end)
src_vma = src_vma->vm_next;
if (!src_vma || (src_vma->vm_flags & VM_SHM))
return -EINVAL;
src_table = PAGE_DIR_OFFSET(tsk, stmp);
if (!*src_table)
return -EINVAL;
src_table = (unsigned long *)((*src_table & PAGE_MASK) + PAGE_PTR(stmp));
if (!*src_table)
return -EINVAL;
if (stmp < src_vma->vm_start) {
if (!(src_vma->vm_flags & VM_GROWSDOWN))
return -EINVAL;
if (src_vma->vm_end - stmp > current->rlim[RLIMIT_STACK].rlim_cur)
return -EINVAL;
}
stmp += PAGE_SIZE;
}
src_vma = task[i]->mm->mmap;
stmp = vma->vm_offset;
dtmp = vma->vm_start;
while (dtmp < vma->vm_end) {
while (src_vma && stmp > src_vma->vm_end)
src_vma = src_vma->vm_next;
src_table = PAGE_DIR_OFFSET(tsk, stmp);
src_table = (unsigned long *)((*src_table & PAGE_MASK) + PAGE_PTR(stmp));
dest_table = PAGE_DIR_OFFSET(current, dtmp);
if (!*dest_table) {
*dest_table = get_free_page(GFP_KERNEL);
if (!*dest_table) { oom(current); *dest_table=BAD_PAGE; }
else *dest_table |= PAGE_TABLE;
}
dest_table = (unsigned long *)((*dest_table & PAGE_MASK) + PAGE_PTR(dtmp));
if (!(*src_table & PAGE_PRESENT))
do_no_page(src_vma, stmp, PAGE_PRESENT);
if ((vma->vm_flags & VM_WRITE) && !(*src_table & PAGE_RW))
do_wp_page(src_vma, stmp, PAGE_RW | PAGE_PRESENT);
*src_table |= PAGE_DIRTY;
*dest_table = *src_table;
mem_map[MAP_NR(*src_table)]++;
stmp += PAGE_SIZE;
dtmp += PAGE_SIZE;
}
invalidate();
return 0;
struct task_struct *tsk;
pgd_t *src_dir, *dest_dir;
pte_t *src_table, *dest_table;
unsigned long stmp, dtmp;
struct vm_area_struct *src_vma = NULL;
int i;
/* Get the source's task information */
tsk = NULL;
for (i = 1 ; i < NR_TASKS ; i++)
if (task[i] && task[i]->pid == (inode->i_ino >> 16)) {
tsk = task[i];
src_vma = task[i]->mm->mmap;
break;
}
if (!tsk)
return -EACCES;
/* Ensure that we have a valid source area. (Has to be mmap'ed and
have valid page information.) We can't map shared memory at the
moment because working out the vm_area_struct & nattach stuff isn't
worth it. */
stmp = vma->vm_offset;
while (stmp < vma->vm_offset + (vma->vm_end - vma->vm_start)) {
while (src_vma && stmp > src_vma->vm_end)
src_vma = src_vma->vm_next;
if (!src_vma || (src_vma->vm_flags & VM_SHM))
return -EINVAL;
src_dir = PAGE_DIR_OFFSET(tsk, stmp);
if (pgd_none(*src_dir))
return -EINVAL;
if (pgd_bad(*src_dir)) {
printk("Bad source page dir entry %08lx\n", pgd_val(*src_dir));
return -EINVAL;
}
src_table = (pte_t *)(pgd_page(*src_dir) + PAGE_PTR(stmp));
if (pte_none(*src_table))
return -EINVAL;
if (stmp < src_vma->vm_start) {
if (!(src_vma->vm_flags & VM_GROWSDOWN))
return -EINVAL;
if (src_vma->vm_end - stmp > current->rlim[RLIMIT_STACK].rlim_cur)
return -EINVAL;
}
stmp += PAGE_SIZE;
}
src_vma = task[i]->mm->mmap;
stmp = vma->vm_offset;
dtmp = vma->vm_start;
while (dtmp < vma->vm_end) {
while (src_vma && stmp > src_vma->vm_end)
src_vma = src_vma->vm_next;
src_dir = PAGE_DIR_OFFSET(tsk, stmp);
src_table = (pte_t *) (pgd_page(*src_dir) + PAGE_PTR(stmp));
dest_dir = PAGE_DIR_OFFSET(current, dtmp);
if (pgd_none(*dest_dir)) {
unsigned long page = get_free_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
if (pgd_none(*dest_dir)) {
pgd_set(dest_dir, (pte_t *) page);
} else {
free_page(page);
}
}
if (pgd_bad(*dest_dir)) {
printk("Bad dest directory entry %08lx\n", pgd_val(*dest_dir));
return -EINVAL;
}
dest_table = (pte_t *) (pgd_page(*dest_dir) + PAGE_PTR(dtmp));
if (!pte_present(*src_table))
do_no_page(src_vma, stmp, 1);
if ((vma->vm_flags & VM_WRITE) && !pte_write(*src_table))
do_wp_page(src_vma, stmp, 1);
*src_table = pte_mkdirty(*src_table);
*dest_table = *src_table;
mem_map[MAP_NR(pte_page(*src_table))]++;
stmp += PAGE_SIZE;
dtmp += PAGE_SIZE;
}
invalidate();
return 0;
}
static struct file_operations proc_mem_operations = {
......
......@@ -12,44 +12,35 @@
extern unsigned long high_memory;
static int check_one_table(unsigned long * page_dir)
static int check_one_table(struct pde * page_dir)
{
unsigned long pg_table = *page_dir;
if (!pg_table)
if (pgd_none(*page_dir))
return 0;
if (pg_table >= high_memory || !(pg_table & PAGE_PRESENT)) {
if (pgd_bad(*page_dir))
return 1;
}
return 0;
}
/*
* This function frees up all page tables of a process when it exits.
* This function checks all page tables of "current"
*/
void check_page_tables(void)
{
unsigned long pg_dir;
struct pgd * pg_dir;
static int err = 0;
int stack_level = (long)(&pg_dir)-current->kernel_stack_page;
if (stack_level < 1500) printk ("** %d ** ",stack_level);
pg_dir = current->tss.cr3;
if (mem_map[MAP_NR(pg_dir)] > 1) {
return;
}
if (err == 0){
unsigned long *page_dir = (unsigned long *) pg_dir;
unsigned long *base = page_dir;
pg_dir = PAGE_DIR_OFFSET(current, 0);
if (err == 0) {
int i;
for (i = 0 ; i < PTRS_PER_PAGE ; i++,page_dir++){
int notok = check_one_table(page_dir);
if (notok){
err++;
printk ("|%d| ",page_dir-base);
printk ("|%d:%08lx| ",i, page_dir->pgd);
}
}
if (err) printk ("Erreur MM %d\n",err);
if (err) printk ("\nErreur MM %d\n",err);
}
}
#ifndef _ALPHA_PAGE_H
#define _ALPHA_PAGE_H
#define CONFIG_STRICT_MM_TYPECHECKS
#define invalidate_all() \
__asm__ __volatile__( \
"lda $16,-2($31)\n\t" \
......@@ -19,29 +21,114 @@ __asm__ __volatile__( \
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#ifdef __KERNEL__
#define PAGE_OFFSET 0xFFFFFC0000000000
#define MAP_NR(addr) (((addr) - PAGE_OFFSET) >> PAGE_SHIFT)
#define MAP_PAGE_RESERVED (1<<31)
typedef unsigned int mem_map_t;
#define PAGE_PRESENT 0x001
#define PAGE_RW 0x002
#define PAGE_USER 0x004
#define PAGE_ACCESSED 0x020
#define PAGE_DIRTY 0x040
#define PAGE_COW 0x200 /* implemented in software (one of the AVL bits) */
#ifdef CONFIG_STRICT_MM_TYPECHECKS
/*
* These are used to make use of C type-checking..
*/
typedef struct { unsigned long pte; } pte_t;
typedef struct { unsigned long pgd; } pgd_t;
typedef struct { unsigned long pgprot; } pgprot_t;
#define pte_val(x) ((x).pte)
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot)
#define PAGE_PRIVATE (PAGE_PRESENT | PAGE_RW | PAGE_USER | PAGE_ACCESSED | PAGE_COW)
#define PAGE_SHARED (PAGE_PRESENT | PAGE_RW | PAGE_USER | PAGE_ACCESSED)
#define PAGE_COPY (PAGE_PRESENT | PAGE_USER | PAGE_ACCESSED | PAGE_COW)
#define PAGE_READONLY (PAGE_PRESENT | PAGE_USER | PAGE_ACCESSED)
#define PAGE_EXECONLY (PAGE_PRESENT | PAGE_USER | PAGE_ACCESSED)
#define PAGE_TABLE (PAGE_PRESENT | PAGE_RW | PAGE_USER | PAGE_ACCESSED)
#define __pte(x) ((pte_t) { (x) } )
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
#define PAGE_CHG_MASK (PAGE_MASK | PAGE_ACCESSED | PAGE_DIRTY)
#else
/*
* .. while these make it easier on the compiler
*/
typedef unsigned long pte_t;
typedef unsigned long pgd_t;
typedef unsigned long pgprot_t;
#ifdef __KERNEL__
#define pte_val(x) (x)
#define pgd_val(x) (x)
#define pgprot_val(x) (x)
#define __pte(x) (x)
#define __pgd(x) (x)
#define __pgprot(x) (x)
#endif
/*
* OSF/1 PAL-code-imposed page table bits
*/
#define _PAGE_VALID 0x0001
#define _PAGE_FOR 0x0002 /* used for page protection (fault on read) */
#define _PAGE_FOW 0x0004 /* used for page protection (fault on write) */
#define _PAGE_FOE 0x0008 /* used for page protection (fault on exec) */
#define _PAGE_ASM 0x0010
#define _PAGE_KRE 0x0100 /* xxx - see below on the "accessed" bit */
#define _PAGE_URE 0x0200 /* xxx */
#define _PAGE_KWE 0x1000 /* used to do the dirty bit in software */
#define _PAGE_UWE 0x2000 /* used to do the dirty bit in software */
/* .. and these are ours ... */
#define _PAGE_COW 0x10000
#define _PAGE_DIRTY 0x20000
#define _PAGE_ACCESSED 0x40000
/*
* NOTE! The "accessed" bit isn't necessarily exact: it can be kept exactly
* by software (use the KRE/URE/KWE/UWE bits appropritely), but I'll fake it.
* Under Linux/AXP, the "accessed" bit just means "read", and I'll just use
* the KRE/URE bits to watch for it. That way we don't need to overload the
* KWE/UWE bits with both handling dirty and accessed.
*
* Note that the kernel uses the accessed bit just to check whether to page
* out a page or not, so it doesn't have to be exact anyway.
*/
#define __DIRTY_BITS (_PAGE_DIRTY | _PAGE_KWE | _PAGE_UWE)
#define __ACCESS_BITS (_PAGE_ACCESSED | _PAGE_KRE | _PAGE_URE)
#define _PFN_MASK 0xFFFFFFFF00000000
#define _PAGE_TABLE (_PAGE_VALID | __DIRTY_BITS | __ACCESS_BITS)
#define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS)
/*
* All the normal masks have the "page accessed" bits on, as any time they are used,
* the page is accessed. They are cleared only by the page-out routines
*/
#define PAGE_NONE __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE)
#define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS)
#define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_COW)
#define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
#define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | __ACCESS_BITS | __DIRTY_BITS)
#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x))
#define __P000 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE)
#define __P001 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOW | _PAGE_FOE)
#define __P010 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOR | _PAGE_FOE)
#define __P011 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOE)
#define __P100 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOR | _PAGE_FOW)
#define __P101 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOW)
#define __P110 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOR)
#define __P111 _PAGE_NORMAL(_PAGE_COW)
#define __S000 _PAGE_NORMAL(_PAGE_FOR | _PAGE_FOW | _PAGE_FOE)
#define __S001 _PAGE_NORMAL(_PAGE_FOW | _PAGE_FOE)
#define __S010 _PAGE_NORMAL(_PAGE_FOR | _PAGE_FOE)
#define __S011 _PAGE_NORMAL(_PAGE_FOE)
#define __S100 _PAGE_NORMAL(_PAGE_FOR | _PAGE_FOW)
#define __S101 _PAGE_NORMAL(_PAGE_FOW)
#define __S110 _PAGE_NORMAL(_PAGE_FOR)
#define __S111 _PAGE_NORMAL(0)
/*
* BAD_PAGETABLE is used when we need a bogus page-table, while
......@@ -50,8 +137,9 @@ typedef unsigned int mem_map_t;
* ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc..
*/
extern unsigned long __bad_page(void);
extern unsigned long __bad_pagetable(void);
extern pte_t __bad_page(void);
extern pte_t * __bad_pagetable(void);
extern unsigned long __zero_page(void);
#define BAD_PAGETABLE __bad_pagetable()
......@@ -74,7 +162,6 @@ extern unsigned long __zero_page(void);
#define PTR_MASK (~(sizeof(void*)-1))
/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
/* 64-bit machines, beware! SRB. */
#define SIZEOF_PTR_LOG2 3
/* to find an entry in a page-table-directory */
......@@ -83,7 +170,7 @@ extern unsigned long __zero_page(void);
* This is just for getting it through the compiler right now
*/
#define PAGE_DIR_OFFSET(tsk,address) \
((unsigned long *) ((tsk)->tss.ptbr + ((((unsigned long)(address)) >> 21) & PTR_MASK & ~PAGE_MASK)))
((pgd_t *) ((tsk)->tss.ptbr + ((((unsigned long)(address)) >> 21) & PTR_MASK & ~PAGE_MASK)))
/* to find an entry in a page-table */
#define PAGE_PTR(address) \
......@@ -104,6 +191,57 @@ do { \
invalidate(); \
} while (0)
extern unsigned long high_memory;
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
*/
extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
{ pte_t pte; pte_val(pte) = (page << (32-PAGE_SHIFT)) | pgprot_val(pgprot); return pte; }
extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
extern inline void pgd_set(pgd_t * pgdp, pte_t * ptep)
{ pgd_val(*pgdp) = _PAGE_TABLE | (((unsigned long) ptep) << (32-PAGE_SHIFT)); }
extern inline unsigned long pte_page(pte_t pte) { return (pte_val(pte) & _PFN_MASK) >> (32-PAGE_SHIFT); }
extern inline unsigned long pgd_page(pgd_t pgd) { return (pgd_val(pgd) & _PFN_MASK) >> (32-PAGE_SHIFT); }
extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_VALID; }
extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; }
extern inline int pgd_none(pgd_t pgd) { return !pgd_val(pgd); }
extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~_PFN_MASK) != _PAGE_TABLE || pgd_page(pgd) > high_memory; }
extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_VALID; }
extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; }
/*
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
extern inline int pte_read(pte_t pte) { return !(pte_val(pte) & _PAGE_FOR); }
extern inline int pte_write(pte_t pte) { return !(pte_val(pte) & _PAGE_FOW); }
extern inline int pte_exec(pte_t pte) { return !(pte_val(pte) & _PAGE_FOE); }
extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
extern inline int pte_cow(pte_t pte) { return pte_val(pte) & _PAGE_COW; }
extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOW; return pte; }
extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOR; return pte; }
extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOE; return pte; }
extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~(__DIRTY_BITS); return pte; }
extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~(__ACCESS_BITS); return pte; }
extern inline pte_t pte_uncow(pte_t pte) { pte_val(pte) &= ~_PAGE_COW; return pte; }
extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= _PAGE_FOW; return pte; }
extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) &= _PAGE_FOR; return pte; }
extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) &= _PAGE_FOE; return pte; }
extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= __DIRTY_BITS; return pte; }
extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= __ACCESS_BITS; return pte; }
extern inline pte_t pte_mkcow(pte_t pte) { pte_val(pte) |= _PAGE_COW; return pte; }
#endif /* __KERNEL__ */
#endif /* _ALPHA_PAGE_H */
#ifndef _I386_PAGE_H
#define _I386_PAGE_H
#define CONFIG_STRICT_MM_TYPECHECKS
#define invalidate() \
__asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax")
/* PAGE_SHIFT determines the page size */
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
#define PGDIR_SHIFT 22
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#ifdef __KERNEL__
#define PAGE_OFFSET 0
#define MAP_NR(addr) ((addr) >> PAGE_SHIFT)
#define MAP_PAGE_RESERVED (1<<15)
typedef unsigned short mem_map_t;
#define PAGE_PRESENT 0x001
#define PAGE_RW 0x002
#define PAGE_USER 0x004
#define PAGE_PWT 0x008 /* 486 only - not used currently */
#define PAGE_PCD 0x010 /* 486 only - not used currently */
#define PAGE_ACCESSED 0x020
#define PAGE_DIRTY 0x040
#define PAGE_COW 0x200 /* implemented in software (one of the AVL bits) */
#ifdef CONFIG_STRICT_MM_TYPECHECKS
/*
* These are used to make use of C type-checking..
*/
typedef struct { unsigned long pte; } pte_t;
typedef struct { unsigned long pgd; } pgd_t;
typedef struct { unsigned long pgprot; } pgprot_t;
#define PAGE_PRIVATE (PAGE_PRESENT | PAGE_RW | PAGE_USER | PAGE_ACCESSED | PAGE_COW)
#define PAGE_SHARED (PAGE_PRESENT | PAGE_RW | PAGE_USER | PAGE_ACCESSED)
#define PAGE_COPY (PAGE_PRESENT | PAGE_USER | PAGE_ACCESSED | PAGE_COW)
#define PAGE_READONLY (PAGE_PRESENT | PAGE_USER | PAGE_ACCESSED)
#define PAGE_EXECONLY (PAGE_PRESENT | PAGE_USER | PAGE_ACCESSED)
#define PAGE_TABLE (PAGE_PRESENT | PAGE_RW | PAGE_USER | PAGE_ACCESSED)
#define pte_val(x) ((x).pte)
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot)
#define PAGE_CHG_MASK (PAGE_MASK | PAGE_ACCESSED | PAGE_DIRTY | PAGE_PWT | PAGE_PCD)
#define __pte(x) ((pte_t) { (x) } )
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
#ifdef __KERNEL__
#else
/*
* .. while these make it easier on the compiler
*/
typedef unsigned long pte_t;
typedef unsigned long pgd_t;
typedef unsigned long pgprot_t;
#define pte_val(x) (x)
#define pgd_val(x) (x)
#define pgprot_val(x) (x)
#define __pte(x) (x)
#define __pgd(x) (x)
#define __pgprot(x) (x)
#endif
#define _PAGE_PRESENT 0x001
#define _PAGE_RW 0x002
#define _PAGE_USER 0x004
#define _PAGE_ACCESSED 0x020
#define _PAGE_DIRTY 0x040
#define _PAGE_COW 0x200 /* implemented in software (one of the AVL bits) */
#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_COW)
#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
/*
* The i386 can't do page protection for execute, and considers that the same are read.
* Also, write permissions imply read permissions. This is the closest we can get..
*/
#define __P000 PAGE_NONE
#define __P001 PAGE_READONLY
#define __P010 PAGE_COPY
#define __P011 PAGE_COPY
#define __P100 PAGE_READONLY
#define __P101 PAGE_READONLY
#define __P110 PAGE_COPY
#define __P111 PAGE_COPY
#define __S000 PAGE_NONE
#define __S001 PAGE_READONLY
#define __S010 PAGE_SHARED
#define __S011 PAGE_SHARED
#define __S100 PAGE_READONLY
#define __S101 PAGE_READONLY
#define __S110 PAGE_SHARED
#define __S111 PAGE_SHARED
/*
* Define this if things work differently on a i386 and a i486:
......@@ -53,8 +109,9 @@ extern unsigned long pg0[1024];
* ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc..
*/
extern unsigned long __bad_page(void);
extern unsigned long __bad_pagetable(void);
extern pte_t __bad_page(void);
extern pte_t * __bad_pagetable(void);
extern unsigned long __zero_page(void);
#define BAD_PAGETABLE __bad_pagetable()
......@@ -82,10 +139,10 @@ extern unsigned long __zero_page(void);
/* to find an entry in a page-table-directory */
#define PAGE_DIR_OFFSET(tsk,address) \
((((unsigned long)(address)) >> 22) + (unsigned long *) (tsk)->tss.cr3)
((((unsigned long)(address)) >> 22) + (pgd_t *) (tsk)->tss.cr3)
/* to find an entry in a page-table */
#define PAGE_PTR(address) \
#define PAGE_PTR(address) \
((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
/* the no. of pointers that fit on a page */
......@@ -99,6 +156,57 @@ do { \
__asm__ __volatile__("movl %0,%%cr3": :"a" ((tsk)->tss.cr3)); \
} while (0)
extern unsigned long high_memory;
extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; }
extern inline int pgd_none(pgd_t pgd) { return !pgd_val(pgd); }
extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~PAGE_MASK) != _PAGE_TABLE || pgd_val(pgd) > high_memory; }
extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_PRESENT; }
extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; }
/*
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
extern inline int pte_cow(pte_t pte) { return pte_val(pte) & _PAGE_COW; }
extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_RW; return pte; }
extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; }
extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; }
extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
extern inline pte_t pte_uncow(pte_t pte) { pte_val(pte) &= ~_PAGE_COW; return pte; }
extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; }
extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; }
extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; }
extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
extern inline pte_t pte_mkcow(pte_t pte) { pte_val(pte) |= _PAGE_COW; return pte; }
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
*/
extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; }
extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
extern inline unsigned long pte_page(pte_t pte) { return pte_val(pte) & PAGE_MASK; }
extern inline unsigned long pgd_page(pgd_t pgd) { return pgd_val(pgd) & PAGE_MASK; }
extern inline void pgd_set(pgd_t * pgdp, pte_t * ptep)
{ pgd_val(*pgdp) = _PAGE_TABLE | (unsigned long) ptep; }
#endif /* __KERNEL__ */
#endif /* _I386_PAGE_H */
/* $Id$
/* $Id: aztcd.h,v 0.80 1995/01/21 19:55:04 root Exp $
* Definitions for a AztechCD268 CD-ROM interface
* Copyright (C) 1994, 1995 Werner Zimmermann
*
......@@ -20,12 +20,14 @@
*
* History: W.Zimmermann adaption to Aztech CD268-01A Version 1.3
* Oktober 1994 Email: zimmerma@rz.fht-esslingen.de
* Note: Points marked with ??? are questionable !
*/
/* *** change this to set the I/O port address */
#define AZT_BASE_ADDR 0x320
/* use incompatible ioctls for reading in raw and cooked mode */
#define AZT_PRIVATE_IOCTLS
/* Increase this if you get lots of timeouts; if you get kernel panic, replace
STEN_LOW_WAIT by STEN_LOW in the source code */
#define AZT_STATUS_DELAY 400 /*for timer wait, STEN_LOW_WAIT*/
......@@ -35,17 +37,6 @@
/* number of times to retry a command before giving up */
#define AZT_RETRY_ATTEMPTS 3
/*defines for compatibility with mcd.c/mcd.h for Mitsumi drive, will probably
go away, when the AZTECH driver is integrated in the standard Linux kernel*/
#ifdef CONFIG_AZTCD
#else
#define AZTCD_TIMER MCD_TIMER
#define aztcd_init mcd_init
#define do_aztcd_request do_mcd_request
#define aztcd_setup mcd_setup
#define check_aztcd_media_change check_mcd_media_change
#endif
/* port access macros */
#define CMD_PORT azt_port
#define DATA_PORT azt_port
......@@ -87,13 +78,12 @@
#define ACMD_SET_MODE 0xA1 /* set drive mode */
#define ACMD_SET_VOLUME 0xAE /* set audio level */
/* borrowed from hd.c */
#define SET_TIMER(func, jifs) \
((timer_table[AZTCD_TIMER].expires = jiffies + jifs), \
(timer_table[AZTCD_TIMER].fn = func), \
(timer_active |= 1<<AZTCD_TIMER))
delay_timer.expires = jifs; \
delay_timer.function = (void *) func; \
add_timer(&delay_timer);
#define CLEAR_TIMER timer_active &= ~(1<<AZTCD_TIMER)
#define CLEAR_TIMER del_timer(&delay_timer)
#define MAX_TRACKS 104
......
......@@ -5,7 +5,6 @@ typedef struct desc_struct {
unsigned long a,b;
} desc_table[256];
extern unsigned long swapper_pg_dir[1024];
extern desc_table idt,gdt;
#define GDT_NUL 0
......
#ifndef _LINUX_MM_H
#define _LINUX_MM_H
extern unsigned long high_memory;
#include <asm/page.h>
#include <linux/sched.h>
......@@ -11,6 +13,8 @@
#define VERIFY_READ 0
#define VERIFY_WRITE 1
extern pgd_t swapper_pg_dir[1024];
extern int verify_area(int, const void *, unsigned long);
/*
......@@ -32,14 +36,14 @@ struct vm_area_struct {
struct task_struct * vm_task; /* VM area parameters */
unsigned long vm_start;
unsigned long vm_end;
unsigned short vm_page_prot;
pgprot_t vm_page_prot;
unsigned short vm_flags;
/* linked list of VM areas per task, sorted by address */
struct vm_area_struct * vm_next;
/* AVL tree of VM areas per task, sorted by address */
short vm_avl_height;
struct vm_area_struct * vm_avl_left;
struct vm_area_struct * vm_avl_right;
short vm_avl_height;
/* linked list of VM areas per task, sorted by address */
struct vm_area_struct * vm_next;
/* for areas with inode, the circular list inode->i_mmap */
/* for shm areas, the circular list of attaches */
/* otherwise unused */
......@@ -74,6 +78,13 @@ struct vm_area_struct {
#define VM_STACK_FLAGS 0x0177
/*
* mapping from the currently active vm_flags protection bits (the
* low four bits) to a page protection mask..
*/
extern pgprot_t protection_map[16];
/*
* These are the virtual MM functions - opening of an area, closing and
* unmapping it (needed to keep files on disk up-to-date etc), pointer
......@@ -90,8 +101,8 @@ struct vm_operations_struct {
unsigned long page, int write_access);
unsigned long (*wppage)(struct vm_area_struct * area, unsigned long address,
unsigned long page);
void (*swapout)(struct vm_area_struct *, unsigned long, unsigned long *);
unsigned long (*swapin)(struct vm_area_struct *, unsigned long, unsigned long);
void (*swapout)(struct vm_area_struct *, unsigned long, pte_t *);
pte_t (*swapin)(struct vm_area_struct *, unsigned long, unsigned long);
};
extern mem_map_t * mem_map;
......@@ -167,8 +178,8 @@ extern void clear_page_tables(struct task_struct * tsk);
extern int copy_page_tables(struct task_struct * to);
extern int clone_page_tables(struct task_struct * to);
extern int unmap_page_range(unsigned long from, unsigned long size);
extern int remap_page_range(unsigned long from, unsigned long to, unsigned long size, int mask);
extern int zeromap_page_range(unsigned long from, unsigned long size, int mask);
extern int remap_page_range(unsigned long from, unsigned long to, unsigned long size, pgprot_t prot);
extern int zeromap_page_range(unsigned long from, unsigned long size, pgprot_t prot);
extern void do_wp_page(struct vm_area_struct * vma, unsigned long address, int write_access);
extern void do_no_page(struct vm_area_struct * vma, unsigned long address, int write_access);
......@@ -187,9 +198,10 @@ extern int vread(char *buf, char *addr, int count);
/* swap.c */
extern void swap_free(unsigned long page_nr);
extern unsigned long swap_duplicate(unsigned long page_nr);
extern unsigned long swap_in(unsigned long entry);
extern void swap_free(unsigned long);
extern void swap_duplicate(unsigned long);
extern void swap_in(struct vm_area_struct *, pte_t *, unsigned long id, int write_access);
extern void si_swapinfo(struct sysinfo * val);
extern void rw_swap_page(int rw, unsigned long nr, char * buf);
......@@ -211,8 +223,6 @@ extern unsigned long get_unmapped_area(unsigned long);
#define write_swap_page(nr,buf) \
rw_swap_page(WRITE,(nr),(buf))
extern unsigned long high_memory;
#define GFP_BUFFER 0x00
#define GFP_ATOMIC 0x01
#define GFP_USER 0x02
......@@ -276,7 +286,7 @@ extern inline int delete_from_swap_cache(unsigned long addr)
#ifdef SWAP_CACHE_INFO
swap_cache_del_total++;
#endif
entry = (unsigned long) xchg_ptr(swap_cache + MAP_NR(addr), NULL);
entry= (unsigned long) xchg_ptr(swap_cache + MAP_NR(addr), NULL);
if (entry) {
#ifdef SWAP_CACHE_INFO
swap_cache_del_success++;
......
......@@ -25,7 +25,7 @@
/* Configuration method #1 */
#define PCI_CONFIG1_ADDRESS_REG 0xcf8
#define PCI_CONFIG1_ENABLE 0x80000000
#define PCI_CONFIG1_TUPPLE (bus, device, function, register) \
#define PCI_CONFIG1_TUPPLE(bus, device, function, register) \
(PCI_CONFIG1_ENABLE | ((bus) << 16) & 0xff0000 | \
((device) << 11) & 0xf800 | ((function) << 8) & 0x700 | \
((register) << 2) & 0xfc)
......@@ -34,7 +34,7 @@
/* Configuration method #2, deprecated */
#define PCI_CONFIG2_ENABLE_REG 0xcf8
#define PCI_CONFIG2_ENABLE 0xf0
#define PCI_CONFIG2_TUPPLE (function) \
#define PCI_CONFIG2_TUPPLE(function) \
(PCI_CONFIG2_ENABLE | ((function) << 1) & 0xe)
#define PCI_CONFIG2_FORWARD_REG 0xcfa
......@@ -208,7 +208,8 @@ struct pci_class_type {
#define PCI_DEVICE_ID_S3_864_1 0x88c0
#define PCI_DEVICE_ID_S3_864_2 0x88c1
#define PCI_DEVICE_ID_S3_928 0x88b0
#define PCI_DEVICE_ID_S3_964 0x88d0
#define PCI_DEVICE_ID_S3_964_1 0x88d0
#define PCI_DEVICE_ID_S3_964_2 0x88d1
#define PCI_DEVICE_ID_S3_811 0x8811
#define PCI_VENDOR_ID_OPTI 0x1045
......@@ -257,12 +258,17 @@ struct pci_class_type {
#define PCI_VENDOR_ID_N9 0x105D
#define PCI_DEVICE_ID_N9_I128 0x2309
#define PCI_VENDOR_ID_ALI 0x1025
#define PCI_DEVICE_ID_ALI_M1435 0x1435
#define PCI_VENDOR_ID_AI 0x1025
#define PCI_DEVICE_ID_AI_M1435 0x1435
#define PCI_VENDOR_ID_AL 0x10b9
#define PCI_DEVICE_ID_AL_M1449 0x4449
#define PCI_DEVICE_ID_AL_M1451 0x1451
#define PCI_VENDOR_ID_TSENG 0x100c
#define PCI_DEVICE_ID_TSENG_W32P_2 0x3202
#define PCI_DEVICE_ID_TSENG_W32P_5 0x3205
#define PCI_DEVICE_ID_TSENG_W32P_b 0x3205
#define PCI_DEVICE_ID_TSENG_W32P_a 0x3207
#define PCI_VENDOR_ID_CMD 0x1095
#define PCI_DEVICE_ID_CMD_640 0x0640
......@@ -276,8 +282,8 @@ struct pci_class_type {
#define PCI_VENDOR_ID_VLSI 0x1004
#define PCI_DEVICE_ID_VLSI_82C593 0x0006
#define PCI_VENDOR_ID_AL 0x1005
#define PCI_DEVICE_ID_AL_2301 0x2301
#define PCI_VENDOR_ID_ADL 0x1005
#define PCI_DEVICE_ID_ADL_2301 0x2301
#define PCI_VENDOR_ID_SYMPHONY 0x1c1c
#define PCI_DEVICE_ID_SYMPHONY_101 0x0001
......@@ -285,13 +291,18 @@ struct pci_class_type {
#define PCI_VENDOR_ID_TRIDENT 0x1023
#define PCI_DEVICE_ID_TRIDENT_9420 0x9420
#define PCI_VENDOR_ID_CONTAQ 0x1023
#define PCI_DEVICE_ID_CONTAQ_82C599 0x0600
#define PCI_VENDOR_ID_NS 0x100b
struct pci_vendor_type {
unsigned short vendor_id;
char *vendor_name;
};
#define PCI_VENDOR_NUM 24
#define PCI_VENDOR_NUM 27
#define PCI_VENDOR_TYPE { \
{PCI_VENDOR_ID_NCR, "NCR"}, \
{PCI_VENDOR_ID_ADAPTEC, "Adaptec"}, \
......@@ -307,16 +318,19 @@ struct pci_vendor_type {
{PCI_VENDOR_ID_WEITEK, "Weitek"}, \
{PCI_VENDOR_ID_CIRRUS, "Cirrus Logic"}, \
{PCI_VENDOR_ID_BUSLOGIC, "Bus Logic"}, \
{PCI_VENDOR_ID_N9, "Number #9"}, \
{PCI_VENDOR_ID_ALI, "ALI"}, \
{PCI_VENDOR_ID_N9, "Number Nine"}, \
{PCI_VENDOR_ID_AI, "Acer Incorporated"}, \
{PCI_VENDOR_ID_AL, "Acer Labs"}, \
{PCI_VENDOR_ID_TSENG, "Tseng'Lab"}, \
{PCI_VENDOR_ID_CMD, "CMD"}, \
{PCI_VENDOR_ID_VISION, "Vision"}, \
{PCI_VENDOR_ID_AMD, "AMD"}, \
{PCI_VENDOR_ID_VLSI, "VLSI"}, \
{PCI_VENDOR_ID_AL, "Advance Logic"}, \
{PCI_VENDOR_ID_ADL, "Advance Logic"}, \
{PCI_VENDOR_ID_SYMPHONY, "Symphony"}, \
{PCI_VENDOR_ID_TRIDENT, "Trident"} \
{PCI_VENDOR_ID_TRIDENT, "Trident"}, \
{PCI_VENDOR_ID_CONTAQ, "Contaq"}, \
{PCI_VENDOR_ID_NS, "NS"} \
}
......@@ -335,7 +349,7 @@ struct pci_device_type {
char *device_name;
};
#define PCI_DEVICE_NUM 45
#define PCI_DEVICE_NUM 50
#define PCI_DEVICE_TYPE { \
{0xff, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, "53c810"}, \
{0xff, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C815, "53c815"}, \
......@@ -346,8 +360,9 @@ struct pci_device_type {
{0xff, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_864_1, "Vision 864-P"}, \
{0xff, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_864_2, "Vision 864-P"}, \
{0xff, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_928, "Vision 928-P"}, \
{0xff, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_964, "Vision 964-P"}, \
{0xff, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_811, "Trio64"}, \
{0xff, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_964_1, "Vision 964-P"}, \
{0xff, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_964_2, "Vision 964-P"}, \
{0xff, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_811, "Trio32/Trio64"}, \
{0x02, PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C822, "82C822"}, \
{0xff, PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, "82C621"}, \
{0xff, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8881F, "UM8881F"}, \
......@@ -372,16 +387,20 @@ struct pci_device_type {
{0xff, PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729, "CL 6729"}, \
{0xff, PCI_VENDOR_ID_BUSLOGIC,PCI_DEVICE_ID_BUSLOGIC_946C, "946C"}, \
{0xff, PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128, "Imagine 128"}, \
{0xff, PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_M1435, "M1435"}, \
{0xff, PCI_VENDOR_ID_AI, PCI_DEVICE_ID_AI_M1435, "M1435"}, \
{0xff, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1449, "M1449"}, \
{0xff, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1451, "M1451"}, \
{0xff, PCI_VENDOR_ID_TSENG, PCI_DEVICE_ID_TSENG_W32P_2, "ET4000W32P"}, \
{0xff, PCI_VENDOR_ID_TSENG, PCI_DEVICE_ID_TSENG_W32P_5, "ET4000W32P"}, \
{0xff, PCI_VENDOR_ID_TSENG, PCI_DEVICE_ID_TSENG_W32P_b, "ET4000W32P rev B"}, \
{0xff, PCI_VENDOR_ID_TSENG, PCI_DEVICE_ID_TSENG_W32P_a, "ET4000W32P rev A"}, \
{0xff, PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640, "640A"}, \
{0xff, PCI_VENDOR_ID_VISION, PCI_DEVICE_ID_VISION_QD8500, "QD-8500PCI"}, \
{0xff, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, "79C970"}, \
{0xff, PCI_VENDOR_ID_VLSI, PCI_DEVICE_ID_VLSI_82C593, "82C593-FC1"}, \
{0xff, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_2301, "2301"}, \
{0xff, PCI_VENDOR_ID_ADL, PCI_DEVICE_ID_ADL_2301, "2301"}, \
{0xff, PCI_VENDOR_ID_SYMPHONY, PCI_DEVICE_ID_SYMPHONY_101, "82C101"}, \
{0xff, PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_9420, "TG 9420"} \
{0xff, PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_9420, "TG 9420"}, \
{0xff, PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C599, "82C599"} \
}
/* An item of this structure has the following meaning */
......
......@@ -123,7 +123,7 @@ struct mm_struct {
struct vm_area_struct * mmap_avl;
};
#define INIT_MMAP { &init_task, 0, 0x40000000, PAGE_SHARED, }
#define INIT_MMAP { &init_task, 0, 0x40000000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC }
#define INIT_MM { \
0, \
......
......@@ -31,7 +31,6 @@
*
* MCD_TIMER Mitsumi CD-ROM Timer
*
* AZTCD_TIMER Aztech CD-ROM Timer
*/
#define BLANK_TIMER 0
......@@ -49,7 +48,6 @@
#define MCD_TIMER 23
#define HD_TIMER2 24
#define AZTCD_TIMER 25
struct timer_struct {
unsigned long expires;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment