]> Zhao Yanbai Git Server - minix.git/commitdiff
bios_wini driver
authorPhilip Homburg <philip@cs.vu.nl>
Fri, 29 Jul 2005 10:21:04 +0000 (10:21 +0000)
committerPhilip Homburg <philip@cs.vu.nl>
Fri, 29 Jul 2005 10:21:04 +0000 (10:21 +0000)
18 files changed:
drivers/Makefile
drivers/bios_wini/Makefile [new file with mode: 0644]
drivers/bios_wini/bios_wini.c [new file with mode: 0644]
include/ibm/int86.h
include/minix/com.h
include/minix/config.h
include/minix/syslib.h
kernel/system.c
kernel/system.h
kernel/system/Makefile
kernel/system/do_bios.c [new file with mode: 0644]
kernel/system/do_getinfo.c
kernel/system/do_int86.c [new file with mode: 0644]
kernel/table.c
lib/syslib/Makefile
lib/syslib/sys_int86.c [new file with mode: 0644]
servers/fs/dmap.c
tools/Makefile

index 56ac13ff541af3e078869083a8fc32c08869c3da..f3f0d7c98b7ae7ddcd0bbb4e35b78cb180c70f6a 100644 (file)
@@ -25,3 +25,4 @@ all install depend clean:
        cd ./fxp && $(MAKE) $@
        cd ./dpeth && $(MAKE) $@
        cd ./log && $(MAKE) $@
+       cd ./bios_wini && $(MAKE) $@
diff --git a/drivers/bios_wini/Makefile b/drivers/bios_wini/Makefile
new file mode 100644 (file)
index 0000000..f2922fd
--- /dev/null
@@ -0,0 +1,46 @@
+# Makefile for the BIOS disk driver (BIOS_WINI)
+DRIVER = bios_wini
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+MAKE = exec make
+CC =   exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsysutil -lsys -ltimers
+
+OBJ = bios_wini.o 
+LIBDRIVER = $d/libdriver/driver.o $d/libdriver/drvlib.o
+
+
+# build local binary
+all build:     $(DRIVER)
+$(DRIVER):     $(OBJ) $(LIBDRIVER)
+       $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS)
+       install -S 256w $(DRIVER)
+
+$(LIBDRIVER): 
+       cd $d/libdriver && $(MAKE) 
+
+# install with other drivers
+install:       /usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):   $(DRIVER)
+       install -o root -cs $? $@
+
+# clean up local files
+clean:
+       rm -f $(DRIVER) *.o *.bak 
+
+depend: 
+       /usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c ../libdriver/*.c > .depend
+
+# Include generated dependencies.
+include .depend
+
diff --git a/drivers/bios_wini/bios_wini.c b/drivers/bios_wini/bios_wini.c
new file mode 100644 (file)
index 0000000..ab2fd1a
--- /dev/null
@@ -0,0 +1,476 @@
+/* This file contains the "device dependent" part of a hard disk driver that
+ * uses the ROM BIOS.  It makes a call and just waits for the transfer to
+ * happen.  It is not interrupt driven and thus will (*) have poor performance.
+ * The advantage is that it should work on virtually any PC, XT, 386, PS/2
+ * or clone.  The demo disk uses this driver.  It is suggested that all
+ * MINIX users try the other drivers, and use this one only as a last resort,
+ * if all else fails.
+ *
+ * (*) The performance is within 10% of the AT driver for reads on any disk
+ *     and writes on a 2:1 interleaved disk, it will be DMA_BUF_SIZE bytes
+ *     per revolution for a minimum of 60 kb/s for writes to 1:1 disks.
+ *
+ * The file contains one entry point:
+ *
+ *      bios_winchester_task:  main entry when system is brought up
+ *
+ *
+ * Changes:
+ *     30 Apr 1992 by Kees J. Bot: device dependent/independent split.
+ *     14 May 2000 by Kees J. Bot: d-d/i rewrite.
+ */
+
+#include "../drivers.h"
+#include "../libdriver/driver.h"
+#include "../libdriver/drvlib.h"
+#include <minix/sysutil.h>
+#include <minix/keymap.h>
+#include <sys/ioc_disk.h>
+#include <ibm/int86.h>
+#include <assert.h>
+
+#if ENABLE_BIOS_WINI
+
+#define ME "BIOS_WINI"
+
+/* Error codes */
+#define ERR             (-1)   /* general error */
+
+/* Parameters for the disk drive. */
+#define MAX_DRIVES         4   /* this driver supports 4 drives (d0 - d3)*/
+#define MAX_SECS        255    /* bios can transfer this many sectors */
+#define NR_DEVICES      (MAX_DRIVES * DEV_PER_DRIVE)
+#define SUB_PER_DRIVE  (NR_PARTITIONS * NR_PARTITIONS)
+#define NR_SUBDEVS     (MAX_DRIVES * SUB_PER_DRIVE)
+
+PRIVATE int pc_at = 1; /* What about PC XTs? */
+
+/* Variables. */
+PRIVATE struct wini {          /* main drive struct, one entry per drive */
+  unsigned cylinders;          /* number of cylinders */
+  unsigned heads;              /* number of heads */
+  unsigned sectors;            /* number of sectors per track */
+  unsigned open_ct;            /* in-use count */
+  int int13ext;                        /* IBM/MS INT 13 extensions supported? */
+  struct device part[DEV_PER_DRIVE];   /* disks and partitions */
+  struct device subpart[SUB_PER_DRIVE]; /* subpartitions */
+} wini[MAX_DRIVES], *w_wn;
+
+PRIVATE int nr_drives = MAX_DRIVES;    /* Number of drives */
+PRIVATE int w_drive;                   /* selected drive */
+PRIVATE struct device *w_dv;           /* device's base and size */
+PRIVATE vir_bytes bios_buf_vir, bios_buf_size;
+PRIVATE phys_bytes bios_buf_phys;
+
+_PROTOTYPE(int main, (void) );
+FORWARD _PROTOTYPE( struct device *w_prepare, (int device) );
+FORWARD _PROTOTYPE( char *w_name, (void) );
+FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, off_t position,
+                                       iovec_t *iov, unsigned nr_req) );
+FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( void w_init, (void) );
+FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry));
+FORWARD _PROTOTYPE( int nop_other, (struct driver *dp, message *m_ptr) );
+
+/* Entry points to this driver. */
+PRIVATE struct driver w_dtab = {
+  w_name,      /* current device's name */
+  w_do_open,   /* open or mount request, initialize device */
+  w_do_close,  /* release device */
+  do_diocntl,  /* get or set a partition's geometry */
+  w_prepare,   /* prepare for I/O on a given minor device */
+  w_transfer,  /* do the I/O */
+  nop_cleanup, /* no cleanup needed */
+  w_geometry,  /* tell the geometry of the disk */
+  nop_signal,          /* no cleanup needed on shutdown */
+  nop_alarm,           /* ignore leftover alarms */
+  nop_cancel,          /* ignore CANCELs */
+  nop_select,          /* ignore selects */
+  nop_other            /* catch-all for unrecognized commands and ioctls */
+};
+
+
+/*===========================================================================*
+ *                             bios_winchester_task                         *
+ *===========================================================================*/
+PUBLIC int main()
+{
+/* Set special disk parameters then call the generic main loop. */
+  driver_task(&w_dtab);
+}
+
+
+/*===========================================================================*
+ *                             w_prepare                                    *
+ *===========================================================================*/
+PRIVATE struct device *w_prepare(device)
+int device;
+{
+/* Prepare for I/O on a device. */
+
+  if (device < NR_DEVICES) {                   /* d0, d0p[0-3], d1, ... */
+       w_drive = device / DEV_PER_DRIVE;       /* save drive number */
+       w_wn = &wini[w_drive];
+       w_dv = &w_wn->part[device % DEV_PER_DRIVE];
+  } else
+  if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/
+       w_drive = device / SUB_PER_DRIVE;
+       w_wn = &wini[w_drive];
+       w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];
+  } else {
+       return(NIL_DEV);
+  }
+  return(w_drive < nr_drives ? w_dv : NIL_DEV);
+}
+
+
+/*===========================================================================*
+ *                             w_name                                       *
+ *===========================================================================*/
+PRIVATE char *w_name()
+{
+/* Return a name for the current device. */
+  static char name[] = "bios-d0";
+
+  name[6] = '0' + w_drive;
+  return name;
+}
+
+
+/*===========================================================================*
+ *                             w_transfer                                   *
+ *===========================================================================*/
+PRIVATE int w_transfer(proc_nr, opcode, position, iov, nr_req)
+int proc_nr;                   /* process doing the request */
+int opcode;                    /* DEV_GATHER or DEV_SCATTER */
+off_t position;                        /* offset on device to read or write */
+iovec_t *iov;                  /* pointer to read or write request vector */
+unsigned nr_req;               /* length of request vector */
+{
+  struct wini *wn = w_wn;
+  iovec_t *iop, *iov_end = iov + nr_req;
+  int r, errors;
+  unsigned nbytes, count, chunk;
+  unsigned long block;
+  vir_bytes i13e_rw_off, rem_buf_size;
+  unsigned long dv_size = cv64ul(w_dv->dv_size);
+  unsigned secspcyl = wn->heads * wn->sectors;
+  struct int13ext_rw {
+       u8_t    len;
+       u8_t    res1;
+       u16_t   count;
+       u16_t   addr[2];
+       u32_t   block[2];
+  } i13e_rw;
+  struct reg86u reg86;
+
+  /* Check disk address. */
+  if ((position & SECTOR_MASK) != 0) return(EINVAL);
+
+  errors = 0;
+
+  i13e_rw_off= bios_buf_size-sizeof(i13e_rw);
+  rem_buf_size= (i13e_rw_off & ~SECTOR_MASK);
+  assert(rem_buf_size != 0);
+
+  while (nr_req > 0) {
+       /* How many bytes to transfer? */
+       nbytes = 0;
+       for (iop = iov; iop < iov_end; iop++) {
+               if (nbytes + iop->iov_size > rem_buf_size) {
+                       /* Don't do half a segment if you can avoid it. */
+                       if (nbytes == 0) nbytes = rem_buf_size;
+                       break;
+               }
+               nbytes += iop->iov_size;
+       }
+       if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
+
+       /* Which block on disk and how close to EOF? */
+       if (position >= dv_size) return(OK);            /* At EOF */
+       if (position + nbytes > dv_size) nbytes = dv_size - position;
+       block = div64u(add64ul(w_dv->dv_base, position), SECTOR_SIZE);
+
+       /* Degrade to per-sector mode if there were errors. */
+       if (errors > 0) nbytes = SECTOR_SIZE;
+
+       if (opcode == DEV_SCATTER) {
+               /* Copy from user space to the DMA buffer. */
+               count = 0;
+               for (iop = iov; count < nbytes; iop++) {
+                       chunk = iov->iov_size;
+                       if (count + chunk > nbytes) chunk = nbytes - count;
+                       assert(chunk <= rem_buf_size);
+                       r= sys_vircopy(proc_nr, D, iop->iov_addr,
+                               SYSTEM, D, bios_buf_vir+count, 
+                               chunk);
+                       if (r != OK)
+                               panic(ME, "sys_vircopy failed", r);
+                       count += chunk;
+               }
+       }
+
+       /* Do the transfer */
+       if (wn->int13ext) {
+               i13e_rw.len = 0x10;
+               i13e_rw.res1 = 0;
+               i13e_rw.count = nbytes >> SECTOR_SHIFT;
+               i13e_rw.addr[0] = bios_buf_phys % HCLICK_SIZE;
+               i13e_rw.addr[1] = bios_buf_phys / HCLICK_SIZE;
+               i13e_rw.block[0] = block;
+               i13e_rw.block[1] = 0;
+               r= sys_vircopy(SELF, D, (vir_bytes)&i13e_rw,
+                       SYSTEM, D, (bios_buf_vir+i13e_rw_off), 
+                       sizeof(i13e_rw));
+               if (r != OK)
+                       panic(ME, "sys_vircopy failed", r);
+
+               /* Set up an extended read or write BIOS call. */
+               reg86.u.b.intno = 0x13;
+               reg86.u.w.ax = opcode == DEV_SCATTER ? 0x4300 : 0x4200;
+               reg86.u.b.dl = 0x80 + w_drive;
+               reg86.u.w.si = (bios_buf_phys + i13e_rw_off) % HCLICK_SIZE;
+               reg86.u.w.ds = (bios_buf_phys + i13e_rw_off) / HCLICK_SIZE;
+       } else {
+               /* Set up an ordinary read or write BIOS call. */
+               unsigned cylinder = block / secspcyl;
+               unsigned sector = (block % wn->sectors) + 1;
+               unsigned head = (block % secspcyl) / wn->sectors;
+
+               reg86.u.b.intno = 0x13;
+               reg86.u.b.ah = opcode == DEV_SCATTER ? 0x03 : 0x02;
+               reg86.u.b.al = nbytes >> SECTOR_SHIFT;
+               reg86.u.w.bx = (bios_buf_phys + i13e_rw_off) % HCLICK_SIZE;
+               reg86.u.w.es = (bios_buf_phys + i13e_rw_off) / HCLICK_SIZE;
+               reg86.u.b.ch = cylinder & 0xFF;
+               reg86.u.b.cl = sector | ((cylinder & 0x300) >> 2);
+               reg86.u.b.dh = head;
+               reg86.u.b.dl = 0x80 + w_drive;
+       }
+
+       r= sys_int86(&reg86);
+       if (r != OK)
+               panic(ME, "BIOS call failed", r);
+
+       if (reg86.u.w.f & 0x0001) {
+               /* An error occurred, try again sector by sector unless */
+               if (++errors == 2) return(EIO);
+               continue;
+       }
+
+       if (opcode == DEV_GATHER) {
+               /* Copy from the DMA buffer to user space. */
+               count = 0;
+               for (iop = iov; count < nbytes; iop++) {
+                       chunk = iov->iov_size;
+                       if (count + chunk > nbytes) chunk = nbytes - count;
+                       assert(chunk <= rem_buf_size);
+                       r= sys_vircopy(SYSTEM, D, bios_buf_vir+count, 
+                               proc_nr, D, iop->iov_addr,
+                               chunk);
+                       if (r != OK)
+                               panic(ME, "sys_vircopy failed", r);
+                       count += chunk;
+               }
+       }
+
+       /* Book the bytes successfully transferred. */
+       position += nbytes;
+       for (;;) {
+               if (nbytes < iov->iov_size) {
+                       /* Not done with this one yet. */
+                       iov->iov_addr += nbytes;
+                       iov->iov_size -= nbytes;
+                       break;
+               }
+               nbytes -= iov->iov_size;
+               iov->iov_addr += iov->iov_size;
+               iov->iov_size = 0;
+               if (nbytes == 0) {
+                       /* The rest is optional, so we return to give FS a
+                        * chance to think it over.
+                        */
+                       return(OK);
+               }
+               iov++;
+               nr_req--;
+       }
+  }
+  return(OK);
+}
+
+
+/*============================================================================*
+ *                             w_do_open                                     *
+ *============================================================================*/
+PRIVATE int w_do_open(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+/* Device open: Initialize the controller and read the partition table. */
+
+  static int init_done = FALSE;
+
+  if (!init_done) { w_init(); init_done = TRUE; }
+
+  if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
+
+  if (w_wn->open_ct++ == 0) {
+       /* Partition the disk. */
+       partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY);
+  }
+  return(OK);
+}
+
+
+/*============================================================================*
+ *                             w_do_close                                    *
+ *============================================================================*/
+PRIVATE int w_do_close(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+/* Device close: Release a device. */
+
+  if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
+  w_wn->open_ct--;
+  return(OK);
+}
+
+
+/*===========================================================================*
+ *                             w_init                                       *
+ *===========================================================================*/
+PRIVATE void w_init()
+{
+/* This routine is called at startup to initialize the drive parameters. */
+
+  int r, drive;
+  struct wini *wn;
+  unsigned long capacity;
+  struct int13ext_params {
+       u16_t   len;
+       u16_t   flags;
+       u32_t   cylinders;
+       u32_t   heads;
+       u32_t   sectors;
+       u32_t   capacity[2];
+       u16_t   bts_per_sec;
+       u16_t   config[2];
+  } i13e_par;
+  struct reg86u reg86;
+
+  /* Ask the system task for a suitable buffer */
+  r= sys_getbiosbuffer(&bios_buf_vir, &bios_buf_size);
+  if (r != OK)
+       panic(ME, "sys_getbiosbuffer failed", r);
+  r= sys_umap(SYSTEM, D, (vir_bytes)bios_buf_vir, (phys_bytes)bios_buf_size,
+       &bios_buf_phys);
+  if (r != OK)
+       panic(ME, "sys_umap failed", r);
+  if (bios_buf_phys+bios_buf_size > 0x100000)
+       panic(ME, "bad BIOS buffer, phys", bios_buf_phys);
+#if 0
+  printf("bios_wini: got buffer size %d, virtual 0x%x, phys 0x%x\n",
+               bios_buf_size, bios_buf_vir, bios_buf_phys);
+#endif
+
+  /* Get the geometry of the drives */
+  for (drive = 0; drive < nr_drives; drive++) {
+       (void) w_prepare(drive * DEV_PER_DRIVE);
+       wn = w_wn;
+       reg86.u.b.intno = 0x13;
+       reg86.u.b.ah = 0x08;    /* Get drive parameters. */
+       reg86.u.b.dl = 0x80 + drive;
+       r= sys_int86(&reg86);
+       if (r != OK)
+               panic(ME, "BIOS call failed", r);
+
+       nr_drives = !(reg86.u.w.f & 0x0001) ? reg86.u.b.dl : drive;
+       if (nr_drives > MAX_DRIVES) nr_drives = MAX_DRIVES;
+       if (drive >= nr_drives) break;
+
+       wn->heads = reg86.u.b.dh + 1;
+       wn->sectors = reg86.u.b.cl & 0x3F;
+       wn->cylinders = (reg86.u.b.ch | ((reg86.u.b.cl & 0xC0) << 2)) + 1;
+
+       capacity = (unsigned long) wn->cylinders * wn->heads * wn->sectors;
+
+       reg86.u.b.intno = 0x13;
+       reg86.u.b.ah = 0x41;    /* INT 13 Extensions - Installation check */
+       reg86.u.w.bx = 0x55AA;
+       reg86.u.b.dl = 0x80 + drive;
+
+       if (pc_at) {
+               r= sys_int86(&reg86);
+               if (r != OK)
+                       panic(ME, "BIOS call failed", r);
+       }
+
+       if (!(reg86.u.w.f & 0x0001) && reg86.u.w.bx == 0xAA55
+                               && (reg86.u.w.cx & 0x0001)) {
+               /* INT 13 Extensions available. */
+               i13e_par.len = 0x001E;  /* Input size of parameter packet */
+               r= sys_vircopy(SELF, D, (vir_bytes)&i13e_par,
+                       SYSTEM, D, bios_buf_vir, 
+                       sizeof(i13e_par));
+               if (r != OK)
+                       panic(ME, "sys_vircopy failed\n", r);
+               reg86.u.b.intno = 0x13;
+               reg86.u.b.ah = 0x48;    /* Ext. Get drive parameters. */
+               reg86.u.b.dl = 0x80 + drive;
+               reg86.u.w.si = bios_buf_phys % HCLICK_SIZE;
+               reg86.u.w.ds = bios_buf_phys / HCLICK_SIZE;
+
+               r= sys_int86(&reg86);
+               if (r != OK)
+                       panic(ME, "BIOS call failed", r);
+
+               r= sys_vircopy(SYSTEM, D, bios_buf_vir,
+                        SELF, D, (vir_bytes)&i13e_par,
+                       sizeof(i13e_par));
+               if (r != OK)
+                       panic(ME, "sys_vircopy failed\n", r);
+
+               if (!(reg86.u.w.f & 0x0001)) {
+                       wn->int13ext = 1;       /* Extensions can be used. */
+                       capacity = i13e_par.capacity[0];
+                       if (i13e_par.capacity[1] != 0) capacity = 0xFFFFFFFF;
+               }
+       }
+
+       if (wn->int13ext) {
+               printf("%s: %lu sectors\n", w_name(), capacity);
+       } else {
+               printf("%s: %d cylinders, %d heads, %d sectors per track\n",
+                       w_name(), wn->cylinders, wn->heads, wn->sectors);
+       }
+       wn->part[0].dv_size = mul64u(capacity, SECTOR_SIZE);
+  }
+}
+
+
+/*============================================================================*
+ *                             w_geometry                                    *
+ *============================================================================*/
+PRIVATE void w_geometry(entry)
+struct partition *entry;
+{
+  entry->cylinders = w_wn->cylinders;
+  entry->heads = w_wn->heads;
+  entry->sectors = w_wn->sectors;
+}
+
+/*============================================================================*
+ *                             nop_other                                     *
+ *============================================================================*/
+PRIVATE int nop_other(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+       printf("bios_wini: in nop_other\n");
+       return OK;
+}
+
+#endif /* ENABLE_BIOS_WINI */
index 7d42b004308ab734e46baf728ac274f4ea31409a..30d6fa67f31e273bc0060bda2cc8183e3e4f077d 100755 (executable)
@@ -44,9 +44,7 @@ union reg86 {
     } b;
 };
 
-#ifdef _SYSTEM         /* Kernel: Registers used in an 8086 interrupt */
-EXTERN union reg86 reg86;
-#endif
+struct reg86u { union reg86 u; };      /* Better for forward declarations */
 
 /* Parameters passed on ioctls to the memory task. */
 
index 53145f63a6bcf3e04fdd59e713b2b39dde888219..fd525880b2381be4073ebccd4b13299ac503d308 100755 (executable)
 #define FXP            (RTL8139 + ENABLE_FXP)  /* Intel Pro/100 */
 #define DPETH          (FXP + ENABLE_DPETH)    /* ISA Network task */
 #define LOG_PROC_NR    (DPETH + ENABLE_LOG)    /* log device */
-#define INIT_PROC_NR   (LOG_PROC_NR + 1)       /* init -- goes multiuser */
+#define BIOS_WINI      (LOG_PROC_NR + ENABLE_BIOS_WINI) /* BIOS disk device */
+#define INIT_PROC_NR   (BIOS_WINI + 1)         /* init -- goes multiuser */
 
 /* Number of processes contained in the system image. */
 #define NR_BOOT_PROCS  (NR_TASKS + \
                        6 + ENABLE_AT_WINI + ENABLE_FLOPPY + \
                        ENABLE_PRINTER + ENABLE_RTL8139 + ENABLE_FXP + \
-                       ENABLE_DPETH + ENABLE_LOG + 1 ) 
+                       ENABLE_DPETH + ENABLE_LOG + ENABLE_BIOS_WINI + 1 )      
 
 
 /*===========================================================================*
 #  define SYS_VIRVCOPY   (KERNEL_CALL + 32)    /* sys_virvcopy() */
 #  define SYS_MEMSET     (KERNEL_CALL + 33)    /* sys_memset() */
 #  define SYS_NICE       (KERNEL_CALL + 34)    /* sys_nice() */
-#define NR_SYS_CALLS   35      /* number of system calls */ 
+#  define SYS_INT86      (KERNEL_CALL + 35)    /* sys_int86() */
+#define NR_SYS_CALLS   36      /* number of system calls */ 
 
 /* Field names for SYS_MEMSET, SYS_SEGCTL. */
 #define MEM_PTR                m1_p1   /* base */
 #   define GET_PROC      11    /* get process slot if given process */
 #   define GET_MACHINE           12    /* get machine information */
 #   define GET_LOCKTIMING 13   /* get lock()/unlock() latency timing */
+#   define GET_BIOSBUFFER 14   /* get a buffer for BIOS calls */
 #define I_PROC_NR      m7_i4   /* calling process */
 #define I_VAL_PTR      m7_p1   /* virtual address at caller */ 
 #define I_VAL_LEN      m7_i1   /* max length of value */
 #define PR_IP_PTR       m1_p3  /* initial value for ip after exec */
 #define PR_MEM_PTR     m1_p1   /* tells where memory map is for sys_newmap */
 
+/* Field names for SYS_INT86 */
+#define INT86_REG86    m1_p1   /* Point to registers */
+
 /* Field names for SELECT (FS). */
 #define SEL_NFDS       m8_i1
 #define SEL_READFDS    m8_p1
index 03e288b8898068f67dfd32790a64b82a024f95cc..6c9bcb664b4ebd5b4d454ff6c2b2e4b3a16ab890 100755 (executable)
@@ -70,7 +70,7 @@
 #define ENABLE_BOOTDEV    0
 
 /* Include or exclude device drivers.  Set to 1 to include, 0 to exclude. */
-#define ENABLE_BIOS_WINI   0   /* enable BIOS winchester driver */
+#define ENABLE_BIOS_WINI   1   /* enable BIOS winchester driver */
 #define ENABLE_ESDI_WINI   0   /* enable ESDI winchester driver */
 #define ENABLE_XT_WINI     0   /* enable XT winchester driver */
 #define ENABLE_AHA1540     0   /* enable Adaptec 1540 SCSI driver */
@@ -81,7 +81,7 @@
 
 /* Include or exclude user-level device drivers (and supporting servers). */
 #define ENABLE_PRINTER     0   /* user-level Centronics printer driver */
-#define ENABLE_FLOPPY      1   /* enable floppy disk driver */
+#define ENABLE_FLOPPY      0   /* enable floppy disk driver */
 #define ENABLE_AT_WINI     1   /* enable AT winchester driver */
 #define   ENABLE_ATAPI     1   /* add ATAPI support to AT driver */
 
index 665b1fc5921bdf50e8f0f3d207c79e4577af9239..aa29ead48b1713abf92611bad6e6a79cf266f02b 100755 (executable)
@@ -15,6 +15,9 @@
 #include <minix/devio.h>
 #endif
 
+/* Forward declaration */
+struct reg86u;
+
 #define SYSTASK SYSTEM
 
 /*==========================================================================* 
@@ -33,6 +36,7 @@ _PROTOTYPE( int sys_trace, (int req, int proc, long addr, long *data_p)       );
 _PROTOTYPE( int sys_svrctl, (int proc, int req, int priv,vir_bytes argp));
 _PROTOTYPE( int sys_nice, (int proc, int prio)                         );
 
+_PROTOTYPE( int sys_int86, (struct reg86u *reg86p)                             );
 
 /* Shorthands for sys_sdevio() system call. */
 #define sys_insb(port, proc_nr, buffer, count) \
@@ -101,6 +105,8 @@ _PROTOTYPE(int sys_segctl, (int *index, u16_t *seg, vir_bytes *off,
 #define sys_getmonparams(v,vl) sys_getinfo(GET_MONPARAMS, v,vl, 0,0)
 #define sys_getschedinfo(v1,v2)        sys_getinfo(GET_SCHEDINFO, v1,0, v2,0)
 #define sys_getlocktimings(dst)        sys_getinfo(GET_LOCKTIMING, dst, 0,0,0)
+#define sys_getbiosbuffer(virp, sizep) sys_getinfo(GET_BIOSBUFFER, virp, \
+       sizeof(*virp), sizep, sizeof(*sizep))
 _PROTOTYPE(int sys_getinfo, (int request, void *val_ptr, int val_len,
                                 void *val_ptr2, int val_len2)          );
 
index bb35eb570f4cf43e07114362b01d2b8769bd4c05..66875b7dca858edb3dbe2e38247ad18454e4849a 100755 (executable)
@@ -148,6 +148,7 @@ PRIVATE void initialize(void)
   map(SYS_DEVIO, do_devio);            /* inb, inw, inl, outb, outw, outl */ 
   map(SYS_SDEVIO, do_sdevio);          /* phys_insb, _insw, _outsb, _outsw */
   map(SYS_VDEVIO, do_vdevio);                  /* vector with devio requests */ 
+  map(SYS_INT86, do_int86);            /* BIOS call */ 
 
   /* System control. */
   map(SYS_ABORT, do_abort);            /* abort MINIX */
index 116f13e5b301ef75b170fe9d1f84ac50f3d94272..3073bce697a9feabb5c386c0f9582f18512c5bfa 100644 (file)
@@ -107,6 +107,8 @@ _PROTOTYPE( int do_vdevio, (message *m_ptr) );
 #define do_vdevio do_unused
 #endif
 
+_PROTOTYPE( int do_int86, (message *m_ptr) );
+
 _PROTOTYPE( int do_sdevio, (message *m_ptr) );
 #if ! USE_SDEVIO
 #define do_sdevio do_unused
index 4ad4619218c5b3835a218e1fe6281822169793f5..96e2c53d5f8ffc687e9e9d36198b83af28c2fc06 100644 (file)
@@ -29,6 +29,7 @@ OBJECTS       = \
        $(SYSTEM)(do_irqctl.o) \
        $(SYSTEM)(do_devio.o) \
        $(SYSTEM)(do_vdevio.o) \
+       $(SYSTEM)(do_int86.o) \
        $(SYSTEM)(do_sdevio.o) \
        $(SYSTEM)(do_copy.o) \
        $(SYSTEM)(do_vcopy.o) \
@@ -96,6 +97,9 @@ $(SYSTEM)(do_sdevio.o):       do_sdevio.c
 $(SYSTEM)(do_vdevio.o):        do_vdevio.c
        $(CC) do_vdevio.c
 
+$(SYSTEM)(do_int86.o): do_int86.c
+       $(CC) do_int86.c
+
 $(SYSTEM)(do_copy.o):  do_copy.c
        $(CC) do_copy.c
 
@@ -134,4 +138,3 @@ $(SYSTEM)(do_privctl.o):    do_privctl.c
 
 $(SYSTEM)(do_segctl.o):        do_segctl.c
        $(CC) do_segctl.c
-
diff --git a/kernel/system/do_bios.c b/kernel/system/do_bios.c
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
index 90492f39cc68a0569ba727e632072332534e2d22..a7cbb2644f320b74df317ab7e57079e5ff2a861f 100644 (file)
@@ -15,6 +15,9 @@
 
 #include "../system.h"
 
+static unsigned long bios_buf[1024];   /* 4K, what about alignment */
+static vir_bytes bios_buf_vir, bios_buf_len;
+
 #if USE_GETINFO
 
 /*===========================================================================*
@@ -113,6 +116,22 @@ register message *m_ptr;   /* pointer to request message */
     break;
     }
 #endif
+    case GET_BIOSBUFFER:
+       bios_buf_vir = (vir_bytes)bios_buf;
+       bios_buf_len = sizeof(bios_buf);
+
+       length = sizeof(bios_buf_len);
+       src_phys = vir2phys(&bios_buf_len);
+       if (length != m_ptr->I_VAL_LEN2) return (EINVAL);
+       proc_nr = m_ptr->m_source;      /* only caller can request copy */
+       dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR2, length); 
+       if (src_phys == 0 || dst_phys == 0) return(EFAULT);
+       phys_copy(src_phys, dst_phys, length);
+
+       length = sizeof(bios_buf_vir);
+       src_phys = vir2phys(&bios_buf_vir);
+       break;
+
     default:
         return(EINVAL);
   }
diff --git a/kernel/system/do_int86.c b/kernel/system/do_int86.c
new file mode 100644 (file)
index 0000000..004d4b9
--- /dev/null
@@ -0,0 +1,46 @@
+/* The system call implemented in this file:
+ *   m_type:   SYS_INT86
+ *
+ * The parameters for this system call are:
+ *    m1_p1:   INT86_REG86     
+ */
+
+#include "../system.h"
+#include <minix/type.h>
+#include <ibm/int86.h>
+
+struct reg86u reg86;
+
+/*===========================================================================*
+ *                             do_int86                                             *
+ *===========================================================================*/
+PUBLIC int do_int86(m_ptr)
+register message *m_ptr;       /* pointer to request message */
+{
+  int caller;
+  vir_bytes caller_vir;
+  phys_bytes caller_phys, kernel_phys;
+
+  caller = (int) m_ptr->m_source; 
+  caller_vir = (vir_bytes) m_ptr->INT86_REG86;
+  caller_phys = umap_local(proc_addr(caller), D, caller_vir, sizeof(reg86));
+  if (0 == caller_phys) return(EFAULT);
+  kernel_phys = vir2phys(&reg86);
+  phys_copy(caller_phys, kernel_phys, (phys_bytes) sizeof(reg86));
+
+  level0(int86);
+
+  /* Copy results back to the caller */
+  phys_copy(kernel_phys, caller_phys, (phys_bytes) sizeof(reg86));
+
+  /* The BIOS call eats interrupts. Call get_randomness to generate some
+   * entropy. Normally, get_randomness is called from an interrupt handler.
+   * Figuring out the exact source is too complicated. CLOCK_IRQ is normally
+   * not very random.
+   */
+  lock(0, "do_int86");
+  get_randomness(CLOCK_IRQ);
+  unlock(0);
+
+  return(OK);
+}
index 8730ac72458d61e3f2ad37d673f95f5526abaeb6..c11ed4982c8975e6d7ae7434dcad6b97492662a6 100755 (executable)
@@ -99,6 +99,9 @@ PUBLIC struct system_image image[] = {
 #endif
 #if ENABLE_LOG
  { LOG_PROC_NR, 0,     SYS_F, SYS_T, 2, 0,           FILLED_MASK,  SYSTEM_SEND_MASK,  "LOG" },
+#endif
+#if ENABLE_BIOS_WINI
+ { BIOS_WINI, 0,     SYS_F, SYS_T, 2, 0,           FILLED_MASK,  SYSTEM_SEND_MASK,  "BIOS" },
 #endif
  { INIT_PROC_NR, 0,    USER_F, USER_T, USER_Q, 0,         USER_CALL_MASK,    USER_SEND_MASK,  "INIT"    },
 };
index 36c72a94d1b859ce28a9668fd6fe0d072bc3d0b2..165747130b77fd41eeb4a7f91dc7ebfc6315c552 100755 (executable)
@@ -14,6 +14,7 @@ OBJECTS       = \
        $(LIBSYS)(sys_abort.o) \
        $(LIBSYS)(sys_exec.o) \
        $(LIBSYS)(sys_fork.o) \
+       $(LIBSYS)(sys_int86.o) \
        $(LIBSYS)(sys_kill.o) \
        $(LIBSYS)(sys_newmap.o) \
        $(LIBSYS)(sys_sigsend.o) \
@@ -62,6 +63,9 @@ $(LIBSYS)(sys_exec.o):        sys_exec.c
 $(LIBSYS)(sys_fork.o): sys_fork.c
        $(CC1) sys_fork.c
 
+$(LIBSYS)(sys_int86.o):        sys_int86.c
+       $(CC1) sys_int86.c
+
 $(LIBSYS)(sys_kill.o): sys_kill.c
        $(CC1) sys_kill.c
 
diff --git a/lib/syslib/sys_int86.c b/lib/syslib/sys_int86.c
new file mode 100644 (file)
index 0000000..4389774
--- /dev/null
@@ -0,0 +1,17 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_int86                                 *
+ *===========================================================================*/
+PUBLIC int sys_int86(reg86p)
+struct reg86u *reg86p;
+{
+    message m;
+    int result;
+
+    m.m1_p1= (char *)reg86p;
+
+    result = _taskcall(SYSTASK, SYS_INT86, &m);
+    return(result);
+}
+
index 5fa611088868de1eb7110cb92ce2835a6841c3c4..0abed3682b282b5caf4c841b7968feb3dbdb7079 100644 (file)
@@ -115,7 +115,7 @@ PUBLIC void map_controllers()
       char proc_name[8];
   } drivertab[] = {
        { "at",         "AT_WINI"       },      /* AT Winchester */
-       { "bios",       "..." },
+       { "bios",       "BIOS" },
        { "esdi",       "..." },
        { "xt",         "..." },
        { "aha1540",    "..." },
index 7cf049a72dd6e04f7c86957c8f195d079042ff99..189826266b7eb7d530a393a2943286c53b178821 100755 (executable)
@@ -15,10 +15,10 @@ PROGRAMS=   ../kernel/kernel \
        ../drivers/tty/tty \
        ../drivers/memory/memory \
        ../drivers/at_wini/at_wini \
-       ../drivers/floppy/floppy \
        ../drivers/rtl8139/rtl8139 \
        ../drivers/fxp/fxp \
        ../drivers/log/log \
+       ../drivers/bios_wini/bios_wini \
        ../servers/init/init \
 #      bootdev.img