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();
{
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);
}
}
+/*===========================================================================*
+ * 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;
LDFLAGS = -i -L../libdriver
LIBS = -ldriver -lsys -ltimers
-OBJ = at_wini.o
+OBJ = at_wini.o liveupdate.o
# build local binary
#include <ibm/pci.h>
#include <sys/mman.h>
-#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 {
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,
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.
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 */
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();
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 *
*===========================================================================*/
*/
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:
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
panic(w_name(), "sys_in failed", NO_NUM);
}
+
#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"
+
--- /dev/null
+#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)));
+}
+
# 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
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
$(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
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
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;
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);
}
}
+/*===========================================================================*
+ * 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;
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 */
}
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;
}
--- /dev/null
+#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));
+}
+
# 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
NULL /* leftover hardware interrupts */
};
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
+
/*===========================================================================*
* bios_winchester_task *
*===========================================================================*/
{
long v;
+ /* SEF local startup. */
+ sef_local_startup();
+
v= 0;
env_parse("bios_remap_first", "d", 0, &v, 0, 1);
remap_first= v;
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 *
*===========================================================================*/
return EINVAL;
}
+
return r;
}
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
+
/*===========================================================================*
* dpeth_task *
*===========================================================================*/
dpeth_t *dep;
long v;
+ /* SEF local startup. */
+ sef_local_startup();
+
system_hz = sys_hz();
if (argc < 1)
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;
}
}
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* No live update support for now. */
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
#if 0
/*===========================================================================*
* dp8390_dump *
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";
}
}
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
+
/*
** Name: int dpeth_task(void)
** Function: Main entry for dp task
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);
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));
/* 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();
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 **/
_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 *
*===========================================================================*/
e1000_t *e;
long v;
+ /* SEF local startup. */
+ sef_local_startup();
+
/* Verify command-line arguments. */
if (argc < 1)
{
*/
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;
}
}
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* No live update support for now. */
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
/*===========================================================================*
* e1000_init *
*===========================================================================*/
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)) {
exit(0);
}
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
+
/*===========================================================================*
* main *
*===========================================================================*/
message m_out;
int r;
+ /* SEF local startup. */
+ sef_local_startup();
+
r = parse_arguments(argc, argv);
if(r != OK) {
printf("Filter: wrong argument!\n");
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
return 0;
}
+
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* No live update support for now. */
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
LDFLAGS = -i -L../libdriver
LIBS = -ldriver -lsys -ltimers
-OBJ = floppy.o
+OBJ = floppy.o liveupdate.o
# build local binary
all build: $(DRIVER)
#include <minix/sysutil.h>
#include <minix/syslib.h>
#include <minix/endpoint.h>
+#include <stdio.h>
/* I/O Ports used by floppy disk task. */
#define DOR 0x3F2 /* motor drive control bits */
} 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 */
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,
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 *
*===========================================================================*/
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);
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;
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;
* 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;
/* 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;
entry->sectors = f_sectors;
}
+
_PROTOTYPE(void main, (void));
+
--- /dev/null
+#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)));
+}
+
}
}
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
+
/*===========================================================================*
* main *
*===========================================================================*/
long v;
vir_bytes ft = sizeof(*fxp_table)*FXP_PORT_NR;
+ /* SEF local startup. */
+ sef_local_startup();
+
system_hz = sys_hz();
if (argc < 1)
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;
}
}
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* No live update support for now. */
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
/*===========================================================================*
* fxp_init *
*===========================================================================*/
static char *progname;
phys_bytes lance_buf_phys;
-
+
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
+
/*===========================================================================*
* main *
*===========================================================================*/
int fkeys, sfkeys;
#endif
+ /* SEF local startup. */
+ sef_local_startup();
+
(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
env_setargs( argc, 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;i<EC_PORT_NR_MAX;++i)
{
ec= &ec_table[i];
if (is_notify(m.m_type)) {
switch(_ENDPOINT_P(m.m_source)) {
- case RS_PROC_NR:
- notify(m.m_source);
- break;
case TTY_PROC_NR:
lance_dump();
break;
}
}
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* No live update support for now. */
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
/*===========================================================================*
* lance_dump *
*===========================================================================*/
} else {
int s;
/* Wait for a request to read or write a disk block. */
- if ((s=receive(ANY, &mess)) != OK)
- panic((*dp->dr_name)(),"receive() failed", s);
+ if ((s=sef_receive(ANY, &mess)) != OK)
+ panic((*dp->dr_name)(),"sef_receive() failed", s);
}
device_caller = mess.m_source;
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);
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)
--- /dev/null
+#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));
+}
+
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);
}
/*===========================================================================*
- * 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()
{
return(ready_ops);
}
+
#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 *
*===========================================================================*/
/* 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;
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 *
*===========================================================================*/
entry->heads = 64;
entry->sectors = 32;
}
+
boot
-175 400
+200 400
d--755 0 0
bin d--755 0 0
at_wini ---755 0 0 at_wini
static char *progname;
extern int errno;
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
+
/*****************************************************************************
* main *
* *
long v = 0;
t_or *orp;
+ /* SEF local startup. */
+ sef_local_startup();
+
system_hz = sys_hz();
(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
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;
}
}
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* No live update support for now. */
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
/*****************************************************************************
* check_int_events *
* *
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;
}
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;
{
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)
--- /dev/null
+#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));
+}
+
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 */
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 *
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);
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;
}
}
+/*===========================================================================*
+ * 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 *
else { /* done! report back to FS */
status = orig_count;
}
+ is_status_msg_expected = TRUE;
revive_pending = TRUE;
revive_status = status;
notify(caller);
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 */
}
#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 *
*===========================================================================*/
#include <time.h>
#include <errno.h>
#include <signal.h>
+#include <minix/const.h>
#include <minix/type.h>
#include <minix/syslib.h>
#include <minix/com.h>
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;
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);
exit(0);
}
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
void errmsg(char *s)
{
static char *prompt = "readclock: ";
LDFLAGS = -i
LIBS = -lsys -ltimers
-OBJ = rtl8139.o
+OBJ = rtl8139.o liveupdate.o
# build local binary
all build: $(DRIVER)
--- /dev/null
+#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; i<RE_PORT_NR && !found_processing; i++) {
+ rep = &re_table[i];
+
+ if (rep->re_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));
+}
+
*
*/
-#include "../drivers.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <minix/com.h>
-#include <minix/ds.h>
-#include <minix/keymap.h>
-#include <minix/syslib.h>
-#include <minix/type.h>
-#include <minix/sysutil.h>
-#include <minix/endpoint.h>
-#include <timers.h>
-#include <net/hton.h>
-#include <net/gen/ether.h>
-#include <net/gen/eth_io.h>
-#include <ibm/pci.h>
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/ioc_memory.h>
-#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;
{ 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;
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 *
*===========================================================================*/
re_t *rep;
long v;
+ /* SEF local startup. */
+ sef_local_startup();
+
system_hz = sys_hz();
(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
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
}
}
+/*===========================================================================*
+ * 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 *
*===========================================================================*/
Created: Aug 2003 by Philip Homburg <philip@cs.vu.nl>
*/
+#include "../drivers.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+#include <minix/com.h>
+#include <minix/ds.h>
+#include <minix/keymap.h>
+#include <minix/syslib.h>
+#include <minix/type.h>
+#include <minix/sysutil.h>
+#include <minix/endpoint.h>
+#include <timers.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include <ibm/pci.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/ioc_memory.h>
+#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
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 $
*/
static char *progname;
u32_t system_hz;
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
+
/*===========================================================================*
* main *
*===========================================================================*/
re_t *rep;
long v;
+ /* SEF local startup. */
+ sef_local_startup();
+
system_hz = sys_hz();
(progname = strrchr(argv[0], '/')) ? progname++ : (progname = argv[0]);
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
}
}
+/*===========================================================================*
+ * 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;
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;
# 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)
#include <sys/ioc_sound.h>
#include <minix/sound.h>
-
#define SB_TIMEOUT 32000 /* timeout count */
/* IRQ, base address and DMA channels */
#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
int r, caller, proc_nr, s;
message mess;
+ /* SEF local startup. */
+ sef_local_startup();
+
dprint("sb16_dsp.c: main()\n");
/* Get a DMA buffer. */
while(TRUE) {
/* Wait for an incoming message */
- receive(ANY, &mess);
+ sef_receive(ANY, &mess);
caller = mess.m_source;
proc_nr = mess.IO_ENDPT;
}
+/*===========================================================================*
+ * 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
}
reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, SUSPEND);
+ is_processing = TRUE;
if(DmaBusy < 0) { /* Dma tranfer not yet started */
} 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);
}
+ is_status_msg_expected = TRUE;
revivePending = 1;
reviveStatus = DspFragmentSize;
reviveProcNr = m_ptr->IO_ENDPT;
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 */
--- /dev/null
+#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));
+}
+
#define dprint (void)
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (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;
}
}
+/*===========================================================================*
+ * 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
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)
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;
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 *
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);
}
/* 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.
/* run watchdogs of expired timers */
expire_timers();
break;
- case RS_PROC_NR:
- notify(tty_mess.m_source);
- break;
case HARDWARE:
/* hardware interrupt notification */
return 0;
}
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* No live update support for now. */
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
/*===========================================================================*
* do_status *
*===========================================================================*/
#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 */
#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 */
# 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 *
*===========================================================================*/
--- /dev/null
+/* 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 <stdio.h>
+#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 */
+
#endif
#include <minix/safecopies.h>
+#include <minix/sef.h>
/* Forward declaration */
struct reg86u;
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 \
--- /dev/null
+#include "syslib.h"
+#include <assert.h>
+#include <minix/sysutil.h>
+#include <stdio.h>
+
+/* 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;
+}
+
--- /dev/null
+#include "syslib.h"
+#include <assert.h>
+#include <minix/sysutil.h>
+
+/* 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);
+}
+
--- /dev/null
+#include "syslib.h"
+#include <assert.h>
+#include <minix/sysutil.h>
+
+/* 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);
+}
+
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 *
*===========================================================================*/
int result;
sigset_t sigset;
+ /* SEF local startup. */
+ sef_local_startup();
+
/* Initialize the server, then go to work. */
init_server(argc, argv);
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 *
*===========================================================================*/
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 */
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;
u8_t randbits[32];
struct timeval tv;
+ /* SEF local startup. */
+ sef_local_startup();
+
#if DEBUG
printf("Starting inet...\n");
printf("%s\n", version);
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));
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();
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)
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;
return -1;
}
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* No live update support for now. */
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
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);
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 *
*===========================================================================*/
int result;
sigset_t sigset;
+ /* SEF local startup. */
+ sef_local_startup();
+
/* Initialize the server, then go to work. */
init_server(argc, argv);
case TTY_PROC_NR:
result = do_fkey_pressed(&m_in);
break;
- case RS_PROC_NR:
- notify(m_in.m_source);
- continue;
}
}
else {
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 *
*===========================================================================*/
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 */
}
panic("IS", "unable to send reply!", send_status);
}
+
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 *
*===========================================================================*/
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) {
}
}
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* No live update support for now. */
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
/*===========================================================================*
* init_server *
*===========================================================================*/
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);
}
/*===========================================================================*
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 *
int error, ind;
message m;
+ /* SEF local startup. */
+ sef_local_startup();
+
/* Initialize the server, then go to work. */
init_server();
}
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* No live update support for now. */
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
/*===========================================================================*
* init_server *
*===========================================================================*/
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) {
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 *
*===========================================================================*/
int error, ind;
message m;
+ /* SEF local startup. */
+ sef_local_startup();
+
/* Initialize the server, then go to work. */
init_server();
return(OK);
}
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* No live update support for now. */
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
/*===========================================================================*
* init_server *
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) {
#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 *
*===========================================================================*/
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. */
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);
$(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)
#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
#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 */
*/
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;
/* Flag set when memory unmapping can be done. */
EXTERN int unmap_ok;
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
+
/*===========================================================================*
* main *
*===========================================================================*/
sigset_t sigset; /* system signal set */
int s;
+ /* SEF local startup. */
+ sef_local_startup();
+
/* Initialize the server, then go to work. */
init_server();
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)
*/
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;
}
}
- /* 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 {
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:
}
}
+/*===========================================================================*
+ * sef_local_startup *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+ /* No live update support for now. */
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
/*===========================================================================*
* exec_image_copy *
*===========================================================================*/
/* 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);
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);
}
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);
}
/*===========================================================================*
/*
* 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)
*/
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;
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; rp<END_RPROC_ADDR; rp++) {
+ if (rp->r_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 *
*===========================================================================*/
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");
}
}
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);
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
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; rp<END_RPROC_ADDR; rp++) {
- if (rp->r_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
}
}
+ /* 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);
if (s != OK) {
printf("RS: warning: publish_service failed: %d\n", s);
}
- 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) {
- report("RS", "couldn't map driver (continuing)", errno);
- }
- }
- /* 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.
+ /* 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 = set_privs(child_proc_nr_e, &rp->r_priv, SYS_PRIV_SET_SYS)) != OK) {
- report("RS","set_privs failed", s);
+ 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) {
+ report("RS", "couldn't map driver (continuing)", errno);
+ }
+ }
+
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,
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;
}
}
-/*===========================================================================*
- * 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 *
*===========================================================================*/
+++ /dev/null
-/* 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)
-
_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));
* 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 <stdarg.h>
"refresh",
"restart",
"shutdown",
+ "update",
"catch for illegal requests"
};
#define ILLEGAL_REQUEST sizeof(known_requests)/sizeof(char *)
#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 */
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];
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 <dir>\n", app_name);
fprintf(stderr, " %s shutdown\n", app_name);
fprintf(stderr, "\n");
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;
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);
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;
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 */
FORWARD _PROTOTYPE( void init_root, (void) );
FORWARD _PROTOTYPE( void service_pm, (void) );
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
/*===========================================================================*
* main *
*/
int error;
+ /* SEF local startup. */
+ sef_local_startup();
+
fs_init();
SANITYCHECK;
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 *
*===========================================================================*/
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);
* 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;
/* 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);
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);
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 *
message msg;
int result, who_e;
+ /* SEF local startup. */
+ sef_local_startup();
+
#if SANITYCHECKS
incheck = nocheck = 0;
FIXME("VM SANITYCHECKS are on");
}
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);
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;
/*===========================================================================*