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; /*===========================================================================*