2005-07-29 12:21:04 +02:00
|
|
|
/* This file contains the "device dependent" part of a hard disk driver that
|
|
|
|
* uses the ROM BIOS. It makes a call and just waits for the transfer to
|
|
|
|
* happen. It is not interrupt driven and thus will (*) have poor performance.
|
|
|
|
* The advantage is that it should work on virtually any PC, XT, 386, PS/2
|
|
|
|
* or clone. The demo disk uses this driver. It is suggested that all
|
|
|
|
* MINIX users try the other drivers, and use this one only as a last resort,
|
|
|
|
* if all else fails.
|
|
|
|
*
|
|
|
|
* (*) The performance is within 10% of the AT driver for reads on any disk
|
|
|
|
* and writes on a 2:1 interleaved disk, it will be DMA_BUF_SIZE bytes
|
|
|
|
* per revolution for a minimum of 60 kb/s for writes to 1:1 disks.
|
|
|
|
*
|
|
|
|
* The file contains one entry point:
|
|
|
|
*
|
|
|
|
* bios_winchester_task: main entry when system is brought up
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Changes:
|
|
|
|
* 30 Apr 1992 by Kees J. Bot: device dependent/independent split.
|
|
|
|
* 14 May 2000 by Kees J. Bot: d-d/i rewrite.
|
|
|
|
*/
|
|
|
|
|
2010-03-22 22:25:22 +01:00
|
|
|
#include <minix/drivers.h>
|
|
|
|
#include <minix/driver.h>
|
|
|
|
#include <minix/drvlib.h>
|
2005-07-29 12:21:04 +02:00
|
|
|
#include <minix/sysutil.h>
|
2006-06-20 10:52:26 +02:00
|
|
|
#include <minix/safecopies.h>
|
2005-07-29 12:21:04 +02:00
|
|
|
#include <sys/ioc_disk.h>
|
2010-03-08 12:04:59 +01:00
|
|
|
#include <machine/int86.h>
|
2005-07-29 12:21:04 +02:00
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#define ME "BIOS_WINI"
|
|
|
|
|
|
|
|
/* Parameters for the disk drive. */
|
2005-08-15 15:19:02 +02:00
|
|
|
#define MAX_DRIVES 8 /* this driver supports 8 drives (d0 - d7)*/
|
2005-08-04 11:26:36 +02:00
|
|
|
#define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE)
|
2005-07-29 12:21:04 +02:00
|
|
|
#define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS)
|
|
|
|
#define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE)
|
|
|
|
|
|
|
|
/* Variables. */
|
|
|
|
PRIVATE struct wini { /* main drive struct, one entry per drive */
|
|
|
|
unsigned cylinders; /* number of cylinders */
|
|
|
|
unsigned heads; /* number of heads */
|
|
|
|
unsigned sectors; /* number of sectors per track */
|
|
|
|
unsigned open_ct; /* in-use count */
|
2005-08-15 15:19:02 +02:00
|
|
|
int drive_id; /* Drive ID at BIOS level */
|
|
|
|
int present; /* Valid drive */
|
2005-07-29 12:21:04 +02:00
|
|
|
int int13ext; /* IBM/MS INT 13 extensions supported? */
|
|
|
|
struct device part[DEV_PER_DRIVE]; /* disks and partitions */
|
|
|
|
struct device subpart[SUB_PER_DRIVE]; /* subpartitions */
|
|
|
|
} wini[MAX_DRIVES], *w_wn;
|
|
|
|
|
|
|
|
PRIVATE int w_drive; /* selected drive */
|
|
|
|
PRIVATE struct device *w_dv; /* device's base and size */
|
2009-09-21 16:25:54 +02:00
|
|
|
PRIVATE char *bios_buf_v;
|
2005-07-29 12:21:04 +02:00
|
|
|
PRIVATE phys_bytes bios_buf_phys;
|
2005-08-15 15:19:02 +02:00
|
|
|
PRIVATE int remap_first = 0; /* Remap drives for CD HD emulation */
|
2009-09-21 16:25:54 +02:00
|
|
|
#define BIOSBUF 16384
|
2005-07-29 12:21:04 +02:00
|
|
|
|
|
|
|
_PROTOTYPE(int main, (void) );
|
|
|
|
FORWARD _PROTOTYPE( struct device *w_prepare, (int device) );
|
|
|
|
FORWARD _PROTOTYPE( char *w_name, (void) );
|
2006-11-27 15:21:43 +01:00
|
|
|
FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, u64_t position,
|
2009-12-02 10:57:48 +01:00
|
|
|
iovec_t *iov, unsigned nr_req) );
|
2005-07-29 12:21:04 +02:00
|
|
|
FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
|
|
|
|
FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
|
|
|
|
FORWARD _PROTOTYPE( void w_init, (void) );
|
|
|
|
FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry));
|
2009-12-02 10:57:48 +01:00
|
|
|
FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr) );
|
2005-07-29 12:21:04 +02:00
|
|
|
|
|
|
|
/* Entry points to this driver. */
|
|
|
|
PRIVATE struct driver w_dtab = {
|
|
|
|
w_name, /* current device's name */
|
|
|
|
w_do_open, /* open or mount request, initialize device */
|
|
|
|
w_do_close, /* release device */
|
|
|
|
do_diocntl, /* get or set a partition's geometry */
|
|
|
|
w_prepare, /* prepare for I/O on a given minor device */
|
|
|
|
w_transfer, /* do the I/O */
|
|
|
|
nop_cleanup, /* no cleanup needed */
|
|
|
|
w_geometry, /* tell the geometry of the disk */
|
|
|
|
nop_alarm, /* ignore leftover alarms */
|
|
|
|
nop_cancel, /* ignore CANCELs */
|
|
|
|
nop_select, /* ignore selects */
|
2005-09-24 14:26:31 +02:00
|
|
|
w_other, /* catch-all for unrecognized commands and ioctls */
|
2005-08-25 10:19:11 +02:00
|
|
|
NULL /* leftover hardware interrupts */
|
2005-07-29 12:21:04 +02:00
|
|
|
};
|
|
|
|
|
Basic System Event Framework (SEF) with ping and live update.
SYSLIB CHANGES:
- SEF must be used by every system process and is thereby part of the system
library.
- The framework provides a receive() interface (sef_receive) for system
processes to automatically catch known system even messages and process them.
- SEF provides a default behavior for each type of system event, but allows
system processes to register callbacks to override the default behavior.
- Custom (local to the process) or predefined (provided by SEF) callback
implementations can be registered to SEF.
- SEF currently includes support for 2 types of system events:
1. SEF Ping. The event occurs every time RS sends a ping to figure out
whether a system process is still alive. The default callback implementation
provided by SEF is to notify RS back to let it know the process is alive
and kicking.
2. SEF Live update. The event occurs every time RS sends a prepare to update
message to let a system process know an update is available and to prepare
for it. The live update support is very basic for now. SEF only deals with
verifying if the prepare state can be supported by the process, dumping the
state for debugging purposes, and providing an event-driven programming
model to the process to react to state changes check-in when ready to update.
- SEF should be extended in the future to integrate support for more types of
system events. Ideally, all the cross-cutting concerns should be integrated into
SEF to avoid duplicating code and ease extensibility. Examples include:
* PM notify messages primarily used at shutdown.
* SYSTEM notify messages primarily used for signals.
* CLOCK notify messages used for system alarms.
* Debug messages. IS could still be in charge of fkey handling but would
forward the debug message to the target process (e.g. PM, if the user
requested debug information about PM). SEF would then catch the message and
do nothing unless the process has registered an appropriate callback to
deal with the event. This simplifies the programming model to print debug
information, avoids duplicating code, and reduces the effort to print
debug information.
SYSTEM PROCESSES CHANGES:
- Every system process registers SEF callbacks it needs to override the default
system behavior and calls sef_startup() right after being started.
- sef_startup() does almost nothing now, but will be extended in the future to
support callbacks of its own to let RS control and synchronize with every
system process at initialization time.
- Every system process calls sef_receive() now rather than receive() directly,
to let SEF handle predefined system events.
RS CHANGES:
- RS supports a basic single-component live update protocol now, as follows:
* When an update command is issued (via "service update *"), RS notifies the
target system process to prepare for a specific update state.
* If the process doesn't respond back in time, the update is aborted.
* When the process responds back, RS kills it and marks it for refreshing.
* The process is then automatically restarted as for a buggy process and can
start running again.
* Live update is currently prototyped as a controlled failure.
2009-12-21 15:12:21 +01:00
|
|
|
/* SEF functions and variables. */
|
|
|
|
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
Initialization protocol for system services.
SYSLIB CHANGES:
- SEF framework now supports a new SEF Init request type from RS. 3 different
callbacks are available (init_fresh, init_lu, init_restart) to specify
initialization code when a service starts fresh, starts after a live update,
or restarts.
SYSTEM SERVICE CHANGES:
- Initialization code for system services is now enclosed in a callback SEF will
automatically call at init time. The return code of the callback will
tell RS whether the initialization completed successfully.
- Each init callback can access information passed by RS to initialize. As of
now, each system service has access to the public entries of RS's system process
table to gather all the information required to initialize. This design
eliminates many existing or potential races at boot time and provides a uniform
initialization interface to system services. The same interface will be reused
for the upcoming publish/subscribe model to handle dynamic
registration / deregistration of system services.
VM CHANGES:
- Uniform privilege management for all system services. Every service uses the
same call mask format. For boot services, VM copies the call mask from init
data. For dynamic services, VM still receives the call mask via rs_set_priv
call that will be soon replaced by the upcoming publish/subscribe model.
RS CHANGES:
- The system process table has been reorganized and split into private entries
and public entries. Only the latter ones are exposed to system services.
- VM call masks are now entirely configured in rs/table.c
- RS has now its own slot in the system process table. Only kernel tasks and
user processes not included in the boot image are now left out from the system
process table.
- RS implements the initialization protocol for system services.
- For services in the boot image, RS blocks till initialization is complete and
panics when failure is reported back. Services are initialized in their order of
appearance in the boot image priv table and RS blocks to implements synchronous
initialization for every system service having the flag SF_SYNCH_BOOT set.
- For services started dynamically, the initialization protocol is implemented
as though it were the first ping for the service. In this case, if the
system service fails to report back (or reports failure), RS brings the service
down rather than trying to restart it.
2010-01-08 02:20:42 +01:00
|
|
|
FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
|
Basic System Event Framework (SEF) with ping and live update.
SYSLIB CHANGES:
- SEF must be used by every system process and is thereby part of the system
library.
- The framework provides a receive() interface (sef_receive) for system
processes to automatically catch known system even messages and process them.
- SEF provides a default behavior for each type of system event, but allows
system processes to register callbacks to override the default behavior.
- Custom (local to the process) or predefined (provided by SEF) callback
implementations can be registered to SEF.
- SEF currently includes support for 2 types of system events:
1. SEF Ping. The event occurs every time RS sends a ping to figure out
whether a system process is still alive. The default callback implementation
provided by SEF is to notify RS back to let it know the process is alive
and kicking.
2. SEF Live update. The event occurs every time RS sends a prepare to update
message to let a system process know an update is available and to prepare
for it. The live update support is very basic for now. SEF only deals with
verifying if the prepare state can be supported by the process, dumping the
state for debugging purposes, and providing an event-driven programming
model to the process to react to state changes check-in when ready to update.
- SEF should be extended in the future to integrate support for more types of
system events. Ideally, all the cross-cutting concerns should be integrated into
SEF to avoid duplicating code and ease extensibility. Examples include:
* PM notify messages primarily used at shutdown.
* SYSTEM notify messages primarily used for signals.
* CLOCK notify messages used for system alarms.
* Debug messages. IS could still be in charge of fkey handling but would
forward the debug message to the target process (e.g. PM, if the user
requested debug information about PM). SEF would then catch the message and
do nothing unless the process has registered an appropriate callback to
deal with the event. This simplifies the programming model to print debug
information, avoids duplicating code, and reduces the effort to print
debug information.
SYSTEM PROCESSES CHANGES:
- Every system process registers SEF callbacks it needs to override the default
system behavior and calls sef_startup() right after being started.
- sef_startup() does almost nothing now, but will be extended in the future to
support callbacks of its own to let RS control and synchronize with every
system process at initialization time.
- Every system process calls sef_receive() now rather than receive() directly,
to let SEF handle predefined system events.
RS CHANGES:
- RS supports a basic single-component live update protocol now, as follows:
* When an update command is issued (via "service update *"), RS notifies the
target system process to prepare for a specific update state.
* If the process doesn't respond back in time, the update is aborted.
* When the process responds back, RS kills it and marks it for refreshing.
* The process is then automatically restarted as for a buggy process and can
start running again.
* Live update is currently prototyped as a controlled failure.
2009-12-21 15:12:21 +01:00
|
|
|
|
2005-07-29 12:21:04 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* bios_winchester_task *
|
|
|
|
*===========================================================================*/
|
|
|
|
PUBLIC int main()
|
|
|
|
{
|
Basic System Event Framework (SEF) with ping and live update.
SYSLIB CHANGES:
- SEF must be used by every system process and is thereby part of the system
library.
- The framework provides a receive() interface (sef_receive) for system
processes to automatically catch known system even messages and process them.
- SEF provides a default behavior for each type of system event, but allows
system processes to register callbacks to override the default behavior.
- Custom (local to the process) or predefined (provided by SEF) callback
implementations can be registered to SEF.
- SEF currently includes support for 2 types of system events:
1. SEF Ping. The event occurs every time RS sends a ping to figure out
whether a system process is still alive. The default callback implementation
provided by SEF is to notify RS back to let it know the process is alive
and kicking.
2. SEF Live update. The event occurs every time RS sends a prepare to update
message to let a system process know an update is available and to prepare
for it. The live update support is very basic for now. SEF only deals with
verifying if the prepare state can be supported by the process, dumping the
state for debugging purposes, and providing an event-driven programming
model to the process to react to state changes check-in when ready to update.
- SEF should be extended in the future to integrate support for more types of
system events. Ideally, all the cross-cutting concerns should be integrated into
SEF to avoid duplicating code and ease extensibility. Examples include:
* PM notify messages primarily used at shutdown.
* SYSTEM notify messages primarily used for signals.
* CLOCK notify messages used for system alarms.
* Debug messages. IS could still be in charge of fkey handling but would
forward the debug message to the target process (e.g. PM, if the user
requested debug information about PM). SEF would then catch the message and
do nothing unless the process has registered an appropriate callback to
deal with the event. This simplifies the programming model to print debug
information, avoids duplicating code, and reduces the effort to print
debug information.
SYSTEM PROCESSES CHANGES:
- Every system process registers SEF callbacks it needs to override the default
system behavior and calls sef_startup() right after being started.
- sef_startup() does almost nothing now, but will be extended in the future to
support callbacks of its own to let RS control and synchronize with every
system process at initialization time.
- Every system process calls sef_receive() now rather than receive() directly,
to let SEF handle predefined system events.
RS CHANGES:
- RS supports a basic single-component live update protocol now, as follows:
* When an update command is issued (via "service update *"), RS notifies the
target system process to prepare for a specific update state.
* If the process doesn't respond back in time, the update is aborted.
* When the process responds back, RS kills it and marks it for refreshing.
* The process is then automatically restarted as for a buggy process and can
start running again.
* Live update is currently prototyped as a controlled failure.
2009-12-21 15:12:21 +01:00
|
|
|
/* SEF local startup. */
|
|
|
|
sef_local_startup();
|
|
|
|
|
Initialization protocol for system services.
SYSLIB CHANGES:
- SEF framework now supports a new SEF Init request type from RS. 3 different
callbacks are available (init_fresh, init_lu, init_restart) to specify
initialization code when a service starts fresh, starts after a live update,
or restarts.
SYSTEM SERVICE CHANGES:
- Initialization code for system services is now enclosed in a callback SEF will
automatically call at init time. The return code of the callback will
tell RS whether the initialization completed successfully.
- Each init callback can access information passed by RS to initialize. As of
now, each system service has access to the public entries of RS's system process
table to gather all the information required to initialize. This design
eliminates many existing or potential races at boot time and provides a uniform
initialization interface to system services. The same interface will be reused
for the upcoming publish/subscribe model to handle dynamic
registration / deregistration of system services.
VM CHANGES:
- Uniform privilege management for all system services. Every service uses the
same call mask format. For boot services, VM copies the call mask from init
data. For dynamic services, VM still receives the call mask via rs_set_priv
call that will be soon replaced by the upcoming publish/subscribe model.
RS CHANGES:
- The system process table has been reorganized and split into private entries
and public entries. Only the latter ones are exposed to system services.
- VM call masks are now entirely configured in rs/table.c
- RS has now its own slot in the system process table. Only kernel tasks and
user processes not included in the boot image are now left out from the system
process table.
- RS implements the initialization protocol for system services.
- For services in the boot image, RS blocks till initialization is complete and
panics when failure is reported back. Services are initialized in their order of
appearance in the boot image priv table and RS blocks to implements synchronous
initialization for every system service having the flag SF_SYNCH_BOOT set.
- For services started dynamically, the initialization protocol is implemented
as though it were the first ping for the service. In this case, if the
system service fails to report back (or reports failure), RS brings the service
down rather than trying to restart it.
2010-01-08 02:20:42 +01:00
|
|
|
/* Call the generic receive loop. */
|
2009-12-02 10:57:48 +01:00
|
|
|
driver_task(&w_dtab, DRIVER_STD);
|
Initialization protocol for system services.
SYSLIB CHANGES:
- SEF framework now supports a new SEF Init request type from RS. 3 different
callbacks are available (init_fresh, init_lu, init_restart) to specify
initialization code when a service starts fresh, starts after a live update,
or restarts.
SYSTEM SERVICE CHANGES:
- Initialization code for system services is now enclosed in a callback SEF will
automatically call at init time. The return code of the callback will
tell RS whether the initialization completed successfully.
- Each init callback can access information passed by RS to initialize. As of
now, each system service has access to the public entries of RS's system process
table to gather all the information required to initialize. This design
eliminates many existing or potential races at boot time and provides a uniform
initialization interface to system services. The same interface will be reused
for the upcoming publish/subscribe model to handle dynamic
registration / deregistration of system services.
VM CHANGES:
- Uniform privilege management for all system services. Every service uses the
same call mask format. For boot services, VM copies the call mask from init
data. For dynamic services, VM still receives the call mask via rs_set_priv
call that will be soon replaced by the upcoming publish/subscribe model.
RS CHANGES:
- The system process table has been reorganized and split into private entries
and public entries. Only the latter ones are exposed to system services.
- VM call masks are now entirely configured in rs/table.c
- RS has now its own slot in the system process table. Only kernel tasks and
user processes not included in the boot image are now left out from the system
process table.
- RS implements the initialization protocol for system services.
- For services in the boot image, RS blocks till initialization is complete and
panics when failure is reported back. Services are initialized in their order of
appearance in the boot image priv table and RS blocks to implements synchronous
initialization for every system service having the flag SF_SYNCH_BOOT set.
- For services started dynamically, the initialization protocol is implemented
as though it were the first ping for the service. In this case, if the
system service fails to report back (or reports failure), RS brings the service
down rather than trying to restart it.
2010-01-08 02:20:42 +01:00
|
|
|
|
2005-08-25 15:31:35 +02:00
|
|
|
return(OK);
|
2005-07-29 12:21:04 +02:00
|
|
|
}
|
|
|
|
|
Basic System Event Framework (SEF) with ping and live update.
SYSLIB CHANGES:
- SEF must be used by every system process and is thereby part of the system
library.
- The framework provides a receive() interface (sef_receive) for system
processes to automatically catch known system even messages and process them.
- SEF provides a default behavior for each type of system event, but allows
system processes to register callbacks to override the default behavior.
- Custom (local to the process) or predefined (provided by SEF) callback
implementations can be registered to SEF.
- SEF currently includes support for 2 types of system events:
1. SEF Ping. The event occurs every time RS sends a ping to figure out
whether a system process is still alive. The default callback implementation
provided by SEF is to notify RS back to let it know the process is alive
and kicking.
2. SEF Live update. The event occurs every time RS sends a prepare to update
message to let a system process know an update is available and to prepare
for it. The live update support is very basic for now. SEF only deals with
verifying if the prepare state can be supported by the process, dumping the
state for debugging purposes, and providing an event-driven programming
model to the process to react to state changes check-in when ready to update.
- SEF should be extended in the future to integrate support for more types of
system events. Ideally, all the cross-cutting concerns should be integrated into
SEF to avoid duplicating code and ease extensibility. Examples include:
* PM notify messages primarily used at shutdown.
* SYSTEM notify messages primarily used for signals.
* CLOCK notify messages used for system alarms.
* Debug messages. IS could still be in charge of fkey handling but would
forward the debug message to the target process (e.g. PM, if the user
requested debug information about PM). SEF would then catch the message and
do nothing unless the process has registered an appropriate callback to
deal with the event. This simplifies the programming model to print debug
information, avoids duplicating code, and reduces the effort to print
debug information.
SYSTEM PROCESSES CHANGES:
- Every system process registers SEF callbacks it needs to override the default
system behavior and calls sef_startup() right after being started.
- sef_startup() does almost nothing now, but will be extended in the future to
support callbacks of its own to let RS control and synchronize with every
system process at initialization time.
- Every system process calls sef_receive() now rather than receive() directly,
to let SEF handle predefined system events.
RS CHANGES:
- RS supports a basic single-component live update protocol now, as follows:
* When an update command is issued (via "service update *"), RS notifies the
target system process to prepare for a specific update state.
* If the process doesn't respond back in time, the update is aborted.
* When the process responds back, RS kills it and marks it for refreshing.
* The process is then automatically restarted as for a buggy process and can
start running again.
* Live update is currently prototyped as a controlled failure.
2009-12-21 15:12:21 +01:00
|
|
|
/*===========================================================================*
|
|
|
|
* sef_local_startup *
|
|
|
|
*===========================================================================*/
|
|
|
|
PRIVATE void sef_local_startup()
|
|
|
|
{
|
Initialization protocol for system services.
SYSLIB CHANGES:
- SEF framework now supports a new SEF Init request type from RS. 3 different
callbacks are available (init_fresh, init_lu, init_restart) to specify
initialization code when a service starts fresh, starts after a live update,
or restarts.
SYSTEM SERVICE CHANGES:
- Initialization code for system services is now enclosed in a callback SEF will
automatically call at init time. The return code of the callback will
tell RS whether the initialization completed successfully.
- Each init callback can access information passed by RS to initialize. As of
now, each system service has access to the public entries of RS's system process
table to gather all the information required to initialize. This design
eliminates many existing or potential races at boot time and provides a uniform
initialization interface to system services. The same interface will be reused
for the upcoming publish/subscribe model to handle dynamic
registration / deregistration of system services.
VM CHANGES:
- Uniform privilege management for all system services. Every service uses the
same call mask format. For boot services, VM copies the call mask from init
data. For dynamic services, VM still receives the call mask via rs_set_priv
call that will be soon replaced by the upcoming publish/subscribe model.
RS CHANGES:
- The system process table has been reorganized and split into private entries
and public entries. Only the latter ones are exposed to system services.
- VM call masks are now entirely configured in rs/table.c
- RS has now its own slot in the system process table. Only kernel tasks and
user processes not included in the boot image are now left out from the system
process table.
- RS implements the initialization protocol for system services.
- For services in the boot image, RS blocks till initialization is complete and
panics when failure is reported back. Services are initialized in their order of
appearance in the boot image priv table and RS blocks to implements synchronous
initialization for every system service having the flag SF_SYNCH_BOOT set.
- For services started dynamically, the initialization protocol is implemented
as though it were the first ping for the service. In this case, if the
system service fails to report back (or reports failure), RS brings the service
down rather than trying to restart it.
2010-01-08 02:20:42 +01:00
|
|
|
/* Register init callbacks. */
|
|
|
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
|
|
|
sef_setcb_init_lu(sef_cb_init_fresh);
|
|
|
|
sef_setcb_init_restart(sef_cb_init_fresh);
|
|
|
|
|
Basic System Event Framework (SEF) with ping and live update.
SYSLIB CHANGES:
- SEF must be used by every system process and is thereby part of the system
library.
- The framework provides a receive() interface (sef_receive) for system
processes to automatically catch known system even messages and process them.
- SEF provides a default behavior for each type of system event, but allows
system processes to register callbacks to override the default behavior.
- Custom (local to the process) or predefined (provided by SEF) callback
implementations can be registered to SEF.
- SEF currently includes support for 2 types of system events:
1. SEF Ping. The event occurs every time RS sends a ping to figure out
whether a system process is still alive. The default callback implementation
provided by SEF is to notify RS back to let it know the process is alive
and kicking.
2. SEF Live update. The event occurs every time RS sends a prepare to update
message to let a system process know an update is available and to prepare
for it. The live update support is very basic for now. SEF only deals with
verifying if the prepare state can be supported by the process, dumping the
state for debugging purposes, and providing an event-driven programming
model to the process to react to state changes check-in when ready to update.
- SEF should be extended in the future to integrate support for more types of
system events. Ideally, all the cross-cutting concerns should be integrated into
SEF to avoid duplicating code and ease extensibility. Examples include:
* PM notify messages primarily used at shutdown.
* SYSTEM notify messages primarily used for signals.
* CLOCK notify messages used for system alarms.
* Debug messages. IS could still be in charge of fkey handling but would
forward the debug message to the target process (e.g. PM, if the user
requested debug information about PM). SEF would then catch the message and
do nothing unless the process has registered an appropriate callback to
deal with the event. This simplifies the programming model to print debug
information, avoids duplicating code, and reduces the effort to print
debug information.
SYSTEM PROCESSES CHANGES:
- Every system process registers SEF callbacks it needs to override the default
system behavior and calls sef_startup() right after being started.
- sef_startup() does almost nothing now, but will be extended in the future to
support callbacks of its own to let RS control and synchronize with every
system process at initialization time.
- Every system process calls sef_receive() now rather than receive() directly,
to let SEF handle predefined system events.
RS CHANGES:
- RS supports a basic single-component live update protocol now, as follows:
* When an update command is issued (via "service update *"), RS notifies the
target system process to prepare for a specific update state.
* If the process doesn't respond back in time, the update is aborted.
* When the process responds back, RS kills it and marks it for refreshing.
* The process is then automatically restarted as for a buggy process and can
start running again.
* Live update is currently prototyped as a controlled failure.
2009-12-21 15:12:21 +01:00
|
|
|
/* 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();
|
|
|
|
}
|
|
|
|
|
Initialization protocol for system services.
SYSLIB CHANGES:
- SEF framework now supports a new SEF Init request type from RS. 3 different
callbacks are available (init_fresh, init_lu, init_restart) to specify
initialization code when a service starts fresh, starts after a live update,
or restarts.
SYSTEM SERVICE CHANGES:
- Initialization code for system services is now enclosed in a callback SEF will
automatically call at init time. The return code of the callback will
tell RS whether the initialization completed successfully.
- Each init callback can access information passed by RS to initialize. As of
now, each system service has access to the public entries of RS's system process
table to gather all the information required to initialize. This design
eliminates many existing or potential races at boot time and provides a uniform
initialization interface to system services. The same interface will be reused
for the upcoming publish/subscribe model to handle dynamic
registration / deregistration of system services.
VM CHANGES:
- Uniform privilege management for all system services. Every service uses the
same call mask format. For boot services, VM copies the call mask from init
data. For dynamic services, VM still receives the call mask via rs_set_priv
call that will be soon replaced by the upcoming publish/subscribe model.
RS CHANGES:
- The system process table has been reorganized and split into private entries
and public entries. Only the latter ones are exposed to system services.
- VM call masks are now entirely configured in rs/table.c
- RS has now its own slot in the system process table. Only kernel tasks and
user processes not included in the boot image are now left out from the system
process table.
- RS implements the initialization protocol for system services.
- For services in the boot image, RS blocks till initialization is complete and
panics when failure is reported back. Services are initialized in their order of
appearance in the boot image priv table and RS blocks to implements synchronous
initialization for every system service having the flag SF_SYNCH_BOOT set.
- For services started dynamically, the initialization protocol is implemented
as though it were the first ping for the service. In this case, if the
system service fails to report back (or reports failure), RS brings the service
down rather than trying to restart it.
2010-01-08 02:20:42 +01:00
|
|
|
/*===========================================================================*
|
|
|
|
* sef_cb_init_fresh *
|
|
|
|
*===========================================================================*/
|
2010-04-01 14:51:31 +02:00
|
|
|
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
|
Initialization protocol for system services.
SYSLIB CHANGES:
- SEF framework now supports a new SEF Init request type from RS. 3 different
callbacks are available (init_fresh, init_lu, init_restart) to specify
initialization code when a service starts fresh, starts after a live update,
or restarts.
SYSTEM SERVICE CHANGES:
- Initialization code for system services is now enclosed in a callback SEF will
automatically call at init time. The return code of the callback will
tell RS whether the initialization completed successfully.
- Each init callback can access information passed by RS to initialize. As of
now, each system service has access to the public entries of RS's system process
table to gather all the information required to initialize. This design
eliminates many existing or potential races at boot time and provides a uniform
initialization interface to system services. The same interface will be reused
for the upcoming publish/subscribe model to handle dynamic
registration / deregistration of system services.
VM CHANGES:
- Uniform privilege management for all system services. Every service uses the
same call mask format. For boot services, VM copies the call mask from init
data. For dynamic services, VM still receives the call mask via rs_set_priv
call that will be soon replaced by the upcoming publish/subscribe model.
RS CHANGES:
- The system process table has been reorganized and split into private entries
and public entries. Only the latter ones are exposed to system services.
- VM call masks are now entirely configured in rs/table.c
- RS has now its own slot in the system process table. Only kernel tasks and
user processes not included in the boot image are now left out from the system
process table.
- RS implements the initialization protocol for system services.
- For services in the boot image, RS blocks till initialization is complete and
panics when failure is reported back. Services are initialized in their order of
appearance in the boot image priv table and RS blocks to implements synchronous
initialization for every system service having the flag SF_SYNCH_BOOT set.
- For services started dynamically, the initialization protocol is implemented
as though it were the first ping for the service. In this case, if the
system service fails to report back (or reports failure), RS brings the service
down rather than trying to restart it.
2010-01-08 02:20:42 +01:00
|
|
|
{
|
|
|
|
/* Initialize the bios_wini driver. */
|
|
|
|
long v;
|
|
|
|
|
|
|
|
v = 0;
|
|
|
|
env_parse("bios_remap_first", "d", 0, &v, 0, 1);
|
|
|
|
remap_first = v;
|
|
|
|
|
2010-04-08 15:41:35 +02:00
|
|
|
/* Announce we are up! */
|
|
|
|
driver_announce();
|
|
|
|
|
Initialization protocol for system services.
SYSLIB CHANGES:
- SEF framework now supports a new SEF Init request type from RS. 3 different
callbacks are available (init_fresh, init_lu, init_restart) to specify
initialization code when a service starts fresh, starts after a live update,
or restarts.
SYSTEM SERVICE CHANGES:
- Initialization code for system services is now enclosed in a callback SEF will
automatically call at init time. The return code of the callback will
tell RS whether the initialization completed successfully.
- Each init callback can access information passed by RS to initialize. As of
now, each system service has access to the public entries of RS's system process
table to gather all the information required to initialize. This design
eliminates many existing or potential races at boot time and provides a uniform
initialization interface to system services. The same interface will be reused
for the upcoming publish/subscribe model to handle dynamic
registration / deregistration of system services.
VM CHANGES:
- Uniform privilege management for all system services. Every service uses the
same call mask format. For boot services, VM copies the call mask from init
data. For dynamic services, VM still receives the call mask via rs_set_priv
call that will be soon replaced by the upcoming publish/subscribe model.
RS CHANGES:
- The system process table has been reorganized and split into private entries
and public entries. Only the latter ones are exposed to system services.
- VM call masks are now entirely configured in rs/table.c
- RS has now its own slot in the system process table. Only kernel tasks and
user processes not included in the boot image are now left out from the system
process table.
- RS implements the initialization protocol for system services.
- For services in the boot image, RS blocks till initialization is complete and
panics when failure is reported back. Services are initialized in their order of
appearance in the boot image priv table and RS blocks to implements synchronous
initialization for every system service having the flag SF_SYNCH_BOOT set.
- For services started dynamically, the initialization protocol is implemented
as though it were the first ping for the service. In this case, if the
system service fails to report back (or reports failure), RS brings the service
down rather than trying to restart it.
2010-01-08 02:20:42 +01:00
|
|
|
return(OK);
|
|
|
|
}
|
|
|
|
|
2005-07-29 12:21:04 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* w_prepare *
|
|
|
|
*===========================================================================*/
|
|
|
|
PRIVATE struct device *w_prepare(device)
|
|
|
|
int device;
|
|
|
|
{
|
|
|
|
/* Prepare for I/O on a device. */
|
|
|
|
|
2005-08-04 11:26:36 +02:00
|
|
|
if (device < NR_MINORS) { /* d0, d0p[0-3], d1, ... */
|
2005-07-29 12:21:04 +02:00
|
|
|
w_drive = device / DEV_PER_DRIVE; /* save drive number */
|
|
|
|
w_wn = &wini[w_drive];
|
|
|
|
w_dv = &w_wn->part[device % DEV_PER_DRIVE];
|
|
|
|
} else
|
|
|
|
if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/
|
|
|
|
w_drive = device / SUB_PER_DRIVE;
|
|
|
|
w_wn = &wini[w_drive];
|
|
|
|
w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];
|
|
|
|
} else {
|
2010-05-10 15:26:00 +02:00
|
|
|
return(NULL);
|
2005-07-29 12:21:04 +02:00
|
|
|
}
|
2005-08-15 15:19:02 +02:00
|
|
|
if (w_drive >= MAX_DRIVES || !w_wn->present)
|
2010-05-10 15:26:00 +02:00
|
|
|
return NULL;
|
2005-08-15 15:19:02 +02:00
|
|
|
return(w_dv);
|
2005-07-29 12:21:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* w_name *
|
|
|
|
*===========================================================================*/
|
|
|
|
PRIVATE char *w_name()
|
|
|
|
{
|
|
|
|
/* Return a name for the current device. */
|
|
|
|
static char name[] = "bios-d0";
|
|
|
|
|
|
|
|
name[6] = '0' + w_drive;
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2006-06-20 10:52:26 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* w_transfer *
|
|
|
|
*===========================================================================*/
|
2009-12-02 10:57:48 +01:00
|
|
|
PRIVATE int w_transfer(proc_nr, opcode, pos64, iov, nr_req)
|
2005-07-29 12:21:04 +02:00
|
|
|
int proc_nr; /* process doing the request */
|
|
|
|
int opcode; /* DEV_GATHER or DEV_SCATTER */
|
2006-11-27 15:21:43 +01:00
|
|
|
u64_t pos64; /* offset on device to read or write */
|
2005-07-29 12:21:04 +02:00
|
|
|
iovec_t *iov; /* pointer to read or write request vector */
|
|
|
|
unsigned nr_req; /* length of request vector */
|
|
|
|
{
|
|
|
|
struct wini *wn = w_wn;
|
|
|
|
iovec_t *iop, *iov_end = iov + nr_req;
|
|
|
|
int r, errors;
|
2010-03-30 16:07:15 +02:00
|
|
|
unsigned count;
|
|
|
|
vir_bytes chunk, nbytes;
|
2005-07-29 12:21:04 +02:00
|
|
|
unsigned long block;
|
|
|
|
vir_bytes i13e_rw_off, rem_buf_size;
|
|
|
|
unsigned secspcyl = wn->heads * wn->sectors;
|
|
|
|
struct int13ext_rw {
|
|
|
|
u8_t len;
|
|
|
|
u8_t res1;
|
|
|
|
u16_t count;
|
|
|
|
u16_t addr[2];
|
|
|
|
u32_t block[2];
|
2009-09-21 16:25:54 +02:00
|
|
|
} *i13e_rw;
|
2005-07-29 12:21:04 +02:00
|
|
|
struct reg86u reg86;
|
2009-09-21 16:25:54 +02:00
|
|
|
u32_t lopos;
|
2005-07-29 12:21:04 +02:00
|
|
|
|
2009-09-21 16:25:54 +02:00
|
|
|
lopos= ex64lo(pos64);
|
2006-11-27 15:21:43 +01:00
|
|
|
|
2005-07-29 12:21:04 +02:00
|
|
|
/* Check disk address. */
|
2009-09-21 16:25:54 +02:00
|
|
|
if ((lopos & SECTOR_MASK) != 0) return(EINVAL);
|
2005-07-29 12:21:04 +02:00
|
|
|
|
|
|
|
errors = 0;
|
|
|
|
|
2009-09-21 16:25:54 +02:00
|
|
|
i13e_rw_off= BIOSBUF-sizeof(*i13e_rw);
|
2005-07-29 12:21:04 +02:00
|
|
|
rem_buf_size= (i13e_rw_off & ~SECTOR_MASK);
|
2009-09-21 16:25:54 +02:00
|
|
|
i13e_rw = (struct int13ext_rw *) (bios_buf_v + i13e_rw_off);
|
2005-07-29 12:21:04 +02:00
|
|
|
assert(rem_buf_size != 0);
|
|
|
|
|
|
|
|
while (nr_req > 0) {
|
|
|
|
/* How many bytes to transfer? */
|
|
|
|
nbytes = 0;
|
|
|
|
for (iop = iov; iop < iov_end; iop++) {
|
|
|
|
if (nbytes + iop->iov_size > rem_buf_size) {
|
|
|
|
/* Don't do half a segment if you can avoid it. */
|
|
|
|
if (nbytes == 0) nbytes = rem_buf_size;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
nbytes += iop->iov_size;
|
|
|
|
}
|
|
|
|
if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
|
|
|
|
|
|
|
|
/* Which block on disk and how close to EOF? */
|
2009-09-21 16:25:54 +02:00
|
|
|
if (cmp64(pos64, w_dv->dv_size) >= 0) return(OK); /* At EOF */
|
|
|
|
if (cmp64(add64u(pos64, nbytes), w_dv->dv_size) > 0) {
|
|
|
|
u64_t n;
|
|
|
|
n = sub64(w_dv->dv_size, pos64);
|
|
|
|
assert(ex64hi(n) == 0);
|
|
|
|
nbytes = ex64lo(n);
|
|
|
|
}
|
|
|
|
block = div64u(add64(w_dv->dv_base, pos64), SECTOR_SIZE);
|
2005-07-29 12:21:04 +02:00
|
|
|
|
|
|
|
/* Degrade to per-sector mode if there were errors. */
|
|
|
|
if (errors > 0) nbytes = SECTOR_SIZE;
|
|
|
|
|
2007-02-07 17:22:19 +01:00
|
|
|
if (opcode == DEV_SCATTER_S) {
|
2005-07-29 12:21:04 +02:00
|
|
|
/* Copy from user space to the DMA buffer. */
|
|
|
|
count = 0;
|
|
|
|
for (iop = iov; count < nbytes; iop++) {
|
2009-10-01 18:59:04 +02:00
|
|
|
chunk = iop->iov_size;
|
2005-07-29 12:21:04 +02:00
|
|
|
if (count + chunk > nbytes) chunk = nbytes - count;
|
|
|
|
assert(chunk <= rem_buf_size);
|
2009-09-21 16:25:54 +02:00
|
|
|
|
2009-12-02 10:57:48 +01:00
|
|
|
if(proc_nr != SELF) {
|
2009-09-21 16:25:54 +02:00
|
|
|
r=sys_safecopyfrom(proc_nr,
|
|
|
|
(cp_grant_id_t) iop->iov_addr,
|
|
|
|
0, (vir_bytes) (bios_buf_v+count),
|
|
|
|
chunk, D);
|
|
|
|
if (r != OK)
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("copy failed: %d", r);
|
2009-09-21 16:25:54 +02:00
|
|
|
} else {
|
|
|
|
memcpy(bios_buf_v+count,
|
|
|
|
(char *) iop->iov_addr, chunk);
|
|
|
|
}
|
2005-07-29 12:21:04 +02:00
|
|
|
count += chunk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Do the transfer */
|
|
|
|
if (wn->int13ext) {
|
2009-09-21 16:25:54 +02:00
|
|
|
i13e_rw->len = 0x10;
|
|
|
|
i13e_rw->res1 = 0;
|
|
|
|
i13e_rw->count = nbytes >> SECTOR_SHIFT;
|
|
|
|
i13e_rw->addr[0] = bios_buf_phys % HCLICK_SIZE;
|
|
|
|
i13e_rw->addr[1] = bios_buf_phys / HCLICK_SIZE;
|
|
|
|
i13e_rw->block[0] = block;
|
|
|
|
i13e_rw->block[1] = 0;
|
2005-07-29 12:21:04 +02:00
|
|
|
|
|
|
|
/* Set up an extended read or write BIOS call. */
|
|
|
|
reg86.u.b.intno = 0x13;
|
2007-02-07 17:22:19 +01:00
|
|
|
reg86.u.w.ax = opcode == DEV_SCATTER_S ? 0x4300 : 0x4200;
|
2005-08-15 15:19:02 +02:00
|
|
|
reg86.u.b.dl = wn->drive_id;
|
2005-07-29 12:21:04 +02:00
|
|
|
reg86.u.w.si = (bios_buf_phys + i13e_rw_off) % HCLICK_SIZE;
|
|
|
|
reg86.u.w.ds = (bios_buf_phys + i13e_rw_off) / HCLICK_SIZE;
|
|
|
|
} else {
|
|
|
|
/* Set up an ordinary read or write BIOS call. */
|
|
|
|
unsigned cylinder = block / secspcyl;
|
|
|
|
unsigned sector = (block % wn->sectors) + 1;
|
|
|
|
unsigned head = (block % secspcyl) / wn->sectors;
|
|
|
|
|
|
|
|
reg86.u.b.intno = 0x13;
|
2007-02-07 17:22:19 +01:00
|
|
|
reg86.u.b.ah = opcode == DEV_SCATTER_S ? 0x03 : 0x02;
|
2005-07-29 12:21:04 +02:00
|
|
|
reg86.u.b.al = nbytes >> SECTOR_SHIFT;
|
2005-08-11 15:55:06 +02:00
|
|
|
reg86.u.w.bx = bios_buf_phys % HCLICK_SIZE;
|
|
|
|
reg86.u.w.es = bios_buf_phys / HCLICK_SIZE;
|
2005-07-29 12:21:04 +02:00
|
|
|
reg86.u.b.ch = cylinder & 0xFF;
|
|
|
|
reg86.u.b.cl = sector | ((cylinder & 0x300) >> 2);
|
|
|
|
reg86.u.b.dh = head;
|
2005-08-15 15:19:02 +02:00
|
|
|
reg86.u.b.dl = wn->drive_id;
|
2005-07-29 12:21:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
r= sys_int86(®86);
|
|
|
|
if (r != OK)
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("BIOS call failed: %d", r);
|
2005-07-29 12:21:04 +02:00
|
|
|
|
|
|
|
if (reg86.u.w.f & 0x0001) {
|
|
|
|
/* An error occurred, try again sector by sector unless */
|
|
|
|
if (++errors == 2) return(EIO);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2007-02-07 17:22:19 +01:00
|
|
|
if (opcode == DEV_GATHER_S) {
|
2005-07-29 12:21:04 +02:00
|
|
|
/* Copy from the DMA buffer to user space. */
|
|
|
|
count = 0;
|
|
|
|
for (iop = iov; count < nbytes; iop++) {
|
2009-10-01 18:59:04 +02:00
|
|
|
chunk = iop->iov_size;
|
2005-07-29 12:21:04 +02:00
|
|
|
if (count + chunk > nbytes) chunk = nbytes - count;
|
|
|
|
assert(chunk <= rem_buf_size);
|
2009-09-21 16:25:54 +02:00
|
|
|
|
2009-12-02 10:57:48 +01:00
|
|
|
if(proc_nr != SELF) {
|
2009-09-21 16:25:54 +02:00
|
|
|
r=sys_safecopyto(proc_nr, iop->iov_addr,
|
2009-12-02 10:57:48 +01:00
|
|
|
0, (vir_bytes) (bios_buf_v+count),
|
|
|
|
chunk, D);
|
2009-09-21 16:25:54 +02:00
|
|
|
|
|
|
|
if (r != OK)
|
2011-03-25 11:45:57 +01:00
|
|
|
panic("sys_safecopy failed: %d", r);
|
2009-09-21 16:25:54 +02:00
|
|
|
} else {
|
|
|
|
memcpy((char *) iop->iov_addr,
|
|
|
|
bios_buf_v+count, chunk);
|
|
|
|
}
|
2005-07-29 12:21:04 +02:00
|
|
|
count += chunk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Book the bytes successfully transferred. */
|
2009-09-21 16:25:54 +02:00
|
|
|
pos64 = add64ul(pos64, nbytes);
|
2005-07-29 12:21:04 +02:00
|
|
|
for (;;) {
|
|
|
|
if (nbytes < iov->iov_size) {
|
|
|
|
/* Not done with this one yet. */
|
|
|
|
iov->iov_size -= nbytes;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
nbytes -= iov->iov_size;
|
|
|
|
iov->iov_size = 0;
|
|
|
|
if (nbytes == 0) {
|
|
|
|
/* The rest is optional, so we return to give FS a
|
|
|
|
* chance to think it over.
|
|
|
|
*/
|
|
|
|
return(OK);
|
|
|
|
}
|
|
|
|
iov++;
|
|
|
|
nr_req--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*============================================================================*
|
|
|
|
* w_do_open *
|
|
|
|
*============================================================================*/
|
|
|
|
PRIVATE int w_do_open(dp, m_ptr)
|
|
|
|
struct driver *dp;
|
|
|
|
message *m_ptr;
|
|
|
|
{
|
|
|
|
/* Device open: Initialize the controller and read the partition table. */
|
|
|
|
|
|
|
|
static int init_done = FALSE;
|
|
|
|
|
|
|
|
if (!init_done) { w_init(); init_done = TRUE; }
|
|
|
|
|
2010-05-10 15:26:00 +02:00
|
|
|
if (w_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
2005-07-29 12:21:04 +02:00
|
|
|
|
|
|
|
if (w_wn->open_ct++ == 0) {
|
|
|
|
/* Partition the disk. */
|
2005-08-08 14:16:59 +02:00
|
|
|
partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY, 0);
|
2005-07-29 12:21:04 +02:00
|
|
|
}
|
|
|
|
return(OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*============================================================================*
|
|
|
|
* w_do_close *
|
|
|
|
*============================================================================*/
|
|
|
|
PRIVATE int w_do_close(dp, m_ptr)
|
|
|
|
struct driver *dp;
|
|
|
|
message *m_ptr;
|
|
|
|
{
|
|
|
|
/* Device close: Release a device. */
|
|
|
|
|
2010-05-10 15:26:00 +02:00
|
|
|
if (w_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
2005-07-29 12:21:04 +02:00
|
|
|
w_wn->open_ct--;
|
|
|
|
return(OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* w_init *
|
|
|
|
*===========================================================================*/
|
|
|
|
PRIVATE void w_init()
|
|
|
|
{
|
|
|
|
/* This routine is called at startup to initialize the drive parameters. */
|
|
|
|
|
2005-08-15 15:19:02 +02:00
|
|
|
int r, drive, drive_id, nr_drives;
|
2005-07-29 12:21:04 +02:00
|
|
|
struct wini *wn;
|
|
|
|
unsigned long capacity;
|
|
|
|
struct int13ext_params {
|
|
|
|
u16_t len;
|
|
|
|
u16_t flags;
|
|
|
|
u32_t cylinders;
|
|
|
|
u32_t heads;
|
|
|
|
u32_t sectors;
|
|
|
|
u32_t capacity[2];
|
|
|
|
u16_t bts_per_sec;
|
|
|
|
u16_t config[2];
|
2009-09-21 16:25:54 +02:00
|
|
|
} *i13e_par;
|
2005-07-29 12:21:04 +02:00
|
|
|
struct reg86u reg86;
|
|
|
|
|
|
|
|
/* Ask the system task for a suitable buffer */
|
2009-09-21 16:25:54 +02:00
|
|
|
if(!(bios_buf_v = alloc_contig(BIOSBUF, AC_LOWER1M, &bios_buf_phys))) {
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("allocating bios buffer failed: %d", ENOMEM);
|
2006-06-20 10:52:26 +02:00
|
|
|
}
|
|
|
|
|
2009-09-21 16:25:54 +02:00
|
|
|
if (bios_buf_phys+BIOSBUF > 0x100000)
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("bad BIOS buffer / phys: %d", bios_buf_phys);
|
2005-07-29 12:21:04 +02:00
|
|
|
#if 0
|
|
|
|
printf("bios_wini: got buffer size %d, virtual 0x%x, phys 0x%x\n",
|
2009-09-21 16:25:54 +02:00
|
|
|
BIOSBUF, bios_buf_v, bios_buf_phys);
|
2005-07-29 12:21:04 +02:00
|
|
|
#endif
|
|
|
|
|
2009-09-21 16:25:54 +02:00
|
|
|
i13e_par = (struct int13ext_params *) bios_buf_v;
|
|
|
|
|
2005-07-29 12:21:04 +02:00
|
|
|
/* Get the geometry of the drives */
|
2005-08-15 15:19:02 +02:00
|
|
|
for (drive = 0; drive < MAX_DRIVES; drive++) {
|
|
|
|
if (remap_first)
|
|
|
|
{
|
|
|
|
if (drive == 7)
|
|
|
|
drive_id= 0x80;
|
|
|
|
else
|
|
|
|
drive_id= 0x80 + drive + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
drive_id= 0x80 + drive;
|
|
|
|
|
2005-07-29 12:21:04 +02:00
|
|
|
(void) w_prepare(drive * DEV_PER_DRIVE);
|
|
|
|
wn = w_wn;
|
2005-08-15 15:19:02 +02:00
|
|
|
wn->drive_id= drive_id;
|
|
|
|
|
2005-07-29 12:21:04 +02:00
|
|
|
reg86.u.b.intno = 0x13;
|
|
|
|
reg86.u.b.ah = 0x08; /* Get drive parameters. */
|
2005-08-15 15:19:02 +02:00
|
|
|
reg86.u.b.dl = drive_id;
|
2005-07-29 12:21:04 +02:00
|
|
|
r= sys_int86(®86);
|
|
|
|
if (r != OK)
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("BIOS call failed: %d", r);
|
2005-07-29 12:21:04 +02:00
|
|
|
|
|
|
|
nr_drives = !(reg86.u.w.f & 0x0001) ? reg86.u.b.dl : drive;
|
2005-08-15 15:19:02 +02:00
|
|
|
if (drive_id >= 0x80 + nr_drives) continue;
|
|
|
|
wn->present= 1;
|
2005-07-29 12:21:04 +02:00
|
|
|
|
|
|
|
wn->heads = reg86.u.b.dh + 1;
|
|
|
|
wn->sectors = reg86.u.b.cl & 0x3F;
|
|
|
|
wn->cylinders = (reg86.u.b.ch | ((reg86.u.b.cl & 0xC0) << 2)) + 1;
|
|
|
|
|
|
|
|
capacity = (unsigned long) wn->cylinders * wn->heads * wn->sectors;
|
|
|
|
|
|
|
|
reg86.u.b.intno = 0x13;
|
|
|
|
reg86.u.b.ah = 0x41; /* INT 13 Extensions - Installation check */
|
|
|
|
reg86.u.w.bx = 0x55AA;
|
2005-08-15 15:19:02 +02:00
|
|
|
reg86.u.b.dl = drive_id;
|
2005-07-29 12:21:04 +02:00
|
|
|
|
2011-09-16 20:03:15 +02:00
|
|
|
r= sys_int86(®86);
|
|
|
|
if (r != OK)
|
|
|
|
panic("BIOS call failed: %d", r);
|
2005-07-29 12:21:04 +02:00
|
|
|
|
|
|
|
if (!(reg86.u.w.f & 0x0001) && reg86.u.w.bx == 0xAA55
|
|
|
|
&& (reg86.u.w.cx & 0x0001)) {
|
|
|
|
/* INT 13 Extensions available. */
|
2009-09-21 16:25:54 +02:00
|
|
|
i13e_par->len = 0x001E; /* Input size of parameter packet */
|
2005-07-29 12:21:04 +02:00
|
|
|
reg86.u.b.intno = 0x13;
|
|
|
|
reg86.u.b.ah = 0x48; /* Ext. Get drive parameters. */
|
2005-08-15 15:19:02 +02:00
|
|
|
reg86.u.b.dl = drive_id;
|
2005-07-29 12:21:04 +02:00
|
|
|
reg86.u.w.si = bios_buf_phys % HCLICK_SIZE;
|
|
|
|
reg86.u.w.ds = bios_buf_phys / HCLICK_SIZE;
|
|
|
|
|
|
|
|
r= sys_int86(®86);
|
|
|
|
if (r != OK)
|
2010-03-05 16:05:11 +01:00
|
|
|
panic("BIOS call failed: %d", r);
|
2005-07-29 12:21:04 +02:00
|
|
|
|
|
|
|
if (!(reg86.u.w.f & 0x0001)) {
|
|
|
|
wn->int13ext = 1; /* Extensions can be used. */
|
2009-09-21 16:25:54 +02:00
|
|
|
capacity = i13e_par->capacity[0];
|
|
|
|
if (i13e_par->capacity[1] != 0) capacity = 0xFFFFFFFF;
|
2005-07-29 12:21:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wn->int13ext) {
|
|
|
|
printf("%s: %lu sectors\n", w_name(), capacity);
|
|
|
|
} else {
|
|
|
|
printf("%s: %d cylinders, %d heads, %d sectors per track\n",
|
|
|
|
w_name(), wn->cylinders, wn->heads, wn->sectors);
|
|
|
|
}
|
|
|
|
wn->part[0].dv_size = mul64u(capacity, SECTOR_SIZE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*============================================================================*
|
|
|
|
* w_geometry *
|
|
|
|
*============================================================================*/
|
|
|
|
PRIVATE void w_geometry(entry)
|
|
|
|
struct partition *entry;
|
|
|
|
{
|
|
|
|
entry->cylinders = w_wn->cylinders;
|
|
|
|
entry->heads = w_wn->heads;
|
|
|
|
entry->sectors = w_wn->sectors;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*============================================================================*
|
2005-09-24 14:26:31 +02:00
|
|
|
* w_other *
|
2005-07-29 12:21:04 +02:00
|
|
|
*============================================================================*/
|
2010-04-07 13:25:51 +02:00
|
|
|
PRIVATE int w_other(struct driver *UNUSED(dr), message *m)
|
2005-07-29 12:21:04 +02:00
|
|
|
{
|
2010-01-15 22:45:30 +01:00
|
|
|
int r;
|
2005-09-24 14:26:31 +02:00
|
|
|
|
2007-02-07 17:22:19 +01:00
|
|
|
if (m->m_type != DEV_IOCTL_S )
|
2005-09-24 14:26:31 +02:00
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
if (m->REQUEST == DIOCOPENCT) {
|
|
|
|
int count;
|
2010-05-10 15:26:00 +02:00
|
|
|
if (w_prepare(m->DEVICE) == NULL) return ENXIO;
|
2005-09-24 14:26:31 +02:00
|
|
|
count = w_wn->open_ct;
|
Server/driver protocols: no longer allow third-party copies.
Before safecopies, the IO_ENDPT and DL_ENDPT message fields were needed
to know which actual process to copy data from/to, as that process may
not always be the caller. Now that we have full safecopy support, these
fields have become useless for that purpose: the owner of the grant is
*always* the caller. Allowing the caller to supply another endpoint is
in fact dangerous, because the callee may then end up using a grant
from a third party. One could call this a variant of the confused
deputy problem.
From now on, safecopy calls should always use the caller's endpoint as
grant owner. This fully obsoletes the DL_ENDPT field in the
inet/ethernet protocol. IO_ENDPT has other uses besides identifying the
grant owner though. This patch renames IO_ENDPT to USER_ENDPT, not only
because that is a more fitting name (it should never be used for I/O
after all), but also in order to intentionally break any old system
source code outside the base system. If this patch breaks your code,
fixing it is fairly simple:
- DL_ENDPT should be replaced with m_source;
- IO_ENDPT should be replaced with m_source when used for safecopies;
- IO_ENDPT should be replaced with USER_ENDPT for any other use, e.g.
when setting REP_ENDPT, matching requests in CANCEL calls, getting
DEV_SELECT flags, and retrieving of the real user process's endpoint
in DEV_OPEN.
The changes in this patch are binary backward compatible.
2011-04-11 19:35:05 +02:00
|
|
|
r=sys_safecopyto(m->m_source, (cp_grant_id_t)m->IO_GRANT,
|
2006-06-20 10:52:26 +02:00
|
|
|
0, (vir_bytes)&count, sizeof(count), D);
|
|
|
|
|
|
|
|
if(r != OK)
|
2005-09-24 14:26:31 +02:00
|
|
|
return r;
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINVAL;
|
2005-07-29 12:21:04 +02:00
|
|
|
}
|
|
|
|
|
Basic System Event Framework (SEF) with ping and live update.
SYSLIB CHANGES:
- SEF must be used by every system process and is thereby part of the system
library.
- The framework provides a receive() interface (sef_receive) for system
processes to automatically catch known system even messages and process them.
- SEF provides a default behavior for each type of system event, but allows
system processes to register callbacks to override the default behavior.
- Custom (local to the process) or predefined (provided by SEF) callback
implementations can be registered to SEF.
- SEF currently includes support for 2 types of system events:
1. SEF Ping. The event occurs every time RS sends a ping to figure out
whether a system process is still alive. The default callback implementation
provided by SEF is to notify RS back to let it know the process is alive
and kicking.
2. SEF Live update. The event occurs every time RS sends a prepare to update
message to let a system process know an update is available and to prepare
for it. The live update support is very basic for now. SEF only deals with
verifying if the prepare state can be supported by the process, dumping the
state for debugging purposes, and providing an event-driven programming
model to the process to react to state changes check-in when ready to update.
- SEF should be extended in the future to integrate support for more types of
system events. Ideally, all the cross-cutting concerns should be integrated into
SEF to avoid duplicating code and ease extensibility. Examples include:
* PM notify messages primarily used at shutdown.
* SYSTEM notify messages primarily used for signals.
* CLOCK notify messages used for system alarms.
* Debug messages. IS could still be in charge of fkey handling but would
forward the debug message to the target process (e.g. PM, if the user
requested debug information about PM). SEF would then catch the message and
do nothing unless the process has registered an appropriate callback to
deal with the event. This simplifies the programming model to print debug
information, avoids duplicating code, and reduces the effort to print
debug information.
SYSTEM PROCESSES CHANGES:
- Every system process registers SEF callbacks it needs to override the default
system behavior and calls sef_startup() right after being started.
- sef_startup() does almost nothing now, but will be extended in the future to
support callbacks of its own to let RS control and synchronize with every
system process at initialization time.
- Every system process calls sef_receive() now rather than receive() directly,
to let SEF handle predefined system events.
RS CHANGES:
- RS supports a basic single-component live update protocol now, as follows:
* When an update command is issued (via "service update *"), RS notifies the
target system process to prepare for a specific update state.
* If the process doesn't respond back in time, the update is aborted.
* When the process responds back, RS kills it and marks it for refreshing.
* The process is then automatically restarted as for a buggy process and can
start running again.
* Live update is currently prototyped as a controlled failure.
2009-12-21 15:12:21 +01:00
|
|
|
|