436d6012a3
-Move libdriver to lib/ -Install all boot image services on filesystem to aid restartability
214 lines
5.1 KiB
C
214 lines
5.1 KiB
C
#include <minix/drivers.h>
|
|
#include <minix/driver.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <minix/ds.h>
|
|
#include "hello.h"
|
|
|
|
/*
|
|
* Function prototypes for the hello driver.
|
|
*/
|
|
FORWARD _PROTOTYPE( char * hello_name, (void) );
|
|
FORWARD _PROTOTYPE( int hello_open, (struct driver *d, message *m) );
|
|
FORWARD _PROTOTYPE( int hello_close, (struct driver *d, message *m) );
|
|
FORWARD _PROTOTYPE( struct device * hello_prepare, (int device) );
|
|
FORWARD _PROTOTYPE( int hello_transfer, (int procnr, int opcode,
|
|
u64_t position, iovec_t *iov,
|
|
unsigned nr_req) );
|
|
FORWARD _PROTOTYPE( void hello_geometry, (struct partition *entry) );
|
|
|
|
/* SEF functions and variables. */
|
|
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
|
FORWARD _PROTOTYPE( int sef_cb_init, (int type, sef_init_info_t *info) );
|
|
FORWARD _PROTOTYPE( int sef_cb_lu_state_save, (int) );
|
|
FORWARD _PROTOTYPE( int lu_state_restore, (void) );
|
|
|
|
/* Entry points to the hello driver. */
|
|
PRIVATE struct driver hello_tab =
|
|
{
|
|
hello_name,
|
|
hello_open,
|
|
hello_close,
|
|
nop_ioctl,
|
|
hello_prepare,
|
|
hello_transfer,
|
|
nop_cleanup,
|
|
hello_geometry,
|
|
nop_alarm,
|
|
nop_cancel,
|
|
nop_select,
|
|
nop_ioctl,
|
|
do_nop,
|
|
};
|
|
|
|
/** Represents the /dev/hello device. */
|
|
PRIVATE struct device hello_device;
|
|
|
|
/** State variable to count the number of times the device has been opened. */
|
|
PRIVATE int open_counter;
|
|
|
|
PRIVATE char * hello_name(void)
|
|
{
|
|
printf("hello_name()\n");
|
|
return "hello";
|
|
}
|
|
|
|
PRIVATE int hello_open(d, m)
|
|
struct driver *d;
|
|
message *m;
|
|
{
|
|
printf("hello_open(). Called %d time(s).\n", ++open_counter);
|
|
return OK;
|
|
}
|
|
|
|
PRIVATE int hello_close(d, m)
|
|
struct driver *d;
|
|
message *m;
|
|
{
|
|
printf("hello_close()\n");
|
|
return OK;
|
|
}
|
|
|
|
PRIVATE struct device * hello_prepare(dev)
|
|
int dev;
|
|
{
|
|
hello_device.dv_base.lo = 0;
|
|
hello_device.dv_base.hi = 0;
|
|
hello_device.dv_size.lo = strlen(HELLO_MESSAGE);
|
|
hello_device.dv_size.hi = 0;
|
|
return &hello_device;
|
|
}
|
|
|
|
PRIVATE int hello_transfer(proc_nr, opcode, position, iov, nr_req)
|
|
int proc_nr;
|
|
int opcode;
|
|
u64_t position;
|
|
iovec_t *iov;
|
|
unsigned nr_req;
|
|
{
|
|
int bytes, ret;
|
|
|
|
printf("hello_transfer()\n");
|
|
|
|
bytes = strlen(HELLO_MESSAGE) - position.lo < iov->iov_size ?
|
|
strlen(HELLO_MESSAGE) - position.lo : iov->iov_size;
|
|
|
|
if (bytes <= 0)
|
|
{
|
|
return OK;
|
|
}
|
|
switch (opcode)
|
|
{
|
|
case DEV_GATHER_S:
|
|
ret = sys_safecopyto(proc_nr, iov->iov_addr, 0,
|
|
(vir_bytes) (HELLO_MESSAGE + position.lo),
|
|
bytes, D);
|
|
iov->iov_size -= bytes;
|
|
break;
|
|
|
|
default:
|
|
return EINVAL;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
PRIVATE void hello_geometry(entry)
|
|
struct partition *entry;
|
|
{
|
|
printf("hello_geometry()\n");
|
|
entry->cylinders = 0;
|
|
entry->heads = 0;
|
|
entry->sectors = 0;
|
|
}
|
|
|
|
PRIVATE int sef_cb_lu_state_save(int state) {
|
|
/* Save the state. */
|
|
ds_publish_u32("open_counter", open_counter, DSF_OVERWRITE);
|
|
|
|
return OK;
|
|
}
|
|
|
|
PRIVATE int lu_state_restore() {
|
|
/* Restore the state. */
|
|
u32_t value;
|
|
|
|
ds_retrieve_u32("open_counter", &value);
|
|
ds_delete_u32("open_counter");
|
|
open_counter = (int) value;
|
|
|
|
return OK;
|
|
}
|
|
|
|
PRIVATE void sef_local_startup()
|
|
{
|
|
/*
|
|
* Register init callbacks. Use the same function for all event types
|
|
*/
|
|
sef_setcb_init_fresh(sef_cb_init);
|
|
sef_setcb_init_lu(sef_cb_init);
|
|
sef_setcb_init_restart(sef_cb_init);
|
|
|
|
/*
|
|
* Register live update callbacks.
|
|
*/
|
|
/* - Agree to update immediately when LU is requested in a valid state. */
|
|
sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
|
|
/* - Support live update starting from any standard state. */
|
|
sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
|
|
/* - Register a custom routine to save the state. */
|
|
sef_setcb_lu_state_save(sef_cb_lu_state_save);
|
|
|
|
/* Let SEF perform startup. */
|
|
sef_startup();
|
|
}
|
|
|
|
PRIVATE int sef_cb_init(int type, sef_init_info_t *info)
|
|
{
|
|
/* Initialize the hello driver. */
|
|
int do_mapdriver = TRUE;
|
|
|
|
open_counter = 0;
|
|
switch(type) {
|
|
case SEF_INIT_FRESH:
|
|
printf("%s", HELLO_MESSAGE);
|
|
break;
|
|
|
|
case SEF_INIT_LU:
|
|
/* Restore the state. */
|
|
lu_state_restore();
|
|
do_mapdriver = FALSE;
|
|
|
|
printf("%sHey, I'm a new version!\n", HELLO_MESSAGE);
|
|
break;
|
|
|
|
case SEF_INIT_RESTART:
|
|
printf("%sHey, I've just been restarted!\n", HELLO_MESSAGE);
|
|
break;
|
|
}
|
|
|
|
/* Map major number to our process. */
|
|
if (do_mapdriver && mapdriver("hello", HELLO_MAJOR, STYLE_DEV, TRUE) != OK)
|
|
{
|
|
printf("hello: mapdriver() failed: %s\n",
|
|
strerror(errno));
|
|
return EINVAL;
|
|
}
|
|
|
|
/* Initialization completed successfully. */
|
|
return OK;
|
|
}
|
|
|
|
PUBLIC int main(int argc, char **argv)
|
|
{
|
|
/*
|
|
* Perform initialization.
|
|
*/
|
|
sef_local_startup();
|
|
|
|
/*
|
|
* Run the main loop.
|
|
*/
|
|
driver_task(&hello_tab, DRIVER_STD);
|
|
return OK;
|
|
}
|
|
|