From: Philip Homburg Date: Fri, 29 Jul 2005 10:21:04 +0000 (+0000) Subject: bios_wini driver X-Git-Tag: v3.1.0~499 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/Bv9ARM.ch09.html?a=commitdiff_plain;h=49c25df56904c02b5df092c6b6b115de6858831c;p=minix.git bios_wini driver --- diff --git a/drivers/Makefile b/drivers/Makefile index 56ac13ff5..f3f0d7c98 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -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 index 000000000..f2922fd97 --- /dev/null +++ b/drivers/bios_wini/Makefile @@ -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 index 000000000..ab2fd1ade --- /dev/null +++ b/drivers/bios_wini/bios_wini.c @@ -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 +#include +#include +#include +#include + +#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(®86); + 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(®86); + 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(®86); + 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(®86); + 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 */ diff --git a/include/ibm/int86.h b/include/ibm/int86.h index 7d42b0043..30d6fa67f 100755 --- a/include/ibm/int86.h +++ b/include/ibm/int86.h @@ -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. */ diff --git a/include/minix/com.h b/include/minix/com.h index 53145f63a..fd525880b 100755 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -49,13 +49,14 @@ #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 ) /*===========================================================================* @@ -265,7 +266,8 @@ # 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 */ @@ -366,6 +368,7 @@ # 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 */ @@ -412,6 +415,9 @@ #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 diff --git a/include/minix/config.h b/include/minix/config.h index 03e288b88..6c9bcb664 100755 --- a/include/minix/config.h +++ b/include/minix/config.h @@ -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 */ diff --git a/include/minix/syslib.h b/include/minix/syslib.h index 665b1fc59..aa29ead48 100755 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -15,6 +15,9 @@ #include #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) ); diff --git a/kernel/system.c b/kernel/system.c index bb35eb570..66875b7dc 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -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 */ diff --git a/kernel/system.h b/kernel/system.h index 116f13e5b..3073bce69 100644 --- a/kernel/system.h +++ b/kernel/system.h @@ -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 diff --git a/kernel/system/Makefile b/kernel/system/Makefile index 4ad461921..96e2c53d5 100644 --- a/kernel/system/Makefile +++ b/kernel/system/Makefile @@ -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 index 000000000..8b1378917 --- /dev/null +++ b/kernel/system/do_bios.c @@ -0,0 +1 @@ + diff --git a/kernel/system/do_getinfo.c b/kernel/system/do_getinfo.c index 90492f39c..a7cbb2644 100644 --- a/kernel/system/do_getinfo.c +++ b/kernel/system/do_getinfo.c @@ -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 index 000000000..004d4b9ea --- /dev/null +++ b/kernel/system/do_int86.c @@ -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 +#include + +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(®86); + 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); +} diff --git a/kernel/table.c b/kernel/table.c index 8730ac724..c11ed4982 100755 --- a/kernel/table.c +++ b/kernel/table.c @@ -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" }, }; diff --git a/lib/syslib/Makefile b/lib/syslib/Makefile index 36c72a94d..165747130 100755 --- a/lib/syslib/Makefile +++ b/lib/syslib/Makefile @@ -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 index 000000000..43897748f --- /dev/null +++ b/lib/syslib/sys_int86.c @@ -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); +} + diff --git a/servers/fs/dmap.c b/servers/fs/dmap.c index 5fa611088..0abed3682 100644 --- a/servers/fs/dmap.c +++ b/servers/fs/dmap.c @@ -115,7 +115,7 @@ PUBLIC void map_controllers() char proc_name[8]; } drivertab[] = { { "at", "AT_WINI" }, /* AT Winchester */ - { "bios", "..." }, + { "bios", "BIOS" }, { "esdi", "..." }, { "xt", "..." }, { "aha1540", "..." }, diff --git a/tools/Makefile b/tools/Makefile index 7cf049a72..189826266 100755 --- a/tools/Makefile +++ b/tools/Makefile @@ -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