From 1f5841c8ed7efaa3b843ec1b63c78c0aa6921cde Mon Sep 17 00:00:00 2001 From: Cristiano Giuffrida Date: Mon, 21 Dec 2009 14:12:21 +0000 Subject: [PATCH] Basic System Event Framework (SEF) with ping and live update. SYSLIB CHANGES: - SEF must be used by every system process and is thereby part of the system library. - The framework provides a receive() interface (sef_receive) for system processes to automatically catch known system even messages and process them. - SEF provides a default behavior for each type of system event, but allows system processes to register callbacks to override the default behavior. - Custom (local to the process) or predefined (provided by SEF) callback implementations can be registered to SEF. - SEF currently includes support for 2 types of system events: 1. SEF Ping. The event occurs every time RS sends a ping to figure out whether a system process is still alive. The default callback implementation provided by SEF is to notify RS back to let it know the process is alive and kicking. 2. SEF Live update. The event occurs every time RS sends a prepare to update message to let a system process know an update is available and to prepare for it. The live update support is very basic for now. SEF only deals with verifying if the prepare state can be supported by the process, dumping the state for debugging purposes, and providing an event-driven programming model to the process to react to state changes check-in when ready to update. - SEF should be extended in the future to integrate support for more types of system events. Ideally, all the cross-cutting concerns should be integrated into SEF to avoid duplicating code and ease extensibility. Examples include: * PM notify messages primarily used at shutdown. * SYSTEM notify messages primarily used for signals. * CLOCK notify messages used for system alarms. * Debug messages. IS could still be in charge of fkey handling but would forward the debug message to the target process (e.g. PM, if the user requested debug information about PM). SEF would then catch the message and do nothing unless the process has registered an appropriate callback to deal with the event. This simplifies the programming model to print debug information, avoids duplicating code, and reduces the effort to print debug information. SYSTEM PROCESSES CHANGES: - Every system process registers SEF callbacks it needs to override the default system behavior and calls sef_startup() right after being started. - sef_startup() does almost nothing now, but will be extended in the future to support callbacks of its own to let RS control and synchronize with every system process at initialization time. - Every system process calls sef_receive() now rather than receive() directly, to let SEF handle predefined system events. RS CHANGES: - RS supports a basic single-component live update protocol now, as follows: * When an update command is issued (via "service update *"), RS notifies the target system process to prepare for a specific update state. * If the process doesn't respond back in time, the update is aborted. * When the process responds back, RS kills it and marks it for refreshing. * The process is then automatically restarted as for a buggy process and can start running again. * Live update is currently prototyped as a controlled failure. --- drivers/amddev/amddev.c | 23 ++- drivers/at_wini/Makefile | 2 +- drivers/at_wini/at_wini.c | 251 +++-------------------- drivers/at_wini/at_wini.h | 214 ++++++++++++++++++++ drivers/at_wini/liveupdate.c | 78 ++++++++ drivers/audio/es1370/Makefile | 8 +- drivers/audio/es1371/Makefile | 6 +- drivers/audio/framework/Makefile | 8 +- drivers/audio/framework/audio_fw.c | 30 ++- drivers/audio/framework/liveupdate.c | 117 +++++++++++ drivers/audio/sb16/Makefile | 8 +- drivers/bios_wini/bios_wini.c | 20 ++ drivers/dp8390/dp8390.c | 24 ++- drivers/dpeth/dp.c | 25 ++- drivers/e1000/e1000.c | 25 ++- drivers/filter/driver.c | 4 +- drivers/filter/main.c | 22 +- drivers/floppy/Makefile | 2 +- drivers/floppy/floppy.c | 58 ++++-- drivers/floppy/floppy.h | 1 + drivers/floppy/liveupdate.c | 81 ++++++++ drivers/fxp/fxp.c | 24 ++- drivers/lance/lance.c | 28 ++- drivers/libdriver/driver.c | 7 +- drivers/log/Makefile | 2 +- drivers/log/liveupdate.c | 101 ++++++++++ drivers/log/log.c | 28 ++- drivers/memory/memory.c | 20 ++ drivers/memory/ramdisk/proto | 2 +- drivers/orinoco/orinoco.c | 24 ++- drivers/pci/main.c | 23 ++- drivers/printer/Makefile | 4 +- drivers/printer/liveupdate.c | 69 +++++++ drivers/printer/printer.c | 32 ++- drivers/random/main.c | 19 ++ drivers/readclock/readclock.c | 16 ++ drivers/rtl8139/Makefile | 2 +- drivers/rtl8139/liveupdate.c | 108 ++++++++++ drivers/rtl8139/rtl8139.c | 144 +++---------- drivers/rtl8139/rtl8139.h | 112 +++++++++++ drivers/rtl8169/rtl8169.c | 28 ++- drivers/sb16/Makefile | 4 +- drivers/sb16/sb16.h | 1 - drivers/sb16/sb16_dsp.c | 32 ++- drivers/sb16/sb16_dsp_liveupdate.c | 70 +++++++ drivers/sb16/sb16_mixer.c | 19 +- drivers/ti1225/ti1225.c | 23 ++- drivers/tty/tty.c | 23 ++- include/minix/com.h | 10 +- include/minix/sef.h | 120 +++++++++++ include/minix/syslib.h | 1 + lib/syslib/Makefile.in | 3 + lib/syslib/sef.c | 153 ++++++++++++++ lib/syslib/sef_liveupdate.c | 245 +++++++++++++++++++++++ lib/syslib/sef_ping.c | 63 ++++++ servers/ds/main.c | 19 +- servers/inet/inet.c | 19 +- servers/ipc/main.c | 21 +- servers/is/dmp_rs.c | 2 +- servers/is/main.c | 27 ++- servers/iso9660fs/main.c | 25 ++- servers/mfs/main.c | 20 +- servers/pfs/main.c | 20 +- servers/pm/main.c | 21 +- servers/rs/Makefile | 2 +- servers/rs/const.h | 5 + servers/rs/glo.h | 5 + servers/rs/main.c | 53 ++++- servers/rs/manager.c | 289 ++++++++++++++++++++++----- servers/rs/manager.h | 96 --------- servers/rs/proto.h | 2 + servers/rs/service.c | 56 +++++- servers/rs/type.h | 8 + servers/vfs/main.c | 24 ++- servers/vfs/request.c | 2 +- servers/vm/main.c | 20 +- 76 files changed, 2654 insertions(+), 649 deletions(-) create mode 100644 drivers/at_wini/liveupdate.c create mode 100644 drivers/audio/framework/liveupdate.c create mode 100644 drivers/floppy/liveupdate.c create mode 100644 drivers/log/liveupdate.c create mode 100644 drivers/printer/liveupdate.c create mode 100644 drivers/rtl8139/liveupdate.c create mode 100644 drivers/sb16/sb16_dsp_liveupdate.c create mode 100644 include/minix/sef.h create mode 100644 lib/syslib/sef.c create mode 100644 lib/syslib/sef_liveupdate.c create mode 100644 lib/syslib/sef_ping.c delete mode 100644 servers/rs/manager.h diff --git a/drivers/amddev/amddev.c b/drivers/amddev/amddev.c index e476551f4..86267550e 100644 --- a/drivers/amddev/amddev.c +++ b/drivers/amddev/amddev.c @@ -63,11 +63,17 @@ static void del_range(u32_t busaddr, u32_t size); static int do_pm_notify(message *m); static void report_exceptions(void); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + int main(void) { int r; message m; + /* SEF local startup. */ + sef_local_startup(); + printf("amddev: starting\n"); init(); @@ -76,9 +82,9 @@ int main(void) { report_exceptions(); - r= receive(ANY, &m); + r= sef_receive(ANY, &m); if (r != OK) - panic(__FILE__, "receive failed", r); + panic(__FILE__, "sef_receive failed", r); if (is_notify(m.m_type)) { if (_ENDPOINT_P(m.m_source) == PM_PROC_NR) { do_pm_notify(&m); @@ -95,6 +101,19 @@ int main(void) } } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard); + + /* Let SEF perform startup. */ + sef_startup(); +} + static int init() { int r, n_maps, n_domains, revision; diff --git a/drivers/at_wini/Makefile b/drivers/at_wini/Makefile index 70f93f9ef..333a9459e 100644 --- a/drivers/at_wini/Makefile +++ b/drivers/at_wini/Makefile @@ -17,7 +17,7 @@ CFLAGS = -I$i $(CPROFILE) LDFLAGS = -i -L../libdriver LIBS = -ldriver -lsys -ltimers -OBJ = at_wini.o +OBJ = at_wini.o liveupdate.o # build local binary diff --git a/drivers/at_wini/at_wini.c b/drivers/at_wini/at_wini.c index 017907462..23c69b6fc 100644 --- a/drivers/at_wini/at_wini.c +++ b/drivers/at_wini/at_wini.c @@ -24,180 +24,7 @@ #include #include -#define ATAPI_DEBUG 0 /* To debug ATAPI code. */ - -/* I/O Ports used by winchester disk controllers. */ - -/* Read and write registers */ -#define REG_CMD_BASE0 0x1F0 /* command base register of controller 0 */ -#define REG_CMD_BASE1 0x170 /* command base register of controller 1 */ -#define REG_CTL_BASE0 0x3F6 /* control base register of controller 0 */ -#define REG_CTL_BASE1 0x376 /* control base register of controller 1 */ - -#define PCI_CTL_OFF 2 /* Offset of control registers from BAR2 */ -#define PCI_DMA_2ND_OFF 8 /* Offset of DMA registers from BAR4 for - * secondary channel - */ - -#define REG_DATA 0 /* data register (offset from the base reg.) */ -#define REG_PRECOMP 1 /* start of write precompensation */ -#define REG_COUNT 2 /* sectors to transfer */ -#define REG_SECTOR 3 /* sector number */ -#define REG_CYL_LO 4 /* low byte of cylinder number */ -#define REG_CYL_HI 5 /* high byte of cylinder number */ -#define REG_LDH 6 /* lba, drive and head */ -#define LDH_DEFAULT 0xA0 /* ECC enable, 512 bytes per sector */ -#define LDH_LBA 0x40 /* Use LBA addressing */ -#define LDH_DEV 0x10 /* Drive 1 iff set */ -#define ldh_init(drive) (LDH_DEFAULT | ((drive) << 4)) - -/* Read only registers */ -#define REG_STATUS 7 /* status */ -#define STATUS_BSY 0x80 /* controller busy */ -#define STATUS_RDY 0x40 /* drive ready */ -#define STATUS_WF 0x20 /* write fault */ -#define STATUS_SC 0x10 /* seek complete (obsolete) */ -#define STATUS_DRQ 0x08 /* data transfer request */ -#define STATUS_CRD 0x04 /* corrected data */ -#define STATUS_IDX 0x02 /* index pulse */ -#define STATUS_ERR 0x01 /* error */ -#define STATUS_ADMBSY 0x100 /* administratively busy (software) */ -#define REG_ERROR 1 /* error code */ -#define ERROR_BB 0x80 /* bad block */ -#define ERROR_ECC 0x40 /* bad ecc bytes */ -#define ERROR_ID 0x10 /* id not found */ -#define ERROR_AC 0x04 /* aborted command */ -#define ERROR_TK 0x02 /* track zero error */ -#define ERROR_DM 0x01 /* no data address mark */ - -/* Write only registers */ -#define REG_COMMAND 7 /* command */ -#define CMD_IDLE 0x00 /* for w_command: drive idle */ -#define CMD_RECALIBRATE 0x10 /* recalibrate drive */ -#define CMD_READ 0x20 /* read data */ -#define CMD_READ_EXT 0x24 /* read data (LBA48 addressed) */ -#define CMD_READ_DMA_EXT 0x25 /* read data using DMA (w/ LBA48) */ -#define CMD_WRITE 0x30 /* write data */ -#define CMD_WRITE_EXT 0x34 /* write data (LBA48 addressed) */ -#define CMD_WRITE_DMA_EXT 0x35 /* write data using DMA (w/ LBA48) */ -#define CMD_READVERIFY 0x40 /* read verify */ -#define CMD_FORMAT 0x50 /* format track */ -#define CMD_SEEK 0x70 /* seek cylinder */ -#define CMD_DIAG 0x90 /* execute device diagnostics */ -#define CMD_SPECIFY 0x91 /* specify parameters */ -#define CMD_READ_DMA 0xC8 /* read data using DMA */ -#define CMD_WRITE_DMA 0xCA /* write data using DMA */ -#define ATA_IDENTIFY 0xEC /* identify drive */ -/* #define REG_CTL 0x206 */ /* control register */ -#define REG_CTL 0 /* control register */ -#define CTL_NORETRY 0x80 /* disable access retry */ -#define CTL_NOECC 0x40 /* disable ecc retry */ -#define CTL_EIGHTHEADS 0x08 /* more than eight heads */ -#define CTL_RESET 0x04 /* reset controller */ -#define CTL_INTDISABLE 0x02 /* disable interrupts */ -#define REG_CTL_ALTSTAT 0 /* alternate status register */ - -/* Identify words */ -#define ID_GENERAL 0x00 /* General configuration information */ -#define ID_GEN_NOT_ATA 0x8000 /* Not an ATA device */ -#define ID_CAPABILITIES 0x31 /* Capabilities (49)*/ -#define ID_CAP_LBA 0x0200 /* LBA supported */ -#define ID_CAP_DMA 0x0100 /* DMA supported */ -#define ID_FIELD_VALIDITY 0x35 /* Field Validity (53) */ -#define ID_FV_88 0x04 /* Word 88 is valid (UDMA) */ -#define ID_MULTIWORD_DMA 0x3f /* Multiword DMA (63) */ -#define ID_MWDMA_2_SEL 0x0400 /* Mode 2 is selected */ -#define ID_MWDMA_1_SEL 0x0200 /* Mode 1 is selected */ -#define ID_MWDMA_0_SEL 0x0100 /* Mode 0 is selected */ -#define ID_MWDMA_2_SUP 0x0004 /* Mode 2 is supported */ -#define ID_MWDMA_1_SUP 0x0002 /* Mode 1 is supported */ -#define ID_MWDMA_0_SUP 0x0001 /* Mode 0 is supported */ -#define ID_CSS 0x53 /* Command Sets Supported (83) */ -#define ID_CSS_LBA48 0x0400 -#define ID_ULTRA_DMA 0x58 /* Ultra DMA (88) */ -#define ID_UDMA_5_SEL 0x2000 /* Mode 5 is selected */ -#define ID_UDMA_4_SEL 0x1000 /* Mode 4 is selected */ -#define ID_UDMA_3_SEL 0x0800 /* Mode 3 is selected */ -#define ID_UDMA_2_SEL 0x0400 /* Mode 2 is selected */ -#define ID_UDMA_1_SEL 0x0200 /* Mode 1 is selected */ -#define ID_UDMA_0_SEL 0x0100 /* Mode 0 is selected */ -#define ID_UDMA_5_SUP 0x0020 /* Mode 5 is supported */ -#define ID_UDMA_4_SUP 0x0010 /* Mode 4 is supported */ -#define ID_UDMA_3_SUP 0x0008 /* Mode 3 is supported */ -#define ID_UDMA_2_SUP 0x0004 /* Mode 2 is supported */ -#define ID_UDMA_1_SUP 0x0002 /* Mode 1 is supported */ -#define ID_UDMA_0_SUP 0x0001 /* Mode 0 is supported */ - -/* DMA registers */ -#define DMA_COMMAND 0 /* Command register */ -#define DMA_CMD_WRITE 0x08 /* PCI bus master writes */ -#define DMA_CMD_START 0x01 /* Start Bus Master */ -#define DMA_STATUS 2 /* Status register */ -#define DMA_ST_D1_DMACAP 0x40 /* Drive 1 is DMA capable */ -#define DMA_ST_D0_DMACAP 0x20 /* Drive 0 is DMA capable */ -#define DMA_ST_INT 0x04 /* Interrupt */ -#define DMA_ST_ERROR 0x02 /* Error */ -#define DMA_ST_BM_ACTIVE 0x01 /* Bus Master IDE Active */ -#define DMA_PRDTP 4 /* PRD Table Pointer */ - -/* Check for the presence of LBA48 only on drives that are 'big'. */ -#define LBA48_CHECK_SIZE 0x0f000000 -#define LBA_MAX_SIZE 0x0fffffff /* Highest sector size for - * regular LBA. - */ - -#if ENABLE_ATAPI -#define ERROR_SENSE 0xF0 /* sense key mask */ -#define SENSE_NONE 0x00 /* no sense key */ -#define SENSE_RECERR 0x10 /* recovered error */ -#define SENSE_NOTRDY 0x20 /* not ready */ -#define SENSE_MEDERR 0x30 /* medium error */ -#define SENSE_HRDERR 0x40 /* hardware error */ -#define SENSE_ILRQST 0x50 /* illegal request */ -#define SENSE_UATTN 0x60 /* unit attention */ -#define SENSE_DPROT 0x70 /* data protect */ -#define SENSE_ABRT 0xb0 /* aborted command */ -#define SENSE_MISCOM 0xe0 /* miscompare */ -#define ERROR_MCR 0x08 /* media change requested */ -#define ERROR_ABRT 0x04 /* aborted command */ -#define ERROR_EOM 0x02 /* end of media detected */ -#define ERROR_ILI 0x01 /* illegal length indication */ -#define REG_FEAT 1 /* features */ -#define FEAT_OVERLAP 0x02 /* overlap */ -#define FEAT_DMA 0x01 /* dma */ -#define REG_IRR 2 /* interrupt reason register */ -#define IRR_REL 0x04 /* release */ -#define IRR_IO 0x02 /* direction for xfer */ -#define IRR_COD 0x01 /* command or data */ -#define REG_SAMTAG 3 -#define REG_CNT_LO 4 /* low byte of cylinder number */ -#define REG_CNT_HI 5 /* high byte of cylinder number */ -#define REG_DRIVE 6 /* drive select */ -#endif - -#define REG_STATUS 7 /* status */ -#define STATUS_BSY 0x80 /* controller busy */ -#define STATUS_DRDY 0x40 /* drive ready */ -#define STATUS_DMADF 0x20 /* dma ready/drive fault */ -#define STATUS_SRVCDSC 0x10 /* service or dsc */ -#define STATUS_DRQ 0x08 /* data transfer request */ -#define STATUS_CORR 0x04 /* correctable error occurred */ -#define STATUS_CHECK 0x01 /* check error */ - -#ifdef ENABLE_ATAPI -#define ATAPI_PACKETCMD 0xA0 /* packet command */ -#define ATAPI_IDENTIFY 0xA1 /* identify drive */ -#define SCSI_READ10 0x28 /* read from disk */ -#define SCSI_SENSE 0x03 /* sense request */ - -#define CD_SECTOR_SIZE 2048 /* sector size of a CD-ROM */ -#endif /* ATAPI */ - -/* Interrupt request lines. */ -#define NO_IRQ 0 /* no IRQ set yet */ - -#define ATAPI_PACKETSIZE 12 -#define SENSE_PACKETSIZE 18 +/* Variables. */ /* Common command block */ struct command { @@ -216,44 +43,6 @@ struct command { u8_t cyl_hi_prev; }; -/* Error codes */ -#define ERR (-1) /* general error */ -#define ERR_BAD_SECTOR (-2) /* block marked bad detected */ - -/* Some controllers don't interrupt, the clock will wake us up. */ -#define WAKEUP_SECS 32 /* drive may be out for 31 seconds max */ -#define WAKEUP_TICKS (WAKEUP_SECS*system_hz) - -/* Miscellaneous. */ -#define MAX_DRIVES 8 -#define COMPAT_DRIVES 4 -#if _WORD_SIZE > 2 -#define MAX_SECS 256 /* controller can transfer this many sectors */ -#else -#define MAX_SECS 127 /* but not to a 16 bit process */ -#endif -#define MAX_ERRORS 4 /* how often to try rd/wt before quitting */ -#define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE) -#define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS) -#define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE) -#define DELAY_USECS 1000 /* controller timeout in microseconds */ -#define DELAY_TICKS 1 /* controller timeout in ticks */ -#define DEF_TIMEOUT_TICKS 300 /* controller timeout in ticks */ -#define RECOVERY_USECS 500000 /* controller recovery time in microseconds */ -#define RECOVERY_TICKS 30 /* controller recovery time in ticks */ -#define INITIALIZED 0x01 /* drive is initialized */ -#define DEAF 0x02 /* controller must be reset */ -#define SMART 0x04 /* drive supports ATA commands */ -#if ENABLE_ATAPI -#define ATAPI 0x08 /* it is an ATAPI device */ -#else -#define ATAPI 0 /* don't bother with ATAPI; optimise out */ -#endif -#define IDENTIFIED 0x10 /* w_identify done successfully */ -#define IGNORING 0x20 /* w_identify failed once */ - -#define NO_DMA_VAR "ata_no_dma" - /* Timeouts and max retries. */ int timeout_ticks = DEF_TIMEOUT_TICKS, max_errors = MAX_ERRORS; long w_standard_timeouts = 0, w_pci_debug = 0, w_instance = 0, @@ -266,8 +55,6 @@ int w_next_drive = 0; u32_t system_hz; -/* Variables. */ - /* The struct wini is indexed by controller first, then drive (0-3). * Controller 0 is always the 'compatability' ide controller, at * the fixed locations, whether present or not. @@ -303,7 +90,7 @@ PRIVATE int w_controller = -1; PRIVATE int w_major = -1; PRIVATE int win_tasknr; /* my task number */ -PRIVATE int w_command; /* current command in execution */ +PUBLIC int w_command; /* current command in execution */ PRIVATE u8_t w_byteval; /* used for SYS_IRQCTL */ PRIVATE int w_drive; /* selected drive */ PRIVATE int w_controller; /* selected controller */ @@ -428,14 +215,23 @@ PRIVATE struct driver w_dtab = { w_hw_int /* leftover hardware interrupts */ }; +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); +EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) ); +EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) ); +EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) ); + /*===========================================================================* * at_winchester_task * *===========================================================================*/ PUBLIC int main(int argc, char *argv[]) { -/* Install signal handlers. Ask PM to transform signal into message. */ struct sigaction sa; + /* SEF local startup. */ + sef_local_startup(); + + /* Install signal handlers. Ask PM to transform signal into message. */ system_hz = sys_hz(); init_buffer(); @@ -456,6 +252,20 @@ PUBLIC int main(int argc, char *argv[]) return(OK); } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid); + sef_setcb_lu_state_dump(sef_cb_lu_state_dump); + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * init_params * *===========================================================================*/ @@ -2070,8 +1880,8 @@ PRIVATE void w_intr_wait() */ while (w_wn->w_status & (STATUS_ADMBSY|STATUS_BSY)) { int rr; - if((rr=receive(ANY, &m)) != OK) - panic("at_wini", "receive(ANY) failed", rr); + if((rr=sef_receive(ANY, &m)) != OK) + panic("at_wini", "sef_receive(ANY) failed", rr); if (is_notify(m.m_type)) { switch (_ENDPOINT_P(m.m_source)) { case CLOCK: @@ -2088,10 +1898,6 @@ PRIVATE void w_intr_wait() w_wn->w_status= w_status; ack_irqs(m.NOTIFY_ARG); break; - case RS_PROC_NR: - /* RS monitor ping. */ - notify(m.m_source); - break; default: /* * unhandled message. queue it and @@ -2792,3 +2598,4 @@ PRIVATE int at_in(int line, u32_t port, u32_t *value, panic(w_name(), "sys_in failed", NO_NUM); } + diff --git a/drivers/at_wini/at_wini.h b/drivers/at_wini/at_wini.h index 3b0b8d0c4..258f023e6 100644 --- a/drivers/at_wini/at_wini.h +++ b/drivers/at_wini/at_wini.h @@ -6,3 +6,217 @@ _PROTOTYPE(int main, (int argc, char *argv[])); #define VERBOSE 0 /* display identify messages during boot */ #define ENABLE_ATAPI 1 /* add ATAPI cd-rom support to driver */ + +#define ATAPI_DEBUG 0 /* To debug ATAPI code. */ + +/* I/O Ports used by winchester disk controllers. */ + +/* Read and write registers */ +#define REG_CMD_BASE0 0x1F0 /* command base register of controller 0 */ +#define REG_CMD_BASE1 0x170 /* command base register of controller 1 */ +#define REG_CTL_BASE0 0x3F6 /* control base register of controller 0 */ +#define REG_CTL_BASE1 0x376 /* control base register of controller 1 */ + +#define PCI_CTL_OFF 2 /* Offset of control registers from BAR2 */ +#define PCI_DMA_2ND_OFF 8 /* Offset of DMA registers from BAR4 for + * secondary channel + */ + +#define REG_DATA 0 /* data register (offset from the base reg.) */ +#define REG_PRECOMP 1 /* start of write precompensation */ +#define REG_COUNT 2 /* sectors to transfer */ +#define REG_SECTOR 3 /* sector number */ +#define REG_CYL_LO 4 /* low byte of cylinder number */ +#define REG_CYL_HI 5 /* high byte of cylinder number */ +#define REG_LDH 6 /* lba, drive and head */ +#define LDH_DEFAULT 0xA0 /* ECC enable, 512 bytes per sector */ +#define LDH_LBA 0x40 /* Use LBA addressing */ +#define LDH_DEV 0x10 /* Drive 1 iff set */ +#define ldh_init(drive) (LDH_DEFAULT | ((drive) << 4)) + +/* Read only registers */ +#define REG_STATUS 7 /* status */ +#define STATUS_BSY 0x80 /* controller busy */ +#define STATUS_RDY 0x40 /* drive ready */ +#define STATUS_WF 0x20 /* write fault */ +#define STATUS_SC 0x10 /* seek complete (obsolete) */ +#define STATUS_DRQ 0x08 /* data transfer request */ +#define STATUS_CRD 0x04 /* corrected data */ +#define STATUS_IDX 0x02 /* index pulse */ +#define STATUS_ERR 0x01 /* error */ +#define STATUS_ADMBSY 0x100 /* administratively busy (software) */ +#define REG_ERROR 1 /* error code */ +#define ERROR_BB 0x80 /* bad block */ +#define ERROR_ECC 0x40 /* bad ecc bytes */ +#define ERROR_ID 0x10 /* id not found */ +#define ERROR_AC 0x04 /* aborted command */ +#define ERROR_TK 0x02 /* track zero error */ +#define ERROR_DM 0x01 /* no data address mark */ + +/* Write only registers */ +#define REG_COMMAND 7 /* command */ +#define CMD_IDLE 0x00 /* for w_command: drive idle */ +#define CMD_RECALIBRATE 0x10 /* recalibrate drive */ +#define CMD_READ 0x20 /* read data */ +#define CMD_READ_EXT 0x24 /* read data (LBA48 addressed) */ +#define CMD_READ_DMA_EXT 0x25 /* read data using DMA (w/ LBA48) */ +#define CMD_WRITE 0x30 /* write data */ +#define CMD_WRITE_EXT 0x34 /* write data (LBA48 addressed) */ +#define CMD_WRITE_DMA_EXT 0x35 /* write data using DMA (w/ LBA48) */ +#define CMD_READVERIFY 0x40 /* read verify */ +#define CMD_FORMAT 0x50 /* format track */ +#define CMD_SEEK 0x70 /* seek cylinder */ +#define CMD_DIAG 0x90 /* execute device diagnostics */ +#define CMD_SPECIFY 0x91 /* specify parameters */ +#define CMD_READ_DMA 0xC8 /* read data using DMA */ +#define CMD_WRITE_DMA 0xCA /* write data using DMA */ +#define ATA_IDENTIFY 0xEC /* identify drive */ +/* #define REG_CTL 0x206 */ /* control register */ +#define REG_CTL 0 /* control register */ +#define CTL_NORETRY 0x80 /* disable access retry */ +#define CTL_NOECC 0x40 /* disable ecc retry */ +#define CTL_EIGHTHEADS 0x08 /* more than eight heads */ +#define CTL_RESET 0x04 /* reset controller */ +#define CTL_INTDISABLE 0x02 /* disable interrupts */ +#define REG_CTL_ALTSTAT 0 /* alternate status register */ + +/* Identify words */ +#define ID_GENERAL 0x00 /* General configuration information */ +#define ID_GEN_NOT_ATA 0x8000 /* Not an ATA device */ +#define ID_CAPABILITIES 0x31 /* Capabilities (49)*/ +#define ID_CAP_LBA 0x0200 /* LBA supported */ +#define ID_CAP_DMA 0x0100 /* DMA supported */ +#define ID_FIELD_VALIDITY 0x35 /* Field Validity (53) */ +#define ID_FV_88 0x04 /* Word 88 is valid (UDMA) */ +#define ID_MULTIWORD_DMA 0x3f /* Multiword DMA (63) */ +#define ID_MWDMA_2_SEL 0x0400 /* Mode 2 is selected */ +#define ID_MWDMA_1_SEL 0x0200 /* Mode 1 is selected */ +#define ID_MWDMA_0_SEL 0x0100 /* Mode 0 is selected */ +#define ID_MWDMA_2_SUP 0x0004 /* Mode 2 is supported */ +#define ID_MWDMA_1_SUP 0x0002 /* Mode 1 is supported */ +#define ID_MWDMA_0_SUP 0x0001 /* Mode 0 is supported */ +#define ID_CSS 0x53 /* Command Sets Supported (83) */ +#define ID_CSS_LBA48 0x0400 +#define ID_ULTRA_DMA 0x58 /* Ultra DMA (88) */ +#define ID_UDMA_5_SEL 0x2000 /* Mode 5 is selected */ +#define ID_UDMA_4_SEL 0x1000 /* Mode 4 is selected */ +#define ID_UDMA_3_SEL 0x0800 /* Mode 3 is selected */ +#define ID_UDMA_2_SEL 0x0400 /* Mode 2 is selected */ +#define ID_UDMA_1_SEL 0x0200 /* Mode 1 is selected */ +#define ID_UDMA_0_SEL 0x0100 /* Mode 0 is selected */ +#define ID_UDMA_5_SUP 0x0020 /* Mode 5 is supported */ +#define ID_UDMA_4_SUP 0x0010 /* Mode 4 is supported */ +#define ID_UDMA_3_SUP 0x0008 /* Mode 3 is supported */ +#define ID_UDMA_2_SUP 0x0004 /* Mode 2 is supported */ +#define ID_UDMA_1_SUP 0x0002 /* Mode 1 is supported */ +#define ID_UDMA_0_SUP 0x0001 /* Mode 0 is supported */ + +/* DMA registers */ +#define DMA_COMMAND 0 /* Command register */ +#define DMA_CMD_WRITE 0x08 /* PCI bus master writes */ +#define DMA_CMD_START 0x01 /* Start Bus Master */ +#define DMA_STATUS 2 /* Status register */ +#define DMA_ST_D1_DMACAP 0x40 /* Drive 1 is DMA capable */ +#define DMA_ST_D0_DMACAP 0x20 /* Drive 0 is DMA capable */ +#define DMA_ST_INT 0x04 /* Interrupt */ +#define DMA_ST_ERROR 0x02 /* Error */ +#define DMA_ST_BM_ACTIVE 0x01 /* Bus Master IDE Active */ +#define DMA_PRDTP 4 /* PRD Table Pointer */ + +/* Check for the presence of LBA48 only on drives that are 'big'. */ +#define LBA48_CHECK_SIZE 0x0f000000 +#define LBA_MAX_SIZE 0x0fffffff /* Highest sector size for + * regular LBA. + */ + +#if ENABLE_ATAPI +#define ERROR_SENSE 0xF0 /* sense key mask */ +#define SENSE_NONE 0x00 /* no sense key */ +#define SENSE_RECERR 0x10 /* recovered error */ +#define SENSE_NOTRDY 0x20 /* not ready */ +#define SENSE_MEDERR 0x30 /* medium error */ +#define SENSE_HRDERR 0x40 /* hardware error */ +#define SENSE_ILRQST 0x50 /* illegal request */ +#define SENSE_UATTN 0x60 /* unit attention */ +#define SENSE_DPROT 0x70 /* data protect */ +#define SENSE_ABRT 0xb0 /* aborted command */ +#define SENSE_MISCOM 0xe0 /* miscompare */ +#define ERROR_MCR 0x08 /* media change requested */ +#define ERROR_ABRT 0x04 /* aborted command */ +#define ERROR_EOM 0x02 /* end of media detected */ +#define ERROR_ILI 0x01 /* illegal length indication */ +#define REG_FEAT 1 /* features */ +#define FEAT_OVERLAP 0x02 /* overlap */ +#define FEAT_DMA 0x01 /* dma */ +#define REG_IRR 2 /* interrupt reason register */ +#define IRR_REL 0x04 /* release */ +#define IRR_IO 0x02 /* direction for xfer */ +#define IRR_COD 0x01 /* command or data */ +#define REG_SAMTAG 3 +#define REG_CNT_LO 4 /* low byte of cylinder number */ +#define REG_CNT_HI 5 /* high byte of cylinder number */ +#define REG_DRIVE 6 /* drive select */ +#endif + +#define REG_STATUS 7 /* status */ +#define STATUS_BSY 0x80 /* controller busy */ +#define STATUS_DRDY 0x40 /* drive ready */ +#define STATUS_DMADF 0x20 /* dma ready/drive fault */ +#define STATUS_SRVCDSC 0x10 /* service or dsc */ +#define STATUS_DRQ 0x08 /* data transfer request */ +#define STATUS_CORR 0x04 /* correctable error occurred */ +#define STATUS_CHECK 0x01 /* check error */ + +#if ENABLE_ATAPI +#define ATAPI_PACKETCMD 0xA0 /* packet command */ +#define ATAPI_IDENTIFY 0xA1 /* identify drive */ +#define SCSI_READ10 0x28 /* read from disk */ +#define SCSI_SENSE 0x03 /* sense request */ + +#define CD_SECTOR_SIZE 2048 /* sector size of a CD-ROM */ +#endif /* ATAPI */ + +/* Interrupt request lines. */ +#define NO_IRQ 0 /* no IRQ set yet */ + +#define ATAPI_PACKETSIZE 12 +#define SENSE_PACKETSIZE 18 + +/* Error codes */ +#define ERR (-1) /* general error */ +#define ERR_BAD_SECTOR (-2) /* block marked bad detected */ + +/* Some controllers don't interrupt, the clock will wake us up. */ +#define WAKEUP_SECS 32 /* drive may be out for 31 seconds max */ +#define WAKEUP_TICKS (WAKEUP_SECS*system_hz) + +/* Miscellaneous. */ +#define MAX_DRIVES 8 +#define COMPAT_DRIVES 4 +#if _WORD_SIZE > 2 +#define MAX_SECS 256 /* controller can transfer this many sectors */ +#else +#define MAX_SECS 127 /* but not to a 16 bit process */ +#endif +#define MAX_ERRORS 4 /* how often to try rd/wt before quitting */ +#define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE) +#define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS) +#define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE) +#define DELAY_USECS 1000 /* controller timeout in microseconds */ +#define DELAY_TICKS 1 /* controller timeout in ticks */ +#define DEF_TIMEOUT_TICKS 300 /* controller timeout in ticks */ +#define RECOVERY_USECS 500000 /* controller recovery time in microseconds */ +#define RECOVERY_TICKS 30 /* controller recovery time in ticks */ +#define INITIALIZED 0x01 /* drive is initialized */ +#define DEAF 0x02 /* controller must be reset */ +#define SMART 0x04 /* drive supports ATA commands */ +#if ENABLE_ATAPI +#define ATAPI 0x08 /* it is an ATAPI device */ +#else +#define ATAPI 0 /* don't bother with ATAPI; optimise out */ +#endif +#define IDENTIFIED 0x10 /* w_identify done successfully */ +#define IGNORING 0x20 /* w_identify failed once */ + +#define NO_DMA_VAR "ata_no_dma" + diff --git a/drivers/at_wini/liveupdate.c b/drivers/at_wini/liveupdate.c new file mode 100644 index 000000000..188736886 --- /dev/null +++ b/drivers/at_wini/liveupdate.c @@ -0,0 +1,78 @@ +#include "at_wini.h" + +/* State management variables. */ +EXTERN int w_command; + +/* State management helpers. */ +#define IS_REQUEST_PENDING(c) ((c) != CMD_IDLE) +#define IS_READ_PENDING(c) ((c) == CMD_READ \ + || (c) == CMD_READ_EXT || (c) == CMD_READ_DMA || (c) == CMD_READ_DMA_EXT) +#define IS_WRITE_PENDING(c) ((c) == CMD_WRITE \ + || (c) == CMD_WRITE_EXT || (c) == CMD_WRITE_DMA || (c) == CMD_WRITE_DMA_EXT) + +/* Custom states definition. */ +#define AT_STATE_READ_REQUEST_FREE (SEF_LU_STATE_CUSTOM_BASE + 0) +#define AT_STATE_WRITE_REQUEST_FREE (SEF_LU_STATE_CUSTOM_BASE + 1) +#define AT_STATE_IS_CUSTOM(s) \ + ((s) >= AT_STATE_READ_REQUEST_FREE && (s) <= AT_STATE_WRITE_REQUEST_FREE) + +/*===========================================================================* + * sef_cb_lu_prepare * + *===========================================================================*/ +PUBLIC void sef_cb_lu_prepare(int state) +{ + int is_ready; + + /* Check if we are ready for the target state. */ + is_ready = FALSE; + switch(state) { + /* Standard states. */ + case SEF_LU_STATE_REQUEST_FREE: + case SEF_LU_STATE_PROTOCOL_FREE: + is_ready = (!IS_REQUEST_PENDING(w_command)); + break; + + /* Custom states. */ + case AT_STATE_READ_REQUEST_FREE: + is_ready = (!IS_READ_PENDING(w_command)); + break; + + case AT_STATE_WRITE_REQUEST_FREE: + is_ready = (!IS_WRITE_PENDING(w_command)); + break; + } + + /* Tell SEF if we are ready. */ + if(is_ready) { + sef_lu_ready(OK); + } +} + +/*===========================================================================* + * sef_cb_lu_state_isvalid * + *===========================================================================*/ +PUBLIC int sef_cb_lu_state_isvalid(int state) +{ + return SEF_LU_STATE_IS_STANDARD(state) || AT_STATE_IS_CUSTOM(state); +} + +/*===========================================================================* + * sef_cb_lu_state_dump * + *===========================================================================*/ +PUBLIC void sef_cb_lu_state_dump(int state) +{ + sef_lu_dprint("at_wini: live update state = %d\n", state); + sef_lu_dprint("at_wini: w_command = 0x%02X\n", w_command); + + sef_lu_dprint("at_wini: SEF_LU_STATE_WORK_FREE(%d) reached = %d\n", + SEF_LU_STATE_WORK_FREE, TRUE); + sef_lu_dprint("at_wini: SEF_LU_STATE_REQUEST_FREE(%d) reached = %d\n", + SEF_LU_STATE_REQUEST_FREE, (!IS_REQUEST_PENDING(w_command))); + sef_lu_dprint("at_wini: SEF_LU_STATE_PROTOCOL_FREE(%d) reached = %d\n", + SEF_LU_STATE_PROTOCOL_FREE, (!IS_REQUEST_PENDING(w_command))); + sef_lu_dprint("at_wini: AT_STATE_READ_REQUEST_FREE(%d) reached = %d\n", + AT_STATE_READ_REQUEST_FREE, (!IS_READ_PENDING(w_command))); + sef_lu_dprint("at_wini: AT_STATE_WRITE_REQUEST_FREE(%d) reached = %d\n", + AT_STATE_WRITE_REQUEST_FREE, (!IS_WRITE_PENDING(w_command))); +} + diff --git a/drivers/audio/es1370/Makefile b/drivers/audio/es1370/Makefile index d10121df6..828a415ca 100644 --- a/drivers/audio/es1370/Makefile +++ b/drivers/audio/es1370/Makefile @@ -17,11 +17,11 @@ LIBS = -lsys # build local binary all: es1370 -es1370: es1370.o ak4531.o audio_fw.o pci_helper.o - $(CC) -o $@ $(LDFLAGS) es1370.o ak4531.o audio_fw.o pci_helper.o $(LIBS) +es1370: es1370.o ak4531.o audio_fw.o liveupdate.o pci_helper.o + $(CC) -o $@ $(LDFLAGS) es1370.o ak4531.o audio_fw.o liveupdate.o pci_helper.o $(LIBS) -audio_fw.o: ../framework/audio_fw.c ../framework/audio_fw.h - $(CC) -c ../framework/audio_fw.c +audio_fw.o liveupdate.o: ../framework/audio_fw.c ../framework/liveupdate.c ../framework/audio_fw.h + $(CC) -c ../framework/audio_fw.c ../framework/liveupdate.c install: /usr/sbin/es1370 /usr/sbin/es1370: es1370 diff --git a/drivers/audio/es1371/Makefile b/drivers/audio/es1371/Makefile index ae7d5faf1..db5df78a3 100644 --- a/drivers/audio/es1371/Makefile +++ b/drivers/audio/es1371/Makefile @@ -15,7 +15,7 @@ LIBS = -lsys PROGRAM_NAME = es1371 INSTALL_BIN = /usr/sbin/$(PROGRAM_NAME) -OBJ = es1371.o AC97.o audio_fw.o pci_helper.o wait.o sample_rate_converter.o +OBJ = es1371.o AC97.o audio_fw.o liveupdate.o pci_helper.o wait.o sample_rate_converter.o @@ -27,8 +27,8 @@ $(PROGRAM_NAME): $(OBJ) $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS) -audio_fw.o: ../framework/audio_fw.c ../framework/audio_fw.h - $(CC) -c ../framework/audio_fw.c +audio_fw.o liveupdate.o: ../framework/audio_fw.c ../framework/liveupdate.c ../framework/audio_fw.h + $(CC) -c ../framework/audio_fw.c ../framework/liveupdate.c %.o: %.c diff --git a/drivers/audio/framework/Makefile b/drivers/audio/framework/Makefile index 4273ada8c..c210c8d13 100644 --- a/drivers/audio/framework/Makefile +++ b/drivers/audio/framework/Makefile @@ -1,9 +1,9 @@ CC = exec cc -all: audio_fw.o +all: audio_fw.o liveupdate.o -audio_fw.o: - $(CC) -c audio_fw.c +audio_fw.o liveupdate.o: + $(CC) -c audio_fw.c liveupdate.c clean: - rm -f a.out *.bak core errs audio_fw.o + rm -f a.out *.bak core errs audio_fw.o liveupdate.o diff --git a/drivers/audio/framework/audio_fw.c b/drivers/audio/framework/audio_fw.c index 70c7c1bf8..84951eb7c 100644 --- a/drivers/audio/framework/audio_fw.c +++ b/drivers/audio/framework/audio_fw.c @@ -77,19 +77,28 @@ PRIVATE int irq_hook_id = 0; /* id of irq hook at the kernel */ PRIVATE int irq_hook_set = FALSE; PRIVATE device_available = 0;/*todo*/ +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); +EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) ); +EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) ); +EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) ); +PUBLIC int is_status_msg_expected = FALSE; PUBLIC void main(void) { int r, caller, proc_nr, chan; message mess, repl_mess; + /* SEF local startup. */ + sef_local_startup(); + drv_init(); /* Here is the main loop of the dma driver. It waits for a message, carries it out, and sends a reply. */ while(1) { - receive(ANY, &mess); + sef_receive(ANY, &mess); caller = mess.m_source; proc_nr = mess.IO_ENDPT; @@ -102,10 +111,6 @@ PUBLIC void main(void) case PM_PROC_NR: msg_sig_stop(); break; - case RS_PROC_NR: - /* Got ping from RS. Just notify RS */ - notify(RS_PROC_NR); - break; default: dprint("%s: %d uncaught notify!\n", drv.DriverName, mess.m_type); @@ -175,6 +180,19 @@ PUBLIC void main(void) } } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid); + sef_setcb_lu_state_dump(sef_cb_lu_state_dump); + + /* Let SEF perform startup. */ + sef_startup(); +} PRIVATE int init_driver(void) { u32_t i; char irq; @@ -589,6 +607,7 @@ PRIVATE void msg_status(message *m_ptr) sub_dev[i].ReadyToRevive = FALSE; sub_dev[i].RevivePending = 0; + is_status_msg_expected = TRUE; return; /* stop after one mess, file system will get back for other processes */ } @@ -596,6 +615,7 @@ PRIVATE void msg_status(message *m_ptr) m_ptr->m_type = DEV_NO_STATUS; m_ptr->REP_STATUS = 0; send(m_ptr->m_source, m_ptr); /* send DEV_NO_STATUS message */ + is_status_msg_expected = FALSE; } diff --git a/drivers/audio/framework/liveupdate.c b/drivers/audio/framework/liveupdate.c new file mode 100644 index 000000000..dc8546745 --- /dev/null +++ b/drivers/audio/framework/liveupdate.c @@ -0,0 +1,117 @@ +#include "audio_fw.h" + +/* State management variables. */ +EXTERN int is_status_msg_expected; +/* + * - From audio_fw.h: + * EXTERN drv_t drv; + * EXTERN sub_dev_t sub_dev[]; +*/ + +/* State management helpers */ +PRIVATE int is_read_pending; +PRIVATE int is_write_pending; +PRIVATE void load_state_info(void) +{ + int i, dma_mode, found_pending; + + /* Check if reads or writes are pending. */ + is_read_pending = FALSE; + is_write_pending = FALSE; + found_pending = FALSE; + for (i = 0; i < drv.NrOfSubDevices && !found_pending; i++) { + if(sub_dev[i].RevivePending) { + dma_mode = sub_dev[i].DmaMode; + + if(dma_mode = DEV_READ_S) { + is_read_pending = TRUE; + } + else if (dma_mode = DEV_WRITE_S){ + is_write_pending = TRUE; + } + } + + found_pending = (is_read_pending && is_write_pending); + } +} + +/* Custom states definition. */ +#define AUDIO_STATE_READ_REQUEST_FREE (SEF_LU_STATE_CUSTOM_BASE + 0) +#define AUDIO_STATE_WRITE_REQUEST_FREE (SEF_LU_STATE_CUSTOM_BASE + 1) +#define AUDIO_STATE_IS_CUSTOM(s) \ + ((s) >= AUDIO_STATE_READ_REQUEST_FREE && (s) <=AUDIO_STATE_WRITE_REQUEST_FREE) + +/*===========================================================================* + * sef_cb_lu_prepare * + *===========================================================================*/ +PUBLIC void sef_cb_lu_prepare(int state) +{ + int is_ready; + + /* Load state information. */ + load_state_info(); + + /* Check if we are ready for the target state. */ + is_ready = FALSE; + switch(state) { + /* Standard states. */ + case SEF_LU_STATE_REQUEST_FREE: + is_ready = (!is_read_pending && !is_write_pending); + break; + + case SEF_LU_STATE_PROTOCOL_FREE: + is_ready = (!is_read_pending && !is_write_pending + && !is_status_msg_expected); + break; + + /* Custom states. */ + case AUDIO_STATE_READ_REQUEST_FREE: + is_ready = (!is_read_pending); + break; + + case AUDIO_STATE_WRITE_REQUEST_FREE: + is_ready = (!is_write_pending); + break; + } + + /* Tell SEF if we are ready. */ + if(is_ready) { + sef_lu_ready(OK); + } +} + +/*===========================================================================* + * sef_cb_lu_state_isvalid * + *===========================================================================*/ +PUBLIC int sef_cb_lu_state_isvalid(int state) +{ + return SEF_LU_STATE_IS_STANDARD(state) || AUDIO_STATE_IS_CUSTOM(state); +} + +/*===========================================================================* + * sef_cb_lu_state_dump * + *===========================================================================*/ +PUBLIC void sef_cb_lu_state_dump(int state) +{ + /* Load state information. */ + load_state_info(); + + sef_lu_dprint("audio: live update state = %d\n", state); + sef_lu_dprint("audio: is_status_msg_expected = %d\n", + is_status_msg_expected); + sef_lu_dprint("audio: is_read_pending = %d\n", is_read_pending); + sef_lu_dprint("audio: is_write_pending = %d\n", is_write_pending); + + sef_lu_dprint("audio: SEF_LU_STATE_WORK_FREE(%d) reached = %d\n", + SEF_LU_STATE_WORK_FREE, TRUE); + sef_lu_dprint("audio: SEF_LU_STATE_REQUEST_FREE(%d) reached = %d\n", + SEF_LU_STATE_REQUEST_FREE, (!is_read_pending && !is_write_pending)); + sef_lu_dprint("audio: SEF_LU_STATE_PROTOCOL_FREE(%d) reached = %d\n", + SEF_LU_STATE_PROTOCOL_FREE, (!is_read_pending && !is_write_pending + && !is_status_msg_expected)); + sef_lu_dprint("audio: AUDIO_STATE_READ_REQUEST_FREE(%d) reached = %d\n", + AUDIO_STATE_READ_REQUEST_FREE, (!is_read_pending)); + sef_lu_dprint("audio: AUDIO_STATE_WRITE_REQUEST_FREE(%d) reached = %d\n", + AUDIO_STATE_WRITE_REQUEST_FREE, (!is_write_pending)); +} + diff --git a/drivers/audio/sb16/Makefile b/drivers/audio/sb16/Makefile index 2b2591f33..ae892173d 100644 --- a/drivers/audio/sb16/Makefile +++ b/drivers/audio/sb16/Makefile @@ -18,11 +18,11 @@ LIBS = -lsys # build local binary all build: sb16 -sb16: sb16.o mixer.o audio_fw.o - $(CC) -o $@ $(LDFLAGS) sb16.o mixer.o audio_fw.o $(LIBS) +sb16: sb16.o mixer.o audio_fw.o liveupdate.o + $(CC) -o $@ $(LDFLAGS) sb16.o mixer.o audio_fw.o liveupdate.o $(LIBS) -audio_fw.o: ../framework/audio_fw.c ../framework/audio_fw.h - $(CC) -c ../framework/audio_fw.c +audio_fw.o liveupdate.o: ../framework/audio_fw.c ../framework/liveupdate.c ../framework/audio_fw.h + $(CC) -c ../framework/audio_fw.c ../framework/liveupdate.c # install with other drivers install: /usr/sbin/sb16 diff --git a/drivers/bios_wini/bios_wini.c b/drivers/bios_wini/bios_wini.c index b8e4cce40..c14ce12da 100644 --- a/drivers/bios_wini/bios_wini.c +++ b/drivers/bios_wini/bios_wini.c @@ -94,6 +94,9 @@ PRIVATE struct driver w_dtab = { NULL /* leftover hardware interrupts */ }; +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * bios_winchester_task * *===========================================================================*/ @@ -101,6 +104,9 @@ PUBLIC int main() { long v; + /* SEF local startup. */ + sef_local_startup(); + v= 0; env_parse("bios_remap_first", "d", 0, &v, 0, 1); remap_first= v; @@ -110,6 +116,19 @@ PUBLIC int main() return(OK); } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard); + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * w_prepare * *===========================================================================*/ @@ -512,3 +531,4 @@ message *m; return EINVAL; } + diff --git a/drivers/dp8390/dp8390.c b/drivers/dp8390/dp8390.c index cce2c0ab8..9dfac7d63 100644 --- a/drivers/dp8390/dp8390.c +++ b/drivers/dp8390/dp8390.c @@ -232,6 +232,9 @@ PRIVATE int handle_hw_intr(void) return r; } +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * dpeth_task * *===========================================================================*/ @@ -242,6 +245,9 @@ int main(int argc, char *argv[]) dpeth_t *dep; long v; + /* SEF local startup. */ + sef_local_startup(); + system_hz = sys_hz(); if (argc < 1) @@ -270,14 +276,11 @@ int main(int argc, char *argv[]) while (TRUE) { - if ((r= receive(ANY, &m)) != OK) - panic("", "dp8390: receive failed", r); + if ((r= sef_receive(ANY, &m)) != OK) + panic("", "dp8390: sef_receive failed", r); if (is_notify(m.m_type)) { switch (_ENDPOINT_P(m.m_source)) { - case RS_PROC_NR: - notify(m.m_source); - break; case HARDWARE: r = handle_hw_intr(); break; @@ -323,6 +326,17 @@ int main(int argc, char *argv[]) } } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + #if 0 /*===========================================================================* * dp8390_dump * diff --git a/drivers/dpeth/dp.c b/drivers/dpeth/dp.c index afbb73861..7de00b474 100644 --- a/drivers/dpeth/dp.c +++ b/drivers/dpeth/dp.c @@ -86,7 +86,7 @@ static dp_conf_t dp_conf[DE_PORT_NR] = { static char CopyErrMsg[] = "unable to read/write user data"; static char PortErrMsg[] = "illegal port"; -static char RecvErrMsg[] = "receive failed"; +static char RecvErrMsg[] = "sef_receive failed"; static char SendErrMsg[] = "send failed"; static char SizeErrMsg[] = "illegal packet size"; static char TypeErrMsg[] = "illegal message type"; @@ -577,6 +577,9 @@ PRIVATE void handle_hw_intr(void) } } +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /* ** Name: int dpeth_task(void) ** Function: Main entry for dp task @@ -587,6 +590,9 @@ PUBLIC int main(int argc, char **argv) dpeth_t *dep; int rc, fkeys, sfkeys, tasknr; + /* SEF local startup. */ + sef_local_startup(); + (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]); env_setargs(argc, argv); @@ -612,7 +618,7 @@ PUBLIC int main(int argc, char **argv) notify(tasknr); while (TRUE) { - if ((rc = receive(ANY, &m)) != OK) panic(dep->de_name, RecvErrMsg, rc); + if ((rc = sef_receive(ANY, &m)) != OK) panic(dep->de_name, RecvErrMsg, rc); DEBUG(printf("eth: got message %d, ", m.m_type)); @@ -622,10 +628,6 @@ PUBLIC int main(int argc, char **argv) /* to be defined */ do_watchdog(&m); break; - case RS_PROC_NR: - /* Status request from RS */ - notify(m.m_source); - break; case HARDWARE: /* Interrupt from device */ handle_hw_intr(); @@ -673,4 +675,15 @@ PUBLIC int main(int argc, char **argv) return OK; /* Never reached, but keeps compiler happy */ } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + /** dp.c **/ diff --git a/drivers/e1000/e1000.c b/drivers/e1000/e1000.c index 3e9c887e2..22c5a4ebb 100644 --- a/drivers/e1000/e1000.c +++ b/drivers/e1000/e1000.c @@ -62,6 +62,9 @@ _PROTOTYPE( PRIVATE int eeprom_ich_cycle, (e1000_t *e, u32_t timeout) ); _PROTOTYPE( PRIVATE void reply, (e1000_t *e, int err, int may_block) ); _PROTOTYPE( PRIVATE void mess_reply, (message *req, message *reply) ); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -73,6 +76,9 @@ int main(int argc, char *argv[]) e1000_t *e; long v; + /* SEF local startup. */ + sef_local_startup(); + /* Verify command-line arguments. */ if (argc < 1) { @@ -104,18 +110,14 @@ int main(int argc, char *argv[]) */ while (TRUE) { - if ((r= receive(ANY, &m)) != OK) + if ((r= sef_receive(ANY, &m)) != OK) { - panic("e1000", "receive failed", r); + panic("e1000", "sef_receive failed", r); } if (is_notify(m.m_type)) { switch (_ENDPOINT_P(m.m_source)) { - case RS_PROC_NR: - notify(m.m_source); - break; - case HARDWARE: e1000_interrupt(&m); break; @@ -143,6 +145,17 @@ int main(int argc, char *argv[]) } } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * e1000_init * *===========================================================================*/ diff --git a/drivers/filter/driver.c b/drivers/filter/driver.c index 97e095850..e840308f2 100644 --- a/drivers/filter/driver.c +++ b/drivers/filter/driver.c @@ -583,9 +583,9 @@ static int flt_receive(message *mess, int which) int r; for (;;) { - r = receive(ANY, mess); + r = sef_receive(ANY, mess); if(r != OK) - panic(__FILE__, "receive returned error", r); + panic(__FILE__, "sef_receive returned error", r); if(mess->m_source == CLOCK && is_notify(mess->m_type)) { if (mess->NOTIFY_TIMESTAMP < flt_alarm(-1)) { diff --git a/drivers/filter/main.c b/drivers/filter/main.c index 0813ecd84..a973f1a3b 100644 --- a/drivers/filter/main.c +++ b/drivers/filter/main.c @@ -376,6 +376,9 @@ static void got_signal(void) exit(0); } +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -384,6 +387,9 @@ int main(int argc, char *argv[]) message m_out; int r; + /* SEF local startup. */ + sef_local_startup(); + r = parse_arguments(argc, argv); if(r != OK) { printf("Filter: wrong argument!\n"); @@ -399,8 +405,8 @@ int main(int argc, char *argv[]) for (;;) { /* Wait for request. */ - if(receive(ANY, &m_in) != OK) { - panic(__FILE__, "receive failed", NO_NUM); + if(sef_receive(ANY, &m_in) != OK) { + panic(__FILE__, "sef_receive failed", NO_NUM); } #if DEBUG2 @@ -444,3 +450,15 @@ int main(int argc, char *argv[]) return 0; } + +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + diff --git a/drivers/floppy/Makefile b/drivers/floppy/Makefile index 07dcf18fd..e690291fd 100644 --- a/drivers/floppy/Makefile +++ b/drivers/floppy/Makefile @@ -16,7 +16,7 @@ CFLAGS = -I$i $(CPROFILE) LDFLAGS = -i -L../libdriver LIBS = -ldriver -lsys -ltimers -OBJ = floppy.o +OBJ = floppy.o liveupdate.o # build local binary all build: $(DRIVER) diff --git a/drivers/floppy/floppy.c b/drivers/floppy/floppy.c index 27c7215e0..3788d8a3d 100644 --- a/drivers/floppy/floppy.c +++ b/drivers/floppy/floppy.c @@ -29,6 +29,7 @@ #include #include #include +#include /* I/O Ports used by floppy disk task. */ #define DOR 0x3F2 /* motor drive control bits */ @@ -219,15 +220,15 @@ PRIVATE struct floppy { /* main drive struct, one entry per drive */ } floppy[NR_DRIVES]; PRIVATE int irq_hook_id; /* id of irq hook at the kernel */ -PRIVATE int motor_status; /* bitmap of current motor status */ +PUBLIC int motor_status; /* bitmap of current motor status */ PRIVATE int need_reset; /* set to 1 when controller must be reset */ -PRIVATE unsigned f_drive; /* selected drive */ +PUBLIC unsigned f_drive; /* selected drive */ PRIVATE unsigned f_device; /* selected minor device */ PRIVATE struct floppy *f_fp; /* current drive */ PRIVATE struct density *f_dp; /* current density parameters */ PRIVATE struct density *prev_dp;/* previous density parameters */ PRIVATE unsigned f_sectors; /* equal to f_dp->secpt (needed a lot) */ -PRIVATE u16_t f_busy; /* BSY_IDLE, BSY_IO, BSY_WAKEN */ +PUBLIC u16_t f_busy; /* BSY_IDLE, BSY_IO, BSY_WAKEN */ PRIVATE struct device *f_dv; /* device's base and size */ PRIVATE struct disk_parameter_s fmt_param; /* parameters for format */ PRIVATE u8_t f_results[MAX_RESULTS];/* the controller can give lots of output */ @@ -289,16 +290,25 @@ PRIVATE struct driver f_dtab = { static char *floppy_buf; static phys_bytes floppy_buf_phys; +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); +EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) ); +EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) ); +EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) ); +PUBLIC int last_transfer_opcode; + /*===========================================================================* * floppy_task * *===========================================================================*/ PUBLIC void main() { -/* Initialize the floppy structure and the timers. */ - struct floppy *fp; int s; + /* SEF local startup. */ + sef_local_startup(); + + /* Initialize the floppy structure and the timers. */ system_hz = sys_hz(); if(!(floppy_buf = alloc_contig(2*DMA_BUF_SIZE, @@ -330,6 +340,20 @@ PUBLIC void main() driver_task(&f_dtab, DRIVER_STD); } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid); + sef_setcb_lu_state_dump(sef_cb_lu_state_dump); + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * f_expire_tmrs * *===========================================================================*/ @@ -469,6 +493,9 @@ unsigned nr_req; /* length of request vector */ return OK; /* Way beyond EOF */ position= cv64ul(pos64); + /* Record the opcode of the last transfer performed. */ + last_transfer_opcode = opcode; + /* Check disk address. */ if ((position & SECTOR_MASK) != 0) return(EINVAL); @@ -759,16 +786,13 @@ PRIVATE void start_motor() f_set_timer(&f_tmr_timeout, f_dp->start_ms * system_hz / 1000, f_timeout); f_busy = BSY_IO; do { - receive(ANY, &mess); + sef_receive(ANY, &mess); if (is_notify(mess.m_type)) { switch (_ENDPOINT_P(mess.m_source)) { case CLOCK: f_expire_tmrs(NULL, NULL); break; - case RS_PROC_NR: - notify(mess.m_source); - break; default : f_busy = BSY_IDLE; break; @@ -851,16 +875,13 @@ PRIVATE int seek() f_set_timer(&f_tmr_timeout, system_hz/30, f_timeout); f_busy = BSY_IO; do { - receive(ANY, &mess); + sef_receive(ANY, &mess); if (is_notify(mess.m_type)) { switch (_ENDPOINT_P(mess.m_source)) { case CLOCK: f_expire_tmrs(NULL, NULL); break; - case RS_PROC_NR: - notify(mess.m_source); - break; default : f_busy = BSY_IDLE; break; @@ -1133,15 +1154,12 @@ PRIVATE void f_reset() * but be prepared to handle a timeout. */ do { - receive(ANY, &mess); + sef_receive(ANY, &mess); if (is_notify(mess.m_type)) { switch (_ENDPOINT_P(mess.m_source)) { case CLOCK: f_expire_tmrs(NULL, NULL); break; - case RS_PROC_NR: - notify(mess.m_source); - break; default : f_busy = BSY_IDLE; break; @@ -1185,15 +1203,12 @@ PRIVATE int f_intr_wait() /* We expect an interrupt, but if a timeout, occurs, report an error. */ do { - receive(ANY, &mess); + sef_receive(ANY, &mess); if (is_notify(mess.m_type)) { switch (_ENDPOINT_P(mess.m_source)) { case CLOCK: f_expire_tmrs(NULL, NULL); break; - case RS_PROC_NR: - notify(mess.m_source); - break; default : f_busy = BSY_IDLE; break; @@ -1365,3 +1380,4 @@ struct partition *entry; entry->sectors = f_sectors; } + diff --git a/drivers/floppy/floppy.h b/drivers/floppy/floppy.h index b1c64ccf1..6d737ab7e 100644 --- a/drivers/floppy/floppy.h +++ b/drivers/floppy/floppy.h @@ -4,3 +4,4 @@ _PROTOTYPE(void main, (void)); + diff --git a/drivers/floppy/liveupdate.c b/drivers/floppy/liveupdate.c new file mode 100644 index 000000000..0d4d1421a --- /dev/null +++ b/drivers/floppy/liveupdate.c @@ -0,0 +1,81 @@ +#include "floppy.h" + +/* State management variables. */ +EXTERN u16_t f_busy; +EXTERN int motor_status; +EXTERN unsigned f_drive; +EXTERN int last_transfer_opcode; +#define BSY_IO 1 /* busy doing I/O */ + +/* State management helpers. */ +#define IS_REQUEST_PENDING(b) ((b) == BSY_IO) +#define IS_READ_PENDING(b, c) \ + (IS_REQUEST_PENDING((b)) && (c) == DEV_GATHER_S) +#define IS_WRITE_PENDING(b, c) \ + (IS_REQUEST_PENDING((b)) && (c) == DEV_SCATTER_S) +#define IS_MOTOR_RUNNING(s, d) ((s) & (1 << (d))) + +/* Custom states definition. */ +#define FL_STATE_MOTOR_OFF (SEF_LU_STATE_CUSTOM_BASE + 0) +#define FL_STATE_IS_CUSTOM(s) ((s) == FL_STATE_MOTOR_OFF) + +/*===========================================================================* + * sef_cb_lu_prepare * + *===========================================================================*/ +PUBLIC void sef_cb_lu_prepare(int state) +{ + int is_ready; + + /* Check if we are ready for the target state. */ + is_ready = FALSE; + switch(state) { + /* Standard states. */ + case SEF_LU_STATE_REQUEST_FREE: + case SEF_LU_STATE_PROTOCOL_FREE: + is_ready = (!IS_REQUEST_PENDING(f_busy)); + break; + + /* Custom states. */ + case FL_STATE_MOTOR_OFF: + is_ready = (!IS_REQUEST_PENDING(f_busy) + && !IS_MOTOR_RUNNING(motor_status, f_drive)); + break; + } + + /* Tell SEF if we are ready. */ + if(is_ready) { + sef_lu_ready(OK); + } +} + +/*===========================================================================* + * sef_cb_lu_state_isvalid * + *===========================================================================*/ +PUBLIC int sef_cb_lu_state_isvalid(int state) +{ + return SEF_LU_STATE_IS_STANDARD(state) || FL_STATE_IS_CUSTOM(state); +} + +/*===========================================================================* + * sef_cb_lu_state_dump * + *===========================================================================*/ +PUBLIC void sef_cb_lu_state_dump(int state) +{ + sef_lu_dprint("floppy: live update state = %d\n", state); + sef_lu_dprint("floppy: f_busy = %d\n", f_busy); + sef_lu_dprint("floppy: motor_status = 0x%02X\n", motor_status); + sef_lu_dprint("floppy: f_drive = %d\n", f_drive); + sef_lu_dprint("floppy: last_transfer_opcode = 0x%02X\n", + last_transfer_opcode); + + sef_lu_dprint("floppy: SEF_LU_STATE_WORK_FREE(%d) reached = %d\n", + SEF_LU_STATE_WORK_FREE, TRUE); + sef_lu_dprint("floppy: SEF_LU_STATE_REQUEST_FREE(%d) reached = %d\n", + SEF_LU_STATE_REQUEST_FREE, (!IS_REQUEST_PENDING(f_busy))); + sef_lu_dprint("floppy: SEF_LU_STATE_PROTOCOL_FREE(%d) reached = %d\n", + SEF_LU_STATE_PROTOCOL_FREE, (!IS_REQUEST_PENDING(f_busy))); + sef_lu_dprint("floppy: FL_STATE_MOTOR_OFF(%d) reached = %d\n", + FL_STATE_MOTOR_OFF, (!IS_REQUEST_PENDING(f_busy) + && !IS_MOTOR_RUNNING(motor_status, f_drive))); +} + diff --git a/drivers/fxp/fxp.c b/drivers/fxp/fxp.c index 78ff9fbbc..576f2f27b 100644 --- a/drivers/fxp/fxp.c +++ b/drivers/fxp/fxp.c @@ -301,6 +301,9 @@ PRIVATE void handle_hw_intr(void) } } +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -312,6 +315,9 @@ int main(int argc, char *argv[]) long v; vir_bytes ft = sizeof(*fxp_table)*FXP_PORT_NR; + /* SEF local startup. */ + sef_local_startup(); + system_hz = sys_hz(); if (argc < 1) @@ -342,14 +348,11 @@ int main(int argc, char *argv[]) while (TRUE) { - if ((r= receive(ANY, &m)) != OK) - panic("FXP","receive failed", r); + if ((r= sef_receive(ANY, &m)) != OK) + panic("FXP","sef_receive failed", r); if (is_notify(m.m_type)) { switch (_ENDPOINT_P(m.m_source)) { - case RS_PROC_NR: - notify(m.m_source); - break; case HARDWARE: handle_hw_intr(); break; @@ -393,6 +396,17 @@ int main(int argc, char *argv[]) } } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * fxp_init * *===========================================================================*/ diff --git a/drivers/lance/lance.c b/drivers/lance/lance.c index 38c22f46c..5975f9a3d 100644 --- a/drivers/lance/lance.c +++ b/drivers/lance/lance.c @@ -264,7 +264,10 @@ static char isstored[TX_RING_SIZE]; /* Tx-slot in-use */ static char *progname; phys_bytes lance_buf_phys; - + +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -279,6 +282,9 @@ void main( int argc, char **argv ) int fkeys, sfkeys; #endif + /* SEF local startup. */ + sef_local_startup(); + (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]); env_setargs( argc, argv ); @@ -310,9 +316,9 @@ void main( int argc, char **argv ) sys_irqenable(&ec->ec_hook); } - if ((r= receive(ANY, &m)) != OK) - panic( "lance", "receive failed", r); - + if ((r= sef_receive(ANY, &m)) != OK) + panic( "lance", "sef_receive failed", r); + for (i=0;idr_name)(),"receive() failed", s); + if ((s=sef_receive(ANY, &mess)) != OK) + panic((*dp->dr_name)(),"sef_receive() failed", s); } device_caller = mess.m_source; @@ -172,9 +172,6 @@ int type; /* Driver type (DRIVER_STD or DRIVER_ASYN) */ case CLOCK: (*dp->dr_alarm)(dp, &mess); break; - case RS_PROC_NR: - notify(mess.m_source); - break; default: if(dp->dr_other) r = (*dp->dr_other)(dp, &mess); diff --git a/drivers/log/Makefile b/drivers/log/Makefile index e7ebfb6c2..eecdc5e69 100644 --- a/drivers/log/Makefile +++ b/drivers/log/Makefile @@ -16,7 +16,7 @@ LDFLAGS = -i -L../libdriver LIBS = -ldriver -lsys LIB_DEP = ../libdriver/libdriver.a -OBJ = log.o diag.o +OBJ = log.o diag.o liveupdate.o # build local binary all build: $(DRIVER) diff --git a/drivers/log/liveupdate.c b/drivers/log/liveupdate.c new file mode 100644 index 000000000..793b415d7 --- /dev/null +++ b/drivers/log/liveupdate.c @@ -0,0 +1,101 @@ +#include "log.h" + +/* State management variables. */ +#define NR_DEVS 1 /* number of minor devices */ +EXTERN struct logdevice logdevices[NR_DEVS]; + +/* State management helpers. */ +PRIVATE int is_read_pending; +PRIVATE int is_select_callback_pending; +PRIVATE void load_state_info(void) +{ + int i, found_pending; + struct logdevice *log; + + /* Check if reads or select callbacks are pending. */ + is_read_pending = FALSE; + is_select_callback_pending = FALSE; + found_pending = FALSE; + for (i = 0; i < NR_DEVS && !found_pending; i++) { + log = &logdevices[i]; + if(log->log_proc_nr) { + is_read_pending = TRUE; + } + if(log->log_selected) { + is_select_callback_pending = TRUE; + } + + found_pending = (is_read_pending && is_select_callback_pending); + } +} + +/* Custom states definition. */ +#define LOG_STATE_SELECT_PROTOCOL_FREE (SEF_LU_STATE_CUSTOM_BASE + 0) +#define LOG_STATE_IS_CUSTOM(s) ((s) == LOG_STATE_SELECT_PROTOCOL_FREE) + +/*===========================================================================* + * sef_cb_lu_prepare * + *===========================================================================*/ +PUBLIC void sef_cb_lu_prepare(int state) +{ + int is_ready; + + /* Load state information. */ + load_state_info(); + + /* Check if we are ready for the target state. */ + is_ready = FALSE; + switch(state) { + /* Standard states. */ + case SEF_LU_STATE_REQUEST_FREE: + is_ready = (!is_read_pending); + break; + + case SEF_LU_STATE_PROTOCOL_FREE: + is_ready = (!is_read_pending && !is_select_callback_pending); + break; + + /* Custom states. */ + case LOG_STATE_SELECT_PROTOCOL_FREE: + is_ready = (!is_select_callback_pending); + break; + } + + /* Tell SEF if we are ready. */ + if(is_ready) { + sef_lu_ready(OK); + } +} + +/*===========================================================================* + * sef_cb_lu_state_isvalid * + *===========================================================================*/ +PUBLIC int sef_cb_lu_state_isvalid(int state) +{ + return SEF_LU_STATE_IS_STANDARD(state) || LOG_STATE_IS_CUSTOM(state); +} + +/*===========================================================================* + * sef_cb_lu_state_dump * + *===========================================================================*/ +PUBLIC void sef_cb_lu_state_dump(int state) +{ + /* Load state information. */ + load_state_info(); + + sef_lu_dprint("log: live update state = %d\n", state); + sef_lu_dprint("log: is_read_pending = %d\n", is_read_pending); + sef_lu_dprint("log: is_select_callback_pending = %d\n", + is_select_callback_pending); + + sef_lu_dprint("log: SEF_LU_STATE_WORK_FREE(%d) reached = %d\n", + SEF_LU_STATE_WORK_FREE, TRUE); + sef_lu_dprint("log: SEF_LU_STATE_REQUEST_FREE(%d) reached = %d\n", + SEF_LU_STATE_REQUEST_FREE, (!is_read_pending)); + sef_lu_dprint("log: SEF_LU_STATE_PROTOCOL_FREE(%d) reached = %d\n", + SEF_LU_STATE_PROTOCOL_FREE, (!is_read_pending + && !is_select_callback_pending)); + sef_lu_dprint("log: LOG_STATE_SELECT_PROTOCOL_FREE(%d) reached = %d\n", + LOG_STATE_SELECT_PROTOCOL_FREE, (!is_select_callback_pending)); +} + diff --git a/drivers/log/log.c b/drivers/log/log.c index 5edf5d4aa..7009526d5 100644 --- a/drivers/log/log.c +++ b/drivers/log/log.c @@ -54,12 +54,23 @@ PRIVATE struct driver log_dtab = { extern int device_caller; +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); +EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) ); +EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) ); +EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) ); + /*===========================================================================* * main * *===========================================================================*/ PUBLIC int main(void) { int i; + + /* SEF local startup. */ + sef_local_startup(); + + /* Initialize log devices. */ for(i = 0; i < NR_DEVS; i++) { log_geom[i].dv_size = cvul64(LOG_SIZE); log_geom[i].dv_base = cvul64((long)logdevices[i].log_buffer); @@ -76,7 +87,21 @@ PUBLIC int main(void) } /*===========================================================================* - * log_name * + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid); + sef_setcb_lu_state_dump(sef_cb_lu_state_dump); + + /* Let SEF perform startup. */ + sef_startup(); +} + +/*===========================================================================* + * log_name * *===========================================================================*/ PRIVATE char *log_name() { @@ -462,3 +487,4 @@ message *m_ptr; return(ready_ops); } + diff --git a/drivers/memory/memory.c b/drivers/memory/memory.c index 24896659b..0c33ed831 100644 --- a/drivers/memory/memory.c +++ b/drivers/memory/memory.c @@ -83,6 +83,9 @@ PRIVATE char dev_zero[ZERO_BUF_SIZE]; #define click_to_round_k(n) \ ((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024)) +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -91,6 +94,9 @@ PUBLIC int main(void) /* Main program. Initialize the memory driver and start the main loop. */ struct sigaction sa; + /* SEF local startup. */ + sef_local_startup(); + sa.sa_handler = SIG_MESS; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; @@ -101,6 +107,19 @@ PUBLIC int main(void) return(OK); } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard); + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * m_name * *===========================================================================*/ @@ -469,3 +488,4 @@ struct partition *entry; entry->heads = 64; entry->sectors = 32; } + diff --git a/drivers/memory/ramdisk/proto b/drivers/memory/ramdisk/proto index bd21e6d88..9547833cd 100644 --- a/drivers/memory/ramdisk/proto +++ b/drivers/memory/ramdisk/proto @@ -1,5 +1,5 @@ boot -175 400 +200 400 d--755 0 0 bin d--755 0 0 at_wini ---755 0 0 at_wini diff --git a/drivers/orinoco/orinoco.c b/drivers/orinoco/orinoco.c index 8d8268a11..4b3105ce5 100644 --- a/drivers/orinoco/orinoco.c +++ b/drivers/orinoco/orinoco.c @@ -236,6 +236,9 @@ u32_t system_hz; static char *progname; extern int errno; +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /***************************************************************************** * main * * * @@ -248,6 +251,9 @@ int main(int argc, char *argv[]) { long v = 0; t_or *orp; + /* SEF local startup. */ + sef_local_startup(); + system_hz = sys_hz(); (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]); @@ -269,14 +275,11 @@ int main(int argc, char *argv[]) { printf("orinoco: ds_retrieve_u32 failed for 'inet': %d\n", r); while (TRUE) { - if ((r = receive (ANY, &m)) != OK) - panic(__FILE__, "orinoco: receive failed", NO_NUM); + if ((r = sef_receive (ANY, &m)) != OK) + panic(__FILE__, "orinoco: sef_receive failed", NO_NUM); if (is_notify(m.m_type)) { switch (_ENDPOINT_P(m.m_source)) { - case RS_PROC_NR: - notify(m.m_source); - break; case CLOCK: or_watchdog_f(NULL); break; @@ -346,6 +349,17 @@ int main(int argc, char *argv[]) { } } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + /***************************************************************************** * check_int_events * * * diff --git a/drivers/pci/main.c b/drivers/pci/main.c index 1cf529f48..fecbef644 100644 --- a/drivers/pci/main.c +++ b/drivers/pci/main.c @@ -41,19 +41,25 @@ FORWARD _PROTOTYPE( struct rs_pci *find_acl, (int endpoint) ); extern int debug; +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + int main(void) { int i, r; message m; + /* SEF local startup. */ + sef_local_startup(); + pci_init(); for(;;) { - r= receive(ANY, &m); + r= sef_receive(ANY, &m); if (r < 0) { - printf("PCI: receive from ANY failed: %d\n", r); + printf("PCI: sef_receive from ANY failed: %d\n", r); break; } @@ -101,6 +107,19 @@ int main(void) return 0; } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard); + + /* Let SEF perform startup. */ + sef_startup(); +} + PRIVATE void do_init(mp) message *mp; { diff --git a/drivers/printer/Makefile b/drivers/printer/Makefile index 7e3228fb4..b3a9d8c7f 100644 --- a/drivers/printer/Makefile +++ b/drivers/printer/Makefile @@ -13,9 +13,9 @@ d = .. CC = exec cc CFLAGS = -I$i $(CPROFILE) LDFLAGS = -i -LIBS = -lsys -lsys +LIBS = -lsys -OBJ = printer.o +OBJ = printer.o liveupdate.o # build local binary all build: $(DRIVER) diff --git a/drivers/printer/liveupdate.c b/drivers/printer/liveupdate.c new file mode 100644 index 000000000..b65d61b01 --- /dev/null +++ b/drivers/printer/liveupdate.c @@ -0,0 +1,69 @@ +#include "../drivers.h" + +/* State management variables. */ +EXTERN int writing; +EXTERN int is_status_msg_expected; + +/* Custom states definition. */ +#define PR_STATE_WRITE_PROTOCOL_FREE (SEF_LU_STATE_CUSTOM_BASE + 0) +#define PR_STATE_IS_CUSTOM(s) ((s) == PR_STATE_WRITE_PROTOCOL_FREE) + +/*===========================================================================* + * sef_cb_lu_prepare * + *===========================================================================*/ +PUBLIC void sef_cb_lu_prepare(int state) +{ + int is_ready; + + /* Check if we are ready for the target state. */ + is_ready = FALSE; + switch(state) { + /* Standard states. */ + case SEF_LU_STATE_REQUEST_FREE: + is_ready = TRUE; + break; + + case SEF_LU_STATE_PROTOCOL_FREE: + is_ready = (!writing && !is_status_msg_expected); + break; + + /* Custom states. */ + case PR_STATE_WRITE_PROTOCOL_FREE: + is_ready = (!writing); + break; + } + + /* Tell SEF if we are ready. */ + if(is_ready) { + sef_lu_ready(OK); + } +} + +/*===========================================================================* + * sef_cb_lu_state_isvalid * + *===========================================================================*/ +PUBLIC int sef_cb_lu_state_isvalid(int state) +{ + return SEF_LU_STATE_IS_STANDARD(state) || PR_STATE_IS_CUSTOM(state); +} + +/*===========================================================================* + * sef_cb_lu_state_dump * + *===========================================================================*/ +PUBLIC void sef_cb_lu_state_dump(int state) +{ + sef_lu_dprint("printer: live update state = %d\n", state); + sef_lu_dprint("printer: writing = %d\n", writing); + sef_lu_dprint("printer: is_status_msg_expected = %d\n", + is_status_msg_expected); + + sef_lu_dprint("printer: SEF_LU_STATE_WORK_FREE(%d) reached = %d\n", + SEF_LU_STATE_WORK_FREE, TRUE); + sef_lu_dprint("printer: SEF_LU_STATE_REQUEST_FREE(%d) reached = %d\n", + SEF_LU_STATE_REQUEST_FREE, TRUE); + sef_lu_dprint("printer: SEF_LU_STATE_PROTOCOL_FREE(%d) reached = %d\n", + SEF_LU_STATE_PROTOCOL_FREE, (!writing && !is_status_msg_expected)); + sef_lu_dprint("printer: PR_STATE_WRITE_PROTOCOL_FREE(%d) reached = %d\n", + PR_STATE_WRITE_PROTOCOL_FREE, (!writing)); +} + diff --git a/drivers/printer/printer.c b/drivers/printer/printer.c index 00ec2e469..e61153d5f 100644 --- a/drivers/printer/printer.c +++ b/drivers/printer/printer.c @@ -100,7 +100,7 @@ PRIVATE int user_left; /* bytes of output left in user buf */ PRIVATE vir_bytes user_vir_g; /* start of user buf (address or grant) */ PRIVATE vir_bytes user_vir_d; /* offset in user buf */ PRIVATE int user_safe; /* address or grant? */ -PRIVATE int writing; /* nonzero while write is in progress */ +PUBLIC int writing; /* nonzero while write is in progress */ PRIVATE int irq_hook_id; /* id of irq hook at kernel */ extern int errno; /* error number */ @@ -115,6 +115,12 @@ FORWARD _PROTOTYPE( void reply, (int code,int replyee,int proc,int status)); FORWARD _PROTOTYPE( void do_printer_output, (void) ); FORWARD _PROTOTYPE( void do_signal, (void) ); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); +EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) ); +EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) ); +EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) ); +PUBLIC int is_status_msg_expected = FALSE; /*===========================================================================* * printer_task * @@ -126,6 +132,9 @@ PUBLIC void main(void) struct sigaction sa; int s; + /* SEF local startup. */ + sef_local_startup(); + /* Install signal handlers. Ask PM to transform signal into message. */ sa.sa_handler = SIG_MESS; sigemptyset(&sa.sa_mask); @@ -133,16 +142,13 @@ PUBLIC void main(void) if (sigaction(SIGTERM,&sa,NULL)<0) panic("PRN","sigaction failed", errno); while (TRUE) { - receive(ANY, &pr_mess); + sef_receive(ANY, &pr_mess); if (is_notify(pr_mess.m_type)) { switch (_ENDPOINT_P(pr_mess.m_source)) { case HARDWARE: do_printer_output(); break; - case RS_PROC_NR: - notify(pr_mess.m_source); - break; case PM_PROC_NR: do_signal(); break; @@ -169,6 +175,19 @@ PUBLIC void main(void) } } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid); + sef_setcb_lu_state_dump(sef_cb_lu_state_dump); + + /* Let SEF perform startup. */ + sef_startup(); +} /*===========================================================================* * do_signal * @@ -275,6 +294,7 @@ PRIVATE void output_done() else { /* done! report back to FS */ status = orig_count; } + is_status_msg_expected = TRUE; revive_pending = TRUE; revive_status = status; notify(caller); @@ -296,6 +316,8 @@ register message *m_ptr; /* pointer to the newly arrived message */ revive_pending = FALSE; /* unmark event */ } else { m_ptr->m_type = DEV_NO_STATUS; + + is_status_msg_expected = FALSE; } send(m_ptr->m_source, m_ptr); /* send the message */ } diff --git a/drivers/random/main.c b/drivers/random/main.c index 13a4830fd..97024a806 100644 --- a/drivers/random/main.c +++ b/drivers/random/main.c @@ -54,16 +54,35 @@ PRIVATE struct driver r_dtab = { #define RANDOM_BUF_SIZE 1024 PRIVATE char random_buf[RANDOM_BUF_SIZE]; +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ PUBLIC int main(void) { + /* SEF local startup. */ + sef_local_startup(); + r_init(); /* initialize the memory driver */ driver_task(&r_dtab, DRIVER_ASYN); /* start driver's main loop */ return(OK); } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard); + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * r_name * *===========================================================================*/ diff --git a/drivers/readclock/readclock.c b/drivers/readclock/readclock.c index b2cb6b2da..f52fb4938 100644 --- a/drivers/readclock/readclock.c +++ b/drivers/readclock/readclock.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -87,6 +88,9 @@ int bcd_to_dec(int n); int dec_to_bcd(int n); void usage(void); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + int main(int argc, char **argv) { struct tm time1; @@ -98,6 +102,9 @@ int main(int argc, char **argv) unsigned char mach_id, cmos_state; struct sysgetenv sysgetenv; + /* SEF local startup. */ + sef_local_startup(); + if((s=sys_readbios(MACH_ID_ADDR, &mach_id, sizeof(mach_id))) != OK) { printf("readclock: sys_readbios failed: %d.\n", s); exit(1); @@ -212,6 +219,15 @@ int main(int argc, char **argv) exit(0); } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Let SEF perform startup. */ + sef_startup(); +} + void errmsg(char *s) { static char *prompt = "readclock: "; diff --git a/drivers/rtl8139/Makefile b/drivers/rtl8139/Makefile index 0e6d2bb11..36c1faeee 100644 --- a/drivers/rtl8139/Makefile +++ b/drivers/rtl8139/Makefile @@ -16,7 +16,7 @@ CFLAGS = -I$i $(CPROFILE) LDFLAGS = -i LIBS = -lsys -ltimers -OBJ = rtl8139.o +OBJ = rtl8139.o liveupdate.o # build local binary all build: $(DRIVER) diff --git a/drivers/rtl8139/liveupdate.c b/drivers/rtl8139/liveupdate.c new file mode 100644 index 000000000..19e064132 --- /dev/null +++ b/drivers/rtl8139/liveupdate.c @@ -0,0 +1,108 @@ +#include "rtl8139.h" + +/* State management variables. */ +EXTERN re_t re_table[RE_PORT_NR]; + +/* Custom states definition. */ +#define RL_STATE_READ_PROTOCOL_FREE (SEF_LU_STATE_CUSTOM_BASE + 0) +#define RL_STATE_WRITE_PROTOCOL_FREE (SEF_LU_STATE_CUSTOM_BASE + 1) +#define RL_STATE_IS_CUSTOM(s) \ + ((s) >= RL_STATE_READ_PROTOCOL_FREE && (s) <= RL_STATE_WRITE_PROTOCOL_FREE) + +/* State management helpers. */ +PRIVATE int is_reading; +PRIVATE int is_writing; +PRIVATE void load_state_info(void) +{ + int i, found_processing; + re_t *rep; + + /* Check if we are reading or writing. */ + is_reading = FALSE; + is_writing = FALSE; + found_processing = FALSE; + for (i= 0; ire_flags & REF_READING) { + is_reading = TRUE; + } + + if (rep->re_flags & REF_SEND_AVAIL) { + is_writing = TRUE; + } + + found_processing = (is_reading && is_writing); + } +} + +/*===========================================================================* + * sef_cb_lu_prepare * + *===========================================================================*/ +PUBLIC void sef_cb_lu_prepare(int state) +{ + int is_ready; + + /* Load state information. */ + load_state_info(); + + /* Check if we are ready for the target state. */ + is_ready = FALSE; + switch(state) { + /* Standard states. */ + case SEF_LU_STATE_REQUEST_FREE: + is_ready = TRUE; + break; + + case SEF_LU_STATE_PROTOCOL_FREE: + is_ready = (!is_reading && !is_writing); + break; + + /* Custom states. */ + case RL_STATE_READ_PROTOCOL_FREE: + is_ready = (!is_reading); + break; + + case RL_STATE_WRITE_PROTOCOL_FREE: + is_ready = (!is_writing); + break; + } + + /* Tell SEF if we are ready. */ + if(is_ready) { + sef_lu_ready(OK); + } +} + +/*===========================================================================* + * sef_cb_lu_state_isvalid * + *===========================================================================*/ +PUBLIC int sef_cb_lu_state_isvalid(int state) +{ + return SEF_LU_STATE_IS_STANDARD(state) || RL_STATE_IS_CUSTOM(state); +} + +/*===========================================================================* + * sef_cb_lu_state_dump * + *===========================================================================*/ +PUBLIC void sef_cb_lu_state_dump(int state) +{ + /* Load state information. */ + load_state_info(); + + sef_lu_dprint("rtl8139: live update state = %d\n", state); + sef_lu_dprint("rtl8139: is_reading = %d\n", is_reading); + sef_lu_dprint("rtl8139: is_writing = %d\n", is_writing); + + sef_lu_dprint("rtl8139: SEF_LU_STATE_WORK_FREE(%d) reached = %d\n", + SEF_LU_STATE_WORK_FREE, TRUE); + sef_lu_dprint("rtl8139: SEF_LU_STATE_REQUEST_FREE(%d) reached = %d\n", + SEF_LU_STATE_REQUEST_FREE, TRUE); + sef_lu_dprint("rtl8139: SEF_LU_STATE_PROTOCOL_FREE(%d) reached = %d\n", + SEF_LU_STATE_PROTOCOL_FREE, (!is_reading && !is_writing)); + sef_lu_dprint("rtl8139: RL_STATE_READ_PROTOCOL_FREE(%d) reached = %d\n", + RL_STATE_READ_PROTOCOL_FREE, (!is_reading)); + sef_lu_dprint("rtl8139: RL_STATE_WRITE_PROTOCOL_FREE(%d) reached = %d\n", + RL_STATE_WRITE_PROTOCOL_FREE, (!is_writing)); +} + diff --git a/drivers/rtl8139/rtl8139.c b/drivers/rtl8139/rtl8139.c index e736972ea..d4b91d771 100644 --- a/drivers/rtl8139/rtl8139.c +++ b/drivers/rtl8139/rtl8139.c @@ -55,57 +55,8 @@ * */ -#include "../drivers.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include "../../kernel/const.h" -#include "../../kernel/config.h" -#include "../../kernel/type.h" - -#define tmra_ut timer_t -#define tmra_inittimer(tp) tmr_inittimer(tp) -#define Proc_number(p) proc_number(p) -#define debug 0 -#define printW() ((void)0) -#define vm_1phys2bus(p) (p) - -#define VERBOSE 1 /* display message during init */ - #include "rtl8139.h" -#define RX_BUFSIZE RL_RCR_RBLEN_64K_SIZE -#define RX_BUFBITS RL_RCR_RBLEN_64K -#define N_TX_BUF RL_N_TX - -#define RE_PORT_NR 1 /* Minix */ - -/* I/O vectors are handled IOVEC_NR entries at a time. */ -#define IOVEC_NR 16 - -/* Configuration */ -#define RL_ENVVAR "RTLETH" - PRIVATE struct pcitab { u16_t vid; @@ -136,70 +87,7 @@ PRIVATE struct pcitab { 0x0000, 0x0000, 0 } }; -typedef struct re -{ - port_t re_base_port; - int re_irq; - int re_mode; - int re_flags; - int re_client; - int re_link_up; - int re_got_int; - int re_send_int; - int re_report_link; - int re_clear_rx; - int re_need_reset; - int re_tx_alive; - char *re_model; - - /* Rx */ - phys_bytes re_rx_buf; - char *v_re_rx_buf; - vir_bytes re_read_s; - - /* Tx */ - int re_tx_head; - int re_tx_tail; - struct - { - int ret_busy; - phys_bytes ret_buf; - char * v_ret_buf; - } re_tx[N_TX_BUF]; - u32_t re_ertxth; /* Early Tx Threshold */ - - /* PCI related */ - int re_seen; /* TRUE iff device available */ - u8_t re_pcibus; - u8_t re_pcidev; - u8_t re_pcifunc; - - /* 'large' items */ - int re_hook_id; /* IRQ hook id at kernel */ - eth_stat_t re_stat; - ether_addr_t re_address; - message re_rx_mess; - message re_tx_mess; - char re_name[sizeof("rtl8139#n")]; - iovec_t re_iovec[IOVEC_NR]; - iovec_s_t re_iovec_s[IOVEC_NR]; -} -re_t; - -#define REM_DISABLED 0x0 -#define REM_ENABLED 0x1 - -#define REF_PACK_SENT 0x001 -#define REF_PACK_RECV 0x002 -#define REF_SEND_AVAIL 0x004 -#define REF_READING 0x010 -#define REF_EMPTY 0x000 -#define REF_PROMISC 0x040 -#define REF_MULTI 0x080 -#define REF_BROAD 0x100 -#define REF_ENABLED 0x200 - -static re_t re_table[RE_PORT_NR]; +PUBLIC re_t re_table[RE_PORT_NR]; static u16_t eth_ign_proto; static tmra_ut rl_watchdog; @@ -303,6 +191,12 @@ static char *progname; extern int errno; u32_t system_hz; +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); +EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) ); +EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) ); +EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -314,6 +208,9 @@ int main(int argc, char *argv[]) re_t *rep; long v; + /* SEF local startup. */ + sef_local_startup(); + system_hz = sys_hz(); (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]); @@ -345,14 +242,11 @@ int main(int argc, char *argv[]) while (TRUE) { - if ((r= receive(ANY, &m)) != OK) - panic("rtl8139","receive failed", r); + if ((r= sef_receive(ANY, &m)) != OK) + panic("rtl8139","sef_receive failed", r); if (is_notify(m.m_type)) { switch (_ENDPOINT_P(m.m_source)) { - case RS_PROC_NR: - notify(m.m_source); - break; case CLOCK: /* * Under MINIX, synchronous alarms are @@ -418,6 +312,20 @@ int main(int argc, char *argv[]) } } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid); + sef_setcb_lu_state_dump(sef_cb_lu_state_dump); + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * check_int_events * *===========================================================================*/ diff --git a/drivers/rtl8139/rtl8139.h b/drivers/rtl8139/rtl8139.h index 7613ec6e1..218be4b5c 100644 --- a/drivers/rtl8139/rtl8139.h +++ b/drivers/rtl8139/rtl8139.h @@ -4,6 +4,34 @@ ibm/rtl8139.h Created: Aug 2003 by Philip Homburg */ +#include "../drivers.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "../../kernel/const.h" +#include "../../kernel/config.h" +#include "../../kernel/type.h" + #define RL_IDR 0x00 /* Ethernet address * Note: RL_9346CR_EEM_CONFIG mode is * required the change the ethernet @@ -424,6 +452,90 @@ d8 R/W Config5 Configuration register 5 d9-ff reserved #endif +#define tmra_ut timer_t +#define tmra_inittimer(tp) tmr_inittimer(tp) +#define Proc_number(p) proc_number(p) +#define debug 0 +#define printW() ((void)0) +#define vm_1phys2bus(p) (p) + +#define VERBOSE 1 /* display message during init */ + +#define RX_BUFSIZE RL_RCR_RBLEN_64K_SIZE +#define RX_BUFBITS RL_RCR_RBLEN_64K +#define N_TX_BUF RL_N_TX + +#define RE_PORT_NR 1 /* Minix */ + +/* I/O vectors are handled IOVEC_NR entries at a time. */ +#define IOVEC_NR 16 + +/* Configuration */ +#define RL_ENVVAR "RTLETH" + +typedef struct re +{ + port_t re_base_port; + int re_irq; + int re_mode; + int re_flags; + int re_client; + int re_link_up; + int re_got_int; + int re_send_int; + int re_report_link; + int re_clear_rx; + int re_need_reset; + int re_tx_alive; + char *re_model; + + /* Rx */ + phys_bytes re_rx_buf; + char *v_re_rx_buf; + vir_bytes re_read_s; + + /* Tx */ + int re_tx_head; + int re_tx_tail; + struct + { + int ret_busy; + phys_bytes ret_buf; + char * v_ret_buf; + } re_tx[N_TX_BUF]; + u32_t re_ertxth; /* Early Tx Threshold */ + + /* PCI related */ + int re_seen; /* TRUE iff device available */ + u8_t re_pcibus; + u8_t re_pcidev; + u8_t re_pcifunc; + + /* 'large' items */ + int re_hook_id; /* IRQ hook id at kernel */ + eth_stat_t re_stat; + ether_addr_t re_address; + message re_rx_mess; + message re_tx_mess; + char re_name[sizeof("rtl8139#n")]; + iovec_t re_iovec[IOVEC_NR]; + iovec_s_t re_iovec_s[IOVEC_NR]; +} +re_t; + +#define REM_DISABLED 0x0 +#define REM_ENABLED 0x1 + +#define REF_PACK_SENT 0x001 +#define REF_PACK_RECV 0x002 +#define REF_SEND_AVAIL 0x004 +#define REF_READING 0x010 +#define REF_EMPTY 0x000 +#define REF_PROMISC 0x040 +#define REF_MULTI 0x080 +#define REF_BROAD 0x100 +#define REF_ENABLED 0x200 + /* * $PchId: rtl8139.h,v 1.1 2003/09/05 10:58:50 philip Exp $ */ diff --git a/drivers/rtl8169/rtl8169.c b/drivers/rtl8169/rtl8169.c index e3de8e398..e5b46b3a3 100644 --- a/drivers/rtl8169/rtl8169.c +++ b/drivers/rtl8169/rtl8169.c @@ -284,6 +284,9 @@ PRIVATE int int_event_check; /* set to TRUE if events arrived */ static char *progname; u32_t system_hz; +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -294,6 +297,9 @@ int main(int argc, char *argv[]) re_t *rep; long v; + /* SEF local startup. */ + sef_local_startup(); + system_hz = sys_hz(); (progname = strrchr(argv[0], '/')) ? progname++ : (progname = argv[0]); @@ -321,14 +327,11 @@ int main(int argc, char *argv[]) printf("rtl8169: ds_retrieve_u32 failed for 'inet': %d\n", r); #endif while (TRUE) { - if ((r = receive(ANY, &m)) != OK) - panic("rtl8169", "receive failed", r); + if ((r = sef_receive(ANY, &m)) != OK) + panic("rtl8169", "sef_receive failed", r); if (is_notify(m.m_type)) { switch (_ENDPOINT_P(m.m_source)) { - case RS_PROC_NR: - notify(m.m_source); - break; case CLOCK: /* * Under MINIX, synchronous alarms are used @@ -383,6 +386,17 @@ int main(int argc, char *argv[]) } } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + static void mdio_write(U16_t port, int regaddr, int value) { int i; @@ -1254,8 +1268,8 @@ void transmittest(re_t *rep) do { message m; int r; - if ((r = receive(ANY, &m)) != OK) - panic("rtl8169", "receive failed", r); + if ((r = sef_receive(ANY, &m)) != OK) + panic("rtl8169", "sef_receive failed", r); } while(m.m_source != HARDWARE); assert(!(rep->re_flags & REF_SEND_AVAIL)); rep->re_flags |= REF_SEND_AVAIL; diff --git a/drivers/sb16/Makefile b/drivers/sb16/Makefile index 3f159633a..73c76a07a 100644 --- a/drivers/sb16/Makefile +++ b/drivers/sb16/Makefile @@ -17,8 +17,8 @@ LIBS = -lsys # build local binary all build: sb16_dsp sb16_mixer -sb16_dsp: sb16.o sb16_dsp.o - $(CC) -o $@ $(LDFLAGS) sb16.o sb16_dsp.o $(LIBS) +sb16_dsp: sb16.o sb16_dsp.o sb16_dsp_liveupdate.o + $(CC) -o $@ $(LDFLAGS) sb16.o sb16_dsp.o sb16_dsp_liveupdate.o $(LIBS) sb16_mixer: sb16.o sb16_mixer.o $(CC) -o $@ $(LDFLAGS) sb16.o sb16_mixer.o $(LIBS) diff --git a/drivers/sb16/sb16.h b/drivers/sb16/sb16.h index 3396743c1..0f0f80a47 100644 --- a/drivers/sb16/sb16.h +++ b/drivers/sb16/sb16.h @@ -5,7 +5,6 @@ #include #include - #define SB_TIMEOUT 32000 /* timeout count */ /* IRQ, base address and DMA channels */ diff --git a/drivers/sb16/sb16_dsp.c b/drivers/sb16/sb16_dsp.c index 893248170..954e05689 100644 --- a/drivers/sb16/sb16_dsp.c +++ b/drivers/sb16/sb16_dsp.c @@ -77,6 +77,13 @@ PRIVATE int reviveProcNr; #define dprint (void) +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); +EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) ); +EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) ); +EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) ); +PUBLIC int is_processing = FALSE; +PUBLIC int is_status_msg_expected = FALSE; /*===========================================================================* * main @@ -86,6 +93,9 @@ PUBLIC void main() int r, caller, proc_nr, s; message mess; + /* SEF local startup. */ + sef_local_startup(); + dprint("sb16_dsp.c: main()\n"); /* Get a DMA buffer. */ @@ -93,7 +103,7 @@ PUBLIC void main() while(TRUE) { /* Wait for an incoming message */ - receive(ANY, &mess); + sef_receive(ANY, &mess); caller = mess.m_source; proc_nr = mess.IO_ENDPT; @@ -137,6 +147,19 @@ send_reply: } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid); + sef_setcb_lu_state_dump(sef_cb_lu_state_dump); + + /* Let SEF perform startup. */ + sef_startup(); +} /*===========================================================================* * dsp_open @@ -242,6 +265,7 @@ message *m_ptr; } reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, SUSPEND); + is_processing = TRUE; if(DmaBusy < 0) { /* Dma tranfer not yet started */ @@ -269,7 +293,7 @@ message *m_ptr; } else { /* Dma buffer is full, filling second buffer */ while(BufReadNext == BufFillNext) { /* Second buffer also full, wait for space to become available */ - receive(HARDWARE, &mess); + sef_receive(HARDWARE, &mess); dsp_hardware_msg(); } sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)Buffer + BufFillNext * DspFragmentSize, (phys_bytes)DspFragmentSize); @@ -278,6 +302,7 @@ message *m_ptr; } + is_status_msg_expected = TRUE; revivePending = 1; reviveStatus = DspFragmentSize; reviveProcNr = m_ptr->IO_ENDPT; @@ -338,8 +363,11 @@ message *m_ptr; /* pointer to the newly arrived message */ m_ptr->REP_STATUS = reviveStatus; revivePending = 0; /* unmark event */ + is_processing = FALSE; } else { m_ptr->m_type = DEV_NO_STATUS; + + is_status_msg_expected = FALSE; } send(m_ptr->m_source, m_ptr); /* send the message */ diff --git a/drivers/sb16/sb16_dsp_liveupdate.c b/drivers/sb16/sb16_dsp_liveupdate.c new file mode 100644 index 000000000..83f915c56 --- /dev/null +++ b/drivers/sb16/sb16_dsp_liveupdate.c @@ -0,0 +1,70 @@ +#include "sb16.h" + +/* State management variables. */ +EXTERN int is_processing; +EXTERN int is_status_msg_expected; + +/* Custom states definition. */ +#define SB16_STATE_PROCESSING_PROTOCOL_FREE (SEF_LU_STATE_CUSTOM_BASE + 0) +#define SB16_STATE_IS_CUSTOM(s) \ + ((s) == SB16_STATE_PROCESSING_PROTOCOL_FREE) + +/*===========================================================================* + * sef_cb_lu_prepare * + *===========================================================================*/ +PUBLIC void sef_cb_lu_prepare(int state) +{ + int is_ready; + + /* Check if we are ready for the target state. */ + is_ready = FALSE; + switch(state) { + /* Standard states. */ + case SEF_LU_STATE_REQUEST_FREE: + is_ready = TRUE; + break; + + case SEF_LU_STATE_PROTOCOL_FREE: + is_ready = (!is_processing && !is_status_msg_expected); + break; + + /* Custom states. */ + case SB16_STATE_PROCESSING_PROTOCOL_FREE: + is_ready = (!is_processing); + break; + } + + /* Tell SEF if we are ready. */ + if(is_ready) { + sef_lu_ready(OK); + } +} + +/*===========================================================================* + * sef_cb_lu_state_isvalid * + *===========================================================================*/ +PUBLIC int sef_cb_lu_state_isvalid(int state) +{ + return SEF_LU_STATE_IS_STANDARD(state) || SB16_STATE_IS_CUSTOM(state); +} + +/*===========================================================================* + * sef_cb_lu_state_dump * + *===========================================================================*/ +PUBLIC void sef_cb_lu_state_dump(int state) +{ + sef_lu_dprint("sb16: live update state = %d\n", state); + sef_lu_dprint("sb16: is_processing = %d\n", is_processing); + sef_lu_dprint("sb16: is_status_msg_expected = %d\n", + is_status_msg_expected); + + sef_lu_dprint("sb16: SEF_LU_STATE_WORK_FREE(%d) reached = %d\n", + SEF_LU_STATE_WORK_FREE, TRUE); + sef_lu_dprint("sb16: SEF_LU_STATE_REQUEST_FREE(%d) reached = %d\n", + SEF_LU_STATE_REQUEST_FREE, TRUE); + sef_lu_dprint("sb16: SEF_LU_STATE_PROTOCOL_FREE(%d) reached = %d\n", + SEF_LU_STATE_PROTOCOL_FREE, (!is_processing && !is_status_msg_expected)); + sef_lu_dprint("sb16: SB16_STATE_PROCESSING_PROTOCOL_FREE(%d) reached = %d\n", + SB16_STATE_PROCESSING_PROTOCOL_FREE, (!is_processing)); +} + diff --git a/drivers/sb16/sb16_mixer.c b/drivers/sb16/sb16_mixer.c index 6e4a9f141..03b698022 100644 --- a/drivers/sb16/sb16_mixer.c +++ b/drivers/sb16/sb16_mixer.c @@ -40,6 +40,8 @@ PRIVATE int mixer_avail = 0; /* Mixer exists? */ #define dprint (void) +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); /*===========================================================================* * main @@ -48,11 +50,14 @@ PUBLIC void main() { message mess; int err, caller, proc_nr; + /* SEF local startup. */ + sef_local_startup(); + /* Here is the main loop of the mixer task. It waits for a message, carries * it out, and sends a reply. */ while (TRUE) { - receive(ANY, &mess); + sef_receive(ANY, &mess); caller = mess.m_source; proc_nr = mess.IO_ENDPT; @@ -88,6 +93,18 @@ message mess; } } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard); + + /* Let SEF perform startup. */ + sef_startup(); +} /*=========================================================================* * mixer_open diff --git a/drivers/ti1225/ti1225.c b/drivers/ti1225/ti1225.c index eeed9b237..dcb29779d 100644 --- a/drivers/ti1225/ti1225.c +++ b/drivers/ti1225/ti1225.c @@ -59,11 +59,17 @@ FORWARD _PROTOTYPE( u8_t read_exca, (struct port *pp, int socket, int reg) ); FORWARD _PROTOTYPE( void do_outb, (port_t port, u8_t value) ); FORWARD _PROTOTYPE( u8_t do_inb, (port_t port) ); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + int main(int argc, char *argv[]) { int c, r; message m; + /* SEF local startup. */ + sef_local_startup(); + (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]); if((r=micro_delay_calibrate()) != OK) @@ -84,15 +90,28 @@ int main(int argc, char *argv[]) for (;;) { - r= receive(ANY, &m); + r= sef_receive(ANY, &m); if (r != OK) - panic("ti1225", "receive failed", r); + panic("ti1225", "sef_receive failed", r); printf("ti1225: got message %u from %d\n", m.m_type, m.m_source); } return 0; } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard); + + /* Let SEF perform startup. */ + sef_startup(); +} + PRIVATE void init() { int i, r, first, devind, port; diff --git a/drivers/tty/tty.c b/drivers/tty/tty.c index 784c77ca1..8574bc62f 100644 --- a/drivers/tty/tty.c +++ b/drivers/tty/tty.c @@ -146,6 +146,8 @@ extern PUBLIC unsigned info_location; extern PUBLIC phys_bytes vid_size; /* 0x2000 for color or 0x0800 for mono */ extern PUBLIC phys_bytes vid_base; +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); /*===========================================================================* * tty_task * @@ -159,6 +161,9 @@ PUBLIC int main(void) int r, s; register tty_t *tp; + /* SEF local startup. */ + sef_local_startup(); + /* Get kernel environment (protected_mode, pc_at and ega are needed). */ if (OK != (s=sys_getmachine(&machine))) { panic("TTY","Couldn't obtain kernel environment.", s); @@ -179,9 +184,9 @@ PUBLIC int main(void) } /* Get a request message. */ - r= receive(ANY, &tty_mess); + r= sef_receive(ANY, &tty_mess); if (r != 0) - panic("TTY", "receive failed with %d", r); + panic("TTY", "sef_receive failed with %d", r); /* First handle all kernel notification types that the TTY supports. * - An alarm went off, expire all timers and handle the events. @@ -199,9 +204,6 @@ PUBLIC int main(void) /* run watchdogs of expired timers */ expire_timers(); break; - case RS_PROC_NR: - notify(tty_mess.m_source); - break; case HARDWARE: /* hardware interrupt notification */ @@ -330,6 +332,17 @@ PUBLIC int main(void) return 0; } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * do_status * *===========================================================================*/ diff --git a/include/minix/com.h b/include/minix/com.h index 2825d14f9..b7419a970 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -355,9 +355,6 @@ #define NR_SYS_CALLS 47 /* number of system calls */ -/* Pseudo call for use in kernel/table.c. */ -#define SYS_ALL_CALLS (NR_SYS_CALLS) - /* Subfunctions for SYS_PRIVCTL */ #define SYS_PRIV_ALLOW 1 /* Allow process to run */ #define SYS_PRIV_DISALLOW 2 /* Disallow process to run */ @@ -677,9 +674,12 @@ #define RS_REFRESH (RS_RQ_BASE + 2) /* refresh system service */ #define RS_RESTART (RS_RQ_BASE + 3) /* restart system service */ #define RS_SHUTDOWN (RS_RQ_BASE + 4) /* alert about shutdown */ +#define RS_UPDATE (RS_RQ_BASE + 5) /* update system service */ #define RS_LOOKUP (RS_RQ_BASE + 8) /* lookup server name */ +#define RS_LU_PREPARE (RS_RQ_BASE + 21) /* prepare to update message */ + # define RS_CMD_ADDR m1_p1 /* command string */ # define RS_CMD_LEN m1_i1 /* length of command */ # define RS_PERIOD m1_i2 /* heartbeat period */ @@ -690,6 +690,10 @@ # define RS_NAME m1_p1 /* name */ # define RS_NAME_LEN m1_i1 /* namelen */ +# define RS_LU_RESULT m1_i1 /* live update result */ +# define RS_LU_STATE m1_i2 /* state required to update */ +# define RS_LU_PREPARE_MAXTIME m1_i3 /* the max time to prepare */ + /*===========================================================================* * Messages for the Data Store Server * *===========================================================================*/ diff --git a/include/minix/sef.h b/include/minix/sef.h new file mode 100644 index 000000000..26a573475 --- /dev/null +++ b/include/minix/sef.h @@ -0,0 +1,120 @@ +/* Prototypes for System Event Framework (SEF) functions. */ + +#ifndef _SEF_H +#define _SEF_H + +/* SEF entry points for system processes. */ +_PROTOTYPE( void sef_startup, (void) ); +_PROTOTYPE( int sef_receive, (endpoint_t src, message *m_ptr) ); + +/* SEF Debug. */ +#include +#define sef_dprint printf +#define sef_debug_begin() (void)(NULL) +#define sef_debug_end() fflush(stdout) + +/*===========================================================================* + * SEF Ping * + *===========================================================================*/ +/* What to intercept. */ +#define INTERCEPT_SEF_PING_REQUESTS 1 +#define IS_SEF_PING_REQUEST(mp) (is_notify((mp)->m_type) \ + && (mp)->m_source == RS_PROC_NR) + +/* Callback type definitions. */ +typedef void(*sef_cb_ping_reply_t)(message *m_ptr); + +/* Callback registration helpers. */ +_PROTOTYPE( void sef_setcb_ping_reply, (sef_cb_ping_reply_t cb)); + +/* Predefined callback implementations. */ +_PROTOTYPE( void sef_cb_ping_reply_null, (message *m_ptr) ); + +_PROTOTYPE( void sef_cb_ping_reply_pong, (message *m_ptr) ); + +/* Macros for predefined callback implementations. */ +#define SEF_CB_PING_REPLY_NULL sef_cb_ping_reply_null + +#define SEF_CB_PING_REPLY_DEFAULT sef_cb_ping_reply_pong + +/* Debug. */ +#define SEF_PING_DEBUG_DEFAULT 0 + +#ifndef SEF_PING_DEBUG +#define SEF_PING_DEBUG SEF_PING_DEBUG_DEFAULT +#endif + +#define sef_ping_dprint sef_dprint +#define sef_ping_debug_begin sef_debug_begin +#define sef_ping_debug_end sef_debug_end + +/*===========================================================================* + * SEF Live update * + *===========================================================================*/ +/* What to intercept. */ +#define INTERCEPT_SEF_LU_REQUESTS 1 +#define IS_SEF_LU_REQUEST(mp) ((mp)->m_type == RS_LU_PREPARE \ + && (mp)->m_source == RS_PROC_NR) + +/* Global helpers. */ +_PROTOTYPE( void sef_lu_ready, (int result) ); + +/* Callback type definitions. */ +typedef void(*sef_cb_lu_prepare_t)(int); +typedef int(*sef_cb_lu_state_isvalid_t)(int); +typedef void(*sef_cb_lu_state_changed_t)(int, int); +typedef void(*sef_cb_lu_state_dump_t)(int); +typedef int(*sef_cb_lu_ready_pre_t)(int); + +/* Callback registration helpers. */ +_PROTOTYPE( void sef_setcb_lu_prepare, (sef_cb_lu_prepare_t cb) ); +_PROTOTYPE( void sef_setcb_lu_state_isvalid, (sef_cb_lu_state_isvalid_t cb) ); +_PROTOTYPE( void sef_setcb_lu_state_changed, (sef_cb_lu_state_changed_t cb) ); +_PROTOTYPE( void sef_setcb_lu_state_dump, (sef_cb_lu_state_dump_t cb) ); +_PROTOTYPE( void sef_setcb_lu_ready_pre, (sef_cb_lu_ready_pre_t cb) ); + +/* Predefined callback implementations. */ +_PROTOTYPE( void sef_cb_lu_prepare_null, (int state) ); +_PROTOTYPE( int sef_cb_lu_state_isvalid_null, (int state) ); +_PROTOTYPE( void sef_cb_lu_state_changed_null, (int old_state, int state) ); +_PROTOTYPE( void sef_cb_lu_state_dump_null, (int state) ); +_PROTOTYPE( int sef_cb_lu_ready_pre_null, (int result) ); + +_PROTOTYPE( void sef_cb_lu_prepare_always_ready, (int state) ); +_PROTOTYPE( int sef_cb_lu_state_isvalid_standard, (int state) ); + +/* Macros for predefined callback implementations. */ +#define SEF_CB_LU_PREPARE_NULL sef_cb_lu_prepare_null +#define SEF_CB_LU_STATE_ISVALID_NULL sef_cb_lu_state_isvalid_null +#define SEF_CB_LU_STATE_CHANGED_NULL sef_cb_lu_state_changed_null +#define SEF_CB_LU_STATE_DUMP_NULL sef_cb_lu_state_dump_null +#define SEF_CB_LU_READY_PRE_NULL sef_cb_lu_ready_pre_null + +#define SEF_CB_LU_PREPARE_DEFAULT sef_cb_lu_prepare_null +#define SEF_CB_LU_STATE_ISVALID_DEFAULT sef_cb_lu_state_isvalid_null +#define SEF_CB_LU_STATE_CHANGED_DEFAULT sef_cb_lu_state_changed_null +#define SEF_CB_LU_STATE_DUMP_DEFAULT sef_cb_lu_state_dump_null +#define SEF_CB_LU_READY_PRE_DEFAULT sef_cb_lu_ready_pre_null + +/* Standard live update states. */ +#define SEF_LU_STATE_NULL 0 /* null state */ +#define SEF_LU_STATE_WORK_FREE 1 /* no work in progress */ +#define SEF_LU_STATE_REQUEST_FREE 2 /* no request in progress */ +#define SEF_LU_STATE_PROTOCOL_FREE 3 /* no protocol in progress */ +#define SEF_LU_STATE_CUSTOM_BASE (SEF_LU_STATE_PROTOCOL_FREE+1) +#define SEF_LU_STATE_IS_STANDARD(s) ((s) > SEF_LU_STATE_NULL \ + && (s) < SEF_LU_STATE_CUSTOM_BASE) + +/* Debug. */ +#define SEF_LU_DEBUG_DEFAULT 1 + +#ifndef SEF_LU_DEBUG +#define SEF_LU_DEBUG SEF_LU_DEBUG_DEFAULT +#endif + +#define sef_lu_dprint sef_dprint +#define sef_lu_debug_begin sef_debug_begin +#define sef_lu_debug_end sef_debug_end + +#endif /* _SEF_H */ + diff --git a/include/minix/syslib.h b/include/minix/syslib.h index 60f8587da..d47c643dc 100644 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -18,6 +18,7 @@ #endif #include +#include /* Forward declaration */ struct reg86u; diff --git a/lib/syslib/Makefile.in b/lib/syslib/Makefile.in index 3c2793856..0bcad8885 100644 --- a/lib/syslib/Makefile.in +++ b/lib/syslib/Makefile.in @@ -27,6 +27,9 @@ libsys_FILES=" \ pci_set_acl.c \ pci_slot_name.c \ safecopies.c \ + sef.c \ + sef_liveupdate.c \ + sef_ping.c \ sys_abort.c \ sys_cprof.c \ sys_endsig.c \ diff --git a/lib/syslib/sef.c b/lib/syslib/sef.c new file mode 100644 index 000000000..3f1d145d3 --- /dev/null +++ b/lib/syslib/sef.c @@ -0,0 +1,153 @@ +#include "syslib.h" +#include +#include +#include + +/* Self variables. */ +#define SEF_SELF_NAME_MAXLEN 20 +PRIVATE char sef_self_name[SEF_SELF_NAME_MAXLEN]; +PRIVATE endpoint_t sef_self_endpoint; + +/* Debug. */ +#define SEF_DEBUG_HEADER_MAXLEN 32 +PRIVATE time_t sef_debug_boottime = 0; +PRIVATE u32_t sef_debug_system_hz = 0; +PRIVATE time_t sef_debug_time_sec = 0; +PRIVATE time_t sef_debug_time_us = 0; +PRIVATE char sef_debug_header_buff[SEF_DEBUG_HEADER_MAXLEN]; +FORWARD _PROTOTYPE( void sef_debug_refresh_params, (void) ); +PUBLIC _PROTOTYPE( char* sef_debug_header, (void) ); + +/* SEF Live update prototypes. */ +EXTERN _PROTOTYPE( void do_sef_lu_before_receive, (void) ); +EXTERN _PROTOTYPE( int do_sef_lu_request, (message *m_ptr) ); + +/* SEF Ping prototypes. */ +EXTERN _PROTOTYPE( int do_sef_ping_request, (message *m_ptr) ); + +/*===========================================================================* + * sef_startup * + *===========================================================================*/ +PUBLIC void sef_startup() +{ +/* SEF startup interface for system processes. */ + int r; + + /* Get information about self. */ + r = sys_whoami(&sef_self_endpoint, sef_self_name, SEF_SELF_NAME_MAXLEN); + if ( r != OK) { + sef_self_endpoint = SELF; + sprintf(sef_self_name, "%s", "Unknown"); + } +} + +/*===========================================================================* + * sef_receive * + *===========================================================================*/ +PUBLIC int sef_receive(endpoint_t src, message *m_ptr) +{ +/* SEF receive() interface for system processes. */ + int r; + + while(TRUE) { + +#if INTERCEPT_SEF_LU_REQUESTS + /* Handle SEF Live update before receive events. */ + do_sef_lu_before_receive(); +#endif + + /* Receive and return in case of error. */ + r = receive(src, m_ptr); + if(r != OK) { + return r; + } + +#if INTERCEPT_SEF_PING_REQUESTS + /* Intercept SEF Ping requests. */ + if(IS_SEF_PING_REQUEST(m_ptr)) { + if(do_sef_ping_request(m_ptr) == OK) { + continue; + } + } +#endif + +#if INTERCEPT_SEF_LU_REQUESTS + /* Intercept SEF Live update requests. */ + if(IS_SEF_LU_REQUEST(m_ptr)) { + if(do_sef_lu_request(m_ptr) == OK) { + continue; + } + } +#endif + + /* If we get this far, this is not a valid SEF request, return and + * let the caller deal with that. + */ + break; + } + + return r; +} + +/*===========================================================================* + * sef_debug_refresh_params * + *===========================================================================*/ +PRIVATE void sef_debug_refresh_params(void) +{ +/* Refresh SEF debug params. */ + clock_t uptime; + endpoint_t endpoint; + int r; + + /* Get boottime the first time. */ + if(!sef_debug_boottime) { + r = sys_times(NONE, NULL, NULL, NULL, &sef_debug_boottime); + if ( r != OK) { + sef_debug_boottime = -1; + } + } + + /* Get system hz the first time. */ + if(!sef_debug_system_hz) { + r = sys_getinfo(GET_HZ, &sef_debug_system_hz, + sizeof(sef_debug_system_hz), 0, 0); + if ( r != OK) { + sef_debug_system_hz = -1; + } + } + + /* Get uptime. */ + uptime = -1; + if(sef_debug_boottime!=-1 && sef_debug_system_hz!=-1) { + r = sys_times(NONE, NULL, NULL, &uptime, NULL); + if ( r != OK) { + uptime = -1; + } + } + + /* Compute current time. */ + if(sef_debug_boottime==-1 || sef_debug_system_hz==-1 || uptime==-1) { + sef_debug_time_sec = 0; + sef_debug_time_us = 0; + } + else { + sef_debug_time_sec = (time_t) (sef_debug_boottime + + (uptime/sef_debug_system_hz)); + sef_debug_time_us = (uptime%sef_debug_system_hz) + * 1000000/sef_debug_system_hz; + } +} + +/*===========================================================================* + * sef_debug_header * + *===========================================================================*/ +PUBLIC char* sef_debug_header(void) +{ +/* Build and return a SEF debug header. */ + sef_debug_refresh_params(); + sprintf(sef_debug_header_buff, "%s: time = %ds %06dus", + sef_self_name, sef_debug_time_sec, sef_debug_time_us); + + return sef_debug_header_buff; +} + diff --git a/lib/syslib/sef_liveupdate.c b/lib/syslib/sef_liveupdate.c new file mode 100644 index 000000000..862f113ce --- /dev/null +++ b/lib/syslib/sef_liveupdate.c @@ -0,0 +1,245 @@ +#include "syslib.h" +#include +#include + +/* SEF Live update variables. */ +PRIVATE int sef_lu_state = SEF_LU_STATE_NULL; + +/* SEF Live update callbacks. */ +PRIVATE struct sef_cbs { + sef_cb_lu_prepare_t sef_cb_lu_prepare; + sef_cb_lu_state_isvalid_t sef_cb_lu_state_isvalid; + sef_cb_lu_state_changed_t sef_cb_lu_state_changed; + sef_cb_lu_state_dump_t sef_cb_lu_state_dump; + sef_cb_lu_ready_pre_t sef_cb_lu_ready_pre; +} sef_cbs = { + SEF_CB_LU_PREPARE_DEFAULT, + SEF_CB_LU_STATE_ISVALID_DEFAULT, + SEF_CB_LU_STATE_CHANGED_DEFAULT, + SEF_CB_LU_STATE_DUMP_DEFAULT, + SEF_CB_LU_READY_PRE_DEFAULT, +}; + +/* SEF Live update prototypes for sef_receive(). */ +PUBLIC _PROTOTYPE( void do_sef_lu_before_receive, (void) ); +PUBLIC _PROTOTYPE( int do_sef_lu_request, (message *m_ptr) ); + +/* Debug. */ +EXTERN _PROTOTYPE( char* sef_debug_header, (void) ); +PRIVATE int sef_lu_debug_cycle = 0; + +/*===========================================================================* + * do_sef_lu_before_receive * + *===========================================================================*/ +PUBLIC void do_sef_lu_before_receive() +{ +/* Handle SEF Live update before receive events. */ + + /* Nothing to do if we are not preparing for a live update. */ + if(sef_lu_state == SEF_LU_STATE_NULL) { + return; + } + + /* Debug. */ +#if SEF_LU_DEBUG + sef_lu_debug_cycle++; + sef_lu_debug_begin(); + sef_lu_dprint("%s, cycle=%d. Dumping state variables:\n", + sef_debug_header(), sef_lu_debug_cycle); + sef_cbs.sef_cb_lu_state_dump(sef_lu_state); + sef_lu_debug_end(); +#endif + + /* Let the callback code handle the event. + * For SEF_LU_STATE_WORK_FREE, we're always ready, tell immediately. + */ + if(sef_lu_state == SEF_LU_STATE_WORK_FREE) { + sef_lu_ready(OK); + } + else { + sef_cbs.sef_cb_lu_prepare(sef_lu_state); + } +} + +/*===========================================================================* + * do_sef_lu_request * + *===========================================================================*/ +PUBLIC int do_sef_lu_request(message *m_ptr) +{ +/* Handle a SEF Live update request. */ + int old_state, is_valid_state; + + sef_lu_debug_cycle = 0; + old_state = sef_lu_state; + + /* Only accept live update requests with a valid state. */ + is_valid_state = sef_cbs.sef_cb_lu_state_isvalid(m_ptr->RS_LU_STATE); + if(!is_valid_state) { + sef_lu_ready(EINVAL); + } + else { + /* Set the new live update state. */ + sef_lu_state = m_ptr->RS_LU_STATE; + + /* If the live update state changed, let the callback code + * handle the rest. + */ + if(old_state != sef_lu_state) { + sef_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state); + } + } + + /* Return OK not to let anybody else intercept the request. */ + return(OK); +} + +/*===========================================================================* + * sef_lu_ready * + *===========================================================================*/ +PUBLIC void sef_lu_ready(int result) +{ + message m; + int old_state, r; + +#if SEF_LU_DEBUG + sef_lu_debug_begin(); + sef_lu_dprint("%s, cycle=%d. Ready to update with result: %d%s\n", + sef_debug_header(), sef_lu_debug_cycle, + result, (result == OK ? "(OK)" : "")); + sef_lu_debug_end(); +#endif + + /* Let the callback code perform any pre-ready operations. */ + r = sef_cbs.sef_cb_lu_ready_pre(result); + if(r != OK) { + /* Abort update if callback returned error. */ + result = r; + } + else { + /* Inform RS that we're ready with the given result. */ + m.m_type = RS_LU_PREPARE; + m.RS_LU_STATE = sef_lu_state; + m.RS_LU_RESULT = result; + r = sendrec(RS_PROC_NR, &m); + if ( r != OK) { + panic("SEF", "sendrec failed", r); + } + } + +#if SEF_LU_DEBUG + sef_lu_debug_begin(); + sef_lu_dprint("%s, cycle=%d. The %s aborted the update!\n", + sef_debug_header(), sef_lu_debug_cycle, + (result == OK ? "server" : "client")); + sef_lu_debug_end(); +#endif + + /* Something went wrong. Update was aborted and we didn't get updated. + * Restore things back to normal and continue executing. + */ + old_state = sef_lu_state; + sef_lu_state = SEF_LU_STATE_NULL; + if(old_state != sef_lu_state) { + sef_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state); + } +} + +/*===========================================================================* + * sef_setcb_lu_prepare * + *===========================================================================*/ +PUBLIC void sef_setcb_lu_prepare(sef_cb_lu_prepare_t cb) +{ + assert(cb != NULL); + sef_cbs.sef_cb_lu_prepare = cb; +} + +/*===========================================================================* + * sef_setcb_lu_state_isvalid * + *===========================================================================*/ +PUBLIC void sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_t cb) +{ + assert(cb != NULL); + sef_cbs.sef_cb_lu_state_isvalid = cb; +} + +/*===========================================================================* + * sef_setcb_lu_state_changed * + *===========================================================================*/ +PUBLIC void sef_setcb_lu_state_changed(sef_cb_lu_state_changed_t cb) +{ + assert(cb != NULL); + sef_cbs.sef_cb_lu_state_changed = cb; +} + +/*===========================================================================* + * sef_setcb_lu_state_dump * + *===========================================================================*/ +PUBLIC void sef_setcb_lu_state_dump(sef_cb_lu_state_dump_t cb) +{ + assert(cb != NULL); + sef_cbs.sef_cb_lu_state_dump = cb; +} + +/*===========================================================================* + * sef_setcb_lu_ready_pre * + *===========================================================================*/ +PUBLIC void sef_setcb_lu_ready_pre(sef_cb_lu_ready_pre_t cb) +{ + assert(cb != NULL); + sef_cbs.sef_cb_lu_ready_pre = cb; +} + +/*===========================================================================* + * sef_cb_lu_prepare_null * + *===========================================================================*/ +PUBLIC void sef_cb_lu_prepare_null(int state) +{ +} + +/*===========================================================================* + * sef_cb_lu_state_isvalid_null * + *===========================================================================*/ +PUBLIC int sef_cb_lu_state_isvalid_null(int state) +{ + return FALSE; +} + +/*===========================================================================* + * sef_cb_lu_state_changed_null * + *===========================================================================*/ +PUBLIC void sef_cb_lu_state_changed_null(int old_state, int state) +{ +} + +/*===========================================================================* + * sef_cb_lu_state_dump_null * + *===========================================================================*/ +PUBLIC void sef_cb_lu_state_dump_null(int state) +{ + sef_lu_dprint("NULL\n"); +} + +/*===========================================================================* + * sef_cb_lu_ready_pre_null * + *===========================================================================*/ +PUBLIC int sef_cb_lu_ready_pre_null(int result) +{ + return(OK); +} + +/*===========================================================================* + * sef_cb_lu_prepare_always_ready * + *===========================================================================*/ +PUBLIC void sef_cb_lu_prepare_always_ready(int state) +{ + sef_lu_ready(OK); +} + +/*===========================================================================* + * sef_cb_lu_state_isvalid_standard * + *===========================================================================*/ +PUBLIC int sef_cb_lu_state_isvalid_standard(int state) +{ + return SEF_LU_STATE_IS_STANDARD(state); +} + diff --git a/lib/syslib/sef_ping.c b/lib/syslib/sef_ping.c new file mode 100644 index 000000000..60c6734d3 --- /dev/null +++ b/lib/syslib/sef_ping.c @@ -0,0 +1,63 @@ +#include "syslib.h" +#include +#include + +/* SEF Ping callbacks. */ +PRIVATE struct sef_cbs { + sef_cb_ping_reply_t sef_cb_ping_reply; +} sef_cbs = { + SEF_CB_PING_REPLY_DEFAULT +}; + +/* SEF Ping prototypes for sef_receive(). */ +PUBLIC _PROTOTYPE( int do_sef_ping_request, (message *m_ptr) ); + +/* Debug. */ +EXTERN _PROTOTYPE( char* sef_debug_header, (void) ); + +/*===========================================================================* + * do_sef_ping_request * + *===========================================================================*/ +PUBLIC int do_sef_ping_request(message *m_ptr) +{ +/* Handle a SEF Ping request. */ + + /* Debug. */ +#if SEF_PING_DEBUG + sef_ping_debug_begin(); + sef_ping_dprint("%s. Got a SEF Ping request! About to reply.\n", + sef_debug_header()); + sef_ping_debug_end(); +#endif + + /* Let the callback code handle the request. */ + sef_cbs.sef_cb_ping_reply(m_ptr); + + /* Return OK not to let anybody else intercept the request. */ + return(OK); +} + +/*===========================================================================* + * sef_setcb_ping_reply * + *===========================================================================*/ +PUBLIC void sef_setcb_ping_reply(sef_cb_ping_reply_t cb) +{ + assert(cb != NULL); + sef_cbs.sef_cb_ping_reply = cb; +} + +/*===========================================================================* + * sef_cb_ping_reply_null * + *===========================================================================*/ +PUBLIC void sef_cb_ping_reply_null(message *m_ptr) +{ +} + +/*===========================================================================* + * sef_cb_ping_reply_pong * + *===========================================================================*/ +PUBLIC void sef_cb_ping_reply_pong(message *m_ptr) +{ + notify(m_ptr->m_source); +} + diff --git a/servers/ds/main.c b/servers/ds/main.c index d6edc50ce..978da669b 100644 --- a/servers/ds/main.c +++ b/servers/ds/main.c @@ -25,6 +25,9 @@ FORWARD _PROTOTYPE(void sig_handler, (void) ); FORWARD _PROTOTYPE(void get_work, (message *m_ptr) ); FORWARD _PROTOTYPE(void reply, (int whom, message *m_ptr) ); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -38,6 +41,9 @@ PUBLIC int main(int argc, char **argv) int result; sigset_t sigset; + /* SEF local startup. */ + sef_local_startup(); + /* Initialize the server, then go to work. */ init_server(argc, argv); @@ -93,6 +99,17 @@ send_reply: return(OK); /* shouldn't come here */ } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * init_server * *===========================================================================*/ @@ -142,7 +159,7 @@ PRIVATE void get_work(m_ptr) message *m_ptr; /* message buffer */ { int status = 0; - status = receive(ANY, m_ptr); /* this blocks until message arrives */ + status = sef_receive(ANY, m_ptr); /* this blocks until message arrives */ if (OK != status) panic("DS","failed to receive message!", status); who_e = m_ptr->m_source; /* message arrived! set sender */ diff --git a/servers/inet/inet.c b/servers/inet/inet.c index a6a59e2c4..ae20e1034 100644 --- a/servers/inet/inet.c +++ b/servers/inet/inet.c @@ -97,6 +97,9 @@ _PROTOTYPE( void main, (void) ); FORWARD _PROTOTYPE( void nw_conf, (void) ); FORWARD _PROTOTYPE( void nw_init, (void) ); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + PUBLIC void main() { mq_t *mq; @@ -110,6 +113,9 @@ PUBLIC void main() u8_t randbits[32]; struct timeval tv; + /* SEF local startup. */ + sef_local_startup(); + #if DEBUG printf("Starting inet...\n"); printf("%s\n", version); @@ -235,7 +241,7 @@ PUBLIC void main() if (!mq) ip_panic(("out of messages")); - r= receive (ANY, &mq->mq_mess); + r= sef_receive(ANY, &mq->mq_mess); if (r<0) { ip_panic(("unable to receive: %d", r)); @@ -291,6 +297,17 @@ PUBLIC void main() ip_panic(("task is not allowed to terminate")); } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + PRIVATE void nw_conf() { read_conf(); diff --git a/servers/ipc/main.c b/servers/ipc/main.c index f72ed7b78..2310a245c 100644 --- a/servers/ipc/main.c +++ b/servers/ipc/main.c @@ -23,10 +23,16 @@ struct { int verbose = 0; +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + PUBLIC int main(int argc, char *argv[]) { message m; + /* SEF local startup. */ + sef_local_startup(); + SELF_E = getprocnr(); if(verbose) @@ -36,8 +42,8 @@ PUBLIC int main(int argc, char *argv[]) int r; int i; - if ((r = receive(ANY, &m)) != OK) - printf("IPC receive error %d.\n", r); + if ((r = sef_receive(ANY, &m)) != OK) + printf("sef_receive failed %d.\n", r); who_e = m.m_source; call_type = m.m_type; @@ -100,3 +106,14 @@ PUBLIC int main(int argc, char *argv[]) return -1; } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + diff --git a/servers/is/dmp_rs.c b/servers/is/dmp_rs.c index da7b7cfba..709ffbd46 100644 --- a/servers/is/dmp_rs.c +++ b/servers/is/dmp_rs.c @@ -56,7 +56,7 @@ PRIVATE char *s_flags_str(int flags) str[1] = (flags & RS_EXITING) ? 'E' : '-'; str[2] = (flags & RS_REFRESHING) ? 'R' : '-'; str[3] = (flags & RS_NOPINGREPLY) ? 'N' : '-'; - str[4] = '-'; + str[4] = (flags & RS_UPDATING) ? 'u' : '-'; str[5] = '\0'; return(str); diff --git a/servers/is/main.c b/servers/is/main.c index 15f2b5ee0..c2e88ab00 100644 --- a/servers/is/main.c +++ b/servers/is/main.c @@ -24,6 +24,9 @@ FORWARD _PROTOTYPE(void sig_handler, (void) ); FORWARD _PROTOTYPE(void get_work, (void) ); FORWARD _PROTOTYPE(void reply, (int whom, int result) ); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -36,6 +39,9 @@ PUBLIC int main(int argc, char **argv) int result; sigset_t sigset; + /* SEF local startup. */ + sef_local_startup(); + /* Initialize the server, then go to work. */ init_server(argc, argv); @@ -60,9 +66,6 @@ PUBLIC int main(int argc, char **argv) case TTY_PROC_NR: result = do_fkey_pressed(&m_in); break; - case RS_PROC_NR: - notify(m_in.m_source); - continue; } } else { @@ -79,6 +82,19 @@ PUBLIC int main(int argc, char **argv) return(OK); /* shouldn't come here */ } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* Register live update callbacks. */ + sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); + sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard); + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * init_server * *===========================================================================*/ @@ -123,9 +139,9 @@ PRIVATE void sig_handler() PRIVATE void get_work() { int status = 0; - status = receive(ANY, &m_in); /* this blocks until message arrives */ + status = sef_receive(ANY, &m_in); /* this blocks until message arrives */ if (OK != status) - panic("IS","failed to receive message!", status); + panic("IS","sef_receive failed!", status); who_e = m_in.m_source; /* message arrived! set sender */ callnr = m_in.m_type; /* set function call number */ } @@ -144,3 +160,4 @@ int result; /* report result to replyee */ panic("IS", "unable to send reply!", send_status); } + diff --git a/servers/iso9660fs/main.c b/servers/iso9660fs/main.c index 38bbd7555..6bff616d7 100644 --- a/servers/iso9660fs/main.c +++ b/servers/iso9660fs/main.c @@ -12,6 +12,9 @@ FORWARD _PROTOTYPE(void init_server, (void) ); FORWARD _PROTOTYPE(void get_work, (message *m_in) ); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -19,9 +22,12 @@ PUBLIC int main(void) { int who_e, ind, error; message m; + /* SEF local startup. */ + sef_local_startup(); + /* Initialize the server, then go to work. */ init_server(); - + fs_m_in.m_type = FS_READY; if (send(FS_PROC_NR, &fs_m_in) != OK) { @@ -65,6 +71,17 @@ PUBLIC int main(void) { } } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * init_server * *===========================================================================*/ @@ -87,9 +104,9 @@ PRIVATE void init_server(void) PRIVATE void get_work(m_in) message *m_in; /* pointer to message */ { - int s; /* receive status */ - if (OK != (s = receive(ANY, m_in))) /* wait for message */ - panic("ISOFS","receive failed", s); + int s; /* receive status */ + if (OK != (s = sef_receive(ANY, m_in))) /* wait for message */ + panic("ISOFS","sef_receive failed", s); } /*===========================================================================* diff --git a/servers/mfs/main.c b/servers/mfs/main.c index 38a5c12bc..d946b4d03 100644 --- a/servers/mfs/main.c +++ b/servers/mfs/main.c @@ -14,6 +14,8 @@ FORWARD _PROTOTYPE(void init_server, (void) ); FORWARD _PROTOTYPE(void get_work, (message *m_in) ); FORWARD _PROTOTYPE(void cch_check, (void) ); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); /*===========================================================================* * main * @@ -27,6 +29,9 @@ PUBLIC int main(int argc, char *argv[]) int error, ind; message m; + /* SEF local startup. */ + sef_local_startup(); + /* Initialize the server, then go to work. */ init_server(); @@ -84,6 +89,17 @@ PUBLIC int main(int argc, char *argv[]) } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * init_server * *===========================================================================*/ @@ -119,8 +135,8 @@ message *m_in; /* pointer to message */ endpoint_t src; do { - if ((r = receive(ANY, m_in)) != OK) /* wait for message */ - panic("MFS","receive failed", r); + if ((r = sef_receive(ANY, m_in)) != OK) /* wait for message */ + panic("MFS","sef_receive failed", r); src = fs_m_in.m_source; if (src != FS_PROC_NR) { diff --git a/servers/pfs/main.c b/servers/pfs/main.c index 0040006ce..f386b0797 100644 --- a/servers/pfs/main.c +++ b/servers/pfs/main.c @@ -10,6 +10,9 @@ FORWARD _PROTOTYPE(void init_server, (void) ); FORWARD _PROTOTYPE(void get_work, (message *m_in) ); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -22,6 +25,9 @@ PUBLIC int main(int argc, char *argv[]) int error, ind; message m; + /* SEF local startup. */ + sef_local_startup(); + /* Initialize the server, then go to work. */ init_server(); @@ -60,6 +66,16 @@ PUBLIC int main(int argc, char *argv[]) return(OK); } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} /*===========================================================================* * init_server * @@ -99,8 +115,8 @@ message *m_in; /* pointer to message */ endpoint_t src; do { - if ((r = receive(ANY, m_in)) != OK) /* wait for message */ - panic("PFS","receive failed", r); + if ((r = sef_receive(ANY, m_in)) != OK) /* wait for message */ + panic("PFS","sef_receive failed", r); src = fs_m_in.m_source; if (src != VFS_PROC_NR) { diff --git a/servers/pm/main.c b/servers/pm/main.c index 4c5623448..64f5f2f8d 100644 --- a/servers/pm/main.c +++ b/servers/pm/main.c @@ -48,6 +48,9 @@ FORWARD _PROTOTYPE( void handle_fs_reply, (void) ); #define click_to_round_k(n) \ ((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024)) +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -58,6 +61,9 @@ PUBLIC int main() struct mproc *rmp; sigset_t sigset; + /* SEF local startup. */ + sef_local_startup(); + pm_init(); /* initialize process manager tables */ /* This is PM's main loop- get work and do it, forever and forever. */ @@ -176,14 +182,25 @@ send_reply: return(OK); } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * get_work * *===========================================================================*/ PRIVATE void get_work() { /* Wait for the next message and extract useful information from it. */ - if (receive(ANY, &m_in) != OK) - panic(__FILE__,"PM receive error", NO_NUM); + if (sef_receive(ANY, &m_in) != OK) + panic(__FILE__,"PM sef_receive error", NO_NUM); who_e = m_in.m_source; /* who sent the message */ if(pm_isokendpt(who_e, &who_p) != OK) panic(__FILE__, "PM got message from invalid endpoint", who_e); diff --git a/servers/rs/Makefile b/servers/rs/Makefile index 72cd9261b..7c820a8fc 100644 --- a/servers/rs/Makefile +++ b/servers/rs/Makefile @@ -27,7 +27,7 @@ $(UTIL): $(UTIL_OBJ) $(CC) -o $@ $(LDFLAGS) $(UTIL_OBJ) $(UTIL_LIBS) $(SERVER): $(OBJ) $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS) - install -S 350k $@ + install -S 450k $@ # install with other servers install: /bin/$(UTIL) /usr/sbin/$(SERVER) diff --git a/servers/rs/const.h b/servers/rs/const.h index c415ad45d..dff91414a 100644 --- a/servers/rs/const.h +++ b/servers/rs/const.h @@ -26,6 +26,7 @@ #define RS_CRASHED 0x040 /* service crashed */ #define RS_LATEREPLY 0x080 /* no reply sent to RS_DOWN caller yet */ #define RS_SIGNALED 0x100 /* service crashed */ +#define RS_UPDATING 0x200 /* set when update must be done */ /* Sys flag values. */ #define SF_CORE_PROC 0x001 /* set for core system processes @@ -47,6 +48,10 @@ #define END_RPROC_ADDR (&rproc[NR_SYS_PROCS]) #define NIL_RPROC ((struct mproc *) 0) +/* Constants for live update. */ +#define RS_DEFAULT_PREPARE_MAXTIME 2*RS_DELTA_T /* default prepare max time */ +#define RS_MAX_PREPARE_MAXTIME 20*RS_DELTA_T /* max prepare max time */ + /* Definitions for boot info tables. */ #define NULL_BOOT_NR NR_BOOT_PROCS /* marks a null boot entry */ diff --git a/servers/rs/glo.h b/servers/rs/glo.h index e1681b342..9d9f4dd8a 100644 --- a/servers/rs/glo.h +++ b/servers/rs/glo.h @@ -37,6 +37,11 @@ EXTERN struct rproc *rproc_ptr[NR_PROCS]; /* mapping for fast access */ */ EXTERN int exec_pipe[2]; +/* Global update descriptor. This descriptor holds data when a live update + * is in progress. + */ +EXTERN struct rupdate rupdate; + /* Enable/disable verbose output. */ EXTERN long rs_verbose; diff --git a/servers/rs/main.c b/servers/rs/main.c index 7243614c0..2b3a0a460 100644 --- a/servers/rs/main.c +++ b/servers/rs/main.c @@ -44,6 +44,9 @@ PRIVATE char *boot_image_buffer; /* Flag set when memory unmapping can be done. */ EXTERN int unmap_ok; +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -59,6 +62,9 @@ PUBLIC int main(void) sigset_t sigset; /* system signal set */ int s; + /* SEF local startup. */ + sef_local_startup(); + /* Initialize the server, then go to work. */ init_server(); @@ -74,9 +80,10 @@ PUBLIC int main(void) call_nr = m.m_type; - /* Now determine what to do. Three types of requests are expected: + /* Now determine what to do. Four types of requests are expected: * - Heartbeat messages (notifications from registered system services) * - System notifications (POSIX signals or synchronous alarm) + * - Ready to update messages (reply messages from registered services) * - User requests (control messages to manage system services) */ @@ -87,10 +94,9 @@ PUBLIC int main(void) switch (who_p) { case CLOCK: do_period(&m); /* check services status */ - continue; - case PM_PROC_NR: - sig_handler(); - continue; + continue; + case PM_PROC_NR: /* signal or PM heartbeat */ + sig_handler(); default: /* heartbeat notification */ if (rproc_ptr[who_p] != NULL) { /* mark heartbeat time */ rproc_ptr[who_p]->r_alive_tm = m.NOTIFY_TIMESTAMP; @@ -101,7 +107,21 @@ PUBLIC int main(void) } } - /* If this is not a notification message, it is a normal request. + /* See if this is a ready to update message. + * If the message was expected, update the originating process + */ + else if(call_nr == RS_LU_PREPARE) { + result = do_upd_ready(&m); + + /* Send reply only if something went wrong. */ + if (result != OK) { + m.m_type = result; + reply(who_e, &m); + } + } + + /* If this is neither a ready to update message nor a notification + * message, it is a normal request. * Handle the request and send a reply to the caller. */ else { @@ -121,6 +141,7 @@ PUBLIC int main(void) case RS_REFRESH: result = do_refresh(&m); break; case RS_RESTART: result = do_restart(&m); break; case RS_SHUTDOWN: result = do_shutdown(&m); break; + case RS_UPDATE: result = do_update(&m); break; case GETSYSINFO: result = do_getsysinfo(&m); break; case RS_LOOKUP: result = do_lookup(&m); break; default: @@ -138,6 +159,17 @@ PUBLIC int main(void) } } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * exec_image_copy * *===========================================================================*/ @@ -322,6 +354,9 @@ PRIVATE void init_server(void) /* See if we run in verbose mode. */ env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1); + /* Initialize the global update descriptor. */ + rupdate.flags = 0; + /* Get a copy of the boot image table. */ if ((s = sys_getimage(image)) != OK) { panic("RS", "unable to get copy of boot image table", s); @@ -495,7 +530,7 @@ PRIVATE void init_server(void) boot_image_info_lookup(boot_image_priv->endpoint, image, &ip, NULL, NULL, NULL); - /* Allow the process to run. */ + /* Allow the service to run. */ if ((s = sys_privctl(ip->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) { panic("RS", "unable to initialize privileges", s); } @@ -618,8 +653,8 @@ PRIVATE void get_work(m_in) message *m_in; /* pointer to message */ { int s; /* receive status */ - if (OK != (s=receive(ANY, m_in))) /* wait for message */ - panic("RS","receive failed", s); + if (OK != (s=sef_receive(ANY, m_in))) /* wait for message */ + panic("RS", "sef_receive failed", s); } /*===========================================================================* diff --git a/servers/rs/manager.c b/servers/rs/manager.c index c2fd0ca5c..0fc66b166 100644 --- a/servers/rs/manager.c +++ b/servers/rs/manager.c @@ -1,5 +1,6 @@ /* * Changes: + * Nov 22, 2009: added basic live update support (Cristiano Giuffrida) * Mar 02, 2009: Extended isolation policies (Jorrit N. Herder) * Jul 22, 2005: Created (Jorrit N. Herder) */ @@ -38,9 +39,9 @@ FORWARD _PROTOTYPE( void add_forward_ipc, (struct rproc *rp, FORWARD _PROTOTYPE( void add_backward_ipc, (struct rproc *rp, struct priv *privp) ); FORWARD _PROTOTYPE( void init_privs, (struct rproc *rp, struct priv *privp) ); -FORWARD _PROTOTYPE( int set_privs, (endpoint_t endpoint, struct priv *privp, - int req) ); FORWARD _PROTOTYPE( void init_pci, (struct rproc *rp, int endpoint) ); +FORWARD _PROTOTYPE( void update_period, (message *m_ptr) ); +FORWARD _PROTOTYPE( void end_update, (clock_t now) ); PRIVATE int shutting_down = FALSE; @@ -590,6 +591,190 @@ PUBLIC int do_shutdown(message *m_ptr) return(OK); } +/*===========================================================================* + * do_update * + *===========================================================================*/ +PUBLIC int do_update(message *m_ptr) +{ + register struct rproc *rp; + size_t len; + int s; + char label[MAX_LABEL_LEN]; + int lu_state; + int prepare_maxtime; + + /* Retrieve label. */ + len= m_ptr->RS_CMD_LEN; + if (len >= sizeof(label)) + return EINVAL; /* Too long */ + s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR, + SELF, (vir_bytes) label, len); + if (s != OK) return(s); + label[len]= '\0'; + + /* Retrieve live update state. */ + lu_state = m_ptr->RS_LU_STATE; + if(lu_state == SEF_LU_STATE_NULL) { + return(EINVAL); + } + + /* Retrieve prepare max time. */ + prepare_maxtime = m_ptr->RS_LU_PREPARE_MAXTIME; + if(prepare_maxtime) { + if(prepare_maxtime < 0 || prepare_maxtime > RS_MAX_PREPARE_MAXTIME) { + return(EINVAL); + } + } + else { + prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME; + } + + /* Make sure we are not already updating. */ + if(rupdate.flags & RS_UPDATING) { + if(rs_verbose) { + printf("RS: do_update: an update is already in progress"); + } + return(EBUSY); + } + + /* Try to start the update process. */ + for (rp=BEG_RPROC_ADDR; rpr_flags & RS_IN_USE && strcmp(rp->r_label, label) == 0) { + if(rs_verbose) { + printf("RS: updating %s (%d)\n", rp->r_label, rp->r_pid); + } + + rp->r_flags |= RS_UPDATING; + rupdate.flags |= RS_UPDATING; + getuptime(&rupdate.prepare_tm); + rupdate.prepare_maxtime = prepare_maxtime; + rupdate.rp = rp; + + m_ptr->m_type = RS_LU_PREPARE; + asynsend(rp->r_proc_nr_e, m_ptr); /* request to prepare for update */ + + return(OK); + } + } + if(rs_verbose) { + printf("RS: do_update: '%s' not found\n", label); + } + + return(ESRCH); +} + +/*===========================================================================* + * do_upd_ready * + *===========================================================================*/ +PUBLIC int do_upd_ready(message *m_ptr) +{ + register struct rproc *rp; + int who_p; + clock_t now = m_ptr->NOTIFY_TIMESTAMP; + int result; + + who_p = _ENDPOINT_P(m_ptr->m_source); + rp = rproc_ptr[who_p]; + result = m_ptr->RS_LU_RESULT; + + /* Make sure the originating process was requested to prepare for update. */ + if(! (rp->r_flags & RS_UPDATING) ) { + if(rs_verbose) { + printf("RS: do_upd_ready: got unexpected update ready msg from %d\n", + m_ptr->m_source); + } + return(EINVAL); + } + + /* Check if something went wrong and the process failed to prepare + * for the update. In that case, end the update process. + */ + if(result != OK) { + end_update(now); + switch(result) { + case EACCES: + printf("RS: update failed: %s\n", + "process does not support live update"); + break; + + case EINVAL: + printf("RS: update failed: %s\n", + "process does not support the required state"); + break; + + case EBUSY: + printf("RS: update failed: %s\n", + "process is not able to prepare for the update now"); + break; + + case EGENERIC: + printf("RS: update failed: %s\n", + "a generic error occurred while preparing for the update"); + break; + + default: + printf("RS: update failed: %s (%d)\n", + "an unknown error occurred while preparing for the update\n", + result); + break; + } + + return ENOTREADY; + } + + /* Kill the process now and mark it for refresh, the new version will + * be automatically restarted. + */ + rp->r_flags &= ~RS_EXITING; + rp->r_flags |= RS_REFRESHING; + kill(rp->r_pid, SIGKILL); + + return(OK); +} + +/*===========================================================================* + * update_period * + *===========================================================================*/ +PRIVATE void update_period(message *m_ptr) +{ + clock_t now = m_ptr->NOTIFY_TIMESTAMP; + short has_update_timed_out; + message m; + + /* See if a timeout has occurred. */ + has_update_timed_out = (now - rupdate.prepare_tm > rupdate.prepare_maxtime); + + /* If an update timed out, end the update process and notify the service. */ + if(has_update_timed_out) { + end_update(now); + printf("RS: update failed: maximum prepare time reached\n"); + + /* Prepare cancel request. */ + m.m_type = RS_LU_PREPARE; + m.RS_LU_STATE = SEF_LU_STATE_NULL; + asynsend(rupdate.rp->r_proc_nr_e, &m); + } +} + +/*===========================================================================* + * end_update * + *===========================================================================*/ +PRIVATE void end_update(clock_t now) +{ + /* End the update process and mark the affected service as no longer under + * update. Eventual late ready to update message (if any) will simply be + * ignored and the service can continue executing. + * Also, if the service has a period, update the alive and check timestamps + * of the service to force a status request in the next period. + */ + rupdate.flags &= ~RS_UPDATING; + rupdate.rp->r_flags &= ~RS_UPDATING; + if(rupdate.rp->r_period > 0 ) { + rupdate.rp->r_alive_tm = now; + rupdate.rp->r_check_tm = now - rupdate.rp->r_period - 1; + } +} + /*===========================================================================* * do_exit * *===========================================================================*/ @@ -599,6 +784,7 @@ PUBLIC void do_exit(message *m_ptr) pid_t exit_pid; int exit_status, r, slot_nr; endpoint_t ep; + clock_t now = m_ptr->NOTIFY_TIMESTAMP; if(rs_verbose) printf("RS: got SIGCHLD signal, doing wait to get exited child.\n"); @@ -682,6 +868,9 @@ PUBLIC void do_exit(message *m_ptr) } } else if(rp->r_flags & RS_REFRESHING) { + short is_updating = rp->r_flags & RS_UPDATING; + + /* Refresh */ rp->r_restarts = -1; /* reset counter */ if (rp->r_script[0] != '\0') run_script(rp); @@ -690,6 +879,12 @@ PUBLIC void do_exit(message *m_ptr) if(m_ptr) m_ptr->RS_ENDPOINT = ep; } + + /* If updating, end the update process. */ + if(is_updating) { + end_update(now); + printf("RS: update succeeded\n"); + } } else { /* Determine what to do. If this is the first unexpected @@ -749,9 +944,16 @@ message *m_ptr; int s; endpoint_t ep; - /* Search system services table. Only check slots that are in use. */ + /* If an update is in progress, check its status. */ + if(rupdate.flags & RS_UPDATING) { + update_period(m_ptr); + } + + /* Search system services table. Only check slots that are in use and not + * updating. + */ for (rp=BEG_RPROC_ADDR; rpr_flags & RS_IN_USE) { + if ((rp->r_flags & RS_IN_USE) && !(rp->r_flags & RS_UPDATING)) { /* If the service is to be revived (because it repeatedly exited, * and was not directly restarted), the binary backoff field is @@ -946,6 +1148,15 @@ endpoint_t *endpoint; } } + /* Set and synch the privilege structure for the new service. */ + if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_SET_SYS, &rp->r_priv)) != OK + || (s = sys_getpriv(&rp->r_priv, child_proc_nr_e)) != OK) { + report("RS","unable to set privileges", s); + kill(child_pid, SIGKILL); /* kill the service */ + rp->r_flags |= RS_EXITING; /* expect exit */ + return(s); /* return error */ + } + /* If PCI properties are set, inform the PCI driver about the new service. */ if(rp->r_nr_pci_id || rp->r_nr_pci_class) { init_pci(rp, child_proc_nr_e); @@ -969,6 +1180,22 @@ endpoint_t *endpoint; if (s != OK) { printf("RS: warning: publish_service failed: %d\n", s); } + + /* Allow the service to run. + * XXX FIXME: we should let the service run only after publishing information + * about the new system service, but this is not currently possible due to + * the blocking nature of mapdriver() that expects the service to be running. + * The current solution is not race-free. This hack can go once service + * publishing is made fully asynchronous in RS. + */ + if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_ALLOW, NULL)) != OK) { + report("RS","unable to allow the service to run", s); + kill(child_pid, SIGKILL); /* kill the service */ + rp->r_flags |= RS_EXITING; /* expect exit */ + return(s); /* return error */ + } + + /* Map the new service. */ if (rp->r_dev_nr > 0) { /* set driver map */ if ((s=mapdriver5(rp->r_label, strlen(rp->r_label), rp->r_dev_nr, rp->r_dev_style, !!use_copy /* force */)) < 0) { @@ -976,17 +1203,6 @@ endpoint_t *endpoint; } } - /* Set the privilege structure for the child process. - * That will also cause the child process to start running. - * This call should succeed: we tested number in use above. - */ - if ((s = set_privs(child_proc_nr_e, &rp->r_priv, SYS_PRIV_SET_SYS)) != OK) { - report("RS","set_privs failed", s); - kill(child_pid, SIGKILL); /* kill the service */ - rp->r_flags |= RS_EXITING; /* expect exit */ - return(s); /* return error */ - } - if(rs_verbose) printf("RS: started '%s', major %d, pid %d, endpoint %d, proc %d\n", rp->r_cmd, rp->r_dev_nr, child_pid, @@ -1171,12 +1387,15 @@ struct rproc *rp; rp->r_script, strerror(errno)); exit(1); default: - /* Set the privilege structure for the child process and let it - * run. - */ + /* Set the privilege structure for the child process. */ proc_nr_e = getnprocnr(pid); - if ((r= set_privs(proc_nr_e, NULL, SYS_PRIV_SET_USER)) != OK) { - printf("RS: run_script: set_privs call failed: %d\n",r); + if ((r = sys_privctl(proc_nr_e, SYS_PRIV_SET_USER, NULL)) + != OK) { + printf("RS: run_script: can't set privileges: %d\n",r); + } + /* Allow the process to run. */ + if ((r = sys_privctl(proc_nr_e, SYS_PRIV_ALLOW, NULL)) != OK) { + printf("RS: run_script: process can't run: %d\n",r); } /* Do not wait for the child */ break; @@ -1408,36 +1627,6 @@ struct priv *privp; } } -/*===========================================================================* - * set_privs * - *===========================================================================*/ -PRIVATE int set_privs(endpoint, privp, req) -endpoint_t endpoint; -struct priv *privp; -int req; -{ - int r; - - /* Set the privilege structure. */ - if ((r = sys_privctl(endpoint, req, privp)) != OK) { - return r; - } - - /* Synch the privilege structure with the kernel for system services. */ - if(req == SYS_PRIV_SET_SYS) { - if ((r = sys_getpriv(privp, endpoint)) != OK) { - return r; - } - } - - /* Allow the process to run. */ - if ((r = sys_privctl(endpoint, SYS_PRIV_ALLOW, NULL)) != OK) { - return r; - } - - return(OK); -} - /*===========================================================================* * init_pci * *===========================================================================*/ diff --git a/servers/rs/manager.h b/servers/rs/manager.h deleted file mode 100644 index 2c21e6e76..000000000 --- a/servers/rs/manager.h +++ /dev/null @@ -1,96 +0,0 @@ -/* This table has one slot per system process. It contains information for - * servers and driver needed by the reincarnation server to keep track of - * each process' status. - */ - -/* Space reserved for program and arguments. */ -#define MAX_COMMAND_LEN 512 /* maximum argument string length */ -#define MAX_LABEL_LEN 16 /* Unique name of (this instance of) - * the driver - */ -#define MAX_SCRIPT_LEN 256 /* maximum restart script name length */ -#define MAX_NR_ARGS 4 /* maximum number of arguments */ -#define MAX_RESCUE_DIR_LEN 64 /* maximum rescue dir length */ - -#define MAX_IPC_LIST 256 /* Max size of list for IPC target - * process names - */ -#define MAX_VM_LIST 256 - -/* Definition of the system process table. This table only has entries for - * the servers and drivers, and thus is not directly indexed by slot number. - */ -extern struct rproc { - int r_proc_nr_e; /* process endpoint number */ - pid_t r_pid; /* process id, -1 if the process is not there */ - dev_t r_dev_nr; /* major device number */ - int r_dev_style; /* device style */ - - int r_restarts; /* number of restarts (initially zero) */ - long r_backoff; /* number of periods to wait before revive */ - unsigned r_flags; /* status and policy flags */ - - long r_period; /* heartbeat period (or zero) */ - clock_t r_check_tm; /* timestamp of last check */ - clock_t r_alive_tm; /* timestamp of last heartbeat */ - clock_t r_stop_tm; /* timestamp of SIGTERM signal */ - endpoint_t r_caller; /* RS_LATEREPLY caller */ - - char *r_exec; /* Executable image */ - size_t r_exec_len; /* Length of image */ - - char r_label[MAX_LABEL_LEN]; /* unique name of this driver */ - char r_cmd[MAX_COMMAND_LEN]; /* raw command plus arguments */ - char r_script[MAX_SCRIPT_LEN]; /* name of the restart script executable */ - char *r_argv[MAX_NR_ARGS+2]; /* parsed arguments vector */ - int r_argc; /* number of arguments */ - - /* Resources */ - int r_set_resources; - struct priv r_priv; /* Privilege structure to be passed to the - * kernel. - */ - uid_t r_uid; - int r_nice; - int r_nr_pci_id; /* Number of PCI devices IDs */ - struct { u16_t vid; u16_t did; } r_pci_id[RSS_NR_PCI_ID]; - int r_nr_pci_class; /* Number of PCI class IDs */ - struct { u32_t class; u32_t mask; } r_pci_class[RSS_NR_PCI_CLASS]; - - u32_t r_call_mask[RSS_NR_SYSTEM]; - char r_ipc_list[MAX_IPC_LIST]; - bitchunk_t r_vm[RSS_VM_CALL_SIZE]; - int r_nr_control; - char r_control[RSS_NR_CONTROL][MAX_LABEL_LEN]; -} rproc[NR_SYS_PROCS]; - -/* Mapping for fast access to the system process table. */ -extern struct rproc *rproc_ptr[NR_PROCS]; - -/* Pipe for detection of exec failures. The pipe is close-on-exec, and - * no data will be written to the pipe if the exec succeeds. After an - * exec failure, the slot number is written to the pipe. After each exit, - * a non-blocking read retrieves the slot number from the pipe. - */ -int exec_pipe[2]; - -/* Flag values. */ -#define RS_IN_USE 0x001 /* set when process slot is in use */ -#define RS_EXITING 0x004 /* set when exit is expected */ -#define RS_REFRESHING 0x008 /* set when refresh must be done */ -#define RS_NOPINGREPLY 0x010 /* driver failed to reply to a ping request */ -#define RS_KILLED 0x020 /* driver is killed */ -#define RS_CRASHED 0x040 /* driver crashed */ -#define RS_LATEREPLY 0x080 /* no reply sent to RS_DOWN caller yet */ -#define RS_SIGNALED 0x100 /* driver crashed */ - -/* Constants determining RS period and binary exponential backoff. */ -#define RS_DELTA_T 60 /* check every T ticks */ -#define BACKOFF_BITS (sizeof(long)*8) /* bits in backoff field */ -#define MAX_BACKOFF 30 /* max backoff in RS_DELTA_T */ - -/* Magic process table addresses. */ -#define BEG_RPROC_ADDR (&rproc[0]) -#define END_RPROC_ADDR (&rproc[NR_SYS_PROCS]) -#define NIL_RPROC ((struct mproc *) 0) - diff --git a/servers/rs/proto.h b/servers/rs/proto.h index 4372f0ed0..7bccb85ae 100644 --- a/servers/rs/proto.h +++ b/servers/rs/proto.h @@ -18,6 +18,8 @@ _PROTOTYPE( int do_restart, (message *m)); _PROTOTYPE( int do_lookup, (message *m)); _PROTOTYPE( int do_shutdown, (message *m)); _PROTOTYPE( void do_period, (message *m)); +_PROTOTYPE( int do_update, (message *m)); +_PROTOTYPE( int do_upd_ready, (message *m)); _PROTOTYPE( void do_exit, (message *m)); _PROTOTYPE( int do_getsysinfo, (message *m)); diff --git a/servers/rs/service.c b/servers/rs/service.c index f1ed0114d..e8aa3f082 100644 --- a/servers/rs/service.c +++ b/servers/rs/service.c @@ -2,7 +2,8 @@ * reincarnation server that does the actual work. * * Changes: - * Jul 22, 2005: Created (Jorrit N. Herder) + * Nov 22, 2009: added basic live update support (Cristiano Giuffrida) + * Jul 22, 2005: Created (Jorrit N. Herder) */ #include @@ -36,6 +37,7 @@ PRIVATE char *known_requests[] = { "refresh", "restart", "shutdown", + "update", "catch for illegal requests" }; #define ILLEGAL_REQUEST sizeof(known_requests)/sizeof(char *) @@ -57,6 +59,8 @@ PRIVATE char *known_requests[] = { #define ARG_REQUEST 0 /* request to perform */ #define ARG_PATH 1 /* rescue dir or system service */ #define ARG_LABEL 1 /* name of system service */ +#define ARG_LU_STATE 2 /* the state required to update */ +#define ARG_PREPARE_MAXTIME 3 /* max time to prepare for the update */ #define MIN_ARG_COUNT 1 /* require an action */ @@ -92,6 +96,8 @@ PRIVATE char *req_ipc; PRIVATE char *req_config = PATH_CONFIG; PRIVATE int req_printep; PRIVATE int class_recurs; /* Nesting level of class statements */ +PRIVATE int req_lu_state; +PRIVATE int req_prepare_maxtime; /* Buffer to build "/command arg1 arg2 ..." string to pass to RS server. */ PRIVATE char command[4096]; @@ -111,6 +117,7 @@ PRIVATE void print_usage(char *app_name, char *problem) fprintf(stderr, " %s down label\n", app_name); fprintf(stderr, " %s refresh label\n", app_name); fprintf(stderr, " %s restart label\n", app_name); + fprintf(stderr, " %s update label state maxtime\n", app_name); fprintf(stderr, " %s rescue \n", app_name); fprintf(stderr, " %s shutdown\n", app_name); fprintf(stderr, "\n"); @@ -131,7 +138,7 @@ PRIVATE void failure(int num) PRIVATE int parse_arguments(int argc, char **argv) { struct stat stat_buf; - char *hz; + char *hz, *buff; int req_nr; int c, i; int c_flag, r_flag; @@ -294,6 +301,43 @@ PRIVATE int parse_arguments(int argc, char **argv) else if (req_nr == RS_SHUTDOWN) { /* no extra arguments required */ } + else if (req_nr == RS_UPDATE) { + /* Check for mandatory arguments */ + if (argc - 1 < optind+ARG_LU_STATE) { + print_usage(argv[ARG_NAME], + "action requires at least a label and a live update state"); + exit(EINVAL); + } + + /* Label. */ + req_label= argv[optind+ARG_LABEL]; + + /* Live update state. */ + errno=0; + req_lu_state=strtol(argv[optind+ARG_LU_STATE], &buff, 10); + if(errno || strcmp(buff, "")) { + print_usage(argv[ARG_NAME], + "action requires a correct live update state"); + exit(EINVAL); + } + if(req_lu_state == SEF_LU_STATE_NULL) { + print_usage(argv[ARG_NAME], + "action requires a non-null live update state."); + exit(EINVAL); + } + + /* Prepare max time. */ + req_prepare_maxtime=0; + if (argc - 1 >= optind+ARG_PREPARE_MAXTIME) { + req_prepare_maxtime=strtol(argv[optind+ARG_PREPARE_MAXTIME], + &buff, 10); + if(errno || strcmp(buff, "") || req_prepare_maxtime<0) { + print_usage(argv[ARG_NAME], + "action requires a correct max time to prepare for the update"); + exit(EINVAL); + } + } + } /* Return the request number if no error were found. */ return(req_nr); @@ -1115,6 +1159,14 @@ PUBLIC int main(int argc, char **argv) if (OK != (s=_taskcall(RS_PROC_NR, request, &m))) failure(-s); break; + case RS_UPDATE: + m.RS_CMD_ADDR = req_label; + m.RS_CMD_LEN = strlen(req_label); + m.RS_LU_STATE = req_lu_state; + m.RS_LU_PREPARE_MAXTIME = req_prepare_maxtime; + if (OK != (s=_taskcall(RS_PROC_NR, request, &m))) + failure(-s); + break; default: print_usage(argv[ARG_NAME], "request is not yet supported"); result = EGENERIC; diff --git a/servers/rs/type.h b/servers/rs/type.h index 4d1bd5ee0..473bd511b 100644 --- a/servers/rs/type.h +++ b/servers/rs/type.h @@ -75,4 +75,12 @@ struct rproc { char r_control[RSS_NR_CONTROL][MAX_LABEL_LEN]; }; +/* Definition of the global update descriptor. */ +struct rupdate { + int flags; /* flags to keep track of the status of the update */ + clock_t prepare_tm; /* timestamp of when the update was scheduled */ + clock_t prepare_maxtime; /* max time to wait for the process to be ready */ + struct rproc *rp; /* the process under update */ +}; + #endif /* RS_TYPE_H */ diff --git a/servers/vfs/main.c b/servers/vfs/main.c index ba47955b5..983019a6d 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -44,6 +44,8 @@ FORWARD _PROTOTYPE( void get_work, (void) ); FORWARD _PROTOTYPE( void init_root, (void) ); FORWARD _PROTOTYPE( void service_pm, (void) ); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); /*===========================================================================* * main * @@ -56,6 +58,9 @@ PUBLIC int main(void) */ int error; + /* SEF local startup. */ + sef_local_startup(); + fs_init(); SANITYCHECK; @@ -223,6 +228,17 @@ PUBLIC int main(void) return(OK); /* shouldn't come here */ } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + /*===========================================================================* * get_work * *===========================================================================*/ @@ -282,8 +298,8 @@ PRIVATE void get_work() for(;;) { int r; /* Normal case. No one to revive. */ - if ((r=receive(ANY, &m_in)) != OK) - panic(__FILE__,"fs receive error", r); + if ((r=sef_receive(ANY, &m_in)) != OK) + panic(__FILE__,"fs sef_receive error", r); who_e = m_in.m_source; who_p = _ENDPOINT_P(who_e); @@ -358,7 +374,7 @@ PRIVATE void fs_init() * Then, stop and synchronize with the PM. */ do { - if (OK != (s=receive(PM_PROC_NR, &mess))) + if (OK != (s=sef_receive(PM_PROC_NR, &mess))) panic(__FILE__,"FS couldn't receive from PM", s); if (NONE == mess.PR_ENDPT) break; @@ -434,7 +450,7 @@ PRIVATE void init_root() /* Wait FS login message */ if (last_login_fs_e != ROOT_FS_E) { /* Wait FS login message */ - if (receive(ROOT_FS_E, &m) != OK) { + if (sef_receive(ROOT_FS_E, &m) != OK) { printf("VFS: Error receiving login request from FS_e %d\n", ROOT_FS_E); panic(__FILE__, "Error receiving login request from root filesystem\n", ROOT_FS_E); diff --git a/servers/vfs/request.c b/servers/vfs/request.c index c28e42d6e..9b6882ffb 100644 --- a/servers/vfs/request.c +++ b/servers/vfs/request.c @@ -1097,7 +1097,7 @@ PRIVATE int fs_sendrec_f(char *file, int line, endpoint_t fs_e, message *reqm) for (;;) { new_driver_e = 0; printf("VFSdead_driver: waiting for new driver\n"); - r = receive(RS_PROC_NR, &m); + r = sef_receive(RS_PROC_NR, &m); if (r != OK) { panic(__FILE__, "VFSdead_driver: unable to receive from RS", r); diff --git a/servers/vm/main.c b/servers/vm/main.c index d270a6b06..a568529da 100644 --- a/servers/vm/main.c +++ b/servers/vm/main.c @@ -67,6 +67,8 @@ struct { FORWARD _PROTOTYPE(void vm_init, (void)); FORWARD _PROTOTYPE(int vm_acl_ok, (endpoint_t caller, int call)); +/* SEF functions and variables. */ +FORWARD _PROTOTYPE( void sef_local_startup, (void) ); /*===========================================================================* * main * @@ -76,6 +78,9 @@ PUBLIC int main(void) message msg; int result, who_e; + /* SEF local startup. */ + sef_local_startup(); + #if SANITYCHECKS incheck = nocheck = 0; FIXME("VM SANITYCHECKS are on"); @@ -99,8 +104,8 @@ PUBLIC int main(void) } SANITYCHECK(SCL_DETAIL); - if ((r=receive(ANY, &msg)) != OK) - vm_panic("receive() error", r); + if ((r=sef_receive(ANY, &msg)) != OK) + vm_panic("sef_receive() error", r); SANITYCHECK(SCL_DETAIL); @@ -161,6 +166,17 @@ PUBLIC int main(void) return(OK); } +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +PRIVATE void sef_local_startup() +{ + /* No live update support for now. */ + + /* Let SEF perform startup. */ + sef_startup(); +} + extern int unmap_ok; /*===========================================================================*