VERSION = 1
PATCHLEVEL = 0
-SUBLEVEL = 4
+SUBLEVEL = 5
all: Version zImage
AS =as
LD =ld
+LDFLAGS =#-qmagic
HOSTCC =gcc
CC =gcc -D__KERNEL__
MAKE =make
--Bill Metzenthen
- Feb 1994
+ March 1994
----------------------- Internals of wm-FPU-emu -----------------------
----------------------- Limitations of wm-FPU-emu -----------------------
There are a number of differences between the current wm-FPU-emu
-(version beta 1.10) and the 80486 FPU (apart from bugs). Some of the
+(version beta 1.11) and the 80486 FPU (apart from bugs). Some of the
more important differences are listed below:
The Roundup flag does not have much meaning for the transcendental
exception. For this case, the emulator cannot emulate the behaviour of
an 80486DX.
+Handling of the address size override prefix byte (0x67) has not been
+extensively tested yet. A major problem exists because using it in
+vm86 mode can cause a general protection fault. Address offsets
+greater than 0xffff appear to be illegal in vm86 mode but are quite
+acceptable (and work) in real mode. A small test program developed to
+check the addressing, and which runs successfully in real mode,
+crashes dosemu under Linux and also brings Windows down with a general
+protection fault message when run under the MS-DOS prompt of Windows
+3.1. (The program simply reads data from a valid address).
+
+
----------------------- Performance of wm-FPU-emu -----------------------
Speed.
Hamish Coleman, t933093@minyos.xx.rmit.oz.au
Bruce Evans, bde@kralizec.zeta.org.au
Timo Korvola, Timo.Korvola@hut.fi
+Rick Lyons, rick@razorback.brisnet.org.au
...and numerous others who responded to my request for help with
a real 80486.
#define PREFIX_FS_ 4
#define PREFIX_GS_ 5
#define PREFIX_SS_ 6
+#define PREFIX_DEFAULT 7
/* These are to defeat the default action, giving the instruction
no net effect: */
RE_ENTRANT_CHECK_OFF;
FPU_code_verify_area(1);
- FPU_modrm = get_fs_byte((unsigned short *) FPU_EIP);
+ FPU_modrm = get_fs_byte((unsigned char *) FPU_EIP);
RE_ENTRANT_CHECK_ON;
FPU_EIP++;
FPU_EIP = FPU_ORIG_EIP; /* Point to current FPU instruction. */
+ if ( addr_modes.vm86 )
+ FPU_EIP -= FPU_CS << 4;
+
RE_ENTRANT_CHECK_OFF;
current->tss.trap_no = 16;
current->tss.error_code = 0;
get_address_16(FPU_modrm, &FPU_EIP, addr_modes);
else
get_address(FPU_modrm, &FPU_EIP, addr_modes);
+
if ( !(byte1 & 1) )
{
unsigned short status1 = partial_status;
unsigned char byte;
unsigned char *ip = *fpu_eip;
- *override = (overrides) { 0, 0, PREFIX_DS_ }; /* defaults */
+ *override = (overrides) { 0, 0, PREFIX_DEFAULT }; /* defaults */
RE_ENTRANT_CHECK_OFF;
FPU_code_verify_area(1);
case PREFIX_GS:
override->segment = PREFIX_GS_;
goto do_next_byte;
-
- case PREFIX_DS: /* Redundant unless preceded by another override. */
+ case PREFIX_DS:
override->segment = PREFIX_DS_;
+ goto do_next_byte;
/* lock is not a valid prefix for FPU instructions,
let the cpu handle it to generate a SIGILL. */
offsetof(struct info,___vm86_es),
offsetof(struct info,___vm86_fs),
offsetof(struct info,___vm86_gs),
- offsetof(struct info,___ss)
+ offsetof(struct info,___ss),
+ offsetof(struct info,___vm86_ds)
};
#define VM86_REG_(x) (*(unsigned short *) \
break;
case 2:
offset += FPU_info->___ebp + FPU_info->___esi;
+ if ( addr_modes.override.segment == PREFIX_DEFAULT )
+ addr_modes.override.segment = PREFIX_SS_;
break;
case 3:
offset += FPU_info->___ebp + FPU_info->___edi;
+ if ( addr_modes.override.segment == PREFIX_DEFAULT )
+ addr_modes.override.segment = PREFIX_SS_;
break;
case 4:
offset += FPU_info->___esi;
break;
case 6:
offset += FPU_info->___ebp;
+ if ( addr_modes.override.segment == PREFIX_DEFAULT )
+ addr_modes.override.segment = PREFIX_SS_;
break;
case 7:
offset += FPU_info->___ebx;
FPU_data_address = (void *)offset ;
}
-
| |
+---------------------------------------------------------------------------*/
-#define FPU_VERSION "wm-FPU-emu version Beta 1.10"
+#define FPU_VERSION "wm-FPU-emu version Beta 1.11"
sizeof (pid_t));
if (retval)
return retval;
- if (current->tty != termios_dev)
+ /* If a master pty, return the slave's tpgid.
+ If not, only return the tpgid if this is
+ the controlling tty. */
+ if (tty == termios_tty && current->tty != dev)
return -ENOTTY;
put_fs_long(termios_tty->pgrp, (pid_t *) arg);
return 0;
#AHA152X = -DDEBUG -DAUTOCONF -DIRQ=11 -DSCSI_ID=7 -DRECONNECT=0 \
# -DPORTBASE=0x340 -DSKIP_BIOSTEST -DDONT_SNARF
-AHA152X = -DDEBUG -DAUTOCONF
+AHA152X = -DDEBUG_AHA152X -DAUTOCONF
SCSI_OBJS =
SCSI_SRCS =
/* aha152x.c -- Adaptec AHA-152x driver
* Author: Juergen E. Fischer, fischer@server.et-inf.fho-emden.de
- * Copyright 1993 Juergen E. Fischer
+ * Copyright 1993, 1994 Juergen E. Fischer
*
*
* This driver is based on
* General Public License for more details.
*
- * $Id: aha152x.c,v 0.101 1993/12/13 01:16:27 root Exp $
+ * $Id: aha152x.c,v 1.0 1994/03/25 12:52:00 root Exp $
*
* $Log: aha152x.c,v $
+ * Revision 1.0 1994/03/25 12:52:00 root
+ * - Fixed "more data than expected" problem
+ * - added new BIOS signatures
+ *
+ * Revision 0.102 1994/01/31 20:44:12 root
+ * - minor changes in insw/outsw handling
+ *
* Revision 0.101 1993/12/13 01:16:27 root
* - fixed STATUS phase (non-GOOD stati were dropped sometimes;
* fixes problems with CD-ROM sector size detection & media change)
/* I use this when I'm looking for weird bugs */
#define DEBUG_TIMING
-#if defined(DEBUG)
+#if defined(DEBUG_AHA152X)
#undef SKIP_PORTS /* don't display ports */
#define P_BUSFREE 1
#define P_PARITY 2
-char *aha152x_id = "Adaptec 152x SCSI driver; $Revision: 0.101 $\n";
+static char *aha152x_id = AHA152X_REVID;
static int port_base = 0;
static int this_host = 0;
/* possible interrupt channels */
static unsigned short ints[] = { 9, 10, 11, 12 };
-/* signatures for various AIC-6260 based controllers */
+/* signatures for various AIC-6[23]60 based controllers.
+ The point in detecting signatures is to avoid useless
+ and maybe harmful probes on ports. I'm not sure that
+ all listed boards pass auto-configuration. For those
+ which fail the BIOS signature is obsolete, because
+ user intervention to supply the configuration is
+ needed anyway. */
static struct signature {
char *signature;
int sig_offset;
int sig_length;
} signatures[] =
{
- {
- "Adaptec AHA-1520 BIOS\r\n\0\
-Version 1.4 \r\n\0\
-Copyright 1990 Adaptec, Inc.\r\n\
-All Rights Reserved\r\n \r\n \r\n", 0x102e, 101
- }, /* Adaptec 152x */
- {
- "Adaptec ASW-B626 BIOS\r\n\0\
-Version 1.0 \r\n\0\
-Copyright 1990 Adaptec, Inc.\r\n\
-All Rights Reserved\r\n\0 \r\n \r\n", 0x1029, 102
- }, /* on-board controller */
- { "Adaptec BIOS: ASW-B626", 0x0F, 22}, /* on-board controller */
- { "Adaptec ASW-B626 S2 BIOS", 0x2e6c, 24}, /* on-board controller */
+ { "Adaptec AHA-1520 BIOS", 0x102e, 21 }, /* Adaptec 152x */
+ { "Adaptec ASW-B626 BIOS", 0x1029, 21 }, /* on-board controller */
+ { "Adaptec BIOS: ASW-B626", 0x0f, 22 }, /* on-board controller */
+ { "Adaptec ASW-B626 S2", 0x2e6c, 19 }, /* on-board controller */
+ { "Adaptec BIOS:AIC-6360", 0xc, 21 }, /* on-board controller */
+ { "ScsiPro SP-360 BIOS", 0x2873, 19 }, /* ScsiPro-Controller with AIC-6360 */
+ { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 }, /* Gigabyte Local-Bus-SCSI */
};
#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
enter_driver("detect");
#endif
- printk("aha152x: Probing: ");
-
if(setup_called)
{
- printk("processing commandline: ");
+ printk("aha152x: processing commandline: ");
if(setup_called!=4)
{
printk("reconnect %d should be 0 or 1\n", can_disconnect);
panic("aha152x panics in line %d", __LINE__);
}
- printk("ok, ");
+ printk("ok\n");
}
else
{
#if !defined(SKIP_BIOSTEST)
- printk("BIOS test: ");
ok=0;
for( i=0; i < ADDRESS_COUNT && !ok; i++)
for( j=0; (j < SIGNATURE_COUNT) && !ok; j++)
printk("failed\n");
return 0;
}
- printk("ok, ");
+ printk("aha152x: BIOS test: passed, ");
+#else
+ printk("aha152x: ");
#endif /* !SKIP_BIOSTEST */
#if !defined(PORTBASE)
*/
const char *aha152x_info(void)
{
-#if defined(DEBUG_RACE)
- enter_driver("info");
- leave_driver("info");
-#else
-#if defined(DEBUG_INFO)
- printk("\naha152x: info()\n");
-#endif
-#endif
return(aha152x_id);
}
cli();
#if defined(DEBUG_ABORT)
- printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned long) SCpnt );
+ printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt );
#endif
show_queues();
*/
int aha152x_biosparam( int size, int dev, int *info_array )
{
-#if defined(DEBUG_RACE)
- enter_driver("biosparam");
-#else
#if defined(DEBUG_BIOSPARAM)
- printk("\naha152x: biosparam(), ");
-#endif
-#endif
-
-#if defined(DEBUG_BIOSPARAM)
- printk("dev=%x, size=%d, ", dev, size);
+ printk("aha152x_biosparam: dev=%x, size=%d, ", dev, size);
#endif
/* I took this from other SCSI drivers, since it provides
printk("WARNING: check, if the bios geometry is correct.\n");
#endif
-#if defined(DEBUG_RACE)
- leave_driver("biosparam");
-#endif
return 0;
}
;
if( TESTHI( DMASTAT, DFIFOFULL ) )
- fifodata=132;
+ fifodata=GETPORT(FIFOSTAT);
else
{
/* wait for SCSI fifo to get empty */
}
}
- /* rare (but possible) status bytes (probably also DISCONNECT
- messages) get transfered in the data phase, so I assume 1
- additional byte is ok */
- if(fifodata>1)
+ /*
+ * Fifo should be empty
+ */
+ if(fifodata>0)
{
printk("aha152x: more data than expected (%d bytes)\n",
GETPORT(FIFOSTAT));
+ SETBITS(DMACNTRL0, _8BIT );
+ printk("aha152x: data ( ");
+ while(fifodata--)
+ printk("%2x ", GETPORT( DATAPORT ));
+ printk(")\n");
}
#if defined(DEBUG_DATAI)
int i;
printk("0x%08x: target=%d; lun=%d; cmnd=( ",
- (unsigned long) ptr, ptr->target, ptr->lun);
+ (unsigned int) ptr, ptr->target, ptr->lun);
for(i=0; i<COMMAND_SIZE(ptr->cmnd[0]); i++)
printk("%02x ", ptr->cmnd[i]);
if(ptr->SCp.phase & (1<<16))
printk("; phaseend");
}
- printk("; next=0x%08x\n", (unsigned long) ptr->host_scribble);
+ printk("; next=0x%08x\n", (unsigned int) ptr->host_scribble);
}
/*
#define _AHA152X_H
/*
- * $Id: aha152x.h,v 0.2 1993/10/03 00:58:03 root Exp $
+ * $Id: aha152x.h,v 1.0 1994/03/25 12:52:00 root Exp $
*/
#include "../block/blk.h"
(unless we support more than 1 cmd_per_lun this should do) */
#define AHA152X_MAXQUEUE 7
+#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.0 $"
+
/* Initial value of Scsi_Host entry */
-#define AHA152X { /* name */ "Adaptec 152x SCSI driver", \
+#define AHA152X { /* name */ AHA152X_REVID, \
/* detect */ aha152x_detect, \
/* info */ aha152x_info, \
/* command */ aha152x_command, \
printk("status=%x intrflags=%x\n", s, i, WAITnexttimeout-WAITtimeout); */
}
+/* This is a bit complicated, but we need to make sure that an interrupt
+ routine does not send something out while we are in the middle of this.
+ Fortunately, it is only at boot time that multi-byte messages
+ are ever sent. */
static int aha1542_out(unsigned int base, unchar *cmdp, int len)
{
+ if(len == 1) {
+ while(1==1){
+ WAIT(STATUS(base), CDF, 0, CDF);
+ cli();
+ if(inb(STATUS(base)) & CDF) {sti(); continue;}
+ outb(*cmdp, DATA(base));
+ sti();
+ return 0;
+ }
+ } else {
+ cli();
while (len--)
{
- WAIT(STATUS(base), CDF, 0, CDF);
- outb(*cmdp++, DATA(base));
+ WAIT(STATUS(base), CDF, 0, CDF);
+ outb(*cmdp++, DATA(base));
}
+ sti();
+ }
return 0;
fail:
+ sti();
printk("aha1542_out failed(%d): ", len+1); aha1542_stat();
return 1;
}
+/* Only used at boot time, so we do not need to worry about latency as much
+ here */
static int aha1542_in(unsigned int base, unchar *cmdp, int len)
{
+ cli();
while (len--)
{
WAIT(STATUS(base), DF, DF, 0);
*cmdp++ = inb(DATA(base));
}
+ sti();
return 0;
fail:
+ sti();
printk("aha1542_in failed(%d): ", len+1); aha1542_stat();
return 1;
}
port_base = ports[i];
if (check_region( port_base, 0x10 )) {
#if DEBUG_DETECT
- printf( " (%x inuse),", port_base );
+ printk( " (%x inuse),", port_base );
#endif
continue;
}
static int get_kstat(char * buffer)
{
- return sprintf(buffer, "cpu %u %u %u %lu\n"
- "disk %u %u %u %u\n"
- "page %u %u\n"
- "swap %u %u\n"
- "intr %u\n"
- "ctxt %u\n"
- "btime %lu\n",
- kstat.cpu_user,
- kstat.cpu_nice,
- kstat.cpu_system,
- jiffies - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
- kstat.dk_drive[0],
- kstat.dk_drive[1],
- kstat.dk_drive[2],
- kstat.dk_drive[3],
- kstat.pgpgin,
- kstat.pgpgout,
- kstat.pswpin,
- kstat.pswpout,
- kstat.interrupts,
- kstat.context_swtch,
- xtime.tv_sec - jiffies / HZ);
+ int i, len;
+ unsigned sum = 0;
+
+ for (i = 0 ; i < 16 ; i++)
+ sum += kstat.interrupts[i];
+ len = sprintf(buffer,
+ "cpu %u %u %u %lu\n"
+ "disk %u %u %u %u\n"
+ "page %u %u\n"
+ "swap %u %u\n"
+ "%u",
+ kstat.cpu_user,
+ kstat.cpu_nice,
+ kstat.cpu_system,
+ jiffies - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
+ kstat.dk_drive[0],
+ kstat.dk_drive[1],
+ kstat.dk_drive[2],
+ kstat.dk_drive[3],
+ kstat.pgpgin,
+ kstat.pgpgout,
+ kstat.pswpin,
+ kstat.pswpout,
+ sum);
+ for (i = 0 ; i < 16 ; i++)
+ len += sprintf(buffer + len, " %u", kstat.interrupts[i]);
+ len += sprintf(buffer + len,
+ "\nctxt %u\n"
+ "btime %lu\n",
+ kstat.context_swtch,
+ xtime.tv_sec - jiffies / HZ);
+ return len;
}
struct nfs_inode_info nfs_i;
struct xiafs_inode_info xiafs_i;
struct sysv_inode_info sysv_i;
+ void * generic_ip;
} u;
};
struct nfs_sb_info nfs_sb;
struct xiafs_sb_info xiafs_sb;
struct sysv_sb_info sysv_sb;
+ void *generic_sbp;
} u;
};
unsigned int dk_drive[DK_NDRIVE];
unsigned int pgpgin, pgpgout;
unsigned int pswpin, pswpout;
- unsigned int interrupts;
+ unsigned int interrupts[16];
unsigned int ipackets, opackets;
unsigned int ierrors, oerrors;
unsigned int collisions;
#define MAX_INIT_ARGS 8
#define MAX_INIT_ENVS 8
#define COMMAND_LINE ((char *) (PARAM+2048))
+#define COMMAND_LINE_SIZE 256
extern void time_init(void);
static char fpu_error = 0;
-static char command_line[80] = { 0, };
+static char command_line[COMMAND_LINE_SIZE] = { 0, };
char *get_options(char *str, int *ints)
{
static void copy_options(char * to, char * from)
{
char c = ' ';
+ int len = 0;
- do {
- if (c == ' ' && !memcmp("mem=", from, 4))
+ for (;;) {
+ if (c == ' ' && *(unsigned long *)from == *(unsigned long *)"mem=")
memory_end = simple_strtoul(from+4, &from, 0);
- c = *(to++) = *(from++);
- } while (c);
+ c = *(from++);
+ if (!c)
+ break;
+ if (COMMAND_LINE_SIZE <= ++len)
+ break;
+ *(to++) = c;
+ }
+ *to = '\0';
}
static void copro_timeout(void)
{
struct sigaction * sa = irq + irq_sigaction;
- kstat.interrupts++;
+ kstat.interrupts[irq]++;
sa->sa_handler((int) regs);
}
{
struct sigaction * sa = irq + irq_sigaction;
- kstat.interrupts++;
+ kstat.interrupts[irq]++;
sa->sa_handler(irq);
}