From dd49f3586fa740a36bec811484a5e56729ed815f Mon Sep 17 00:00:00 2001 From: Jorrit Herder Date: Fri, 21 Oct 2005 13:24:22 +0000 Subject: [PATCH] New Rescue Device Driver (RAM disk like) Allow restarting RTL8139 --- drivers/rescue/Makefile | 48 +++++++++ drivers/rescue/rescue.c | 220 ++++++++++++++++++++++++++++++++++++++ drivers/rtl8139/rtl8139.c | 33 ++++++ 3 files changed, 301 insertions(+) create mode 100644 drivers/rescue/Makefile create mode 100644 drivers/rescue/rescue.c diff --git a/drivers/rescue/Makefile b/drivers/rescue/Makefile new file mode 100644 index 000000000..30c1abc56 --- /dev/null +++ b/drivers/rescue/Makefile @@ -0,0 +1,48 @@ +# Makefile for rescue driver +DRIVER = rescue + +# 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 = -lsys -lsysutil + +OBJ = rescue.o +LIBDRIVER = $d/libdriver/driver.o + + +# build local binary +all build: $(DRIVER) +$(DRIVER): $(OBJ) $(LIBDRIVER) + $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS) + install -S 1024w $(DRIVER) + +$(LIBDRIVER): + cd $d/libdriver && $(MAKE) + + +# install with other drivers +install: /sbin/$(DRIVER) +/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/rescue/rescue.c b/drivers/rescue/rescue.c new file mode 100644 index 000000000..1b4df7776 --- /dev/null +++ b/drivers/rescue/rescue.c @@ -0,0 +1,220 @@ +/* This file contains the rescue device driver (/dev/rescue) + * + * Changes: + * Oct 21, 1992 created (Jorrit N. Herder) + */ + +#include "../drivers.h" +#include "../libdriver/driver.h" +#include "../../kernel/const.h" +#include "../../kernel/config.h" +#include "../../kernel/type.h" + + +#define NR_DEVS 1 /* number of rescue devices */ +#define RESCUE_KBYTES 128 /* default size in kilobytes */ + +PRIVATE struct device m_geom[NR_DEVS]; /* base and size of each device */ +PRIVATE int m_seg[NR_DEVS]; /* segment index of each device */ +PRIVATE int m_device; /* current device */ + +extern int errno; /* error number for PM calls */ + +FORWARD _PROTOTYPE( void m_init, (int argc, char **argv) ); +FORWARD _PROTOTYPE( char *m_name, (void) ); +FORWARD _PROTOTYPE( struct device *m_prepare, (int device) ); +FORWARD _PROTOTYPE( int m_transfer, (int proc_nr, int opcode, off_t position, + iovec_t *iov, unsigned nr_req) ); +FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) ); +FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) ); + +/* Entry points to this driver. */ +PRIVATE struct driver m_dtab = { + m_name, /* current device's name */ + m_do_open, /* open or mount */ + do_nop, /* nothing on a close */ + do_diocntl, /* standard I/O controls */ + m_prepare, /* prepare for I/O on a given minor device */ + m_transfer, /* do the I/O */ + nop_cleanup, /* no need to clean up */ + m_geometry, /* memory device "geometry" */ + nop_signal, /* system signals */ + nop_alarm, + nop_cancel, + nop_select, + NULL, + NULL +}; + + +/*===========================================================================* + * main * + *===========================================================================*/ +PUBLIC int main(int argc, char **argv) +{ +/* Main program. Initialize the rescue driver and start the main loop. */ + m_init(argc, argv); + driver_task(&m_dtab); + return(OK); +} + +/*===========================================================================* + * m_name * + *===========================================================================*/ +PRIVATE char *m_name() +{ +/* Return a name for the current device. */ + static char name[] = "rescue"; + return name; +} + +/*===========================================================================* + * m_prepare * + *===========================================================================*/ +PRIVATE struct device *m_prepare(device) +int device; +{ +/* Prepare for I/O on a device: check if the minor device number is ok. */ + if (device < 0 || device >= NR_DEVS) return(NIL_DEV); + m_device = device; + + return(&m_geom[device]); +} + +/*===========================================================================* + * m_transfer * + *===========================================================================*/ +PRIVATE int m_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 */ +{ +/* Read or write one the driver's minor devices. */ + int seg; + unsigned count, left, chunk; + vir_bytes user_vir; + struct device *dv; + unsigned long dv_size; + int s; + + /* Get and check minor device number. */ + if ((unsigned) m_device > NR_DEVS - 1) return(ENXIO); + dv = &m_geom[m_device]; + dv_size = cv64ul(dv->dv_size); + + while (nr_req > 0) { + + /* How much to transfer and where to / from. */ + count = iov->iov_size; + user_vir = iov->iov_addr; + + /* Virtual copying. For rescue device. */ + if (position >= dv_size) return(OK); /* check for EOF */ + if (position + count > dv_size) count = dv_size - position; + seg = m_seg[m_device]; + + if (opcode == DEV_GATHER) { /* copy actual data */ + sys_vircopy(SELF,seg,position, proc_nr,D,user_vir, count); + } else { + sys_vircopy(proc_nr,D,user_vir, SELF,seg,position, count); + } + + /* Book the number of bytes transferred. */ + position += count; + iov->iov_addr += count; + if ((iov->iov_size -= count) == 0) { iov++; nr_req--; } + + } + return(OK); +} + +/*===========================================================================* + * m_do_open * + *===========================================================================*/ +PRIVATE int m_do_open(dp, m_ptr) +struct driver *dp; +message *m_ptr; +{ +/* Check device number on open. */ + if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO); + return(OK); +} + +/*===========================================================================* + * m_init * + *===========================================================================*/ +PRIVATE void m_init(argc,argv) +int argc; +char **argv; +{ + /* Initialize this task. All minor devices are initialized one by one. */ + phys_bytes rescue_size; + phys_bytes rescue_base; + message m; + int i, s; + + /* Initialize all rescue devices in a loop. */ + for (i=0; i< NR_DEVS; i++) { + + /* Determine size and base of rescue disks. See if rescue disk details + * exist in the data store. If no memory for the rescue disk was claimed + * yet, do it below. + */ + m.DS_KEY = (RESCUE_MAJOR << 8) + i; + if (OK == (s = _taskcall(DS_PROC_NR, DS_RETRIEVE, &m))) { + rescue_size = m.DS_VAL_L1; + rescue_base = m.DS_VAL_L2; + } + else { /* no details known */ + if (argc>i+1) rescue_size = atoi(argv[i+1]) * 1024; + else rescue_size = RESCUE_KBYTES * 1024; + + if (allocmem(rescue_size, &rescue_base) < 0) { + report("RESCUE", "warning, allocmem failed", errno); + rescue_size = 0; + } + } + + /* Now that we have the base and size of the rescue disk, set up all + * data structures if the rescue has a positive (nonzero) size. + */ + if (rescue_size > 0) { + + /* Create a new remote segment to make virtual copies. */ + if (OK != (s=sys_segctl(&m_seg[i], (u16_t *) &s, + (vir_bytes *) &s, rescue_base, rescue_size))) { + panic("RESCUE","Couldn't install remote segment.",s); + } + + /* Set the device geometry for the outside world. */ + m_geom[i].dv_base = cvul64(rescue_base); + m_geom[i].dv_size = cvul64(rescue_size); + + /* Store the values in the data store for future retrieval. */ + m.DS_KEY = (RESCUE_MAJOR << 8) + i; + m.DS_VAL_L1 = rescue_size; + m.DS_VAL_L2 = rescue_base; + if (OK != (s = _taskcall(DS_PROC_NR, DS_PUBLISH, &m))) { + panic("RESCUE","Couldn't store rescue disk details at DS.",s); + } + + printf("RESCUE disk %d (size %u/base %u) initialized\n", + i, rescue_size, rescue_base); + } + } +} + +/*===========================================================================* + * m_geometry * + *===========================================================================*/ +PRIVATE void m_geometry(entry) +struct partition *entry; +{ + /* Memory devices don't have a geometry, but the outside world insists. */ + entry->cylinders = div64u(m_geom[m_device].dv_size, SECTOR_SIZE) / (64 * 32); + entry->heads = 64; + entry->sectors = 32; +} + diff --git a/drivers/rtl8139/rtl8139.c b/drivers/rtl8139/rtl8139.c index d40b7de3c..3b5ce9662 100755 --- a/drivers/rtl8139/rtl8139.c +++ b/drivers/rtl8139/rtl8139.c @@ -24,6 +24,8 @@ * |------------|----------|---------|----------|---------|---------| * | DL_GETSTAT | port nr | proc nr | | | address | * |------------|----------|---------|----------|---------|---------| + * | DL_GETNAME | | | | | | + * |------------|----------|---------|----------|---------|---------| * | DL_STOP | port_nr | | | | | * |------------|----------|---------|----------|---------|---------| * @@ -247,6 +249,7 @@ _PROTOTYPE( static void mii_print_stat_speed, (U16_t stat, _PROTOTYPE( static void rl_clear_rx, (re_t *rep) ); _PROTOTYPE( static void rl_do_reset, (re_t *rep) ); _PROTOTYPE( static void rl_getstat, (message *mp) ); +_PROTOTYPE( static void rl_getname, (message *mp) ); _PROTOTYPE( static void reply, (re_t *rep, int err, int may_block) ); _PROTOTYPE( static void mess_reply, (message *req, message *reply) ); _PROTOTYPE( static void put_userdata, (int user_proc, @@ -267,6 +270,7 @@ _PROTOTYPE( static void rl_watchdog_f, (timer_t *tp) ); PRIVATE message m; PRIVATE int int_event_check; /* set to TRUE if events arrived */ +static char *progname; extern int errno; /*===========================================================================* @@ -275,6 +279,7 @@ extern int errno; int main(int argc, char *argv[]) { int fkeys, sfkeys; + int inet_proc_nr; int i, r; re_t *rep; long v; @@ -294,6 +299,15 @@ int main(int argc, char *argv[]) for (rep= &re_table[0]; rep < re_table+RE_PORT_NR; rep++) rl_init_buf(rep); + /* Try to notify inet that we are present (again). */ + (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]); + r = findproc("inet", &inet_proc_nr); + if (r == OK) + notify(inet_proc_nr); + else + printf("rtl8139: cannot find proc number for inet: %d\n", r); + + while (TRUE) { if ((r= receive(ANY, &m)) != OK) @@ -309,6 +323,7 @@ int main(int argc, char *argv[]) case DL_READV: rl_readv(&m, FALSE, TRUE); break; case DL_INIT: rl_init(&m); break; case DL_GETSTAT: rl_getstat(&m); break; + case DL_GETNAME: rl_getname(&m); break; #if 0 case DL_STOP: do_stop(&m); break; #endif @@ -1879,6 +1894,24 @@ message *mp; reply(rep, OK, FALSE); } + +/*===========================================================================* + * rl_getname * + *===========================================================================*/ +static void rl_getname(mp) +message *mp; +{ + int r; + + strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME)); + mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0'; + mp->m_type= DL_NAME_REPLY; + r= send(mp->m_source, mp); + if (r != OK) + panic("RTL8139", "rl_getname: send failed: %d\n", r); +} + + /*===========================================================================* * reply * *===========================================================================*/