Commit 6e995ea9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Import 1.3.43

parent 770b8afb
...@@ -593,6 +593,15 @@ S: 25 McMillan Street ...@@ -593,6 +593,15 @@ S: 25 McMillan Street
S: Victoria Park 6100 S: Victoria Park 6100
S: Australia S: Australia
N: Martin Mares
E: mj@k332.feld.cvut.cz
D: BIOS video mode handling code
D: Miscellaneous kernel fixes
D: MOXA C-218 serial board driver
S: Kankovskeho 1241
S: 182 00 Praha 8
S: Czech Republic
N: John A. Martin N: John A. Martin
E: jam@acm.org E: jam@acm.org
D: FSSTND contributor D: FSSTND contributor
......
...@@ -41,8 +41,8 @@ foo \kill}% ...@@ -41,8 +41,8 @@ foo \kill}%
{\end{tabbing}} {\end{tabbing}}
% %
\title{{\bf Linux Allocated Devices}} \title{{\bf Linux Allocated Devices}}
\author{Maintained by H. Peter Anvin $<$Peter.Anvin@linux.org$>$} \author{Maintained by H. Peter Anvin $<$hpa@storm.net$>$}
\date{Last revised: September 20, 1995} \date{Last revised: November 17, 1995}
\maketitle \maketitle
% %
\noindent \noindent
...@@ -140,9 +140,13 @@ an unreasonable effort. ...@@ -140,9 +140,13 @@ an unreasonable effort.
\major{ }{}{block}{Fourth IDE hard disk/CD-ROM interface} \major{ }{}{block}{Fourth IDE hard disk/CD-ROM interface}
\major{35}{}{char }{tclmidi MIDI driver} \major{35}{}{char }{tclmidi MIDI driver}
\major{ }{}{block}{Modular RAM disk} \major{ }{}{block}{Modular RAM disk}
\major{36}{}{block}{MCA ESDI hard disk} \major{36}{}{char }{Netlink support}
\major{37--223}{}{}{Unallocated} \major{ }{}{block}{MCA ESDI hard disk}
\major{224--254}{}{}{Local use} \major{37}{--41}{}{Unallocated}
\major{42}{}{}{Demo/sample use}
\major{43}{--223}{}{Unallocated}
\major{224}{--239}{}{SEE NOTE}
\major{240}{--254}{}{Local use}
\major{255}{}{}{Reserved} \major{255}{}{}{Reserved}
\end{devicelist} \end{devicelist}
...@@ -770,7 +774,11 @@ major number 3). ...@@ -770,7 +774,11 @@ major number 3).
\end{devicelist} \end{devicelist}
\begin{devicelist} \begin{devicelist}
\major{36}{}{block}{MCA ESDI hard disk} \major{36}{}{char }{Netlink support}
\minor{0}{/dev/route}{Routing, device updates (kernel to user)}
\minor{1}{/dev/skip}{enSKIP security cache control}
\\
\major{ }{}{block}{MCA ESDI hard disk}
\minor{0}{/dev/eda}{First ESDI disk whole disk} \minor{0}{/dev/eda}{First ESDI disk whole disk}
\minor{64}{/dev/edb}{Second ESDI disk whole disk} \minor{64}{/dev/edb}{Second ESDI disk whole disk}
\minordots \minordots
...@@ -781,11 +789,40 @@ Partitions are handled the same way as for IDE disks (see major number ...@@ -781,11 +789,40 @@ Partitions are handled the same way as for IDE disks (see major number
3). 3).
\begin{devicelist} \begin{devicelist}
\major{37}{--223}{}{Unallocated} \major{37}{--41}{}{Unallocated}
\end{devicelist}
\begin{devicelist}
\major{42}{}{}{Demo/sample use}
\end{devicelist}
\noindent
This number is indended for use in sample code, as well as a general
``example'' device number. It should never be used for a device
driver that is being distributed; either obtain an official number or
use the local/experimental range. The sudden addition or removal of a
driver with this number should not cause ill effects to the system
(bugs excepted.)
\begin{devicelist}
\major{43}{--223}{}{Unallocated}
\end{devicelist} \end{devicelist}
\begin{devicelist} \begin{devicelist}
\major{224}{--254}{}{Local/experimental use} \major{224}{--239}{}{SEE NOTE}
\end{devicelist}
\noindent
This range is currently assigned as part of the local/experimental
range. However, because of the Linux way of setting a limit on the
highest device number in the system, currently set at 63 by default, I
am considering changing the local/experimental use to 60--63,
120--127, 240--254. If you are currently using the range 224--239 and
such a change would pose a problem for you, please contact
$<$hpa@storm.net$>$ as soon as possible.
\begin{devicelist}
\major{240}{--254}{}{Local/experimental use}
\end{devicelist} \end{devicelist}
\noindent \noindent
...@@ -846,6 +883,8 @@ exist, they should have the following uses. ...@@ -846,6 +883,8 @@ exist, they should have the following uses.
\vlink{/dev/mouse}{mouse port}{symbolic}{Current mouse device} \vlink{/dev/mouse}{mouse port}{symbolic}{Current mouse device}
\vlink{/dev/tape}{tape device}{symbolic}{Current tape device} \vlink{/dev/tape}{tape device}{symbolic}{Current tape device}
\vlink{/dev/cdrom}{CD-ROM device}{symbolic}{Current CD-ROM device} \vlink{/dev/cdrom}{CD-ROM device}{symbolic}{Current CD-ROM device}
\vlink{/dev/cdwriter}{CD-writer}{symbolic}{Current CD-writer device}
\vlink{/dev/scanner}{scanner device}{symbolic}{Current scanner device}
\vlink{/dev/modem}{modem port}{symbolic}{Current dialout device} \vlink{/dev/modem}{modem port}{symbolic}{Current dialout device}
\vlink{/dev/root}{root device}{symbolic}{Current root filesystem} \vlink{/dev/root}{root device}{symbolic}{Current root filesystem}
\vlink{/dev/swap}{swap device}{symbolic}{Current swap device} \vlink{/dev/swap}{swap device}{symbolic}{Current swap device}
...@@ -857,6 +896,15 @@ dialin as well as dialout, as it tends to cause lock file problems. ...@@ -857,6 +896,15 @@ dialin as well as dialout, as it tends to cause lock file problems.
If it exists, {\file /dev/modem} should point to the appropriate If it exists, {\file /dev/modem} should point to the appropriate
dialout (alternate) device. dialout (alternate) device.
For SCSI devices, {\file /dev/tape} and {\file /dev/cdrom} should
point to the ``cooked'' devices ({\file /dev/st*} and {\file
/dev/sr*}, respectively), whereas {\file /dev/cdwriter} and {\file
/dev/scanner} should point to the appropriate generic SCSI devices
({\file /dev/sg*}.)
{\file /dev/mouse} may point to a dialout (alternate) TTY device, a
hardware mouse device, or a socket for a mouse driver program.
\subsection{Sockets and pipes} \subsection{Sockets and pipes}
Non-transient sockets or named pipes may exist in {\file /dev}. Non-transient sockets or named pipes may exist in {\file /dev}.
...@@ -868,3 +916,4 @@ Common entries are: ...@@ -868,3 +916,4 @@ Common entries are:
\end{nodelist} \end{nodelist}
\end{document} \end{document}
...@@ -522,7 +522,10 @@ an unreasonable effort. ...@@ -522,7 +522,10 @@ an unreasonable effort.
... ...
255 = /dev/ram255 256th modular RAM disk 255 = /dev/ram255 256th modular RAM disk
36 block MCA ESDI hard disk 36 char Netlink support
0 = /dev/route Routing, device updates, kernel to user
1 = /dev/skip enSKIP security cache control
block MCA ESDI hard disk
0 = /dev/eda First ESDI disk whole disk 0 = /dev/eda First ESDI disk whole disk
64 = /dev/edb Second ESDI disk whole disk 64 = /dev/edb Second ESDI disk whole disk
... ...
...@@ -530,9 +533,33 @@ an unreasonable effort. ...@@ -530,9 +533,33 @@ an unreasonable effort.
Partitions are handled in the same way as IDE disks Partitions are handled in the same way as IDE disks
(see major number 3). (see major number 3).
37-223 UNALLOCATED 37-41 UNALLOCATED
224-254 LOCAL USE 42 Demo/sample use
This number is indended for use in sample code, as
well as a general "example" device number. It
should never be used for a device driver that is being
distributed; either obtain an official number or use
the local/experimental range. The sudden addition or
removal of a driver with this number should not cause
ill effects to the system (bugs excepted.)
43-223 UNALLOCATED
224-239 SEE NOTE
This range is currently assigned as part of the
local/experimental range. However, because of the
Linux way of setting a limit on the highest device
number in the system, currently set at 63 by default,
I am considering changing the local/experimental use
to 60-63, 120-127, 240-254. If you are currently
using the range 224-239 and such a change would pose a
problem for you, please contact <hpa@storm.net> as
soon as possible.
240-254 LOCAL USE
Allocated for local/experimental use Allocated for local/experimental use
Please note that MAX_CHRDEV and MAX_BLKDEV in Please note that MAX_CHRDEV and MAX_BLKDEV in
...@@ -586,6 +613,8 @@ exist, they should have the following uses. ...@@ -586,6 +613,8 @@ exist, they should have the following uses.
/dev/mouse mouse port symbolic Current mouse device /dev/mouse mouse port symbolic Current mouse device
/dev/tape tape device symbolic Current tape device /dev/tape tape device symbolic Current tape device
/dev/cdrom CD-ROM device symbolic Current CD-ROM device /dev/cdrom CD-ROM device symbolic Current CD-ROM device
/dev/cdwriter CD-writer symbolic Current CD-writer device
/dev/scanner scanner symbolic Current scanner device
/dev/modem modem port symbolic Current dialout device /dev/modem modem port symbolic Current dialout device
/dev/root root device symbolic Current root filesystem /dev/root root device symbolic Current root filesystem
/dev/swap swap device symbolic Current swap device /dev/swap swap device symbolic Current swap device
...@@ -595,6 +624,13 @@ well as dialout, as it tends to cause lock file problems. If it ...@@ -595,6 +624,13 @@ well as dialout, as it tends to cause lock file problems. If it
exists, /dev/modem shold point to the appropriate dialout (alternate) exists, /dev/modem shold point to the appropriate dialout (alternate)
device. device.
For SCSI devices, /dev/tape and /dev/cdrom should point to the
``cooked'' devices (/dev/st* and /dev/sr*, respectively), whereas
/dev/cdwriter and /dev/scanner should point to the appropriate generic
SCSI devices (/dev/sg*).
/dev/mouse may point to a dialout (alternate) TTY device, a hardware
mouse device, or a socket for a mouse driver program.
Sockets and pipes Sockets and pipes
......
...@@ -30,6 +30,9 @@ directly to the loaded font, bypassing the translation table. The ...@@ -30,6 +30,9 @@ directly to the loaded font, bypassing the translation table. The
user-defined map now defaults to U+F000 to U+F1FF, emulating the user-defined map now defaults to U+F000 to U+F1FF, emulating the
previous behaviour. previous behaviour.
Actual characters assigned in the Corporate Zone
------------------------------------------------
In addition, the following characters not present in Unicode 1.1.4 (at In addition, the following characters not present in Unicode 1.1.4 (at
least, I have not found them!) have been defined; these are used by least, I have not found them!) have been defined; these are used by
the DEC VT graphics map: the DEC VT graphics map:
...@@ -45,5 +48,79 @@ omitted the scan 5 line, since it is also used as a block-graphics ...@@ -45,5 +48,79 @@ omitted the scan 5 line, since it is also used as a block-graphics
character, and hence has been coded as U+2500 FORMS LIGHT HORIZONTAL. character, and hence has been coded as U+2500 FORMS LIGHT HORIZONTAL.
However, I left U+F802 blank should the need arise. However, I left U+F802 blank should the need arise.
H. Peter Anvin <Peter.Anvin@linux.org> Klingon language support
Yggdrasil Computing, Inc. ------------------------
Unfortunately, Unicode/ISO 10646 does not allocate code points for the
language Klingon, probably fearing the potential code point explosion
if many fictional lanugages were submitted for inclusion. There are
also political reasons (the Japanese, for example, are not too happy
about the whole 16-bit concept to begin with.) However, with Linux
being a hacker-driven OS it seems this is a brilliant linguistic hack
worth supporting. Hence I have chosen to add it to the list in the
Linux "Corporate" Zone.
Several glyph forms for the Klingon alphabet has been proposed.
However, since the set of symbols appear to be consistent throughout,
with only the actual shapes being different, in keeping with standard
Unicode practice these differences are considered font variants.
Klingon has an alphabet of 26 characters, a positional numeric writing
system with 10 digits, and is written left-to-right, top-to-bottom.
Punctuation appears to be only used in Latin transliteration; it is
appears customary to write each sentence on its own line, and
centered. Space has been reserved for punctuation should it prove
necessary.
This encoding has been endorsed by the Klingon Language Institute.
For more information, contact them at:
http://www.kli.org/
Since the characters in the beginning of the Linux CZ have been more
of the dingbats/symbols/forms type and this is a language, I have
located it at the end, on a 16-cell boundary in keeping with standard
Unicode practice.
U+F8D0 KLINGON LETTER A
U+F8D1 KLINGON LETTER B
U+F8D2 KLINGON LETTER CH
U+F8D3 KLINGON LETTER D
U+F8D4 KLINGON LETTER E
U+F8D5 KLINGON LETTER GH
U+F8D6 KLINGON LETTER H
U+F8D7 KLINGON LETTER I
U+F8D8 KLINGON LETTER J
U+F8D9 KLINGON LETTER L
U+F8DA KLINGON LETTER M
U+F8DB KLINGON LETTER N
U+F8DC KLINGON LETTER NG
U+F8DD KLINGON LETTER O
U+F8DE KLINGON LETTER P
U+F8DF KLINGON LETTER Q
- Written <q> in standard Okrand Latin transliteration
U+F8E0 KLINGON LETTER QH
- Written <Q> in standard Okrand Latin transliteration
U+F8E1 KLINGON LETTER R
U+F8E2 KLINGON LETTER S
U+F8E3 KLINGON LETTER T
U+F8E4 KLINGON LETTER TLH
U+F8E5 KLINGON LETTER U
U+F8E6 KLINGON LETTER V
U+F8E7 KLINGON LETTER W
U+F8E8 KLINGON LETTER Y
U+F8E9 KLINGON LETTER GLOTTAL STOP
U+F8F0 KLINGON DIGIT ZERO
U+F8F1 KLINGON DIGIT ONE
U+F8F2 KLINGON DIGIT TWO
U+F8F3 KLINGON DIGIT THREE
U+F8F4 KLINGON DIGIT FOUR
U+F8F5 KLINGON DIGIT FIVE
U+F8F6 KLINGON DIGIT SIX
U+F8F7 KLINGON DIGIT SEVEN
U+F8F8 KLINGON DIGIT EIGHT
U+F8F9 KLINGON DIGIT NINE
H. Peter Anvin <hpa@storm.net>
VERSION = 1 VERSION = 1
PATCHLEVEL = 3 PATCHLEVEL = 3
SUBLEVEL = 42 SUBLEVEL = 43
ARCH = i386 ARCH = i386
......
...@@ -57,8 +57,8 @@ void hard_reset_now(void) ...@@ -57,8 +57,8 @@ void hard_reset_now(void)
void show_regs(struct pt_regs * regs) void show_regs(struct pt_regs * regs)
{ {
printk("\nps: %04lx pc: %016lx\n", regs->ps, regs->pc); printk("\nps: %04lx pc: [<%016lx>]\n", regs->ps, regs->pc);
printk("rp: %016lx sp: %p\n", regs->r26, regs+1); printk("rp: [<%016lx>] sp: %p\n", regs->r26, regs+1);
printk(" r0: %016lx r1: %016lx r2: %016lx r3: %016lx\n", printk(" r0: %016lx r1: %016lx r2: %016lx r3: %016lx\n",
regs->r0, regs->r1, regs->r2, regs->r3); regs->r0, regs->r1, regs->r2, regs->r3);
printk(" r4: %016lx r5: %016lx r6: %016lx r7: %016lx\n", printk(" r4: %016lx r5: %016lx r6: %016lx r7: %016lx\n",
......
...@@ -25,8 +25,8 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err) ...@@ -25,8 +25,8 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err)
return; return;
printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err); printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
sp = (unsigned long) (regs+1); sp = (unsigned long) (regs+1);
printk("pc = %lx ps = %04lx\n", regs->pc, regs->ps); printk("pc = [<%lx>] ps = %04lx\n", regs->pc, regs->ps);
printk("rp = %lx sp = %lx\n", regs->r26, sp); printk("rp = [<%lx>] sp = %lx\n", regs->r26, sp);
printk("r0=%lx r1=%lx r2=%lx r3=%lx\n", printk("r0=%lx r1=%lx r2=%lx r3=%lx\n",
regs->r0, regs->r1, regs->r2, regs->r3); regs->r0, regs->r1, regs->r2, regs->r3);
printk("r8=%lx\n", regs->r8); printk("r8=%lx\n", regs->r8);
......
...@@ -54,10 +54,8 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr, long c ...@@ -54,10 +54,8 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr, long c
goto good_area; goto good_area;
if (!(vma->vm_flags & VM_GROWSDOWN)) if (!(vma->vm_flags & VM_GROWSDOWN))
goto bad_area; goto bad_area;
if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur) if (expand_stack(vma, address))
goto bad_area; goto bad_area;
vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
vma->vm_start = (address & PAGE_MASK);
/* /*
* Ok, we have a good vm_area for this memory access, so * Ok, we have a good vm_area for this memory access, so
* we can handle it.. * we can handle it..
......
...@@ -5,13 +5,14 @@ ...@@ -5,13 +5,14 @@
* adapted for Linux. * adapted for Linux.
* *
* malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
* puts by Nick Holloway 1993 * puts by Nick Holloway 1993, better puts by Martin Mares 1995
*/ */
#include "gzip.h" #include "gzip.h"
#include "lzw.h" #include "lzw.h"
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/io.h>
/* /*
* These are set up by the setup-routine at boot-time: * These are set up by the setup-routine at boot-time:
...@@ -24,9 +25,9 @@ struct screen_info { ...@@ -24,9 +25,9 @@ struct screen_info {
unsigned short orig_video_page; unsigned short orig_video_page;
unsigned char orig_video_mode; unsigned char orig_video_mode;
unsigned char orig_video_cols; unsigned char orig_video_cols;
unsigned short orig_video_ega_ax; unsigned short unused2;
unsigned short orig_video_ega_bx; unsigned short orig_video_ega_bx;
unsigned short orig_video_ega_cx; unsigned short unused3;
unsigned char orig_video_lines; unsigned char orig_video_lines;
unsigned char orig_video_isVGA; unsigned char orig_video_isVGA;
}; };
...@@ -77,6 +78,7 @@ void makecrc(void); ...@@ -77,6 +78,7 @@ void makecrc(void);
local int get_method(int); local int get_method(int);
char *vidmem = (char *)0xb8000; char *vidmem = (char *)0xb8000;
int vidport;
int lines, cols; int lines, cols;
static void puts(const char *); static void puts(const char *);
...@@ -128,7 +130,7 @@ static void scroll() ...@@ -128,7 +130,7 @@ static void scroll()
static void puts(const char *s) static void puts(const char *s)
{ {
int x,y; int x,y,pos;
char c; char c;
x = SCREEN_INFO.orig_x; x = SCREEN_INFO.orig_x;
...@@ -155,6 +157,12 @@ static void puts(const char *s) ...@@ -155,6 +157,12 @@ static void puts(const char *s)
SCREEN_INFO.orig_x = x; SCREEN_INFO.orig_x = x;
SCREEN_INFO.orig_y = y; SCREEN_INFO.orig_y = y;
pos = (x + cols * y) * 2; /* Update cursor position */
outb_p(14, vidport);
outb_p(0xff & (pos >> 9), vidport+1);
outb_p(15, vidport);
outb_p(0xff & (pos >> 1), vidport+1);
} }
__ptr_t memset(__ptr_t s, int c, size_t n) __ptr_t memset(__ptr_t s, int c, size_t n)
...@@ -315,10 +323,13 @@ struct { ...@@ -315,10 +323,13 @@ struct {
void decompress_kernel() void decompress_kernel()
{ {
if (SCREEN_INFO.orig_video_mode == 7) if (SCREEN_INFO.orig_video_mode == 7) {
vidmem = (char *) 0xb0000; vidmem = (char *) 0xb0000;
else vidport = 0x3b4;
} else {
vidmem = (char *) 0xb8000; vidmem = (char *) 0xb8000;
vidport = 0x3d4;
}
lines = SCREEN_INFO.orig_video_lines; lines = SCREEN_INFO.orig_video_lines;
cols = SCREEN_INFO.orig_video_cols; cols = SCREEN_INFO.orig_video_cols;
......
...@@ -343,10 +343,6 @@ ret_from_sys_call: ...@@ -343,10 +343,6 @@ ret_from_sys_call:
#endif #endif
cmpl SYMBOL_NAME(task),%eax # task[0] cannot have signals cmpl SYMBOL_NAME(task),%eax # task[0] cannot have signals
je 2f je 2f
cmpl $0,state(%eax) # state
jne reschedule
cmpl $0,counter(%eax) # counter
je reschedule
movl blocked(%eax),%ecx movl blocked(%eax),%ecx
movl %ecx,%ebx # save blocked in %ebx for signal handling movl %ecx,%ebx # save blocked in %ebx for signal handling
notl %ecx notl %ecx
...@@ -660,4 +656,11 @@ ENTRY(sys_call_table) ...@@ -660,4 +656,11 @@ ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_msync) .long SYMBOL_NAME(sys_msync)
.long SYMBOL_NAME(sys_readv) /* 145 */ .long SYMBOL_NAME(sys_readv) /* 145 */
.long SYMBOL_NAME(sys_writev) .long SYMBOL_NAME(sys_writev)
.space (NR_syscalls-146)*4 .long 0
.long 0
.long 0
.long SYMBOL_NAME(sys_mlock) /* 150 */
.long SYMBOL_NAME(sys_munlock)
.long SYMBOL_NAME(sys_mlockall)
.long SYMBOL_NAME(sys_munlockall)
.space (NR_syscalls-154)*4
...@@ -124,7 +124,7 @@ void hard_reset_now(void) ...@@ -124,7 +124,7 @@ void hard_reset_now(void)
void show_regs(struct pt_regs * regs) void show_regs(struct pt_regs * regs)
{ {
printk("\n"); printk("\n");
printk("EIP: %04x:%08lx",0xffff & regs->cs,regs->eip); printk("EIP: %04x:[<%08lx>]",0xffff & regs->cs,regs->eip);
if (regs->cs & 3) if (regs->cs & 3)
printk(" ESP: %04x:%08lx",0xffff & regs->ss,regs->esp); printk(" ESP: %04x:%08lx",0xffff & regs->ss,regs->esp);
printk(" EFLAGS: %08lx\n",regs->eflags); printk(" EFLAGS: %08lx\n",regs->eflags);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
/* /*
* This file handles the architecture-dependent parts of process handling.. * This file handles the architecture-dependent parts of initialization
*/ */
#include <linux/errno.h> #include <linux/errno.h>
...@@ -152,12 +152,39 @@ void setup_arch(char **cmdline_p, ...@@ -152,12 +152,39 @@ void setup_arch(char **cmdline_p,
request_region(0xf0,0x10,"npu"); request_region(0xf0,0x10,"npu");
} }
static const char * i486model(unsigned int nr)
{
static const char *model[] = {
"0", "DX","SX","DX/2","4","SX/2","6","DX/2-WB","DX/4"
};
if (nr < sizeof(model)/sizeof(char *))
return model[nr];
return "Unknown";
}
static const char * i586model(unsigned int nr)
{
static const char *model[] = {
"0", "Pentium 60/66","Pentium 75+"
};
if (nr < sizeof(model)/sizeof(char *))
return model[nr];
return "Unknown";
}
static const char * getmodel(int x86, int model)
{
switch (x86) {
case 4:
return i486model(model);
case 5:
return i586model(model);
}
return "Unknown";
}
int get_cpuinfo(char * buffer) int get_cpuinfo(char * buffer)
{ {
static const char *model[2][9]={{"DX","SX","DX/2","4","SX/2","6",
"DX/2-WB","DX/4"},
{"Pentium 60/66","Pentium 75+","3",
"4","5","6","7","8"}};
char mask[2]; char mask[2];
#ifndef __SMP__ #ifndef __SMP__
mask[0] = x86_mask+'@'; mask[0] = x86_mask+'@';
...@@ -180,7 +207,7 @@ int get_cpuinfo(char * buffer) ...@@ -180,7 +207,7 @@ int get_cpuinfo(char * buffer)
"CMPXCHGB8B\t: %s\n" "CMPXCHGB8B\t: %s\n"
"BogoMips\t: %lu.%02lu\n", "BogoMips\t: %lu.%02lu\n",
x86+'0', x86+'0',
x86_model ? model[x86-4][x86_model-1] : "Unknown", getmodel(x86, x86_model),
x86_mask ? mask : "Unknown", x86_mask ? mask : "Unknown",
x86_vendor_id, x86_vendor_id,
fdiv_bug ? "yes" : "no", fdiv_bug ? "yes" : "no",
...@@ -207,8 +234,7 @@ int get_cpuinfo(char * buffer) ...@@ -207,8 +234,7 @@ int get_cpuinfo(char * buffer)
bp+=sprintf(bp,"\nmodel\t\t: "); bp+=sprintf(bp,"\nmodel\t\t: ");
for(i=0;i<32;i++) for(i=0;i<32;i++)
if(cpu_present_map&(1<<i)) if(cpu_present_map&(1<<i))
bp+=sprintf(bp,"%-16s",cpu_data[i].x86_model? bp+=sprintf(bp,"%-16s",getmodel(cpu_data[i].x86,cpu_data[i].x86_model));
model[cpu_data[i].x86-4][cpu_data[i].x86_model-1]:"Unknown");
bp+=sprintf(bp,"\nmask\t\t: "); bp+=sprintf(bp,"\nmask\t\t: ");
for(i=0;i<32;i++) for(i=0;i<32;i++)
if(cpu_present_map&(1<<i)) if(cpu_present_map&(1<<i))
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
asmlinkage int system_call(void); asmlinkage int system_call(void);
asmlinkage void lcall7(void); asmlinkage void lcall7(void);
struct desc_struct default_ldt; struct desc_struct default_ldt = { 0, 0 };
static inline void console_verbose(void) static inline void console_verbose(void)
{ {
...@@ -113,7 +113,7 @@ int kstack_depth_to_print = 24; ...@@ -113,7 +113,7 @@ int kstack_depth_to_print = 24;
console_verbose(); console_verbose();
printk("%s: %04lx\n", str, err & 0xffff); printk("%s: %04lx\n", str, err & 0xffff);
printk("CPU: %d\n", smp_processor_id()); printk("CPU: %d\n", smp_processor_id());
printk("EIP: %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags); printk("EIP: %04x:[<%08lx>]\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags);
printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
regs->eax, regs->ebx, regs->ecx, regs->edx); regs->eax, regs->ebx, regs->ecx, regs->edx);
printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
...@@ -153,7 +153,7 @@ int kstack_depth_to_print = 24; ...@@ -153,7 +153,7 @@ int kstack_depth_to_print = 24;
((addr >= module_start) && (addr <= module_end))) { ((addr >= module_start) && (addr <= module_end))) {
if (i && ((i % 8) == 0)) if (i && ((i % 8) == 0))
printk("\n "); printk("\n ");
printk("%08lx ", addr); printk("[<%08lx>] ", addr);
i++; i++;
} }
} }
......
...@@ -46,8 +46,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -46,8 +46,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
goto good_area; goto good_area;
if (!(vma->vm_flags & VM_GROWSDOWN)) if (!(vma->vm_flags & VM_GROWSDOWN))
goto bad_area; goto bad_area;
if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur)
goto bad_area;
if (error_code & 4) { if (error_code & 4) {
/* /*
* accessing the stack below %esp is always a bug. * accessing the stack below %esp is always a bug.
...@@ -58,8 +56,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -58,8 +56,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
if (address + 32 < regs->esp) if (address + 32 < regs->esp)
goto bad_area; goto bad_area;
} }
vma->vm_offset -= vma->vm_start - (address & PAGE_MASK); if (expand_stack(vma, address))
vma->vm_start = (address & PAGE_MASK); goto bad_area;
/* /*
* Ok, we have a good vm_area for this memory access, so * Ok, we have a good vm_area for this memory access, so
* we can handle it.. * we can handle it..
......
...@@ -34,6 +34,8 @@ NEW! - support for reliable operation of buggy CMD-640 interfaces ...@@ -34,6 +34,8 @@ NEW! - support for reliable operation of buggy CMD-640 interfaces
- PCI support is automatic - PCI support is automatic
- for VLB, use kernel command line option: ide0=cmd640_vlb - for VLB, use kernel command line option: ide0=cmd640_vlb
- this support also enables the secondary i/f on most cards - this support also enables the secondary i/f on most cards
- experimental interface timing parameter support
NEW! - experimental support for UMC 8672 interfaces
NEW! - support for secondary interface on the FGI/Holtek HT-6560B VLB i/f NEW! - support for secondary interface on the FGI/Holtek HT-6560B VLB i/f
- use kernel command line option: ide1=ht6560 - use kernel command line option: ide1=ht6560
NEW! - experimental "fast" speed support for QD6580 interfaces NEW! - experimental "fast" speed support for QD6580 interfaces
...@@ -45,7 +47,10 @@ NEW! - support for removeable devices, including door lock/unlock ...@@ -45,7 +47,10 @@ NEW! - support for removeable devices, including door lock/unlock
NEW! - transparent support for DiskManager 6.0x and "Dynamic Disk Overlay" NEW! - transparent support for DiskManager 6.0x and "Dynamic Disk Overlay"
- works with Linux fdisk, LILO, loadlin, bootln, etc.. - works with Linux fdisk, LILO, loadlin, bootln, etc..
NEW! - mostly transparent support for EZ-Drive NEW! - mostly transparent support for EZ-Drive
- LILO is incompatible (also harmless) with EZ-Drive NEW! - to use LILO with EZ, install LILO on the linux partition
rather than on the master boot record, and then mark the
linux partition as "bootable" or "active" using fdisk.
(courtesy of Juha Laiho <jlaiho@ichaos.nullnet.fi>).
NEW! - ide-cd.c now compiles separate from ide.c NEW! - ide-cd.c now compiles separate from ide.c
NEW! - Bus-Master DMA support for Intel PCI Triton chipset IDE interfaces NEW! - Bus-Master DMA support for Intel PCI Triton chipset IDE interfaces
- for details, see comments at top of triton.c - for details, see comments at top of triton.c
...@@ -466,24 +471,62 @@ Silicon Valley - best day job in the world ...@@ -466,24 +471,62 @@ Silicon Valley - best day job in the world
================================================================================ ================================================================================
from: 'delman@mipg.upenn.edu' 1995 Nov 16 at 08:25 EST
subject: rz1000 from: 'dwhysong@dolphin.physics.ucsb.edu' (BNR400)
[I'm cc'ing this to Mark Lord: FYI, I've got at DTC2278S VLB EIDE
controller with a Connor CFA850A as /dev/hda and a Maxtor 7213A as
/dev/hdb using Linux 1.2.13 w/patches for assembly strcpy and the kswap
patches. I'm getting strange behavior and an unstable system when I try to
use 32 bit VLB data transfer to the interface card. However, hdparm
reports that the Connor is extremely fast when I can get the 32 bit mode
enabled using hdparm -c1 /dev/hd(a|b). However, if I don't do hdparm -c1
on both /dev/hda and /dev/hdb, then when I run "hdparm -t /dev/hda" the
disk subsystem locks up... the disk LED comes on and stays on, and no
other programs are able to get disk access (I can switch VC's, but I can't
get past the username prompt). I thought you should know about this. I'm
not sure if it's a problem with the support for the DTC cards, or a
peculiarity with my hardware configuration. I doubt that my hardware
itself is flaky, though that's always a possibility.]
On Wed, 15 Nov 1995, Michael Faurot wrote:
> > The trick is setting BOTH drives to use the 32 bit interface.
>
> Congrats on getting it going. Those are some great transfer
> rates. I noticed you did switch on the unmasking. Noticed any
> problems with things under extreme load or with serial transfers?
I've never had any problems which I could trace to interrupt unmasking.
Of course, my system usually doesn't have a really heavy load, either.
These numbers seem way too high for a disk with something like 3500 (?)
RPM.
Sleepy# hdparm -t /dev/hda
/dev/hda:
Timing buffer-cache reads: 32 MB in 2.24 seconds =14.29 MB/sec
Timing buffered disk reads: 16 MB in 3.63 seconds = 4.41 MB/sec
Estimating raw driver speed: 16 MB in 2.51 seconds = 6.37 MB/sec
> Not sure I was much help to you, but I'm glad to hear you got it
> working--and pretty impressivly at that. :-)
Mmm, well, about that... I've found that my Connor drive (/dev/hda) is
pretty fast when I have my system configured like this. I'm still not
sure I trust the "hdparm -t" results, though. However, when I try
"hdparm -t /dev/hdb" (/dev/hdb is an older Maxtor 7213A) I have the same
problem I had before with my disk subsystem locking up.
I've tried just about every possible combination of flags in ide.c and
hdparm, and I can't get decent performance out of this drive/controller
combination without some kind of instability creeping in. I'm living with
the situation now only because /dev/hdb is a DOS-only drive, and I don't
need it under Linux. However, I don't really like the situation.
-Dave
dwhysong@physics.ucsb.edu
(Why can't this stuff be simple? Plug the card in, and it works? Every
hardware manufacturer has to have their own way of doing things...)
Hi Mark! Looks like you managed to get the info from Intel to disable
the read-ahead feature of the RZ1000. My encounter with
Zeos (subsidiary of Micron which owns PCTech) has not been as
successful --- one guy needs to ask his supervisors about NDA, another
guy thinks that there is too much of a performance hit with read-ahead
disabled.
Did the following benchmark to see how true the claim is.
With Linux 1.2.13, average of 10 "hdparm -t" in MB/s:
hdparm -c0 hdparm -c1
read-ahead enabled 4.28 4.25
read-ahead disabled 3.58 4.30
Maybe -c1 should be the default for the RZ1000, or as a suggestion in
the README for people with the RZ1000.
Cheers, Delman.
/*
* linux/drivers/block/cmd640.c Version 0.01 Nov 16, 1995
*
* Copyright (C) 1995 Linus Torvalds & author (see below)
*/
/*
* Principal Author/Maintainer: abramov@cecmow.enet.dec.com (Igor)
*
* This file provides support for the advanced features and bugs
* of IDE interfaces using the CMD Technologies 0640 IDE interface chip.
*
* Version 0.01 Initial version, hacked out of ide.c,
* and #include'd rather than compiled separately.
* This will get cleaned up in a subsequent release.
*/
/* Interface to access cmd640x registers */
static void (*put_cmd640_reg)(int key, int reg_no, int val);
static byte (*get_cmd640_reg)(int key, int reg_no);
enum { none, vlb, pci1, pci2 };
static int bus_type = none;
static int cmd640_chip_version;
static int cmd640_key;
static byte is_cmd640[MAX_HWIFS];
/*
* For some unknown reasons pcibios functions which read and write registers
* do not work with cmd640. We use direct io instead.
*/
/* PCI method 1 access */
static void put_cmd640_reg_pci1(int key, int reg_no, int val)
{
unsigned long flags;
save_flags(flags);
cli();
outl_p((reg_no & 0xfc) | key, 0xcf8);
outb_p(val, (reg_no & 3) + 0xcfc);
restore_flags(flags);
}
static byte get_cmd640_reg_pci1(int key, int reg_no)
{
byte b;
unsigned long flags;
save_flags(flags);
cli();
outl_p((reg_no & 0xfc) | key, 0xcf8);
b = inb(0xcfc + (reg_no & 3));
restore_flags(flags);
return b;
}
/* PCI method 2 access (from CMD datasheet) */
static void put_cmd640_reg_pci2(int key, int reg_no, int val)
{
unsigned long flags;
save_flags(flags);
cli();
outb_p(0x10, 0xcf8);
outb_p(val, key + reg_no);
outb_p(0, 0xcf8);
restore_flags(flags);
}
static byte get_cmd640_reg_pci2(int key, int reg_no)
{
byte b;
unsigned long flags;
save_flags(flags);
cli();
outb_p(0x10, 0xcf8);
b = inb(key + reg_no);
outb_p(0, 0xcf8);
restore_flags(flags);
return b;
}
/* VLB access */
static void put_cmd640_reg_vlb(int key, int reg_no, int val)
{
unsigned long flags;
save_flags(flags);
cli();
outb(reg_no, key + 8);
outb(val, key + 0xc);
restore_flags(flags);
}
static byte get_cmd640_reg_vlb(int key, int reg_no)
{
byte b;
unsigned long flags;
save_flags(flags);
cli();
outb(reg_no, key + 8);
b = inb(key + 0xc);
restore_flags(flags);
return b;
}
/*
* Probe for CMD640x -- pci method 1
*/
static int probe_for_cmd640_pci1(void)
{
long id;
int k;
for (k = 0x80000000; k <= 0x8000f800; k += 0x800) {
outl(k, 0xcf8);
id = inl(0xcfc);
if (id != 0x06401095)
continue;
put_cmd640_reg = put_cmd640_reg_pci1;
get_cmd640_reg = get_cmd640_reg_pci1;
cmd640_key = k;
return 1;
}
return 0;
}
/*
* Probe for CMD640x -- pci method 2
*/
static int probe_for_cmd640_pci2(void)
{
int i;
int v_id;
int d_id;
for (i = 0xc000; i <= 0xcf00; i += 0x100) {
outb(0x10, 0xcf8);
v_id = inw(i);
d_id = inw(i + 2);
outb(0, 0xcf8);
if (v_id != 0x1095 || d_id != 0x640)
continue;
put_cmd640_reg = put_cmd640_reg_pci2;
get_cmd640_reg = get_cmd640_reg_pci2;
cmd640_key = i;
return 1;
}
return 0;
}
/*
* Probe for CMD640x -- vlb
*/
static int probe_for_cmd640_vlb(void) {
byte b;
outb(0x50, 0x178);
b = inb(0x17c);
if (b == 0xff || b == 0 || (b & 0x20)) {
outb(0x50, 0xc78);
b = inb(0x7c);
if (b == 0xff || b == 0 || !(b & 0x20))
return 0;
cmd640_key = 0x70;
} else {
cmd640_key = 0x170;
}
put_cmd640_reg = put_cmd640_reg_vlb;
get_cmd640_reg = get_cmd640_reg_vlb;
return 1;
}
/*
* Probe for Cmd640x and initialize it if found
*/
int ide_probe_for_cmd640x(void)
{
int i;
for (i = 0; i < MAX_HWIFS; i++)
is_cmd640[i] = 0;
if (probe_for_cmd640_pci1()) {
bus_type = pci1;
} else if (probe_for_cmd640_pci2()) {
bus_type = pci2;
} else if (cmd640_vlb && probe_for_cmd640_vlb()) {
/* May be remove cmd640_vlb at all, and probe in any case */
bus_type = vlb;
} else {
return 0;
}
/*
* Undocumented magic. (There is no 0x5b port in specs)
*/
put_cmd640_reg(cmd640_key, 0x5b, 0xbd);
if (get_cmd640_reg(cmd640_key, 0x5b) != 0xbd) {
printk("ide: can't initialize cmd640 -- wrong value in 0x5b\n");
return 0;
}
put_cmd640_reg(cmd640_key, 0x5b, 0);
/*
* Documented magic.
*/
cmd640_chip_version = get_cmd640_reg(cmd640_key, 0x50) & 3;
if (cmd640_chip_version == 0) {
printk ("ide: wrong CMD640 version -- 0\n");
return 0;
}
put_cmd640_reg(cmd640_key, 0x51, get_cmd640_reg(cmd640_key, 0x51) | 0xc8);
put_cmd640_reg(cmd640_key, 0x57, 0);
put_cmd640_reg(cmd640_key, 0x57, get_cmd640_reg(cmd640_key, 0x57) | 0x0c);
serialized = 1;
printk("ide: buggy CMD640 interface at ");
switch (bus_type) {
case vlb :
printk("local bus, port 0x%x", cmd640_key);
break;
case pci1:
printk("pci, (0x%x)", cmd640_key);
break;
case pci2:
printk("pci,(access method 2) (0x%x)", cmd640_key);
break;
}
is_cmd640[0] = is_cmd640[1] = 1;
/*
* Reset interface timings
*/
put_cmd640_reg(cmd640_key, 0x58, 0);
put_cmd640_reg(cmd640_key, 0x52, 0);
printk("\n ... serialized, disabled read-ahead, secondary interface enabled\n");
return 1;
}
static int as_clocks(int a) {
switch (a & 0xf0) {
case 0 : return 4;
case 0x40 : return 2;
case 0x80 : return 3;
case 0xc0 : return 5;
default : return -1;
}
}
/*
* Tuning of drive parameters
*/
static void cmd640_set_timing(int if_num, int dr_num, int r1, int r2) {
int b_reg;
byte b;
int r52;
b_reg = if_num ? 0x57 : dr_num ? 0x55 : 0x53;
if (if_num == 0) {
put_cmd640_reg(cmd640_key, b_reg, r1);
put_cmd640_reg(cmd640_key, b_reg + 1, r2);
} else {
b = get_cmd640_reg(cmd640_key, b_reg);
if ((b&1) == 0) {
put_cmd640_reg(cmd640_key, b_reg, r1);
} else {
if (as_clocks(b) < as_clocks(r1))
put_cmd640_reg(cmd640_key, b_reg, r1);
}
b = get_cmd640_reg(cmd640_key, b_reg + 1);
if (b == 0) {
put_cmd640_reg(cmd640_key, b_reg + 1, r2);
} else {
r52 = (b&0xf) < (r2&0xf) ? (r2&0xf) : (b&0xf);
r52 |= (b&0xf0) < (r2&0xf0) ? (r2&0xf0) : (b&0xf0);
put_cmd640_reg(cmd640_key, b_reg+1, r52);
}
}
b = get_cmd640_reg(cmd640_key, 0x52);
if (b == 0) {
put_cmd640_reg(cmd640_key, 0x52, r2);
} else {
r52 = (b&0xf) < (r2&0xf) ? (r2&0xf) : (b&0xf);
r52 |= (b&0xf0) < (r2&0xf0) ? (r2&0xf0) : (b&0xf0);
put_cmd640_reg(cmd640_key, 0x52, r52);
}
}
static int bus_speed = 33; /* MHz */
struct pio_timing {
int mc_time; /* Minimal cycle time (ns) */
int av_time; /* Address valid to DIOR-/DIOW- setup (ns) */
int ds_time; /* DIOR data setup (ns) */
} pio_timings[6] = {
{ 70, 165, 600 }, /* PIO Mode 0 */
{ 50, 125, 383 }, /* PIO Mode 1 */
{ 30, 100, 240 }, /* PIO Mode 2 */
{ 30, 80, 180 }, /* PIO Mode 3 */
{ 25, 70, 125 }, /* PIO Mode 4 */
{ 20, 50, 100 } /* PIO Mode ? */
};
struct drive_pio_info {
const char *name;
int pio;
} drive_pios[] = {
{ "Maxtor 7131 AT", 1 },
{ "Maxtor 7171 AT", 1 },
{ "Maxtor 7213 AT", 1 },
{ "Maxtor 7245 AT", 1 },
{ "SAMSUNG SHD-3122A", 1 },
{ "QUANTUM ELS127A", 0 },
{ "QUANTUM LPS240A", 0 },
{ "QUANTUM LPS270A", 3 },
{ "QUANTUM LPS540A", 3 },
{ NULL, 0 }
};
static int known_drive_pio(char* name) {
struct drive_pio_info* pi;
for (pi = drive_pios; pi->name != NULL; pi++) {
if (strcmp(pi->name, name) == 0)
return pi->pio;
}
return -1;
}
static void cmd640_timings_to_regvals(int mc_time, int av_time, int ds_time,
int clock_time,
int* r1, int* r2)
{
int a, b;
a = (mc_time + clock_time - 1)/clock_time;
if (a <= 2) *r1 = 0x40;
else if (a == 3) *r1 = 0x80;
else if (a == 4) *r1 = 0;
else *r1 = 0xc0;
a = (av_time + clock_time - 1)/clock_time;
if (a < 2)
a = 2;
b = (ds_time + clock_time - 1)/clock_time - a;
if (b < 2)
b = 2;
if (b > 0x11) {
a += b - 0x11;
b = 0x11;
}
if (a > 0xf)
a = 0;
if (cmd640_chip_version > 1)
b -= 1;
if (b > 0xf)
b = 0;
*r2 = (a << 4) | b;
}
static void set_pio_mode(int if_num, int drv_num, int mode_num) {
int p_base;
int i;
p_base = if_num ? 0x170 : 0x1f0;
outb(3, p_base + 1);
outb(mode_num | 8, p_base + 2);
outb((drv_num | 0xa) << 4, p_base + 6);
outb(0xef, p_base + 7);
for (i = 0; (i < 100) && (inb (p_base + 7) & 0x80); i++)
delay_10ms();
}
void cmd640_tune_drive(ide_drive_t* drive) {
int interface_number;
int drive_number;
int clock_time; /* ns */
int max_pio;
int mc_time, av_time, ds_time;
struct hd_driveid* id;
int r1, r2;
/*
* Determine if drive is under cmd640 control
*/
interface_number = HWIF(drive) - ide_hwifs;
if (!is_cmd640[interface_number])
return;
drive_number = drive - HWIF(drive)->drives;
clock_time = 1000/bus_speed;
id = drive->id;
if ((max_pio = known_drive_pio(id->model)) != -1) {
mc_time = pio_timings[max_pio].mc_time;
av_time = pio_timings[max_pio].av_time;
ds_time = pio_timings[max_pio].ds_time;
} else {
max_pio = id->tPIO;
mc_time = pio_timings[max_pio].mc_time;
av_time = pio_timings[max_pio].av_time;
ds_time = pio_timings[max_pio].ds_time;
if (id->field_valid & 2) {
if ((id->capability & 8) && (id->eide_pio_modes & 7)) {
if (id->eide_pio_modes & 4) max_pio = 5;
else if (id->eide_pio_modes & 2) max_pio = 4;
else max_pio = 3;
ds_time = id->eide_pio_iordy;
mc_time = pio_timings[max_pio].mc_time;
av_time = pio_timings[max_pio].av_time;
} else {
ds_time = id->eide_pio;
}
if (ds_time == 0)
ds_time = pio_timings[max_pio].ds_time;
}
}
cmd640_timings_to_regvals(mc_time, av_time, ds_time, clock_time,
&r1, &r2);
set_pio_mode(interface_number, drive_number, max_pio);
cmd640_set_timing(interface_number, drive_number, r1, r2);
printk ("Mode and Timing set to PIO%d (0x%x 0x%x)\n", max_pio, r1, r2);
}
...@@ -1089,10 +1089,8 @@ static inline void perpendicular_mode(void) ...@@ -1089,10 +1089,8 @@ static inline void perpendicular_mode(void)
{ {
unsigned char perp_mode; unsigned char perp_mode;
if (!floppy) if (raw_cmd->rate & 0x40){
return; switch(raw_cmd->rate & 3){
if (floppy->rate & 0x40){
switch(raw_cmd->rate){
case 0: case 0:
perp_mode=2; perp_mode=2;
break; break;
...@@ -1222,18 +1220,18 @@ static void fdc_specify(void) ...@@ -1222,18 +1220,18 @@ static void fdc_specify(void)
static int fdc_dtr(void) static int fdc_dtr(void)
{ {
/* If data rate not already set to desired value, set it. */ /* If data rate not already set to desired value, set it. */
if (raw_cmd->rate == FDCS->dtr) if ((raw_cmd->rate & 3) == FDCS->dtr)
return 0; return 0;
/* Set dtr */ /* Set dtr */
fd_outb(raw_cmd->rate, FD_DCR); fd_outb(raw_cmd->rate & 3, FD_DCR);
/* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB) /* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB)
* need a stabilization period of several milliseconds to be * need a stabilization period of several milliseconds to be
* enforced after data rate changes before R/W operations. * enforced after data rate changes before R/W operations.
* Pause 5 msec to avoid trouble. (Needs to be 2 jiffies) * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
*/ */
FDCS->dtr = raw_cmd->rate; FDCS->dtr = raw_cmd->rate & 3;
return(wait_for_completion(jiffies+2*HZ/100, return(wait_for_completion(jiffies+2*HZ/100,
(timeout_fn) floppy_ready)); (timeout_fn) floppy_ready));
} /* fdc_dtr */ } /* fdc_dtr */
...@@ -1979,7 +1977,7 @@ static void setup_format_params(int track) ...@@ -1979,7 +1977,7 @@ static void setup_format_params(int track)
raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
/*FD_RAW_NEED_DISK |*/ FD_RAW_NEED_SEEK; /*FD_RAW_NEED_DISK |*/ FD_RAW_NEED_SEEK;
raw_cmd->rate = floppy->rate & 0x3; raw_cmd->rate = floppy->rate & 0x43;
raw_cmd->cmd_count = NR_F; raw_cmd->cmd_count = NR_F;
COMMAND = FM_MODE(floppy,FD_FORMAT); COMMAND = FM_MODE(floppy,FD_FORMAT);
DR_SELECT = UNIT(current_drive) + PH_HEAD(floppy,format_req.head); DR_SELECT = UNIT(current_drive) + PH_HEAD(floppy,format_req.head);
...@@ -2385,7 +2383,7 @@ static int make_raw_rw_request(void) ...@@ -2385,7 +2383,7 @@ static int make_raw_rw_request(void)
SIZECODE = 2; SIZECODE = 2;
} else } else
SIZECODE = FD_SIZECODE(floppy); SIZECODE = FD_SIZECODE(floppy);
raw_cmd->rate = floppy->rate & 3; raw_cmd->rate = floppy->rate & 0x43;
if ((floppy->rate & FD_2M) && if ((floppy->rate & FD_2M) &&
(TRACK || HEAD) && (TRACK || HEAD) &&
raw_cmd->rate == 2) raw_cmd->rate == 2)
...@@ -2951,7 +2949,7 @@ static inline int raw_cmd_copyin(int cmd, char *param, ...@@ -2951,7 +2949,7 @@ static inline int raw_cmd_copyin(int cmd, char *param,
rcmd = & (ptr->next); rcmd = & (ptr->next);
if (!(ptr->flags & FD_RAW_MORE)) if (!(ptr->flags & FD_RAW_MORE))
return 0; return 0;
ptr->rate &= 0x03; ptr->rate &= 0x43;
} }
} }
......
/* /*
* linux/drivers/block/ide.c Version 5.17 Nov 3, 1995 * linux/drivers/block/ide.c Version 5.18 Nov 16, 1995
* *
* Copyright (C) 1994, 1995 Linus Torvalds & authors (see below) * Copyright (C) 1994, 1995 Linus Torvalds & authors (see below)
*/ */
/* /*
* This is the multiple IDE interface driver, as evolved from hd.c. * This is the multiple IDE interface driver, as evolved from hd.c.
* It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15). * It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15).
* There can be up to two drives per interface, as per the ATA-2 spec. * There can be up to two drives per interface, as per the ATA-2 spec.
* *
...@@ -13,17 +13,17 @@ ...@@ -13,17 +13,17 @@
* Secondary i/f: ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64 * Secondary i/f: ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64
* Tertiary i/f: ide2: major=33; (hde) minor=0; (hdf) minor=64 * Tertiary i/f: ide2: major=33; (hde) minor=0; (hdf) minor=64
* Quaternary i/f: ide3: major=34; (hdg) minor=0; (hdh) minor=64 * Quaternary i/f: ide3: major=34; (hdg) minor=0; (hdh) minor=64
* *
* It is easy to extend ide.c to handle more than four interfaces: * It is easy to extend ide.c to handle more than four interfaces:
* *
* Change the MAX_HWIFS constant in ide.h. * Change the MAX_HWIFS constant in ide.h.
* *
* Define some new major numbers (in major.h), and insert them into * Define some new major numbers (in major.h), and insert them into
* the ide_hwif_to_major table in ide.c. * the ide_hwif_to_major table in ide.c.
* *
* Fill in the extra values for the new interfaces into the two tables * Fill in the extra values for the new interfaces into the two tables
* inside ide.c: default_io_base[] and default_irqs[]. * inside ide.c: default_io_base[] and default_irqs[].
* *
* Create the new request handlers by cloning "do_ide3_request()" * Create the new request handlers by cloning "do_ide3_request()"
* for each new interface, and add them to the switch statement * for each new interface, and add them to the switch statement
* in the ide_init() function in ide.c. * in the ide_init() function in ide.c.
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
* Maintained by Mark Lord (mlord@bnr.ca): ide.c, ide.h, triton.c, hd.c, .. * Maintained by Mark Lord (mlord@bnr.ca): ide.c, ide.h, triton.c, hd.c, ..
* *
* This was a rewrite of just about everything from hd.c, though some original * This was a rewrite of just about everything from hd.c, though some original
* code is still sprinkled about. Think of it as a major evolution, with * code is still sprinkled about. Think of it as a major evolution, with
* inspiration from lots of linux users, esp. hamish@zot.apana.org.au * inspiration from lots of linux users, esp. hamish@zot.apana.org.au
* *
* Version 1.0 ALPHA initial code, primary i/f working okay * Version 1.0 ALPHA initial code, primary i/f working okay
...@@ -167,15 +167,18 @@ ...@@ -167,15 +167,18 @@
* remove "Huh?" from cmd640 code * remove "Huh?" from cmd640 code
* added qd6580 interface speed select from Colten Edwards * added qd6580 interface speed select from Colten Edwards
* Version 5.17 kludge around bug in BIOS32 on Intel triton motherboards * Version 5.17 kludge around bug in BIOS32 on Intel triton motherboards
* Version 5.18 new CMD640 code, moved to cmd640.c, #include'd for now
* new UMC8672 code, moved to umc8672.c, #include'd for now
* disallow turning on DMA when h/w not capable of DMA
* *
* Driver compile-time options are in ide.h * Driver compile-time options are in ide.h
* *
* To do, in likely order of completion: * To do, in likely order of completion:
* - make cmd640.c and umc8672.c compile separately from ide.c
* - add ALI M1443/1445 chipset support from derekn@vw.ece.cmu.edu * - add ALI M1443/1445 chipset support from derekn@vw.ece.cmu.edu
* - add Promise Caching controller support from peterd@pnd-pc.demon.co.uk
* - add ioctls to get/set interface timings on various interfaces * - add ioctls to get/set interface timings on various interfaces
* - add Promise Caching controller support from peterd@pnd-pc.demon.co.uk
* - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f * - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
* - improved CMD support: handed this off to someone else
* - find someone to work on IDE *tape drive* support * - find someone to work on IDE *tape drive* support
*/ */
...@@ -209,9 +212,14 @@ ...@@ -209,9 +212,14 @@
#include "ide.h" #include "ide.h"
#ifdef SUPPORT_CMD640
void cmd640_tune_drive(ide_drive_t *);
static int cmd640_vlb = 0;
#endif
ide_hwif_t ide_hwifs[MAX_HWIFS]; /* hwif info */ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* hwif info */
static ide_hwgroup_t *irq_to_hwgroup [16]; static ide_hwgroup_t *irq_to_hwgroup [16];
static const byte ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR}; static const byte ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};
static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168}; static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168};
static const byte default_irqs[MAX_HWIFS] = {14, 15, 11, 10}; static const byte default_irqs[MAX_HWIFS] = {14, 15, 11, 10};
...@@ -999,7 +1007,7 @@ static void write_intr (ide_drive_t *drive) ...@@ -999,7 +1007,7 @@ static void write_intr (ide_drive_t *drive)
/* /*
* multwrite() transfers a block of one or more sectors of data to a drive * multwrite() transfers a block of one or more sectors of data to a drive
* as part of a disk multwrite operation. * as part of a disk multwrite operation.
*/ */
static void multwrite (ide_drive_t *drive) static void multwrite (ide_drive_t *drive)
{ {
...@@ -1232,7 +1240,7 @@ static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned ...@@ -1232,7 +1240,7 @@ static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned
if (drive->select.b.lba) { if (drive->select.b.lba) {
#ifdef DEBUG #ifdef DEBUG
printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n", printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n",
drive->name, (rq->cmd==READ)?"read":"writ", drive->name, (rq->cmd==READ)?"read":"writ",
block, rq->nr_sectors, (unsigned long) rq->buffer); block, rq->nr_sectors, (unsigned long) rq->buffer);
#endif #endif
OUT_BYTE(block,io_base+IDE_SECTOR_OFFSET); OUT_BYTE(block,io_base+IDE_SECTOR_OFFSET);
...@@ -1495,7 +1503,7 @@ static void timer_expiry (unsigned long data) ...@@ -1495,7 +1503,7 @@ static void timer_expiry (unsigned long data)
printk("%s: marginal timeout\n", drive->name); printk("%s: marginal timeout\n", drive->name);
} else { /* drive not responding */ } else { /* drive not responding */
hwgroup->handler = NULL; hwgroup->handler = NULL;
if (hwgroup->hwif->dmaproc) if (hwgroup->hwif->dmaproc)
(void) hwgroup->hwif->dmaproc (ide_dma_abort, drive); (void) hwgroup->hwif->dmaproc (ide_dma_abort, drive);
if (!ide_error(drive, "irq timeout", GET_STAT())) if (!ide_error(drive, "irq timeout", GET_STAT()))
do_hwgroup_request (hwgroup); do_hwgroup_request (hwgroup);
...@@ -1522,7 +1530,7 @@ static void timer_expiry (unsigned long data) ...@@ -1522,7 +1530,7 @@ static void timer_expiry (unsigned long data)
* In reality, this is a non-issue. The new command is not sent unless the * In reality, this is a non-issue. The new command is not sent unless the
* drive is ready to accept one, in which case we know the drive is not * drive is ready to accept one, in which case we know the drive is not
* trying to interrupt us. And ide_set_handler() is always invoked before * trying to interrupt us. And ide_set_handler() is always invoked before
* completing the issuance of any new drive command, so we will not be * completing the issuance of any new drive command, so we will not be
* accidently invoked as a result of any valid command completion interrupt. * accidently invoked as a result of any valid command completion interrupt.
* *
*/ */
...@@ -1806,24 +1814,24 @@ static int ide_ioctl (struct inode *inode, struct file *file, ...@@ -1806,24 +1814,24 @@ static int ide_ioctl (struct inode *inode, struct file *file,
case BLKRAGET: case BLKRAGET:
return write_fs_long(arg, read_ahead[MAJOR(inode->i_rdev)]); return write_fs_long(arg, read_ahead[MAJOR(inode->i_rdev)]);
case BLKGETSIZE: /* Return device size */ case BLKGETSIZE: /* Return device size */
return write_fs_long(arg, drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects); return write_fs_long(arg, drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects);
case BLKRRPART: /* Re-read partition tables */ case BLKRRPART: /* Re-read partition tables */
return revalidate_disk(inode->i_rdev); return revalidate_disk(inode->i_rdev);
case HDIO_GET_KEEPSETTINGS: case HDIO_GET_KEEPSETTINGS:
return write_fs_long(arg, drive->keep_settings); return write_fs_long(arg, drive->keep_settings);
case HDIO_GET_UNMASKINTR: case HDIO_GET_UNMASKINTR:
return write_fs_long(arg, drive->unmask); return write_fs_long(arg, drive->unmask);
case HDIO_GET_DMA: case HDIO_GET_DMA:
return write_fs_long(arg, drive->using_dma); return write_fs_long(arg, drive->using_dma);
case HDIO_GET_CHIPSET: case HDIO_GET_CHIPSET:
return write_fs_long(arg, drive->chipset); return write_fs_long(arg, drive->chipset);
case HDIO_GET_MULTCOUNT: case HDIO_GET_MULTCOUNT:
return write_fs_long(arg, drive->mult_count); return write_fs_long(arg, drive->mult_count);
case HDIO_GET_IDENTITY: case HDIO_GET_IDENTITY:
...@@ -1858,6 +1866,10 @@ static int ide_ioctl (struct inode *inode, struct file *file, ...@@ -1858,6 +1866,10 @@ static int ide_ioctl (struct inode *inode, struct file *file,
cli(); cli();
switch (cmd) { switch (cmd) {
case HDIO_SET_DMA: case HDIO_SET_DMA:
if (!(HWIF(drive)->dmaproc)) {
restore_flags(flags);
return -EPERM;
}
drive->using_dma = arg; drive->using_dma = arg;
break; break;
case HDIO_SET_KEEPSETTINGS: case HDIO_SET_KEEPSETTINGS:
...@@ -2046,7 +2058,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ...@@ -2046,7 +2058,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
drive->present = 1; drive->present = 1;
drive->cyl = drive->bios_cyl = id->cyls; drive->cyl = drive->bios_cyl = id->cyls;
drive->head = drive->bios_head = id->heads; drive->head = drive->bios_head = id->heads;
drive->sect = drive->bios_sect = id->sectors; drive->sect = drive->bios_sect = id->sectors;
} }
/* Handle logical geometry translation by the drive */ /* Handle logical geometry translation by the drive */
if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads
...@@ -2055,7 +2067,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ...@@ -2055,7 +2067,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
/* /*
* Extract the physical drive geometry for our use. * Extract the physical drive geometry for our use.
* Note that we purposely do *not* update the bios info. * Note that we purposely do *not* update the bios info.
* This way, programs that use it (like fdisk) will * This way, programs that use it (like fdisk) will
* still have the same logical view as the BIOS does, * still have the same logical view as the BIOS does,
* which keeps the partition table from being screwed. * which keeps the partition table from being screwed.
* *
...@@ -2079,7 +2091,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ...@@ -2079,7 +2091,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
if ((!drive->head || drive->head > 16) && id->heads && id->heads <= 16) { if ((!drive->head || drive->head > 16) && id->heads && id->heads <= 16) {
drive->cyl = id->cyls; drive->cyl = id->cyls;
drive->head = id->heads; drive->head = id->heads;
drive->sect = id->sectors; drive->sect = id->sectors;
} }
/* Correct the number of cyls if the bios value is too small */ /* Correct the number of cyls if the bios value is too small */
if (drive->sect == drive->bios_sect && drive->head == drive->bios_head) { if (drive->sect == drive->bios_sect && drive->head == drive->bios_head) {
...@@ -2107,6 +2119,9 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ...@@ -2107,6 +2119,9 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
printk(", DMA"); printk(", DMA");
} }
printk("\n"); printk("\n");
#ifdef SUPPORT_CMD640
cmd640_tune_drive(drive); /* but can we tune a fish? */
#endif
} }
/* /*
...@@ -2336,8 +2351,8 @@ static void probe_for_drives (ide_hwif_t *hwif) ...@@ -2336,8 +2351,8 @@ static void probe_for_drives (ide_hwif_t *hwif)
* The code enables the secondary IDE controller and the PIO4 (3?) timings on * The code enables the secondary IDE controller and the PIO4 (3?) timings on
* the primary (EIDE). You may probably have to enable the 32-bit support to * the primary (EIDE). You may probably have to enable the 32-bit support to
* get the full speed. You better get the disk interrupts disabled ( hdparm -u0 * get the full speed. You better get the disk interrupts disabled ( hdparm -u0
* /dev/hd.. ) for the drives connected to the EIDE interface. (I get my * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my
* filesystem corrupted with -u1, but under heavy disk load only :-) * filesystem corrupted with -u1, but under heavy disk load only :-)
* *
* From: mlord@bnr.ca -- this chipset is now forced to use the "serialize" feature, * From: mlord@bnr.ca -- this chipset is now forced to use the "serialize" feature,
* which hopefully will make it more reliable to use.. maybe it has the same bugs * which hopefully will make it more reliable to use.. maybe it has the same bugs
...@@ -2417,59 +2432,13 @@ static void init_qd6580 (void) ...@@ -2417,59 +2432,13 @@ static void init_qd6580 (void)
} }
#endif /* SUPPORT_QD6580 */ #endif /* SUPPORT_QD6580 */
#if SUPPORT_CMD640 #ifdef SUPPORT_UMC8672
/* #include "umc8672.c" /* until we tidy up the interface some more */
* ??? fixme:
*/
byte read_cmd640_vlb (byte port, byte reg)
{
byte val;
unsigned long flags;
save_flags(flags);
cli();
outw(reg, port);
val = inb(port+4);
restore_flags(flags);
return val;
}
void write_cmd640_vlb (byte port, byte reg, byte val)
{
unsigned long flags;
save_flags(flags);
cli();
outw(reg, port);
outw(val, port+4);
restore_flags(flags);
}
void init_cmd640_vlb (void)
{
byte reg;
unsigned short port = 0x178;
serialized = 1;
printk("ide: buggy CMD640 interface: serialized, ");
reg = read_cmd640_vlb(port, 0x50);
if (reg == 0xff || (reg & 0x90) != 0x90) {
#if TRY_CMD640_VLB_AT_0x78
port = 0x78;
reg = read_cmd640_vlb(port, 0x50);
if (reg == 0xff || (reg & 0x90) != 0x90)
#endif #endif
{
disallow_unmask = 1;
printk("(probe failed) disabled unmasking\n");
return;
}
}
write_cmd640_vlb(port, 0x51, read_cmd640_vlb(port, 0x51)|0xc8);
write_cmd640_vlb(port, 0x57, read_cmd640_vlb(port, 0x57)|0x0c);
printk("disabled read-ahead, enabled secondary\n");
} #ifdef SUPPORT_CMD640
#endif /* SUPPORT_CMD640 */ #include "cmd640.c" /* until we tidy up the interface some more */
#endif
/* /*
* stridx() returns the offset of c within s, * stridx() returns the offset of c within s,
...@@ -2488,7 +2457,7 @@ static int stridx (const char *s, char c) ...@@ -2488,7 +2457,7 @@ static int stridx (const char *s, char c)
* 2. if the remainder matches one of the supplied keywords, * 2. if the remainder matches one of the supplied keywords,
* the index (1 based) of the keyword is negated and returned. * the index (1 based) of the keyword is negated and returned.
* 3. if the remainder is a series of no more than max_vals numbers * 3. if the remainder is a series of no more than max_vals numbers
* separated by commas, the numbers are saved in vals[] and a * separated by commas, the numbers are saved in vals[] and a
* count of how many were saved is returned. Base10 is assumed, * count of how many were saved is returned. Base10 is assumed,
* and base16 is allowed when prefixed with "0x". * and base16 is allowed when prefixed with "0x".
* 4. otherwise, zero is returned. * 4. otherwise, zero is returned.
...@@ -2511,7 +2480,7 @@ static int match_parm (char *s, const char *keywords[], int vals[], int max_vals ...@@ -2511,7 +2480,7 @@ static int match_parm (char *s, const char *keywords[], int vals[], int max_vals
/* /*
* Look for a series of no more than "max_vals" * Look for a series of no more than "max_vals"
* numeric values separated by commas, in base10, * numeric values separated by commas, in base10,
* or base16 when prefixed with "0x". * or base16 when prefixed with "0x".
* Return a count of how many were found. * Return a count of how many were found.
*/ */
for (n = 0; (i = stridx(decimal, *s)) >= 0;) { for (n = 0; (i = stridx(decimal, *s)) >= 0;) {
...@@ -2621,11 +2590,18 @@ void ide_setup (char *s) ...@@ -2621,11 +2590,18 @@ void ide_setup (char *s)
* Look for interface options: "idex=" * Look for interface options: "idex="
*/ */
if (s[0] == 'i' && s[1] == 'd' && s[2] == 'e' && s[3] >= '0' && s[3] <= max_hwif) { if (s[0] == 'i' && s[1] == 'd' && s[2] == 'e' && s[3] >= '0' && s[3] <= max_hwif) {
const char *ide_words[] = {"noprobe", "serialize", "dtc2278", "ht6560b", "cmd640_vlb", "qd6580", NULL}; const char *ide_words[] = {"noprobe", "serialize", "dtc2278", "ht6560b",
"cmd640_vlb", "qd6580", "umc8672", NULL};
hw = s[3] - '0'; hw = s[3] - '0';
hwif = &ide_hwifs[hw]; hwif = &ide_hwifs[hw];
switch (match_parm(&s[4], ide_words, vals, 3)) { switch (match_parm(&s[4], ide_words, vals, 3)) {
#if SUPPORT_UMC8672
case -7: /* "umc8672" */
if (hw != 0) goto bad_hwif;
init_umc8672();
goto done;
#endif /* SUPPORT_UMC8672 */
#if SUPPORT_QD6580 #if SUPPORT_QD6580
case -6: /* "qd6580" */ case -6: /* "qd6580" */
if (hw != 0) goto bad_hwif; if (hw != 0) goto bad_hwif;
...@@ -2635,8 +2611,7 @@ void ide_setup (char *s) ...@@ -2635,8 +2611,7 @@ void ide_setup (char *s)
#if SUPPORT_CMD640 #if SUPPORT_CMD640
case -5: /* "cmd640_vlb" */ case -5: /* "cmd640_vlb" */
if (hw > 1) goto bad_hwif; if (hw > 1) goto bad_hwif;
init_cmd640_vlb(); cmd640_vlb = 1;
goto do_serialize; /* not necessary once we implement the above */
break; break;
#endif /* SUPPORT_CMD640 */ #endif /* SUPPORT_CMD640 */
#if SUPPORT_HT6560B #if SUPPORT_HT6560B
...@@ -2709,7 +2684,7 @@ int ide_xlate_1024 (kdev_t i_rdev, int offset, const char *msg) ...@@ -2709,7 +2684,7 @@ int ide_xlate_1024 (kdev_t i_rdev, int offset, const char *msg)
drive->cyl = drive->bios_cyl = drive->id->cyls; drive->cyl = drive->bios_cyl = drive->id->cyls;
drive->head = drive->bios_head = drive->id->heads; drive->head = drive->bios_head = drive->id->heads;
drive->sect = drive->bios_sect = drive->id->sectors; drive->sect = drive->bios_sect = drive->id->sectors;
drive->special.b.set_geometry = 1; drive->special.b.set_geometry = 1;
tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63; tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63;
...@@ -2745,7 +2720,7 @@ int ide_xlate_1024 (kdev_t i_rdev, int offset, const char *msg) ...@@ -2745,7 +2720,7 @@ int ide_xlate_1024 (kdev_t i_rdev, int offset, const char *msg)
* drives in the system -- the ones reflected as drive 1 or 2. The first * drives in the system -- the ones reflected as drive 1 or 2. The first
* drive is stored in the high nibble of CMOS byte 0x12, the second in the low * drive is stored in the high nibble of CMOS byte 0x12, the second in the low
* nibble. This will be either a 4 bit drive type or 0xf indicating use byte * nibble. This will be either a 4 bit drive type or 0xf indicating use byte
* 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value
* means we have an AT controller hard disk for that drive. * means we have an AT controller hard disk for that drive.
* *
* Of course, there is no guarantee that either drive is actually on the * Of course, there is no guarantee that either drive is actually on the
...@@ -2905,45 +2880,6 @@ void init_rz1000 (byte bus, byte fn) ...@@ -2905,45 +2880,6 @@ void init_rz1000 (byte bus, byte fn)
} }
#endif /* SUPPORT_RZ1000 */ #endif /* SUPPORT_RZ1000 */
#if SUPPORT_CMD640
void init_cmd640 (byte bus, byte fn)
{
int rc;
unsigned char reg;
serialized = 1;
printk("ide: buggy CMD640 interface: ");
#if 0 /* funny.. the cmd640b I tried this on claimed to not be enabled.. */
unsigned short sreg;
if ((rc = pcibios_read_config_word (bus, fn, PCI_COMMAND, &sreg))) {
ide_pci_access_error (rc);
} else if (!(sreg & 1)) {
printk("not enabled\n");
} else {
/*
* The first part is undocumented magic from the DOS driver.
* According to the datasheet, there is no port 0x5b on the cmd640.
*/
(void) pcibios_write_config_byte(bus, fn, 0x5b, 0xbd);
if (pcibios_write_config_byte(bus, fn, 0x5b, 0xbd) != 0xbd)
printk("init_cmd640: huh? 0x5b read back wrong\n");
(void) pcibios_write_config_byte(bus, fn, 0x5b, 0);
#endif /* 0 */
/*
* The rest is from the cmd640b datasheet.
*/
if ((rc = pcibios_read_config_byte(bus, fn, 0x51, &reg))
|| (rc = pcibios_write_config_byte(bus, fn, 0x51, reg | 0xc0)) /* 0xc8 to enable 2nd i/f */
|| (rc = pcibios_read_config_byte(bus, fn, 0x57, &reg))
|| (rc = pcibios_write_config_byte(bus, fn, 0x57, reg | 0x0c)))
buggy_interface_fallback (rc);
else
printk("serialized, disabled read-ahead\n");
}
#endif /* SUPPORT_CMD640 */
typedef void (ide_pci_init_proc_t)(byte, byte); typedef void (ide_pci_init_proc_t)(byte, byte);
/* /*
...@@ -2966,7 +2902,7 @@ static void ide_probe_pci (unsigned short vendor, unsigned short device, ide_pci ...@@ -2966,7 +2902,7 @@ static void ide_probe_pci (unsigned short vendor, unsigned short device, ide_pci
/* /*
* ide_init_pci() finds/initializes "known" PCI IDE interfaces * ide_init_pci() finds/initializes "known" PCI IDE interfaces
* *
* This routine should ideally be using pcibios_find_class() to find * This routine should ideally be using pcibios_find_class() to find
* all IDE interfaces, but that function causes some systems to "go weird". * all IDE interfaces, but that function causes some systems to "go weird".
*/ */
...@@ -2975,9 +2911,6 @@ static void ide_init_pci (void) ...@@ -2975,9 +2911,6 @@ static void ide_init_pci (void)
#if SUPPORT_RZ1000 #if SUPPORT_RZ1000
ide_probe_pci (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, &init_rz1000, 0); ide_probe_pci (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, &init_rz1000, 0);
#endif #endif
#if SUPPORT_CMD640
ide_probe_pci (PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640, &init_cmd640, 0);
#endif
#ifdef CONFIG_BLK_DEV_TRITON #ifdef CONFIG_BLK_DEV_TRITON
/* /*
* Apparently the BIOS32 services on Intel motherboards are buggy, * Apparently the BIOS32 services on Intel motherboards are buggy,
...@@ -3008,6 +2941,9 @@ int ide_init (void) ...@@ -3008,6 +2941,9 @@ int ide_init (void)
if (pcibios_present()) if (pcibios_present())
ide_init_pci (); ide_init_pci ();
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
#ifdef SUPPORT_CMD640
ide_probe_for_cmd640x();
#endif
/* /*
* Probe for drives in the usual way.. CMOS/BIOS, then poke at ports * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports
......
...@@ -40,6 +40,9 @@ ...@@ -40,6 +40,9 @@
#ifndef SUPPORT_CMD640 /* 1 to support CMD640 chipset */ #ifndef SUPPORT_CMD640 /* 1 to support CMD640 chipset */
#define SUPPORT_CMD640 1 /* 0 to reduce kernel size */ #define SUPPORT_CMD640 1 /* 0 to reduce kernel size */
#endif #endif
#ifndef SUPPORT_UMC8672 /* 1 to support UMC8672 chipset */
#define SUPPORT_UMC8672 1 /* 0 to reduce kernel size */
#endif
#ifndef SUPPORT_HT6560B /* 1 to support HT6560B chipset */ #ifndef SUPPORT_HT6560B /* 1 to support HT6560B chipset */
#define SUPPORT_HT6560B 1 /* 0 to reduce kernel size */ #define SUPPORT_HT6560B 1 /* 0 to reduce kernel size */
#endif #endif
......
...@@ -229,6 +229,19 @@ void set_device_ro(kdev_t dev,int flag) ...@@ -229,6 +229,19 @@ void set_device_ro(kdev_t dev,int flag)
else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31)); else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
} }
static inline void drive_stat_acct(int cmd, unsigned long nr_sectors, short disk_index)
{
kstat.dk_drive[disk_index]++;
if (cmd == READ || cmd == READA) {
kstat.dk_drive_rio[disk_index]++;
kstat.dk_drive_rblk[disk_index] += nr_sectors;
}
else if (cmd == WRITE || cmd == WRITEA) {
kstat.dk_drive_wio[disk_index]++;
kstat.dk_drive_wblk[disk_index] += nr_sectors;
}
}
/* /*
* add-request adds a request to the linked list. * add-request adds a request to the linked list.
* It disables interrupts so that it can muck with the * It disables interrupts so that it can muck with the
...@@ -243,16 +256,16 @@ static void add_request(struct blk_dev_struct * dev, struct request * req) ...@@ -243,16 +256,16 @@ static void add_request(struct blk_dev_struct * dev, struct request * req)
case SCSI_DISK_MAJOR: case SCSI_DISK_MAJOR:
disk_index = (MINOR(req->rq_dev) & 0x0070) >> 4; disk_index = (MINOR(req->rq_dev) & 0x0070) >> 4;
if (disk_index < 4) if (disk_index < 4)
kstat.dk_drive[disk_index]++; drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
break; break;
case IDE0_MAJOR: /* same as HD_MAJOR */ case IDE0_MAJOR: /* same as HD_MAJOR */
case XT_DISK_MAJOR: case XT_DISK_MAJOR:
disk_index = (MINOR(req->rq_dev) & 0x0040) >> 6; disk_index = (MINOR(req->rq_dev) & 0x0040) >> 6;
kstat.dk_drive[disk_index]++; drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
break; break;
case IDE1_MAJOR: case IDE1_MAJOR:
disk_index = ((MINOR(req->rq_dev) & 0x0040) >> 6) + 2; disk_index = ((MINOR(req->rq_dev) & 0x0040) >> 6) + 2;
kstat.dk_drive[disk_index]++; drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
default: default:
break; break;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment