aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@klaava.Helsinki.FI>1992-12-02 21:24:46 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:10 -0400
commit3412f7ea7c0414a6191cf5b5d474e8a7f6137fc5 (patch)
treeb61b0be7582787bed7155005e1e27102104b17df
parentcbfd22851e4393ec3b1c9975f522fb3e01b204cf (diff)
downloadarchive-3412f7ea7c0414a6191cf5b5d474e8a7f6137fc5.tar.gz
ANNOUNCE: linux-0.98 patchlevel 6v0.98-pl6
You all know what the above subject-line means by now... Currently only the full sources to 0.98pl6 are available (at nic.funet.fi in the directory pub/OS/Linux/PEOPLE/Linus), but I'll probably make context-diffs later today. It depends a bit on the size of the diffs: the changes in pl6 aren't very suitable for diffing (renaming of some SCSI files etc). Anyway, 0.98pl6 is hopefully the last release before 0.99: there are a few known problems left in this release. Most notable is the serial code: it works for most people, but others still have problems with it. I hope this will get fixed within a week (tytso is working on it). It also seems as if the PS/2 mouse code has some problems. pl6 contains these fixes: - all the tcp/ip patches I've received (and I fixed one bug that gcc-2.3 seems to have found). - math-emu patch for the problem that resulted in FPU errors with some operations. - I fixed gcc-2.3 warnings as well as most of the old warnings. You shouldn't get more than one or two warnings when recompiling the whole kernel. - /proc filesystem extensions. Based on ideas (and some code) by Darren Senn, but mostly written by yours truly. More about that later. - some tty_io fixes (there was a bug in the /dev/console handling when you changed VC's while using the general console device). - re-organization of the keyboard-driver internal data-structures. The changes are mostly preliminary: they change the keyboard flags to be more easily adaptive to a reprogrammable keyboard driver. No actual new features yet. - new SCSI drivers: reportedly much faster than the old ones (but not all drivers take advantage of it yet..) - various other fixes: pty's etc have minor changes. I hope to make 0.99 in a week or so, and 1.0 after that has been tested some. I hope people will test out pl6 - 0.99 won't be much different, and if you don't test pl6, any bugs relating to your particular hardware may not be found in time for 0.99... Linus ===== /proc filesystem comments, ignore if not interested ===== If people want to test out the new /proc filesystem features, please do # mount -t proc /proc /proc (or add the line "/proc /proc proc defaults 0 0" to your /etc/mtab). You obviously need a /proc subdirectory for the above. After mounting the proc fs, your /proc should look something like this: # ls -l /proc .... dr-xr-xr-x 4 root root 0 Dec 2 22:55 936 dr-xr-xr-x 4 root root 0 Dec 2 22:55 983 -r--r--r-- 1 root root 0 Dec 2 22:55 loadavg -r--r--r-- 1 root root 0 Dec 2 22:55 meminfo -r--r--r-- 1 root root 0 Dec 2 22:55 uptime The numeric entries correspond with the pid's of the running procedures, while the alphabetic entries are vaious general info-files (don't be fooled by the zero length). # cat /proc/meminfo total: used: free: shared: buffers: Mem: 15831040 15601664 229376 3952640 8904704 Swap: 5521408 0 5521408 # cat /proc/loadavg 0.01 0.02 0.00 # cat /proc/uptime 12981 The info should be pretty self-evident (uptime is in seconds, and yes, I reboot pretty often). For each <pid> in the system, the per-process directory looks like this: # ls -l /proc/50/ total 3 -r--r--r-- 1 root root 0 Dec 2 23:00 cmdline lrwx------ 1 root root 3 Dec 2 23:00 cwd -> --- -r--r--r-- 1 root root 0 Dec 2 23:00 environ lrwx------ 1 root root 3 Dec 2 23:00 exe -> --- dr-x------ 2 root root 0 Dec 2 23:00 fd dr-x------ 2 root root 0 Dec 2 23:00 lib crw------- 1 root root 1, 1 Dec 2 23:00 mem lrwx------ 1 root root 3 Dec 2 23:00 root -> --- -r--r--r-- 1 root root 0 Dec 2 23:00 stat The most interesting entries are probably the new ones: cmdline, environ and stat. They give the process command-line, environment and some statistics respectively. The file protections will probably have to be changed. # cat /proc/50/cmdline | tr '\000' ' ' && echo X :0 -pn # cat /proc/50/environ | tr '\000' ' ' && echo SHELL=/bin/sh SHLVL=2 BASH=/bin/sh MAIL=/var/spool/mail/root HOME=/usr/root PATH=/bin:/usr/bin:/etc:/usr/local/bin:/usr/bin/X11 LOGNAME=root LESS=-MM TERM=console ignoreeof=10 HOSTTYPE=i386 DISPLAY=:0 _=/usr/bin/X11/xinit The 'tr' and 'echo' commands are there to make it look a bit nicer: the command line arguments and environment variables are separated by '\0' characters and aren't terminated by a newline. Note that the /proc filesystem doesn't try to fetch command line data that is swapped out, so when you are swapping, one or both of the above may be empty or truncated. Also, the code I wrote to fetch the above may nor be complete yet, and doesn't seem to be able to find all of the cmdline all of the time.. Finally there is the (not completely implemented) process status file: # cat /proc/50/stat 50 (X) R 49 50 10 1 This currently gives the pid, short name ("X", max 8 chars, but you get it even when the process is swapped out), the state (R for running etc), ppid (49), pgrp (50), session (10) and controlling terminal (1 - /dev/tty1). The status file will have to be extended to tell you more about the process, but that should be easy now that the general code is there..
-rw-r--r--Makefile27
-rw-r--r--boot/bootsect.S12
-rw-r--r--boot/setup.S2
-rw-r--r--fs/Makefile196
-rw-r--r--fs/block_dev.c159
-rw-r--r--fs/buffer.c18
-rw-r--r--fs/exec.c6
-rw-r--r--fs/ext/Makefile114
-rw-r--r--fs/ext/dir.c20
-rw-r--r--fs/ext/file.c139
-rw-r--r--fs/ext/freelists.c9
-rw-r--r--fs/ext/namei.c39
-rw-r--r--fs/fifo.c1
-rw-r--r--fs/filesystems.c6
-rw-r--r--fs/isofs/Makefile117
-rw-r--r--fs/isofs/blkdev.c67
-rw-r--r--fs/isofs/chrdev.c68
-rw-r--r--fs/isofs/dir.c225
-rw-r--r--fs/isofs/file.c269
-rw-r--r--fs/isofs/inode.c579
-rw-r--r--fs/isofs/namei.c248
-rw-r--r--fs/isofs/rock.c463
-rw-r--r--fs/isofs/rock.h111
-rw-r--r--fs/isofs/symlink.c108
-rw-r--r--fs/isofs/util.c137
-rw-r--r--fs/minix/Makefile112
-rw-r--r--fs/minix/bitmap.c13
-rw-r--r--fs/minix/dir.c2
-rw-r--r--fs/minix/file.c139
-rw-r--r--fs/minix/inode.c4
-rw-r--r--fs/minix/namei.c15
-rw-r--r--fs/msdos/Makefile71
-rw-r--r--fs/msdos/dir.c18
-rw-r--r--fs/msdos/fat.c2
-rw-r--r--fs/msdos/file.c2
-rw-r--r--fs/msdos/inode.c9
-rw-r--r--fs/msdos/misc.c4
-rw-r--r--fs/msdos/namei.c7
-rw-r--r--fs/namei.c6
-rw-r--r--fs/open.c11
-rw-r--r--fs/proc/Makefile80
-rw-r--r--fs/proc/array.c244
-rw-r--r--fs/proc/base.c13
-rw-r--r--fs/proc/inode.c23
-rw-r--r--fs/proc/root.c132
-rw-r--r--fs/select.c15
-rw-r--r--fs/super.c10
-rw-r--r--include/asm/dma.h218
-rw-r--r--include/asm/io.h8
-rw-r--r--include/asm/irq.h5
-rw-r--r--include/asm/segment.h2
-rw-r--r--include/linux/config.dist.h2
-rw-r--r--include/linux/config.h4
-rw-r--r--include/linux/ext_fs.h2
-rw-r--r--include/linux/fcntl.h7
-rw-r--r--include/linux/fs.h28
-rw-r--r--include/linux/ioctl.h11
-rw-r--r--include/linux/iso_fs.h211
-rw-r--r--include/linux/iso_fs_i.h13
-rw-r--r--include/linux/iso_fs_sb.h30
-rw-r--r--include/linux/kernel.h15
-rw-r--r--include/linux/keyboard.h103
-rw-r--r--include/linux/limits.h21
-rw-r--r--include/linux/lp.h96
-rw-r--r--include/linux/minix_fs.h2
-rw-r--r--include/linux/mm.h2
-rw-r--r--include/linux/mtio.h17
-rw-r--r--include/linux/proc_fs.h8
-rw-r--r--include/linux/sched.h22
-rw-r--r--include/linux/sys.h3
-rw-r--r--include/linux/unistd.h1
-rw-r--r--init/main.c9
-rw-r--r--kernel/FPU-emu/Makefile117
-rw-r--r--kernel/FPU-emu/errors.c23
-rw-r--r--kernel/FPU-emu/load_store.c1
-rw-r--r--kernel/FPU-emu/reg_ld_str.c28
-rw-r--r--kernel/FPU-emu/version.h2
-rw-r--r--kernel/Makefile155
-rw-r--r--kernel/blk_drv/Makefile58
-rw-r--r--kernel/blk_drv/blk.h15
-rw-r--r--kernel/blk_drv/floppy.c4
-rw-r--r--kernel/blk_drv/genhd.c9
-rw-r--r--kernel/blk_drv/hd.c10
-rw-r--r--kernel/blk_drv/ll_rw_blk.c99
-rw-r--r--kernel/blk_drv/ramdisk.c4
-rw-r--r--kernel/blk_drv/scsi/7000fasst.c465
-rw-r--r--kernel/blk_drv/scsi/7000fasst.h137
-rw-r--r--kernel/blk_drv/scsi/Makefile318
-rw-r--r--kernel/blk_drv/scsi/Makefile.in121
-rw-r--r--kernel/blk_drv/scsi/aha1542.c514
-rw-r--r--kernel/blk_drv/scsi/aha1542.h23
-rw-r--r--kernel/blk_drv/scsi/aha1740.c428
-rw-r--r--kernel/blk_drv/scsi/aha1740.h175
-rw-r--r--kernel/blk_drv/scsi/config.in29
-rw-r--r--kernel/blk_drv/scsi/config.out10
-rw-r--r--kernel/blk_drv/scsi/fdomain.c937
-rw-r--r--kernel/blk_drv/scsi/fdomain.h29
-rw-r--r--kernel/blk_drv/scsi/hosts.c73
-rw-r--r--kernel/blk_drv/scsi/hosts.h99
-rw-r--r--kernel/blk_drv/scsi/scsi.c1167
-rw-r--r--kernel/blk_drv/scsi/scsi.h229
-rw-r--r--kernel/blk_drv/scsi/scsi_debug.c515
-rw-r--r--kernel/blk_drv/scsi/scsi_debug.h27
-rw-r--r--kernel/blk_drv/scsi/scsi_ioctl.c128
-rw-r--r--kernel/blk_drv/scsi/scsi_ioctl.h12
-rw-r--r--kernel/blk_drv/scsi/sd.c662
-rw-r--r--kernel/blk_drv/scsi/sd.h16
-rw-r--r--kernel/blk_drv/scsi/sd_ioctl.c47
-rw-r--r--kernel/blk_drv/scsi/seagate.c86
-rw-r--r--kernel/blk_drv/scsi/seagate.h13
-rw-r--r--kernel/blk_drv/scsi/sr.c523
-rw-r--r--kernel/blk_drv/scsi/sr.h14
-rw-r--r--kernel/blk_drv/scsi/sr_ioctl.c137
-rw-r--r--kernel/blk_drv/scsi/st.c1081
-rw-r--r--kernel/blk_drv/scsi/st.h41
-rw-r--r--kernel/blk_drv/scsi/st_ioctl.c19
-rw-r--r--kernel/blk_drv/scsi/ultrastor.c78
-rw-r--r--kernel/blk_drv/scsi/ultrastor.h15
-rw-r--r--kernel/blk_drv/scsi/wd7000.c619
-rw-r--r--kernel/blk_drv/scsi/wd7000.h187
-rw-r--r--kernel/chr_drv/Makefile180
-rw-r--r--kernel/chr_drv/console.c113
-rw-r--r--kernel/chr_drv/keyboard.c261
-rw-r--r--kernel/chr_drv/lp.c160
-rw-r--r--kernel/chr_drv/psaux.c6
-rw-r--r--kernel/chr_drv/tty_io.c188
-rw-r--r--kernel/chr_drv/tty_ioctl.c12
-rw-r--r--kernel/chr_drv/vt.c60
-rw-r--r--kernel/dma.c4
-rw-r--r--kernel/exit.c4
-rw-r--r--kernel/fork.c2
-rw-r--r--kernel/info.c39
-rw-r--r--kernel/irq.c2
-rw-r--r--kernel/printk.c2
-rw-r--r--kernel/sched.c4
-rw-r--r--kernel/sys.c2
-rw-r--r--kernel/vsprintf.c12
-rw-r--r--lib/Makefile7
-rw-r--r--mm/Makefile37
-rw-r--r--mm/memory.c32
-rw-r--r--mm/swap.c25
-rw-r--r--net/Makefile29
-rw-r--r--net/tcp/Makefile243
-rw-r--r--net/tcp/Space.c5
-rw-r--r--net/tcp/arp.c41
-rw-r--r--net/tcp/arp.h10
-rw-r--r--net/tcp/dev.c38
-rw-r--r--net/tcp/icmp.c22
-rw-r--r--net/tcp/icmp.h5
-rw-r--r--net/tcp/ip.c32
-rw-r--r--net/tcp/loopback.c34
-rw-r--r--net/tcp/packet.c9
-rw-r--r--net/tcp/protocols.c5
-rw-r--r--net/tcp/raw.c151
-rw-r--r--net/tcp/sock.c110
-rw-r--r--net/tcp/tcp.c42
-rw-r--r--net/tcp/udp.c39
-rw-r--r--net/tcp/we.c31
-rw-r--r--tools/version.h6
159 files changed, 12096 insertions, 4319 deletions
diff --git a/Makefile b/Makefile
index 9bf0399..02ac8ad 100644
--- a/Makefile
+++ b/Makefile
@@ -92,7 +92,7 @@ LD86 =ld86 -0
AS =as
LD =ld
-HOSTCC =gcc -static
+HOSTCC =gcc
CC =gcc -DKERNEL
MAKE =make
CPP =$(CC) -E $(LIMIT_MEMORY)
@@ -127,7 +127,7 @@ linuxsubdirs: dummy
Version:
@./makever.sh
- @echo \#define UTS_RELEASE \"0.98.pl5-`cat .version`\" > tools/version.h
+ @echo \#define UTS_RELEASE \"0.98.pl6-`cat .version`\" > tools/version.h
@echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h
@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
@@ -170,11 +170,11 @@ boot/setup: boot/setup.s
$(AS86) -o boot/setup.o boot/setup.s
$(LD86) -s -o boot/setup boot/setup.o
-boot/setup.s: boot/setup.S include/linux/config.h Makefile
- $(CPP) -traditional $(SVGA_MODE) boot/setup.S -o boot/setup.s
+boot/setup.s: boot/setup.S include/linux/config.h
+ $(CPP) -traditional boot/setup.S -o boot/setup.s
-boot/bootsect.s: boot/bootsect.S include/linux/config.h
- $(CPP) -traditional boot/bootsect.S -o boot/bootsect.s
+boot/bootsect.s: boot/bootsect.S include/linux/config.h Makefile
+ $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) boot/bootsect.S -o boot/bootsect.s
boot/bootsect: boot/bootsect.s
$(AS86) -o boot/bootsect.o boot/bootsect.s
@@ -208,15 +208,16 @@ depend dep:
dummy:
### Dependencies:
-init/main.o : init/main.c /usr/lib/gcc-lib/i386-linux/2.2.2d/include/stdarg.h /usr/include/asm/system.h \
+init/main.o : init/main.c /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h /usr/include/asm/system.h \
/usr/include/asm/io.h /usr/include/linux/mktime.h /usr/include/linux/types.h \
/usr/include/linux/fcntl.h /usr/include/linux/config.h /usr/include/linux/config.dist.h \
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
- /usr/include/linux/unistd.h /usr/include/linux/string.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/linux/unistd.h \
+ /usr/include/linux/string.h
diff --git a/boot/bootsect.S b/boot/bootsect.S
index b69e95c..d9a44b2 100644
--- a/boot/bootsect.S
+++ b/boot/bootsect.S
@@ -40,6 +40,12 @@ ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
! ROOT_DEV & SWAP_DEV are now written by "build".
ROOT_DEV = 0
SWAP_DEV = 0
+#ifndef SVGA_MODE
+#define SVGA_MODE ASK_VGA
+#endif
+#ifndef RAMDISK
+#define RAMDISK 0
+#endif
! ld86 requires an entry symbol. This may as well be the usual one.
.globl _main
@@ -425,9 +431,13 @@ msg1:
.byte 13,10
.ascii "Loading"
-.org 506
+.org 502
swap_dev:
.word SWAP_DEV
+ram_size:
+ .word RAMDISK
+vid_mode:
+ .word SVGA_MODE
root_dev:
.word ROOT_DEV
boot_flag:
diff --git a/boot/setup.S b/boot/setup.S
index 5316dcf..e3df8f8 100644
--- a/boot/setup.S
+++ b/boot/setup.S
@@ -265,7 +265,9 @@ getkey:
chsvga: cld
push ds
push cs
+ mov ax,[0x01fa]
pop ds
+ mov modesave,ax
mov ax,#0xc000
mov es,ax
mov ax,modesave
diff --git a/fs/Makefile b/fs/Makefile
index d2a5900..0f97234 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -7,7 +7,7 @@
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-SUBDIRS = minix ext msdos proc
+SUBDIRS = minix ext msdos proc isofs
.c.s:
$(CC) $(CFLAGS) -S $<
@@ -49,159 +49,169 @@ block_dev.o : block_dev.c /usr/include/linux/errno.h /usr/include/linux/sched.h
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/asm/segment.h /usr/include/asm/system.h
-buffer.o : buffer.c /usr/lib/gcc-lib/i386-linux/2.2.2d/include/stdarg.h /usr/include/linux/config.h \
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/locks.h /usr/include/asm/segment.h /usr/include/asm/system.h
+buffer.o : buffer.c /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h /usr/include/linux/config.h \
/usr/include/linux/config.dist.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/string.h /usr/include/linux/locks.h /usr/include/asm/system.h \
- /usr/include/asm/io.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \
+ /usr/include/linux/locks.h /usr/include/asm/system.h /usr/include/asm/io.h
exec.o : exec.c /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/sched.h /usr/include/linux/head.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/a.out.h \
- /usr/include/linux/errno.h /usr/include/linux/string.h /usr/include/linux/stat.h \
- /usr/include/linux/fcntl.h /usr/include/linux/ptrace.h /usr/include/linux/user.h \
- /usr/include/asm/segment.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/a.out.h /usr/include/linux/errno.h \
+ /usr/include/linux/string.h /usr/include/linux/stat.h /usr/include/linux/fcntl.h \
+ /usr/include/linux/ptrace.h /usr/include/linux/user.h /usr/include/asm/segment.h
fcntl.o : fcntl.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/errno.h /usr/include/linux/stat.h /usr/include/linux/fcntl.h \
- /usr/include/linux/string.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
+ /usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/linux/string.h
fifo.o : fifo.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
- /usr/include/linux/fcntl.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/errno.h /usr/include/linux/fcntl.h
file_table.o : file_table.c /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/string.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/string.h
filesystems.o : filesystems.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/minix_fs.h /usr/include/linux/proc_fs.h \
- /usr/include/linux/ext_fs.h /usr/include/linux/msdos_fs.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/minix_fs.h /usr/include/linux/proc_fs.h /usr/include/linux/ext_fs.h \
+ /usr/include/linux/msdos_fs.h
inode.o : inode.c /usr/include/linux/stat.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/string.h /usr/include/asm/system.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \
+ /usr/include/asm/system.h
ioctl.o : ioctl.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/errno.h /usr/include/linux/string.h /usr/include/linux/stat.h \
- /usr/include/linux/termios.h /usr/include/linux/fcntl.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
+ /usr/include/linux/string.h /usr/include/linux/stat.h /usr/include/linux/termios.h \
+ /usr/include/linux/fcntl.h
locks.o : locks.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/errno.h /usr/include/linux/stat.h /usr/include/linux/fcntl.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
+ /usr/include/linux/stat.h /usr/include/linux/fcntl.h
namei.o : namei.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/fcntl.h \
- /usr/include/linux/stat.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/string.h /usr/include/linux/fcntl.h /usr/include/linux/stat.h
open.o : open.c /usr/include/linux/vfs.h /usr/include/linux/types.h /usr/include/linux/utime.h \
/usr/include/linux/errno.h /usr/include/linux/fcntl.h /usr/include/linux/stat.h \
/usr/include/linux/string.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
- /usr/include/asm/system.h /usr/include/asm/segment.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/asm/segment.h
pipe.o : pipe.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/errno.h /usr/include/linux/fcntl.h /usr/include/linux/termios.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
+ /usr/include/linux/fcntl.h /usr/include/linux/termios.h
read_write.o : read_write.c /usr/include/linux/types.h /usr/include/linux/errno.h \
/usr/include/linux/stat.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h \
- /usr/include/asm/segment.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/asm/segment.h
select.o : select.c /usr/include/linux/types.h /usr/include/linux/time.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/kernel.h \
- /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/mm.h \
- /usr/include/linux/signal.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \
- /usr/include/linux/stat.h /usr/include/linux/errno.h /usr/include/asm/segment.h \
- /usr/include/asm/system.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \
+ /usr/include/linux/head.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/stat.h \
+ /usr/include/linux/errno.h /usr/include/asm/segment.h /usr/include/asm/system.h
stat.o : stat.c /usr/include/linux/errno.h /usr/include/linux/stat.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/asm/segment.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/sched.h \
+ /usr/include/linux/head.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/asm/segment.h
super.o : super.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/stat.h \
- /usr/include/linux/errno.h /usr/include/linux/string.h /usr/include/linux/locks.h \
- /usr/include/asm/system.h /usr/include/asm/segment.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/stat.h /usr/include/linux/errno.h \
+ /usr/include/linux/string.h /usr/include/linux/locks.h /usr/include/asm/system.h \
+ /usr/include/asm/segment.h
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 8bb0add..8b57a6e 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -7,6 +7,7 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
+#include <linux/locks.h>
#include <asm/segment.h>
#include <asm/system.h>
@@ -56,40 +57,154 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
return written;
}
+#define NBUF 16
+
+
int block_read(struct inode * inode, struct file * filp, char * buf, int count)
{
unsigned int block = filp->f_pos >> BLOCK_SIZE_BITS;
unsigned int offset = filp->f_pos & (BLOCK_SIZE-1);
+ int blocks, left;
+ int bhrequest;
+ int ra_blocks, max_block, nextblock;
+ struct buffer_head ** bhb, ** bhe;
+ struct buffer_head * buflist[NBUF];
+ struct buffer_head * bhreq[NBUF];
unsigned int chars;
unsigned int size;
unsigned int dev;
int read = 0;
- struct buffer_head * bh;
- register char * p;
dev = inode->i_rdev;
if (blk_size[MAJOR(dev)])
- size = blk_size[MAJOR(dev)][MINOR(dev)];
+ size = blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
else
size = 0x7fffffff;
- while (count>0) {
- if (block >= size)
- return read;
- chars = BLOCK_SIZE-offset;
- if (chars > count)
- chars = count;
- if (!(bh = breada(dev,block,block+1,block+2,-1)))
- return read?read:-EIO;
- block++;
- p = offset + bh->b_data;
- offset = 0;
- filp->f_pos += chars;
- read += chars;
- count -= chars;
- memcpy_tofs(buf,p,chars);
- p += chars;
- buf += chars;
- brelse(bh);
- }
+
+ if (filp->f_pos > size)
+ left = 0;
+ else
+ left = size - filp->f_pos;
+ if (left > count)
+ left = count;
+ if (left <= 0)
+ return 0;
+
+ blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ bhb = bhe = buflist;
+ ra_blocks = read_ahead[MAJOR(dev)] / (BLOCK_SIZE >> 9);
+ max_block = size;
+ nextblock = -1;
+
+ /* We do this in a two stage process. We first try and request
+ as many blocks as we can, then we wait for the first one to
+ complete, and then we try and wrap up as many as are actually
+ done. This routine is rather generic, in that it can be used
+ in a filesystem by substituting the appropriate function in
+ for getblk.
+
+ This routine is optimized to make maximum use of the various
+ buffers and caches. */
+
+ do {
+ bhrequest = 0;
+ while (blocks) {
+ int uptodate;
+ --blocks;
+ *bhb = getblk(dev, block++, BLOCK_SIZE);
+ uptodate = 1;
+ if (*bhb && !(*bhb)->b_uptodate) {
+ uptodate = 0;
+ bhreq[bhrequest++] = *bhb;
+ nextblock = (*bhb)->b_blocknr + 1;
+ };
+
+ if (++bhb == &buflist[NBUF])
+ bhb = buflist;
+
+ /* If the block we have on hand is uptodate, go ahead
+ and complete processing. */
+ if(bhrequest == 0 && uptodate) break;
+
+ if (bhb == bhe)
+ break;
+ }
+
+ if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) {
+ /* If we are going to read something anyways, add in the
+ read-ahead blocks */
+ while(ra_blocks){
+ if (block >= max_block) break;
+ if(bhrequest == NBUF) break; /* Block full */
+ --ra_blocks;
+ *bhb = getblk(dev, block++, BLOCK_SIZE);
+
+ if (*bhb && !(*bhb)->b_uptodate) {
+ if((*bhb)->b_blocknr != nextblock) {
+ brelse(*bhb);
+ break;
+ };
+ nextblock = (*bhb)->b_blocknr + 1;
+ bhreq[bhrequest++] = *bhb;
+ };
+
+ if (++bhb == &buflist[NBUF])
+ bhb = buflist;
+
+ if (bhb == bhe)
+ break;
+ };
+ };
+ /* Now request them all */
+ if (bhrequest)
+ ll_rw_block(READ, bhrequest, bhreq);
+
+ do{ /* Finish off all I/O that has actually completed */
+ if (*bhe) {/* test for valid buffer */
+ wait_on_buffer(*bhe);
+ if (!(*bhe)->b_uptodate) {
+ do {
+ brelse(*bhe);
+ if (++bhe == &buflist[NBUF])
+ bhe = buflist;
+ } while (bhe != bhb);
+ break;
+ }
+ }
+
+ if (left < BLOCK_SIZE - offset)
+ chars = left;
+ else
+ chars = BLOCK_SIZE - offset;
+ filp->f_pos += chars;
+ left -= chars;
+ read += chars;
+ if (*bhe) {
+ memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
+ brelse(*bhe);
+ buf += chars;
+ } else {
+ while (chars-->0)
+ put_fs_byte(0,buf++);
+ }
+ offset = 0;
+ if (++bhe == &buflist[NBUF])
+ bhe = buflist;
+ } while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) &&
+ (left > 0));
+ } while (left > 0);
+
+/* Release the read-ahead blocks */
+ while (bhe != bhb) {
+ if (*bhe) brelse(*bhe);
+ if (++bhe == &buflist[NBUF])
+ bhe = buflist;
+ };
+
+ filp->f_reada = 1;
+
+ if (!read)
+ return -EIO;
+
return read;
}
diff --git a/fs/buffer.c b/fs/buffer.c
index 6969f0a..009a5a1 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -43,6 +43,7 @@ static struct buffer_head * unused_list = NULL;
static struct wait_queue * buffer_wait = NULL;
int nr_buffers = 0;
+int buffermem = 0;
int nr_buffer_heads = 0;
/*
@@ -306,7 +307,8 @@ struct buffer_head * getblk(dev_t dev, int block, int size)
int buffers;
repeat:
- if (bh = get_hash_table(dev, block, size)) {
+ bh = get_hash_table(dev, block, size);
+ if (bh) {
if (bh->b_uptodate && !bh->b_dirt)
put_last_free(bh);
return bh;
@@ -417,15 +419,21 @@ __asm__("cld\n\t" \
void bread_page(unsigned long address, dev_t dev, int b[4])
{
struct buffer_head * bh[4];
+ struct buffer_head * bhr[4];
+ int bhnum = 0;
int i;
for (i=0 ; i<4 ; i++)
if (b[i]) {
- if (bh[i] = getblk(dev, b[i], 1024))
- if (!bh[i]->b_uptodate)
- ll_rw_block(READ, 1, &bh[i]);
+ bh[i] = getblk(dev, b[i], 1024);
+ if (bh[i] && !bh[i]->b_uptodate)
+ bhr[bhnum++] = bh[i];
} else
bh[i] = NULL;
+
+ if(bhnum)
+ ll_rw_block(READ, bhnum, bhr);
+
for (i=0 ; i<4 ; i++,address += BLOCK_SIZE)
if (bh[i]) {
wait_on_buffer(bh[i]);
@@ -564,6 +572,7 @@ void grow_buffers(int size)
break;
}
tmp->b_this_page = bh;
+ buffermem += 4096;
return;
/*
* In case anything failed, we just free everything we got.
@@ -605,6 +614,7 @@ static int try_to_free(struct buffer_head * bh)
remove_from_queues(p);
put_unused_buffer_head(p);
} while (tmp != bh);
+ buffermem -= 4096;
free_page(page);
return 1;
}
diff --git a/fs/exec.c b/fs/exec.c
index 6397653..fd4f589 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -128,7 +128,7 @@ int core_dump(long signr, struct pt_regs * regs)
/* Flag indicating the math stuff is valid. We don't support this for the
soft-float routines yet */
if (hard_math) {
- if (dump.u_fpvalid = current->used_math) {
+ if ((dump.u_fpvalid = current->used_math) != 0) {
if (last_task_used_math == current)
__asm__("clts ; fnsave %0"::"m" (dump.i387));
else
@@ -264,7 +264,7 @@ static int count(char ** argv)
int i=0;
char ** tmp;
- if (tmp = argv)
+ if ((tmp = argv) != 0)
while (get_fs_long((unsigned long *) (tmp++)))
i++;
@@ -481,7 +481,7 @@ restart_interp:
brelse(bh);
iput(inode);
buf[127] = '\0';
- if (cp = strchr(buf, '\n')) {
+ if ((cp = strchr(buf, '\n')) != NULL) {
*cp = '\0';
for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
}
diff --git a/fs/ext/Makefile b/fs/ext/Makefile
index 55cb096..69ca71d 100644
--- a/fs/ext/Makefile
+++ b/fs/ext/Makefile
@@ -34,93 +34,101 @@ blkdev.o : blkdev.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/in
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h \
- /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
- /usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/linux/errno.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h /usr/include/linux/tty.h \
+ /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/stat.h \
+ /usr/include/linux/fcntl.h /usr/include/linux/errno.h
chrdev.o : chrdev.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h \
- /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
- /usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/linux/errno.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h /usr/include/linux/tty.h \
+ /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/stat.h \
+ /usr/include/linux/fcntl.h /usr/include/linux/errno.h
dir.o : dir.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/kernel.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/ext_fs.h /usr/include/linux/stat.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/ext_fs.h /usr/include/linux/stat.h
fifo.o : fifo.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h
file.o : file.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h /usr/include/linux/errno.h \
- /usr/include/linux/fcntl.h /usr/include/linux/stat.h /usr/include/linux/locks.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/ext_fs.h /usr/include/linux/errno.h /usr/include/linux/fcntl.h \
+ /usr/include/linux/stat.h /usr/include/linux/locks.h
freelists.o : freelists.c /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/ext_fs.h /usr/include/linux/string.h /usr/include/linux/locks.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h \
+ /usr/include/linux/stat.h /usr/include/linux/string.h /usr/include/linux/locks.h
inode.o : inode.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h \
- /usr/include/linux/string.h /usr/include/linux/stat.h /usr/include/linux/locks.h \
- /usr/include/asm/system.h /usr/include/asm/segment.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h /usr/include/linux/string.h \
+ /usr/include/linux/stat.h /usr/include/linux/locks.h /usr/include/asm/system.h \
+ /usr/include/asm/segment.h
namei.o : namei.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h \
- /usr/include/linux/string.h /usr/include/linux/stat.h /usr/include/linux/fcntl.h \
- /usr/include/linux/errno.h /usr/include/asm/segment.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h /usr/include/linux/string.h \
+ /usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/linux/errno.h \
+ /usr/include/asm/segment.h
symlink.o : symlink.c /usr/include/asm/segment.h /usr/include/linux/errno.h \
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h \
- /usr/include/linux/stat.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h /usr/include/linux/stat.h
truncate.o : truncate.c /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/ext_fs.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
- /usr/include/asm/system.h /usr/include/linux/stat.h /usr/include/linux/fcntl.h \
- /usr/include/linux/errno.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/linux/errno.h
diff --git a/fs/ext/dir.c b/fs/ext/dir.c
index 1c4b7f1..68aabc5 100644
--- a/fs/ext/dir.c
+++ b/fs/ext/dir.c
@@ -69,6 +69,8 @@ static int ext_readdir(struct inode * inode, struct file * filp,
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
+ if (filp->f_pos % 8 != 0)
+ return -EBADF;
while (filp->f_pos < inode->i_size) {
offset = filp->f_pos & 1023;
bh = ext_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0);
@@ -78,18 +80,22 @@ static int ext_readdir(struct inode * inode, struct file * filp,
}
de = (struct ext_dir_entry *) (offset + bh->b_data);
while (offset < 1024 && filp->f_pos < inode->i_size) {
- offset += de->rec_len;
- filp->f_pos += de->rec_len;
- if (de->rec_len < 8 || de->rec_len % 4 != 0 ||
- de->rec_len < de->name_len + 8) {
- printk ("ext_readdir: bad directory entry\n");
+ if (de->rec_len < 8 || de->rec_len % 8 != 0 ||
+ de->rec_len < de->name_len + 8 ||
+ (de->rec_len + filp->f_pos - 1) / 1024 > (filp->f_pos / 1024)) {
+ printk ("ext_readdir: bad dir entry, skipping\n");
printk ("dev=%d, dir=%d, offset=%d, rec_len=%d, name_len=%d\n",
inode->i_dev, inode->i_ino, offset, de->rec_len, de->name_len);
- return 0;
+ filp->f_pos += 1024-offset;
+ if (filp->f_pos > inode->i_size)
+ filp->f_pos = inode->i_size;
+ continue;
}
+ offset += de->rec_len;
+ filp->f_pos += de->rec_len;
if (de->inode) {
for (i = 0; i < de->name_len; i++)
- if (c = de->name[i])
+ if ((c = de->name[i]) != 0)
put_fs_byte(c,i+dirent->d_name);
else
break;
diff --git a/fs/ext/file.c b/fs/ext/file.c
index ce8313c..e8684d5 100644
--- a/fs/ext/file.c
+++ b/fs/ext/file.c
@@ -71,7 +71,10 @@ static int ext_file_read(struct inode * inode, struct file * filp, char * buf, i
{
int read,left,chars;
int block, blocks, offset;
+ int bhrequest;
+ int ra_blocks, max_block, nextblock;
struct buffer_head ** bhb, ** bhe;
+ struct buffer_head * bhreq[NBUF];
struct buffer_head * buflist[NBUF];
if (!inode) {
@@ -95,50 +98,118 @@ static int ext_file_read(struct inode * inode, struct file * filp, char * buf, i
offset = filp->f_pos & (BLOCK_SIZE-1);
blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE;
bhb = bhe = buflist;
+
+ ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
+ max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE;
+ nextblock = -1;
+
+ /* We do this in a two stage process. We first try and request
+ as many blocks as we can, then we wait for the first one to
+ complete, and then we try and wrap up as many as are actually
+ done. This routine is rather generic, in that it can be used
+ in a filesystem by substituting the appropriate function in
+ for getblk.
+
+ This routine is optimized to make maximum use of the various
+ buffers and caches. */
+
do {
- if (blocks) {
+ bhrequest = 0;
+ while (blocks) {
+ int uptodate;
--blocks;
- *bhb = ext_getblk(inode,block++,0);
- if (*bhb && !(*bhb)->b_uptodate)
- ll_rw_block(READ, 1, bhb);
+ *bhb = ext_getblk(inode, block++, 0);
+ uptodate = 1;
+ if (*bhb && !(*bhb)->b_uptodate) {
+ uptodate = 0;
+ bhreq[bhrequest++] = *bhb;
+ nextblock = (*bhb)->b_blocknr + 1;
+ };
if (++bhb == &buflist[NBUF])
bhb = buflist;
- if (bhb != bhe)
- continue;
- }
- if (*bhe) {
- wait_on_buffer(*bhe);
- if (!(*bhe)->b_uptodate) {
- do {
- brelse(*bhe);
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
- } while (bhe != bhb);
+ /* If the block we have on hand is uptodate, go ahead
+ and complete processing. */
+ if(bhrequest == 0 && uptodate) break;
+
+ if (bhb == bhe)
break;
- }
- }
+ }
- if (left < BLOCK_SIZE - offset)
- chars = left;
- else
- chars = BLOCK_SIZE - offset;
- filp->f_pos += chars;
- left -= chars;
- read += chars;
- if (*bhe) {
- memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
+ if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) {
+ /* If we are going to read something anyways, add in the
+ read-ahead blocks */
+ while(ra_blocks){
+ if (block >= max_block) break;
+ if(bhrequest == NBUF) break; /* Block full */
+ --ra_blocks;
+ *bhb = ext_getblk(inode, block++, 0);
+
+ if (*bhb && !(*bhb)->b_uptodate) {
+ if((*bhb)->b_blocknr != nextblock) {
+ brelse(*bhb);
+ break;
+ };
+ nextblock = (*bhb)->b_blocknr + 1;
+ bhreq[bhrequest++] = *bhb;
+ };
+
+ if (++bhb == &buflist[NBUF])
+ bhb = buflist;
+
+ if (bhb == bhe)
+ break;
+ };
+ };
+ /* Now request them all */
+ if (bhrequest)
+ ll_rw_block(READ, bhrequest, bhreq);
+
+ do{ /* Finish off all I/O that has actually completed */
+ if (*bhe) {/* test for valid buffer */
+ wait_on_buffer(*bhe);
+ if (!(*bhe)->b_uptodate) {
+ do {
brelse(*bhe);
- buf += chars;
- } else {
- while (chars-->0)
- put_fs_byte(0,buf++);
- }
- offset = 0;
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
+ if (++bhe == &buflist[NBUF])
+ bhe = buflist;
+ } while (bhe != bhb);
+ break;
+ }
+ }
+
+ if (left < BLOCK_SIZE - offset)
+ chars = left;
+ else
+ chars = BLOCK_SIZE - offset;
+ filp->f_pos += chars;
+ left -= chars;
+ read += chars;
+ if (*bhe) {
+ memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
+ brelse(*bhe);
+ buf += chars;
+ } else {
+ while (chars-->0)
+ put_fs_byte(0,buf++);
+ }
+ offset = 0;
+ if (++bhe == &buflist[NBUF])
+ bhe = buflist;
+ } while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) &&
+ (left > 0));
} while (left > 0);
+
+/* Release the read-ahead blocks */
+ while (bhe != bhb) {
+ if (*bhe) brelse(*bhe);
+ if (++bhe == &buflist[NBUF])
+ bhe = buflist;
+ };
+
+ filp->f_reada = 1;
+
if (!read)
return -EIO;
if (!IS_RDONLY(inode)) {
diff --git a/fs/ext/freelists.c b/fs/ext/freelists.c
index e7801c8..6b092ea 100644
--- a/fs/ext/freelists.c
+++ b/fs/ext/freelists.c
@@ -32,6 +32,7 @@
#include <linux/sched.h>
#include <linux/ext_fs.h>
+#include <linux/stat.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/locks.h>
@@ -230,15 +231,17 @@ printk("ext_free_inode: inode full, skipping to %d\n", inode->i_ino);
clear_inode(inode);
}
-struct inode * ext_new_inode(struct super_block * sb)
+struct inode * ext_new_inode(const struct inode * dir)
{
+ struct super_block * sb;
struct inode * inode;
struct ext_free_inode * efi;
unsigned long block;
int j;
- if (!sb || !(inode=get_empty_inode()))
+ if (!dir || !(inode=get_empty_inode()))
return NULL;
+ sb = dir->i_sb;
inode->i_sb = sb;
inode->i_flags = sb->s_flags;
if (!sb->u.ext_sb.s_firstfreeinodeblock)
@@ -275,7 +278,7 @@ printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
inode->i_nlink = 1;
inode->i_dev = sb->s_dev;
inode->i_uid = current->euid;
- inode->i_gid = current->egid;
+ inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->egid;
inode->i_dirt = 1;
inode->i_ino = j;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
diff --git a/fs/ext/namei.c b/fs/ext/namei.c
index d92cab8..b094fbe 100644
--- a/fs/ext/namei.c
+++ b/fs/ext/namei.c
@@ -122,18 +122,23 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
if (prev_dir)
*prev_dir = NULL;
}
- if (de->rec_len < 8 || de->rec_len % 4 != 0 ||
- de->rec_len < de->name_len + 8) {
+ if (de->rec_len < 8 || de->rec_len % 8 != 0 ||
+ de->rec_len < de->name_len + 8 ||
+ (((char *) de) + de->rec_len-1 >= BLOCK_SIZE+bh->b_data)) {
printk ("ext_find_entry: bad dir entry\n");
printk ("dev=%d, dir=%d, offset=%d, rec_len=%d, name_len=%d\n",
dir->i_dev, dir->i_ino, offset, de->rec_len, de->name_len);
- brelse (bh);
- return NULL;
+ de = (struct ext_dir_entry *) (bh->b_data+BLOCK_SIZE);
+ offset = ((offset / BLOCK_SIZE) + 1) * BLOCK_SIZE;
+ continue;
+/* brelse (bh);
+ return NULL; */
}
if (ext_match(namelen,name,de)) {
*res_dir = de;
if (next_dir)
- if (offset + de->rec_len < dir->i_size)
+ if (offset + de->rec_len < dir->i_size &&
+ ((char *)de) + de->rec_len < BLOCK_SIZE+bh->b_data)
*next_dir = (struct ext_dir_entry *)
((char *) de + de->rec_len);
else
@@ -221,15 +226,15 @@ printk ("ext_add_entry: skipping to next block\n");
#endif
brelse(bh);
bh = NULL;
- bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,1);
+ bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,0);
if (!bh)
return NULL;
de = (struct ext_dir_entry *) bh->b_data;
}
if (offset >= dir->i_size) {
/* Check that the directory entry fits in the block */
- if (offset % BLOCK_SIZE == 0
- || (BLOCK_SIZE - (offset % BLOCK_SIZE)) < rec_len) {
+ if (offset % BLOCK_SIZE == 0 ||
+ (BLOCK_SIZE - (offset % BLOCK_SIZE)) < rec_len) {
if ((offset % BLOCK_SIZE) != 0) {
/* If the entry does not fit in the
block, the remainder of the block
@@ -262,7 +267,8 @@ printk ("ext_add_entry : creating next block\n");
dir->i_ctime = CURRENT_TIME;
}
if (de->rec_len < 8 || de->rec_len % 4 != 0 ||
- de->rec_len < de->name_len + 8) {
+ de->rec_len < de->name_len + 8 ||
+ (((char *) de) + de->rec_len-1 >= BLOCK_SIZE+bh->b_data)) {
printk ("ext_addr_entry: bad dir entry\n");
printk ("dev=%d, dir=%d, offset=%d, rec_len=%d, name_len=%d\n",
dir->i_dev, dir->i_ino, offset, de->rec_len, de->name_len);
@@ -307,7 +313,7 @@ int ext_create(struct inode * dir,const char * name, int len, int mode,
*result = NULL;
if (!dir)
return -ENOENT;
- inode = ext_new_inode(dir->i_sb);
+ inode = ext_new_inode(dir);
if (!inode) {
iput(dir);
return -ENOSPC;
@@ -345,7 +351,7 @@ int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev
iput(dir);
return -EEXIST;
}
- inode = ext_new_inode(dir->i_sb);
+ inode = ext_new_inode(dir);
if (!inode) {
iput(dir);
return -ENOSPC;
@@ -355,8 +361,11 @@ int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev
inode->i_op = NULL;
if (S_ISREG(inode->i_mode))
inode->i_op = &ext_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
+ else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &ext_dir_inode_operations;
+ if (dir->i_mode & S_ISGID)
+ inode->i_mode |= S_ISGID;
+ }
else if (S_ISLNK(inode->i_mode))
inode->i_op = &ext_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode))
@@ -403,7 +412,7 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
iput(dir);
return -EEXIST;
}
- inode = ext_new_inode(dir->i_sb);
+ inode = ext_new_inode(dir);
if (!inode) {
iput(dir);
return -ENOSPC;
@@ -437,6 +446,8 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
dir_block->b_dirt = 1;
brelse(dir_block);
inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
+ if (dir->i_mode & S_ISGID)
+ inode->i_mode |= S_ISGID;
inode->i_dirt = 1;
bh = ext_add_entry(dir,name,len,&de);
if (!bh) {
@@ -617,7 +628,7 @@ int ext_symlink(struct inode * dir, const char * name, int len, const char * sym
int i;
char c;
- if (!(inode = ext_new_inode(dir->i_sb))) {
+ if (!(inode = ext_new_inode(dir))) {
iput(dir);
return -ENOSPC;
}
diff --git a/fs/fifo.c b/fs/fifo.c
index 7d12559..3918251 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -93,6 +93,7 @@ static int fifo_open(struct inode * inode,struct file * filp)
}
if (!page)
return -ENOMEM;
+ PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
PIPE_BASE(*inode) = (char *) page;
return 0;
}
diff --git a/fs/filesystems.c b/fs/filesystems.c
index 7844781..c19c4d6 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -23,6 +23,9 @@
#ifdef NFS_FS
#include <linux/nfs_fs.h>
#endif
+#ifdef ISO9660_FS
+#include <linux/iso_fs.h>
+#endif
struct file_system_type file_systems[] = {
#ifdef MINIX_FS
@@ -40,5 +43,8 @@ struct file_system_type file_systems[] = {
#ifdef NFS_FS
{nfs_read_super, "nfs", 0},
#endif
+#ifdef ISO9660_FS
+ {isofs_read_super, "iso9660", 1},
+#endif
{NULL, NULL, 0}
};
diff --git a/fs/isofs/Makefile b/fs/isofs/Makefile
new file mode 100644
index 0000000..0c51e9e
--- /dev/null
+++ b/fs/isofs/Makefile
@@ -0,0 +1,117 @@
+#
+# Makefile for the linux isofs-filesystem routines.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.c.s:
+ $(CC) $(CFLAGS) -S $<
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+.s.o:
+ $(AS) -o $*.o $<
+
+OBJS= namei.o inode.o file.o dir.o util.o rock.o symlink.o blkdev.o chrdev.o
+
+isofs.o: $(OBJS)
+ $(LD) -r -o isofs.o $(OBJS)
+
+clean:
+ rm -f core *.o *.a tmp_make
+ for i in *.c;do rm -f `basename $$i .c`.s;done
+
+dep:
+ sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+ for i in *.c;do $(CPP) -M $$i;done >> tmp_make
+ cp tmp_make Makefile
+
+### Dependencies:
+blkdev.o : blkdev.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \
+ /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
+ /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
+ /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/linux/stat.h /usr/include/linux/fcntl.h
+chrdev.o : chrdev.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \
+ /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
+ /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
+ /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/linux/stat.h /usr/include/linux/fcntl.h
+dir.o : dir.c /usr/include/linux/errno.h /usr/include/asm/segment.h /usr/include/linux/fs.h \
+ /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
+ /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
+ /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/iso_fs.h \
+ /usr/include/linux/kernel.h /usr/include/linux/stat.h /usr/include/linux/string.h \
+ /usr/include/linux/mm.h
+file.o : file.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/sched.h \
+ /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
+ /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
+ /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/iso_fs.h /usr/include/linux/fcntl.h /usr/include/linux/errno.h \
+ /usr/include/linux/stat.h /usr/include/linux/locks.h
+inode.o : inode.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
+ /usr/include/linux/stat.h /usr/include/linux/sched.h /usr/include/linux/head.h \
+ /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
+ /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
+ /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \
+ /usr/include/linux/string.h /usr/include/linux/locks.h /usr/include/asm/system.h \
+ /usr/include/asm/segment.h /usr/include/linux/errno.h
+namei.o : namei.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
+ /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
+ /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
+ /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h /usr/include/linux/string.h \
+ /usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/asm/segment.h \
+ /usr/include/linux/errno.h
+rock.o : rock.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
+ /usr/include/linux/stat.h /usr/include/linux/sched.h /usr/include/linux/head.h \
+ /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
+ /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
+ /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \
+ /usr/include/linux/string.h rock.h
+symlink.o : symlink.c /usr/include/asm/segment.h /usr/include/linux/errno.h \
+ /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
+ /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
+ /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
+ /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h /usr/include/linux/stat.h
+util.o : util.c
diff --git a/fs/isofs/blkdev.c b/fs/isofs/blkdev.c
new file mode 100644
index 0000000..7b93d74
--- /dev/null
+++ b/fs/isofs/blkdev.c
@@ -0,0 +1,67 @@
+/*
+ * linux/fs/isofs/blkdev.c
+ *
+ * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * isofs blkdev handling code. This is only used with the Rock Ridge
+ * extensions to iso9660
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/iso_fs.h>
+#include <linux/tty.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+
+/*
+ * Called every time a isofs block special file is opened
+ */
+static int blkdev_open(struct inode * inode, struct file * filp)
+{
+ int i;
+
+ i = MAJOR(inode->i_rdev);
+ if (i < MAX_BLKDEV) {
+ filp->f_op = blkdev_fops[i];
+ if (filp->f_op && filp->f_op->open)
+ return filp->f_op->open(inode,filp);
+ }
+ return 0;
+}
+
+/*
+ * Dummy default file-operations: the only thing this does
+ * is contain the open that then fills in the correct operations
+ * depending on the special file...
+ */
+static struct file_operations def_blk_fops = {
+ NULL, /* lseek */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* select */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ blkdev_open, /* open */
+ NULL, /* release */
+};
+
+struct inode_operations isofs_blkdev_inode_operations = {
+ &def_blk_fops, /* default file operations */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ isofs_bmap, /* bmap */
+ NULL /* truncate */
+};
diff --git a/fs/isofs/chrdev.c b/fs/isofs/chrdev.c
new file mode 100644
index 0000000..fc69b12
--- /dev/null
+++ b/fs/isofs/chrdev.c
@@ -0,0 +1,68 @@
+/*
+ * linux/fs/isofs/chrdev.c
+ *
+ * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * isofs chrdev handling code. This is only used with the Rock Ridge
+ * extensions to iso9660
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/iso_fs.h>
+#include <linux/tty.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+
+/*
+ * Called every time a isofs character special file is opened
+ */
+static int chrdev_open(struct inode * inode, struct file * filp)
+{
+ int i;
+
+ i = MAJOR(inode->i_rdev);
+ if (i < MAX_CHRDEV) {
+ filp->f_op = chrdev_fops[i];
+ if (filp->f_op && filp->f_op->open)
+ return filp->f_op->open(inode,filp);
+ }
+ return 0;
+}
+
+/*
+ * Dummy default file-operations: the only thing this does
+ * is contain the open that then fills in the correct operations
+ * depending on the special file...
+ */
+static struct file_operations def_chr_fops = {
+ NULL, /* lseek */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* select */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ chrdev_open, /* open */
+ NULL, /* release */
+};
+
+struct inode_operations isofs_chrdev_inode_operations = {
+ &def_chr_fops, /* default file operations */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ isofs_bmap, /* bmap */
+ NULL /* truncate */
+};
+
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
new file mode 100644
index 0000000..ac61fcb
--- /dev/null
+++ b/fs/isofs/dir.c
@@ -0,0 +1,225 @@
+/*
+ * linux/fs/isofs/dir.c
+ *
+ * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
+ *
+ * (C) 1991 Linus Torvalds - minix filesystem
+ *
+ * isofs directory handling functions
+ */
+
+#include <linux/errno.h>
+
+#include <asm/segment.h>
+
+#include <linux/fs.h>
+#include <linux/iso_fs.h>
+#include <linux/kernel.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+
+static int isofs_readdir(struct inode *, struct file *, struct dirent *, int);
+
+static struct file_operations isofs_dir_operations = {
+ NULL, /* lseek - default */
+ isofs_file_read, /* read */
+ NULL, /* write - bad */
+ isofs_readdir, /* readdir */
+ NULL, /* select - default */
+ NULL, /* ioctl - default */
+ NULL, /* no special open code */
+ NULL /* no special release code */
+};
+
+/*
+ * directories can handle most operations...
+ */
+struct inode_operations isofs_dir_inode_operations = {
+ &isofs_dir_operations, /* default directory file-ops */
+ NULL, /* create */
+ isofs_lookup, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ isofs_bmap, /* bmap */
+ NULL /* truncate */
+};
+
+/* This is used to speed up lookup. Without this we would need to
+make a linear search of the directory to find the file that the
+directory read just returned. This is a single element cache. */
+
+struct lookup_cache cache = {0,};
+
+static int isofs_readdir(struct inode * inode, struct file * filp,
+ struct dirent * dirent, int count)
+{
+ unsigned int block,offset,i, j;
+ char c = 0;
+ int inode_number;
+ struct buffer_head * bh;
+ char * cpnt = 0;
+ unsigned int old_offset;
+ int dlen, rrflag;
+ char * dpnt;
+ struct iso_directory_record * de;
+
+ if (!inode || !S_ISDIR(inode->i_mode))
+ return -EBADF;
+
+ offset = filp->f_pos & (BLOCK_SIZE - 1);
+ block = isofs_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
+ if (!block || !(bh = bread(inode->i_dev,block,ISOFS_BUFFER_SIZE)))
+ return 0;
+
+ while (filp->f_pos < inode->i_size) {
+#ifdef DEBUG
+ printk("Block, offset: %x %x %x\n",block, offset, filp->f_pos);
+#endif
+ de = (struct iso_directory_record *) (offset + bh->b_data);
+ inode_number = (block << BLOCK_SIZE_BITS)+(offset & (BLOCK_SIZE - 1));
+
+ /* If the length byte is zero, we should move on to the next CDROM sector.
+ If we are at the end of the directory, we kick out of the while loop. */
+
+ if (*((char*) de) == 0) {
+ brelse(bh);
+ offset = 0;
+ filp->f_pos =(filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))+ISOFS_BLOCK_SIZE;
+ block = isofs_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
+ if (!block || !(bh = bread(inode->i_dev,block,ISOFS_BUFFER_SIZE)))
+ return 0;
+ continue;
+ }
+
+ /* Make sure that the entire directory record is in the current bh block.
+ If not, we malloc a buffer, and put the two halves together, so that
+ we can cleanly read the block */
+
+ old_offset = offset;
+ offset += *((unsigned char*) de);
+ filp->f_pos += *((unsigned char*) de);
+ if (offset >= BLOCK_SIZE) {
+ cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
+ memcpy(cpnt, bh->b_data, BLOCK_SIZE);
+ de = (struct iso_directory_record *) (old_offset + cpnt);
+ brelse(bh);
+ offset = filp->f_pos & (BLOCK_SIZE - 1);
+ block = isofs_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
+ if (!block || !(bh = bread(inode->i_dev,block,ISOFS_BUFFER_SIZE)))
+ return 0;
+ memcpy(cpnt+BLOCK_SIZE, bh->b_data, BLOCK_SIZE);
+ }
+
+ /* Handle the case of the '.' directory */
+
+ rrflag = 0;
+ i = 1;
+ if (de->name_len[0] == 1 && de->name[0] == 0) {
+ put_fs_byte('.',dirent->d_name);
+ inode_number = inode->i_ino;
+ dpnt = ".";
+ }
+
+ /* Handle the case of the '..' directory */
+
+ else if (de->name_len[0] == 1 && de->name[0] == 1) {
+ put_fs_byte('.',dirent->d_name);
+ put_fs_byte('.',dirent->d_name+1);
+ i = 2;
+ dpnt = "..";
+ if((inode->i_sb->u.isofs_sb.s_firstdatazone << BLOCK_SIZE_BITS) != inode->i_ino)
+ inode_number = inode->u.isofs_i.i_backlink;
+ else
+ inode_number = inode->i_ino;
+
+ /* This should never happen, but who knows. Try to be forgiving */
+ if(inode_number == -1) {
+ inode_number =
+ isofs_lookup_grandparent(inode,
+ find_rock_ridge_relocation(de, inode));
+ if(inode_number == -1){ /* Should never happen */
+ printk("Backlink not properly set.\n");
+ goto out;
+ };
+ }
+ }
+
+ /* Handle everything else. Do name translation if there
+ is no Rock Ridge NM field. */
+
+ else {
+ dlen = de->name_len[0];
+ dpnt = de->name;
+ i = dlen;
+ rrflag = get_rock_ridge_filename(de, &dpnt, &dlen, inode);
+ if (rrflag) {
+ if (rrflag == -1) { /* This is a rock ridge reloc dir */
+ if (cpnt) {
+ kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
+ cpnt = 0;
+ };
+ continue;
+ };
+ i = dlen;
+ }
+ else
+ if(inode->i_sb->u.isofs_sb.s_mapping == 'n')
+ for (i = 0; i < dlen && i < NAME_MAX; i++) {
+ if (!(c = dpnt[i])) break;
+ if (c >= 'A' && c <= 'Z') c |= 0x20; /* lower case */
+ if (c == ';' && i == dlen-2 && de->name[i+1] == '1')
+ break; /* Drop trailing ';1' */
+ if (c == ';') c = '.'; /* Convert remaining ';' to '.' */
+ dpnt[i] = c;
+ };
+
+ for(j=0; j<i; j++)
+ put_fs_byte(dpnt[j],j+dirent->d_name); /* And save it */
+ };
+#if 0
+ printk("Nchar: %d\n",i);
+#endif
+
+ if (i) {
+ while (cache.lock);
+ cache.lock = 1;
+ cache.ino = inode_number;
+ cache.dir = inode->i_ino;
+ cache.dev = inode->i_dev;
+ strncpy(cache.filename, dpnt, i);
+ cache.dlen = dlen;
+ cache.lock = 0;
+ };
+
+ if (rrflag) kfree(dpnt);
+ if (cpnt) {
+ kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
+ cpnt = 0;
+ };
+
+ if (i) {
+ put_fs_long(inode_number, &dirent->d_ino);
+ put_fs_byte(0,i+dirent->d_name);
+ put_fs_word(i,&dirent->d_reclen);
+ brelse(bh);
+ return i;
+ }
+ }
+ /* We go here for any condition we cannot handle. We also drop through
+ to here at the end of the directory. */
+ out:
+ if (cpnt) kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
+ brelse(bh);
+ return 0;
+}
+
+
+
diff --git a/fs/isofs/file.c b/fs/isofs/file.c
new file mode 100644
index 0000000..ff14934
--- /dev/null
+++ b/fs/isofs/file.c
@@ -0,0 +1,269 @@
+/*
+ * linux/fs/isofs/file.c
+ *
+ * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
+ *
+ * (C) 1991 Linus Torvalds - minix filesystem
+ *
+ * isofs regular file handling primitives
+ */
+
+#include <asm/segment.h>
+#include <asm/system.h>
+
+#include <linux/sched.h>
+#include <linux/iso_fs.h>
+#include <linux/fcntl.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/stat.h>
+#include <linux/locks.h>
+
+#include <linux/dirent.h>
+
+#define NBUF 16
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
+
+#include <linux/fs.h>
+#include <linux/iso_fs.h>
+
+int isofs_file_read(struct inode *, struct file *, char *, int);
+
+/*
+ * We have mostly NULL's here: the current defaults are ok for
+ * the isofs filesystem.
+ */
+static struct file_operations isofs_file_operations = {
+ NULL, /* lseek - default */
+ isofs_file_read, /* read */
+ NULL, /* write */
+ NULL, /* readdir - bad */
+ NULL, /* select - default */
+ NULL, /* ioctl - default */
+ NULL, /* no special open is needed */
+ NULL /* release */
+};
+
+struct inode_operations isofs_file_inode_operations = {
+ &isofs_file_operations, /* default file operations */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ isofs_bmap, /* bmap */
+ NULL /* truncate */
+};
+
+/* This is a heuristic to determine if a file is text of binary. If it
+ * is text, then we translate all 0x0d characters to spaces. If the 0x0d
+ * character is not preceeded or followed by a 0x0a, then we turn it into
+ * a 0x0a. A control-Z is also turned into a linefeed.
+ */
+
+static inline void unixify_text_buffer(char * buffer, int chars, int mode)
+{
+ while(chars--){
+ if(*buffer == 0x1a) *buffer = 0x0a;
+ if(*buffer == 0x0d){
+ if(mode == ISOFS_FILE_TEXT_M) *buffer = 0x0a;
+ if(mode == ISOFS_FILE_TEXT) *buffer = ' ';
+ }
+ buffer++;
+ }
+}
+
+/*This function determines if a given file has a DOS-like text format or not*/
+
+static void isofs_determine_filetype(struct inode * inode)
+{
+ int block;
+ int result, i;
+ struct buffer_head * bh;
+ unsigned char * pnt;
+
+ block = isofs_bmap(inode,0);
+ if (block && (bh = bread(inode->i_dev,block, ISOFS_BUFFER_SIZE))) {
+ pnt = (char*) bh->b_data;
+ result = ISOFS_FILE_TEXT_M;
+ for(i=0;i<(inode->i_size < ISOFS_BUFFER_SIZE ? inode->i_size : ISOFS_BUFFER_SIZE);
+ i++,pnt++){
+ if(*pnt & 0x80) {result = ISOFS_FILE_BINARY; break;};
+ if(*pnt >= 0x20 || *pnt == 0x1a) continue;
+ if(*pnt == 0x0a) {result = ISOFS_FILE_TEXT; continue;};
+ if(*pnt >= 0x9 && *pnt <= 0x0d) continue;
+ result = ISOFS_FILE_BINARY;
+ break;
+ }
+ brelse(bh);
+ inode->u.isofs_i.i_file_format = result;
+ }
+}
+
+/*
+ * isofs_file_read() is also needed by the directory read-routine,
+ * so it's not static. NOTE! reading directories directly is a bad idea,
+ * but has to be supported for now for compatability reasons with older
+ * versions.
+ */
+int isofs_file_read(struct inode * inode, struct file * filp, char * buf, int count)
+{
+ int read,left,chars;
+ int block, blocks, offset;
+ int bhrequest;
+ int ra_blocks, max_block, nextblock;
+ struct buffer_head ** bhb, ** bhe;
+ struct buffer_head * bhreq[NBUF];
+ struct buffer_head * buflist[NBUF];
+
+ if (!inode) {
+ printk("isofs_file_read: inode = NULL\n");
+ return -EINVAL;
+ }
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
+ printk("isofs_file_read: mode = %07o\n",inode->i_mode);
+ return -EINVAL;
+ }
+ if (inode->u.isofs_i.i_file_format == ISOFS_FILE_UNKNOWN)
+ isofs_determine_filetype(inode);
+ if (filp->f_pos > inode->i_size)
+ left = 0;
+ else
+ left = inode->i_size - filp->f_pos;
+ if (left > count)
+ left = count;
+ if (left <= 0)
+ return 0;
+ read = 0;
+ block = filp->f_pos >> ISOFS_BUFFER_BITS;
+ offset = filp->f_pos & (ISOFS_BUFFER_SIZE-1);
+ blocks = (left + offset + ISOFS_BUFFER_SIZE - 1) / ISOFS_BUFFER_SIZE;
+ bhb = bhe = buflist;
+
+ ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
+ max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE;
+ nextblock = -1;
+
+ /* We do this in a two stage process. We first try and request
+ as many blocks as we can, then we wait for the first one to
+ complete, and then we try and wrap up as many as are actually
+ done. This routine is rather generic, in that it can be used
+ in a filesystem by substituting the appropriate function in
+ for getblk.
+
+ This routine is optimized to make maximum use of the various
+ buffers and caches. */
+
+ do {
+ bhrequest = 0;
+ while (blocks) {
+ int uptodate;
+ --blocks;
+ *bhb = getblk(inode->i_dev,isofs_bmap(inode, block++), ISOFS_BUFFER_SIZE);
+ uptodate = 1;
+ if (*bhb && !(*bhb)->b_uptodate) {
+ uptodate = 0;
+ bhreq[bhrequest++] = *bhb;
+ nextblock = (*bhb)->b_blocknr + 1;
+ };
+
+ if (++bhb == &buflist[NBUF])
+ bhb = buflist;
+
+ /* If the block we have on hand is uptodate, go ahead
+ and complete processing. */
+ if(bhrequest == 0 && uptodate) break;
+
+ if (bhb == bhe)
+ break;
+ }
+
+ if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) {
+ /* If we are going to read something anyways, add in the
+ read-ahead blocks */
+ while(ra_blocks){
+ if (block >= max_block) break;
+ if(bhrequest == NBUF) break; /* Block full */
+ --ra_blocks;
+ *bhb = getblk(inode->i_dev,isofs_bmap(inode, block++), ISOFS_BUFFER_SIZE);
+
+ if (*bhb && !(*bhb)->b_uptodate) {
+ if((*bhb)->b_blocknr != nextblock) {
+ brelse(*bhb);
+ break;
+ };
+ nextblock = (*bhb)->b_blocknr + 1;
+ bhreq[bhrequest++] = *bhb;
+ };
+
+ if (++bhb == &buflist[NBUF])
+ bhb = buflist;
+
+ if (bhb == bhe)
+ break;
+ };
+ };
+ /* Now request them all */
+ if (bhrequest)
+ ll_rw_block(READ, bhrequest, bhreq);
+
+ do{ /* Finish off all I/O that has actually completed */
+ if (*bhe) {/* test for valid buffer */
+ wait_on_buffer(*bhe);
+ if (!(*bhe)->b_uptodate) {
+ do {
+ brelse(*bhe);
+ if (++bhe == &buflist[NBUF])
+ bhe = buflist;
+ } while (bhe != bhb);
+ break;
+ }
+ }
+
+ if (left < ISOFS_BUFFER_SIZE - offset)
+ chars = left;
+ else
+ chars = ISOFS_BUFFER_SIZE - offset;
+ filp->f_pos += chars;
+ left -= chars;
+ read += chars;
+ if (*bhe) {
+ if (inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT ||
+ inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT_M)
+ unixify_text_buffer(offset+(*bhe)->b_data,
+ chars, inode->u.isofs_i.i_file_format);
+ memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
+ brelse(*bhe);
+ buf += chars;
+ } else {
+ while (chars-->0)
+ put_fs_byte(0,buf++);
+ }
+ offset = 0;
+ if (++bhe == &buflist[NBUF])
+ bhe = buflist;
+ } while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) &&
+ (left > 0));
+ } while (left > 0);
+
+/* Release the read-ahead blocks */
+ while (bhe != bhb) {
+ if (*bhe) brelse(*bhe);
+ if (++bhe == &buflist[NBUF])
+ bhe = buflist;
+ };
+
+ filp->f_reada = 1;
+
+ if (!read)
+ return -EIO;
+ return read;
+}
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
new file mode 100644
index 0000000..7585abb
--- /dev/null
+++ b/fs/isofs/inode.c
@@ -0,0 +1,579 @@
+/*
+ * linux/fs/isofs/inode.c
+ *
+ * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
+ *
+ * (C) 1991 Linus Torvalds - minix filesystem
+ */
+#include <linux/config.h>
+#include <linux/stat.h>
+#include <linux/sched.h>
+#include <linux/iso_fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <linux/errno.h>
+
+#ifndef CONFIG_BLK_DEV_SR
+#error The iso9660 filesystem can only be used with CDROM.
+#endif
+
+extern int check_cdrom_media_change(int, int);
+
+#ifdef LEAK_CHECK
+static int check_malloc = 0;
+static int check_bread = 0;
+#endif
+
+void isofs_put_super(struct super_block *sb)
+{
+ lock_super(sb);
+
+#ifdef LEAK_CHECK
+ printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
+ check_malloc, check_bread);
+#endif
+ sb->s_dev = 0;
+ unlock_super(sb);
+ return;
+}
+
+static struct super_operations isofs_sops = {
+ isofs_read_inode,
+ NULL, /* notify_change */
+ NULL, /* write_inode */
+ NULL, /* put_inode */
+ isofs_put_super,
+ NULL, /* write_super */
+ isofs_statfs
+};
+
+
+
+static int parse_options(char *options,char *map,char *conversion, char * rock, char * cruft)
+{
+ char *this,*value;
+
+ *map = 'n';
+ *rock = 'y';
+ *cruft = 'n';
+ *conversion = 'a';
+ if (!options) return 1;
+ for (this = strtok(options,","); this; this = strtok(NULL,",")) {
+ if (strncmp(this,"norock",6) == 0) {
+ *rock = 'n';
+ continue;
+ };
+ if (strncmp(this,"cruft",5) == 0) {
+ *cruft = 'y';
+ continue;
+ };
+ if ((value = strchr(this,'=')) != NULL)
+ *value++ = 0;
+ if (!strcmp(this,"map") && value) {
+ if (value[0] && !value[1] && strchr("on",*value))
+ *map = *value;
+ else if (!strcmp(value,"off")) *map = 'o';
+ else if (!strcmp(value,"normal")) *map = 'n';
+ else return 0;
+ }
+ else if (!strcmp(this,"conv") && value) {
+ if (value[0] && !value[1] && strchr("bta",*value))
+ *conversion = *value;
+ else if (!strcmp(value,"binary")) *conversion = 'b';
+ else if (!strcmp(value,"text")) *conversion = 't';
+ else if (!strcmp(value,"mtext")) *conversion = 'm';
+ else if (!strcmp(value,"auto")) *conversion = 'a';
+ else return 0;
+ }
+ else return 0;
+ }
+ return 1;
+}
+
+struct super_block *isofs_read_super(struct super_block *s,void *data)
+{
+ struct buffer_head *bh;
+ int iso_blknum;
+ int high_sierra;
+ int dev=s->s_dev;
+ struct iso_volume_descriptor *vdp;
+ struct hs_volume_descriptor *hdp;
+
+ struct iso_primary_descriptor *pri = NULL;
+ struct hs_primary_descriptor *h_pri = NULL;
+
+ struct iso_directory_record *rootp;
+
+ char map, conversion, rock, cruft;
+
+ if (!parse_options((char *) data,&map,&conversion, &rock, &cruft)) {
+ s->s_dev = 0;
+ return NULL;
+ }
+
+ lock_super(s);
+
+ s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
+
+ for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
+ if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-ISOFS_BUFFER_BITS), ISOFS_BUFFER_SIZE))) {
+ s->s_dev=0;
+ printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n",
+ dev, iso_blknum);
+ unlock_super(s);
+ return NULL;
+ }
+
+ vdp = (struct iso_volume_descriptor *)bh->b_data;
+ hdp = (struct hs_volume_descriptor *)bh->b_data;
+
+
+ if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
+ if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
+ goto out;
+ if (isonum_711 (hdp->type) == ISO_VD_END)
+ goto out;
+
+ s->u.isofs_sb.s_high_sierra = 1;
+ high_sierra = 1;
+ rock = 'n';
+ h_pri = (struct hs_primary_descriptor *)vdp;
+ break;
+ };
+
+ if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
+ if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
+ goto out;
+ if (isonum_711 (vdp->type) == ISO_VD_END)
+ goto out;
+
+ pri = (struct iso_primary_descriptor *)vdp;
+ break;
+ };
+
+ brelse(bh);
+ }
+ if(iso_blknum == 100) {
+ printk("Unable to identify CD-ROM format.\n");
+ s->s_dev = 0;
+ unlock_super(s);
+ return NULL;
+ };
+
+
+ if(high_sierra){
+ rootp = (struct iso_directory_record *) h_pri->root_directory_record;
+ if (isonum_723 (h_pri->volume_set_size) != 1) {
+ printk("Multi-volume disks not (yet) supported.\n");
+ goto out;
+ };
+ s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
+ s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
+ s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
+ } else {
+ rootp = (struct iso_directory_record *) pri->root_directory_record;
+ if (isonum_723 (pri->volume_set_size) != 1) {
+ printk("Multi-volume disks not (yet) supported.\n");
+ goto out;
+ };
+ s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
+ s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
+ s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
+ }
+
+ s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */
+
+ s->u.isofs_sb.s_firstdatazone = isonum_733( rootp->extent) <<
+ (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
+ s->s_magic = ISOFS_SUPER_MAGIC;
+
+ /* The CDROM is read-only, has no nodes (devices) on it, and since
+ all of the files appear to be owned by root, we really do not want
+ to allow suid. (suid or devices will not show up unless we have
+ Rock Ridge extensions) */
+
+ s->s_flags = MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
+
+ if(s->u.isofs_sb.s_log_zone_size != (1 << ISOFS_BLOCK_BITS)) {
+ printk("1 <<Block bits != Block size\n");
+ goto out;
+ };
+
+ brelse(bh);
+
+ printk("Max size:%d Log zone size:%d\n",s->u.isofs_sb.s_max_size,
+ s->u.isofs_sb.s_log_zone_size);
+ printk("First datazone:%d Root inode number %d\n",s->u.isofs_sb.s_firstdatazone,
+ isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
+ if(high_sierra) printk("Disc in High Sierra format.\n");
+ unlock_super(s);
+ /* set up enough so that it can read an inode */
+
+ s->s_dev = dev;
+ s->s_op = &isofs_sops;
+ s->u.isofs_sb.s_mapping = map;
+ s->u.isofs_sb.s_rock = (rock == 'y' ? 1 : 0);
+ s->u.isofs_sb.s_conversion = conversion;
+ s->u.isofs_sb.s_cruft = cruft;
+ s->s_blocksize = ISOFS_BUFFER_SIZE;
+ s->s_mounted = iget(s, isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
+ unlock_super(s);
+
+ if (!(s->s_mounted)) {
+ s->s_dev=0;
+ printk("get root inode failed\n");
+ return NULL;
+ }
+ if(MAJOR(s->s_dev) == 11) {
+ /* Chech this one more time. */
+ if(check_cdrom_media_change(s->s_dev, 0))
+ goto out;
+ };
+ return s;
+ out: /* Kick out for various error conditions */
+ brelse(bh);
+ s->s_dev = 0;
+ unlock_super(s);
+ return NULL;
+}
+
+void isofs_statfs (struct super_block *sb, struct statfs *buf)
+{
+ put_fs_long(ISOFS_SUPER_MAGIC, &buf->f_type);
+ put_fs_long(1 << ISOFS_BLOCK_BITS, &buf->f_bsize);
+ put_fs_long(sb->u.isofs_sb.s_nzones, &buf->f_blocks);
+ put_fs_long(0, &buf->f_bfree);
+ put_fs_long(0, &buf->f_bavail);
+ put_fs_long(sb->u.isofs_sb.s_ninodes, &buf->f_files);
+ put_fs_long(0, &buf->f_ffree);
+ /* Don't know what value to put in buf->f_fsid */
+}
+
+int isofs_bmap(struct inode * inode,int block)
+{
+
+ if (block<0) {
+ printk("_isofs_bmap: block<0");
+ return 0;
+ }
+ return inode->u.isofs_i.i_first_extent + block;
+}
+
+void isofs_read_inode(struct inode * inode)
+{
+ struct buffer_head * bh;
+ unsigned char * pnt, *cpnt = 0;
+ struct iso_directory_record * raw_inode;
+ int high_sierra;
+ int block;
+ int i;
+
+ block = inode->i_ino >> ISOFS_BUFFER_BITS;
+ if (!(bh=bread(inode->i_dev,block, ISOFS_BUFFER_SIZE)))
+ panic("unable to read i-node block");
+
+ pnt = ((char *) bh->b_data) + (inode->i_ino & (ISOFS_BUFFER_SIZE - 1));
+
+ raw_inode = ((struct iso_directory_record *) pnt);
+ high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
+
+ if ((inode->i_ino & (ISOFS_BUFFER_SIZE - 1)) + *pnt > ISOFS_BUFFER_SIZE){
+ cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
+ memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
+ brelse(bh);
+ if (!(bh = bread(inode->i_dev,++block, ISOFS_BUFFER_SIZE)))
+ panic("unable to read i-node block");
+ memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
+ pnt = ((char *) cpnt) + (inode->i_ino & (ISOFS_BUFFER_SIZE - 1));
+ raw_inode = ((struct iso_directory_record *) pnt);
+ };
+
+
+ inode->i_mode = 0444; /* Everybody gets to read the file. */
+ inode->i_nlink = 1;
+
+ if (raw_inode->flags[-high_sierra] & 2) {
+ inode->i_mode = 0555 | S_IFDIR;
+ inode->i_nlink = 2; /* There are always at least 2. It is
+ hard to figure out what is correct*/
+ } else {
+ inode->i_mode = 0444; /* Everybody gets to read the file. */
+ inode->i_nlink = 1;
+ inode->i_mode |= S_IFREG;
+/* If there are no periods in the name, then set the execute permission bit */
+ for(i=0; i< raw_inode->name_len[0]; i++)
+ if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
+ break;
+ if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
+ inode->i_mode |= 0111; /* execute permission */
+ };
+ inode->i_uid = 0;
+ inode->i_gid = 0;
+ inode->i_size = isonum_733 (raw_inode->size);
+
+/* Some dipshit decided to store some other bit of information in the high
+ byte of the file length. Catch this and holler. WARNING: this will make
+ it impossible for a file to be > 16Mb on the CDROM!!!*/
+
+ if(inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
+ inode->i_size & 0xff000000){
+/* printk("Illegal format on cdrom. Pester manufacturer.\n"); */
+ inode->i_size &= 0x00ffffff;
+ };
+
+ if (isonum_723 (raw_inode->volume_sequence_number) != 1) {
+ panic("Multi volume CD somehow got mounted.\n");
+ };
+
+ if (raw_inode->interleave[0]) {
+ printk("Interleaved files not (yet) supported.\n");
+ inode->i_size = 0;
+ };
+
+#ifdef DEBUG
+ /* I have no idea what extended attributes are used for, so
+ we will flag it for now */
+ if(raw_inode->ext_attr_length[0] != 0){
+ printk("Extended attributes present for ISO file (%d).\n",
+ inode->i_ino);
+ }
+#endif
+
+ /* I have no idea what file_unit_size is used for, so
+ we will flag it for now */
+ if(raw_inode->file_unit_size[0] != 0){
+ printk("File unit size != 0 for ISO file.(%d)\n",inode->i_ino);
+ }
+
+ /* I have no idea what other flag bits are used for, so
+ we will flag it for now */
+ if((raw_inode->flags[-high_sierra] & ~2)!= 0){
+ printk("Unusual flag settings for ISO file.(%d %x)\n",
+ inode->i_ino, raw_inode->flags[-high_sierra]);
+ }
+
+#ifdef DEBUG
+ printk("Get inode %d: %d %d: %d\n",inode->i_ino, block,
+ ((int)pnt) & 0x3ff, inode->i_size);
+#endif
+
+ inode->i_mtime = inode->i_atime = inode->i_ctime =
+ iso_date(raw_inode->date, high_sierra);
+
+ inode->u.isofs_i.i_first_extent = isonum_733 (raw_inode->extent) <<
+ (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
+
+ inode->u.isofs_i.i_backlink = -1; /* Will be used for previous directory */
+ switch (inode->i_sb->u.isofs_sb.s_conversion){
+ case 'a':
+ inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN; /* File type */
+ break;
+ case 'b':
+ inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY; /* File type */
+ break;
+ case 't':
+ inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT; /* File type */
+ break;
+ case 'm':
+ inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M; /* File type */
+ break;
+ };
+
+
+/* Now test for possible Rock Ridge extensions which will override some of
+ these numbers in the inode structure. */
+
+ if (!high_sierra)
+ parse_rock_ridge_inode(raw_inode, inode);
+
+#ifdef DEBUG
+ printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
+#endif
+ brelse(bh);
+
+ if (cpnt) {
+ kfree_s (cpnt, 1 << ISOFS_BLOCK_BITS);
+ cpnt = 0;
+ };
+
+ inode->i_op = NULL;
+ if (S_ISREG(inode->i_mode))
+ inode->i_op = &isofs_file_inode_operations;
+ else if (S_ISDIR(inode->i_mode))
+ inode->i_op = &isofs_dir_inode_operations;
+ else if (S_ISLNK(inode->i_mode))
+ inode->i_op = &isofs_symlink_inode_operations;
+ else if (S_ISCHR(inode->i_mode))
+ inode->i_op = &isofs_chrdev_inode_operations;
+ else if (S_ISBLK(inode->i_mode))
+ inode->i_op = &isofs_blkdev_inode_operations;
+}
+
+/* There are times when we need to know the inode number of a parent of
+ a particular directory. When control passes through a routine that
+ has access to the parent information, it fills it into the inode structure,
+ but sometimes the inode gets flushed out of the queue, and someone
+ remmembers the number. When they try to open up again, we have lost
+ the information. The '..' entry on the disc points to the data area
+ for a particular inode, so we can follow these links back up, but since
+ we do not know the inode number, we do not actually know how large the
+ directory is. The disc is almost always correct, and there is
+ enough error checking on the drive itself, but an open ended search
+ makes me a little nervous.
+
+ The bsd iso filesystem uses the extent number for an inode, and this
+ would work really nicely for us except that the read_inode function
+ would not have any clean way of finding the actual directory record
+ that goes with the file. If we had such info, then it would pay
+ to change the inode numbers and eliminate this function.
+*/
+
+int isofs_lookup_grandparent(struct inode * parent, int extent) {
+ unsigned int block,offset;
+ int parent_dir, inode_number;
+ int old_offset;
+ char * cpnt = 0;
+ int result;
+ struct buffer_head * bh;
+ struct iso_directory_record * de;
+
+ offset = 0;
+ block = extent << (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
+ if (!(bh = bread(parent->i_dev, block, ISOFS_BUFFER_SIZE))) return 0;
+
+ while (1 == 1) {
+ de = (struct iso_directory_record *) (offset + bh->b_data);
+
+ if (*((char*) de) == 0)
+ {
+ brelse(bh);
+ return -1;
+ }
+
+ offset += *((unsigned char*) de);
+
+ if (offset >= ISOFS_BUFFER_SIZE)
+ {
+ printk(".. Directory not in first block of directory.\n");
+ brelse(bh);
+ return -1;
+ }
+
+ if (de->name_len[0] == 1 && de->name[0] == 1)
+ {
+ brelse(bh);
+ parent_dir = find_rock_ridge_relocation(de, parent);
+ break;
+ };
+ }
+#ifdef DEBUG
+ printk("Parent dir:%x\n",parent_dir);
+#endif
+ /* Now we know the extent where the parent dir starts on. We have no
+ idea how long it is, so we just start reading until we either find it
+ or we find some kind of unreasonable circumstance. */
+
+ result = -1;
+
+ offset = 0;
+ block = parent_dir << (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
+ if (!block || !(bh = bread(parent->i_dev,block, ISOFS_BUFFER_SIZE)))
+ return 0;
+
+ while (1==1) {
+ de = (struct iso_directory_record *) (offset + bh->b_data);
+ inode_number = (block << ISOFS_BUFFER_BITS)+(offset & (ISOFS_BUFFER_SIZE - 1));
+
+ /* If the length byte is zero, we should move on to the next CDROM sector.
+ If we are at the end of the directory, we kick out of the while loop. */
+
+ if (*((char*) de) == 0)
+ {
+ brelse(bh);
+ offset = 0;
+ block++;
+ if(block & 1) return -1;
+ if (!block || !(bh = bread(parent->i_dev,block, ISOFS_BUFFER_SIZE)))
+ return -1;
+ continue;
+ }
+
+ /* Make sure that the entire directory record is in the current bh block.
+ If not, we malloc a buffer, and put the two halves together, so that
+ we can cleanly read the block */
+
+ old_offset = offset;
+ offset += *((unsigned char*) de);
+ if (offset >= ISOFS_BUFFER_SIZE)
+ {
+ cpnt = kmalloc(1<<ISOFS_BLOCK_BITS,GFP_KERNEL);
+ memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
+ de = (struct iso_directory_record *) (old_offset + cpnt);
+ brelse(bh);
+ offset -= ISOFS_BUFFER_SIZE;
+ block++;
+ if((block & 1) == 0) return -1;
+ if (!(bh = bread(parent->i_dev,block, ISOFS_BUFFER_SIZE)))
+ return -1;
+ memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
+ }
+
+ if (find_rock_ridge_relocation(de, parent) == extent){
+ result = inode_number;
+ goto out;
+ };
+
+ if (cpnt) {
+ kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
+ cpnt = 0;
+ };
+ }
+ /* We go here for any condition we cannot handle. We also drop through
+ to here at the end of the directory. */
+
+ out:
+ if (cpnt) {
+ kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
+ cpnt = 0;
+ };
+ brelse(bh);
+#ifdef DEBUG
+ printk("Resultant Inode %d\n",result);
+#endif
+ return result;
+}
+
+#ifdef LEAK_CHECK
+#undef malloc
+#undef free_s
+#undef bread
+#undef brelse
+
+void * leak_check_malloc(unsigned int size){
+ void * tmp;
+ check_malloc++;
+ tmp = kmalloc(size, GFP_KERNEL);
+ return tmp;
+}
+
+void leak_check_free_s(void * obj, int size){
+ check_malloc--;
+ return kfree_s(obj, size);
+}
+
+struct buffer_head * leak_check_bread(int dev, int block, int size){
+ check_bread++;
+ return bread(dev, block, size);
+}
+
+void leak_check_brelse(struct buffer_head * bh){
+ check_bread--;
+ return brelse(bh);
+}
+
+#endif
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
new file mode 100644
index 0000000..1481bf2
--- /dev/null
+++ b/fs/isofs/namei.c
@@ -0,0 +1,248 @@
+/*
+ * linux/fs/isofs/namei.c
+ *
+ * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
+ *
+ * (C) 1991 Linus Torvalds - minix filesystem
+ */
+
+#include <linux/sched.h>
+#include <linux/iso_fs.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <asm/segment.h>
+
+#include <linux/errno.h>
+
+/*
+ * ok, we cannot use strncmp, as the name is not in our data space.
+ * Thus we'll have to use isofs_match. No big problem. Match also makes
+ * some sanity tests.
+ *
+ * NOTE! unlike strncmp, isofs_match returns 1 for success, 0 for failure.
+ */
+static int isofs_match(int len,const char * name, char * compare, int dlen)
+{
+ register int same __asm__("ax");
+
+ if (!compare) return 0;
+ /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
+ if (!len && (compare[0]==0) && (dlen==1))
+ return 1;
+
+ if (compare[0]==0 && dlen==1 && len == 1)
+ compare = ".";
+ if (compare[0]==1 && dlen==1 && len == 2) {
+ compare = "..";
+ dlen = 2;
+ };
+#if 0
+ if (len <= 2) printk("Match: %d %d %s %d %d \n",len,dlen,compare,de->name[0], dlen);
+#endif
+
+ if (dlen != len)
+ return 0;
+ __asm__("cld\n\t"
+ "fs ; repe ; cmpsb\n\t"
+ "setz %%al"
+ :"=a" (same)
+ :"0" (0),"S" ((long) name),"D" ((long) compare),"c" (len)
+ :"cx","di","si");
+ return same;
+}
+
+/*
+ * isofs_find_entry()
+ *
+ * finds an entry in the specified directory with the wanted name. It
+ * returns the cache buffer in which the entry was found, and the entry
+ * itself (as an inode number). It does NOT read the inode of the
+ * entry - you'll have to do that yourself if you want to.
+ */
+static struct buffer_head * isofs_find_entry(struct inode * dir,
+ const char * name, int namelen, int * ino, int * ino_back)
+{
+ unsigned int block,i, f_pos, offset, inode_number;
+ struct buffer_head * bh;
+ char * cpnt = 0;
+ unsigned int old_offset;
+ unsigned int backlink;
+ int dlen, rrflag, match;
+ char * dpnt;
+ struct iso_directory_record * de;
+ char c;
+
+ *ino = 0;
+ if (!dir) return NULL;
+
+ if (!(block = dir->u.isofs_i.i_first_extent)) return NULL;
+
+ f_pos = 0;
+
+ offset = f_pos & (ISOFS_BUFFER_SIZE - 1);
+ block = isofs_bmap(dir,f_pos >> ISOFS_BUFFER_BITS);
+ if (!block || !(bh = bread(dir->i_dev,block,ISOFS_BUFFER_SIZE))) return NULL;
+
+ while (f_pos < dir->i_size) {
+ de = (struct iso_directory_record *) (offset + bh->b_data);
+ backlink = dir->i_ino;
+ inode_number = (block << ISOFS_BUFFER_BITS)+(offset & (ISOFS_BUFFER_SIZE - 1));
+
+ /* If byte is zero, this is the end of file, or time to move to
+ the next sector. Usually 2048 byte boundaries. */
+
+ if (*((unsigned char*) de) == 0) {
+ brelse(bh);
+ offset = 0;
+ f_pos =(f_pos & ~(ISOFS_BLOCK_SIZE - 1))+ISOFS_BLOCK_SIZE;
+ block = isofs_bmap(dir,(f_pos)>>ISOFS_BUFFER_BITS);
+ if (!block || !(bh = bread(dir->i_dev,block,ISOFS_BUFFER_SIZE)))
+ return 0;
+ continue; /* Will kick out if past end of directory */
+ };
+
+ old_offset = offset;
+ offset += *((unsigned char*) de);
+ f_pos += *((unsigned char*) de);
+
+ /* Handle case where the directory entry spans two blocks. Usually
+ 1024 byte boundaries */
+
+ if (offset >= ISOFS_BUFFER_SIZE) {
+ cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
+ memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
+ de = (struct iso_directory_record *) (old_offset + cpnt);
+ brelse(bh);
+ offset = f_pos & (ISOFS_BUFFER_SIZE - 1);
+ block = isofs_bmap(dir,f_pos>>ISOFS_BUFFER_BITS);
+ if (!block || !(bh = bread(dir->i_dev,block,ISOFS_BUFFER_SIZE)))
+ return 0;
+ memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
+ }
+
+ /* Handle the '.' case */
+
+ if (de->name[0]==0 && de->name_len[0]==1) {
+ inode_number = dir->i_ino;
+ backlink = 0;
+ }
+
+ /* Handle the '..' case */
+
+ if (de->name[0]==1 && de->name_len[0]==1) {
+#if 0
+ printk("Doing .. (%d %d)",dir->i_sb->s_firstdatazone << ISOFS_BUFFER_BITS, dir->i_ino);
+#endif
+ if((dir->i_sb->u.isofs_sb.s_firstdatazone << ISOFS_BUFFER_BITS) != dir->i_ino)
+ inode_number = dir->u.isofs_i.i_backlink;
+ else
+ inode_number = dir->i_ino;
+ backlink = 0;
+ }
+
+ dlen = de->name_len[0];
+ dpnt = de->name;
+ /* Now convert the filename in the buffer to lower case */
+ rrflag = get_rock_ridge_filename(de, &dpnt, &dlen, dir);
+ if (rrflag) {
+ if (rrflag == -1) goto out; /* Relocated deep directory */
+ } else {
+ if(dir->i_sb->u.isofs_sb.s_mapping == 'n') {
+ for (i = 0; i < dlen; i++) {
+ c = dpnt[i];
+ if (c >= 'A' && c <= 'Z') c |= 0x20; /* lower case */
+ if (c == ';' && i == dlen-2 && dpnt[i+1] == '1') {
+ dlen -= 2;
+ break;
+ };
+ if (c == ';') c = '.';
+ de->name[i] = c;
+ };
+ /* This allows us to match with and without a trailing period */
+ if(dpnt[dlen-1] == '.' && namelen == dlen-1)
+ dlen--;
+ };
+ };
+ match = isofs_match(namelen,name,dpnt, dlen);
+ if (cpnt) { kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS); cpnt = 0;};
+
+ if(rrflag) kfree(dpnt);
+ if (match) {
+ if(inode_number == -1) { /* Should only happen for the '..' entry */
+ inode_number =
+ isofs_lookup_grandparent(dir,
+ find_rock_ridge_relocation(de,dir));
+ if(inode_number == -1){ /* Should never happen */
+ printk("Backlink not properly set.\n");
+ goto out;
+ };
+ };
+ *ino = inode_number;
+ *ino_back = backlink;
+ return bh;
+ }
+ }
+ out:
+ if (cpnt) kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
+ brelse(bh);
+ return NULL;
+}
+
+int isofs_lookup(struct inode * dir,const char * name, int len,
+ struct inode ** result)
+{
+ int ino, ino_back;
+ struct buffer_head * bh;
+
+#ifdef DEBUG
+ printk("lookup: %x %d\n",dir->i_ino, len);
+#endif
+ *result = NULL;
+ if (!dir)
+ return -ENOENT;
+
+ if (!S_ISDIR(dir->i_mode)) {
+ iput(dir);
+ return -ENOENT;
+ }
+
+ ino = 0;
+ while(cache.lock);
+ cache.lock = 1;
+ if (dir->i_dev == cache.dev &&
+ dir->i_ino == cache.dir &&
+ len == cache.dlen &&
+ isofs_match(len, name, cache.filename, cache.dlen))
+ {
+ ino = cache.ino;
+ ino_back = dir->i_ino;
+ /* These two cases are special, but since they are at the start
+ of the directory, we can just as easily search there */
+ if (cache.dlen == 1 && cache.filename[0] == '.') ino = 0;
+ if (cache.dlen == 2 && cache.filename[0] == '.' &&
+ cache.filename[1] == '.') ino = 0;
+ };
+ cache.lock = 0;
+
+ if (!ino) {
+ if (!(bh = isofs_find_entry(dir,name,len, &ino, &ino_back))) {
+ iput(dir);
+ return -ENOENT;
+ }
+ brelse(bh);
+ };
+
+ if (!(*result = iget(dir->i_sb,ino))) {
+ iput(dir);
+ return -EACCES;
+ }
+
+ /* We need this backlink for the .. entry */
+
+ if (ino_back) (*result)->u.isofs_i.i_backlink = ino_back;
+
+ iput(dir);
+ return 0;
+}
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
new file mode 100644
index 0000000..eb6f071
--- /dev/null
+++ b/fs/isofs/rock.c
@@ -0,0 +1,463 @@
+/*
+ * linux/fs/isofs/rock.c
+ *
+ * (C) 1992 Eric Youngdale
+ *
+ * Rock Ridge Extensions to iso9660
+ */
+#include <linux/config.h>
+#include <linux/stat.h>
+#include <linux/sched.h>
+#include <linux/iso_fs.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+
+#include "rock.h"
+
+/* These functions are designed to read the system areas of a directory record
+ * and extract relevant information. There are different functions provided
+ * depending upon what information we need at the time. One function fills
+ * out an inode structure, a second one extracts a filename, a third one
+ * returns a symbolic link name, and a fourth one returns the extent number
+ * for the file. */
+
+#define SIG(A,B) ((A << 8) | B)
+
+
+/* This is a way of ensuring that we have something in the system
+ use fields that is compatible with Rock Ridge */
+#define CHECK_SP(FAIL) \
+ if(rr->u.SP.magic[0] != 0xbe) FAIL; \
+ if(rr->u.SP.magic[1] != 0xef) FAIL;
+
+/* We define a series of macros because each function must do exactly the
+ same thing in certain places. We use the macros to ensure that everyting
+ is done correctly */
+
+#define CONTINUE_DECLS \
+ int cont_extent = 0, cont_offset = 0, cont_size = 0; \
+ char * buffer = 0
+
+#define CHECK_CE \
+ {cont_extent = isonum_733(rr->u.CE.extent); \
+ cont_offset = isonum_733(rr->u.CE.offset); \
+ cont_size = isonum_733(rr->u.CE.size);}
+
+#define SETUP_ROCK_RIDGE(DE,CHR,LEN) \
+ {LEN= sizeof(struct iso_directory_record) + DE->name_len[0]; \
+ if(LEN & 1) LEN++; \
+ CHR = ((unsigned char *) DE) + LEN; \
+ LEN = *((unsigned char *) DE) - LEN;}
+
+#define MAYBE_CONTINUE(LABEL,DEV) \
+ {if (buffer) kfree(buffer); \
+ if (cont_extent){ \
+ int block, offset; \
+ struct buffer_head * bh; \
+ buffer = kmalloc(cont_size,GFP_KERNEL); \
+ block = cont_extent << 1; \
+ offset = cont_offset; \
+ if (offset >= 1024) block++; \
+ offset &= 1023; \
+ bh = bread(DEV, block, 1024); \
+ memcpy(buffer, bh->b_data, cont_size); \
+ brelse(bh); \
+ chr = buffer; \
+ len = cont_size; \
+ cont_extent = 0; \
+ cont_size = 0; \
+ cont_offset = 0; \
+ goto LABEL; \
+ }}
+
+
+/* This is the inner layer of the get filename routine, and is called
+ for each system area and continuation record related to the file */
+
+int find_rock_ridge_relocation(struct iso_directory_record * de,
+ struct inode * inode) {
+ int flag;
+ int len;
+ int retval;
+ unsigned char * chr;
+ CONTINUE_DECLS;
+ flag = 0;
+
+ /* If this is a '..' then we are looking for the parent, otherwise we
+ are looking for the child */
+
+ if (de->name[0]==1 && de->name_len[0]==1) flag = 1;
+ /* Return value if we do not find appropriate record. */
+ retval = isonum_733 (de->extent);
+
+ if (!inode->i_sb->u.isofs_sb.s_rock) return retval;
+
+ SETUP_ROCK_RIDGE(de, chr, len);
+ repeat:
+ {
+ int rrflag, sig;
+ struct rock_ridge * rr;
+
+ while (len > 1){ /* There may be one byte for padding somewhere */
+ rr = (struct rock_ridge *) chr;
+ if (rr->len == 0) goto out; /* Something got screwed up here */
+ sig = (chr[0] << 8) + chr[1];
+ chr += rr->len;
+ len -= rr->len;
+
+ switch(sig){
+ case SIG('R','R'):
+ rrflag = rr->u.RR.flags[0];
+ if (flag && !(rrflag & RR_PL)) goto out;
+ if (!flag && !(rrflag & RR_CL)) goto out;
+ break;
+ case SIG('S','P'):
+ CHECK_SP(goto out);
+ break;
+ case SIG('C','L'):
+ printk("RR: CL\n");
+ if (flag == 0) {
+ retval = isonum_733(rr->u.CL.location);
+ goto out;
+ };
+ break;
+ case SIG('P','L'):
+ printk("RR: PL\n");
+ if (flag != 0) {
+ retval = isonum_733(rr->u.PL.location);
+ goto out;
+ };
+ break;
+ case SIG('C','E'):
+ CHECK_CE; /* This tells is if there is a continuation record */
+ break;
+ default:
+ break;
+ }
+ };
+ };
+ MAYBE_CONTINUE(repeat, inode->i_dev);
+ return retval;
+ out:
+ if(buffer) kfree(buffer);
+ return retval;
+}
+
+int get_rock_ridge_filename(struct iso_directory_record * de,
+ char ** name, int * namlen, struct inode * inode)
+{
+ int len;
+ unsigned char * chr;
+ CONTINUE_DECLS;
+ char * retname = NULL;
+ int retnamlen = 0, truncate=0;
+
+ if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
+
+ SETUP_ROCK_RIDGE(de, chr, len);
+ repeat:
+ {
+ struct rock_ridge * rr;
+ int sig;
+
+ while (len > 1){ /* There may be one byte for padding somewhere */
+ rr = (struct rock_ridge *) chr;
+ if (rr->len == 0) goto out; /* Something got screwed up here */
+ sig = (chr[0] << 8) + chr[1];
+ chr += rr->len;
+ len -= rr->len;
+
+ switch(sig){
+ case SIG('R','R'):
+ if((rr->u.RR.flags[0] & RR_NM) == 0) goto out;
+ break;
+ case SIG('S','P'):
+ CHECK_SP(goto out);
+ break;
+ case SIG('C','E'):
+ CHECK_CE;
+ break;
+ case SIG('N','M'):
+ if (truncate) break;
+ if (rr->u.NM.flags & ~1) {
+ printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
+ break;
+ };
+ if (!retname){
+ retname = (char *) kmalloc (255,GFP_KERNEL);
+ /* This may be a waste, but we only
+ need this for a moment. The layers
+ that call this function should
+ deallocate the mem fairly soon
+ after control is returned */
+
+ *retname = 0; /* Zero length string */
+ retnamlen = 0;
+ };
+ if((strlen(retname) + rr->len - 5) >= 254) {
+ truncate = 1;
+ break;
+ };
+ strncat(retname, rr->u.NM.name, rr->len - 5);
+ retnamlen += rr->len - 5;
+ break;
+ case SIG('R','E'):
+ printk("RR: RE (%x)\n", inode->i_ino);
+ if (buffer) kfree(buffer);
+ if (retname) kfree(retname);
+ return -1;
+ default:
+ break;
+ }
+ };
+ }
+ MAYBE_CONTINUE(repeat,inode->i_dev);
+ if(retname){
+ *name = retname;
+ *namlen = retnamlen;
+ return 1;
+ };
+ return 0; /* This file did not have a NM field */
+ out:
+ if(buffer) kfree(buffer);
+ if (retname) kfree(retname);
+ return 0;
+}
+
+int parse_rock_ridge_inode(struct iso_directory_record * de,
+ struct inode * inode){
+ int len;
+ unsigned char * chr;
+ CONTINUE_DECLS;
+
+ if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
+
+ SETUP_ROCK_RIDGE(de, chr, len);
+ repeat:
+ {
+ int cnt, sig;
+ struct inode * reloc;
+ struct rock_ridge * rr;
+
+ while (len > 1){ /* There may be one byte for padding somewhere */
+ rr = (struct rock_ridge *) chr;
+ if (rr->len == 0) goto out; /* Something got screwed up here */
+ sig = (chr[0] << 8) + chr[1];
+ chr += rr->len;
+ len -= rr->len;
+
+ switch(sig){
+ case SIG('R','R'):
+ if((rr->u.RR.flags[0] &
+ (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out;
+ break;
+ case SIG('S','P'):
+ CHECK_SP(goto out);
+ break;
+ case SIG('C','E'):
+ CHECK_CE;
+ break;
+ case SIG('E','R'):
+ printk("ISO9660 Extensions: ");
+ { int p;
+ for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
+ };
+ printk("\n");
+ break;
+ case SIG('P','X'):
+ inode->i_mode = isonum_733(rr->u.PX.mode);
+ inode->i_nlink = isonum_733(rr->u.PX.n_links);
+ inode->i_uid = isonum_733(rr->u.PX.uid);
+ inode->i_gid = isonum_733(rr->u.PX.gid);
+ break;
+ case SIG('P','N'):
+ { int high, low;
+ high = isonum_733(rr->u.PN.dev_high);
+ low = isonum_733(rr->u.PN.dev_low);
+ inode->i_rdev = ((high << 8) | (low && 0xff)) & 0xffff;
+ };
+ break;
+ case SIG('T','F'):
+ cnt = 0; /* Rock ridge never appears on a High Sierra disk */
+ if(rr->u.TF.flags & TF_CREATE) inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
+ if(rr->u.TF.flags & TF_MODIFY) inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
+ if(rr->u.TF.flags & TF_ACCESS) inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0);
+ break;
+ case SIG('S','L'):
+ {int slen;
+ struct SL_component * slp;
+ slen = rr->len - 5;
+ slp = &rr->u.SL.link;
+ while (slen > 1){
+ switch(slp->flags &~1){
+ case 0:
+ inode->i_size += slp->len;
+ break;
+ case 2:
+ inode->i_size += 1;
+ break;
+ case 4:
+ inode->i_size += 2;
+ break;
+ case 8:
+ inode->i_size += 1;
+ break;
+ default:
+ printk("Symlink component flag not implemented\n");
+ };
+ slen -= slp->len + 2;
+ slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
+
+ if(slen < 2) break;
+ inode->i_size += 1;
+ };
+ };
+ break;
+ case SIG('R','E'):
+ printk("Attempt to read inode for relocated directory\n");
+ goto out;
+ case SIG('C','L'):
+ printk("RR CL (%x)\n",inode->i_ino);
+ inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location);
+ reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent << ISOFS_BLOCK_BITS);
+ inode->i_mode = reloc->i_mode;
+ inode->i_nlink = reloc->i_nlink;
+ inode->i_uid = reloc->i_uid;
+ inode->i_gid = reloc->i_gid;
+ inode->i_rdev = reloc->i_rdev;
+ inode->i_size = reloc->i_size;
+ inode->i_atime = reloc->i_atime;
+ inode->i_ctime = reloc->i_ctime;
+ inode->i_mtime = reloc->i_mtime;
+ iput(reloc);
+ break;
+ default:
+ break;
+ }
+ };
+ }
+ MAYBE_CONTINUE(repeat,inode->i_dev);
+ return 0;
+ out:
+ if(buffer) kfree(buffer);
+ return 0;
+}
+
+
+/* Returns the name of the file that this inode is symlinked to. This is
+ in malloc'd memory, so it needs to be freed, once we are through with it */
+
+char * get_rock_ridge_symlink(struct inode * inode)
+{
+ struct buffer_head * bh;
+ unsigned char * pnt, *cpnt = 0;
+ char * rpnt;
+ struct iso_directory_record * raw_inode;
+ CONTINUE_DECLS;
+ int block;
+ int sig;
+ int len;
+ char * chr;
+ struct rock_ridge * rr;
+
+ if (!inode->i_sb->u.isofs_sb.s_rock)
+ panic("Cannot have symlink with high sierra variant of iso filesystem\n");
+
+ rpnt = 0;
+
+ block = inode->i_ino >> ISOFS_BUFFER_BITS;
+ if (!(bh=bread(inode->i_dev,block, ISOFS_BUFFER_SIZE)))
+ panic("unable to read i-node block");
+
+ pnt = ((char *) bh->b_data) + (inode->i_ino & (ISOFS_BUFFER_SIZE - 1));
+
+ raw_inode = ((struct iso_directory_record *) pnt);
+
+ if ((inode->i_ino & (ISOFS_BUFFER_SIZE - 1)) + *pnt > ISOFS_BUFFER_SIZE){
+ cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
+ memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
+ brelse(bh);
+ if (!(bh = bread(inode->i_dev,++block, ISOFS_BUFFER_SIZE)))
+ panic("unable to read i-node block");
+ memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
+ pnt = ((char *) cpnt) + (inode->i_ino & (ISOFS_BUFFER_SIZE - 1));
+ raw_inode = ((struct iso_directory_record *) pnt);
+ };
+
+ /* Now test for possible Rock Ridge extensions which will override some of
+ these numbers in the inode structure. */
+
+ SETUP_ROCK_RIDGE(raw_inode, chr, len);
+
+ repeat:
+ while (len > 1){ /* There may be one byte for padding somewhere */
+ if (rpnt) break;
+ rr = (struct rock_ridge *) chr;
+ if (rr->len == 0) goto out; /* Something got screwed up here */
+ sig = (chr[0] << 8) + chr[1];
+ chr += rr->len;
+ len -= rr->len;
+
+ switch(sig){
+ case SIG('R','R'):
+ if((rr->u.RR.flags[0] & RR_SL) == 0) goto out;
+ break;
+ case SIG('S','P'):
+ CHECK_SP(goto out);
+ break;
+ case SIG('S','L'):
+ {int slen;
+ struct SL_component * slp;
+ slen = rr->len - 5;
+ slp = &rr->u.SL.link;
+ while (slen > 1){
+ if (!rpnt){
+ rpnt = (char *) kmalloc (inode->i_size +1, GFP_KERNEL);
+ *rpnt = 0;
+ };
+ switch(slp->flags &~1){
+ case 0:
+ strncat(rpnt,slp->text, slp->len);
+ break;
+ case 2:
+ strcat(rpnt,".");
+ break;
+ case 4:
+ strcat(rpnt,"..");
+ break;
+ case 8:
+ strcpy(rpnt,"/");
+ break;
+ default:
+ printk("Symlink component flag not implemented (%d)\n",slen);
+ };
+ slen -= slp->len + 2;
+ slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
+
+ if(slen < 2) break;
+ strcat(rpnt,"/");
+ };
+ break;
+ default:
+ break;
+ }
+ };
+ };
+ MAYBE_CONTINUE(repeat,inode->i_dev);
+ brelse(bh);
+
+ if (cpnt) {
+ kfree(cpnt);
+ cpnt = 0;
+ };
+ return rpnt;
+ out:
+ if(buffer) kfree(buffer);
+ return 0;
+}
+
+
+
+
+
+
diff --git a/fs/isofs/rock.h b/fs/isofs/rock.h
new file mode 100644
index 0000000..5f1d28e
--- /dev/null
+++ b/fs/isofs/rock.h
@@ -0,0 +1,111 @@
+/* These structs are used by the system-use-sharing protocol, in which the
+ Rock Ridge extensions are imbedded. It is quite possible that other
+ extensions are present on the disk, and this is fine as long as they
+ all use SUSP */
+
+struct SU_SP{
+ unsigned char magic[2];
+ unsigned char skip;
+};
+
+struct SU_CE{
+ char extent[8];
+ char offset[8];
+ char size[8];
+};
+
+struct SU_ER{
+ unsigned char len_id;
+ unsigned char len_des;
+ unsigned char len_src;
+ unsigned char ext_ver;
+ char data[0];
+};
+
+struct RR_RR{
+ char flags[1];
+};
+
+struct RR_PX{
+ char mode[8];
+ char n_links[8];
+ char uid[8];
+ char gid[8];
+};
+
+struct RR_PN{
+ char dev_high[8];
+ char dev_low[8];
+};
+
+
+struct SL_component{
+ unsigned char flags;
+ unsigned char len;
+ char text[0];
+};
+
+struct RR_SL{
+ unsigned char flags;
+ struct SL_component link;
+};
+
+struct RR_NM{
+ unsigned char flags;
+ char name[0];
+};
+
+struct RR_CL{
+ char location[8];
+};
+
+struct RR_PL{
+ char location[8];
+};
+
+struct stamp{
+ char time[7];
+};
+
+struct RR_TF{
+ char flags;
+ struct stamp times[0]; /* Variable number of these beasts */
+};
+
+/* These are the bits and their meanings for flags in the TF structure. */
+#define TF_CREATE 1
+#define TF_MODIFY 2
+#define TF_ACCESS 4
+#define TF_ATTRIBUTES 8
+#define TF_BACKUP 16
+#define TF_EXPIRATION 32
+#define TF_EFFECTIVE 64
+#define TF_LONG_FORM 128
+
+struct rock_ridge{
+ char signature[2];
+ unsigned char len;
+ unsigned char version;
+ union{
+ struct SU_SP SP;
+ struct SU_CE CE;
+ struct SU_ER ER;
+ struct RR_RR RR;
+ struct RR_PX PX;
+ struct RR_PN PN;
+ struct RR_SL SL;
+ struct RR_NM NM;
+ struct RR_CL CL;
+ struct RR_PL PL;
+ struct RR_TF TF;
+ } u;
+};
+
+#define RR_PX 1 /* POSIX attributes */
+#define RR_PN 2 /* POSIX devices */
+#define RR_SL 4 /* Symbolic link */
+#define RR_NM 8 /* Alternate Name */
+#define RR_CL 16 /* Child link */
+#define RR_PL 32 /* Parent link */
+#define RR_RE 64 /* Relocation directory */
+#define RR_TF 128 /* Timestamps */
diff --git a/fs/isofs/symlink.c b/fs/isofs/symlink.c
new file mode 100644
index 0000000..a368cd9
--- /dev/null
+++ b/fs/isofs/symlink.c
@@ -0,0 +1,108 @@
+/*
+ * linux/fs/isofs/symlink.c
+ *
+ * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * isofs symlink handling code. This is only used with the Rock Ridge
+ * extensions to iso9660
+ */
+
+#include <asm/segment.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/iso_fs.h>
+#include <linux/stat.h>
+
+static int isofs_readlink(struct inode *, char *, int);
+static int isofs_follow_link(struct inode *, struct inode *, int, int, struct inode **);
+
+/*
+ * symlinks can't do much...
+ */
+struct inode_operations isofs_symlink_inode_operations = {
+ NULL, /* no file-operations */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ isofs_readlink, /* readlink */
+ isofs_follow_link, /* follow_link */
+ NULL, /* bmap */
+ NULL /* truncate */
+};
+
+static int isofs_follow_link(struct inode * dir, struct inode * inode,
+ int flag, int mode, struct inode ** res_inode)
+{
+ int error;
+ unsigned short fs;
+ char * pnt;
+
+ if (!dir) {
+ dir = current->root;
+ dir->i_count++;
+ }
+ if (!inode) {
+ iput(dir);
+ *res_inode = NULL;
+ return -ENOENT;
+ }
+ if (!S_ISLNK(inode->i_mode)) {
+ iput(dir);
+ *res_inode = inode;
+ return 0;
+ }
+ __asm__("mov %%fs,%0":"=r" (fs));
+ if ((current->link_count > 5) ||
+ !(pnt = get_rock_ridge_symlink(inode))) {
+ iput(dir);
+ iput(inode);
+ *res_inode = NULL;
+ return -ELOOP;
+ }
+ iput(inode);
+ __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
+ current->link_count++;
+ error = open_namei(pnt,flag,mode,res_inode,dir);
+ current->link_count--;
+ __asm__("mov %0,%%fs"::"r" (fs));
+ kfree(pnt);
+ return error;
+}
+
+static int isofs_readlink(struct inode * inode, char * buffer, int buflen)
+{
+ char * pnt;
+ int i;
+ char c;
+
+ if (!S_ISLNK(inode->i_mode)) {
+ iput(inode);
+ return -EINVAL;
+ }
+
+ if (buflen > 1023)
+ buflen = 1023;
+ pnt = get_rock_ridge_symlink(inode);
+
+ iput(inode);
+ if (!pnt)
+ return 0;
+ i = 0;
+
+ while (i<buflen && (c = pnt[i])) {
+ i++;
+ put_fs_byte(c,buffer++);
+ }
+ kfree(pnt);
+ return i;
+}
diff --git a/fs/isofs/util.c b/fs/isofs/util.c
new file mode 100644
index 0000000..a91c109
--- /dev/null
+++ b/fs/isofs/util.c
@@ -0,0 +1,137 @@
+/*
+ * linux/fs/isofs/util.c
+ *
+ * The special functions in the file are numbered according to the section
+ * of the iso 9660 standard in which they are described. isonum_733 will
+ * convert numbers according to section 7.3.3, etc.
+ *
+ * isofs special functions. This file was lifted in it's entirety from
+ * the bsd386 iso9660 filesystem, by Pace Williamson.
+ */
+
+
+int
+isonum_711 (p)
+char *p;
+{
+ return (*p & 0xff);
+}
+
+int
+isonum_712 (p)
+char *p;
+{
+ int val;
+
+ val = *p;
+ if (val & 0x80)
+ val |= 0xffffff00;
+ return (val);
+}
+
+int
+isonum_721 (p)
+char *p;
+{
+ return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
+}
+
+int
+isonum_722 (p)
+char *p;
+{
+ return (((p[0] & 0xff) << 8) | (p[1] & 0xff));
+}
+
+int
+isonum_723 (p)
+char *p;
+{
+#if 0
+ if (p[0] != p[3] || p[1] != p[2]) {
+ fprintf (stderr, "invalid format 7.2.3 number\n");
+ exit (1);
+ }
+#endif
+ return (isonum_721 (p));
+}
+
+int
+isonum_731 (p)
+char *p;
+{
+ return ((p[0] & 0xff)
+ | ((p[1] & 0xff) << 8)
+ | ((p[2] & 0xff) << 16)
+ | ((p[3] & 0xff) << 24));
+}
+
+int
+isonum_732 (p)
+char *p;
+{
+ return (((p[0] & 0xff) << 24)
+ | ((p[1] & 0xff) << 16)
+ | ((p[2] & 0xff) << 8)
+ | (p[3] & 0xff));
+}
+
+int
+isonum_733 (p)
+char *p;
+{
+#if 0
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (p[i] != p[7-i]) {
+ fprintf (stderr, "bad format 7.3.3 number\n");
+ exit (1);
+ }
+ }
+#endif
+ return (isonum_731 (p));
+}
+
+int iso_date(p, flag)
+char * p;
+int flag;
+{
+ int year, month, day, hour ,minute, second, tz;
+ int crtime, days, i;
+
+ year = p[0] - 70;
+ month = p[1];
+ day = p[2];
+ hour = p[3];
+ minute = p[4];
+ second = p[5];
+ if (flag == 0) tz = p[6]; /* High sierra has no time zone */
+ else tz = 0;
+
+ if (year < 0) {
+ crtime = 0;
+ } else {
+ int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
+ days = year * 365;
+ if (year > 2)
+ days += (year+2) / 4;
+ for (i = 1; i < month; i++)
+ days += monlen[i-1];
+ if (((year+2) % 4) == 0 && month > 2)
+ days++;
+ days += day - 1;
+ crtime = ((((days * 24) + hour) * 60 + minute) * 60)
+ + second;
+
+ /* sign extend */
+ if (tz & 0x80)
+ tz |= (-1 << 8);
+
+ /* timezone offset is unreliable on some disks */
+ if (-48 <= tz && tz <= 52)
+ crtime += tz * 15 * 60;
+ }
+ return crtime;
+}
+
diff --git a/fs/minix/Makefile b/fs/minix/Makefile
index 5f7d43a..0482477 100644
--- a/fs/minix/Makefile
+++ b/fs/minix/Makefile
@@ -34,93 +34,101 @@ bitmap.o : bitmap.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/in
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/stat.h \
/usr/include/linux/string.h
blkdev.o : blkdev.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/minix_fs.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
- /usr/include/asm/system.h /usr/include/linux/stat.h /usr/include/linux/fcntl.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/linux/stat.h /usr/include/linux/fcntl.h
chrdev.o : chrdev.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/minix_fs.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
- /usr/include/asm/system.h /usr/include/linux/stat.h /usr/include/linux/fcntl.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/linux/stat.h /usr/include/linux/fcntl.h
dir.o : dir.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/minix_fs.h /usr/include/linux/stat.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/minix_fs.h \
+ /usr/include/linux/stat.h
fifo.o : fifo.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h
file.o : file.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/errno.h \
- /usr/include/linux/fcntl.h /usr/include/linux/stat.h /usr/include/linux/locks.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/minix_fs.h /usr/include/linux/errno.h /usr/include/linux/fcntl.h \
+ /usr/include/linux/stat.h /usr/include/linux/locks.h
inode.o : inode.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h \
- /usr/include/linux/string.h /usr/include/linux/stat.h /usr/include/linux/locks.h \
- /usr/include/asm/system.h /usr/include/asm/segment.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/string.h \
+ /usr/include/linux/stat.h /usr/include/linux/locks.h /usr/include/asm/system.h \
+ /usr/include/asm/segment.h
namei.o : namei.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h \
- /usr/include/linux/string.h /usr/include/linux/stat.h /usr/include/linux/fcntl.h \
- /usr/include/linux/errno.h /usr/include/asm/segment.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/string.h \
+ /usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/linux/errno.h \
+ /usr/include/asm/segment.h
symlink.o : symlink.c /usr/include/asm/segment.h /usr/include/linux/errno.h \
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h \
- /usr/include/linux/stat.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/stat.h
truncate.o : truncate.c /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/tty.h \
- /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/stat.h \
- /usr/include/linux/fcntl.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/minix_fs.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
+ /usr/include/asm/system.h /usr/include/linux/stat.h /usr/include/linux/fcntl.h
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index 3a9049e..169b87e 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -8,6 +8,7 @@
#include <linux/sched.h>
#include <linux/minix_fs.h>
+#include <linux/stat.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@ -117,7 +118,7 @@ int minix_new_block(struct super_block * sb)
repeat:
j = 8192;
for (i=0 ; i<8 ; i++)
- if (bh=sb->u.minix_sb.s_zmap[i])
+ if ((bh=sb->u.minix_sb.s_zmap[i]) != NULL)
if ((j=find_first_zero(bh->b_data))<8192)
break;
if (i>=8 || !bh || j>=8192)
@@ -187,19 +188,21 @@ void minix_free_inode(struct inode * inode)
clear_inode(inode);
}
-struct inode * minix_new_inode(struct super_block * sb)
+struct inode * minix_new_inode(const struct inode * dir)
{
+ struct super_block * sb;
struct inode * inode;
struct buffer_head * bh;
int i,j;
- if (!sb || !(inode = get_empty_inode()))
+ if (!dir || !(inode = get_empty_inode()))
return NULL;
+ sb = dir->i_sb;
inode->i_sb = sb;
inode->i_flags = inode->i_sb->s_flags;
j = 8192;
for (i=0 ; i<8 ; i++)
- if (bh=inode->i_sb->u.minix_sb.s_imap[i])
+ if ((bh = inode->i_sb->u.minix_sb.s_imap[i]) != NULL)
if ((j=find_first_zero(bh->b_data))<8192)
break;
if (!bh || j >= 8192 || j+i*8192 > inode->i_sb->u.minix_sb.s_ninodes) {
@@ -216,7 +219,7 @@ struct inode * minix_new_inode(struct super_block * sb)
inode->i_nlink = 1;
inode->i_dev = sb->s_dev;
inode->i_uid = current->euid;
- inode->i_gid = current->egid;
+ inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->egid;
inode->i_dirt = 1;
inode->i_ino = j + i*8192;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index 349139f..289f494 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -77,7 +77,7 @@ static int minix_readdir(struct inode * inode, struct file * filp,
filp->f_pos += sizeof (struct minix_dir_entry);
if (de->inode) {
for (i = 0; i < MINIX_NAME_LEN; i++)
- if (c = de->name[i])
+ if ((c = de->name[i]) != 0)
put_fs_byte(c,i+dirent->d_name);
else
break;
diff --git a/fs/minix/file.c b/fs/minix/file.c
index 13b54f0..0f17e2e 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -65,7 +65,10 @@ static int minix_file_read(struct inode * inode, struct file * filp, char * buf,
{
int read,left,chars;
int block, blocks, offset;
+ int bhrequest;
+ int ra_blocks, max_block, nextblock;
struct buffer_head ** bhb, ** bhe;
+ struct buffer_head * bhreq[NBUF];
struct buffer_head * buflist[NBUF];
if (!inode) {
@@ -89,50 +92,118 @@ static int minix_file_read(struct inode * inode, struct file * filp, char * buf,
offset = filp->f_pos & (BLOCK_SIZE-1);
blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE;
bhb = bhe = buflist;
+
+ ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
+ max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE;
+ nextblock = -1;
+
+ /* We do this in a two stage process. We first try and request
+ as many blocks as we can, then we wait for the first one to
+ complete, and then we try and wrap up as many as are actually
+ done. This routine is rather generic, in that it can be used
+ in a filesystem by substituting the appropriate function in
+ for getblk.
+
+ This routine is optimized to make maximum use of the various
+ buffers and caches. */
+
do {
- if (blocks) {
+ bhrequest = 0;
+ while (blocks) {
+ int uptodate;
--blocks;
- *bhb = minix_getblk(inode,block++,0);
- if (*bhb && !(*bhb)->b_uptodate)
- ll_rw_block(READ, 1, bhb);
+ *bhb = minix_getblk(inode, block++, 0);
+ uptodate = 1;
+ if (*bhb && !(*bhb)->b_uptodate) {
+ uptodate = 0;
+ bhreq[bhrequest++] = *bhb;
+ nextblock = (*bhb)->b_blocknr + 1;
+ };
if (++bhb == &buflist[NBUF])
bhb = buflist;
- if (bhb != bhe)
- continue;
- }
- if (*bhe) {
- wait_on_buffer(*bhe);
- if (!(*bhe)->b_uptodate) {
- do {
- brelse(*bhe);
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
- } while (bhe != bhb);
+ /* If the block we have on hand is uptodate, go ahead
+ and complete processing. */
+ if(bhrequest == 0 && uptodate) break;
+
+ if (bhb == bhe)
break;
- }
- }
+ }
- if (left < BLOCK_SIZE - offset)
- chars = left;
- else
- chars = BLOCK_SIZE - offset;
- filp->f_pos += chars;
- left -= chars;
- read += chars;
- if (*bhe) {
- memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
+ if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) {
+ /* If we are going to read something anyways, add in the
+ read-ahead blocks */
+ while(ra_blocks){
+ if (block >= max_block) break;
+ if(bhrequest == NBUF) break; /* Block full */
+ --ra_blocks;
+ *bhb = minix_getblk(inode, block++, 0);
+
+ if (*bhb && !(*bhb)->b_uptodate) {
+ if((*bhb)->b_blocknr != nextblock) {
+ brelse(*bhb);
+ break;
+ };
+ nextblock = (*bhb)->b_blocknr + 1;
+ bhreq[bhrequest++] = *bhb;
+ };
+
+ if (++bhb == &buflist[NBUF])
+ bhb = buflist;
+
+ if (bhb == bhe)
+ break;
+ };
+ };
+ /* Now request them all */
+ if (bhrequest)
+ ll_rw_block(READ, bhrequest, bhreq);
+
+ do{ /* Finish off all I/O that has actually completed */
+ if (*bhe) {/* test for valid buffer */
+ wait_on_buffer(*bhe);
+ if (!(*bhe)->b_uptodate) {
+ do {
brelse(*bhe);
- buf += chars;
- } else {
- while (chars-->0)
- put_fs_byte(0,buf++);
- }
- offset = 0;
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
+ if (++bhe == &buflist[NBUF])
+ bhe = buflist;
+ } while (bhe != bhb);
+ break;
+ }
+ }
+
+ if (left < BLOCK_SIZE - offset)
+ chars = left;
+ else
+ chars = BLOCK_SIZE - offset;
+ filp->f_pos += chars;
+ left -= chars;
+ read += chars;
+ if (*bhe) {
+ memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
+ brelse(*bhe);
+ buf += chars;
+ } else {
+ while (chars-->0)
+ put_fs_byte(0,buf++);
+ }
+ offset = 0;
+ if (++bhe == &buflist[NBUF])
+ bhe = buflist;
+ } while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) &&
+ (left > 0));
} while (left > 0);
+
+/* Release the read-ahead blocks */
+ while (bhe != bhb) {
+ if (*bhe) brelse(*bhe);
+ if (++bhe == &buflist[NBUF])
+ bhe = buflist;
+ };
+
+ filp->f_reada = 1;
+
if (!read)
return -EIO;
if (!IS_RDONLY(inode)) {
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 273187b..8904083 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -86,12 +86,12 @@ struct super_block *minix_read_super(struct super_block *s,void *data)
s->u.minix_sb.s_zmap[i] = NULL;
block=2;
for (i=0 ; i < s->u.minix_sb.s_imap_blocks ; i++)
- if (s->u.minix_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE))
+ if ((s->u.minix_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE)) != NULL)
block++;
else
break;
for (i=0 ; i < s->u.minix_sb.s_zmap_blocks ; i++)
- if (s->u.minix_sb.s_zmap[i]=bread(dev,block,BLOCK_SIZE))
+ if ((s->u.minix_sb.s_zmap[i]=bread(dev,block,BLOCK_SIZE)) != NULL)
block++;
else
break;
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 1093294..45242f7 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -205,7 +205,7 @@ int minix_create(struct inode * dir,const char * name, int len, int mode,
*result = NULL;
if (!dir)
return -ENOENT;
- inode = minix_new_inode(dir->i_sb);
+ inode = minix_new_inode(dir);
if (!inode) {
iput(dir);
return -ENOSPC;
@@ -243,7 +243,7 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
iput(dir);
return -EEXIST;
}
- inode = minix_new_inode(dir->i_sb);
+ inode = minix_new_inode(dir);
if (!inode) {
iput(dir);
return -ENOSPC;
@@ -253,8 +253,11 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
inode->i_op = NULL;
if (S_ISREG(inode->i_mode))
inode->i_op = &minix_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
+ else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &minix_dir_inode_operations;
+ if (dir->i_mode & S_ISGID)
+ inode->i_mode |= S_ISGID;
+ }
else if (S_ISLNK(inode->i_mode))
inode->i_op = &minix_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode))
@@ -301,7 +304,7 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
iput(dir);
return -EEXIST;
}
- inode = minix_new_inode(dir->i_sb);
+ inode = minix_new_inode(dir);
if (!inode) {
iput(dir);
return -ENOSPC;
@@ -327,6 +330,8 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
dir_block->b_dirt = 1;
brelse(dir_block);
inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
+ if (dir->i_mode & S_ISGID)
+ inode->i_mode |= S_ISGID;
inode->i_dirt = 1;
bh = minix_add_entry(dir,name,len,&de);
if (!bh) {
@@ -496,7 +501,7 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
int i;
char c;
- if (!(inode = minix_new_inode(dir->i_sb))) {
+ if (!(inode = minix_new_inode(dir))) {
iput(dir);
return -ENOSPC;
}
diff --git a/fs/msdos/Makefile b/fs/msdos/Makefile
index 6fd9644..2ca5a9e 100644
--- a/fs/msdos/Makefile
+++ b/fs/msdos/Makefile
@@ -33,53 +33,58 @@ dir.o : dir.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/msdos_fs.h /usr/include/linux/errno.h /usr/include/linux/stat.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/msdos_fs.h \
+ /usr/include/linux/errno.h /usr/include/linux/stat.h
fat.o : fat.c /usr/include/linux/msdos_fs.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/kernel.h \
- /usr/include/linux/errno.h /usr/include/linux/stat.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/kernel.h /usr/include/linux/errno.h \
+ /usr/include/linux/stat.h
file.o : file.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/msdos_fs.h /usr/include/linux/errno.h \
- /usr/include/linux/fcntl.h /usr/include/linux/stat.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/msdos_fs.h /usr/include/linux/errno.h /usr/include/linux/fcntl.h \
+ /usr/include/linux/stat.h
inode.o : inode.c /usr/include/linux/msdos_fs.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/kernel.h \
- /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/mm.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/errno.h /usr/include/linux/string.h /usr/include/linux/ctype.h \
- /usr/include/linux/stat.h /usr/include/linux/locks.h /usr/include/asm/segment.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \
+ /usr/include/linux/head.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
+ /usr/include/linux/string.h /usr/include/linux/ctype.h /usr/include/linux/stat.h \
+ /usr/include/linux/locks.h /usr/include/asm/segment.h
misc.o : misc.c /usr/include/linux/msdos_fs.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/sched.h \
- /usr/include/linux/head.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/errno.h /usr/include/linux/string.h /usr/include/linux/stat.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/sched.h /usr/include/linux/head.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
+ /usr/include/linux/string.h /usr/include/linux/stat.h
namei.o : namei.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/msdos_fs.h /usr/include/linux/errno.h /usr/include/linux/string.h \
- /usr/include/linux/stat.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/msdos_fs.h \
+ /usr/include/linux/errno.h /usr/include/linux/string.h /usr/include/linux/stat.h
diff --git a/fs/msdos/dir.c b/fs/msdos/dir.c
index c19cb8e..3ca3595 100644
--- a/fs/msdos/dir.c
+++ b/fs/msdos/dir.c
@@ -85,18 +85,16 @@ static int msdos_readdir(struct inode *inode,struct file *filp,
put_fs_byte(c,i+dirent->d_name);
}
i = last;
- if (de->ext[0] && de->ext[0] != ' ') {
- put_fs_byte('.',i+dirent->d_name);
+ put_fs_byte('.',i+dirent->d_name);
+ i++;
+ for (i2 = 0; i2 < 3; i2++) {
+ if (!(c = de->ext[i2])) break;
+ if (c >= 'A' && c <= 'Z') c += 32;
+ if (c != ' ') last = i+1;
+ put_fs_byte(c,i+dirent->d_name);
i++;
- for (i2 = 0; i2 < 3; i2++) {
- if (!(c = de->ext[i2])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
- put_fs_byte(c,i+dirent->d_name);
- i++;
- if (c != ' ') last = i;
- }
}
- if (i = last) {
+ if ((i = last) != 0) {
if (!strcmp(de->name,MSDOS_DOT))
ino = inode->i_ino;
else if (!strcmp(de->name,MSDOS_DOTDOT))
diff --git a/fs/msdos/fat.c b/fs/msdos/fat.c
index 26d3832..8e766c1 100644
--- a/fs/msdos/fat.c
+++ b/fs/msdos/fat.c
@@ -282,7 +282,7 @@ int fat_free(struct inode *inode,int skip)
panic("fat_free: deleting beyond EOF");
if (MSDOS_SB(inode->i_sb)->free_clusters != -1)
MSDOS_SB(inode->i_sb)->free_clusters++;
- inode->i_blocks--;
+ inode->i_blocks -= MSDOS_SB(inode->i_sb)->cluster_size;
}
unlock_fat(inode->i_sb);
cache_inval_inode(inode);
diff --git a/fs/msdos/file.c b/fs/msdos/file.c
index f362b3b..b28c1a1 100644
--- a/fs/msdos/file.c
+++ b/fs/msdos/file.c
@@ -94,7 +94,7 @@ static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
}
if (filp->f_pos >= inode->i_size || count <= 0) return 0;
start = buf;
- while (left = MIN(inode->i_size-filp->f_pos,count-(buf-start))) {
+ while ((left = MIN(inode->i_size-filp->f_pos,count-(buf-start))) > 0){
if (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
break;
offset = filp->f_pos & (SECTOR_SIZE-1);
diff --git a/fs/msdos/inode.c b/fs/msdos/inode.c
index dfba933..346c1f2 100644
--- a/fs/msdos/inode.c
+++ b/fs/msdos/inode.c
@@ -70,7 +70,8 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
*umask = current->umask;
if (!options) return 1;
for (this = strtok(options,","); this; this = strtok(NULL,",")) {
- if (value = strchr(this,'=')) *value++ = 0;
+ if ((value = strchr(this,'=')) != NULL)
+ *value++ = 0;
if (!strcmp(this,"check") && value) {
if (value[0] && !value[1] && strchr("rns",*value))
*check = *value;
@@ -254,7 +255,7 @@ void msdos_read_inode(struct inode *inode)
inode->i_blksize = MSDOS_SB(inode->i_sb)->cluster_size*
SECTOR_SIZE;
inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
- inode->i_blksize;
+ inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size;
MSDOS_I(inode)->i_start = 0;
MSDOS_I(inode)->i_attrs = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
@@ -279,7 +280,7 @@ void msdos_read_inode(struct inode *inode)
}
#endif
inode->i_size = 0;
- if (this = raw_entry->start)
+ if ((this = raw_entry->start) != 0)
while (this != -1) {
inode->i_size += SECTOR_SIZE*MSDOS_SB(inode->
i_sb)->cluster_size;
@@ -304,7 +305,7 @@ void msdos_read_inode(struct inode *inode)
/* this is as close to the truth as we can get ... */
inode->i_blksize = MSDOS_SB(inode->i_sb)->cluster_size*SECTOR_SIZE;
inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
- inode->i_blksize;
+ inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size;
inode->i_mtime = inode->i_atime = inode->i_ctime =
date_dos2unix(raw_entry->time,raw_entry->date);
brelse(bh);
diff --git a/fs/msdos/misc.c b/fs/msdos/misc.c
index 40d2243..e75f0f5 100644
--- a/fs/msdos/misc.c
+++ b/fs/msdos/misc.c
@@ -118,7 +118,7 @@ printk("free cluster: %d\n",this);
printk("set to %x\n",fat_access(inode->i_sb,this,-1));
#endif
last = 0;
- if (current = MSDOS_I(inode)->i_start) {
+ if ((current = MSDOS_I(inode)->i_start) != 0) {
cache_lookup(inode,0x7fffffff,&last,&current);
while (current && current != -1)
if (!(current = fat_access(inode->i_sb,
@@ -163,7 +163,7 @@ printk("zeroing sector %d\n",sector);
brelse(bh);
}
}
- inode->i_blocks++;
+ inode->i_blocks += MSDOS_SB(inode->i_sb)->cluster_size;
if (S_ISDIR(inode->i_mode)) {
if (inode->i_size & (SECTOR_SIZE-1))
panic("Odd directory size");
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 80d5194..6fda997 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -24,7 +24,7 @@ static char *reserved_names[] = {
/* Characters that are undesirable in an MS-DOS file name */
-static char bad_chars[] = "*?<>|\" ";
+static char bad_chars[] = "*?<>|\"";
static char bad_if_strict[] = "+=,;";
@@ -180,7 +180,8 @@ static int msdos_create_entry(struct inode *dir,char *name,int is_dir,
date_unix2dos(CURRENT_TIME,&de->time,&de->date);
de->size = 0;
bh->b_dirt = 1;
- if (*result = iget(dir->i_sb,ino)) msdos_read_inode(*result);
+ if ((*result = iget(dir->i_sb,ino)) != NULL)
+ msdos_read_inode(*result);
brelse(bh);
if (!*result) return -EIO;
(*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
@@ -409,7 +410,7 @@ static int rename_same_dir(struct inode *old_dir,char *old_name,
memcpy(old_de->name,new_name,MSDOS_NAME);
old_bh->b_dirt = 1;
if (MSDOS_SB(old_dir->i_sb)->conversion == 'a') /* update binary info */
- if (old_inode = iget(old_dir->i_sb,old_ino)) {
+ if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
msdos_read_inode(old_inode);
iput(old_inode);
}
diff --git a/fs/namei.c b/fs/namei.c
index 930975b..175526b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -65,7 +65,8 @@ int lookup(struct inode * dir,const char * name, int len,
else if ((sb = dir->i_sb) && (dir == sb->s_mounted)) {
sb = dir->i_sb;
iput(dir);
- if (dir = sb->s_covered)
+ dir = sb->s_covered;
+ if (dir)
dir->i_count++;
}
}
@@ -258,7 +259,8 @@ int open_namei(const char * pathname, int flag, int mode,
iput(inode);
return -EEXIST;
}
- if (error = follow_link(dir,inode,flag,mode,&inode))
+ error = follow_link(dir,inode,flag,mode,&inode);
+ if (error)
return error;
if (S_ISDIR(inode->i_mode) && (flag & 2)) {
iput(inode);
diff --git a/fs/open.c b/fs/open.c
index 610316b..8f0bdff 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -357,7 +357,8 @@ int sys_open(const char * filename,int flag,int mode)
return -ENFILE;
current->filp[fd] = f;
f->f_flags = flag;
- if (f->f_mode = (flag+1) & O_ACCMODE)
+ f->f_mode = (flag+1) & O_ACCMODE;
+ if (f->f_mode)
flag++;
if (flag & (O_TRUNC | O_CREAT))
flag |= 2;
@@ -388,13 +389,15 @@ int sys_open(const char * filename,int flag,int mode)
f->f_op = NULL;
if (inode->i_op)
f->f_op = inode->i_op->default_file_ops;
- if (f->f_op && f->f_op->open)
- if (i = f->f_op->open(inode,f)) {
+ if (f->f_op && f->f_op->open) {
+ i = f->f_op->open(inode,f);
+ if (i) {
iput(inode);
f->f_count--;
current->filp[fd]=NULL;
return i;
}
+ }
f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
return (fd);
}
@@ -457,7 +460,7 @@ static void kill_wait(struct wait_queue **q, int sig)
do {
tmp = next;
next = tmp->next;
- if (p = tmp->task)
+ if ((p = tmp->task) != NULL)
send_sig (sig, p , 1);
} while (next && next != *q);
}
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index fd3ad65..efe8294 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -14,7 +14,7 @@
.s.o:
$(AS) -o $*.o $<
-OBJS= inode.o root.o base.o mem.o link.o fd.o
+OBJS= inode.o root.o base.o mem.o link.o fd.o array.o
proc.o: $(OBJS)
$(LD) -r -o proc.o $(OBJS)
@@ -29,58 +29,74 @@ dep:
cp tmp_make Makefile
### Dependencies:
+array.o : array.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
+ /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
+ /usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
+ /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/asm/segment.h \
+ /usr/include/asm/io.h
base.o : base.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/proc_fs.h /usr/include/linux/stat.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/proc_fs.h /usr/include/linux/stat.h
fd.o : fd.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/proc_fs.h /usr/include/linux/stat.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/proc_fs.h /usr/include/linux/stat.h
inode.o : inode.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/proc_fs.h \
- /usr/include/linux/string.h /usr/include/linux/stat.h /usr/include/linux/locks.h \
- /usr/include/asm/system.h /usr/include/asm/segment.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/proc_fs.h /usr/include/linux/string.h \
+ /usr/include/linux/stat.h /usr/include/linux/locks.h /usr/include/asm/system.h \
+ /usr/include/asm/segment.h
link.o : link.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/stat.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/minix_fs.h /usr/include/linux/stat.h
mem.o : mem.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/asm/segment.h /usr/include/asm/io.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/asm/segment.h \
+ /usr/include/asm/io.h
root.o : root.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/proc_fs.h /usr/include/linux/stat.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/proc_fs.h /usr/include/linux/stat.h
diff --git a/fs/proc/array.c b/fs/proc/array.c
new file mode 100644
index 0000000..49b77a1
--- /dev/null
+++ b/fs/proc/array.c
@@ -0,0 +1,244 @@
+/*
+ * linux/fs/proc/array.c
+ *
+ * Copyright (C) 1992 by Linus Torvalds
+ * based on ideas by Darren Senn
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+
+static int get_loadavg(char * buffer)
+{
+ return sprintf(buffer,"%d.%02d %d.%02d %d.%02d\n",
+ avenrun[0] >> FSHIFT,
+ (FIXED_1/2 + (avenrun[0] & (FIXED_1-1))*100) >> FSHIFT,
+ avenrun[1] >> FSHIFT,
+ (FIXED_1/2 + (avenrun[1] & (FIXED_1-1))*100) >> FSHIFT,
+ avenrun[2] >> FSHIFT,
+ (FIXED_1/2 + (avenrun[2] & (FIXED_1-1))*100) >> FSHIFT);
+}
+
+static int get_uptime(char * buffer)
+{
+ return sprintf(buffer,"%d\n",(jiffies+jiffies_offset)/HZ);
+}
+
+static int get_meminfo(char * buffer)
+{
+ struct sysinfo i;
+
+ si_meminfo(&i);
+ si_swapinfo(&i);
+ return sprintf(buffer, " total: used: free: shared: buffers:\n"
+ "Mem: %8d %8d %8d %8d %8d\n"
+ "Swap: %8d %8d %8d\n",
+ i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram,
+ i.totalswap, i.totalswap-i.freeswap, i.freeswap);
+}
+
+static struct task_struct ** get_task(pid_t pid)
+{
+ struct task_struct ** p;
+
+ p = task;
+ while (++p < task+NR_TASKS) {
+ if (*p && (*p)->pid == pid)
+ return p;
+ }
+ return NULL;
+}
+
+static unsigned long get_phys_addr(struct task_struct ** p, unsigned long ptr)
+{
+ unsigned long page;
+
+ if (!p || !*p || ptr >= TASK_SIZE)
+ return 0;
+ page = (*p)->tss.cr3;
+ page += (ptr >> 20) & 0xffc;
+ page = *(unsigned long *) page;
+ if (!(page & 1))
+ return 0;
+ page &= 0xfffff000;
+ page += (ptr >> 10) & 0xffc;
+ page = *(unsigned long *) page;
+ if (!(page & 1))
+ return 0;
+ page &= 0xfffff000;
+ page += ptr & 0xfff;
+ return page;
+}
+
+static unsigned long get_long(struct task_struct ** p, unsigned long ptr)
+{
+ unsigned long addr;
+
+ if (ptr & 3)
+ return 0;
+ addr = get_phys_addr(p,ptr);
+ if (!addr)
+ return 0;
+ return *(unsigned long *) addr;
+}
+
+static int get_char(struct task_struct ** p, unsigned long ptr)
+{
+ unsigned long addr;
+
+ addr = get_phys_addr(p,ptr);
+ if (!addr)
+ return -1;
+ return *(unsigned char *) addr;
+}
+
+static int get_array(struct task_struct ** p, unsigned long ptr, char * buffer)
+{
+ unsigned long tmp;
+ int size = 0, result = 0;
+ unsigned long array;
+ char c;
+
+ array = get_long(p,ptr);
+ if (!ptr)
+ return 0;
+ for (;;) {
+ tmp = get_long(p,array);
+ if (!tmp)
+ return result;
+ array += 4;
+ while ((c = get_char(p,tmp++)) > 0) {
+ if (size < PAGE_SIZE)
+ buffer[size++] = c;
+ else
+ return result;
+ }
+ if (c < 0)
+ return result;
+ result = size;
+ if (size < PAGE_SIZE)
+ buffer[size++] = '\0';
+ }
+}
+
+static int get_env(int pid, char * buffer)
+{
+ struct task_struct ** p = get_task(pid);
+
+ if (!p || !*p)
+ return 0;
+ return get_array(p, (*p)->start_stack+8, buffer);
+}
+
+static int get_arg(int pid, char * buffer)
+{
+ struct task_struct ** p = get_task(pid);
+
+ if (!p || !*p)
+ return 0;
+ return get_array(p, (*p)->start_stack+4, buffer);
+}
+
+static int get_stat(int pid, char * buffer)
+{
+ struct task_struct ** p = get_task(pid);
+ char state;
+
+ if (!p || !*p)
+ return 0;
+ if ((*p)->state < 0)
+ state = '.';
+ else
+ state = "RSDZTD"[(*p)->state];
+ return sprintf(buffer,"%d (%s) %c %d %d %d %d\n",
+ pid,
+ (*p)->comm,
+ state,
+ (*p)->p_pptr->pid,
+ (*p)->pgrp,
+ (*p)->session,
+ (*p)->tty);
+}
+
+static int array_read(struct inode * inode, struct file * file,char * buf, int count)
+{
+ char * page;
+ int length;
+ int end;
+ int type, pid;
+
+ if (count < 0)
+ return -EINVAL;
+ page = (char *) get_free_page(GFP_KERNEL);
+ *page = 0;
+ if (!page)
+ return -ENOMEM;
+ type = inode->i_ino;
+ pid = type >> 16;
+ type &= 0x0000ffff;
+ switch (type) {
+ case 2:
+ length = get_loadavg(page);
+ break;
+ case 3:
+ length = get_uptime(page);
+ break;
+ case 4:
+ length = get_meminfo(page);
+ break;
+ case 9:
+ length = get_env(pid, page);
+ break;
+ case 10:
+ length = get_arg(pid, page);
+ break;
+ case 11:
+ length = get_stat(pid, page);
+ break;
+ default:
+ return -EBADF;
+ }
+ if (file->f_pos >= length)
+ return 0;
+ if (count + file->f_pos > length)
+ count = length - file->f_pos;
+ end = count + file->f_pos;
+ memcpy_tofs(buf, page + file->f_pos, count);
+ free_page((unsigned long) page);
+ file->f_pos = end;
+ return count;
+}
+
+static struct file_operations proc_array_operations = {
+ NULL, /* array_lseek */
+ array_read,
+ NULL, /* array_write */
+ NULL, /* array_readdir */
+ NULL, /* array_select */
+ NULL, /* array_ioctl */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL /* no special release code */
+};
+
+struct inode_operations proc_array_inode_operations = {
+ &proc_array_operations, /* default base directory file-ops */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* bmap */
+ NULL /* truncate */
+};
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 6c5dd2e..fc37cc4 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -48,12 +48,6 @@ struct inode_operations proc_base_inode_operations = {
NULL /* truncate */
};
-struct proc_dir_entry {
- unsigned short low_ino;
- unsigned short namelen;
- char * name;
-};
-
static struct proc_dir_entry base_dir[] = {
{ 1,2,".." },
{ 2,1,"." },
@@ -62,12 +56,15 @@ static struct proc_dir_entry base_dir[] = {
{ 5,4,"root" },
{ 6,3,"exe" },
{ 7,2,"fd" },
- { 8,3,"lib" }
+ { 8,3,"lib" },
+ { 9,7,"environ" },
+ { 10,7,"cmdline" },
+ { 11,4,"stat" }
};
#define NR_BASE_DIRENTRY ((sizeof (base_dir))/(sizeof (base_dir[0])))
-static int proc_match(int len,const char * name,struct proc_dir_entry * de)
+int proc_match(int len,const char * name,struct proc_dir_entry * de)
{
register int same __asm__("ax");
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 5451bdb..9f206b0 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -11,6 +11,7 @@
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/locks.h>
+#include <linux/limits.h>
#include <asm/system.h>
#include <asm/segment.h>
@@ -100,21 +101,25 @@ void proc_read_inode(struct inode * inode)
return;
if (ino == PROC_ROOT_INO) {
inode->i_mode = S_IFDIR | 0555;
+ inode->i_nlink = 2;
+ for (i = 1 ; i < NR_TASKS ; i++)
+ if (task[i])
+ inode->i_nlink++;
inode->i_op = &proc_root_inode_operations;
return;
}
- if (!pid)
+ if (!pid) {
+ inode->i_mode = S_IFREG | 0444;
+ inode->i_op = &proc_array_inode_operations;
return;
+ }
ino &= 0x0000ffff;
inode->i_uid = p->euid;
inode->i_gid = p->egid;
switch (ino) {
case 2:
- inode->i_nlink = 2;
- for (i = 1 ; i < NR_TASKS ; i++)
- if (task[i])
- inode->i_nlink++;
- inode->i_mode = S_IFDIR | 0500;
+ inode->i_nlink = 4;
+ inode->i_mode = S_IFDIR | 0555;
inode->i_op = &proc_base_inode_operations;
return;
case 3:
@@ -135,6 +140,12 @@ void proc_read_inode(struct inode * inode)
inode->i_op = &proc_fd_inode_operations;
inode->i_nlink = 2;
return;
+ case 9:
+ case 10:
+ case 11:
+ inode->i_mode = S_IFREG | 0444;
+ inode->i_op = &proc_array_inode_operations;
+ return;
}
switch (ino >> 8) {
case 1:
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 78b5360..8ad4eca 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -48,6 +48,16 @@ struct inode_operations proc_root_inode_operations = {
NULL /* truncate */
};
+static struct proc_dir_entry root_dir[] = {
+ { 1,1,"." },
+ { 1,2,".." },
+ { 2,7,"loadavg" },
+ { 3,6,"uptime" },
+ { 4,7,"meminfo" }
+};
+
+#define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0])))
+
static int proc_lookuproot(struct inode * dir,const char * name, int len,
struct inode ** result)
{
@@ -61,34 +71,40 @@ static int proc_lookuproot(struct inode * dir,const char * name, int len,
iput(dir);
return -ENOENT;
}
- pid = 0;
- if (!len || (get_fs_byte(name) == '.' && (len == 1 ||
- (get_fs_byte(name+1) == '.' && len == 2)))) {
- *result = dir;
- return 0;
- }
- while (len-- > 0) {
- c = get_fs_byte(name) - '0';
- name++;
- if (c > 9) {
- pid = 0;
- break;
+ i = NR_ROOT_DIRENTRY;
+ while (i-- > 0 && !proc_match(len,name,root_dir+i))
+ /* nothing */;
+ if (i >= 0) {
+ ino = root_dir[i].low_ino;
+ if (ino == 1) {
+ *result = dir;
+ return 0;
}
- pid *= 10;
- pid += c;
- if (pid & 0xffff0000) {
- pid = 0;
- break;
+ } else {
+ pid = 0;
+ while (len-- > 0) {
+ c = get_fs_byte(name) - '0';
+ name++;
+ if (c > 9) {
+ pid = 0;
+ break;
+ }
+ pid *= 10;
+ pid += c;
+ if (pid & 0xffff0000) {
+ pid = 0;
+ break;
+ }
}
+ for (i = 0 ; i < NR_TASKS ; i++)
+ if (task[i] && task[i]->pid == pid)
+ break;
+ if (!pid || i >= NR_TASKS) {
+ iput(dir);
+ return -ENOENT;
+ }
+ ino = (pid << 16) + 2;
}
- for (i = 0 ; i < NR_TASKS ; i++)
- if (task[i] && task[i]->pid == pid)
- break;
- if (!pid || i >= NR_TASKS) {
- iput(dir);
- return -ENOENT;
- }
- ino = (pid << 16) + 2;
if (!(*result = iget(dir->i_sb,ino))) {
iput(dir);
return -ENOENT;
@@ -101,42 +117,48 @@ static int proc_readroot(struct inode * inode, struct file * filp,
struct dirent * dirent, int count)
{
struct task_struct * p;
- unsigned int pid;
+ unsigned int nr,pid;
int i,j;
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
- while ((pid = filp->f_pos) < NR_TASKS+2) {
+repeat:
+ nr = filp->f_pos;
+ if (nr < NR_ROOT_DIRENTRY) {
+ struct proc_dir_entry * de = root_dir + nr;
+
filp->f_pos++;
- if (pid < 2) {
- i = j = pid+1;
- put_fs_long(1, &dirent->d_ino);
- put_fs_word(i, &dirent->d_reclen);
- put_fs_byte(0, i+dirent->d_name);
- while (i--)
- put_fs_byte('.', i+dirent->d_name);
- return j;
- }
- p = task[pid-2];
- if (!p || !(pid = p->pid))
- continue;
- if (pid & 0xffff0000)
- continue;
- j = 10;
- i = 1;
- while (pid >= j) {
- j *= 10;
- i++;
- }
+ i = de->namelen;
+ put_fs_long(de->low_ino, &dirent->d_ino);
+ put_fs_word(i,&dirent->d_reclen);
+ put_fs_byte(0,i+dirent->d_name);
j = i;
- put_fs_long((pid << 16)+2, &dirent->d_ino);
- put_fs_word(i, &dirent->d_reclen);
- put_fs_byte(0, i+dirent->d_name);
- while (i--) {
- put_fs_byte('0'+(pid % 10), i+dirent->d_name);
- pid /= 10;
- }
+ while (i--)
+ put_fs_byte(de->name[i], i+dirent->d_name);
return j;
}
- return 0;
+ nr -= NR_ROOT_DIRENTRY;
+ if (nr >= NR_TASKS)
+ return 0;
+ filp->f_pos++;
+ p = task[nr];
+ if (!p || !(pid = p->pid))
+ goto repeat;
+ if (pid & 0xffff0000)
+ goto repeat;
+ j = 10;
+ i = 1;
+ while (pid >= j) {
+ j *= 10;
+ i++;
+ }
+ j = i;
+ put_fs_long((pid << 16)+2, &dirent->d_ino);
+ put_fs_word(i, &dirent->d_reclen);
+ put_fs_byte(0, i+dirent->d_name);
+ while (i--) {
+ put_fs_byte('0'+(pid % 10), i+dirent->d_name);
+ pid /= 10;
+ }
+ return j;
}
diff --git a/fs/select.c b/fs/select.c
index 100e73b..ea97e58 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -102,11 +102,11 @@ int do_select(int n, fd_set *in, fd_set *out, fd_set *ex,
FD_ZERO(res_out);
FD_ZERO(res_ex);
count = 0;
-repeat:
wait_table.nr = 0;
wait_table.entry = entry;
- current->state = TASK_INTERRUPTIBLE;
wait = &wait_table;
+repeat:
+ current->state = TASK_INTERRUPTIBLE;
for (i = 0 ; i < n ; i++) {
if (FD_ISSET(i,in) && check(SEL_IN,wait,current->filp[i])) {
FD_SET(i, res_in);
@@ -124,10 +124,9 @@ repeat:
wait = NULL;
}
}
- if (!count && current->timeout
- && !(current->signal & ~current->blocked)) {
+ wait = NULL;
+ if (!count && current->timeout && !(current->signal & ~current->blocked)) {
schedule();
- free_wait(&wait_table);
goto repeat;
}
free_wait(&wait_table);
@@ -198,9 +197,11 @@ int sys_select( unsigned long *buffer )
get_fd_set(n, exp, &ex);
timeout = 0xffffffff;
if (tvp) {
- timeout = get_fs_long((unsigned long *)&tvp->tv_usec)/(1000000/HZ);
+ timeout = jiffies;
+ timeout += get_fs_long((unsigned long *)&tvp->tv_usec)/(1000000/HZ);
timeout += get_fs_long((unsigned long *)&tvp->tv_sec) * HZ;
- timeout += jiffies;
+ if (timeout <= jiffies)
+ timeout = 0;
}
current->timeout = timeout;
i = do_select(n, &in, &out, &ex, &res_in, &res_out, &res_ex);
diff --git a/fs/super.c b/fs/super.c
index 4c75b07..f18e24d 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -121,7 +121,8 @@ static struct super_block * read_super(dev_t dev,char *name,int flags,void *data
if (!dev)
return NULL;
check_disk_change(dev);
- if (s = get_super(dev))
+ s = get_super(dev);
+ if (s)
return s;
if (!(type = get_fs_type(name))) {
printk("get fs type failed %s\n",name);
@@ -304,7 +305,6 @@ static int do_mount(dev_t dev, const char * dir, char * type, int flags, void *
iput(dir_i);
return -EBUSY;
}
- sb->s_flags = flags;
sb->s_covered = dir_i;
dir_i->i_mount = 1;
return 0; /* we don't iput(dir_i) - see umount */
@@ -348,7 +348,8 @@ int sys_mount(char * dev_name, char * dir_name, char * type,
return -ENODEV;
t = fstype->name;
if (fstype->requires_dev) {
- if (retval = namei(dev_name,&inode))
+ retval = namei(dev_name,&inode);
+ if (retval)
return retval;
if (!S_ISBLK(inode->i_mode)) {
iput(inode);
@@ -371,7 +372,8 @@ int sys_mount(char * dev_name, char * dir_name, char * type,
}
fops = blkdev_fops[MAJOR(dev)];
if (fops && fops->open) {
- if (retval = fops->open(inode,NULL)) {
+ retval = fops->open(inode,NULL);
+ if (retval) {
iput(inode);
return retval;
}
diff --git a/include/asm/dma.h b/include/asm/dma.h
index e04f196..18cccbf 100644
--- a/include/asm/dma.h
+++ b/include/asm/dma.h
@@ -1,14 +1,15 @@
-/* $Header: /sys/linux-0.97/include/asm/RCS/dma.h,v 1.4 1992/09/21 03:15:46 root Exp root $
+/* $Id: dma.h,v 1.5 1992/11/18 02:37:20 root Exp root $
* linux/include/asm/dma.h: Defines for using and allocating dma channels.
* Written by Hennus Bergman, 1992.
- *
- * High DMA channel support by Hannu Savolainen
+ * High DMA channel support & info by Hannu Savolainen
+ * and John Boyd, Nov. 1992.
*/
#ifndef _ASM_DMA_H
#define _ASM_DMA_H
#include <asm/io.h> /* need byte IO */
+#include <linux/kernel.h> /* need panic() [FIXME] */
#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
@@ -16,62 +17,111 @@
#endif
/*
- * The routines below should in most cases (with optimizing on) result
- * in equal or better code than similar code using macros.
+ * NOTES about DMA transfers:
*
- * NOTE about DMA transfers: The DMA controller cannot handle transfers
- * that cross a 64k boundary. When the address reaches 0xNffff, it will wrap
- * around to 0xN0000, rather than increment to 0x(N+1)0000 !
- * Make sure you align your buffers properly! Runtime check recommended.
-
- ****** Correction!!!!!
- * Channels 4-7 16 bit channels and capable to cross 64k boundaries
- * but not 128k boundaries. Transfer count must be given as words.
- * Maximum transfer size is 65k words = 128kb.
+ * controller 1: channels 0-3, byte operations, ports 00-1F
+ * controller 2: channels 4-7, word operations, ports C0-DF
*
- * NOTE2: DMA1..3 can only use the lower 1MB of physical memory. DMA4..7
- * can access the lower 16MB. There are people with >16MB, so beware!
-
- * **** Not correct!!! All channels are able to access the first 16MB *******
- */
-
-
-#define MAX_DMA_CHANNELS 8
-
-/* SOMEBODY should check the following:
- * Channels 0..3 are on the first DMA controller, channels 4..7 are
- * on the second. Channel 0 is for refresh, 4 is for cascading.
- * The first DMA controller uses bytes, the second words.
+ * - ALL registers are 8 bits only, regardless of transfer size
+ * - channel 4 is not used - cascades 1 into 2.
+ * - channels 0-3 are byte - addresses/counts are for physical bytes
+ * - channels 5-7 are word - addresses/counts are for physical words
+ * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries
+ * - transfer count loaded to registers is 1 less than actual count
+ * - controller 2 offsets are all even (2x offsets for controller 1)
+ * - page registers for 5-7 don't use data bit 0, represent 128K pages
+ * - page registers for 0-3 use bit 0, represent 64K pages
+ *
+ * DMA transfers are limited to the lower 16MB of _physical_ memory.
+ * Note that addresses loaded into registers must be _physical_ addresses,
+ * not logical addresses (which may differ if paging is active).
+ *
+ * Address mapping for channels 0-3:
+ *
+ * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses)
+ * | ... | | ... | | ... |
+ * | ... | | ... | | ... |
+ * | ... | | ... | | ... |
+ * P7 ... P0 A7 ... A0 A7 ... A0
+ * | Page | Addr MSB | Addr LSB | (DMA registers)
+ *
+ * Address mapping for channels 5-7:
+ *
+ * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses)
+ * | ... | \ \ ... \ \ \ ... \ \
+ * | ... | \ \ ... \ \ \ ... \ (not used)
+ * | ... | \ \ ... \ \ \ ... \
+ * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0
+ * | Page | Addr MSB | Addr LSB | (DMA registers)
+ *
+ * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses
+ * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at
+ * the hardware level, so odd-byte transfers aren't possible).
+ *
+ * Transfer count (_not # bytes_) is limited to 64K, represented as actual
+ * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more,
+ * and up to 128K bytes may be transferred on channels 5-7 in one operation.
*
- * Where are the page regs for the second DMA controller?????
- * (ch 5=0x8b, 6=0x89, 7=0x8a)
*/
+#define MAX_DMA_CHANNELS 8
/* 8237 DMA controllers */
#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
/* DMA controller registers */
-#define DMA1_CMD_REG 0x08 /* DMA command register */
-#define DMA1_STAT_REG 0x08 /* DMA status register */
-#define DMA1_MASK_REG 0x0A /* mask individual channels */
-#define DMA1_MODE_REG 0x0B /* set modes for individual channels */
-#define DMA1_CLEAR_FF_REG 0x0C /* Write 0 for LSB, 1 for MSB */
-#define DMA1_RESET_REG 0x0D /* Write here to reset DMA controller */
-
-#define DMA2_CMD_REG 0xD0 /* DMA command register */
-#define DMA2_STAT_REG 0xD0 /* DMA status register */
-#define DMA2_MASK_REG 0xD4
-#define DMA2_MODE_REG 0xD6
-#define DMA2_CLEAR_FF_REG 0xD8
-#define DMA2_RESET_REG 0xDA /* Write here to reset DMA controller */
+#define DMA1_CMD_REG 0x08 /* command register (w) */
+#define DMA1_STAT_REG 0x08 /* status register (r) */
+#define DMA1_REQ_REG 0x09 /* request register (w) */
+#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
+#define DMA1_MODE_REG 0x0B /* mode register (w) */
+#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
+#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
+#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
+#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
+#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
+
+#define DMA2_CMD_REG 0xD0 /* command register (w) */
+#define DMA2_STAT_REG 0xD0 /* status register (r) */
+#define DMA2_REQ_REG 0xD2 /* request register (w) */
+#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
+#define DMA2_MODE_REG 0xD6 /* mode register (w) */
+#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
+#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
+#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
+#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
+#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
+
+#define DMA_ADDR_0 0x00 /* DMA address registers */
+#define DMA_ADDR_1 0x02
+#define DMA_ADDR_2 0x04
+#define DMA_ADDR_3 0x06
+#define DMA_ADDR_4 0xC0
+#define DMA_ADDR_5 0xC4
+#define DMA_ADDR_6 0xC8
+#define DMA_ADDR_7 0xCC
+
+#define DMA_CNT_0 0x01 /* DMA count registers */
+#define DMA_CNT_1 0x03
+#define DMA_CNT_2 0x05
+#define DMA_CNT_3 0x07
+#define DMA_CNT_4 0xC2
+#define DMA_CNT_5 0xC6
+#define DMA_CNT_6 0xCA
+#define DMA_CNT_7 0xCE
+
+#define DMA_PAGE_0 0x87 /* DMA page registers */
+#define DMA_PAGE_1 0x83
+#define DMA_PAGE_2 0x81
+#define DMA_PAGE_3 0x82
+#define DMA_PAGE_5 0x8B
+#define DMA_PAGE_6 0x89
+#define DMA_PAGE_7 0x8A
#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */
#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */
-/* cascade mode (for DMA2 controller only) */
-#define DMA_MODE_CASCADE 0x40 /* 0xC0 */
-
+#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
/* enable/disable a specific DMA channel */
static __inline__ void enable_dma(unsigned int dmanr)
@@ -111,7 +161,7 @@ static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
if (dmanr<=3)
outb(mode | dmanr, DMA1_MODE_REG);
else
- outb(DMA_MODE_CASCADE | mode | (dmanr&3), DMA2_MODE_REG);
+ outb(mode | (dmanr&3), DMA2_MODE_REG);
}
/* Set only the page register bits of the transfer address.
@@ -123,28 +173,25 @@ static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
{
switch(dmanr) {
case 0:
- outb(pagenr, 0x80);
+ outb(pagenr, DMA_PAGE_0);
break;
case 1:
- outb(pagenr, 0x83);
+ outb(pagenr, DMA_PAGE_1);
break;
case 2:
- outb(pagenr, 0x81);
+ outb(pagenr, DMA_PAGE_2);
break;
case 3:
- outb(pagenr, 0x82);
- break;
- case 4:
- outb(pagenr, 0x8f);
+ outb(pagenr, DMA_PAGE_3);
break;
case 5:
- outb(pagenr, 0x8b);
+ outb(pagenr & 0xfe, DMA_PAGE_5);
break;
case 6:
- outb(pagenr, 0x89);
+ outb(pagenr & 0xfe, DMA_PAGE_6);
break;
case 7:
- outb(pagenr, 0x8a);
+ outb(pagenr & 0xfe, DMA_PAGE_7);
break;
}
}
@@ -152,58 +199,59 @@ static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
/* Set transfer address & page bits for specific DMA channel.
* Assumes dma flipflop is clear.
- *
- * NOTE! A word address is assumed for the channels 4 to 7.
*/
static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
{
- unsigned int io_base = (dmanr<=3)? IO_DMA1_BASE : IO_DMA2_BASE;
- unsigned int page = a>>16;
-
- if (dmanr>3) page &= 0xfe; /* The last bit is never used */
-
- set_dma_page(dmanr, page);
-
- if (dmanr>3) a >>= 1;
-
- outb(a & 0xff, ((dmanr&3)<<1) + io_base);
- outb((a>>8) & 0xff, ((dmanr&3)<<1) + io_base);
+ set_dma_page(dmanr, a>>16);
+ if (dmanr <= 3) {
+ outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
+ outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
+ } else {
+ outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
+ outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
+ }
}
-/* Set transfer size (max 64k) for a specific DMA channel.
+/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for
+ * a specific DMA channel.
* You must ensure the parameters are valid.
- * NOTE: from a manual: "the number of transfers is one more
+ * NOTE: from a manual: "the number of transfers is one more
* than the initial word count"! This is taken into account.
* Assumes dma flip-flop is clear.
+ * NOTE 2: "count" must represent _words_ for channels 5-7.
*/
static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
{
- unsigned int dc;
- unsigned int io_base = (dmanr<=3)? IO_DMA1_BASE : IO_DMA2_BASE;
-
- if (dmanr>3) count >>=1;
- dc = count - 1;
-
- outb(dc & 0xff, ((dmanr&3)<<1) + 1 + io_base);
- outb((dc>>8) & 0xff, ((dmanr&3)<<1) + 1 + io_base);
+ count--;
+ if (dmanr <= 3) {
+ outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
+ outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
+ } else {
+ outb( count & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
+ outb( (count>>8) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
+ }
}
/* Get DMA residue count. After a DMA transfer, this
* should return zero. Reading this while a DMA transfer is
+ * should return zero. Reading this while a DMA transfer is
* still in progress will return unpredictable results.
* If called before the channel has been used, it may return 1.
- * Otherwise, it returns the number of bytes left to transfer,
- * minus 1, modulo 64k.
+ * Otherwise, it returns the number of bytes (or words) left to
+ * transfer, minus 1, modulo 64k.
* Assumes DMA flip-flop is clear.
*/
static __inline__ short int get_dma_residue(unsigned int dmanr)
{
- unsigned int io_base = (dmanr<=3)? IO_DMA1_BASE : IO_DMA2_BASE;
-
- return 1 + inb( ((dmanr&3)<<1) + 1 + io_base ) +
- ( inb( ((dmanr&3)<<1) + 1 + io_base ) << 8 );
+ if (dmanr <= 3) {
+ return 1 + inb( ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ) +
+ (inb( ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ) << 8);
+ } else {
+ return 1 + inb( ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ) +
+ (inb( ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ) << 8);
+ }
}
/* These are in kernel/dma.c: */
diff --git a/include/asm/io.h b/include/asm/io.h
index 8e7810b..5059de6 100644
--- a/include/asm/io.h
+++ b/include/asm/io.h
@@ -24,13 +24,13 @@
#define SLOW_DOWN_IO __SLOW_DOWN_IO
#endif
-extern void inline outb(char value, unsigned short port)
+extern inline void outb(char value, unsigned short port)
{
__asm__ __volatile__ ("outb %%al,%%dx"
::"a" ((char) value),"d" ((unsigned short) port));
}
-extern unsigned int inline inb(unsigned short port)
+extern inline unsigned int inb(unsigned short port)
{
unsigned int _v;
__asm__ __volatile__ ("inb %%dx,%%al"
@@ -38,14 +38,14 @@ __asm__ __volatile__ ("inb %%dx,%%al"
return _v;
}
-extern void inline outb_p(char value, unsigned short port)
+extern inline void outb_p(char value, unsigned short port)
{
__asm__ __volatile__ ("outb %%al,%%dx"
::"a" ((char) value),"d" ((unsigned short) port));
SLOW_DOWN_IO;
}
-extern unsigned int inline inb_p(unsigned short port)
+extern inline unsigned int inb_p(unsigned short port)
{
unsigned int _v;
__asm__ __volatile__ ("inb %%dx,%%al"
diff --git a/include/asm/irq.h b/include/asm/irq.h
index d8a131a..fe82a03 100644
--- a/include/asm/irq.h
+++ b/include/asm/irq.h
@@ -119,8 +119,6 @@ __asm__( \
"pushl $" #nr "\n\t" \
"call _do_IRQ\n\t" \
"addl $8,%esp\n\t" \
- "testl %eax,%eax\n\t" \
- "jne ret_from_sys_call\n\t" \
"cli\n\t" \
UNBLK_##chip(mask) \
"jmp ret_from_sys_call\n" \
@@ -131,11 +129,8 @@ __asm__( \
"pushl $" #nr "\n\t" \
"call _do_fast_IRQ\n\t" \
"addl $4,%esp\n\t" \
- "testl %eax,%eax\n\t" \
- "jne 2f\n\t" \
"cli\n\t" \
UNBLK_##chip(mask) \
- "\n2:\t" \
RESTORE_MOST \
"\n\n.align 2\n" \
"_bad_IRQ" #nr "_interrupt:\n\t" \
diff --git a/include/asm/segment.h b/include/asm/segment.h
index 49fda90..17a1cfe 100644
--- a/include/asm/segment.h
+++ b/include/asm/segment.h
@@ -1,6 +1,6 @@
extern inline unsigned char get_fs_byte(const char * addr)
{
- unsigned register char _v;
+ register unsigned char _v;
__asm__ ("movb %%fs:%1,%0":"=q" (_v):"m" (*addr));
return _v;
diff --git a/include/linux/config.dist.h b/include/linux/config.dist.h
index 0ed4d5c..f933e36 100644
--- a/include/linux/config.dist.h
+++ b/include/linux/config.dist.h
@@ -7,6 +7,8 @@
#undef CONFIG_SCSI_AHA1542
#define CONFIG_SCSI_AHA1542
+#undef CONFIG_SCSI_AHA1740
+#define CONFIG_SCSI_AHA1740
#undef CONFIG_SCSI_CSC
#define CONFIG_SCSI_CSC
#undef CONFIG_SCSI_DTC
diff --git a/include/linux/config.h b/include/linux/config.h
index c08f507..59a636a 100644
--- a/include/linux/config.h
+++ b/include/linux/config.h
@@ -78,6 +78,7 @@
*/
#undef CONFIG_SCSI_AHA1542
+#undef CONFIG_SCSI_AHA1740
#undef CONFIG_SCSI_ALWAYS
#undef CONFIG_SCSI_CSC
#undef CONFIG_SCSI_DTC
@@ -92,7 +93,7 @@ defined(CONFIG_CHR_DEV_ST)
#define CONFIG_SCSI
#endif
-#if !defined(CONFIG_SCSI_AHA1542) && !defined(CONFIG_SCSI_CSC) && !defined(CONFIG_SCSI_DTC) && \
+#if !defined(CONFIG_SCSI_AHA1542) && !defined(CONFIG_SCSI_AHA1740) && !defined(CONFIG_SCSI_CSC) && !defined(CONFIG_SCSI_DTC) && \
!defined(CONFIG_SCSI_FUTURE_DOMAIN) && !defined(CONFIG_SCSI_SEAGATE) && !defined(CONFIG_SCSI_ULTRASTOR) && \
!defined(CONFIG_SCSI_7000FASST)
#error Error : SCSI devices enabled, but no low level drivers have been enabled.
@@ -108,6 +109,7 @@ defined(CONFIG_CHR_DEV_ST)
#define MSDOS_FS
#define PROC_FS
#undef NFS_FS
+#undef ISO9660_FS
#ifdef CONFIG_DISTRIBUTION
#include <linux/config.dist.h>
diff --git a/include/linux/ext_fs.h b/include/linux/ext_fs.h
index 9e16cba..d758843 100644
--- a/include/linux/ext_fs.h
+++ b/include/linux/ext_fs.h
@@ -74,7 +74,7 @@ extern int ext_link(struct inode * oldinode, struct inode * dir, const char * na
extern int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
extern int ext_rename(struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len);
-extern struct inode * ext_new_inode(struct super_block * sb);
+extern struct inode * ext_new_inode(const struct inode * dir);
extern void ext_free_inode(struct inode * inode);
extern unsigned long ext_count_free_inodes(struct super_block *sb);
extern int ext_new_block(struct super_block * sb);
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index 99361ed..8b0721a 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -15,10 +15,6 @@
#define O_NDELAY O_NONBLOCK
#define O_SYNC 010000
-/* Defines for fcntl-commands. Note that currently
- * locking isn't supported, and other things aren't really
- * tested.
- */
#define F_DUPFD 0 /* dup */
#define F_GETFD 1 /* get f_flags */
#define F_SETFD 2 /* set f_flags */
@@ -34,9 +30,6 @@
/* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-/* Ok, these are locking features, and aren't implemented at any
- * level. POSIX wants them.
- */
#define F_RDLCK 0
#define F_WRLCK 1
#define F_UNLCK 2
diff --git a/include/linux/fs.h b/include/linux/fs.h
index cf725b9..3f66d6f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -12,6 +12,27 @@
#include <linux/dirent.h>
#include <linux/vfs.h>
+/*
+ * It's silly to have NR_OPEN bigger than NR_FILE, but I'll fix
+ * that later. Anyway, now the file code is no longer dependent
+ * on bitmaps in unsigned longs, but uses the new fd_set structure..
+ *
+ * Some programs (notably those using select()) may have to be
+ * recompiled to take full advantage of the new limits..
+ */
+#undef NR_OPEN
+#define NR_OPEN 256
+
+#define NR_INODE 128
+#define NR_FILE 128
+#define NR_SUPER 16
+#define NR_HASH 997
+#define NR_FILE_LOCKS 32
+#define BLOCK_SIZE 1024
+#define BLOCK_SIZE_BITS 10
+#define MAX_CHRDEV 32
+#define MAX_BLKDEV 32
+
/* devices are as follows: (same as minix, so we can use the minix
* file system. These are major numbers.)
*
@@ -86,6 +107,7 @@ extern void inode_init(void);
#define BLKROSET 4701 /* set device read-only (0 = read-write) */
#define BLKROGET 4702 /* get read-only status (0 = read_write) */
#define BLKRRPART 4703 /* re-read partition table */
+#define BLKGETSIZE 4704 /* return device size */
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
#define FIBMAP 1 /* bmap access */
@@ -115,6 +137,7 @@ struct buffer_head {
#include <linux/minix_fs_i.h>
#include <linux/ext_fs_i.h>
#include <linux/msdos_fs_i.h>
+#include <linux/iso_fs_i.h>
struct inode {
dev_t i_dev;
@@ -151,6 +174,7 @@ struct inode {
struct minix_inode_info minix_i;
struct ext_inode_info ext_i;
struct msdos_inode_info msdos_i;
+ struct iso_inode_info isofs_i;
} u;
};
@@ -178,6 +202,7 @@ struct file_lock {
#include <linux/minix_fs_sb.h>
#include <linux/ext_fs_sb.h>
#include <linux/msdos_fs_sb.h>
+#include <linux/iso_fs_sb.h>
struct super_block {
dev_t s_dev;
@@ -196,6 +221,7 @@ struct super_block {
struct minix_sb_info minix_sb;
struct ext_sb_info ext_sb;
struct msdos_sb_info msdos_sb;
+ struct isofs_sb_info isofs_sb;
} u;
};
@@ -259,6 +285,7 @@ extern void grow_buffers(int size);
extern int shrink_buffers(unsigned int priority);
extern int nr_buffers;
+extern int buffermem;
extern int nr_buffer_heads;
extern void check_disk_change(dev_t dev);
@@ -301,6 +328,7 @@ extern void mount_root(void);
extern int char_read(struct inode *, struct file *, char *, int);
extern int block_read(struct inode *, struct file *, char *, int);
+extern int read_ahead[];
extern int char_write(struct inode *, struct file *, char *, int);
extern int block_write(struct inode *, struct file *, char *, int);
diff --git a/include/linux/ioctl.h b/include/linux/ioctl.h
index aa54938..68474e7 100644
--- a/include/linux/ioctl.h
+++ b/include/linux/ioctl.h
@@ -1,9 +1,11 @@
+/* $Id: ioctl.h,v 1.2 1992/11/18 01:31:16 root Exp root $
+ *
+ * linux/ioctl.h for Linux by H.H. Bergman.
+ */
+
#ifndef _LINUX_IOCTL_H
#define _LINUX_IOCTL_H
-/*
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
/* ioctl command encoding: 32 bits total, command in lower 16 bits,
* size of the parameter structure in the upper 14 bits.
@@ -34,4 +36,5 @@
#define _IOWR(c,d,t) (IOC_INOUT | (sizeof(t)<<16) & IOCSIZE_MASK) | \
(c<<8) | d)
-#endif
+#endif /* _LINUX_IOCTL_H */
+
diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h
new file mode 100644
index 0000000..4461913
--- /dev/null
+++ b/include/linux/iso_fs.h
@@ -0,0 +1,211 @@
+
+#ifndef _ISOFS_FS_H
+#define _ISOFS_FS_H
+
+#include <linux/types.h>
+/*
+ * The isofs filesystem constants/structures
+ */
+
+/* This part borrowed from the bsd386 isofs */
+#define ISODCL(from, to) (to - from + 1)
+
+struct iso_volume_descriptor {
+ char type[ISODCL(1,1)]; /* 711 */
+ char id[ISODCL(2,6)];
+ char version[ISODCL(7,7)];
+ char data[ISODCL(8,2048)];
+};
+
+/* volume descriptor types */
+#define ISO_VD_PRIMARY 1
+#define ISO_VD_END 255
+
+#define ISO_STANDARD_ID "CD001"
+
+struct iso_primary_descriptor {
+ char type [ISODCL ( 1, 1)]; /* 711 */
+ char id [ISODCL ( 2, 6)];
+ char version [ISODCL ( 7, 7)]; /* 711 */
+ char unused1 [ISODCL ( 8, 8)];
+ char system_id [ISODCL ( 9, 40)]; /* achars */
+ char volume_id [ISODCL ( 41, 72)]; /* dchars */
+ char unused2 [ISODCL ( 73, 80)];
+ char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
+ char unused3 [ISODCL ( 89, 120)];
+ char volume_set_size [ISODCL (121, 124)]; /* 723 */
+ char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
+ char logical_block_size [ISODCL (129, 132)]; /* 723 */
+ char path_table_size [ISODCL (133, 140)]; /* 733 */
+ char type_l_path_table [ISODCL (141, 144)]; /* 731 */
+ char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
+ char type_m_path_table [ISODCL (149, 152)]; /* 732 */
+ char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
+ char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
+ char volume_set_id [ISODCL (191, 318)]; /* dchars */
+ char publisher_id [ISODCL (319, 446)]; /* achars */
+ char preparer_id [ISODCL (447, 574)]; /* achars */
+ char application_id [ISODCL (575, 702)]; /* achars */
+ char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
+ char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
+ char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
+ char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
+ char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
+ char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
+ char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
+ char file_structure_version [ISODCL (882, 882)]; /* 711 */
+ char unused4 [ISODCL (883, 883)];
+ char application_data [ISODCL (884, 1395)];
+ char unused5 [ISODCL (1396, 2048)];
+};
+
+
+#define HS_STANDARD_ID "CDROM"
+
+struct hs_volume_descriptor {
+ char foo [ISODCL ( 1, 8)]; /* 733 */
+ char type [ISODCL ( 9, 9)]; /* 711 */
+ char id [ISODCL ( 10, 14)];
+ char version [ISODCL ( 15, 15)]; /* 711 */
+ char data[ISODCL(16,2048)];
+};
+
+
+struct hs_primary_descriptor {
+ char foo [ISODCL ( 1, 8)]; /* 733 */
+ char type [ISODCL ( 9, 9)]; /* 711 */
+ char id [ISODCL ( 10, 14)];
+ char version [ISODCL ( 15, 15)]; /* 711 */
+ char unused1 [ISODCL ( 16, 16)]; /* 711 */
+ char system_id [ISODCL ( 17, 48)]; /* achars */
+ char volume_id [ISODCL ( 49, 80)]; /* dchars */
+ char unused2 [ISODCL ( 81, 88)]; /* 733 */
+ char volume_space_size [ISODCL ( 89, 96)]; /* 733 */
+ char unused3 [ISODCL ( 97, 128)]; /* 733 */
+ char volume_set_size [ISODCL (129, 132)]; /* 723 */
+ char volume_sequence_number [ISODCL (133, 136)]; /* 723 */
+ char logical_block_size [ISODCL (137, 140)]; /* 723 */
+ char path_table_size [ISODCL (141, 148)]; /* 733 */
+ char type_l_path_table [ISODCL (149, 152)]; /* 731 */
+ char unused4 [ISODCL (153, 180)]; /* 733 */
+ char root_directory_record [ISODCL (181, 214)]; /* 9.1 */
+};
+
+/* We use this to help us look up the parent inode numbers. */
+
+struct iso_path_table{
+ char name_len[2]; /* 721 */
+ char extent[4]; /* 731 */
+ char parent[2]; /* 721 */
+ char name[0];
+};
+
+/* high sierra is identical to iso, except that the date is only 6 bytes, and
+ there is an extra reserved byte after the flags */
+
+struct iso_directory_record {
+ char length [ISODCL (1, 1)]; /* 711 */
+ char ext_attr_length [ISODCL (2, 2)]; /* 711 */
+ char extent [ISODCL (3, 10)]; /* 733 */
+ char size [ISODCL (11, 18)]; /* 733 */
+ char date [ISODCL (19, 25)]; /* 7 by 711 */
+ char flags [ISODCL (26, 26)];
+ char file_unit_size [ISODCL (27, 27)]; /* 711 */
+ char interleave [ISODCL (28, 28)]; /* 711 */
+ char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
+ char name_len [ISODCL (33, 33)]; /* 711 */
+ char name [0];
+};
+
+extern int isonum_711(char *);
+extern int isonum_712(char *);
+extern int isonum_721(char *);
+extern int isonum_722(char *);
+extern int isonum_723(char *);
+extern int isonum_731(char *);
+extern int isonum_732(char *);
+extern int isonum_733(char *);
+extern int iso_date(char *, int);
+
+extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *);
+extern int get_rock_ridge_filename(struct iso_directory_record *, char ** name, int * len, struct inode *);
+
+extern char * get_rock_ridge_symlink(struct inode *);
+extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inode *);
+
+#define ISOFS_BLOCK_BITS 11
+#define ISOFS_BLOCK_SIZE 2048
+
+/* We use these until the buffer cache supports 2048 */
+#define ISOFS_BUFFER_BITS 10
+#define ISOFS_BUFFER_SIZE 1024
+
+#define ISOFS_BLOCK_NUMBER(X) (X<<1)
+
+
+#define ISOFS_SUPER_MAGIC 0x9660
+#define ISOFS_FILE_UNKNOWN 0
+#define ISOFS_FILE_TEXT 1
+#define ISOFS_FILE_BINARY 2
+#define ISOFS_FILE_TEXT_M 3
+
+
+/* The stuff that follows may be totally unneeded. I have not checked to see
+ which prototypes we are still using. */
+
+extern int isofs_open(struct inode * inode, struct file * filp);
+extern void isofs_release(struct inode * inode, struct file * filp);
+extern int isofs_lookup(struct inode * dir,const char * name, int len,
+ struct inode ** result);
+extern unsigned long isofs_count_free_inodes(struct super_block *sb);
+extern int isofs_new_block(int dev);
+extern int isofs_free_block(int dev, int block);
+extern int isofs_bmap(struct inode *,int);
+
+extern void isofs_put_super(struct super_block *);
+extern struct super_block *isofs_read_super(struct super_block *,void *);
+extern void isofs_read_inode(struct inode *);
+extern void isofs_put_inode(struct inode *);
+extern void isofs_statfs(struct super_block *, struct statfs *);
+
+extern int isofs_lseek(struct inode *, struct file *, off_t, int);
+extern int isofs_read(struct inode *, struct file *, char *, int);
+extern int isofs_file_read(struct inode *, struct file *, char *, int);
+extern int isofs_lookup_grandparent(struct inode *, int);
+
+extern struct inode_operations isofs_file_inode_operations;
+extern struct inode_operations isofs_dir_inode_operations;
+extern struct inode_operations isofs_symlink_inode_operations;
+extern struct inode_operations isofs_chrdev_inode_operations;
+extern struct inode_operations isofs_blkdev_inode_operations;
+
+extern struct file_operations isofs_file_operations;
+extern struct file_operations isofs_dir_operations;
+
+struct lookup_cache{
+ char lock;
+ unsigned long dir; /* If this matches... */
+ dev_t dev; /* And this matches */
+ unsigned short dlen; /* and this matches... */
+ char filename[256]; /* and this matches... */
+ unsigned long ino; /* Then this is the file we are looking for */
+};
+
+extern struct lookup_cache cache;
+
+/* The following macros are used to check for memory leaks. */
+#ifdef LEAK_CHECK
+#define free_s leak_check_free_s
+#define malloc leak_check_malloc
+#define bread leak_check_bread
+#define brelse leak_check_brelse
+extern void * leak_check_malloc(unsigned int size);
+extern void leak_check_free_s(void * obj, int size);
+extern struct buffer_head * leak_check_bread(int dev, int block, int size);
+extern void leak_check_brelse(struct buffer_head * bh);
+#endif /* LEAK_CHECK */
+
+#endif
+
+
+
diff --git a/include/linux/iso_fs_i.h b/include/linux/iso_fs_i.h
new file mode 100644
index 0000000..d806550
--- /dev/null
+++ b/include/linux/iso_fs_i.h
@@ -0,0 +1,13 @@
+#ifndef _ISO_FS_I
+#define _ISO_FS_I
+
+/*
+ * iso fs inode data in memory
+ */
+struct iso_inode_info {
+ unsigned int i_first_extent;
+ unsigned int i_backlink;
+ unsigned char i_file_format;
+};
+
+#endif
diff --git a/include/linux/iso_fs_sb.h b/include/linux/iso_fs_sb.h
new file mode 100644
index 0000000..ee2595a
--- /dev/null
+++ b/include/linux/iso_fs_sb.h
@@ -0,0 +1,30 @@
+#ifndef _ISOFS_FS_SB
+#define _ISOFS_FS_SB
+
+/*
+ * minix super-block data in memory
+ */
+struct isofs_sb_info {
+ unsigned long s_ninodes;
+ unsigned long s_nzones;
+ unsigned long s_firstdatazone;
+ unsigned long s_log_zone_size;
+ unsigned long s_max_size;
+
+ unsigned char s_high_sierra; /* A simple flag */
+ unsigned char s_mapping;
+ unsigned char s_conversion;
+ unsigned char s_rock;
+ unsigned char s_cruft; /* Broken disks with high
+ byte of length containing
+ junk */
+};
+
+#endif
+
+
+
+
+
+
+
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e80507f..fbfec68 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -9,6 +9,7 @@ void verify_area(void * addr,int count);
volatile void panic(const char * str);
volatile void do_exit(long error_code);
unsigned long simple_strtoul(const char *,char **,unsigned int);
+int sprintf(char * buf, const char * fmt, ...);
int printk(const char * fmt, ...);
void * kmalloc(unsigned int size, int priority);
@@ -25,4 +26,18 @@ void kfree_s(void * obj, int size);
*/
#define suser() (current->euid == 0)
+#define SI_LOAD_SHIFT 16
+struct sysinfo {
+ long uptime; /* Seconds since boot */
+ unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
+ unsigned long totalram; /* Total usable main memory size */
+ unsigned long freeram; /* Available memory size */
+ unsigned long sharedram; /* Amount of shared memory */
+ unsigned long bufferram; /* Memory used by buffers */
+ unsigned long totalswap; /* Total swap space size */
+ unsigned long freeswap; /* swap space still available */
+ unsigned short procs; /* Number of current processes */
+ char _f[22]; /* Pads structure to 64 bytes */
+};
+
#endif
diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h
new file mode 100644
index 0000000..b3f01b6
--- /dev/null
+++ b/include/linux/keyboard.h
@@ -0,0 +1,103 @@
+#ifndef __LINUX_KEYBOARD_H
+#define __LINUX_KEYBOARD_H
+
+/*
+ * Global flags: things that don't change between virtual consoles.
+ * This includes things like "key-down" flags - if the shift key is
+ * down when you change a console, it's down in both.
+ *
+ * Note that the KG_CAPSLOCK flags is NOT the flag that decides if
+ * capslock is on or not: it's just a flag about the key being
+ * physically down. The actual capslock status is in the local flags.
+ */
+extern unsigned long kbd_flags;
+
+/*
+ * These are the hardcoded global flags - use the numbers beyond 16
+ * for non-standard or keyboard-dependent flags
+ */
+#define KG_LSHIFT 0
+#define KG_RSHIFT 1
+#define KG_LCTRL 2
+#define KG_RCTRL 3
+#define KG_ALT 4
+#define KG_ALTGR 5
+#define KG_CAPSLOCK 6
+#define KG_E0 7
+#define KG_E1 8
+
+/*
+ * kbd->xxx contains the VC-local things (flag settings etc..)
+ * The low 3 local flags are hardcoded to be the led setting..
+ */
+struct kbd_struct {
+ unsigned long flags;
+ unsigned long default_flags;
+ unsigned char kbd_flags;
+};
+
+extern struct kbd_struct kbd_table[];
+
+/*
+ * These are the local "softflags", giving actual keyboard modes. The
+ * three first flags are coded to the led settings.
+ */
+#define VC_SCROLLOCK 0 /* scroll-lock mode */
+#define VC_NUMLOCK 1 /* numeric lock mode */
+#define VC_CAPSLOCK 2 /* capslock mode */
+#define VC_APPLIC 3 /* application key mode */
+#define VC_CKMODE 5 /* cursor key mode */
+#define VC_REPEAT 6 /* keyboard repeat */
+#define VC_RAW 7 /* raw (scancode) mode */
+#define VC_CRLF 8 /* 0 - enter sends CR, 1 - enter sends CRLF */
+#define VC_META 9 /* 0 - meta, 1 - meta=prefix with ESC */
+
+#define LED_MASK 7
+
+#ifndef KBD_DEFFLAGS
+#define KBD_DEFFLAGS ((1 << VC_NUMLOCK) | (1 << VC_REPEAT))
+#endif
+
+extern unsigned long kbd_init(unsigned long);
+
+extern inline int kbd_flag(int flag)
+{
+ return kbd_flags & (1 << flag);
+}
+
+extern inline void set_kbd_flag(int flag)
+{
+ kbd_flags |= 1 << flag;
+}
+
+extern inline void clr_kbd_flag(int flag)
+{
+ kbd_flags &= ~(1 << flag);
+}
+
+extern inline void chg_kbd_flag(int flag)
+{
+ kbd_flags ^= 1 << flag;
+}
+
+extern inline int vc_kbd_flag(struct kbd_struct * kbd, int flag)
+{
+ return ((kbd->flags >> flag) & 1);
+}
+
+extern inline void set_vc_kbd_flag(struct kbd_struct * kbd, int flag)
+{
+ kbd->flags |= 1 << flag;
+}
+
+extern inline void clr_vc_kbd_flag(struct kbd_struct * kbd, int flag)
+{
+ kbd->flags &= ~(1 << flag);
+}
+
+extern inline void chg_vc_kbd_flag(struct kbd_struct * kbd, int flag)
+{
+ kbd->flags ^= 1 << flag;
+}
+
+#endif
diff --git a/include/linux/limits.h b/include/linux/limits.h
index adfdf8f..4163ab7 100644
--- a/include/linux/limits.h
+++ b/include/linux/limits.h
@@ -1,26 +1,7 @@
#ifndef _LINUX_LIMITS_H
#define _LINUX_LIMITS_H
-#define NAME_MAX 255
-
-/*
- * It's silly to have NR_OPEN bigger than NR_FILE, but I'll fix
- * that later. Anyway, now the file code is no longer dependent
- * on bitmaps in unsigned longs, but uses the new fd_set structure..
- *
- * Some programs (notably those using select()) may have to be
- * recompiled to take full advantage of the new limits..
- */
-#define NR_OPEN 256
-#define NR_INODE 128
-#define NR_FILE 128
-#define NR_SUPER 16
-#define NR_HASH 997
-#define NR_FILE_LOCKS 32
-#define BLOCK_SIZE 1024
-#define BLOCK_SIZE_BITS 10
-#define MAX_CHRDEV 32
-#define MAX_BLKDEV 32
+#define NR_OPEN 256
#define NGROUPS_MAX 32 /* supplemental group IDs are available */
#define ARG_MAX 131072 /* # bytes of args + environ for exec() */
diff --git a/include/linux/lp.h b/include/linux/lp.h
index d0d1607..b73709c 100644
--- a/include/linux/lp.h
+++ b/include/linux/lp.h
@@ -14,13 +14,6 @@
*/
/*
- * caveat: my machine only has 1 printer @ lpt2 so lpt1 & lpt3 are
- * implemented but UNTESTED
- *
- * My machine (Michael K. Johnson) has only lpt1... dupla caveat...
- */
-
-/*
* Per POSIX guidelines, this module reserves the LP and lp prefixes
* These are the lp_table[minor].flags flags...
*/
@@ -30,28 +23,60 @@
#define LP_OFFL 0x0008
#define LP_NOPA 0x0010
#define LP_ERR 0x0020
+#define LP_ABORT 0x0040
+
+/* timeout for each character. This is relative to bus cycles -- it
+ * is the count in a busy loop. THIS IS THE VALUE TO CHANGE if you
+ * have extremely slow printing, or if the machine seems to slow down
+ * a lot when you print. If you have slow printing, increase this
+ * number and recompile, and if your system gets bogged down, decrease
+ * this number. This can be changed with the tunelp(8) command.
+ */
+
+#define LP_INIT_CHAR 250
+
+/* The parallel port specs apparently say that there needs to be
+ * a .5usec wait before and after the strobe. Since there are wildly
+ * different computers running linux, I can't come up with a perfect
+ * value, but since it worked well on most printers before without,
+ * and I have seen some improvement on my computer by making it a
+ * small number, I'll initialize it to 2.
+ */
+
+#define LP_INIT_WAIT 2
+
+/* This is the amount of time that the driver waits for the printer to
+ * catch up when the printer's buffer appears to be filled. If you
+ * want to tune this and have a fast printer (i.e. HPIIIP), decrease
+ * this number, and if you have a slow printer, increase this number.
+ * This is in hundredths of a second, the default 10 being .1 second.
+ * Or use the tunelp(8) command, which is especially nice if you want
+ * change back and forth between character and graphics printing, which
+ * are wildly different...
+ */
+
+#define LP_INIT_TIME 10
-/* timeout for each character (This is a good case 50 Mhz computer
- at a poor case 10 KBS xfer rate to the printer, as best as I can
- tell.) This is in instruction cycles, kinda -- it is the count
- in a busy loop. THIS IS THE VALUE TO CHANGE if you have extremely
- slow printing, or if the machine seems to slow down a lot when you
- print. If you have slow printing, increase this number and recompile,
- and if your system gets bogged down, decrease this number.*/
-#define LP_TIME_CHAR 5000
+/* IOCTL numbers */
+#define LPCHAR 0x0001 /* corresponds to LP_INIT_CHAR */
+#define LPTIME 0x0002 /* corresponds to LP_INIT_TIME */
+#define LPABORT 0x0004 /* call with TRUE arg to abort on error,
+ FALSE to retry. Default is retry. */
+#define LPWAIT 0x0008 /* corresponds to LP_INIT_WAIT */
/* timeout for printk'ing a timeout, in jiffies (100ths of a second).
- If your printer isn't printing at least one character every five seconds,
- you have worse problems than a slow printer driver and lp_timeout printed
- every five seconds while trying to print. */
-#define LP_TIMEOUT 5000
+ This is also used for re-checking error conditions if LP_ABORT is
+ not set. This is the default behavior. */
+
+#define LP_TIMEOUT 1000
#define LP_B(minor) lp_table[(minor)].base /* IO address */
#define LP_F(minor) lp_table[(minor)].flags /* flags for busy, etc. */
#define LP_S(minor) inb(LP_B((minor)) + 1) /* status port */
#define LP_C(minor) (lp_table[(minor)].base + 2) /* control port */
-#define LP_COUNT(minor) lp_table[(minor)].count /* last count */
-#define LP_TIME(minor) lp_table[(minor)].time /* last time */
+#define LP_CHAR(minor) lp_table[(minor)].chars /* busy timeout */
+#define LP_TIME(minor) lp_table[(minor)].time /* wait time */
+#define LP_WAIT(minor) lp_table[(minor)].wait /* strobe wait */
/*
since we are dealing with a horribly slow device
@@ -60,28 +85,11 @@ I don't see the need for a queue
struct lp_struct {
int base;
int flags;
- int count;
- int time;
+ unsigned int chars;
+ unsigned int time;
+ unsigned int wait;
};
-/* This is the starting value for the heuristic algorithm. If you
- * want to tune this and have a fast printer (i.e. HPIIIP), decrease
- * this number, and if you have a slow printer, increase this number.
- * This is not stricly necessary, as the algorithm should be able to
- * adapt to your printer relatively quickly.
- * this is in hundredths of a second, the default 50 being .5 seconds.
- */
-
-#define LP_INIT_TIME 50
-
-/* This is our first guess at the size of the buffer on the printer,
- * in characters. I am assuming a 4K buffer because most newer printers
- * have larger ones, which will be adapted to. At this time, it really
- * doesn't matter, as this value isn't used.
- */
-
-#define LP_INIT_COUNT 4096
-
/* the BIOS manuals say there can be up to 4 lpt devices
* but I have not seen a board where the 4th address is listed
* if you have different hardware change the table below
@@ -89,9 +97,9 @@ struct lp_struct {
* if you have more than 3 printers, remember to increase LP_NO
*/
struct lp_struct lp_table[] = {
- { 0x3bc, 0, LP_INIT_COUNT, LP_INIT_TIME, },
- { 0x378, 0, LP_INIT_COUNT, LP_INIT_TIME, },
- { 0x278, 0, LP_INIT_COUNT, LP_INIT_TIME, }
+ { 0x3bc, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, },
+ { 0x378, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, },
+ { 0x278, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, },
};
#define LP_NO 3
diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h
index c709962..f97fbcd 100644
--- a/include/linux/minix_fs.h
+++ b/include/linux/minix_fs.h
@@ -57,7 +57,7 @@ extern int minix_link(struct inode * oldinode, struct inode * dir, const char *
extern int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
extern int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len);
-extern struct inode * minix_new_inode(struct super_block * sb);
+extern struct inode * minix_new_inode(const struct inode * dir);
extern void minix_free_inode(struct inode * inode);
extern unsigned long minix_count_free_inodes(struct super_block *sb);
extern int minix_new_block(struct super_block * sb);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index e250898..146e569 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -96,12 +96,14 @@ extern void mem_init(unsigned long low_start_mem,
extern void show_mem(void);
extern void do_page_fault(unsigned long *esp, unsigned long error_code);
extern void oom(struct task_struct * task);
+extern void si_meminfo(struct sysinfo * val);
/* swap.c */
extern void swap_free(unsigned int page_nr);
extern void swap_duplicate(unsigned int page_nr);
extern void swap_in(unsigned long *table_ptr);
+extern void si_swapinfo(struct sysinfo * val);
#define invalidate() \
__asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3":::"ax")
diff --git a/include/linux/mtio.h b/include/linux/mtio.h
index 4c39a8a..47f803f 100644
--- a/include/linux/mtio.h
+++ b/include/linux/mtio.h
@@ -1,9 +1,12 @@
+/* $Id: mtio.h,v 1.4 1992/11/18 01:32:03 root Exp root $
+ *
+ * linux/mtio.h header file for Linux. Written by H. Bergman
+ */
+
#ifndef _LINUX_MTIO_H
#define _LINUX_MTIO_H
-/*
- * linux/mtio.h header file for Linux. Written by H. Bergman
- */
+#include <linux/ioctl.h>
/*
* Structures and definitions for mag tape io control commands
@@ -42,12 +45,9 @@ struct mtop {
#define MTSETBLK 20 /* set block length (SCSI) */
+#define MTSETDENSITY 21 /* set tape density (SCSI) */
-/* may need to add
-#define MTFORMAT
- * or something similar for QIC-40/80 type tapes.
- */
/* structure for MTIOCGET - mag tape get status command */
@@ -138,4 +138,5 @@ struct mt_tape_info {
* I think DDS drives are DAT drives.
*/
-#endif /* not _LINUX_MTIO_H */
+#endif /* _LINUX_MTIO_H */
+
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 67f3cad..b8bc123 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -9,16 +9,24 @@
#define PROC_SUPER_MAGIC 0x9fa0
+struct proc_dir_entry {
+ unsigned short low_ino;
+ unsigned short namelen;
+ char * name;
+};
+
extern struct super_block *proc_read_super(struct super_block *,void *);
extern void proc_put_inode(struct inode *);
extern void proc_put_super(struct super_block *);
extern void proc_statfs(struct super_block *, struct statfs *);
extern void proc_read_inode(struct inode *);
extern void proc_write_inode(struct inode *);
+extern int proc_match(int, const char *, struct proc_dir_entry *);
extern struct inode_operations proc_root_inode_operations;
extern struct inode_operations proc_base_inode_operations;
extern struct inode_operations proc_mem_inode_operations;
+extern struct inode_operations proc_array_inode_operations;
extern struct inode_operations proc_link_inode_operations;
extern struct inode_operations proc_fd_inode_operations;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 3e9bd9a..b6fd6df 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -38,6 +38,8 @@
* the EXP_n values would be 1981, 2034 and 2043 if still using only
* 11 bit fractions.
*/
+extern unsigned long avenrun[]; /* Load averages */
+
#define FSHIFT 11 /* nr of bits of precision */
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */
#define LOAD_FREQ (5*HZ) /* 5 sec intervals */
@@ -77,7 +79,7 @@
#define NULL ((void *) 0)
#endif
-#define MAX_SHARED_LIBS 6
+#define MAX_SHARED_LIBS 16
extern void sched_init(void);
extern void show_state(void);
@@ -107,7 +109,7 @@ union i387_union {
long foo;
long fos;
long top;
- struct fpu_reg regs[8]; /* 8*16 bytes for each FP-reg = 112 bytes */
+ struct fpu_reg regs[8]; /* 8*16 bytes for each FP-reg = 128 bytes */
unsigned char lookahead;
struct info *info;
unsigned long entry_eip;
@@ -221,7 +223,7 @@ struct task_struct {
*/
#define INIT_TASK \
/* state etc */ { 0,15,15, \
-/* signals */ 0,{{},},0,0,0, \
+/* signals */ 0,{{ 0, },},0,0,0, \
/* flags */ 0, \
/* ec,brk... */ 0,0,0,0,0,0,0,0, \
/* pid etc.. */ 0,0,0,0, \
@@ -238,9 +240,9 @@ struct task_struct {
/* comm */ "swapper", \
/* vm86_info */ NULL, 0, \
/* fs info */ 0,-1,0022,NULL,NULL,NULL,NULL, \
-/* libraries */ { { NULL, 0, 0}, }, 0, \
+/* libraries */ { { NULL, 0, 0, 0}, }, 0, \
/* filp */ {NULL,}, \
-/* cloe */ {0,}, \
+/* cloe */ {{ 0, }}, \
{ \
{0,0}, \
/* ldt */ {0x9f,0xc0c0fa00}, \
@@ -251,8 +253,8 @@ struct task_struct {
0,0,0,0,0,0,0,0, \
0,0,0x17,0x17,0x17,0x17,0x17,0x17, \
_LDT(0),0x80000000,{0xffffffff}, \
- { { 0, } } \
- }, \
+ { { 0, }, } \
+ } \
}
extern struct task_struct *task[NR_TASKS];
@@ -430,7 +432,7 @@ extern inline void select_wait(struct wait_queue ** wait_address, select_table *
p->nr++;
}
-static unsigned long inline _get_base(char * addr)
+static inline unsigned long _get_base(char * addr)
{
unsigned long __base;
__asm__("movb %3,%%dh\n\t"
@@ -446,7 +448,7 @@ static unsigned long inline _get_base(char * addr)
#define get_base(ldt) _get_base( ((char *)&(ldt)) )
-static unsigned long inline get_limit(unsigned long segment)
+static inline unsigned long get_limit(unsigned long segment)
{
unsigned long __limit;
__asm__("lsll %1,%0"
@@ -464,7 +466,7 @@ static unsigned long inline get_limit(unsigned long segment)
#define SET_LINKS(p) \
(p)->p_ysptr = NULL; \
- if ((p)->p_osptr = (p)->p_pptr->p_cptr) \
+ if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \
(p)->p_osptr->p_ysptr = p; \
(p)->p_pptr->p_cptr = p
diff --git a/include/linux/sys.h b/include/linux/sys.h
index 0955745..c5c831c 100644
--- a/include/linux/sys.h
+++ b/include/linux/sys.h
@@ -118,6 +118,7 @@ extern int sys_idle();
extern int sys_vm86();
extern int sys_wait4();
extern int sys_swapoff();
+extern int sys_sysinfo();
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
@@ -140,7 +141,7 @@ sys_truncate, sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority,
sys_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm,
sys_socketcall, sys_syslog, sys_setitimer, sys_getitimer, sys_newstat,
sys_newlstat, sys_newfstat, sys_newuname, sys_iopl, sys_vhangup,
-sys_idle, sys_vm86, sys_wait4, sys_swapoff };
+sys_idle, sys_vm86, sys_wait4, sys_swapoff, sys_sysinfo };
/* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
diff --git a/include/linux/unistd.h b/include/linux/unistd.h
index f28aa00..e5ef1be 100644
--- a/include/linux/unistd.h
+++ b/include/linux/unistd.h
@@ -122,6 +122,7 @@
#define __NR_vm86 113
#define __NR_wait4 114
#define __NR_swapoff 115
+#define __NR_sysinfo 116
extern int errno;
diff --git a/init/main.c b/init/main.c
index f321081..0f664b5 100644
--- a/init/main.c
+++ b/init/main.c
@@ -78,6 +78,7 @@ extern unsigned long scsi_dev_init(unsigned long, unsigned long);
#define EXT_MEM_K (*(unsigned short *)0x90002)
#define DRIVE_INFO (*(struct drive_info *)0x90080)
#define SCREEN_INFO (*(struct screen_info *)0x90000)
+#define RAMDISK_SIZE (*(unsigned short *)0x901F8)
#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
#define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
@@ -145,6 +146,7 @@ struct drive_info { char dummy[32]; } drive_info;
struct screen_info screen_info;
unsigned char aux_device_present;
+int ramdisk_size;
static char command_line[80] = { 0, };
@@ -169,8 +171,8 @@ static void parse_options(char *line)
args = 0;
envs = 1; /* TERM is set to 'console' by default */
next = line;
- while (line = next) {
- if (next = strchr(line,' '))
+ while ((line = next) != NULL) {
+ if ((next = strchr(line,' ')) != NULL)
*next++ = 0;
/*
* check for kernel options first..
@@ -209,6 +211,7 @@ void start_kernel(void)
aux_device_present = AUX_DEVICE_INFO;
memory_end = (1<<20) + (EXT_MEM_K<<10);
memory_end &= 0xfffff000;
+ ramdisk_size = RAMDISK_SIZE;
#ifdef MAX_16M
if (memory_end > 16*1024*1024)
memory_end = 16*1024*1024;
@@ -294,7 +297,7 @@ void init(void)
while (pid != wait(&i))
/* nothing */;
while (1) {
- if ((pid=fork())<0) {
+ if ((pid = fork()) < 0) {
printf("Fork failed in init\r\n");
continue;
}
diff --git a/kernel/FPU-emu/Makefile b/kernel/FPU-emu/Makefile
index d7db872..25abfd8 100644
--- a/kernel/FPU-emu/Makefile
+++ b/kernel/FPU-emu/Makefile
@@ -54,74 +54,79 @@ errors.o : errors.c /usr/include/linux/signal.h /usr/include/asm/segment.h fpu_s
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h exception.h fpu_emu.h fpu_proto.h status_w.h control_w.h \
- reg_constant.h version.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ exception.h fpu_emu.h fpu_proto.h status_w.h control_w.h reg_constant.h version.h
fpu_arith.o : fpu_arith.c fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- fpu_emu.h fpu_proto.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h fpu_emu.h fpu_proto.h
fpu_aux.o : fpu_aux.c fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- exception.h fpu_emu.h fpu_proto.h status_w.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h exception.h fpu_emu.h \
+ fpu_proto.h status_w.h
fpu_entry.o : fpu_entry.c /usr/include/linux/signal.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h
fpu_etc.o : fpu_etc.c fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- exception.h fpu_emu.h fpu_proto.h status_w.h reg_constant.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h exception.h fpu_emu.h \
+ fpu_proto.h status_w.h reg_constant.h
fpu_trig.o : fpu_trig.c fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- exception.h fpu_emu.h fpu_proto.h status_w.h control_w.h reg_constant.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h exception.h fpu_emu.h \
+ fpu_proto.h status_w.h control_w.h reg_constant.h
get_address.o : get_address.c /usr/include/linux/stddef.h /usr/include/asm/segment.h \
fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h exception.h fpu_emu.h \
- fpu_proto.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h exception.h fpu_emu.h fpu_proto.h
load_store.o : load_store.c /usr/include/asm/segment.h fpu_system.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h exception.h fpu_emu.h fpu_proto.h status_w.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ exception.h fpu_emu.h fpu_proto.h status_w.h
poly_2xm1.o : poly_2xm1.c exception.h fpu_emu.h /usr/include/linux/math_emu.h \
fpu_proto.h reg_constant.h
poly_atan.o : poly_atan.c exception.h fpu_emu.h /usr/include/linux/math_emu.h \
@@ -138,30 +143,32 @@ reg_compare.o : reg_compare.c fpu_system.h /usr/include/linux/sched.h /usr/inclu
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- exception.h fpu_emu.h fpu_proto.h status_w.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h exception.h fpu_emu.h \
+ fpu_proto.h status_w.h
reg_constant.o : reg_constant.c fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- fpu_emu.h fpu_proto.h status_w.h reg_constant.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h fpu_emu.h fpu_proto.h \
+ status_w.h reg_constant.h
reg_ld_str.o : reg_ld_str.c /usr/include/asm/segment.h fpu_system.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h exception.h fpu_emu.h fpu_proto.h reg_constant.h \
- control_w.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ exception.h fpu_emu.h fpu_proto.h reg_constant.h control_w.h
reg_mul.o : reg_mul.c exception.h fpu_emu.h /usr/include/linux/math_emu.h fpu_proto.h \
reg_constant.h
div_small.o : div_small.S fpu_asm.h fpu_emu.h
diff --git a/kernel/FPU-emu/errors.c b/kernel/FPU-emu/errors.c
index 3ab5287..1cf6503 100644
--- a/kernel/FPU-emu/errors.c
+++ b/kernel/FPU-emu/errors.c
@@ -160,16 +160,16 @@ static struct {
int type;
char *name;
} exception_names[] = {
- EX_StackOver, "stack overflow",
- EX_StackUnder, "stack underflow",
- EX_Precision, "loss of precision",
- EX_Underflow, "underflow",
- EX_Overflow, "overflow",
- EX_ZeroDiv, "divide by zero",
- EX_Denormal, "denormalized operand",
- EX_Invalid, "invalid operation",
- EX_INTERNAL, "INTERNAL BUG in "FPU_VERSION,
- 0,0
+ { EX_StackOver, "stack overflow" },
+ { EX_StackUnder, "stack underflow" },
+ { EX_Precision, "loss of precision" },
+ { EX_Underflow, "underflow" },
+ { EX_Overflow, "overflow" },
+ { EX_ZeroDiv, "divide by zero" },
+ { EX_Denormal, "denormalized operand" },
+ { EX_Invalid, "invalid operation" },
+ { EX_INTERNAL, "INTERNAL BUG in "FPU_VERSION },
+ { 0, NULL }
};
/*
@@ -220,7 +220,8 @@ static struct {
void exception(int n)
{
int i, int_type;
-
+
+ int_type = 0;
if ( n & EX_INTERNAL )
{
int_type = n - EX_INTERNAL;
diff --git a/kernel/FPU-emu/load_store.c b/kernel/FPU-emu/load_store.c
index 7e66a51..011ff34 100644
--- a/kernel/FPU-emu/load_store.c
+++ b/kernel/FPU-emu/load_store.c
@@ -48,6 +48,7 @@ void load_store_instr(char type)
{
FPU_REG *pop_ptr; /* We need a version of FPU_st0_ptr which won't change. */
+ pop_ptr = NULL;
switch ( type_table[(int) (unsigned) type] )
{
case _NONE_:
diff --git a/kernel/FPU-emu/reg_ld_str.c b/kernel/FPU-emu/reg_ld_str.c
index 9028bd4..b6e87db 100644
--- a/kernel/FPU-emu/reg_ld_str.c
+++ b/kernel/FPU-emu/reg_ld_str.c
@@ -805,7 +805,8 @@ int reg_store_int64(void)
round_to_int(&t);
((long *)&tll)[0] = t.sigl;
((long *)&tll)[1] = t.sigh;
- if ( t.sigh & 0x80000000 )
+ if ( (t.sigh & 0x80000000) &&
+ !((t.sigh == 0x80000000) && (t.sigl == 0) && (t.sign == SIGN_NEG)) )
{
EXCEPTION(EX_Invalid);
/* This is a special case: see sec 16.2.5.1 of the 80486 book */
@@ -819,7 +820,7 @@ put_indefinite:
else
return 0;
}
- else if (t.sign)
+ else if ( t.sign )
tll = - tll;
RE_ENTRANT_CHECK_OFF
@@ -837,7 +838,6 @@ int reg_store_int32(void)
{
long *d = (long *)FPU_data_address;
FPU_REG t;
- long tl;
if ( FPU_st0_tag == TW_Empty )
{
@@ -859,24 +859,26 @@ int reg_store_int32(void)
reg_move(FPU_st0_ptr, &t);
round_to_int(&t);
- if (t.sigh || (t.sigl & 0x80000000))
+ if (t.sigh ||
+ ((t.sigl & 0x80000000) &&
+ !((t.sigl == 0x80000000) && (t.sign == SIGN_NEG))) )
{
EXCEPTION(EX_Invalid);
/* This is a special case: see sec 16.2.5.1 of the 80486 book */
if ( control_word & EX_Invalid )
{
/* Produce "indefinite" */
- tl = 0x80000000;
+ t.sigl = 0x80000000;
}
else
return 0;
}
- else
- tl = FPU_st0_ptr->sign ? -t.sigl : t.sigl;
+ else if ( t.sign )
+ t.sigl = -(long)t.sigl;
RE_ENTRANT_CHECK_OFF
verify_area(d,4);
- put_fs_long(tl, (unsigned long *) d);
+ put_fs_long(t.sigl, (unsigned long *) d);
RE_ENTRANT_CHECK_ON
return 1;
@@ -910,7 +912,9 @@ int reg_store_int16(void)
reg_move(FPU_st0_ptr, &t);
round_to_int(&t);
- if (t.sigh || (t.sigl & 0xFFFF8000))
+ if (t.sigh ||
+ ((t.sigl & 0xffff8000) &&
+ !((t.sigl == 0x8000) && (t.sign == SIGN_NEG))) )
{
EXCEPTION(EX_Invalid);
/* This is a special case: see sec 16.2.5.1 of the 80486 book */
@@ -922,12 +926,12 @@ int reg_store_int16(void)
else
return 0;
}
- else
- ts = FPU_st0_ptr->sign ? -t.sigl : t.sigl;
+ else if ( t.sign )
+ t.sigl = -t.sigl;
RE_ENTRANT_CHECK_OFF
verify_area(d,2);
- put_fs_word(ts,(short *) d);
+ put_fs_word((short)t.sigl,(short *) d);
RE_ENTRANT_CHECK_ON
return 1;
diff --git a/kernel/FPU-emu/version.h b/kernel/FPU-emu/version.h
index 7d69a85..4472e47 100644
--- a/kernel/FPU-emu/version.h
+++ b/kernel/FPU-emu/version.h
@@ -8,5 +8,5 @@
| |
+---------------------------------------------------------------------------*/
-#define FPU_VERSION "wm-FPU-emu version ALPHA 0.7"
+#define FPU_VERSION "wm-FPU-emu version ALPHA 0.8"
diff --git a/kernel/Makefile b/kernel/Makefile
index fa352d2..fd910e5 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -20,7 +20,8 @@ SUBDIRS = chr_drv blk_drv FPU-emu
OBJS = sched.o sys_call.o traps.o irq.o dma.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
- signal.o mktime.o ptrace.o ioport.o itimer.o
+ signal.o mktime.o ptrace.o ioport.o itimer.o \
+ info.o
all: kernel.o kernelsubdirs
@@ -58,117 +59,133 @@ exit.o : exit.c /usr/include/linux/wait.h /usr/include/linux/errno.h /usr/includ
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
- /usr/include/asm/segment.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \
+ /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/asm/segment.h
fork.o : fork.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/stddef.h /usr/include/asm/segment.h /usr/include/asm/system.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/stddef.h \
+ /usr/include/asm/segment.h /usr/include/asm/system.h
+info.o : info.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \
+ /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
+ /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
+ /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \
+ /usr/include/linux/unistd.h
ioport.o : ioport.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/errno.h
irq.o : irq.c /usr/include/linux/ptrace.h /usr/include/linux/errno.h /usr/include/linux/signal.h \
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/asm/system.h /usr/include/asm/io.h \
- /usr/include/asm/irq.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/asm/system.h /usr/include/asm/io.h /usr/include/asm/irq.h
itimer.o : itimer.c /usr/include/linux/signal.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \
- /usr/include/linux/errno.h /usr/include/asm/segment.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/errno.h \
+ /usr/include/asm/segment.h
mktime.o : mktime.c /usr/include/linux/mktime.h
panic.o : panic.c /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h
-printk.o : printk.c /usr/lib/gcc-lib/i386-linux/2.2.2d/include/stdarg.h /usr/include/asm/segment.h \
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h
+printk.o : printk.c /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h /usr/include/asm/segment.h \
/usr/include/asm/system.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h
ptrace.o : ptrace.c /usr/include/linux/head.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
- /usr/include/linux/ptrace.h /usr/include/asm/segment.h /usr/include/asm/system.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/errno.h /usr/include/linux/ptrace.h \
+ /usr/include/asm/segment.h /usr/include/asm/system.h
sched.o : sched.c /usr/include/linux/signal.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/timer.h \
- /usr/include/linux/sys.h /usr/include/linux/fdreg.h /usr/include/linux/errno.h \
- /usr/include/linux/ptrace.h /usr/include/asm/system.h /usr/include/asm/io.h \
- /usr/include/asm/segment.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/timer.h /usr/include/linux/sys.h \
+ /usr/include/linux/fdreg.h /usr/include/linux/errno.h /usr/include/linux/ptrace.h \
+ /usr/include/asm/system.h /usr/include/asm/io.h /usr/include/asm/segment.h
signal.o : signal.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
- /usr/include/linux/ptrace.h /usr/include/asm/segment.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/errno.h /usr/include/linux/ptrace.h \
+ /usr/include/asm/segment.h
sys.o : sys.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
- /usr/include/linux/config.h /usr/include/linux/config.dist.h /usr/include/linux/times.h \
- /usr/include/linux/utsname.h /usr/include/linux/string.h /usr/include/linux/ptrace.h \
- /usr/include/asm/segment.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \
+ /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/config.h \
+ /usr/include/linux/config.dist.h /usr/include/linux/times.h /usr/include/linux/utsname.h \
+ /usr/include/linux/string.h /usr/include/linux/ptrace.h /usr/include/asm/segment.h
traps.o : traps.c /usr/include/linux/head.h /usr/include/linux/sched.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \
- /usr/include/linux/errno.h /usr/include/asm/system.h /usr/include/asm/segment.h \
- /usr/include/asm/io.h
-vsprintf.o : vsprintf.c /usr/lib/gcc-lib/i386-linux/2.2.2d/include/stdarg.h \
- /usr/include/linux/types.h /usr/include/linux/string.h /usr/include/linux/ctype.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/errno.h \
+ /usr/include/asm/system.h /usr/include/asm/segment.h /usr/include/asm/io.h
+vsprintf.o : vsprintf.c /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h /usr/include/linux/types.h \
+ /usr/include/linux/string.h /usr/include/linux/ctype.h
diff --git a/kernel/blk_drv/Makefile b/kernel/blk_drv/Makefile
index 58b9340..2343ec6 100644
--- a/kernel/blk_drv/Makefile
+++ b/kernel/blk_drv/Makefile
@@ -48,39 +48,51 @@ floppy.o : floppy.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/in
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/timer.h \
- /usr/include/linux/fdreg.h /usr/include/linux/fd.h /usr/include/linux/errno.h \
- /usr/include/asm/dma.h /usr/include/asm/io.h /usr/include/asm/system.h /usr/include/asm/segment.h \
- blk.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/timer.h /usr/include/linux/fdreg.h \
+ /usr/include/linux/fd.h /usr/include/linux/errno.h /usr/include/asm/dma.h /usr/include/asm/io.h \
+ /usr/include/asm/system.h /usr/include/asm/segment.h blk.h
genhd.o : genhd.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/genhd.h /usr/include/linux/kernel.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/genhd.h /usr/include/linux/kernel.h
hd.o : hd.c /usr/include/linux/config.h /usr/include/linux/config.dist.h /usr/include/linux/errno.h \
/usr/include/linux/signal.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/timer.h \
- /usr/include/linux/hdreg.h /usr/include/linux/genhd.h /usr/include/asm/system.h \
- /usr/include/asm/io.h /usr/include/asm/segment.h blk.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/timer.h /usr/include/linux/hdreg.h \
+ /usr/include/linux/genhd.h /usr/include/asm/system.h /usr/include/asm/io.h /usr/include/asm/segment.h \
+ blk.h
ll_rw_blk.o : ll_rw_blk.c /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/errno.h /usr/include/linux/string.h /usr/include/linux/config.h \
- /usr/include/linux/config.dist.h /usr/include/linux/locks.h /usr/include/asm/system.h \
- blk.h
-ramdisk.o : ramdisk.c /usr/include/linux/config.h /usr/include/linux/config.dist.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
+ /usr/include/linux/string.h /usr/include/linux/config.h /usr/include/linux/config.dist.h \
+ /usr/include/linux/locks.h /usr/include/asm/system.h blk.h
+ramdisk.o : ramdisk.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
+ /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
+ /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
+ /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
+ /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/string.h \
+ /usr/include/asm/system.h /usr/include/asm/segment.h blk.h
diff --git a/kernel/blk_drv/blk.h b/kernel/blk_drv/blk.h
index a4641c3..792cae9 100644
--- a/kernel/blk_drv/blk.h
+++ b/kernel/blk_drv/blk.h
@@ -73,6 +73,10 @@ extern unsigned long hd_init(unsigned long mem_start, unsigned long mem_end);
extern int is_read_only(int dev);
extern void set_device_ro(int dev,int flag);
+extern void rd_load(void);
+extern long rd_init(long mem_start, int length);
+extern int ramdisk_size;
+
#define RO_IOCTLS(dev,where) \
case BLKROSET: if (!suser()) return -EPERM; \
set_device_ro((dev),get_fs_long((long *) (where))); return 0; \
@@ -167,7 +171,7 @@ void (*DEVICE_INTR)(void) = NULL;
timer_active &= ~(1<<DEVICE_TIMEOUT)
#define SET_INTR(x) \
-if (DEVICE_INTR = (x)) \
+if ((DEVICE_INTR = (x)) != NULL) \
SET_TIMER; \
else \
CLEAR_TIMER;
@@ -187,6 +191,8 @@ extern inline void unlock_buffer(struct buffer_head * bh)
wake_up(&bh->b_wait);
}
+/* SCSI devices have their own version */
+#if (MAJOR_NR != 8 && MAJOR_NR != 9 && MAJOR_NR != 11)
static void end_request(int uptodate)
{
struct request * req;
@@ -204,12 +210,12 @@ static void end_request(int uptodate)
req->sector &= ~SECTOR_MASK;
}
- if (bh = req->bh) {
+ if ((bh = req->bh) != NULL) {
req->bh = bh->b_reqnext;
bh->b_reqnext = NULL;
bh->b_uptodate = uptodate;
unlock_buffer(bh);
- if (bh = req->bh) {
+ if ((bh = req->bh) != NULL) {
req->current_nr_sectors = bh->b_size >> 9;
if (req->nr_sectors < req->current_nr_sectors) {
req->nr_sectors = req->current_nr_sectors;
@@ -221,7 +227,7 @@ static void end_request(int uptodate)
}
DEVICE_OFF(req->dev);
CURRENT = req->next;
- if (p = req->waiting) {
+ if ((p = req->waiting) != NULL) {
req->waiting = NULL;
p->state = TASK_RUNNING;
if (p->counter > current->counter)
@@ -230,6 +236,7 @@ static void end_request(int uptodate)
req->dev = -1;
wake_up(&wait_for_request);
}
+#endif
#ifdef DEVICE_INTR
#define CLEAR_INTR SET_INTR(NULL)
diff --git a/kernel/blk_drv/floppy.c b/kernel/blk_drv/floppy.c
index 7afaf53..446cd48 100644
--- a/kernel/blk_drv/floppy.c
+++ b/kernel/blk_drv/floppy.c
@@ -460,7 +460,7 @@ static void bad_flp_intr(void)
* 82077 Untested! 1Mbps data rate only possible with 82077-1.
* TODO: increase MAX_BUFFER_SECTORS, add floppy_type entries.
*/
-static void inline perpendicular_mode(unsigned char rate)
+static inline void perpendicular_mode(unsigned char rate)
{
if (fdc_version == FDC_TYPE_82077) {
output_byte(FD_PERPENDICULAR);
@@ -923,6 +923,8 @@ static void redo_fd_request(void)
char * buffer_area;
int device;
+ if (CURRENT && CURRENT->dev < 0) return;
+
repeat:
if (format_status == FORMAT_WAIT)
format_status = FORMAT_BUSY;
diff --git a/kernel/blk_drv/genhd.c b/kernel/blk_drv/genhd.c
index 0e539da..291ca30 100644
--- a/kernel/blk_drv/genhd.c
+++ b/kernel/blk_drv/genhd.c
@@ -14,10 +14,14 @@
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/kernel.h>
+
struct gendisk *gendisk_head = NULL;
static int current_minor = 0;
extern int *blk_size[];
+extern void rd_load(void);
+extern int ramdisk_size;
+
/*
* Create devices for each logical partition in an extended partition.
* The logical partitions form a linked list, with each entry being
@@ -211,9 +215,8 @@ int sys_setup(void * BIOS)
if (nr)
printk("Partition table%s ok.\n\r",(nr>1)?"s":"");
-#ifdef RAMDISK
- rd_load();
-#endif
+ if (ramdisk_size)
+ rd_load();
mount_root();
return (0);
}
diff --git a/kernel/blk_drv/hd.c b/kernel/blk_drv/hd.c
index 4182189..df05a47 100644
--- a/kernel/blk_drv/hd.c
+++ b/kernel/blk_drv/hd.c
@@ -206,7 +206,7 @@ static int drive_busy(void)
return 0;
}
printk("HD controller times out, status = 0x%02x\n\r",c);
- return(1);
+ return 1;
}
static void reset_controller(void)
@@ -421,6 +421,8 @@ static void do_hd_request(void)
unsigned int sec,head,cyl,track;
unsigned int nsect;
+ if (CURRENT && CURRENT->dev < 0) return;
+
if (DEVICE_INTR)
return;
repeat:
@@ -513,6 +515,12 @@ static int hd_ioctl(struct inode * inode, struct file * file,
put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
(long *) &loc->start);
return 0;
+ case BLKGETSIZE: /* Return device size */
+ if (!arg) return -EINVAL;
+ verify_area((long *) arg, sizeof(long));
+ put_fs_long(hd[MINOR(inode->i_rdev)].nr_sects,
+ (long *) arg);
+ return 0;
case BLKRRPART: /* Re-read partition tables */
return revalidate_hddisk(inode->i_rdev, 1);
RO_IOCTLS(inode->i_rdev,arg);
diff --git a/kernel/blk_drv/ll_rw_blk.c b/kernel/blk_drv/ll_rw_blk.c
index c785af8..5e0eb5b 100644
--- a/kernel/blk_drv/ll_rw_blk.c
+++ b/kernel/blk_drv/ll_rw_blk.c
@@ -18,8 +18,6 @@
#include "blk.h"
-extern long rd_init(long mem_start, int length);
-
/*
* The request-struct contains all necessary data
* to load a nr of sectors into memory
@@ -31,6 +29,11 @@ struct request request[NR_REQUEST];
*/
struct wait_queue * wait_for_request = NULL;
+/* This specifies how many blocks to read ahead on the disk. We might want
+ to change this to sectors later, but for now this will work */
+
+int read_ahead[NR_BLK_DEV] = {0, };
+
/* blk_dev_struct is:
* do_request-address
* next-request
@@ -109,6 +112,13 @@ static void add_request(struct blk_dev_struct * dev, struct request * req)
}
req->next = tmp->next;
tmp->next = req;
+
+/* Scsi devices are treated differently */
+ if(MAJOR(req->dev) == 8 ||
+ MAJOR(req->dev) == 9 ||
+ MAJOR(req->dev) == 11)
+ (dev->request_fn)();
+
sti();
}
@@ -120,7 +130,8 @@ static void make_request(int major,int rw, struct buffer_head * bh)
/* WRITEA/READA is special case - it is not really needed, so if the */
/* buffer is locked, we just forget about it, else it's a normal read */
- if (rw_ahead = (rw == READA || rw == WRITEA)) {
+ rw_ahead = (rw == READA || rw == WRITEA);
+ if (rw_ahead) {
if (bh->b_lock)
return;
if (rw == READA)
@@ -144,10 +155,15 @@ static void make_request(int major,int rw, struct buffer_head * bh)
unlock_buffer(bh);
return;
}
+/* The scsi disk drivers completely remove the request from the queue when
+ they start processing an entry. For this reason it is safe to continue
+ to add links to the top entry for scsi devices */
+
repeat:
cli();
if ((major == 3 || major == 8 || major == 11)&& (req = blk_dev[major].current_request)) {
- while (req = req->next) {
+ if(major == 3) req = req->next;
+ while (req) {
if (req->dev == bh->b_dev &&
!req->waiting &&
req->cmd == rw &&
@@ -159,9 +175,10 @@ repeat:
bh->b_dirt = 0;
sti();
return;
- }
- }
- }
+ }
+ req = req->next;
+ }
+ }
/* we don't allow the write-requests to fill up the queue completely:
* we want some room for reads: they take precedence. The last third
* of the requests are only for reads.
@@ -243,30 +260,71 @@ repeat:
schedule();
}
+/* This function can be used to request a number of buffers from a block
+ device. Currently the only restriction is that all buffers must belong to
+ the same device */
+
void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
{
unsigned int major;
- if (nr!=1) panic("ll_rw_block: only one block at a time implemented");
- if (!bh[0])
- return;
- if (bh[0]->b_size != 1024) {
- printk("ll_rw_block: only 1024-char blocks implemented (%d)\n",bh[0]->b_size);
- bh[0]->b_dirt = bh[0]->b_uptodate = 0;
- return;
- }
+ struct request plug;
+ int plugged;
+ struct blk_dev_struct * dev;
+ int i, j;
+
+ /* Make sure that the first block contains something reasonable */
+ while(!bh[0]){
+ bh++;
+ nr--;
+ if (nr <= 0) return;
+ };
+
+ for(j=0;j<nr; j++){
+ if(!bh[j]) continue;
+ if (bh[j]->b_size != 1024) {
+ printk("ll_rw_block: only 1024-char blocks implemented (%d)\n",bh[0]->b_size);
+ for (i=0;i<nr; i++)
+ if (bh[i]) bh[i]->b_dirt = bh[i]->b_uptodate = 0;
+ return;
+ }
+ };
+
if ((major=MAJOR(bh[0]->b_dev)) >= NR_BLK_DEV ||
!(blk_dev[major].request_fn)) {
printk("ll_rw_block: Trying to read nonexistent block-device %04x (%d)\n",bh[0]->b_dev,bh[0]->b_blocknr);
- bh[0]->b_dirt = bh[0]->b_uptodate = 0;
+ for (i=0;i<nr; i++)
+ if (bh[i]) bh[i]->b_dirt = bh[i]->b_uptodate = 0;
return;
}
if ((rw == WRITE || rw == WRITEA) && is_read_only(bh[0]->b_dev)) {
printk("Can't write to read-only device 0x%X\n\r",bh[0]->b_dev);
- bh[0]->b_dirt = bh[0]->b_uptodate = 0;
+ for (i=0;i<nr; i++)
+ if (bh[i]) bh[i]->b_dirt = bh[i]->b_uptodate = 0;
return;
}
- make_request(major,rw,bh[0]);
+/* If there are no pending requests for this device, then we insert a dummy
+ request for that device. This will prevent the request from starting until
+ we have shoved all of the blocks into the queue, and then we let it rip */
+
+ plugged = 0;
+ cli();
+ if (!blk_dev[major].current_request && nr > 1) {
+ blk_dev[major].current_request = &plug;
+ plug.dev = -1;
+ plug.next = NULL;
+ plugged = 1;
+ };
+ sti();
+ for (i=0;i<nr; i++)
+ if (bh[i]) make_request(major, rw, bh[i]);
+ if(plugged){
+ cli();
+ blk_dev[major].current_request = plug.next;
+ dev = major+blk_dev;
+ (dev->request_fn)();
+ sti();
+ };
}
void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buf)
@@ -329,8 +387,7 @@ long blk_dev_init(long mem_start, long mem_end)
#ifdef CONFIG_BLK_DEV_HD
mem_start = hd_init(mem_start,mem_end);
#endif
-#ifdef RAMDISK
- mem_start += rd_init(mem_start, RAMDISK*1024);
-#endif
+ if (ramdisk_size)
+ mem_start += rd_init(mem_start, ramdisk_size*1024);
return mem_start;
}
diff --git a/kernel/blk_drv/ramdisk.c b/kernel/blk_drv/ramdisk.c
index d70ee08..3bdcf5d 100644
--- a/kernel/blk_drv/ramdisk.c
+++ b/kernel/blk_drv/ramdisk.c
@@ -6,7 +6,6 @@
#include <linux/config.h>
-#ifdef RAMDISK
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/fs.h>
@@ -87,7 +86,7 @@ void rd_load(void)
{
struct buffer_head *bh;
struct minix_super_block s;
- int block = 256; /* Start at block 256 */
+ int block = 512; /* Start at block 512 */
int i = 1;
int nblocks;
char *cp; /* Move pointer */
@@ -138,4 +137,3 @@ void rd_load(void)
printk("\ndone\n");
ROOT_DEV=0x0101;
}
-#endif
diff --git a/kernel/blk_drv/scsi/7000fasst.c b/kernel/blk_drv/scsi/7000fasst.c
deleted file mode 100644
index 8a72be4..0000000
--- a/kernel/blk_drv/scsi/7000fasst.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/* $Id: 7000fasst.c,v 1.1 1992/07/24 06:27:38 root Exp root $
- * linux/kernel/7000fasst.c
- *
- * Copyright (C) 1992 Thomas Wuensche
- * closely related to the aha1542 driver from Tommy Thorn
- * ( as close as different hardware allows on a lowlevel-driver :-) )
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/head.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include "scsi.h"
-#include "hosts.h"
-
-struct mailbox{
- unchar status;
- unchar scbptr[3];
-};
-
-/* #define DEBUG */
-
-#include "7000fasst.h"
-#ifdef DEBUG
-#define DEB(x) x
-#else
-#define DEB(x)
-#endif
-
-/*static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/7000fasst.c,v 1.1 1992/07/24 06:27:38 root Exp root $";*/
-
-static struct scb scbs[OGMB_CNT];
-
-long wd7000fasst_WAITnexttimeout = 3000000;
-
-void (*wd7000fasst_do_done)() = NULL;
-extern void wd7000fasst_interrupt();
-void wd7000fasst_call_buh();
-
-static unchar controlstat = 0;
-static unchar wd7000fasst_hostno;
-
-#define wd7000fasst_intr_reset() outb(0,INTR_ACK)
-#define PC_IMR 0x21
-#define AT_IMR 0xa1
-
-#define wd7000fasst_enable_intr(){\
- controlstat |= INT_EN;\
- outb(controlstat,CONTROL);\
- outb((inb((intr_chan<=7)?PC_IMR:AT_IMR))& ~0xff,(intr_chan<=7)?PC_IMR:AT_IMR);}
-
-#define wd7000fasst_disable_intr() outb(controlstat |= INT_EN, CONTROL)
-#define wd7000fasst_enable_dma() {\
- controlstat |= DMA_EN;\
- outb(controlstat,CONTROL);\
- outb((DMA_CH|CASCADE),DMA_MODE_REG);\
- outb(DMA_CH,DMA_MASK_REG);}
-
-#define wd7000fasst_disable_dma() {\
- outb(DMA_CH|S_DMA_MASK,DMA_MASK_REG);\
- controlstat &= ~DMA_EN;\
- outb(controlstat,CONTROL);}
-
-#define WAIT(port, mask, allof, noneof) \
- { register WAITbits; \
- register WAITtimeout = wd7000fasst_WAITnexttimeout; \
- while (1) { \
- WAITbits = inb(port) & (mask); \
- if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
- break; \
- if (--WAITtimeout == 0) goto fail; \
- } \
- }
-
-static void wd7000fasst_stat(void)
-{
-/* int s = inb(ASC_STAT), i = inb(INTR_STAT);*/
-/* printk("status = %x, intrflags = %x served %d last %x\n", s, i, intr_flag, intr_last);
- printk("status=%x intrflags=%x\n", s, i);
-*/}
-
-static int wd7000fasst_out(unchar *cmdp, int len)
-{
- while (len--)
- {
- WAIT(ASC_STAT, STATMASK, CMD_RDY, 0);
- outb(*cmdp++, COMMAND);
- }
- return 0;
- fail:
- printk("wd7000fasst_out failed(%d): ", len+1); wd7000fasst_stat();
- return 1;
-}
-
-int wd7000fasst_make_error_code(unsigned hosterr, unsigned scsierr)
-{
-#ifdef DEBUG
- int in_error=hosterr;
-#endif
- switch ((hosterr&0xff00)>>8){
- case 0: /* It is reserved, should never happen */
- hosterr=DID_ERROR;
- break;
- case 1: hosterr=DID_OK;
- break;
- case 2: /* Command complete with logged error */
- /* My actual copies of the manual pages are unreadable
- * For now we simply tell there is an error */
- DEB(printk("Hosterror: VUE = %x\n",hosterr&0xff);)
- switch (hosterr&0xff) {
- default: DEB(printk("wd7000fasst_make_error_code: unknown hoststatus %x\n", hosterr);)
- hosterr=DID_ERROR;
- break;
- }
- break;
- case 4: hosterr=DID_BAD_TARGET; /* Command failed to complete without SCSI status */
- break;
- case 5: hosterr=DID_RESET; /* Cmd terminated; Bus reset by external device */
- break;
- case 6: hosterr=DID_ERROR;/* Hardware Failure, requires host reset */
- break;
- case 7: hosterr=DID_RESET;
- break;
- case 8: hosterr=DID_OK;
- printk("wd7000fasst: Linked command not implemented\n");
- break;
- }
-#ifdef DEBUG
- if (scsierr||hosterr) printk("SCSI-Command error: SCSI %x HOST %x RETURN %x\n",scsierr,in_error,hosterr);
-#endif
- return scsierr|(hosterr << 16);
-}
-
-/* The following is space for the Mailboxes */
-struct{ struct mailbox ombox[OGMB_CNT];
- struct mailbox imbox[ICMB_CNT]; } mbstruct;
-
-int wd7000fasst_init(void)
-{ int i;
- volatile int debug = 0;
- /* Page 47 */
- unchar init_block[]={ 1, 7, 0x18, 0x18, 0, 0, 0, 0, OGMB_CNT, ICMB_CNT };
- /* Reset the adapter. I ought to make a hard reset, but it's not really nessesary */
-
- DEB(printk("wd7000fasst_init called \n"));
-
- outb(SCSI_RES|ASC_RES, CONTROL);
- /* Wait at least 25 us */
- for (i=0; i< 1000; i++) inb(ASC_STAT);
- /* Now reset the reset */
- outb(0,CONTROL);
- debug = 1;
- /* Expect Command Port Ready */
- WAIT(ASC_STAT, STATMASK, CMD_RDY, 0);
- DEB(printk("wd7000fasst_init: Power on Diagnostics finished\n"));
- if ((i=inb(INTR_STAT))!=1)
- printk("Power on Diagnostics error %x\n",i);
-
- debug = 2;
- /* Clear mbstruct */
- memset(&mbstruct,0,sizeof (mbstruct));
- /* Set up init block */
- any2scsi(init_block+5,&mbstruct);
- /* Execute init command */
- wd7000fasst_out(init_block,sizeof(init_block));
- DEB(printk("Init-Block :");
- for (i=0;i<sizeof(init_block);i++) printk(" %x",init_block[i]);
- printk("\n");)
- /* Wait until init finished */
- WAIT(ASC_STAT, STATMASK, CMD_RDY | ASC_INI, 0);
- outb(2,COMMAND);
- WAIT(ASC_STAT, STATMASK, CMD_RDY | ASC_INI, 0);
- /* Enable Interrupt and DMA */
- wd7000fasst_enable_dma();
- wd7000fasst_call_buh();
- DEB(printk("wd7000fasst_detect: enable interrupt channel %d\n", intr_chan));
- wd7000fasst_enable_intr();
- printk("wd7000fasst_init: Controller initialized\n");
- return 1;
- fail:
- return 0; /* 0 = not ok */
-}
-
-/* What's this little function for? */
-char *wd7000fasst_info(void)
-{
- static char buffer[] = "Western Digital 7000-FASST";
- return buffer;
-}
-
-/* A "high" level interrupt handler */
-void wd7000fasst_intr_handle(void)
-{ struct scb * scbptr;
- DEB(int len=sizeof (struct scb);)
- DEB(int k;)
- unsigned host_error,scsi_error;
- int flag = inb(INTR_STAT);
- void (*my_done)() = wd7000fasst_do_done;
- int errstatus;
- DEB(printk("WD Interrupt aufgetreten\n"));
- if (!(inb(ASC_STAT)&0x80)){
- printk("Interrupt without Interrupt\n");
- wd7000fasst_intr_reset();
- return;
- }
- wd7000fasst_do_done = NULL;
- if (!my_done) {
- printk("wd7000fasst_intr_handle: Unexpected interrupt\n");
- wd7000fasst_intr_reset();
- return;
- }
-
- /* is there mail for me :-) */
- if ((flag&0xc0)==0xc0){
- /* Ok, the interrupt is for an incoming mailbox */
- /* We make the content available for the starter of the command */
- DEB(if ((flag&0xc0)==0xc0) printk("INTR_STAT: %x mbstat: %x\n",flag,mbstruct.imbox[flag&0x3f].status));
- if (mbstruct.imbox[flag&0x3f].status==0){
- /* Something strange happened */
- wd7000fasst_intr_reset();
- return;
- ;
- }
- scbptr=(struct scb *)scsi2int(mbstruct.imbox[flag&0x3f].scbptr);
- DEB(printk("Datenbereiche aus %x ein %x \n",scbptr,&(scbs[flag&0x3f]));
- printk("SCB after return:\n");
- k=0;
- while (len-- >0){
- printk("%x ",*((unchar *)scbptr));
- ((unchar *)scbptr)++;
- if (++k==16){ printk("\n"); k=0; }
- });
- }
- else { printk("Error in interrupt\n"); return; }
- /* more error checking left out here */
-
- scbptr=(struct scb *)scsi2int(mbstruct.imbox[flag&0x3f].scbptr);
- host_error=scbptr->vue | mbstruct.imbox[flag&0x3f].status<<8;
- scsi_error=scbptr->sretstat;
- errstatus=wd7000fasst_make_error_code(host_error,scsi_error);
- DEB(if (errstatus) printk("Target was %x\n",scbptr->idlun>>5);)
- DEB(if (errstatus) printk("wd7000fasst_intr_handle: returning %6x\n", errstatus));
- DEB(printk("wd7000fasst_intr_handle: Status of the finished command: %x\n",mbstruct.imbox[flag&0x3f].status));
- /* I make a SCSI reset */
- /* Left out */
- my_done(wd7000fasst_hostno,errstatus);
- wd7000fasst_intr_reset();
- return;
-}
-
-volatile static int internal_done_flag = 0;
-volatile static int internal_done_errcode = 0;
-
-/* The following code queues a SCSI command */
-int wd7000fasst_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen,
- void (*done)(int, int))
-{
- int i;
-#ifdef DEBUG
- int j;
-#endif
- unchar *cmd = (unchar *) cmnd;
-/* We first look for a free outgoing mailbox */
- for (i=0;i<OGMB_CNT;i++){
- if (mbstruct.ombox[i].status==0){
- /* We found one, now set up the scb */
- DEB(printk("Found outgoing mbox %x\n",i));
- memset(&scbs[i], 0, sizeof(struct scb));
- /* scbs[i].cdblen = (*cmd<=0x1f)?6:10; */ /* SCSI Command Descriptor Block Length */
- memcpy(scbs[i].scbdata, cmd, (*cmd<=0x1f)?6:10);
- scbs[i].op = 0; /* SCSI Initiator Command */
- scbs[i].idlun = (target<<5)&0xe0; /* SCSI Target Id Bit 7-5 Target Id*/
- any2scsi(scbs[i].dataptr,buff);
- any2scsi(scbs[i].maxdata,bufflen);
- scbs[i].direc=0x40; /* Disable direction check */
- DEB(printk("Kommando fuer target %x ist: ",target);
- for (j=0;j<12;j++) printk(" %x",scbs[i].scbdata[j]);
- printk("\n"));
- /* Now we set up the pointer to scb, then the status of the mbox */
- any2scsi((mbstruct.ombox[i].scbptr),&(scbs[i]));
- mbstruct.ombox[i].status=1;
- /* Everything set up, start the command */
- break;
- }
- }
- if (i==OGMB_CNT){
- /* No free mbox, send command "Interrupt on free OGMB" */
- DEB(printk("No free Mailbox\n"));
- return 0;
- }
- { int len,k;
- struct scb * scbptr;
- DEB(printk("Found outgoing mbox %x\n",i));
- scbptr=&(scbs[i]);
- len=sizeof(struct scb);
- k=0;
- DEB(printk("SCB before execute:\n");
- while (len-- >0){
- printk("%x ",*((unchar *)scbptr));
- ((unchar *)scbptr)++;
- if (++k==16){ printk("\n"); k=0; }
- };)
- }
- /* Set up the "done" response function */
- if (done) {
- DEB(printk("wd7000fasst_queuecommand: now waiting for interrupt ");
- wd7000fasst_stat());
- if (wd7000fasst_do_done)
- printk("wd7000fasst_queuecommand: Two concurrent queuecommand?\n");
- else
- wd7000fasst_do_done = done;
- DEB(wd7000fasst_stat());
- wd7000fasst_enable_intr();
- }
- else{
- printk("wd7000fasst_queuecommand: done can't be NULL\n");
- return 0;
- }
- /* Now we initialize execution */
-retry: WAIT(ASC_STAT,STATMASK,CMD_RDY,0);
- outb(0x80+i,COMMAND);
- WAIT(ASC_STAT,STATMASK,CMD_RDY,0);
- if (inb(ASC_STAT)&CMD_REJ) goto retry;
- return 1;
- /* Wait until done */
-
-fail:
- return 0;
-}
-
-/* We use this function for queueing a command from wd7000fasst_command */
-static void internal_done(int host, int errcode)
-{
- internal_done_errcode = errcode;
- ++internal_done_flag;
-}
-
-int wd7000fasst_command(unchar target, const void *cmnd, void *buff, int bufflen)
-{
-#ifdef DEBUG
- int k;
-#endif
- wd7000fasst_queuecommand(target, cmnd, buff, bufflen, internal_done);
-
- while (!internal_done_flag);
- internal_done_flag = 0;
- DEB(printk("wd7000fasst_command finished: ..leaving with errcode %x\n",
- internal_done_errcode));
- DEB(for (k=0;k<5000000;k++) inb(INTR_STAT));
- return internal_done_errcode;
-}
-
-/* a hack to avoid a strange compilation error */
-
-void wd7000fasst_call_buh()
-{
- set_intr_gate((intr_chan<=7)?intr_chan+8:intr_chan+0x20,&wd7000fasst_interrupt);
-}
-
-/* return non-zero on detection */
-static const char *wd_bases[] = {(char *)0xce000};
-typedef struct {char * signature;
- unsigned offset;
- unsigned length;
- }Signature;
-
-static const Signature signatures[] =
- {{"SSTBIOS",0xd,0x7}};
-
-#define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature))
-
-int wd7000fasst_detect(int hostnum) /* hostnum ignored for now */
-{
- int i,j;
- char const * base_address = 0;
- /* Store our host number */
- wd7000fasst_hostno=hostnum;
- DEB(printk("wd7000fasst_detect: \n"));
-
- for(i=0;i<(sizeof(wd_bases)/sizeof(char *));i++){
- for(j=0;j<NUM_SIGNATURES;j++){
- if(!memcmp((void *)(wd_bases[i] + signatures[j].offset),
- (void *) signatures[j].signature,signatures[j].length)){
- base_address=wd_bases[i];
- printk("WD 7000-FASST detected\n");
- }
- }
- }
- if (!base_address) return 0;
- wd7000fasst_init();
-
- /* Set the Bus on/off-times as not to ruin floppy performens */
-
- wd7000fasst_stat();
-
- printk(" *** READ CAPACITY ***\n");
-
- { unchar rstat;
- unchar buf[8];
- static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- int i;
-
- for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87;
- for (i = 0; i < 3; ++i){
- rstat=0;
- while (rstat<2){
- if (wd7000fasst_command(i, cmd, buf, sizeof(buf))) rstat++;
- else break;
- }
- if (rstat<2)
- printk("wd7000fasst_detect: LU %d sector_size 0x%x device_size 0x%x capacity %d\n",
- i, xscsi2int(buf+4), xscsi2int(buf), xscsi2int(buf+4)*xscsi2int(buf));
- }
- }
-
- return 1;
-}
-
-int wd7000fasst_abort(int i)
-{
- printk("wd7000fasst_abort\n");
- return 0;
-}
-
-int wd7000fasst_reset(void)
-{
- printk("wd7000fasst_reset called\n");
- return 0;
-}
-
-__asm__("
-_wd7000fasst_interrupt:
- cld
- pushl %eax
- pushl %ecx
- pushl %edx
- push %ds
- push %es
- push %fs
- movl $0x10,%eax
- mov %ax,%ds
- mov %ax,%es
- movl $0x17,%eax
- mov %ax,%fs
-# Please, someone, change this to use the timer
-# andl $0xfffeffff,_timer_active
- movl $_wd7000fasst_intr_handle,%edx
- call *%edx # ``interesting'' way of handling intr.
-# Free the interrupt only after resetting the host interrupt
- movb $0x20,%al
- outb %al,$0xA0 # EOI to interrupt controller #1
- jmp 1f # give port chance to breathe
-1: jmp 1f
-1: outb %al,$0x20
- pop %fs
- pop %es
- pop %ds
- popl %edx
- popl %ecx
- popl %eax
- iret
-");
diff --git a/kernel/blk_drv/scsi/7000fasst.h b/kernel/blk_drv/scsi/7000fasst.h
deleted file mode 100644
index daa6f1f..0000000
--- a/kernel/blk_drv/scsi/7000fasst.h
+++ /dev/null
@@ -1,137 +0,0 @@
-#ifndef _WD7000FASST_H
-
-/* $Id: 7000fasst.h,v 1.1 1992/07/24 06:27:38 root Exp root $
- *
- * Header file for the WD 7000-FASST driver for Linux
- *
- * $Log: 7000fasst.h,v $
- * Revision 1.1 1992/07/24 06:27:38 root
- * Initial revision
- *
- * Revision 1.1 1992/07/05 08:32:32 root
- * Initial revision
- *
- * Revision 1.1 1992/05/15 18:38:05 root
- * Initial revision
- *
- * Revision 1.1 1992/04/02 03:23:13 drew
- * Initial revision
- *
- * Revision 1.3 1992/01/27 14:46:29 tthorn
- * *** empty log message ***
- *
- */
-
-#include <linux/types.h>
-
-#undef STATMASK
-#undef CONTROL
-
-#define io_base 0x350
-#define intr_chan 15
-#define dma_chan 6
-#define OGMB_CNT 8
-#define ICMB_CNT 8
-
-/* I/O Port interface 4.2 */
-/* READ */
-#define ASC_STAT io_base
-#define INT_IM 0x80 /* Interrupt Image Flag */
-#define CMD_RDY 0x40 /* Command Port Ready */
-#define CMD_REJ 0x20 /* Command Port Byte Rejected */
-#define ASC_INI 0x10 /* ASC Initialized Flag */
-#define STATMASK 0xf0 /* The lower 4 Bytes are reserved */
-
-/* This register saves two purposes
- * Diagnostics error
- * Interrupt Status
- */
-#define INTR_STAT ASC_STAT+1
-#define ANYINTR 0x80 /* Mailbox Service possible/required */
-#define IMB 0x40 /* 1 Incoming / 0 Outgoing */
-#define MBMASK 0x3f
-/* if MSB is zero, the content of the lower ones keeps Diagnostic State *
- * 00 Power-on, no diagnostics executed
- * 01 No diagnostic Error Occured
- * 02 RAM Failed
- * 03 FIFO R/W Failed
- * ...
-*/
-
-/* WRITE */
-#define COMMAND ASC_STAT
-
-#define INTR_ACK ASC_STAT+1
-
-
-#define CONTROL ASC_STAT+2
-#define INT_EN 0x08 /* Interrupt Enable */
-#define DMA_EN 0x04 /* DMA Enable */
-#define SCSI_RES 0x02 /* SCSI Reset */
-#define ASC_RES 0x01 /* ASC Reset */
-
-/* The DMA-Controller */
-#define DMA_MODE_REG 0xd6
-#define DMA_MASK_REG 0xd4
-#define S_DMA_MSK 0x04
-#define DMA_CH 0x02
-#define CASCADE 0xc0
-
-/* Mailbox Definition 5.3 */
-
-/* These belong in scsi.h also */
-#undef any2scsi
-#define any2scsi(up, p) \
-(up)[0] = (((long)(p)) >> 16); \
-(up)[1] = ((long)(p)) >> 8; \
-(up)[2] = ((long)(p));
-
-#define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) )
-
-#define xany2scsi(up, p) \
-(up)[0] = ((long)(p)) >> 24; \
-(up)[1] = ((long)(p)) >> 16; \
-(up)[2] = ((long)(p)) >> 8; \
-(up)[3] = ((long)(p));
-
-#define xscsi2int(up) ( (((long)(up)[0]) << 24) + (((long)(up)[1]) << 16) \
- + (((long)(up)[2]) << 8) + ((long)(up)[3]) )
-
-#define MAX_CDB 12
-#define MAX_SENSE 14
-
-struct scb { /* Command Control Block 5.4.1 */
- unchar op; /* Command Control Block Operation Code */
- unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */
- /* Outbound data transfer, length is checked*/
- /* Inbound data transfer, length is checked */
- /* Logical Unit Number */
- unchar scbdata[12]; /* SCSI Command Block */
- unchar sretstat; /* SCSI Return Status */
- unchar vue; /* Vendor Unique Error Code */
- unchar maxdata[3]; /* Maximum Data Transfer Length */
- unchar dataptr[3]; /* SCSI Data Block Pointer */
- unchar linkptr[3]; /* Next Command Link Pointer */
- unchar direc; /* Transfer Direction */
- unchar reserved2[6]; /* SCSI Command Descriptor Block */
- /* REQUEST SENSE */
-};
-
-int wd7000fasst_detect(int);
-int wd7000fasst_command(unsigned char target, const void *cmnd, void *buff, int bufflen);
-int wd7000fasst_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int,int));
-int wd7000fasst_abort(int);
-char *wd7000fasst_info(void);
-int wd7000fasst_reset(void);
-
-#ifndef NULL
- #define NULL 0
-#endif
-
-#define WD7000FASST {"Western Digital 7000FASST", wd7000fasst_detect, \
- wd7000fasst_info, wd7000fasst_command, \
- wd7000fasst_queuecommand, \
- wd7000fasst_abort, \
- wd7000fasst_reset, \
- 1, 7, 0, 1}
-#endif
diff --git a/kernel/blk_drv/scsi/Makefile b/kernel/blk_drv/scsi/Makefile
index 5765807..2109e0a 100644
--- a/kernel/blk_drv/scsi/Makefile
+++ b/kernel/blk_drv/scsi/Makefile
@@ -1,12 +1,45 @@
-#
-# Makefile for the linux kernel block device drivers.
-#
+# 1 "tmp_make.c"
+
+# Makefile for kernel/blk_drv/scsi
+
+# Note! This Makefile is automatically generated from makefile.in.
+# DO NOT edit makefile, edit makefile.in instead.
+
# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
+# removes any old dependencies. DONT put your own dependencies here
+# unless its something special (ie not a .c file).
+
+# 1 "/usr/include/linux/config.h" 1 3
+
+
+
+
+
+
+
+
+
+
-#DEBUG = -DDEBUG=0xffffffff -DDEBUG_NO_CMD
+
+
+
+
+
+
+
+
+# 101 "/usr/include/linux/config.h" 3
+
+
+
+# 1 "/usr/include/linux/config.dist.h" 1 3
+
+# 115 "/usr/include/linux/config.h" 2 3
+
+
+
+# 12 "tmp_make.c" 2
.c.s:
$(CC) $(CFLAGS) $(DEBUG) -S $<
@@ -17,166 +50,223 @@
.c.o:
$(CC) $(CFLAGS) $(DEBUG) -c $<
+ST_CSRC = st.c
+ST_OBJS = st.o
-LOWLEVELCSRC = aha1542.c fdomain.c seagate.c ultrastor.c 7000fasst.c
-LOWLEVELHSRC = aha1542.h fdomain.h seagate.h ultrastor.h 7000fasst.h
-
-CSRC = hosts.c sd.c sd_ioctl.c st.c st_ioctl.c sr.c sr_ioctl.c scsi.c scsi_ioctl.c $(LOWLEVELCSRC)
-HSRC = hosts.h sd.h st.h sr.h sr_ioctl.h scsi.h scsi_ioctl.h $(LOWLEVELHSRC)
+SD_CSRC = sd.c sd_ioctl.c
+SD_OBJS = sd.o sd_ioctl.o
+
+SR_CSRC = sr.c sr_ioctl.c
+SR_OBJS = sr.o sr_ioctl.o
+
+AHA1542_OBJS = aha1542.o
+
+AHA1740_OBJS = aha1740.o
+
+FDOMAIN_OBJS = fdomain.o
+
+ULTRASTOR_OBJS = ultrastor.o
-OBJS = scsi.o hosts.o scsi_ioctl.o sd.o sd_ioctl.o st.o st_ioctl.o \
- sr.o sr_ioctl.o \
- aha1542.o fdomain.o seagate.o ultrastor.o 7000fasst.o
+WD7000_OBJS = wd7000.o
-all: scsi.a
+SEAGATE_OBJS = seagate.o
-figure : hosts.h $(KERNELHDRS)/linux/config.h hosts.c
- $(HOSTCC) -N -DFIGURE_MAX_SCSI_HOSTS hosts.c -o figure
+SCSI_OBJS = hosts.o scsi.o scsi_ioctl.o
+
+OBJS = $(SCSI_OBJS) $(SD_OBJS) $(ST_OBJS) $(SR_OBJS) $(AHA1542_OBJS) $(AHA1740_OBJS) $(FDOMAIN_OBJS) $(SEAGATE_OBJS) $(ULTRASTOR_OBJS) $(WD7000_OBJS) $(SCSI_DEBUG_OBJS)
+
+all:
+ $(MAKE) Makefile
+ $(MAKE) scsi.a
+
+figure : hosts.h $(KERNELHDRS)/linux/config.h hosts.c
+ $(HOSTCC) -I$(KERNELHDRS) -DFIGURE_MAX_SCSI_HOSTS hosts.c -o figure
max_hosts.h : figure
- (echo "#ifndef _MAX_HOSTS_H"; \
- echo "#define _MAX_HOSTS_H"; \
- echo "#define MAX_SCSI_HOSTS `./figure`";\
- echo "#endif") > tmp_max
+ (echo "#ifndef _MAX_HOSTS_H"; echo "#define _MAX_HOSTS_H"; echo "#define MAX_SCSI_HOSTS `./figure`"; echo "#endif") > tmp_max
+
cp tmp_max max_hosts.h
+have_makefile:
+ touch have_makefile
+
+Makefile: ../../../include/linux/config.h ../../../include/linux/config.site.h ../../../include/linux/config.dist.h Makefile.in have_makefile
+
+ cp Makefile.in tmp_make.c
+ $(CPP) -E tmp_make.c | uniq > tmp_make
+
+ rm tmp_make.c
+ cp tmp_make Makefile
+ rm -f tmp_make*
+ $(MAKE) dep
+
scsi.a: $(OBJS)
+ rm -f scsi.a
$(AR) rcs scsi.a $(OBJS)
sync
clean:
- rm -f core *.o *.a tmp_make tmp_max figure max_hosts.h
+ rm -f core *.o *.a tmp_make tmp_max figure max_hosts.h have_makefile
seagate.o: seagate.c
- $(CC) -Wall -c seagate.c
+ $(CC) -Wall -I$(KERNELHDRS) -c seagate.c
-dep:
- touch max_hosts.h
- sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+dep: max_hosts.h
+ sed '/\# \X\XDependencies/q' < Makefile > tmp_make
$(CPP) -M *.c >> tmp_make
- rm max_hosts.h
cp tmp_make Makefile
-### Dependencies:
-7000fasst.o : 7000fasst.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
- /usr/include/linux/kernel.h /usr/include/linux/head.h /usr/include/linux/types.h \
- /usr/include/linux/string.h /usr/include/asm/system.h /usr/include/asm/io.h \
- scsi.h hosts.h max_hosts.h 7000fasst.h
-aha1542.o : aha1542.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
- /usr/include/linux/kernel.h /usr/include/linux/head.h /usr/include/linux/types.h \
- /usr/include/linux/string.h /usr/include/asm/system.h /usr/include/asm/io.h \
- scsi.h hosts.h max_hosts.h aha1542.h
-fdomain.o : fdomain.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
- /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
- /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
+# XXDependencies:
+aha1542.o : aha1542.c /usr/include/linux/kernel.h /usr/include/linux/head.h \
+ /usr/include/linux/types.h /usr/include/linux/string.h /usr/include/linux/sched.h \
+ /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/asm/io.h \
- fdomain.h scsi.h hosts.h max_hosts.h /usr/include/asm/system.h /usr/include/linux/errno.h
-hosts.o : hosts.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
- /usr/include/linux/kernel.h scsi.h hosts.h max_hosts.h aha1542.h /usr/include/linux/types.h \
- fdomain.h seagate.h ultrastor.h 7000fasst.h
-scsi.o : scsi.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
- /usr/include/asm/system.h /usr/include/linux/sched.h /usr/include/linux/head.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/asm/dma.h /usr/include/asm/io.h /usr/include/asm/system.h ../blk.h \
+ scsi.h hosts.h aha1542.h
+aha1740.o : aha1740.c /usr/include/linux/kernel.h /usr/include/linux/head.h \
+ /usr/include/linux/types.h /usr/include/linux/string.h /usr/include/linux/sched.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
- /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
- /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
+ /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/timer.h /usr/include/linux/string.h scsi.h hosts.h max_hosts.h \
- sd.h /usr/include/linux/genhd.h st.h sr.h
-scsi_ioctl.o : scsi_ioctl.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
- /usr/include/asm/io.h /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/errno.h \
- /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
+ /usr/include/asm/dma.h /usr/include/asm/io.h /usr/include/asm/system.h ../blk.h \
+ scsi.h hosts.h aha1740.h
+fdomain.o : fdomain.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
+ /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
+ /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
+ /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/asm/io.h ../blk.h scsi.h hosts.h \
+ fdomain.h /usr/include/asm/system.h /usr/include/linux/errno.h
+hosts.o : hosts.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
+ ../blk.h /usr/include/linux/kernel.h scsi.h max_hosts.h hosts.h aha1542.h /usr/include/linux/types.h \
+ aha1740.h fdomain.h seagate.h ultrastor.h wd7000.h
+scsi.o : scsi.c /usr/include/asm/system.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \
- scsi.h hosts.h max_hosts.h scsi_ioctl.h
-sd.o : sd.c /usr/include/linux/config.h /usr/include/linux/config.dist.h /usr/include/linux/fs.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/timer.h \
+ /usr/include/linux/string.h ../blk.h scsi.h hosts.h
+scsi_debug.o : scsi_debug.c /usr/include/linux/kernel.h /usr/include/linux/sched.h \
+ /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
+ /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
+ /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/timer.h \
+ /usr/include/linux/string.h /usr/include/linux/genhd.h /usr/include/asm/system.h \
+ /usr/include/asm/io.h ../blk.h scsi.h hosts.h scsi_debug.h
+scsi_ioctl.o : scsi_ioctl.c /usr/include/asm/io.h /usr/include/asm/segment.h \
+ /usr/include/asm/system.h /usr/include/linux/errno.h /usr/include/linux/kernel.h \
+ /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/string.h ../blk.h scsi.h hosts.h scsi_ioctl.h
+sd.o : sd.c /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
+ /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
+ /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
/usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
/usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/errno.h \
- /usr/include/asm/system.h scsi.h hosts.h max_hosts.h sd.h /usr/include/linux/genhd.h \
- scsi_ioctl.h ../blk.h
-sd_ioctl.o : sd_ioctl.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
- /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
- /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
- /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
- /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
+ /usr/include/asm/system.h ../blk.h scsi.h hosts.h sd.h /usr/include/linux/genhd.h \
+ scsi_ioctl.h
+sd_ioctl.o : sd_ioctl.c /usr/include/linux/kernel.h /usr/include/linux/sched.h \
+ /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
+ /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
+ /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h scsi.h sd.h /usr/include/linux/genhd.h
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/hdreg.h \
+ /usr/include/linux/errno.h /usr/include/asm/segment.h ../blk.h scsi.h hosts.h \
+ sd.h /usr/include/linux/genhd.h
seagate.o : seagate.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
/usr/include/asm/io.h /usr/include/asm/system.h /usr/include/linux/signal.h \
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h seagate.h scsi.h hosts.h max_hosts.h
-sr.o : sr.c /usr/include/linux/config.h /usr/include/linux/config.dist.h /usr/include/linux/fs.h \
- /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
- /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
- /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ ../blk.h scsi.h hosts.h seagate.h
+sr.o : sr.c /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
+ /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
+ /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
/usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
/usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/errno.h \
- scsi.h sr.h scsi_ioctl.h ../blk.h
-sr_ioctl.o : sr_ioctl.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
- /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
- /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
- /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
- /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
+ /usr/include/asm/system.h ../blk.h scsi.h hosts.h sr.h scsi_ioctl.h
+sr_ioctl.o : sr_ioctl.c /usr/include/linux/kernel.h /usr/include/linux/sched.h \
+ /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
+ /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
+ /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
/usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/asm/segment.h \
/usr/include/linux/errno.h ../blk.h scsi.h sr.h scsi_ioctl.h /usr/include/linux/cdrom.h
-st.o : st.c /usr/include/linux/config.h /usr/include/linux/config.dist.h scsi.h \
- st.h /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
+st.o : st.c /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \
- /usr/include/linux/head.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h ../blk.h
-st_ioctl.o : st_ioctl.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
+ /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/errno.h \
+ /usr/include/linux/mtio.h /usr/include/linux/ioctl.h /usr/include/linux/fcntl.h \
+ /usr/include/asm/segment.h /usr/include/asm/system.h ../blk.h scsi.h st.h
+ultrastor.o : ultrastor.c /usr/include/linux/stddef.h /usr/include/linux/string.h \
+ /usr/include/linux/types.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
- /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
- /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h st.h scsi.h
-ultrastor.o : ultrastor.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
- /usr/include/linux/stddef.h /usr/include/linux/string.h /usr/include/linux/types.h \
- /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
- /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
- /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
+ /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
/usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
/usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
/usr/include/linux/math_emu.h /usr/include/asm/io.h /usr/include/asm/system.h \
- ultrastor.h scsi.h hosts.h max_hosts.h
+ /usr/include/asm/dma.h ../blk.h scsi.h hosts.h ultrastor.h
+wd7000.o : wd7000.c /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h /usr/include/linux/kernel.h \
+ /usr/include/linux/head.h /usr/include/linux/types.h /usr/include/linux/string.h \
+ /usr/include/linux/sched.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
+ /usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
+ /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/asm/system.h /usr/include/asm/dma.h \
+ /usr/include/asm/io.h ../blk.h scsi.h hosts.h wd7000.h
diff --git a/kernel/blk_drv/scsi/Makefile.in b/kernel/blk_drv/scsi/Makefile.in
new file mode 100644
index 0000000..8385d2c
--- /dev/null
+++ b/kernel/blk_drv/scsi/Makefile.in
@@ -0,0 +1,121 @@
+#
+# Makefile for kernel/blk_drv/scsi
+#
+# Note! This Makefile is automatically generated from makefile.in.
+# DO NOT edit makefile, edit makefile.in instead.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DONT put your own dependencies here
+# unless its something special (ie not a .c file).
+#
+
+#include <linux/config.h>
+#undef linux
+
+.c.s:
+ $(CC) $(CFLAGS) $(DEBUG) -S $<
+
+.s.o:
+ $(AS) -c -o $*.o $<
+
+.c.o:
+ $(CC) $(CFLAGS) $(DEBUG) -c $<
+
+#ifdef CONFIG_SCSI
+#ifdef CONFIG_BLK_DEV_ST
+ST_CSRC = st.c
+ST_OBJS = st.o
+#endif
+
+#ifdef CONFIG_BLK_DEV_SD
+SD_CSRC = sd.c sd_ioctl.c
+SD_OBJS = sd.o sd_ioctl.o
+#endif
+
+#ifdef CONFIG_BLK_DEV_SR
+SR_CSRC = sr.c sr_ioctl.c
+SR_OBJS = sr.o sr_ioctl.o
+#endif
+
+#ifdef CONFIG_SCSI_AHA1542
+AHA1542_OBJS = aha1542.o
+#endif
+
+#ifdef CONFIG_SCSI_AHA1740
+AHA1740_OBJS = aha1740.o
+#endif
+
+#ifdef CONFIG_SCSI_FUTURE_DOMAIN
+FDOMAIN_OBJS = fdomain.o
+#endif
+
+#ifdef CONFIG_SCSI_ULTRASTOR
+ULTRASTOR_OBJS = ultrastor.o
+#endif
+
+#ifdef CONFIG_SCSI_7000FASST
+WD7000_OBJS = wd7000.o
+#endif
+
+#if defined(CONFIG_SCSI_SEAGATE) || defined(CONFIG_SCSI_FD_88x)
+SEAGATE_OBJS = seagate.o
+#endif
+
+#ifdef CONFIG_SCSI_DEBUG
+SCSI_DEBUG_OBJS = scsi_debug.o
+#endif
+
+SCSI_OBJS = hosts.o scsi.o scsi_ioctl.o
+
+#endif
+
+OBJS = $(SCSI_OBJS) $(SD_OBJS) $(ST_OBJS) $(SR_OBJS) \
+ $(AHA1542_OBJS) $(AHA1740_OBJS) $(FDOMAIN_OBJS) $(SEAGATE_OBJS) \
+ $(ULTRASTOR_OBJS) $(WD7000_OBJS) $(SCSI_DEBUG_OBJS)
+
+all:
+ $(MAKE) Makefile
+ $(MAKE) scsi.a
+
+figure : hosts.h $(KERNELHDRS)/linux/config.h hosts.c
+ $(HOSTCC) -I$(KERNELHDRS) -DFIGURE_MAX_SCSI_HOSTS hosts.c -o figure
+
+max_hosts.h : figure
+ (echo "#ifndef _MAX_HOSTS_H"; \
+ echo "#define _MAX_HOSTS_H"; \
+ echo "#define MAX_SCSI_HOSTS `./figure`";\
+ echo "#endif") > tmp_max
+ cp tmp_max max_hosts.h
+
+have_makefile:
+ touch have_makefile
+
+Makefile: ../../../include/linux/config.h \
+ ../../../include/linux/config.site.h \
+ ../../../include/linux/config.dist.h \
+ Makefile.in have_makefile
+ cp Makefile.in tmp_make.c
+ $(CPP) -E tmp_make.c \
+ | uniq > tmp_make
+ rm tmp_make.c
+ cp tmp_make Makefile
+ rm -f tmp_make*
+ $(MAKE) dep
+
+scsi.a: $(OBJS)
+ rm -f scsi.a
+ $(AR) rcs scsi.a $(OBJS)
+ sync
+
+clean:
+ rm -f core *.o *.a tmp_make tmp_max figure max_hosts.h have_makefile
+
+seagate.o: seagate.c
+ $(CC) -Wall -I$(KERNELHDRS) -c seagate.c
+
+dep: max_hosts.h
+ sed '/\# \X\XDependencies/q' < Makefile > tmp_make
+ $(CPP) -M *.c >> tmp_make
+ cp tmp_make Makefile
+
+# XXDependencies:
diff --git a/kernel/blk_drv/scsi/aha1542.c b/kernel/blk_drv/scsi/aha1542.c
index b49e1d3..01678b4 100644
--- a/kernel/blk_drv/scsi/aha1542.c
+++ b/kernel/blk_drv/scsi/aha1542.c
@@ -2,47 +2,73 @@
* linux/kernel/aha1542.c
*
* Copyright (C) 1992 Tommy Thorn
+ *
+ * Modified by Eric Youngdale
+ * Use request_irq and request_dma to help prevent unexpected conflicts
+ * Set up on-board DMA controller, such that we do not have to
+ * have the bios enabled to use the aha1542.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/head.h>
#include <linux/types.h>
#include <linux/string.h>
+#include <linux/sched.h>
+#include <asm/dma.h>
+
#include <asm/system.h>
#include <asm/io.h>
+#include "../blk.h"
#include "scsi.h"
#include "hosts.h"
#include "aha1542.h"
+
#ifdef DEBUG
#define DEB(x) x
#else
#define DEB(x)
#endif
-
/*
static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $";
*/
-#define base 0x330
-#define intr_chan 11
+/* The adaptec can be configured for quite a number of addresses, but
+I generally do not want the card poking around at random. We allow
+two addresses - this allows people to use the Adaptec with a Midi
+card, which also used 0x330 */
+
+static unsigned int bases[]={0x330, 0x334};
+
+static unsigned int base;
+static unsigned char dma_chan;
+static unsigned char irq_level;
-static struct mailbox mb[2];
-static struct ccb ccb;
+static int aha_disable = 0;
-extern int slow_scsi_io;
+/* The DMA-Controller. We need to fool with this because we want to
+ be able to use the aha1542 without having to have the bios enabled */
+#define DMA_MODE_REG 0xd6
+#define DMA_MASK_REG 0xd4
+#define CASCADE 0xc0
-long WAITtimeout, WAITnexttimeout = 3000000;
+static struct mailbox mb[2*AHA1542_MAILBOXES];
+static struct ccb ccb[AHA1542_MAILBOXES];
-void (*do_done)(int, int) = NULL;
-int aha1542_host = 0;
+static Scsi_Cmnd * SCint[AHA1542_MAILBOXES] = {NULL, };
+
+/* This will effectively start both of them at the first mailbox */
+static int aha1542_last_mbi_used = (2*AHA1542_MAILBOXES - 1);
+static int aha1542_last_mbo_used = (AHA1542_MAILBOXES - 1);
+
+
+static long WAITnexttimeout = 3000000;
+
+static int aha1542_host = 0;
extern void aha1542_interrupt();
#define aha1542_intr_reset() outb(IRST, CONTROL)
-#define aha1542_enable_intr() outb(inb_p(0xA1) & ~8, 0xA1)
-#define aha1542_disable_intr() outb(inb_p(0xA1) | 8, 0xA1)
#define WAIT(port, mask, allof, noneof) \
{ register WAITbits; \
@@ -141,10 +167,11 @@ int makecode(unsigned hosterr, unsigned scsierr)
return scsierr|(hosterr << 16);
}
-int aha1542_test_port(void)
+int aha1542_test_port(int bse)
{
volatile int debug = 0;
+ base = bse;
/* Reset the adapter. I ought to make a hard reset, but it's not really nessesary */
/* DEB(printk("aha1542_test_port called \n")); */
@@ -200,19 +227,20 @@ int aha1542_test_port(void)
}
/* What's this little function for? */
-char *aha1542_info(void)
+const char *aha1542_info(void)
{
static char buffer[] = ""; /* looks nicer without anything here */
return buffer;
}
/* A "high" level interrupt handler */
-void aha1542_intr_handle(void)
+void aha1542_intr_handle(int foo)
{
- void (*my_done)(int, int) = do_done;
- int errstatus;
+ void (*my_done)(Scsi_Cmnd *) = NULL;
+ int errstatus, mbi, mbo, mbistatus;
+ int number_serviced;
+ Scsi_Cmnd * SCtmp;
- do_done = NULL;
#ifdef DEBUG
{
int flag = inb(INTRFLAGS);
@@ -223,67 +251,134 @@ void aha1542_intr_handle(void)
if (flag&HACC) printk("HACC ");
if (flag&SCRD) printk("SCRD ");
printk("status %02x\n", inb(STATUS));
- if (ccb.tarstat|ccb.hastat)
- printk("aha1542_command: returning %x (status %d)\n", ccb.tarstat + ((int) ccb.hastat << 16), mb[1].status);
};
#endif
- aha1542_intr_reset();
- if (!my_done) {
- printk("aha1542_intr_handle: Unexpected interrupt\n");
+ number_serviced = 0;
+
+ while(1==1){
+ aha1542_intr_reset();
+
+ cli();
+ mbi = aha1542_last_mbi_used + 1;
+ if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES;
+
+ do{
+ if(mb[mbi].status != 0) break;
+ mbi++;
+ if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES;
+ } while (mbi != aha1542_last_mbi_used);
+
+ if(mb[mbi].status == 0){
+ sti();
+ /* Hmm, no mail. Must have read it the last time around */
+ if (number_serviced) return;
+ printk("aha1542.c: interrupt received, but no mail.\n");
return;
- }
-
- /* is there mail :-) */
-
- if (!mb[1].status) {
- DEB(printk("aha1542_intr_handle: strange: mbif but no mail!\n"));
- my_done(aha1542_host, DID_TIME_OUT << 16);
- return;
- }
+ };
+
+ mbo = (scsi2int(mb[mbi].ccbptr) - ((unsigned int) &ccb[0])) / sizeof(struct ccb);
+ mbistatus = mb[mbi].status;
+ mb[mbi].status = 0;
+ aha1542_last_mbi_used = mbi;
+ sti();
+
+#ifdef DEBUG
+ {
+ if (ccb[mbo].tarstat|ccb[mbo].hastat)
+ printk("aha1542_command: returning %x (status %d)\n",
+ ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
+ };
+#endif
- /* more error checking left out here */
- if (mb[1].status != 1)
- /* This is surely wrong, but I don't know what's right */
- errstatus = makecode(ccb.hastat, ccb.tarstat);
- else
- errstatus = 0;
+ if(mbistatus == 3) continue; /* Aborted command not found */
- mb[1].status = 0;
+#ifdef DEBUG
+ printk("...done %d %d\n",mbo, mbi);
+#endif
+
+ SCtmp = SCint[mbo];
+ my_done = SCtmp->scsi_done;
+ if (SCtmp->host_scribble) scsi_free(SCtmp->host_scribble, 512);
+
+ if (!my_done) {
+ printk("aha1542_intr_handle: Unexpected interrupt\n");
+ return;
+ }
+
+ /* Fetch the sense data, and tuck it away, in the required slot. The
+ Adaptec automatically fetches it, and there is no guarantee that
+ we will still have it in the cdb when we come back */
+ if (ccb[mbo].tarstat == 2)
+ memcpy(SCtmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
+ sizeof(SCtmp->sense_buffer));
+
+
+ /* is there mail :-) */
+
+ /* more error checking left out here */
+ if (mbistatus != 1)
+ /* This is surely wrong, but I don't know what's right */
+ errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
+ else
+ errstatus = 0;
+
+#ifdef DEBUG
+ if(errstatus) printk("(aha1542 error:%x %x %x) ",errstatus,
+ ccb[mbo].hastat, ccb[mbo].tarstat);
+#endif
- if (ccb.tarstat == 2) {
+ if (ccb[mbo].tarstat == 2) {
#ifdef DEBUG
int i;
#endif
DEB(printk("aha1542_intr_handle: sense:"));
#ifdef DEBUG
for (i = 0; i < 12; i++)
- printk("%02x ", ccb.cdb[ccb.cdblen+i]);
+ printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen+i]);
printk("\n");
#endif
-/*
- DEB(printk("aha1542_intr_handle: buf:"));
- for (i = 0; i < bufflen; i++)
+ /*
+ DEB(printk("aha1542_intr_handle: buf:"));
+ for (i = 0; i < bufflen; i++)
printk("%02x ", ((unchar *)buff)[i]);
- printk("\n");
-*/
- }
- DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
- my_done(aha1542_host, errstatus);
- return;
+ printk("\n");
+ */
+ }
+ DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
+ SCtmp->result = errstatus;
+ SCint[mbo] = NULL; /* This effectively frees up the mailbox slot, as
+ far as queuecommand is concerned */
+ my_done(SCtmp);
+ number_serviced++;
+ };
}
-int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int, int))
+int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
{
unchar ahacmd = CMD_START_SCSI;
unchar direction;
- unchar *cmd = (unchar *) cmnd;
+ unchar *cmd = (unchar *) SCpnt->cmnd;
+ unchar target = SCpnt->target;
+ unchar lun = SCpnt->lun;
+ void *buff = SCpnt->request_buffer;
+ int bufflen = SCpnt->request_bufflen;
+ int mbo;
+
DEB(int i);
- DEB(if (target > 1) {done(aha1542_host, DID_TIME_OUT << 16); return 0;});
+ DEB(if (target > 1) {
+ SCpnt->result = DID_TIME_OUT << 16;
+ done(SCpnt); return 0;});
if(*cmd == REQUEST_SENSE){
- memcpy(buff, &ccb.cdb[ccb.cdblen], bufflen);
- done(aha1542_host, 0);
+#ifndef DEBUG
+ if (bufflen != 16) {
+ printk("Wrong buffer length supplied for request sense (%d)\n",bufflen);
+ panic("aha1542.c");
+ };
+#endif
+ SCpnt->result = 0;
+ done(SCpnt);
return 0;
};
@@ -305,9 +400,36 @@ int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int buffle
if (*cmd == WRITE_10 || *cmd == WRITE_6)
return 0; /* we are still testing, so *don't* write */
#endif
- memset(&ccb, 0, sizeof ccb);
+/* Use the outgoing mailboxes in a round-robin fashion, because this
+ is how the host adapter will scan for them */
- ccb.cdblen = (*cmd<=0x1f)?6:10; /* SCSI Command Descriptor Block Length */
+ cli();
+ mbo = aha1542_last_mbo_used + 1;
+ if (mbo >= AHA1542_MAILBOXES) mbo = 0;
+
+ do{
+ if(mb[mbo].status == 0 && SCint[mbo] == NULL)
+ break;
+ mbo++;
+ if (mbo >= AHA1542_MAILBOXES) mbo = 0;
+ } while (mbo != aha1542_last_mbo_used);
+
+ if(mb[mbo].status || SCint[mbo])
+ panic("Unable to find empty mailbox for aha1542.\n");
+
+ SCint[mbo] = SCpnt; /* This will effectively prevent someone else from
+ screwing with this cdb. */
+
+ aha1542_last_mbo_used = mbo;
+ sti();
+
+#ifdef DEBUG
+ printk("Sending command (%d %x)...",mbo, done);
+#endif
+
+ memset(&ccb[mbo], 0, sizeof(struct ccb));
+
+ ccb[mbo].cdblen = (*cmd<=0x1f)?6:10; /* SCSI Command Descriptor Block Length */
direction = 0;
if (*cmd == READ_10 || *cmd == READ_6)
@@ -315,33 +437,69 @@ int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int buffle
else if (*cmd == WRITE_10 || *cmd == WRITE_6)
direction = 16;
- memcpy(ccb.cdb, cmd, ccb.cdblen);
- ccb.op = 0; /* SCSI Initiator Command */
- ccb.idlun = (target&7)<<5 | direction; /* SCSI Target Id */
- ccb.rsalen = 12;
- any2scsi(ccb.datalen, bufflen);
- any2scsi(ccb.dataptr, buff);
- ccb.linkptr[0] = ccb.linkptr[1] = ccb.linkptr[2] = 0;
- ccb.commlinkid = 0;
-
- mb[0].status = 1;
- mb[1].status = 0;
-
+ memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
+
+ if (SCpnt->use_sg) {
+ struct scatterlist * sgpnt;
+ struct chain * cptr;
+#ifdef DEBUG
+ unsigned char * ptr;
+#endif
+ int i;
+ ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather*/
+ SCpnt->host_scribble = scsi_malloc(512);
+ sgpnt = (struct scatterlist *) SCpnt->request_buffer;
+ cptr = (struct chain *) SCpnt->host_scribble;
+ if (cptr == NULL) panic("aha1542.c: unable to allocate DMA memory\n");
+ for(i=0; i<SCpnt->use_sg; i++) {
+ if(sgpnt[i].length == 0 || SCpnt->use_sg > 16 ||
+ (((int)sgpnt[i].address) & 1) || (sgpnt[i].length & 1)){
+ unsigned char * ptr;
+ printk("Bad segment list supplied to aha1542.c (%d, %d)\n",SCpnt->use_sg,i);
+ for(i=0;i<SCpnt->use_sg++;i++){
+ printk("%d: %x %x %d\n",i,sgpnt[i].address, sgpnt[i].alt_address,
+ sgpnt[i].length);
+ };
+ printk("cptr %x: ",cptr);
+ ptr = (unsigned char *) &cptr[i];
+ for(i=0;i<18;i++) printk("%02x ", ptr[i]);
+ panic("Foooooooood fight!");
+ };
+ any2scsi(cptr[i].dataptr, sgpnt[i].address);
+ any2scsi(cptr[i].datalen, sgpnt[i].length);
+ };
+ any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
+ any2scsi(ccb[mbo].dataptr, cptr);
+#ifdef DEBUG
+ printk("cptr %x: ",cptr);
+ ptr = (unsigned char *) cptr;
+ for(i=0;i<18;i++) printk("%02x ", ptr[i]);
+#endif
+ } else {
+ ccb[mbo].op = 0; /* SCSI Initiator Command */
+ SCpnt->host_scribble = NULL;
+ any2scsi(ccb[mbo].datalen, bufflen);
+ any2scsi(ccb[mbo].dataptr, buff);
+ };
+ ccb[mbo].idlun = (target&7)<<5 | direction | (lun & 7); /*SCSI Target Id*/
+ ccb[mbo].rsalen = 12;
+ ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
+ ccb[mbo].commlinkid = 0;
+
#ifdef DEBUGd
+ { int i;
printk("aha1542_command: sending.. ");
- for (i = 0; i < sizeof(ccb)-10; i++)
- printk("%02x ", ((unchar *)&ccb)[i]);
+ for (i = 0; i < sizeof(ccb[mbo])-10; i++)
+ printk("%02x ", ((unchar *)&ccb[mbo])[i]);
+ };
#endif
if (done) {
DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
- if (do_done)
- printk("aha1542_queuecommand: Two concurrent queuecommand?\n");
- else
- do_done = done;
+ SCpnt->scsi_done = done;
+ mb[mbo].status = 1;
aha1542_out(&ahacmd, 1); /* start scsi command */
DEB(aha1542_stat());
- aha1542_enable_intr();
}
else
printk("aha1542_queuecommand: done can't be NULL\n");
@@ -349,18 +507,19 @@ int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int buffle
return 0;
}
-volatile static int internal_done_flag = 0;
-volatile static int internal_done_errcode = 0;
-static void internal_done(int host, int errcode)
+static volatile int internal_done_flag = 0;
+static volatile int internal_done_errcode = 0;
+static void internal_done(Scsi_Cmnd * SCpnt)
{
- internal_done_errcode = errcode;
+ internal_done_errcode = SCpnt->result;
++internal_done_flag;
}
-int aha1542_command(unchar target, const void *cmnd, void *buff, int bufflen)
+int aha1542_command(Scsi_Cmnd * SCpnt)
{
DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
- aha1542_queuecommand(target, cmnd, buff, bufflen, internal_done);
+
+ aha1542_queuecommand(SCpnt, internal_done);
while (!internal_done_flag);
internal_done_flag = 0;
@@ -370,12 +529,15 @@ int aha1542_command(unchar target, const void *cmnd, void *buff, int bufflen)
/* Initialize mailboxes */
static void setup_mailboxes()
{
- static unchar cmd[5] = {CMD_MBINIT, 1};
-
- mb[0].status = mb[1].status = 0;
- aha1542_intr_reset(); /* reset interrupts, so they don't block */
+ int i;
+ static unchar cmd[5] = {CMD_MBINIT, AHA1542_MAILBOXES};
+
+ for(i=0; i<AHA1542_MAILBOXES; i++){
+ mb[i].status = mb[AHA1542_MAILBOXES+i].status = 0;
+ any2scsi(mb[i].ccbptr, &ccb[i]);
+ };
+ aha1542_intr_reset(); /* reset interrupts, so they don't block */
any2scsi((cmd+2), mb);
- any2scsi(mb[0].ccbptr, &ccb);
aha1542_out(cmd, 5);
WAIT(INTRFLAGS, INTRMASK, HACC, 0);
while (0) {
@@ -385,11 +547,65 @@ static void setup_mailboxes()
aha1542_intr_reset();
}
-/* a hack to avoid a strange compilation error */
-
-void call_buh()
+/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
+static int aha1542_getconfig(int hostnum)
{
- set_intr_gate(0x2b,&aha1542_interrupt);
+ static unchar inquiry_cmd[] = {CMD_RETCONF };
+ static unchar inquiry_result[3];
+ int i;
+ i = inb(STATUS);
+ if (i & DF) {
+ i = inb(DATA);
+ };
+ aha1542_out(inquiry_cmd, 1);
+ aha1542_in(inquiry_result, 3);
+ WAIT(INTRFLAGS, INTRMASK, HACC, 0);
+ while (0) {
+ fail:
+ printk("aha1542_detect: query board settings\n");
+ }
+ aha1542_intr_reset();
+ switch(inquiry_result[0]){
+ case 0x80:
+ dma_chan = 7;
+ break;
+ case 0x40:
+ dma_chan = 6;
+ break;
+ case 0x20:
+ dma_chan = 5;
+ break;
+ case 1:
+ printk("DMA priority 0 not available for Adaptec driver\n");
+ return -1;
+ default:
+ printk("Unable to determine Adaptec DMA priority. Disabling board\n");
+ return -1;
+ };
+ switch(inquiry_result[1]){
+ case 0x40:
+ irq_level = 15;
+ break;
+ case 0x20:
+ irq_level = 14;
+ break;
+ case 0x8:
+ irq_level = 12;
+ break;
+ case 0x4:
+ irq_level = 11;
+ break;
+ case 0x2:
+ irq_level = 10;
+ break;
+ case 0x1:
+ irq_level = 9;
+ break;
+ default:
+ printk("Unable to determine Adaptec IRQ level. Disabling board\n");
+ return -1;
+ };
+ return 0;
}
/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
@@ -411,32 +627,38 @@ static void aha1542_query(int hostnum)
}
aha1542_intr_reset();
-/* For an AHA1740 series board, we select slower I/O because there is a
- hardware bug which can lead to wrong blocks being returned. The slow
- I/O somehow prevents this. Once we have drivers for extended mode
- on the aha1740, this will no longer be required.
+/* For an AHA1740 series board, we ignore the board since there is a
+ hardware bug which can lead to wrong blocks being returned if the board
+ is operating in the 1542 emulation mode. Since there is an extended mode
+ driver, we simply ignore the board and let the 1740 driver pick it up.
*/
if (inquiry_result[0] == 0x43) {
- slow_scsi_io = hostnum;
- printk("aha1542.c: Slow SCSI disk I/O selected for AHA 174N hardware.\n");
+ printk("aha1542.c: Emulation mode not supported for AHA 174N hardware.\n");
+ aha_disable = 1;
};
}
+
/* return non-zero on detection */
int aha1542_detect(int hostnum)
{
int i;
+ int indx;
DEB(printk("aha1542_detect: \n"));
- if (!(i = aha1542_test_port())) {
- return 0;
+ indx = 0;
+ while(indx < sizeof(bases)/sizeof(bases[0])){
+ i = aha1542_test_port(bases[indx]);
+ if (i) break;
+ indx++;
}
+ if (indx == sizeof(bases)/sizeof(bases[0])) return 0;
- /* Set the Bus on/off-times as not to ruin floppy performens */
+ /* Set the Bus on/off-times as not to ruin floppy performance */
{
- static unchar oncmd[] = {CMD_BUSON_TIME, 5};
- static unchar offcmd[] = {CMD_BUSOFF_TIME, 9};
+ static unchar oncmd[] = {CMD_BUSON_TIME, 7};
+ static unchar offcmd[] = {CMD_BUSOFF_TIME, 5};
aha1542_intr_reset();
aha1542_out(oncmd, 2);
@@ -452,21 +674,37 @@ int aha1542_detect(int hostnum)
}
aha1542_query(hostnum);
+ if (aha_disable) return 0;
+
+ if (aha1542_getconfig(hostnum) == -1) return 0;
+
+ printk("Configuring Adaptec at IO:%x, IRQ %d, DMA priority %d\n",base,
+ irq_level, dma_chan);
+
DEB(aha1542_stat());
setup_mailboxes();
DEB(aha1542_stat());
- DEB(printk("aha1542_detect: enable interrupt channel %d\n", intr_chan));
- call_buh();
+ DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
- if (intr_chan >= 8)
- outb(inb_p(0x21)&0xfb,0x21); /* open for slave ?? */
+ if (request_irq(irq_level,aha1542_intr_handle)) {
+ printk("Unable to allocate IRQ for adaptec controller.\n");
+ return 0;
+ };
- DEB(printk("aha1542_detect: enabling interrupts\n"));
- aha1542_enable_intr();
+ if(request_dma(dma_chan)){
+ printk("Unable to allocate DMA channel for Adaptec.\n");
+ free_irq(irq_level);
+ return 0;
+ };
-#ifdef DEBUG
+ if(dma_chan >= 5){
+ outb(((dma_chan - 4)|CASCADE),DMA_MODE_REG);
+ outb((dma_chan-4),DMA_MASK_REG);
+ };
+
+#if 0
DEB(printk(" *** READ CAPACITY ***\n"));
{
@@ -503,9 +741,27 @@ int aha1542_detect(int hostnum)
return 1;
}
-int aha1542_abort(int i)
+/* The abort command does not leave the device in a clean state where
+ it is available to be used again. Until this gets worked out, we will
+ leave it commented out. */
+
+int aha1542_abort(Scsi_Cmnd * SCpnt, int i)
{
+#if 0
+ unchar ahacmd = CMD_START_SCSI;
+ int mbo;
+#endif
DEB(printk("aha1542_abort\n"));
+#if 0
+ cli();
+ for(mbo = 0; mbo < AHA1542_MAILBOXES; mbo++)
+ if (SCpnt == SCint[mbo]){
+ mb[mbo].status = 2; /* Abort command */
+ aha1542_out(&ahacmd, 1); /* start scsi command */
+ sti();
+ break;
+ };
+#endif
return 0;
}
@@ -515,34 +771,10 @@ int aha1542_reset(void)
return 0;
}
-__asm__("
-_aha1542_interrupt:
- cld
- pushl %eax
- pushl %ecx
- pushl %edx
- push %ds
- push %es
- push %fs
- movl $0x10,%eax
- mov %ax,%ds
- mov %ax,%es
- movl $0x17,%eax
- mov %ax,%fs
- movb $0x20,%al
- outb %al,$0xA0 # EOI to interrupt controller #1
- jmp 1f # give port chance to breathe
-1: jmp 1f
-1: outb %al,$0x20
-# Please, someone, change this to use the timer
-# andl $0xfffeffff,_timer_active
- movl $_aha1542_intr_handle,%edx
- call *%edx # ``interesting'' way of handling intr.
- pop %fs
- pop %es
- pop %ds
- popl %edx
- popl %ecx
- popl %eax
- iret
-");
+int aha1542_biosparam(int size, int dev, int* info){
+ info[0] = 32;
+ info[1] = 64;
+ info[2] = (size + 2047) >> 11;
+ if (info[2] >= 1024) info[2] = 1024;
+ return 0;
+}
diff --git a/kernel/blk_drv/scsi/aha1542.h b/kernel/blk_drv/scsi/aha1542.h
index aa57544..10131d6 100644
--- a/kernel/blk_drv/scsi/aha1542.h
+++ b/kernel/blk_drv/scsi/aha1542.h
@@ -80,6 +80,12 @@ struct mailbox {
unchar ccbptr[3]; /* msb, .., lsb */
};
+/* This is used with scatter-gather */
+struct chain {
+ unchar datalen[3]; /* Size of this part of chain */
+ unchar dataptr[3]; /* Location of data */
+};
+
/* These belong in scsi.h also */
#define any2scsi(up, p) \
(up)[0] = (((unsigned long)(p)) >> 16) ; \
@@ -120,11 +126,15 @@ struct ccb { /* Command Control Block 5.3 */
};
int aha1542_detect(int);
-int aha1542_command(unsigned char target, const void *cmnd, void *buff, int bufflen);
-int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int, int));
-int aha1542_abort(int);
-char *aha1542_info(void);
+int aha1542_command(Scsi_Cmnd *);
+int aha1542_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int aha1542_abort(Scsi_Cmnd *, int);
+const char *aha1542_info(void);
int aha1542_reset(void);
+int aha1542_biosparam(int, int, int*);
+
+#define AHA1542_MAILBOXES 8
+#define AHA1542_SCATTER 16
#ifndef NULL
#define NULL 0
@@ -135,5 +145,8 @@ int aha1542_reset(void);
aha1542_queuecommand, \
aha1542_abort, \
aha1542_reset, \
- 1, 7, 0, 1}
+ NULL, \
+ aha1542_biosparam, \
+ AHA1542_MAILBOXES, 7, AHA1542_SCATTER, 1, 0, 1}
+
#endif
diff --git a/kernel/blk_drv/scsi/aha1740.c b/kernel/blk_drv/scsi/aha1740.c
new file mode 100644
index 0000000..d58b3e0
--- /dev/null
+++ b/kernel/blk_drv/scsi/aha1740.c
@@ -0,0 +1,428 @@
+/* $Id: aha1740.c,v 1.1 1992/07/24 06:27:38 root Exp root $
+ * linux/kernel/aha1740.c
+ *
+ * Based loosely on aha1542.c which is
+ * Copyright (C) 1992 Tommy Thorn
+ * and
+ * Modified by Eric Youngdale
+ *
+ * This file is aha1740.c, written and
+ * Copyright (C) 1992 Brad McLean
+ *
+ * aha1740_makecode needs more work
+ */
+
+#include <linux/kernel.h>
+#include <linux/head.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <linux/sched.h>
+#include <asm/dma.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include "../blk.h"
+#include "scsi.h"
+#include "hosts.h"
+
+#include "aha1740.h"
+/* #define DEBUG */
+#ifdef DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+/*
+static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1740.c,v 1.1 1992/07/24 06:27:38 root Exp root $";
+*/
+
+static unsigned int slot, base;
+static unsigned char irq_level;
+
+static struct ecb ecb[AHA1740_ECBS]; /* One for each queued operation */
+
+static int aha1740_last_ecb_used = 0; /* optimization */
+
+int aha1740_makecode(unchar *sense, unchar *status)
+{
+ struct statusword {
+ ushort don:1, /* Command Done - No Error */
+ du:1, /* Data underrun */
+ :1, qf:1, /* Queue full */
+ sc:1, /* Specification Check */
+ dor:1, /* Data overrun */
+ ch:1, /* Chaining Halted */
+ intr:1, /* Interrupt issued */
+ asa:1, /* Additional Status Available */
+ sns:1, /* Sense information Stored */
+ :1, ini:1, /* Initialization Required */
+ me:1, /* Major error or exception */
+ :1, eca:1, :1; /* Extended Contingent alliance */
+ } status_word;
+ int retval = DID_OK;
+
+ status_word = * (struct statusword *) status;
+#ifdef DEBUG
+printk("makecode from %x,%x,%x,%x %x,%x,%x,%x",status[0],status[1],status[2],status[3],
+sense[0],sense[1],sense[2],sense[3]);
+#endif
+ if ( status_word.don )
+ return 0;
+/*
+ if ( status_word.du && status[2] != 0x11 )
+ return 0;
+*/
+ if ( status[2] == 0x11 )
+ retval = DID_TIME_OUT;
+ else
+ retval = DID_ERROR;
+ return status[3] | retval << 16; /* OKAY, SO I'M LAZY! I'll fix it later... */
+}
+
+int aha1740_test_port()
+{
+ char name[4],tmp;
+
+ /* Okay, look for the EISA ID's */
+ name[0]= 'A' -1 + ((tmp = inb(HID0)) >> 2); /* First character */
+ name[1]= 'A' -1 + ((tmp & 3) << 3);
+ name[1]+= ((tmp = inb(HID1)) >> 5)&0x7; /* Second Character */
+ name[2]= 'A' -1 + (tmp & 0x1f); /* Third Character */
+ name[3]=0;
+ tmp = inb(HID2);
+ if ( strcmp ( name, HID_MFG ) || inb(HID2) != HID_PRD )
+ return 0; /* Not an Adaptec 174x */
+
+/* if ( inb(HID3) < HID_REV ) */
+ if ( inb(HID3) != HID_REV )
+ printk("aha1740: Warning; board revision of %d; expected %d\n",
+ inb(HID3),HID_REV);
+
+ if ( inb(EBCNTRL) != EBCNTRL_VALUE )
+ {
+ printk("aha1740: Board detected, but EBCNTRL = %x, so disabled it.\n",
+ inb(EBCNTRL));
+ return 0;
+ }
+
+ if ( inb(PORTADR) & PORTADDR_ENH )
+ return 1; /* Okay, we're all set */
+ printk("aha1740: Board detected, but not in enhanced mode, so disabled it.\n");
+ return 0;
+}
+
+/* What's this little function for? */
+const char *aha1740_info(void)
+{
+ static char buffer[] = ""; /* looks nicer without anything here */
+ return buffer;
+}
+
+/* A "high" level interrupt handler */
+void aha1740_intr_handle(int foo)
+{
+ void (*my_done)(Scsi_Cmnd *);
+ int errstatus, adapstat;
+ int number_serviced;
+ struct ecb *ecbptr;
+ Scsi_Cmnd *SCtmp;
+
+ number_serviced = 0;
+
+ while(inb(G2STAT) & G2STAT_INTPEND){
+ DEB(printk("aha1740_intr top of loop.\n"));
+ adapstat = inb(G2INTST);
+ outb(G2CNTRL_IRST,G2CNTRL); /* interrupt reset */
+
+ switch ( adapstat & G2INTST_MASK )
+ {
+ case G2INTST_CCBRETRY:
+ printk("aha1740 complete with retry!\n");
+ case G2INTST_CCBERROR:
+ case G2INTST_CCBGOOD:
+ ecbptr = (void *) ( ((ulong) inb(MBOXIN0)) +
+ ((ulong) inb(MBOXIN1) <<8) +
+ ((ulong) inb(MBOXIN2) <<16) +
+ ((ulong) inb(MBOXIN3) <<24) );
+ outb(G2CNTRL_HRDY,G2CNTRL); /* Host Ready -> Mailbox in complete */
+ SCtmp = ecbptr->SCpnt;
+ if (SCtmp->host_scribble)
+ scsi_free(SCtmp->host_scribble, 512);
+ /* Fetch the sense data, and tuck it away, in the required slot. The
+ Adaptec automatically fetches it, and there is no guarantee that
+ we will still have it in the cdb when we come back */
+ if ( (adapstat & G2INTST_MASK) == G2INTST_CCBERROR )
+ {
+ memcpy(SCtmp->sense_buffer, ecbptr->sense,
+ sizeof(SCtmp->sense_buffer));
+ errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status);
+ }
+ else
+ errstatus = 0;
+ DEB(if (errstatus) printk("aha1740_intr_handle: returning %6x\n", errstatus));
+ SCtmp->result = errstatus;
+ my_done = ecbptr->done;
+ memset(ecbptr,0,sizeof(struct ecb));
+ if ( my_done )
+ my_done(SCtmp);
+ break;
+ case G2INTST_HARDFAIL:
+ printk("aha1740 hardware failure!\n");
+ panic("aha1740.c"); /* Goodbye */
+ case G2INTST_ASNEVENT:
+ printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",adapstat,
+ inb(MBOXIN0),inb(MBOXIN1),inb(MBOXIN2),inb(MBOXIN3)); /* Say What? */
+ outb(G2CNTRL_HRDY,G2CNTRL); /* Host Ready -> Mailbox in complete */
+ break;
+ case G2INTST_CMDGOOD:
+ /* set immediate command success flag here: */
+ break;
+ case G2INTST_CMDERROR:
+ /* Set immediate command failure flag here: */
+ break;
+ }
+ number_serviced++;
+ };
+}
+
+int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
+{
+ unchar direction;
+ unchar *cmd = (unchar *) SCpnt->cmnd;
+ unchar target = SCpnt->target;
+ void *buff = SCpnt->request_buffer;
+ int bufflen = SCpnt->request_bufflen;
+ int ecbno;
+ DEB(int i);
+
+ DEB(if (target > 0 || SCpnt->lun > 0) {
+ SCpnt->result = DID_TIME_OUT << 16;
+ done(SCpnt); return 0;});
+
+ if(*cmd == REQUEST_SENSE){
+#ifndef DEBUG
+ if (bufflen != 16) {
+ printk("Wrong buffer length supplied for request sense (%d)\n",bufflen);
+ panic("aha1740.c");
+ };
+#endif
+ SCpnt->result = 0;
+ done(SCpnt);
+ return 0;
+ };
+
+#ifdef DEBUG
+ if (*cmd == READ_10 || *cmd == WRITE_10)
+ i = xscsi2int(cmd+2);
+ else if (*cmd == READ_6 || *cmd == WRITE_6)
+ i = scsi2int(cmd+2);
+ else
+ i = -1;
+ if (done)
+ printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
+ else
+ printk("aha1740_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
+ printk("scsi cmd:");
+ for (i = 0; i < (*cmd<=0x1f?6:10); i++) printk("%02x ", cmd[i]);
+ printk("\n");
+#ifdef 0
+ if (*cmd == WRITE_10 || *cmd == WRITE_6)
+ return 0; /* we are still testing, so *don't* write */
+#endif
+#endif
+
+/* locate an available ecb */
+
+ cli();
+ ecbno = aha1740_last_ecb_used + 1;
+ if (ecbno >= AHA1740_ECBS) ecbno = 0;
+
+ do{
+ if( ! ecb[ecbno].cmdw )
+ break;
+ ecbno++;
+ if (ecbno >= AHA1740_ECBS ) ecbno = 0;
+ } while (ecbno != aha1740_last_ecb_used);
+
+ if( ecb[ecbno].cmdw )
+ panic("Unable to find empty ecb for aha1740.\n");
+
+ ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command to reserve*/
+
+ aha1740_last_ecb_used = ecbno;
+ sti();
+
+#ifdef DEBUG
+ printk("Sending command (%d %x)...",ecbno, done);
+#endif
+
+ ecb[ecbno].cdblen = (*cmd<=0x1f)?6:10; /* SCSI Command Descriptor Block Length */
+
+ direction = 0;
+ if (*cmd == READ_10 || *cmd == READ_6)
+ direction = 1;
+ else if (*cmd == WRITE_10 || *cmd == WRITE_6)
+ direction = 0;
+
+ memcpy(ecb[ecbno].cdb, cmd, ecb[ecbno].cdblen);
+
+ if (SCpnt->use_sg) {
+ struct scatterlist * sgpnt;
+ struct aha1740_chain * cptr;
+#ifdef DEBUG
+ unsigned char * ptr;
+#endif
+ int i;
+ ecb[ecbno].sg = 1; /* SCSI Initiator Command w/scatter-gather*/
+ SCpnt->host_scribble = scsi_malloc(512);
+ sgpnt = (struct scatterlist *) SCpnt->request_buffer;
+ cptr = (struct aha1740_chain *) SCpnt->host_scribble;
+ if (cptr == NULL) panic("aha1740.c: unable to allocate DMA memory\n");
+ for(i=0; i<SCpnt->use_sg; i++) {
+ cptr[i].dataptr = (long) sgpnt[i].address;
+ cptr[i].datalen = sgpnt[i].length;
+ };
+ ecb[ecbno].datalen = SCpnt->use_sg * sizeof(struct aha1740_chain);
+ ecb[ecbno].dataptr = (long) cptr;
+#ifdef DEBUG
+ printk("cptr %x: ",cptr);
+ ptr = (unsigned char *) cptr;
+ for(i=0;i<24;i++) printk("%02x ", ptr[i]);
+#endif
+ } else {
+ SCpnt->host_scribble = NULL;
+ ecb[ecbno].datalen = bufflen;
+ ecb[ecbno].dataptr = (long) buff;
+ };
+ ecb[ecbno].lun = SCpnt->lun;
+ ecb[ecbno].ses = 1; /* Suppress underrun errors */
+/* ecb[ecbno].dat=1; */ /* Yes, check the data direction */
+ ecb[ecbno].dir= direction;
+ ecb[ecbno].ars=1; /* Yes, get the sense on an error */
+ ecb[ecbno].senselen = 12; /* Why 12? Eric? MAXSENSE? */
+ ecb[ecbno].senseptr = (long) ecb[ecbno].sense;
+ ecb[ecbno].statusptr = (long) ecb[ecbno].status;
+ ecb[ecbno].done = done;
+ ecb[ecbno].SCpnt = SCpnt;
+#ifdef DEBUG
+ { int i;
+ printk("aha1740_command: sending.. ");
+ for (i = 0; i < sizeof(ecb[ecbno])-10; i++)
+ printk("%02x ", ((unchar *)&ecb[ecbno])[i]);
+ };
+ printk("\n");
+#endif
+ if (done) { ulong adrs;
+
+ if ( ! (inb(G2STAT) & G2STAT_MBXOUT) ) /* Spec claim's it's so fast */
+ printk("aha1740_mbxout wait!\n"); /* that this is okay? It seems */
+ while ( ! (inb(G2STAT) & G2STAT_MBXOUT) ); /* to work, so I'll leave it */
+ adrs = (ulong) &(ecb[ecbno]);
+ outb((char) (adrs&0xff), MBOXOUT0);
+ outb((char) ((adrs>>8)&0xff), MBOXOUT1);
+ outb((char) ((adrs>>16)&0xff), MBOXOUT2);
+ outb((char) ((adrs>>24)&0xff), MBOXOUT3);
+ if ( inb(G2STAT) & G2STAT_BUSY ) /* Again, allegedly fast */
+ printk("aha1740_attn wait!\n");
+ while ( inb(G2STAT) & G2STAT_BUSY );
+ outb(ATTN_START | (target & 7), ATTN); /* Start it up */
+ }
+ else
+ printk("aha1740_queuecommand: done can't be NULL\n");
+
+ return 0;
+}
+
+static volatile int internal_done_flag = 0;
+static volatile int internal_done_errcode = 0;
+static void internal_done(Scsi_Cmnd * SCpnt)
+{
+ internal_done_errcode = SCpnt->result;
+ ++internal_done_flag;
+}
+
+int aha1740_command(Scsi_Cmnd * SCpnt)
+{
+ aha1740_queuecommand(SCpnt, internal_done);
+
+ while (!internal_done_flag);
+ internal_done_flag = 0;
+ return internal_done_errcode;
+}
+
+/* Query the board for it's port addresses, etc. Actually, the irq_level is
+ all we care about for this board, since it's EISA */
+
+static int aha1740_getconfig()
+{
+ int iop, bios, scsi, dma;
+ static int iotab[] = { 0, 0, 0x130, 0x134, 0x230, 0x234, 0x330, 0x334 };
+ static int intab[] = { 9,10,11,12,0,14,15,0 };
+ static int dmatab[] = { 0,5,6,7 };
+
+ iop = iotab [ inb(PORTADR)&0x7 ];
+ bios = inb(BIOSADR);
+ irq_level = intab [ inb(INTDEF)&0x7 ];
+ scsi = inb(SCSIDEF);
+ dma = dmatab[ (inb(BUSDEF)>>2) & 0x3 ];
+ return 0;
+}
+
+int aha1740_detect(int hostnum)
+{
+ memset(ecb,0,sizeof(ecb));
+ DEB(printk("aha1740_detect: \n"));
+
+ for ( slot=MINEISA; slot <= MAXEISA; slot++ )
+ {
+ base = SLOTBASE(slot);
+ if ( aha1740_test_port(base)) break;
+ }
+ if ( slot > MAXEISA )
+ return 0;
+
+ if (aha1740_getconfig() == -1)
+ return 0;
+
+ if ( (inb(G2STAT) & (G2STAT_MBXOUT | G2STAT_BUSY) ) != G2STAT_MBXOUT )
+ {
+ outb(G2CNTRL_HRST,G2CNTRL);
+ /* 10 Msec Delay Here */
+ outb(0,G2CNTRL);
+ }
+
+ printk("Configuring Adaptec at IO:%x, IRQ %d\n",base,
+ irq_level);
+
+ DEB(printk("aha1740_detect: enable interrupt channel %d\n", irq_level));
+
+ if (request_irq(irq_level,aha1740_intr_handle)) {
+ printk("Unable to allocate IRQ for adaptec controller.\n");
+ return 0;
+ };
+ return 1;
+}
+
+int aha1740_abort(Scsi_Cmnd * SCpnt, int i)
+{
+ DEB(printk("aha1740_abort\n"));
+ return 0;
+}
+
+int aha1740_reset(void)
+{
+ DEB(printk("aha1740_reset called\n"));
+ return 0;
+}
+
+int aha1740_biosparam(int size, int dev, int* info){
+DEB(printk("aha1740_biosparam\n"));
+ info[0] = 32;
+ info[1] = 64;
+ info[2] = (size + 2047) >> 11;
+ if (info[2] >= 1024) info[2] = 1024;
+ return 0;
+}
+
+
diff --git a/kernel/blk_drv/scsi/aha1740.h b/kernel/blk_drv/scsi/aha1740.h
new file mode 100644
index 0000000..178fdf0
--- /dev/null
+++ b/kernel/blk_drv/scsi/aha1740.h
@@ -0,0 +1,175 @@
+#ifndef _AHA1740_H
+
+/* $Id: aha1740.h,v 1.1 1992/07/24 06:27:38 root Exp root $
+ *
+ * Header file for the adaptec 1740 driver for Linux
+ *
+ */
+
+#include <linux/types.h>
+
+/* Eisa Enhanced mode operation - slot locating and addressing */
+#define MINEISA 1 /* I don't have an EISA Spec to know these ranges, so I */
+#define MAXEISA 6 /* Just took my machine's specifications. Adjust to fit.*/
+#define SLOTBASE(x) ((x << 12)+ 0xc80 )
+#define BASE (base)
+
+/* EISA configuration registers & values */
+#define HID0 (base + 0x0)
+#define HID1 (base + 0x1)
+#define HID2 (base + 0x2)
+#define HID3 (base + 0x3)
+#define EBCNTRL (base + 0x4)
+#define PORTADR (base + 0x40)
+#define BIOSADR (base + 0x41)
+#define INTDEF (base + 0x42)
+#define SCSIDEF (base + 0x43)
+#define BUSDEF (base + 0x44)
+#define RESV0 (base + 0x45)
+#define RESV1 (base + 0x46)
+#define RESV2 (base + 0x47)
+
+#define HID_MFG "ADP"
+#define HID_PRD 0
+#define HID_REV 1
+#define EBCNTRL_VALUE 1
+#define PORTADDR_ENH 0x80
+/* READ */
+#define G2INTST (BASE + 0x56)
+#define G2STAT (BASE + 0x57)
+#define MBOXIN0 (BASE + 0x58)
+#define MBOXIN1 (BASE + 0x59)
+#define MBOXIN2 (BASE + 0x5a)
+#define MBOXIN3 (BASE + 0x5b)
+#define G2STAT2 (BASE + 0x5c)
+
+#define G2INTST_MASK 0xf0 /* isolate the status */
+#define G2INTST_CCBGOOD 0x10 /* CCB Completed */
+#define G2INTST_CCBRETRY 0x50 /* CCB Completed with a retry */
+#define G2INTST_HARDFAIL 0x70 /* Adapter Hardware Failure */
+#define G2INTST_CMDGOOD 0xa0 /* Immediate command success */
+#define G2INTST_CCBERROR 0xc0 /* CCB Completed with error */
+#define G2INTST_ASNEVENT 0xd0 /* Asynchronous Event Notification */
+#define G2INTST_CMDERROR 0xe0 /* Immediate command error */
+
+#define G2STAT_MBXOUT 4 /* Mailbox Out Empty Bit */
+#define G2STAT_INTPEND 2 /* Interrupt Pending Bit */
+#define G2STAT_BUSY 1 /* Busy Bit (attention pending) */
+
+#define G2STAT2_READY 0 /* Host Ready Bit */
+
+/* WRITE (and ReadBack) */
+#define MBOXOUT0 (BASE + 0x50)
+#define MBOXOUT1 (BASE + 0x51)
+#define MBOXOUT2 (BASE + 0x52)
+#define MBOXOUT3 (BASE + 0x53)
+#define ATTN (BASE + 0x54)
+#define G2CNTRL (BASE + 0x55)
+
+#define ATTN_IMMED 0x10 /* Immediate Command */
+#define ATTN_START 0x40 /* Start CCB */
+#define ATTN_ABORT 0x50 /* Abort CCB */
+
+#define G2CNTRL_HRST 0x80 /* Hard Reset */
+#define G2CNTRL_IRST 0x40 /* Clear EISA Interrupt */
+#define G2CNTRL_HRDY 0x20 /* Sets HOST ready */
+
+/* This is used with scatter-gather */
+struct aha1740_chain {
+ ulong dataptr; /* Location of data */
+ ulong datalen; /* Size of this part of chain */
+};
+
+/* These belong in scsi.h also */
+#define any2scsi(up, p) \
+(up)[0] = (((unsigned long)(p)) >> 16) ; \
+(up)[1] = (((unsigned long)(p)) >> 8); \
+(up)[2] = ((unsigned long)(p));
+
+#define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) )
+
+#define xany2scsi(up, p) \
+(up)[0] = ((long)(p)) >> 24; \
+(up)[1] = ((long)(p)) >> 16; \
+(up)[2] = ((long)(p)) >> 8; \
+(up)[3] = ((long)(p));
+
+#define xscsi2int(up) ( (((long)(up)[0]) << 24) + (((long)(up)[1]) << 16) \
+ + (((long)(up)[2]) << 8) + ((long)(up)[3]) )
+
+#define MAX_CDB 12
+#define MAX_SENSE 14
+#define MAX_STATUS 32
+
+struct ecb { /* Enhanced Control Block 6.1 */
+ ushort cmdw; /* Command Word */
+ /* Flag Word 1 */
+ ushort cne:1, /* Control Block Chaining */
+ :6, di:1, /* Disable Interrupt */
+ :2, ses:1, /* Suppress Underrun error */
+ :1, sg:1, /* Scatter/Gather */
+ :1, dsb:1, /* Disable Status Block */
+ ars:1; /* Automatic Request Sense */
+ /* Flag Word 2 */
+ ushort lun:3, /* Logical Unit */
+ tag:1, /* Tagged Queuing */
+ tt:2, /* Tag Type */
+ nd:1, /* No Disconnect */
+ :1, dat:1, /* Data transfer - check direction */
+ dir:1, /* Direction of transfer 1 = datain */
+ st:1, /* Suppress Transfer */
+ chk:1, /* Calculate Checksum */
+ :2, rec:1, :1; /* Error Recovery */
+ ushort nil0; /* nothing */
+ ulong dataptr; /* Data or Scatter List ptr */
+ ulong datalen; /* Data or Scatter List len */
+ ulong statusptr; /* Status Block ptr */
+ ulong linkptr; /* Chain Address */
+ ulong nil1; /* nothing */
+ ulong senseptr; /* Sense Info Pointer */
+ unchar senselen; /* Sense Length */
+ unchar cdblen; /* CDB Length */
+ ushort datacheck; /* Data checksum */
+ unchar cdb[MAX_CDB]; /* CDB area */
+ /* Hardware defined portion ends here, rest is driver defined */
+ unchar sense[MAX_SENSE]; /* Sense area */
+ unchar status[MAX_STATUS]; /* Status area */
+ Scsi_Cmnd *SCpnt; /* Link to the SCSI Command Block */
+ void (*done)(Scsi_Cmnd *); /* Completion Function */
+};
+
+#define AHA1740CMD_NOP 0x00 /* No OP */
+#define AHA1740CMD_INIT 0x01 /* Initiator SCSI Command */
+#define AHA1740CMD_DIAG 0x05 /* Run Diagnostic Command */
+#define AHA1740CMD_SCSI 0x06 /* Initialize SCSI */
+#define AHA1740CMD_SENSE 0x08 /* Read Sense Information */
+#define AHA1740CMD_DOWN 0x09 /* Download Firmware (yeah, I bet!) */
+#define AHA1740CMD_RINQ 0x0a /* Read Host Adapter Inquiry Data */
+#define AHA1740CMD_TARG 0x10 /* Target SCSI Command */
+
+int aha1740_detect(int);
+int aha1740_command(Scsi_Cmnd *);
+int aha1740_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int aha1740_abort(Scsi_Cmnd *, int);
+const char *aha1740_info(void);
+int aha1740_reset(void);
+int aha1740_biosparam(int, int, int*);
+
+#define AHA1740_ECBS 64
+#define AHA1740_SCATTER 16
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+#define AHA1740 {"Adaptec 1740", aha1740_detect, \
+ aha1740_info, aha1740_command, \
+ aha1740_queuecommand, \
+ aha1740_abort, \
+ aha1740_reset, \
+ NULL, \
+ aha1740_biosparam, \
+ AHA1740_ECBS, 7, AHA1740_SCATTER, 1, 0, 0}
+
+#endif
+
diff --git a/kernel/blk_drv/scsi/config.in b/kernel/blk_drv/scsi/config.in
deleted file mode 100644
index 75c1fde..0000000
--- a/kernel/blk_drv/scsi/config.in
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <linux/config.h>
-
-#ifdef CONFIG_SCSI
-scsi.o
-hosts.o
-scsi_ioctl.o
-#endif
-
-#ifdef CONFIG_BLK_DEV_SD
-sd.o
-sd_ioctl.o
-#endif
-
-#ifdef CONFIG_BLK_DEV_ST
-st.o
-st_ioctl.o
-#endif
-
-#ifdef CONFIG_SCSI_AHA1542
-aha1542.o
-#endif
-
-#ifdef CONFIG_SCSI_SEAGATE
-seagate.o
-#endif
-
-#ifdef CONFIG_SCSI_ULTRASTOR
-ultrastor.o
-#endif
diff --git a/kernel/blk_drv/scsi/config.out b/kernel/blk_drv/scsi/config.out
deleted file mode 100644
index 83ce57d..0000000
--- a/kernel/blk_drv/scsi/config.out
+++ /dev/null
@@ -1,10 +0,0 @@
-scsi.o
-hosts.o
-scsi_ioctl.o
-sd.o
-sd_ioctl.o
-st.o
-st_ioctl.o
-aha1542.o
-seagate.o
-ultrastor.o
diff --git a/kernel/blk_drv/scsi/fdomain.c b/kernel/blk_drv/scsi/fdomain.c
index ae05651..2d03815 100644
--- a/kernel/blk_drv/scsi/fdomain.c
+++ b/kernel/blk_drv/scsi/fdomain.c
@@ -1,6 +1,6 @@
/* fdomain.c -- Future Domain TMC-1660/TMC-1680 driver
- * Created: Sun May 3 18:53:19 1992
- * Revised: Tue Jul 28 19:45:25 1992 by root
+ * Created: Sun May 3 18:53:19 1992 by faith
+ * Revised: Fri Nov 27 22:57:28 1992 by root
* Author: Rickard E. Faith, faith@cs.unc.edu
* Copyright 1992 Rickard E. Faith
*
@@ -32,42 +32,45 @@
* source was $750 [both required a non-disclosure agreement]. Ever wonder
* why there are no freely available Future Domain drivers?)
- * Thanks to Todd Carrico (todd@wutc.wustl.edu), Dan Poirier
+ * Thanks to: Todd Carrico (todd@wutc.wustl.edu), Dan Poirier
* (poirier@cs.unc.edu ), Ken Corey (kenc@sol.acs.unt.edu), and C. de Bruin
* (bruin@dutiba.tudelft.nl) for alpha testing. Also thanks to Drew
- * Eckhardt (drew@cs.colorado.edu) for answering questions. */
-
-#include <linux/config.h>
-
-#ifdef CONFIG_SCSI_FUTURE_DOMAIN
+ * Eckhardt (drew@cs.colorado.edu) for answering questions, and to Doug
+ * Hoffman (hoffman@cs.unc.edu) for lending me SCSI devices to make driver
+ * more robust. */
#include <linux/sched.h>
#include <asm/io.h>
-#include "fdomain.h"
+#include "../blk.h"
#include "scsi.h"
#include "hosts.h"
-#if QUEUE
+#include "fdomain.h"
#include <asm/system.h>
#include <linux/errno.h>
-#endif
-#define VERSION "1.9" /* Change with each revision */
+#define VERSION "3.1" /* Change with each revision */
+
+/* START OF USER DEFINABLE OPTIONS */
+
#define DEBUG 1 /* Enable debugging output */
-#define SEND_IDENTIFY 0 /* Send IDENTIFY message -- DOESN'T WORK! */
-#define USE_FIFO 1 /* Use the FIFO buffer for I/O */
-#define FAST_SYNCH 1 /* Enable Fast Synchronous */
-#define ALLOW_ALL_IRQ 0 /* Allow all IRQ's -- NOT RECOMMENDED */
-#define NEW_IRQ 1 /* Enable new IRQ handling */
-#define DECREASE_IL 1 /* Try to decrease interrupt latency */
+#define ENABLE_PARITY 1 /* Enable SCSI Parity */
+#define QUEUE 1 /* Enable command queueing */
+#define FIFO_COUNT 2 /* Number of 512 byte blocks before INTR */
+#define DO_DETECT 0 /* Do device detection here (see scsi.c) */
+#define RESELECTION 0 /* Support RESELECTION PHASE (NOT stable) */
+
+/* END OF USER DEFINABLE OPTIONS */
#if DEBUG
#define EVERY_ACCESS 0 /* Write a line on every scsi access */
#define ERRORS_ONLY 1 /* Only write a line if there is an error */
#define DEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */
+#define DEBUG_MESSAGES 0 /* Debug MESSAGE IN PHASE */
#else
#define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
#define ERRORS_ONLY 0
#define DEBUG_DETECT 0
+#define DEBUG_MESSAGES 0
#endif
/* Errors are reported on the line, so we don't need to report them again */
@@ -76,10 +79,15 @@
#define ERRORS_ONLY 0
#endif
+#if ENABLE_PARITY
+#define PARITY_MASK 0x08
+#else
+#define PARITY_MASK 0x00
+#endif
+
static int port_base = 0;
static void *bios_base = NULL;
static int interrupt_level = 0;
-static volatile int aborted = 0;
static int Data_Mode_Cntl_port;
static int FIFO_Data_Count_port;
@@ -93,38 +101,23 @@ static int TMC_Status_port;
static int Write_FIFO_port;
static int Write_SCSI_Data_port;
-#if QUEUE
-static unsigned char current_target = 0;
-static unsigned char current_cmnd[10] = { 0, };
-static void *current_buff = NULL;
-static int current_bufflen = 0;
-static void (*current_done)(int,int) = NULL;
-
-volatile static int in_command = 0;
-volatile static int current_phase;
static int this_host = 0;
+static int can_queue = QUEUE;
-enum { in_arbitration, in_selection, in_other };
+static volatile int in_command = 0;
+static volatile int in_interrupt_code = 0;
+static Scsi_Cmnd *current_SC = NULL;
-#if NEW_IRQ
-extern void fdomain_16x0_intr( int unused );
-#else
-extern void fdomain_16x0_interrupt();
-#endif
-
-static const char *cmd_pt;
-static const char *the_command;
-static unsigned char *out_buf_pt;
-static unsigned char *in_buf_pt;
-volatile static int Status;
-volatile static int Message;
-volatile static unsigned data_sent;
-volatile static int have_data_in;
-
-volatile static int in_interrupt_code = 0;
-
-#endif
+enum { non_queueing = 0x01,
+ in_arbitration = 0x02,
+ in_selection = 0x04,
+ in_other = 0x08,
+ disconnect = 0x10,
+ aborted = 0x20,
+ sent_ident = 0x40,
+ };
+extern void fdomain_16x0_intr( int unused );
enum in_port_type { Read_SCSI_Data = 0, SCSI_Status = 1, TMC_Status = 2,
LSB_ID_Code = 5, MSB_ID_Code = 6, Read_Loopback = 7,
@@ -156,28 +149,18 @@ static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
READ EVERY WORD, ESPECIALLY THE WORD *NOT*
This driver works *ONLY* for Future Domain cards using the
- TMC-1600 chip. This includes models TMC-1660 and TMC-1680
+ TMC-1800 chip. This includes models TMC-1660 and TMC-1680
*ONLY*.
- The following is a BIOS signature for a TMC-950 board, which
- looks like it is a 16 bit board (based on card edge), but
- which only uses the extra lines for IRQ's (not for data):
+ The following BIOS signatures have been tried with this driver. These
+ signatures are for boards which do *NOT* work with this driver (but the
+ first one should work with the Seagate driver):
- FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90
-
- THIS WILL *NOT* WORK WITH THIS DRIVER!
-
- Here is another BIOS signature for yet another Future
- Domain board WHICH WILL *NOT* WORK WITH THIS DRIVER:
+ FUTURE DOMAIN COPR. (C) 1986-1989 V6.0A7/28/90
FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90
- Here is another BIOS signature for the TMC-88x series:
-
- FUTURE DOMAIN COPR. (C) 1986-1989 V6.0A7/28/90
-
- THIS WILL *NOT* WORK WITH THIS DRIVER, but it *WILL*
- work with the *SEAGATE* ST-01/ST-02 driver.
+ FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90
*/
@@ -196,8 +179,7 @@ struct signature {
/* These functions are based on include/asm/io.h */
-#if 1
-static unsigned short inline inw( unsigned short port )
+inline static unsigned short inw( unsigned short port )
{
unsigned short _v;
@@ -206,25 +188,12 @@ static unsigned short inline inw( unsigned short port )
return _v;
}
-static void inline outw( unsigned short value, unsigned short port )
+inline static void outw( unsigned short value, unsigned short port )
{
__asm__ volatile ("outw %0,%1"
::"a" ((unsigned short) value),
"d" ((unsigned short) port));
}
-#else
-
-#define inw( port ) \
- ({ unsigned short _v; \
- __asm__ volatile ("inw %1,%0" \
- : "=a" (_v) : "d" ((unsigned short) port)); \
- _v; })
-
-#define outw( value ) \
- __asm__ volatile \
- ("outw %0,%1" : : "a" ((unsigned short) value), \
- "d" ((unsigned short) port))
-#endif
/* These defines are copied from kernel/blk_drv/hd.c */
@@ -233,7 +202,7 @@ static void inline outw( unsigned short value, unsigned short port )
__asm__ volatile \
( "cld;rep;insw"::"d" (port),"D" (buf),"c" (count):"cx","di" )
-#define outsw( buf, count, port) \
+#define outsw( buf, count, port ) \
__asm__ volatile \
("cld;rep;outsw"::"d" (port),"S" (buf),"c" (count):"cx","si")
@@ -245,11 +214,11 @@ static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
while (jiffies < the_time);
}
-static void inline fdomain_make_bus_idle( void )
+inline static void fdomain_make_bus_idle( void )
{
outb( 0, SCSI_Cntl_port );
outb( 0, Data_Mode_Cntl_port );
- outb( 1, TMC_Cntl_port );
+ outb( 1 | PARITY_MASK, TMC_Cntl_port );
}
static int fdomain_is_valid_port( int port )
@@ -278,7 +247,7 @@ static int fdomain_is_valid_port( int port )
Now, check to be sure the bios_base matches these ports.
If someone was unlucky enough to have purchased more than one
Future Domain board, then they will have to modify this code, as
- we only detect one board here. [The one with the lowest bios_base].
+ we only detect one board here. [The one with the lowest bios_base.]
*/
options = inb( port + Option_Select );
@@ -306,45 +275,20 @@ static int fdomain_test_loopback( void )
return 0;
}
-#if !NEW_IRQ
-static void fdomain_enable_interrupt( void )
-{
- if (!interrupt_level) return;
-
-#if ALLOW_ALL_IRQ
- if (interrupt_level < 8) {
- outb( inb_p( 0x21 ) & ~(1 << interrupt_level), 0x21 );
- } else
-#endif
- {
- outb( inb_p( 0xa1 ) & ~(1 << (interrupt_level - 8)), 0xa1 );
- }
-}
-
-static void fdomain_disable_interrupt( void )
-{
- if (!interrupt_level) return;
-
-#if ALLOW_ALL_IRQ
- if (interrupt_level < 8) {
- outb( inb_p( 0x21 ) | (1 << interrupt_level), 0x21 );
- } else
-#endif
- {
- outb( inb_p( 0xa1 ) | (1 << (interrupt_level - 8)), 0xa1 );
- }
-}
-#endif
-
int fdomain_16x0_detect( int hostnum )
{
- int i, j;
- int flag;
- unsigned char do_inquiry[] = { 0x12, 0, 0, 0, 255, 0 };
- unsigned char do_request_sense[] = { 0x03, 0, 0, 0, 255, 0 };
- unsigned char do_read_capacity[] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned char buf[256];
- unsigned retcode;
+ int i, j;
+ int flag;
+ struct sigaction sa;
+ int retcode;
+#if DO_DETECT
+ const int buflen = 255;
+ Scsi_Cmnd SCinit;
+ unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 };
+ unsigned char do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 };
+ unsigned char do_read_capacity[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ unsigned char buf[buflen];
+#endif
#if DEBUG_DETECT
printk( "SCSI: fdomain_16x0_detect()," );
@@ -371,7 +315,7 @@ int fdomain_16x0_detect( int hostnum )
/* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM.
Assuming the ROM is enabled (otherwise we wouldn't have been
- able to read the ROM signature :-), then the ROM set up the
+ able to read the ROM signature :-), then the ROM sets up the
RAM area with some magic numbers, such as a list of port
base addresses and a list of the disk "geometry" reported to
DOS (this geometry has nothing to do with physical geometry).
@@ -400,6 +344,7 @@ int fdomain_16x0_detect( int hostnum )
#if DEBUG_DETECT
printk( " RAM FAILED, " );
#endif
+
/* Anyway, the alternative to finding the address in the RAM is
to just search through every possible port address for one
that is attached to the Future Domain card. Don't panic,
@@ -431,10 +376,10 @@ int fdomain_16x0_detect( int hostnum )
#endif
if (interrupt_level) {
- printk( "Future Domain BIOS at %x; port base at %x; using IRQ %d\n",
+ printk( "Future Domain: BIOS at %x; port base at %x; using IRQ %d\n",
(unsigned)bios_base, port_base, interrupt_level );
} else {
- printk( "Future Domain BIOS at %x; port base at %x; *NO* IRQ\n",
+ printk( "Future Domain: BIOS at %x; port base at %x; *NO* IRQ\n",
(unsigned)bios_base, port_base );
}
@@ -450,7 +395,7 @@ int fdomain_16x0_detect( int hostnum )
Write_FIFO_port = port_base + Write_FIFO;
Write_SCSI_Data_port = port_base + Write_SCSI_Data;
- fdomain_16x0_reset();
+ fdomain_16x0_reset();
if (fdomain_test_loopback()) {
#if DEBUG_DETECT
@@ -459,92 +404,102 @@ int fdomain_16x0_detect( int hostnum )
return 0;
}
- /* These routines are here because of the way the SCSI bus behaves
- after a reset. This appropriate behavior was not handled correctly
- by the higher level SCSI routines when I first wrote this driver.
+#if DO_DETECT
+
+ /* These routines are here because of the way the SCSI bus behaves after
+ a reset. This appropriate behavior was not handled correctly by the
+ higher level SCSI routines when I first wrote this driver. Now,
+ however, correct scan routines are part of scsi.c and these routines
+ are no longer needed. However, this code is still good for
+ debugging.
*/
-
+
+ SCinit.request_buffer = SCinit.buffer = buf;
+ SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
+ SCinit.use_sg = 0;
+ SCinit.lun = 0;
+
printk( "Future Domain detection routine scanning for devices:\n" );
for (i = 0; i < 8; i++) {
+ SCinit.target = i;
if (i == 6) continue; /* The host adapter is at SCSI ID 6 */
- retcode = fdomain_16x0_command( i, do_request_sense, buf, 255 );
+ memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
+ retcode = fdomain_16x0_command(&SCinit);
if (!retcode) {
- retcode = fdomain_16x0_command( i, do_inquiry, buf, 255 );
+ memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
+ retcode = fdomain_16x0_command(&SCinit);
if (!retcode) {
printk( " SCSI ID %d: ", i );
- for (j = 8; j < 32; j++) printk( "%c", buf[j] );
- retcode = fdomain_16x0_command( i, do_read_capacity, buf, 255 );
+ for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
+ printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
+ memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
+ retcode = fdomain_16x0_command(&SCinit);
if (!retcode) {
unsigned long blocks, size, capacity;
blocks = (buf[0] << 24) | (buf[1] << 16)
| (buf[2] << 8) | buf[3];
size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
- capacity = +(blocks * size * 10) / +(1024L * 1024L);
+ capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
printk( "%lu MB (%lu byte blocks)",
((capacity + 5L) / 10L), size );
+ } else {
+ memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
+ retcode = fdomain_16x0_command(&SCinit);
}
printk ("\n" );
+ } else {
+ memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
+ retcode = fdomain_16x0_command(&SCinit);
}
}
}
-
-#if QUEUE
-#if !ALLOW_ALL_IRQ
- if (interrupt_level < 8) {
- printk( "Future Domain: WILL NOT USE IRQ LESS THAN 8 FOR QUEUEING!\n" );
- scsi_hosts[hostnum].can_queue = 0;
- } else
#endif
-#if NEW_IRQ
- {
- int retcode;
- struct sigaction sa;
- this_host = hostnum;
-
- sa.sa_handler = fdomain_16x0_intr;
- sa.sa_flags = SA_INTERRUPT;
- sa.sa_mask = 0;
- sa.sa_restorer = NULL;
-
- retcode = irqaction( interrupt_level, &sa );
+ this_host = hostnum;
+
+ if (!QUEUE || !interrupt_level) {
+ printk( "Future Domain: *NO* interrupt level selected!\n" );
+ printk( " COMMAND QUEUEING DISABLED!\n" );
+ can_queue = scsi_hosts[this_host].can_queue = 0;
+ scsi_hosts[this_host].sg_tablesize = SG_NONE;
+ } else {
+ /* Register the IRQ with the kernel */
- if (retcode < 0) {
- if (retcode == -EINVAL) {
- printk( "Future Domain: IRQ %d is bad!\n", interrupt_level );
- printk( " This shouldn't happen: REPORT TO RIK!\n" );
- } else if (retcode == -EBUSY) {
- printk( "Future Domain: IRQ %d is already in use!\n",
- interrupt_level );
- printk( " Please use another IRQ for the FD card!\n" );
- } else {
- printk( "Future Domain: Error getting IRQ %d\n",
- interrupt_level );
- printk( " This shouldn't happen: REPORT TO RIK!\n" );
- }
- printk( " IRQs WILL NOT BE USED!\n" );
-
- scsi_hosts[this_host].can_queue = 0;
- } else {
- printk( "Future Domain: IRQ %d selected with retcode = %d\n",
- interrupt_level, retcode );
- }
- }
-#else
- {
- this_host = hostnum;
- set_intr_gate( 0x20 + interrupt_level, &fdomain_16x0_interrupt );
- fdomain_enable_interrupt();
+ sa.sa_handler = fdomain_16x0_intr;
+ sa.sa_flags = SA_INTERRUPT;
+ sa.sa_mask = 0;
+ sa.sa_restorer = NULL;
+
+ retcode = irqaction( interrupt_level, &sa );
+
+ if (retcode < 0) {
+ if (retcode == -EINVAL) {
+ printk( "Future Domain: IRQ %d is bad!\n", interrupt_level );
+ printk( " This shouldn't happen: REPORT TO RIK!\n" );
+ } else if (retcode == -EBUSY) {
+ printk( "Future Domain: IRQ %d is already in use!\n",
+ interrupt_level );
+ printk( " Please use another IRQ for the FD card!\n" );
+ } else {
+ printk( "Future Domain: Error getting IRQ %d\n", interrupt_level );
+ printk( " This shouldn't happen: REPORT TO RIK!\n" );
}
-#endif
-#endif
-
+ printk( " COMMAND QUEUEING DISABLED!\n" );
+
+ can_queue = scsi_hosts[this_host].can_queue = 0;
+ scsi_hosts[this_host].sg_tablesize = SG_NONE;
+ } else {
+ printk( "Future Domain: IRQ %d requested from kernel\n",
+ interrupt_level );
+ }
+ }
+
return 1;
}
-char *fdomain_16x0_info(void)
+const char *fdomain_16x0_info(void)
{
static char buffer[] =
"Future Domain TMC-1660/TMC-1680 SCSI driver version "
@@ -558,13 +513,13 @@ static int fdomain_arbitrate( void )
int status = 0;
unsigned long timeout;
-#if VERBOSE
+#if EVERY_ACCESS
printk( "SCSI: fdomain_arbitrate()\n" );
#endif
outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */
outb( 0x40, port_base + SCSI_Data_NoACK ); /* Set our id bit */
- outb( 0x04, TMC_Cntl_port ); /* Start arbitration */
+ outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
timeout = jiffies + 50; /* 500 mS */
while (jiffies < timeout) {
@@ -579,7 +534,8 @@ static int fdomain_arbitrate( void )
printk( "Arbitration failed, status = %x\n", status );
#endif
#if ERRORS_ONLY
- printk( "SCSI: Arbitration failed, status = %x", status );
+ printk( "SCSI (Future Domain): Arbitration failed, status = %x",
+ status );
#endif
return 1;
}
@@ -589,50 +545,37 @@ static int fdomain_select( int target )
int status;
unsigned long timeout;
- outb( 0x80, SCSI_Cntl_port ); /* Bus Enable */
- outb( 0x8a, SCSI_Cntl_port ); /* Bus Enable + Attention + Select */
-
/* Send our address OR'd with target address */
-#if SEND_IDENTIFY
outb( 0x40 | (1 << target), port_base + SCSI_Data_NoACK );
-#else
- outb( (1 << target), port_base + SCSI_Data_NoACK );
-#endif
- /* Stop arbitration (also set FIFO for output and enable parity) */
- outb( 0xc8, TMC_Cntl_port );
+ if (RESELECTION && can_queue)
+ outb( 0x8a, SCSI_Cntl_port ); /* Bus Enable + Attention + Select */
+ else
+ outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
+
+ /* Stop arbitration (also set FIFO for output and enable parity) */
+ outb( 0xc0 | PARITY_MASK, TMC_Cntl_port );
timeout = jiffies + 25; /* 250mS */
while (jiffies < timeout) {
status = inb( SCSI_Status_port ); /* Read adapter status */
if (status & 1) { /* Busy asserted */
/* Enable SCSI Bus (on error, should make bus idle with 0) */
-#if SEND_IDENTIFY
- /* Also, set ATN so that the drive will make a MESSAGE OUT phase */
- outb( 0x88, SCSI_Cntl_port );
-#else
outb( 0x80, SCSI_Cntl_port );
-#endif
return 0;
}
}
/* Make bus idle */
fdomain_make_bus_idle();
#if EVERY_ACCESS
- if (!target) printk( "Select failed\n" );
+ if (!target) printk( "Selection failed\n" );
#endif
#if ERRORS_ONLY
- if (!target) printk( "SCSI: Select failed" );
+ if (!target) printk( "SCSI (Future Domain): Selection failed" );
#endif
return 1;
}
-#if QUEUE
-
-#if !USE_FIFO
-#pragma error QUEUE requires USE_FIFO
-#endif
-
void my_done( int error )
{
if (in_command) {
@@ -640,26 +583,21 @@ void my_done( int error )
in_interrupt_code = 0;
outb( 0x00, Interrupt_Cntl_port );
fdomain_make_bus_idle();
- if (current_done) current_done( this_host, error );
- else panic( "SCSI (Future Domain): current_done() == NULL" );
+ current_SC->result = error;
+ if (current_SC->scsi_done) current_SC->scsi_done( current_SC );
+ else panic( "SCSI (Future Domain): current_SC->scsi_done() == NULL" );
} else {
panic( "SCSI (Future Domain): my_done() called outside of command\n" );
}
}
-#if NEW_IRQ
void fdomain_16x0_intr( int unused )
-#else
-void fdomain_16x0_intr( void )
-#endif
{
int status;
int done = 0;
unsigned data_count;
-#if NEW_IRQ
sti();
-#endif
if (in_interrupt_code)
panic( "SCSI (Future Domain): fdomain_16x0_intr() NOT REENTRANT!\n" );
@@ -668,124 +606,163 @@ void fdomain_16x0_intr( void )
outb( 0x00, Interrupt_Cntl_port );
+ if (current_SC->SCp.phase & aborted) {
#if EVERY_ACCESS
- printk( "aborted = %d, ", aborted );
-#endif
-
- if (aborted) {
- /* Force retry for timeouts after selection complete */
- if (current_phase == in_other)
- my_done( DID_BUS_BUSY << 16 );
+ if (current_SC->SCp.phase & (in_other || disconnect))
+ printk( "aborted (%s) = %d, ",
+ current_SC->SCp.phase & in_other
+ ? "in_other" : "disconnect",
+ current_SC->result );
else
- my_done( aborted << 16 );
-#if NEW_IRQ && !DECREASE_IL
- cli();
+ printk( "aborted = %d, ",
+ current_SC->result );
#endif
+ /* Force retry for timeouts after selection complete */
+ if (current_SC->SCp.phase & (in_other || disconnect)) {
+ fdomain_16x0_reset();
+ my_done( DID_RESET << 16 );
+ } else {
+ my_done( current_SC->result << 16 );
+ }
return;
}
/* We usually have one spurious interrupt after each command. Ignore it. */
if (!in_command) { /* Spurious interrupt */
in_interrupt_code = 0;
-#if NEW_IRQ && !DECREASE_IL
- cli();
-#endif
return;
}
-
- if (current_phase == in_arbitration) {
+
+#if RESELECTION
+ if (current_SC->SCp.phase & disconnect) {
+ printk( " RECON %x ", inb( port_base + SCSI_Data_NoACK ) );
+ current_SC->SCp.phase = in_other;
+ outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
+ outb( 0x84, SCSI_Cntl_port );
+ while ( (status = inb( SCSI_Status_port )) & 0x20 ) {
+ printk( "s = %x, ", status );
+ }
+ outb( 0x80, SCSI_Cntl_port );
+ } else
+#endif
+ if (current_SC->SCp.phase & in_arbitration) {
status = inb( TMC_Status_port ); /* Read adapter status */
if (!(status & 0x02)) {
#if EVERY_ACCESS
printk( " AFAIL " );
#endif
- my_done( DID_TIME_OUT << 16 );
-#if NEW_IRQ && !DECREASE_IL
- cli();
-#endif
+ my_done( DID_BUS_BUSY << 16 );
return;
}
- current_phase = in_selection;
+ current_SC->SCp.phase = in_selection;
- outb( 0x80, SCSI_Cntl_port ); /* Bus Enable */
- outb( 0x8a, SCSI_Cntl_port ); /* Bus Enable + Attention + Select */
-
- outb( (1 << current_target), port_base + SCSI_Data_NoACK );
+ outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
+
+ outb( 0x40 | (1 << current_SC->target), port_base + SCSI_Data_NoACK );
+
+#if RESELECTION
+ outb( 0x8a, SCSI_Cntl_port ); /* Bus Enable + Attention + Select */
+#else
+ outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
+#endif
- outb( 0x40, Interrupt_Cntl_port );
/* Stop arbitration (also set FIFO for output and enable parity) */
+ outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
+
in_interrupt_code = 0;
- outb( 0xd8, TMC_Cntl_port );
-#if NEW_IRQ && !DECREASE_IL
- cli();
-#endif
return;
- } else if (current_phase == in_selection) {
+ } else if (current_SC->SCp.phase & in_selection) {
status = inb( SCSI_Status_port );
if (!(status & 0x01)) {
+ /* Try again, for slow devices */
+ if (fdomain_select( current_SC->target )) {
#if EVERY_ACCESS
- printk( " SFAIL " );
+ printk( " SFAIL " );
#endif
- my_done( DID_NO_CONNECT << 16 );
-#if NEW_IRQ && !DECREASE_IL
- cli();
+ my_done( DID_NO_CONNECT << 16 );
+ return;
+ }
+#if EVERY_ACCESS
+ else printk( " AltSel " );
#endif
- return;
}
- current_phase = in_other;
-#if FAST_SYNCH
- outb( 0xc0, Data_Mode_Cntl_port );
-#endif
+ current_SC->SCp.phase = in_other;
in_interrupt_code = 0;
- outb( 0x90, Interrupt_Cntl_port );
+ outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
+#if RESELECTION
+ outb( 0x88, SCSI_Cntl_port );
+#else
outb( 0x80, SCSI_Cntl_port );
-#if NEW_IRQ && !DECREASE_IL
- cli();
#endif
return;
}
- /* current_phase == in_other: this is the body of the routine */
+ /* current_SC->SCp.phase == in_other: this is the body of the routine */
- switch ((unsigned char)*the_command) {
+ switch (current_SC->cmnd[0]) {
case 0x04: case 0x07: case 0x0a: case 0x15: case 0x2a:
case 0x2e: case 0x3b: case 0xea: case 0x3f:
- data_count = 0x2000 - inw( FIFO_Data_Count_port );
- if (current_bufflen - data_sent < data_count)
- data_count = current_bufflen - data_sent;
- if (data_count > 0) {
-/* if (data_count > 512) data_count = 512; */
+ while ( (data_count = 0x2000 - inw( FIFO_Data_Count_port )) > 512 ) {
#if EVERY_ACCESS
- printk( "%d OUT, ", data_count );
+ printk( "DC=%d, ", data_count );
#endif
- if (data_count == 1) {
- outb( *out_buf_pt++, Write_FIFO_port );
- ++data_sent;
- } else {
- data_count >>= 1;
- outsw( out_buf_pt, data_count, Write_FIFO_port );
- out_buf_pt += 2 * data_count;
- data_sent += 2 * data_count;
+ if (data_count > current_SC->SCp.this_residual)
+ data_count = current_SC->SCp.this_residual;
+ if (data_count > 0) {
+#if EVERY_ACCESS
+ printk( "%d OUT, ", data_count );
+#endif
+ if (data_count == 1) {
+ outb( *current_SC->SCp.ptr++, Write_FIFO_port );
+ --current_SC->SCp.this_residual;
+ } else {
+ data_count >>= 1;
+ outsw( current_SC->SCp.ptr, data_count, Write_FIFO_port );
+ current_SC->SCp.ptr += 2 * data_count;
+ current_SC->SCp.this_residual -= 2 * data_count;
+ }
+ }
+ if (!current_SC->SCp.this_residual) {
+ if (current_SC->SCp.buffers_residual) {
+ --current_SC->SCp.buffers_residual;
+ ++current_SC->SCp.buffer;
+ current_SC->SCp.ptr = current_SC->SCp.buffer->address;
+ current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
+ } else
+ break;
}
}
break;
default:
- if (!have_data_in) {
- outb( 0x98, TMC_Cntl_port );
- ++have_data_in;
+ if (!current_SC->SCp.have_data_in) {
+ outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
+ ++current_SC->SCp.have_data_in;
} else {
- data_count = inw( FIFO_Data_Count_port );
-/* if (data_count > 512) data_count = 512; */
- if (data_count) {
+ while ((data_count = inw( FIFO_Data_Count_port )) != 0) {
#if EVERY_ACCESS
- printk( "%d IN, ", data_count );
+ printk( "DC=%d, ", data_count );
#endif
- if (data_count == 1) {
- *in_buf_pt++ = inb( Read_FIFO_port );
- } else {
- data_count >>= 1; /* Number of words */
- insw( in_buf_pt, data_count, Read_FIFO_port );
- in_buf_pt += 2 * data_count;
+ if (data_count > current_SC->SCp.this_residual)
+ data_count = current_SC->SCp.this_residual;
+ if (data_count) {
+#if EVERY_ACCESS
+ printk( "%d IN, ", data_count );
+#endif
+ if (data_count == 1) {
+ *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
+ --current_SC->SCp.this_residual;
+ } else {
+ data_count >>= 1; /* Number of words */
+ insw( current_SC->SCp.ptr, data_count, Read_FIFO_port );
+ current_SC->SCp.ptr += 2 * data_count;
+ current_SC->SCp.this_residual -= 2 * data_count;
+ }
+ }
+ if (!current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) {
+ --current_SC->SCp.buffers_residual;
+ ++current_SC->SCp.buffer;
+ current_SC->SCp.ptr = current_SC->SCp.buffer->address;
+ current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
}
}
}
@@ -798,41 +775,73 @@ void fdomain_16x0_intr( void )
switch (status & 0x0e) {
case 0x08: /* COMMAND OUT */
- outb( *cmd_pt++, Write_SCSI_Data_port );
+#if 0
+ if (!current_SC->SCp.sent_command) {
+ int i;
+
+ ++current_SC->SCp.sent_command;
+
+ for (i = 0; i < COMMAND_SIZE( current_SC->cmnd[0] ); i++) {
+ outb( current_SC->cmnd[i], Write_SCSI_Data_port );
+#if EVERY_ACCESS
+ printk( "CMD = %x,", current_SC->cmnd[i] );
+#endif
+ }
+ }
+#else
+ outb( current_SC->cmnd[current_SC->SCp.sent_command++],
+ Write_SCSI_Data_port );
#if EVERY_ACCESS
- printk( "CMD = %x,", (unsigned char)cmd_pt[-1] );
+ printk( "CMD = %x,",
+ current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
+#endif
+
#endif
break;
case 0x0c: /* STATUS IN */
- Status = inb( Read_SCSI_Data_port );
+ current_SC->SCp.Status = inb( Read_SCSI_Data_port );
#if EVERY_ACCESS
- printk( "Status = %x, ", Status );
+ printk( "Status = %x, ", current_SC->SCp.Status );
#endif
#if ERRORS_ONLY
- if (Status) {
- printk( "SCSI: target = %d, command = %x, Status = %x\n",
- current_target, (unsigned char)*the_command, Status );
+ if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {
+ printk( "SCSI (Future Domain): target = %d, command = %x, Status = %x\n",
+ current_SC->target, current_SC->cmnd[0], current_SC->SCp.Status );
}
#endif
break;
case 0x0a: /* MESSAGE OUT */
-#if SEND_IDENTIFY
- /* On the first request, send an Identify message */
- if (!sent_identify) {
- outb( 0x80, SCSI_Cntl_port ); /* Lower ATN */
- outb( 0x80, Write_SCSI_Data_port ); /* Identify */
- ++sent_identify;
+#if RESELECTION
+ if (!(current_SC->SCp.phase & sent_ident)) {
+#if EVERY_ACCESS
+ printk( " IDENT " );
+#endif
+ outb( 0x80, SCSI_Cntl_port );
+ outb( IDENTIFY( 1, 0 ), Write_SCSI_Data_port );
+ current_SC->SCp.phase |= sent_ident;
} else
#else
- outb( 0x07, Write_SCSI_Data_port ); /* Reject */
+ outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */
#endif
break;
case 0x0e: /* MESSAGE IN */
- Message = inb( Read_SCSI_Data_port );
+ current_SC->SCp.Message = inb( Read_SCSI_Data_port );
#if EVERY_ACCESS
- printk( "Message = %x, ", Message );
+ printk( "Message = %x, ", current_SC->SCp.Message );
+#endif
+ if (!current_SC->SCp.Message) ++done;
+#if RESELECTION
+ if (current_SC->SCp.Message == DISCONNECT) {
+ printk( " DISCON " );
+ current_SC->SCp.phase = disconnect;
+ }
+#endif
+#if DEBUG_MESSAGES || EVERY_ACCESS
+ if (current_SC->SCp.Message) {
+ printk( "SCSI (Future Domain): Message = %x\n",
+ current_SC->SCp.Message );
+ }
#endif
- if (!Message) ++done;
break;
}
}
@@ -842,14 +851,32 @@ void fdomain_16x0_intr( void )
printk( " ** IN DONE ** " );
#endif
- if (have_data_in) {
- while (data_count = inw( FIFO_Data_Count_port )) {
- if (data_count == 1) {
- *in_buf_pt++ = inb( Read_FIFO_port );
- } else {
- data_count >>= 1; /* Number of words */
- insw( in_buf_pt, data_count, Read_FIFO_port );
- in_buf_pt += 2 * data_count;
+ if (current_SC->SCp.have_data_in) {
+ while ((data_count = inw( FIFO_Data_Count_port )) != 0) {
+ if (data_count > current_SC->SCp.this_residual)
+ data_count = current_SC->SCp.this_residual;
+
+ if (data_count) {
+#if EVERY_ACCESS
+ printk( "%d IN, ", data_count );
+#endif
+ if (data_count == 1) {
+ *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
+ --current_SC->SCp.this_residual;
+ } else {
+ data_count >>= 1; /* Number of words */
+ insw( current_SC->SCp.ptr, data_count, Read_FIFO_port );
+ current_SC->SCp.this_residual -= 2 * data_count;
+ }
+ }
+
+ if (!current_SC->SCp.this_residual
+ && current_SC->SCp.buffers_residual) {
+
+ --current_SC->SCp.buffers_residual;
+ ++current_SC->SCp.buffer;
+ current_SC->SCp.ptr = current_SC->SCp.buffer->address;
+ current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
}
}
}
@@ -858,79 +885,103 @@ void fdomain_16x0_intr( void )
#endif
#if ERRORS_ONLY
- if (*the_command == REQUEST_SENSE && !Status) {
- if ((unsigned char)(*((char *)current_buff + 2)) & 0x0f) {
- printk( "SCSI REQUEST SENSE: Sense Key = %x, Sense Code = %x\n",
- (unsigned char)(*((char *)current_buff + 2)) & 0x0f,
- (unsigned char)(*((char *)current_buff + 12)) );
+ if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
+ if ((unsigned char)(*((char *)current_SC->request_buffer + 2)) & 0x0f) {
+ unsigned char key;
+ unsigned char code;
+
+ key = (unsigned char)(*((char *)current_SC->request_buffer + 2)) & 0x0f;
+ code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
+
+ if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
+ && !(key == ILLEGAL_REQUEST && (code == 0x25 || !code)))
+
+ printk( "SCSI REQUEST SENSE: Sense Key = %x, Sense Code = %x\n",
+ key, code );
}
}
#endif
#if EVERY_ACCESS
- printk( "BEFORE MY_DONE\n" );
+ printk( "BEFORE MY_DONE. . ." );
+#endif
+ my_done( (current_SC->SCp.Status & 0xff) | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
+#if EVERY_ACCESS
+ printk( "RETURNING.\n" );
#endif
- my_done( (Status & 0xff) | ((Message & 0xff) << 8) | (DID_OK << 16) );
+
} else {
in_interrupt_code = 0;
- outb( 0x90, Interrupt_Cntl_port );
+ if (current_SC->SCp.phase & disconnect) {
+ outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
+ outb( 0x00, SCSI_Cntl_port );
+ } else {
+ outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
+ }
}
-#if NEW_IRQ && !DECREASE_IL
- cli();
-#endif
return;
}
-int fdomain_16x0_queue( unsigned char target, const void *cmnd,
- void *buff, int bufflen, void (*done)(int,int) )
+int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
{
if (in_command) {
panic( "SCSI (Future Domain): fdomain_16x0_queue() NOT REENTRANT!\n" );
}
#if EVERY_ACCESS
- printk( "queue %d %x\n", target, *(unsigned char *)cmnd );
+ printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
+ SCpnt->target,
+ *(unsigned char *)SCpnt->cmnd,
+ SCpnt->use_sg,
+ SCpnt->request_bufflen );
#endif
fdomain_make_bus_idle();
- aborted = 0;
- current_target = target;
- memcpy( current_cmnd, cmnd, ((*(unsigned char *)cmnd) <= 0x1f ? 6 : 10 ) );
- current_buff = buff;
- current_bufflen = bufflen;
- current_done = done;
+ current_SC = SCpnt; /* Save this for the done function */
+ current_SC->scsi_done = done;
/* Initialize static data */
- cmd_pt = current_cmnd;
- the_command = current_cmnd;
- out_buf_pt = current_buff;
- in_buf_pt = current_buff;
+
+ if (current_SC->use_sg) {
+ current_SC->SCp.buffer =
+ (struct scatterlist *)current_SC->request_buffer;
+ current_SC->SCp.ptr = current_SC->SCp.buffer->address;
+ current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
+ current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
+ } else {
+ current_SC->SCp.ptr = current_SC->request_buffer;
+ current_SC->SCp.this_residual = current_SC->request_bufflen;
+ current_SC->SCp.buffer = NULL;
+ current_SC->SCp.buffers_residual = 0;
+ }
+
- Status = 0;
- Message = 0;
- data_sent = 0;
- have_data_in = 0;
+ current_SC->SCp.Status = 0;
+ current_SC->SCp.Message = 0;
+ current_SC->SCp.have_data_in = 0;
+ current_SC->SCp.sent_command = 0;
+ current_SC->SCp.phase = in_arbitration;
/* Start arbitration */
- current_phase = in_arbitration;
outb( 0x00, Interrupt_Cntl_port );
outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */
outb( 0x40, port_base + SCSI_Data_NoACK ); /* Set our id bit */
++in_command;
outb( 0x20, Interrupt_Cntl_port );
- outb( 0x1c, TMC_Cntl_port ); /* Start arbitration */
+ outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
return 0;
}
-#endif
-int fdomain_16x0_command( unsigned char target, const void *cmnd,
- void *buff, int bufflen )
+int fdomain_16x0_command( Scsi_Cmnd *SCpnt )
{
- const char *cmd_pt = cmnd;
- const char *the_command = cmnd;
- unsigned char *out_buf_pt = buff;
- unsigned char *in_buf_pt = buff;
+ const char *cmd_pt = SCpnt->cmnd;
+ const char *the_command = SCpnt->cmnd;
+ unsigned char *out_buf_pt = SCpnt->request_buffer;
+ unsigned char *in_buf_pt = SCpnt->request_buffer;
+ unsigned char target = SCpnt->target;
+ void *buff = SCpnt->request_buffer;
+ int bufflen = SCpnt->request_bufflen;
int Status = 0;
int Message = 0;
int status;
@@ -938,12 +989,9 @@ int fdomain_16x0_command( unsigned char target, const void *cmnd,
unsigned long timeout;
unsigned data_sent = 0;
unsigned data_count;
-#if USE_FIFO
int have_data_in = 0;
-#endif
-#if SEND_IDENTITY
- int sent_identify = 0;
-#endif
+
+ current_SC = SCpnt;
#if EVERY_ACCESS
printk( "fdomain_command(%d, %x): ", target, (unsigned char)*the_command );
@@ -966,13 +1014,8 @@ int fdomain_16x0_command( unsigned char target, const void *cmnd,
}
timeout = jiffies + 500; /* 5000 mS -- For Maxtor after a RST */
- aborted = 0; /* How is this supposed to get reset??? */
-
-#if FAST_SYNCH
- outb( 0xc0, Data_Mode_Cntl_port );
-#endif
+ current_SC->SCp.phase = non_queueing;
-#if USE_FIFO
switch ((unsigned char)*the_command) {
case 0x04: case 0x07: case 0x0a: case 0x15: case 0x2a:
case 0x2e: case 0x3b: case 0xea: case 0x3f:
@@ -990,20 +1033,19 @@ int fdomain_16x0_command( unsigned char target, const void *cmnd,
}
break;
default:
- outb( 0x88, TMC_Cntl_port );
+ outb( 0x80 | PARITY_MASK, TMC_Cntl_port );
++have_data_in;
break;
}
-#endif
while (((status = inb( SCSI_Status_port )) & 1)
- && !done && !aborted && jiffies < timeout) {
+ && !done && !(current_SC->SCp.phase & aborted)
+ && jiffies < timeout) {
if (status & 0x10) { /* REQ */
switch (status & 0x0e) {
case 0x00: /* DATA OUT */
-#if USE_FIFO
data_count = 0x2000 - inw( FIFO_Data_Count_port );
if (bufflen - data_sent < data_count)
data_count = bufflen - data_sent;
@@ -1016,14 +1058,10 @@ int fdomain_16x0_command( unsigned char target, const void *cmnd,
out_buf_pt += 2 * data_count;
data_sent += 2 * data_count;
}
-#else
- outb( *out_buf_pt++, Write_SCSI_Data_port );
-#endif
break;
case 0x04: /* DATA IN */
-#if USE_FIFO
if (!have_data_in) {
- outb( 0x88, TMC_Cntl_port );
+ outb( 0x80 | PARITY_MASK, TMC_Cntl_port );
++have_data_in;
}
data_count = inw( FIFO_Data_Count_port );
@@ -1034,9 +1072,6 @@ int fdomain_16x0_command( unsigned char target, const void *cmnd,
insw( in_buf_pt, data_count, Read_FIFO_port );
in_buf_pt += 2 * data_count;
}
-#else
- *in_buf_pt++ = inb( Read_SCSI_Data_port );
-#endif
break;
case 0x08: /* COMMAND OUT */
outb( *cmd_pt++, Write_SCSI_Data_port );
@@ -1051,22 +1086,13 @@ int fdomain_16x0_command( unsigned char target, const void *cmnd,
#endif
#if ERRORS_ONLY
if (Status) {
- printk( "SCSI: target = %d, command = %x, Status = %x\n",
+ printk( "SCSI (Future Domain): target = %d, command = %x, Status = %x\n",
target, (unsigned char)*the_command, Status );
}
#endif
break;
case 0x0a: /* MESSAGE OUT */
-#if SEND_IDENTIFY
- /* On the first request, send an Identify message */
- if (!sent_identify) {
- outb( 0x80, SCSI_Cntl_port ); /* Lower ATN */
- outb( 0x80, Write_SCSI_Data_port ); /* Identify */
- ++sent_identify;
- } else
-#else
- outb( 0x07, Write_SCSI_Data_port ); /* Reject */
-#endif
+ outb( 0x07, Write_SCSI_Data_port ); /* Reject */
break;
case 0x0e: /* MESSAGE IN */
Message = inb( Read_SCSI_Data_port );
@@ -1074,6 +1100,7 @@ int fdomain_16x0_command( unsigned char target, const void *cmnd,
printk( "Message = %x, ", Message );
#endif
if (!Message) ++done;
+ if (Message == DISCONNECT) printk( "DISCONNECT\n" );
break;
}
}
@@ -1084,27 +1111,28 @@ int fdomain_16x0_command( unsigned char target, const void *cmnd,
printk( "Time out, status = %x\n", status );
#endif
#if ERRORS_ONLY
- printk( "SCSI: Time out, status = %x (target = %d, command = %x)\n",
+ printk( "SCSI (Future Domain): "
+ "Time out, status = %x (target = %d, command = %x)\n",
status, target, (unsigned char)*the_command );
#endif
fdomain_make_bus_idle();
return DID_BUS_BUSY << 16;
}
- if (aborted) {
+ if (current_SC->SCp.phase & aborted) {
#if EVERY_ACCESS
printk( "Aborted\n" );
#endif
-#if ONLY_ERRORS
- printk( "SCSI: Aborted (command = %x)\n", (unsigned char)*the_command );
+#if ERRORS_ONLY
+ printk( "SCSI (Future Domain): Aborted (command = %x)\n",
+ (unsigned char)*the_command );
#endif
fdomain_16x0_reset();
- return DID_ABORT << 16;
+ return DID_RESET << 16;
}
-#if USE_FIFO
if (have_data_in) {
- while (data_count = inw( FIFO_Data_Count_port )) {
+ while ((data_count = inw( FIFO_Data_Count_port )) != 0) {
if (data_count == 1) {
*in_buf_pt++ = inb( Read_FIFO_port );
} else {
@@ -1114,7 +1142,6 @@ int fdomain_16x0_command( unsigned char target, const void *cmnd,
}
}
}
-#endif
fdomain_make_bus_idle();
@@ -1135,100 +1162,90 @@ int fdomain_16x0_command( unsigned char target, const void *cmnd,
return (Status & 0xff) | ((Message & 0xff) << 8) | (DID_OK << 16);
}
-int fdomain_16x0_abort( int code )
+int fdomain_16x0_abort( Scsi_Cmnd *SCpnt, int code )
{
-#if EVERY_ACCESS
- printk( " ABORT " );
+#if EVERY_ACCESS || ERRORS_ONLY
+ printk( "SCSI (Future Domain): Abort " );
#endif
-#if QUEUE
cli();
if (!in_command) {
+#if EVERY_ACCESS || ERRORS_ONLY
+ printk( " (not in command)\n" );
+#endif
sti();
return 0;
+ } else {
+#if EVERY_ACCESS || ERRORS_ONLY
+ printk( " code = %d\n", code );
+#endif
}
- aborted = code ? code : DID_ABORT;
+ current_SC->SCp.phase |= aborted;
+
+ current_SC->result = code ? code : DID_ABORT;
sti();
- fdomain_make_bus_idle();
-#else
- aborted = code ? code : DID_ABORT;
+
+ /* Aborts are not done well. . . */
+#if 0
+ my_done( code << 16 );
#endif
-
return 0;
}
int fdomain_16x0_reset( void )
{
+#if ERRORS_ONLY
+ printk( "Future Domain: SCSI Bus Reset\n" );
+#endif
outb( 1, SCSI_Cntl_port );
do_pause( 2 );
outb( 0, SCSI_Cntl_port );
do_pause( 115 );
outb( 0, Data_Mode_Cntl_port );
- outb( 0, TMC_Cntl_port );
-
- aborted = DID_RESET;
-
+ outb( PARITY_MASK, TMC_Cntl_port );
return 0;
}
-#if QUEUE && !NEW_IRQ
-
-/* This is copied from kernel/sys_calls.s
- and from kernel/blk_drv/scsi/aha1542.c */
-
-__asm__("
-_fdomain_16x0_interrupt:
- cld
- push %gs
- push %fs
- push %es
- push %ds
- pushl %eax
- pushl %ebp
- pushl %edi
- pushl %esi
- pushl %edx
- pushl %ecx
- pushl %ebx
- movl $0x10,%edx
- mov %dx,%ds
- mov %dx,%es
- movl $0x17,%edx
- mov %dx,%fs
-
- movl $_fdomain_disable_interrupt,%edx
- call *%edx
-
- movb $0x20,%al
- outb %al,$0xA0 # EOI to interrupt controller #1
- jmp 1f # give port chance to breathe
-1: jmp 1f
-1: outb %al,$0x20
-
- sti
- movl $_fdomain_16x0_intr,%edx
- call *%edx # ``interesting'' way of handling intr.
- cli
-
- movl $_fdomain_enable_interrupt,%edx
- call *%edx
-
- popl %ebx
- popl %ecx
- popl %edx
- popl %esi
- popl %edi
- popl %ebp
- popl %eax
- pop %ds
- pop %es
- pop %fs
- pop %gs
- iret
-");
-#endif
+int fdomain_16x0_biosparam( int size, int dev, int *info )
+{
+ int drive;
+ struct drive_info {
+ unsigned short cylinders;
+ unsigned char heads;
+ unsigned char sectors;
+ } *i;
+
+ /* NOTES:
+ The RAM area starts at 0x1f00 from the bios_base address.
+ The drive parameter table seems to start at 0x1f30.
+ The first byte's purpose is not known.
+ Next is the cylinder, head, and sector information.
+ The last 4 bytes appear to be the drive's size in sectors.
+ The other bytes in the drive parameter table are unknown.
+ If anyone figures them out, please send me mail, and I will
+ update these notes.
+
+ Tape drives do not get placed in this table.
+
+ There is another table at 0x1fea:
+ If the byte is 0x01, then the SCSI ID is not in use.
+ If the byte is 0x18 or 0x48, then the SCSI ID is in use,
+ although tapes don't seem to be in this table. I haven't
+ seen any other numbers (in a limited sample).
+
+ 0x1f2d is a drive count (i.e., not including tapes)
+
+ The table at 0x1fcc are I/O ports addresses for the various
+ operations. I calculate these by hand in this driver code.
+ */
-#endif
+ drive = MINOR(dev) / 16;
+ i = (struct drive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
+ info[0] = i->heads;
+ info[1] = i->sectors;
+ info[2] = i->cylinders;
+ return 0;
+}
diff --git a/kernel/blk_drv/scsi/fdomain.h b/kernel/blk_drv/scsi/fdomain.h
index 40e4609..dea29a2 100644
--- a/kernel/blk_drv/scsi/fdomain.h
+++ b/kernel/blk_drv/scsi/fdomain.h
@@ -1,6 +1,6 @@
/* fdomain.h -- Header for Future Domain TMC-1660/TMC-1680 driver
* Created: Sun May 3 18:47:33 1992
- * Revised: Sat May 23 22:42:55 1992 by root
+ * Revised: Fri Nov 27 22:12:55 1992 by root
* Author: Rickard E. Faith, faith@cs.unc.edu
* Copyright 1992 Rickard E. Faith
* This program comes with ABSOLUTELY NO WARRANTY.
@@ -11,18 +11,13 @@
#ifndef _FDOMAIN_H
#define _FDOMAIN_H
-#define QUEUE 1 /* Enable command queueing */
-
int fdomain_16x0_detect( int );
-int fdomain_16x0_command( unsigned char target, const void *cmnd,
- void *buff, int bufflen);
-int fdomain_16x0_abort( int );
-char *fdomain_16x0_info( void );
+int fdomain_16x0_command( Scsi_Cmnd * );
+int fdomain_16x0_abort( Scsi_Cmnd *, int );
+const char *fdomain_16x0_info( void );
int fdomain_16x0_reset( void );
-
-#if QUEUE
-int fdomain_16x0_queue( unsigned char target, const void *cmnd,
- void *buff, int bufflen, void (*done)(int,int) );
+int fdomain_16x0_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) );
+int fdomain_16x0_biosparam( int, int, int * );
#define FDOMAIN_16X0 { "Future Domain TMC-1660/TMC-1680", \
fdomain_16x0_detect, \
@@ -31,15 +26,7 @@ int fdomain_16x0_queue( unsigned char target, const void *cmnd,
fdomain_16x0_queue, \
fdomain_16x0_abort, \
fdomain_16x0_reset, \
- 1, 6, 0 }
-#else
-#define FDOMAIN_16X0 { "Future Domain TMC-1660/TMC-1680", \
- fdomain_16x0_detect, \
- fdomain_16x0_info, \
- fdomain_16x0_command, \
NULL, \
- fdomain_16x0_abort, \
- fdomain_16x0_reset, \
- 0, 6, 0 ,0}
-#endif
+ fdomain_16x0_biosparam, \
+ 1, 6, 64 /* SG_NONE */, 1 ,0, 0}
#endif
diff --git a/kernel/blk_drv/scsi/hosts.c b/kernel/blk_drv/scsi/hosts.c
index b4f227c..93cc5cc 100644
--- a/kernel/blk_drv/scsi/hosts.c
+++ b/kernel/blk_drv/scsi/hosts.c
@@ -16,6 +16,7 @@
#include <linux/config.h>
#ifdef CONFIG_SCSI
+#include "../blk.h"
#include <linux/kernel.h>
#include "scsi.h"
@@ -27,12 +28,20 @@
#define MAX_SCSI_HOSTS
#endif
+#ifndef MAX_SCSI_HOSTS
+ #include "max_hosts.h"
+#endif
+
#include "hosts.h"
#ifdef CONFIG_SCSI_AHA1542
#include "aha1542.h"
#endif
+#ifdef CONFIG_SCSI_AHA1740
+#include "aha1740.h"
+#endif
+
#ifdef CONFIG_SCSI_FUTURE_DOMAIN
#include "fdomain.h"
#endif
@@ -46,7 +55,11 @@
#endif
#ifdef CONFIG_SCSI_7000FASST
-#include "7000fasst.h"
+#include "wd7000.h"
+#endif
+
+#ifdef CONFIG_SCSI_DEBUG
+#include "scsi_debug.h"
#endif
/*
@@ -83,6 +96,10 @@ Scsi_Host scsi_hosts[] =
BLANKIFY(AHA1542),
#endif
+#ifdef CONFIG_SCSI_AHA1740
+ BLANKIFY(AHA1740),
+#endif
+
#ifdef CONFIG_SCSI_FUTURE_DOMAIN
BLANKIFY(FDOMAIN_16X0),
#endif
@@ -94,7 +111,10 @@ Scsi_Host scsi_hosts[] =
BLANKIFY(ULTRASTOR_14F),
#endif
#ifdef CONFIG_SCSI_7000FASST
- BLANKIFY(WD7000FASST),
+ BLANKIFY(WD7000),
+#endif
+#ifdef CONFIG_SCSI_DEBUG
+ BLANKIFY(SCSI_DEBUG),
#endif
};
@@ -116,7 +136,10 @@ void main (void)
volatile unsigned char host_busy[MAX_SCSI_HOSTS];
volatile int host_timeout[MAX_SCSI_HOSTS];
-volatile Scsi_Cmnd *host_queue[MAX_SCSI_HOSTS];
+int last_reset[MAX_SCSI_HOSTS];
+Scsi_Cmnd *host_queue[MAX_SCSI_HOSTS];
+struct wait_queue *host_wait[MAX_SCSI_HOSTS] = {NULL,}; /* For waiting until host available*/
+int max_scsi_hosts = MAX_SCSI_HOSTS; /* This is used by scsi.c */
void scsi_init(void)
{
@@ -133,7 +156,6 @@ void scsi_init(void)
*/
host_busy[i] = 0;
- host_timeout[i] = 0;
host_queue[i] = NULL;
if ((scsi_hosts[i].detect) && (scsi_hosts[i].present = scsi_hosts[i].detect(i)))
@@ -155,3 +177,46 @@ void main(void) {
printf("0\n");
}
#endif
+
+
+#ifndef CONFIG_BLK_DEV_SD
+unsigned long sd_init(unsigned long memory_start, unsigned long memory_end){
+ return memory_start;
+};
+unsigned long sd_init1(unsigned long memory_start, unsigned long memory_end){
+ return memory_start;
+};
+void sd_attach(Scsi_Device * SDp){
+};
+int NR_SD=-1;
+int MAX_SD=0;
+#endif
+
+
+#ifndef CONFIG_BLK_DEV_SR
+unsigned long sr_init(unsigned long memory_start, unsigned long memory_end){
+ return memory_start;
+};
+unsigned long sr_init1(unsigned long memory_start, unsigned long memory_end){
+ return memory_start;
+};
+void sr_attach(Scsi_Device * SDp){
+};
+int NR_SR=-1;
+int MAX_SR=0;
+#endif
+
+
+#ifndef CONFIG_BLK_DEV_ST
+unsigned long st_init(unsigned long memory_start, unsigned long memory_end){
+ return memory_start;
+};
+unsigned long st_init1(unsigned long memory_start, unsigned long memory_end){
+ return memory_start;
+};
+void st_attach(Scsi_Device * SDp){
+};
+int NR_ST=-1;
+int MAX_ST=0;
+#endif
+
diff --git a/kernel/blk_drv/scsi/hosts.h b/kernel/blk_drv/scsi/hosts.h
index 686aae3..e9485d7 100644
--- a/kernel/blk_drv/scsi/hosts.h
+++ b/kernel/blk_drv/scsi/hosts.h
@@ -4,47 +4,34 @@
* Drew Eckhardt
*
* <drew@colorado.edu>
+ *
+ * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to
+ * add scatter-gather, multiple outstanding request, and other
+ * enhancements.
*/
#ifndef _HOSTS_H
#define _HOSTS_H
-#ifndef MAX_SCSI_HOSTS
- #include "max_hosts.h"
-#endif
-
/*
$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/hosts.h,v 1.1 1992/07/24 06:27:38 root Exp root $
*/
/*
- The Scsi_Cmnd structure is used by scsi.c internally, and for communication with
- low level drivers that support multiple outstanding commands.
+ The Scsi_Host type has all that is needed to interface with a SCSI
+ host in a device independant matter.
*/
-typedef struct scsi_cmnd {
- int host;
- unsigned char target, lun;
- unsigned char cmnd[10];
- unsigned bufflen;
- void *buffer;
-
- unsigned char sense_cmnd[6];
- unsigned char *sense_buffer;
-
- unsigned flags;
-
- int retries;
- int allowed;
- int timeout_per_command, timeout_total, timeout;
-
- void (*done)(int,int);
- struct scsi_cmnd *next, *prev;
- } Scsi_Cmnd;
+#define SG_NONE 0
+#define SG_ALL 0xff
-/*
- The Scsi_Host type has all that is needed to interface with a SCSI
- host in a device independant matter.
+/* The various choices mean:
+ NONE: Self evident. Host adapter is not capable of scatter-gather.
+ ALL: Means that the host adapter module can do scatter-gather,
+ and that there is no limit to the size of the table to which
+ we scatter/gather data.
+ Anything else: Indicates the maximum number of chains that can be
+ used in one scatter-gather request.
*/
typedef struct
@@ -70,7 +57,7 @@ typedef struct
information the developer sees fit.
*/
- char *(* info)(void);
+ const char *(* info)(void);
/*
The command function takes a target, a command (this is a SCSI
@@ -84,8 +71,7 @@ typedef struct
3 mid level error return
*/
- int (* command)(unsigned char target, const void *cmnd,
- void *buff, int bufflen);
+ int (* command)(Scsi_Cmnd *);
/*
The QueueCommand function works in a similar manner
@@ -96,10 +82,8 @@ typedef struct
host adapter.
*/
- int (* queuecommand)(unsigned char target, const void *cmnd,
- void *buff, int bufflen, void (*done)(int,int));
+ int (* queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-
/*
Since the mid level driver handles time outs, etc, we want to
be able to abort the current command. Abort returns 0 if the
@@ -111,7 +95,7 @@ typedef struct
resetting the bus, etc. if necessary.
*/
- int (* abort)(int);
+ int (* abort)(Scsi_Cmnd *, int);
/*
The reset function will reset the SCSI bus. Any executing
@@ -119,25 +103,58 @@ typedef struct
*/
int (* reset)(void);
+ /*
+ This function is used to select synchronous communications,
+ which will result in a higher data throughput. Not implemented
+ yet.
+ */
+
+ int (* slave_attach)(int, int);
+ /*
+ This function determines the bios parameters for a given
+ harddisk. These tend to be numbers that are made up by
+ the host adapter. Parameters:
+ size, device number, list (heads, sectors, cylinders)
+ */
+
+ int (* bios_param)(int, int, int []);
/*
This determines if we will use a non-interrupt driven
or an interrupt driven scheme, It is set to the maximum number
of simulataneous commands a given host adapter will accept.
*/
-
int can_queue;
/*
In many instances, especially where disconnect / reconnect are
supported, our host also has an ID on the SCSI bus. If this is
- the case, then it must be reserved. Please set this_id to -1 if your settup is in single initiator mode, and the host lacks an
+ the case, then it must be reserved. Please set this_id to -1 if
+ your settup is in single initiator mode, and the host lacks an
ID.
*/
int this_id;
/*
+ This determines the degree to which the host adapter is capable
+ of scatter-gather.
+ */
+
+ short unsigned int sg_tablesize;
+
+ /*
+ True if this host adapter can make good use of linked commands.
+ This will allow more than one command to be queued to a given
+ unit on a given host. Set this to the maximum number of command
+ blocks to be provided for each device. Set this to 1 for one
+ command block per lun, 2 for two, etc. Do not set this to 0.
+ You should make sure that the host adapter will do the right thing
+ before you try setting this above 1.
+ */
+
+ short cmd_per_lun;
+ /*
present contains a flag as to weather we are present -
so we don't have to call detect multiple times.
*/
@@ -147,7 +164,6 @@ typedef struct
true if this host adapter uses unchecked DMA onto an ISA bus.
*/
unsigned unchecked_isa_dma:1;
-
} Scsi_Host;
/*
@@ -164,14 +180,15 @@ extern Scsi_Host scsi_hosts[];
*/
extern volatile unsigned char host_busy[];
-extern volatile int host_timeout[];
/*
This is the queue of currently pending commands for a given
SCSI host.
*/
-extern volatile Scsi_Cmnd *host_queue[];
+extern Scsi_Cmnd *host_queue[];
+
+extern struct wait_queue *host_wait[]; /* For waiting until host available*/
/*
scsi_init initializes the scsi hosts.
@@ -180,5 +197,5 @@ extern volatile Scsi_Cmnd *host_queue[];
void scsi_init(void);
-#define BLANK_HOST {"", 0, 0, 0, 0, 0, 0, 0, 0, 0}
+#define BLANK_HOST {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#endif
diff --git a/kernel/blk_drv/scsi/scsi.c b/kernel/blk_drv/scsi/scsi.c
index fd7457e..88d3364 100644
--- a/kernel/blk_drv/scsi/scsi.c
+++ b/kernel/blk_drv/scsi/scsi.c
@@ -8,41 +8,32 @@
* Bug correction thanks go to :
* Rik Faith <faith@cs.unc.edu>
* Tommy Thorn <tthorn>
- * Thomas Wuensche <tw@fgb1.fgb.mw.tu-meunchen.de>
+ * Thomas Wuensche <tw@fgb1.fgb.mw.tu-muenchen.de>
+ *
+ * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to
+ * add scatter-gather, multiple outstanding request, and other
+ * enhancements.
*/
-#include <linux/config.h>
-
-#ifdef CONFIG_SCSI
#include <asm/system.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h>
+#include "../blk.h"
#include "scsi.h"
#include "hosts.h"
-#ifdef CONFIG_BLK_DEV_SD
-#include "sd.h"
-#endif
-
-#ifdef CONFIG_BLK_DEV_ST
-#include "st.h"
-#endif
-
-#ifdef CONFIG_BLK_DEV_SR
-#include "sr.h"
-#endif
-
/*
static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/scsi.c,v 1.1 1992/07/24 06:27:38 root Exp root $";
*/
#define INTERNAL_ERROR (printk ("Internal error in file %s, line %d.\n", __FILE__, __LINE__), panic(""))
-static void scsi_done (int host, int result);
-static void update_timeout (void);
+static void scsi_done (Scsi_Cmnd *SCpnt);
+static int update_timeout (Scsi_Cmnd *, int);
static void print_inquiry(unsigned char *data);
+static void scsi_times_out (Scsi_Cmnd * SCpnt);
static int time_start;
static int time_elapsed;
@@ -55,9 +46,14 @@ static int time_elapsed;
*/
int NR_SCSI_DEVICES=0;
-Scsi_Device scsi_devices[MAX_SCSI_DEVICE];
-#define SENSE_LENGTH 255
+Scsi_Device * scsi_devices = NULL;
+
+static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0};
+
+/* We make this not static so that we can read the array with gdb. */
+/* static */ Scsi_Cmnd * last_cmnd = NULL;
+
/*
* As the scsi do command functions are inteligent, and may need to
* redo a command, we need to keep track of the last command
@@ -69,8 +65,7 @@ Scsi_Device scsi_devices[MAX_SCSI_DEVICE];
#define WAS_SENSE 0x04
#define IS_RESETTING 0x08
-static Scsi_Cmnd last_cmnd[MAX_SCSI_HOSTS];
-static int last_reset[MAX_SCSI_HOSTS];
+extern int last_reset[];
/*
* This is the number of clock ticks we should wait before we time out
@@ -99,6 +94,34 @@ static int last_reset[MAX_SCSI_HOSTS];
#define MIN_RESET_DELAY 25
#endif
+/* The following devices are known not to tolerate a lun != 0 scan for
+ one reason or another. Some will respond to all luns, others will
+ lock up. */
+
+ struct blist{
+ char * vendor;
+ char * model;
+ char * revision; /* Latest revision known to be bad. Not used yet */
+ };
+
+static struct blist blacklist[] =
+{{"TANDBERG","TDC 3600","U07"}, /* Locks up if polled for lun != 0 */
+ {"SEAGATE","ST296","921"}, /* Responds to all lun */
+ {"NEWBURY","NDR3380S","2.10"}, /* Responds to all lun */
+ {NULL, NULL, NULL}};
+
+static int blacklisted(char * response_data){
+ int i = 0;
+ for(i=0; 1; i++){
+ if(blacklist[i].vendor == NULL) return 0;
+ if(strncmp(blacklist[i].vendor, &response_data[8],
+ strlen(blacklist[i].vendor))) continue;
+ if(strncmp(blacklist[i].model, &response_data[16],
+ strlen(blacklist[i].model))) continue;
+ return 1;
+ };
+};
+
/*
* As the actual SCSI command runs in the background, we must set up a
* flag that tells scan_scsis() when the result it has is valid.
@@ -108,16 +131,15 @@ static int last_reset[MAX_SCSI_HOSTS];
* scsi_do_cmd() function.
*/
-volatile static int in_scan = 0;
+static volatile int in_scan = 0;
static int the_result;
-static unsigned char sense_buffer[SENSE_LENGTH];
-static void scan_scsis_done (int host, int result)
+static void scan_scsis_done (Scsi_Cmnd * SCpnt)
{
#ifdef DEBUG
- printk ("scan_scsis_done(%d, %06x)\n\r", host, result);
+ printk ("scan_scsis_done(%d, %06x)\n\r", SCpnt->host, SCpnt->result);
#endif
- the_result = result;
+ SCpnt->request.dev = 0xfffe;
}
/*
* Detecting SCSI devices :
@@ -128,236 +150,200 @@ static void scan_scsis_done (int host, int result)
*/
static void scan_scsis (void)
- {
- int host_nr , dev, lun, type, maxed, slave;
- static unsigned char scsi_cmd [12];
- static unsigned char scsi_result [256];
-
- ++in_scan;
-
- for (slave = host_nr = 0; host_nr < MAX_SCSI_HOSTS; ++host_nr,
- slave = 0)
- if (scsi_hosts[host_nr].present)
- {
- for (dev = 0; dev < 7; ++dev)
- if (scsi_hosts[host_nr].this_id != dev)
- #ifdef MULTI_LUN
- for (lun = 0; lun < 8; ++lun)
- {
- #else
- {
- lun = 0;
- #endif
-/*
- * Build an INQUIRY command block.
- */
-
- scsi_cmd[0] = INQUIRY;
- scsi_cmd[1] = (lun << 5) & 0xe0;
- scsi_cmd[2] = 0;
- scsi_cmd[3] = 0;
- scsi_cmd[4] = 255;
- scsi_cmd[5] = 0;
- the_result = -1;
-#ifdef DEBUG
- memset ((void *) scsi_result , 0, 255);
-#endif
- scsi_do_cmd (host_nr, dev, (void *) scsi_cmd, (void *)
- scsi_result, 256, scan_scsis_done,
- SCSI_TIMEOUT, sense_buffer, 3);
-
-/*
- * Wait for valid result
- */
-
- while (the_result < 0);
-
- if (!the_result)
- {
- scsi_devices[NR_SCSI_DEVICES].
- host_no = host_nr;
- scsi_devices[NR_SCSI_DEVICES].
- id = dev;
- scsi_devices[NR_SCSI_DEVICES].
- lun = lun;
- scsi_devices[NR_SCSI_DEVICES].
- removable = (0x80 &
- scsi_result[1]) >> 7;
- scsi_devices[NR_SCSI_DEVICES].
- changed = 0;
- scsi_devices[NR_SCSI_DEVICES].
- access_count = 0;
- scsi_devices[NR_SCSI_DEVICES].
- busy = 0;
+{
+ int host_nr , dev, lun, type;
+ unsigned char scsi_cmd [12];
+ unsigned char scsi_result [256];
+ Scsi_Cmnd SCmd;
+
+ ++in_scan;
+ lun = 0;
+
+ SCmd.next = NULL;
+ SCmd.prev = NULL;
+ for (host_nr = 0; host_nr < max_scsi_hosts; ++host_nr)
+ if (scsi_hosts[host_nr].present)
+ {
+ host_queue[host_nr] = &SCmd; /* We need this so that commands can
+ time out */
+ for (dev = 0; dev < 8; ++dev)
+ if (scsi_hosts[host_nr].this_id != dev)
+ for (lun = 0; lun < 8; ++lun)
+ {
+ scsi_devices[NR_SCSI_DEVICES].host_no = host_nr;
+ scsi_devices[NR_SCSI_DEVICES].id = dev;
+ scsi_devices[NR_SCSI_DEVICES].lun = lun;
+ scsi_devices[NR_SCSI_DEVICES].index = NR_SCSI_DEVICES;
+ scsi_devices[NR_SCSI_DEVICES].device_wait = NULL;
+
+ scsi_cmd[0] = TEST_UNIT_READY;
+ scsi_cmd[1] = lun << 5;
+ scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
+ scsi_cmd[4] = 0;
+
+ SCmd.host = host_nr;
+ SCmd.target = dev;
+ SCmd.lun = lun;
+
+ SCmd.request.dev = 0xffff; /* Mark not busy */
+ SCmd.use_sg = 0;
+
+ scsi_do_cmd (&SCmd,
+ (void *) scsi_cmd, (void *)
+ scsi_result, 256, scan_scsis_done,
+ SCSI_TIMEOUT + 400, 3);
+
+ while (SCmd.request.dev != 0xfffe);
+
+ if(SCmd.result) {
+ if ((driver_byte(SCmd.result) & DRIVER_SENSE) &&
+ ((SCmd.sense_buffer[0] & 0x70) >> 4) == 7) {
+ if (SCmd.sense_buffer[2] &0xe0)
+ continue; /* No devices here... */
+ if((SCmd.sense_buffer[2] & 0xf != NOT_READY) &&
+ (SCmd.sense_buffer[2] & 0xf != UNIT_ATTENTION))
+ continue;
+ }
+ else
+ break;
+ };
+
+ /*
+ * Build an INQUIRY command block.
+ */
+
+ scsi_cmd[0] = INQUIRY;
+ scsi_cmd[1] = (lun << 5) & 0xe0;
+ scsi_cmd[2] = 0;
+ scsi_cmd[3] = 0;
+ scsi_cmd[4] = 255;
+ scsi_cmd[5] = 0;
+
+ SCmd.request.dev = 0xffff; /* Mark not busy */
+
+ scsi_do_cmd (&SCmd,
+ (void *) scsi_cmd, (void *)
+ scsi_result, 256, scan_scsis_done,
+ SCSI_TIMEOUT, 3);
+
+ while (SCmd.request.dev != 0xfffe);
+
+ the_result = SCmd.result;
+
+ if(the_result) break;
+ /* skip other luns on this device */
+
+ if (!the_result)
+ {
+ scsi_devices[NR_SCSI_DEVICES].
+ removable = (0x80 &
+ scsi_result[1]) >> 7;
+ scsi_devices[NR_SCSI_DEVICES].
+ changed = 0;
+ scsi_devices[NR_SCSI_DEVICES].
+ access_count = 0;
+ scsi_devices[NR_SCSI_DEVICES].
+ busy = 0;
/*
* Currently, all sequential devices are assumed to be tapes,
* all random devices disk, with the appropriate read only
* flags set for ROM / WORM treated as RO.
*/
- switch (type = scsi_result[0])
- {
- case TYPE_TAPE :
- case TYPE_DISK :
- scsi_devices[NR_SCSI_DEVICES].writeable = 1;
- break;
- case TYPE_WORM :
- case TYPE_ROM :
- scsi_devices[NR_SCSI_DEVICES].writeable = 0;
- break;
- default :
- type = -1;
- }
-
- scsi_devices[NR_SCSI_DEVICES].random = (type == TYPE_TAPE) ? 0 : 1;
-
- maxed = 0;
- switch (type)
- {
- case -1 :
- break;
- case TYPE_TAPE :
-#ifdef DEBUG
- printk("Detected scsi tape at host %d, ID %d, lun %d \n", host_nr, dev, lun);
-#endif
-#ifdef CONFIG_BLK_DEV_ST
- if (!(maxed = (NR_ST == MAX_ST)))
- scsi_tapes[NR_ST].device = &scsi_devices[NR_SCSI_DEVICES];
-#endif
- break;
- case TYPE_ROM:
- printk("Detected scsi CD-ROM at host %d, ID %d, lun %d \n", host_nr, dev, lun);
-#ifdef CONFIG_BLK_DEV_SR
- if (!(maxed = (NR_SR >= MAX_SR)))
- scsi_CDs[NR_SR].device = &scsi_devices[NR_SCSI_DEVICES];
-#endif
- break;
- default :
-#ifdef DEBUG
- printk("Detected scsi disk at host %d, ID %d, lun %d \n", host_nr, dev, lun);
-#endif
-#ifdef CONFIG_BLK_DEV_SD
- if (!(maxed = (NR_SD >= MAX_SD)))
- rscsi_disks[NR_SD].device = &scsi_devices[NR_SCSI_DEVICES];
-#endif
- }
-
- print_inquiry(scsi_result);
-
- if (maxed)
- {
- printk ("Already have detected "
- "maximum number of SCSI "
- "%ss Unable to \n"
- "add drive at SCSI host "
- "%s, ID %d, LUN %d\n\r",
- (type == TYPE_TAPE) ?
- "tape" :
- (type == TYPE_DISK) ?
- "disk" : "CD-ROM",
- scsi_hosts[host_nr].name,
- dev, lun);
- type = -1;
- break;
- }
-
- else if (type != -1)
- {
- char *p;
- char str[25];
-memcpy((void *) str, (void *) &scsi_result[8], 8);
-for (p = str; (p < (str + 8)) && (*p != ' '); ++p);
-*p++ = ' ';
-memcpy((void *) p, (void *) &scsi_result[16], 16);
-for (; *p != ' '; ++p);
-*p = 0;
-
-printk("s%c%d at scsi%d, id %d, lun %d : %s\n",
- (type == TYPE_TAPE) ? 't' : ((type == TYPE_ROM) ? 'r' : 'd'),
- (type == TYPE_TAPE) ?
-#ifdef CONFIG_BLK_DEV_ST
- NR_ST
-#else
- -1
-#endif
- :
- (type == TYPE_ROM ?
-#ifdef CONFIG_BLK_DEV_SR
- NR_SR
-#else
- -1
-#endif
- :
-#ifdef CONFIG_BLK_DEV_SD
- NR_SD
-#else
- -1
-#endif
- )
-
- ,host_nr , dev, lun, p);
- if (type == TYPE_TAPE)
-#ifdef CONFIG_BLK_DEV_ST
- ++NR_ST;
-#else
-;
-#endif
-
- else if (type == TYPE_DISK)
-#ifdef CONFIG_BLK_DEV_SD
- ++NR_SD;
-#else
-;
-#endif
- else
-#ifdef CONFIG_BLK_DEV_SR
- ++NR_SR;
-#else
-;
-#endif
- }
- ++slave;
- ++NR_SCSI_DEVICES;
- } /* if result == DID_OK ends */
- } /* for lun ends */
- } /* if present */
-
- printk("scsi : detected "
-#ifdef CONFIG_BLK_DEV_SD
- "%d SCSI disk%s "
-#endif
-
-#ifdef CONFIG_BLK_DEV_ST
- "%d tape%s "
-#endif
-
-#ifdef CONFIG_BLK_DEV_SR
-"%d CD-ROM drive%s "
-#endif
-
- "total.\n"
-
-#ifdef CONFIG_BLK_DEV_SD
- , NR_SD, (NR_SD != 1) ? "s" : ""
-#endif
-
-#ifdef CONFIG_BLK_DEV_ST
- , NR_ST, (NR_ST != 1) ? "s" : ""
-#endif
-
-#ifdef CONFIG_BLK_DEV_SR
- , NR_SR, (NR_SR != 1) ? "s" : ""
-#endif
- );
- in_scan = 0;
- } /* scan_scsis ends */
-
-/*
- * We handle the timeout differently if it happens when a reset,
- * abort, etc are in process.
- */
-
-static unsigned char internal_timeout[MAX_SCSI_HOSTS];
+ switch (type = scsi_result[0])
+ {
+ case TYPE_TAPE :
+ case TYPE_DISK :
+ scsi_devices[NR_SCSI_DEVICES].writeable = 1;
+ break;
+ case TYPE_WORM :
+ case TYPE_ROM :
+ scsi_devices[NR_SCSI_DEVICES].writeable = 0;
+ break;
+ default :
+ type = -1;
+ }
+
+ scsi_devices[NR_SCSI_DEVICES].random =
+ (type == TYPE_TAPE) ? 0 : 1;
+ scsi_devices[NR_SCSI_DEVICES].type = type;
+
+ if (type != -1)
+ {
+ print_inquiry(scsi_result);
+ switch(type){
+ case TYPE_TAPE:
+ printk("Detected scsi tape st%d at scsi%d, id %d, lun %d\n", MAX_ST,
+ host_nr , dev, lun);
+ if(NR_ST != -1) ++MAX_ST;
+ break;
+ case TYPE_ROM:
+ printk("Detected scsi CD-ROM sr%d at scsi%d, id %d, lun %d\n", MAX_SR,
+ host_nr , dev, lun);
+ if(NR_SR != -1) ++MAX_SR;
+ break;
+ case TYPE_DISK:
+ printk("Detected scsi disk sd%d at scsi%d, id %d, lun %d\n", MAX_SD,
+ host_nr , dev, lun);
+ if(NR_SD != -1) ++MAX_SD;
+ break;
+ default:
+ break;
+ };
+
+ /* These devices need this "key" to unlock the device
+ so we can use it */
+ if(strncmp("INSITE", &scsi_result[8], 6) == 0 &&
+ strncmp("Floptical F*8I", &scsi_result[16], 16) == 0) {
+ scsi_cmd[0] = MODE_SENSE;
+ scsi_cmd[1] = (lun << 5) & 0xe0;
+ scsi_cmd[2] = 0x2e;
+ scsi_cmd[3] = 0;
+ scsi_cmd[4] = 0x2a;
+ scsi_cmd[5] = 0;
+
+ SCmd.request.dev = 0xffff; /* Mark not busy */
+
+ scsi_do_cmd (&SCmd,
+ (void *) scsi_cmd, (void *)
+ scsi_result, 0x2a, scan_scsis_done,
+ SCSI_TIMEOUT, 3);
+
+ while (SCmd.request.dev != 0xfffe);
+ };
+
+ ++NR_SCSI_DEVICES;
+ /* Some scsi devices cannot be polled for lun != 0
+ due to firmware bugs */
+ if(blacklisted(scsi_result)) break;
+
+ /* Some scsi-1 peripherals do not handle lun != 0.
+ I am assuming that scsi-2 peripherals do better */
+ if((scsi_result[2] & 0x07) == 1 &&
+ (scsi_result[3] & 0x0f) == 0) break;
+ }
+ } /* if result == DID_OK ends */
+ } /* for lun ends */
+ host_queue[host_nr] = NULL; /* No longer needed here */
+ } /* if present */
+
+ for (host_nr = 0; host_nr < max_scsi_hosts; ++host_nr)
+ if (scsi_hosts[host_nr].present)
+ if(host_queue[host_nr]) panic("host_queue not cleared");
+
+ printk("scsi : detected ");
+ if(NR_SD != -1)
+ printk("%d SCSI disk%s ", MAX_SD, (MAX_SD != 1) ? "s" : "");
+
+ if(NR_ST != -1)
+ printk("%d tape%s ", MAX_ST, (MAX_ST != 1) ? "s" : "");
+
+ if(NR_SR != -1)
+ printk("%d CD-ROM drive%s ", MAX_SR, (MAX_SR != 1) ? "s" : "");
+
+ printk("total.\n");
+ in_scan = 0;
+} /* scan_scsis ends */
/*
* Flag bits for the internal_timeout array
@@ -372,26 +358,26 @@ static unsigned char internal_timeout[MAX_SCSI_HOSTS];
command, that failing perform a kernel panic.
*/
-static void scsi_times_out (int host)
+static void scsi_times_out (Scsi_Cmnd * SCpnt)
{
- switch (internal_timeout[host] & (IN_ABORT | IN_RESET))
+ switch (SCpnt->internal_timeout & (IN_ABORT | IN_RESET))
{
case NORMAL_TIMEOUT:
if (!in_scan)
printk("SCSI host %d timed out - aborting command \r\n",
- host);
+ SCpnt->host);
- if (!scsi_abort (host, DID_TIME_OUT))
+ if (!scsi_abort (SCpnt, DID_TIME_OUT))
return;
case IN_ABORT:
printk("SCSI host %d abort() timed out - reseting \r\n",
- host);
- if (!scsi_reset (host))
+ SCpnt->host);
+ if (!scsi_reset (SCpnt))
return;
case IN_RESET:
case (IN_ABORT | IN_RESET):
- printk("Unable to reset scsi host %d\r\n",host);
+ printk("Unable to reset scsi host %d\r\n",SCpnt->host);
panic("");
default:
INTERNAL_ERROR;
@@ -399,22 +385,131 @@ static void scsi_times_out (int host)
}
+
+/* This function takes a quick look at a request, and decides if it
+can be queued now, or if there would be a stall while waiting for
+something else to finish. This routine assumes that interrupts are
+turned off when entering the routine. It is the responsibility
+of the calling code to ensure that this is the case. */
+
+Scsi_Cmnd * request_queueable (struct request * req, int index)
+{
+ int host;
+ Scsi_Cmnd * SCpnt = NULL;
+
+ if ((index < 0) || (index > NR_SCSI_DEVICES))
+ panic ("Index number in allocate_device() is out of range.\n");
+
+ if (req && req->dev <= 0)
+ panic("Invalid device in allocate_device");
+
+ host = scsi_devices[index].host_no;
+ SCpnt = host_queue[host];
+ while(SCpnt){
+ if(SCpnt->target == scsi_devices[index].id &&
+ SCpnt->lun == scsi_devices[index].lun)
+ if(SCpnt->request.dev < 0) break;
+ SCpnt = SCpnt->next;
+ };
+
+ if (!SCpnt) return NULL;
+
+ if (scsi_hosts[host].can_queue
+ && host_busy[host] >= scsi_hosts[host].can_queue) return NULL;
+
+ if (req) {
+ memcpy(&SCpnt->request, req, sizeof(struct request));
+ req->dev = -1;
+ } else
+ SCpnt->request.dev = 0xffff; /* Busy, but no request */
+
+ SCpnt->use_sg = 0; /* Reset the scatter-gather flag */
+ return SCpnt;
+}
+
+/* This function returns a structure pointer that will be valid for
+the device. The wait parameter tells us whether we should wait for
+the unit to become free or not. We are also able to tell this routine
+not to return a descriptor if the host is unable to accept any more
+commands for the time being. We need to keep in mind that there is no
+guarantee that the host remain not busy. Keep in mind the
+request_queueable function also knows the internal allocation scheme
+of the packets for each device */
+
+Scsi_Cmnd * allocate_device (struct request ** reqp, int index, int wait)
+{
+ int host, dev = -1;
+ struct request * req = NULL;
+ Scsi_Cmnd * SCpnt = NULL;
+ Scsi_Cmnd * SCwait = NULL;
+
+ if ((index < 0) || (index > NR_SCSI_DEVICES))
+ panic ("Index number in allocate_device() is out of range.\n");
+
+ if (reqp) req = *reqp;
+
+ if (req && (dev = req->dev) <= 0)
+ panic("Invalid device in allocate_device");
+
+ host = scsi_devices[index].host_no;
+
+ while (1==1){
+ SCpnt = host_queue[host];
+ while(SCpnt){
+ if(SCpnt->target == scsi_devices[index].id &&
+ SCpnt->lun == scsi_devices[index].lun) {
+ SCwait = SCpnt;
+ if(SCpnt->request.dev < 0) break;
+ };
+ SCpnt = SCpnt->next;
+ };
+ cli();
+ /* See if this request has already been queued by an interrupt routine */
+ if (req && ((req->dev < 0) || (req->dev != dev))) return NULL;
+ if (!SCpnt || SCpnt->request.dev >= 0) /* Might have changed */
+ {
+ sti();
+ if(!wait) return NULL;
+ if (!SCwait) {
+ printk("Attempt to allocate device index %d, target %d, lun %d\n",
+ index, scsi_devices[index].id ,scsi_devices[index].lun);
+ panic("No device found in allocate_device\n");
+ };
+ SCSI_SLEEP(&scsi_devices[SCwait->index].device_wait,
+ (SCwait->request.dev > 0));
+ } else {
+ if (req) {
+ memcpy(&SCpnt->request, req, sizeof(struct request));
+ req->dev = -1;
+ *reqp = req->next;
+ } else {
+ SCpnt->request.dev = 0xffff; /* Busy */
+ };
+ sti();
+ break;
+ };
+ };
+
+ SCpnt->use_sg = 0; /* Reset the scatter-gather flag */
+ return SCpnt;
+}
+
/*
This is inline because we have stack problemes if we recurse to deeply.
*/
-static void internal_cmnd (int host, unsigned char target, const void *cmnd ,
- void *buffer, unsigned bufflen, void (*done)(int,int))
+inline void internal_cmnd (Scsi_Cmnd * SCpnt)
{
- int temp;
+ int temp, host;
#ifdef DEBUG_DELAY
int clock;
#endif
- if ((host < 0) || (host > MAX_SCSI_HOSTS))
- panic ("Host number in internal_cmnd() is out of range.\n");
+ host = SCpnt->host;
+ if ((host < 0) || (host > max_scsi_hosts))
+ panic ("Host number in internal_cmnd() is out of range.\n");
/*
We will wait MIN_RESET_DELAY clock ticks after the last reset so
@@ -423,8 +518,7 @@ static void internal_cmnd (int host, unsigned char target, const void *cmnd ,
temp = last_reset[host];
while (jiffies < temp);
-host_timeout[host] = last_cmnd[host].timeout_per_command;
-update_timeout();
+update_timeout(SCpnt, SCpnt->timeout_per_command);
/*
We will use a queued command if possible, otherwise we will emulate the
@@ -432,7 +526,7 @@ update_timeout();
*/
#ifdef DEBUG
printk("internal_cmnd (host = %d, target = %d, command = %08x, buffer = %08x, \n"
- "bufflen = %d, done = %08x)\n", host, target, cmnd, buffer, bufflen, done);
+ "bufflen = %d, done = %08x)\n", SCpnt->host, SCpnt->target, SCpnt->cmnd, SCpnt->buffer, SCpnt->bufflen, SCpnt->done);
#endif
if (scsi_hosts[host].can_queue)
@@ -441,8 +535,7 @@ update_timeout();
printk("queuecommand : routine at %08x\n",
scsi_hosts[host].queuecommand);
#endif
- scsi_hosts[host].queuecommand (target, cmnd, buffer, bufflen,
- done);
+ scsi_hosts[host].queuecommand (SCpnt, scsi_done);
}
else
{
@@ -450,37 +543,38 @@ update_timeout();
#ifdef DEBUG
printk("command() : routine at %08x\n", scsi_hosts[host].command);
#endif
- temp=scsi_hosts[host].command (target, cmnd, buffer, bufflen);
-
+ temp=scsi_hosts[host].command (SCpnt);
+ SCpnt->result = temp;
#ifdef DEBUG_DELAY
clock = jiffies + 400;
while (jiffies < clock);
printk("done(host = %d, result = %04x) : routine at %08x\n", host, temp, done);
#endif
- done(host, temp);
+ scsi_done(SCpnt);
}
#ifdef DEBUG
printk("leaving internal_cmnd()\n");
#endif
}
-static void scsi_request_sense (int host, unsigned char target,
- unsigned char lun)
+static void scsi_request_sense (Scsi_Cmnd * SCpnt)
{
cli();
- host_timeout[host] = SENSE_TIMEOUT;
- update_timeout();
- last_cmnd[host].flags |= WAS_SENSE;
+ SCpnt->flags |= WAS_SENSE;
+ update_timeout(SCpnt, SENSE_TIMEOUT);
sti();
- last_cmnd[host].sense_cmnd[1] = lun << 5;
- internal_cmnd (host, target, (void *) last_cmnd[host].sense_cmnd,
- (void *) last_cmnd[host].sense_buffer, SENSE_LENGTH,
- scsi_done);
- }
+ memcpy ((void *) SCpnt->cmnd , (void *) generic_sense,
+ sizeof(generic_sense));
+ SCpnt->cmnd[1] = SCpnt->lun << 5;
+ SCpnt->cmnd[4] = sizeof(SCpnt->sense_buffer);
+ SCpnt->request_buffer = &SCpnt->sense_buffer;
+ SCpnt->request_bufflen = sizeof(SCpnt->sense_buffer);
+ internal_cmnd (SCpnt);
+ }
@@ -491,24 +585,27 @@ static void scsi_request_sense (int host, unsigned char target,
drivers go for the same host at the same time.
*/
-void scsi_do_cmd (int host, unsigned char target, const void *cmnd ,
- void *buffer, unsigned bufflen, void (*done)(int,int),
- int timeout, unsigned char *sense_buffer, int retries
+void scsi_do_cmd (Scsi_Cmnd * SCpnt, const void *cmnd ,
+ void *buffer, unsigned bufflen, void (*done)(Scsi_Cmnd *),
+ int timeout, int retries
)
{
- int ok = 0;
+ int host = SCpnt->host;
#ifdef DEBUG
+ {
int i;
+ int target = SCpnt->target;
printk ("scsi_do_cmd (host = %d, target = %d, buffer =%08x, "
"bufflen = %d, done = %08x, timeout = %d, retries = %d)\n"
"command : " , host, target, buffer, bufflen, done, timeout, retries);
for (i = 0; i < 10; ++i)
printk ("%02x ", ((unsigned char *) cmnd)[i]);
printk("\n");
+ };
#endif
- if ((host >= MAX_SCSI_HOSTS) || !scsi_hosts[host].present)
+ if ((host < 0) || (host >= max_scsi_hosts) || !scsi_hosts[host].present)
{
printk ("Invalid or not present host number. %d\n", host);
panic("");
@@ -523,28 +620,20 @@ void scsi_do_cmd (int host, unsigned char target, const void *cmnd ,
ourselves.
*/
- do {
- cli();
- if (host_busy[host])
- {
- sti();
-#ifdef DEBUG
- printk("Host %d is busy.\n", host);
-#endif
- while (host_busy[host]);
-#ifdef DEBUG
- printk("Host %d is no longer busy.\n", host);
-#endif
- }
- else
- {
- host_busy[host] = 1;
- ok = 1;
- sti();
- }
- } while (!ok);
-
-
+ while (1==1){
+ cli();
+ if (scsi_hosts[host].can_queue
+ && host_busy[host] >= scsi_hosts[host].can_queue)
+ {
+ sti();
+ SCSI_SLEEP(&host_wait[host],
+ (host_busy[host] >= scsi_hosts[host].can_queue));
+ } else {
+ host_busy[host]++;
+ sti();
+ break;
+ };
+ };
/*
Our own function scsi_done (which marks the host as not busy, disables
the timeout counter, etc) will be called by us or by the
@@ -553,23 +642,28 @@ void scsi_do_cmd (int host, unsigned char target, const void *cmnd ,
*/
- memcpy ((void *) last_cmnd[host].cmnd , (void *) cmnd, 10);
- last_cmnd[host].host = host;
- last_cmnd[host].target = target;
- last_cmnd[host].lun = (last_cmnd[host].cmnd[1] >> 5);
- last_cmnd[host].bufflen = bufflen;
- last_cmnd[host].buffer = buffer;
- last_cmnd[host].sense_buffer = sense_buffer;
- last_cmnd[host].flags=0;
- last_cmnd[host].retries=0;
- last_cmnd[host].allowed=retries;
- last_cmnd[host].done = done;
- last_cmnd[host].timeout_per_command = timeout;
+ memcpy ((void *) SCpnt->data_cmnd , (void *) cmnd, 10);
+#if 0
+ SCpnt->host = host;
+ SCpnt->target = target;
+ SCpnt->lun = (SCpnt->data_cmnd[1] >> 5);
+#endif
+ SCpnt->bufflen = bufflen;
+ SCpnt->buffer = buffer;
+ SCpnt->flags=0;
+ SCpnt->retries=0;
+ SCpnt->allowed=retries;
+ SCpnt->done = done;
+ SCpnt->timeout_per_command = timeout;
+ memcpy ((void *) SCpnt->cmnd , (void *) cmnd, 10);
+ SCpnt->request_buffer = buffer;
+ SCpnt->request_bufflen = bufflen;
+
/* Start the timer ticking. */
- internal_timeout[host] = 0;
- internal_cmnd (host, target, cmnd , buffer, bufflen, scsi_done);
+ SCpnt->internal_timeout = 0;
+ internal_cmnd (SCpnt);
#ifdef DEBUG
printk ("Leaving scsi_do_cmd()\n");
@@ -577,34 +671,37 @@ void scsi_do_cmd (int host, unsigned char target, const void *cmnd ,
}
+
/*
The scsi_done() function disables the timeout timer for the scsi host,
marks the host as not busy, and calls the user specified completion
function for that host's current command.
*/
-static void reset (int host)
+static void reset (Scsi_Cmnd * SCpnt)
{
#ifdef DEBUG
- printk("reset(%d)\n", host);
+ printk("reset(%d)\n", SCpnt->host);
#endif
- last_cmnd[host].flags |= (WAS_RESET | IS_RESETTING);
- scsi_reset(host);
+ SCpnt->flags |= (WAS_RESET | IS_RESETTING);
+ scsi_reset(SCpnt);
#ifdef DEBUG
printk("performing request sense\n");
#endif
- scsi_request_sense (host, last_cmnd[host].target, last_cmnd[host].lun);
+ scsi_request_sense (SCpnt);
}
-static int check_sense (int host)
+static int check_sense (Scsi_Cmnd * SCpnt)
{
- if (((last_cmnd[host].sense_buffer[0] & 0x70) >> 4) == 7)
- switch (last_cmnd[host].sense_buffer[2] & 0xf)
+ if (((SCpnt->sense_buffer[0] & 0x70) >> 4) == 7) {
+ if (SCpnt->sense_buffer[2] &0xe0)
+ return SUGGEST_ABORT;
+ switch (SCpnt->sense_buffer[2] & 0xf)
{
case NO_SENSE:
case RECOVERED_ERROR:
@@ -630,6 +727,7 @@ static int check_sense (int host)
default:
return SUGGEST_ABORT;
}
+ }
else
return SUGGEST_RETRY;
}
@@ -655,15 +753,15 @@ static int check_sense (int host)
* will hang. If more than one of the above actions are taken by
* scsi_done, then unpredictable behavior will result.
*/
-static void scsi_done (int host, int result)
+static void scsi_done (Scsi_Cmnd * SCpnt)
{
int status=0;
int exit=0;
int checked;
int oldto;
- oldto = host_timeout[host];
- host_timeout[host] = 0;
- update_timeout();
+ int host = SCpnt->host;
+ int result = SCpnt->result;
+ oldto = update_timeout(SCpnt, 0);
#define FINISHED 0
#define MAYREDO 1
@@ -673,34 +771,31 @@ static void scsi_done (int host, int result)
#ifdef DEBUG
printk("In scsi_done(host = %d, result = %06x)\n", host, result);
#endif
- if (host > MAX_SCSI_HOSTS || host < 0)
+ if (host > max_scsi_hosts || host < 0)
{
- host_timeout[host] = 0;
- update_timeout();
+ update_timeout(SCpnt, 0);
panic("scsi_done() called with invalid host number.\n");
}
switch (host_byte(result))
{
case DID_OK:
- if (last_cmnd[host].flags & IS_RESETTING)
+ if (SCpnt->flags & IS_RESETTING)
{
- last_cmnd[host].flags &= ~IS_RESETTING;
+ SCpnt->flags &= ~IS_RESETTING;
status = REDO;
break;
}
- if (status_byte(result) && (last_cmnd[host].flags &
- WAS_SENSE))
+ if (status_byte(result) && (SCpnt->flags &
+ WAS_SENSE)) /* Failed to obtain sense information */
{
- last_cmnd[host].flags &= ~WAS_SENSE;
- cli();
- internal_timeout[host] &= ~SENSE_TIMEOUT;
- sti();
+ SCpnt->flags &= ~WAS_SENSE;
+ SCpnt->internal_timeout &= ~SENSE_TIMEOUT;
- if (!(last_cmnd[host].flags & WAS_RESET))
+ if (!(SCpnt->flags & WAS_RESET))
{
- reset(host);
+ reset(SCpnt);
return;
}
else
@@ -715,26 +810,23 @@ static void scsi_done (int host, int result)
switch (status_byte(result))
{
case GOOD:
- if (last_cmnd[host].flags & WAS_SENSE)
+ if (SCpnt->flags & WAS_SENSE)
{
#ifdef DEBUG
printk ("In scsi_done, GOOD status, COMMAND COMPLETE, parsing sense information.\n");
#endif
- last_cmnd[host].flags &= ~WAS_SENSE;
- cli();
- internal_timeout[host] &= ~SENSE_TIMEOUT;
- sti();
+ SCpnt->flags &= ~WAS_SENSE;
+ SCpnt->internal_timeout &= ~SENSE_TIMEOUT;
- switch (checked = check_sense(host))
+ switch (checked = check_sense(SCpnt))
{
case 0:
#ifdef DEBUG
printk("NO SENSE. status = REDO\n");
#endif
- host_timeout[host] = oldto;
- update_timeout();
+ update_timeout(SCpnt, oldto);
status = REDO;
break;
case SUGGEST_REMAP:
@@ -776,7 +868,7 @@ static void scsi_done (int host, int result)
printk("CHECK CONDITION message returned, performing request sense.\n");
#endif
- scsi_request_sense (host, last_cmnd[host].target, last_cmnd[host].lun);
+ scsi_request_sense (SCpnt);
status = PENDING;
break;
@@ -792,13 +884,12 @@ static void scsi_done (int host, int result)
#ifdef DEBUG
printk("BUSY message returned, performing REDO");
#endif
- host_timeout[host] = oldto;
- update_timeout();
+ update_timeout(SCpnt, oldto);
status = REDO;
break;
case RESERVATION_CONFLICT:
- reset(host);
+ reset(SCpnt);
return;
#if 0
exit = DRIVER_SOFT | SUGGEST_ABORT;
@@ -821,7 +912,7 @@ static void scsi_done (int host, int result)
printk("Host returned DID_TIME_OUT - ");
#endif
- if (last_cmnd[host].flags & WAS_TIMEDOUT)
+ if (SCpnt->flags & WAS_TIMEDOUT)
{
#ifdef DEBUG
printk("Aborting\n");
@@ -833,7 +924,7 @@ static void scsi_done (int host, int result)
#ifdef DEBUG
printk ("Retrying.\n");
#endif
- last_cmnd[host].flags |= WAS_TIMEDOUT;
+ SCpnt->flags |= WAS_TIMEDOUT;
status = REDO;
}
break;
@@ -868,15 +959,15 @@ static void scsi_done (int host, int result)
#ifdef DEBUG
printk("In MAYREDO, allowing %d retries, have %d\n\r",
- last_cmnd[host].allowed, last_cmnd[host].retries);
+ SCpnt->allowed, SCpnt->retries);
#endif
- if ((++last_cmnd[host].retries) < last_cmnd[host].allowed)
+ if ((++SCpnt->retries) < SCpnt->allowed)
{
- if ((last_cmnd[host].retries >= (last_cmnd[host].allowed >> 1))
- && !(last_cmnd[host].flags & WAS_RESET))
+ if ((SCpnt->retries >= (SCpnt->allowed >> 1))
+ && !(SCpnt->flags & WAS_RESET))
{
- reset(host);
+ reset(SCpnt);
break;
}
@@ -889,14 +980,17 @@ static void scsi_done (int host, int result)
/* fall through to REDO */
case REDO:
- if (last_cmnd[host].flags & WAS_SENSE)
- scsi_request_sense (host, last_cmnd[host].target,
- last_cmnd[host].lun);
+ if (SCpnt->flags & WAS_SENSE)
+ scsi_request_sense(SCpnt);
else
- internal_cmnd (host, last_cmnd[host].target,
- last_cmnd[host].cmnd,
- last_cmnd[host].buffer,
- last_cmnd[host].bufflen, scsi_done);
+ {
+ memcpy ((void *) SCpnt->cmnd,
+ (void*) SCpnt->data_cmnd,
+ sizeof(SCpnt->data_cmnd));
+ SCpnt->request_buffer = SCpnt->buffer;
+ SCpnt->request_bufflen = SCpnt->bufflen;
+ internal_cmnd (SCpnt);
+ };
break;
default:
INTERNAL_ERROR;
@@ -905,10 +999,12 @@ static void scsi_done (int host, int result)
if (status == FINISHED)
{
#ifdef DEBUG
- printk("Calling done function - at address %08x\n", last_cmnd[host].done);
+ printk("Calling done function - at address %08x\n", SCpnt->done);
#endif
- host_busy[host] = 0;
- last_cmnd[host].done (host, (result | ((exit & 0xff) << 24)));
+ host_busy[host]--; /* Indicate that we are free */
+ wake_up(&host_wait[host]);
+ SCpnt->result = result | ((exit & 0xff) << 24);
+ SCpnt->done (SCpnt);
}
@@ -934,82 +1030,88 @@ static void scsi_done (int host, int result)
*/
-int scsi_abort (int host, int why)
+int scsi_abort (Scsi_Cmnd * SCpnt, int why)
{
int temp, oldto;
+ int host = SCpnt->host;
while(1)
{
cli();
- if (internal_timeout[host] & IN_ABORT)
+ if (SCpnt->internal_timeout & IN_ABORT)
{
sti();
- while (internal_timeout[host] & IN_ABORT);
+ while (SCpnt->internal_timeout & IN_ABORT);
}
else
{
- oldto = host_timeout[host];
- internal_timeout[host] |= IN_ABORT;
- host_timeout[host] = ABORT_TIMEOUT;
- update_timeout();
+ SCpnt->internal_timeout |= IN_ABORT;
+ oldto = update_timeout(SCpnt, ABORT_TIMEOUT);
sti();
- if (!host_busy[host] || !scsi_hosts[host].abort(why))
+ if (!host_busy[host] || !scsi_hosts[host].abort(SCpnt, why))
temp = 0;
else
temp = 1;
cli();
- internal_timeout[host] &= ~IN_ABORT;
- host_timeout[host]=oldto;
- update_timeout();
+ SCpnt->internal_timeout &= ~IN_ABORT;
+ update_timeout(SCpnt, oldto);
sti();
return temp;
}
}
}
-int scsi_reset (int host)
+int scsi_reset (Scsi_Cmnd * SCpnt)
{
int temp, oldto;
+ Scsi_Cmnd * SCpnt1;
+ int host = SCpnt->host;
+#ifdef DEBUG
+ printk("Danger Will Robinson! - SCSI bus for host %d is being reset.\n",host);
+#endif
while (1) {
cli();
- if (internal_timeout[host] & IN_RESET)
+ if (SCpnt->internal_timeout & IN_RESET)
{
sti();
- while (internal_timeout[host] & IN_RESET);
+ while (SCpnt->internal_timeout & IN_RESET);
}
else
{
- oldto = host_timeout[host];
- host_timeout[host] = RESET_TIMEOUT;
- update_timeout();
- internal_timeout[host] |= IN_RESET;
+ SCpnt->internal_timeout |= IN_RESET;
+ oldto = update_timeout(SCpnt, RESET_TIMEOUT);
if (host_busy[host])
{
sti();
- if (!(last_cmnd[host].flags & IS_RESETTING) && !(internal_timeout[host] & IN_ABORT))
- scsi_abort(host, DID_RESET);
+ SCpnt1 = host_queue[host];
+ while(SCpnt1) {
+ if ((SCpnt1->request.dev > 0) &&
+ !(SCpnt1->flags & IS_RESETTING) &&
+ !(SCpnt1->internal_timeout & IN_ABORT))
+ scsi_abort(SCpnt1, DID_RESET);
+ SCpnt1 = SCpnt1->next;
+ };
temp = scsi_hosts[host].reset();
}
else
{
- host_busy[host]=1;
+ host_busy[host]++;
sti();
temp = scsi_hosts[host].reset();
last_reset[host] = jiffies;
- host_busy[host]=0;
+ host_busy[host]--;
}
cli();
- host_timeout[host] = oldto;
- update_timeout();
- internal_timeout[host] &= ~IN_RESET;
+ SCpnt->internal_timeout &= ~IN_RESET;
+ update_timeout(SCpnt, oldto);
sti();
return temp;
}
@@ -1023,7 +1125,8 @@ static void scsi_main_timeout(void)
We must not enter update_timeout with a timeout condition still pending.
*/
- int i, timed_out;
+ int timed_out, host;
+ Scsi_Cmnd * SCpnt = NULL;
do {
cli();
@@ -1033,19 +1136,25 @@ static void scsi_main_timeout(void)
time remaining on them.
*/
- for (i = timed_out = 0; i < MAX_SCSI_HOSTS; ++i)
- if (host_timeout[i] != 0 && host_timeout[i] <= time_elapsed)
- {
- sti();
- host_timeout[i] = 0;
- scsi_times_out(i);
- ++timed_out;
- }
-
- update_timeout();
- } while (timed_out);
+ timed_out = 0;
+ for(host = 0; host < max_scsi_hosts; host++) {
+ SCpnt = host_queue[host];
+ while (SCpnt){
+ if (SCpnt->timeout != 0 && SCpnt->timeout <= time_elapsed)
+ {
+ sti();
+ SCpnt->timeout = 0;
+ scsi_times_out(SCpnt);
+ ++timed_out;
+ cli();
+ }
+ SCpnt = SCpnt->next;
+ };
+ };
+ update_timeout(NULL, 0);
+ } while (timed_out);
sti();
- }
+ }
/*
These are used to keep track of things.
@@ -1056,11 +1165,16 @@ static int time_start, time_elapsed;
/*
The strategy is to cause the timer code to call scsi_times_out()
when the soonest timeout is pending.
+ The arguments are used when we are queueing a new command, because
+ we do not want to subtract the time used from this time, but when we
+ set the timer, we want to take this value into account.
*/
-static void update_timeout(void)
+static int update_timeout(Scsi_Cmnd * SCset, int timeout)
{
- unsigned int i, least, used;
+ unsigned int least, used, host;
+ unsigned int oldto;
+ Scsi_Cmnd * SCpnt = NULL;
cli();
@@ -1076,9 +1190,23 @@ static void update_timeout(void)
update_timeout.
*/
- for (i = 0, least = 0xffffffff; i < MAX_SCSI_HOSTS; ++i)
- if (host_timeout[i] > 0 && (host_timeout[i] -= used) < least)
- least = host_timeout[i];
+ oldto = 0;
+
+ if(SCset){
+ oldto = SCset->timeout - used;
+ SCset->timeout = timeout + used;
+ };
+
+ least = 0xffffffff;
+
+ for(host = 0; host < max_scsi_hosts; host++) {
+ SCpnt = host_queue[host];
+ while (SCpnt){
+ if (SCpnt->timeout > 0 && (SCpnt->timeout -= used) < least)
+ least = SCpnt->timeout;
+ SCpnt = SCpnt->next;
+ };
+ };
/*
If something is due to timeout again, then we will set the next timeout
@@ -1097,17 +1225,86 @@ static void update_timeout(void)
timer_active &= ~(1 << SCSI_TIMER);
}
sti();
+ return oldto;
}
+
+
+static unsigned short * dma_malloc_freelist = NULL;
+static unsigned int dma_sectors = 0;
+unsigned int dma_free_sectors = 0;
+unsigned int need_isa_buffer = 0;
+static unsigned char * dma_malloc_buffer = NULL;
+
+char *scsi_malloc(unsigned int len)
+{
+ unsigned int nbits, mask;
+ int i, j;
+ if((len & 0x1ff) || len > 4096)
+ panic("Inappropriate buffer size requested");
+
+ cli();
+ nbits = len >> 9;
+ mask = (1 << nbits) - 1;
+
+ for(i=0;i < (dma_sectors >> 4); i++)
+ for(j=0; j<17-nbits; j++){
+ if ((dma_malloc_freelist[i] & (mask << j)) == 0){
+ dma_malloc_freelist[i] |= (mask << j);
+ sti();
+ dma_free_sectors -= nbits;
+#ifdef DEBUG
+ printk("SMalloc: %d %x ",len, dma_malloc_buffer + (i << 13) + (j << 9));
+#endif
+ return (void*) ((unsigned long) dma_malloc_buffer + (i << 13) + (j << 9));
+ };
+ };
+ sti();
+ return NULL; /* Nope. No more */
+}
+
+int scsi_free(char *obj, unsigned int len)
+{
+ int offset;
+ int page, sector, nbits, mask;
+
+#ifdef DEBUG
+ printk("Sfree %x %d\n",obj, len);
+#endif
+
+ offset = ((int) obj) - ((int) dma_malloc_buffer);
+
+ if (offset < 0) panic("Bad offset");
+ page = offset >> 13;
+ sector = offset >> 9;
+ if(sector >= dma_sectors) panic ("Bad page");
+
+ sector = (offset >> 9) & 15;
+ nbits = len >> 9;
+ mask = (1 << nbits) - 1;
+
+ if ((mask << sector) > 0xffff) panic ("Bad memory alignment");
+
+ cli();
+ if(dma_malloc_freelist[page] & (mask << sector) != (mask<<sector))
+ panic("Trying to free unused memory");
+
+ dma_free_sectors += nbits;
+ dma_malloc_freelist[page] &= ~(mask << sector);
+ sti();
+ return 0;
+}
+
/*
scsi_dev_init() is our initialization routine, which inturn calls host
initialization, bus scanning, and sd/st initialization routines. It
should be called from main().
*/
-static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0};
unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end)
{
int i;
+ int host;
+ Scsi_Cmnd * SCpnt;
#ifdef FOO_ON_YOU
return;
#endif
@@ -1115,60 +1312,123 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end
timer_table[SCSI_TIMER].expires = 0;
scsi_init(); /* initialize all hosts */
-/*
- * Set up sense command in each host structure.
- */
- for (i = 0; i < MAX_SCSI_HOSTS; ++i)
- {
- memcpy ((void *) last_cmnd[i].sense_cmnd, (void *) generic_sense,
- 6);
+ for (i = 0; i < max_scsi_hosts; ++i)
last_reset[i] = 0;
- }
+ scsi_devices = (Scsi_Device *) memory_start;
scan_scsis(); /* scan for scsi devices */
-
-#ifdef CONFIG_BLK_DEV_SD
- memory_start = sd_init(memory_start, memory_end); /* init scsi disks */
-#endif
-
-#ifdef CONFIG_BLK_DEV_ST
- memory_start = st_init(memory_start, memory_end); /* init scsi tapes */
-#endif
-
-#ifdef CONFIG_BLK_DEV_SR
+ memory_start += NR_SCSI_DEVICES * sizeof(Scsi_Device);
+
+ memory_start = sd_init1(memory_start, memory_end);
+ memory_start = st_init1(memory_start, memory_end);
+ memory_start = sr_init1(memory_start, memory_end);
+
+ last_cmnd = (Scsi_Cmnd *) memory_start;
+
+ SCpnt = last_cmnd;
+
+ for (i=0; i< NR_SCSI_DEVICES; i++) {
+ int j;
+ switch (scsi_devices[i].type)
+ {
+ case TYPE_TAPE :
+ st_attach(&scsi_devices[i]);
+ break;
+ case TYPE_ROM:
+ sr_attach(&scsi_devices[i]);
+ break;
+ case TYPE_DISK:
+ sd_attach(&scsi_devices[i]);
+ default:
+ break;
+ };
+ if(scsi_devices[i].type != -1){
+ for(j=0;j<scsi_hosts[scsi_devices[i].host_no].cmd_per_lun;j++){
+ SCpnt->host = scsi_devices[i].host_no;
+ SCpnt->target = scsi_devices[i].id;
+ SCpnt->lun = scsi_devices[i].lun;
+ SCpnt->index = i;
+ SCpnt->request.dev = -1; /* Mark not busy */
+ SCpnt->use_sg = 0;
+ host = scsi_devices[i].host_no;
+ if(host_queue[host])
+ host_queue[host]->prev = SCpnt;
+ SCpnt->next = host_queue[host];
+ SCpnt->prev = NULL;
+ host_queue[host] = SCpnt;
+ SCpnt++;
+ };
+ };
+ };
+
+ memory_start = (int) SCpnt;
+
+ if (NR_SD > 0 || NR_SR > 0 || NR_ST > 0)
+ dma_sectors = 16; /* Base value we use */
+
+ for (i = 0; i < NR_SCSI_DEVICES; ++i) {
+ int host;
+ host = scsi_devices[i].host_no;
+
+ if(scsi_devices[i].type != TYPE_TAPE)
+ dma_sectors += ((scsi_hosts[host].sg_tablesize *
+ sizeof(struct scatterlist) + 511) >> 9) *
+ scsi_hosts[host].cmd_per_lun;
+
+ if(scsi_hosts[host].unchecked_isa_dma &&
+ memory_end > ISA_DMA_THRESHOLD &&
+ scsi_devices[i].type != TYPE_TAPE) {
+ dma_sectors += 32 * scsi_hosts[host].cmd_per_lun;
+ need_isa_buffer++;
+ };
+ };
+
+ dma_sectors = (dma_sectors + 15) & 0xfff0;
+ dma_free_sectors = dma_sectors; /* This must be a multiple of 16 */
+
+ memory_start = (memory_start + 3) & 0xfffffffc;
+ dma_malloc_freelist = (unsigned short *) memory_start;
+ memory_start += dma_sectors >> 3;
+ memset(dma_malloc_freelist, 0, dma_sectors >> 3);
+
+ if(memory_start & 1) memory_start++; /* Some host adapters require
+ buffers to be word aligned */
+ dma_malloc_buffer = (char *) memory_start;
+ memory_start += dma_sectors << 9;
+
+ memory_start = sd_init(memory_start, memory_end); /* init scsi disks */
+ memory_start = st_init(memory_start, memory_end); /* init scsi tapes */
memory_start = sr_init(memory_start, memory_end);
-#endif
return memory_start;
}
-#endif
static void print_inquiry(unsigned char *data)
{
int i;
- printk(" Vendor:");
- for (i = 8; i < 15; i++)
+ printk(" Vendor: ");
+ for (i = 8; i < 16; i++)
{
- if (data[i] >= 20)
+ if (data[i] >= 20 && i < data[4] + 5)
printk("%c", data[i]);
else
printk(" ");
}
- printk(" Model:");
- for (i = 16; i < 31; i++)
+ printk(" Model: ");
+ for (i = 16; i < 32; i++)
{
- if (data[i] >= 20)
+ if (data[i] >= 20 && i < data[4] + 5)
printk("%c", data[i]);
else
printk(" ");
}
- printk(" Rev:");
- for (i = 32; i < 35; i++)
+ printk(" Rev: ");
+ for (i = 32; i < 36; i++)
{
- if (data[i] >= 20)
+ if (data[i] >= 20 && i < data[4] + 5)
printk("%c", data[i]);
else
printk(" ");
@@ -1178,7 +1438,7 @@ static void print_inquiry(unsigned char *data)
i = data[0] & 0x1f;
- printk(" Type: %s ", i == 0x00 ? "Direct-Access " :
+ printk(" Type: %s ", i == 0x00 ? "Direct-Access " :
i == 0x01 ? "Sequential-Access" :
i == 0x02 ? "Printer " :
i == 0x03 ? "Processor " :
@@ -1189,6 +1449,9 @@ static void print_inquiry(unsigned char *data)
i == 0x08 ? "Medium Changer " :
i == 0x09 ? "Communications " :
"Unknown " );
- printk("ANSI SCSI revision: %02x\n", data[2] & 0x07);
+ printk(" ANSI SCSI revision: %02x", data[2] & 0x07);
+ if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1)
+ printk(" CCS\n");
+ else
+ printk("\n");
}
-
diff --git a/kernel/blk_drv/scsi/scsi.h b/kernel/blk_drv/scsi/scsi.h
index 14b9dde..0528775 100644
--- a/kernel/blk_drv/scsi/scsi.h
+++ b/kernel/blk_drv/scsi/scsi.h
@@ -4,10 +4,15 @@
* Drew Eckhardt
*
* <drew@colorado.edu>
+ *
+ * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to
+ * add scatter-gather, multiple outstanding request, and other
+ * enhancements.
*/
#ifndef _SCSI_H
- #define _SCSI_H
+#define _SCSI_H
+
/*
$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/scsi.h,v 1.1 1992/07/24 06:27:38 root Exp root $
@@ -24,18 +29,24 @@
#define REZERO_UNIT 0x01
#define REQUEST_SENSE 0x03
#define FORMAT_UNIT 0x04
+#define READ_BLOCK_LIMITS 0x05
#define REASSIGN_BLOCKS 0x07
#define READ_6 0x08
#define WRITE_6 0x0a
#define SEEK_6 0x0b
+#define READ_REVERSE 0x0f
+#define WRITE_FILEMARKS 0x10
+#define SPACE 0x11
#define INQUIRY 0x12
+#define RECOVER_BUFFERED_DATA 0x14
#define MODE_SELECT 0x15
#define RESERVE 0x16
#define RELEASE 0x17
#define COPY 0x18
+#define ERASE 0x19
#define MODE_SENSE 0x1a
#define START_STOP 0x1b
-#define RECIEVE_DAIGNOSTIC 0x1c
+#define RECEIVE_DIAGNOSTIC 0x1c
#define SEND_DIAGNOSTIC 0x1d
#define ALLOW_MEDIUM_REMOVAL 0x1e
@@ -49,8 +60,20 @@
#define SEARCH_EQUAL 0x31
#define SEARCH_LOW 0x32
#define SET_LIMITS 0x33
+#define PRE_FETCH 0x34
+#define SYNCRONIZE_CACHE 0x35
+#define LOCK_UNLOCK_CACHE 0x36
+#define READ_DEFECT_DATA 0x37
#define COMPARE 0x39
#define COPY_VERIFY 0x3a
+#define WRITE_BUFFER 0x3b
+#define READ_BUFFER 0x3c
+#define READ_LONG 0x3e
+#define CHANGE_DEFINITION 0x40
+#define LOG_SELECT 0x4c
+#define LOG_SENSE 0x4d
+#define MODE_SELECT_10 0x55
+#define MODE_SENSE_10 0x5a
#define COMMAND_SIZE(opcode) ((opcode) ? ((opcode) > 0x20 ? 10 : 6) : 0)
@@ -212,8 +235,10 @@
*/
typedef struct scsi_device {
- unsigned char host_no, id, lun;
+ unsigned char host_no, id, lun, index;
int access_count; /* Count of open channels/mounts */
+ struct wait_queue * device_wait; /* Used to wait if device is busy */
+ char type;
unsigned writeable:1;
unsigned removable:1;
unsigned random:1;
@@ -238,35 +263,203 @@ typedef struct scsi_device {
These are the SCSI devices available on the system.
*/
-#define MAX_SCSI_DEVICE 4
extern int NR_SCSI_DEVICES;
-extern Scsi_Device scsi_devices[MAX_SCSI_DEVICE];
+extern Scsi_Device * scsi_devices;
/*
- scsi_abort aborts the current command that is executing on host host.
- The error code, if non zero is returned in the host byte, otherwise
- DID_ABORT is returned in the hostbyte.
+ Initializes all SCSI devices. This scans all scsi busses.
*/
-extern int scsi_abort (int host, int code);
+extern unsigned long scsi_dev_init (unsigned long, unsigned long);
+
+struct scatterlist {
+ char * address; /* Location data is to be transferred to */
+ char * alt_address; /* Location of actual if address is a
+ dma indirect buffer. NULL otherwise */
+ unsigned short length;
+ };
+
+#define ISA_DMA_THRESHOLD (0x00ffffff)
+
+char * scsi_malloc(unsigned int);
+int scsi_free(char *, unsigned int);
+extern unsigned int dma_free_sectors; /* How much room do we have left */
+extern unsigned int need_isa_buffer; /* True if some devices need indirection
+ buffers */
/*
- Initializes all SCSI devices. This scans all scsi busses.
+ The Scsi_Cmnd structure is used by scsi.c internally, and for communication with
+ low level drivers that support multiple outstanding commands.
*/
+typedef struct scsi_pointer {
+ char * ptr; /* data pointer */
+ int this_residual; /* left in this buffer */
+ struct scatterlist *buffer; /* which buffer */
+ int buffers_residual; /* how many buffers left */
+
+ volatile int Status;
+ volatile int Message;
+ volatile int have_data_in;
+ volatile int sent_command;
+ volatile int phase;
+} Scsi_Pointer;
+
+typedef struct scsi_cmnd {
+ int host;
+ unsigned char target, lun, index;
+ struct scsi_cmnd *next, *prev;
+
+/* These elements define the operation we are about to perform */
+ unsigned char cmnd[10];
+ unsigned request_bufflen; /* Actual request size */
+
+ void * request_buffer; /* Actual requested buffer */
+
+/* These elements define the operation we ultimately want to perform */
+ unsigned char data_cmnd[10];
+ unsigned short use_sg; /* Number of pieces of scatter-gather */
+ unsigned short sglist_len; /* size of malloc'd scatter-gather list */
+ unsigned bufflen; /* Size of data buffer */
+ void *buffer; /* Data buffer */
+
+ struct request request; /* A copy of the command we are working on*/
+
+ unsigned char sense_buffer[16]; /* Sense for this command, if needed*/
-extern unsigned long scsi_dev_init (unsigned long, unsigned long);
+ int retries;
+ int allowed;
+ int timeout_per_command, timeout_total, timeout;
/*
- You guesed it. This sends a command to the selected SCSI host
+ * We handle the timeout differently if it happens when a reset,
+ * abort, etc are in process.
+ */
-extern void print_inquiry(unsigned char *data);
+ unsigned char internal_timeout;
-*/
+ unsigned flags;
+
+/* These variables are for the cdrom only. Once we have variable size buffers
+ in the buffer cache, they will go away. */
+ int this_count;
+/* End of special cdrom variables */
+
+ /* Low-level done function - can be used by low-level driver to point
+ to completion function. Not used by mid/upper level code. */
+ void (*scsi_done)(struct scsi_cmnd *);
+
+ void (*done)(struct scsi_cmnd *); /* Mid-level done function */
+
+/* The following fields can be written to by the host specific code.
+ Everything else should be left alone. */
+
+ Scsi_Pointer SCp; /* Scratchpad used by some host adapters */
+
+ unsigned char * host_scribble; /* The host adapter is allowed to
+ call scsi_malloc and get some memory
+ and hang it here. The host adapter
+ is also expected to call scsi_free
+ to release this memory. (The memory
+ obtained by scsi_malloc is guaranteed
+ to be at an address < 16Mb). */
+
+ int result; /* Status code from lower level driver */
+ } Scsi_Cmnd;
+/*
+ scsi_abort aborts the current command that is executing on host host.
+ The error code, if non zero is returned in the host byte, otherwise
+ DID_ABORT is returned in the hostbyte.
+*/
+extern int scsi_abort (Scsi_Cmnd *, int code);
+
+extern void scsi_do_cmd (Scsi_Cmnd *, const void *cmnd ,
+ void *buffer, unsigned bufflen, void (*done)(struct scsi_cmnd *),
+ int timeout, int retries);
+
+
+extern Scsi_Cmnd * allocate_device(struct request **, int, int);
+
+extern Scsi_Cmnd * request_queueable(struct request *, int);
+
+extern int scsi_reset (Scsi_Cmnd *);
+
+extern int max_scsi_hosts;
+extern int MAX_SD, NR_SD, MAX_ST, NR_ST, MAX_SR, NR_SR;
+extern unsigned long sd_init(unsigned long, unsigned long);
+extern unsigned long sd_init1(unsigned long, unsigned long);
+extern void sd_attach(Scsi_Device *);
+
+extern unsigned long sr_init(unsigned long, unsigned long);
+extern unsigned long sr_init1(unsigned long, unsigned long);
+extern void sr_attach(Scsi_Device *);
+
+extern unsigned long st_init(unsigned long, unsigned long);
+extern unsigned long st_init1(unsigned long, unsigned long);
+extern void st_attach(Scsi_Device *);
+
+#if defined(MAJOR_NR) && (MAJOR_NR != 9)
+static void end_scsi_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors)
+{
+ struct request * req;
+ struct buffer_head * bh;
+ struct task_struct * p;
+
+ req = &SCpnt->request;
+ req->errors = 0;
+ if (!uptodate) {
+ printk(DEVICE_NAME " I/O error\n\r");
+ printk("dev %04x, sector %d\n\r",req->dev,req->sector);
+ }
+
+ do {
+ if ((bh = req->bh) != NULL) {
+ req->bh = bh->b_reqnext;
+ req->nr_sectors -= bh->b_size >> 9;
+ req->sector += bh->b_size >> 9;
+ bh->b_reqnext = NULL;
+ bh->b_uptodate = uptodate;
+ unlock_buffer(bh);
+ sectors -= bh->b_size >> 9;
+ if ((bh = req->bh) != NULL) {
+ req->current_nr_sectors = bh->b_size >> 9;
+ if (req->nr_sectors < req->current_nr_sectors) {
+ req->nr_sectors = req->current_nr_sectors;
+ printk("end_scsi_request: buffer-list destroyed\n");
+ }
+ }
+ }
+ } while(sectors && bh);
+ if (req->bh){
+ req->buffer = bh->b_data;
+ return;
+ };
+ DEVICE_OFF(req->dev);
+ if ((p = req->waiting) != NULL) {
+ req->waiting = NULL;
+ p->state = TASK_RUNNING;
+ if (p->counter > current->counter)
+ need_resched = 1;
+ }
+ req->dev = -1;
+ wake_up(&scsi_devices[SCpnt->index].device_wait);
+ return;
+}
+#endif
-extern void scsi_do_cmd (int host, unsigned char target, const void *cmnd ,
- void *buffer, unsigned bufflen, void (*done)(int,int),
- int timeout, unsigned char *sense_buffer, int retries);
+#define SCSI_SLEEP(QUEUE, CONDITION) { \
+ if (CONDITION) { \
+ struct wait_queue wait = { current, NULL}; \
+ add_wait_queue(QUEUE, &wait); \
+sleep_repeat: \
+ current->state = TASK_UNINTERRUPTIBLE; \
+ if (CONDITION) { \
+ schedule(); \
+ goto sleep_repeat; \
+ } \
+ remove_wait_queue(QUEUE, &wait); \
+ current->state = TASK_RUNNING; \
+ }; }
-extern int scsi_reset (int host);
#endif
+
diff --git a/kernel/blk_drv/scsi/scsi_debug.c b/kernel/blk_drv/scsi/scsi_debug.c
new file mode 100644
index 0000000..d17ab23
--- /dev/null
+++ b/kernel/blk_drv/scsi/scsi_debug.c
@@ -0,0 +1,515 @@
+/* $Id: scsi_debug.c,v 1.1 1992/07/24 06:27:38 root Exp root $
+ * linux/kernel/scsi_debug.c
+ *
+ * Copyright (C) 1992 Eric Youngdale
+ * Simulate a host adapter with 2 disks attached. Do a lot of checking
+ * to make sure that we are not getting blocks mixed up, and panic if
+ * anything out of the ordinary is seen.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/head.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/genhd.h>
+#include <linux/fs.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include "../blk.h"
+#include "scsi.h"
+#include "hosts.h"
+
+/* Number of real scsi disks that will be detected ahead of time */
+static int NR_REAL=-1;
+
+#define NR_BLK_DEV 12
+#define MAJOR_NR 8
+#define START_PARTITION 4
+#define SCSI_DEBUG_TIMER 20
+/* Number of jiffies to wait before completing a command */
+#define DISK_SPEED 10
+#define CAPACITY (0x80000)
+
+static int starts[] = {4, 1000, 50000, CAPACITY, 0};
+static int npart = 0;
+
+#include "scsi_debug.h"
+#ifdef DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+#define VERIFY1_DEBUG(RW) \
+ if (bufflen != 1024) {printk("%d", bufflen); panic("(1)Bad bufflen");}; \
+ start = 0; \
+ if ((SCpnt->request.dev & 0xf) != 0) start = starts[(SCpnt->request.dev & 0xf) - 1]; \
+ if (bh){ \
+ if (bh->b_size != 1024) panic ("Wrong bh size"); \
+ if ((bh->b_blocknr << 1) + start != block) \
+ { printk("Wrong bh block# %d %d ",bh->b_blocknr, block); \
+ panic ("Wrong bh block#");}; \
+ if (bh->b_dev != SCpnt->request.dev) panic ("Bad bh target");\
+ };
+
+#if 0
+/* This had been in the VERIFY_DEBUG macro, but it fails if there is already
+ a disk on the system */
+ if ((SCpnt->request.dev & 0xfff0) != ((target + NR_REAL) << 4) +(MAJOR_NR << 8)){ \
+ printk("Dev #s %x %x ",SCpnt->request.dev, target); \
+ panic ("Bad target");}; \
+
+#endif
+
+#define VERIFY_DEBUG(RW) \
+ if (bufflen != 1024 && (!SCpnt->use_sg)) {printk("%x %d\n ",bufflen, SCpnt->use_sg); panic("Bad bufflen");}; \
+ start = 0; \
+ if ((SCpnt->request.dev & 0xf) > npart) panic ("Bad partition"); \
+ if ((SCpnt->request.dev & 0xf) != 0) start = starts[(SCpnt->request.dev & 0xf) - 1]; \
+ if (SCpnt->request.cmd != RW) panic ("Wrong operation"); \
+ if (SCpnt->request.sector + start != block) panic("Wrong block."); \
+ if (SCpnt->request.current_nr_sectors != 2 && (!SCpnt->use_sg)) panic ("Wrong # blocks"); \
+ if (SCpnt->request.bh){ \
+ if (SCpnt->request.bh->b_size != 1024) panic ("Wrong bh size"); \
+ if ((SCpnt->request.bh->b_blocknr << 1) + start != block) \
+ { printk("Wrong bh block# %d %d ",SCpnt->request.bh->b_blocknr, block); \
+ panic ("Wrong bh block#");}; \
+ if (SCpnt->request.bh->b_dev != SCpnt->request.dev) panic ("Bad bh target");\
+ };
+
+static volatile void (*do_done[SCSI_DEBUG_MAILBOXES])(Scsi_Cmnd *) = {NULL, };
+static int scsi_debug_host = 0;
+extern void scsi_debug_interrupt();
+
+volatile Scsi_Cmnd * SCint[SCSI_DEBUG_MAILBOXES] = {NULL,};
+static volatile unsigned int timeout[SCSI_DEBUG_MAILBOXES] ={0,};
+
+static char sense_buffer[128] = {0,};
+
+static void scsi_dump(Scsi_Cmnd * SCpnt, int flag){
+ int i;
+#if 0
+ unsigned char * pnt;
+#endif
+ unsigned int * lpnt;
+ struct scatterlist * sgpnt = NULL;
+ printk("use_sg: %d",SCpnt->use_sg);
+ if (SCpnt->use_sg){
+ sgpnt = (struct scatterlist *) SCpnt->buffer;
+ for(i=0; i<SCpnt->use_sg; i++) {
+ lpnt = (int *) sgpnt[i].alt_address;
+ printk(":%x %x %d\n",sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
+ if (lpnt) printk(" (Alt %x) ",lpnt[15]);
+ };
+ } else {
+ printk("nosg: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer,
+ SCpnt->bufflen);
+ lpnt = (int *) SCpnt->request.buffer;
+ if (lpnt) printk(" (Alt %x) ",lpnt[15]);
+ };
+ lpnt = (unsigned int *) SCpnt;
+ for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {
+ if ((i & 7) == 0) printk("\n");
+ printk("%x ",*lpnt++);
+ };
+ printk("\n");
+ if (flag == 0) return;
+ lpnt = (unsigned int *) sgpnt[0].alt_address;
+ for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {
+ if ((i & 7) == 0) printk("\n");
+ printk("%x ",*lpnt++);
+ };
+#if 0
+ printk("\n");
+ lpnt = (unsigned int *) sgpnt[0].address;
+ for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {
+ if ((i & 7) == 0) printk("\n");
+ printk("%x ",*lpnt++);
+ };
+ printk("\n");
+#endif
+ printk("DMA free %d sectors.\n", dma_free_sectors);
+}
+
+int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
+{
+ unchar *cmd = (unchar *) SCpnt->cmnd;
+ struct partition * p;
+ int block, start;
+ struct buffer_head * bh = NULL;
+ unsigned char * buff;
+ int nbytes, sgcount;
+ int scsi_debug_errsts;
+ struct scatterlist * sgpnt;
+ int target = SCpnt->target;
+ int bufflen = SCpnt->request_bufflen;
+ int i;
+ sgcount = 0;
+ sgpnt = NULL;
+
+ DEB(if (target > 1) { SCpnt->result = DID_TIME_OUT << 16;done(SCpnt);return 0;});
+
+ buff = (unsigned char *) SCpnt->request_buffer;
+
+ if(target>=2 || SCpnt->lun != 0) {
+ SCpnt->result = DID_NO_CONNECT << 16;
+ done(SCpnt);
+ return 0;
+ };
+
+ switch(*cmd){
+ case REQUEST_SENSE:
+ printk("Request sense...\n");
+#ifndef DEBUG
+ { int i;
+ printk("scsi_debug: Requesting sense buffer (%x %x %x %d):", SCpnt, buff, done, bufflen);
+ for(i=0;i<12;i++) printk("%d ",sense_buffer[i]);
+ printk("\n");
+ };
+#endif
+ memset(buff, 0, bufflen);
+ memcpy(buff, sense_buffer, bufflen);
+ memset(sense_buffer, 0, sizeof(sense_buffer));
+ SCpnt->result = 0;
+ done(SCpnt);
+ return 0;
+ case ALLOW_MEDIUM_REMOVAL:
+ if(cmd[4]) printk("Medium removal inhibited...");
+ else printk("Medium removal enabled...");
+ scsi_debug_errsts = 0;
+ break;
+ case INQUIRY:
+ printk("Inquiry...(%x %d)\n", buff, bufflen);
+ memset(buff, 0, bufflen);
+ buff[0] = TYPE_DISK;
+ buff[1] = 0x80; /* Removable disk */
+ buff[2] = 1;
+ memcpy(&buff[8],"Foo Inc",7);
+ memcpy(&buff[16],"XYZZY",5);
+ memcpy(&buff[32],"1",1);
+ scsi_debug_errsts = 0;
+ break;
+ case TEST_UNIT_READY:
+ printk("Test unit ready.\n");
+ if (buff)
+ memset(buff, 0, bufflen);
+ scsi_debug_errsts = 0;
+ break;
+ case READ_CAPACITY:
+ printk("Read Capacity\n");
+ if(NR_REAL < 0) NR_REAL = (SCpnt->request.dev >> 4) & 0x0f;
+ memset(buff, 0, bufflen);
+ buff[0] = (CAPACITY >> 24);
+ buff[1] = (CAPACITY >> 16) & 0xff;
+ buff[2] = (CAPACITY >> 8) & 0xff;
+ buff[3] = CAPACITY & 0xff;
+ buff[6] = 2; /* 512 byte sectors */
+ scsi_debug_errsts = 0;
+ break;
+ case READ_10:
+ case READ_6:
+#ifdef DEBUG
+ printk("Read...");
+#endif
+ if ((*cmd) == READ_10)
+ block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
+ else
+ block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
+ VERIFY_DEBUG(READ);
+ printk("(r%d)",SCpnt->request.nr_sectors);
+ nbytes = bufflen;
+ if(SCpnt->use_sg){
+ sgcount = 0;
+ sgpnt = (struct scatterlist *) buff;
+ buff = sgpnt[sgcount].address;
+ bufflen = sgpnt[sgcount].length;
+ bh = SCpnt->request.bh;
+ };
+ scsi_debug_errsts = 0;
+ do{
+ VERIFY1_DEBUG(READ);
+ memset(buff, 0, bufflen);
+/* If this is block 0, then we want to read the partition table for this
+ device. Let's make one up */
+ if(block == 0 && target == 0) {
+ *((unsigned short *) (buff+510)) = 0xAA55;
+ p = (struct partition* ) (buff + 0x1be);
+ npart = 0;
+ while(starts[npart+1]){
+ p->start_sect = starts[npart];
+ p->nr_sects = starts[npart+1] - starts [npart];
+ p->sys_ind = 0x81; /* Linux partition */
+ p++;
+ npart++;
+ };
+ scsi_debug_errsts = 0;
+ break;
+ };
+#ifdef DEBUG
+ if (SCpnt->use_sg) printk("Block %x (%d %d)\n",block, SCpnt->request.nr_sectors,
+ SCpnt->request.current_nr_sectors);
+#endif
+ /* Simulate a disk change */
+ if(block == 0xfff0) {
+ sense_buffer[0] = 0x70;
+ sense_buffer[2] = UNIT_ATTENTION;
+ starts[0] += 10;
+ starts[1] += 10;
+ starts[2] += 10;
+
+#ifdef DEBUG
+ { int i;
+ printk("scsi_debug: Filling sense buffer:");
+ for(i=0;i<12;i++) printk("%d ",sense_buffer[i]);
+ printk("\n");
+ };
+#endif
+ scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
+ break;
+ } /* End phony disk change code */
+ memset(buff, 0, bufflen);
+ memcpy(buff, &target, sizeof(target));
+ memcpy(buff+sizeof(target), cmd, 24);
+ memcpy(buff+60, &block, sizeof(block));
+ memcpy(buff+64, SCpnt, sizeof(Scsi_Cmnd));
+ nbytes -= bufflen;
+ if(SCpnt->use_sg){
+ memcpy(buff+128, bh, sizeof(struct buffer_head));
+ block += bufflen >> 9;
+ bh = bh->b_reqnext;
+ sgcount++;
+ if (nbytes) {
+ if(!bh) panic("Too few blocks for linked request.");
+ buff = sgpnt[sgcount].address;
+ bufflen = sgpnt[sgcount].length;
+ };
+ }
+ } while(nbytes);
+ if (SCpnt->use_sg && !scsi_debug_errsts)
+ if(bh) scsi_dump(SCpnt, 0);
+ break;
+ case WRITE_10:
+ case WRITE_6:
+#ifdef DEBUG
+ printk("Write\n");
+#endif
+ if ((*cmd) == WRITE_10)
+ block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
+ else
+ block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
+ VERIFY_DEBUG(WRITE);
+ printk("(w%d)",SCpnt->request.nr_sectors);
+ if (SCpnt->use_sg){
+ if ((bufflen >> 9) != SCpnt->request.nr_sectors)
+ panic ("Trying to write wrong number of blocks\n");
+ sgpnt = (struct scatterlist *) buff;
+ buff = sgpnt[sgcount].address;
+ };
+#if 0
+ if (block != *((unsigned long *) (buff+60))) {
+ printk("%x %x :",block, *((unsigned long *) (buff+60)));
+ scsi_dump(SCpnt,1);
+ panic("Bad block written.\n");
+ };
+#endif
+ scsi_debug_errsts = 0;
+ break;
+ default:
+ printk("Unknown command %d\n",*cmd);
+ SCpnt->result = DID_NO_CONNECT << 16;
+ done(SCpnt);
+ return 0;
+ };
+
+ cli();
+ for(i=0;i<SCSI_DEBUG_MAILBOXES; i++){
+ if (SCint[i] == 0) break;
+ };
+
+ if (i >= SCSI_DEBUG_MAILBOXES || SCint[i] != 0)
+ panic("Unable to find empty SCSI_DEBUG command slot.\n");
+
+ SCint[i] = SCpnt;
+
+ if (done) {
+ DEB(printk("scsi_debug_queuecommand: now waiting for interrupt "););
+ if (do_done[i])
+ printk("scsi_debug_queuecommand: Two concurrent queuecommand?\n");
+ else
+ do_done[i] = done;
+ }
+ else
+ printk("scsi_debug_queuecommand: done cant be NULL\n");
+
+ timeout[i] = jiffies+DISK_SPEED;
+
+/* If no timers active, then set this one */
+ if ((timer_active & (1 << SCSI_DEBUG_TIMER)) == 0) {
+ timer_table[SCSI_DEBUG_TIMER].expires = timeout[i];
+ timer_active |= 1 << SCSI_DEBUG_TIMER;
+ };
+
+ SCpnt->result = scsi_debug_errsts;
+ sti();
+
+#if 0
+ printk("Sending command (%d %x %d %d)...", i, done, timeout[i],jiffies);
+#endif
+
+ return 0;
+}
+
+volatile static int internal_done_flag = 0;
+volatile static int internal_done_errcode = 0;
+static void internal_done(Scsi_Cmnd * SCpnt)
+{
+ internal_done_errcode = SCpnt->result;
+ ++internal_done_flag;
+}
+
+int scsi_debug_command(Scsi_Cmnd * SCpnt)
+{
+ DEB(printk("scsi_debug_command: ..calling scsi_debug_queuecommand\n"));
+ scsi_debug_queuecommand(SCpnt, internal_done);
+
+ while (!internal_done_flag);
+ internal_done_flag = 0;
+ return internal_done_errcode;
+}
+
+/* A "high" level interrupt handler. This should be called once per jiffy
+ to simulate a regular scsi disk. We use a timer to do this. */
+
+static void scsi_debug_intr_handle(void)
+{
+ Scsi_Cmnd * SCtmp;
+ int i, pending;
+ void (*my_done)(Scsi_Cmnd *);
+ int to;
+
+ timer_table[SCSI_DEBUG_TIMER].expires = 0;
+ timer_active &= ~(1 << SCSI_DEBUG_TIMER);
+
+ repeat:
+ cli();
+ for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
+ if (SCint[i] == 0) continue;
+ if (timeout[i] == 0) continue;
+ if (timeout[i] <= jiffies) break;
+ };
+
+ if(i == SCSI_DEBUG_MAILBOXES){
+ pending = 0x7fffffff;
+ for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
+ if (SCint[i] == 0) continue;
+ if (timeout[i] == 0) continue;
+ if (timeout[i] <= jiffies) {sti(); goto repeat;};
+ if (timeout[i] > jiffies) {
+ if (pending > timeout[i]) pending = timeout[i];
+ continue;
+ };
+ };
+ if (pending && pending != 0x7fffffff) {
+ timer_table[SCSI_DEBUG_TIMER].expires =
+ (pending <= jiffies ? jiffies+1 : pending);
+ timer_active |= 1 << SCSI_DEBUG_TIMER;
+ };
+ sti();
+ return;
+ };
+
+ if(i < SCSI_DEBUG_MAILBOXES){
+ timeout[i] = 0;
+ my_done = do_done[i];
+ do_done[i] = NULL;
+ to = timeout[i];
+ timeout[i] = 0;
+ SCtmp = (Scsi_Cmnd *) SCint[i];
+ SCint[i] = NULL;
+ sti();
+
+ if (!my_done) {
+ printk("scsi_debug_intr_handle: Unexpected interrupt\n");
+ return;
+ }
+
+#ifdef DEBUG
+ printk("In intr_handle...");
+ printk("...done %d %x %d %d\n",i , my_done, to, jiffies);
+ printk("In intr_handle: %d %x %x\n",i, SCtmp, my_done);
+#endif
+
+ my_done(SCtmp);
+#ifdef DEBUG
+ printk("Called done.\n");
+#endif
+ };
+ goto repeat;
+}
+
+
+int scsi_debug_detect(int hostnum)
+{
+ scsi_debug_host = hostnum;
+ timer_table[SCSI_DEBUG_TIMER].fn = scsi_debug_intr_handle;
+ timer_table[SCSI_DEBUG_TIMER].expires = 0;
+ return 1;
+}
+
+int scsi_debug_abort(Scsi_Cmnd * SCpnt,int i)
+{
+ int j;
+ void (*my_done)(Scsi_Cmnd *);
+ DEB(printk("scsi_debug_abort\n"));
+ SCpnt->result = i << 16;
+ for(j=0;j<SCSI_DEBUG_MAILBOXES; j++) {
+ if(SCpnt == SCint[j]) {
+ my_done = do_done[j];
+ my_done(SCpnt);
+ cli();
+ timeout[j] = 0;
+ SCint[j] = NULL;
+ do_done[j] = NULL;
+ sti();
+ };
+ };
+ return 0;
+}
+
+int scsi_debug_biosparam(int size, int* info){
+ info[0] = 32;
+ info[1] = 64;
+ info[2] = (size + 2047) >> 11;
+ if (info[2] >= 1024) info[2] = 1024;
+ return 0;
+}
+
+int scsi_debug_reset(void)
+{
+ int i;
+ void (*my_done)(Scsi_Cmnd *);
+ DEB(printk("scsi_debug_reset called\n"));
+ for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
+ if (SCint[i] == NULL) continue;
+ SCint[i]->result = DID_ABORT << 16;
+ my_done = do_done[i];
+ my_done(SCint[i]);
+ cli();
+ SCint[i] = NULL;
+ do_done[i] = NULL;
+ timeout[i] = 0;
+ sti();
+ };
+ return 0;
+}
+
+char *scsi_debug_info(void)
+{
+ static char buffer[] = " "; /* looks nicer without anything here */
+ return buffer;
+}
+
+
diff --git a/kernel/blk_drv/scsi/scsi_debug.h b/kernel/blk_drv/scsi/scsi_debug.h
new file mode 100644
index 0000000..263fda3
--- /dev/null
+++ b/kernel/blk_drv/scsi/scsi_debug.h
@@ -0,0 +1,27 @@
+#ifndef _SCSI_DEBUG_H
+
+#include <linux/types.h>
+
+int scsi_debug_detect(int);
+int scsi_debug_command(Scsi_Cmnd *);
+int scsi_debug_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int scsi_debug_abort(Scsi_Cmnd *, int);
+int scsi_debug_biosparam(int, int*);
+char *scsi_debug_info(void);
+int scsi_debug_reset(void);
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+#define SCSI_DEBUG_MAILBOXES 8
+
+#define SCSI_DEBUG {"SCSI DEBUG", scsi_debug_detect, \
+ scsi_debug_info, scsi_debug_command, \
+ scsi_debug_queuecommand, \
+ scsi_debug_abort, \
+ scsi_debug_reset, \
+ NULL, \
+ scsi_debug_biosparam, \
+ SCSI_DEBUG_MAILBOXES, 7, SG_ALL, 1, 0, 1}
+#endif
diff --git a/kernel/blk_drv/scsi/scsi_ioctl.c b/kernel/blk_drv/scsi/scsi_ioctl.c
index 73c3ea9..213e416 100644
--- a/kernel/blk_drv/scsi/scsi_ioctl.c
+++ b/kernel/blk_drv/scsi/scsi_ioctl.c
@@ -1,6 +1,3 @@
-#include <linux/config.h>
-#ifdef CONFIG_SCSI
-
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/system.h>
@@ -10,6 +7,7 @@
#include <linux/sched.h>
#include <linux/string.h>
+#include "../blk.h"
#include "scsi.h"
#include "hosts.h"
#include "scsi_ioctl.h"
@@ -63,47 +61,42 @@ static int ioctl_probe(int dev, void *buffer)
* The output area is then filled in starting from the command byte.
*/
-static int the_result[MAX_SCSI_HOSTS] = {0,};
-
-static void scsi_ioctl_done (int host, int result)
+static void scsi_ioctl_done (Scsi_Cmnd * SCpnt)
{
- the_result[host] = result;
+ struct request * req;
+ struct task_struct * p;
+
+ req = &SCpnt->request;
+ req->dev = 0xfffe; /* Busy, but indicate request done */
+
+ if ((p = req->waiting) != NULL) {
+ req->waiting = NULL;
+ p->state = TASK_RUNNING;
+ if (p->counter > current->counter)
+ need_resched = 1;
+ }
}
-/* This function will operate certain scsi functions which require no
- data transfer */
-static int ioctl_internal_command(Scsi_Device *dev, char ** command)
+static int ioctl_internal_command(Scsi_Device *dev, char * cmd)
{
- char * cmd;
- int temp, host;
- char sense_buffer[256];
+ int host, result;
+ Scsi_Cmnd * SCpnt;
host = dev->host_no;
- cmd = command[0];
-
- do {
- cli();
- if (the_result[host]) {
- sti();
- while(the_result[host])
- /* nothing */;
- } else {
- the_result[host]=-1;
- sti();
- break;
- }
- } while (1);
- scsi_do_cmd(host, dev->id, cmd, NULL, 0,
+ SCpnt = allocate_device(NULL, dev->index, 1);
+ scsi_do_cmd(SCpnt, cmd, NULL, 0,
scsi_ioctl_done, MAX_TIMEOUT,
- sense_buffer, MAX_RETRIES);
+ MAX_RETRIES);
- while (the_result[host] == -1)
- /* nothing */;
- temp = the_result[host];
+ if (SCpnt->request.dev != 0xfffe){
+ SCpnt->request.waiting = current;
+ current->state = TASK_UNINTERRUPTIBLE;
+ while (SCpnt->request.dev != 0xfffe) schedule();
+ };
- if(driver_byte(the_result[host]) != 0)
- switch(sense_buffer[2] & 0xf) {
+ if(driver_byte(SCpnt->result) != 0)
+ switch(SCpnt->sense_buffer[2] & 0xf) {
case ILLEGAL_REQUEST:
printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n");
break;
@@ -115,7 +108,7 @@ static int ioctl_internal_command(Scsi_Device *dev, char ** command)
case UNIT_ATTENTION:
if (dev->removable){
dev->changed = 1;
- temp = 0; /* This is no longer considered an error */
+ SCpnt->result = 0; /* This is no longer considered an error */
printk("Disc change detected.\n");
break;
};
@@ -124,16 +117,18 @@ static int ioctl_internal_command(Scsi_Device *dev, char ** command)
dev->host_no,
dev->id,
dev->lun,
- the_result);
+ SCpnt->result);
printk("\tSense class %x, sense error %x, extended sense %x\n",
- sense_class(sense_buffer[0]),
- sense_error(sense_buffer[0]),
- sense_buffer[2] & 0xf);
+ sense_class(SCpnt->sense_buffer[0]),
+ sense_error(SCpnt->sense_buffer[0]),
+ SCpnt->sense_buffer[2] & 0xf);
};
- the_result[host] = 0;
- return temp;
+ result = SCpnt->result;
+ SCpnt->request.dev = -1; /* Mark as not busy */
+ wake_up(&scsi_devices[SCpnt->index].device_wait);
+ return result;
}
static int ioctl_command(Scsi_Device *dev, void *buffer)
@@ -141,8 +136,10 @@ static int ioctl_command(Scsi_Device *dev, void *buffer)
char buf[MAX_BUF];
char cmd[10];
char * cmd_in;
+ Scsi_Cmnd * SCpnt;
unsigned char opcode;
- int inlen, outlen, cmdlen, temp, host;
+ int inlen, outlen, cmdlen, host;
+ int result;
if (!buffer)
return -EINVAL;
@@ -158,29 +155,25 @@ static int ioctl_command(Scsi_Device *dev, void *buffer)
host = dev->host_no;
#ifndef DEBUG_NO_CMD
- do {
- cli();
- if (the_result[host]) {
- sti();
- while(the_result[host])
- /* nothing */;
- } else {
- the_result[host]=-1;
- sti();
- break;
- }
- } while (1);
- scsi_do_cmd(host, dev->id, cmd, buf, ((outlen > MAX_BUF) ?
+ SCpnt = allocate_device(NULL, dev->index, 1);
+
+ scsi_do_cmd(SCpnt, cmd, buf, ((outlen > MAX_BUF) ?
MAX_BUF : outlen), scsi_ioctl_done, MAX_TIMEOUT,
- buf, MAX_RETRIES);
+ MAX_RETRIES);
+
+ if (SCpnt->request.dev != 0xfffe){
+ SCpnt->request.waiting = current;
+ current->state = TASK_UNINTERRUPTIBLE;
+ while (SCpnt->request.dev != 0xfffe) schedule();
+ };
- while (the_result[host] == -1)
- /* nothing */;
- temp = the_result[host];
- the_result[host] = 0;
+ verify_area(cmd_in, (outlen > MAX_BUF) ? MAX_BUF : outlen);
memcpy_tofs ((void *) cmd_in, buf, (outlen > MAX_BUF) ? MAX_BUF : outlen);
- return temp;
+ result = SCpnt->result;
+ SCpnt->request.dev = -1; /* Mark as not busy */
+ wake_up(&scsi_devices[SCpnt->index].device_wait);
+ return result;
#else
{
int i;
@@ -208,11 +201,10 @@ static int ioctl_command(Scsi_Device *dev, void *buffer)
int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
{
char scsi_cmd[10];
- char * command[2];
if ((cmd != 0 && dev->id > NR_SCSI_DEVICES))
return -ENODEV;
- if ((cmd == 0 && dev->host_no > MAX_SCSI_HOSTS))
+ if ((cmd == 0 && dev->host_no > max_scsi_hosts))
return -ENODEV;
switch (cmd) {
@@ -226,8 +218,7 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
scsi_cmd[1] = dev->lun << 5;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
- command[0] = scsi_cmd;
- return ioctl_internal_command((Scsi_Device *) dev, command);
+ return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
break;
case SCSI_IOCTL_DOORUNLOCK:
if (!dev->removable) return 0;
@@ -235,18 +226,15 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
scsi_cmd[1] = dev->lun << 5;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
- command[0] = scsi_cmd;
- return ioctl_internal_command((Scsi_Device *) dev, command);
+ return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
case SCSI_IOCTL_TEST_UNIT_READY:
scsi_cmd[0] = TEST_UNIT_READY;
scsi_cmd[1] = dev->lun << 5;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = 0;
- command[0] = scsi_cmd;
- return ioctl_internal_command((Scsi_Device *) dev, command);
+ return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
break;
default :
return -EINVAL;
}
}
-#endif
diff --git a/kernel/blk_drv/scsi/scsi_ioctl.h b/kernel/blk_drv/scsi/scsi_ioctl.h
index 50769c0..531f27a 100644
--- a/kernel/blk_drv/scsi/scsi_ioctl.h
+++ b/kernel/blk_drv/scsi/scsi_ioctl.h
@@ -1,10 +1,6 @@
#ifndef _SCSI_IOCTL_H
#define _SCSI_IOCTL_H
-#ifndef _CONFIG_H
-#include <linux/config.h>
-#endif
-
#define SCSI_IOCTL_PROBE_HOST 0
#define SCSI_IOCTL_SEND_COMMAND 1
#define SCSI_IOCTL_TEST_UNIT_READY 2
@@ -16,14 +12,6 @@
#define SCSI_REMOVAL_PREVENT 1
#define SCSI_REMOVAL_ALLOW 0
-#ifdef CONFIG_BLK_DEV_SD
-/* Should start at 128 */
-#endif
-
-#ifdef CONFIG_BLK_DEV_SD
-/* Should start at 256 */
-#endif
-
#endif
diff --git a/kernel/blk_drv/scsi/sd.c b/kernel/blk_drv/scsi/sd.c
index 97fc97a..c8a4d00 100644
--- a/kernel/blk_drv/scsi/sd.c
+++ b/kernel/blk_drv/scsi/sd.c
@@ -1,14 +1,15 @@
/*
- * sd.c Copyright (C) 1992 Drew Eckhardt
+ * sd.c Copyright (C) 1992 Drew Eckhardt
* Linux scsi disk driver by
- * Drew Eckhardt
+ * Drew Eckhardt
*
* <drew@colorado.edu>
+ *
+ * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to
+ * add scatter-gather, multiple outstanding request, and other
+ * enhancements.
*/
-#include <linux/config.h>
-
-#ifdef CONFIG_BLK_DEV_SD
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -16,14 +17,15 @@
#include <linux/errno.h>
#include <asm/system.h>
+
+#define MAJOR_NR 8
+
+#include "../blk.h"
#include "scsi.h"
#include "hosts.h"
#include "sd.h"
#include "scsi_ioctl.h"
-#define MAJOR_NR 8
-
-#include "../blk.h"
#include <linux/genhd.h>
/*
@@ -38,28 +40,12 @@ static const char RCSid[] = "$Header:";
#define SD_TIMEOUT 200
-#define ISA_DMA_THRESHOLD (0x00ffffff)
-struct hd_struct sd[MAX_SD << 4];
-
-/* For a > 16 Mb system, we may need an intermediate buffer for data */
-
-struct block_buffer
- {
- unsigned long int use;
- unsigned char buffer[4096];
- };
-
-static struct block_buffer * bb = NULL;
+struct hd_struct * sd;
int NR_SD=0;
-Scsi_Disk rscsi_disks[MAX_SD];
-static int sd_sizes[MAX_SD << 4] = {0, };
-static int this_count, total_count = 0;
-static int the_result;
-static int boot_init_done = 0;
-
-static char sense_buffer[255];
-int slow_scsi_io = -1; /* This is set by aha1542.c, and others, if needed */
+int MAX_SD=0;
+Scsi_Disk * rscsi_disks;
+int * sd_sizes;
/* used to re-read partitions. */
extern void resetup_one_dev(struct gendisk *, unsigned int);
@@ -68,6 +54,8 @@ extern int sd_ioctl(struct inode *, struct file *, unsigned int, unsigned int);
static sd_init_onedisk(int);
+static void requeue_sd_request (Scsi_Cmnd * SCpnt);
+
static int sd_open(struct inode * inode, struct file * filp)
{
int target;
@@ -75,7 +63,7 @@ static int sd_open(struct inode * inode, struct file * filp)
if(target >= NR_SD || !rscsi_disks[target].device)
return -EACCES; /* No such device */
-
+
/* Make sure that only one process can do a check_change_disk at one time.
This is also used to lock out further access when the partition table is being re-read. */
@@ -115,7 +103,6 @@ static void sd_geninit (void) {
sd_gendisk.nr_real = NR_SD;
}
-
static struct file_operations sd_fops = {
NULL, /* lseek - default */
block_read, /* read - general block-dev read */
@@ -133,12 +120,12 @@ static struct gendisk sd_gendisk = {
"sd", /* Major name */
4, /* Bits to shift to get real from partition */
1 << 4, /* Number of partitions per real */
- MAX_SD, /* maximum number of real */
+ 0, /* maximum number of real */
sd_geninit, /* init function */
- sd, /* hd struct */
- sd_sizes, /* block sizes */
+ NULL, /* hd struct */
+ NULL, /* block sizes */
0, /* number */
- (void *) rscsi_disks, /* internal */
+ NULL, /* internal */
NULL /* next */
};
@@ -148,89 +135,106 @@ static struct gendisk sd_gendisk = {
will take on of several actions based on success or failure.
*/
-static void rw_intr (int host, int result)
+static void rw_intr (Scsi_Cmnd *SCpnt)
{
- if (HOST != host)
- panic ("sd.o : rw_intr() recieving interrupt for different host.");
+ int result = SCpnt->result;
+ int this_count = SCpnt->bufflen >> 9;
#ifdef DEBUG
- printk("sd%d : rw_intr(%d, %x)\n", MINOR(CURRENT->dev), host, result);
+ printk("sd%d : rw_intr(%d, %x)\n", MINOR(SCpnt->request.dev), SCpnt->host, result);
#endif
/*
- First case : we assume that the command succeeded. One of two things will
- happen here. Either we will be finished, or there will be more
- sectors that we were unable to read last time.
+ First case : we assume that the command succeeded. One of two things will
+ happen here. Either we will be finished, or there will be more
+ sectors that we were unable to read last time.
*/
- if (!result) {
- if (bb && bb[DEVICE_NR(CURRENT->dev)].use && CURRENT->cmd == READ)
- {
- memcpy((char *)CURRENT->buffer,
- bb[DEVICE_NR(CURRENT->dev)].buffer,
- this_count << 9);
+ if (!result) {
+
#ifdef DEBUG
- printk("R");
+ printk("sd%d : %d sectors remain.\n", MINOR(SCpnt->request.dev), SCpnt->request.nr_sectors);
+ printk("use_sg is %d\n ",SCpnt->use_sg);
#endif
- };
- if(bb) bb[DEVICE_NR(CURRENT->dev)].use = 0;
-
- CURRENT->nr_sectors -= this_count;
- if (slow_scsi_io == host) {
- total_count -= this_count;
- if(total_count){
- CURRENT->sector += this_count;
- CURRENT->buffer += (this_count << 9);
- do_sd_request();
- return;
- };
- };
-
+ if (SCpnt->use_sg) {
+ struct scatterlist * sgpnt;
+ int i;
+ sgpnt = (struct scatterlist *) SCpnt->buffer;
+ for(i=0; i<SCpnt->use_sg; i++) {
#ifdef DEBUG
- printk("sd%d : %d sectors remain.\n", MINOR(CURRENT->dev), CURRENT->nr_sectors);
+ printk(":%x %x %d\n",sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
#endif
-
+ if (sgpnt[i].alt_address) {
+ if (SCpnt->request.cmd == READ)
+ memcpy(sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
+ scsi_free(sgpnt[i].address, sgpnt[i].length);
+ };
+ };
+ scsi_free(SCpnt->buffer, SCpnt->sglist_len); /* Free list of scatter-gather pointers */
+ } else {
+ if (SCpnt->buffer != SCpnt->request.buffer) {
+#ifdef DEBUG
+ printk("nosg: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer,
+ SCpnt->bufflen);
+#endif
+ if (SCpnt->request.cmd == READ)
+ memcpy(SCpnt->request.buffer, SCpnt->buffer,
+ SCpnt->bufflen);
+ scsi_free(SCpnt->buffer, SCpnt->bufflen);
+ };
+ };
/*
* If multiple sectors are requested in one buffer, then
* they will have been finished off by the first command. If
* not, then we have a multi-buffer command.
*/
- if (CURRENT->nr_sectors)
- {
- CURRENT->sector += this_count;
- CURRENT->errors = 0;
-
- if (!CURRENT->bh)
- {
+ if (SCpnt->request.nr_sectors > this_count)
+ {
+ SCpnt->request.errors = 0;
+
+ if (!SCpnt->request.bh)
+ {
#ifdef DEBUG
- printk("sd%d : handling page request, no buffer\n",
- MINOR(CURRENT->dev));
+ printk("sd%d : handling page request, no buffer\n",
+ MINOR(SCpnt->request.dev));
#endif
-
/*
- The CURRENT->nr_sectors field is always done in 512 byte sectors,
- even if this really isn't the case.
+ The SCpnt->request.nr_sectors field is always done in 512 byte sectors,
+ even if this really isn't the case.
*/
- (char *) CURRENT->buffer += this_count << 9;
- }
- else
- {
+ printk("sd.c: linked page request. (%x %x)",
+ SCpnt->request.sector, this_count);
+ panic("Aiiiiiiiiiiiieeeeeeeee");
+ }
+ }
+ end_scsi_request(SCpnt, 1, this_count);
+ requeue_sd_request(SCpnt);
+ return;
+ }
+
+/* Free up any indirection buffers we allocated for DMA purposes. */
+ if (SCpnt->use_sg) {
+ struct scatterlist * sgpnt;
+ int i;
+ sgpnt = (struct scatterlist *) SCpnt->buffer;
+ for(i=0; i<SCpnt->use_sg; i++) {
#ifdef DEBUG
- printk("sd%d : handling linked buffer request\n", MINOR(CURRENT->dev));
+ printk("err: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer,
+ SCpnt->bufflen);
#endif
- end_request(1);
- }
- }
- else
- end_request(1);
- do_sd_request();
- }
-
-/*
- * Of course, the error handling code is a little Fubar down in scsi.c.
- * Version 2 of the drivers will fix that, and we will *really* recover
- * from errors.
- */
+ if (sgpnt[i].alt_address) {
+ scsi_free(sgpnt[i].address, sgpnt[i].length);
+ };
+ };
+ scsi_free(SCpnt->buffer, SCpnt->sglist_len); /* Free list of scatter-gather pointers */
+ } else {
+#ifdef DEBUG
+ printk("nosgerr: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer,
+ SCpnt->bufflen);
+#endif
+ if (SCpnt->buffer != SCpnt->request.buffer)
+ scsi_free(SCpnt->buffer, SCpnt->bufflen);
+ };
/*
Now, if we were good little boys and girls, Santa left us a request
@@ -238,96 +242,151 @@ static void rw_intr (int host, int result)
can choose a block to remap, etc.
*/
- else if (driver_byte(result) & DRIVER_SENSE) {
- if (bb) bb[DEVICE_NR(CURRENT->dev)].use = 0;
- if (sugestion(result) == SUGGEST_REMAP) {
+ if (driver_byte(result) != 0) {
+ {
+ int i;
+ printk("Dumping sense buffer: ");
+ for(i=0;i<10;i++) printk(" %d",SCpnt->sense_buffer[i]);
+ };
+ if (sugestion(result) == SUGGEST_REMAP) {
#ifdef REMAP
/*
Not yet implemented. A read will fail after being remapped,
a write will call the strategy routine again.
*/
- if rscsi_disks[DEVICE_NR(CURRENT->dev)].remap
- {
- result = 0;
- }
- else
-
+ if rscsi_disks[DEVICE_NR(SCpnt->request.dev)].remap
+ {
+ result = 0;
+ }
+ else
+
#endif
- }
-
-/* A unit attention comes up if there is a media change on a removable
- disk drive */
-
- else if ((sense_buffer[0] & 0x7f) == 0x70) {
- if ((sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
- /* detected disc change. set a bit and quietly refuse */
- /* further access. */
-
- rscsi_disks[DEVICE_NR(CURRENT->dev)].device->changed = 1;
- end_request(0);
- do_sd_request();
- return;
- }
- }
-
-/*
- If we had an ILLEGAL REQUEST returned, then we may have performed
- an unsupported command. The only thing this should be would be a ten
- byte read where only a six byte read was supportted. Also, on a
- system where READ CAPACITY failed, we mave have read past the end of the
- disk.
+ }
+
+ if ((SCpnt->sense_buffer[0] & 0x7f) == 0x70) {
+ if ((SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
+ /* detected disc change. set a bit and quietly refuse */
+ /* further access. */
+
+ rscsi_disks[DEVICE_NR(SCpnt->request.dev)].device->changed = 1;
+ end_scsi_request(SCpnt, 0, this_count);
+ requeue_sd_request(SCpnt);
+ return;
+ }
+ }
+
+
+/* If we had an ILLEGAL REQUEST returned, then we may have
+performed an unsupported command. The only thing this should be would
+be a ten byte read where only a six byte read was supportted. Also,
+on a system where READ CAPACITY failed, we mave have read past the end
+of the disk.
*/
- else if (sense_buffer[7] == ILLEGAL_REQUEST) {
- if (rscsi_disks[DEVICE_NR(CURRENT->dev)].ten) {
- rscsi_disks[DEVICE_NR(CURRENT->dev)].ten = 0;
- do_sd_request();
- result = 0;
- } else {
- }
- }
- }
+
+ if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) {
+ if (rscsi_disks[DEVICE_NR(SCpnt->request.dev)].ten) {
+ rscsi_disks[DEVICE_NR(SCpnt->request.dev)].ten = 0;
+ requeue_sd_request(SCpnt);
+ result = 0;
+ } else {
+ }
+ }
+ } /* driver byte != 0 */
if (result) {
- if (bb) bb[DEVICE_NR(CURRENT->dev)].use = 0;
printk("SCSI disk error : host %d id %d lun %d return code = %x\n",
- rscsi_disks[DEVICE_NR(CURRENT->dev)].device->host_no,
- rscsi_disks[DEVICE_NR(CURRENT->dev)].device->id,
- rscsi_disks[DEVICE_NR(CURRENT->dev)].device->lun, result);
+ rscsi_disks[DEVICE_NR(SCpnt->request.dev)].device->host_no,
+ rscsi_disks[DEVICE_NR(SCpnt->request.dev)].device->id,
+ rscsi_disks[DEVICE_NR(SCpnt->request.dev)].device->lun, result);
if (driver_byte(result) & DRIVER_SENSE)
printk("\tSense class %x, sense error %x, extended sense %x\n",
- sense_class(sense_buffer[0]),
- sense_error(sense_buffer[0]),
- sense_buffer[2] & 0xf);
+ sense_class(SCpnt->sense_buffer[0]),
+ sense_error(SCpnt->sense_buffer[0]),
+ SCpnt->sense_buffer[2] & 0xf);
- end_request(0);
- do_sd_request();
+ end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
+ requeue_sd_request(SCpnt);
+ return;
}
}
/*
- do_sd_request() is the request handler function for the sd driver.
+ requeue_sd_request() is the request handler function for the sd driver.
Its function in life is to take block device requests, and translate
them to SCSI commands.
*/
static void do_sd_request (void)
{
- int dev, block;
+ Scsi_Cmnd * SCpnt = NULL;
+ struct request * req = NULL;
+ while (1==1){
+ if (CURRENT != NULL && CURRENT->dev == -1) return;
+
+ INIT_REQUEST;
+
+ SCpnt = allocate_device(&CURRENT,
+ rscsi_disks[DEVICE_NR(MINOR(CURRENT->dev))].device->index, 0);
+
+/* This is a performance enhancement. We dig down into the request list and
+ try and find a queueable request (i.e. device not busy, and host able to
+ accept another command. If we find one, then we queue it. This can
+ make a big difference on systems with more than one disk drive. We want
+ to have the interrupts off when monkeying with the request list, because
+ otherwise the kernel might try and slip in a request inbetween somewhere. */
+
+ if (!SCpnt && NR_SD > 1){
+ struct request *req1;
+ req1 = NULL;
+ cli();
+ req = CURRENT;
+ while(req){
+ SCpnt = request_queueable(req,
+ rscsi_disks[DEVICE_NR(MINOR(req->dev))].device->index);
+ if(SCpnt) break;
+ req1 = req;
+ req = req->next;
+ };
+ if (SCpnt) {
+ if (req == CURRENT)
+ CURRENT = CURRENT->next;
+ else
+ req1->next = req->next;
+ };
+ sti();
+ };
+
+ if (!SCpnt) return; /* Could not find anything to do */
+
+ wake_up(&wait_for_request);
+
+ /* Queue command */
+ requeue_sd_request(SCpnt);
+ }; /* While */
+}
+
+static void requeue_sd_request (Scsi_Cmnd * SCpnt)
+{
+ int dev, block, this_count;
unsigned char cmd[10];
char * buff;
repeat:
- INIT_REQUEST;
- dev = MINOR(CURRENT->dev);
- block = CURRENT->sector;
+
+ if(SCpnt->request.dev <= 0)
+ return do_sd_request();
+
+ dev = MINOR(SCpnt->request.dev);
+ block = SCpnt->request.sector;
+ this_count = 0;
#ifdef DEBUG
printk("Doing sd request, dev = %d, block = %d\n", dev, block);
#endif
- if (dev >= (NR_SD << 4) || block + CURRENT->nr_sectors > sd[dev].nr_sects)
+ if (dev >= (NR_SD << 4) || block + SCpnt->request.nr_sectors > sd[dev].nr_sects)
{
- end_request(0);
+ end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
goto repeat;
}
@@ -340,40 +399,20 @@ repeat:
* quietly refuse to do anything to a changed disc until the changed bit has been reset
*/
/* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
- end_request(0);
+ end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
goto repeat;
}
#ifdef DEBUG
- printk("sd%d : real dev = /dev/sd%d, block = %d\n", MINOR(CURRENT->dev), dev, block);
-#endif
-
-
- if (!CURRENT->bh)
- this_count = CURRENT->nr_sectors;
- else
- this_count = (BLOCK_SIZE / 512);
-
-
-/* This is a temporary hack for the AHA1742. */
- if(slow_scsi_io == HOST) {
- if(total_count == 0)
- total_count = this_count;
- this_count = 1; /* Take only 512 bytes at a time */
- };
-
-#ifdef DEBUG
- printk("sd%d : %s %d/%d 512 byte blocks.\n", MINOR(CURRENT->dev),
- (CURRENT->cmd == WRITE) ? "writing" : "reading",
- this_count, CURRENT->nr_sectors);
+ printk("sd%d : real dev = /dev/sd%d, block = %d\n", MINOR(SCpnt->request.dev), dev, block);
#endif
- switch (CURRENT->cmd)
+ switch (SCpnt->request.cmd)
{
case WRITE :
if (!rscsi_disks[dev].device->writeable)
{
- end_request(0);
+ end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
goto repeat;
}
cmd[0] = WRITE_6;
@@ -382,29 +421,132 @@ repeat:
cmd[0] = READ_6;
break;
default :
- printk ("Unknown sd command %d\r\n", CURRENT->cmd);
+ printk ("Unknown sd command %d\r\n", SCpnt->request.cmd);
panic("");
- }
+ }
- cmd[1] = (LUN << 5) & 0xe0;
+ SCpnt->this_count = 0;
+
+ if (!SCpnt->request.bh ||
+ (SCpnt->request.nr_sectors == SCpnt->request.current_nr_sectors)) {
+
+ /* case of page request (i.e. raw device), or unlinked buffer */
+ this_count = SCpnt->request.nr_sectors;
+ buff = SCpnt->request.buffer;
+ SCpnt->use_sg = 0;
+
+ } else if (scsi_hosts[SCpnt->host].sg_tablesize == 0 ||
+ (need_isa_buffer &&
+ dma_free_sectors < 10)) {
+
+ /* Case of host adapter that cannot scatter-gather. We also
+ come here if we are running low on DMA buffer memory. We set
+ a threshold higher than that we would need for this request so
+ we leave room for other requests. Even though we would not need
+ it all, we need to be conservative, because if we run low enough
+ we have no choice but to panic. */
+
+ if (scsi_hosts[SCpnt->host].sg_tablesize != 0 &&
+ need_isa_buffer &&
+ dma_free_sectors < 10)
+ printk("Warning: SCSI DMA buffer space running low. Using non scatter-gather I/O.\n");
+
+ this_count = SCpnt->request.current_nr_sectors;
+ buff = SCpnt->request.buffer;
+ SCpnt->use_sg = 0;
+
+ } else {
+
+ /* Scatter-gather capable host adapter */
+ struct buffer_head * bh;
+ struct scatterlist * sgpnt;
+ int count, this_count_max;
+ bh = SCpnt->request.bh;
+ this_count = 0;
+ this_count_max = (rscsi_disks[dev].ten ? 0xffff : 0xff);
+ count = 0;
+ while(bh && count < scsi_hosts[SCpnt->host].sg_tablesize) {
+ if ((this_count + (bh->b_size >> 9)) > this_count_max) break;
+ this_count += (bh->b_size >> 9);
+ count++;
+ bh = bh->b_reqnext;
+ };
+ SCpnt->use_sg = count; /* Number of chains */
+ count = 512;/* scsi_malloc can only allocate in chunks of 512 bytes*/
+ while( count < (SCpnt->use_sg * sizeof(struct scatterlist)))
+ count = count << 1;
+ SCpnt->sglist_len = count;
+ sgpnt = (struct scatterlist * ) scsi_malloc(count);
+ if (!sgpnt) {
+ printk("Warning - running *really* short on DMA buffers\n");
+ SCpnt->use_sg = 0; /* No memory left - bail out */
+ this_count = SCpnt->request.current_nr_sectors;
+ buff = SCpnt->request.buffer;
+ } else {
+ buff = (char *) sgpnt;
+ count = 0;
+ bh = SCpnt->request.bh;
+ for(count = 0, bh = SCpnt->request.bh; count < SCpnt->use_sg;
+ count++, bh = bh->b_reqnext) {
+ sgpnt[count].address = bh->b_data;
+ sgpnt[count].alt_address = NULL;
+ sgpnt[count].length = bh->b_size;
+ if (((int) sgpnt[count].address) + sgpnt[count].length >
+ ISA_DMA_THRESHOLD & (scsi_hosts[SCpnt->host].unchecked_isa_dma)) {
+ sgpnt[count].alt_address = sgpnt[count].address;
+ /* We try and avoid exhausting the DMA pool, since it is easier
+ to control usage here. In other places we might have a more
+ pressing need, and we would be screwed if we ran out */
+ if(dma_free_sectors < (bh->b_size >> 9) + 5) {
+ sgpnt[count].address = NULL;
+ } else {
+ sgpnt[count].address = scsi_malloc(sgpnt[count].length);
+ };
+/* If we start running low on DMA buffers, we abort the scatter-gather
+ operation, and free all of the memory we have allocated. We want to
+ ensure that all scsi operations are able to do at least a non-scatter/gather
+ operation */
+ if(sgpnt[count].address == NULL){ /* Out of dma memory */
+ printk("Warning: Running low on SCSI DMA buffers");
+ /* Try switching back to a non scatter-gather operation. */
+ while(--count){
+ if(sgpnt[count].alt_address)
+ scsi_free(sgpnt[count].address, sgpnt[count].length);
+ };
+ this_count = SCpnt->request.current_nr_sectors;
+ buff = SCpnt->request.buffer;
+ SCpnt->use_sg = 0;
+ scsi_free(buff, SCpnt->sglist_len);
+ break;
+ };
- buff = CURRENT->buffer;
+ if (SCpnt->request.cmd == WRITE)
+ memcpy(sgpnt[count].address, sgpnt[count].alt_address,
+ sgpnt[count].length);
+ };
+ }; /* for loop */
+ }; /* Able to malloc sgpnt */
+ }; /* Host adapter capable of scatter-gather */
+
+/* Now handle the possibility of DMA to addresses > 16Mb */
+
+ if(SCpnt->use_sg == 0){
+ if (((int) buff) + (this_count << 9) > ISA_DMA_THRESHOLD &&
+ (scsi_hosts[SCpnt->host].unchecked_isa_dma)) {
+ buff = scsi_malloc(this_count << 9);
+ if(buff == NULL) panic("Ran out of DMA buffers.");
+ if (SCpnt->request.cmd == WRITE)
+ memcpy(buff, (char *)SCpnt->request.buffer, this_count << 9);
+ };
+ };
-/* Curses, curses. If this is a DMA transfer, we could be screwed. */
- if (((int) buff) + (this_count << 9) > ISA_DMA_THRESHOLD &&
- (scsi_hosts[HOST].unchecked_isa_dma)) {
- if (bb[DEVICE_NR(CURRENT->dev)].use) panic ("block buffer already in use");
- bb[DEVICE_NR(CURRENT->dev)].use = 1;
- if(this_count > 8) this_count = 8;
- if (CURRENT->cmd == WRITE) {
- memcpy(bb[DEVICE_NR(CURRENT->dev)].buffer,
- (char *)CURRENT->buffer, this_count << 9);
#ifdef DEBUG
- printk("W");
+ printk("sd%d : %s %d/%d 512 byte blocks.\n", MINOR(SCpnt->request.dev),
+ (SCpnt->request.cmd == WRITE) ? "writing" : "reading",
+ this_count, SCpnt->request.nr_sectors);
#endif
- };
- buff = bb[DEVICE_NR(CURRENT->dev)].buffer;
- };
+
+ cmd[1] = (SCpnt->lun << 5) & 0xe0;
if (((this_count > 0xff) || (block > 0x1fffff)) && rscsi_disks[dev].ten)
{
@@ -432,8 +574,8 @@ repeat:
cmd[5] = 0;
}
- scsi_do_cmd (HOST, ID, (void *) cmd, buff, this_count << 9,
- rw_intr, SD_TIMEOUT, sense_buffer, MAX_RETRIES);
+ scsi_do_cmd (SCpnt, (void *) cmd, buff, this_count << 9,
+ rw_intr, SD_TIMEOUT, MAX_RETRIES);
}
int check_scsidisk_media_change(int full_dev, int flag){
@@ -468,44 +610,68 @@ int check_scsidisk_media_change(int full_dev, int flag){
return retval;
}
-static void sd_init_done (int host, int result)
+static void sd_init_done (Scsi_Cmnd * SCpnt)
{
- the_result = result;
+ struct request * req;
+ struct task_struct * p;
+
+ req = &SCpnt->request;
+ req->dev = 0xfffe; /* Busy, but indicate request done */
+
+ if ((p = req->waiting) != NULL) {
+ req->waiting = NULL;
+ p->state = TASK_RUNNING;
+ if (p->counter > current->counter)
+ need_resched = 1;
+ }
}
-
static int sd_init_onedisk(int i)
{
int j = 0;
unsigned char cmd[10];
unsigned char buffer[513];
- int try_again;
+ int the_result, retries;
+ Scsi_Cmnd * SCpnt;
- try_again=2;
- cmd[0] = READ_CAPACITY;
- cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
- memset ((void *) &cmd[2], 0, 8);
+ /* We need to retry the READ_CAPACITY because a UNIT_ATTENTION is considered
+ a fatal error, and many devices report such an error just after a scsi
+ bus reset. */
- /*
- * Super Kludge - since the midlevel error handling code doesn't work
- * Version 2 will - it's under development 8^)
- *
- * We manually retry
- */
+ SCpnt = allocate_device(NULL, rscsi_disks[i].device->index, 1);
+ retries = 3;
do {
- the_result = -1;
-#ifdef DEBUG
- printk("sd%d : READ CAPACITY\n ", i);
-#endif
- scsi_do_cmd (rscsi_disks[i].device->host_no ,
- rscsi_disks[i].device->id,
+ cmd[0] = READ_CAPACITY;
+ cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
+ memset ((void *) &cmd[2], 0, 8);
+ SCpnt->request.dev = 0xffff; /* Mark as really busy again */
+
+ scsi_do_cmd (SCpnt,
(void *) cmd, (void *) buffer,
- 512, sd_init_done, SD_TIMEOUT, sense_buffer,
+ 512, sd_init_done, SD_TIMEOUT,
MAX_RETRIES);
+
+ if (current == task[0])
+ while(SCpnt->request.dev != 0xfffe);
+ else
+ if (SCpnt->request.dev != 0xfffe){
+ SCpnt->request.waiting = current;
+ current->state = TASK_UNINTERRUPTIBLE;
+ while (SCpnt->request.dev != 0xfffe) schedule();
+ };
+
+ the_result = SCpnt->result;
+ retries--;
+
+ } while(the_result && retries);
+
+ SCpnt->request.dev = -1; /* Mark as not busy */
+
+ wake_up(&scsi_devices[SCpnt->index].device_wait);
+
+ /* Wake up a process waiting for device*/
- while(the_result < 0);
- } while (try_again && the_result);
/*
* The SCSI standard says "READ CAPACITY is necessary for self confuring software"
* While not mandatory, support of READ CAPACITY is strongly encouraged.
@@ -532,12 +698,12 @@ static int sd_init_onedisk(int i)
driver_byte(the_result)
);
if (driver_byte(the_result) & DRIVER_SENSE)
- printk("sd%d : extended sense code = %1x \n", i, sense_buffer[2] & 0xf);
+ printk("sd%d : extended sense code = %1x \n", i, SCpnt->sense_buffer[2] & 0xf);
else
printk("sd%d : sense not available. \n", i);
printk("sd%d : block size assumed to be 512 bytes, disk size 1GB. \n", i);
- rscsi_disks[i].capacity = 0x1fffff;
+ rscsi_disks[i].capacity = 0xfffff;
rscsi_disks[i].sector_size = 512;
}
else
@@ -554,13 +720,14 @@ static int sd_init_onedisk(int i)
{
printk ("sd%d : unsupported sector size %d.\n",
i, rscsi_disks[i].sector_size);
- if(rscsi_disks[j].device->removable){
- rscsi_disks[j].capacity = 0;
+ if(rscsi_disks[i].device->removable){
+ rscsi_disks[i].capacity = 0;
} else {
printk ("scsi : deleting disk entry.\n");
- for (j=i; j < NR_SD;)
+ for (j=i; j < NR_SD - 1;)
rscsi_disks[j] = rscsi_disks[++j];
--i;
+ --NR_SD;
return i;
};
}
@@ -580,23 +747,50 @@ unsigned long sd_init(unsigned long memory_start, unsigned long memory_end)
{
int i;
+ if (MAX_SD == 0) return memory_start;
+
+ sd_sizes = (int *) memory_start;
+ memory_start += (MAX_SD << 4) * sizeof(int);
+ memset(sd_sizes, 0, (MAX_SD << 4) * sizeof(int));
+
+ sd = (struct hd_struct *) memory_start;
+ memory_start += (MAX_SD << 4) * sizeof(struct hd_struct);
+
+ sd_gendisk.max_nr = MAX_SD;
+ sd_gendisk.part = sd;
+ sd_gendisk.sizes = sd_sizes;
+ sd_gendisk.real_devices = (void *) rscsi_disks;
+
for (i = 0; i < NR_SD; ++i)
i = sd_init_onedisk(i);
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
blkdev_fops[MAJOR_NR] = &sd_fops;
+
+ /* If our host adapter is capable of scatter-gather, then we increase
+ the read-ahead to 8 blocks (16 sectors). If not, we use
+ a two block (4 sector) read ahead. */
+ if(scsi_hosts[rscsi_disks[0].device->host_no].sg_tablesize)
+ read_ahead[MAJOR_NR] = 16; /* 16 sector read-ahead */
+ else
+ read_ahead[MAJOR_NR] = 4; /* 4 sector read-ahead */
+
sd_gendisk.next = gendisk_head;
gendisk_head = &sd_gendisk;
- boot_init_done++;
-/* Allocate DMA block buffer */
- if(memory_end > ISA_DMA_THRESHOLD) {
- bb = (struct block_buffer *) memory_start;
- memory_start += NR_SD * sizeof(struct block_buffer);
- for (i=0; i < NR_SD; ++i) bb[i].use = 0;
- };
return memory_start;
}
+unsigned long sd_init1(unsigned long mem_start, unsigned long mem_end){
+ rscsi_disks = (Scsi_Disk *) mem_start;
+ mem_start += MAX_SD * sizeof(Scsi_Disk);
+ return mem_start;
+};
+
+void sd_attach(Scsi_Device * SDp){
+ rscsi_disks[NR_SD++].device = SDp;
+ if(NR_SD > MAX_SD) panic ("scsi_devices corrupt (sd)");
+};
+
#define DEVICE_BUSY rscsi_disks[target].device->busy
#define USAGE rscsi_disks[target].device->access_count
#define CAPACITY rscsi_disks[target].capacity
@@ -620,14 +814,14 @@ int revalidate_scsidisk(int dev, int maxusage){
target = DEVICE_NR(MINOR(dev));
gdev = &GENDISK_STRUCT;
- sti();
+ cli();
if (DEVICE_BUSY || USAGE > maxusage) {
- cli();
+ sti();
printk("Device busy for revalidation (usage=%d)\n", USAGE);
return -EBUSY;
};
DEVICE_BUSY = 1;
- cli();
+ sti();
max_p = gdev->max_p;
start = target << gdev->minor_shift;
@@ -651,7 +845,3 @@ int revalidate_scsidisk(int dev, int maxusage){
DEVICE_BUSY = 0;
return 0;
}
-#endif
-
-
-
diff --git a/kernel/blk_drv/scsi/sd.h b/kernel/blk_drv/scsi/sd.h
index e36d364..efa63e3 100644
--- a/kernel/blk_drv/scsi/sd.h
+++ b/kernel/blk_drv/scsi/sd.h
@@ -4,6 +4,10 @@
* Drew Eckhardt
*
* <drew@colorado.edu>
+ *
+ * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to
+ * add scatter-gather, multiple outstanding request, and other
+ * enhancements.
*/
#ifndef _SD_H
#define _SD_H
@@ -25,10 +29,7 @@
more in kernel space if that is your thing.
*/
-#define MAX_SD 4
-extern int NR_SD;
-
-extern struct hd_struct sd[MAX_SD << 4];
+extern struct hd_struct * sd;
typedef struct {
unsigned capacity; /* size in blocks */
@@ -40,11 +41,6 @@ typedef struct {
unsigned remap:1; /* support remapping */
} Scsi_Disk;
-extern Scsi_Disk rscsi_disks[MAX_SD];
-
-unsigned long sd_init(unsigned long, unsigned long);
+extern Scsi_Disk * rscsi_disks;
-#define HOST (rscsi_disks[DEVICE_NR(CURRENT->dev)].device->host_no)
-#define ID (rscsi_disks[DEVICE_NR(CURRENT->dev)].device->id)
-#define LUN (rscsi_disks[DEVICE_NR(CURRENT->dev)].device->lun)
#endif
diff --git a/kernel/blk_drv/scsi/sd_ioctl.c b/kernel/blk_drv/scsi/sd_ioctl.c
index 7a447c1..c093306 100644
--- a/kernel/blk_drv/scsi/sd_ioctl.c
+++ b/kernel/blk_drv/scsi/sd_ioctl.c
@@ -1,29 +1,58 @@
-#include <linux/config.h>
-#ifdef CONFIG_BLK_DEV_SD
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
+#include <linux/hdreg.h>
+#include <linux/errno.h>
+
+#include <asm/segment.h>
+
+#include "../blk.h"
#include "scsi.h"
+#include "hosts.h"
#include "sd.h"
extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
extern int revalidate_scsidisk(int, int);
+extern int sd_sizes[];
+
int sd_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsigned long arg)
{
int dev = inode->i_rdev;
+ int host;
+ int diskinfo[4];
+ struct hd_geometry *loc = (void *) arg;
switch (cmd) {
+ case HDIO_REQ: /* Return BIOS disk parameters */
+ if (!loc) return -EINVAL;
+ verify_area(loc, sizeof(*loc));
+ host = rscsi_disks[MINOR(dev) >> 4].device->host_no;
+ diskinfo[0] = 0;
+ diskinfo[1] = 0;
+ diskinfo[2] = 0;
+ if(scsi_hosts[host].bios_param != NULL)
+ scsi_hosts[host].bios_param(sd_sizes[MINOR(dev)],
+ dev,
+ &diskinfo[0]);
+ put_fs_byte(diskinfo[0],
+ (char *) &loc->heads);
+ put_fs_byte(diskinfo[1],
+ (char *) &loc->sectors);
+ put_fs_word(diskinfo[2],
+ (short *) &loc->cylinders);
+ put_fs_long(sd[MINOR(inode->i_rdev)].start_sect,
+ (long *) &loc->start);
+ return 0;
+ case BLKGETSIZE: /* Return device size */
+ if (!arg) return -EINVAL;
+ verify_area((long *) arg, sizeof(long));
+ put_fs_long(sd[MINOR(inode->i_rdev)].nr_sects,
+ (long *) arg);
+ return 0;
case BLKRRPART: /* Re-read partition tables */
return revalidate_scsidisk(dev, 1);
default:
return scsi_ioctl(rscsi_disks[MINOR(dev) >> 4].device , cmd, (void *) arg);
}
}
-#endif
-
-
-
-
-
-
diff --git a/kernel/blk_drv/scsi/seagate.c b/kernel/blk_drv/scsi/seagate.c
index 201b65c..431bed6 100644
--- a/kernel/blk_drv/scsi/seagate.c
+++ b/kernel/blk_drv/scsi/seagate.c
@@ -13,9 +13,10 @@
#include <asm/system.h>
#include <linux/signal.h>
#include <linux/sched.h>
-#include "seagate.h"
+#include "../blk.h"
#include "scsi.h"
#include "hosts.h"
+#include "seagate.h"
static int internal_command(unsigned char target, const void *cmnd,
@@ -196,7 +197,7 @@ static struct sigaction seagate_sigaction = {
}
}
-char *seagate_st0x_info(void)
+const char *seagate_st0x_info(void)
{
static char buffer[] = "Seagate ST-0X SCSI driver by Drew Eckhardt \n"
"$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/seagate.c,v 1.1 1992/07/24 06:27:38 root Exp root $\n";
@@ -211,7 +212,8 @@ char *seagate_st0x_info(void)
static unsigned char current_target;
static unsigned char *current_cmnd, *current_data;
static int current_bufflen;
-static void (*done_fn)(int, int) = NULL;
+static void (*done_fn)(Scsi_Cmnd *) = NULL;
+static Scsi_Cmnd * SCint = NULL;
/*
* These control whether or not disconnect / reconnect will be attempted,
@@ -268,7 +270,8 @@ static void seagate_reconnect_intr (int unused)
printk("scsi%d : done_fn(%d,%08x)", hostno,
hostno, temp);
#endif
- done_fn (hostno, temp);
+ SCint->result = temp;
+ done_fn (SCint);
}
else
printk("done_fn() not defined.\n");
@@ -283,33 +286,34 @@ static void seagate_reconnect_intr (int unused)
* is set to the one passed to the function.
*/
-int seagate_st0x_queue_command (unsigned char target, const void *cmnd,
- void *buff, int bufflen, void (*fn)(int,
- int))
+int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
{
int result;
- done_fn = fn;
- current_target = target;
- (const void *) current_cmnd = cmnd;
- current_data = buff;
- current_bufflen = bufflen;
+ done_fn = done;
+ current_target = SCpnt->target;
+ (const void *) current_cmnd = SCpnt->cmnd;
+ current_data = SCpnt->request_buffer;
+ current_bufflen = SCpnt->request_bufflen;
+ SCint = SCpnt;
- result = internal_command (target, cmnd, buff, bufflen,
+ result = internal_command (SCpnt->target, SCpnt->cmnd, SCpnt->request_buffer,
+ SCpnt->request_bufflen,
CAN_RECONNECT);
if (msg_byte(result) == DISCONNECT)
return 0;
else
{
- done_fn (hostno, result);
+ SCpnt->result = result;
+ done_fn (SCpnt);
return 1;
}
}
-int seagate_st0x_command (unsigned char target, const void *cmnd,
- void *buff, int bufflen)
+int seagate_st0x_command (Scsi_Cmnd * SCpnt)
{
- return internal_command (target, cmnd, buff, bufflen,
+ return internal_command (SCpnt->target, SCpnt->cmnd, SCpnt->request_buffer,
+ SCpnt->request_bufflen,
(int) NO_RECONNECT);
}
@@ -658,7 +662,7 @@ static int internal_command(unsigned char target, const void *cmnd,
* We loop as long as we are in a data out phase, there is data to send,
* and BSY is still active.
*/
- __asm__ ("
+ __asm__ (
/*
Local variables :
@@ -669,9 +673,9 @@ static int internal_command(unsigned char target, const void *cmnd,
Test for any data here at all.
*/
- movl %0, %%esi /* local value of data */
- movl %1, %%ecx /* local value of len */
- orl %%ecx, %%ecx
+ "movl %0, %%esi\n" /* local value of data */
+ "\tmovl %1, %%ecx\n" /* local value of len */
+ "\torl %%ecx, %%ecx
jz 2f
cld
@@ -679,23 +683,23 @@ static int internal_command(unsigned char target, const void *cmnd,
movl _st0x_cr_sr, %%ebx
movl _st0x_dr, %%edi
-1: movb (%%ebx), %%al
+1: movb (%%ebx), %%al\n"
/*
Test for BSY
*/
- test $1, %%al
- jz 2f
+ "\ttest $1, %%al
+ jz 2f\n"
/*
Test for data out phase - STATUS & REQ_MASK should be REQ_DATAOUT, which is 0.
*/
- test $0xe, %%al
- jnz 2f
+ "\ttest $0xe, %%al
+ jnz 2f \n"
/*
Test for REQ
*/
- test $0x10, %%al
+ "\ttest $0x10, %%al
jz 1b
lodsb
movb %%al, (%%edi)
@@ -720,7 +724,7 @@ static int internal_command(unsigned char target, const void *cmnd,
* and BSY is still active
*/
- __asm__ ("
+ __asm__ (
/*
Local variables :
ecx = len
@@ -731,44 +735,44 @@ static int internal_command(unsigned char target, const void *cmnd,
Test for room to read
*/
- movl %0, %%edi /* data */
- movl %1, %%ecx /* len */
- orl %%ecx, %%ecx
+ "movl %0, %%edi\n" /* data */
+ "\tmovl %1, %%ecx\n" /* len */
+ "\torl %%ecx, %%ecx
jz 2f
cld
movl _st0x_cr_sr, %%esi
movl _st0x_dr, %%ebx
-1: movb (%%esi), %%al
+1: movb (%%esi), %%al\n"
/*
Test for BSY
*/
- test $1, %%al
- jz 2f
+ "\ttest $1, %%al
+ jz 2f\n"
/*
Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN, = STAT_IO, which is 4.
*/
- movb $0xe, %%ah
+ "\tmovb $0xe, %%ah
andb %%al, %%ah
cmpb $0x04, %%ah
- jne 2f
+ jne 2f\n"
/*
Test for REQ
*/
- test $0x10, %%al
+ "\ttest $0x10, %%al
jz 1b
movb (%%ebx), %%al
stosb
loop 1b
-2: movl %%edi, %2 /* data */
- movl %%ecx, %3 /* len */
- ":
+2: movl %%edi, %2\n" /* data */
+ "\tmovl %%ecx, %3\n" /* len */
+ :
/* output */
"=r" (data), "=r" (len) :
/* input */
@@ -923,7 +927,7 @@ static int internal_command(unsigned char target, const void *cmnd,
return retcode (st0x_aborted);
}
-int seagate_st0x_abort (int code)
+int seagate_st0x_abort (Scsi_Cmnd * SCpnt, int code)
{
if (code)
st0x_aborted = code;
diff --git a/kernel/blk_drv/scsi/seagate.h b/kernel/blk_drv/scsi/seagate.h
index 744f8d5..b40b706 100644
--- a/kernel/blk_drv/scsi/seagate.h
+++ b/kernel/blk_drv/scsi/seagate.h
@@ -13,13 +13,11 @@
*/
#ifndef ASM
int seagate_st0x_detect(int);
-int seagate_st0x_command(unsigned char target, const void *cmnd, void *buff,
- int bufflen);
-int seagate_st0x_queue_command(unsigned char target, const void *cmnd,
- void *buff, int bufflen, void (*done)(int, int));
+int seagate_st0x_command(Scsi_Cmnd *);
+int seagate_st0x_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-int seagate_st0x_abort(int);
-char *seagate_st0x_info(void);
+int seagate_st0x_abort(Scsi_Cmnd *, int);
+const char *seagate_st0x_info(void);
int seagate_st0x_reset(void);
#ifndef NULL
@@ -29,7 +27,8 @@ int seagate_st0x_reset(void);
#define SEAGATE_ST0X {"Seagate ST-01/ST-02", seagate_st0x_detect, \
seagate_st0x_info, seagate_st0x_command, \
seagate_st0x_queue_command, seagate_st0x_abort, \
- seagate_st0x_reset, 1, 7, 0, 0}
+ seagate_st0x_reset, NULL, NULL, \
+ 1, 7, SG_NONE, 1, 0, 0}
#endif
diff --git a/kernel/blk_drv/scsi/sr.c b/kernel/blk_drv/scsi/sr.c
index 97a16bc..0bab02a 100644
--- a/kernel/blk_drv/scsi/sr.c
+++ b/kernel/blk_drv/scsi/sr.c
@@ -7,48 +7,41 @@
* Drew Eckhardt
*
* <drew@colorado.edu>
+ *
+ * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to
+ * add scatter-gather, multiple outstanding request, and other
+ * enhancements.
*/
-#include <linux/config.h>
-
-#ifdef CONFIG_BLK_DEV_SR
-
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/errno.h>
-
-#include "scsi.h"
-#include "sr.h"
-#include "scsi_ioctl.h" /* For the door lock/unlock commands */
+#include <asm/system.h>
#define MAJOR_NR 11
#include "../blk.h"
+#include "scsi.h"
+#include "hosts.h"
+#include "sr.h"
+#include "scsi_ioctl.h" /* For the door lock/unlock commands */
#define MAX_RETRIES 0
-#define SR_TIMEOUT 200
+#define SR_TIMEOUT 250
int NR_SR=0;
-Scsi_CD scsi_CDs[MAX_SR];
-static int sr_sizes[MAX_SR << 4];
-static unsigned long int this_count;
-
-struct block_buffer
- {
- unsigned block;
- unsigned start;
- unsigned use:1;
- unsigned char buffer[2048];
- };
-
-static struct block_buffer * bb;
+int MAX_SR=0;
+Scsi_CD * scsi_CDs;
+static int * sr_sizes;
static int sr_open(struct inode *, struct file *);
extern int sr_ioctl(struct inode *, struct file *, unsigned int, unsigned int);
+void requeue_sr_request (Scsi_Cmnd * SCpnt);
+
static void sr_release(struct inode * inode, struct file * file)
{
sync_dev(inode->i_rdev);
@@ -109,93 +102,135 @@ int check_cdrom_media_change(int full_dev, int flag){
}
/*
- * The sense_buffer is where we put data for all mode sense commands performed.
- */
-static unsigned char sense_buffer[255];
-
-/*
* rw_intr is the interrupt routine for the device driver. It will be notified on the
* end of a SCSI read / write, and will take on of several actions based on success or failure.
*/
-static void rw_intr (int host, int result)
+static void rw_intr (Scsi_Cmnd * SCpnt)
{
- if (SR_HOST != host)
- {
- panic ("sr.o : rw_intr() recieving interrupt for different host.");
- }
+ int result = SCpnt->result;
+ int this_count = SCpnt->this_count;
+#ifdef DEBUG
+ printk("sr.c done: %x %x\n",result, SCpnt->request.bh->b_data);
+#endif
if (!result)
{ /* No error */
- if (bb[DEVICE_NR(CURRENT->dev)].use)
- {
- memcpy((char *)CURRENT->buffer,
- bb[DEVICE_NR(CURRENT->dev)].buffer +
- (bb[DEVICE_NR(CURRENT->dev)].start << 9),
+ if (SCpnt->use_sg == 0) {
+ if (SCpnt->buffer != SCpnt->request.buffer)
+ {
+ int offset;
+ offset = (SCpnt->request.sector % 4) << 9;
+ memcpy((char *)SCpnt->request.buffer,
+ SCpnt->buffer + offset,
this_count << 9);
- }
-
- CURRENT->nr_sectors -= this_count;
+ /* Even though we are not using scatter-gather, we look
+ ahead and see if there is a linked request for the
+ other half of this buffer. If there is, then satisfy
+ it. */
+ if((offset == 0) && this_count == 2 &&
+ SCpnt->request.nr_sectors > this_count &&
+ SCpnt->request.bh &&
+ SCpnt->request.bh->b_reqnext &&
+ SCpnt->request.bh->b_reqnext->b_size == 1024) {
+ memcpy((char *)SCpnt->request.bh->b_reqnext->b_data,
+ SCpnt->buffer + 1024,
+ 1024);
+ this_count += 2;
+ };
+
+ scsi_free(SCpnt->buffer, 2048);
+ }
+ } else {
+ struct scatterlist * sgpnt;
+ int i;
+ sgpnt = (struct scatterlist *) SCpnt->buffer;
+ for(i=0; i<SCpnt->use_sg; i++) {
+ if (sgpnt[i].alt_address) {
+ if (sgpnt[i].alt_address != sgpnt[i].address) {
+ memcpy(sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
+ };
+ scsi_free(sgpnt[i].address, sgpnt[i].length);
+ };
+ };
+ scsi_free(SCpnt->buffer, SCpnt->sglist_len); /* Free list of scatter-gather pointers */
+ if(SCpnt->request.sector % 4) this_count -= 2;
+/* See if there is a padding record at the end that needs to be removed */
+ if(this_count > SCpnt->request.nr_sectors)
+ this_count -= 2;
+ };
#ifdef DEBUG
- printk("(%x %x %x) ",CURRENT->bh, CURRENT->nr_sectors,
+ printk("(%x %x %x) ",SCpnt->request.bh, SCpnt->request.nr_sectors,
this_count);
#endif
- if (CURRENT->nr_sectors)
+ if (SCpnt->request.nr_sectors > this_count)
{
- CURRENT->sector += this_count;
- CURRENT->errors = 0;
- if (!CURRENT->bh)
+ SCpnt->request.errors = 0;
+ if (!SCpnt->request.bh)
{
- (char *) CURRENT->buffer += this_count << 9;
- } else {
- end_request(1);
- do_sr_request();
+ printk("sr.c: linked page request. (%x %x)",
+ SCpnt->request.sector, this_count);
+ panic("Aiiiiiiiiiiiieeeeeeeee");
}
}
- else
- {
- end_request(1); /* All done */
- do_sr_request();
- }
- }
+
+ end_scsi_request(SCpnt, 1, this_count); /* All done */
+ requeue_sr_request(SCpnt);
+ return;
+ } /* Normal completion */
/* We only come through here if we have an error of some kind */
+/* Free up any indirection buffers we allocated for DMA purposes. */
+ if (SCpnt->use_sg) {
+ struct scatterlist * sgpnt;
+ int i;
+ sgpnt = (struct scatterlist *) SCpnt->buffer;
+ for(i=0; i<SCpnt->use_sg; i++) {
+ if (sgpnt[i].alt_address) {
+ scsi_free(sgpnt[i].address, sgpnt[i].length);
+ };
+ };
+ scsi_free(SCpnt->buffer, SCpnt->sglist_len); /* Free list of scatter-gather pointers */
+ } else {
+ if (SCpnt->buffer != SCpnt->request.buffer)
+ scsi_free(SCpnt->buffer, SCpnt->bufflen);
+ };
+
if (driver_byte(result) != 0) {
- bb[DEVICE_NR(CURRENT->dev)].block = -1;
-
- if ((sense_buffer[0] & 0x7f) == 0x70) {
- if ((sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
+ if ((SCpnt->sense_buffer[0] & 0x7f) == 0x70) {
+ if ((SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
/* detected disc change. set a bit and quietly refuse */
/* further access. */
- scsi_CDs[DEVICE_NR(CURRENT->dev)].device->changed = 1;
- end_request(0);
- do_sr_request();
+ scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->changed = 1;
+ end_scsi_request(SCpnt, 0, this_count);
+ requeue_sr_request(SCpnt);
return;
}
}
- if (sense_buffer[2] == ILLEGAL_REQUEST) {
+ if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) {
printk("CD-ROM error: Drive reports ILLEGAL REQUEST.\n");
- if (scsi_CDs[DEVICE_NR(CURRENT->dev)].ten) {
- scsi_CDs[DEVICE_NR(CURRENT->dev)].ten = 0;
- do_sr_request();
+ if (scsi_CDs[DEVICE_NR(SCpnt->request.dev)].ten) {
+ scsi_CDs[DEVICE_NR(SCpnt->request.dev)].ten = 0;
+ requeue_sr_request(SCpnt);
result = 0;
return;
} else {
- printk("CD-ROM error: Drive reports %d.\n", sense_buffer[2]); end_request(0);
- do_sr_request(); /* Do next request */
- return;
+ printk("CD-ROM error: Drive reports %d.\n", SCpnt->sense_buffer[2]);
+ end_scsi_request(SCpnt, 0, this_count);
+ requeue_sr_request(SCpnt); /* Do next request */
+ return;
}
}
- if (sense_buffer[2] == NOT_READY) {
+ if (SCpnt->sense_buffer[2] == NOT_READY) {
printk("CDROM not ready. Make sure you have a disc in the drive.\n");
- end_request(0);
- do_sr_request(); /* Do next request */
+ end_scsi_request(SCpnt, 0, this_count);
+ requeue_sr_request(SCpnt); /* Do next request */
return;
};
}
@@ -203,25 +238,25 @@ static void rw_intr (int host, int result)
/* We only get this far if we have an error we have not recognized */
if(result) {
printk("SCSI CD error : host %d id %d lun %d return code = %03x\n",
- scsi_CDs[DEVICE_NR(CURRENT->dev)].device->host_no,
- scsi_CDs[DEVICE_NR(CURRENT->dev)].device->id,
- scsi_CDs[DEVICE_NR(CURRENT->dev)].device->lun,
+ scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->host_no,
+ scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->id,
+ scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->lun,
result);
if (status_byte(result) == CHECK_CONDITION)
printk("\tSense class %x, sense error %x, extended sense %x\n",
- sense_class(sense_buffer[0]),
- sense_error(sense_buffer[0]),
- sense_buffer[2] & 0xf);
+ sense_class(SCpnt->sense_buffer[0]),
+ sense_error(SCpnt->sense_buffer[0]),
+ SCpnt->sense_buffer[2] & 0xf);
- end_request(0);
- do_sr_request();
+ end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
+ requeue_sr_request(SCpnt);
}
}
static int sr_open(struct inode * inode, struct file * filp)
{
- if(MINOR(inode->i_rdev) >= NR_SR ||
+ if(MINOR(inode->i_rdev) >= NR_SR ||
!scsi_CDs[MINOR(inode->i_rdev)].device) return -EACCES; /* No such device */
check_disk_change(inode->i_rdev);
@@ -231,30 +266,85 @@ static int sr_open(struct inode * inode, struct file * filp)
return 0;
}
+
/*
* do_sr_request() is the request handler function for the sr driver. Its function in life
* is to take block device requests, and translate them to SCSI commands.
*/
-void do_sr_request (void)
+static void do_sr_request (void)
+{
+ Scsi_Cmnd * SCpnt = NULL;
+ struct request * req = NULL;
+
+ while (1==1){
+ if (CURRENT != NULL && CURRENT->dev == -1) return;
+
+ INIT_REQUEST;
+
+ SCpnt = allocate_device(&CURRENT,
+ scsi_CDs[DEVICE_NR(MINOR(CURRENT->dev))].device->index, 0);
+
+
+/* This is a performance enhancement. We dig down into the request list and
+ try and find a queueable request (i.e. device not busy, and host able to
+ accept another command. If we find one, then we queue it. This can
+ make a big difference on systems with more than one disk drive. We want
+ to have the interrupts off when monkeying with the request list, because
+ otherwise the kernel might try and slip in a request inbetween somewhere. */
+
+ if (!SCpnt && NR_SR > 1){
+ struct request *req1;
+ req1 = NULL;
+ cli();
+ req = CURRENT;
+ while(req){
+ SCpnt = request_queueable(req,
+ scsi_CDs[DEVICE_NR(MINOR(req->dev))].device->index);
+ if(SCpnt) break;
+ req1 = req;
+ req = req->next;
+ };
+ if (SCpnt) {
+ if (req == CURRENT)
+ CURRENT = CURRENT->next;
+ else
+ req1->next = req->next;
+ };
+ sti();
+ };
+
+ if (!SCpnt)
+ return; /* Could not find anything to do */
+
+ wake_up(&wait_for_request);
+
+/* Queue command */
+ requeue_sr_request(SCpnt);
+ }; /* While */
+}
+
+void requeue_sr_request (Scsi_Cmnd * SCpnt)
{
unsigned int dev, block, realcount;
unsigned char cmd[10], *buffer, tries;
+ int this_count, start, end_rec;
tries = 2;
repeat:
- INIT_REQUEST;
- dev = MINOR(CURRENT->dev);
- block = CURRENT->sector;
+ if(SCpnt->request.dev <= 0)
+ return do_sr_request();
- bb[dev].start = block % 4;
- block = block / 4;
+ dev = MINOR(SCpnt->request.dev);
+ block = SCpnt->request.sector;
+ buffer = NULL;
+ this_count = 0;
if (dev >= NR_SR)
{
/* printk("CD-ROM request error: invalid device.\n"); */
- end_request(0);
+ end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
tries = 2;
goto repeat;
}
@@ -262,7 +352,7 @@ void do_sr_request (void)
if (!scsi_CDs[dev].use)
{
/* printk("CD-ROM request error: device marked not in use.\n"); */
- end_request(0);
+ end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
tries = 2;
goto repeat;
}
@@ -273,69 +363,184 @@ void do_sr_request (void)
* quietly refuse to do anything to a changed disc until the changed bit has been reset
*/
/* printk("CD-ROM has been changed. Prohibiting further I/O.\n"); */
- end_request(0);
+ end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
tries = 2;
goto repeat;
}
- if (!CURRENT->bh)
- this_count = CURRENT->nr_sectors;
- else
- this_count = (CURRENT->bh->b_size / 512);
-
- if (bb[dev].start)
- {
- bb[dev].use = 1;
-
- this_count = ((this_count > 4 - bb[dev].start) ?
- (4 - bb[dev].start) : (this_count));
-
- if (bb[dev].block == block)
- {
- rw_intr(SR_HOST, 0);
- return;
- }
-
- buffer = bb[dev].buffer;
- bb[dev].block = block;
- }
- else if (this_count < 4)
- {
- bb[dev].use = 1;
-
- if (bb[dev].block == block)
- {
- rw_intr(SR_HOST, 0);
- return;
- }
-
- buffer = bb[dev].buffer;
- bb[dev].block = block;
- }
- else
- {
- this_count -= this_count % 4;
- buffer = CURRENT->buffer;
- bb[dev].use = 0;
- }
-
- realcount = (this_count + 3) / 4;
-
- switch (CURRENT->cmd)
+ switch (SCpnt->request.cmd)
{
case WRITE:
- end_request(0);
+ end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
goto repeat;
break;
case READ :
cmd[0] = READ_6;
break;
default :
- printk ("Unknown sr command %d\r\n", CURRENT->cmd);
+ printk ("Unknown sr command %d\r\n", SCpnt->request.cmd);
panic("");
}
- cmd[1] = (SR_LUN << 5) & 0xe0;
+ cmd[1] = (SCpnt->lun << 5) & 0xe0;
+
+/*
+ Now do the grungy work of figuring out which sectors we need, and
+ where in memory we are going to put them.
+
+ The variables we need are:
+
+ this_count= number of 512 byte sectors being read
+ block = starting cdrom sector to read.
+ realcount = # of cdrom sectors to read
+
+ The major difference between a scsi disk and a scsi cdrom
+is that we will always use scatter-gather if we can, because we can
+work around the fact that the buffer cache has a block size of 1024,
+and we have 2048 byte sectors. This code should work for buffers that
+are any multiple of 512 bytes long. */
+
+ SCpnt->use_sg = 0;
+
+ if (scsi_hosts[SCpnt->host].sg_tablesize > 0 &&
+ (!need_isa_buffer ||
+ dma_free_sectors >= 10)) {
+ struct buffer_head * bh;
+ struct scatterlist * sgpnt;
+ int count, this_count_max;
+ bh = SCpnt->request.bh;
+ this_count = 0;
+ count = 0;
+ this_count_max = (scsi_CDs[dev].ten ? 0xffff : 0xff) << 4;
+ /* Calculate how many links we can use. First see if we need
+ a padding record at the start */
+ this_count = SCpnt->request.sector % 4;
+ if(this_count) count++;
+ while(bh && count < scsi_hosts[SCpnt->host].sg_tablesize) {
+ if ((this_count + (bh->b_size >> 9)) > this_count_max) break;
+ this_count += (bh->b_size >> 9);
+ count++;
+ bh = bh->b_reqnext;
+ };
+ /* Fix up in case of an odd record at the end */
+ end_rec = 0;
+ if(this_count % 4) {
+ if (count < scsi_hosts[SCpnt->host].sg_tablesize) {
+ count++;
+ end_rec = (4 - (this_count % 4)) << 9;
+ this_count += 4 - (this_count % 4);
+ } else {
+ count--;
+ this_count -= (this_count % 4);
+ };
+ };
+ SCpnt->use_sg = count; /* Number of chains */
+ count = 512;/* scsi_malloc can only allocate in chunks of 512 bytes*/
+ while( count < (SCpnt->use_sg * sizeof(struct scatterlist)))
+ count = count << 1;
+ SCpnt->sglist_len = count;
+ sgpnt = (struct scatterlist * ) scsi_malloc(count);
+ if (!sgpnt) {
+ printk("Warning - running *really* short on DMA buffers\n");
+ SCpnt->use_sg = 0; /* No memory left - bail out */
+ } else {
+ buffer = (char *) sgpnt;
+ count = 0;
+ bh = SCpnt->request.bh;
+ if(SCpnt->request.sector % 4) {
+ sgpnt[count].length = (SCpnt->request.sector % 4) << 9;
+ sgpnt[count].address = scsi_malloc(sgpnt[count].length);
+ if(!sgpnt[count].address) panic("SCSI DMA pool exhausted.");
+ sgpnt[count].alt_address = sgpnt[count].address; /* Flag to delete
+ if needed */
+ count++;
+ };
+ for(bh = SCpnt->request.bh; count < SCpnt->use_sg;
+ count++, bh = bh->b_reqnext) {
+ if (bh) { /* Need a placeholder at the end of the record? */
+ sgpnt[count].address = bh->b_data;
+ sgpnt[count].length = bh->b_size;
+ sgpnt[count].alt_address = NULL;
+ } else {
+ sgpnt[count].address = scsi_malloc(end_rec);
+ if(!sgpnt[count].address) panic("SCSI DMA pool exhausted.");
+ sgpnt[count].length = end_rec;
+ sgpnt[count].alt_address = sgpnt[count].address;
+ if (count+1 != SCpnt->use_sg) panic("Bad sr request list");
+ break;
+ };
+ if (((int) sgpnt[count].address) + sgpnt[count].length >
+ ISA_DMA_THRESHOLD & (scsi_hosts[SCpnt->host].unchecked_isa_dma)) {
+ sgpnt[count].alt_address = sgpnt[count].address;
+ /* We try and avoid exhausting the DMA pool, since it is easier
+ to control usage here. In other places we might have a more
+ pressing need, and we would be screwed if we ran out */
+ if(dma_free_sectors < (sgpnt[count].length >> 9) + 5) {
+ sgpnt[count].address = NULL;
+ } else {
+ sgpnt[count].address = scsi_malloc(sgpnt[count].length);
+ };
+/* If we start running low on DMA buffers, we abort the scatter-gather
+ operation, and free all of the memory we have allocated. We want to
+ ensure that all scsi operations are able to do at least a non-scatter/gather
+ operation */
+ if(sgpnt[count].address == NULL){ /* Out of dma memory */
+ printk("Warning: Running low on SCSI DMA buffers");
+ /* Try switching back to a non scatter-gather operation. */
+ while(--count){
+ if(sgpnt[count].alt_address)
+ scsi_free(sgpnt[count].address, sgpnt[count].length);
+ };
+ SCpnt->use_sg = 0;
+ scsi_free(buffer, SCpnt->sglist_len);
+ break;
+ }; /* if address == NULL */
+ }; /* if need DMA fixup */
+ }; /* for loop to fill list */
+#ifdef DEBUG
+ printk("SG: %d %d %d %d %d *** ",SCpnt->use_sg, SCpnt->request.sector,
+ this_count,
+ SCpnt->request.current_nr_sectors,
+ SCpnt->request.nr_sectors);
+ for(count=0; count<SCpnt->use_sg; count++)
+ printk("SGlist: %d %x %x %x\n", count,
+ sgpnt[count].address,
+ sgpnt[count].alt_address,
+ sgpnt[count].length);
+#endif
+ }; /* Able to allocate scatter-gather list */
+ };
+
+ if (SCpnt->use_sg == 0){
+ /* We cannot use scatter-gather. Do this the old fashion way */
+ if (!SCpnt->request.bh)
+ this_count = SCpnt->request.nr_sectors;
+ else
+ this_count = (SCpnt->request.bh->b_size >> 9);
+
+ start = block % 4;
+ if (start)
+ {
+ this_count = ((this_count > 4 - start) ?
+ (4 - start) : (this_count));
+ buffer = scsi_malloc(2048);
+ }
+ else if (this_count < 4)
+ {
+ buffer = scsi_malloc(2048);
+ }
+ else
+ {
+ this_count -= this_count % 4;
+ buffer = SCpnt->request.buffer;
+ if (((int) buffer) + (this_count << 9) > ISA_DMA_THRESHOLD &
+ (scsi_hosts[SCpnt->host].unchecked_isa_dma))
+ buffer = scsi_malloc(this_count << 9);
+ }
+ };
+
+ block = block >> 2; /* These are the sectors that the cdrom uses */
+ realcount = (this_count + 3) / 4;
if (((realcount > 0xff) || (block > 0x1fffff)) && scsi_CDs[dev].ten)
{
@@ -369,16 +574,35 @@ void do_sr_request (void)
cmd[5] = 0;
}
- scsi_do_cmd (SR_HOST, SR_ID, (void *) cmd, buffer, realcount << 11,
- rw_intr, SR_TIMEOUT, sense_buffer, MAX_RETRIES);
+#ifdef DEBUG
+ printk("ReadCD: %d %d %d\n",block, realcount, buffer);
+#endif
+
+ SCpnt->this_count = this_count;
+ scsi_do_cmd (SCpnt, (void *) cmd, buffer, realcount << 11,
+ rw_intr, SR_TIMEOUT, MAX_RETRIES);
}
+unsigned long sr_init1(unsigned long mem_start, unsigned long mem_end){
+ scsi_CDs = (Scsi_CD *) mem_start;
+ mem_start += MAX_SR * sizeof(Scsi_CD);
+ return mem_start;
+};
+
+void sr_attach(Scsi_Device * SDp){
+ scsi_CDs[NR_SR++].device = SDp;
+ if(NR_SR > MAX_SR) panic ("scsi_devices corrupt (sr)");
+};
+
unsigned long sr_init(unsigned long memory_start, unsigned long memory_end)
{
int i;
- bb = (struct block_buffer *) memory_start;
- memory_start += NR_SR * sizeof(struct block_buffer);
+ if(MAX_SR == 0) return memory_start;
+
+ sr_sizes = (int *) memory_start;
+ memory_start += MAX_SR * sizeof(int);
+ memset(sr_sizes, 0, MAX_SR * sizeof(int));
for (i = 0; i < NR_SR; ++i)
{
@@ -388,18 +612,19 @@ unsigned long sr_init(unsigned long memory_start, unsigned long memory_end)
scsi_CDs[i].ten = 1;
scsi_CDs[i].remap = 1;
sr_sizes[i] = scsi_CDs[i].capacity;
-
- bb[i].block = -1;
}
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
blk_size[MAJOR_NR] = sr_sizes;
+
+ /* If our host adapter is capable of scatter-gather, then we increase
+ the read-ahead to 8 blocks (16 sectors). If not, we use
+ a two block (4 sector) read ahead. */
+ if(scsi_hosts[scsi_CDs[0].device->host_no].sg_tablesize)
+ read_ahead[MAJOR_NR] = 16; /* 16 sector read-ahead */
+ else
+ read_ahead[MAJOR_NR] = 4; /* 4 sector read-ahead */
+
blkdev_fops[MAJOR_NR] = &sr_fops;
return memory_start;
}
-#endif
-
-
-
-
-
diff --git a/kernel/blk_drv/scsi/sr.h b/kernel/blk_drv/scsi/sr.h
index 865d8d0..4ac2e44 100644
--- a/kernel/blk_drv/scsi/sr.h
+++ b/kernel/blk_drv/scsi/sr.h
@@ -8,6 +8,10 @@
* Drew Eckhardt
*
* <drew@colorado.edu>
+ *
+ * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to
+ * add scatter-gather, multiple outstanding request, and other
+ * enhancements.
*/
#ifndef _SR_H
@@ -15,9 +19,6 @@
#include "scsi.h"
-#define MAX_SR 2
-extern int NR_SR;
-
typedef struct
{
unsigned capacity; /* size in blocks */
@@ -30,11 +31,6 @@ typedef struct
unsigned use:1; /* is this device still supportable */
} Scsi_CD;
-extern Scsi_CD scsi_CDs[MAX_SR];
-
-unsigned long sr_init(unsigned long, unsigned long);
+extern Scsi_CD * scsi_CDs;
-#define SR_HOST (scsi_CDs[DEVICE_NR(CURRENT->dev)].device->host_no)
-#define SR_ID (scsi_CDs[DEVICE_NR(CURRENT->dev)].device->id)
-#define SR_LUN (scsi_CDs[DEVICE_NR(CURRENT->dev)].device->lun)
#endif
diff --git a/kernel/blk_drv/scsi/sr_ioctl.c b/kernel/blk_drv/scsi/sr_ioctl.c
index cdb71bc..bffa55e 100644
--- a/kernel/blk_drv/scsi/sr_ioctl.c
+++ b/kernel/blk_drv/scsi/sr_ioctl.c
@@ -1,5 +1,3 @@
-#include <linux/config.h>
-#ifdef CONFIG_BLK_DEV_SR
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
@@ -17,72 +15,50 @@
/* The CDROM is fairly slow, so we need a little extra time */
#define IOCTL_TIMEOUT 200
-static u_char sr_cmd[10];
-static u_char data_buffer[255];
-static u_char sense_buffer[255];
-static int the_result;
-
-static struct wait_queue *sr_cmd_wait = NULL; /* For waiting until cmd done*/
-static u_char sr_lock = 0; /* To make sure that only one person is doing
- an ioctl at one time */
-static int target;
-
extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
-static void lock_sr_ioctl( void )
+static void sr_ioctl_done(Scsi_Cmnd * SCpnt)
{
- /* We do not use wakeup here because there could conceivably be three
- processes trying to get at the drive simultaneously, and we would
- be screwed if that happened.
- */
-
- while (sr_lock);
- sr_lock = 1;
-}
-
-static void unlock_sr_ioctl( void )
-{
- sr_lock = 0;
-}
-
-static void sr_ioctl_done( int host, int result )
-{
- the_result = result;
- wake_up(&sr_cmd_wait);
+ struct request * req;
+ struct task_struct * p;
+
+ req = &SCpnt->request;
+ req->dev = 0xfffe; /* Busy, but indicate request done */
+
+ if ((p = req->waiting) != NULL) {
+ req->waiting = NULL;
+ p->state = TASK_RUNNING;
+ if (p->counter > current->counter)
+ need_resched = 1;
+ }
}
/* We do our own retries because we want to know what the specific
error code is. Normally the UNIT_ATTENTION code will automatically
clear after one error */
-static int do_ioctl( void )
+static int do_ioctl(int target, unsigned char * sr_cmd)
{
- int retries = IOCTL_RETRIES;
-retry:
-
- the_result = -1;
+ Scsi_Cmnd * SCpnt;
+ int result;
- scsi_do_cmd(scsi_CDs[target].device->host_no, scsi_CDs[target].device->id,
- (void *) sr_cmd, (void *) data_buffer, 255, sr_ioctl_done,
- IOCTL_TIMEOUT, (void *) sense_buffer, 0);
+ SCpnt = allocate_device(NULL, scsi_CDs[target].device->index, 1);
+ scsi_do_cmd(SCpnt,
+ (void *) sr_cmd, NULL, 255, sr_ioctl_done,
+ IOCTL_TIMEOUT, IOCTL_RETRIES);
- while (the_result < 0) sleep_on(&sr_cmd_wait);
- if(driver_byte(the_result) != 0 &&
- (sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
- scsi_CDs[target].device->changed = 1;
- printk("Disc change detected.\n");
+ if (SCpnt->request.dev != 0xfffe){
+ SCpnt->request.waiting = current;
+ current->state = TASK_UNINTERRUPTIBLE;
+ while (SCpnt->request.dev != 0xfffe) schedule();
};
- if (the_result && retries)
- {
- retries--;
- goto retry;
- }
+ result = SCpnt->result;
/* Minimal error checking. Ignore cases we know about, and report the rest. */
- if(driver_byte(the_result) != 0)
- switch(sense_buffer[2] & 0xf) {
+ if(driver_byte(result) != 0)
+ switch(SCpnt->sense_buffer[2] & 0xf) {
case UNIT_ATTENTION:
scsi_CDs[target].device->changed = 1;
printk("Disc change detected.\n");
@@ -98,20 +74,27 @@ retry:
scsi_CDs[target].device->host_no,
scsi_CDs[target].device->id,
scsi_CDs[target].device->lun,
- the_result);
+ result);
printk("\tSense class %x, sense error %x, extended sense %x\n",
- sense_class(sense_buffer[0]),
- sense_error(sense_buffer[0]),
- sense_buffer[2] & 0xf);
+ sense_class(SCpnt->sense_buffer[0]),
+ sense_error(SCpnt->sense_buffer[0]),
+ SCpnt->sense_buffer[2] & 0xf);
};
- return the_result;
+
+ result = SCpnt->result;
+ SCpnt->request.dev = -1; /* Deallocate */
+ wake_up(&scsi_devices[SCpnt->index].device_wait);
+ /* Wake up a process waiting for device*/
+ return result;
}
int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsigned long arg)
{
+ u_char sr_cmd[10];
+
int dev = inode->i_rdev;
- int result;
+ int result, target;
target = MINOR(dev);
@@ -119,7 +102,6 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsign
{
/* Sun-compatible */
case CDROMPAUSE:
- lock_sr_ioctl();
sr_cmd[0] = SCMD_PAUSE_RESUME;
sr_cmd[1] = scsi_CDs[target].device->lun << 5;
@@ -128,13 +110,10 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsign
sr_cmd[8] = 1;
sr_cmd[9] = 0;
- result = do_ioctl();
-
- unlock_sr_ioctl();
+ result = do_ioctl(target, sr_cmd);
return result;
case CDROMRESUME:
- lock_sr_ioctl();
sr_cmd[0] = SCMD_PAUSE_RESUME;
sr_cmd[1] = scsi_CDs[target].device->lun << 5;
@@ -143,16 +122,13 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsign
sr_cmd[8] = 0;
sr_cmd[9] = 0;
- result = do_ioctl();
+ result = do_ioctl(target, sr_cmd);
- unlock_sr_ioctl();
return result;
case CDROMPLAYMSF:
{
struct cdrom_msf msf;
- lock_sr_ioctl();
-
memcpy_fromfs(&msf, (void *) arg, sizeof(msf));
sr_cmd[0] = SCMD_PLAYAUDIO_MSF;
@@ -166,17 +142,13 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsign
sr_cmd[8] = msf.cdmsf_frame1;
sr_cmd[9] = 0;
- result = do_ioctl();
-
- unlock_sr_ioctl();
+ result = do_ioctl(target, sr_cmd);
return result;
}
case CDROMPLAYTRKIND:
{
struct cdrom_ti ti;
- lock_sr_ioctl();
-
memcpy_fromfs(&ti, (void *) arg, sizeof(ti));
sr_cmd[0] = SCMD_PLAYAUDIO_TI;
@@ -190,9 +162,8 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsign
sr_cmd[8] = ti.cdti_ind1;
sr_cmd[9] = 0;
- result = do_ioctl();
+ result = do_ioctl(target, sr_cmd);
- unlock_sr_ioctl();
return result;
}
@@ -202,42 +173,30 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsign
return -EINVAL;
case CDROMSTOP:
- lock_sr_ioctl();
-
sr_cmd[0] = START_STOP;
sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
sr_cmd[4] = 0;
- result = do_ioctl();
-
- unlock_sr_ioctl();
+ result = do_ioctl(target, sr_cmd);
return result;
case CDROMSTART:
- lock_sr_ioctl();
-
sr_cmd[0] = START_STOP;
sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
sr_cmd[4] = 1;
- result = do_ioctl();
-
- unlock_sr_ioctl();
+ result = do_ioctl(target, sr_cmd);
return result;
case CDROMEJECT:
- lock_sr_ioctl();
-
sr_cmd[0] = START_STOP;
sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
sr_cmd[4] = 0x02;
- result = do_ioctl();
-
- unlock_sr_ioctl();
+ result = do_ioctl(target, sr_cmd);
return result;
case CDROMVOLCTRL:
@@ -254,5 +213,3 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsign
return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
}
}
-
-#endif
diff --git a/kernel/blk_drv/scsi/st.c b/kernel/blk_drv/scsi/st.c
index 01feaac..7e295ad 100644
--- a/kernel/blk_drv/scsi/st.c
+++ b/kernel/blk_drv/scsi/st.c
@@ -1,34 +1,1077 @@
/*
- The st.c file is a sub-stub file. I just wanted to have all the detect code, etc in the
- mid level driver present and working. If no one else volunteers for this, I'll
- do it - but it's low on my list of priorities.
-*/
-#include <linux/config.h>
+ SCSI Tape Driver for Linux
-#ifdef CONFIG_BLK_DEV_ST
-#include "scsi.h"
-#include "st.h"
+ Version 0.02 for Linux 0.98.4 and Eric Youngdale's new scsi driver
+
+ History:
+ Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
+
+ Features:
+ - support for different block sizes and internal buffering
+ - *nix-style ioctl with codes from mtio.h from the QIC-02 driver by
+ Hennus Bergman (command MTSETBLK added)
+ - character device
+ - rewind and non-rewind devices
+ - capability to handle several tape drives simultaneously
+ - one buffer if one drive, two buffers if more than one drive (limits the
+ number of simultaneously open drives to two)
+ - write behind
+
+ Devices:
+ Autorewind devices have minor numbers equal to the tape numbers (0 > ).
+ Nonrewind device has the minor number equal to tape number + 128.
+
+ Problems:
+ The end of media detection may not work correctly because of the buffering.
+ If you want to do multiple tape backups relying on end of tape detection,
+ you should disable write behind and in addition to that check that the
+ tapes are readable.
+
+ Kai Makisara, Nov 9, 1992 email makisara@vtinsx.ins.vtt.fi or
+ Kai.Makisara@vtt.fi
+ Last changes Nov 29, 1992.
+*/
-#define MAJOR_NR 9
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
-#include "../blk.h"
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/mtio.h>
+#include <linux/ioctl.h>
+#include <linux/fcntl.h>
+#include <asm/segment.h>
+#include <asm/system.h>
-Scsi_Tape scsi_tapes[MAX_ST];
-static int st_sizes[MAX_ST];
+#define MAJOR_NR 9
+#include "../blk.h"
+#include "scsi.h"
+#include "st.h"
+
+#define MAX_RETRIES 5
+#define NO_TAPE NOT_READY
+
+/* #define DEBUG */
+
+#define ST_TIMEOUT 1000
+#define ST_LONG_TIMEOUT 200000
+
+/* Number of ST_BLOCK_SIZE blocks in the buffers */
+#define ST_BUFFER_BLOCKS 64
+/* Write-behind can be disabled by setting ST_WRITE_THRESHOLD_BLOCKS equal to or
+ larger than ST_BUFFER_BLOCKS */
+#define ST_WRITE_THRESHOLD_BLOCKS 60
+#define ST_BLOCK_SIZE 512
+#define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_BLOCK_SIZE)
+#define ST_WRITE_THRESHOLD (ST_WRITE_THRESHOLD_BLOCKS * ST_BLOCK_SIZE)
+
+static int st_nbr_buffers;
+static ST_buffer *st_buffers[2];
+
+static Scsi_Tape * scsi_tapes;
int NR_ST=0;
+int MAX_ST=0;
+
+static int st_int_ioctl(struct inode * inode,struct file * file,
+ unsigned int cmd_in, unsigned int arg);
+
+
+
+
+/* Wakeup from interrupt */
+static void st_sleep_done (Scsi_Cmnd * SCpnt)
+{
+ int st_nbr;
+
+ if ((st_nbr = SCpnt->request.dev) < NR_ST && st_nbr >= 0) {
+ if (scsi_tapes[st_nbr].buffer->writing &&
+ (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
+ (SCpnt->sense_buffer[2] & 0x40))
+ scsi_tapes[st_nbr].buffer->last_result = 0x7fffffff;
+ else
+ scsi_tapes[st_nbr].buffer->last_result = SCpnt->result;
+ if (scsi_tapes[st_nbr].buffer->writing)
+ SCpnt->request.dev = -1;
+ else
+ SCpnt->request.dev = 0xffff;
+ if (scsi_tapes[st_nbr].buffer->writing <= 0)
+ wake_up( &scsi_tapes[st_nbr].waiting );
+ }
+#ifdef DEBUG
+ else
+ printk("st?: Illegal interrupt device %x\n", st_nbr);
+#endif
+}
+
+
+
+#ifdef DEBUG
+/* Print sense information */
+static void decode_sns(int dev, char *sense_buffer)
+{
+ static char *snstext[] = {
+ "None","Recovered Error","Not Ready","Medium Error","Hardware Error",
+ "Illegal Request","Unit Attention","Data Protect","Blank Check",
+ "Key=E","Key=F","Filemark","End-Of-Medium","Incorrect Block Length",
+ "14","15"};
+
+ if (sense_buffer[0]!=0) {
+ if ((sense_buffer[0] & 0x70) == 0x70) {
+ if (sense_buffer[2] & 0x80) printk( "FMK ");
+ if (sense_buffer[2] & 0x40) printk( "EOM ");
+ if (sense_buffer[2] & 0x20) printk( "ILI ");
+ printk( "st%d: sense key %s\n", dev, snstext[sense_buffer[2] & 0x0f]);
+ } else {
+ if (sense_buffer[0] < 15)
+ printk("st%d: old sense key %s\n", dev, snstext[sense_buffer[0] & 0x0f]);
+ else
+ printk("st%d: sns = %2x %2x\n", dev, sense_buffer[0], sense_buffer[2]);
+ }
+ }
+ return;
+}
+#endif
+
+
+/* Convert the result to success code */
+static int st_chk_result(int dev, int result, char *sense)
+{
+ if (!result)
+ return 0;
+#ifdef DEBUG
+ printk("st%d: Error: %x\n", dev, result);
+ decode_sns(dev, sense);
+#endif
+ if ((sense[0] & 0x70) == 0x70 &&
+ ((sense[2] & 0x80) /* || ((sense[2] & 0x0f) == 8) */ ))
+ return 0;
+ return (-EIO);
+}
+
+
+#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
+/* Handle the write-behind checking */
+static void write_behind_check(int dev)
+{
+ cli();
+ if (scsi_tapes[dev].buffer->last_result < 0) {
+ scsi_tapes[dev].buffer->writing = (- scsi_tapes[dev].buffer->writing);
+ sleep_on( &scsi_tapes[dev].waiting );
+ scsi_tapes[dev].buffer->writing = (- scsi_tapes[dev].buffer->writing);
+ }
+ sti();
+
+ if (scsi_tapes[dev].buffer->writing < scsi_tapes[dev].buffer->buffer_bytes)
+ memcpy(scsi_tapes[dev].buffer->b_data,
+ scsi_tapes[dev].buffer->b_data + scsi_tapes[dev].buffer->writing,
+ scsi_tapes[dev].buffer->buffer_bytes -
+ scsi_tapes[dev].buffer->writing);
+ scsi_tapes[dev].buffer->buffer_bytes -= scsi_tapes[dev].buffer->writing;
+ scsi_tapes[dev].buffer->writing = 0;
+
+ return;
+}
+#endif
+
+
+
+/* Open the device */
+static int scsi_tape_open(struct inode * inode, struct file * filp)
+{
+ int dev;
+ unsigned short flags;
+ int i;
+ unsigned char cmd[10];
+ Scsi_Cmnd * SCpnt;
+
+ dev = inode->i_rdev & 127;
+ if (dev >= NR_ST)
+ return (-ENXIO);
+ if (scsi_tapes[dev].in_use) {
+ printk("st%d: Device already in use.\n", dev);
+ return (-EBUSY);
+ }
+
+ /* Allocate buffer for this user */
+ for (i=0; i < st_nbr_buffers; i++)
+ if (!st_buffers[i]->in_use)
+ break;
+ if (i >= st_nbr_buffers) {
+ printk("st%d: No free buffers.\n", dev);
+ return (-EBUSY);
+ }
+ st_buffers[i]->in_use = 1;
+ st_buffers[i]->writing = 0;
+ scsi_tapes[dev].buffer = st_buffers[i];
+ scsi_tapes[dev].in_use = 1;
+
+ flags = filp->f_flags;
+ scsi_tapes[dev].write_prot = ((flags & O_ACCMODE) == O_RDONLY);
+
+ scsi_tapes[dev].dirty = 0;
+ scsi_tapes[dev].rw = 0;
+ scsi_tapes[dev].eof = 0;
+ scsi_tapes[dev].eof_hit = 0;
+
+ SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
+ if (!SCpnt) {
+ printk("st%d: Tape request not allocated", dev);
+ return (-EBUSY);
+ }
+
+ SCpnt->sense_buffer[0]=0;
+ memset ((void *) &cmd[0], 0, 10);
+ cmd[0] = TEST_UNIT_READY;
+ SCpnt->request.dev = dev;
+ scsi_do_cmd(SCpnt,
+ (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
+ ST_BLOCK_SIZE, st_sleep_done, ST_LONG_TIMEOUT, MAX_RETRIES);
+
+ if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
+
+ if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
+ (SCpnt->sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
+#ifdef DEBUG
+ decode_sns(dev, SCpnt->sense_buffer);
+#endif
+ SCpnt->sense_buffer[0]=0;
+ memset ((void *) &cmd[0], 0, 10);
+ cmd[0] = TEST_UNIT_READY;
+ SCpnt->request.dev = dev;
+ scsi_do_cmd(SCpnt,
+ (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
+ ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
+
+ if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
+ }
+
+ if (SCpnt->result != 0) {
+#ifdef DEBUG
+ decode_sns(dev, SCpnt->sense_buffer);
+#endif
+ if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
+ (SCpnt->sense_buffer[2] & 0x0f) == NO_TAPE)
+ printk("st%d: No tape.\n", dev);
+ else
+ printk("st%d: Error %x.\n", dev, SCpnt->result);
+ scsi_tapes[dev].buffer->in_use = 0;
+ scsi_tapes[dev].in_use = 0;
+ SCpnt->request.dev = -1; /* Mark as not busy */
+ return (-EIO);
+ }
+
+ SCpnt->sense_buffer[0]=0;
+ memset ((void *) &cmd[0], 0, 10);
+ cmd[0] = READ_BLOCK_LIMITS;
+ SCpnt->request.dev = dev;
+ scsi_do_cmd(SCpnt,
+ (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
+ ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
+
+ if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
+
+ if (!SCpnt->result && !SCpnt->sense_buffer[0]) {
+ scsi_tapes[dev].max_block = (scsi_tapes[dev].buffer->b_data[1] << 16) |
+ (scsi_tapes[dev].buffer->b_data[2] << 8) | scsi_tapes[dev].buffer->b_data[3];
+ scsi_tapes[dev].min_block = (scsi_tapes[dev].buffer->b_data[4] << 8) |
+ scsi_tapes[dev].buffer->b_data[5];
+#ifdef DEBUG
+ printk("st%d: Block limits %d - %d bytes.\n", dev, scsi_tapes[dev].min_block,
+ scsi_tapes[dev].max_block);
+#endif
+ }
+ else {
+ scsi_tapes[dev].min_block = scsi_tapes[dev].max_block = (-1);
+#ifdef DEBUG
+ printk("st%d: Can't read block limits.\n", dev);
+#endif
+ }
+
+ SCpnt->sense_buffer[0]=0;
+ memset ((void *) &cmd[0], 0, 10);
+ cmd[0] = MODE_SENSE;
+ cmd[4] = 12;
+ SCpnt->request.dev = dev;
+ scsi_do_cmd(SCpnt,
+ (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
+ ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
+
+ if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
+
+ i = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
+ if (i) {
+#ifdef DEBUG
+ printk("st%d: No Mode Sense.\n", dev);
+#endif
+ scsi_tapes[dev].buffer->b_data[2] =
+ scsi_tapes[dev].buffer->b_data[3] = 0;
+ }
+ SCpnt->request.dev = -1; /* Mark as not busy */
+
+#ifdef DEBUG
+ printk("st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", dev,
+ scsi_tapes[dev].buffer->b_data[0], scsi_tapes[dev].buffer->b_data[1],
+ scsi_tapes[dev].buffer->b_data[2], scsi_tapes[dev].buffer->b_data[3]);
+#endif
+
+ if (scsi_tapes[dev].buffer->b_data[3] >= 8) {
+ scsi_tapes[dev].block_size = scsi_tapes[dev].buffer->b_data[9] * 65536 +
+ scsi_tapes[dev].buffer->b_data[10] * 256 + scsi_tapes[dev].buffer->b_data[11];
+#ifdef DEBUG
+ printk("st%d: Density %x, tape length: %x, blocksize: %d\n", dev,
+ scsi_tapes[dev].buffer->b_data[4], scsi_tapes[dev].buffer->b_data[5] *
+ 65536 + scsi_tapes[dev].buffer->b_data[6] * 256 +
+ scsi_tapes[dev].buffer->b_data[7], scsi_tapes[dev].buffer->b_data[9] *
+ 65536 + scsi_tapes[dev].buffer->b_data[10] * 256 +
+ scsi_tapes[dev].buffer->b_data[11]);
+#endif
+ if (scsi_tapes[dev].block_size == 0) {
+ printk("st%d: Fixing block size to 512 bytes.\n", dev);
+ if (st_int_ioctl(inode, filp, MTSETBLK, ST_BLOCK_SIZE)) {
+ printk("st%d: Can't set fixed block size.\n", dev);
+ scsi_tapes[dev].buffer->in_use = 0;
+ scsi_tapes[dev].in_use = 0;
+ return (-EIO);
+ }
+ scsi_tapes[dev].block_size = ST_BLOCK_SIZE;
+ }
+ }
+ else
+ scsi_tapes[dev].block_size = ST_BLOCK_SIZE;
+
+ scsi_tapes[dev].buffer->buffer_blocks =
+ ST_BUFFER_SIZE / scsi_tapes[dev].block_size;
+ scsi_tapes[dev].buffer->buffer_size =
+ scsi_tapes[dev].buffer->buffer_blocks * scsi_tapes[dev].block_size;
+ scsi_tapes[dev].buffer->buffer_bytes = scsi_tapes[dev].buffer->read_pointer = 0;
+
+#ifdef DEBUG
+ printk("st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev,
+ scsi_tapes[dev].block_size, scsi_tapes[dev].buffer->buffer_size,
+ scsi_tapes[dev].buffer->buffer_blocks);
+#endif
+
+ if (scsi_tapes[dev].buffer->b_data[2] & 0x80) {
+ scsi_tapes[dev].write_prot = 1;
+#ifdef DEBUG
+ printk( "st%d: Write protected\n", dev);
+#endif
+ }
+
+ return 0;
+}
+
+
+/* Close the device*/
+static void scsi_tape_close(struct inode * inode, struct file * filp)
+{
+ int dev;
+ int offset, transfer, blks, rewind;
+ static unsigned char cmd[10];
+ Scsi_Cmnd * SCpnt;
+
+ dev = inode->i_rdev;
+ rewind = (dev & 0x80) == 0;
+ dev = dev & 127;
+
+ if ( scsi_tapes[dev].rw == 2) {
+
+#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
+ if (scsi_tapes[dev].buffer->writing) {
+ write_behind_check(dev);
+ if (scsi_tapes[dev].buffer->last_result) {
+ /* What should actually be done here ? */
+ printk("st%d: Async write error %x.\n", dev,
+ scsi_tapes[dev].buffer->last_result);
+ }
+ }
+#endif
+
+ SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
+
+ if (scsi_tapes[dev].dirty==1) {
+ offset = scsi_tapes[dev].buffer->buffer_bytes;
+ transfer = ((offset + scsi_tapes[dev].block_size - 1) /
+ scsi_tapes[dev].block_size) * scsi_tapes[dev].block_size;
+#ifdef DEBUG
+ printk("st%d: Final transfer %d bytes (length %d).\n", dev,
+ transfer, filp->f_pos);
+#endif
+ memset(scsi_tapes[dev].buffer->b_data + offset, 0, transfer - offset);
+
+ SCpnt->sense_buffer[0] = 0;
+ memset(cmd, 0, 10);
+ cmd[0] = WRITE_6;
+ cmd[1] = 1;
+ blks = transfer / scsi_tapes[dev].block_size;
+ cmd[2] = blks >> 16;
+ cmd[3] = blks >> 8;
+ cmd[4] = blks;
+ SCpnt->request.dev = dev;
+ scsi_do_cmd (SCpnt,
+ (void *) cmd, scsi_tapes[dev].buffer->b_data, transfer,
+ st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
+
+ if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
+
+ if (SCpnt->result != 0) {
+ printk("st%d: Error on last write:\n", dev);
+#ifdef DEBUG
+ st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
+#endif
+ SCpnt->request.dev = -1; /* Mark as not busy */
+ if (rewind)
+ st_int_ioctl(inode, filp, MTREW, 1);
+ scsi_tapes[dev].buffer->in_use = 0;
+ scsi_tapes[dev].in_use = 0;
+ return;
+ }
+ }
-void do_st_request(void)
+ SCpnt->sense_buffer[0] = 0;
+ memset(cmd, 0, 10);
+ cmd[0] = WRITE_FILEMARKS;
+ cmd[4] = 1;
+ SCpnt->request.dev = dev;
+ scsi_do_cmd( SCpnt,
+ (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data, ST_BLOCK_SIZE,
+ st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
+
+ if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
+ if (SCpnt->result) {
+ printk("st%d: Error on write filemark:\n", dev);
+#ifdef DEBUG
+ st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
+#endif
+ SCpnt->request.dev = -1; /* Mark as not busy */
+ if (rewind)
+ st_int_ioctl(inode, filp, MTREW, 1);
+ scsi_tapes[dev].buffer->in_use = 0;
+ scsi_tapes[dev].in_use = 0;
+ return;
+ }
+ SCpnt->request.dev = -1; /* Mark as not busy */
+
+#ifdef DEBUG
+ printk("st%d: Buffer flushed, EOF written\n", dev);
+#endif
+ }
+ else if (!rewind && scsi_tapes[dev].eof && !scsi_tapes[dev].eof_hit)
+ st_int_ioctl(inode, filp, MTBSF, 1);
+ /* Back over the EOF hit inadvertently */
+
+ if (rewind)
+ st_int_ioctl(inode, filp, MTREW, 1);
+
+ scsi_tapes[dev].buffer->in_use = 0;
+ scsi_tapes[dev].in_use = 0;
+
+ return;
+}
+
+
+/* Write command */
+int st_write(struct inode * inode, struct file * filp, char * buf, int count)
{
- panic("There is no st driver.\n\r");
+ int dev;
+ int total, do_count, blks, retval;
+ static unsigned char cmd[10];
+ char *b_point;
+ Scsi_Cmnd * SCpnt;
+
+ dev = inode->i_rdev & 127;
+#ifdef DEBUG
+ if (!scsi_tapes[dev].in_use) {
+ printk("st%d: Incorrect device.\n", dev);
+ return (-EIO);
+ }
+#endif
+
+ if (scsi_tapes[dev].write_prot)
+ return (-EACCES);
+
+ if (scsi_tapes[dev].rw == 1) {
+ printk("st%d: No write allowed after read.\n", dev);
+ return (-EACCES);
+ }
+
+#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
+ if (scsi_tapes[dev].buffer->writing) {
+ write_behind_check(dev);
+ if (scsi_tapes[dev].buffer->last_result) {
+#ifdef DEBUG
+ printk("st%d: Async write error %x.\n", dev,
+ scsi_tapes[dev].buffer->last_result);
+#endif
+ /*if (scsi_tapes[dev].buffer->last_result = 0x7fffffff)
+ retval = (-ENOSPC);
+ else */
+ retval = (-EIO);
+ return retval;
+ }
+ }
+#endif
+
+ SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
+
+ total = count;
+
+ memset(cmd, 0, 10);
+ cmd[0] = WRITE_6;
+ cmd[1] = 1;
+
+ scsi_tapes[dev].rw = 2;
+
+ b_point = buf;
+ while((scsi_tapes[dev].buffer->buffer_bytes + count) >=
+ scsi_tapes[dev].buffer->buffer_size) {
+ do_count = scsi_tapes[dev].buffer->buffer_size -
+ scsi_tapes[dev].buffer->buffer_bytes;
+ memcpy_fromfs(scsi_tapes[dev].buffer->b_data +
+ scsi_tapes[dev].buffer->buffer_bytes,b_point,do_count);
+
+ blks = scsi_tapes[dev].buffer->buffer_blocks;
+ cmd[2] = blks >> 16;
+ cmd[3] = blks >> 8;
+ cmd[4] = blks;
+ SCpnt->sense_buffer[0] = 0;
+ SCpnt->request.dev = dev;
+ scsi_do_cmd (SCpnt,
+ (void *) cmd, scsi_tapes[dev].buffer->b_data,
+ scsi_tapes[dev].buffer->buffer_size,
+ st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
+
+ if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
+
+ if (SCpnt->result || SCpnt->sense_buffer[0] != 0) {
+#ifdef DEBUG
+ printk("st%d: Error on write:\n", dev);
+ st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
+#endif
+ if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
+ (SCpnt->sense_buffer[2] & 0x40))
+ retval = (-ENOSPC); /* EOM */
+ else
+ retval = (-EIO);
+ SCpnt->request.dev = -1; /* Mark as not busy */
+ if (count < total)
+ return total - count;
+ else
+ return retval;
+ }
+ filp->f_pos += do_count;
+ b_point += do_count;
+ count -= do_count;
+ scsi_tapes[dev].buffer->buffer_bytes = 0;
+ scsi_tapes[dev].dirty = 0;
+ }
+ if (count != 0) {
+ scsi_tapes[dev].dirty = 1;
+ memcpy_fromfs(scsi_tapes[dev].buffer->b_data +
+ scsi_tapes[dev].buffer->buffer_bytes,b_point,count);
+ filp->f_pos += count;
+ scsi_tapes[dev].buffer->buffer_bytes += count;
+ count = 0;
+ }
+
+ do_count = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
+ if (do_count) {
+ SCpnt->request.dev = -1;
+ return do_count;
+ }
+
+#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
+ if (scsi_tapes[dev].buffer->buffer_bytes >= ST_WRITE_THRESHOLD) {
+ /* Schedule an asynchronous write */
+ scsi_tapes[dev].buffer->writing = (scsi_tapes[dev].buffer->buffer_bytes /
+ scsi_tapes[dev].block_size) * scsi_tapes[dev].block_size;
+ scsi_tapes[dev].dirty = 0;
+
+ blks = scsi_tapes[dev].buffer->writing / scsi_tapes[dev].block_size;
+ cmd[2] = blks >> 16;
+ cmd[3] = blks >> 8;
+ cmd[4] = blks;
+ SCpnt->result = scsi_tapes[dev].buffer->last_result = -1;
+ SCpnt->sense_buffer[0] = 0;
+ SCpnt->request.dev = dev;
+ scsi_do_cmd (SCpnt,
+ (void *) cmd, scsi_tapes[dev].buffer->b_data,
+ scsi_tapes[dev].buffer->writing,
+ st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
+ }
+ else
+#endif
+ SCpnt->request.dev = -1; /* Mark as not busy */
+
+ return( total);
+}
+
+
+/* Read command */
+int st_read(struct inode * inode, struct file * filp, char * buf, int count)
+{
+ int dev;
+ int total;
+ int transfer, blks;
+ static unsigned char cmd[10];
+ Scsi_Cmnd * SCpnt;
+
+ dev = inode->i_rdev & 127;
+#ifdef DEBUG
+ if (!scsi_tapes[dev].in_use) {
+ printk("st%d: Incorrect device.\n", dev);
+ return (-EIO);
+ }
+#endif
+
+ if (scsi_tapes[dev].rw == 2) {
+ printk("st%d: No read allowed after write.\n", dev);
+ return (-EACCES);
+ }
+
+#ifdef DEBUG
+ if (scsi_tapes[dev].eof)
+ printk("st%d: EOF flag up. Bytes %d\n", dev,
+ scsi_tapes[dev].buffer->buffer_bytes);
+#endif
+ if ((scsi_tapes[dev].buffer->buffer_bytes == 0) && scsi_tapes[dev].eof) {
+ if (scsi_tapes[dev].eof == 1)
+ return 0;
+ else /* EOM or blank check */
+ return (-EIO);
+ }
+
+ scsi_tapes[dev].rw = 1;
+
+ SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
+
+ for (total = 0; total < count; ) {
+
+ if (scsi_tapes[dev].buffer->buffer_bytes == 0 && scsi_tapes[dev].eof == 0) {
+
+ memset(cmd, 0, 10);
+ cmd[0] = READ_6;
+ cmd[1] = 1;
+ blks = scsi_tapes[dev].buffer->buffer_blocks;
+ cmd[2] = blks >> 16;
+ cmd[3] = blks >> 8;
+ cmd[4] = blks;
+
+ SCpnt->sense_buffer[0] = 0;
+ SCpnt->request.dev = dev;
+ scsi_do_cmd (SCpnt,
+ (void *) cmd, scsi_tapes[dev].buffer->b_data,
+ scsi_tapes[dev].buffer->buffer_size,
+ st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
+
+ if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
+
+ scsi_tapes[dev].buffer->read_pointer = 0;
+
+ if (SCpnt->result != 0 || SCpnt->sense_buffer[0] != 0) {
+#ifdef DEBUG
+ printk("st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", dev,
+ SCpnt->sense_buffer[0], SCpnt->sense_buffer[1],
+ SCpnt->sense_buffer[2], SCpnt->sense_buffer[3],
+ SCpnt->sense_buffer[4], SCpnt->sense_buffer[5],
+ SCpnt->sense_buffer[6], SCpnt->sense_buffer[7]);
+#endif
+ if ((SCpnt->sense_buffer[0] & 0x70) == 0x70) { /* extended sense */
+
+ if ((SCpnt->sense_buffer[2] & 0xe0) != 0) { /* EOF, EOM, or ILI */
+ transfer = (SCpnt->sense_buffer[3] << 24) |
+ (SCpnt->sense_buffer[4] << 16) |
+ (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6];
+
+ if (SCpnt->sense_buffer[2] & 0x20) {
+ printk("st%d: Incorrect block size.\n", dev);
+ SCpnt->request.dev = -1; /* Mark as not busy */
+ return (-EIO);
+ }
+ else if (SCpnt->sense_buffer[2] & 0x40) {
+ scsi_tapes[dev].eof = 2; /* What should be done at EOM ? */
+ scsi_tapes[dev].buffer->buffer_bytes =
+ (scsi_tapes[dev].buffer->buffer_blocks - transfer) *
+ scsi_tapes[dev].block_size;
+#ifdef DEBUG
+ printk("st%d: EOM detected (%d blocks read).\n", dev,
+ scsi_tapes[dev].buffer->buffer_blocks - transfer);
+#endif
+ }
+ else if (SCpnt->sense_buffer[2] & 0x80) {
+ scsi_tapes[dev].eof = 1;
+ scsi_tapes[dev].buffer->buffer_bytes =
+ (scsi_tapes[dev].buffer->buffer_blocks - transfer) *
+ scsi_tapes[dev].block_size;
+#ifdef DEBUG
+ printk("st%d: EOF detected (%d blocks read, transferred %d bytes).\n",
+ dev, scsi_tapes[dev].buffer->buffer_blocks - transfer, total);
+#endif
+ } /* end of EOF, EOM, ILI test */
+ }
+ else { /* nonzero sense key */
+#ifdef DEBUG
+ printk("st%d: Tape error. Sense key %x\n", dev,
+ SCpnt->sense_buffer[2] & 0x0f);
+ decode_sns(dev, SCpnt->sense_buffer);
+#endif
+ SCpnt->request.dev = -1;
+ if (total)
+ return total;
+ else
+ return -EIO;
+ }
+ }
+ else {
+ transfer = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
+ SCpnt->request.dev = -1; /* Mark as not busy */
+ return transfer;
+ }
+ }
+ else
+ scsi_tapes[dev].buffer->buffer_bytes = scsi_tapes[dev].buffer->buffer_size;
+ } /* if (SCpnt->result != 0 || SCpnt->sense_buffer[0] != 0) */
+
+ if (scsi_tapes[dev].buffer->buffer_bytes > 0) {
+#ifdef DEBUG
+ if (scsi_tapes[dev].eof)
+ printk("st%d: EOF up. Left %d, needed %d.\n", dev,
+ scsi_tapes[dev].buffer->buffer_bytes, count - total);
+#endif
+ transfer = scsi_tapes[dev].buffer->buffer_bytes < count - total ?
+ scsi_tapes[dev].buffer->buffer_bytes : count - total;
+ memcpy_tofs(buf, scsi_tapes[dev].buffer->b_data +
+ scsi_tapes[dev].buffer->read_pointer,transfer);
+ filp->f_pos += transfer;
+ buf += transfer;
+ total += transfer;
+ scsi_tapes[dev].buffer->buffer_bytes -= transfer;
+ scsi_tapes[dev].buffer->read_pointer += transfer;
+ }
+ else if (scsi_tapes[dev].eof) {
+ scsi_tapes[dev].eof_hit = 1;
+ SCpnt->request.dev = -1; /* Mark as not busy */
+ if (total)
+ return total;
+ else
+ return (-EIO);
+ }
+
+ } /* for (total = 0; total < count; ) */
+
+ SCpnt->request.dev = -1; /* Mark as not busy */
+
+ return total;
}
-unsigned long st_init(unsigned long memory_start, unsigned long memory_end)
+
+/* Internal ioctl function */
+static int st_int_ioctl(struct inode * inode,struct file * file,
+ unsigned int cmd_in, unsigned int arg)
{
- blk_dev[MAJOR_NR].request_fn = do_st_request;
- blk_size[MAJOR_NR] = st_sizes;
- return memory_start;
+ int dev = inode->i_rdev;
+ int timeout = ST_LONG_TIMEOUT;
+ long ltmp;
+ int ioctl_result;
+ unsigned char cmd[10];
+ Scsi_Cmnd * SCpnt;
+
+ dev = dev & 127;
+
+ SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
+
+ memset(cmd, 0, 10);
+ switch (cmd_in) {
+ case MTFSF:
+ case MTFSFM:
+ cmd[0] = SPACE;
+ cmd[1] = 0x01; /* Space FileMarks */
+ cmd[2] = (arg >> 16);
+ cmd[3] = (arg >> 8);
+ cmd[4] = arg;
+#ifdef DEBUG
+ printk("st%d: Spacing tape forward %d files.\n", dev,
+ cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
+#endif
+ break;
+ case MTBSF:
+ case MTBSFM:
+ cmd[0] = SPACE;
+ cmd[1] = 0x01; /* Space FileMarks */
+ ltmp = (-arg);
+ cmd[2] = (ltmp >> 16);
+ cmd[3] = (ltmp >> 8);
+ cmd[4] = ltmp;
+#ifdef DEBUG
+ if (cmd[2] & 0x80)
+ ltmp = 0xff000000;
+ ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
+ printk("st%d: Spacing tape backward %d files.\n", dev, (-ltmp));
+#endif
+ break;
+ case MTFSR:
+ cmd[0] = SPACE;
+ cmd[1] = 0x00; /* Space Blocks */
+ cmd[2] = (arg >> 16);
+ cmd[3] = (arg >> 8);
+ cmd[4] = arg;
+#ifdef DEBUG
+ printk("st%d: Spacing tape forward %d blocks.\n", dev,
+ cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
+#endif
+ break;
+ case MTBSR:
+ cmd[0] = SPACE;
+ cmd[1] = 0x00; /* Space Blocks */
+ ltmp = (-arg);
+ cmd[2] = (ltmp >> 16);
+ cmd[3] = (ltmp >> 8);
+ cmd[4] = ltmp;
+ SCpnt->result = -1;
+#ifdef DEBUG
+ if (cmd[2] & 0x80)
+ ltmp = 0xff000000;
+ ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
+ printk("st%d: Spacing tape backward %d blocks.\n", dev, (-ltmp));
+#endif
+ break;
+ case MTWEOF:
+ if (scsi_tapes[dev].write_prot)
+ return (-EACCES);
+ cmd[0] = WRITE_FILEMARKS;
+ cmd[2] = (arg >> 16);
+ cmd[3] = (arg >> 8);
+ cmd[4] = arg;
+ timeout = ST_TIMEOUT;
+#ifdef DEBUG
+ printk("st%d: Writing %d filemarks.\n", dev,
+ cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
+#endif
+ break;
+ case MTREW:
+ cmd[0] = REZERO_UNIT;
+ cmd[1] = 1; /* Don't wait for completion */
+ timeout = ST_TIMEOUT;
+#ifdef DEBUG
+ printk("st%d: Rewinding tape.\n", dev);
+#endif
+ break;
+ case MTOFFL:
+ cmd[0] = START_STOP;
+ cmd[1] = 1; /* Don't wait for completion */
+ timeout = ST_TIMEOUT;
+#ifdef DEBUG
+ printk("st%d: Unloading tape.\n", dev);
+#endif
+ break;
+ case MTNOP:
+#ifdef DEBUG
+ printk("st%d: No op on tape.\n", dev);
+#endif
+ return 0; /* Should do something ? */
+ break;
+ case MTRETEN:
+ cmd[0] = START_STOP;
+ cmd[1] = 1; /* Don't wait for completion */
+ cmd[4] = 3;
+ timeout = ST_TIMEOUT;
+#ifdef DEBUG
+ printk("st%d: Retensioning tape.\n", dev);
+#endif
+ break;
+ case MTEOM:
+ cmd[0] = SPACE;
+ cmd[1] = 3;
+#ifdef DEBUG
+ printk("st%d: Spacing to end of tape media.\n", dev);
+#endif
+ break;
+ case MTERASE:
+ if (scsi_tapes[dev].write_prot)
+ return (-EACCES);
+ cmd[0] = ERASE;
+ cmd[1] = 1; /* To the end of tape */
+#ifdef DEBUG
+ printk("st%d: Erasing tape.\n", dev);
+#endif
+ break;
+ case MTSETBLK: /* Set block length */
+ case MTSETDENSITY: /* Set tape density */
+ if (scsi_tapes[dev].dirty || scsi_tapes[dev].buffer->buffer_bytes != 0)
+ return (-EIO); /* Not allowed if data in buffer */
+ if (cmd_in == MTSETBLK &&
+ (arg < scsi_tapes[dev].min_block || arg > scsi_tapes[dev].max_block ||
+ arg > ST_BUFFER_SIZE)) {
+ printk("st%d: Illegal block size.\n", dev);
+ return (-EINVAL);
+ }
+ cmd[0] = MODE_SELECT;
+ cmd[4] = 12;
+
+ memset(scsi_tapes[dev].buffer->b_data, 0, 12);
+ scsi_tapes[dev].buffer->b_data[2] = 0x10; /* buffered mode */
+ scsi_tapes[dev].buffer->b_data[3] = 8; /* block descriptor length */
+ if (cmd_in == MTSETBLK)
+ ltmp = arg;
+ else {
+ scsi_tapes[dev].buffer->b_data[4] = arg;
+ ltmp = scsi_tapes[dev].block_size;
+ }
+ scsi_tapes[dev].buffer->b_data[9] = (ltmp >> 16);
+ scsi_tapes[dev].buffer->b_data[10] = (ltmp >> 8);
+ scsi_tapes[dev].buffer->b_data[11] = ltmp;
+ timeout = ST_TIMEOUT;
+#ifdef DEBUG
+ if (cmd_in == MTSETBLK)
+ printk("st%d: Setting block size to %d bytes.\n", dev,
+ scsi_tapes[dev].buffer->b_data[9] * 65536 +
+ scsi_tapes[dev].buffer->b_data[10] * 256 +
+ scsi_tapes[dev].buffer->b_data[11]);
+ else
+ printk("st%d: Setting density code to %x.\n", dev,
+ scsi_tapes[dev].buffer->b_data[4]);
+#endif
+ break;
+ default:
+ printk("st%d: Unknown st_ioctl command %x.\n", dev, cmd_in);
+ SCpnt->request.dev = -1; /* Mark as not busy */
+ return (-ENOSYS);
+ }
+
+ SCpnt->sense_buffer[0] = 0;
+ SCpnt->request.dev = dev;
+ scsi_do_cmd(SCpnt,
+ (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data, ST_BLOCK_SIZE,
+ st_sleep_done, timeout, MAX_RETRIES);
+
+ if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
+
+ SCpnt->request.dev = -1; /* Mark as not busy */
+
+ ioctl_result = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
+
+ if (!ioctl_result && cmd_in == MTBSFM)
+ ioctl_result = st_int_ioctl(inode, file, MTFSF, 1);
+
+ return ioctl_result ;
+}
+
+
+
+/* The ioctl command */
+static int st_ioctl(struct inode * inode,struct file * file,
+ unsigned int cmd_in, unsigned int arg)
+{
+ int dev = inode->i_rdev;
+ int i, cmd;
+ struct mtop mtc;
+ char *stp, *argp;
+
+ dev = dev & 127;
+#ifdef DEBUG
+ if (!scsi_tapes[dev].in_use) {
+ printk("st%d: Incorrect device.\n", dev);
+ return (-EIO);
+ }
+#endif
+
+ cmd = cmd_in & IOCCMD_MASK;
+ if (cmd == (MTIOCTOP & IOCCMD_MASK)) {
+
+ if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(mtc))
+ return (-EINVAL);
+ verify_area((void *)arg, sizeof(mtc));
+
+ stp = (char *) &mtc;
+ argp = (char *) arg;
+ for (i=0; i < sizeof(mtc); i++)
+ *stp++ = get_fs_byte(argp++);
+
+ return st_int_ioctl(inode, file, mtc.mt_op, mtc.mt_count);
+ }
+ else if (cmd == (MTIOCGET & IOCCMD_MASK)) {
+
+ if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(struct mtget))
+ return (-EINVAL);
+ verify_area((void *)arg, sizeof(struct mtget));
+
+ stp = (char *) scsi_tapes[dev].buffer->mt_status;
+ argp = (char *) arg;
+ for (i=0; i < sizeof(struct mtget); i++)
+ put_fs_byte(*stp++, argp++);
+ return 0;
+ }
+ else
+ return (-EINVAL);
}
-#endif
+
+
+static struct file_operations st_fops = {
+ NULL, /* lseek - default */
+ st_read, /* read - general block-dev read */
+ st_write, /* write - general block-dev write */
+ NULL, /* readdir - bad */
+ NULL, /* select */
+ st_ioctl, /* ioctl */
+ NULL, /* mmap */
+ scsi_tape_open, /* open */
+ scsi_tape_close /* release */
+};
+
+void st_attach(Scsi_Device * SDp){
+ scsi_tapes[NR_ST++].device = SDp;
+ if(NR_ST > MAX_ST) panic ("scsi_devices corrupt (st)");
+};
+
+unsigned long st_init1(unsigned long mem_start, unsigned long mem_end){
+ scsi_tapes = (Scsi_Tape *) mem_start;
+ mem_start += MAX_ST * sizeof(Scsi_Tape);
+ return mem_start;
+};
+
+/* Driver initialization */
+unsigned long st_init(unsigned long mem_start, unsigned long mem_end)
+{
+ int i;
+
+ if (NR_ST == 0) return mem_start;
+
+#ifdef DEBUG
+ printk("st: Init tape.\n");
+#endif
+ chrdev_fops[MAJOR_NR] = &st_fops;
+
+ for (i=0; i < NR_ST; ++i) {
+ scsi_tapes[i].capacity = 0xfffff;
+ scsi_tapes[i].dirty = 0;
+ scsi_tapes[i].rw = 0;
+ scsi_tapes[i].eof = 0;
+ scsi_tapes[i].waiting = NULL;
+ scsi_tapes[i].in_use = 0;
+ }
+
+
+ /* Allocate the buffers */
+ if (NR_ST == 1)
+ st_nbr_buffers = 1;
+ else
+ st_nbr_buffers = 2;
+ for (i=0; i < st_nbr_buffers; i++) {
+ st_buffers[i] = (ST_buffer *) mem_start;
+#ifdef DEBUG
+ printk("st: Buffer address: %x\n", st_buffers[i]);
+#endif
+ mem_start += sizeof(ST_buffer) - 1 + ST_BUFFER_BLOCKS * ST_BLOCK_SIZE;
+ st_buffers[i]->mt_status = (struct mtget *) mem_start;
+ mem_start += sizeof(struct mtget);
+ st_buffers[i]->in_use = 0;
+ st_buffers[i]->writing = 0;
+
+ /* "generic" status */
+ memset((void *) st_buffers[i]->mt_status, 0, sizeof(struct mtget));
+ st_buffers[i]->mt_status->mt_type = MT_ISSCSI1;
+ }
+
+ return mem_start;
+}
diff --git a/kernel/blk_drv/scsi/st.h b/kernel/blk_drv/scsi/st.h
index ca957df..08218a4 100644
--- a/kernel/blk_drv/scsi/st.h
+++ b/kernel/blk_drv/scsi/st.h
@@ -2,25 +2,42 @@
#ifndef _ST_H
#define _ST_H
/*
- $Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/st.h,v 1.1 1992/07/24 06:27:38 root Exp root $
+ $Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/st.h,v 1.1 1992/04/24 18:01:50 root Exp root $
*/
#ifndef _SCSI_H
#include "scsi.h"
#endif
-#define MAX_ST 1
+typedef struct {
+ int in_use;
+ struct mtget * mt_status;
+ int buffer_size;
+ int buffer_blocks;
+ int buffer_bytes;
+ int read_pointer;
+ int writing;
+ int last_result;
+ unsigned char b_data[1];
+} ST_buffer;
-typedef struct
- {
- /*
- Undecided goodies go here!!!
- */
- Scsi_Device* device;
- } Scsi_Tape;
+typedef struct {
+ unsigned capacity;
+ struct wait_queue * waiting;
+ Scsi_Device* device;
+ unsigned dirty:1;
+ unsigned rw:2;
+ unsigned eof:1;
+ unsigned write_prot:1;
+ unsigned in_use:1;
+ unsigned eof_hit:2;
+ ST_buffer * buffer;
+ int block_size;
+ int min_block;
+ int max_block;
+ Scsi_Cmnd SCpnt;
+} Scsi_Tape;
-extern int NR_ST;
-extern Scsi_Tape scsi_tapes[MAX_ST];
-unsigned long st_init(unsigned long, unsigned long);
#endif
+
diff --git a/kernel/blk_drv/scsi/st_ioctl.c b/kernel/blk_drv/scsi/st_ioctl.c
deleted file mode 100644
index 4780989..0000000
--- a/kernel/blk_drv/scsi/st_ioctl.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <linux/config.h>
-#ifdef CONFIG_BLK_DEV_ST
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include "st.h"
-
-extern int scsi_ioctl(Scsi_Device *dev, int cmd, void *arg);
-
-int st_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsigned long arg)
-{
- int dev = inode->i_rdev;
-
- switch (cmd) {
- default:
- return scsi_ioctl(scsi_tapes[MINOR(dev)].device, cmd, (void *) arg);
- }
-}
-#endif
diff --git a/kernel/blk_drv/scsi/ultrastor.c b/kernel/blk_drv/scsi/ultrastor.c
index 6b6b172..b6541e0 100644
--- a/kernel/blk_drv/scsi/ultrastor.c
+++ b/kernel/blk_drv/scsi/ultrastor.c
@@ -33,10 +33,6 @@
* option.
*/
-#include <linux/config.h>
-
-#ifdef CONFIG_SCSI_ULTRASTOR
-
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/sched.h>
@@ -44,13 +40,15 @@
#include <asm/io.h>
#include <asm/system.h>
+#include <asm/dma.h>
#define ULTRASTOR_PRIVATE /* Get the private stuff from ultrastor.h */
-#include "ultrastor.h"
+#include "../blk.h"
#include "scsi.h"
#include "hosts.h"
+#include "ultrastor.h"
-#define VERSION "1.0 beta"
+#define VERSION "1.1 alpha"
#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])
#define BIT(n) (1ul << (n))
@@ -148,15 +146,18 @@ static int host_number;
static volatile int aborted = 0;
+/* A probe of address 0x310 screws up NE2000 cards */
+
#ifndef PORT_OVERRIDE
static const unsigned short ultrastor_ports[] = {
- 0x330, 0x340, 0x310, 0x230, 0x240, 0x210, 0x130, 0x140,
+ 0x330, 0x340, /* 0x310,*/ 0x230, 0x240, 0x210, 0x130, 0x140,
};
#endif
static void ultrastor_interrupt(int cpl);
-static void (*ultrastor_done)(int, int) = 0;
+static void (*ultrastor_done)(Scsi_Cmnd *) = 0;
+static Scsi_Cmnd *SCint = NULL;
static const struct {
const char *signature;
@@ -290,37 +291,36 @@ int ultrastor_14f_detect(int hostnum)
#endif
host_number = hostnum;
scsi_hosts[hostnum].this_id = config.ha_scsi_id;
+
#ifndef NO_QUEUEING
- {
- struct sigaction sa;
-
- sa.sa_handler = ultrastor_interrupt;
- sa.sa_mask = 0;
- sa.sa_flags = SA_INTERRUPT; /* ??? Do we really need this? */
- sa.sa_restorer = 0;
- if (irqaction(config.interrupt, &sa)) {
- printk("Unable to get IRQ%u for UltraStor controller\n",
- config.interrupt);
- return FALSE;
- }
+ if (request_irq(config.interrupt, ultrastor_interrupt)) {
+ printk("Unable to allocate IRQ%u for UltraStor controller.\n",
+ config.interrupt);
+ return FALSE;
}
#endif
+ if (request_dma(config.dma_channel)) {
+ printk("Unable to allocate DMA channel %u for UltraStor controller.\n",
+ config.dma_channel);
+#ifndef NO_QUEUEING
+ free_irq(config.interrupt);
+#endif
+ return FALSE;
+ }
+
return TRUE;
}
const char *ultrastor_14f_info(void)
{
- return "UltraStor 14F SCSI driver version "
- VERSION
- " by David B. Gentzel\n";
+ return "UltraStor 14F SCSI driver version " VERSION;
}
static struct mscp mscp = {
OP_SCSI, DTD_SCSI, 0, 1, 0 /* This stuff doesn't change */
};
-int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
- void *buff, int bufflen, void (*done)(int, int))
+int ultrastor_14f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
{
unsigned char in_byte;
@@ -330,12 +330,13 @@ int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
/* Skip first (constant) byte */
memset((char *)&mscp + 1, 0, sizeof (struct mscp) - 1);
- mscp.target_id = target;
- /* mscp.lun = ???; */
- mscp.transfer_data = *(Longword *)&buff;
- mscp.transfer_data_length = *(Longword *)&bufflen,
- mscp.length_of_scsi_cdbs = ((*(unsigned char *)cmnd <= 0x1F) ? 6 : 10);
- memcpy(mscp.scsi_cdbs, cmnd, mscp.length_of_scsi_cdbs);
+ mscp.target_id = SCpnt->target;
+ mscp.lun = SCpnt->lun;
+ mscp.transfer_data = *(Longword *)&SCpnt->request_buffer;
+ mscp.transfer_data_length = *(Longword *)&SCpnt->request_bufflen;
+ mscp.length_of_scsi_cdbs
+ = ((*(unsigned char *)SCpnt->cmnd <= 0x1F) ? 6 : 10);
+ memcpy(mscp.scsi_cdbs, SCpnt->cmnd, mscp.length_of_scsi_cdbs);
/* Find free OGM slot (OGMINT bit is 0) */
do
@@ -359,6 +360,7 @@ int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
outb_p(0x1, LCL_DOORBELL_INTR(PORT_ADDRESS));
ultrastor_done = done;
+ SCint = SCpnt;
#if (ULTRASTOR_DEBUG & UD_COMMAND)
printk("US14F: queuecommand: returning\n");
@@ -368,8 +370,7 @@ int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
}
#ifdef NO_QUEUEING
-int ultrastor_14f_command(unsigned char target, const void *cmnd,
- void *buff, int bufflen)
+int ultrastor_14f_command(Scsi_Cmnd SCpnt)
{
unsigned char in_byte;
@@ -377,7 +378,7 @@ int ultrastor_14f_command(unsigned char target, const void *cmnd,
printk("US14F: command: called\n");
#endif
- (void)ultrastor_14f_queuecommand(target, cmnd, buff, bufflen, 0);
+ (void)ultrastor_14f_queuecommand(SCpnt, NULL);
/* Wait for ICM interrupt */
do
@@ -404,7 +405,7 @@ int ultrastor_14f_command(unsigned char target, const void *cmnd,
}
#endif
-int ultrastor_14f_abort(int code)
+int ultrastor_14f_abort(Scsi_Cmnd *SCpnt, int code)
{
#if (ULTRASTOR_DEBUG & UD_ABORT)
printk("US14F: abort: called\n");
@@ -454,7 +455,7 @@ static void ultrastor_interrupt(int cpl)
if (ultrastor_done == 0)
panic("US14F: interrupt: unexpected interrupt!\n");
else {
- void (*done)(int, int);
+ void (*done)(Scsi_Cmnd *);
/* Save ultrastor_done locally and zero before calling. This is needed
as once we call done, we may get another command queued before this
@@ -467,7 +468,8 @@ static void ultrastor_interrupt(int cpl)
/* Let the higher levels know that we're done */
/* ??? status is wrong here... */
- done(host_number, (mscp.adapter_status << 16) | mscp.target_status);
+ SCint->result = (mscp.adapter_status << 16) | mscp.target_status;
+ done(SCint);
}
#if (ULTRASTOR_DEBUG & UD_INTERRUPT)
@@ -475,5 +477,3 @@ static void ultrastor_interrupt(int cpl)
#endif
}
#endif
-
-#endif
diff --git a/kernel/blk_drv/scsi/ultrastor.h b/kernel/blk_drv/scsi/ultrastor.h
index cf8c1ac..99b9cde 100644
--- a/kernel/blk_drv/scsi/ultrastor.h
+++ b/kernel/blk_drv/scsi/ultrastor.h
@@ -23,27 +23,26 @@
int ultrastor_14f_detect(int);
const char *ultrastor_14f_info(void);
-int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
- void *buff, int bufflen,
- void (*done)(int, int));
+int ultrastor_14f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
#ifdef NO_QUEUEING
-int ultrastor_14f_command(unsigned char target, const void *cmnd,
- void *buff, int bufflen);
+int ultrastor_14f_command(Scsi_Cmnd *);
#endif
-int ultrastor_14f_abort(int);
+int ultrastor_14f_abort(Scsi_Cmnd *, int);
int ultrastor_14f_reset(void);
#ifndef NO_QUEUEING
#define ULTRASTOR_14F \
{ "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, 0, \
ultrastor_14f_queuecommand, ultrastor_14f_abort, ultrastor_14f_reset, \
- 1, 0, 0 }
+ NULL, NULL, 1, 0, SG_NONE, 1, 0, 1}
/* ??? What should can_queue be set to? Currently 1... */
+/* Set it to the number of outstanding requests that the host adapter can keep
+ track of at one time. ERY */
#else
#define ULTRASTOR_14F \
{ "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, \
ultrastor_14f_command, 0, ultrastor_14f_abort, ultrastor_14f_reset, \
- 0, 0, 0, 1 }
+ NULL, NULL, 0, 0, SG_NONE, 1, 0, 1}
#endif
#define UD_ABORT 0x0001
diff --git a/kernel/blk_drv/scsi/wd7000.c b/kernel/blk_drv/scsi/wd7000.c
new file mode 100644
index 0000000..21beb60
--- /dev/null
+++ b/kernel/blk_drv/scsi/wd7000.c
@@ -0,0 +1,619 @@
+/* $Id: $
+ * linux/kernel/wd7000.c
+ *
+ * Copyright (C) 1992 Thomas Wuensche
+ * closely related to the aha1542 driver from Tommy Thorn
+ * ( as close as different hardware allows on a lowlevel-driver :-) )
+ *
+ * Revised (and renamed) by John Boyd <boyd@cis.ohio-state.edu> to
+ * accomodate Eric Youngdale's modifications to scsi.c. Nov 1992.
+ */
+
+#include <stdarg.h>
+#include <linux/kernel.h>
+#include <linux/head.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include "../blk.h"
+#include "scsi.h"
+#include "hosts.h"
+
+/* #define DEBUG */
+
+#include "wd7000.h"
+
+
+#ifdef DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+
+/*
+ Driver data structures:
+ - mb and scbs are required for interfacing with the host adapter.
+ An SCB has extra fields not visible to the adapter; mb's
+ _cannot_ do this, since the adapter assumes they are contiguous in
+ memory, 4 bytes each, with ICMBs following OGMBs, and uses this fact
+ to access them.
+ - An icb is for host-only (non-SCSI) commands. ICBs are 16 bytes each;
+ the additional bytes are used only by the driver.
+ - For now, a pool of SCBs are kept in global storage by this driver,
+ and are allocated and freed as needed.
+
+ For two reasons, I decided not to use a single SCB per OGMB:
+ - the 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command,
+ not when it has finished. Since the SCB must be around for completion,
+ problems arise when SCBs correspond to OGMBs, which may be reallocated
+ earlier (or delayed unnecessarily until a command completes).
+ - Scatter/gather can be implemented by this driver using an SCB per
+ scatter/gather buffer, but this is difficult when SCBs and Scsi_Cmnds
+ are matched 1-1 via this correspondence.
+
+ Instead, mailboxes are used as transient data structures, simply for
+ carrying SCB addresses to/from the 7000-FASST2. SCBs are allocated as
+ "host_scribble" in an Scsi_Cmnd, and are maintained relative to that
+ Scsi_Cmnd.
+
+ Note also since SCBs are not "permanently" associated with mailboxes,
+ there is no need to keep a global list of Scsi_Cmnd pointers indexed
+ by OGMB. Again, SCBs reference their Scsi_Cmnds directly, so mailbox
+ indices need not be involved.
+*/
+
+static struct {
+ struct wd_mailbox ogmb[OGMB_CNT];
+ struct wd_mailbox icmb[ICMB_CNT];
+} mb;
+static int next_ogmb = 0; /* to reduce contention at mailboxes */
+
+static Scb scbs[MAX_SCBS];
+static Scb *scbfree = NULL;
+
+static int wd7000_host = 0;
+static unchar controlstat = 0;
+
+#define wd7000_intr_ack() outb(0,INTR_ACK)
+
+static long WAITnexttimeout = 3000000;
+
+
+static inline void wd7000_enable_intr()
+{
+ controlstat |= INT_EN;
+ outb(controlstat,CONTROL);
+}
+
+
+static inline void wd7000_enable_dma()
+{
+ controlstat |= DMA_EN;
+ outb(controlstat,CONTROL);
+ set_dma_mode(DMA_CH, DMA_MODE_CASCADE);
+ enable_dma(DMA_CH);
+}
+
+
+#define WAIT(port, mask, allof, noneof) \
+ { register WAITbits; \
+ register WAITtimeout = WAITnexttimeout; \
+ while (1) { \
+ WAITbits = inb(port) & (mask); \
+ if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
+ break; \
+ if (--WAITtimeout == 0) goto fail; \
+ } \
+ }
+
+
+static inline void delay( unsigned how_long )
+{
+ unsigned long time = jiffies + how_long;
+
+ while (jiffies < time);
+}
+
+
+static inline int command_out(unchar *cmdp, int len)
+{
+ while (len--) {
+ WAIT(ASC_STAT, STATMASK, CMD_RDY, 0);
+ outb(*cmdp++, COMMAND);
+ }
+ return 1;
+
+fail:
+ printk("wd7000_out WAIT failed(%d): ", len+1);
+ return 0;
+}
+
+static inline Scb *alloc_scb(void)
+{
+ Scb *scb;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ if (scbfree == NULL) {
+ panic("wd7000: can't allocate free SCB.\n");
+ restore_flags(flags);
+ return NULL;
+ }
+ scb = scbfree; scbfree = scb->next;
+ memset(scb, 0, sizeof(Scb)); scb->next = NULL;
+
+ restore_flags(flags);
+
+ return scb;
+}
+
+
+static inline void free_scb( Scb *scb )
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ memset(scb, 0, sizeof(Scb));
+ scb->next = scbfree; scbfree = scb;
+
+ restore_flags(flags);
+}
+
+
+static inline void init_scbs(void)
+{
+ int i;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ scbfree = &(scbs[0]);
+ for (i = 0; i < MAX_SCBS-1; i++) scbs[i].next = &(scbs[i+1]);
+ scbs[MAX_SCBS-1].next = NULL;
+
+ restore_flags(flags);
+}
+
+
+static int mail_out( Scb *scbptr )
+/*
+ * Note: this can also be used for ICBs; just cast to the parm type.
+ */
+{
+ int i, ogmb;
+ unsigned long flags;
+
+ DEB(printk("wd7000_scb_out: %06x");)
+
+ /* We first look for a free outgoing mailbox */
+ save_flags(flags);
+ cli();
+ ogmb = next_ogmb;
+ for (i = 0; i < OGMB_CNT; i++) {
+ if (mb.ogmb[ogmb].status == 0) {
+ DEB(printk(" using OGMB %x",ogmb));
+ mb.ogmb[ogmb].status = 1;
+ any2scsi(mb.ogmb[ogmb].scbptr, scbptr);
+
+ next_ogmb = (ogmb+1) % OGMB_CNT;
+ break;
+ } else
+ ogmb = (++ogmb) % OGMB_CNT;
+ }
+ restore_flags(flags);
+
+ if (i >= OGMB_CNT) {
+ DEB(printk(", no free OGMBs.\n");)
+ /* Alternatively, issue "interrupt on free OGMB", and sleep... */
+ return 0;
+ }
+
+ wd7000_enable_intr();
+ do {
+ WAIT(ASC_STAT,STATMASK,CMD_RDY,0);
+ outb(START_OGMB|ogmb, COMMAND);
+ WAIT(ASC_STAT,STATMASK,CMD_RDY,0);
+ } while (inb(ASC_STAT) & CMD_REJ);
+
+ DEB(printk(", awaiting interrupt.\n");)
+ return 1;
+
+fail:
+ DEB(printk(", WAIT timed out.\n");)
+ return 0;
+}
+
+
+int make_code(unsigned hosterr, unsigned scsierr)
+{
+#ifdef DEBUG
+ int in_error = hosterr;
+#endif
+
+ switch ((hosterr>>8)&0xff){
+ case 0: /* Reserved */
+ hosterr = DID_ERROR;
+ break;
+ case 1: /* Command Complete, no errors */
+ hosterr = DID_OK;
+ break;
+ case 2: /* Command complete, error logged in scb status (scsierr) */
+ hosterr = DID_OK;
+ break;
+ case 4: /* Command failed to complete - timeout */
+ hosterr = DID_TIME_OUT;
+ break;
+ case 5: /* Command terminated; Bus reset by external device */
+ hosterr = DID_RESET;
+ break;
+ case 6: /* Unexpected Command Received w/ host as target */
+ hosterr = DID_BAD_TARGET;
+ break;
+ case 80: /* Unexpected Reselection */
+ case 81: /* Unexpected Selection */
+ hosterr = DID_BAD_INTR;
+ break;
+ case 82: /* Abort Command Message */
+ hosterr = DID_ABORT;
+ break;
+ case 83: /* SCSI Bus Software Reset */
+ case 84: /* SCSI Bus Hardware Reset */
+ hosterr = DID_RESET;
+ break;
+ default: /* Reserved */
+ hosterr = DID_ERROR;
+ break;
+ }
+#ifdef DEBUG
+ if (scsierr||hosterr)
+ printk("\nSCSI command error: SCSI %02x host %04x return %d",
+ scsierr,in_error,hosterr);
+#endif
+ return scsierr | (hosterr << 16);
+}
+
+
+static void wd7000_scsi_done(Scsi_Cmnd * SCpnt)
+{
+ DEB(printk("wd7000_scsi_done: %06x\n",SCpnt);)
+ SCpnt->SCp.phase = 0;
+}
+
+
+void wd7000_intr_handle(int irq)
+{
+ int flag, icmb, errstatus, icmb_status;
+ int host_error, scsi_error;
+ Scb *scb, *scbn; /* for SCSI commands */
+ unchar *icb; /* for host commands */
+ Scsi_Cmnd *SCpnt;
+
+ flag = inb(INTR_STAT);
+ DEB(printk("wd7000_intr_handle: intr stat = %02x",flag);)
+
+ if (!(inb(ASC_STAT)&0x80)){
+ DEB(printk("\nwd7000_intr_handle: phantom interrupt...\n");)
+ wd7000_intr_ack();
+ return;
+ }
+
+ /* check for an incoming mailbox */
+ if ((flag & 0x40) == 0) {
+ /* for a free OGMB - need code for this case... */
+ DEB(printk("wd7000_intr_handle: free outgoing mailbox\n");)
+ wd7000_intr_ack();
+ return;
+ }
+ /* The interrupt is for an incoming mailbox */
+ icmb = flag & 0x3f;
+ scb = (struct scb *) scsi2int(mb.icmb[icmb].scbptr);
+ icmb_status = mb.icmb[icmb].status;
+ mb.icmb[icmb].status = 0;
+
+#ifdef DEBUG
+ printk(" ICMB %d posted for SCB/ICB %06x, status %02x",
+ icmb, scb, icmb_status );
+#endif
+
+ if (scb->op == 0) { /* an SCB is done */
+ SCpnt = scb->SCpnt;
+ if (--(SCpnt->SCp.phase) <= 0) { /* all scbs for SCpnt are done */
+ host_error = scb->vue | (icmb_status << 8);
+ scsi_error = scb->status;
+ errstatus = make_code(host_error,scsi_error);
+ SCpnt->result = errstatus;
+
+ scb = (Scb *) SCpnt->host_scribble; scbn = scb;
+ while (scb != NULL) {
+ scbn = scb->next;
+ free_scb(scb);
+ scb = scbn;
+ }
+
+ SCpnt->scsi_done(SCpnt);
+ }
+ } else { /* an ICB is done */
+ icb = (unchar *) scb;
+ icb[ICB_STATUS] = icmb_status;
+ icb[ICB_PHASE] = 0;
+ }
+
+ wd7000_intr_ack();
+ DEB(printk(".\n");)
+ return;
+}
+
+
+int wd7000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
+{
+ Scb *scb;
+ unchar *cdb;
+ unchar idlun;
+ short cdblen;
+
+ cdb = (unchar *) SCpnt->cmnd;
+ cdblen = (*cdb <= 0x1f ? 6 : 10);
+ idlun = ((SCpnt->target << 5) & 0xe0) | (SCpnt->lun & 7);
+ SCpnt->scsi_done = done;
+
+ if (SCpnt->use_sg) { /* set up linked SCBs to do scatter/gather */
+#ifdef 0
+ struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
+ short i;
+ Scb *scbn;
+
+ /*
+ Allocate the scbs first, and set the next pointers, since we
+ need these later.
+ Save the list via host_scribble.
+ */
+ scbn = NULL;
+ for (i = 0; i < SCpnt->use_sg; i++) {
+ scb = alloc_scb(); scb->next = scbn; scbn = scb;
+ }
+ SCpnt->host_scribble = (unchar *) scb;
+ /*
+ Note that the following is set up do to scatter/gather via
+ linked commands, with an interrupt only after _all_ are
+ finished. This is mostly to simplify error handling, which
+ hasn't been added to the interrupt handler for the other case
+ (interrupt per SCB). However, this should work with intr/SCB
+ by setting phase = use_sg and setting the flag bit in each
+ of the CDBs.
+ */
+ SCpnt->SCp.phase = 1; /* set this to the # of interrupts expected */
+
+ for (i = 0; i < SCpnt->use_sg; i++) {
+ scb->op = 0;
+ scb->idlun = idlun;
+ memcpy(scb->cdb, cdb, cdblen);
+ /*
+ Here, set CDB fields for block address & block count.
+ I don't know block size; that's why this whole thing is
+ commented out. Would be nice if scatterlist had both
+ byte and block counts per element (block address could be
+ computed).
+ Also need to know for sure if any SCSI commands other than
+ READ/WRITE can use scatter/gather - I would hope not.
+ */
+ any2scsi(scb->dataptr, sg[i].address);
+ any2scsi(scb->maxlen, sg[i].length);
+ if (i < SCpnt->use_sg-1) { /* if this isn't the last */
+ any2scsi(scb->linkptr, scb->next); /* set link */
+ scb->cdb[cdblen-1] |= 0x01; /* set link bit */
+ }
+ scb->direc = 0x40; /* Disable direction check */
+ scb->SCpnt = SCpnt; /* so we can find stuff later */
+ }
+#else
+ panic("wd7000_queuecommand: scatter/gather not implemented.\n");
+#endif
+ } else { /* just one command - use scb[0] */
+ SCpnt->SCp.phase = 1;
+ scb = alloc_scb();
+ SCpnt->host_scribble = (unchar *) scb;
+ scb->op = 0;
+ scb->idlun = idlun;
+ memcpy(scb->cdb, cdb, cdblen);
+ any2scsi(scb->dataptr, SCpnt->request_buffer);
+ any2scsi(scb->maxlen, SCpnt->request_bufflen);
+ scb->direc = 0x40; /* Disable direction check */
+ scb->SCpnt = SCpnt; /* so we can find stuff later */
+ }
+
+ return mail_out(scb);
+}
+
+
+int wd7000_command(Scsi_Cmnd *SCpnt)
+{
+ wd7000_queuecommand(SCpnt, wd7000_scsi_done);
+
+ while (SCpnt->SCp.phase > 0); /* phase counts scbs down to 0 */
+
+ return SCpnt->result;
+}
+
+
+int wd7000_init(void)
+{ int i;
+ unchar init_block[] = {
+ INITIALIZATION, 7, BUS_ON, BUS_OFF, 0, 0, 0, 0, OGMB_CNT, ICMB_CNT
+ };
+
+ /* Reset the adapter. */
+ outb(SCSI_RES|ASC_RES, CONTROL);
+ delay(1); /* reset pulse: this is 10ms, only need 25us */
+ outb(0,CONTROL); controlstat = 0;
+ /*
+ Wait 2 seconds, then expect Command Port Ready.
+
+ I suspect something else needs to be done here, but I don't know
+ what. The OEM doc says power-up diagnostics take 2 seconds, and
+ indeed, SCSI commands submitted before then will time out, but
+ none of what follows seems deterred by _not_ waiting 2 secs.
+ */
+ delay(200);
+
+ WAIT(ASC_STAT, STATMASK, CMD_RDY, 0);
+ DEB(printk("wd7000_init: Power-on Diagnostics finished\n");)
+ if ((i=inb(INTR_STAT)) != 1) {
+ panic("wd7000_init: Power-on Diagnostics error\n");
+ return 0;
+ }
+
+ /* Clear mailboxes */
+ memset(&mb,0,sizeof (mb));
+ /* Set up SCB free list */
+ init_scbs();
+
+ /* Set up init block */
+ any2scsi(init_block+5,&mb);
+ /* Execute init command */
+ if (!command_out(init_block,sizeof(init_block))) {
+ panic("WD-7000 Initialization failed.\n");
+ return 0;
+ }
+
+ /* Wait until init finished */
+ WAIT(ASC_STAT, STATMASK, CMD_RDY | ASC_INI, 0);
+ outb(DISABLE_UNS_INTR, COMMAND);
+ WAIT(ASC_STAT, STATMASK, CMD_RDY | ASC_INI, 0);
+
+ /* Enable Interrupt and DMA */
+ if (request_irq(IRQ_LVL, wd7000_intr_handle)) {
+ panic("Unable to allocate IRQ for WD-7000.\n");
+ return 0;
+ };
+ if(request_dma(DMA_CH)) {
+ panic("Unable to allocate DMA channel for WD-7000.\n");
+ free_irq(IRQ_LVL);
+ return 0;
+ };
+ wd7000_enable_dma();
+ wd7000_enable_intr();
+
+ printk("WD-7000 initialized.\n");
+ return 1;
+ fail:
+ return 0; /* 0 = not ok */
+}
+
+
+static const char *wd_bases[] = {(char *)0xce000};
+typedef struct {
+ char * signature;
+ unsigned offset;
+ unsigned length;
+} Signature;
+
+static const Signature signatures[] = {{"SSTBIOS",0xd,0x7}};
+
+#define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature))
+
+
+int wd7000_detect(int hostnum) /* hostnum ignored for now */
+/*
+ * return non-zero on detection
+ */
+{
+ int i,j;
+ char const * base_address = 0;
+ /* Store our host number */
+ wd7000_host = hostnum;
+
+ for(i=0;i<(sizeof(wd_bases)/sizeof(char *));i++){
+ for(j=0;j<NUM_SIGNATURES;j++){
+ if(!memcmp((void *)(wd_bases[i] + signatures[j].offset),
+ (void *) signatures[j].signature,signatures[j].length)){
+ base_address=wd_bases[i];
+ printk("WD-7000 detected.\n");
+ }
+ }
+ }
+ if (!base_address) return 0;
+ wd7000_init();
+
+ return 1;
+}
+
+
+
+static void wd7000_append_info( char *info, const char *fmt, ... )
+/*
+ * This is just so I can use vsprintf...
+ */
+{
+ va_list args;
+ extern int vsprintf(char *buf, const char *fmt, va_list args);
+
+ va_start(args, fmt);
+ vsprintf(info, fmt, args);
+ va_end(args);
+
+ return;
+}
+
+
+const char *wd7000_info(void)
+{
+ static char info[80] = "Western Digital WD-7000, Firmware Revision ";
+ volatile unchar icb[ICB_LEN] = {0x8c}; /* read firmware revision level */
+ unchar rl1, rl2;
+
+ icb[ICB_PHASE] = 1;
+ mail_out( (struct scb *) icb );
+ while (icb[ICB_PHASE]) /* wait for completion */;
+ rl1 = icb[1];
+ rl2 = icb[2];
+
+ /* now format the above, and append to info */
+ wd7000_append_info( info+strlen(info), "%d.%d.\n", rl1, rl2 );
+
+ return info;
+}
+
+
+int wd7000_abort(Scsi_Cmnd * SCpnt, int i)
+{
+#ifdef DEBUG
+ printk("wd7000_abort: Scsi_Cmnd = 0x%08x, code = %d ", SCpnt, i);
+ printk("id %d lun %d cdb", SCpnt->target, SCpnt->lun);
+ { int j; unchar *cdbj = (unchar *) SCpnt->cmnd;
+ for (j=0; j < (*cdbj <= 0x1f?6:10); j++) printk(" %02x", *(cdbj++));
+ printk(" result %08x\n", SCpnt->result);
+ }
+#endif
+ return 0;
+}
+
+
+int wd7000_reset(void)
+{
+ printk("wd7000_reset\n");
+ return 0;
+}
+
+
+int wd7000_biosparam(int size, int dev, int* info)
+/*
+ * This is borrowed directly from aha1542.c, but my disks are organized
+ * this way, so I think it will work OK.
+ */
+{
+ info[0] = 32;
+ info[1] = 64;
+ info[2] = (size + 2047) >> 11;
+ if (info[2] >= 1024) info[2] = 1024;
+ return 0;
+}
+
diff --git a/kernel/blk_drv/scsi/wd7000.h b/kernel/blk_drv/scsi/wd7000.h
new file mode 100644
index 0000000..a32498e
--- /dev/null
+++ b/kernel/blk_drv/scsi/wd7000.h
@@ -0,0 +1,187 @@
+#ifndef _WD7000_H
+
+/* $Id: $
+ *
+ * Header file for the WD-7000 driver for Linux
+ *
+ * $Log: $
+ * Revision 1.1 1992/07/24 06:27:38 root
+ * Initial revision
+ *
+ * Revision 1.1 1992/07/05 08:32:32 root
+ * Initial revision
+ *
+ * Revision 1.1 1992/05/15 18:38:05 root
+ * Initial revision
+ *
+ * Revision 1.1 1992/04/02 03:23:13 drew
+ * Initial revision
+ *
+ * Revision 1.3 1992/01/27 14:46:29 tthorn
+ * *** empty log message ***
+ *
+ */
+
+#include <linux/types.h>
+
+#undef STATMASK
+#undef CONTROL
+
+#define IO_BASE 0x350
+#define IRQ_LVL 15
+#define DMA_CH 6
+#define OGMB_CNT 8
+#define ICMB_CNT 16
+
+/* I/O Port interface 4.2 */
+/* READ */
+#define ASC_STAT IO_BASE
+#define INT_IM 0x80 /* Interrupt Image Flag */
+#define CMD_RDY 0x40 /* Command Port Ready */
+#define CMD_REJ 0x20 /* Command Port Byte Rejected */
+#define ASC_INI 0x10 /* ASC Initialized Flag */
+#define STATMASK 0xf0 /* The lower 4 Bytes are reserved */
+
+/* This register serves two purposes
+ * Diagnostics error code
+ * Interrupt Status
+ */
+#define INTR_STAT ASC_STAT+1
+#define ANYINTR 0x80 /* Mailbox Service possible/required */
+#define IMB 0x40 /* 1 Incoming / 0 Outgoing */
+#define MBMASK 0x3f
+/* if MSb is zero, the lower bits are diagnostic status *
+ * Diagnostics:
+ * 01 No diagnostic error occurred
+ * 02 RAM failure
+ * 03 FIFO R/W failed
+ * 04 SBIC register read/write failed
+ * 05 Initialization D-FF failed
+ * 06 Host IRQ D-FF failed
+ * 07 ROM checksum error
+ * Interrupt status (bitwise):
+ * 10NNNNNN outgoing mailbox NNNNNN is free
+ * 11NNNNNN incoming mailbox NNNNNN needs service
+ */
+
+/* WRITE */
+#define COMMAND ASC_STAT
+/*
+ * COMMAND opcodes
+ */
+#define NO_OP 0
+#define INITIALIZATION 1 /* initialization after reset (10 bytes) */
+#define DISABLE_UNS_INTR 2 /* disable unsolicited interrupts */
+#define ENABLE_UNS_INTR 3 /* enable unsolicited interrupts */
+#define INTR_ON_FREE_OGMB 4 /* interrupt on free OGMB */
+#define SCSI_SOFT_RESET 5 /* SCSI soft reset */
+#define SCSI_HARD_RESET 6 /* SCSI hard reset acknowledge */
+#define START_OGMB 0x80 /* start command in OGMB (n) */
+#define SCAN_OGMBS 0xc0 /* start multiple commands, signature (n) */
+ /* where (n) = lower 6 bits */
+/*
+ * For INITIALIZATION:
+ */
+#define BUS_ON 24 /* x 125ns, 24 = 3000ns, BIOS uses 8000ns */
+#define BUS_OFF 24 /* x 125ns, BIOS uses 1875ns */
+
+#define INTR_ACK ASC_STAT+1
+
+
+#define CONTROL ASC_STAT+2
+#define INT_EN 0x08 /* Interrupt Enable */
+#define DMA_EN 0x04 /* DMA Enable */
+#define SCSI_RES 0x02 /* SCSI Reset */
+#define ASC_RES 0x01 /* ASC Reset */
+
+/* Mailbox Definition */
+
+struct wd_mailbox{
+ unchar status;
+ unchar scbptr[3];
+};
+
+
+/* These belong in scsi.h also */
+#undef any2scsi
+#define any2scsi(up, p) \
+(up)[0] = (((long)(p)) >> 16); \
+(up)[1] = ((long)(p)) >> 8; \
+(up)[2] = ((long)(p));
+
+#define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) )
+
+#define xany2scsi(up, p) \
+(up)[0] = ((long)(p)) >> 24; \
+(up)[1] = ((long)(p)) >> 16; \
+(up)[2] = ((long)(p)) >> 8; \
+(up)[3] = ((long)(p));
+
+#define xscsi2int(up) ( (((long)(up)[0]) << 24) + (((long)(up)[1]) << 16) \
+ + (((long)(up)[2]) << 8) + ((long)(up)[3]) )
+
+#define MAX_CDB 12
+#define MAX_SENSE 14
+
+typedef struct scb { /* Command Control Block 5.4.1 */
+ unchar op; /* Command Control Block Operation Code */
+ unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */
+ /* Outbound data transfer, length is checked*/
+ /* Inbound data transfer, length is checked */
+ /* Logical Unit Number */
+ unchar cdb[12]; /* SCSI Command Block */
+ unchar status; /* SCSI Return Status */
+ unchar vue; /* Vendor Unique Error Code */
+ unchar maxlen[3]; /* Maximum Data Transfer Length */
+ unchar dataptr[3]; /* SCSI Data Block Pointer */
+ unchar linkptr[3]; /* Next Command Link Pointer */
+ unchar direc; /* Transfer Direction */
+ unchar reserved2[6]; /* SCSI Command Descriptor Block */
+ /* end of hardware SCB */
+ Scsi_Cmnd *SCpnt; /* Scsi_Cmnd using this SCB */
+ struct scb *next; /* for lists of scbs */
+} Scb;
+
+/*
+ * Note: MAX_SCBS _must_ be defined large enough to keep ahead of the
+ * demand for SCBs, which will be at most WD7000_Q * WD7000_SG. 1 is
+ * added to each because they can be 0.
+ */
+#define MAX_SCBS ((WD7000_Q+1) * (WD7000_SG+1))
+
+/*
+ * The driver is written to allow host-only commands to be executed. These
+ * use a 16-byte block called an ICB.
+ *
+ * (Currently, only wd7000_info uses this, to get the firmware rev. level.)
+ */
+#define ICB_STATUS 16 /* set to icmb status by wd7000_intr_handle */
+#define ICB_PHASE 17 /* set to 0 by wd7000_intr_handle */
+#define ICB_LEN 18 /* actually 16; this includes the above */
+
+int wd7000_detect(int);
+int wd7000_command(Scsi_Cmnd *);
+int wd7000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int wd7000_abort(Scsi_Cmnd *, int);
+const char *wd7000_info(void);
+int wd7000_reset(void);
+int wd7000_biosparam(int, int, int*);
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+#define WD7000_Q OGMB_CNT
+#define WD7000_SG SG_NONE
+
+#define WD7000 {\
+ "Western Digital WD-7000", \
+ wd7000_detect, \
+ wd7000_info, wd7000_command, \
+ wd7000_queuecommand, \
+ wd7000_abort, \
+ wd7000_reset, \
+ NULL, \
+ wd7000_biosparam, \
+ WD7000_Q, 7, WD7000_SG, 1, 0, 1}
+#endif
diff --git a/kernel/chr_drv/Makefile b/kernel/chr_drv/Makefile
index 0c79e8c..4c04ab4 100644
--- a/kernel/chr_drv/Makefile
+++ b/kernel/chr_drv/Makefile
@@ -44,144 +44,156 @@ atixlmouse.o : atixlmouse.c /usr/include/linux/kernel.h /usr/include/linux/sched
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
- /usr/include/linux/errno.h /usr/include/asm/io.h /usr/include/asm/segment.h \
- /usr/include/asm/irq.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \
+ /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/errno.h \
+ /usr/include/asm/io.h /usr/include/asm/segment.h /usr/include/asm/irq.h
busmouse.o : busmouse.c /usr/include/linux/kernel.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/busmouse.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
- /usr/include/asm/system.h /usr/include/linux/errno.h /usr/include/asm/io.h /usr/include/asm/segment.h \
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/busmouse.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/linux/errno.h /usr/include/asm/io.h /usr/include/asm/segment.h \
/usr/include/asm/irq.h
console.o : console.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/timer.h \
- /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
- /usr/include/linux/config.h /usr/include/linux/config.dist.h /usr/include/linux/string.h \
- /usr/include/linux/errno.h /usr/include/linux/kd.h /usr/include/asm/io.h /usr/include/asm/segment.h \
- vt_kern.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/timer.h /usr/include/linux/tty.h \
+ /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/config.h \
+ /usr/include/linux/config.dist.h /usr/include/linux/string.h /usr/include/linux/errno.h \
+ /usr/include/linux/kd.h /usr/include/linux/keyboard.h /usr/include/asm/io.h \
+ /usr/include/asm/segment.h vt_kern.h
keyboard.o : keyboard.c /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/ctype.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
- /usr/include/asm/system.h /usr/include/linux/ptrace.h /usr/include/asm/io.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/ctype.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/linux/ptrace.h /usr/include/linux/keyboard.h /usr/include/asm/io.h
lp.o : lp.c /usr/include/linux/lp.h /usr/include/linux/errno.h /usr/include/linux/kernel.h \
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/asm/io.h /usr/include/asm/segment.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/asm/io.h /usr/include/asm/segment.h
mem.o : mem.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
- /usr/include/linux/mouse.h /usr/include/linux/user.h /usr/include/linux/ptrace.h \
- /usr/include/linux/a.out.h /usr/include/linux/string.h /usr/include/asm/segment.h \
- /usr/include/asm/io.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \
+ /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/mouse.h \
+ /usr/include/linux/user.h /usr/include/linux/ptrace.h /usr/include/linux/a.out.h \
+ /usr/include/linux/string.h /usr/include/asm/segment.h /usr/include/asm/io.h
mouse.o : mouse.c /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/errno.h /usr/include/linux/mouse.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/errno.h /usr/include/linux/mouse.h
msbusmouse.o : msbusmouse.c /usr/include/linux/kernel.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/busmouse.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
- /usr/include/asm/system.h /usr/include/linux/errno.h /usr/include/asm/io.h /usr/include/asm/segment.h \
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/busmouse.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/linux/errno.h /usr/include/asm/io.h /usr/include/asm/segment.h \
/usr/include/asm/irq.h
psaux.o : psaux.c /usr/include/linux/timer.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/fcntl.h /usr/include/linux/errno.h /usr/include/asm/io.h \
- /usr/include/asm/segment.h /usr/include/asm/system.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h \
+ /usr/include/linux/errno.h /usr/include/asm/io.h /usr/include/asm/segment.h \
+ /usr/include/asm/system.h
pty.o : pty.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
- /usr/include/linux/fcntl.h /usr/include/asm/io.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \
+ /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/fcntl.h \
+ /usr/include/asm/io.h
serial.o : serial.c /usr/include/linux/errno.h /usr/include/linux/signal.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/timer.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
- /usr/include/asm/system.h /usr/include/linux/serial.h /usr/include/asm/io.h \
- /usr/include/asm/segment.h /usr/include/asm/bitops.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/timer.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/linux/serial.h /usr/include/asm/io.h /usr/include/asm/segment.h \
+ /usr/include/asm/bitops.h
tty_io.o : tty_io.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/signal.h \
/usr/include/linux/fcntl.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
- /usr/include/asm/system.h /usr/include/linux/ctype.h /usr/include/linux/kd.h \
- /usr/include/linux/string.h /usr/include/asm/segment.h /usr/include/asm/bitops.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/linux/ctype.h /usr/include/linux/kd.h /usr/include/linux/string.h \
+ /usr/include/linux/keyboard.h /usr/include/asm/segment.h /usr/include/asm/bitops.h \
vt_kern.h
tty_ioctl.o : tty_ioctl.c /usr/include/linux/types.h /usr/include/linux/termios.h \
/usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \
- /usr/include/asm/system.h /usr/include/linux/fcntl.h /usr/include/asm/io.h /usr/include/asm/segment.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/tty.h /usr/include/asm/system.h \
+ /usr/include/linux/fcntl.h /usr/include/asm/io.h /usr/include/asm/segment.h
vt.o : vt.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
- /usr/include/linux/timer.h /usr/include/linux/kd.h /usr/include/linux/vt.h /usr/include/asm/io.h \
- /usr/include/asm/segment.h vt_kern.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \
+ /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/timer.h \
+ /usr/include/linux/keyboard.h /usr/include/linux/kd.h /usr/include/linux/vt.h \
+ /usr/include/asm/io.h /usr/include/asm/segment.h vt_kern.h
diff --git a/kernel/chr_drv/console.c b/kernel/chr_drv/console.c
index 359b6a3..44f9c0b 100644
--- a/kernel/chr_drv/console.c
+++ b/kernel/chr_drv/console.c
@@ -35,8 +35,6 @@
* <g-hunt@ee.utah.edu>
*/
-#define KEYBOARD_IRQ 1
-
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/tty.h>
@@ -45,6 +43,7 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/kd.h>
+#include <linux/keyboard.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -55,17 +54,7 @@
#define NPAR 16
extern void vt_init(void);
-extern void keyboard_interrupt(int pt_regs);
extern void set_leds(void);
-extern unsigned char kapplic;
-extern unsigned char ckmode;
-extern unsigned char krepeat;
-extern unsigned char default_kleds;
-extern unsigned char kleds;
-extern unsigned char kmode;
-extern unsigned char kraw;
-extern unsigned char ke0;
-extern unsigned char lfnlmode;
unsigned long video_num_columns; /* Number of text columns */
unsigned long video_num_lines; /* Number of test lines */
@@ -160,14 +149,11 @@ static int console_blanked = 0;
#define video_mem_start (vc_cons[currcons].vc_video_mem_start)
#define video_mem_end (vc_cons[currcons].vc_video_mem_end)
#define video_erase_char (vc_cons[currcons].vc_video_erase_char)
-#define decckm (vc_cons[currcons].vc_decckm)
#define decscnm (vc_cons[currcons].vc_decscnm)
#define decom (vc_cons[currcons].vc_decom)
#define decawm (vc_cons[currcons].vc_decawm)
-#define decarm (vc_cons[currcons].vc_decarm)
#define deccm (vc_cons[currcons].vc_deccm)
#define decim (vc_cons[currcons].vc_decim)
-#define lnm (vc_cons[currcons].vc_lnm)
#define kbdapplic (vc_cons[currcons].vc_kbdapplic)
#define need_wrap (vc_cons[currcons].vc_need_wrap)
#define color (vc_cons[currcons].vc_color)
@@ -189,14 +175,16 @@ static int console_blanked = 0;
#define halfcolor (vc_cons[currcons].vc_halfcolor)
#define kbdmode (vc_cons[currcons].vc_kbdmode)
#define tab_stop (vc_cons[currcons].vc_tab_stop)
-#define kbdraw (vt_cons[currcons].vc_kbdraw)
-#define kbdleds (vt_cons[currcons].vc_kbdleds)
#define vtmode (vt_cons[currcons].vt_mode)
-#define SET(mode,fg,v) \
- (mode) = (v); \
- if (currcons == fg_console) \
- (fg) = (v)
+#define set_kbd(x) set_vc_kbd_flag(kbd_table+currcons,x)
+#define clr_kbd(x) clr_vc_kbd_flag(kbd_table+currcons,x)
+#define is_kbd(x) vc_kbd_flag(kbd_table+currcons,x)
+
+#define decarm VC_REPEAT
+#define decckm VC_APPLIC
+#define kbdraw VC_RAW
+#define lnm VC_CRLF
int blankinterval = 10*60*HZ;
static int screen_size = 0;
@@ -671,7 +659,10 @@ static void set_mode(int currcons, int on_off)
for (i=0; i<=npar; i++)
if (ques) switch(par[i]) { /* DEC private modes set/reset */
case 1: /* Cursor keys send ^[Ox/^[[x */
- SET(decckm,ckmode,on_off);
+ if (on_off)
+ set_kbd(decckm);
+ else
+ clr_kbd(decckm);
break;
case 3: /* 80/132 mode switch unimplemented */
csi_J(currcons,2);
@@ -692,7 +683,10 @@ static void set_mode(int currcons, int on_off)
decawm = on_off;
break;
case 8: /* Autorepeat on/off */
- SET(decarm,krepeat,on_off);
+ if (on_off)
+ set_kbd(decarm);
+ else
+ clr_kbd(decarm);
break;
case 25: /* Cursor on/off */
deccm = on_off;
@@ -703,7 +697,10 @@ static void set_mode(int currcons, int on_off)
decim = on_off;
break;
case 20: /* Lf, Enter == CrLf/Lf */
- SET(lnm,lfnlmode,on_off);
+ if (on_off)
+ set_kbd(lnm);
+ else
+ clr_kbd(lnm);
break;
}
}
@@ -867,22 +864,16 @@ static void reset_terminal(int currcons, int do_clear)
deccm = 1;
decim = 0;
- if (currcons == fg_console) {
- krepeat = 1;
- ckmode = 0;
- kapplic = 0;
- lfnlmode = 0;
- kleds = default_kleds;
- kmode = 0;
- set_leds();
- } else {
- decarm = 1;
- decckm = 0;
- kbdapplic = 0;
- lnm = 0;
- kbdleds = default_kleds;
- kbdmode = 0;
- }
+ set_kbd(decarm);
+ clr_kbd(decckm);
+ clr_kbd(kbdapplic);
+ clr_kbd(lnm);
+#define is_kbd(x) vc_kbd_flag(kbd_table+currcons,x)
+ kbd_table[currcons].flags =
+ (kbd_table[currcons].flags & ~LED_MASK) |
+ (kbd_table[currcons].default_flags & LED_MASK);
+ kbdmode = 0;
+ set_leds();
default_attr(currcons);
update_attr(currcons);
@@ -953,7 +944,7 @@ void con_write(struct tty_struct * tty)
continue;
case 10: case 11: case 12:
lf(currcons);
- if (!lfnlmode)
+ if (!is_kbd(lnm))
continue;
case 13:
cr(currcons);
@@ -1021,10 +1012,10 @@ void con_write(struct tty_struct * tty)
reset_terminal(currcons,1);
continue;
case '>': /* Numeric keypad */
- SET(kbdapplic,kapplic,0);
+ kbdapplic = 0;
continue;
case '=': /* Appl. keypad */
- SET(kbdapplic,kapplic,1);
+ kbdapplic = 1;
continue;
}
continue;
@@ -1037,7 +1028,8 @@ void con_write(struct tty_struct * tty)
state=ESfunckey;
continue;
}
- if (ques=(c=='?'))
+ ques = (c=='?');
+ if (ques)
continue;
case ESgetpars:
if (c==';' && npar<NPAR-1) {
@@ -1249,7 +1241,6 @@ return s;
*/
long con_init(long kmem_start)
{
- register unsigned char a;
char *display_desc = "????";
char *display_ptr;
int currcons = 0;
@@ -1326,7 +1317,7 @@ long con_init(long kmem_start)
scr_end = video_mem_end = (base += screen_size);
vc_scrbuf[currcons] = (unsigned short *) origin;
vtmode = KD_TEXT;
- kbdraw = 0;
+ clr_kbd(kbdraw);
def_color = 0x07; /* white */
ulcolor = 0x0f; /* bold white */
halfcolor = 0x08; /* grey */
@@ -1342,34 +1333,15 @@ long con_init(long kmem_start)
save_cur(currcons);
gotoxy(currcons,orig_x,orig_y);
update_screen(fg_console);
-
- if (request_irq(KEYBOARD_IRQ,keyboard_interrupt))
- printk("Unable to get IRQ%d for keyboard driver\n",KEYBOARD_IRQ);
- a=inb_p(0x61);
- outb_p(a|0x80,0x61);
- outb_p(a,0x61);
return kmem_start;
}
+/*
+ * kbdsave doesn't need to do anything: it's all handled automatically
+ * with the new data structures..
+ */
void kbdsave(int new_console)
{
- int currcons = fg_console;
- kbdmode = kmode;
- kbdraw = kraw;
- kbdleds = kleds;
- kbdapplic = kapplic;
- decckm = ckmode;
- decarm = krepeat;
- lnm = lfnlmode;
- currcons = new_console;
- kmode = (kmode & 0x3F) | (kbdmode & 0xC0);
- kraw = kbdraw;
- kleds = kbdleds;
- kapplic = kbdapplic;
- ckmode = decckm;
- krepeat = decarm;
- lfnlmode = lnm;
- set_leds();
}
static void get_scrmem(int currcons)
@@ -1426,6 +1398,7 @@ void update_screen(int new_console)
set_scrmem(fg_console);
set_origin(fg_console);
set_cursor(new_console);
+ set_leds();
lock = 0;
}
@@ -1477,7 +1450,7 @@ void console_print(const char * b)
if (currcons<0 || currcons>=NR_CONSOLES)
currcons = 0;
- while (c = *(b++)) {
+ while ((c = *(b++)) != 0) {
if (c == 10 || c == 13 || need_wrap) {
if (c != 13)
lf(currcons);
diff --git a/kernel/chr_drv/keyboard.c b/kernel/chr_drv/keyboard.c
index a17d60a..73a71e9 100644
--- a/kernel/chr_drv/keyboard.c
+++ b/kernel/chr_drv/keyboard.c
@@ -7,11 +7,14 @@
* the assembly version by Linus (with diacriticals added)
*/
+#define KEYBOARD_IRQ 1
+
#include <linux/sched.h>
#include <linux/ctype.h>
#include <linux/tty.h>
#include <linux/mm.h>
#include <linux/ptrace.h>
+#include <linux/keyboard.h>
/*
* The default IO slowdown is doing 'inb()'s from 0x61, which should be
@@ -24,44 +27,18 @@
#include <asm/io.h>
#include <asm/system.h>
-#define LSHIFT 0x01
-#define RSHIFT 0x02
-#define LCTRL 0x04
-#define RCTRL 0x08
-#define ALT 0x10
-#define ALTGR 0x20
-#define CAPS 0x40
-#define CAPSDOWN 0x80
-
-#define SCRLED 0x01
-#define NUMLED 0x02
-#define CAPSLED 0x04
-
-#define NO_META_BIT 0x80
-
-#ifndef KBD_DEFLOCK
-#define KBD_DEFLOCK NUMLED
-#endif
-
-unsigned char kapplic = 0;
-unsigned char ckmode = 0;
-unsigned char krepeat = 1;
-unsigned char kmode = 0;
-unsigned char default_kleds = KBD_DEFLOCK;
-unsigned char kleds = KBD_DEFLOCK;
-unsigned char ke0 = 0;
-unsigned char kraw = 0;
-unsigned char kbd_flags = KBDFLAGS;
-unsigned char lfnlmode = 0;
-
extern void do_keyboard_interrupt(void);
extern void ctrl_alt_del(void);
extern void change_console(unsigned int new_console);
-extern struct tty_queue *table_list[];
+
+unsigned long kbd_flags = 0;
+
+struct kbd_struct kbd_table[NR_CONSOLES];
+static struct kbd_struct * kbd = kbd_table;
+static struct tty_struct * tty = NULL;
typedef void (*fptr)(int);
-static unsigned char old_leds = NUMLED;
static int diacr = -1;
static int npadch = 0;
fptr key_table[];
@@ -70,38 +47,34 @@ static void put_queue(int);
void set_leds(void);
static void applkey(int);
static void cur(int);
-static void kb_wait(void), kb_ack(void);
static unsigned int handle_diacr(unsigned int);
static struct pt_regs * pt_regs;
-void keyboard_interrupt(int int_pt_regs)
+static void keyboard_interrupt(int int_pt_regs)
{
- static unsigned char rep = 0xff, repke0 = 0;
+ static unsigned char rep = 0xff;
unsigned char scancode, x;
- struct tty_struct * tty = TTY_TABLE(0);
pt_regs = (struct pt_regs *) int_pt_regs;
scancode=inb_p(0x60);
x=inb_p(0x61);
outb_p(x|0x80, 0x61);
outb_p(x&0x7f, 0x61);
- outb(0x20, 0x20);
- sti();
-
- if (kraw) {
+ if (scancode == 0xe0)
+ set_kbd_flag(KG_E0);
+ else if (scancode == 0xe1)
+ set_kbd_flag(KG_E1);
+ tty = TTY_TABLE(0);
+ kbd = kbd_table + fg_console;
+ if (vc_kbd_flag(kbd,VC_RAW)) {
+ kbd_flags = 0;
put_queue(scancode);
do_keyboard_interrupt();
return;
}
- if (scancode == 0xe0) {
- ke0 = 1;
- return;
- }
- if (scancode == 0xe1) {
- ke0 = 2;
+ if (scancode == 0xe0 || scancode == 0xe1)
return;
- }
/*
* The keyboard maintains its own internal caps lock and num lock
* statuses. In caps lock mode E0 AA precedes make code and E0 2A
@@ -109,8 +82,9 @@ void keyboard_interrupt(int int_pt_regs)
* code and E0 AA follows break code. We do our own book-keeping,
* so we will just ignore these.
*/
- if (ke0 == 1 && (scancode == 0x2a || scancode == 0xaa)) {
- ke0 = 0;
+ if (kbd_flag(KG_E0) && (scancode == 0x2a || scancode == 0xaa)) {
+ clr_kbd_flag(KG_E0);
+ clr_kbd_flag(KG_E1);
return;
}
/*
@@ -118,31 +92,26 @@ void keyboard_interrupt(int int_pt_regs)
* characters get echoed locally. This makes key repeat usable
* with slow applications and unders heavy loads.
*/
- if (rep == 0xff) {
- if (scancode < 0x80) {
- rep = scancode;
- repke0 = ke0;
- }
- } else if (ke0 == repke0 && (scancode & 0x7f) == rep) {
- if (scancode & 0x80)
- rep = 0xff;
- else if (!(krepeat && tty &&
+ if (scancode == rep) {
+ if (!(vc_kbd_flag(kbd,VC_REPEAT) && tty &&
(L_ECHO(tty) ||
(EMPTY(&tty->secondary) &&
EMPTY(&tty->read_q))))) {
- ke0 = 0;
+ clr_kbd_flag(KG_E0);
+ clr_kbd_flag(KG_E1);
return;
}
}
+ rep = scancode;
key_table[scancode](scancode);
do_keyboard_interrupt();
- ke0 = 0;
+ clr_kbd_flag(KG_E0);
+ clr_kbd_flag(KG_E1);
}
static void put_queue(int ch)
{
struct tty_queue *qp;
- struct tty_struct *tty = TTY_TABLE(0);
unsigned long new_head;
wake_up_interruptible(&keypress_wait);
@@ -159,7 +128,6 @@ static void put_queue(int ch)
static void puts_queue(char *cp)
{
struct tty_queue *qp;
- struct tty_struct *tty = TTY_TABLE(0);
unsigned long new_head;
char ch;
@@ -168,7 +136,7 @@ static void puts_queue(char *cp)
return;
qp = &tty->read_q;
- while (ch=*cp++) {
+ while ((ch = *(cp++)) != 0) {
qp->buf[qp->head]=ch;
if ((new_head=(qp->head+1)&(TTY_BUF_SIZE-1))
!= qp->tail)
@@ -179,34 +147,34 @@ static void puts_queue(char *cp)
static void ctrl(int sc)
{
- if (ke0)
- kmode|=RCTRL;
+ if (kbd_flag(KG_E0))
+ set_kbd_flag(KG_RCTRL);
else
- kmode|=LCTRL;
+ set_kbd_flag(KG_LCTRL);
}
static void alt(int sc)
{
- if (ke0)
- kmode|=ALTGR;
+ if (kbd_flag(KG_E0))
+ set_kbd_flag(KG_ALTGR);
else
- kmode|=ALT;
+ set_kbd_flag(KG_ALT);
}
static void unctrl(int sc)
{
- if (ke0)
- kmode&=(~RCTRL);
+ if (kbd_flag(KG_E0))
+ clr_kbd_flag(KG_RCTRL);
else
- kmode&=(~LCTRL);
+ clr_kbd_flag(KG_LCTRL);
}
static void unalt(int sc)
{
- if (ke0)
- kmode&=(~ALTGR);
+ if (kbd_flag(KG_E0))
+ clr_kbd_flag(KG_ALTGR);
else {
- kmode&=(~ALT);
+ clr_kbd_flag(KG_ALT);
if (npadch != 0) {
put_queue(npadch);
npadch=0;
@@ -216,50 +184,36 @@ static void unalt(int sc)
static void lshift(int sc)
{
- kmode|=LSHIFT;
+ set_kbd_flag(KG_LSHIFT);
}
static void unlshift(int sc)
{
- kmode&=(~LSHIFT);
+ clr_kbd_flag(KG_LSHIFT);
}
static void rshift(int sc)
{
- kmode|=RSHIFT;
+ set_kbd_flag(KG_RSHIFT);
}
static void unrshift(int sc)
{
- kmode&=(~RSHIFT);
+ clr_kbd_flag(KG_RSHIFT);
}
static void caps(int sc)
{
- if (!(kmode & CAPSDOWN)) {
- kleds ^= CAPSLED;
- kmode ^= CAPS;
- kmode |= CAPSDOWN;
- set_leds();
- }
-}
-
-void set_leds(void)
-{
- if (kleds != old_leds) {
- old_leds = kleds;
- kb_wait();
- outb(0xed, 0x60); /* set leds command */
- kb_ack();
- kb_wait();
- outb(kleds, 0x60);
- kb_ack();
- }
+ if (kbd_flag(KG_CAPSLOCK))
+ return; /* key already pressed: defeat repeat */
+ set_kbd_flag(KG_CAPSLOCK);
+ chg_vc_kbd_flag(kbd,VC_CAPSLOCK);
+ set_leds();
}
static void uncaps(int sc)
{
- kmode &= ~CAPSDOWN;
+ clr_kbd_flag(KG_CAPSLOCK);
}
static void show_ptregs(void)
@@ -279,22 +233,24 @@ static void show_ptregs(void)
static void scroll(int sc)
{
- if (kmode & (LSHIFT | RSHIFT))
+ if (kbd_flag(KG_LSHIFT) || kbd_flag(KG_RSHIFT))
show_mem();
- else if (kmode & (ALT | ALTGR))
+ else if (kbd_flag(KG_ALT) || kbd_flag(KG_ALTGR))
show_ptregs();
- else if (kmode & (LCTRL | RCTRL))
+ else if (kbd_flag(KG_LCTRL) || kbd_flag(KG_RCTRL))
show_state();
- kleds ^= SCRLED;
- set_leds();
+ else {
+ chg_vc_kbd_flag(kbd,VC_SCROLLOCK);
+ set_leds();
+ }
}
static void num(int sc)
{
- if (kapplic)
+ if (vc_kbd_flag(kbd,VC_APPLIC))
applkey(0x50);
else {
- kleds ^= NUMLED;
+ chg_vc_kbd_flag(kbd,VC_NUMLOCK);
set_leds();
}
}
@@ -1062,9 +1018,10 @@ static void do_self(int sc)
{
unsigned char ch;
- if (kmode & ALTGR)
+ if (kbd_flag(KG_ALTGR))
ch = alt_map[sc];
- else if (kmode & (LSHIFT | RSHIFT | LCTRL | RCTRL))
+ else if (kbd_flag(KG_LSHIFT) || kbd_flag(KG_RSHIFT) ||
+ kbd_flag(KG_LCTRL) || kbd_flag(KG_RCTRL))
ch = shift_map[sc];
else
ch = key_map[sc];
@@ -1075,14 +1032,15 @@ static void do_self(int sc)
if ((ch = handle_diacr(ch)) == 0)
return;
- if (kmode & (LCTRL | RCTRL | CAPS)) /* ctrl or caps */
+ if (kbd_flag(KG_LCTRL) || kbd_flag(KG_RCTRL) ||
+ vc_kbd_flag(kbd,VC_CAPSLOCK)) /* ctrl or caps */
if ((ch >= 'a' && ch <= 'z') || (ch >= 224 && ch <= 254))
ch -= 32;
- if (kmode & (LCTRL | RCTRL)) /* ctrl */
+ if (kbd_flag(KG_LCTRL) || kbd_flag(KG_RCTRL)) /* ctrl */
ch &= 0x1f;
- if (kmode & ALT)
- if (kbd_flags & NO_META_BIT) {
+ if (kbd_flag(KG_ALT))
+ if (vc_kbd_flag(kbd,VC_META)) {
put_queue('\033');
put_queue(ch);
} else
@@ -1124,7 +1082,7 @@ unsigned int handle_diacr(unsigned int ch)
int i;
for(i=0; diacr_table[i]; i++)
- if (ch==diacr_table[i] && ((1<<i)&kbd_flags)) {
+ if (ch==diacr_table[i] && ((1<<i)&kbd->kbd_flags)) {
if (diacr == i) {
diacr=-1;
return ch; /* pressed twice */
@@ -1202,27 +1160,31 @@ static void cursor(int sc)
{
if (sc < 0x47 || sc > 0x53)
return;
- sc-=0x47;
- if (sc == 12 && (kmode&(LCTRL|RCTRL)) && (kmode&(ALT|ALTGR))) {
+ sc -= 0x47;
+ if (sc == 12 &&
+ (kbd_flag(KG_LCTRL) || kbd_flag(KG_RCTRL)) &&
+ (kbd_flag(KG_ALT) || kbd_flag(KG_ALTGR))) {
ctrl_alt_del();
return;
}
- if (ke0 == 1) {
+ if (kbd_flag(KG_E0)) {
cur(sc);
return;
}
- if ((kmode&ALT) && sc!=12) { /* Alt-numpad */
+ if (kbd_flag(KG_ALT) && sc != 12) { /* Alt-numpad */
npadch=npadch*10+pad_table[sc];
return;
}
- if (kapplic && !(kmode&(LSHIFT|RSHIFT))) { /* shift forces cursor */
+ if (vc_kbd_flag(kbd,VC_APPLIC) &&
+ !kbd_flag(KG_LSHIFT) && /* shift forces cursor */
+ !kbd_flag(KG_RSHIFT)) {
applkey(appl_table[sc]);
return;
}
- if (kleds&NUMLED) {
+ if (vc_kbd_flag(kbd,VC_NUMLOCK)) {
put_queue(num_table[sc]);
} else
cur(sc);
@@ -1236,7 +1198,9 @@ static void cur(int sc)
if (buf[2] < '9')
buf[3]='~';
else
- if ((buf[2] >= 'A' && buf[2] <= 'D') ? ckmode : kapplic)
+ if ((buf[2] >= 'A' && buf[2] <= 'D') ?
+ vc_kbd_flag(kbd,VC_CKMODE) :
+ vc_kbd_flag(kbd,VC_APPLIC))
buf[1]='O';
puts_queue(buf);
}
@@ -1251,10 +1215,10 @@ static void func(int sc)
if (sc < 10 || sc > 11)
return;
}
- if (kmode&ALT)
+ if (kbd_flag(KG_ALT))
change_console(sc);
else
- if (kmode & ( LSHIFT | RSHIFT)) /* DEC F11 - F20 */
+ if (kbd_flag(KG_LSHIFT) || kbd_flag(KG_RSHIFT)) /* DEC F11 - F20 */
puts_queue(func_table[1][sc]);
else /* DEC F1 - F10 */
puts_queue(func_table[0][sc]);
@@ -1262,9 +1226,9 @@ static void func(int sc)
static void slash(int sc)
{
- if (ke0 != 1)
+ if (!kbd_flag(KG_E0))
do_self(sc);
- else if (kapplic)
+ else if (vc_kbd_flag(kbd,VC_APPLIC))
applkey('Q');
else
put_queue('/');
@@ -1272,7 +1236,7 @@ static void slash(int sc)
static void star(int sc)
{
- if (kapplic)
+ if (vc_kbd_flag(kbd,VC_APPLIC))
applkey('R');
else
do_self(sc);
@@ -1280,18 +1244,18 @@ static void star(int sc)
static void enter(int sc)
{
- if (ke0 == 1 && kapplic)
+ if (kbd_flag(KG_E0) && vc_kbd_flag(kbd,VC_APPLIC))
applkey('M');
else {
put_queue(13);
- if (lfnlmode)
+ if (vc_kbd_flag(kbd,VC_CRLF))
put_queue(10);
}
}
static void minus(int sc)
{
- if (kapplic)
+ if (vc_kbd_flag(kbd,VC_APPLIC))
applkey('S');
else
do_self(sc);
@@ -1299,7 +1263,7 @@ static void minus(int sc)
static void plus(int sc)
{
- if (kapplic)
+ if (vc_kbd_flag(kbd,VC_APPLIC))
applkey('l');
else
do_self(sc);
@@ -1312,7 +1276,6 @@ static void none(int sc)
/*
* kb_wait waits for the keyboard controller buffer to empty.
*/
-
static void kb_wait(void)
{
int i;
@@ -1333,8 +1296,7 @@ static void kb_wait(void)
* I don't know how much waiting actually is required,
* but this seems to work
*/
-
-void kb_ack(void)
+static void kb_ack(void)
{
int i;
@@ -1343,6 +1305,22 @@ void kb_ack(void)
break;
}
+void set_leds(void)
+{
+ static unsigned char old_leds = -1;
+ unsigned char leds = kbd_table[fg_console].flags & LED_MASK;
+
+ if (leds != old_leds) {
+ old_leds = leds;
+ kb_wait();
+ outb(0xed, 0x60); /* set leds command */
+ kb_ack();
+ kb_wait();
+ outb(leds, 0x60);
+ kb_ack();
+ }
+}
+
long no_idt[2] = {0, 0};
/*
@@ -1436,3 +1414,22 @@ static fptr key_table[] = {
none,none,none,none, /* F8-FB ? ? ? ? */
none,none,none,none /* FC-FF ? ? ? ? */
};
+
+unsigned long kbd_init(unsigned long kmem_start)
+{
+ int i;
+ unsigned char a;
+ struct kbd_struct * kbd;
+
+ kbd = kbd_table + 0;
+ for (i = 0 ; i < NR_CONSOLES ; i++,kbd++) {
+ kbd->flags = KBD_DEFFLAGS;
+ kbd->default_flags = KBD_DEFFLAGS;
+ kbd->kbd_flags = KBDFLAGS;
+ }
+ request_irq(KEYBOARD_IRQ,keyboard_interrupt);
+ a=inb_p(0x61);
+ outb_p(a|0x80,0x61);
+ outb_p(a,0x61);
+ return kmem_start;
+}
diff --git a/kernel/chr_drv/lp.c b/kernel/chr_drv/lp.c
index bfa02c7..45e338b 100644
--- a/kernel/chr_drv/lp.c
+++ b/kernel/chr_drv/lp.c
@@ -1,10 +1,16 @@
-/*
- * Copyright (C) 1992 by Jim Weigand, Linus Torvalds, and Michael K. Johnson
- */
+/* Copyright (C) 1992 by Jim Weigand, Linus Torvalds, and Michael K. Johnson
+*/
#include <linux/lp.h>
/* sched.h is included from lp.h */
+/*
+ * All my debugging code assumes that you debug with only one printer at
+ * a time. RWWH
+ */
+
+#undef LP_DEBUG
+
static int lp_reset(int minor)
{
int testvalue;
@@ -17,108 +23,134 @@ static int lp_reset(int minor)
return LP_S(minor);
}
+#ifdef LP_DEBUG
+static int lp_max_count = 1;
+#endif
+
static int lp_char(char lpchar, int minor)
{
- int retval = 0;
+ int retval = 0, wait = 0;
unsigned long count = 0;
outb(lpchar, LP_B(minor));
do {
retval = LP_S(minor);
count ++;
- if (need_resched)
+ if(need_resched)
schedule();
- } while(!(retval & LP_PBUSY) && count < LP_TIME_CHAR);
+ } while(!(retval & LP_PBUSY) && count < LP_CHAR(minor));
- if (count == LP_TIME_CHAR) {
+ if (count == LP_CHAR(minor)) {
return 0;
/* we timed out, and the character was /not/ printed */
}
+#ifdef LP_DEBUG
+ if (count > lp_max_count) {
+ printk("lp success after %d counts.\n",count);
+ lp_max_count=count;
+ }
+#endif
+ /* must wait before taking strobe high, and after taking strobe
+ low, according spec. Some printers need it, others don't. */
+ while(wait != LP_WAIT(minor)) wait++;
/* control port takes strobe high */
outb(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
+ while(wait) wait--;
/* take strobe low */
outb(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
/* get something meaningful for return value */
return LP_S(minor);
}
+#ifdef LP_DEBUG
+ unsigned int lp_total_chars = 0;
+ unsigned int lp_last_call = 0;
+#endif
+
static int lp_write(struct inode * inode, struct file * file, char * buf, int count)
{
int retval;
unsigned int minor = MINOR(inode->i_rdev);
- unsigned int each_cnt = 0, old_cnt = 0;
char c, *temp = buf;
+#ifdef LP_DEBUG
+ if (jiffies-lp_last_call > LP_TIME(minor)) {
+ lp_total_chars = 0;
+ lp_max_count = 1;
+ }
+ lp_last_call = jiffies;
+#endif
+
temp = buf;
while (count > 0) {
c = get_fs_byte(temp);
retval = lp_char(c, minor);
/* only update counting vars if character was printed */
- if (retval) {
- count--;
- temp++;
+ if (retval) { count--; temp++;
+#ifdef LP_DEBUG
+ lp_total_chars++;
+#endif
}
-
if (!retval) { /* if printer timed out */
- each_cnt = count - old_cnt;
- old_cnt = count;
-
- /* here we do calculations based on old count
- and change the time that we will sleep.
- For now this will be hard coded... */
-
/* check for signals before going to sleep */
if (current->signal & ~current->blocked) {
- return temp-buf?temp-buf:-ERESTARTSYS;
+ if (count > 0) return -EINTR;
}
+#ifdef LP_DEBUG
+ printk("lp sleeping at %d characters for %d jiffies\n",
+ lp_total_chars, LP_TIME(minor));
+ lp_total_chars=0;
+#endif
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + LP_TIME(minor);
schedule();
- LP_COUNT(minor) = each_cnt;
- /* the following is ugly, but should alert me if
- something dreadful is going on. It will disappear
- in the final versions of the driver. */
+ /* If nothing is getting to the printer
+ for a considerable length of time,
+ someone oughtta know. */
if (!(LP_S(minor) & LP_BUSY)) {
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + LP_TIMEOUT;
schedule();
if (!(LP_S(minor) & LP_BUSY))
- printk("lp%d timeout\n\r", minor);
+ printk("lp%d timeout\n", minor);
}
} else {
if (retval & LP_POUTPA) {
- LP_F(minor) |= LP_NOPA;
- printk("lp%d out of paper\n\r", minor);
- return temp-buf?temp-buf:-ENOSPC;
+ printk("lp%d out of paper\n", minor);
+ if(LP_F(minor) && LP_ABORT)
+ return temp-buf?temp-buf:-ENOSPC;
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + LP_TIMEOUT;
+ schedule();
} else
- LP_F(minor) &= ~LP_NOPA;
if (!(retval & LP_PSELECD)) {
- LP_F(minor) |= LP_SELEC;
- printk("lp%d off-line\n\r", minor);
- return temp-buf?temp-buf:-EFAULT;
+ printk("lp%d off-line\n", minor);
+ if(LP_F(minor) && LP_ABORT)
+ return temp-buf?temp-buf:-EIO;
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + LP_TIMEOUT;
+ schedule();
} else
- LP_F(minor) &= ~LP_SELEC;
/* not offline or out of paper. on fire? */
if (!(retval & LP_PERRORP)) {
- LP_F(minor) |= LP_ERR;
- printk("lp%d on fire\n\r", minor);
- return temp-buf?temp-buf:-EIO;
- } else
- LP_F(minor) &= ~LP_SELEC;
+ printk("lp%d on fire\n", minor);
+ if(LP_F(minor) && LP_ABORT)
+ return temp-buf?temp-buf:-EFAULT;
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + LP_TIMEOUT;
+ schedule();
+ }
}
}
return temp-buf;
}
-static int lp_read(struct inode * inode, struct file * file, char * buf, int count)
-{
- return -EINVAL;
-}
-static int lp_lseek(struct inode * inode, struct file * file, off_t offset, int origin)
+static int lp_lseek(struct inode * inode, struct file * file,
+ off_t offset, int origin)
{
return -EINVAL;
}
@@ -144,14 +176,48 @@ static void lp_release(struct inode * inode, struct file * file)
LP_F(minor) &= ~LP_BUSY;
}
+
+static int lp_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned int arg)
+{
+ unsigned int minor = MINOR(inode->i_rdev);
+
+#ifdef LP_DEBUG
+ printk("lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
+#endif
+ if (minor >= LP_NO)
+ return -ENODEV;
+ if ((LP_F(minor) & LP_EXIST) == 0)
+ return -ENODEV;
+ switch ( cmd ) {
+ case LPTIME:
+ LP_TIME(minor) = arg;
+ break;
+ case LPCHAR:
+ LP_CHAR(minor) = arg;
+ break;
+ case LPABORT:
+ if(arg)
+ LP_F(minor) |= LP_ABORT;
+ else LP_F(minor) &= ~LP_ABORT;
+ break;
+ case LPWAIT:
+ LP_WAIT(minor) = arg;
+ break;
+ default: arg = -EINVAL;
+ }
+ return arg;
+}
+
+
static struct file_operations lp_fops = {
- lp_lseek, /* why not null? */
- lp_read, /* why not null? */
+ lp_lseek,
+ NULL, /* lp_read */
lp_write,
NULL, /* lp_readdir */
NULL, /* lp_select */
- NULL, /* lp_ioctl */
- NULL, /* mmap */
+ lp_ioctl,
+ NULL, /* lp_mmap */
lp_open,
lp_release
};
diff --git a/kernel/chr_drv/psaux.c b/kernel/chr_drv/psaux.c
index a3750bf..8b1c8c1 100644
--- a/kernel/chr_drv/psaux.c
+++ b/kernel/chr_drv/psaux.c
@@ -75,11 +75,9 @@ static int aux_present = 0;
static int poll_status(void);
-
/*
* Write to aux device
*/
-
static void aux_write_dev(int val)
{
poll_status();
@@ -89,7 +87,7 @@ static void aux_write_dev(int val)
}
-
+#if 0
/*
* Write to device & handle returned ack
*/
@@ -104,7 +102,7 @@ static int aux_write_ack(int val)
}
return 0;
}
-
+#endif
/*
* Write aux device command
diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c
index 0b9e8cc..b468cba 100644
--- a/kernel/chr_drv/tty_io.c
+++ b/kernel/chr_drv/tty_io.c
@@ -32,6 +32,7 @@
#include <linux/kd.h>
#include <linux/mm.h>
#include <linux/string.h>
+#include <linux/keyboard.h>
#include <asm/segment.h>
#include <asm/system.h>
@@ -52,7 +53,8 @@ int fg_console = 0;
struct tty_struct * redirect = NULL;
struct wait_queue * keypress_wait = NULL;
-int initialize_tty_struct(struct tty_struct *tty, int line);
+static int initialize_tty_struct(struct tty_struct *tty, int line);
+static void reset_tty_termios(int line);
void put_tty_queue(char c, struct tty_queue * queue)
{
@@ -279,28 +281,13 @@ static void wait_for_canon_input(struct tty_struct * tty)
__wait_for_canon_input(tty);
}
-static int read_chan(unsigned int channel, struct file * file, char * buf, int nr)
+static int read_chan(struct tty_struct * tty, struct file * file, char * buf, int nr)
{
- struct tty_struct * tty;
struct wait_queue wait = { current, NULL };
int c;
char * b=buf;
int minimum,time;
- if (channel > 255)
- return -EIO;
- tty = TTY_TABLE(channel);
- if (!tty)
- return -EIO;
- if ((tty->pgrp > 0) &&
- (current->tty == channel) &&
- (tty->pgrp != current->pgrp))
- if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
- return -EIO;
- else {
- (void) kill_pg(current->pgrp, SIGTTIN, 1);
- return -ERESTARTSYS;
- }
if (L_CANON(tty))
minimum = time = current->timeout = 0;
else {
@@ -445,29 +432,11 @@ static int available_canon_input(struct tty_struct * tty)
return 0;
}
-static int write_chan(unsigned int channel, struct file * file, char * buf, int nr)
+static int write_chan(struct tty_struct * tty, struct file * file, char * buf, int nr)
{
- struct tty_struct * tty;
struct wait_queue wait = { current, NULL };
char c, *b=buf;
- if (channel > 255)
- return -EIO;
- if (redirect && ((channel == 0) || (channel == fg_console+1)))
- tty = redirect;
- else
- tty = TTY_TABLE(channel);
- if (!tty || !tty->write)
- return -EIO;
- if (L_TOSTOP(tty) && (tty->pgrp > 0) &&
- (current->tty == channel) && (tty->pgrp != current->pgrp)) {
- if (is_orphaned_pgrp(tty->pgrp))
- return -EIO;
- if (!is_ignored(SIGTTOU)) {
- (void) kill_pg(current->pgrp, SIGTTOU, 1);
- return -ERESTARTSYS;
- }
- }
if (nr < 0)
return -EINVAL;
if (!nr)
@@ -524,13 +493,28 @@ static int write_chan(unsigned int channel, struct file * file, char * buf, int
static int tty_read(struct inode * inode, struct file * file, char * buf, int count)
{
- int i;
+ int i, dev;
+ struct tty_struct * tty;
- if (MAJOR(file->f_rdev) != 4) {
+ dev = file->f_rdev;
+ if (MAJOR(dev) != 4) {
printk("tty_read: pseudo-major != 4\n");
return -EINVAL;
}
- i = read_chan(MINOR(file->f_rdev),file,buf,count);
+ dev = MINOR(dev);
+ tty = TTY_TABLE(dev);
+ if (!tty)
+ return -EIO;
+ if (MINOR(inode->i_rdev) && (tty->pgrp > 0) &&
+ (current->tty == dev) &&
+ (tty->pgrp != current->pgrp))
+ if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
+ return -EIO;
+ else {
+ (void) kill_pg(current->pgrp, SIGTTIN, 1);
+ return -ERESTARTSYS;
+ }
+ i = read_chan(tty,file,buf,count);
if (i > 0)
inode->i_atime = CURRENT_TIME;
return i;
@@ -538,13 +522,32 @@ static int tty_read(struct inode * inode, struct file * file, char * buf, int co
static int tty_write(struct inode * inode, struct file * file, char * buf, int count)
{
- int i;
-
- if (MAJOR(file->f_rdev) != 4) {
+ int dev,i;
+ struct tty_struct * tty;
+
+ dev = file->f_rdev;
+ if (MAJOR(dev) != 4) {
printk("tty_write: pseudo-major != 4\n");
return -EINVAL;
}
- i = write_chan(MINOR(file->f_rdev),file,buf,count);
+ dev = MINOR(dev);
+ if (redirect && ((dev == 0) || (dev == fg_console+1)))
+ tty = redirect;
+ else
+ tty = TTY_TABLE(dev);
+ if (!tty || !tty->write)
+ return -EIO;
+ if (MINOR(inode->i_rdev) &&
+ L_TOSTOP(tty) && (tty->pgrp > 0) &&
+ (current->tty == dev) && (tty->pgrp != current->pgrp)) {
+ if (is_orphaned_pgrp(tty->pgrp))
+ return -EIO;
+ if (!is_ignored(SIGTTOU)) {
+ (void) kill_pg(current->pgrp, SIGTTOU, 1);
+ return -ERESTARTSYS;
+ }
+ }
+ i = write_chan(tty,file,buf,count);
if (i > 0)
inode->i_mtime = CURRENT_TIME;
return i;
@@ -562,6 +565,9 @@ static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int
*
* Open-counting is needed for pty masters, as well as for keeping
* track of serial lines: DTR is dropped when the last close happens.
+ *
+ * The termios state of a pty is reset on first open so that
+ * settings don't persist across reuse.
*/
static int tty_open(struct inode * inode, struct file * filp)
{
@@ -574,16 +580,18 @@ static int tty_open(struct inode * inode, struct file * filp)
else
dev = MINOR(dev);
if (dev < 0)
- return -ENODEV;
+ return -ENXIO;
+ if (!dev)
+ dev = fg_console + 1;
filp->f_rdev = 0x0400 | dev;
/*
* There be race-conditions here... Lots of them. Careful now.
*/
tty = o_tty = NULL;
- if (!TTY_TABLE(dev)) {
+ if (!tty_table[dev]) {
tty = (struct tty_struct *) get_free_page(GFP_KERNEL);
if (tty) {
- retval = initialize_tty_struct(tty, TTY_TABLE_IDX(dev));
+ retval = initialize_tty_struct(tty, dev);
if (retval) {
free_page((unsigned long)tty);
return retval;
@@ -607,11 +615,11 @@ static int tty_open(struct inode * inode, struct file * filp)
return -ENOMEM;
}
}
- if (TTY_TABLE(dev)) {
+ if (tty_table[dev]) {
free_page((unsigned long) tty);
- tty = TTY_TABLE(dev);
+ tty = tty_table[dev];
} else if (tty)
- TTY_TABLE(dev) = tty;
+ tty_table[dev] = tty;
else {
free_page((unsigned long) o_tty);
return -ENOMEM;
@@ -628,13 +636,12 @@ static int tty_open(struct inode * inode, struct file * filp)
if (IS_A_PTY_MASTER(dev)) {
if (tty->count)
return -EAGAIN;
- if (tty->link)
- tty->link->count++;
-
- /* perhaps user applications that don't take care of
- this deserve what the get, but I think my system
- has hung do to this, esp. in X. -RAB */
- tty->termios->c_lflag &= ~ECHO;
+ if (tty->link && tty->link->count++ == 0)
+ reset_tty_termios(PTY_OTHER(dev));
+ reset_tty_termios(dev);
+ } else if (IS_A_PTY_SLAVE(dev)) {
+ if (tty->count == 0)
+ reset_tty_termios(dev);
}
tty->count++;
retval = 0;
@@ -680,9 +687,11 @@ static void tty_release(struct inode * inode, struct file * filp)
return;
}
dev = MINOR(filp->f_rdev);
- tty = TTY_TABLE(dev);
+ if (!dev)
+ dev = fg_console+1;
+ tty = tty_table[dev];
if (!tty) {
- printk("tty_release: TTY_TABLE(%d) was NULL\n", dev);
+ printk("tty_release: tty_table[%d] was NULL\n", dev);
return;
}
if (IS_A_PTY_MASTER(dev) && tty->link) {
@@ -693,7 +702,7 @@ static void tty_release(struct inode * inode, struct file * filp)
}
}
if (--tty->count < 0) {
- printk("tty_release: bad TTY_TABLE(%d)->count: %d\n",
+ printk("tty_release: bad tty_table[%d]->count: %d\n",
dev, tty->count);
tty->count = 0;
}
@@ -708,11 +717,11 @@ static void tty_release(struct inode * inode, struct file * filp)
if (tty->link) {
if (tty->link->count)
return;
- free_page((unsigned long) TTY_TABLE(PTY_OTHER(dev)));
- TTY_TABLE(PTY_OTHER(dev)) = 0;
+ free_page((unsigned long) tty_table[PTY_OTHER(dev)]);
+ tty_table[PTY_OTHER(dev)] = 0;
}
- free_page((unsigned long) TTY_TABLE(dev));
- TTY_TABLE(dev) = 0;
+ free_page((unsigned long) tty_table[dev]);
+ tty_table[dev] = 0;
}
static int tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
@@ -815,35 +824,18 @@ void do_SAK( struct tty_struct *tty)
* This subroutine initializes a tty structure. We have to set up
* things correctly for each different type of tty.
*/
-int initialize_tty_struct(struct tty_struct *tty, int line)
+static int initialize_tty_struct(struct tty_struct *tty, int line)
{
- struct termios *tp;
-
memset(tty, 0, sizeof(struct tty_struct));
tty->line = line;
tty->pgrp = -1;
tty->winsize.ws_row = 24;
tty->winsize.ws_col = 80;
if (!tty_termios[line]) {
- tp = tty_termios[line] = kmalloc(sizeof(struct termios),
- GFP_KERNEL);
- if (!tp)
+ tty_termios[line] = kmalloc(sizeof(struct termios), GFP_KERNEL);
+ if (!tty_termios[line])
return -ENOMEM;
- memset(tp, 0, sizeof(struct termios));
- memcpy(tp->c_cc, INIT_C_CC, NCCS);
- if (IS_A_CONSOLE(line)) {
- tp->c_iflag = ICRNL | IXON;
- tp->c_oflag = OPOST | ONLCR;
- tp->c_cflag = B38400 | CS8 | CREAD;
- tp->c_lflag = ISIG | ICANON | ECHO | ECHOCTL | ECHOKE;
- } else if (IS_A_SERIAL(line)) {
- tp->c_cflag = B2400 | CS8 | CREAD | HUPCL;
- } else if (IS_A_PTY_MASTER(line)) {
- tp->c_cflag = B9600 | CS8 | CREAD;
- } else if (IS_A_PTY_SLAVE(line)) {
- tp->c_cflag = B9600 | CS8 | CREAD;
- tp->c_lflag = ISIG | ICANON;
- }
+ reset_tty_termios(line);
}
tty->termios = tty_termios[line];
@@ -859,6 +851,33 @@ int initialize_tty_struct(struct tty_struct *tty, int line)
return 0;
}
+static void reset_tty_termios(int line)
+{
+ struct termios *tp = tty_termios[line];
+
+ if (!tp) {
+ printk("termios of line was NULL\n");
+ return;
+ }
+ memset(tp, 0, sizeof(struct termios));
+ memcpy(tp->c_cc, INIT_C_CC, NCCS);
+ if (IS_A_CONSOLE(line)) {
+ tp->c_iflag = ICRNL | IXON;
+ tp->c_oflag = OPOST | ONLCR;
+ tp->c_cflag = B38400 | CS8 | CREAD;
+ tp->c_lflag = ISIG | ICANON | ECHO | ECHOCTL | ECHOKE;
+ } else if (IS_A_SERIAL(line)) {
+ tp->c_cflag = B2400 | CS8 | CREAD | HUPCL;
+ } else if (IS_A_PTY_MASTER(line)) {
+ tp->c_cflag = B9600 | CS8 | CREAD;
+ } else if (IS_A_PTY_SLAVE(line)) {
+ tp->c_iflag = ICRNL | IXON;
+ tp->c_oflag = OPOST | ONLCR;
+ tp->c_cflag = B38400 | CS8 | CREAD;
+ tp->c_lflag = ISIG | ICANON | ECHO | ECHOCTL | ECHOKE;
+ }
+}
+
long tty_init(long kmem_start)
{
int i;
@@ -869,6 +888,7 @@ long tty_init(long kmem_start)
tty_table[i] = 0;
tty_termios[i] = 0;
}
+ kmem_start = kbd_init(kmem_start);
kmem_start = con_init(kmem_start);
kmem_start = rs_init(kmem_start);
printk("%d virtual consoles\n\r",NR_CONSOLES);
diff --git a/kernel/chr_drv/tty_ioctl.c b/kernel/chr_drv/tty_ioctl.c
index 1bde890..02e7203 100644
--- a/kernel/chr_drv/tty_ioctl.c
+++ b/kernel/chr_drv/tty_ioctl.c
@@ -39,7 +39,7 @@ void flush_input(struct tty_struct * tty)
flush(&tty->secondary);
tty->secondary.data = 0;
- if (tty = tty->link) {
+ if ((tty = tty->link) != NULL) {
flush(&tty->write_q);
wake_up_interruptible(&tty->write_q.proc_list);
}
@@ -51,7 +51,7 @@ void flush_output(struct tty_struct * tty)
tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
flush(&tty->write_q);
wake_up_interruptible(&tty->write_q.proc_list);
- if (tty = tty->link) {
+ if ((tty = tty->link) != NULL) {
flush(&tty->read_q);
wake_up_interruptible(&tty->read_q.proc_list);
flush(&tty->secondary);
@@ -336,19 +336,19 @@ int tty_ioctl(struct inode * inode, struct file * file,
return -EINVAL; /* set controlling term NI */
case TIOCGPGRP:
verify_area((void *) arg,4);
- put_fs_long(tty->pgrp,(unsigned long *) arg);
+ put_fs_long(termios_tty->pgrp,(unsigned long *) arg);
return 0;
case TIOCSPGRP:
if ((current->tty < 0) ||
- (current->tty != dev) ||
- (tty->session != current->session))
+ (current->tty != termios_dev) ||
+ (termios_tty->session != current->session))
return -ENOTTY;
pgrp=get_fs_long((unsigned long *) arg);
if (pgrp < 0)
return -EINVAL;
if (session_of_pgrp(pgrp) != current->session)
return -EPERM;
- tty->pgrp = pgrp;
+ termios_tty->pgrp = pgrp;
return 0;
case TIOCOUTQ:
verify_area((void *) arg,4);
diff --git a/kernel/chr_drv/vt.c b/kernel/chr_drv/vt.c
index acb6dc7..b319734 100644
--- a/kernel/chr_drv/vt.c
+++ b/kernel/chr_drv/vt.c
@@ -10,6 +10,7 @@
#include <linux/tty.h>
#include <linux/timer.h>
#include <linux/kernel.h>
+#include <linux/keyboard.h>
#include <linux/kd.h>
#include <linux/vt.h>
@@ -24,10 +25,6 @@
struct vt_cons vt_cons[NR_CONSOLES];
-extern unsigned char kleds;
-extern unsigned char kraw;
-extern unsigned char ke0;
-
extern int sys_ioperm(unsigned long from, unsigned long num, int on);
extern void set_leds(void);
@@ -71,12 +68,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
{
int console;
unsigned char ucval;
+ struct kbd_struct * kbd;
console = tty->line - 1;
if (console < 0 || console >= NR_CONSOLES)
return -EINVAL;
+ kbd = kbd_table + console;
switch (cmd) {
case KIOCSOUND:
return kiocsound((unsigned int)arg);
@@ -148,19 +147,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
case KDSKBMODE:
if (arg == K_RAW) {
- if (console == fg_console) {
- kraw = 1;
- ke0 = 0;
- } else {
- vt_cons[console].vc_kbdraw = 1;
- vt_cons[console].vc_kbde0 = 0;
- }
- }
- else if (arg == K_XLATE) {
- if (console == fg_console)
- kraw = 0;
- else
- vt_cons[console].vc_kbdraw = 0;
+ set_vc_kbd_flag(kbd, VC_RAW);
+ } else if (arg == K_XLATE) {
+ clr_vc_kbd_flag(kbd, VC_RAW);
}
else
return -EINVAL;
@@ -168,32 +157,37 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return 0;
case KDGKBMODE:
verify_area((void *) arg, sizeof(unsigned long));
- ucval = (console == fg_console) ? kraw :
- vt_cons[console].vc_kbdraw;
+ ucval = vc_kbd_flag(kbd, VC_RAW);
put_fs_long(ucval ? K_RAW : K_XLATE, (unsigned long *) arg);
return 0;
case KDGETLED:
verify_area((void *) arg, sizeof(unsigned char));
- ucval = (console == fg_console) ? kleds :
- vt_cons[console].vc_kbdleds;
- put_fs_byte((((ucval & 1) ? LED_SCR : 0) |
- ((ucval & 2) ? LED_NUM : 0) |
- ((ucval & 4) ? LED_CAP : 0)),
- (unsigned char *) arg);
+ ucval = 0;
+ if (vc_kbd_flag(kbd, VC_SCROLLOCK))
+ ucval |= LED_SCR;
+ if (vc_kbd_flag(kbd, VC_NUMLOCK))
+ ucval |= LED_NUM;
+ if (vc_kbd_flag(kbd, VC_CAPSLOCK))
+ ucval |= LED_CAP;
+ put_fs_byte(ucval, (unsigned char *) arg);
return 0;
case KDSETLED:
if (arg & ~7)
return -EINVAL;
- ucval = (((arg & LED_SCR) ? 1 : 0) |
- ((arg & LED_NUM) ? 2 : 0) |
- ((arg & LED_CAP) ? 4 : 0));
- if (console == fg_console) {
- kleds = ucval;
- set_leds();
- }
+ if (arg & LED_SCR)
+ set_vc_kbd_flag(kbd, VC_SCROLLOCK);
+ else
+ clr_vc_kbd_flag(kbd, VC_SCROLLOCK);
+ if (arg & LED_NUM)
+ set_vc_kbd_flag(kbd, VC_NUMLOCK);
+ else
+ clr_vc_kbd_flag(kbd, VC_NUMLOCK);
+ if (arg & LED_CAP)
+ set_vc_kbd_flag(kbd, VC_CAPSLOCK);
else
- vt_cons[console].vc_kbdleds = ucval;
+ clr_vc_kbd_flag(kbd, VC_CAPSLOCK);
+ set_leds();
return 0;
default:
diff --git a/kernel/dma.c b/kernel/dma.c
index e168383..b010163 100644
--- a/kernel/dma.c
+++ b/kernel/dma.c
@@ -1,4 +1,4 @@
-/* $Header: /sys/linux-0.97/kernel/RCS/dma.c,v 1.4 1992/09/18 02:54:14 root Exp $
+/* $Id: dma.c,v 1.5 1992/11/18 02:49:05 root Exp root $
* linux/kernel/dma.c: A DMA channel allocator. Inspired by linux/kernel/irq.c.
* Written by Hennus Bergman, 1992.
*/
@@ -41,7 +41,7 @@ static volatile unsigned int dma_chan_busy[MAX_DMA_CHANNELS] = {
* Maybe this should be in include/asm/mutex.h and be used for
* implementing kernel-semaphores as well.
*/
-static unsigned int __inline__ mutex_atomic_swap(volatile unsigned int * p, unsigned int newval)
+static __inline__ unsigned int mutex_atomic_swap(volatile unsigned int * p, unsigned int newval)
{
unsigned int semval = newval;
diff --git a/kernel/exit.c b/kernel/exit.c
index 30b14e0..5df7516 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -198,7 +198,7 @@ int kill_pg(int pgrp, int sig, int priv)
return -EINVAL;
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if (*p && (*p)->pgrp == pgrp) {
- if (err = send_sig(sig,*p,priv))
+ if ((err = send_sig(sig,*p,priv)) != 0)
retval = err;
else
found++;
@@ -345,7 +345,7 @@ fake_volatile:
* as a result of our exiting, and if they have any stopped
* jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
*/
- while (p = current->p_cptr) {
+ while ((p = current->p_cptr) != NULL) {
current->p_cptr = p->p_osptr;
p->p_ysptr = NULL;
p->flags &= ~(PF_PTRACED|PF_TRACESYS);
diff --git a/kernel/fork.c b/kernel/fork.c
index 8eb1a87..d7ff3cd 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -172,7 +172,7 @@ int sys_fork(long ebx,long ecx,long edx,
}
p->tss.esp0 = PAGE_SIZE + p->kernel_stack_page;
for (i=0; i<NR_OPEN;i++)
- if (f=p->filp[i])
+ if ((f = p->filp[i]) != NULL)
f->f_count++;
if (current->pwd)
current->pwd->i_count++;
diff --git a/kernel/info.c b/kernel/info.c
new file mode 100644
index 0000000..0a373a9
--- /dev/null
+++ b/kernel/info.c
@@ -0,0 +1,39 @@
+/*
+ * linux/kernel/info.c
+ *
+ * Copyright (C) 1992 Darren Senn
+ */
+
+/* This implements the sysinfo() system call */
+
+#include <asm/segment.h>
+
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/unistd.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+
+int sys_sysinfo(struct sysinfo *info)
+{
+ struct sysinfo val;
+ struct task_struct **p;
+
+ verify_area(info, sizeof(struct sysinfo));
+ memset((char *)&val, 0, sizeof(struct sysinfo));
+
+ val.uptime = (jiffies + jiffies_offset) / HZ;
+
+ val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
+ val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
+ val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
+
+ for (p = &LAST_TASK; p > &FIRST_TASK; p--)
+ if (*p) val.procs++;
+
+ si_meminfo(&val);
+ si_swapinfo(&val);
+
+ memcpy_tofs(info, &val, sizeof(struct sysinfo));
+ return 0;
+}
diff --git a/kernel/irq.c b/kernel/irq.c
index b3105a3..a287bf1 100644
--- a/kernel/irq.c
+++ b/kernel/irq.c
@@ -124,7 +124,6 @@ int do_IRQ(int irq, struct pt_regs * regs)
struct sigaction * sa = irq + irq_sigaction;
sa->sa_handler((int) regs);
- return 0; /* re-enable the irq when returning */
}
/*
@@ -137,7 +136,6 @@ int do_fast_IRQ(int irq)
struct sigaction * sa = irq + irq_sigaction;
sa->sa_handler(irq);
- return 0; /* re-enable the irq when returning */
}
int irqaction(unsigned int irq, struct sigaction * new)
diff --git a/kernel/printk.c b/kernel/printk.c
index 8113392..c555f9f 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -42,7 +42,7 @@ int sys_syslog(int type, char * buf, int len)
if (log_page) {
free_page(i);
return 0;
- } else if (log_page = i) {
+ } else if ((log_page = i) != 0) {
log_start = log_size = 0;
return 0;
}
diff --git a/kernel/sched.c b/kernel/sched.c
index 6f508b2..b648da0 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -169,7 +169,7 @@ void wake_up(struct wait_queue **q)
if (!q || !(tmp = *q))
return;
do {
- if (p = tmp->task) {
+ if ((p = tmp->task) != NULL) {
if ((p->state == TASK_UNINTERRUPTIBLE) ||
(p->state == TASK_INTERRUPTIBLE)) {
p->state = TASK_RUNNING;
@@ -196,7 +196,7 @@ void wake_up_interruptible(struct wait_queue **q)
if (!q || !(tmp = *q))
return;
do {
- if (p = tmp->task) {
+ if ((p = tmp->task) != NULL) {
if (p->state == TASK_INTERRUPTIBLE) {
p->state = TASK_RUNNING;
if (p->counter > current->counter)
diff --git a/kernel/sys.c b/kernel/sys.c
index 744d357..26e2671 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -151,7 +151,7 @@ static void mark_screen_rdonly(struct task_struct * tsk)
unsigned long tmp;
unsigned long *pg_table;
- if (tmp = tsk->tss.cr3) {
+ if ((tmp = tsk->tss.cr3) != 0) {
tmp = *(unsigned long *) tmp;
if (tmp & PAGE_PRESENT) {
tmp &= 0xfffff000;
diff --git a/kernel/vsprintf.c b/kernel/vsprintf.c
index 03b33c1..8cb121f 100644
--- a/kernel/vsprintf.c
+++ b/kernel/vsprintf.c
@@ -258,3 +258,15 @@ int vsprintf(char *buf, const char *fmt, va_list args)
*str = '\0';
return str-buf;
}
+
+int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
diff --git a/lib/Makefile b/lib/Makefile
index fb6eaae..693db67 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -40,9 +40,10 @@ malloc.o : malloc.c /usr/include/linux/kernel.h /usr/include/linux/mm.h /usr/inc
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/string.h /usr/include/asm/system.h
-open.o : open.c /usr/include/linux/unistd.h /usr/lib/gcc-lib/i386-linux/2.2.2d/include/stdarg.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/string.h \
+ /usr/include/asm/system.h
+open.o : open.c /usr/include/linux/unistd.h /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h
setsid.o : setsid.c /usr/include/linux/types.h /usr/include/linux/unistd.h
string.o : string.c /usr/include/linux/types.h /usr/include/linux/string.h
wait.o : wait.c /usr/include/linux/unistd.h /usr/include/linux/types.h
diff --git a/mm/Makefile b/mm/Makefile
index 7e9e19a..097aa59 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -33,27 +33,30 @@ memory.o : memory.c /usr/include/asm/system.h /usr/include/linux/signal.h /usr/i
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/errno.h /usr/include/linux/string.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
+ /usr/include/linux/string.h
mmap.o : mmap.c /usr/include/linux/stat.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/errno.h /usr/include/linux/mman.h /usr/include/linux/string.h \
- /usr/include/asm/segment.h /usr/include/asm/system.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
+ /usr/include/linux/mman.h /usr/include/linux/string.h /usr/include/asm/segment.h \
+ /usr/include/asm/system.h
swap.o : swap.c /usr/include/linux/mm.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/kernel.h \
- /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
- /usr/include/linux/string.h /usr/include/linux/stat.h /usr/include/asm/system.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \
+ /usr/include/linux/head.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/errno.h /usr/include/linux/string.h \
+ /usr/include/linux/stat.h /usr/include/asm/system.h
diff --git a/mm/memory.c b/mm/memory.c
index 429fefa..e74712e 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -36,6 +36,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
+#include <linux/types.h>
unsigned long high_memory = 0;
@@ -259,7 +260,7 @@ int unmap_page_range(unsigned long from, unsigned long size)
poff = 0;
}
for (pc = pcnt; pc--; page_table++) {
- if (page = *page_table) {
+ if ((page = *page_table) != 0) {
--current->rss;
*page_table = 0;
if (1 & page)
@@ -336,7 +337,7 @@ int remap_page_range(unsigned long from, unsigned long to, unsigned long size,
if (permiss & 4)
mask |= 1;
- if (page = *page_table) {
+ if ((page = *page_table) != 0) {
*page_table = 0;
--current->rss;
if (1 & page)
@@ -661,7 +662,7 @@ repeat:
*p = page | PAGE_ACCESSED | 7;
return *p;
}
- if (page = get_free_page(GFP_KERNEL))
+ if ((page = get_free_page(GFP_KERNEL)) != 0)
goto repeat;
oom(current);
*p = BAD_PAGETABLE | 7;
@@ -955,3 +956,28 @@ void mem_init(unsigned long start_low_mem,
datapages << 2);
return;
}
+
+void si_meminfo(struct sysinfo *val)
+{
+ int i;
+
+ i = high_memory >> PAGE_SHIFT;
+ val->totalram = 0;
+ val->freeram = 0;
+ val->sharedram = 0;
+ val->bufferram = buffermem;
+ while (i-- > 0) {
+ if (mem_map[i] & MAP_PAGE_RESERVED)
+ continue;
+ val->totalram++;
+ if (!mem_map[i]) {
+ val->freeram++;
+ continue;
+ }
+ val->sharedram += mem_map[i]-1;
+ }
+ val->totalram <<= PAGE_SHIFT;
+ val->freeram <<= PAGE_SHIFT;
+ val->sharedram <<= PAGE_SHIFT;
+ return;
+}
diff --git a/mm/swap.c b/mm/swap.c
index 0a47c0d..ed441f1 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -406,7 +406,7 @@ void free_page(unsigned long addr)
*/
#define REMOVE_FROM_MEM_QUEUE(queue,nr) \
cli(); \
- if (result = queue) { \
+ if ((result = queue) != 0) { \
if (!(result & 0xfff) && result < high_memory) { \
queue = *(unsigned long *) result; \
if (!mem_map[MAP_NR(result)]) { \
@@ -706,3 +706,26 @@ int sys_swapon(const char * specialfile)
printk("Adding Swap: %dk swap-space\n\r",j<<2);
return 0;
}
+
+void si_swapinfo(struct sysinfo *val)
+{
+ unsigned int i, j;
+
+ val->freeswap = val->totalswap = 0;
+ for (i = 0; i < nr_swapfiles; i++) {
+ if (!(swap_info[i].flags & SWP_USED))
+ continue;
+ for (j = 0; j < 4096; ++j)
+ switch (swap_info[i].swap_map[j]) {
+ case 128:
+ continue;
+ case 0:
+ ++val->freeswap;
+ default:
+ ++val->totalswap;
+ }
+ }
+ val->freeswap <<= PAGE_SHIFT;
+ val->totalswap <<= PAGE_SHIFT;
+ return;
+}
diff --git a/net/Makefile b/net/Makefile
index b29a4d8..4247e95 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -47,21 +47,22 @@ socket.o : socket.c /usr/include/linux/signal.h /usr/include/linux/errno.h /usr/
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/stat.h /usr/include/linux/socket.h /usr/include/linux/fcntl.h \
- /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/asm/segment.h \
- kern_sock.h socketcall.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/stat.h \
+ /usr/include/linux/socket.h /usr/include/linux/fcntl.h /usr/include/linux/termios.h \
+ /usr/include/asm/system.h /usr/include/asm/segment.h kern_sock.h socketcall.h
unix.o : unix.c /usr/include/linux/signal.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
- /usr/include/linux/string.h /usr/include/linux/stat.h /usr/include/linux/socket.h \
- /usr/include/linux/un.h /usr/include/linux/fcntl.h /usr/include/linux/termios.h \
- /usr/include/asm/system.h /usr/include/asm/segment.h kern_sock.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/errno.h /usr/include/linux/string.h \
+ /usr/include/linux/stat.h /usr/include/linux/socket.h /usr/include/linux/un.h \
+ /usr/include/linux/fcntl.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/asm/segment.h kern_sock.h
diff --git a/net/tcp/Makefile b/net/tcp/Makefile
index e4f7131..6fbd5a7 100644
--- a/net/tcp/Makefile
+++ b/net/tcp/Makefile
@@ -44,175 +44,184 @@ arp.o : arp.c /usr/include/linux/types.h /usr/include/linux/string.h /usr/includ
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
- /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
- /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
- /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
- /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
- /usr/include/linux/socket.h /usr/include/netinet/in.h /usr/include/features.h \
- /usr/include/sys/socket.h /usr/include/traditional.h /usr/include/asm/system.h \
- timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h arp.h
+ /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+ /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
+ /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
+ /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+ /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/socket.h \
+ /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \
+ /usr/include/asm/system.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \
+ eth.h tcp.h sock.h arp.h
dev.o : dev.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/types.h \
/usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/socket.h \
- /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/socket.h \
- /usr/include/traditional.h dev.h eth.h timer.h ip.h /usr/include/linux/sock_ioctl.h \
- tcp.h sock.h /usr/include/linux/errno.h arp.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/string.h /usr/include/linux/socket.h /usr/include/netinet/in.h \
+ /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h dev.h \
+ eth.h timer.h ip.h /usr/include/linux/sock_ioctl.h tcp.h sock.h /usr/include/linux/errno.h \
+ arp.h
eth.o : eth.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/types.h \
/usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/socket.h \
- /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/socket.h \
- /usr/include/traditional.h dev.h eth.h timer.h ip.h /usr/include/linux/sock_ioctl.h \
- tcp.h sock.h /usr/include/linux/errno.h arp.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/string.h /usr/include/linux/socket.h /usr/include/netinet/in.h \
+ /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h dev.h \
+ eth.h timer.h ip.h /usr/include/linux/sock_ioctl.h tcp.h sock.h /usr/include/linux/errno.h \
+ arp.h
icmp.o : icmp.c /usr/include/linux/types.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h \
- /usr/include/linux/socket.h /usr/include/netinet/in.h /usr/include/features.h \
- /usr/include/sys/socket.h /usr/include/traditional.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \
- eth.h tcp.h sock.h /usr/include/linux/errno.h /usr/include/linux/timer.h /usr/include/asm/system.h \
- /usr/include/asm/segment.h ../kern_sock.h icmp.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h /usr/include/linux/socket.h \
+ /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \
+ timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h /usr/include/linux/errno.h \
+ /usr/include/linux/timer.h /usr/include/asm/system.h /usr/include/asm/segment.h \
+ icmp.h
ip.o : ip.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/types.h \
/usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/socket.h \
- /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/socket.h \
- /usr/include/traditional.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \
- eth.h tcp.h sock.h /usr/include/linux/errno.h arp.h icmp.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/string.h /usr/include/linux/socket.h /usr/include/netinet/in.h \
+ /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h timer.h \
+ ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h /usr/include/linux/errno.h \
+ arp.h icmp.h
loopback.o : loopback.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
/usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \
- /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/ptrace.h \
- /usr/include/linux/string.h /usr/include/asm/segment.h /usr/include/asm/io.h \
- /usr/include/errno.h /usr/include/traditional.h /usr/include/linux/errno.h /usr/include/linux/fcntl.h \
- /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/socket.h \
- /usr/include/linux/socket.h dev.h eth.h timer.h ip.h /usr/include/linux/sock_ioctl.h \
- tcp.h sock.h arp.h ../kern_sock.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
+ /usr/include/asm/system.h /usr/include/linux/ptrace.h /usr/include/linux/string.h \
+ /usr/include/asm/segment.h /usr/include/asm/io.h /usr/include/errno.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/linux/errno.h /usr/include/linux/fcntl.h \
+ /usr/include/netinet/in.h /usr/include/sys/socket.h /usr/include/linux/socket.h \
+ dev.h eth.h timer.h ip.h /usr/include/linux/sock_ioctl.h tcp.h sock.h arp.h
pack_type.o : pack_type.c /usr/include/linux/stddef.h dev.h eth.h
packet.o : packet.c /usr/include/linux/types.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h \
- /usr/include/linux/socket.h /usr/include/netinet/in.h /usr/include/features.h \
- /usr/include/sys/socket.h /usr/include/traditional.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \
- eth.h tcp.h sock.h /usr/include/linux/errno.h /usr/include/linux/timer.h /usr/include/asm/system.h \
- /usr/include/asm/segment.h ../kern_sock.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h /usr/include/linux/socket.h \
+ /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \
+ timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h /usr/include/linux/errno.h \
+ /usr/include/linux/timer.h /usr/include/asm/system.h /usr/include/asm/segment.h \
+ ../kern_sock.h
protocols.o : protocols.c /usr/include/asm/segment.h /usr/include/asm/system.h \
/usr/include/linux/types.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \
- /usr/include/linux/socket.h /usr/include/netinet/in.h /usr/include/features.h \
- /usr/include/sys/socket.h /usr/include/traditional.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \
- eth.h tcp.h sock.h icmp.h
+ /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
+ /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+ /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/socket.h \
+ /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \
+ timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h icmp.h
raw.o : raw.c /usr/include/linux/types.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h \
- /usr/include/linux/socket.h /usr/include/netinet/in.h /usr/include/features.h \
- /usr/include/sys/socket.h /usr/include/traditional.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \
- eth.h tcp.h sock.h /usr/include/linux/errno.h /usr/include/linux/timer.h /usr/include/asm/system.h \
- /usr/include/asm/segment.h ../kern_sock.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h /usr/include/linux/socket.h \
+ /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \
+ timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h /usr/include/linux/errno.h \
+ /usr/include/linux/timer.h /usr/include/asm/system.h /usr/include/asm/segment.h \
+ ../kern_sock.h
sock.o : sock.c /usr/include/linux/errno.h /usr/include/linux/types.h /usr/include/linux/socket.h \
- /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/socket.h \
- /usr/include/traditional.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \
- /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
- /usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
- /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/timer.h \
- /usr/include/linux/string.h /usr/include/linux/sock_ioctl.h ../kern_sock.h timer.h \
- ip.h dev.h eth.h tcp.h udp.h sock.h /usr/include/asm/segment.h /usr/include/asm/system.h \
- /usr/include/linux/fcntl.h
+ /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \
+ /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
+ /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
+ /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
+ /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/timer.h /usr/include/linux/string.h /usr/include/linux/sock_ioctl.h \
+ ../kern_sock.h timer.h ip.h dev.h eth.h tcp.h udp.h sock.h /usr/include/asm/segment.h \
+ /usr/include/asm/system.h /usr/include/linux/fcntl.h
tcp.o : tcp.c /usr/include/linux/types.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \
- /usr/include/linux/socket.h /usr/include/netinet/in.h /usr/include/features.h \
- /usr/include/sys/socket.h /usr/include/traditional.h /usr/include/linux/fcntl.h \
- timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h icmp.h tcp.h sock.h \
- /usr/include/linux/errno.h /usr/include/linux/timer.h /usr/include/asm/system.h \
- /usr/include/asm/segment.h /usr/include/linux/termios.h ../kern_sock.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/socket.h \
+ /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \
+ /usr/include/linux/fcntl.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \
+ eth.h icmp.h tcp.h sock.h /usr/include/linux/errno.h /usr/include/linux/timer.h \
+ /usr/include/asm/system.h /usr/include/asm/segment.h /usr/include/linux/termios.h \
+ ../kern_sock.h
timer.o : timer.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/socket.h \
- /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/socket.h \
- /usr/include/traditional.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \
- /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
- /usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
- /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
- /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
- /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/timer.h \
- /usr/include/asm/system.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \
+ /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \
+ /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
+ /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
+ /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
+ /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/timer.h /usr/include/asm/system.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \
eth.h tcp.h sock.h arp.h ../kern_sock.h
udp.o : udp.c /usr/include/linux/types.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
- /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
- /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h \
- /usr/include/linux/socket.h /usr/include/netinet/in.h /usr/include/features.h \
- /usr/include/sys/socket.h /usr/include/traditional.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \
- eth.h tcp.h sock.h /usr/include/linux/errno.h /usr/include/linux/timer.h /usr/include/linux/termios.h \
- /usr/include/asm/system.h /usr/include/asm/segment.h ../kern_sock.h udp.h icmp.h
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
+ /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
+ /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h /usr/include/linux/socket.h \
+ /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \
+ timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h /usr/include/linux/errno.h \
+ /usr/include/linux/timer.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/asm/segment.h ../kern_sock.h udp.h icmp.h
we.o : we.c /usr/include/linux/config.h /usr/include/linux/config.dist.h /usr/include/linux/kernel.h \
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
- /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
- /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \
- /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
- /usr/include/linux/math_emu.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
- /usr/include/asm/system.h /usr/include/linux/ptrace.h /usr/include/linux/string.h \
- /usr/include/asm/segment.h /usr/include/asm/io.h /usr/include/errno.h /usr/include/traditional.h \
+ /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+ /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
+ /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
+ /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
+ /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
+ /usr/include/linux/ptrace.h /usr/include/linux/string.h /usr/include/asm/segment.h \
+ /usr/include/asm/io.h /usr/include/errno.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/linux/errno.h /usr/include/linux/fcntl.h /usr/include/netinet/in.h \
- /usr/include/features.h /usr/include/sys/socket.h /usr/include/linux/socket.h \
- dev.h eth.h timer.h ip.h /usr/include/linux/sock_ioctl.h tcp.h sock.h arp.h \
- wereg.h
+ /usr/include/sys/socket.h /usr/include/linux/socket.h dev.h eth.h timer.h ip.h \
+ /usr/include/linux/sock_ioctl.h tcp.h sock.h arp.h wereg.h
diff --git a/net/tcp/Space.c b/net/tcp/Space.c
index f76483a..b6684ed 100644
--- a/net/tcp/Space.c
+++ b/net/tcp/Space.c
@@ -1,8 +1,11 @@
/* Space.c */
/* Holds initial configuration information for devices. */
-/* $Id: Space.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: Space.c,v 0.8.4.3 1992/11/15 14:55:30 bir7 Exp $ */
/* $Log: Space.c,v $
+ * Revision 0.8.4.3 1992/11/15 14:55:30 bir7
+ * Removed ctrl-h so diff no longer thinks it's a binary file.
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
diff --git a/net/tcp/arp.c b/net/tcp/arp.c
index bca4c88..c9f33fa 100644
--- a/net/tcp/arp.c
+++ b/net/tcp/arp.c
@@ -19,8 +19,12 @@
The Author may be reached as bir7@leland.stanford.edu or
C/O Department of Mathematics; Stanford University; Stanford, CA 94305
*/
-/* $Id: arp.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: arp.c,v 0.8.4.3 1992/11/15 14:55:30 bir7 Exp $ */
/* $Log: arp.c,v $
+ * Revision 0.8.4.3 1992/11/15 14:55:30 bir7
+ * Put more cli/sti pairs in send_q and another sanity check
+ * in arp_queue.
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
@@ -28,7 +32,7 @@
* version change only.
*
* Revision 0.8.3.3 1992/11/10 00:14:47 bir7
- * Changed malloc to kmalloc and added $iId$
+ * Changed malloc to kmalloc and added Id and Log
*
*/
@@ -55,19 +59,22 @@
#endif
static struct arp_table *arp_table[ARP_TABLE_SIZE] ={NULL, };
-static struct sk_buff *arp_q=NULL;
+struct sk_buff *arp_q=NULL;
/* this will try to retransmit everything on the queue. */
static void
send_arp_q(void)
{
struct sk_buff *skb;
+ cli();
if (arp_q == NULL) return;
skb = arp_q;
do {
+ sti();
if (!skb->dev->rebuild_header (skb+1, skb->dev))
{
+ cli();
if (skb->next == skb)
{
arp_q = NULL;
@@ -81,13 +88,16 @@ send_arp_q(void)
skb->next = NULL;
skb->prev = NULL;
skb->arp = 1;
+ sti();
skb->dev->queue_xmit (skb, skb->dev, 0);
+ cli();
if (arp_q == NULL) break;
skb = arp_q;
continue;
}
skb=skb->next;
} while (skb != arp_q);
+ sti();
}
@@ -98,6 +108,11 @@ print_arp(struct arp *arp)
unsigned long *lptr;
unsigned char *ptr;
PRINTK ("arp: \n");
+ if (arp == NULL)
+ {
+ PRINTK ("(null)\n");
+ return;
+ }
PRINTK (" hrd = %d\n",net16(arp->hrd));
PRINTK (" pro = %d\n",net16(arp->pro));
PRINTK (" hlen = %d plen = %d\n",arp->hlen, arp->plen);
@@ -440,15 +455,15 @@ arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
}
}
- /* if we didn't find an entry, we will try to
- send an arp packet. */
- if (apt == NULL || after (timer_seq, apt->last_used+ARP_RES_TIME))
- arp_snd(paddr,dev,saddr);
-
- /* this assume haddr are atleast 4 bytes.
+ /* this assume haddr are at least 4 bytes.
If this isn't true we can use a lookup
table, one for every dev. */
*(unsigned long *)haddr = paddr;
+
+ /* if we didn't find an entry, we will try to
+ send an arp packet. */
+ arp_snd(paddr,dev,saddr);
+
return (1);
}
@@ -476,7 +491,13 @@ arp_add_broad (unsigned long addr, struct device *dev)
void
arp_queue(struct sk_buff *skb)
{
- cli();
+ cli();
+ if (skb->next != NULL)
+ {
+ sti();
+ printk ("arp.c: arp_queue skb already on queue. \n");
+ return;
+ }
if (arp_q == NULL)
{
arp_q = skb;
diff --git a/net/tcp/arp.h b/net/tcp/arp.h
index 75c9932..038f695 100644
--- a/net/tcp/arp.h
+++ b/net/tcp/arp.h
@@ -19,13 +19,19 @@
The Author may be reached as bir7@leland.stanford.edu or
C/O Department of Mathematics; Stanford University; Stanford, CA 94305
*/
-/* $Id: arp.h,v 0.8.4.1 1992/11/10 00:17:18 bir7 Exp $ */
+/* $Id: arp.h,v 0.8.4.2 1992/11/15 14:55:30 bir7 Exp $ */
/* $Log: arp.h,v $
+ * Revision 0.8.4.2 1992/11/15 14:55:30 bir7
+ * make arp_q global so sock.c can mess with it.
+ *
* Revision 0.8.4.1 1992/11/10 00:17:18 bir7
* version change only.
*
* Revision 0.8.3.2 1992/11/10 00:14:47 bir7
* Changed malloc to kmalloc and added $iId$ and $Log: arp.h,v $
+ * Revision 0.8.4.2 1992/11/15 14:55:30 bir7
+ * make arp_q global so sock.c can mess with it.
+ *
* Revision 0.8.4.1 1992/11/10 00:17:18 bir7
* version change only.
*.
@@ -53,7 +59,7 @@ struct arp_table
unsigned char hard[MAX_ADDR_LEN];
};
-
+struct sk_buff *arp_q;
int arp_rcv(struct sk_buff *, struct device *, struct packet_type *);
void arp_snd (unsigned long, struct device *, unsigned long);
diff --git a/net/tcp/dev.c b/net/tcp/dev.c
index 9cac6d7..176fdc7 100644
--- a/net/tcp/dev.c
+++ b/net/tcp/dev.c
@@ -19,8 +19,14 @@
The Author may be reached as bir7@leland.stanford.edu or
C/O Department of Mathematics; Stanford University; Stanford, CA 94305
*/
-/* $Id: dev.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: dev.c,v 0.8.4.4 1992/11/18 15:38:03 bir7 Exp $ */
/* $Log: dev.c,v $
+ * Revision 0.8.4.4 1992/11/18 15:38:03 bir7
+ * Fixed bug in copying packets and changed some printk's
+ *
+ * Revision 0.8.4.3 1992/11/15 14:55:30 bir7
+ * More sanity checks.
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
@@ -131,9 +137,15 @@ void
dev_queue_xmit (struct sk_buff *skb, struct device *dev, int pri)
{
struct sk_buff *skb2;
- PRINTK ("eth_queue_xmit (skb=%X, dev=%X, pri = %d)\n", skb, dev, pri);
- skb->dev = dev;
+ PRINTK ("dev_queue_xmit (skb=%X, dev=%X, pri = %d)\n", skb, dev, pri);
+ if (dev == NULL)
+ {
+ printk ("dev.c: dev_queue_xmit: dev = NULL\n");
+ return;
+ }
+
+ skb->dev = dev;
if (skb->next != NULL)
{
/* make sure we haven't missed an interrupt. */
@@ -152,12 +164,8 @@ dev_queue_xmit (struct sk_buff *skb, struct device *dev, int pri)
return;
}
- /* used to say it is not currently on a send list. */
- skb->next = NULL;
-
-
/* put skb into a bidirectional circular linked list. */
- PRINTK ("eth_queue dev->buffs[%d]=%X\n",pri, dev->buffs[pri]);
+ PRINTK ("dev_queue_xmit dev->buffs[%d]=%X\n",pri, dev->buffs[pri]);
/* interrupts should already be cleared by hard_start_xmit. */
cli();
if (dev->buffs[pri] == NULL)
@@ -313,6 +321,10 @@ dev_rint(unsigned char *buff, unsigned long len, int flags,
if (skb2 == NULL) continue;
memcpy (skb2, skb, skb->mem_len);
skb2->mem_addr = skb2;
+ skb2->h.raw = (void *)((unsigned long)skb2
+ + (unsigned long)skb->h.raw
+ - (unsigned long)skb);
+
}
else
{
@@ -366,15 +378,15 @@ dev_tint(unsigned char *buff, struct device *dev)
}
skb->next = NULL;
skb->prev = NULL;
- sti();
tmp = skb->len;
if (!skb->arp)
{
if (dev->rebuild_header (skb+1, dev))
{
- skb->dev = dev;
- arp_queue (skb);
- continue;
+ skb->dev = dev;
+ sti();
+ arp_queue (skb);
+ continue;
}
}
@@ -394,7 +406,7 @@ dev_tint(unsigned char *buff, struct device *dev)
{
printk ("**** bug len bigger than mtu. \n");
}
-
+ sti();
if (skb->free)
{
kfree_skb(skb, FREE_WRITE);
diff --git a/net/tcp/icmp.c b/net/tcp/icmp.c
index a655877..0ce368d 100644
--- a/net/tcp/icmp.c
+++ b/net/tcp/icmp.c
@@ -23,8 +23,11 @@
The author of this file may be reached at rth@sparta.com or Sparta, Inc.
7926 Jones Branch Dr. Suite 900, McLean Va 22102.
*/
-/* $Id: icmp.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: icmp.c,v 0.8.4.3 1992/11/18 15:38:03 bir7 Exp $ */
/* $Log: icmp.c,v $
+ * Revision 0.8.4.3 1992/11/18 15:38:03 bir7
+ * Fixed some printk's.
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
@@ -53,8 +56,17 @@
#include <linux/timer.h>
#include <asm/system.h>
#include <asm/segment.h>
-#include "../kern_sock.h" /* for PRINTK */
#include "icmp.h"
+#ifdef PRINTK
+#undef PRINTK
+#endif
+
+#undef ICMP_DEBUG
+#ifdef ICMP_DEBUG
+#define PRINTK printk
+#else
+#define PRINTK dummy_routine
+#endif
#define min(a,b) ((a)<(b)?(a):(b))
@@ -168,7 +180,7 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
if( ip_compute_csum( (unsigned char *)icmph, len ) )
{
/* Failed checksum! */
- PRINTK("\nICMP ECHO failed checksum!");
+ PRINTK("ICMP ECHO failed checksum!\n");
skb1->sk = NULL;
kfree_skb (skb1, FREE_READ);
return (0);
@@ -251,7 +263,7 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
if (offset < 0)
{
/* Problems building header */
- PRINTK("\nCould not build IP Header for ICMP ECHO Response");
+ PRINTK("Could not build IP Header for ICMP ECHO Response\n");
kfree_s (skb->mem_addr, skb->mem_len);
skb1->sk = NULL;
kfree_skb (skb1, FREE_READ);
@@ -281,7 +293,7 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
return( 0 );
default:
- PRINTK("\nUnsupported ICMP type = x%x", icmph->type );
+ PRINTK("Unsupported ICMP type = x%x\n", icmph->type );
skb1->sk = NULL;
kfree_skb (skb1, FREE_READ);
return( 0 ); /* just toss the packet */
diff --git a/net/tcp/icmp.h b/net/tcp/icmp.h
index e2c0d65..3188955 100644
--- a/net/tcp/icmp.h
+++ b/net/tcp/icmp.h
@@ -1,7 +1,10 @@
/* Internet Control Message Protocol (ICMP) header file */
-/* $Id: icmp.h,v 0.8.4.1 1992/11/10 00:17:18 bir7 Exp $ */
+/* $Id: icmp.h,v 0.8.4.2 1992/11/15 14:55:30 bir7 Exp $ */
/* $Log: icmp.h,v $
+ * Revision 0.8.4.2 1992/11/15 14:55:30 bir7
+ * Remove ctrl-h so diff no longer thinks it's a binary file.
+ *
* Revision 0.8.4.1 1992/11/10 00:17:18 bir7
* version change only.
*
diff --git a/net/tcp/ip.c b/net/tcp/ip.c
index 52b9ae3..368b442 100644
--- a/net/tcp/ip.c
+++ b/net/tcp/ip.c
@@ -19,8 +19,14 @@
The Author may be reached as bir7@leland.stanford.edu or
C/O Department of Mathematics; Stanford University; Stanford, CA 94305
*/
-/* $Id: ip.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: ip.c,v 0.8.4.4 1992/11/18 15:38:03 bir7 Exp $ */
/* $Log: ip.c,v $
+ * Revision 0.8.4.4 1992/11/18 15:38:03 bir7
+ * Fixed bug in copying packet and checking packet type.
+ *
+ * Revision 0.8.4.3 1992/11/17 14:19:47 bir7
+ * *** empty log message ***
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
@@ -197,8 +203,8 @@ print_rt(struct rtable *rt)
void
print_ipprot (struct ip_protocol *ipprot)
{
- PRINTK ("handler = %X, protocol = %d\n",
- ipprot->handler, ipprot->protocol);
+ PRINTK ("handler = %X, protocol = %d, copy=%d \n",
+ ipprot->handler, ipprot->protocol, ipprot->copy);
}
/* This assumes that address are all in net order. */
@@ -301,7 +307,7 @@ ip_set_dev (struct ip_config *u_ipc)
if (ip_ads >= MAX_IP_ADDRES) return (-EINVAL);
- verify_area (u_ipc, sizeof (ipc));
+/* verify_area (u_ipc, sizeof (ipc));*/
memcpy_fromfs(&ipc, u_ipc, sizeof (ipc));
ipc.name[MAX_IP_NAME-1] = 0;
dev = get_dev (ipc.name);
@@ -368,6 +374,7 @@ ip_route_check (unsigned long daddr)
{
}
+#if 0
/* this routine puts the options at the end of an ip header. */
static int
build_options (struct ip_header *iph, struct options *opt)
@@ -378,6 +385,7 @@ build_options (struct ip_header *iph, struct options *opt)
*ptr = 0;
return (4);
}
+#endif
/* This routine builds the appropriate hardware/ip headers for
the routine. It assumes that if *prot != NULL then the
@@ -731,6 +739,7 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
for (ipprot = ip_protos[hash]; ipprot != NULL; ipprot=ipprot->next)
{
struct sk_buff *skb2;
+ if (ipprot->protocol != iph->protocol) continue;
PRINTK ("Using protocol = %X:\n", ipprot);
print_ipprot (ipprot);
/* pass it off to everyone who wants it. */
@@ -741,10 +750,13 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
if (ipprot->copy)
{
- skb2 = kmalloc (skb->mem_len, GFP_KERNEL);
+ skb2 = kmalloc (skb->mem_len, GFP_ATOMIC);
if (skb2 == NULL) continue;
memcpy (skb2, skb, skb->mem_len);
skb2->mem_addr = skb2;
+ skb2->h.raw = (void *)((unsigned long)skb2
+ + (unsigned long)skb->h.raw
+ - (unsigned long)skb);
}
else
{
@@ -817,10 +829,14 @@ ip_queue_xmit (volatile struct sock *sk, struct device *dev,
}
if (dev->up)
{
- if (sk)
- dev->queue_xmit(skb, dev, sk->priority);
+ if (sk != NULL)
+ {
+ dev->queue_xmit(skb, dev, sk->priority);
+ }
else
- dev->queue_xmit (skb, dev, SOPRI_NORMAL);
+ {
+ dev->queue_xmit (skb, dev, SOPRI_NORMAL);
+ }
}
else
{
diff --git a/net/tcp/loopback.c b/net/tcp/loopback.c
index fb6ff32..e41d7e8 100644
--- a/net/tcp/loopback.c
+++ b/net/tcp/loopback.c
@@ -19,8 +19,11 @@
The Author may be reached as bir7@leland.stanford.edu or
C/O Department of Mathematics; Stanford University; Stanford, CA 94305
*/
-/* $Id: loopback.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: loopback.c,v 0.8.4.3 1992/11/18 15:38:03 bir7 Exp $ */
/* $Log: loopback.c,v $
+ * Revision 0.8.4.3 1992/11/18 15:38:03 bir7
+ * Fixed bug in start_xmit.
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
@@ -54,9 +57,15 @@
#include "sock.h"
#include "arp.h"
-#include "../kern_sock.h" /* for PRINTK */
-
+#ifdef PRINTK
+#undef PRINTK
+#endif
+#ifdef LOOPBACK_DEBUG
+#define PRINTK printk
+#else
+#define PRINTK dummy_routine
+#endif
static int
loopback_xmit(struct sk_buff *skb, struct device *dev)
@@ -77,27 +86,36 @@ loopback_xmit(struct sk_buff *skb, struct device *dev)
}
inuse = 1;
sti();
- tmp = NULL;
- done = dev_rint ((unsigned char *)(skb+1), skb->len, 0, dev);
+
+ done = -1;
+ while (done == -1)
+ done = dev_rint ((unsigned char *)(skb+1), skb->len, 0, dev);
if (skb->free)
kfree_skb (skb, FREE_WRITE);
+ tmp = NULL;
+ i = 0;
while (done != 1)
{
if (done != -1 && (i = dev_tint (buff,dev)) != 0)
{
/* print out the buffer. */
- PRINTK ("ethernet xmit: \n");
+ PRINTK ("loopback xmit: \n");
eth = (struct enet_header *)buff;
print_eth (eth);
tmp = buff;
done = dev_rint (buff, i, 0, dev);
- if (done != -1) tmp = NULL;
+ if (done != -1)
+ {
+ tmp = NULL;
+ i = 0;
+ }
}
else
{
- done = dev_rint (tmp, 0, 0, dev);
+ if (i == 0) tmp = NULL;
+ done = dev_rint (tmp, i, 0, dev);
}
}
diff --git a/net/tcp/packet.c b/net/tcp/packet.c
index a644e61..d594ed3 100644
--- a/net/tcp/packet.c
+++ b/net/tcp/packet.c
@@ -19,8 +19,11 @@
The Author may be reached as bir7@leland.stanford.edu or
C/O Department of Mathematics; Stanford University; Stanford, CA 94305
*/
-/* $Id: packet.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: packet.c,v 0.8.4.3 1992/11/17 14:19:47 bir7 Exp $ */
/* $Log: packet.c,v $
+ * Revision 0.8.4.3 1992/11/17 14:19:47 bir7
+ * *** empty log message ***
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
@@ -132,7 +135,7 @@ packet_sendto (volatile struct sock *sk, unsigned char *from, int len,
{
if (addr_len < sizeof (saddr))
return (-EINVAL);
- verify_area (usin, sizeof (saddr));
+/* verify_area (usin, sizeof (saddr));*/
memcpy_fromfs (&saddr, usin, sizeof(saddr));
}
else
@@ -158,7 +161,7 @@ packet_sendto (volatile struct sock *sk, unsigned char *from, int len,
sk->prot->wfree (sk, skb->mem_addr, skb->mem_len);
return (-ENXIO);
}
- verify_area (from, len);
+/* verify_area (from, len);*/
memcpy_fromfs (skb+1, from, len);
skb->len = len;
skb->next = NULL;
diff --git a/net/tcp/protocols.c b/net/tcp/protocols.c
index 231e251..fa61e7b 100644
--- a/net/tcp/protocols.c
+++ b/net/tcp/protocols.c
@@ -3,8 +3,11 @@
/* these headers are overkill, but until I clean up the socket header
files, this is the best way. */
-/* $Id: protocols.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: protocols.c,v 0.8.4.3 1992/11/15 14:55:30 bir7 Exp $ */
/* $Log: protocols.c,v $
+ * Revision 0.8.4.3 1992/11/15 14:55:30 bir7
+ * Remove ctrl-h so diff no longer thinks it's a binary file.
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
diff --git a/net/tcp/raw.c b/net/tcp/raw.c
index dd1f1ef..abfbeae 100644
--- a/net/tcp/raw.c
+++ b/net/tcp/raw.c
@@ -19,8 +19,18 @@
The Author may be reached as bir7@leland.stanford.edu or
C/O Department of Mathematics; Stanford University; Stanford, CA 94305
*/
-/* $Id: raw.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: raw.c,v 0.8.4.6 1992/11/18 15:38:03 bir7 Exp $ */
/* $Log: raw.c,v $
+ * Revision 0.8.4.6 1992/11/18 15:38:03 bir7
+ * Works now.
+ *
+ *
+ * Revision 0.8.4.4 1992/11/17 09:27:07 bir7
+ * Fixed error in header building.
+ *
+ * Revision 0.8.4.3 1992/11/16 16:13:40 bir7
+ * Added debuggin information.
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
@@ -48,6 +58,18 @@
#include <linux/kernel.h>
#include "../kern_sock.h" /* for PRINTK */
+
+#ifdef PRINTK
+#undef PRINTK
+#endif
+
+#undef RAW_DEBUG
+#ifdef RAW_DEBUG
+#define PRINTK printk
+#else
+#define PRINTK dummy_routine
+#endif
+
extern struct proto raw_prot;
static unsigned long
@@ -65,16 +87,34 @@ raw_rcv (struct sk_buff *skb, struct device *dev, struct options *opt,
int redo, struct ip_protocol *protocol)
{
- volatile struct sock *sk;
+ volatile struct sock *sk;
+
+ PRINTK ("raw_rcv (skb=%X, dev=%X, opt=%X, daddr=%X,\n"
+ " len=%d, saddr=%X, redo=%d, protocol=%X)\n",
+ skb, dev, opt, daddr, len, saddr, redo, protocol);
+ if (skb == NULL) return (0);
+ if (protocol == NULL)
+ {
+ kfree_skb (skb, FREE_READ);
+ return (0);
+ }
sk = protocol->data;
-
+ if (sk == NULL)
+ {
+ kfree_skb (skb, FREE_READ);
+ return (0);
+ }
+
/* now we need to copy this into memory. */
+ skb->sk = sk;
+ skb->len = len;
+ skb->dev = dev;
+ skb->saddr = daddr;
+ skb->daddr = saddr;
+
if (!redo )
{
- skb->dev = dev;
- skb->saddr = daddr;
- skb->daddr = saddr;
/* now see if we are in use. */
cli();
if (sk->inuse)
@@ -100,9 +140,6 @@ raw_rcv (struct sk_buff *skb, struct device *dev, struct options *opt,
sti();
}
- skb->sk = sk;
- skb->len = len;
-
/* charge it too the socket. */
if (sk->rmem_alloc + skb->mem_len >= SK_RMEM_MAX)
{
@@ -127,31 +164,11 @@ raw_rcv (struct sk_buff *skb, struct device *dev, struct options *opt,
skb->prev->next = skb;
skb->next->prev = skb;
}
- skb->len = len;
wake_up (sk->sleep);
release_sock (sk);
return (0);
}
-static int
-raw_loopback (volatile struct sock *sk, int prot, char *from, int len,
- unsigned long daddr)
-{
- /* just pretend it just came in. */
- struct sk_buff *skb;
- int err;
- skb = kmalloc (len+sizeof (*skb), GFP_KERNEL);
- if (skb == NULL) return (-ENOMEM);
-
- skb->mem_addr = skb;
- skb->mem_len = len + sizeof (*skb);
- skb->h.raw = (unsigned char *)(skb+1);
- verify_area (from, len);
- memcpy_fromfs (skb+1, from, len);
- err = raw_rcv (skb, NULL, NULL, daddr, len, sk->saddr, prot, 0);
- return (err);
-}
-
/* this will do terrible things if len + ipheader + devheader > dev->mtu */
static int
raw_sendto (volatile struct sock *sk, unsigned char *from, int len,
@@ -163,6 +180,10 @@ raw_sendto (volatile struct sock *sk, unsigned char *from, int len,
struct sockaddr_in sin;
int tmp;
+ PRINTK ("raw_sendto (sk=%X, from=%X, len=%d, noblock=%d, flags=%X,\n"
+ " usin=%X, addr_len = %d)\n", sk, from, len, noblock,
+ flags, usin, addr_len);
+
/* check the flags. */
if (flags) return (-EINVAL);
if (len < 0) return (-EINVAL);
@@ -172,7 +193,7 @@ raw_sendto (volatile struct sock *sk, unsigned char *from, int len,
{
if (addr_len < sizeof (sin))
return (-EINVAL);
- verify_area (usin, sizeof (sin));
+/* verify_area (usin, sizeof (sin));*/
memcpy_fromfs (&sin, usin, sizeof(sin));
if (sin.sin_family &&
sin.sin_family != AF_INET)
@@ -188,43 +209,59 @@ raw_sendto (volatile struct sock *sk, unsigned char *from, int len,
}
if (sin.sin_port == 0) sin.sin_port = sk->protocol;
- if ((sin.sin_addr.s_addr & 0xff000000) == 0)
- {
- int err;
- err = raw_loopback (sk, sin.sin_port, from, len,
- sin.sin_addr.s_addr);
- if (err < 0) return (err);
- }
-
sk->inuse = 1;
- skb = sk->prot->wmalloc (sk, len+sizeof (*skb) + sk->prot->max_header, 0,
- GFP_KERNEL);
- /* this shouldn't happen, but it could. */
- if (skb == NULL)
+ skb = NULL;
+ while (skb == NULL)
{
- PRINTK ("raw_sendto: write buffer full?\n");
- print_sk (sk);
- release_sock (sk);
- return (-EAGAIN);
+ skb = sk->prot->wmalloc (sk, len+sizeof (*skb) + sk->prot->max_header,
+ 0, GFP_KERNEL);
+ /* this shouldn't happen, but it could. */
+ /* need to change this to sleep. */
+ if (skb == NULL)
+ {
+ int tmp;
+ PRINTK ("raw_sendto: write buffer full?\n");
+ print_sk (sk);
+ if (noblock) return (-EAGAIN);
+ tmp = sk->wmem_alloc;
+ release_sock (sk);
+ cli();
+ if (tmp <= sk->wmem_alloc)
+ {
+ interruptible_sleep_on (sk->sleep);
+ if (current->signal & ~current->blocked)
+ {
+ sti();
+ return (-ERESTARTSYS);
+ }
+ }
+ sk->inuse = 1;
+ sti();
+ }
}
skb->mem_addr = skb;
skb->mem_len = len + sizeof (*skb) +sk->prot->max_header;
skb->sk = sk;
+
skb->free = 1; /* these two should be unecessary. */
skb->arp = 0;
+
tmp = sk->prot->build_header (skb, sk->saddr,
sin.sin_addr.s_addr, &dev,
sk->protocol, sk->opt, skb->mem_len);
if (tmp < 0)
{
+ PRINTK ("raw_sendto: error building ip header.\n");
sk->prot->wfree (sk, skb->mem_addr, skb->mem_len);
release_sock (sk);
return (tmp);
}
- verify_area (from, len);
- memcpy_fromfs (skb+1, from, len);
+
+/* verify_area (from, len);*/
+ memcpy_fromfs ((unsigned char *)(skb+1)+tmp, from, len);
skb->len = tmp + len;
sk->prot->queue_xmit (sk, dev, skb, 1);
+ release_sock (sk);
return (len);
}
@@ -240,8 +277,12 @@ raw_close (volatile struct sock *sk, int timeout)
{
sk->inuse = 1;
sk->state = TCP_CLOSE;
- delete_ip_protocol ((struct ip_protocol *)sk->pair);
+ PRINTK ("raw_close: deleting ip_protocol %d\n",
+ ((struct ip_protocol *)sk->pair)->protocol);
+ if (delete_ip_protocol ((struct ip_protocol *)sk->pair) < 0)
+ PRINTK ("raw_close: delete_ip_protocol failed. \n");
kfree_s ((void *)sk->pair, sizeof (struct ip_protocol));
+ sk->pair = NULL;
release_sock (sk);
}
@@ -260,6 +301,8 @@ raw_init (volatile struct sock *sk)
/* we need to remember this somewhere. */
sk->pair = (volatile struct sock *)p;
+ PRINTK ("raw init added protocol %d\n", sk->protocol);
+
return (0);
}
@@ -273,6 +316,11 @@ raw_recvfrom (volatile struct sock *sk, unsigned char *to, int len,
return it, otherwise we block. */
int copied=0;
struct sk_buff *skb;
+
+ PRINTK ("raw_recvfrom (sk=%X, to=%X, len=%d, noblock=%d, flags=%X,\n"
+ " sin=%X, addr_len=%X)\n", sk, to, len, noblock,
+ flags, sin, addr_len);
+
if (len == 0) return (0);
if (len < 0) return (-EINVAL);
if (addr_len)
@@ -286,6 +334,7 @@ raw_recvfrom (volatile struct sock *sk, unsigned char *to, int len,
if (noblock)
{
release_sock (sk);
+ if (copied) return (copied);
return (-EAGAIN);
}
release_sock (sk);
@@ -295,9 +344,11 @@ raw_recvfrom (volatile struct sock *sk, unsigned char *to, int len,
interruptible_sleep_on (sk->sleep);
if (current->signal & ~current->blocked)
{
- return (-ERESTARTSYS);
+ sti();
+ return (-ERESTARTSYS);
}
}
+ sk->inuse = 1;
sti();
}
skb = sk->rqueue;
diff --git a/net/tcp/sock.c b/net/tcp/sock.c
index 7b3ba46..7f4ad2f 100644
--- a/net/tcp/sock.c
+++ b/net/tcp/sock.c
@@ -19,8 +19,22 @@
The Author may be reached as bir7@leland.stanford.edu or
C/O Department of Mathematics; Stanford University; Stanford, CA 94305
*/
-/* $Id: sock.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: sock.c,v 0.8.4.6 1992/11/18 15:38:03 bir7 Exp $ */
/* $Log: sock.c,v $
+ * Revision 0.8.4.6 1992/11/18 15:38:03 bir7
+ * Fixed minor problem in setsockopt.
+ *
+ * Revision 0.8.4.5 1992/11/17 14:19:47 bir7
+ * *** empty log message ***
+ *
+ * Revision 0.8.4.4 1992/11/16 16:13:40 bir7
+ * Fixed some error returns and undid one of the accept changes.
+ *
+ * Revision 0.8.4.3 1992/11/15 14:55:30 bir7
+ * Added more checking for a packet being on a queue before it's
+ * dropped when a socket is closed. Added check to see if it's
+ * on the arp_q also.
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
@@ -421,6 +435,7 @@ destroy_sock(volatile struct sock *sk)
do {
struct sk_buff *skb2;
skb2=skb->next;
+
/* this will take care of closing sockets that were
listening and didn't accept everything. */
@@ -440,29 +455,56 @@ destroy_sock(volatile struct sock *sk)
for (skb = sk->send_head; skb != NULL; )
{
struct sk_buff *skb2;
- /* we need to remove skb from the transmit queue. */
+ /* we need to remove skb from the transmit queue, or
+ maybe the arp queue */
cli();
/* see if it's in a transmit queue. */
if (skb->next != NULL)
{
+ extern struct sk_buff *arp_q;
+ int i;
if (skb->next != skb)
{
skb->next->prev = skb->prev;
skb->prev->next = skb->next;
+
+ if (skb == arp_q)
+ {
+ arp_q = skb->next;
+ }
+ else
+ {
+ for (i = 0; i < DEV_NUMBUFFS; i++)
+ {
+ if (skb->dev && skb->dev->buffs[i] == skb)
+ {
+ skb->dev->buffs[i]= skb->next;
+ break;
+ }
+ }
+ }
}
else
{
- int i;
- for (i = 0; i < DEV_NUMBUFFS; i++)
- {
- if (skb->dev && skb->dev->buffs[i] == skb)
- {
- skb->dev->buffs[i]= NULL;
- break;
- }
- }
+
+ if (skb == arp_q)
+ {
+ arp_q = NULL;
+ }
+ else
+ {
+ for (i = 0; i < DEV_NUMBUFFS; i++)
+ {
+ if (skb->dev && skb->dev->buffs[i] == skb)
+ {
+ skb->dev->buffs[i]= NULL;
+ break;
+ }
+ }
+ }
}
}
+ skb->dev = NULL;
sti();
skb2=skb->link3;
kfree_skb(skb, FREE_WRITE);
@@ -494,7 +536,7 @@ destroy_sock(volatile struct sock *sk)
if (sk->pair)
{
sk->pair->dead = 1;
- sk->pair->prot->close (sk, 0);
+ sk->pair->prot->close (sk->pair, 0);
sk->pair = NULL;
}
@@ -559,7 +601,9 @@ ip_proto_setsockopt(struct socket *sock, int level, int optname,
printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
return (0);
}
- verify_area (optval, sizeof (int));
+ if (optval == NULL) return (-EINVAL);
+
+/* verify_area (optval, sizeof (int));*/
val = get_fs_long ((unsigned long *)optval);
switch (optname)
{
@@ -992,7 +1036,7 @@ ip_proto_bind (struct socket *sock, struct sockaddr *uaddr,
if (sk->state != TCP_CLOSE) return (-EIO);
if (sk->num != 0) return (-EINVAL);
- verify_area (uaddr, addr_len);
+/* verify_area (uaddr, addr_len);*/
memcpy_fromfs (&addr, uaddr, min (sizeof (addr), addr_len));
if (addr.sin_family && addr.sin_family != AF_INET)
return (-EINVAL); /* this needs to be changed. */
@@ -1074,7 +1118,7 @@ ip_proto_connect (struct socket *sock, struct sockaddr * uaddr,
sock->state = SS_CONNECTED;
- if (flags & O_NONBLOCK) return (0);
+ if (flags & O_NONBLOCK) return (-EINPROGRESS);
cli(); /* avoid the race condition */
@@ -1172,11 +1216,9 @@ ip_proto_getname(struct socket *sock, struct sockaddr *uaddr,
struct sockaddr_in sin;
volatile struct sock *sk;
int len;
- verify_area(uaddr_len, sizeof (len));
len = get_fs_long(uaddr_len);
/* check this error. */
if (len < sizeof (sin)) return (-EINVAL);
- verify_area (uaddr, len);
sin.sin_family=AF_INET;
sk = sock->data;
if (sk == NULL)
@@ -1197,7 +1239,9 @@ ip_proto_getname(struct socket *sock, struct sockaddr *uaddr,
sin.sin_addr.s_addr = sk->saddr;
}
len = sizeof (sin);
+ verify_area (uaddr, len);
memcpy_tofs(uaddr, &sin, sizeof (sin));
+ verify_area(uaddr_len, sizeof (len));
put_fs_long (len, uaddr_len);
return (0);
}
@@ -1213,7 +1257,9 @@ ip_proto_read (struct socket *sock, char *ubuf, int size, int noblock)
return (0);
}
if (sk->shutdown & RCV_SHUTDOWN)
- return (-EIO);
+ {
+ return (0); /* this seems to be what sunos does. */
+ }
/* we may need to bind the socket. */
if (sk->num == 0)
@@ -1239,7 +1285,10 @@ ip_proto_recv (struct socket *sock, void *ubuf, int size, int noblock,
return (0);
}
if (sk->shutdown & RCV_SHUTDOWN)
- return (-EIO);
+ {
+ return (0);
+ }
+
/* we may need to bind the socket. */
if (sk->num == 0)
@@ -1264,7 +1313,11 @@ ip_proto_write (struct socket *sock, char *ubuf, int size, int noblock)
return (0);
}
if (sk->shutdown & SEND_SHUTDOWN)
- return (-EIO);
+ {
+ send_sig (SIGPIPE, current, 1);
+ return (-EPIPE);
+ }
+
/* we may need to bind the socket. */
if (sk->num == 0)
@@ -1291,7 +1344,11 @@ ip_proto_send (struct socket *sock, void *ubuf, int size, int noblock,
return (0);
}
if (sk->shutdown & SEND_SHUTDOWN)
- return (-EIO);
+ {
+ send_sig (SIGPIPE, current, 1);
+ return (-EPIPE);
+ }
+
/* we may need to bind the socket. */
if (sk->num == 0)
@@ -1318,7 +1375,11 @@ ip_proto_sendto (struct socket *sock, void *ubuf, int size, int noblock,
return (0);
}
if (sk->shutdown & SEND_SHUTDOWN)
- return (-EIO);
+ {
+ send_sig (SIGPIPE, current, 1);
+ return (-EPIPE);
+ }
+
if (sk->prot->sendto == NULL) return (-EOPNOTSUPP);
/* we may need to bind the socket. */
@@ -1346,7 +1407,10 @@ ip_proto_recvfrom (struct socket *sock, void *ubuf, int size, int noblock,
return (0);
}
if (sk->shutdown & RCV_SHUTDOWN)
- return (-EIO);
+ {
+ return (0);
+ }
+
if (sk->prot->recvfrom == NULL) return (-EOPNOTSUPP);
/* we may need to bind the socket. */
diff --git a/net/tcp/tcp.c b/net/tcp/tcp.c
index 05264cb..71b7e80 100644
--- a/net/tcp/tcp.c
+++ b/net/tcp/tcp.c
@@ -19,8 +19,21 @@
The Author may be reached as bir7@leland.stanford.edu or
C/O Department of Mathematics; Stanford University; Stanford, CA 94305
*/
-/* $Id: tcp.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: tcp.c,v 0.8.4.6 1992/11/18 15:38:03 bir7 Exp $ */
/* $Log: tcp.c,v $
+ * Revision 0.8.4.6 1992/11/18 15:38:03 bir7
+ * fixed minor problem in waiting for memory.
+ *
+ * Revision 0.8.4.5 1992/11/17 14:19:47 bir7
+ * *** empty log message ***
+ *
+ * Revision 0.8.4.4 1992/11/16 16:13:40 bir7
+ * Fixed some error returns and undid one of the accept changes.
+ *
+ * Revision 0.8.4.3 1992/11/15 14:55:30 bir7
+ * Fixed problem with accept. It was charging the memory for the initial
+ * sock buff to one socket, but freeing it from another.
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
@@ -52,6 +65,18 @@
#include <linux/termios.h> /* for ioctl's */
#include "../kern_sock.h" /* for PRINTK */
+#ifdef PRINTK
+#undef PRINTK
+#endif
+
+#undef TCP_DEBUG
+
+#ifdef TCP_DEBUG
+#define PRINTK printk
+#else
+#define PRINTK dummy_routine
+#endif
+
#define tmax(a,b) (before ((a),(b)) ? (b) : (a))
#define swap(a,b) {unsigned long c; c=a; a=b; b=c;}
@@ -512,7 +537,7 @@ tcp_write(volatile struct sock *sk, unsigned char *from,
}
if (copied) return (copied);
if (sk->err) return (-sk->err);
- return (-ENOTCONN);
+ return (-EPIPE);
}
if (nonblock)
@@ -577,8 +602,8 @@ tcp_write(volatile struct sock *sk, unsigned char *from,
return (-ERESTARTSYS);
}
}
- sti();
sk->inuse = 1;
+ sti();
continue;
}
skb->mem_addr = skb;
@@ -1221,7 +1246,7 @@ tcp_conn_request(volatile struct sock *sk, struct sk_buff *skb,
t1->source = newsk->dummy_th.source;
t1->seq = net32(newsk->send_seq++);
t1->ack = 1;
- newsk->window = sk->prot->rspace(newsk);
+ newsk->window = newsk->prot->rspace(newsk);
t1->window = net16(newsk->window);
t1->res1=0;
t1->res2=0;
@@ -1493,9 +1518,9 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr)
int i;
for (i = 0; i < DEV_NUMBUFFS; i++)
{
- if (oskb->dev->buffs[i] = oskb)
+ if (oskb->dev->buffs[i] == oskb)
{
- oskb->dev->buffs[i]= NULL;
+ oskb->dev->buffs[i] = NULL;
break;
}
}
@@ -1955,6 +1980,7 @@ tcp_accept (volatile struct sock *sk, int flags)
/* now all we need to do is return skb->sk. */
newsk = skb->sk;
+
kfree_skb (skb, FREE_READ);
release_sock (sk);
return (newsk);
@@ -1975,7 +2001,7 @@ tcp_connect (volatile struct sock *sk, struct sockaddr_in *usin, int addr_len)
if (sk->state != TCP_CLOSE) return (-EISCONN);
if (addr_len < 8) return (-EINVAL);
- verify_area (usin, addr_len);
+/* verify_area (usin, addr_len);*/
memcpy_fromfs (&sin,usin, min(sizeof (sin), addr_len));
if (sin.sin_family && sin.sin_family != AF_INET) return (-EAFNOSUPPORT);
@@ -2155,6 +2181,7 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
if (th->check && tcp_check (th, len, saddr, daddr ))
{
skb->sk = NULL;
+ PRINTK ("packet dropped with bad checksum.\n");
kfree_skb (skb, 0);
/* we don't release the socket because it was never
marked in use. */
@@ -2225,6 +2252,7 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
if (sk->rmem_alloc + skb->mem_len >= SK_RMEM_MAX)
{
skb->sk = NULL;
+ PRINTK ("dropping packet due to lack of buffer space.\n");
kfree_skb (skb, 0);
release_sock (sk);
return (0);
diff --git a/net/tcp/udp.c b/net/tcp/udp.c
index 676a428..d5c0fb0 100644
--- a/net/tcp/udp.c
+++ b/net/tcp/udp.c
@@ -19,8 +19,17 @@
The Author may be reached as bir7@leland.stanford.edu or
C/O Department of Mathematics; Stanford University; Stanford, CA 94305
*/
-/* $Id: udp.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: udp.c,v 0.8.4.5 1992/11/18 15:38:03 bir7 Exp $ */
/* $Log: udp.c,v $
+ * Revision 0.8.4.5 1992/11/18 15:38:03 bir7
+ * fixed minor problem in waiting for memory.
+ *
+ * Revision 0.8.4.4 1992/11/17 14:19:47 bir7
+ * *** empty log message ***
+ *
+ * Revision 0.8.4.3 1992/11/15 14:55:30 bir7
+ * Fixed ctrl-h and added NULL checking to print_uh
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
@@ -242,7 +251,7 @@ udp_loopback (volatile struct sock *sk, unsigned short port,
uh -> source = sk->dummy_th.source;
uh -> dest = port;
uh -> len = len + sizeof (*uh);
- verify_area (from , len);
+/* verify_area (from , len); */
memcpy_fromfs(uh+1, from, len);
pair->inuse = 1;
if (pair->rqueue == NULL)
@@ -292,7 +301,7 @@ udp_sendto (volatile struct sock *sk, unsigned char *from, int len,
{
if (addr_len < sizeof (sin))
return (-EINVAL);
- verify_area (usin, sizeof (sin));
+/* verify_area (usin, sizeof (sin));*/
memcpy_fromfs (&sin, usin, sizeof(sin));
if (sin.sin_family &&
sin.sin_family != AF_INET)
@@ -340,10 +349,24 @@ udp_sendto (volatile struct sock *sk, unsigned char *from, int len,
{
printk ("udp_sendto: write buffer full?\n");
print_sk(sk);
+ tmp = sk->wmem_alloc;
release_sock (sk);
- if (copied || !noblock)
- return (copied);
- return (-EAGAIN);
+ if (copied) return (copied);
+ if (noblock) return (-EAGAIN);
+ cli();
+ if (tmp <= sk->wmem_alloc)
+ {
+ interruptible_sleep_on (sk->sleep);
+ if (current->signal & ~current->blocked)
+ {
+ sti();
+ if (copied) return (copied);
+ return (-ERESTARTSYS);
+ }
+ }
+ sk->inuse = 1;
+ sti();
+ continue;
}
skb->mem_addr = skb;
@@ -383,7 +406,7 @@ udp_sendto (volatile struct sock *sk, unsigned char *from, int len,
amt -= sizeof (*uh);
buff += sizeof (*uh);
- verify_area (from, amt);
+/* verify_area (from, amt);*/
memcpy_fromfs( buff, from, amt);
len -= amt;
@@ -547,7 +570,7 @@ udp_connect (volatile struct sock *sk, struct sockaddr_in *usin, int addr_len)
{
struct sockaddr_in sin;
if (addr_len < sizeof (sin)) return (-EINVAL);
- verify_area (usin, sizeof (sin));
+/* verify_area (usin, sizeof (sin)); */
memcpy_fromfs (&sin, usin, sizeof (sin));
if (sin.sin_family && sin.sin_family != AF_INET)
return (-EAFNOSUPPORT);
diff --git a/net/tcp/we.c b/net/tcp/we.c
index a62fed6..e5fe880 100644
--- a/net/tcp/we.c
+++ b/net/tcp/we.c
@@ -44,8 +44,12 @@
/* Note: My driver was full of bugs. Basically if it works, credit
Bob Harris. If it's broken blame me. -RAB */
-/* $Id: we.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */
+/* $Id: we.c,v 0.8.4.3 1992/11/15 14:55:30 bir7 Exp $ */
/* $Log: we.c,v $
+ * Revision 0.8.4.3 1992/11/15 14:55:30 bir7
+ * Put more checking in start_xmit to make sure packet doesn't disapear
+ * out from under us.
+ *
* Revision 0.8.4.2 1992/11/10 10:38:48 bir7
* Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
*
@@ -206,25 +210,40 @@ wd8003_start_xmit(struct sk_buff *skb, struct device *dev)
{
/* put in a time out. */
if (jiffies - dev->trans_start < 30)
- return (1);
+ {
+ return (1);
+ }
+
printk ("wd8003 transmit timed out. \n");
}
status |= TRS_BUSY;
- sti();
if (skb == NULL)
{
+ sti();
wd_trs(dev);
return (0);
}
+ /* this should check to see if it's been killed. */
+ if (skb->dev != dev)
+ {
+ sti();
+ return (0);
+ }
+
+
if (!skb->arp)
{
if ( dev->rebuild_header (skb+1, dev))
{
- skb->dev = dev;
- arp_queue (skb);
+ cli();
+ if (skb->dev == dev)
+ {
+ arp_queue (skb);
+ }
status &= ~TRS_BUSY;
+ sti();
return (0);
}
}
@@ -238,7 +257,7 @@ wd8003_start_xmit(struct sk_buff *skb, struct device *dev)
len=max(len, ETHER_MIN_LEN); /* actually we should zero out
the extra memory. */
/* printk ("start_xmit len - %d\n", len);*/
- cli();
+
cmd=inb_p(WD_COMM);
cmd &= ~CPAGE;
outb_p(cmd, WD_COMM);
diff --git a/tools/version.h b/tools/version.h
index a8046f1..6ff3194 100644
--- a/tools/version.h
+++ b/tools/version.h
@@ -1,5 +1,5 @@
-#define UTS_RELEASE "0.98.pl4+-34"
-#define UTS_VERSION "11/14/92"
-#define LINUX_COMPILE_TIME "12:19:20"
+#define UTS_RELEASE "0.98.pl6-40"
+#define UTS_VERSION "12/02/92"
+#define LINUX_COMPILE_TIME "18:49:15"
#define LINUX_COMPILE_BY "root"
#define LINUX_COMPILE_HOST "home"