Split block/character protocols and libdriver
This patch separates the character and block driver communication protocols. The old character protocol remains the same, but a new block protocol is introduced. The libdriver library is replaced by two new libraries: libchardriver and libblockdriver. Their exposed API, and drivers that use them, have been updated accordingly. Together, libbdev and libblockdriver now completely abstract away the message format used by the block protocol. As the memory driver is both a character and a block device driver, it now implements its own message loop. The most important semantic change made to the block protocol is that it is no longer possible to return both partial results and an error for a single transfer. This simplifies the interaction between the caller and the driver, as the I/O vector no longer needs to be copied back. Also, drivers are now no longer supposed to decide based on the layout of the I/O vector when a transfer should be cut short. Put simply, transfers are now supposed to either succeed completely, or result in an error. After this patch, the state of the various pieces is as follows: - block protocol: stable - libbdev API: stable for synchronous communication - libblockdriver API: needs slight revision (the drvlib/partition API in particular; the threading API will also change shortly) - character protocol: needs cleanup - libchardriver API: needs cleanup accordingly - driver restarts: largely unsupported until endpoint changes are reintroduced As a side effect, this patch eliminates several bugs, hacks, and gcc -Wall and -W warnings all over the place. It probably introduces a few new ones, too. Update warning: this patch changes the protocol between MFS and disk drivers, so in order to use old/new images, the MFS from the ramdisk must be used to mount all file systems.
This commit is contained in:
parent
7643f2b25e
commit
b4d909d415
114 changed files with 2682 additions and 2148 deletions
|
@ -5,11 +5,11 @@
|
||||||
INCS+= env.h fetch.h hgfs.h lib.h libutil.h timers.h
|
INCS+= env.h fetch.h hgfs.h lib.h libutil.h timers.h
|
||||||
|
|
||||||
INCS+= minix/acpi.h minix/ansi.h minix/audio_fw.h minix/bitmap.h \
|
INCS+= minix/acpi.h minix/ansi.h minix/audio_fw.h minix/bitmap.h \
|
||||||
minix/bdev.h \
|
minix/bdev.h minix/blockdriver.h minix/blockdriver_mt.h \
|
||||||
minix/callnr.h minix/com.h minix/compiler.h minix/config.h \
|
minix/callnr.h minix/chardriver.h minix/com.h minix/compiler.h \
|
||||||
minix/const.h minix/cpufeature.h minix/crtso.h minix/debug.h \
|
minix/config.h minix/const.h minix/cpufeature.h minix/crtso.h \
|
||||||
minix/devio.h minix/devman.h minix/dmap.h minix/driver.h \
|
minix/debug.h minix/devio.h minix/devman.h minix/dmap.h \
|
||||||
minix/driver_mt.h minix/drivers.h minix/drvlib.h minix/ds.h \
|
minix/driver.h minix/drivers.h minix/drvlib.h minix/ds.h \
|
||||||
minix/endpoint.h minix/fslib.h minix/gcov.h minix/hash.h \
|
minix/endpoint.h minix/fslib.h minix/gcov.h minix/hash.h \
|
||||||
minix/ioctl.h minix/input.h minix/ipc.h minix/ipcconst.h \
|
minix/ioctl.h minix/input.h minix/ipc.h minix/ipcconst.h \
|
||||||
minix/keymap.h minix/limits.h minix/mthread.h minix/minlib.h \
|
minix/keymap.h minix/limits.h minix/mthread.h minix/minlib.h \
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define AUDIO_FW_H
|
#define AUDIO_FW_H
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/driver.h>
|
#include <minix/chardriver.h>
|
||||||
#include <sys/ioc_sound.h>
|
#include <sys/ioc_sound.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
#ifndef __MINIX_BDEV_H
|
#ifndef __MINIX_BDEV_H
|
||||||
#define __MINIX_BDEV_H
|
#define __MINIX_BDEV_H
|
||||||
|
|
||||||
#define BDEV_NOFLAGS 0
|
|
||||||
|
|
||||||
extern void bdev_driver(dev_t dev, endpoint_t endpt);
|
extern void bdev_driver(dev_t dev, endpoint_t endpt);
|
||||||
|
|
||||||
extern int bdev_open(dev_t dev, int access);
|
extern int bdev_open(dev_t dev, int access);
|
||||||
extern int bdev_close(dev_t dev);
|
extern int bdev_close(dev_t dev);
|
||||||
|
|
||||||
extern int bdev_read(dev_t dev, u64_t pos, char *buf, int count, int flags);
|
extern ssize_t bdev_read(dev_t dev, u64_t pos, char *buf, size_t count,
|
||||||
extern int bdev_write(dev_t dev, u64_t pos, char *buf, int count, int flags);
|
int flags);
|
||||||
extern int bdev_gather(dev_t dev, u64_t pos, iovec_t *vec, int count,
|
extern ssize_t bdev_write(dev_t dev, u64_t pos, char *buf, size_t count,
|
||||||
int flags, vir_bytes *size);
|
int flags);
|
||||||
extern int bdev_scatter(dev_t dev, u64_t pos, iovec_t *vec, int count,
|
extern ssize_t bdev_gather(dev_t dev, u64_t pos, iovec_t *vec, int count,
|
||||||
int flags, vir_bytes *size);
|
int flags);
|
||||||
|
extern ssize_t bdev_scatter(dev_t dev, u64_t pos, iovec_t *vec, int count,
|
||||||
|
int flags);
|
||||||
extern int bdev_ioctl(dev_t dev, int request, void *buf);
|
extern int bdev_ioctl(dev_t dev, int request, void *buf);
|
||||||
|
|
||||||
#endif /* __MINIX_BDEV_H */
|
#endif /* __MINIX_BDEV_H */
|
||||||
|
|
54
common/include/minix/blockdriver.h
Normal file
54
common/include/minix/blockdriver.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#ifndef _MINIX_BLOCKDRIVER_H
|
||||||
|
#define _MINIX_BLOCKDRIVER_H
|
||||||
|
|
||||||
|
#include <minix/driver.h>
|
||||||
|
|
||||||
|
typedef int thread_id_t;
|
||||||
|
|
||||||
|
/* Entry points into the device dependent code of block drivers. */
|
||||||
|
struct blockdriver {
|
||||||
|
_PROTOTYPE( int (*bdr_open), (dev_t minor, int access) );
|
||||||
|
_PROTOTYPE( int (*bdr_close), (dev_t minor) );
|
||||||
|
_PROTOTYPE( ssize_t (*bdr_transfer), (dev_t minor, int do_write, u64_t pos,
|
||||||
|
endpoint_t endpt, iovec_t *iov, unsigned count, int flags) );
|
||||||
|
_PROTOTYPE( int (*bdr_ioctl), (dev_t minor, unsigned int request,
|
||||||
|
endpoint_t endpt, cp_grant_id_t grant) );
|
||||||
|
_PROTOTYPE( void (*bdr_cleanup), (void) );
|
||||||
|
_PROTOTYPE( struct device *(*bdr_part), (dev_t minor) );
|
||||||
|
_PROTOTYPE( void (*bdr_geometry), (dev_t minor, struct partition *part) );
|
||||||
|
_PROTOTYPE( void (*bdr_intr), (unsigned int irqs) );
|
||||||
|
_PROTOTYPE( void (*bdr_alarm), (clock_t stamp) );
|
||||||
|
_PROTOTYPE( int (*bdr_other), (message *m_ptr) );
|
||||||
|
_PROTOTYPE( int (*bdr_thread), (dev_t minor, thread_id_t *threadp) );
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Functions defined by libblockdriver. These can be used for both
|
||||||
|
* singlethreaded and multithreaded drivers.
|
||||||
|
*/
|
||||||
|
_PROTOTYPE( void blockdriver_announce, (void) );
|
||||||
|
|
||||||
|
#ifndef _DRIVER_MT_API
|
||||||
|
/* Additional functions for the singlethreaded version. These allow the driver
|
||||||
|
* to either use the stock driver_task(), or implement its own message loop.
|
||||||
|
* To avoid accidents, these functions are not exposed when minix/driver_mt.h
|
||||||
|
* has been included previously.
|
||||||
|
*/
|
||||||
|
_PROTOTYPE( int blockdriver_receive_mq, (message *m_ptr, int *status_ptr) );
|
||||||
|
_PROTOTYPE( void blockdriver_process, (struct blockdriver *dp, message *m_ptr,
|
||||||
|
int ipc_status) );
|
||||||
|
_PROTOTYPE( void blockdriver_terminate, (void) );
|
||||||
|
_PROTOTYPE( void blockdriver_task, (struct blockdriver *bdp) );
|
||||||
|
_PROTOTYPE( int blockdriver_mq_queue, (message *m_ptr, int status) );
|
||||||
|
#endif /* !_DRIVER_MT_API */
|
||||||
|
|
||||||
|
/* Parameters for the disk drive. */
|
||||||
|
#define SECTOR_SIZE 512 /* physical sector size in bytes */
|
||||||
|
#define SECTOR_SHIFT 9 /* for division */
|
||||||
|
#define SECTOR_MASK 511 /* and remainder */
|
||||||
|
|
||||||
|
#define CD_SECTOR_SIZE 2048 /* sector size of a CD-ROM in bytes */
|
||||||
|
|
||||||
|
/* Size of the DMA buffer buffer in bytes. */
|
||||||
|
#define DMA_BUF_SIZE (DMA_SECTORS * SECTOR_SIZE)
|
||||||
|
|
||||||
|
#endif /* _MINIX_BLOCKDRIVER_H */
|
16
common/include/minix/blockdriver_mt.h
Normal file
16
common/include/minix/blockdriver_mt.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef _MINIX_BLOCKDRIVER_MT_H
|
||||||
|
#define _MINIX_BLOCKDRIVER_MT_H
|
||||||
|
|
||||||
|
#define DRIVER_MT_API 1 /* do not expose the singlethreaded API */
|
||||||
|
#include <minix/blockdriver.h>
|
||||||
|
|
||||||
|
/* The maximum number of worker threads. */
|
||||||
|
#define DRIVER_MT_MAX_WORKERS 32
|
||||||
|
|
||||||
|
_PROTOTYPE( void blockdriver_mt_task, (struct blockdriver *driver_tab) );
|
||||||
|
_PROTOTYPE( void blockdriver_mt_sleep, (void) );
|
||||||
|
_PROTOTYPE( void blockdriver_mt_wakeup, (thread_id_t id) );
|
||||||
|
_PROTOTYPE( void blockdriver_mt_stop, (void) );
|
||||||
|
_PROTOTYPE( void blockdriver_mt_terminate, (void) );
|
||||||
|
|
||||||
|
#endif /* _MINIX_BLOCKDRIVER_MT_H */
|
41
common/include/minix/chardriver.h
Normal file
41
common/include/minix/chardriver.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef _MINIX_CHARDRIVER_H
|
||||||
|
#define _MINIX_CHARDRIVER_H
|
||||||
|
|
||||||
|
#include <minix/driver.h>
|
||||||
|
|
||||||
|
/* Entry points into the device dependent code of character drivers. */
|
||||||
|
struct chardriver {
|
||||||
|
_PROTOTYPE( int (*cdr_open), (message *m_ptr) );
|
||||||
|
_PROTOTYPE( int (*cdr_close), (message *m_ptr) );
|
||||||
|
_PROTOTYPE( int (*cdr_ioctl), (message *m_ptr) );
|
||||||
|
_PROTOTYPE( struct device *(*cdr_prepare), (dev_t device) );
|
||||||
|
_PROTOTYPE( int (*cdr_transfer), (endpoint_t endpt, int opcode,
|
||||||
|
u64_t position, iovec_t *iov, unsigned int nr_req,
|
||||||
|
endpoint_t user_endpt) );
|
||||||
|
_PROTOTYPE( void (*cdr_cleanup), (void) );
|
||||||
|
_PROTOTYPE( void (*cdr_alarm), (message *m_ptr) );
|
||||||
|
_PROTOTYPE( int (*cdr_cancel), (message *m_ptr) );
|
||||||
|
_PROTOTYPE( int (*cdr_select), (message *m_ptr) );
|
||||||
|
_PROTOTYPE( int (*cdr_other), (message *m_ptr) );
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CHARDRIVER_SYNC 0 /* use the synchronous protocol */
|
||||||
|
#define CHARDRIVER_ASYNC 1 /* use the asynchronous protocol */
|
||||||
|
|
||||||
|
#define IS_CDEV_MINOR_RQ(type) (IS_DEV_RQ(type) && (type) != DEV_STATUS)
|
||||||
|
|
||||||
|
/* Functions defined by libchardriver. */
|
||||||
|
_PROTOTYPE( void chardriver_announce, (void) );
|
||||||
|
_PROTOTYPE( void chardriver_process, (struct chardriver *cdp, int driver_type,
|
||||||
|
message *m_ptr, int ipc_status) );
|
||||||
|
_PROTOTYPE( void chardriver_terminate, (void) );
|
||||||
|
_PROTOTYPE( void chardriver_task, (struct chardriver *cdp, int driver_type) );
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_nop, (message *m_ptr) );
|
||||||
|
_PROTOTYPE( void nop_cleanup, (void) );
|
||||||
|
_PROTOTYPE( void nop_alarm, (message *m_ptr) );
|
||||||
|
_PROTOTYPE( int nop_cancel, (message *m_ptr) );
|
||||||
|
_PROTOTYPE( int nop_select, (message *m_ptr) );
|
||||||
|
_PROTOTYPE( int nop_ioctl, (message *m_ptr) );
|
||||||
|
|
||||||
|
#endif /* _MINIX_CHARDRIVER_H */
|
|
@ -8,8 +8,8 @@
|
||||||
* 1 - 0xFF POSIX requests (see callnr.h)
|
* 1 - 0xFF POSIX requests (see callnr.h)
|
||||||
* 0x200 - 0x2FF Data link layer requests and responses
|
* 0x200 - 0x2FF Data link layer requests and responses
|
||||||
* 0x300 - 0x3FF Bus controller requests and responses
|
* 0x300 - 0x3FF Bus controller requests and responses
|
||||||
* 0x400 - 0x4FF Block and character device requests
|
* 0x400 - 0x4FF Character device requests
|
||||||
* 0x500 - 0x5FF Block and character device responses
|
* 0x500 - 0x5FF Character device responses
|
||||||
* 0x600 - 0x6FF Kernel calls to SYSTEM task
|
* 0x600 - 0x6FF Kernel calls to SYSTEM task
|
||||||
* 0x700 - 0x7FF Reincarnation Server (RS) requests
|
* 0x700 - 0x7FF Reincarnation Server (RS) requests
|
||||||
* 0x800 - 0x8FF Data Store (DS) requests
|
* 0x800 - 0x8FF Data Store (DS) requests
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
* 0x1200 - 0x12FF Devman
|
* 0x1200 - 0x12FF Devman
|
||||||
* 0x1300 - 0x13FF TTY Input
|
* 0x1300 - 0x13FF TTY Input
|
||||||
* 0x1400 - 0x14FF VFS-FS transaction IDs
|
* 0x1400 - 0x14FF VFS-FS transaction IDs
|
||||||
|
* 0x1500 - 0x15FF Block device requests and responses
|
||||||
*
|
*
|
||||||
* Zero and negative values are widely used for OK and error responses.
|
* Zero and negative values are widely used for OK and error responses.
|
||||||
*/
|
*/
|
||||||
|
@ -182,12 +183,12 @@
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* Messages for BLOCK and CHARACTER device drivers *
|
* Messages for CHARACTER device drivers *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
||||||
/* Message types for device drivers. */
|
/* Message types for character device drivers. */
|
||||||
#define DEV_RQ_BASE 0x400 /* base for device request types */
|
#define DEV_RQ_BASE 0x400 /* base for character device request types */
|
||||||
#define DEV_RS_BASE 0x500 /* base for device response types */
|
#define DEV_RS_BASE 0x500 /* base for character device response types */
|
||||||
|
|
||||||
#define CANCEL (DEV_RQ_BASE + 0) /* force a task to cancel */
|
#define CANCEL (DEV_RQ_BASE + 0) /* force a task to cancel */
|
||||||
#define DEV_OPEN (DEV_RQ_BASE + 6) /* open a minor device */
|
#define DEV_OPEN (DEV_RQ_BASE + 6) /* open a minor device */
|
||||||
|
@ -215,7 +216,7 @@
|
||||||
|
|
||||||
#define IS_DEV_RS(type) (((type) & ~0xff) == DEV_RS_BASE)
|
#define IS_DEV_RS(type) (((type) & ~0xff) == DEV_RS_BASE)
|
||||||
|
|
||||||
/* Field names for messages to block and character device drivers. */
|
/* Field names for messages to character device drivers. */
|
||||||
#define DEVICE m2_i1 /* major-minor device */
|
#define DEVICE m2_i1 /* major-minor device */
|
||||||
#define USER_ENDPT m2_i2 /* which endpoint initiated this call? */
|
#define USER_ENDPT m2_i2 /* which endpoint initiated this call? */
|
||||||
#define COUNT m2_i3 /* how many bytes to transfer */
|
#define COUNT m2_i3 /* how many bytes to transfer */
|
||||||
|
@ -225,7 +226,7 @@
|
||||||
#define ADDRESS m2_p1 /* core buffer address */
|
#define ADDRESS m2_p1 /* core buffer address */
|
||||||
#define IO_GRANT m2_p1 /* grant id (for DEV_*_S variants) */
|
#define IO_GRANT m2_p1 /* grant id (for DEV_*_S variants) */
|
||||||
|
|
||||||
/* Field names for DEV_SELECT messages to device drivers. */
|
/* Field names for DEV_SELECT messages to character device drivers. */
|
||||||
#define DEV_MINOR m2_i1 /* minor device */
|
#define DEV_MINOR m2_i1 /* minor device */
|
||||||
#define DEV_SEL_OPS m2_i2 /* which select operations are requested */
|
#define DEV_SEL_OPS m2_i2 /* which select operations are requested */
|
||||||
|
|
||||||
|
@ -1216,4 +1217,43 @@
|
||||||
#define VFS_TRANSID (VFS_TRANSACTION_BASE + 1)
|
#define VFS_TRANSID (VFS_TRANSACTION_BASE + 1)
|
||||||
#define IS_VFS_FS_TRANSID(type) (((type) & ~0xff) == VFS_TRANSACTION_BASE)
|
#define IS_VFS_FS_TRANSID(type) (((type) & ~0xff) == VFS_TRANSACTION_BASE)
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* Messages for block devices *
|
||||||
|
*===========================================================================*/
|
||||||
|
|
||||||
|
/* Base type for block device requests and responses. */
|
||||||
|
#define BDEV_RQ_BASE 0x1500
|
||||||
|
#define BDEV_RS_BASE 0x1580
|
||||||
|
|
||||||
|
#define IS_BDEV_RQ(type) (((type) & ~0x7f) == BDEV_RQ_BASE)
|
||||||
|
#define IS_BDEV_RS(type) (((type) & ~0x7f) == BDEV_RS_BASE)
|
||||||
|
|
||||||
|
/* Message types for block device requests. */
|
||||||
|
#define BDEV_OPEN (BDEV_RQ_BASE + 0) /* open a minor device */
|
||||||
|
#define BDEV_CLOSE (BDEV_RQ_BASE + 1) /* close a minor device */
|
||||||
|
#define BDEV_READ (BDEV_RQ_BASE + 2) /* read into a buffer */
|
||||||
|
#define BDEV_WRITE (BDEV_RQ_BASE + 3) /* write from a buffer */
|
||||||
|
#define BDEV_GATHER (BDEV_RQ_BASE + 4) /* read into a vector */
|
||||||
|
#define BDEV_SCATTER (BDEV_RQ_BASE + 5) /* write from a vector */
|
||||||
|
#define BDEV_IOCTL (BDEV_RQ_BASE + 6) /* I/O control operation */
|
||||||
|
|
||||||
|
/* Message types for block device responses. */
|
||||||
|
#define BDEV_REPLY (BDEV_RS_BASE + 0) /* general reply code */
|
||||||
|
|
||||||
|
/* Field names for block device messages. */
|
||||||
|
#define BDEV_MINOR m10_i1 /* minor device number */
|
||||||
|
#define BDEV_STATUS m10_i1 /* OK or error code */
|
||||||
|
#define BDEV_ACCESS m10_i2 /* access bits for open requests */
|
||||||
|
#define BDEV_REQUEST m10_i2 /* I/O control request */
|
||||||
|
#define BDEV_COUNT m10_i2 /* number of bytes or elements in transfer */
|
||||||
|
#define BDEV_GRANT m10_i3 /* grant ID of buffer or vector */
|
||||||
|
#define BDEV_FLAGS m10_i4 /* transfer flags */
|
||||||
|
#define BDEV_ID m10_l1 /* opaque request ID */
|
||||||
|
#define BDEV_POS_LO m10_l2 /* transfer position (low bits) */
|
||||||
|
#define BDEV_POS_HI m10_l3 /* transfer position (high bits) */
|
||||||
|
|
||||||
|
/* Bits in 'BDEV_FLAGS' field of block device transfer requests. */
|
||||||
|
# define BDEV_NOFLAGS 0x00 /* no flags are set */
|
||||||
|
# define BDEV_FORCEWRITE 0x01 /* force write to disk immediately */
|
||||||
|
|
||||||
/* _MINIX_COM_H */
|
/* _MINIX_COM_H */
|
||||||
|
|
|
@ -28,8 +28,8 @@ typedef struct { u16_t port; u32_t value; } pvl_pair_t;
|
||||||
(pv).port = _p; \
|
(pv).port = _p; \
|
||||||
(pv).value = _v; \
|
(pv).value = _v; \
|
||||||
if((pv).port != _p || (pv).value != _v) { \
|
if((pv).port != _p || (pv).value != _v) { \
|
||||||
printf("%s:%d: actual port: 0x%x != 0x%lx || " \
|
printf("%s:%d: actual port: 0x%x != 0x%x || " \
|
||||||
"actual value: 0x%x != 0x%lx\n", \
|
"actual value: 0x%x != 0x%x\n", \
|
||||||
__FILE__, __LINE__, (pv).port, _p, (pv).value, _v); \
|
__FILE__, __LINE__, (pv).port, _p, (pv).value, _v); \
|
||||||
panic("pv_set(" #pv ", " #p ", " #v ")"); \
|
panic("pv_set(" #pv ", " #p ", " #v ")"); \
|
||||||
} \
|
} \
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#ifndef __MINIX_DRIVER_H__
|
#ifndef _MINIX_DRIVER_H
|
||||||
#define __MINIX_DRIVER_H__
|
#define _MINIX_DRIVER_H
|
||||||
|
|
||||||
/* Types and constants shared between the generic and device dependent
|
/* Types and constants shared between block and character drivers. */
|
||||||
* device driver code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define _POSIX_SOURCE 1 /* tell headers to include POSIX stuff */
|
#define _POSIX_SOURCE 1 /* tell headers to include POSIX stuff */
|
||||||
#define _MINIX 1 /* tell headers to include MINIX stuff */
|
#define _MINIX 1 /* tell headers to include MINIX stuff */
|
||||||
|
@ -21,36 +19,13 @@
|
||||||
#include <minix/syslib.h>
|
#include <minix/syslib.h>
|
||||||
#include <minix/sysutil.h>
|
#include <minix/sysutil.h>
|
||||||
#include <minix/endpoint.h>
|
#include <minix/endpoint.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
#include <minix/partition.h>
|
|
||||||
#include <minix/u64.h>
|
#include <minix/u64.h>
|
||||||
|
#include <minix/partition.h>
|
||||||
typedef int thread_id_t;
|
|
||||||
|
|
||||||
/* Info about and entry points into the device dependent code. */
|
|
||||||
struct driver {
|
|
||||||
_PROTOTYPE( char *(*dr_name), (void) );
|
|
||||||
_PROTOTYPE( int (*dr_open), (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( int (*dr_close), (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( int (*dr_ioctl), (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( struct device *(*dr_prepare), (int device) );
|
|
||||||
_PROTOTYPE( int (*dr_transfer), (int proc_nr, int opcode, u64_t position,
|
|
||||||
iovec_t *iov, unsigned nr_req) );
|
|
||||||
_PROTOTYPE( void (*dr_cleanup), (void) );
|
|
||||||
_PROTOTYPE( void (*dr_geometry), (struct partition *entry) );
|
|
||||||
_PROTOTYPE( void (*dr_alarm), (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( int (*dr_cancel), (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( int (*dr_select), (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( int (*dr_other), (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( void (*dr_hw_int), (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( int (*dr_thread), (dev_t dev, thread_id_t *threadp) );
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Base and size of a partition in bytes. */
|
/* Base and size of a partition in bytes. */
|
||||||
struct device {
|
struct device {
|
||||||
|
@ -58,52 +33,12 @@ struct device {
|
||||||
u64_t dv_size;
|
u64_t dv_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DRIVER_STD 0 /* Use the standard reply protocol */
|
/* Generic receive function for all drivers. */
|
||||||
#define DRIVER_ASYN 1 /* Use the new asynchronous protocol */
|
#ifndef driver_receive
|
||||||
|
#define driver_receive sef_receive_status
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Maximum supported number of concurrently opened minor devices. */
|
||||||
#define MAX_NR_OPEN_DEVICES 256
|
#define MAX_NR_OPEN_DEVICES 256
|
||||||
|
|
||||||
#define IS_DEV_MINOR_RQ(type) (IS_DEV_RQ(type) && (type) != DEV_STATUS)
|
#endif /* _MINIX_DRIVER_H */
|
||||||
|
|
||||||
/* Functions defined by libdriver. These can be used for both singlethreaded
|
|
||||||
* and multithreaded drivers.
|
|
||||||
*/
|
|
||||||
_PROTOTYPE( void driver_announce, (void) );
|
|
||||||
_PROTOTYPE( char *no_name, (void) );
|
|
||||||
_PROTOTYPE( int do_nop, (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( struct device *nop_prepare, (int device) );
|
|
||||||
_PROTOTYPE( void nop_cleanup, (void) );
|
|
||||||
_PROTOTYPE( void nop_task, (void) );
|
|
||||||
_PROTOTYPE( void nop_alarm, (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( int nop_cancel, (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( int nop_select, (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( int do_diocntl, (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( int nop_ioctl, (struct driver *dp, message *m_ptr) );
|
|
||||||
|
|
||||||
#ifndef _DRIVER_MT_API
|
|
||||||
/* Additional functions for the singlethreaded version. These allow the driver
|
|
||||||
* to either use the stock driver_task(), or implement its own message loop.
|
|
||||||
* To avoid accidents, these functions are not exposed when minix/driver_mt.h
|
|
||||||
* has been included previously.
|
|
||||||
*/
|
|
||||||
_PROTOTYPE( int driver_receive, (endpoint_t src, message *m_ptr,
|
|
||||||
int *status_ptr) );
|
|
||||||
_PROTOTYPE( int driver_receive_mq, (message *m_ptr, int *status_ptr) );
|
|
||||||
_PROTOTYPE( void driver_handle_msg, (struct driver *dp, int type,
|
|
||||||
message *m_ptr, int ipc_status) );
|
|
||||||
_PROTOTYPE( void driver_terminate, (void) );
|
|
||||||
_PROTOTYPE( void driver_task, (struct driver *dr, int type) );
|
|
||||||
_PROTOTYPE( int driver_mq_queue, (message *m_ptr, int status) );
|
|
||||||
#endif /* !_DRIVER_MT_API */
|
|
||||||
|
|
||||||
/* Parameters for the disk drive. */
|
|
||||||
#define SECTOR_SIZE 512 /* physical sector size in bytes */
|
|
||||||
#define SECTOR_SHIFT 9 /* for division */
|
|
||||||
#define SECTOR_MASK 511 /* and remainder */
|
|
||||||
|
|
||||||
#define CD_SECTOR_SIZE 2048 /* sector size of a CD-ROM in bytes */
|
|
||||||
|
|
||||||
/* Size of the DMA buffer buffer in bytes. */
|
|
||||||
#define DMA_BUF_SIZE (DMA_SECTORS * SECTOR_SIZE)
|
|
||||||
|
|
||||||
#endif /* __MINIX_DRIVER_H__ */
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
#ifndef _MINIX_DRIVER_MT_H
|
|
||||||
#define _MINIX_DRIVER_MT_H
|
|
||||||
|
|
||||||
#define DRIVER_MT_API 1 /* do not expose the singlethreaded API */
|
|
||||||
#include <minix/driver.h>
|
|
||||||
|
|
||||||
/* The maximum number of worker threads. */
|
|
||||||
#define DRIVER_MT_MAX_WORKERS 32
|
|
||||||
|
|
||||||
_PROTOTYPE( void driver_mt_task, (struct driver *driver_p, int driver_type) );
|
|
||||||
_PROTOTYPE( void driver_mt_sleep, (void) );
|
|
||||||
_PROTOTYPE( void driver_mt_wakeup, (thread_id_t id) );
|
|
||||||
_PROTOTYPE( void driver_mt_stop, (void) );
|
|
||||||
_PROTOTYPE( void driver_mt_terminate, (void) );
|
|
||||||
|
|
||||||
#endif /* _MINIX_DRIVER_MT_H */
|
|
|
@ -4,19 +4,9 @@
|
||||||
|
|
||||||
#include <machine/partition.h>
|
#include <machine/partition.h>
|
||||||
|
|
||||||
_PROTOTYPE( void partition, (struct driver *dr, int device, int style, int atapi) );
|
_PROTOTYPE( void partition, (struct blockdriver *bdr, int device, int style,
|
||||||
|
int atapi) );
|
||||||
|
|
||||||
/* BIOS parameter table layout. */
|
|
||||||
#define bp_cylinders(t) (* (u16_t *) (&(t)[0]))
|
|
||||||
#define bp_heads(t) (* (u8_t *) (&(t)[2]))
|
|
||||||
#define bp_reduced_wr(t) (* (u16_t *) (&(t)[3]))
|
|
||||||
#define bp_precomp(t) (* (u16_t *) (&(t)[5]))
|
|
||||||
#define bp_max_ecc(t) (* (u8_t *) (&(t)[7]))
|
|
||||||
#define bp_ctlbyte(t) (* (u8_t *) (&(t)[8]))
|
|
||||||
#define bp_landingzone(t) (* (u16_t *) (&(t)[12]))
|
|
||||||
#define bp_sectors(t) (* (u8_t *) (&(t)[14]))
|
|
||||||
|
|
||||||
/* Miscellaneous. */
|
|
||||||
#define DEV_PER_DRIVE (1 + NR_PARTITIONS)
|
#define DEV_PER_DRIVE (1 + NR_PARTITIONS)
|
||||||
#define MINOR_t0 64
|
#define MINOR_t0 64
|
||||||
#define MINOR_r0 120
|
#define MINOR_r0 120
|
||||||
|
|
|
@ -29,6 +29,8 @@ typedef struct {int m7i1, m7i2, m7i3, m7i4, m7i5; char *m7p1, *m7p2;} mess_7;
|
||||||
typedef struct {int m8i1, m8i2; char *m8p1, *m8p2, *m8p3, *m8p4;} mess_8;
|
typedef struct {int m8i1, m8i2; char *m8p1, *m8p2, *m8p3, *m8p4;} mess_8;
|
||||||
typedef struct {long m9l1, m9l2, m9l3, m9l4, m9l5;
|
typedef struct {long m9l1, m9l2, m9l3, m9l4, m9l5;
|
||||||
short m9s1, m9s2, m9s3, m9s4; } mess_9;
|
short m9s1, m9s2, m9s3, m9s4; } mess_9;
|
||||||
|
typedef struct {int m10i1, m10i2, m10i3, m10i4;
|
||||||
|
long m10l1, m10l2, m10l3; } mess_10;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
endpoint_t m_source; /* who sent the message */
|
endpoint_t m_source; /* who sent the message */
|
||||||
|
@ -43,6 +45,7 @@ typedef struct {
|
||||||
mess_8 m_m8;
|
mess_8 m_m8;
|
||||||
mess_6 m_m6;
|
mess_6 m_m6;
|
||||||
mess_9 m_m9;
|
mess_9 m_m9;
|
||||||
|
mess_10 m_m10;
|
||||||
} m_u;
|
} m_u;
|
||||||
} message;
|
} message;
|
||||||
|
|
||||||
|
@ -118,6 +121,14 @@ typedef struct {
|
||||||
#define m9_s3 m_u.m_m9.m9s3
|
#define m9_s3 m_u.m_m9.m9s3
|
||||||
#define m9_s4 m_u.m_m9.m9s4
|
#define m9_s4 m_u.m_m9.m9s4
|
||||||
|
|
||||||
|
#define m10_i1 m_u.m_m10.m10i1
|
||||||
|
#define m10_i2 m_u.m_m10.m10i2
|
||||||
|
#define m10_i3 m_u.m_m10.m10i3
|
||||||
|
#define m10_i4 m_u.m_m10.m10i4
|
||||||
|
#define m10_l1 m_u.m_m10.m10l1
|
||||||
|
#define m10_l2 m_u.m_m10.m10l2
|
||||||
|
#define m10_l3 m_u.m_m10.m10l3
|
||||||
|
|
||||||
/*==========================================================================*
|
/*==========================================================================*
|
||||||
* Minix run-time system (IPC). *
|
* Minix run-time system (IPC). *
|
||||||
*==========================================================================*/
|
*==========================================================================*/
|
||||||
|
|
|
@ -138,8 +138,8 @@ ACPICA_SRCS= \
|
||||||
|
|
||||||
SRCS+=${ACPICA_SRCS}
|
SRCS+=${ACPICA_SRCS}
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS}
|
DPADD+= ${LIBSYS}
|
||||||
LDADD+= -ldriver -lsys
|
LDADD+= -lsys
|
||||||
|
|
||||||
CPPFLAGS += -I${.CURDIR}/include
|
CPPFLAGS += -I${.CURDIR}/include
|
||||||
CFLAGS += -DACPI_LIBRARY
|
CFLAGS += -DACPI_LIBRARY
|
||||||
|
|
|
@ -2,8 +2,12 @@
|
||||||
PROG= ahci
|
PROG= ahci
|
||||||
SRCS= ahci.c
|
SRCS= ahci.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS}
|
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS} ${LIBTIMERS} ${LIBMTHREAD}
|
||||||
LDADD+= -ldriver -lsys -ltimers -lmthread
|
LDADD+= -lblockdriver -lsys -ltimers -lmthread
|
||||||
|
|
||||||
|
.if ${COMPILER_TYPE} == "gnu"
|
||||||
|
LDADD+= -lc
|
||||||
|
.endif
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
* vectors completely filled with 64KB-blocks.
|
* vectors completely filled with 64KB-blocks.
|
||||||
*/
|
*/
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/driver_mt.h>
|
#include <minix/blockdriver_mt.h>
|
||||||
#include <minix/drvlib.h>
|
#include <minix/drvlib.h>
|
||||||
#include <machine/pci.h>
|
#include <machine/pci.h>
|
||||||
#include <sys/ioc_disk.h>
|
#include <sys/ioc_disk.h>
|
||||||
|
@ -180,9 +180,6 @@ PRIVATE int ahci_map[MAX_DRIVES]; /* device-to-port mapping */
|
||||||
|
|
||||||
PRIVATE int ahci_exiting = FALSE; /* exit after last close? */
|
PRIVATE int ahci_exiting = FALSE; /* exit after last close? */
|
||||||
|
|
||||||
PRIVATE struct port_state *current_port; /* currently selected port */
|
|
||||||
PRIVATE struct device *current_dev; /* currently selected device */
|
|
||||||
|
|
||||||
#define dprintf(v,s) do { \
|
#define dprintf(v,s) do { \
|
||||||
if (ahci_verbose >= (v)) \
|
if (ahci_verbose >= (v)) \
|
||||||
printf s; \
|
printf s; \
|
||||||
|
@ -195,35 +192,32 @@ PRIVATE int port_exec(struct port_state *ps, int cmd, clock_t timeout);
|
||||||
PRIVATE void port_timeout(struct timer *tp);
|
PRIVATE void port_timeout(struct timer *tp);
|
||||||
PRIVATE void port_disconnect(struct port_state *ps);
|
PRIVATE void port_disconnect(struct port_state *ps);
|
||||||
|
|
||||||
PRIVATE char *ahci_name(void);
|
|
||||||
PRIVATE char *ahci_portname(struct port_state *ps);
|
PRIVATE char *ahci_portname(struct port_state *ps);
|
||||||
PRIVATE int ahci_open(struct driver *UNUSED(dp), message *m);
|
PRIVATE int ahci_open(dev_t minor, int access);
|
||||||
PRIVATE int ahci_close(struct driver *UNUSED(dp), message *m);
|
PRIVATE int ahci_close(dev_t minor);
|
||||||
PRIVATE struct device *ahci_prepare(int minor);
|
PRIVATE ssize_t ahci_transfer(dev_t minor, int do_write, u64_t position,
|
||||||
PRIVATE int ahci_transfer(endpoint_t endpt, int opcode, u64_t position,
|
endpoint_t endpt, iovec_t *iovec, unsigned int count,
|
||||||
iovec_t *iovec, unsigned int nr_req);
|
int flags);
|
||||||
PRIVATE void ahci_geometry(struct partition *part);
|
PRIVATE struct device *ahci_part(dev_t minor);
|
||||||
PRIVATE void ahci_alarm(struct driver *UNUSED(dp), message *m);
|
PRIVATE void ahci_alarm(clock_t stamp);
|
||||||
PRIVATE int ahci_other(struct driver *UNUSED(dp), message *m);
|
PRIVATE int ahci_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||||
PRIVATE void ahci_intr(struct driver *UNUSED(dp), message *m);
|
cp_grant_id_t grant);
|
||||||
|
PRIVATE void ahci_intr(unsigned int irqs);
|
||||||
PRIVATE int ahci_thread(dev_t minor, thread_id_t *id);
|
PRIVATE int ahci_thread(dev_t minor, thread_id_t *id);
|
||||||
PRIVATE struct port_state *ahci_get_port(dev_t minor);
|
PRIVATE struct port_state *ahci_get_port(dev_t minor);
|
||||||
|
|
||||||
/* AHCI driver table. */
|
/* AHCI driver table. */
|
||||||
PRIVATE struct driver ahci_dtab = {
|
PRIVATE struct blockdriver ahci_dtab = {
|
||||||
ahci_name,
|
|
||||||
ahci_open,
|
ahci_open,
|
||||||
ahci_close,
|
ahci_close,
|
||||||
do_diocntl,
|
|
||||||
ahci_prepare,
|
|
||||||
ahci_transfer,
|
ahci_transfer,
|
||||||
nop_cleanup,
|
ahci_ioctl,
|
||||||
ahci_geometry,
|
NULL, /* bdr_cleanup */
|
||||||
ahci_alarm,
|
ahci_part,
|
||||||
nop_cancel,
|
NULL, /* bdr_geometry */
|
||||||
nop_select,
|
|
||||||
ahci_other,
|
|
||||||
ahci_intr,
|
ahci_intr,
|
||||||
|
ahci_alarm,
|
||||||
|
NULL, /* bdr_other */
|
||||||
ahci_thread
|
ahci_thread
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -950,16 +944,16 @@ PRIVATE int setup_prdt(struct port_state *ps, endpoint_t endpt,
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* port_transfer *
|
* port_transfer *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int port_transfer(struct port_state *ps, int cmd, u64_t pos, u64_t eof,
|
PRIVATE ssize_t port_transfer(struct port_state *ps, int cmd, u64_t pos,
|
||||||
endpoint_t endpt, iovec_s_t *iovec, int nr_req, int write)
|
u64_t eof, endpoint_t endpt, iovec_s_t *iovec, int nr_req, int write)
|
||||||
{
|
{
|
||||||
/* Perform an I/O transfer on a port.
|
/* Perform an I/O transfer on a port.
|
||||||
*/
|
*/
|
||||||
prd_t prdt[NR_PRDS];
|
prd_t prdt[NR_PRDS];
|
||||||
vir_bytes size, lead, chunk;
|
vir_bytes size, lead;
|
||||||
unsigned int count, nr_prds;
|
unsigned int count, nr_prds;
|
||||||
u64_t start_lba;
|
u64_t start_lba;
|
||||||
int i, r;
|
int r;
|
||||||
|
|
||||||
/* Get the total request size from the I/O vector. */
|
/* Get the total request size from the I/O vector. */
|
||||||
if ((r = sum_iovec(ps, endpt, iovec, nr_req, &size)) != OK)
|
if ((r = sum_iovec(ps, endpt, iovec, nr_req, &size)) != OK)
|
||||||
|
@ -996,7 +990,7 @@ PRIVATE int port_transfer(struct port_state *ps, int cmd, u64_t pos, u64_t eof,
|
||||||
if ((lead & 1) || (write && lead != 0)) {
|
if ((lead & 1) || (write && lead != 0)) {
|
||||||
dprintf(V_ERR, ("%s: unaligned position from %d\n",
|
dprintf(V_ERR, ("%s: unaligned position from %d\n",
|
||||||
ahci_portname(ps), endpt));
|
ahci_portname(ps), endpt));
|
||||||
return EIO;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write requests must be sector-aligned. Word alignment of the size is
|
/* Write requests must be sector-aligned. Word alignment of the size is
|
||||||
|
@ -1005,7 +999,7 @@ PRIVATE int port_transfer(struct port_state *ps, int cmd, u64_t pos, u64_t eof,
|
||||||
if (write && (size % ps->sector_size) != 0) {
|
if (write && (size % ps->sector_size) != 0) {
|
||||||
dprintf(V_ERR, ("%s: unaligned size %lu from %d\n",
|
dprintf(V_ERR, ("%s: unaligned size %lu from %d\n",
|
||||||
ahci_portname(ps), size, endpt));
|
ahci_portname(ps), size, endpt));
|
||||||
return EIO;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a vector of physical addresses and sizes for the transfer. */
|
/* Create a vector of physical addresses and sizes for the transfer. */
|
||||||
|
@ -1021,17 +1015,9 @@ PRIVATE int port_transfer(struct port_state *ps, int cmd, u64_t pos, u64_t eof,
|
||||||
r = ata_transfer(ps, cmd, start_lba, count, write, prdt,
|
r = ata_transfer(ps, cmd, start_lba, count, write, prdt,
|
||||||
nr_prds);
|
nr_prds);
|
||||||
|
|
||||||
if (r < 0) return r;
|
if (r != OK) return r;
|
||||||
|
|
||||||
/* The entire operation succeeded; update the original vector. */
|
return size;
|
||||||
for (i = 0; i < nr_req && size > 0; i++) {
|
|
||||||
chunk = MIN(iovec[i].iov_size, size);
|
|
||||||
|
|
||||||
iovec[i].iov_size -= chunk;
|
|
||||||
size -= chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -1478,7 +1464,7 @@ PRIVATE void port_timeout(struct timer *tp)
|
||||||
* is suspended.
|
* is suspended.
|
||||||
*/
|
*/
|
||||||
if (ps->flags & FLAG_SUSPENDED)
|
if (ps->flags & FLAG_SUSPENDED)
|
||||||
driver_mt_wakeup(ps->device);
|
blockdriver_mt_wakeup(ps->device);
|
||||||
|
|
||||||
/* If detection of a device after startup timed out, give up on initial
|
/* If detection of a device after startup timed out, give up on initial
|
||||||
* detection and only look for hot plug events from now on.
|
* detection and only look for hot plug events from now on.
|
||||||
|
@ -1554,7 +1540,7 @@ PRIVATE void port_wait(struct port_state *ps)
|
||||||
ps->flags |= FLAG_SUSPENDED;
|
ps->flags |= FLAG_SUSPENDED;
|
||||||
|
|
||||||
while (ps->flags & FLAG_BUSY)
|
while (ps->flags & FLAG_BUSY)
|
||||||
driver_mt_sleep();
|
blockdriver_mt_sleep();
|
||||||
|
|
||||||
ps->flags &= ~FLAG_SUSPENDED;
|
ps->flags &= ~FLAG_SUSPENDED;
|
||||||
}
|
}
|
||||||
|
@ -1865,9 +1851,9 @@ PRIVATE void ahci_init(int devind)
|
||||||
hba_state.nr_cmds = MIN(NR_CMDS,
|
hba_state.nr_cmds = MIN(NR_CMDS,
|
||||||
((cap >> AHCI_HBA_CAP_NCS_SHIFT) & AHCI_HBA_CAP_NCS_MASK) + 1);
|
((cap >> AHCI_HBA_CAP_NCS_SHIFT) & AHCI_HBA_CAP_NCS_MASK) + 1);
|
||||||
|
|
||||||
dprintf(V_INFO, ("%s: HBA v%d.%d%d, %ld ports, %ld commands, "
|
dprintf(V_INFO, ("AHCI%u: HBA v%d.%d%d, %ld ports, %ld commands, "
|
||||||
"%s queuing, IRQ %d\n",
|
"%s queuing, IRQ %d\n",
|
||||||
ahci_name(),
|
ahci_instance,
|
||||||
(int) (hba_state.base[AHCI_HBA_VS] >> 16),
|
(int) (hba_state.base[AHCI_HBA_VS] >> 16),
|
||||||
(int) ((hba_state.base[AHCI_HBA_VS] >> 8) & 0xFF),
|
(int) ((hba_state.base[AHCI_HBA_VS] >> 8) & 0xFF),
|
||||||
(int) (hba_state.base[AHCI_HBA_VS] & 0xFF),
|
(int) (hba_state.base[AHCI_HBA_VS] & 0xFF),
|
||||||
|
@ -1875,8 +1861,8 @@ PRIVATE void ahci_init(int devind)
|
||||||
((cap >> AHCI_HBA_CAP_NCS_SHIFT) & AHCI_HBA_CAP_NCS_MASK) + 1,
|
((cap >> AHCI_HBA_CAP_NCS_SHIFT) & AHCI_HBA_CAP_NCS_MASK) + 1,
|
||||||
(cap & AHCI_HBA_CAP_SNCQ) ? "supports" : "no",
|
(cap & AHCI_HBA_CAP_SNCQ) ? "supports" : "no",
|
||||||
hba_state.irq));
|
hba_state.irq));
|
||||||
dprintf(V_INFO, ("%s: CAP %08x, CAP2 %08x, PI %08x\n",
|
dprintf(V_INFO, ("AHCI%u: CAP %08x, CAP2 %08x, PI %08x\n",
|
||||||
ahci_name(), cap, hba_state.base[AHCI_HBA_CAP2],
|
ahci_instance, cap, hba_state.base[AHCI_HBA_CAP2],
|
||||||
hba_state.base[AHCI_HBA_PI]));
|
hba_state.base[AHCI_HBA_PI]));
|
||||||
|
|
||||||
/* Initialize each of the implemented ports. We ignore CAP.NP. */
|
/* Initialize each of the implemented ports. We ignore CAP.NP. */
|
||||||
|
@ -1924,19 +1910,19 @@ PRIVATE void ahci_stop(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* ahci_alarm *
|
* ahci_alarm *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void ahci_alarm(struct driver *UNUSED(dp), message *m)
|
PRIVATE void ahci_alarm(clock_t stamp)
|
||||||
{
|
{
|
||||||
/* Process an alarm.
|
/* Process an alarm.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Call the port-specific handler for each port that timed out. */
|
/* Call the port-specific handler for each port that timed out. */
|
||||||
expire_timers(m->NOTIFY_TIMESTAMP);
|
expire_timers(stamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* ahci_intr *
|
* ahci_intr *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void ahci_intr(struct driver *UNUSED(dr), message *UNUSED(m))
|
PRIVATE void ahci_intr(unsigned int UNUSED(irqs))
|
||||||
{
|
{
|
||||||
/* Process an interrupt.
|
/* Process an interrupt.
|
||||||
*/
|
*/
|
||||||
|
@ -1958,7 +1944,7 @@ PRIVATE void ahci_intr(struct driver *UNUSED(dr), message *UNUSED(m))
|
||||||
*/
|
*/
|
||||||
if ((ps->flags & (FLAG_SUSPENDED | FLAG_BUSY)) ==
|
if ((ps->flags & (FLAG_SUSPENDED | FLAG_BUSY)) ==
|
||||||
FLAG_SUSPENDED)
|
FLAG_SUSPENDED)
|
||||||
driver_mt_wakeup(ps->device);
|
blockdriver_mt_wakeup(ps->device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2093,8 +2079,8 @@ PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
/* Create a mapping from device nodes to port numbers. */
|
/* Create a mapping from device nodes to port numbers. */
|
||||||
ahci_set_mapping();
|
ahci_set_mapping();
|
||||||
|
|
||||||
/* Announce we are up. */
|
/* Announce that we are up. */
|
||||||
driver_announce();
|
blockdriver_announce();
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -2145,21 +2131,6 @@ PRIVATE void sef_local_startup(void)
|
||||||
sef_startup();
|
sef_startup();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* ahci_name *
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE char *ahci_name(void)
|
|
||||||
{
|
|
||||||
/* Return a printable name for the controller. We avoid the use of the
|
|
||||||
* currently selected port, as it may not be accurate.
|
|
||||||
*/
|
|
||||||
static char name[] = "AHCI0";
|
|
||||||
|
|
||||||
name[4] = '0' + ahci_instance;
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* ahci_portname *
|
* ahci_portname *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -2188,17 +2159,18 @@ PRIVATE char *ahci_portname(struct port_state *ps)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* ahci_prepare *
|
* ahci_map_minor *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE struct device *ahci_prepare(int minor)
|
PRIVATE struct port_state *ahci_map_minor(dev_t minor, struct device **dvp)
|
||||||
{
|
{
|
||||||
/* Select a device, in the form of a port and (sub)partition, based on
|
/* Map a minor device number to a port and a pointer to the partition's
|
||||||
* the given minor device number and the device-to-port mapping.
|
* device structure. Return NULL if this minor device number does not
|
||||||
|
* identify an actual device.
|
||||||
*/
|
*/
|
||||||
|
struct port_state *ps;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
current_port = NULL;
|
ps = NULL;
|
||||||
current_dev = NULL;
|
|
||||||
|
|
||||||
if (minor < NR_MINORS) {
|
if (minor < NR_MINORS) {
|
||||||
port = ahci_map[minor / DEV_PER_DRIVE];
|
port = ahci_map[minor / DEV_PER_DRIVE];
|
||||||
|
@ -2206,8 +2178,8 @@ PRIVATE struct device *ahci_prepare(int minor)
|
||||||
if (port == NO_PORT)
|
if (port == NO_PORT)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
current_port = &port_state[port];
|
ps = &port_state[port];
|
||||||
current_dev = ¤t_port->part[minor % DEV_PER_DRIVE];
|
*dvp = &ps->part[minor % DEV_PER_DRIVE];
|
||||||
}
|
}
|
||||||
else if ((unsigned) (minor -= MINOR_d0p0s0) < NR_SUBDEVS) {
|
else if ((unsigned) (minor -= MINOR_d0p0s0) < NR_SUBDEVS) {
|
||||||
port = ahci_map[minor / SUB_PER_DRIVE];
|
port = ahci_map[minor / SUB_PER_DRIVE];
|
||||||
|
@ -2215,24 +2187,40 @@ PRIVATE struct device *ahci_prepare(int minor)
|
||||||
if (port == NO_PORT)
|
if (port == NO_PORT)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
current_port = &port_state[port];
|
ps = &port_state[port];
|
||||||
current_dev = ¤t_port->subpart[minor % SUB_PER_DRIVE];
|
*dvp = &ps->subpart[minor % SUB_PER_DRIVE];
|
||||||
}
|
}
|
||||||
|
|
||||||
return current_dev;
|
return ps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* ahci_part *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE struct device *ahci_part(dev_t minor)
|
||||||
|
{
|
||||||
|
/* Return a pointer to the partition information structure of the given
|
||||||
|
* minor device.
|
||||||
|
*/
|
||||||
|
struct device *dv;
|
||||||
|
|
||||||
|
if (ahci_map_minor(minor, &dv) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return dv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* ahci_open *
|
* ahci_open *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int ahci_open(struct driver *UNUSED(dp), message *m)
|
PRIVATE int ahci_open(dev_t minor, int access)
|
||||||
{
|
{
|
||||||
/* Open a device.
|
/* Open a device.
|
||||||
*/
|
*/
|
||||||
struct port_state *ps;
|
struct port_state *ps;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
ps = ahci_get_port(m->DEVICE);
|
ps = ahci_get_port(minor);
|
||||||
|
|
||||||
/* If we are still in the process of initializing this port or device,
|
/* If we are still in the process of initializing this port or device,
|
||||||
* wait for completion of that phase first.
|
* wait for completion of that phase first.
|
||||||
|
@ -2247,7 +2235,7 @@ PRIVATE int ahci_open(struct driver *UNUSED(dp), message *m)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Some devices may only be opened in read-only mode. */
|
/* Some devices may only be opened in read-only mode. */
|
||||||
if ((ps->flags & FLAG_READONLY) && (m->COUNT & W_BIT)) {
|
if ((ps->flags & FLAG_READONLY) && (access & W_BIT)) {
|
||||||
r = EACCES;
|
r = EACCES;
|
||||||
goto err_stop;
|
goto err_stop;
|
||||||
}
|
}
|
||||||
|
@ -2290,7 +2278,7 @@ PRIVATE int ahci_open(struct driver *UNUSED(dp), message *m)
|
||||||
err_stop:
|
err_stop:
|
||||||
/* Stop the thread if the device is now fully closed. */
|
/* Stop the thread if the device is now fully closed. */
|
||||||
if (ps->open_count == 0)
|
if (ps->open_count == 0)
|
||||||
driver_mt_stop();
|
blockdriver_mt_stop();
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -2298,14 +2286,14 @@ err_stop:
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* ahci_close *
|
* ahci_close *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int ahci_close(struct driver *UNUSED(dp), message *m)
|
PRIVATE int ahci_close(dev_t minor)
|
||||||
{
|
{
|
||||||
/* Close a device.
|
/* Close a device.
|
||||||
*/
|
*/
|
||||||
struct port_state *ps;
|
struct port_state *ps;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
ps = ahci_get_port(m->DEVICE);
|
ps = ahci_get_port(minor);
|
||||||
|
|
||||||
/* Decrease the open count. */
|
/* Decrease the open count. */
|
||||||
if (ps->open_count <= 0) {
|
if (ps->open_count <= 0) {
|
||||||
|
@ -2323,7 +2311,7 @@ PRIVATE int ahci_close(struct driver *UNUSED(dp), message *m)
|
||||||
/* The device is now fully closed. That also means that the thread for
|
/* The device is now fully closed. That also means that the thread for
|
||||||
* this device is not needed anymore.
|
* this device is not needed anymore.
|
||||||
*/
|
*/
|
||||||
driver_mt_stop();
|
blockdriver_mt_stop();
|
||||||
|
|
||||||
if (ps->state == STATE_GOOD_DEV && !(ps->flags & FLAG_BARRIER)) {
|
if (ps->state == STATE_GOOD_DEV && !(ps->flags & FLAG_BARRIER)) {
|
||||||
dprintf(V_INFO, ("%s: flushing write cache\n",
|
dprintf(V_INFO, ("%s: flushing write cache\n",
|
||||||
|
@ -2333,8 +2321,8 @@ PRIVATE int ahci_close(struct driver *UNUSED(dp), message *m)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the entire driver has been told to terminate, check whether all
|
/* If the entire driver has been told to terminate, check whether all
|
||||||
* devices are now closed. If so, tell libdriver to quit after replying
|
* devices are now closed. If so, tell libblockdriver to quit after
|
||||||
* to the close request.
|
* replying to the close request.
|
||||||
*/
|
*/
|
||||||
if (ahci_exiting) {
|
if (ahci_exiting) {
|
||||||
for (port = 0; port < hba_state.nr_ports; port++)
|
for (port = 0; port < hba_state.nr_ports; port++)
|
||||||
|
@ -2344,7 +2332,7 @@ PRIVATE int ahci_close(struct driver *UNUSED(dp), message *m)
|
||||||
if (port == hba_state.nr_ports) {
|
if (port == hba_state.nr_ports) {
|
||||||
ahci_stop();
|
ahci_stop();
|
||||||
|
|
||||||
driver_mt_terminate();
|
blockdriver_mt_terminate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2354,76 +2342,53 @@ PRIVATE int ahci_close(struct driver *UNUSED(dp), message *m)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* ahci_transfer *
|
* ahci_transfer *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int ahci_transfer(endpoint_t endpt, int opcode, u64_t position,
|
PRIVATE ssize_t ahci_transfer(dev_t minor, int do_write, u64_t position,
|
||||||
iovec_t *iovec, unsigned int nr_req)
|
endpoint_t endpt, iovec_t *iovec, unsigned int count,
|
||||||
|
int UNUSED(flags))
|
||||||
{
|
{
|
||||||
/* Perform data transfer on the selected device.
|
/* Perform data transfer on the selected device.
|
||||||
*/
|
*/
|
||||||
|
struct port_state *ps;
|
||||||
|
struct device *dv;
|
||||||
u64_t pos, eof;
|
u64_t pos, eof;
|
||||||
|
|
||||||
/* We can safely use current_port, as we won't get interrupted until
|
ps = ahci_get_port(minor);
|
||||||
* the call to port_transfer(), after which it is no longer used.
|
dv = ahci_part(minor);
|
||||||
* Nonpreemptive threading guarantees that we will not be descheduled
|
|
||||||
* before then.
|
|
||||||
*/
|
|
||||||
assert(current_port != NULL);
|
|
||||||
assert(current_dev != NULL);
|
|
||||||
|
|
||||||
if (current_port->state != STATE_GOOD_DEV ||
|
if (ps->state != STATE_GOOD_DEV || (ps->flags & FLAG_BARRIER))
|
||||||
(current_port->flags & FLAG_BARRIER))
|
|
||||||
return EIO;
|
return EIO;
|
||||||
|
|
||||||
if (nr_req > NR_IOREQS)
|
if (count > NR_IOREQS)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
/* Check for basic end-of-partition condition: if the start position of
|
/* Check for basic end-of-partition condition: if the start position of
|
||||||
* the request is outside the partition, return success immediately.
|
* the request is outside the partition, return success immediately.
|
||||||
* The size of the request is obtained, and possibly reduced, later.
|
* The size of the request is obtained, and possibly reduced, later.
|
||||||
*/
|
*/
|
||||||
if (cmp64(position, current_dev->dv_size) >= 0)
|
if (cmp64(position, dv->dv_size) >= 0)
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
pos = add64(current_dev->dv_base, position);
|
pos = add64(dv->dv_base, position);
|
||||||
eof = add64(current_dev->dv_base, current_dev->dv_size);
|
eof = add64(dv->dv_base, dv->dv_size);
|
||||||
|
|
||||||
return port_transfer(current_port, 0, pos, eof, endpt,
|
return port_transfer(ps, 0, pos, eof, endpt, (iovec_s_t *) iovec,
|
||||||
(iovec_s_t *) iovec, nr_req, opcode == DEV_SCATTER_S);
|
count, do_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* ahci_geometry *
|
* ahci_ioctl *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void ahci_geometry(struct partition *part)
|
PRIVATE int ahci_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||||
|
cp_grant_id_t grant)
|
||||||
{
|
{
|
||||||
/* Fill in old-style geometry. We have to supply nonzero numbers, or
|
/* Process I/O control requests.
|
||||||
* part(8) crashes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
assert(current_port->sector_size != 0);
|
|
||||||
|
|
||||||
part->cylinders = div64u(current_port->part[0].dv_size,
|
|
||||||
current_port->sector_size) / (64 * 32);
|
|
||||||
part->heads = 64;
|
|
||||||
part->sectors = 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* ahci_other *
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE int ahci_other(struct driver *UNUSED(dp), message *m)
|
|
||||||
{
|
|
||||||
/* Process any messages not covered by the other calls.
|
|
||||||
* This function only implements IOCTLs.
|
|
||||||
*/
|
*/
|
||||||
struct port_state *ps;
|
struct port_state *ps;
|
||||||
int r, val;
|
int r, val;
|
||||||
|
|
||||||
if (m->m_type != DEV_IOCTL_S)
|
ps = ahci_get_port(minor);
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
ps = ahci_get_port(m->DEVICE);
|
switch (request) {
|
||||||
|
|
||||||
switch (m->REQUEST) {
|
|
||||||
case DIOCEJECT:
|
case DIOCEJECT:
|
||||||
if (ps->state != STATE_GOOD_DEV || (ps->flags & FLAG_BARRIER))
|
if (ps->state != STATE_GOOD_DEV || (ps->flags & FLAG_BARRIER))
|
||||||
return EIO;
|
return EIO;
|
||||||
|
@ -2434,9 +2399,8 @@ PRIVATE int ahci_other(struct driver *UNUSED(dp), message *m)
|
||||||
return atapi_load_eject(ps, 0, FALSE /*load*/);
|
return atapi_load_eject(ps, 0, FALSE /*load*/);
|
||||||
|
|
||||||
case DIOCOPENCT:
|
case DIOCOPENCT:
|
||||||
return sys_safecopyto(m->m_source, (cp_grant_id_t) m->IO_GRANT,
|
return sys_safecopyto(endpt, grant, 0,
|
||||||
0, (vir_bytes) &ps->open_count, sizeof(ps->open_count),
|
(vir_bytes) &ps->open_count, sizeof(ps->open_count), D);
|
||||||
D);
|
|
||||||
|
|
||||||
case DIOCFLUSH:
|
case DIOCFLUSH:
|
||||||
if (ps->state != STATE_GOOD_DEV || (ps->flags & FLAG_BARRIER))
|
if (ps->state != STATE_GOOD_DEV || (ps->flags & FLAG_BARRIER))
|
||||||
|
@ -2448,8 +2412,7 @@ PRIVATE int ahci_other(struct driver *UNUSED(dp), message *m)
|
||||||
if (ps->state != STATE_GOOD_DEV || (ps->flags & FLAG_BARRIER))
|
if (ps->state != STATE_GOOD_DEV || (ps->flags & FLAG_BARRIER))
|
||||||
return EIO;
|
return EIO;
|
||||||
|
|
||||||
if ((r = sys_safecopyfrom(m->m_source,
|
if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &val,
|
||||||
(cp_grant_id_t) m->IO_GRANT, 0, (vir_bytes) &val,
|
|
||||||
sizeof(val), D)) != OK)
|
sizeof(val), D)) != OK)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -2462,8 +2425,8 @@ PRIVATE int ahci_other(struct driver *UNUSED(dp), message *m)
|
||||||
if ((r = gen_get_wcache(ps, 0, &val)) != OK)
|
if ((r = gen_get_wcache(ps, 0, &val)) != OK)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
return sys_safecopyto(m->m_source, (cp_grant_id_t) m->IO_GRANT,
|
return sys_safecopyto(endpt, grant, 0, (vir_bytes) &val,
|
||||||
0, (vir_bytes) &val, sizeof(val), D);
|
sizeof(val), D);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
@ -2476,11 +2439,13 @@ PRIVATE int ahci_thread(dev_t minor, thread_id_t *id)
|
||||||
{
|
{
|
||||||
/* Map a device number to a worker thread number.
|
/* Map a device number to a worker thread number.
|
||||||
*/
|
*/
|
||||||
|
struct port_state *ps;
|
||||||
|
struct device *dv;
|
||||||
|
|
||||||
if (ahci_prepare(minor) == NULL)
|
if ((ps = ahci_map_minor(minor, &dv)) == NULL)
|
||||||
return ENXIO;
|
return ENXIO;
|
||||||
|
|
||||||
*id = current_port->device;
|
*id = ps->device;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -2494,11 +2459,13 @@ PRIVATE struct port_state *ahci_get_port(dev_t minor)
|
||||||
* Called only from worker threads, so the minor device is already
|
* Called only from worker threads, so the minor device is already
|
||||||
* guaranteed to map to a port.
|
* guaranteed to map to a port.
|
||||||
*/
|
*/
|
||||||
|
struct port_state *ps;
|
||||||
|
struct device *dv;
|
||||||
|
|
||||||
if (ahci_prepare(minor) == NULL)
|
if ((ps = ahci_map_minor(minor, &dv)) == NULL)
|
||||||
panic("device mapping for minor %d disappeared", minor);
|
panic("device mapping for minor %d disappeared", minor);
|
||||||
|
|
||||||
return current_port;
|
return ps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -2512,7 +2479,7 @@ PUBLIC int main(int argc, char **argv)
|
||||||
env_setargs(argc, argv);
|
env_setargs(argc, argv);
|
||||||
sef_local_startup();
|
sef_local_startup();
|
||||||
|
|
||||||
driver_mt_task(&ahci_dtab, DRIVER_STD);
|
blockdriver_mt_task(&ahci_dtab);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
PROG= amddev
|
PROG= amddev
|
||||||
SRCS= amddev.c
|
SRCS= amddev.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS}
|
DPADD+= ${LIBSYS}
|
||||||
LDADD+= -ldriver -lsys
|
LDADD+= -lsys
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ PRIVATE void sef_local_startup()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_cb_init_fresh *
|
* sef_cb_init_fresh *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
|
PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
{
|
{
|
||||||
/* Initialize the amddev driver. */
|
/* Initialize the amddev driver. */
|
||||||
int r, n_maps, n_domains, revision;
|
int r, n_maps, n_domains, revision;
|
||||||
|
@ -150,9 +150,6 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
|
||||||
|
|
||||||
printf("after write: DEVF_CR: 0x%x\n", read_reg(DEVF_CR, 0));
|
printf("after write: DEVF_CR: 0x%x\n", read_reg(DEVF_CR, 0));
|
||||||
|
|
||||||
/* Announce we are up! */
|
|
||||||
driver_announce();
|
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +181,7 @@ PRIVATE void sef_cb_signal_handler(int signo)
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(
|
printf(
|
||||||
"amddev: deleting 0x%x@0x%x for proc %d\n",
|
"amddev: deleting 0x%lx@0x%lx for proc %d\n",
|
||||||
size, base, proc_e);
|
size, base, proc_e);
|
||||||
del_range(base, size);
|
del_range(base, size);
|
||||||
r= deldma(proc_e, base, size);
|
r= deldma(proc_e, base, size);
|
||||||
|
@ -302,7 +299,7 @@ static void init_domain(int index)
|
||||||
memset(table, 0x00, size);
|
memset(table, 0x00, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("init_domain: busaddr = %p\n", busaddr);
|
printf("init_domain: busaddr = 0x%lx\n", busaddr);
|
||||||
|
|
||||||
write_reg(DEVF_BASE_HI, index, 0);
|
write_reg(DEVF_BASE_HI, index, 0);
|
||||||
write_reg(DEVF_BASE_LO, index, busaddr | 3);
|
write_reg(DEVF_BASE_LO, index, busaddr | 3);
|
||||||
|
@ -387,12 +384,12 @@ static int do_add4pci(const message *m)
|
||||||
pci_func= m->m1_i3;
|
pci_func= m->m1_i3;
|
||||||
|
|
||||||
printf(
|
printf(
|
||||||
"amddev`do_add4pci: got request for 0x%x@0x%x from %d for pci dev %u.%u.%u\n",
|
"amddev`do_add4pci: got request for 0x%x@0x%lx from %d for pci dev %u.%u.%u\n",
|
||||||
size, start, proc, pci_bus, pci_dev, pci_func);
|
size, start, proc, pci_bus, pci_dev, pci_func);
|
||||||
|
|
||||||
if (start % I386_PAGE_SIZE)
|
if (start % I386_PAGE_SIZE)
|
||||||
{
|
{
|
||||||
printf("amddev`do_add4pci: bad start 0x%x from proc %d\n",
|
printf("amddev`do_add4pci: bad start 0x%lx from proc %d\n",
|
||||||
start, proc);
|
start, proc);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -409,7 +406,7 @@ static int do_add4pci(const message *m)
|
||||||
if (r != OK)
|
if (r != OK)
|
||||||
{
|
{
|
||||||
printf(
|
printf(
|
||||||
"amddev`do_add4pci: umap failed for 0x%x@0x%x, proc %d: %d\n",
|
"amddev`do_add4pci: umap failed for 0x%x@0x%lx, proc %d: %d\n",
|
||||||
size, start, proc, r);
|
size, start, proc, r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -419,7 +416,7 @@ static int do_add4pci(const message *m)
|
||||||
{
|
{
|
||||||
r= -errno;
|
r= -errno;
|
||||||
printf(
|
printf(
|
||||||
"amddev`do_add4pci: adddma failed for 0x%x@0x%x, proc %d: %d\n",
|
"amddev`do_add4pci: adddma failed for 0x%x@0x%lx, proc %d: %d\n",
|
||||||
size, start, proc, r);
|
size, start, proc, r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
PROG= at_wini
|
PROG= at_wini
|
||||||
SRCS= at_wini.c liveupdate.c
|
SRCS= at_wini.c liveupdate.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
|
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS} ${LIBTIMERS}
|
||||||
LDADD+= -ldriver -lsys -ltimers
|
LDADD+= -lblockdriver -lsys -ltimers
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ PRIVATE struct quirk
|
||||||
{ 0x01, 0x04, 0x00, 0x1106, 0x3149 }, /* VIA VT6420 */
|
{ 0x01, 0x04, 0x00, 0x1106, 0x3149 }, /* VIA VT6420 */
|
||||||
{ 0x01, 0x04, 0x00, 0x1095, 0x3512 },
|
{ 0x01, 0x04, 0x00, 0x1095, 0x3512 },
|
||||||
{ 0x01, 0x80, -1, 0x1095, 0x3114 }, /* Silicon Image SATA */
|
{ 0x01, 0x80, -1, 0x1095, 0x3114 }, /* Silicon Image SATA */
|
||||||
{ 0, 0, 0, 0 } /* end of list */
|
{ 0, 0, 0, 0, 0 } /* end of list */
|
||||||
};
|
};
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( void init_params, (void) );
|
FORWARD _PROTOTYPE( void init_params, (void) );
|
||||||
|
@ -141,23 +141,26 @@ FORWARD _PROTOTYPE( void init_drive, (struct wini *w, int base_cmd,
|
||||||
int base_ctl, int base_dma, int irq, int ack, int hook,
|
int base_ctl, int base_dma, int irq, int ack, int hook,
|
||||||
int drive) );
|
int drive) );
|
||||||
FORWARD _PROTOTYPE( void init_params_pci, (int) );
|
FORWARD _PROTOTYPE( void init_params_pci, (int) );
|
||||||
FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int w_do_open, (dev_t minor, int access) );
|
||||||
FORWARD _PROTOTYPE( struct device *w_prepare, (int dev) );
|
FORWARD _PROTOTYPE( struct device *w_prepare, (dev_t dev) );
|
||||||
|
FORWARD _PROTOTYPE( struct device *w_part, (dev_t minor) );
|
||||||
FORWARD _PROTOTYPE( int w_identify, (void) );
|
FORWARD _PROTOTYPE( int w_identify, (void) );
|
||||||
FORWARD _PROTOTYPE( char *w_name, (void) );
|
FORWARD _PROTOTYPE( char *w_name, (void) );
|
||||||
FORWARD _PROTOTYPE( int w_specify, (void) );
|
FORWARD _PROTOTYPE( int w_specify, (void) );
|
||||||
FORWARD _PROTOTYPE( int w_io_test, (void) );
|
FORWARD _PROTOTYPE( int w_io_test, (void) );
|
||||||
FORWARD _PROTOTYPE( int w_transfer, (endpoint_t proc_nr, int opcode,
|
FORWARD _PROTOTYPE( ssize_t w_transfer, (dev_t minor, int do_write,
|
||||||
u64_t position, iovec_t *iov, unsigned nr_req) );
|
u64_t position, endpoint_t proc_nr, iovec_t *iov,
|
||||||
|
unsigned int nr_req, int flags) );
|
||||||
FORWARD _PROTOTYPE( int com_out, (struct command *cmd) );
|
FORWARD _PROTOTYPE( int com_out, (struct command *cmd) );
|
||||||
FORWARD _PROTOTYPE( int com_out_ext, (struct command *cmd) );
|
FORWARD _PROTOTYPE( int com_out_ext, (struct command *cmd) );
|
||||||
FORWARD _PROTOTYPE( int setup_dma, (unsigned *sizep, endpoint_t proc_nr,
|
FORWARD _PROTOTYPE( int setup_dma, (unsigned *sizep, endpoint_t proc_nr,
|
||||||
iovec_t *iov, size_t addr_offset, int do_write) );
|
iovec_t *iov, size_t addr_offset, int do_write) );
|
||||||
FORWARD _PROTOTYPE( void w_need_reset, (void) );
|
FORWARD _PROTOTYPE( void w_need_reset, (void) );
|
||||||
FORWARD _PROTOTYPE( void ack_irqs, (unsigned int) );
|
FORWARD _PROTOTYPE( void ack_irqs, (unsigned int) );
|
||||||
FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int w_do_close, (dev_t minor) );
|
||||||
FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int w_ioctl, (dev_t minor, unsigned int request,
|
||||||
FORWARD _PROTOTYPE( void w_hw_int, (struct driver *dp, message *m_ptr) );
|
endpoint_t endpt, cp_grant_id_t grant) );
|
||||||
|
FORWARD _PROTOTYPE( void w_hw_int, (unsigned int irqs) );
|
||||||
FORWARD _PROTOTYPE( int com_simple, (struct command *cmd) );
|
FORWARD _PROTOTYPE( int com_simple, (struct command *cmd) );
|
||||||
FORWARD _PROTOTYPE( void w_timeout, (void) );
|
FORWARD _PROTOTYPE( void w_timeout, (void) );
|
||||||
FORWARD _PROTOTYPE( int w_reset, (void) );
|
FORWARD _PROTOTYPE( int w_reset, (void) );
|
||||||
|
@ -165,28 +168,30 @@ FORWARD _PROTOTYPE( void w_intr_wait, (void) );
|
||||||
FORWARD _PROTOTYPE( int at_intr_wait, (void) );
|
FORWARD _PROTOTYPE( int at_intr_wait, (void) );
|
||||||
FORWARD _PROTOTYPE( int w_waitfor, (int mask, int value) );
|
FORWARD _PROTOTYPE( int w_waitfor, (int mask, int value) );
|
||||||
FORWARD _PROTOTYPE( int w_waitfor_dma, (int mask, int value) );
|
FORWARD _PROTOTYPE( int w_waitfor_dma, (int mask, int value) );
|
||||||
FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry) );
|
FORWARD _PROTOTYPE( void w_geometry, (dev_t minor,
|
||||||
|
struct partition *entry) );
|
||||||
#if ENABLE_ATAPI
|
#if ENABLE_ATAPI
|
||||||
FORWARD _PROTOTYPE( int atapi_sendpacket, (u8_t *packet, unsigned cnt, int do_dma) );
|
FORWARD _PROTOTYPE( int atapi_sendpacket, (u8_t *packet, unsigned cnt,
|
||||||
|
int do_dma) );
|
||||||
FORWARD _PROTOTYPE( int atapi_intr_wait, (int dma, size_t max) );
|
FORWARD _PROTOTYPE( int atapi_intr_wait, (int dma, size_t max) );
|
||||||
FORWARD _PROTOTYPE( int atapi_open, (void) );
|
FORWARD _PROTOTYPE( int atapi_open, (void) );
|
||||||
FORWARD _PROTOTYPE( void atapi_close, (void) );
|
FORWARD _PROTOTYPE( void atapi_close, (void) );
|
||||||
FORWARD _PROTOTYPE( int atapi_transfer, (int proc_nr, int opcode,
|
FORWARD _PROTOTYPE( int atapi_transfer, (int do_write, u64_t position,
|
||||||
u64_t position, iovec_t *iov, unsigned nr_req) );
|
endpoint_t endpt, iovec_t *iov, unsigned int nr_req) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define sys_voutb(out, n) at_voutb(__LINE__, (out), (n))
|
#define sys_voutb(out, n) at_voutb((out), (n))
|
||||||
FORWARD _PROTOTYPE( int at_voutb, (int line, pvb_pair_t *, int n));
|
FORWARD _PROTOTYPE( int at_voutb, (pvb_pair_t *, int n));
|
||||||
#define sys_vinb(in, n) at_vinb(__LINE__, (in), (n))
|
#define sys_vinb(in, n) at_vinb((in), (n))
|
||||||
FORWARD _PROTOTYPE( int at_vinb, (int line, pvb_pair_t *, int n));
|
FORWARD _PROTOTYPE( int at_vinb, (pvb_pair_t *, int n));
|
||||||
|
|
||||||
#undef sys_outb
|
#undef sys_outb
|
||||||
#undef sys_inb
|
#undef sys_inb
|
||||||
#undef sys_outl
|
#undef sys_outl
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( int at_out, (int line, u32_t port, u32_t value,
|
FORWARD _PROTOTYPE( int at_out, (int line, u32_t port, unsigned long value,
|
||||||
char *typename, int type));
|
char *typename, int type));
|
||||||
FORWARD _PROTOTYPE( int at_in, (int line, u32_t port, u32_t *value,
|
FORWARD _PROTOTYPE( int at_in, (int line, u32_t port, unsigned long *value,
|
||||||
char *typename, int type));
|
char *typename, int type));
|
||||||
|
|
||||||
#define sys_outb(p, v) at_out(__LINE__, (p), (v), "outb", _DIO_BYTE)
|
#define sys_outb(p, v) at_out(__LINE__, (p), (v), "outb", _DIO_BYTE)
|
||||||
|
@ -194,20 +199,18 @@ FORWARD _PROTOTYPE( int at_in, (int line, u32_t port, u32_t *value,
|
||||||
#define sys_outl(p, v) at_out(__LINE__, (p), (v), "outl", _DIO_LONG)
|
#define sys_outl(p, v) at_out(__LINE__, (p), (v), "outl", _DIO_LONG)
|
||||||
|
|
||||||
/* Entry points to this driver. */
|
/* Entry points to this driver. */
|
||||||
PRIVATE struct driver w_dtab = {
|
PRIVATE struct blockdriver w_dtab = {
|
||||||
w_name, /* current device's name */
|
|
||||||
w_do_open, /* open or mount request, initialize device */
|
w_do_open, /* open or mount request, initialize device */
|
||||||
w_do_close, /* release 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 */
|
w_transfer, /* do the I/O */
|
||||||
nop_cleanup, /* nothing to clean up */
|
w_ioctl, /* I/O control requests */
|
||||||
|
NULL, /* nothing to clean up */
|
||||||
|
w_part, /* return partition information */
|
||||||
w_geometry, /* tell the geometry of the disk */
|
w_geometry, /* tell the geometry of the disk */
|
||||||
nop_alarm, /* ignore leftover alarms */
|
w_hw_int, /* leftover hardware interrupts */
|
||||||
nop_cancel, /* ignore CANCELs */
|
NULL, /* ignore leftover alarms */
|
||||||
nop_select, /* ignore selects */
|
NULL, /* ignore unrecognized messages */
|
||||||
w_other, /* catch-all for unrecognized commands and ioctls */
|
NULL /* no multithreading support */
|
||||||
w_hw_int /* leftover hardware interrupts */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SEF functions and variables. */
|
/* SEF functions and variables. */
|
||||||
|
@ -227,7 +230,7 @@ PUBLIC int main(int argc, char *argv[])
|
||||||
sef_local_startup();
|
sef_local_startup();
|
||||||
|
|
||||||
/* Call the generic receive loop. */
|
/* Call the generic receive loop. */
|
||||||
driver_task(&w_dtab, DRIVER_STD);
|
blockdriver_task(&w_dtab);
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
@ -235,7 +238,7 @@ PUBLIC int main(int argc, char *argv[])
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_local_startup *
|
* sef_local_startup *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void sef_local_startup()
|
PRIVATE void sef_local_startup(void)
|
||||||
{
|
{
|
||||||
/* Register init callbacks. */
|
/* Register init callbacks. */
|
||||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||||
|
@ -269,7 +272,7 @@ PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
init_params();
|
init_params();
|
||||||
|
|
||||||
/* Announce we are up! */
|
/* Announce we are up! */
|
||||||
driver_announce();
|
blockdriver_announce();
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
@ -277,7 +280,7 @@ PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* init_params *
|
* init_params *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void init_params()
|
PRIVATE void init_params(void)
|
||||||
{
|
{
|
||||||
/* This routine is called at startup to initialize the drive parameters. */
|
/* This routine is called at startup to initialize the drive parameters. */
|
||||||
|
|
||||||
|
@ -304,20 +307,20 @@ PRIVATE void init_params()
|
||||||
panic("atapi_debug");
|
panic("atapi_debug");
|
||||||
|
|
||||||
if(w_identify_wakeup_ticks <= 0) {
|
if(w_identify_wakeup_ticks <= 0) {
|
||||||
printf("changing wakeup from %d to %d ticks.\n",
|
printf("changing wakeup from %ld to %d ticks.\n",
|
||||||
w_identify_wakeup_ticks, WAKEUP_TICKS);
|
w_identify_wakeup_ticks, WAKEUP_TICKS);
|
||||||
w_identify_wakeup_ticks = WAKEUP_TICKS;
|
w_identify_wakeup_ticks = WAKEUP_TICKS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disable_dma) {
|
if (disable_dma) {
|
||||||
printf("at_wini%d: DMA for ATA devices is disabled.\n", w_instance);
|
printf("at_wini%ld: DMA for ATA devices is disabled.\n", w_instance);
|
||||||
} else {
|
} else {
|
||||||
/* Ask for anonymous memory for DMA, that is physically contiguous. */
|
/* Ask for anonymous memory for DMA, that is physically contiguous. */
|
||||||
dma_buf = alloc_contig(ATA_DMA_BUF_SIZE, 0, &dma_buf_phys);
|
dma_buf = alloc_contig(ATA_DMA_BUF_SIZE, 0, &dma_buf_phys);
|
||||||
prdt = alloc_contig(PRDT_BYTES, 0, &prdt_phys);
|
prdt = alloc_contig(PRDT_BYTES, 0, &prdt_phys);
|
||||||
if(!dma_buf || !prdt) {
|
if(!dma_buf || !prdt) {
|
||||||
disable_dma = 1;
|
disable_dma = 1;
|
||||||
printf("at_wini%d: no dma\n", w_instance);
|
printf("at_wini%ld: no dma\n", w_instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +389,7 @@ PRIVATE void init_drive(struct wini *w, int base_cmd, int base_ctl,
|
||||||
w->base_ctl = base_ctl;
|
w->base_ctl = base_ctl;
|
||||||
w->base_dma = base_dma;
|
w->base_dma = base_dma;
|
||||||
if(w_pci_debug)
|
if(w_pci_debug)
|
||||||
printf("at_wini%d: drive %d: base_cmd 0x%x, base_ctl 0x%x, base_dma 0x%x\n",
|
printf("at_wini%ld: drive %d: base_cmd 0x%x, base_ctl 0x%x, base_dma 0x%x\n",
|
||||||
w_instance, w-wini, w->base_cmd, w->base_ctl, w->base_dma);
|
w_instance, w-wini, w->base_cmd, w->base_ctl, w->base_dma);
|
||||||
w->irq = irq;
|
w->irq = irq;
|
||||||
w->irq_need_ack = ack;
|
w->irq_need_ack = ack;
|
||||||
|
@ -471,7 +474,7 @@ PRIVATE void init_params_pci(int skip)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(pci_reserve_ok(devind) != OK) {
|
if(pci_reserve_ok(devind) != OK) {
|
||||||
printf("at_wini%d: pci_reserve %d failed - "
|
printf("at_wini%ld: pci_reserve %d failed - "
|
||||||
"ignoring controller!\n",
|
"ignoring controller!\n",
|
||||||
w_instance, devind);
|
w_instance, devind);
|
||||||
continue;
|
continue;
|
||||||
|
@ -502,9 +505,10 @@ PRIVATE void init_params_pci(int skip)
|
||||||
base_cmd, base_ctl+PCI_CTL_OFF,
|
base_cmd, base_ctl+PCI_CTL_OFF,
|
||||||
base_dma, irq, 1, irq_hook, 1);
|
base_dma, irq, 1, irq_hook, 1);
|
||||||
if (w_pci_debug)
|
if (w_pci_debug)
|
||||||
printf("at_wini%d: atapci %d: 0x%x 0x%x irq %d\n", w_instance, devind, base_cmd, base_ctl, irq);
|
printf("at_wini%ld: atapci %d: 0x%x 0x%x irq %d\n",
|
||||||
|
w_instance, devind, base_cmd, base_ctl, irq);
|
||||||
w_next_drive += 2;
|
w_next_drive += 2;
|
||||||
} else printf("at_wini%d: atapci: ignored drives on primary channel, base %x\n", w_instance, base_cmd);
|
} else printf("at_wini%ld: atapci: ignored drives on primary channel, base %x\n", w_instance, base_cmd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -514,7 +518,7 @@ PRIVATE void init_params_pci(int skip)
|
||||||
if (wini[i].base_cmd == REG_CMD_BASE0) {
|
if (wini[i].base_cmd == REG_CMD_BASE0) {
|
||||||
wini[i].base_dma= base_dma;
|
wini[i].base_dma= base_dma;
|
||||||
if(w_pci_debug)
|
if(w_pci_debug)
|
||||||
printf("at_wini%d: drive %d: base_dma 0x%x\n",
|
printf("at_wini%ld: drive %d: base_dma 0x%x\n",
|
||||||
w_instance, i, wini[i].base_dma);
|
w_instance, i, wini[i].base_dma);
|
||||||
pci_compat = 1;
|
pci_compat = 1;
|
||||||
}
|
}
|
||||||
|
@ -537,10 +541,10 @@ PRIVATE void init_params_pci(int skip)
|
||||||
base_cmd, base_ctl+PCI_CTL_OFF, base_dma,
|
base_cmd, base_ctl+PCI_CTL_OFF, base_dma,
|
||||||
irq, 1, irq_hook, 3);
|
irq, 1, irq_hook, 3);
|
||||||
if (w_pci_debug)
|
if (w_pci_debug)
|
||||||
printf("at_wini%d: atapci %d: 0x%x 0x%x irq %d\n",
|
printf("at_wini%ld: atapci %d: 0x%x 0x%x irq %d\n",
|
||||||
w_instance, devind, base_cmd, base_ctl, irq);
|
w_instance, devind, base_cmd, base_ctl, irq);
|
||||||
w_next_drive += 2;
|
w_next_drive += 2;
|
||||||
} else printf("at_wini%d: atapci: ignored drives on "
|
} else printf("at_wini%ld: atapci: ignored drives on "
|
||||||
"secondary channel, base %x\n", w_instance, base_cmd);
|
"secondary channel, base %x\n", w_instance, base_cmd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -551,7 +555,7 @@ PRIVATE void init_params_pci(int skip)
|
||||||
if (wini[i].base_cmd == REG_CMD_BASE1 && base_dma != 0) {
|
if (wini[i].base_cmd == REG_CMD_BASE1 && base_dma != 0) {
|
||||||
wini[i].base_dma= base_dma+PCI_DMA_2ND_OFF;
|
wini[i].base_dma= base_dma+PCI_DMA_2ND_OFF;
|
||||||
if (w_pci_debug)
|
if (w_pci_debug)
|
||||||
printf("at_wini%d: drive %d: base_dma 0x%x\n",
|
printf("at_wini%ld: drive %d: base_dma 0x%x\n",
|
||||||
w_instance, i, wini[i].base_dma);
|
w_instance, i, wini[i].base_dma);
|
||||||
pci_compat = 1;
|
pci_compat = 1;
|
||||||
}
|
}
|
||||||
|
@ -560,7 +564,7 @@ PRIVATE void init_params_pci(int skip)
|
||||||
|
|
||||||
if(pci_compat) {
|
if(pci_compat) {
|
||||||
if(pci_reserve_ok(devind) != OK) {
|
if(pci_reserve_ok(devind) != OK) {
|
||||||
printf("at_wini%d (compat): pci_reserve %d failed!\n",
|
printf("at_wini%ld (compat): pci_reserve %d failed!\n",
|
||||||
w_instance, devind);
|
w_instance, devind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,13 +574,13 @@ PRIVATE void init_params_pci(int skip)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_do_open *
|
* w_do_open *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int w_do_open(struct driver *dp, message *m_ptr)
|
PRIVATE int w_do_open(dev_t minor, int access)
|
||||||
{
|
{
|
||||||
/* Device open: Initialize the controller and read the partition table. */
|
/* Device open: Initialize the controller and read the partition table. */
|
||||||
|
|
||||||
struct wini *wn;
|
struct wini *wn;
|
||||||
|
|
||||||
if (w_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
if (w_prepare(minor) == NULL) return(ENXIO);
|
||||||
|
|
||||||
wn = w_wn;
|
wn = w_wn;
|
||||||
|
|
||||||
|
@ -613,7 +617,7 @@ PRIVATE int w_do_open(struct driver *dp, message *m_ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_ATAPI
|
#if ENABLE_ATAPI
|
||||||
if ((wn->state & ATAPI) && (m_ptr->COUNT & W_BIT))
|
if ((wn->state & ATAPI) && (access & W_BIT))
|
||||||
return(EACCES);
|
return(EACCES);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -629,7 +633,8 @@ PRIVATE int w_do_open(struct driver *dp, message *m_ptr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Partition the disk. */
|
/* Partition the disk. */
|
||||||
partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY, wn->state & ATAPI);
|
partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY,
|
||||||
|
wn->state & ATAPI);
|
||||||
}
|
}
|
||||||
wn->open_ct++;
|
wn->open_ct++;
|
||||||
return(OK);
|
return(OK);
|
||||||
|
@ -638,10 +643,10 @@ PRIVATE int w_do_open(struct driver *dp, message *m_ptr)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_prepare *
|
* w_prepare *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE struct device *w_prepare(int device)
|
PRIVATE struct device *w_prepare(dev_t device)
|
||||||
{
|
{
|
||||||
/* Prepare for I/O on a device. */
|
/* Prepare for I/O on a device. */
|
||||||
w_device = device;
|
w_device = (int) device;
|
||||||
|
|
||||||
if (device < NR_MINORS) { /* d0, d0p[0-3], d1, ... */
|
if (device < NR_MINORS) { /* d0, d0p[0-3], d1, ... */
|
||||||
w_drive = device / DEV_PER_DRIVE; /* save drive number */
|
w_drive = device / DEV_PER_DRIVE; /* save drive number */
|
||||||
|
@ -659,6 +664,16 @@ PRIVATE struct device *w_prepare(int device)
|
||||||
return(w_dv);
|
return(w_dv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* w_part *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE struct device *w_part(dev_t device)
|
||||||
|
{
|
||||||
|
/* Return a pointer to the partition information of the given minor device. */
|
||||||
|
|
||||||
|
return w_prepare(device);
|
||||||
|
}
|
||||||
|
|
||||||
#define id_byte(n) (&tmp_buf[2 * (n)])
|
#define id_byte(n) (&tmp_buf[2 * (n)])
|
||||||
#define id_word(n) (((u16_t) id_byte(n)[0] << 0) \
|
#define id_word(n) (((u16_t) id_byte(n)[0] << 0) \
|
||||||
|((u16_t) id_byte(n)[1] << 8))
|
|((u16_t) id_byte(n)[1] << 8))
|
||||||
|
@ -754,7 +769,7 @@ check_dma(struct wini *wn)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_identify *
|
* w_identify *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int w_identify()
|
PRIVATE int w_identify(void)
|
||||||
{
|
{
|
||||||
/* Find out if a device exists, if it is an old AT disk, or a newer ATA
|
/* Find out if a device exists, if it is an old AT disk, or a newer ATA
|
||||||
* drive, a removable media device, etc.
|
* drive, a removable media device, etc.
|
||||||
|
@ -906,7 +921,7 @@ PRIVATE int w_identify()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_name *
|
* w_name *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE char *w_name()
|
PRIVATE char *w_name(void)
|
||||||
{
|
{
|
||||||
/* Return a name for the current device. */
|
/* Return a name for the current device. */
|
||||||
static char name[] = "AT0-D0";
|
static char name[] = "AT0-D0";
|
||||||
|
@ -921,10 +936,11 @@ PRIVATE char *w_name()
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int w_io_test(void)
|
PRIVATE int w_io_test(void)
|
||||||
{
|
{
|
||||||
int r, save_dev;
|
int save_dev;
|
||||||
int save_timeout, save_errors, save_wakeup;
|
int save_timeout, save_errors, save_wakeup;
|
||||||
iovec_t iov;
|
iovec_t iov;
|
||||||
static char *buf;
|
static char *buf;
|
||||||
|
ssize_t r;
|
||||||
|
|
||||||
#ifdef CD_SECTOR_SIZE
|
#ifdef CD_SECTOR_SIZE
|
||||||
#define BUFSIZE CD_SECTOR_SIZE
|
#define BUFSIZE CD_SECTOR_SIZE
|
||||||
|
@ -951,10 +967,8 @@ PRIVATE int w_io_test(void)
|
||||||
w_testing = 1;
|
w_testing = 1;
|
||||||
|
|
||||||
/* Try I/O on the actual drive (not any (sub)partition). */
|
/* Try I/O on the actual drive (not any (sub)partition). */
|
||||||
if (w_prepare(w_drive * DEV_PER_DRIVE) == NULL)
|
r = w_transfer(w_drive * DEV_PER_DRIVE, FALSE /*do_write*/, cvu64(0),
|
||||||
panic("Couldn't switch devices");
|
SELF, &iov, 1, BDEV_NOFLAGS);
|
||||||
|
|
||||||
r = w_transfer(SELF, DEV_GATHER_S, cvu64(0), &iov, 1);
|
|
||||||
|
|
||||||
/* Switch back. */
|
/* Switch back. */
|
||||||
if (w_prepare(save_dev) == NULL)
|
if (w_prepare(save_dev) == NULL)
|
||||||
|
@ -967,19 +981,18 @@ PRIVATE int w_io_test(void)
|
||||||
w_testing = 0;
|
w_testing = 0;
|
||||||
|
|
||||||
/* Test if everything worked. */
|
/* Test if everything worked. */
|
||||||
if (r != OK || iov.iov_size != 0) {
|
if (r != BUFSIZE) {
|
||||||
return ERR;
|
return ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Everything worked. */
|
/* Everything worked. */
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_specify *
|
* w_specify *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int w_specify()
|
PRIVATE int w_specify(void)
|
||||||
{
|
{
|
||||||
/* Routine to initialize the drive after boot or when a reset is needed. */
|
/* Routine to initialize the drive after boot or when a reset is needed. */
|
||||||
|
|
||||||
|
@ -1020,7 +1033,7 @@ PRIVATE int w_specify()
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int do_transfer(const struct wini *wn, unsigned int precomp,
|
PRIVATE int do_transfer(const struct wini *wn, unsigned int precomp,
|
||||||
unsigned int count, unsigned int sector,
|
unsigned int count, unsigned int sector,
|
||||||
unsigned int opcode, int do_dma)
|
unsigned int do_write, int do_dma)
|
||||||
{
|
{
|
||||||
struct command cmd;
|
struct command cmd;
|
||||||
unsigned int sector_high;
|
unsigned int sector_high;
|
||||||
|
@ -1045,21 +1058,20 @@ PRIVATE int do_transfer(const struct wini *wn, unsigned int precomp,
|
||||||
cmd.count = count;
|
cmd.count = count;
|
||||||
if (do_dma)
|
if (do_dma)
|
||||||
{
|
{
|
||||||
cmd.command = opcode == DEV_SCATTER_S ? CMD_WRITE_DMA :
|
cmd.command = do_write ? CMD_WRITE_DMA : CMD_READ_DMA;
|
||||||
CMD_READ_DMA;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cmd.command = opcode == DEV_SCATTER_S ? CMD_WRITE : CMD_READ;
|
cmd.command = do_write ? CMD_WRITE : CMD_READ;
|
||||||
|
|
||||||
if (do_lba48) {
|
if (do_lba48) {
|
||||||
if (do_dma)
|
if (do_dma)
|
||||||
{
|
{
|
||||||
cmd.command = ((opcode == DEV_SCATTER_S) ?
|
cmd.command = (do_write ?
|
||||||
CMD_WRITE_DMA_EXT : CMD_READ_DMA_EXT);
|
CMD_WRITE_DMA_EXT : CMD_READ_DMA_EXT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cmd.command = ((opcode == DEV_SCATTER_S) ?
|
cmd.command = (do_write ?
|
||||||
CMD_WRITE_EXT : CMD_READ_EXT);
|
CMD_WRITE_EXT : CMD_READ_EXT);
|
||||||
}
|
}
|
||||||
cmd.count_prev= (count >> 8);
|
cmd.count_prev= (count >> 8);
|
||||||
|
@ -1119,12 +1131,12 @@ PRIVATE void start_dma(const struct wini *wn, int do_write)
|
||||||
PRIVATE int error_dma(const struct wini *wn)
|
PRIVATE int error_dma(const struct wini *wn)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
u32_t v;
|
unsigned long v;
|
||||||
|
|
||||||
#define DMAERR(msg) \
|
#define DMAERR(msg) \
|
||||||
printf("at_wini%d: bad DMA: %s. Disabling DMA for drive %d.\n", \
|
printf("at_wini%ld: bad DMA: %s. Disabling DMA for drive %d.\n", \
|
||||||
w_instance, msg, wn - wini); \
|
w_instance, msg, wn - wini); \
|
||||||
printf("at_wini%d: workaround: set %s=1 in boot monitor.\n", \
|
printf("at_wini%ld: workaround: set %s=1 in boot monitor.\n", \
|
||||||
w_instance, NO_DMA_VAR); \
|
w_instance, NO_DMA_VAR); \
|
||||||
return 1; \
|
return 1; \
|
||||||
|
|
||||||
|
@ -1151,25 +1163,34 @@ PRIVATE int error_dma(const struct wini *wn)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_transfer *
|
* w_transfer *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int w_transfer(proc_nr, opcode, position, iov, nr_req)
|
PRIVATE ssize_t w_transfer(
|
||||||
endpoint_t proc_nr; /* process doing the request */
|
dev_t minor, /* minor device to perform the transfer on */
|
||||||
int opcode; /* DEV_GATHER_S or DEV_SCATTER_S */
|
int do_write, /* read or write? */
|
||||||
u64_t position; /* offset on device to read or write */
|
u64_t position, /* offset on device to read or write */
|
||||||
iovec_t *iov; /* pointer to read or write request vector */
|
endpoint_t proc_nr, /* process doing the request */
|
||||||
unsigned nr_req; /* length of request vector */
|
iovec_t *iov, /* pointer to read or write request vector */
|
||||||
|
unsigned int nr_req, /* length of request vector */
|
||||||
|
int UNUSED(flags) /* transfer flags */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
struct wini *wn = w_wn;
|
struct wini *wn;
|
||||||
iovec_t *iop, *iov_end = iov + nr_req;
|
iovec_t *iop, *iov_end = iov + nr_req;
|
||||||
int n, r, s, errors, do_dma, do_write;
|
int n, r, s, errors, do_dma;
|
||||||
unsigned long block, w_status;
|
unsigned long block, w_status;
|
||||||
u64_t dv_size = w_dv->dv_size;
|
u64_t dv_size;
|
||||||
unsigned nbytes;
|
unsigned nbytes;
|
||||||
unsigned dma_buf_offset;
|
unsigned dma_buf_offset;
|
||||||
|
ssize_t total = 0;
|
||||||
size_t addr_offset = 0;
|
size_t addr_offset = 0;
|
||||||
|
|
||||||
|
if (w_prepare(minor) == NULL) return(ENXIO);
|
||||||
|
|
||||||
|
wn = w_wn;
|
||||||
|
dv_size = w_dv->dv_size;
|
||||||
|
|
||||||
#if ENABLE_ATAPI
|
#if ENABLE_ATAPI
|
||||||
if (w_wn->state & ATAPI) {
|
if (w_wn->state & ATAPI) {
|
||||||
return atapi_transfer(proc_nr, opcode, position, iov, nr_req);
|
return atapi_transfer(do_write, position, proc_nr, iov, nr_req);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1185,12 +1206,11 @@ unsigned nr_req; /* length of request vector */
|
||||||
if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
|
if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
|
||||||
|
|
||||||
/* Which block on disk and how close to EOF? */
|
/* Which block on disk and how close to EOF? */
|
||||||
if (cmp64(position, dv_size) >= 0) return(OK); /* At EOF */
|
if (cmp64(position, dv_size) >= 0) return(total); /* At EOF */
|
||||||
if (cmp64(add64ul(position, nbytes), dv_size) > 0)
|
if (cmp64(add64ul(position, nbytes), dv_size) > 0)
|
||||||
nbytes = diff64(dv_size, position);
|
nbytes = diff64(dv_size, position);
|
||||||
block = div64u(add64(w_dv->dv_base, position), SECTOR_SIZE);
|
block = div64u(add64(w_dv->dv_base, position), SECTOR_SIZE);
|
||||||
|
|
||||||
do_write= (opcode == DEV_SCATTER_S);
|
|
||||||
do_dma= wn->dma;
|
do_dma= wn->dma;
|
||||||
|
|
||||||
if (nbytes >= wn->max_count) {
|
if (nbytes >= wn->max_count) {
|
||||||
|
@ -1213,12 +1233,12 @@ unsigned nr_req; /* length of request vector */
|
||||||
|
|
||||||
/* Tell the controller to transfer nbytes bytes. */
|
/* Tell the controller to transfer nbytes bytes. */
|
||||||
r = do_transfer(wn, wn->precomp, (nbytes >> SECTOR_SHIFT),
|
r = do_transfer(wn, wn->precomp, (nbytes >> SECTOR_SHIFT),
|
||||||
block, opcode, do_dma);
|
block, do_write, do_dma);
|
||||||
|
|
||||||
if (do_dma)
|
if (do_dma)
|
||||||
start_dma(wn, do_write);
|
start_dma(wn, do_write);
|
||||||
|
|
||||||
if (opcode == DEV_SCATTER_S) {
|
if (do_write) {
|
||||||
/* The specs call for a 400 ns wait after issuing the command.
|
/* The specs call for a 400 ns wait after issuing the command.
|
||||||
* Reading the alternate status register is the suggested
|
* Reading the alternate status register is the suggested
|
||||||
* way to implement this wait.
|
* way to implement this wait.
|
||||||
|
@ -1268,6 +1288,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
/* Book the bytes successfully transferred. */
|
/* Book the bytes successfully transferred. */
|
||||||
nbytes -= n;
|
nbytes -= n;
|
||||||
position= add64ul(position, n);
|
position= add64ul(position, n);
|
||||||
|
total += n;
|
||||||
addr_offset += n;
|
addr_offset += n;
|
||||||
if ((iov->iov_size -= n) == 0) {
|
if ((iov->iov_size -= n) == 0) {
|
||||||
iov++; nr_req--; addr_offset = 0;
|
iov++; nr_req--; addr_offset = 0;
|
||||||
|
@ -1282,7 +1303,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
* interrupt (write).
|
* interrupt (write).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (opcode == DEV_GATHER_S) {
|
if (!do_write) {
|
||||||
/* First an interrupt, then data. */
|
/* First an interrupt, then data. */
|
||||||
if ((r = at_intr_wait()) != OK) {
|
if ((r = at_intr_wait()) != OK) {
|
||||||
/* An error, send data to the bit bucket. */
|
/* An error, send data to the bit bucket. */
|
||||||
|
@ -1304,7 +1325,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
if (!w_waitfor(STATUS_DRQ, STATUS_DRQ)) { r = ERR; break; }
|
if (!w_waitfor(STATUS_DRQ, STATUS_DRQ)) { r = ERR; break; }
|
||||||
|
|
||||||
/* Copy bytes to or from the device's buffer. */
|
/* Copy bytes to or from the device's buffer. */
|
||||||
if (opcode == DEV_GATHER_S) {
|
if (!do_write) {
|
||||||
if(proc_nr != SELF) {
|
if(proc_nr != SELF) {
|
||||||
s=sys_safe_insw(wn->base_cmd + REG_DATA, proc_nr,
|
s=sys_safe_insw(wn->base_cmd + REG_DATA, proc_nr,
|
||||||
(void *) (iov->iov_addr), addr_offset,
|
(void *) (iov->iov_addr), addr_offset,
|
||||||
|
@ -1340,6 +1361,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
nbytes -= SECTOR_SIZE;
|
nbytes -= SECTOR_SIZE;
|
||||||
position= add64u(position, SECTOR_SIZE);
|
position= add64u(position, SECTOR_SIZE);
|
||||||
addr_offset += SECTOR_SIZE;
|
addr_offset += SECTOR_SIZE;
|
||||||
|
total += SECTOR_SIZE;
|
||||||
if ((iov->iov_size -= SECTOR_SIZE) == 0) {
|
if ((iov->iov_size -= SECTOR_SIZE) == 0) {
|
||||||
iov++;
|
iov++;
|
||||||
nr_req--;
|
nr_req--;
|
||||||
|
@ -1358,7 +1380,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
}
|
}
|
||||||
|
|
||||||
w_command = CMD_IDLE;
|
w_command = CMD_IDLE;
|
||||||
return(OK);
|
return(total);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -1469,12 +1491,13 @@ struct command *cmd; /* Command block */
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* setup_dma *
|
* setup_dma *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int setup_dma(sizep, proc_nr, iov, addr_offset, do_write)
|
PRIVATE int setup_dma(
|
||||||
unsigned *sizep;
|
unsigned *sizep,
|
||||||
endpoint_t proc_nr;
|
endpoint_t proc_nr,
|
||||||
iovec_t *iov;
|
iovec_t *iov,
|
||||||
size_t addr_offset;
|
size_t addr_offset,
|
||||||
int do_write;
|
int UNUSED(do_write)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
phys_bytes user_phys;
|
phys_bytes user_phys;
|
||||||
unsigned n, offset, size;
|
unsigned n, offset, size;
|
||||||
|
@ -1496,7 +1519,7 @@ int do_write;
|
||||||
{
|
{
|
||||||
if(verbose) {
|
if(verbose) {
|
||||||
printf(
|
printf(
|
||||||
"at_wini: setup_dma: iov[%d]: addr 0x%x, size %d offset %d, size %d\n",
|
"at_wini: setup_dma: iov[%d]: addr 0x%lx, size %ld offset %d, size %d\n",
|
||||||
i, iov[i].iov_addr, iov[i].iov_size, offset, size);
|
i, iov[i].iov_addr, iov[i].iov_size, offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1564,7 +1587,7 @@ int do_write;
|
||||||
if(verbose) {
|
if(verbose) {
|
||||||
printf("dma not bad\n");
|
printf("dma not bad\n");
|
||||||
for (i= 0; i<j; i++) {
|
for (i= 0; i<j; i++) {
|
||||||
printf("prdt[%d]: base 0x%x, size %d, flags 0x%x\n",
|
printf("prdt[%d]: base 0x%lx, size %d, flags 0x%x\n",
|
||||||
i, prdt[i].prdte_base, prdt[i].prdte_count,
|
i, prdt[i].prdte_base, prdt[i].prdte_count,
|
||||||
prdt[i].prdte_flags);
|
prdt[i].prdte_flags);
|
||||||
}
|
}
|
||||||
|
@ -1592,7 +1615,7 @@ int do_write;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_need_reset *
|
* w_need_reset *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void w_need_reset()
|
PRIVATE void w_need_reset(void)
|
||||||
{
|
{
|
||||||
/* The controller needs to be reset. */
|
/* The controller needs to be reset. */
|
||||||
struct wini *wn;
|
struct wini *wn;
|
||||||
|
@ -1608,10 +1631,10 @@ PRIVATE void w_need_reset()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_do_close *
|
* w_do_close *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int w_do_close(struct driver *dp, message *m_ptr)
|
PRIVATE int w_do_close(dev_t minor)
|
||||||
{
|
{
|
||||||
/* Device close: Release a device. */
|
/* Device close: Release a device. */
|
||||||
if (w_prepare(m_ptr->DEVICE) == NULL)
|
if (w_prepare(minor) == NULL)
|
||||||
return(ENXIO);
|
return(ENXIO);
|
||||||
w_wn->open_ct--;
|
w_wn->open_ct--;
|
||||||
#if ENABLE_ATAPI
|
#if ENABLE_ATAPI
|
||||||
|
@ -1672,7 +1695,7 @@ PRIVATE void w_timeout(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_reset *
|
* w_reset *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int w_reset()
|
PRIVATE int w_reset(void)
|
||||||
{
|
{
|
||||||
/* Issue a reset to the controller. This is done after any catastrophe,
|
/* Issue a reset to the controller. This is done after any catastrophe,
|
||||||
* like the controller refusing to respond.
|
* like the controller refusing to respond.
|
||||||
|
@ -1718,7 +1741,7 @@ PRIVATE int w_reset()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_intr_wait *
|
* w_intr_wait *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void w_intr_wait()
|
PRIVATE void w_intr_wait(void)
|
||||||
{
|
{
|
||||||
/* Wait for a task completion interrupt. */
|
/* Wait for a task completion interrupt. */
|
||||||
|
|
||||||
|
@ -1753,17 +1776,17 @@ PRIVATE void w_intr_wait()
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
* unhandled message. queue it and
|
* unhandled message. queue it and
|
||||||
* handle it in the libdriver loop.
|
* handle it in the blockdriver loop.
|
||||||
*/
|
*/
|
||||||
driver_mq_queue(&m, ipc_status);
|
blockdriver_mq_queue(&m, ipc_status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/*
|
/*
|
||||||
* unhandled message. queue it and handle it in the
|
* unhandled message. queue it and handle it in the
|
||||||
* libdriver loop.
|
* blockdriver loop.
|
||||||
*/
|
*/
|
||||||
driver_mq_queue(&m, ipc_status);
|
blockdriver_mq_queue(&m, ipc_status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1775,7 +1798,7 @@ PRIVATE void w_intr_wait()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* at_intr_wait *
|
* at_intr_wait *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int at_intr_wait()
|
PRIVATE int at_intr_wait(void)
|
||||||
{
|
{
|
||||||
/* Wait for an interrupt, study the status bits and return error/success. */
|
/* Wait for an interrupt, study the status bits and return error/success. */
|
||||||
int r, s;
|
int r, s;
|
||||||
|
@ -1850,10 +1873,13 @@ int value; /* required status */
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_geometry *
|
* w_geometry *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void w_geometry(entry)
|
PRIVATE void w_geometry(dev_t minor, struct partition *entry)
|
||||||
struct partition *entry;
|
|
||||||
{
|
{
|
||||||
struct wini *wn = w_wn;
|
struct wini *wn;
|
||||||
|
|
||||||
|
if (w_prepare(minor) == NULL) return;
|
||||||
|
|
||||||
|
wn = w_wn;
|
||||||
|
|
||||||
if (wn->state & ATAPI) { /* Make up some numbers. */
|
if (wn->state & ATAPI) { /* Make up some numbers. */
|
||||||
entry->cylinders = div64u(wn->part[0].dv_size, SECTOR_SIZE) / (64*32);
|
entry->cylinders = div64u(wn->part[0].dv_size, SECTOR_SIZE) / (64*32);
|
||||||
|
@ -1870,7 +1896,7 @@ struct partition *entry;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* atapi_open *
|
* atapi_open *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int atapi_open()
|
PRIVATE int atapi_open(void)
|
||||||
{
|
{
|
||||||
/* Should load and lock the device and obtain its size. For now just set the
|
/* Should load and lock the device and obtain its size. For now just set the
|
||||||
* size of the device to something big. What is really needed is a generic
|
* size of the device to something big. What is really needed is a generic
|
||||||
|
@ -1883,7 +1909,7 @@ PRIVATE int atapi_open()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* atapi_close *
|
* atapi_close *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void atapi_close()
|
PRIVATE void atapi_close(void)
|
||||||
{
|
{
|
||||||
/* Should unlock the device. For now do nothing. (XXX) */
|
/* Should unlock the device. For now do nothing. (XXX) */
|
||||||
}
|
}
|
||||||
|
@ -1921,12 +1947,13 @@ PRIVATE void sense_request(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* atapi_transfer *
|
* atapi_transfer *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int atapi_transfer(proc_nr, opcode, position, iov, nr_req)
|
PRIVATE int atapi_transfer(
|
||||||
int proc_nr; /* process doing the request */
|
int do_write, /* read or write? */
|
||||||
int opcode; /* DEV_GATHER_S or DEV_SCATTER_S */
|
u64_t position, /* offset on device to read or write */
|
||||||
u64_t position; /* offset on device to read or write */
|
endpoint_t proc_nr, /* process doing the request */
|
||||||
iovec_t *iov; /* pointer to read or write request vector */
|
iovec_t *iov, /* pointer to read or write request vector */
|
||||||
unsigned nr_req; /* length of request vector */
|
unsigned int nr_req /* length of request vector */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
struct wini *wn = w_wn;
|
struct wini *wn = w_wn;
|
||||||
iovec_t *iop, *iov_end = iov + nr_req;
|
iovec_t *iop, *iov_end = iov + nr_req;
|
||||||
|
@ -1938,6 +1965,9 @@ unsigned nr_req; /* length of request vector */
|
||||||
static u8_t packet[ATAPI_PACKETSIZE];
|
static u8_t packet[ATAPI_PACKETSIZE];
|
||||||
size_t addr_offset = 0;
|
size_t addr_offset = 0;
|
||||||
int dmabytes = 0, piobytes = 0;
|
int dmabytes = 0, piobytes = 0;
|
||||||
|
ssize_t total = 0;
|
||||||
|
|
||||||
|
if (do_write) return(EINVAL);
|
||||||
|
|
||||||
errors = fresh = 0;
|
errors = fresh = 0;
|
||||||
|
|
||||||
|
@ -1965,7 +1995,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
if ((before | nbytes) & 1) return(EINVAL);
|
if ((before | nbytes) & 1) return(EINVAL);
|
||||||
|
|
||||||
/* Which block on disk and how close to EOF? */
|
/* Which block on disk and how close to EOF? */
|
||||||
if (cmp64(position, dv_size) >= 0) return(OK); /* At EOF */
|
if (cmp64(position, dv_size) >= 0) return(total); /* At EOF */
|
||||||
if (cmp64(add64ul(position, nbytes), dv_size) > 0)
|
if (cmp64(add64ul(position, nbytes), dv_size) > 0)
|
||||||
nbytes = diff64(dv_size, position);
|
nbytes = diff64(dv_size, position);
|
||||||
|
|
||||||
|
@ -2023,6 +2053,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
chunk = iov->iov_size;
|
chunk = iov->iov_size;
|
||||||
position= add64ul(position, chunk);
|
position= add64ul(position, chunk);
|
||||||
nbytes -= chunk;
|
nbytes -= chunk;
|
||||||
|
total += chunk;
|
||||||
if ((iov->iov_size -= chunk) == 0) {
|
if ((iov->iov_size -= chunk) == 0) {
|
||||||
iov++;
|
iov++;
|
||||||
nr_req--;
|
nr_req--;
|
||||||
|
@ -2069,6 +2100,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
addr_offset += chunk;
|
addr_offset += chunk;
|
||||||
piobytes += chunk;
|
piobytes += chunk;
|
||||||
fresh = 0;
|
fresh = 0;
|
||||||
|
total += chunk;
|
||||||
if ((iov->iov_size -= chunk) == 0) {
|
if ((iov->iov_size -= chunk) == 0) {
|
||||||
iov++;
|
iov++;
|
||||||
nr_req--;
|
nr_req--;
|
||||||
|
@ -2107,7 +2139,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
w_command = CMD_IDLE;
|
w_command = CMD_IDLE;
|
||||||
return(OK);
|
return(total);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -2174,21 +2206,18 @@ int do_dma;
|
||||||
#endif /* ENABLE_ATAPI */
|
#endif /* ENABLE_ATAPI */
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_other *
|
* w_ioctl *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int w_other(dr, m)
|
PRIVATE int w_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||||
struct driver *dr;
|
cp_grant_id_t grant)
|
||||||
message *m;
|
|
||||||
{
|
{
|
||||||
int r, timeout, prev;
|
int r, timeout, prev, count;
|
||||||
struct command cmd;
|
struct command cmd;
|
||||||
|
|
||||||
if (m->m_type != DEV_IOCTL_S )
|
switch (request) {
|
||||||
return EINVAL;
|
case DIOCTIMEOUT:
|
||||||
|
r= sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&timeout,
|
||||||
if (m->REQUEST == DIOCTIMEOUT) {
|
sizeof(timeout), D);
|
||||||
r= sys_safecopyfrom(m->m_source, (cp_grant_id_t) m->IO_GRANT,
|
|
||||||
0, (vir_bytes)&timeout, sizeof(timeout), D);
|
|
||||||
|
|
||||||
if(r != OK)
|
if(r != OK)
|
||||||
return r;
|
return r;
|
||||||
|
@ -2218,28 +2247,28 @@ message *m;
|
||||||
timeout_usecs = timeout;
|
timeout_usecs = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
r= sys_safecopyto(m->m_source,
|
r= sys_safecopyto(endpt, grant, 0, (vir_bytes)&prev,
|
||||||
(cp_grant_id_t) m->IO_GRANT,
|
sizeof(prev), D);
|
||||||
0, (vir_bytes)&prev, sizeof(prev), D);
|
|
||||||
|
|
||||||
if(r != OK)
|
if(r != OK)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
} else if (m->REQUEST == DIOCOPENCT) {
|
|
||||||
int count;
|
case DIOCOPENCT:
|
||||||
if (w_prepare(m->DEVICE) == NULL) return ENXIO;
|
if (w_prepare(minor) == NULL) return ENXIO;
|
||||||
count = w_wn->open_ct;
|
count = w_wn->open_ct;
|
||||||
r= sys_safecopyto(m->m_source, (cp_grant_id_t) m->IO_GRANT,
|
r= sys_safecopyto(endpt, grant, 0, (vir_bytes)&count,
|
||||||
0, (vir_bytes)&count, sizeof(count), D);
|
sizeof(count), D);
|
||||||
|
|
||||||
if(r != OK)
|
if(r != OK)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
} else if (m->REQUEST == DIOCFLUSH) {
|
|
||||||
if (w_prepare(m->DEVICE) == NULL) return ENXIO;
|
case DIOCFLUSH:
|
||||||
|
if (w_prepare(minor) == NULL) return ENXIO;
|
||||||
|
|
||||||
if (w_wn->state & ATAPI) return EINVAL;
|
if (w_wn->state & ATAPI) return EINVAL;
|
||||||
|
|
||||||
|
@ -2253,18 +2282,17 @@ message *m;
|
||||||
|
|
||||||
return (w_wn->w_status & (STATUS_ERR|STATUS_WF)) ? EIO : OK;
|
return (w_wn->w_status & (STATUS_ERR|STATUS_WF)) ? EIO : OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_hw_int *
|
* w_hw_int *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void w_hw_int(dr, m)
|
PRIVATE void w_hw_int(unsigned int irqs)
|
||||||
struct driver *dr;
|
|
||||||
message *m;
|
|
||||||
{
|
{
|
||||||
/* Leftover interrupt(s) received; ack it/them. */
|
/* Leftover interrupt(s) received; ack it/them. */
|
||||||
ack_irqs(m->NOTIFY_ARG);
|
ack_irqs(irqs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2334,7 +2362,7 @@ PRIVATE char *strerr(int e)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* atapi_intr_wait *
|
* atapi_intr_wait *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int atapi_intr_wait(int do_dma, size_t max)
|
PRIVATE int atapi_intr_wait(int UNUSED(do_dma), size_t UNUSED(max))
|
||||||
{
|
{
|
||||||
/* Wait for an interrupt and study the results. Returns a number of bytes
|
/* Wait for an interrupt and study the results. Returns a number of bytes
|
||||||
* that need to be transferred, or an error code.
|
* that need to be transferred, or an error code.
|
||||||
|
@ -2407,49 +2435,49 @@ PRIVATE int atapi_intr_wait(int do_dma, size_t max)
|
||||||
#undef sys_voutb
|
#undef sys_voutb
|
||||||
#undef sys_vinb
|
#undef sys_vinb
|
||||||
|
|
||||||
PRIVATE int at_voutb(int line, pvb_pair_t *pvb, int n)
|
PRIVATE int at_voutb(pvb_pair_t *pvb, int n)
|
||||||
{
|
{
|
||||||
int s, i;
|
int s, i;
|
||||||
if ((s=sys_voutb(pvb,n)) == OK)
|
if ((s=sys_voutb(pvb,n)) == OK)
|
||||||
return OK;
|
return OK;
|
||||||
printf("at_wini%d: sys_voutb failed: %d pvb (%d):\n", w_instance, s, n);
|
printf("at_wini%ld: sys_voutb failed: %d pvb (%d):\n", w_instance, s, n);
|
||||||
for(i = 0; i < n; i++)
|
for(i = 0; i < n; i++)
|
||||||
printf("%2d: %4x -> %4x\n", i, pvb[i].value, pvb[i].port);
|
printf("%2d: %4x -> %4x\n", i, pvb[i].value, pvb[i].port);
|
||||||
panic("sys_voutb failed");
|
panic("sys_voutb failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE int at_vinb(int line, pvb_pair_t *pvb, int n)
|
PRIVATE int at_vinb(pvb_pair_t *pvb, int n)
|
||||||
{
|
{
|
||||||
int s, i;
|
int s, i;
|
||||||
if ((s=sys_vinb(pvb,n)) == OK)
|
if ((s=sys_vinb(pvb,n)) == OK)
|
||||||
return OK;
|
return OK;
|
||||||
printf("at_wini%d: sys_vinb failed: %d pvb (%d):\n", w_instance, s, n);
|
printf("at_wini%ld: sys_vinb failed: %d pvb (%d):\n", w_instance, s, n);
|
||||||
for(i = 0; i < n; i++)
|
for(i = 0; i < n; i++)
|
||||||
printf("%2d: %4x\n", i, pvb[i].port);
|
printf("%2d: %4x\n", i, pvb[i].port);
|
||||||
panic("sys_vinb failed");
|
panic("sys_vinb failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE int at_out(int line, u32_t port, u32_t value,
|
PRIVATE int at_out(int line, u32_t port, unsigned long value,
|
||||||
char *typename, int type)
|
char *typename, int type)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
s = sys_out(port, value, type);
|
s = sys_out(port, value, type);
|
||||||
if(s == OK)
|
if(s == OK)
|
||||||
return OK;
|
return OK;
|
||||||
printf("at_wini%d: line %d: %s failed: %d; %x -> %x\n",
|
printf("at_wini%ld: line %d: %s failed: %d; %lx -> %x\n",
|
||||||
w_instance, line, typename, s, value, port);
|
w_instance, line, typename, s, value, port);
|
||||||
panic("sys_out failed");
|
panic("sys_out failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PRIVATE int at_in(int line, u32_t port, u32_t *value,
|
PRIVATE int at_in(int line, u32_t port, unsigned long *value,
|
||||||
char *typename, int type)
|
char *typename, int type)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
s = sys_in(port, value, type);
|
s = sys_in(port, value, type);
|
||||||
if(s == OK)
|
if(s == OK)
|
||||||
return OK;
|
return OK;
|
||||||
printf("at_wini%d: line %d: %s failed: %d; port %x\n",
|
printf("at_wini%ld: line %d: %s failed: %d; port %x\n",
|
||||||
w_instance, line, typename, s, port);
|
w_instance, line, typename, s, port);
|
||||||
panic("sys_in failed");
|
panic("sys_in failed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/driver.h>
|
#include <minix/blockdriver.h>
|
||||||
#include <minix/drvlib.h>
|
#include <minix/drvlib.h>
|
||||||
|
|
||||||
#define VERBOSE 0 /* display identify messages during boot */
|
#define VERBOSE 0 /* display identify messages during boot */
|
||||||
|
@ -217,3 +217,8 @@
|
||||||
|
|
||||||
#define NO_DMA_VAR "ata_no_dma"
|
#define NO_DMA_VAR "ata_no_dma"
|
||||||
|
|
||||||
|
/* BIOS parameter table layout. */
|
||||||
|
#define bp_cylinders(t) (t[0] | (t[1] << 8))
|
||||||
|
#define bp_heads(t) (t[2])
|
||||||
|
#define bp_precomp(t) (t[5] | (t[6] << 8))
|
||||||
|
#define bp_sectors(t) (t[14])
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
.include <bsd.own.mk>
|
.include <bsd.own.mk>
|
||||||
|
|
||||||
DPADD+= ${LIBAUDIODRIVER} ${LIBDRIVER} ${LIBSYS}
|
DPADD+= ${LIBAUDIODRIVER} ${LIBCHARDRIVER} ${LIBSYS}
|
||||||
LDADD+= -laudiodriver -ldriver -lsys
|
LDADD+= -laudiodriver -lchardriver -lsys
|
||||||
|
|
||||||
.if exists(${.CURDIR}/../../Makefile.inc)
|
.if exists(${.CURDIR}/../../Makefile.inc)
|
||||||
.include "${.CURDIR}/../../Makefile.inc"
|
.include "${.CURDIR}/../../Makefile.inc"
|
||||||
|
|
|
@ -4,8 +4,6 @@ SRCS= es1370.c ak4531.c pci_helper.c
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
LIBS += -ldriver
|
|
||||||
|
|
||||||
BINDIR?= /usr/sbin
|
BINDIR?= /usr/sbin
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
|
|
@ -70,7 +70,7 @@ PRIVATE int ak4531_write (u8_t address, u8_t data) {
|
||||||
u16_t to_be_written;
|
u16_t to_be_written;
|
||||||
|
|
||||||
|
|
||||||
if (address < MASTER_VOLUME_LCH || address > MIC_AMP_GAIN) return -1;
|
if (address > MIC_AMP_GAIN) return -1;
|
||||||
|
|
||||||
to_be_written = (u16_t)((address << 8) | data);
|
to_be_written = (u16_t)((address << 8) | data);
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,7 @@ int drv_reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int drv_start(int sub_dev, int DmaMode) {
|
int drv_start(int sub_dev, int UNUSED(DmaMode)) {
|
||||||
u32_t enable_bit, result = 0;
|
u32_t enable_bit, result = 0;
|
||||||
|
|
||||||
/* Write default values to device in case user failed to configure.
|
/* Write default values to device in case user failed to configure.
|
||||||
|
@ -503,7 +503,7 @@ PRIVATE int set_stereo(u32_t stereo, int sub_dev) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PRIVATE int set_sign(u32_t val, int sub_dev) {
|
PRIVATE int set_sign(u32_t UNUSED(val), int UNUSED(sub_dev)) {
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* helper functions for I/O *
|
* helper functions for I/O *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC unsigned pci_inb(u16_t port) {
|
PUBLIC unsigned pci_inb(u16_t port) {
|
||||||
u32_t value;
|
unsigned long value;
|
||||||
int s;
|
int s;
|
||||||
if ((s=sys_inb(port, &value)) !=OK)
|
if ((s=sys_inb(port, &value)) !=OK)
|
||||||
printf("%s: warning, sys_inb failed: %d\n", DRIVER_NAME, s);
|
printf("%s: warning, sys_inb failed: %d\n", DRIVER_NAME, s);
|
||||||
|
@ -24,7 +24,7 @@ PUBLIC unsigned pci_inb(u16_t port) {
|
||||||
|
|
||||||
|
|
||||||
PUBLIC unsigned pci_inw(u16_t port) {
|
PUBLIC unsigned pci_inw(u16_t port) {
|
||||||
u32_t value;
|
unsigned long value;
|
||||||
int s;
|
int s;
|
||||||
if ((s=sys_inw(port, &value)) !=OK)
|
if ((s=sys_inw(port, &value)) !=OK)
|
||||||
printf("%s: warning, sys_inw failed: %d\n", DRIVER_NAME, s);
|
printf("%s: warning, sys_inw failed: %d\n", DRIVER_NAME, s);
|
||||||
|
@ -33,7 +33,7 @@ PUBLIC unsigned pci_inw(u16_t port) {
|
||||||
|
|
||||||
|
|
||||||
PUBLIC unsigned pci_inl(u16_t port) {
|
PUBLIC unsigned pci_inl(u16_t port) {
|
||||||
u32_t value;
|
unsigned long value;
|
||||||
int s;
|
int s;
|
||||||
if ((s=sys_inl(port, &value)) !=OK)
|
if ((s=sys_inl(port, &value)) !=OK)
|
||||||
printf("%s: warning, sys_inl failed: %d\n", DRIVER_NAME, s);
|
printf("%s: warning, sys_inl failed: %d\n", DRIVER_NAME, s);
|
||||||
|
|
|
@ -227,7 +227,7 @@ int drv_reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int drv_start(int sub_dev, int DmaMode) {
|
int drv_start(int sub_dev, int UNUSED(DmaMode)) {
|
||||||
u32_t enable_bit, result = 0;
|
u32_t enable_bit, result = 0;
|
||||||
|
|
||||||
/* Write default values to device in case user failed to configure.
|
/* Write default values to device in case user failed to configure.
|
||||||
|
@ -504,7 +504,7 @@ PRIVATE int set_stereo(u32_t stereo, int sub_dev) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PRIVATE int set_sign(u32_t val, int sub_dev) {
|
PRIVATE int set_sign(u32_t UNUSED(val), int UNUSED(sub_dev)) {
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* helper functions for I/O *
|
* helper functions for I/O *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC unsigned pci_inb(u16_t port) {
|
PUBLIC unsigned pci_inb(u16_t port) {
|
||||||
u32_t value;
|
unsigned long value;
|
||||||
int s;
|
int s;
|
||||||
if ((s=sys_inb(port, &value)) !=OK)
|
if ((s=sys_inb(port, &value)) !=OK)
|
||||||
printf("%s: warning, sys_inb failed: %d\n", DRIVER_NAME, s);
|
printf("%s: warning, sys_inb failed: %d\n", DRIVER_NAME, s);
|
||||||
|
@ -24,7 +24,7 @@ PUBLIC unsigned pci_inb(u16_t port) {
|
||||||
|
|
||||||
|
|
||||||
PUBLIC unsigned pci_inw(u16_t port) {
|
PUBLIC unsigned pci_inw(u16_t port) {
|
||||||
u32_t value;
|
unsigned long value;
|
||||||
int s;
|
int s;
|
||||||
if ((s=sys_inw(port, &value)) !=OK)
|
if ((s=sys_inw(port, &value)) !=OK)
|
||||||
printf("%s: warning, sys_inw failed: %d\n", DRIVER_NAME, s);
|
printf("%s: warning, sys_inw failed: %d\n", DRIVER_NAME, s);
|
||||||
|
@ -33,7 +33,7 @@ PUBLIC unsigned pci_inw(u16_t port) {
|
||||||
|
|
||||||
|
|
||||||
PUBLIC unsigned pci_inl(u16_t port) {
|
PUBLIC unsigned pci_inl(u16_t port) {
|
||||||
u32_t value;
|
unsigned long value;
|
||||||
int s;
|
int s;
|
||||||
if ((s=sys_inl(port, &value)) !=OK)
|
if ((s=sys_inl(port, &value)) !=OK)
|
||||||
printf("%s: warning, sys_inl failed: %d\n", DRIVER_NAME, s);
|
printf("%s: warning, sys_inl failed: %d\n", DRIVER_NAME, s);
|
||||||
|
|
|
@ -170,7 +170,7 @@ void src_set_rate(const DEV_STRUCT * DSP, char base, u16_t rate) {
|
||||||
|
|
||||||
src_reg_write(DSP, base + SRC_INT_REGS_OFF,
|
src_reg_write(DSP, base + SRC_INT_REGS_OFF,
|
||||||
(wtemp & 0x00ffU) |
|
(wtemp & 0x00ffU) |
|
||||||
(u16_t) (freq >> 6) & 0xfc00);
|
((u16_t) (freq >> 6) & 0xfc00));
|
||||||
|
|
||||||
src_reg_write(DSP, base + SRC_VFREQ_FRAC_OFF, (u16_t) freq >> 1);
|
src_reg_write(DSP, base + SRC_VFREQ_FRAC_OFF, (u16_t) freq >> 1);
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ void src_set_rate(const DEV_STRUCT * DSP, char base, u16_t rate) {
|
||||||
src_reg_read(DSP, base + SRC_INT_REGS_OFF, &wtemp);
|
src_reg_read(DSP, base + SRC_INT_REGS_OFF, &wtemp);
|
||||||
src_reg_write(DSP, base + SRC_INT_REGS_OFF,
|
src_reg_write(DSP, base + SRC_INT_REGS_OFF,
|
||||||
(wtemp & 0x00ffU) |
|
(wtemp & 0x00ffU) |
|
||||||
(u16_t) (freq >> 6) & 0xfc00);
|
((u16_t) (freq >> 6) & 0xfc00));
|
||||||
src_reg_write(DSP, base + SRC_VFREQ_FRAC_OFF, (u16_t) freq >> 1);
|
src_reg_write(DSP, base + SRC_VFREQ_FRAC_OFF, (u16_t) freq >> 1);
|
||||||
|
|
||||||
/* un-freeze the channel */
|
/* un-freeze the channel */
|
||||||
|
|
|
@ -13,7 +13,7 @@ FORWARD _PROTOTYPE( int get_set_output, (struct inout_ctrl *output, int flag));
|
||||||
/*=========================================================================*
|
/*=========================================================================*
|
||||||
* mixer_ioctl
|
* mixer_ioctl
|
||||||
*=========================================================================*/
|
*=========================================================================*/
|
||||||
PUBLIC int mixer_ioctl(int request, void *val, int *len) {
|
PUBLIC int mixer_ioctl(int request, void *val, int *UNUSED(len)) {
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
switch(request) {
|
switch(request) {
|
||||||
|
|
|
@ -190,7 +190,7 @@ PUBLIC int drv_stop(int sub_dev) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PUBLIC int drv_set_dma(u32_t dma, u32_t length, int chan) {
|
PUBLIC int drv_set_dma(u32_t dma, u32_t UNUSED(length), int UNUSED(chan)) {
|
||||||
Dprint(("drv_set_dma():\n"));
|
Dprint(("drv_set_dma():\n"));
|
||||||
DmaPhys = dma;
|
DmaPhys = dma;
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -198,7 +198,7 @@ PUBLIC int drv_set_dma(u32_t dma, u32_t length, int chan) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PUBLIC int drv_reenable_int(int chan) {
|
PUBLIC int drv_reenable_int(int UNUSED(chan)) {
|
||||||
Dprint(("drv_reenable_int()\n"));
|
Dprint(("drv_reenable_int()\n"));
|
||||||
sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));
|
sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -225,7 +225,7 @@ PUBLIC int drv_pause(int chan) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PUBLIC int drv_resume(int chan) {
|
PUBLIC int drv_resume(int UNUSED(chan)) {
|
||||||
dsp_command((DspBits == 8 ? DSP_CMD_DMA8CONT : DSP_CMD_DMA16CONT));
|
dsp_command((DspBits == 8 ? DSP_CMD_DMA8CONT : DSP_CMD_DMA16CONT));
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ PUBLIC int drv_get_irq(char *irq) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PUBLIC int drv_get_frag_size(u32_t *frag_size, int sub_dev) {
|
PUBLIC int drv_get_frag_size(u32_t *frag_size, int UNUSED(sub_dev)) {
|
||||||
Dprint(("drv_get_frag_size():\n"));
|
Dprint(("drv_get_frag_size():\n"));
|
||||||
*frag_size = DspFragmentSize;
|
*frag_size = DspFragmentSize;
|
||||||
return OK;
|
return OK;
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
PROG= bios_wini
|
PROG= bios_wini
|
||||||
SRCS= bios_wini.c
|
SRCS= bios_wini.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
|
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS} ${LIBTIMERS}
|
||||||
LDADD+= -ldriver -lsys -ltimers
|
LDADD+= -lblockdriver -lsys -ltimers
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/driver.h>
|
#include <minix/blockdriver.h>
|
||||||
#include <minix/drvlib.h>
|
#include <minix/drvlib.h>
|
||||||
#include <minix/sysutil.h>
|
#include <minix/sysutil.h>
|
||||||
#include <minix/safecopies.h>
|
#include <minix/safecopies.h>
|
||||||
|
@ -29,8 +29,6 @@
|
||||||
#include <machine/int86.h>
|
#include <machine/int86.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#define ME "BIOS_WINI"
|
|
||||||
|
|
||||||
/* Parameters for the disk drive. */
|
/* Parameters for the disk drive. */
|
||||||
#define MAX_DRIVES 8 /* this driver supports 8 drives (d0 - d7)*/
|
#define MAX_DRIVES 8 /* this driver supports 8 drives (d0 - d7)*/
|
||||||
#define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE)
|
#define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE)
|
||||||
|
@ -58,31 +56,31 @@ PRIVATE int remap_first = 0; /* Remap drives for CD HD emulation */
|
||||||
#define BIOSBUF 16384
|
#define BIOSBUF 16384
|
||||||
|
|
||||||
_PROTOTYPE(int main, (void) );
|
_PROTOTYPE(int main, (void) );
|
||||||
FORWARD _PROTOTYPE( struct device *w_prepare, (int device) );
|
FORWARD _PROTOTYPE( struct device *w_prepare, (dev_t device) );
|
||||||
FORWARD _PROTOTYPE( char *w_name, (void) );
|
FORWARD _PROTOTYPE( struct device *w_part, (dev_t minor) );
|
||||||
FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, u64_t position,
|
FORWARD _PROTOTYPE( ssize_t w_transfer, (dev_t minor, int do_write,
|
||||||
iovec_t *iov, unsigned nr_req) );
|
u64_t position, endpoint_t endpt, iovec_t *iov, unsigned int nr_req,
|
||||||
FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
|
int flags) );
|
||||||
FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int w_do_open, (dev_t minor, int access) );
|
||||||
|
FORWARD _PROTOTYPE( int w_do_close, (dev_t minor) );
|
||||||
FORWARD _PROTOTYPE( void w_init, (void) );
|
FORWARD _PROTOTYPE( void w_init, (void) );
|
||||||
FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry));
|
FORWARD _PROTOTYPE( void w_geometry, (dev_t minor, struct partition *entry));
|
||||||
FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int w_ioctl, (dev_t minor, unsigned int request,
|
||||||
|
endpoint_t endpt, cp_grant_id_t grant) );
|
||||||
|
|
||||||
/* Entry points to this driver. */
|
/* Entry points to this driver. */
|
||||||
PRIVATE struct driver w_dtab = {
|
PRIVATE struct blockdriver w_dtab = {
|
||||||
w_name, /* current device's name */
|
|
||||||
w_do_open, /* open or mount request, initialize device */
|
w_do_open, /* open or mount request, initialize device */
|
||||||
w_do_close, /* release 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 */
|
w_transfer, /* do the I/O */
|
||||||
nop_cleanup, /* no cleanup needed */
|
w_ioctl, /* I/O control */
|
||||||
|
NULL, /* no cleanup needed */
|
||||||
|
w_part, /* return partition information structure */
|
||||||
w_geometry, /* tell the geometry of the disk */
|
w_geometry, /* tell the geometry of the disk */
|
||||||
nop_alarm, /* ignore leftover alarms */
|
NULL, /* leftover hardware interrupts */
|
||||||
nop_cancel, /* ignore CANCELs */
|
NULL, /* ignore leftover alarms */
|
||||||
nop_select, /* ignore selects */
|
NULL, /* catch-all for unrecognized commands */
|
||||||
w_other, /* catch-all for unrecognized commands and ioctls */
|
NULL /* no threading support */
|
||||||
NULL /* leftover hardware interrupts */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SEF functions and variables. */
|
/* SEF functions and variables. */
|
||||||
|
@ -92,13 +90,13 @@ FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* bios_winchester_task *
|
* bios_winchester_task *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int main()
|
PUBLIC int main(void)
|
||||||
{
|
{
|
||||||
/* SEF local startup. */
|
/* SEF local startup. */
|
||||||
sef_local_startup();
|
sef_local_startup();
|
||||||
|
|
||||||
/* Call the generic receive loop. */
|
/* Call the generic receive loop. */
|
||||||
driver_task(&w_dtab, DRIVER_STD);
|
blockdriver_task(&w_dtab);
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
@ -106,7 +104,7 @@ PUBLIC int main()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_local_startup *
|
* sef_local_startup *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void sef_local_startup()
|
PRIVATE void sef_local_startup(void)
|
||||||
{
|
{
|
||||||
/* Register init callbacks. */
|
/* Register init callbacks. */
|
||||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||||
|
@ -124,7 +122,7 @@ PRIVATE void sef_local_startup()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_cb_init_fresh *
|
* sef_cb_init_fresh *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
|
PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
{
|
{
|
||||||
/* Initialize the bios_wini driver. */
|
/* Initialize the bios_wini driver. */
|
||||||
long v;
|
long v;
|
||||||
|
@ -134,7 +132,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
|
||||||
remap_first = v;
|
remap_first = v;
|
||||||
|
|
||||||
/* Announce we are up! */
|
/* Announce we are up! */
|
||||||
driver_announce();
|
blockdriver_announce();
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
@ -142,8 +140,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_prepare *
|
* w_prepare *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE struct device *w_prepare(device)
|
PRIVATE struct device *w_prepare(dev_t device)
|
||||||
int device;
|
|
||||||
{
|
{
|
||||||
/* Prepare for I/O on a device. */
|
/* Prepare for I/O on a device. */
|
||||||
|
|
||||||
|
@ -165,35 +162,36 @@ int device;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_name *
|
* w_part *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE char *w_name()
|
PRIVATE struct device *w_part(dev_t minor)
|
||||||
{
|
{
|
||||||
/* Return a name for the current device. */
|
/* Return a pointer to the partition information of the given minor device. */
|
||||||
static char name[] = "bios-d0";
|
|
||||||
|
|
||||||
name[6] = '0' + w_drive;
|
return w_prepare(minor);
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_transfer *
|
* w_transfer *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int w_transfer(proc_nr, opcode, pos64, iov, nr_req)
|
PRIVATE ssize_t w_transfer(
|
||||||
int proc_nr; /* process doing the request */
|
dev_t minor, /* minor device number */
|
||||||
int opcode; /* DEV_GATHER or DEV_SCATTER */
|
int do_write, /* read or write? */
|
||||||
u64_t pos64; /* offset on device to read or write */
|
u64_t pos64, /* offset on device to read or write */
|
||||||
iovec_t *iov; /* pointer to read or write request vector */
|
endpoint_t proc_nr, /* process doing the request */
|
||||||
unsigned nr_req; /* length of request vector */
|
iovec_t *iov, /* pointer to read or write request vector */
|
||||||
|
unsigned int nr_req, /* length of request vector */
|
||||||
|
int UNUSED(flags) /* transfer flags */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
struct wini *wn = w_wn;
|
struct wini *wn;
|
||||||
iovec_t *iop, *iov_end = iov + nr_req;
|
iovec_t *iop, *iov_end = iov + nr_req;
|
||||||
int r, errors;
|
int r, errors;
|
||||||
unsigned count;
|
unsigned count;
|
||||||
vir_bytes chunk, nbytes;
|
vir_bytes chunk, nbytes;
|
||||||
unsigned long block;
|
unsigned long block;
|
||||||
vir_bytes i13e_rw_off, rem_buf_size;
|
vir_bytes i13e_rw_off, rem_buf_size;
|
||||||
unsigned secspcyl = wn->heads * wn->sectors;
|
unsigned secspcyl;
|
||||||
struct int13ext_rw {
|
struct int13ext_rw {
|
||||||
u8_t len;
|
u8_t len;
|
||||||
u8_t res1;
|
u8_t res1;
|
||||||
|
@ -203,12 +201,19 @@ unsigned nr_req; /* length of request vector */
|
||||||
} *i13e_rw;
|
} *i13e_rw;
|
||||||
struct reg86u reg86;
|
struct reg86u reg86;
|
||||||
u32_t lopos;
|
u32_t lopos;
|
||||||
|
ssize_t total;
|
||||||
|
|
||||||
|
if (w_prepare(minor) == NULL) return(ENXIO);
|
||||||
|
|
||||||
|
wn = w_wn;
|
||||||
|
secspcyl = wn->heads * wn->sectors;
|
||||||
|
|
||||||
lopos= ex64lo(pos64);
|
lopos= ex64lo(pos64);
|
||||||
|
|
||||||
/* Check disk address. */
|
/* Check disk address. */
|
||||||
if ((lopos & SECTOR_MASK) != 0) return(EINVAL);
|
if ((lopos & SECTOR_MASK) != 0) return(EINVAL);
|
||||||
|
|
||||||
|
total = 0;
|
||||||
errors = 0;
|
errors = 0;
|
||||||
|
|
||||||
i13e_rw_off= BIOSBUF-sizeof(*i13e_rw);
|
i13e_rw_off= BIOSBUF-sizeof(*i13e_rw);
|
||||||
|
@ -230,7 +235,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
|
if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
|
||||||
|
|
||||||
/* Which block on disk and how close to EOF? */
|
/* Which block on disk and how close to EOF? */
|
||||||
if (cmp64(pos64, w_dv->dv_size) >= 0) return(OK); /* At EOF */
|
if (cmp64(pos64, w_dv->dv_size) >= 0) return(total); /* At EOF */
|
||||||
if (cmp64(add64u(pos64, nbytes), w_dv->dv_size) > 0) {
|
if (cmp64(add64u(pos64, nbytes), w_dv->dv_size) > 0) {
|
||||||
u64_t n;
|
u64_t n;
|
||||||
n = sub64(w_dv->dv_size, pos64);
|
n = sub64(w_dv->dv_size, pos64);
|
||||||
|
@ -242,7 +247,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
/* Degrade to per-sector mode if there were errors. */
|
/* Degrade to per-sector mode if there were errors. */
|
||||||
if (errors > 0) nbytes = SECTOR_SIZE;
|
if (errors > 0) nbytes = SECTOR_SIZE;
|
||||||
|
|
||||||
if (opcode == DEV_SCATTER_S) {
|
if (do_write) {
|
||||||
/* Copy from user space to the DMA buffer. */
|
/* Copy from user space to the DMA buffer. */
|
||||||
count = 0;
|
count = 0;
|
||||||
for (iop = iov; count < nbytes; iop++) {
|
for (iop = iov; count < nbytes; iop++) {
|
||||||
|
@ -277,7 +282,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
|
|
||||||
/* Set up an extended read or write BIOS call. */
|
/* Set up an extended read or write BIOS call. */
|
||||||
reg86.u.b.intno = 0x13;
|
reg86.u.b.intno = 0x13;
|
||||||
reg86.u.w.ax = opcode == DEV_SCATTER_S ? 0x4300 : 0x4200;
|
reg86.u.w.ax = do_write ? 0x4300 : 0x4200;
|
||||||
reg86.u.b.dl = wn->drive_id;
|
reg86.u.b.dl = wn->drive_id;
|
||||||
reg86.u.w.si = (bios_buf_phys + i13e_rw_off) % HCLICK_SIZE;
|
reg86.u.w.si = (bios_buf_phys + i13e_rw_off) % HCLICK_SIZE;
|
||||||
reg86.u.w.ds = (bios_buf_phys + i13e_rw_off) / HCLICK_SIZE;
|
reg86.u.w.ds = (bios_buf_phys + i13e_rw_off) / HCLICK_SIZE;
|
||||||
|
@ -288,7 +293,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
unsigned head = (block % secspcyl) / wn->sectors;
|
unsigned head = (block % secspcyl) / wn->sectors;
|
||||||
|
|
||||||
reg86.u.b.intno = 0x13;
|
reg86.u.b.intno = 0x13;
|
||||||
reg86.u.b.ah = opcode == DEV_SCATTER_S ? 0x03 : 0x02;
|
reg86.u.b.ah = do_write ? 0x03 : 0x02;
|
||||||
reg86.u.b.al = nbytes >> SECTOR_SHIFT;
|
reg86.u.b.al = nbytes >> SECTOR_SHIFT;
|
||||||
reg86.u.w.bx = bios_buf_phys % HCLICK_SIZE;
|
reg86.u.w.bx = bios_buf_phys % HCLICK_SIZE;
|
||||||
reg86.u.w.es = bios_buf_phys / HCLICK_SIZE;
|
reg86.u.w.es = bios_buf_phys / HCLICK_SIZE;
|
||||||
|
@ -308,7 +313,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode == DEV_GATHER_S) {
|
if (!do_write) {
|
||||||
/* Copy from the DMA buffer to user space. */
|
/* Copy from the DMA buffer to user space. */
|
||||||
count = 0;
|
count = 0;
|
||||||
for (iop = iov; count < nbytes; iop++) {
|
for (iop = iov; count < nbytes; iop++) {
|
||||||
|
@ -333,7 +338,8 @@ unsigned nr_req; /* length of request vector */
|
||||||
|
|
||||||
/* Book the bytes successfully transferred. */
|
/* Book the bytes successfully transferred. */
|
||||||
pos64 = add64ul(pos64, nbytes);
|
pos64 = add64ul(pos64, nbytes);
|
||||||
for (;;) {
|
total += nbytes;
|
||||||
|
while (nbytes > 0) {
|
||||||
if (nbytes < iov->iov_size) {
|
if (nbytes < iov->iov_size) {
|
||||||
/* Not done with this one yet. */
|
/* Not done with this one yet. */
|
||||||
iov->iov_size -= nbytes;
|
iov->iov_size -= nbytes;
|
||||||
|
@ -341,25 +347,17 @@ unsigned nr_req; /* length of request vector */
|
||||||
}
|
}
|
||||||
nbytes -= iov->iov_size;
|
nbytes -= iov->iov_size;
|
||||||
iov->iov_size = 0;
|
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++;
|
iov++;
|
||||||
nr_req--;
|
nr_req--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(OK);
|
return(total);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* w_do_open *
|
* w_do_open *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
PRIVATE int w_do_open(dp, m_ptr)
|
PRIVATE int w_do_open(dev_t minor, int UNUSED(access))
|
||||||
struct driver *dp;
|
|
||||||
message *m_ptr;
|
|
||||||
{
|
{
|
||||||
/* Device open: Initialize the controller and read the partition table. */
|
/* Device open: Initialize the controller and read the partition table. */
|
||||||
|
|
||||||
|
@ -367,7 +365,7 @@ message *m_ptr;
|
||||||
|
|
||||||
if (!init_done) { w_init(); init_done = TRUE; }
|
if (!init_done) { w_init(); init_done = TRUE; }
|
||||||
|
|
||||||
if (w_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
if (w_prepare(minor) == NULL) return(ENXIO);
|
||||||
|
|
||||||
if (w_wn->open_ct++ == 0) {
|
if (w_wn->open_ct++ == 0) {
|
||||||
/* Partition the disk. */
|
/* Partition the disk. */
|
||||||
|
@ -379,13 +377,11 @@ message *m_ptr;
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* w_do_close *
|
* w_do_close *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
PRIVATE int w_do_close(dp, m_ptr)
|
PRIVATE int w_do_close(dev_t minor)
|
||||||
struct driver *dp;
|
|
||||||
message *m_ptr;
|
|
||||||
{
|
{
|
||||||
/* Device close: Release a device. */
|
/* Device close: Release a device. */
|
||||||
|
|
||||||
if (w_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
if (w_prepare(minor) == NULL) return(ENXIO);
|
||||||
w_wn->open_ct--;
|
w_wn->open_ct--;
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
@ -393,7 +389,7 @@ message *m_ptr;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_init *
|
* w_init *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void w_init()
|
PRIVATE void w_init(void)
|
||||||
{
|
{
|
||||||
/* This routine is called at startup to initialize the drive parameters. */
|
/* This routine is called at startup to initialize the drive parameters. */
|
||||||
|
|
||||||
|
@ -490,10 +486,11 @@ PRIVATE void w_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wn->int13ext) {
|
if (wn->int13ext) {
|
||||||
printf("%s: %lu sectors\n", w_name(), capacity);
|
printf("bios-d%u: %lu sectors\n", w_drive, capacity);
|
||||||
} else {
|
} else {
|
||||||
printf("%s: %d cylinders, %d heads, %d sectors per track\n",
|
printf("bios-d%u: %d cylinders, %d heads, "
|
||||||
w_name(), wn->cylinders, wn->heads, wn->sectors);
|
"%d sectors per track\n",
|
||||||
|
w_drive, wn->cylinders, wn->heads, wn->sectors);
|
||||||
}
|
}
|
||||||
wn->part[0].dv_size = mul64u(capacity, SECTOR_SIZE);
|
wn->part[0].dv_size = mul64u(capacity, SECTOR_SIZE);
|
||||||
}
|
}
|
||||||
|
@ -502,37 +499,30 @@ PRIVATE void w_init()
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* w_geometry *
|
* w_geometry *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
PRIVATE void w_geometry(entry)
|
PRIVATE void w_geometry(dev_t minor, struct partition *entry)
|
||||||
struct partition *entry;
|
|
||||||
{
|
{
|
||||||
|
if (w_prepare(minor) == NULL) return;
|
||||||
|
|
||||||
entry->cylinders = w_wn->cylinders;
|
entry->cylinders = w_wn->cylinders;
|
||||||
entry->heads = w_wn->heads;
|
entry->heads = w_wn->heads;
|
||||||
entry->sectors = w_wn->sectors;
|
entry->sectors = w_wn->sectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* w_other *
|
* w_ioctl *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
PRIVATE int w_other(struct driver *UNUSED(dr), message *m)
|
PRIVATE int w_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||||
|
cp_grant_id_t grant)
|
||||||
{
|
{
|
||||||
int r;
|
|
||||||
|
|
||||||
if (m->m_type != DEV_IOCTL_S )
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
if (m->REQUEST == DIOCOPENCT) {
|
|
||||||
int count;
|
int count;
|
||||||
if (w_prepare(m->DEVICE) == NULL) return ENXIO;
|
|
||||||
count = w_wn->open_ct;
|
|
||||||
r=sys_safecopyto(m->m_source, (cp_grant_id_t)m->IO_GRANT,
|
|
||||||
0, (vir_bytes)&count, sizeof(count), D);
|
|
||||||
|
|
||||||
if(r != OK)
|
if (w_prepare(minor) == NULL) return ENXIO;
|
||||||
return r;
|
|
||||||
return OK;
|
if (request == DIOCOPENCT) {
|
||||||
|
count = w_wn->open_ct;
|
||||||
|
return sys_safecopyto(endpt, grant, 0, (vir_bytes)&count,
|
||||||
|
sizeof(count), D);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
PROG= filter
|
PROG= filter
|
||||||
SRCS= main.c sum.c driver.c util.c crc.c md5.c
|
SRCS= main.c sum.c driver.c util.c crc.c md5.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS}
|
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS}
|
||||||
LDADD+= -ldriver -lsys
|
LDADD+= -lblockdriver -lsys
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ unsigned long compute_crc(const unsigned char *b, size_t n)
|
||||||
/* Replace an intermediate zero with the next value
|
/* Replace an intermediate zero with the next value
|
||||||
* from the sequence */
|
* from the sequence */
|
||||||
i = aux++;
|
i = aux++;
|
||||||
if (aux >= sizeof(crctab) / sizeof(crctab[0])) aux = 0;
|
if ((size_t) aux >= sizeof(crctab) / sizeof(crctab[0])) aux = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* New checksum value */
|
/* New checksum value */
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
static struct driverinfo driver[2];
|
static struct driverinfo driver[2];
|
||||||
|
|
||||||
/* State variables. */
|
/* State variables. */
|
||||||
static endpoint_t self_ep;
|
|
||||||
static asynmsg_t amsgtable[2];
|
static asynmsg_t amsgtable[2];
|
||||||
|
|
||||||
static int size_known = 0;
|
static int size_known = 0;
|
||||||
|
@ -29,9 +28,11 @@ static int driver_open(int which)
|
||||||
sector_t sectors;
|
sector_t sectors;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
msg.m_type = DEV_OPEN;
|
memset(&msg, 0, sizeof(msg));
|
||||||
msg.DEVICE = driver[which].minor;
|
msg.m_type = BDEV_OPEN;
|
||||||
msg.USER_ENDPT = self_ep;
|
msg.BDEV_MINOR = driver[which].minor;
|
||||||
|
msg.BDEV_ACCESS = R_BIT | W_BIT;
|
||||||
|
msg.BDEV_ID = 0;
|
||||||
r = sendrec(driver[which].endpt, &msg);
|
r = sendrec(driver[which].endpt, &msg);
|
||||||
|
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
|
@ -41,9 +42,9 @@ static int driver_open(int which)
|
||||||
return RET_REDO;
|
return RET_REDO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(msg.m_type != TASK_REPLY || msg.REP_STATUS != OK) {
|
if(msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) {
|
||||||
printf("Filter: driver_open: sendrec returned %d, %d\n",
|
printf("Filter: driver_open: sendrec returned %d, %d\n",
|
||||||
msg.m_type, msg.REP_STATUS);
|
msg.m_type, msg.BDEV_STATUS);
|
||||||
|
|
||||||
return RET_REDO;
|
return RET_REDO;
|
||||||
}
|
}
|
||||||
|
@ -54,17 +55,18 @@ static int driver_open(int which)
|
||||||
if(!GRANT_VALID(gid))
|
if(!GRANT_VALID(gid))
|
||||||
panic("invalid grant: %d", gid);
|
panic("invalid grant: %d", gid);
|
||||||
|
|
||||||
msg.m_type = DEV_IOCTL_S;
|
memset(&msg, 0, sizeof(msg));
|
||||||
msg.REQUEST = DIOCGETP;
|
msg.m_type = BDEV_IOCTL;
|
||||||
msg.DEVICE = driver[which].minor;
|
msg.BDEV_MINOR = driver[which].minor;
|
||||||
msg.USER_ENDPT = self_ep;
|
msg.BDEV_REQUEST = DIOCGETP;
|
||||||
msg.IO_GRANT = (char *) gid;
|
msg.BDEV_GRANT = gid;
|
||||||
|
msg.BDEV_ID = 0;
|
||||||
|
|
||||||
r = sendrec(driver[which].endpt, &msg);
|
r = sendrec(driver[which].endpt, &msg);
|
||||||
|
|
||||||
cpf_revoke(gid);
|
cpf_revoke(gid);
|
||||||
|
|
||||||
if (r != OK || msg.m_type != TASK_REPLY || msg.REP_STATUS != OK) {
|
if (r != OK || msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) {
|
||||||
/* Not sure what to do here, either. */
|
/* Not sure what to do here, either. */
|
||||||
printf("Filter: ioctl(DIOCGETP) returned (%d, %d)\n",
|
printf("Filter: ioctl(DIOCGETP) returned (%d, %d)\n",
|
||||||
r, msg.m_type);
|
r, msg.m_type);
|
||||||
|
@ -105,9 +107,10 @@ static int driver_close(int which)
|
||||||
message msg;
|
message msg;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
msg.m_type = DEV_CLOSE;
|
memset(&msg, 0, sizeof(msg));
|
||||||
msg.DEVICE = driver[which].minor;
|
msg.m_type = BDEV_CLOSE;
|
||||||
msg.USER_ENDPT = self_ep;
|
msg.BDEV_MINOR = driver[which].minor;
|
||||||
|
msg.BDEV_ID = 0;
|
||||||
r = sendrec(driver[which].endpt, &msg);
|
r = sendrec(driver[which].endpt, &msg);
|
||||||
|
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
|
@ -117,9 +120,9 @@ static int driver_close(int which)
|
||||||
return RET_REDO;
|
return RET_REDO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(msg.m_type != TASK_REPLY || msg.REP_STATUS != OK) {
|
if(msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) {
|
||||||
printf("Filter: driver_close: sendrec returned %d, %d\n",
|
printf("Filter: driver_close: sendrec returned %d, %d\n",
|
||||||
msg.m_type, msg.REP_STATUS);
|
msg.m_type, msg.BDEV_STATUS);
|
||||||
|
|
||||||
return RET_REDO;
|
return RET_REDO;
|
||||||
}
|
}
|
||||||
|
@ -135,8 +138,6 @@ void driver_init(void)
|
||||||
/* Initialize the driver layer. */
|
/* Initialize the driver layer. */
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
self_ep = getprocnr();
|
|
||||||
|
|
||||||
memset(driver, 0, sizeof(driver));
|
memset(driver, 0, sizeof(driver));
|
||||||
|
|
||||||
/* Endpoints unknown. */
|
/* Endpoints unknown. */
|
||||||
|
@ -200,11 +201,11 @@ void driver_shutdown(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(driver_close(DRIVER_MAIN) != OK)
|
if(driver_close(DRIVER_MAIN) != OK)
|
||||||
printf("Filter: DEV_CLOSE failed on shutdown (1)\n");
|
printf("Filter: BDEV_CLOSE failed on shutdown (1)\n");
|
||||||
|
|
||||||
if(USE_MIRROR)
|
if(USE_MIRROR)
|
||||||
if(driver_close(DRIVER_BACKUP) != OK)
|
if(driver_close(DRIVER_BACKUP) != OK)
|
||||||
printf("Filter: DEV_CLOSE failed on shutdown (2)\n");
|
printf("Filter: BDEV_CLOSE failed on shutdown (2)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -520,8 +521,8 @@ static int flt_senda(message *mess, int which)
|
||||||
asynmsg_t *amp;
|
asynmsg_t *amp;
|
||||||
|
|
||||||
/* Fill in the last bits of the message. */
|
/* Fill in the last bits of the message. */
|
||||||
mess->DEVICE = driver[which].minor;
|
mess->BDEV_MINOR = driver[which].minor;
|
||||||
mess->USER_ENDPT = self_ep;
|
mess->BDEV_ID = 0;
|
||||||
|
|
||||||
/* Send the message asynchronously. */
|
/* Send the message asynchronously. */
|
||||||
amp = &amsgtable[which];
|
amp = &amsgtable[which];
|
||||||
|
@ -745,7 +746,7 @@ static int do_sendrec_both(message *m1, message *m2)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_sendrec_one *
|
* do_sendrec_one *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int do_sendrec_one(message *m1, const message *m2)
|
static int do_sendrec_one(message *m1)
|
||||||
{
|
{
|
||||||
/* Only talk to the main driver. If something goes wrong, it will
|
/* Only talk to the main driver. If something goes wrong, it will
|
||||||
* be fixed elsewhere.
|
* be fixed elsewhere.
|
||||||
|
@ -768,14 +769,14 @@ static int paired_sendrec(message *m1, message *m2, int both)
|
||||||
|
|
||||||
#if DEBUG2
|
#if DEBUG2
|
||||||
printf("paired_sendrec(%d) - <%d,%x:%x,%d> - %x,%x\n",
|
printf("paired_sendrec(%d) - <%d,%x:%x,%d> - %x,%x\n",
|
||||||
both, m1->m_type, m1->HIGHPOS, m1->POSITION, m1->COUNT,
|
both, m1->m_type, m1->BDEV_POS_HI, m1->BDEV_POS_LO,
|
||||||
m1->IO_GRANT, m2->IO_GRANT);
|
m1->BDEV_COUNT, m1->BDEV_GRANT, m2->BDEV_GRANT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (both)
|
if (both)
|
||||||
r = do_sendrec_both(m1, m2);
|
r = do_sendrec_both(m1, m2);
|
||||||
else
|
else
|
||||||
r = do_sendrec_one(m1, m2);
|
r = do_sendrec_one(m1);
|
||||||
|
|
||||||
#if DEBUG2
|
#if DEBUG2
|
||||||
if (r != OK)
|
if (r != OK)
|
||||||
|
@ -789,16 +790,14 @@ static int paired_sendrec(message *m1, message *m2, int both)
|
||||||
* single_grant *
|
* single_grant *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int single_grant(endpoint_t endpt, vir_bytes buf, int access,
|
static int single_grant(endpoint_t endpt, vir_bytes buf, int access,
|
||||||
cp_grant_id_t *gid, iovec_s_t vector[NR_IOREQS], const size_t *sizep)
|
cp_grant_id_t *gid, iovec_s_t vector[NR_IOREQS], size_t size)
|
||||||
{
|
{
|
||||||
/* Create grants for a vectored request to a single driver.
|
/* Create grants for a vectored request to a single driver.
|
||||||
*/
|
*/
|
||||||
cp_grant_id_t grant;
|
cp_grant_id_t grant;
|
||||||
size_t size, chunk;
|
size_t chunk;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
size = *sizep;
|
|
||||||
|
|
||||||
/* Split up the request into chunks, if requested. This makes no
|
/* Split up the request into chunks, if requested. This makes no
|
||||||
* difference at all, except that this works around a weird performance
|
* difference at all, except that this works around a weird performance
|
||||||
* bug with large DMA PRDs on some machines.
|
* bug with large DMA PRDs on some machines.
|
||||||
|
@ -825,7 +824,7 @@ static int single_grant(endpoint_t endpt, vir_bytes buf, int access,
|
||||||
|
|
||||||
/* Then create a grant for the vector itself. */
|
/* Then create a grant for the vector itself. */
|
||||||
*gid = cpf_grant_direct(endpt, (vir_bytes) vector,
|
*gid = cpf_grant_direct(endpt, (vir_bytes) vector,
|
||||||
sizeof(vector[0]) * count, CPF_READ | CPF_WRITE);
|
sizeof(vector[0]) * count, CPF_READ);
|
||||||
|
|
||||||
if (!GRANT_VALID(*gid))
|
if (!GRANT_VALID(*gid))
|
||||||
panic("invalid grant: %d", *gid);
|
panic("invalid grant: %d", *gid);
|
||||||
|
@ -837,7 +836,7 @@ static int single_grant(endpoint_t endpt, vir_bytes buf, int access,
|
||||||
* paired_grant *
|
* paired_grant *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int paired_grant(char *buf1, char *buf2, int request,
|
static int paired_grant(char *buf1, char *buf2, int request,
|
||||||
cp_grant_id_t *gids, iovec_s_t vectors[2][NR_IOREQS], size_t *sizes,
|
cp_grant_id_t *gids, iovec_s_t vectors[2][NR_IOREQS], size_t size,
|
||||||
int both)
|
int both)
|
||||||
{
|
{
|
||||||
/* Create memory grants, either to one or to both drivers.
|
/* Create memory grants, either to one or to both drivers.
|
||||||
|
@ -849,15 +848,14 @@ static int paired_grant(char *buf1, char *buf2, int request,
|
||||||
|
|
||||||
if(driver[DRIVER_MAIN].endpt > 0) {
|
if(driver[DRIVER_MAIN].endpt > 0) {
|
||||||
count = single_grant(driver[DRIVER_MAIN].endpt,
|
count = single_grant(driver[DRIVER_MAIN].endpt,
|
||||||
(vir_bytes) buf1, access, &gids[0], vectors[0],
|
(vir_bytes) buf1, access, &gids[0], vectors[0], size);
|
||||||
&sizes[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (both) {
|
if (both) {
|
||||||
if(driver[DRIVER_BACKUP].endpt > 0) {
|
if(driver[DRIVER_BACKUP].endpt > 0) {
|
||||||
count = single_grant(driver[DRIVER_BACKUP].endpt,
|
count = single_grant(driver[DRIVER_BACKUP].endpt,
|
||||||
(vir_bytes) buf2, access, &gids[1],
|
(vir_bytes) buf2, access, &gids[1],
|
||||||
vectors[1], &sizes[1]);
|
vectors[1], size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
@ -866,8 +864,8 @@ static int paired_grant(char *buf1, char *buf2, int request,
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* single_revoke *
|
* single_revoke *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void single_revoke(cp_grant_id_t gid, const iovec_s_t vector[NR_IOREQS],
|
PRIVATE void single_revoke(cp_grant_id_t gid,
|
||||||
size_t *sizep, int count)
|
const iovec_s_t vector[NR_IOREQS], int count)
|
||||||
{
|
{
|
||||||
/* Revoke all grants associated with a request to a single driver.
|
/* Revoke all grants associated with a request to a single driver.
|
||||||
* Modify the given size to reflect the actual I/O performed.
|
* Modify the given size to reflect the actual I/O performed.
|
||||||
|
@ -875,10 +873,8 @@ PRIVATE void single_revoke(cp_grant_id_t gid, const iovec_s_t vector[NR_IOREQS],
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Revoke the grants for all the elements of the vector. */
|
/* Revoke the grants for all the elements of the vector. */
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++)
|
||||||
cpf_revoke(vector[i].iov_grant);
|
cpf_revoke(vector[i].iov_grant);
|
||||||
*sizep -= vector[i].iov_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Then revoke the grant for the vector itself. */
|
/* Then revoke the grant for the vector itself. */
|
||||||
cpf_revoke(gid);
|
cpf_revoke(gid);
|
||||||
|
@ -888,16 +884,15 @@ PRIVATE void single_revoke(cp_grant_id_t gid, const iovec_s_t vector[NR_IOREQS],
|
||||||
* paired_revoke *
|
* paired_revoke *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static void paired_revoke(const cp_grant_id_t *gids,
|
static void paired_revoke(const cp_grant_id_t *gids,
|
||||||
iovec_s_t vectors[2][NR_IOREQS],
|
iovec_s_t vectors[2][NR_IOREQS], int count, int both)
|
||||||
size_t *sizes, int count, int both)
|
|
||||||
{
|
{
|
||||||
/* Revoke grants to drivers for a single request.
|
/* Revoke grants to drivers for a single request.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
single_revoke(gids[0], vectors[0], &sizes[0], count);
|
single_revoke(gids[0], vectors[0], count);
|
||||||
|
|
||||||
if (both)
|
if (both)
|
||||||
single_revoke(gids[1], vectors[1], &sizes[1], count);
|
single_revoke(gids[1], vectors[1], count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -908,32 +903,31 @@ int read_write(u64_t pos, char *bufa, char *bufb, size_t *sizep, int request)
|
||||||
iovec_s_t vectors[2][NR_IOREQS];
|
iovec_s_t vectors[2][NR_IOREQS];
|
||||||
message m1, m2;
|
message m1, m2;
|
||||||
cp_grant_id_t gids[2];
|
cp_grant_id_t gids[2];
|
||||||
size_t sizes[2];
|
|
||||||
int r, both, count;
|
int r, both, count;
|
||||||
|
|
||||||
gids[0] = gids[1] = GRANT_INVALID;
|
gids[0] = gids[1] = GRANT_INVALID;
|
||||||
sizes[0] = sizes[1] = *sizep;
|
|
||||||
|
|
||||||
/* Send two requests only if mirroring is enabled and the given request
|
/* Send two requests only if mirroring is enabled and the given request
|
||||||
* is either FLT_READ2 or FLT_WRITE.
|
* is either FLT_READ2 or FLT_WRITE.
|
||||||
*/
|
*/
|
||||||
both = (USE_MIRROR && request != FLT_READ);
|
both = (USE_MIRROR && request != FLT_READ);
|
||||||
|
|
||||||
count = paired_grant(bufa, bufb, request, gids, vectors, sizes, both);
|
count = paired_grant(bufa, bufb, request, gids, vectors, *sizep, both);
|
||||||
|
|
||||||
m1.m_type = (request == FLT_WRITE) ? DEV_SCATTER_S : DEV_GATHER_S;
|
memset(&m1, 0, sizeof(m1));
|
||||||
m1.COUNT = count;
|
m1.m_type = (request == FLT_WRITE) ? BDEV_SCATTER : BDEV_GATHER;
|
||||||
m1.POSITION = ex64lo(pos);
|
m1.BDEV_COUNT = count;
|
||||||
m1.HIGHPOS = ex64hi(pos);
|
m1.BDEV_POS_LO = ex64lo(pos);
|
||||||
|
m1.BDEV_POS_HI = ex64hi(pos);
|
||||||
|
|
||||||
m2 = m1;
|
m2 = m1;
|
||||||
|
|
||||||
m1.IO_GRANT = (char *) gids[0];
|
m1.BDEV_GRANT = gids[0];
|
||||||
m2.IO_GRANT = (char *) gids[1];
|
m2.BDEV_GRANT = gids[1];
|
||||||
|
|
||||||
r = paired_sendrec(&m1, &m2, both);
|
r = paired_sendrec(&m1, &m2, both);
|
||||||
|
|
||||||
paired_revoke(gids, vectors, sizes, count, both);
|
paired_revoke(gids, vectors, count, both);
|
||||||
|
|
||||||
if(r != OK) {
|
if(r != OK) {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@ -943,51 +937,52 @@ int read_write(u64_t pos, char *bufa, char *bufb, size_t *sizep, int request)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m1.m_type != TASK_REPLY || m1.REP_STATUS != OK) {
|
if (m1.m_type != BDEV_REPLY || m1.BDEV_STATUS < 0) {
|
||||||
printf("Filter: unexpected/invalid reply from main driver: "
|
printf("Filter: unexpected/invalid reply from main driver: "
|
||||||
"(%x, %d)\n", m1.m_type, m1.REP_STATUS);
|
"(%x, %d)\n", m1.m_type, m1.BDEV_STATUS);
|
||||||
|
|
||||||
return bad_driver(DRIVER_MAIN, BD_PROTO,
|
return bad_driver(DRIVER_MAIN, BD_PROTO,
|
||||||
(m1.m_type == TASK_REPLY) ? m1.REP_STATUS : EFAULT);
|
(m1.m_type == BDEV_REPLY) ? m1.BDEV_STATUS : EFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizes[0] != *sizep) {
|
if (m1.BDEV_STATUS != (ssize_t) *sizep) {
|
||||||
printf("Filter: truncated reply from main driver\n");
|
printf("Filter: truncated reply from main driver\n");
|
||||||
|
|
||||||
/* If the driver returned a value *larger* than we requested,
|
/* If the driver returned a value *larger* than we requested,
|
||||||
* OR if we did NOT exceed the disk size, then we should
|
* OR if we did NOT exceed the disk size, then we should
|
||||||
* report the driver for acting strangely!
|
* report the driver for acting strangely!
|
||||||
*/
|
*/
|
||||||
if (sizes[0] > *sizep ||
|
if (m1.BDEV_STATUS > (ssize_t) *sizep ||
|
||||||
cmp64(add64u(pos, sizes[0]), disk_size) < 0)
|
cmp64(add64u(pos, m1.BDEV_STATUS), disk_size) < 0)
|
||||||
return bad_driver(DRIVER_MAIN, BD_PROTO, EFAULT);
|
return bad_driver(DRIVER_MAIN, BD_PROTO, EFAULT);
|
||||||
|
|
||||||
/* Return the actual size. */
|
/* Return the actual size. */
|
||||||
*sizep = sizes[0];
|
*sizep = m1.BDEV_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (both) {
|
if (both) {
|
||||||
if (m2.m_type != TASK_REPLY || m2.REP_STATUS != OK) {
|
if (m2.m_type != BDEV_REPLY || m2.BDEV_STATUS < 0) {
|
||||||
printf("Filter: unexpected/invalid reply from "
|
printf("Filter: unexpected/invalid reply from "
|
||||||
"backup driver (%x, %d)\n",
|
"backup driver (%x, %d)\n",
|
||||||
m2.m_type, m2.REP_STATUS);
|
m2.m_type, m2.BDEV_STATUS);
|
||||||
|
|
||||||
return bad_driver(DRIVER_BACKUP, BD_PROTO,
|
return bad_driver(DRIVER_BACKUP, BD_PROTO,
|
||||||
m2.m_type == TASK_REPLY ? m2.REP_STATUS :
|
m2.m_type == BDEV_REPLY ? m2.BDEV_STATUS :
|
||||||
EFAULT);
|
EFAULT);
|
||||||
}
|
}
|
||||||
if (sizes[1] != *sizep) {
|
if (m2.BDEV_STATUS != (ssize_t) *sizep) {
|
||||||
printf("Filter: truncated reply from backup driver\n");
|
printf("Filter: truncated reply from backup driver\n");
|
||||||
|
|
||||||
/* As above */
|
/* As above */
|
||||||
if (sizes[1] > *sizep ||
|
if (m2.BDEV_STATUS > (ssize_t) *sizep ||
|
||||||
cmp64(add64u(pos, sizes[1]), disk_size) < 0)
|
cmp64(add64u(pos, m2.BDEV_STATUS),
|
||||||
|
disk_size) < 0)
|
||||||
return bad_driver(DRIVER_BACKUP, BD_PROTO,
|
return bad_driver(DRIVER_BACKUP, BD_PROTO,
|
||||||
EFAULT);
|
EFAULT);
|
||||||
|
|
||||||
/* Return the actual size. */
|
/* Return the actual size. */
|
||||||
if (*sizep >= sizes[1])
|
if ((ssize_t) *sizep >= m2.BDEV_STATUS)
|
||||||
*sizep = sizes[1];
|
*sizep = m2.BDEV_STATUS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1000,7 +995,7 @@ int read_write(u64_t pos, char *bufa, char *bufb, size_t *sizep, int request)
|
||||||
void ds_event()
|
void ds_event()
|
||||||
{
|
{
|
||||||
char key[DS_MAX_KEYLEN];
|
char key[DS_MAX_KEYLEN];
|
||||||
char *driver_prefix = "drv.vfs.";
|
char *blkdriver_prefix = "drv.blk.";
|
||||||
u32_t value;
|
u32_t value;
|
||||||
int type;
|
int type;
|
||||||
endpoint_t owner_endpoint;
|
endpoint_t owner_endpoint;
|
||||||
|
@ -1021,7 +1016,7 @@ void ds_event()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only check for VFS driver up events. */
|
/* Only check for VFS driver up events. */
|
||||||
if(strncmp(key, driver_prefix, sizeof(driver_prefix))
|
if(strncmp(key, blkdriver_prefix, strlen(blkdriver_prefix))
|
||||||
|| value != DS_DRIVER_UP) {
|
|| value != DS_DRIVER_UP) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include <minix/partition.h>
|
#include <minix/partition.h>
|
||||||
#include <minix/ds.h>
|
#include <minix/ds.h>
|
||||||
#include <minix/callnr.h>
|
#include <minix/callnr.h>
|
||||||
#include <minix/driver.h>
|
#include <minix/blockdriver.h>
|
||||||
#include <minix/optset.h>
|
#include <minix/optset.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
|
@ -60,14 +60,14 @@ PRIVATE struct optset optset_table[] = {
|
||||||
{ "timeout", OPT_INT, &DRIVER_TIMEOUT, 10 },
|
{ "timeout", OPT_INT, &DRIVER_TIMEOUT, 10 },
|
||||||
{ "T", OPT_INT, &DRIVER_TIMEOUT, 10 },
|
{ "T", OPT_INT, &DRIVER_TIMEOUT, 10 },
|
||||||
{ "chunk", OPT_INT, &CHUNK_SIZE, 10 },
|
{ "chunk", OPT_INT, &CHUNK_SIZE, 10 },
|
||||||
{ NULL }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Request message. */
|
/* Request message. */
|
||||||
static message m_in;
|
static message m_in;
|
||||||
static endpoint_t who_e; /* m_source */
|
static endpoint_t who_e; /* m_source */
|
||||||
static endpoint_t proc_e; /* USER_ENDPT */
|
static long req_id; /* BDEV_ID */
|
||||||
static cp_grant_id_t grant_id; /* IO_GRANT */
|
static cp_grant_id_t grant_id; /* BDEV_GRANT */
|
||||||
|
|
||||||
/* Data buffers. */
|
/* Data buffers. */
|
||||||
static char *buf_array, *buffer; /* contiguous buffer */
|
static char *buf_array, *buffer; /* contiguous buffer */
|
||||||
|
@ -136,8 +136,8 @@ static int do_rdwt(int flag_rw)
|
||||||
u64_t pos;
|
u64_t pos;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
pos = make64(m_in.POSITION, m_in.HIGHPOS);
|
pos = make64(m_in.BDEV_POS_LO, m_in.BDEV_POS_HI);
|
||||||
size = m_in.COUNT;
|
size = m_in.BDEV_COUNT;
|
||||||
|
|
||||||
if (rem64u(pos, SECTOR_SIZE) != 0 || size % SECTOR_SIZE != 0) {
|
if (rem64u(pos, SECTOR_SIZE) != 0 || size % SECTOR_SIZE != 0) {
|
||||||
printf("Filter: unaligned request from caller!\n");
|
printf("Filter: unaligned request from caller!\n");
|
||||||
|
@ -169,7 +169,11 @@ static int do_rdwt(int flag_rw)
|
||||||
carry(size_ret, flag_rw);
|
carry(size_ret, flag_rw);
|
||||||
|
|
||||||
flt_free(buffer, size, buf_array);
|
flt_free(buffer, size, buf_array);
|
||||||
return r != OK ? r : size_ret;
|
|
||||||
|
if (r != OK)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return size_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -177,20 +181,20 @@ static int do_rdwt(int flag_rw)
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int do_vrdwt(int flag_rw)
|
static int do_vrdwt(int flag_rw)
|
||||||
{
|
{
|
||||||
size_t size, size_ret, bytes;
|
size_t size, size_ret;
|
||||||
int grants;
|
int grants;
|
||||||
int r, i;
|
int r, i;
|
||||||
u64_t pos;
|
u64_t pos;
|
||||||
iovec_t iov_proc[NR_IOREQS];
|
iovec_t iov_proc[NR_IOREQS];
|
||||||
|
|
||||||
/* Extract informations. */
|
/* Extract informations. */
|
||||||
grants = m_in.COUNT;
|
grants = m_in.BDEV_COUNT;
|
||||||
if((r = sys_safecopyfrom(who_e, grant_id, 0, (vir_bytes) iov_proc,
|
if((r = sys_safecopyfrom(who_e, grant_id, 0, (vir_bytes) iov_proc,
|
||||||
grants * sizeof(iovec_t), D)) != OK) {
|
grants * sizeof(iovec_t), D)) != OK) {
|
||||||
panic("copying in grant vector failed: %d", r);
|
panic("copying in grant vector failed: %d", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = make64(m_in.POSITION, m_in.HIGHPOS);
|
pos = make64(m_in.BDEV_POS_LO, m_in.BDEV_POS_HI);
|
||||||
for(size = 0, i = 0; i < grants; i++)
|
for(size = 0, i = 0; i < grants; i++)
|
||||||
size += iov_proc[i].iov_size;
|
size += iov_proc[i].iov_size;
|
||||||
|
|
||||||
|
@ -227,22 +231,9 @@ static int do_vrdwt(int flag_rw)
|
||||||
if(flag_rw == FLT_READ)
|
if(flag_rw == FLT_READ)
|
||||||
vcarry(grants, iov_proc, flag_rw, size_ret);
|
vcarry(grants, iov_proc, flag_rw, size_ret);
|
||||||
|
|
||||||
/* Set the result-iovec. */
|
|
||||||
for(i = 0; i < grants && size_ret > 0; i++) {
|
|
||||||
bytes = MIN(size_ret, iov_proc[i].iov_size);
|
|
||||||
|
|
||||||
iov_proc[i].iov_size -= bytes;
|
|
||||||
size_ret -= bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy the caller's grant-table back. */
|
|
||||||
if((r = sys_safecopyto(who_e, grant_id, 0, (vir_bytes) iov_proc,
|
|
||||||
grants * sizeof(iovec_t), D)) != OK) {
|
|
||||||
panic("copying out grant vector failed: %d", r);
|
|
||||||
}
|
|
||||||
|
|
||||||
flt_free(buffer, size, buf_array);
|
flt_free(buffer, size, buf_array);
|
||||||
return OK;
|
|
||||||
|
return size_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -252,7 +243,7 @@ static int do_ioctl(message *m)
|
||||||
{
|
{
|
||||||
struct partition sizepart;
|
struct partition sizepart;
|
||||||
|
|
||||||
switch(m->REQUEST) {
|
switch(m->BDEV_REQUEST) {
|
||||||
case DIOCSETP:
|
case DIOCSETP:
|
||||||
case DIOCTIMEOUT:
|
case DIOCTIMEOUT:
|
||||||
case DIOCOPENCT:
|
case DIOCOPENCT:
|
||||||
|
@ -276,7 +267,8 @@ static int do_ioctl(message *m)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("Filter: unknown ioctl request: %d!\n", m->REQUEST);
|
printf("Filter: unknown ioctl request: %d!\n",
|
||||||
|
m->BDEV_REQUEST);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,8 +364,8 @@ static int parse_arguments(int argc, char *argv[])
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
message m_out;
|
message m_out;
|
||||||
int ipc_status;
|
int r, ipc_status;
|
||||||
int r;
|
size_t size;
|
||||||
|
|
||||||
/* SEF local startup. */
|
/* SEF local startup. */
|
||||||
env_setargs(argc, argv);
|
env_setargs(argc, argv);
|
||||||
|
@ -396,18 +388,19 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
who_e = m_in.m_source;
|
who_e = m_in.m_source;
|
||||||
proc_e = m_in.USER_ENDPT;
|
req_id = m_in.BDEV_ID;
|
||||||
grant_id = (cp_grant_id_t) m_in.IO_GRANT;
|
grant_id = m_in.BDEV_GRANT;
|
||||||
|
size = 0;
|
||||||
|
|
||||||
/* Forword the request message to the drivers. */
|
/* Forword the request message to the drivers. */
|
||||||
switch(m_in.m_type) {
|
switch(m_in.m_type) {
|
||||||
case DEV_OPEN: /* open/close is a noop for filter. */
|
case BDEV_OPEN: /* open/close is a noop for filter. */
|
||||||
case DEV_CLOSE: r = OK; break;
|
case BDEV_CLOSE: r = OK; break;
|
||||||
case DEV_READ_S: r = do_rdwt(FLT_READ); break;
|
case BDEV_READ: r = do_rdwt(FLT_READ); break;
|
||||||
case DEV_WRITE_S: r = do_rdwt(FLT_WRITE); break;
|
case BDEV_WRITE: r = do_rdwt(FLT_WRITE); break;
|
||||||
case DEV_GATHER_S: r = do_vrdwt(FLT_READ); break;
|
case BDEV_GATHER: r = do_vrdwt(FLT_READ); break;
|
||||||
case DEV_SCATTER_S: r = do_vrdwt(FLT_WRITE); break;
|
case BDEV_SCATTER: r = do_vrdwt(FLT_WRITE); break;
|
||||||
case DEV_IOCTL_S: r = do_ioctl(&m_in); break;
|
case BDEV_IOCTL: r = do_ioctl(&m_in); break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("Filter: ignoring unknown request %d from %d\n",
|
printf("Filter: ignoring unknown request %d from %d\n",
|
||||||
|
@ -420,9 +413,9 @@ int main(int argc, char *argv[])
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Send back reply message. */
|
/* Send back reply message. */
|
||||||
m_out.m_type = TASK_REPLY;
|
m_out.m_type = BDEV_REPLY;
|
||||||
m_out.REP_ENDPT = proc_e;
|
m_out.BDEV_ID = req_id;
|
||||||
m_out.REP_STATUS = r;
|
m_out.BDEV_STATUS = r;
|
||||||
send(who_e, &m_out);
|
send(who_e, &m_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,7 +443,7 @@ PRIVATE void sef_local_startup(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_cb_init_fresh *
|
* sef_cb_init_fresh *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
{
|
{
|
||||||
/* Initialize the filter driver. */
|
/* Initialize the filter driver. */
|
||||||
int r;
|
int r;
|
||||||
|
@ -468,14 +461,14 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||||
|
|
||||||
driver_init();
|
driver_init();
|
||||||
|
|
||||||
/* Subscribe to driver events for VFS drivers. */
|
/* Subscribe to block driver events. */
|
||||||
r = ds_subscribe("drv\\.vfs\\..*", DSF_INITIAL | DSF_OVERWRITE);
|
r = ds_subscribe("drv\\.blk\\..*", DSF_INITIAL | DSF_OVERWRITE);
|
||||||
if(r != OK) {
|
if(r != OK) {
|
||||||
panic("Filter: can't subscribe to driver events");
|
panic("Filter: can't subscribe to driver events");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Announce we are up! */
|
/* Announce we are up! */
|
||||||
driver_announce();
|
blockdriver_announce();
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ static void calc_sum(unsigned sector, char *data, char *sum)
|
||||||
memset(sum, 0, SUM_SIZE);
|
memset(sum, 0, SUM_SIZE);
|
||||||
for(i = 0; i < SECTOR_SIZE / SUM_SIZE; i++) {
|
for(i = 0; i < SECTOR_SIZE / SUM_SIZE; i++) {
|
||||||
q = (unsigned long *) sum;
|
q = (unsigned long *) sum;
|
||||||
for(j = 0; j < SUM_SIZE / sizeof(*p); j++) {
|
for(j = 0; (size_t) j < SUM_SIZE / sizeof(*p); j++) {
|
||||||
*q ^= *p;
|
*q ^= *p;
|
||||||
q++;
|
q++;
|
||||||
p++;
|
p++;
|
||||||
|
|
|
@ -48,8 +48,8 @@ char *print64(u64_t p)
|
||||||
static char buf[NB][100];
|
static char buf[NB][100];
|
||||||
u32_t lo = ex64lo(p), hi = ex64hi(p);
|
u32_t lo = ex64lo(p), hi = ex64hi(p);
|
||||||
n = (n+1) % NB;
|
n = (n+1) % NB;
|
||||||
if(!hi) sprintf(buf[n], "%lx", lo);
|
if(!hi) sprintf(buf[n], "%x", lo);
|
||||||
else sprintf(buf[n], "%lx%08lx", hi, lo);
|
else sprintf(buf[n], "%x%08x", hi, lo);
|
||||||
return buf[n];
|
return buf[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
PROG= floppy
|
PROG= floppy
|
||||||
SRCS= floppy.c liveupdate.c
|
SRCS= floppy.c liveupdate.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
|
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS} ${LIBTIMERS}
|
||||||
LDADD+= -ldriver -lsys -ltimers
|
LDADD+= -lblockdriver -lsys -ltimers
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@
|
||||||
#define UNCALIBRATED 0 /* drive needs to be calibrated at next use */
|
#define UNCALIBRATED 0 /* drive needs to be calibrated at next use */
|
||||||
#define CALIBRATED 1 /* no calibration needed */
|
#define CALIBRATED 1 /* no calibration needed */
|
||||||
#define BASE_SECTOR 1 /* sectors are numbered starting at 1 */
|
#define BASE_SECTOR 1 /* sectors are numbered starting at 1 */
|
||||||
#define NO_SECTOR (-1) /* current sector unknown */
|
#define NO_SECTOR ((unsigned) -1) /* current sector unknown */
|
||||||
#define NO_CYL (-1) /* current cylinder unknown, must seek */
|
#define NO_CYL (-1) /* current cylinder unknown, must seek */
|
||||||
#define NO_DENS 100 /* current media unknown */
|
#define NO_DENS 100 /* current media unknown */
|
||||||
#define BSY_IDLE 0 /* busy doing nothing */
|
#define BSY_IDLE 0 /* busy doing nothing */
|
||||||
|
@ -238,19 +238,20 @@ PRIVATE u8_t f_results[MAX_RESULTS];/* the controller can give lots of output */
|
||||||
*/
|
*/
|
||||||
PRIVATE timer_t f_tmr_timeout; /* timer for various timeouts */
|
PRIVATE timer_t f_tmr_timeout; /* timer for various timeouts */
|
||||||
PRIVATE u32_t system_hz; /* system clock frequency */
|
PRIVATE u32_t system_hz; /* system clock frequency */
|
||||||
FORWARD _PROTOTYPE( void f_expire_tmrs, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( void f_expire_tmrs, (clock_t stamp) );
|
||||||
FORWARD _PROTOTYPE( void stop_motor, (timer_t *tp) );
|
FORWARD _PROTOTYPE( void stop_motor, (timer_t *tp) );
|
||||||
FORWARD _PROTOTYPE( void f_timeout, (timer_t *tp) );
|
FORWARD _PROTOTYPE( void f_timeout, (timer_t *tp) );
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( struct device *f_prepare, (int device) );
|
FORWARD _PROTOTYPE( struct device *f_prepare, (dev_t device) );
|
||||||
FORWARD _PROTOTYPE( char *f_name, (void) );
|
FORWARD _PROTOTYPE( struct device *f_part, (dev_t minor) );
|
||||||
FORWARD _PROTOTYPE( void f_cleanup, (void) );
|
FORWARD _PROTOTYPE( void f_cleanup, (void) );
|
||||||
FORWARD _PROTOTYPE( int f_transfer, (int proc_nr, int opcode, u64_t position,
|
FORWARD _PROTOTYPE( ssize_t f_transfer, (dev_t minor, int do_write,
|
||||||
iovec_t *iov, unsigned nr_req) );
|
u64_t position, endpoint_t proc_nr, iovec_t *iov,
|
||||||
FORWARD _PROTOTYPE( int dma_setup, (int opcode) );
|
unsigned int nr_req, int flags) );
|
||||||
|
FORWARD _PROTOTYPE( int dma_setup, (int do_write) );
|
||||||
FORWARD _PROTOTYPE( void start_motor, (void) );
|
FORWARD _PROTOTYPE( void start_motor, (void) );
|
||||||
FORWARD _PROTOTYPE( int seek, (void) );
|
FORWARD _PROTOTYPE( int seek, (void) );
|
||||||
FORWARD _PROTOTYPE( int fdc_transfer, (int opcode) );
|
FORWARD _PROTOTYPE( int fdc_transfer, (int do_write) );
|
||||||
FORWARD _PROTOTYPE( int fdc_results, (void) );
|
FORWARD _PROTOTYPE( int fdc_results, (void) );
|
||||||
FORWARD _PROTOTYPE( int fdc_command, (const u8_t *cmd, int len) );
|
FORWARD _PROTOTYPE( int fdc_command, (const u8_t *cmd, int len) );
|
||||||
FORWARD _PROTOTYPE( void fdc_out, (int val) );
|
FORWARD _PROTOTYPE( void fdc_out, (int val) );
|
||||||
|
@ -258,25 +259,25 @@ FORWARD _PROTOTYPE( int recalibrate, (void) );
|
||||||
FORWARD _PROTOTYPE( void f_reset, (void) );
|
FORWARD _PROTOTYPE( void f_reset, (void) );
|
||||||
FORWARD _PROTOTYPE( int f_intr_wait, (void) );
|
FORWARD _PROTOTYPE( int f_intr_wait, (void) );
|
||||||
FORWARD _PROTOTYPE( int read_id, (void) );
|
FORWARD _PROTOTYPE( int read_id, (void) );
|
||||||
FORWARD _PROTOTYPE( int f_do_open, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int f_do_open, (dev_t minor, int access) );
|
||||||
|
FORWARD _PROTOTYPE( int f_do_close, (dev_t minor) );
|
||||||
FORWARD _PROTOTYPE( int test_read, (int density) );
|
FORWARD _PROTOTYPE( int test_read, (int density) );
|
||||||
FORWARD _PROTOTYPE( void f_geometry, (struct partition *entry) );
|
FORWARD _PROTOTYPE( void f_geometry, (dev_t minor,
|
||||||
|
struct partition *entry) );
|
||||||
|
|
||||||
/* Entry points to this driver. */
|
/* Entry points to this driver. */
|
||||||
PRIVATE struct driver f_dtab = {
|
PRIVATE struct blockdriver f_dtab = {
|
||||||
f_name, /* current device's name */
|
|
||||||
f_do_open, /* open or mount request, sense type of diskette */
|
f_do_open, /* open or mount request, sense type of diskette */
|
||||||
do_nop, /* nothing on a close */
|
f_do_close, /* nothing on a close */
|
||||||
do_diocntl, /* get or set a partitions geometry */
|
|
||||||
f_prepare, /* prepare for I/O on a given minor device */
|
|
||||||
f_transfer, /* do the I/O */
|
f_transfer, /* do the I/O */
|
||||||
|
NULL, /* no other I/O control requests are supported */
|
||||||
f_cleanup, /* cleanup before sending reply to user process */
|
f_cleanup, /* cleanup before sending reply to user process */
|
||||||
|
f_part, /* return partition information structure */
|
||||||
f_geometry, /* tell the geometry of the diskette */
|
f_geometry, /* tell the geometry of the diskette */
|
||||||
|
NULL, /* no processing of hardware interrupts */
|
||||||
f_expire_tmrs,/* expire all alarm timers */
|
f_expire_tmrs,/* expire all alarm timers */
|
||||||
nop_cancel,
|
NULL, /* no processing of other messages */
|
||||||
nop_select,
|
NULL /* no threading support */
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *floppy_buf;
|
static char *floppy_buf;
|
||||||
|
@ -289,7 +290,7 @@ FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
|
||||||
EXTERN _PROTOTYPE( int sef_cb_lu_prepare, (int state) );
|
EXTERN _PROTOTYPE( int sef_cb_lu_prepare, (int state) );
|
||||||
EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) );
|
EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) );
|
||||||
EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
|
EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
|
||||||
PUBLIC int last_transfer_opcode;
|
PUBLIC int last_was_write;
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* floppy_task *
|
* floppy_task *
|
||||||
|
@ -300,7 +301,7 @@ PUBLIC int main(void)
|
||||||
sef_local_startup();
|
sef_local_startup();
|
||||||
|
|
||||||
/* Call the generic receive loop. */
|
/* Call the generic receive loop. */
|
||||||
driver_task(&f_dtab, DRIVER_STD);
|
blockdriver_task(&f_dtab);
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
@ -330,7 +331,7 @@ PRIVATE void sef_local_startup(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_cb_init_fresh *
|
* sef_cb_init_fresh *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
{
|
{
|
||||||
/* Initialize the floppy driver. */
|
/* Initialize the floppy driver. */
|
||||||
struct floppy *fp;
|
struct floppy *fp;
|
||||||
|
@ -362,7 +363,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||||
panic("Couldn't enable IRQs: %d", s);
|
panic("Couldn't enable IRQs: %d", s);
|
||||||
|
|
||||||
/* Announce we are up! */
|
/* Announce we are up! */
|
||||||
driver_announce();
|
blockdriver_announce();
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
@ -386,25 +387,25 @@ PRIVATE void sef_cb_signal_handler(int signo)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* f_expire_tmrs *
|
* f_expire_tmrs *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void f_expire_tmrs(struct driver *dp, message *m_ptr)
|
PRIVATE void f_expire_tmrs(clock_t stamp)
|
||||||
{
|
{
|
||||||
/* A synchronous alarm message was received. Call the watchdog function for
|
/* A synchronous alarm message was received. Call the watchdog function for
|
||||||
* each expired timer, if any.
|
* each expired timer, if any.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
expire_timers(m_ptr->NOTIFY_TIMESTAMP);
|
expire_timers(stamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* f_prepare *
|
* f_prepare *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE struct device *f_prepare(int device)
|
PRIVATE struct device *f_prepare(dev_t device)
|
||||||
{
|
{
|
||||||
/* Prepare for I/O on a device. */
|
/* Prepare for I/O on a device. */
|
||||||
|
|
||||||
f_device = device;
|
f_device = device;
|
||||||
f_drive = device & ~(DEV_TYPE_BITS | FORMAT_DEV_BIT);
|
f_drive = device & ~(DEV_TYPE_BITS | FORMAT_DEV_BIT);
|
||||||
if (f_drive < 0 || f_drive >= NR_DRIVES) return(NULL);
|
if (f_drive >= NR_DRIVES) return(NULL);
|
||||||
|
|
||||||
f_fp = &floppy[f_drive];
|
f_fp = &floppy[f_drive];
|
||||||
f_dv = &f_fp->fl_geom;
|
f_dv = &f_fp->fl_geom;
|
||||||
|
@ -423,15 +424,13 @@ PRIVATE struct device *f_prepare(int device)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* f_name *
|
* f_part *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE char *f_name(void)
|
PRIVATE struct device *f_part(dev_t minor)
|
||||||
{
|
{
|
||||||
/* Return a name for the current device. */
|
/* Return a pointer to the partition information of the given minor device. */
|
||||||
static char name[] = "fd0";
|
|
||||||
|
|
||||||
name[2] = '0' + f_drive;
|
return f_prepare(minor);
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -449,32 +448,41 @@ PRIVATE void f_cleanup(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* f_transfer *
|
* f_transfer *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int f_transfer(proc_nr, opcode, pos64, iov, nr_req)
|
PRIVATE ssize_t f_transfer(
|
||||||
int proc_nr; /* process doing the request */
|
dev_t minor, /* minor device number */
|
||||||
int opcode; /* DEV_GATHER_S or DEV_SCATTER_S */
|
int do_write, /* read or write? */
|
||||||
u64_t pos64; /* offset on device to read or write */
|
u64_t pos64, /* offset on device to read or write */
|
||||||
iovec_t *iov; /* pointer to read or write request vector */
|
endpoint_t proc_nr, /* process doing the request */
|
||||||
unsigned nr_req; /* length of request vector */
|
iovec_t *iov, /* pointer to read or write request vector */
|
||||||
|
unsigned int nr_req, /* length of request vector */
|
||||||
|
int UNUSED(flags) /* transfer flags */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
#define NO_OFFSET -1
|
#define NO_OFFSET -1
|
||||||
struct floppy *fp = f_fp;
|
struct floppy *fp;
|
||||||
iovec_t *iop, *iov_end = iov + nr_req;
|
iovec_t *iop, *iov_end = iov + nr_req;
|
||||||
int s, r, errors, nr;
|
int s, r, errors, nr;
|
||||||
unsigned block; /* Seen any 32M floppies lately? */
|
unsigned block, nbytes, count, chunk, sector;
|
||||||
unsigned nbytes, count, chunk, sector;
|
unsigned long dv_size;
|
||||||
unsigned long dv_size = cv64ul(f_dv->dv_size);
|
|
||||||
vir_bytes user_offset, iov_offset = 0, iop_offset;
|
vir_bytes user_offset, iov_offset = 0, iop_offset;
|
||||||
off_t position;
|
unsigned long position;
|
||||||
signed long uoffsets[MAX_SECTORS], *up;
|
signed long uoffsets[MAX_SECTORS], *up;
|
||||||
cp_grant_id_t ugrants[MAX_SECTORS], *ug;
|
cp_grant_id_t ugrants[MAX_SECTORS], *ug = NULL;
|
||||||
u8_t cmd[3];
|
u8_t cmd[3];
|
||||||
|
ssize_t total;
|
||||||
|
|
||||||
|
if (f_prepare(minor) == NULL) return(ENXIO);
|
||||||
|
|
||||||
|
fp = f_fp;
|
||||||
|
dv_size = cv64ul(f_dv->dv_size);
|
||||||
|
|
||||||
if (ex64hi(pos64) != 0)
|
if (ex64hi(pos64) != 0)
|
||||||
return OK; /* Way beyond EOF */
|
return OK; /* Way beyond EOF */
|
||||||
position= cv64ul(pos64);
|
position= cv64ul(pos64);
|
||||||
|
total = 0;
|
||||||
|
|
||||||
/* Record the opcode of the last transfer performed. */
|
/* Record the direction of the last transfer performed. */
|
||||||
last_transfer_opcode = opcode;
|
last_was_write = do_write;
|
||||||
|
|
||||||
/* Check disk address. */
|
/* Check disk address. */
|
||||||
if ((position & SECTOR_MASK) != 0) return(EINVAL);
|
if ((position & SECTOR_MASK) != 0) return(EINVAL);
|
||||||
|
@ -492,7 +500,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size;
|
for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size;
|
||||||
|
|
||||||
/* Which block on disk and how close to EOF? */
|
/* Which block on disk and how close to EOF? */
|
||||||
if (position >= dv_size) return(OK); /* At EOF */
|
if (position >= dv_size) return(total); /* At EOF */
|
||||||
if (position + nbytes > dv_size) nbytes = dv_size - position;
|
if (position + nbytes > dv_size) nbytes = dv_size - position;
|
||||||
block = div64u(add64ul(f_dv->dv_base, position), SECTOR_SIZE);
|
block = div64u(add64ul(f_dv->dv_base, position), SECTOR_SIZE);
|
||||||
|
|
||||||
|
@ -500,7 +508,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
|
|
||||||
/* Using a formatting device? */
|
/* Using a formatting device? */
|
||||||
if (f_device & FORMAT_DEV_BIT) {
|
if (f_device & FORMAT_DEV_BIT) {
|
||||||
if (opcode != DEV_SCATTER_S) return(EIO);
|
if (!do_write) return(EIO);
|
||||||
if (iov->iov_size < SECTOR_SIZE + sizeof(fmt_param))
|
if (iov->iov_size < SECTOR_SIZE + sizeof(fmt_param))
|
||||||
return(EINVAL);
|
return(EINVAL);
|
||||||
|
|
||||||
|
@ -607,7 +615,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
fp->fl_sector++;
|
fp->fl_sector++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode == DEV_SCATTER_S) {
|
if (do_write) {
|
||||||
/* Copy the user bytes to the DMA buffer. */
|
/* Copy the user bytes to the DMA buffer. */
|
||||||
if(proc_nr != SELF) {
|
if(proc_nr != SELF) {
|
||||||
s=sys_safecopyfrom(proc_nr, *ug, *up,
|
s=sys_safecopyfrom(proc_nr, *ug, *up,
|
||||||
|
@ -623,17 +631,17 @@ unsigned nr_req; /* length of request vector */
|
||||||
|
|
||||||
/* Set up the DMA chip and perform the transfer. */
|
/* Set up the DMA chip and perform the transfer. */
|
||||||
if (r == OK) {
|
if (r == OK) {
|
||||||
if (dma_setup(opcode) != OK) {
|
if (dma_setup(do_write) != OK) {
|
||||||
/* This can only fail for addresses above 16MB
|
/* This can only fail for addresses above 16MB
|
||||||
* that cannot be handled by the controller,
|
* that cannot be handled by the controller,
|
||||||
* because it uses 24-bit addressing.
|
* because it uses 24-bit addressing.
|
||||||
*/
|
*/
|
||||||
return(EIO);
|
return(EIO);
|
||||||
}
|
}
|
||||||
r = fdc_transfer(opcode);
|
r = fdc_transfer(do_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r == OK && opcode == DEV_GATHER_S) {
|
if (r == OK && !do_write) {
|
||||||
/* Copy the DMA buffer to user space. */
|
/* Copy the DMA buffer to user space. */
|
||||||
if(proc_nr != SELF) {
|
if(proc_nr != SELF) {
|
||||||
s=sys_safecopyto(proc_nr, *ug, *up,
|
s=sys_safecopyto(proc_nr, *ug, *up,
|
||||||
|
@ -663,7 +671,8 @@ unsigned nr_req; /* length of request vector */
|
||||||
|
|
||||||
/* Book the bytes successfully transferred. */
|
/* Book the bytes successfully transferred. */
|
||||||
position += nbytes;
|
position += nbytes;
|
||||||
for (;;) {
|
total += nbytes;
|
||||||
|
while (nbytes > 0) {
|
||||||
if (nbytes < iov->iov_size) {
|
if (nbytes < iov->iov_size) {
|
||||||
/* Not done with this one yet. */
|
/* Not done with this one yet. */
|
||||||
iov_offset += nbytes;
|
iov_offset += nbytes;
|
||||||
|
@ -673,25 +682,17 @@ unsigned nr_req; /* length of request vector */
|
||||||
iov_offset = 0;
|
iov_offset = 0;
|
||||||
nbytes -= iov->iov_size;
|
nbytes -= iov->iov_size;
|
||||||
iov->iov_size = 0;
|
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++;
|
iov++;
|
||||||
nr_req--;
|
nr_req--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(OK);
|
return(total);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dma_setup *
|
* dma_setup *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int dma_setup(
|
PRIVATE int dma_setup(int do_write)
|
||||||
int opcode /* DEV_GATHER_S or DEV_SCATTER_S */
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/* The IBM PC can perform DMA operations by using the DMA chip. To use it,
|
/* The IBM PC can perform DMA operations by using the DMA chip. To use it,
|
||||||
* the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address
|
* the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address
|
||||||
|
@ -719,7 +720,7 @@ PRIVATE int dma_setup(
|
||||||
*/
|
*/
|
||||||
pv_set(byte_out[0], DMA_INIT, DMA_RESET_VAL); /* reset the dma controller */
|
pv_set(byte_out[0], DMA_INIT, DMA_RESET_VAL); /* reset the dma controller */
|
||||||
pv_set(byte_out[1], DMA_FLIPFLOP, 0); /* write anything to reset it */
|
pv_set(byte_out[1], DMA_FLIPFLOP, 0); /* write anything to reset it */
|
||||||
pv_set(byte_out[2], DMA_MODE, opcode == DEV_SCATTER_S ? DMA_WRITE : DMA_READ);
|
pv_set(byte_out[2], DMA_MODE, do_write ? DMA_WRITE : DMA_READ);
|
||||||
pv_set(byte_out[3], DMA_ADDR, (unsigned) (floppy_buf_phys >> 0) & 0xff);
|
pv_set(byte_out[3], DMA_ADDR, (unsigned) (floppy_buf_phys >> 0) & 0xff);
|
||||||
pv_set(byte_out[4], DMA_ADDR, (unsigned) (floppy_buf_phys >> 8) & 0xff);
|
pv_set(byte_out[4], DMA_ADDR, (unsigned) (floppy_buf_phys >> 8) & 0xff);
|
||||||
pv_set(byte_out[5], DMA_TOP, (unsigned) (floppy_buf_phys >> 16) & 0xff);
|
pv_set(byte_out[5], DMA_TOP, (unsigned) (floppy_buf_phys >> 16) & 0xff);
|
||||||
|
@ -773,7 +774,7 @@ PRIVATE void start_motor(void)
|
||||||
if (is_ipc_notify(ipc_status)) {
|
if (is_ipc_notify(ipc_status)) {
|
||||||
switch (_ENDPOINT_P(mess.m_source)) {
|
switch (_ENDPOINT_P(mess.m_source)) {
|
||||||
case CLOCK:
|
case CLOCK:
|
||||||
f_expire_tmrs(NULL, &mess);
|
f_expire_tmrs(mess.NOTIFY_TIMESTAMP);
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
f_busy = BSY_IDLE;
|
f_busy = BSY_IDLE;
|
||||||
|
@ -848,7 +849,7 @@ PRIVATE int seek(void)
|
||||||
if (is_ipc_notify(ipc_status)) {
|
if (is_ipc_notify(ipc_status)) {
|
||||||
switch (_ENDPOINT_P(mess.m_source)) {
|
switch (_ENDPOINT_P(mess.m_source)) {
|
||||||
case CLOCK:
|
case CLOCK:
|
||||||
f_expire_tmrs(NULL, &mess);
|
f_expire_tmrs(mess.NOTIFY_TIMESTAMP);
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
f_busy = BSY_IDLE;
|
f_busy = BSY_IDLE;
|
||||||
|
@ -867,9 +868,7 @@ PRIVATE int seek(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* fdc_transfer *
|
* fdc_transfer *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int fdc_transfer(
|
PRIVATE int fdc_transfer(int do_write)
|
||||||
int opcode /* DEV_GATHER_S or DEV_SCATTER_S */
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/* The drive is now on the proper cylinder. Read, write or format 1 block. */
|
/* The drive is now on the proper cylinder. Read, write or format 1 block. */
|
||||||
|
|
||||||
|
@ -892,7 +891,7 @@ PRIVATE int fdc_transfer(
|
||||||
cmd[5] = fmt_param.fill_byte_for_format;
|
cmd[5] = fmt_param.fill_byte_for_format;
|
||||||
if (fdc_command(cmd, 6) != OK) return(ERR_TRANSFER);
|
if (fdc_command(cmd, 6) != OK) return(ERR_TRANSFER);
|
||||||
} else {
|
} else {
|
||||||
cmd[0] = opcode == DEV_SCATTER_S ? FDC_WRITE : FDC_READ;
|
cmd[0] = do_write ? FDC_WRITE : FDC_READ;
|
||||||
cmd[1] = (fp->fl_head << 2) | f_drive;
|
cmd[1] = (fp->fl_head << 2) | f_drive;
|
||||||
cmd[2] = fp->fl_cylinder;
|
cmd[2] = fp->fl_cylinder;
|
||||||
cmd[3] = fp->fl_head;
|
cmd[3] = fp->fl_head;
|
||||||
|
@ -906,7 +905,7 @@ PRIVATE int fdc_transfer(
|
||||||
|
|
||||||
/* Block, waiting for disk interrupt. */
|
/* Block, waiting for disk interrupt. */
|
||||||
if (f_intr_wait() != OK) {
|
if (f_intr_wait() != OK) {
|
||||||
printf("%s: disk interrupt timed out.\n", f_name());
|
printf("fd%u: disk interrupt timed out.\n", f_drive);
|
||||||
return(ERR_TIMEOUT);
|
return(ERR_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -915,7 +914,7 @@ PRIVATE int fdc_transfer(
|
||||||
if (r != OK) return(r);
|
if (r != OK) return(r);
|
||||||
|
|
||||||
if (f_results[ST1] & WRITE_PROTECT) {
|
if (f_results[ST1] & WRITE_PROTECT) {
|
||||||
printf("%s: diskette is write protected.\n", f_name());
|
printf("fd%u: diskette is write protected.\n", f_drive);
|
||||||
return(ERR_WR_PROTECT);
|
return(ERR_WR_PROTECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1127,7 +1126,7 @@ PRIVATE void f_reset(void)
|
||||||
if (is_ipc_notify(ipc_status)) {
|
if (is_ipc_notify(ipc_status)) {
|
||||||
switch (_ENDPOINT_P(mess.m_source)) {
|
switch (_ENDPOINT_P(mess.m_source)) {
|
||||||
case CLOCK:
|
case CLOCK:
|
||||||
f_expire_tmrs(NULL, &mess);
|
f_expire_tmrs(mess.NOTIFY_TIMESTAMP);
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
f_busy = BSY_IDLE;
|
f_busy = BSY_IDLE;
|
||||||
|
@ -1177,7 +1176,7 @@ PRIVATE int f_intr_wait(void)
|
||||||
if (is_ipc_notify(ipc_status)) {
|
if (is_ipc_notify(ipc_status)) {
|
||||||
switch (_ENDPOINT_P(mess.m_source)) {
|
switch (_ENDPOINT_P(mess.m_source)) {
|
||||||
case CLOCK:
|
case CLOCK:
|
||||||
f_expire_tmrs(NULL, &mess);
|
f_expire_tmrs(mess.NOTIFY_TIMESTAMP);
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
f_busy = BSY_IDLE;
|
f_busy = BSY_IDLE;
|
||||||
|
@ -1202,7 +1201,7 @@ PRIVATE int f_intr_wait(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* f_timeout *
|
* f_timeout *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void f_timeout(timer_t *tp)
|
PRIVATE void f_timeout(timer_t *UNUSED(tp))
|
||||||
{
|
{
|
||||||
/* This routine is called when a timer expires. Usually to tell that a
|
/* This routine is called when a timer expires. Usually to tell that a
|
||||||
* motor has spun up, but also to forge an interrupt when it takes too long
|
* motor has spun up, but also to forge an interrupt when it takes too long
|
||||||
|
@ -1250,9 +1249,7 @@ PRIVATE int read_id(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* f_do_open *
|
* f_do_open *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int f_do_open(dp, m_ptr)
|
PRIVATE int f_do_open(dev_t minor, int UNUSED(access))
|
||||||
struct driver *dp;
|
|
||||||
message *m_ptr; /* pointer to open message */
|
|
||||||
{
|
{
|
||||||
/* Handle an open on a floppy. Determine diskette type if need be. */
|
/* Handle an open on a floppy. Determine diskette type if need be. */
|
||||||
|
|
||||||
|
@ -1260,7 +1257,7 @@ message *m_ptr; /* pointer to open message */
|
||||||
struct test_order *top;
|
struct test_order *top;
|
||||||
|
|
||||||
/* Decode the message parameters. */
|
/* Decode the message parameters. */
|
||||||
if (f_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
if (f_prepare(minor) == NULL) return(ENXIO);
|
||||||
|
|
||||||
dtype = f_device & DEV_TYPE_BITS; /* get density from minor dev */
|
dtype = f_device & DEV_TYPE_BITS; /* get density from minor dev */
|
||||||
if (dtype >= MINOR_fd0p0) dtype = 0;
|
if (dtype >= MINOR_fd0p0) dtype = 0;
|
||||||
|
@ -1308,6 +1305,16 @@ message *m_ptr; /* pointer to open message */
|
||||||
return(EIO); /* nothing worked */
|
return(EIO); /* nothing worked */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* f_do_close *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int f_do_close(dev_t UNUSED(minor))
|
||||||
|
{
|
||||||
|
/* Handle a close on a floppy. Nothing to do here. */
|
||||||
|
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* test_read *
|
* test_read *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -1320,7 +1327,7 @@ PRIVATE int test_read(int density)
|
||||||
int device;
|
int device;
|
||||||
off_t position;
|
off_t position;
|
||||||
iovec_t iovec1;
|
iovec_t iovec1;
|
||||||
int result;
|
ssize_t result;
|
||||||
|
|
||||||
f_fp->fl_density = density;
|
f_fp->fl_density = density;
|
||||||
device = ((density + 1) << DEV_TYPE_SHIFT) + f_drive;
|
device = ((density + 1) << DEV_TYPE_SHIFT) + f_drive;
|
||||||
|
@ -1329,9 +1336,10 @@ PRIVATE int test_read(int density)
|
||||||
position = (off_t) f_dp->test << SECTOR_SHIFT;
|
position = (off_t) f_dp->test << SECTOR_SHIFT;
|
||||||
iovec1.iov_addr = (vir_bytes) floppy_buf;
|
iovec1.iov_addr = (vir_bytes) floppy_buf;
|
||||||
iovec1.iov_size = SECTOR_SIZE;
|
iovec1.iov_size = SECTOR_SIZE;
|
||||||
result = f_transfer(SELF, DEV_GATHER_S, cvul64(position), &iovec1, 1);
|
result = f_transfer(device, FALSE /*do_write*/, cvul64(position), SELF,
|
||||||
|
&iovec1, 1, BDEV_NOFLAGS);
|
||||||
|
|
||||||
if (iovec1.iov_size != 0) return(EIO);
|
if (result != SECTOR_SIZE) return(EIO);
|
||||||
|
|
||||||
partition(&f_dtab, f_drive, P_FLOPPY, 0);
|
partition(&f_dtab, f_drive, P_FLOPPY, 0);
|
||||||
return(OK);
|
return(OK);
|
||||||
|
@ -1340,11 +1348,11 @@ PRIVATE int test_read(int density)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* f_geometry *
|
* f_geometry *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void f_geometry(struct partition *entry)
|
PRIVATE void f_geometry(dev_t minor, struct partition *entry)
|
||||||
{
|
{
|
||||||
|
if (f_prepare(minor) == NULL) return;
|
||||||
|
|
||||||
entry->cylinders = f_dp->cyls;
|
entry->cylinders = f_dp->cyls;
|
||||||
entry->heads = NR_HEADS;
|
entry->heads = NR_HEADS;
|
||||||
entry->sectors = f_sectors;
|
entry->sectors = f_sectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/driver.h>
|
#include <minix/blockdriver.h>
|
||||||
#include <minix/drvlib.h>
|
#include <minix/drvlib.h>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
EXTERN u16_t f_busy;
|
EXTERN u16_t f_busy;
|
||||||
EXTERN int motor_status;
|
EXTERN int motor_status;
|
||||||
EXTERN unsigned f_drive;
|
EXTERN unsigned f_drive;
|
||||||
EXTERN int last_transfer_opcode;
|
EXTERN int last_was_write;
|
||||||
#define BSY_IO 1 /* busy doing I/O */
|
#define BSY_IO 1 /* busy doing I/O */
|
||||||
|
|
||||||
/* State management helpers. */
|
/* State management helpers. */
|
||||||
|
@ -63,8 +63,7 @@ PUBLIC void sef_cb_lu_state_dump(int state)
|
||||||
sef_lu_dprint("floppy: f_busy = %d\n", f_busy);
|
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: motor_status = 0x%02X\n", motor_status);
|
||||||
sef_lu_dprint("floppy: f_drive = %d\n", f_drive);
|
sef_lu_dprint("floppy: f_drive = %d\n", f_drive);
|
||||||
sef_lu_dprint("floppy: last_transfer_opcode = 0x%02X\n",
|
sef_lu_dprint("floppy: last_was_write = %d\n", last_was_write);
|
||||||
last_transfer_opcode);
|
|
||||||
|
|
||||||
sef_lu_dprint("floppy: SEF_LU_STATE_WORK_FREE(%d) reached = %d\n",
|
sef_lu_dprint("floppy: SEF_LU_STATE_WORK_FREE(%d) reached = %d\n",
|
||||||
SEF_LU_STATE_WORK_FREE, TRUE);
|
SEF_LU_STATE_WORK_FREE, TRUE);
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
PROG= hello
|
PROG= hello
|
||||||
SRCS= hello.c
|
SRCS= hello.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS}
|
DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
|
||||||
LDADD+= -ldriver -lsys
|
LDADD+= -lchardriver -lsys
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/driver.h>
|
#include <minix/chardriver.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <minix/ds.h>
|
#include <minix/ds.h>
|
||||||
|
@ -8,14 +8,13 @@
|
||||||
/*
|
/*
|
||||||
* Function prototypes for the hello driver.
|
* Function prototypes for the hello driver.
|
||||||
*/
|
*/
|
||||||
FORWARD _PROTOTYPE( char * hello_name, (void) );
|
FORWARD _PROTOTYPE( int hello_open, (message *m) );
|
||||||
FORWARD _PROTOTYPE( int hello_open, (struct driver *d, message *m) );
|
FORWARD _PROTOTYPE( int hello_close, (message *m) );
|
||||||
FORWARD _PROTOTYPE( int hello_close, (struct driver *d, message *m) );
|
FORWARD _PROTOTYPE( struct device * hello_prepare, (dev_t device) );
|
||||||
FORWARD _PROTOTYPE( struct device * hello_prepare, (int device) );
|
FORWARD _PROTOTYPE( int hello_transfer, (endpoint_t endpt, int opcode,
|
||||||
FORWARD _PROTOTYPE( int hello_transfer, (int procnr, int opcode,
|
|
||||||
u64_t position, iovec_t *iov,
|
u64_t position, iovec_t *iov,
|
||||||
unsigned nr_req) );
|
unsigned int nr_req,
|
||||||
FORWARD _PROTOTYPE( void hello_geometry, (struct partition *entry) );
|
endpoint_t user_endpt) );
|
||||||
|
|
||||||
/* SEF functions and variables. */
|
/* SEF functions and variables. */
|
||||||
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
||||||
|
@ -24,21 +23,17 @@ FORWARD _PROTOTYPE( int sef_cb_lu_state_save, (int) );
|
||||||
FORWARD _PROTOTYPE( int lu_state_restore, (void) );
|
FORWARD _PROTOTYPE( int lu_state_restore, (void) );
|
||||||
|
|
||||||
/* Entry points to the hello driver. */
|
/* Entry points to the hello driver. */
|
||||||
PRIVATE struct driver hello_tab =
|
PRIVATE struct chardriver hello_tab =
|
||||||
{
|
{
|
||||||
hello_name,
|
|
||||||
hello_open,
|
hello_open,
|
||||||
hello_close,
|
hello_close,
|
||||||
nop_ioctl,
|
nop_ioctl,
|
||||||
hello_prepare,
|
hello_prepare,
|
||||||
hello_transfer,
|
hello_transfer,
|
||||||
nop_cleanup,
|
nop_cleanup,
|
||||||
hello_geometry,
|
|
||||||
nop_alarm,
|
nop_alarm,
|
||||||
nop_cancel,
|
nop_cancel,
|
||||||
nop_select,
|
nop_select,
|
||||||
nop_ioctl,
|
|
||||||
NULL,
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,47 +43,38 @@ PRIVATE struct device hello_device;
|
||||||
/** State variable to count the number of times the device has been opened. */
|
/** State variable to count the number of times the device has been opened. */
|
||||||
PRIVATE int open_counter;
|
PRIVATE int open_counter;
|
||||||
|
|
||||||
PRIVATE char * hello_name(void)
|
PRIVATE int hello_open(message *UNUSED(m))
|
||||||
{
|
|
||||||
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);
|
printf("hello_open(). Called %d time(s).\n", ++open_counter);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE int hello_close(d, m)
|
PRIVATE int hello_close(message *UNUSED(m))
|
||||||
struct driver *d;
|
|
||||||
message *m;
|
|
||||||
{
|
{
|
||||||
printf("hello_close()\n");
|
printf("hello_close()\n");
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE struct device * hello_prepare(dev)
|
PRIVATE struct device * hello_prepare(dev_t UNUSED(dev))
|
||||||
int dev;
|
|
||||||
{
|
{
|
||||||
hello_device.dv_base = make64(0, 0);
|
hello_device.dv_base = make64(0, 0);
|
||||||
hello_device.dv_size = make64(strlen(HELLO_MESSAGE), 0);
|
hello_device.dv_size = make64(strlen(HELLO_MESSAGE), 0);
|
||||||
return &hello_device;
|
return &hello_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE int hello_transfer(proc_nr, opcode, position, iov, nr_req)
|
PRIVATE int hello_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||||
int proc_nr;
|
iovec_t *iov, unsigned nr_req, endpoint_t UNUSED(user_endpt))
|
||||||
int opcode;
|
|
||||||
u64_t position;
|
|
||||||
iovec_t *iov;
|
|
||||||
unsigned nr_req;
|
|
||||||
{
|
{
|
||||||
int bytes, ret;
|
int bytes, ret;
|
||||||
|
|
||||||
printf("hello_transfer()\n");
|
printf("hello_transfer()\n");
|
||||||
|
|
||||||
|
if (nr_req != 1)
|
||||||
|
{
|
||||||
|
/* This should never trigger for character drivers at the moment. */
|
||||||
|
printf("HELLO: vectored transfer request, using first element only\n");
|
||||||
|
}
|
||||||
|
|
||||||
bytes = strlen(HELLO_MESSAGE) - ex64lo(position) < iov->iov_size ?
|
bytes = strlen(HELLO_MESSAGE) - ex64lo(position) < iov->iov_size ?
|
||||||
strlen(HELLO_MESSAGE) - ex64lo(position) : iov->iov_size;
|
strlen(HELLO_MESSAGE) - ex64lo(position) : iov->iov_size;
|
||||||
|
|
||||||
|
@ -99,7 +85,7 @@ PRIVATE int hello_transfer(proc_nr, opcode, position, iov, nr_req)
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case DEV_GATHER_S:
|
case DEV_GATHER_S:
|
||||||
ret = sys_safecopyto(proc_nr, iov->iov_addr, 0,
|
ret = sys_safecopyto(endpt, (cp_grant_id_t) iov->iov_addr, 0,
|
||||||
(vir_bytes) (HELLO_MESSAGE + ex64lo(position)),
|
(vir_bytes) (HELLO_MESSAGE + ex64lo(position)),
|
||||||
bytes, D);
|
bytes, D);
|
||||||
iov->iov_size -= bytes;
|
iov->iov_size -= bytes;
|
||||||
|
@ -111,16 +97,7 @@ PRIVATE int hello_transfer(proc_nr, opcode, position, iov, nr_req)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE void hello_geometry(entry)
|
PRIVATE int sef_cb_lu_state_save(int UNUSED(state)) {
|
||||||
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. */
|
/* Save the state. */
|
||||||
ds_publish_u32("open_counter", open_counter, DSF_OVERWRITE);
|
ds_publish_u32("open_counter", open_counter, DSF_OVERWRITE);
|
||||||
|
|
||||||
|
@ -161,7 +138,7 @@ PRIVATE void sef_local_startup()
|
||||||
sef_startup();
|
sef_startup();
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE int sef_cb_init(int type, sef_init_info_t *info)
|
PRIVATE int sef_cb_init(int type, sef_init_info_t *UNUSED(info))
|
||||||
{
|
{
|
||||||
/* Initialize the hello driver. */
|
/* Initialize the hello driver. */
|
||||||
int do_announce_driver = TRUE;
|
int do_announce_driver = TRUE;
|
||||||
|
@ -187,14 +164,14 @@ PRIVATE int sef_cb_init(int type, sef_init_info_t *info)
|
||||||
|
|
||||||
/* Announce we are up when necessary. */
|
/* Announce we are up when necessary. */
|
||||||
if (do_announce_driver) {
|
if (do_announce_driver) {
|
||||||
driver_announce();
|
chardriver_announce();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialization completed successfully. */
|
/* Initialization completed successfully. */
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUBLIC int main(int argc, char **argv)
|
PUBLIC int main(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Perform initialization.
|
* Perform initialization.
|
||||||
|
@ -204,7 +181,7 @@ PUBLIC int main(int argc, char **argv)
|
||||||
/*
|
/*
|
||||||
* Run the main loop.
|
* Run the main loop.
|
||||||
*/
|
*/
|
||||||
driver_task(&hello_tab, DRIVER_STD);
|
chardriver_task(&hello_tab, CHARDRIVER_SYNC);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
PROG= log
|
PROG= log
|
||||||
SRCS= log.c diag.c liveupdate.c
|
SRCS= log.c diag.c liveupdate.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS}
|
DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
|
||||||
LDADD+= -ldriver -lsys
|
LDADD+= -lchardriver -lsys
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -22,36 +22,31 @@ PUBLIC struct logdevice logdevices[NR_DEVS];
|
||||||
PRIVATE struct device log_geom[NR_DEVS]; /* base and size of devices */
|
PRIVATE struct device log_geom[NR_DEVS]; /* base and size of devices */
|
||||||
PRIVATE int log_device = -1; /* current device */
|
PRIVATE int log_device = -1; /* current device */
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( char *log_name, (void) );
|
FORWARD _PROTOTYPE( struct device *log_prepare, (dev_t device) );
|
||||||
FORWARD _PROTOTYPE( struct device *log_prepare, (int device) );
|
FORWARD _PROTOTYPE( int log_transfer, (endpoint_t endpt, int opcode,
|
||||||
FORWARD _PROTOTYPE( int log_transfer, (int proc_nr, int opcode, u64_t position,
|
u64_t position, iovec_t *iov, unsigned int nr_req,
|
||||||
iovec_t *iov, unsigned nr_req) );
|
endpoint_t user_endpt) );
|
||||||
FORWARD _PROTOTYPE( int log_do_open, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int log_do_open, (message *m_ptr) );
|
||||||
FORWARD _PROTOTYPE( int log_cancel, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int log_cancel, (message *m_ptr) );
|
||||||
FORWARD _PROTOTYPE( int log_select, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int log_select, (message *m_ptr) );
|
||||||
FORWARD _PROTOTYPE( int log_other, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int log_other, (message *m_ptr) );
|
||||||
FORWARD _PROTOTYPE( void log_geometry, (struct partition *entry) );
|
FORWARD _PROTOTYPE( int subread, (struct logdevice *log, int count,
|
||||||
FORWARD _PROTOTYPE( int subread, (struct logdevice *log, int count, int proc_nr, cp_grant_id_t grant, size_t) );
|
endpoint_t endpt, cp_grant_id_t grant, size_t) );
|
||||||
|
|
||||||
/* Entry points to this driver. */
|
/* Entry points to this driver. */
|
||||||
PRIVATE struct driver log_dtab = {
|
PRIVATE struct chardriver log_dtab = {
|
||||||
log_name, /* current device's name */
|
|
||||||
log_do_open, /* open or mount */
|
log_do_open, /* open or mount */
|
||||||
do_nop, /* nothing on a close */
|
do_nop, /* nothing on a close */
|
||||||
nop_ioctl, /* ioctl nop */
|
nop_ioctl, /* ioctl nop */
|
||||||
log_prepare, /* prepare for I/O on a given minor device */
|
log_prepare, /* prepare for I/O on a given minor device */
|
||||||
log_transfer, /* do the I/O */
|
log_transfer, /* do the I/O */
|
||||||
nop_cleanup, /* no need to clean up */
|
nop_cleanup, /* no need to clean up */
|
||||||
log_geometry, /* geometry */
|
|
||||||
nop_alarm, /* no alarm */
|
nop_alarm, /* no alarm */
|
||||||
log_cancel, /* CANCEL request */
|
log_cancel, /* CANCEL request */
|
||||||
log_select, /* DEV_SELECT request */
|
log_select, /* DEV_SELECT request */
|
||||||
log_other, /* Unrecognized messages */
|
log_other /* Unrecognized messages */
|
||||||
NULL /* HW int */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int device_endpt;
|
|
||||||
|
|
||||||
/* SEF functions and variables. */
|
/* SEF functions and variables. */
|
||||||
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
||||||
FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
|
FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
|
||||||
|
@ -69,7 +64,7 @@ PUBLIC int main(void)
|
||||||
sef_local_startup();
|
sef_local_startup();
|
||||||
|
|
||||||
/* Call the generic receive loop. */
|
/* Call the generic receive loop. */
|
||||||
driver_task(&log_dtab, DRIVER_ASYN);
|
chardriver_task(&log_dtab, CHARDRIVER_ASYNC);
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
@ -99,7 +94,7 @@ PRIVATE void sef_local_startup()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_cb_init_fresh *
|
* sef_cb_init_fresh *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
|
PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
{
|
{
|
||||||
/* Initialize the log driver. */
|
/* Initialize the log driver. */
|
||||||
int i;
|
int i;
|
||||||
|
@ -131,26 +126,15 @@ PRIVATE void sef_cb_signal_handler(int signo)
|
||||||
do_new_kmess();
|
do_new_kmess();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* log_name *
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE char *log_name()
|
|
||||||
{
|
|
||||||
/* Return a name for the current device. */
|
|
||||||
static char name[] = "log";
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* log_prepare *
|
* log_prepare *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE struct device *log_prepare(device)
|
PRIVATE struct device *log_prepare(dev_t device)
|
||||||
int device;
|
|
||||||
{
|
{
|
||||||
/* Prepare for I/O on a device: check if the minor device number is ok. */
|
/* Prepare for I/O on a device: check if the minor device number is ok. */
|
||||||
|
|
||||||
if (device < 0 || device >= NR_DEVS) return(NULL);
|
if (device >= NR_DEVS) return(NULL);
|
||||||
log_device = device;
|
log_device = (int) device;
|
||||||
|
|
||||||
return(&log_geom[device]);
|
return(&log_geom[device]);
|
||||||
}
|
}
|
||||||
|
@ -159,7 +143,7 @@ int device;
|
||||||
* subwrite *
|
* subwrite *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int
|
PRIVATE int
|
||||||
subwrite(struct logdevice *log, int count, int proc_nr,
|
subwrite(struct logdevice *log, int count, endpoint_t endpt,
|
||||||
cp_grant_id_t grant, size_t offset, char *localbuf)
|
cp_grant_id_t grant, size_t offset, char *localbuf)
|
||||||
{
|
{
|
||||||
int d, r;
|
int d, r;
|
||||||
|
@ -174,7 +158,7 @@ subwrite(struct logdevice *log, int count, int proc_nr,
|
||||||
memcpy(buf, localbuf, count);
|
memcpy(buf, localbuf, count);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if((r=sys_safecopyfrom(proc_nr, grant, offset,
|
if((r=sys_safecopyfrom(endpt, grant, offset,
|
||||||
(vir_bytes)buf, count, D)) != OK)
|
(vir_bytes)buf, count, D)) != OK)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -267,7 +251,7 @@ log_append(char *buf, int count)
|
||||||
* subread *
|
* subread *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int
|
PRIVATE int
|
||||||
subread(struct logdevice *log, int count, int proc_nr,
|
subread(struct logdevice *log, int count, endpoint_t endpt,
|
||||||
cp_grant_id_t grant, size_t offset)
|
cp_grant_id_t grant, size_t offset)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
|
@ -278,7 +262,7 @@ subread(struct logdevice *log, int count, int proc_nr,
|
||||||
count = LOG_SIZE - log->log_read;
|
count = LOG_SIZE - log->log_read;
|
||||||
|
|
||||||
buf = log->log_buffer + log->log_read;
|
buf = log->log_buffer + log->log_read;
|
||||||
if((r=sys_safecopyto(proc_nr, grant, offset,
|
if((r=sys_safecopyto(endpt, grant, offset,
|
||||||
(vir_bytes)buf, count, D)) != OK)
|
(vir_bytes)buf, count, D)) != OK)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -291,12 +275,14 @@ subread(struct logdevice *log, int count, int proc_nr,
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* log_transfer *
|
* log_transfer *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int log_transfer(proc_nr, opcode, position, iov, nr_req)
|
PRIVATE int log_transfer(
|
||||||
int proc_nr; /* process doing the request */
|
endpoint_t endpt, /* endpoint of grant owner */
|
||||||
int opcode; /* DEV_GATHER_S or DEV_SCATTER_S */
|
int opcode, /* DEV_GATHER_S or DEV_SCATTER_S */
|
||||||
u64_t position; /* offset on device to read or write */
|
u64_t UNUSED(position), /* offset on device to read or write */
|
||||||
iovec_t *iov; /* pointer to read or write request vector */
|
iovec_t *iov, /* pointer to read or write request vector */
|
||||||
unsigned nr_req; /* length of request vector */
|
unsigned int nr_req, /* length of request vector */
|
||||||
|
endpoint_t user_endpt /* endpoint of user process */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
/* Read or write one the driver's minor devices. */
|
/* Read or write one the driver's minor devices. */
|
||||||
int count;
|
int count;
|
||||||
|
@ -331,27 +317,25 @@ unsigned nr_req; /* length of request vector */
|
||||||
if(accumulated_read)
|
if(accumulated_read)
|
||||||
return OK;
|
return OK;
|
||||||
/* No data available; let caller block. */
|
/* No data available; let caller block. */
|
||||||
log->log_source = proc_nr;
|
log->log_source = endpt;
|
||||||
log->log_iosize = count;
|
log->log_iosize = count;
|
||||||
log->log_user_grant = grant;
|
log->log_user_grant = grant;
|
||||||
log->log_user_offset = 0;
|
log->log_user_offset = 0;
|
||||||
log->log_revive_alerted = 0;
|
log->log_revive_alerted = 0;
|
||||||
|
log->log_proc_nr = user_endpt;
|
||||||
/* device_endpt is a global in drivers library. */
|
|
||||||
log->log_proc_nr = device_endpt;
|
|
||||||
#if LOG_DEBUG
|
#if LOG_DEBUG
|
||||||
printf("blocked %d (%d)\n",
|
printf("blocked %d (%d)\n",
|
||||||
log->log_source, log->log_proc_nr);
|
log->log_source, log->log_proc_nr);
|
||||||
#endif
|
#endif
|
||||||
return(EDONTREPLY);
|
return(EDONTREPLY);
|
||||||
}
|
}
|
||||||
count = subread(log, count, proc_nr, grant, vir_offset);
|
count = subread(log, count, endpt, grant, vir_offset);
|
||||||
if(count < 0) {
|
if(count < 0) {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
accumulated_read += count;
|
accumulated_read += count;
|
||||||
} else {
|
} else {
|
||||||
count = subwrite(log, count, proc_nr, grant, vir_offset, NULL);
|
count = subwrite(log, count, endpt, grant, vir_offset, NULL);
|
||||||
if(count < 0)
|
if(count < 0)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -371,33 +355,16 @@ unsigned nr_req; /* length of request vector */
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* log_do_open *
|
* log_do_open *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
PRIVATE int log_do_open(dp, m_ptr)
|
PRIVATE int log_do_open(message *m_ptr)
|
||||||
struct driver *dp;
|
|
||||||
message *m_ptr;
|
|
||||||
{
|
{
|
||||||
if (log_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
if (log_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*============================================================================*
|
|
||||||
* log_geometry *
|
|
||||||
*============================================================================*/
|
|
||||||
PRIVATE void log_geometry(entry)
|
|
||||||
struct partition *entry;
|
|
||||||
{
|
|
||||||
/* take a page from the fake memory device geometry */
|
|
||||||
entry->heads = 64;
|
|
||||||
entry->sectors = 32;
|
|
||||||
entry->cylinders = div64u(log_geom[log_device].dv_size, SECTOR_SIZE) /
|
|
||||||
(entry->heads * entry->sectors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* log_cancel *
|
* log_cancel *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
PRIVATE int log_cancel(dp, m_ptr)
|
PRIVATE int log_cancel(message *m_ptr)
|
||||||
struct driver *dp;
|
|
||||||
message *m_ptr;
|
|
||||||
{
|
{
|
||||||
int d;
|
int d;
|
||||||
d = m_ptr->TTY_LINE;
|
d = m_ptr->TTY_LINE;
|
||||||
|
@ -411,9 +378,7 @@ message *m_ptr;
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* log_other *
|
* log_other *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
PRIVATE int log_other(dp, m_ptr)
|
PRIVATE int log_other(message *m_ptr)
|
||||||
struct driver *dp;
|
|
||||||
message *m_ptr;
|
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -440,9 +405,7 @@ message *m_ptr;
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* log_select *
|
* log_select *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
PRIVATE int log_select(dp, m_ptr)
|
PRIVATE int log_select(message *m_ptr)
|
||||||
struct driver *dp;
|
|
||||||
message *m_ptr;
|
|
||||||
{
|
{
|
||||||
int d, ready_ops = 0, ops = 0;
|
int d, ready_ops = 0, ops = 0;
|
||||||
d = m_ptr->TTY_LINE;
|
d = m_ptr->TTY_LINE;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* Includes. */
|
/* Includes. */
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/driver.h>
|
#include <minix/chardriver.h>
|
||||||
#include <minix/type.h>
|
#include <minix/type.h>
|
||||||
#include <minix/const.h>
|
#include <minix/const.h>
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
PROG= memory
|
PROG= memory
|
||||||
SRCS= memory.c imgrd.c
|
SRCS= memory.c imgrd.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS}
|
DPADD+= ${LIBBLOCKDRIVER} ${LIBCHARDRIVER} ${LIBSYS}
|
||||||
LDADD+= -ldriver -lsys
|
LDADD+= -lblockdriver -lchardriver -lsys
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/driver.h>
|
#include <minix/chardriver.h>
|
||||||
|
#include <minix/blockdriver.h>
|
||||||
#include <sys/ioc_memory.h>
|
#include <sys/ioc_memory.h>
|
||||||
#include <minix/ds.h>
|
#include <minix/ds.h>
|
||||||
#include <minix/vm.h>
|
#include <minix/vm.h>
|
||||||
|
@ -39,37 +40,53 @@
|
||||||
|
|
||||||
PRIVATE struct device m_geom[NR_DEVS]; /* base and size of each device */
|
PRIVATE struct device m_geom[NR_DEVS]; /* base and size of each device */
|
||||||
PRIVATE vir_bytes m_vaddrs[NR_DEVS];
|
PRIVATE vir_bytes m_vaddrs[NR_DEVS];
|
||||||
PRIVATE int m_device; /* current device */
|
PRIVATE dev_t m_device; /* current minor character device */
|
||||||
PRIVATE struct kinfo kinfo; /* kernel information */
|
|
||||||
|
|
||||||
extern int errno; /* error number for PM calls */
|
|
||||||
|
|
||||||
PRIVATE int openct[NR_DEVS];
|
PRIVATE int openct[NR_DEVS];
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( char *m_name, (void) );
|
FORWARD _PROTOTYPE( struct device *m_prepare, (dev_t device) );
|
||||||
FORWARD _PROTOTYPE( struct device *m_prepare, (int device) );
|
FORWARD _PROTOTYPE( int m_transfer, (endpoint_t endpt, int opcode,
|
||||||
FORWARD _PROTOTYPE( int m_transfer, (int proc_nr, int opcode,
|
u64_t position, iovec_t *iov, unsigned int nr_req,
|
||||||
u64_t position, iovec_t *iov, unsigned nr_req) );
|
endpoint_t user_endpt) );
|
||||||
FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int m_do_open, (message *m_ptr) );
|
||||||
FORWARD _PROTOTYPE( int m_do_close, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int m_do_close, (message *m_ptr) );
|
||||||
FORWARD _PROTOTYPE( int m_ioctl, (struct driver *dp, message *m_ptr) );
|
|
||||||
FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) );
|
|
||||||
|
|
||||||
/* Entry points to this driver. */
|
FORWARD _PROTOTYPE( struct device *m_block_part, (dev_t minor) );
|
||||||
PRIVATE struct driver m_dtab = {
|
FORWARD _PROTOTYPE( int m_block_transfer, (dev_t minor, int do_write,
|
||||||
m_name, /* current device's name */
|
u64_t position, endpoint_t endpt, iovec_t *iov,
|
||||||
|
unsigned int nr_req, int flags) );
|
||||||
|
FORWARD _PROTOTYPE( int m_block_open, (dev_t minor, int access) );
|
||||||
|
FORWARD _PROTOTYPE( int m_block_close, (dev_t minor) );
|
||||||
|
FORWARD _PROTOTYPE( int m_block_ioctl, (dev_t minor,
|
||||||
|
unsigned int request, endpoint_t endpt, cp_grant_id_t grant) );
|
||||||
|
|
||||||
|
/* Entry points to the CHARACTER part of this driver. */
|
||||||
|
PRIVATE struct chardriver m_cdtab = {
|
||||||
m_do_open, /* open or mount */
|
m_do_open, /* open or mount */
|
||||||
m_do_close, /* nothing on a close */
|
m_do_close, /* nothing on a close */
|
||||||
m_ioctl, /* specify ram disk geometry */
|
nop_ioctl, /* no I/O control */
|
||||||
m_prepare, /* prepare for I/O on a given minor device */
|
m_prepare, /* prepare for I/O on a given minor device */
|
||||||
m_transfer, /* do the I/O */
|
m_transfer, /* do the I/O */
|
||||||
nop_cleanup, /* no need to clean up */
|
nop_cleanup, /* no need to clean up */
|
||||||
m_geometry, /* memory device "geometry" */
|
nop_alarm, /* no alarms */
|
||||||
nop_alarm,
|
nop_cancel, /* no blocking operations */
|
||||||
nop_cancel,
|
nop_select, /* select not supported */
|
||||||
nop_select,
|
NULL /* other messages not supported */
|
||||||
NULL,
|
};
|
||||||
NULL
|
|
||||||
|
/* Entry points to the BLOCK part of this driver. */
|
||||||
|
PRIVATE struct blockdriver m_bdtab = {
|
||||||
|
m_block_open, /* open or mount */
|
||||||
|
m_block_close, /* nothing on a close */
|
||||||
|
m_block_transfer, /* do the I/O */
|
||||||
|
m_block_ioctl, /* ram disk I/O control */
|
||||||
|
NULL, /* no need to clean up */
|
||||||
|
m_block_part, /* return partition information */
|
||||||
|
NULL, /* no geometry */
|
||||||
|
NULL, /* no interrupt processing */
|
||||||
|
NULL, /* no alarm processing */
|
||||||
|
NULL, /* no processing of other messages */
|
||||||
|
NULL /* no threading support */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Buffer for the /dev/zero null byte feed. */
|
/* Buffer for the /dev/zero null byte feed. */
|
||||||
|
@ -88,11 +105,23 @@ FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int main(void)
|
PUBLIC int main(void)
|
||||||
{
|
{
|
||||||
|
message msg;
|
||||||
|
int r, ipc_status;
|
||||||
|
|
||||||
/* SEF local startup. */
|
/* SEF local startup. */
|
||||||
sef_local_startup();
|
sef_local_startup();
|
||||||
|
|
||||||
/* Call the generic receive loop. */
|
/* The receive loop. */
|
||||||
driver_task(&m_dtab, DRIVER_STD);
|
for (;;) {
|
||||||
|
if ((r = driver_receive(ANY, &msg, &ipc_status)) != OK)
|
||||||
|
panic("memory: driver_receive failed (%d)", r);
|
||||||
|
|
||||||
|
if (IS_BDEV_RQ(msg.m_type))
|
||||||
|
blockdriver_process(&m_bdtab, &msg, ipc_status);
|
||||||
|
else
|
||||||
|
chardriver_process(&m_cdtab, CHARDRIVER_SYNC, &msg,
|
||||||
|
ipc_status);
|
||||||
|
}
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
@ -118,17 +147,18 @@ PRIVATE void sef_local_startup()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_cb_init_fresh *
|
* sef_cb_init_fresh *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
{
|
{
|
||||||
/* Initialize the memory driver. */
|
/* Initialize the memory driver. */
|
||||||
int i, s;
|
int i;
|
||||||
|
#if 0
|
||||||
|
struct kinfo kinfo; /* kernel information */
|
||||||
|
int s;
|
||||||
|
|
||||||
/* Initialize all minor devices one by one. */
|
|
||||||
if (OK != (s=sys_getkinfo(&kinfo))) {
|
if (OK != (s=sys_getkinfo(&kinfo))) {
|
||||||
panic("Couldn't get kernel information: %d", s);
|
panic("Couldn't get kernel information: %d", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Map in kernel memory for /dev/kmem. */
|
/* Map in kernel memory for /dev/kmem. */
|
||||||
m_geom[KMEM_DEV].dv_base = cvul64(kinfo.kmem_base);
|
m_geom[KMEM_DEV].dv_base = cvul64(kinfo.kmem_base);
|
||||||
m_geom[KMEM_DEV].dv_size = cvul64(kinfo.kmem_size);
|
m_geom[KMEM_DEV].dv_size = cvul64(kinfo.kmem_size);
|
||||||
|
@ -161,23 +191,31 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* m_name *
|
* m_is_block *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE char *m_name()
|
PRIVATE int m_is_block(dev_t minor)
|
||||||
{
|
{
|
||||||
/* Return a name for the current device. */
|
/* Return TRUE iff the given minor device number is for a block device. */
|
||||||
static char name[] = "memory";
|
|
||||||
return name;
|
switch (minor) {
|
||||||
|
case MEM_DEV:
|
||||||
|
case KMEM_DEV:
|
||||||
|
case NULL_DEV:
|
||||||
|
case ZERO_DEV:
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* m_prepare *
|
* m_prepare *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE struct device *m_prepare(device)
|
PRIVATE struct device *m_prepare(dev_t device)
|
||||||
int device;
|
|
||||||
{
|
{
|
||||||
/* Prepare for I/O on a device: check if the minor device number is ok. */
|
/* Prepare for I/O on a device: check if the minor device number is ok. */
|
||||||
if (device < 0 || device >= NR_DEVS) return(NULL);
|
if (device >= NR_DEVS || m_is_block(device)) return(NULL);
|
||||||
m_device = device;
|
m_device = device;
|
||||||
|
|
||||||
return(&m_geom[device]);
|
return(&m_geom[device]);
|
||||||
|
@ -186,20 +224,23 @@ int device;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* m_transfer *
|
* m_transfer *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int m_transfer(proc_nr, opcode, pos64, iov, nr_req)
|
PRIVATE int m_transfer(
|
||||||
int proc_nr; /* process doing the request */
|
endpoint_t endpt, /* endpoint of grant owner */
|
||||||
int opcode; /* DEV_GATHER_S or DEV_SCATTER_S */
|
int opcode, /* DEV_GATHER_S or DEV_SCATTER_S */
|
||||||
u64_t pos64; /* offset on device to read or write */
|
u64_t pos64, /* offset on device to read or write */
|
||||||
iovec_t *iov; /* pointer to read or write request vector */
|
iovec_t *iov, /* pointer to read or write request vector */
|
||||||
unsigned nr_req; /* length of request vector */
|
unsigned int nr_req, /* length of request vector */
|
||||||
|
endpoint_t UNUSED(user_endpt) /* endpoint of user process */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
/* Read or write one the driver's minor devices. */
|
/* Read or write one the driver's character devices. */
|
||||||
unsigned count, left, chunk;
|
unsigned count, left, chunk;
|
||||||
vir_bytes user_vir, vir_offset = 0;
|
vir_bytes vir_offset = 0;
|
||||||
struct device *dv;
|
struct device *dv;
|
||||||
unsigned long dv_size;
|
unsigned long dv_size;
|
||||||
int s, r;
|
int s, r;
|
||||||
off_t position;
|
off_t position;
|
||||||
|
cp_grant_id_t grant;
|
||||||
vir_bytes dev_vaddr;
|
vir_bytes dev_vaddr;
|
||||||
|
|
||||||
/* ZERO_DEV and NULL_DEV are infinite in size. */
|
/* ZERO_DEV and NULL_DEV are infinite in size. */
|
||||||
|
@ -216,7 +257,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
|
|
||||||
/* How much to transfer and where to / from. */
|
/* How much to transfer and where to / from. */
|
||||||
count = iov->iov_size;
|
count = iov->iov_size;
|
||||||
user_vir = iov->iov_addr;
|
grant = (cp_grant_id_t) iov->iov_addr;
|
||||||
|
|
||||||
switch (m_device) {
|
switch (m_device) {
|
||||||
|
|
||||||
|
@ -225,15 +266,9 @@ unsigned nr_req; /* length of request vector */
|
||||||
if (opcode == DEV_GATHER_S) return(OK); /* always at EOF */
|
if (opcode == DEV_GATHER_S) return(OK); /* always at EOF */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Virtual copying. For RAM disks, kernel memory and internal FS. */
|
/* Virtual copying. For kernel memory. */
|
||||||
default:
|
default:
|
||||||
case KMEM_DEV:
|
case KMEM_DEV:
|
||||||
case RAM_DEV_OLD:
|
|
||||||
case IMGRD_DEV:
|
|
||||||
/* Bogus number. */
|
|
||||||
if(m_device < 0 || m_device >= NR_DEVS) {
|
|
||||||
return(EINVAL);
|
|
||||||
}
|
|
||||||
if(!dev_vaddr || dev_vaddr == (vir_bytes) MAP_FAILED) {
|
if(!dev_vaddr || dev_vaddr == (vir_bytes) MAP_FAILED) {
|
||||||
printf("MEM: dev %d not initialized\n", m_device);
|
printf("MEM: dev %d not initialized\n", m_device);
|
||||||
return EIO;
|
return EIO;
|
||||||
|
@ -241,10 +276,10 @@ unsigned nr_req; /* length of request vector */
|
||||||
if (position >= dv_size) return(OK); /* check for EOF */
|
if (position >= dv_size) return(OK); /* check for EOF */
|
||||||
if (position + count > dv_size) count = dv_size - position;
|
if (position + count > dv_size) count = dv_size - position;
|
||||||
if (opcode == DEV_GATHER_S) { /* copy actual data */
|
if (opcode == DEV_GATHER_S) { /* copy actual data */
|
||||||
r=sys_safecopyto(proc_nr, user_vir, vir_offset,
|
r=sys_safecopyto(endpt, grant, vir_offset,
|
||||||
dev_vaddr + position, count, D);
|
dev_vaddr + position, count, D);
|
||||||
} else {
|
} else {
|
||||||
r=sys_safecopyfrom(proc_nr, user_vir, vir_offset,
|
r=sys_safecopyfrom(endpt, grant, vir_offset,
|
||||||
dev_vaddr + position, count, D);
|
dev_vaddr + position, count, D);
|
||||||
}
|
}
|
||||||
if(r != OK) {
|
if(r != OK) {
|
||||||
|
@ -302,10 +337,10 @@ unsigned nr_req; /* length of request vector */
|
||||||
subcount = count;
|
subcount = count;
|
||||||
|
|
||||||
if (opcode == DEV_GATHER_S) { /* copy data */
|
if (opcode == DEV_GATHER_S) { /* copy data */
|
||||||
s=sys_safecopyto(proc_nr, user_vir,
|
s=sys_safecopyto(endpt, grant,
|
||||||
vir_offset, (vir_bytes) vaddr+page_off, subcount, D);
|
vir_offset, (vir_bytes) vaddr+page_off, subcount, D);
|
||||||
} else {
|
} else {
|
||||||
s=sys_safecopyfrom(proc_nr, user_vir,
|
s=sys_safecopyfrom(endpt, grant,
|
||||||
vir_offset, (vir_bytes) vaddr+page_off, subcount, D);
|
vir_offset, (vir_bytes) vaddr+page_off, subcount, D);
|
||||||
}
|
}
|
||||||
if(s != OK)
|
if(s != OK)
|
||||||
|
@ -321,7 +356,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
left = count;
|
left = count;
|
||||||
while (left > 0) {
|
while (left > 0) {
|
||||||
chunk = (left > ZERO_BUF_SIZE) ? ZERO_BUF_SIZE : left;
|
chunk = (left > ZERO_BUF_SIZE) ? ZERO_BUF_SIZE : left;
|
||||||
s=sys_safecopyto(proc_nr, user_vir,
|
s=sys_safecopyto(endpt, grant,
|
||||||
vir_offset+suboffset, (vir_bytes) dev_zero, chunk, D);
|
vir_offset+suboffset, (vir_bytes) dev_zero, chunk, D);
|
||||||
if(s != OK)
|
if(s != OK)
|
||||||
return s;
|
return s;
|
||||||
|
@ -345,10 +380,9 @@ unsigned nr_req; /* length of request vector */
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* m_do_open *
|
* m_do_open *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int m_do_open(dp, m_ptr)
|
PRIVATE int m_do_open(message *m_ptr)
|
||||||
struct driver *dp;
|
|
||||||
message *m_ptr;
|
|
||||||
{
|
{
|
||||||
|
/* Open a memory character device. */
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Check device number on open. */
|
/* Check device number on open. */
|
||||||
|
@ -364,10 +398,6 @@ message *m_ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_device < 0 || m_device >= NR_DEVS) {
|
|
||||||
panic("wrong m_device: %d", m_device);
|
|
||||||
}
|
|
||||||
|
|
||||||
openct[m_device]++;
|
openct[m_device]++;
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
|
@ -376,23 +406,127 @@ message *m_ptr;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* m_do_close *
|
* m_do_close *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int m_do_close(dp, m_ptr)
|
PRIVATE int m_do_close(message *m_ptr)
|
||||||
struct driver *dp;
|
|
||||||
message *m_ptr;
|
|
||||||
{
|
{
|
||||||
|
/* Close a memory character device. */
|
||||||
if (m_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
if (m_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
||||||
|
|
||||||
if(m_device < 0 || m_device >= NR_DEVS) {
|
|
||||||
panic("wrong m_device: %d", m_device);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(openct[m_device] < 1) {
|
if(openct[m_device] < 1) {
|
||||||
panic("closed too often");
|
printf("MEMORY: closing unopened device %d\n", m_device);
|
||||||
|
return(EINVAL);
|
||||||
}
|
}
|
||||||
openct[m_device]--;
|
openct[m_device]--;
|
||||||
|
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* m_block_part *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE struct device *m_block_part(dev_t minor)
|
||||||
|
{
|
||||||
|
/* Prepare for I/O on a device: check if the minor device number is ok. */
|
||||||
|
if (minor >= NR_DEVS || !m_is_block(minor)) return(NULL);
|
||||||
|
|
||||||
|
return(&m_geom[minor]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* m_block_transfer *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int m_block_transfer(
|
||||||
|
dev_t minor, /* minor device number */
|
||||||
|
int do_write, /* read or write? */
|
||||||
|
u64_t pos64, /* offset on device to read or write */
|
||||||
|
endpoint_t endpt, /* process doing the request */
|
||||||
|
iovec_t *iov, /* pointer to read or write request vector */
|
||||||
|
unsigned int nr_req, /* length of request vector */
|
||||||
|
int UNUSED(flags) /* transfer flags */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* Read or write one the driver's block devices. */
|
||||||
|
unsigned count;
|
||||||
|
vir_bytes vir_offset = 0;
|
||||||
|
struct device *dv;
|
||||||
|
unsigned long dv_size;
|
||||||
|
int r;
|
||||||
|
off_t position;
|
||||||
|
vir_bytes dev_vaddr;
|
||||||
|
cp_grant_id_t grant;
|
||||||
|
ssize_t total = 0;
|
||||||
|
|
||||||
|
/* Get minor device information. */
|
||||||
|
if ((dv = m_block_part(minor)) == NULL) return(ENXIO);
|
||||||
|
dv_size = cv64ul(dv->dv_size);
|
||||||
|
dev_vaddr = m_vaddrs[minor];
|
||||||
|
|
||||||
|
if (ex64hi(pos64) != 0)
|
||||||
|
return OK; /* Beyond EOF */
|
||||||
|
position= cv64ul(pos64);
|
||||||
|
|
||||||
|
while (nr_req > 0) {
|
||||||
|
|
||||||
|
/* How much to transfer and where to / from. */
|
||||||
|
count = iov->iov_size;
|
||||||
|
grant = (cp_grant_id_t) iov->iov_addr;
|
||||||
|
|
||||||
|
/* Virtual copying. For RAM disks and internal FS. */
|
||||||
|
if(!dev_vaddr || dev_vaddr == (vir_bytes) MAP_FAILED) {
|
||||||
|
printf("MEM: dev %d not initialized\n", minor);
|
||||||
|
return EIO;
|
||||||
|
}
|
||||||
|
if (position >= dv_size) return(total); /* check for EOF */
|
||||||
|
if (position + count > dv_size) count = dv_size - position;
|
||||||
|
if (!do_write) { /* copy actual data */
|
||||||
|
r=sys_safecopyto(endpt, grant, vir_offset,
|
||||||
|
dev_vaddr + position, count, D);
|
||||||
|
} else {
|
||||||
|
r=sys_safecopyfrom(endpt, grant, vir_offset,
|
||||||
|
dev_vaddr + position, count, D);
|
||||||
|
}
|
||||||
|
if(r != OK) {
|
||||||
|
panic("I/O copy failed: %d", r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Book the number of bytes transferred. */
|
||||||
|
position += count;
|
||||||
|
vir_offset += count;
|
||||||
|
total += count;
|
||||||
|
if ((iov->iov_size -= count) == 0) { iov++; nr_req--; vir_offset = 0; }
|
||||||
|
|
||||||
|
}
|
||||||
|
return(total);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* m_block_open *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int m_block_open(dev_t minor, int UNUSED(access))
|
||||||
|
{
|
||||||
|
/* Open a memory block device. */
|
||||||
|
if (m_block_part(minor) == NULL) return(ENXIO);
|
||||||
|
|
||||||
|
openct[minor]++;
|
||||||
|
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* m_block_close *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int m_block_close(dev_t minor)
|
||||||
|
{
|
||||||
|
/* Close a memory block device. */
|
||||||
|
if (m_block_part(minor) == NULL) return(ENXIO);
|
||||||
|
|
||||||
|
if(openct[minor] < 1) {
|
||||||
|
printf("MEMORY: closing unopened device %d\n", minor);
|
||||||
|
return(EINVAL);
|
||||||
|
}
|
||||||
|
openct[minor]--;
|
||||||
|
|
||||||
/* Special case: free initial ramdisk after it's been unmounted once. */
|
/* Special case: free initial ramdisk after it's been unmounted once. */
|
||||||
if(m_device == IMGRD_DEV && openct[m_device] == 0 && m_vaddrs[IMGRD_DEV]) {
|
if(minor == IMGRD_DEV && openct[minor] == 0 && m_vaddrs[IMGRD_DEV]) {
|
||||||
vir_bytes vaddr, vlen;
|
vir_bytes vaddr, vlen;
|
||||||
vaddr = m_vaddrs[IMGRD_DEV];
|
vaddr = m_vaddrs[IMGRD_DEV];
|
||||||
vlen = imgrd_size;
|
vlen = imgrd_size;
|
||||||
|
@ -417,60 +551,58 @@ message *m_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* m_ioctl *
|
* m_block_ioctl *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int m_ioctl(dp, m_ptr)
|
PRIVATE int m_block_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||||
struct driver *dp; /* pointer to driver structure */
|
cp_grant_id_t grant)
|
||||||
message *m_ptr; /* pointer to control message */
|
|
||||||
{
|
{
|
||||||
/* I/O controls for the memory driver. Currently there is one I/O control:
|
/* I/O controls for the block devices of the memory driver. Currently there is
|
||||||
|
* one I/O control specific to the memory driver:
|
||||||
* - MIOCRAMSIZE: to set the size of the RAM disk.
|
* - MIOCRAMSIZE: to set the size of the RAM disk.
|
||||||
*/
|
*/
|
||||||
struct device *dv;
|
struct device *dv;
|
||||||
|
|
||||||
switch (m_ptr->REQUEST) {
|
|
||||||
case MIOCRAMSIZE: {
|
|
||||||
/* Someone wants to create a new RAM disk with the given size. */
|
|
||||||
u32_t ramdev_size;
|
u32_t ramdev_size;
|
||||||
int s, dev;
|
int s;
|
||||||
void *mem;
|
void *mem;
|
||||||
|
|
||||||
/* A ramdisk can be created only once, and only on RAM disk device. */
|
if (request != MIOCRAMSIZE)
|
||||||
dev = m_ptr->DEVICE;
|
return EINVAL;
|
||||||
if(dev < 0 || dev >= NR_DEVS) {
|
|
||||||
printf("MEM: MIOCRAMSIZE: %d not a valid device\n", dev);
|
/* Someone wants to create a new RAM disk with the given size.
|
||||||
|
* A ramdisk can be created only once, and only on RAM disk device.
|
||||||
|
*/
|
||||||
|
if ((dv = m_block_part(minor)) == NULL) return ENXIO;
|
||||||
|
if((minor < RAM_DEV_FIRST || minor > RAM_DEV_LAST) && minor != RAM_DEV_OLD) {
|
||||||
|
printf("MEM: MIOCRAMSIZE: %d not a ramdisk\n", minor);
|
||||||
|
return EINVAL;
|
||||||
}
|
}
|
||||||
if((dev < RAM_DEV_FIRST || dev > RAM_DEV_LAST) && dev != RAM_DEV_OLD) {
|
|
||||||
printf("MEM: MIOCRAMSIZE: %d not a ramdisk\n", dev);
|
|
||||||
}
|
|
||||||
if ((dv = m_prepare(dev)) == NULL) return(ENXIO);
|
|
||||||
|
|
||||||
/* Get request structure */
|
/* Get request structure */
|
||||||
s= sys_safecopyfrom(m_ptr->m_source, (vir_bytes)m_ptr->IO_GRANT,
|
s= sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&ramdev_size,
|
||||||
0, (vir_bytes)&ramdev_size, sizeof(ramdev_size), D);
|
sizeof(ramdev_size), D);
|
||||||
if (s != OK)
|
if (s != OK)
|
||||||
return s;
|
return s;
|
||||||
if(m_vaddrs[dev] && !cmp64(dv->dv_size, cvul64(ramdev_size))) {
|
if(m_vaddrs[minor] && !cmp64(dv->dv_size, cvul64(ramdev_size))) {
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
/* openct is 1 for the ioctl(). */
|
/* openct is 1 for the ioctl(). */
|
||||||
if(openct[dev] != 1) {
|
if(openct[minor] != 1) {
|
||||||
printf("MEM: MIOCRAMSIZE: %d in use (count %d)\n",
|
printf("MEM: MIOCRAMSIZE: %d in use (count %d)\n",
|
||||||
dev, openct[dev]);
|
minor, openct[minor]);
|
||||||
return(EBUSY);
|
return(EBUSY);
|
||||||
}
|
}
|
||||||
if(m_vaddrs[dev]) {
|
if(m_vaddrs[minor]) {
|
||||||
u32_t size;
|
u32_t size;
|
||||||
if(ex64hi(dv->dv_size)) {
|
if(ex64hi(dv->dv_size)) {
|
||||||
panic("huge old ramdisk");
|
panic("huge old ramdisk");
|
||||||
}
|
}
|
||||||
size = ex64lo(dv->dv_size);
|
size = ex64lo(dv->dv_size);
|
||||||
minix_munmap((void *) m_vaddrs[dev], size);
|
minix_munmap((void *) m_vaddrs[minor], size);
|
||||||
m_vaddrs[dev] = (vir_bytes) NULL;
|
m_vaddrs[minor] = (vir_bytes) NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
printf("MEM:%d: allocating ramdisk of size 0x%x\n", dev, ramdev_size);
|
printf("MEM:%d: allocating ramdisk of size 0x%x\n", minor, ramdev_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Try to allocate a piece of memory for the RAM disk. */
|
/* Try to allocate a piece of memory for the RAM disk. */
|
||||||
|
@ -480,28 +612,9 @@ message *m_ptr; /* pointer to control message */
|
||||||
return(ENOMEM);
|
return(ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vaddrs[dev] = (vir_bytes) mem;
|
m_vaddrs[minor] = (vir_bytes) mem;
|
||||||
|
|
||||||
dv->dv_size = cvul64(ramdev_size);
|
dv->dv_size = cvul64(ramdev_size);
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return(do_diocntl(&m_dtab, m_ptr));
|
|
||||||
}
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* m_geometry *
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE void m_geometry(entry)
|
|
||||||
struct partition *entry;
|
|
||||||
{
|
|
||||||
/* Memory devices don't have a geometry, but the outside world insists. */
|
|
||||||
entry->cylinders = div64u(m_geom[m_device].dv_size, SECTOR_SIZE) / (64 * 32);
|
|
||||||
entry->heads = 64;
|
|
||||||
entry->sectors = 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
PROG= pci
|
PROG= pci
|
||||||
SRCS= main.c pci.c pci_table.c
|
SRCS= main.c pci.c pci_table.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
|
DPADD+= ${LIBSYS} ${LIBTIMERS}
|
||||||
LDADD+= -ldriver -lsys -ltimers
|
LDADD+= -lsys -ltimers
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
PROG= printer
|
PROG= printer
|
||||||
SRCS= printer.c liveupdate.c
|
SRCS= printer.c liveupdate.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS}
|
DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
|
||||||
LDADD+= -ldriver -lsys
|
LDADD+= -lchardriver -lsys
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
#include <minix/endpoint.h>
|
#include <minix/endpoint.h>
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/driver.h>
|
#include <minix/chardriver.h>
|
||||||
|
|
||||||
/* Control bits (in port_base + 2). "+" means positive logic and "-" means
|
/* Control bits (in port_base + 2). "+" means positive logic and "-" means
|
||||||
* negative logic. Most of the signals are negative logic on the pins but
|
* negative logic. Most of the signals are negative logic on the pins but
|
||||||
|
@ -122,7 +122,7 @@ PUBLIC int is_status_msg_expected = FALSE;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* printer_task *
|
* printer_task *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int main(int argc, char *argv[])
|
PUBLIC int main(void)
|
||||||
{
|
{
|
||||||
/* Main routine of the printer task. */
|
/* Main routine of the printer task. */
|
||||||
message pr_mess; /* buffer for all incoming messages */
|
message pr_mess; /* buffer for all incoming messages */
|
||||||
|
@ -190,11 +190,11 @@ PRIVATE void sef_local_startup()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_cb_init_fresh *
|
* sef_cb_init_fresh *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
{
|
{
|
||||||
/* Initialize the printer driver. */
|
/* Initialize the printer driver. */
|
||||||
/* Announce we are up! */
|
/* Announce we are up! */
|
||||||
driver_announce();
|
chardriver_announce();
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ SRCS= main.c random.c rijndael_api.c rijndael_alg.c
|
||||||
|
|
||||||
.PATH: ${.CURDIR}/aes
|
.PATH: ${.CURDIR}/aes
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBMINIXUTIL}
|
DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBMINIXUTIL}
|
||||||
LDADD+= -ldriver -lsys -lminixutil
|
LDADD+= -lchardriver -lsys -lminixutil
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/driver.h>
|
#include <minix/chardriver.h>
|
||||||
#include <minix/type.h>
|
#include <minix/type.h>
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
@ -16,35 +16,31 @@
|
||||||
#define KRANDOM_PERIOD 1 /* ticks between krandom calls */
|
#define KRANDOM_PERIOD 1 /* ticks between krandom calls */
|
||||||
|
|
||||||
PRIVATE struct device m_geom[NR_DEVS]; /* base and size of each device */
|
PRIVATE struct device m_geom[NR_DEVS]; /* base and size of each device */
|
||||||
PRIVATE int m_device; /* current device */
|
PRIVATE dev_t m_device; /* current device */
|
||||||
|
|
||||||
extern int errno; /* error number for PM calls */
|
extern int errno; /* error number for PM calls */
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( char *r_name, (void) );
|
FORWARD _PROTOTYPE( struct device *r_prepare, (dev_t device) );
|
||||||
FORWARD _PROTOTYPE( struct device *r_prepare, (int device) );
|
FORWARD _PROTOTYPE( int r_transfer, (endpoint_t endpt, int opcode,
|
||||||
FORWARD _PROTOTYPE( int r_transfer, (int proc_nr, int opcode, u64_t position,
|
u64_t position, iovec_t *iov, unsigned int nr_req,
|
||||||
iovec_t *iov, unsigned nr_req) );
|
endpoint_t user_endpt) );
|
||||||
FORWARD _PROTOTYPE( int r_do_open, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( int r_do_open, (message *m_ptr) );
|
||||||
FORWARD _PROTOTYPE( int r_ioctl, (struct driver *dp, message *m_ptr) );
|
FORWARD _PROTOTYPE( void r_random, (message *m_ptr) );
|
||||||
FORWARD _PROTOTYPE( void r_geometry, (struct partition *entry) );
|
FORWARD _PROTOTYPE( void r_updatebin, (int source,
|
||||||
FORWARD _PROTOTYPE( void r_random, (struct driver *dp, message *m_ptr) );
|
struct k_randomness_bin *rb) );
|
||||||
FORWARD _PROTOTYPE( void r_updatebin, (int source, struct k_randomness_bin *rb));
|
|
||||||
|
|
||||||
/* Entry points to this driver. */
|
/* Entry points to this driver. */
|
||||||
PRIVATE struct driver r_dtab = {
|
PRIVATE struct chardriver r_dtab = {
|
||||||
r_name, /* current device's name */
|
|
||||||
r_do_open, /* open or mount */
|
r_do_open, /* open or mount */
|
||||||
do_nop, /* nothing on a close */
|
do_nop, /* nothing on a close */
|
||||||
r_ioctl, /* specify ram disk geometry */
|
nop_ioctl, /* no I/O controls supported */
|
||||||
r_prepare, /* prepare for I/O on a given minor device */
|
r_prepare, /* prepare for I/O on a given minor device */
|
||||||
r_transfer, /* do the I/O */
|
r_transfer, /* do the I/O */
|
||||||
nop_cleanup, /* no need to clean up */
|
nop_cleanup, /* no need to clean up */
|
||||||
r_geometry, /* device "geometry" */
|
|
||||||
r_random, /* get randomness from kernel (alarm) */
|
r_random, /* get randomness from kernel (alarm) */
|
||||||
nop_cancel,
|
nop_cancel, /* cancel not supported */
|
||||||
nop_select,
|
nop_select, /* select not supported */
|
||||||
NULL,
|
NULL, /* other messages not supported */
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Buffer for the /dev/random number generator. */
|
/* Buffer for the /dev/random number generator. */
|
||||||
|
@ -64,7 +60,7 @@ PUBLIC int main(void)
|
||||||
sef_local_startup();
|
sef_local_startup();
|
||||||
|
|
||||||
/* Call the generic receive loop. */
|
/* Call the generic receive loop. */
|
||||||
driver_task(&r_dtab, DRIVER_ASYN);
|
chardriver_task(&r_dtab, CHARDRIVER_ASYNC);
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
@ -90,14 +86,14 @@ PRIVATE void sef_local_startup()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_cb_init_fresh *
|
* sef_cb_init_fresh *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
{
|
{
|
||||||
/* Initialize the random driver. */
|
/* Initialize the random driver. */
|
||||||
static struct k_randomness krandom;
|
static struct k_randomness krandom;
|
||||||
int i, s;
|
int i, s;
|
||||||
|
|
||||||
random_init();
|
random_init();
|
||||||
r_random(NULL, NULL); /* also set periodic timer */
|
r_random(NULL); /* also set periodic timer */
|
||||||
|
|
||||||
/* Retrieve first randomness buffer with parameters. */
|
/* Retrieve first randomness buffer with parameters. */
|
||||||
if (OK != (s=sys_getrandomness(&krandom))) {
|
if (OK != (s=sys_getrandomness(&krandom))) {
|
||||||
|
@ -119,30 +115,19 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||||
r_updatebin(i, &krandom.bin[i]);
|
r_updatebin(i, &krandom.bin[i]);
|
||||||
|
|
||||||
/* Announce we are up! */
|
/* Announce we are up! */
|
||||||
driver_announce();
|
chardriver_announce();
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* r_name *
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE char *r_name()
|
|
||||||
{
|
|
||||||
/* Return a name for the current device. */
|
|
||||||
static char name[] = "random";
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* r_prepare *
|
* r_prepare *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE struct device *r_prepare(device)
|
PRIVATE struct device *r_prepare(dev_t device)
|
||||||
int device;
|
|
||||||
{
|
{
|
||||||
/* Prepare for I/O on a device: check if the minor device number is ok. */
|
/* Prepare for I/O on a device: check if the minor device number is ok. */
|
||||||
|
|
||||||
if (device < 0 || device >= NR_DEVS) return(NULL);
|
if (device >= NR_DEVS) return(NULL);
|
||||||
m_device = device;
|
m_device = device;
|
||||||
|
|
||||||
return(&m_geom[device]);
|
return(&m_geom[device]);
|
||||||
|
@ -151,16 +136,18 @@ int device;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* r_transfer *
|
* r_transfer *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int r_transfer(proc_nr, opcode, position, iov, nr_req)
|
PRIVATE int r_transfer(
|
||||||
int proc_nr; /* process doing the request */
|
endpoint_t endpt, /* endpoint of grant owner */
|
||||||
int opcode; /* DEV_GATHER or DEV_SCATTER */
|
int opcode, /* DEV_GATHER or DEV_SCATTER */
|
||||||
u64_t position; /* offset on device to read or write */
|
u64_t position, /* offset on device to read or write */
|
||||||
iovec_t *iov; /* pointer to read or write request vector */
|
iovec_t *iov, /* pointer to read or write request vector */
|
||||||
unsigned nr_req; /* length of request vector */
|
unsigned int nr_req, /* length of request vector */
|
||||||
|
endpoint_t UNUSED(user_endpt) /* endpoint of user process */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
/* Read or write one the driver's minor devices. */
|
/* Read or write one the driver's minor devices. */
|
||||||
unsigned count, left, chunk;
|
unsigned count, left, chunk;
|
||||||
vir_bytes user_vir;
|
cp_grant_id_t grant;
|
||||||
struct device *dv;
|
struct device *dv;
|
||||||
int r;
|
int r;
|
||||||
size_t vir_offset = 0;
|
size_t vir_offset = 0;
|
||||||
|
@ -172,7 +159,7 @@ unsigned nr_req; /* length of request vector */
|
||||||
|
|
||||||
/* How much to transfer and where to / from. */
|
/* How much to transfer and where to / from. */
|
||||||
count = iov->iov_size;
|
count = iov->iov_size;
|
||||||
user_vir = iov->iov_addr;
|
grant = (cp_grant_id_t) iov->iov_addr;
|
||||||
|
|
||||||
switch (m_device) {
|
switch (m_device) {
|
||||||
|
|
||||||
|
@ -185,23 +172,21 @@ unsigned nr_req; /* length of request vector */
|
||||||
chunk = (left > RANDOM_BUF_SIZE) ? RANDOM_BUF_SIZE : left;
|
chunk = (left > RANDOM_BUF_SIZE) ? RANDOM_BUF_SIZE : left;
|
||||||
if (opcode == DEV_GATHER_S) {
|
if (opcode == DEV_GATHER_S) {
|
||||||
random_getbytes(random_buf, chunk);
|
random_getbytes(random_buf, chunk);
|
||||||
r= sys_safecopyto(proc_nr, user_vir, vir_offset,
|
r= sys_safecopyto(endpt, grant, vir_offset,
|
||||||
(vir_bytes) random_buf, chunk, D);
|
(vir_bytes) random_buf, chunk, D);
|
||||||
if (r != OK)
|
if (r != OK)
|
||||||
{
|
{
|
||||||
printf(
|
printf("random: sys_safecopyto failed for proc %d, "
|
||||||
"random: sys_safecopyto failed for proc %d, grant %d\n",
|
"grant %d\n", endpt, grant);
|
||||||
proc_nr, user_vir);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
} else if (opcode == DEV_SCATTER_S) {
|
} else if (opcode == DEV_SCATTER_S) {
|
||||||
r= sys_safecopyfrom(proc_nr, user_vir, vir_offset,
|
r= sys_safecopyfrom(endpt, grant, vir_offset,
|
||||||
(vir_bytes) random_buf, chunk, D);
|
(vir_bytes) random_buf, chunk, D);
|
||||||
if (r != OK)
|
if (r != OK)
|
||||||
{
|
{
|
||||||
printf(
|
printf("random: sys_safecopyfrom failed for proc %d, "
|
||||||
"random: sys_safecopyfrom failed for proc %d, grant %d\n",
|
"grant %d\n", endpt, grant);
|
||||||
proc_nr, user_vir);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
random_putbytes(random_buf, chunk);
|
random_putbytes(random_buf, chunk);
|
||||||
|
@ -224,12 +209,10 @@ unsigned nr_req; /* length of request vector */
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*============================================================================*
|
/*===========================================================================*
|
||||||
* r_do_open *
|
* r_do_open *
|
||||||
*============================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int r_do_open(dp, m_ptr)
|
PRIVATE int r_do_open(message *m_ptr)
|
||||||
struct driver *dp;
|
|
||||||
message *m_ptr;
|
|
||||||
{
|
{
|
||||||
/* Check device number on open.
|
/* Check device number on open.
|
||||||
*/
|
*/
|
||||||
|
@ -238,23 +221,6 @@ message *m_ptr;
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* r_ioctl *
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE int r_ioctl(dp, m_ptr)
|
|
||||||
struct driver *dp; /* pointer to driver structure */
|
|
||||||
message *m_ptr; /* pointer to control message */
|
|
||||||
{
|
|
||||||
if (r_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
|
||||||
|
|
||||||
switch (m_ptr->REQUEST) {
|
|
||||||
|
|
||||||
default:
|
|
||||||
return(do_diocntl(&r_dtab, m_ptr));
|
|
||||||
}
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define UPDATE(binnumber, bp, startitem, elems) { \
|
#define UPDATE(binnumber, bp, startitem, elems) { \
|
||||||
rand_t *r; \
|
rand_t *r; \
|
||||||
int n = elems, item = startitem;\
|
int n = elems, item = startitem;\
|
||||||
|
@ -270,6 +236,9 @@ message *m_ptr; /* pointer to control message */
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* r_updatebin *
|
||||||
|
*===========================================================================*/
|
||||||
PRIVATE void r_updatebin(int source, struct k_randomness_bin *rb)
|
PRIVATE void r_updatebin(int source, struct k_randomness_bin *rb)
|
||||||
{
|
{
|
||||||
int r_next, r_size, r_high;
|
int r_next, r_size, r_high;
|
||||||
|
@ -293,12 +262,10 @@ PRIVATE void r_updatebin(int source, struct k_randomness_bin *rb)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*============================================================================*
|
/*===========================================================================*
|
||||||
* r_random *
|
* r_random *
|
||||||
*============================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void r_random(dp, m_ptr)
|
PRIVATE void r_random(message *UNUSED(m_ptr))
|
||||||
struct driver *dp; /* pointer to driver structure */
|
|
||||||
message *m_ptr; /* pointer to alarm message */
|
|
||||||
{
|
{
|
||||||
/* Fetch random information from the kernel to update /dev/random. */
|
/* Fetch random information from the kernel to update /dev/random. */
|
||||||
int s;
|
int s;
|
||||||
|
@ -322,14 +289,3 @@ message *m_ptr; /* pointer to alarm message */
|
||||||
printf("RANDOM: sys_setalarm failed: %d\n", s);
|
printf("RANDOM: sys_setalarm failed: %d\n", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*============================================================================*
|
|
||||||
* r_geometry *
|
|
||||||
*============================================================================*/
|
|
||||||
PRIVATE void r_geometry(struct partition *entry)
|
|
||||||
{
|
|
||||||
/* Memory devices don't have a geometry, but the outside world insists. */
|
|
||||||
entry->cylinders = div64u(m_geom[m_device].dv_size, SECTOR_SIZE) / (64 * 32);
|
|
||||||
entry->heads = 64;
|
|
||||||
entry->sectors = 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
PROG= readclock.drv
|
PROG= readclock.drv
|
||||||
SRCS= readclock.c
|
SRCS= readclock.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS}
|
DPADD+= ${LIBSYS}
|
||||||
LDADD+= -ldriver -lsys
|
LDADD+= -lsys
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
PROG= ti1225
|
PROG= ti1225
|
||||||
SRCS= ti1225.c
|
SRCS= ti1225.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
|
DPADD+= ${LIBSYS}
|
||||||
LDADD+= -ldriver -lsys -ltimers
|
LDADD+= -lsys
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ PRIVATE void sef_local_startup()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_cb_init_fresh *
|
* sef_cb_init_fresh *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
{
|
{
|
||||||
/* Initialize the ti1225 driver. */
|
/* Initialize the ti1225 driver. */
|
||||||
int c, i, r, first, devind, port;
|
int c, i, r, first, devind, port;
|
||||||
|
@ -175,9 +175,6 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||||
hw_init(&ports[i]);
|
hw_init(&ports[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Announce we are up! */
|
|
||||||
driver_announce();
|
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
PROG= tty
|
PROG= tty
|
||||||
SRCS= tty.c console.c keyboard.c pty.c rs232.c
|
SRCS= tty.c console.c keyboard.c pty.c rs232.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
|
DPADD+= ${LIBSYS} ${LIBTIMERS}
|
||||||
LDADD+= -ldriver -lsys -ltimers
|
LDADD+= -lsys -ltimers
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -896,8 +896,7 @@ clock_t dur;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* stop_beep *
|
* stop_beep *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void stop_beep(tmrp)
|
PRIVATE void stop_beep(timer_t *UNUSED(tmrp))
|
||||||
timer_t *tmrp;
|
|
||||||
{
|
{
|
||||||
/* Turn off the beeper by turning off bits 0 and 1 in PORT_B. */
|
/* Turn off the beeper by turning off bits 0 and 1 in PORT_B. */
|
||||||
unsigned long port_b_val;
|
unsigned long port_b_val;
|
||||||
|
@ -1234,9 +1233,7 @@ struct sequence *seq;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* cons_ioctl *
|
* cons_ioctl *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int cons_ioctl(tp, try)
|
PRIVATE int cons_ioctl(tty_t *tp, int UNUSED(try))
|
||||||
tty_t *tp;
|
|
||||||
int try;
|
|
||||||
{
|
{
|
||||||
/* Set the screen dimensions. */
|
/* Set the screen dimensions. */
|
||||||
|
|
||||||
|
|
|
@ -481,8 +481,7 @@ int scode;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* kbd_interrupt *
|
* kbd_interrupt *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void kbd_interrupt(m_ptr)
|
PUBLIC void kbd_interrupt(message *UNUSED(m_ptr))
|
||||||
message *m_ptr;
|
|
||||||
{
|
{
|
||||||
/* A keyboard interrupt has occurred. Process it. */
|
/* A keyboard interrupt has occurred. Process it. */
|
||||||
int o, isaux;
|
int o, isaux;
|
||||||
|
@ -911,9 +910,9 @@ PRIVATE int kbc_read()
|
||||||
if(sys_inb(KEYBD, &byte) != OK)
|
if(sys_inb(KEYBD, &byte) != OK)
|
||||||
printf("kbc_read: 2 sys_inb failed\n");
|
printf("kbc_read: 2 sys_inb failed\n");
|
||||||
if (st & KB_AUX_BYTE)
|
if (st & KB_AUX_BYTE)
|
||||||
printf("kbc_read: aux byte 0x%x\n", byte);
|
printf("kbc_read: aux byte 0x%lx\n", byte);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
printf("keyboard`kbc_read: returning byte 0x%x\n",
|
printf("keyboard`kbc_read: returning byte 0x%lx\n",
|
||||||
byte);
|
byte);
|
||||||
#endif
|
#endif
|
||||||
return byte;
|
return byte;
|
||||||
|
@ -1296,8 +1295,7 @@ int *isauxp;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* kbd_watchdog *
|
* kbd_watchdog *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void kbd_watchdog(tmrp)
|
PRIVATE void kbd_watchdog(timer_t *UNUSED(tmrp))
|
||||||
timer_t *tmrp;
|
|
||||||
{
|
{
|
||||||
|
|
||||||
kbd_watchdog_set= 0;
|
kbd_watchdog_set= 0;
|
||||||
|
|
|
@ -405,7 +405,7 @@ PRIVATE int pty_read(tty_t *tp, int try)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* pty_close *
|
* pty_close *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int pty_close(tty_t *tp, int try)
|
PRIVATE int pty_close(tty_t *tp, int UNUSED(try))
|
||||||
{
|
{
|
||||||
/* The tty side has closed, so shut down the pty side. */
|
/* The tty side has closed, so shut down the pty side. */
|
||||||
pty_t *pp = tp->tty_priv;
|
pty_t *pp = tp->tty_priv;
|
||||||
|
@ -430,7 +430,7 @@ PRIVATE int pty_close(tty_t *tp, int try)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* pty_icancel *
|
* pty_icancel *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int pty_icancel(tty_t *tp, int try)
|
PRIVATE int pty_icancel(tty_t *tp, int UNUSED(try))
|
||||||
{
|
{
|
||||||
/* Discard waiting input. */
|
/* Discard waiting input. */
|
||||||
pty_t *pp = tp->tty_priv;
|
pty_t *pp = tp->tty_priv;
|
||||||
|
@ -447,7 +447,7 @@ PRIVATE int pty_icancel(tty_t *tp, int try)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* pty_ocancel *
|
* pty_ocancel *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int pty_ocancel(tty_t *tp, int try)
|
PRIVATE int pty_ocancel(tty_t *tp, int UNUSED(try))
|
||||||
{
|
{
|
||||||
/* Drain the output buffer. */
|
/* Drain the output buffer. */
|
||||||
pty_t *pp = tp->tty_priv;
|
pty_t *pp = tp->tty_priv;
|
||||||
|
|
|
@ -324,7 +324,7 @@ int c; /* character to echo */
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* rs_ioctl *
|
* rs_ioctl *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int rs_ioctl(tty_t *tp, int dummy)
|
PRIVATE int rs_ioctl(tty_t *tp, int UNUSED(dummy))
|
||||||
/* tp; which TTY */
|
/* tp; which TTY */
|
||||||
{
|
{
|
||||||
/* Reconfigure the line as soon as the output has drained. */
|
/* Reconfigure the line as soon as the output has drained. */
|
||||||
|
@ -544,7 +544,7 @@ PUBLIC void rs_interrupt(message *m)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* rs_icancel *
|
* rs_icancel *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int rs_icancel(tty_t *tp, int dummy)
|
PRIVATE int rs_icancel(tty_t *tp, int UNUSED(dummy))
|
||||||
{
|
{
|
||||||
/* Cancel waiting input. */
|
/* Cancel waiting input. */
|
||||||
rs232_t *rs = tp->tty_priv;
|
rs232_t *rs = tp->tty_priv;
|
||||||
|
@ -561,7 +561,7 @@ PRIVATE int rs_icancel(tty_t *tp, int dummy)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* rs_ocancel *
|
* rs_ocancel *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int rs_ocancel(tty_t *tp, int dummy)
|
PRIVATE int rs_ocancel(tty_t *tp, int UNUSED(dummy))
|
||||||
{
|
{
|
||||||
/* Cancel pending output. */
|
/* Cancel pending output. */
|
||||||
rs232_t *rs = tp->tty_priv;
|
rs232_t *rs = tp->tty_priv;
|
||||||
|
@ -636,7 +636,7 @@ PRIVATE void rs_ostart(rs232_t *rs)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* rs_break *
|
* rs_break *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int rs_break(tty_t *tp, int dummy)
|
PRIVATE int rs_break(tty_t *tp, int UNUSED(dummy))
|
||||||
{
|
{
|
||||||
/* Generate a break condition by setting the BREAK bit for 0.4 sec. */
|
/* Generate a break condition by setting the BREAK bit for 0.4 sec. */
|
||||||
rs232_t *rs = tp->tty_priv;
|
rs232_t *rs = tp->tty_priv;
|
||||||
|
@ -654,7 +654,7 @@ PRIVATE int rs_break(tty_t *tp, int dummy)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* rs_close *
|
* rs_close *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int rs_close(tty_t *tp, int dummy)
|
PRIVATE int rs_close(tty_t *tp, int UNUSED(dummy))
|
||||||
{
|
{
|
||||||
/* The line is closed; optionally hang up. */
|
/* The line is closed; optionally hang up. */
|
||||||
rs232_t *rs = tp->tty_priv;
|
rs232_t *rs = tp->tty_priv;
|
||||||
|
|
|
@ -309,7 +309,7 @@ PRIVATE void sef_local_startup()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_cb_init_fresh *
|
* sef_cb_init_fresh *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
{
|
{
|
||||||
/* Initialize the tty driver. */
|
/* Initialize the tty driver. */
|
||||||
int r;
|
int r;
|
||||||
|
@ -1524,7 +1524,7 @@ register tty_t *tp;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* tty_devnop *
|
* tty_devnop *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int tty_devnop(tty_t *tp, int try)
|
PRIVATE int tty_devnop(tty_t *UNUSED(tp), int UNUSED(try))
|
||||||
{
|
{
|
||||||
/* Some functions need not be implemented at the device level. */
|
/* Some functions need not be implemented at the device level. */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -16,9 +16,9 @@ LIBCOMPAT_DIR?=
|
||||||
LIBMINLIB_DIR?=
|
LIBMINLIB_DIR?=
|
||||||
LIBASYN_DIR?=
|
LIBASYN_DIR?=
|
||||||
|
|
||||||
SUBDIR= csu ${LIBCOMPAT_DIR} ${LIBC_DIR} libdriver libnetdriver \
|
SUBDIR= csu ${LIBCOMPAT_DIR} ${LIBC_DIR} libblockdriver libchardriver \
|
||||||
libedit ${LIBM_DIR} libsys libtimers ${LIBUTIL_DIR} libl libhgfs \
|
libnetdriver libedit ${LIBM_DIR} libsys libtimers ${LIBUTIL_DIR} \
|
||||||
libz libfetch libvtreefs libaudiodriver libmthread \
|
libl libhgfs libz libfetch libvtreefs libaudiodriver libmthread \
|
||||||
libexec libdevman libusb ${LIBMINLIB_DIR} ${LIBASYN_DIR} \
|
libexec libdevman libusb ${LIBMINLIB_DIR} ${LIBASYN_DIR} \
|
||||||
libddekit libminixfs libbdev
|
libddekit libminixfs libbdev
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) );
|
||||||
EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
|
EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
|
||||||
PUBLIC int is_status_msg_expected = FALSE;
|
PUBLIC int is_status_msg_expected = FALSE;
|
||||||
|
|
||||||
PUBLIC int main(int argc, char *argv[])
|
PUBLIC int main(void)
|
||||||
{
|
{
|
||||||
int r, caller;
|
int r, caller;
|
||||||
message mess, repl_mess;
|
message mess, repl_mess;
|
||||||
|
@ -255,7 +255,7 @@ PRIVATE int init_driver(void) {
|
||||||
irq_hook_set = TRUE; /* now signal handler knows it must unregister policy*/
|
irq_hook_set = TRUE; /* now signal handler knows it must unregister policy*/
|
||||||
|
|
||||||
/* Announce we are up! */
|
/* Announce we are up! */
|
||||||
driver_announce();
|
chardriver_announce();
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,10 @@ static int bdev_opcl(int req, dev_t dev, int access)
|
||||||
*/
|
*/
|
||||||
message m;
|
message m;
|
||||||
|
|
||||||
|
memset(&m, 0, sizeof(m));
|
||||||
m.m_type = req;
|
m.m_type = req;
|
||||||
m.DEVICE = minor(dev);
|
m.BDEV_MINOR = minor(dev);
|
||||||
m.COUNT = access;
|
m.BDEV_ACCESS = access;
|
||||||
|
|
||||||
return bdev_sendrec(dev, &m);
|
return bdev_sendrec(dev, &m);
|
||||||
}
|
}
|
||||||
|
@ -45,7 +46,7 @@ int bdev_open(dev_t dev, int access)
|
||||||
* File system usage note: typically called from mount, after bdev_driver.
|
* File system usage note: typically called from mount, after bdev_driver.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return bdev_opcl(DEV_OPEN, dev, access);
|
return bdev_opcl(BDEV_OPEN, dev, access);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdev_close(dev_t dev)
|
int bdev_close(dev_t dev)
|
||||||
|
@ -54,11 +55,11 @@ int bdev_close(dev_t dev)
|
||||||
* File system usage note: typically called from unmount.
|
* File system usage note: typically called from unmount.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return bdev_opcl(DEV_CLOSE, dev, 0);
|
return bdev_opcl(BDEV_CLOSE, dev, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bdev_rdwt_setup(int req, dev_t dev, u64_t pos, char *buf, int count,
|
static int bdev_rdwt_setup(int req, dev_t dev, u64_t pos, char *buf,
|
||||||
int UNUSED(flags), message *m)
|
size_t count, int flags, message *m)
|
||||||
{
|
{
|
||||||
/* Set up a single-buffer read/write request.
|
/* Set up a single-buffer read/write request.
|
||||||
*/
|
*/
|
||||||
|
@ -66,10 +67,12 @@ static int bdev_rdwt_setup(int req, dev_t dev, u64_t pos, char *buf, int count,
|
||||||
cp_grant_id_t grant;
|
cp_grant_id_t grant;
|
||||||
int access;
|
int access;
|
||||||
|
|
||||||
|
assert((ssize_t) count >= 0);
|
||||||
|
|
||||||
if ((endpt = bdev_driver_get(dev)) == NONE)
|
if ((endpt = bdev_driver_get(dev)) == NONE)
|
||||||
return EDEADSRCDST;
|
return EDEADSRCDST;
|
||||||
|
|
||||||
access = (req == DEV_READ_S) ? CPF_WRITE : CPF_READ;
|
access = (req == BDEV_READ) ? CPF_WRITE : CPF_READ;
|
||||||
|
|
||||||
grant = cpf_grant_direct(endpt, (vir_bytes) buf, count, access);
|
grant = cpf_grant_direct(endpt, (vir_bytes) buf, count, access);
|
||||||
|
|
||||||
|
@ -78,12 +81,14 @@ static int bdev_rdwt_setup(int req, dev_t dev, u64_t pos, char *buf, int count,
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(m, 0, sizeof(*m));
|
||||||
m->m_type = req;
|
m->m_type = req;
|
||||||
m->DEVICE = minor(dev);
|
m->BDEV_MINOR = minor(dev);
|
||||||
m->POSITION = ex64lo(pos);
|
m->BDEV_POS_LO = ex64lo(pos);
|
||||||
m->HIGHPOS = ex64hi(pos);
|
m->BDEV_POS_HI = ex64hi(pos);
|
||||||
m->COUNT = count;
|
m->BDEV_COUNT = count;
|
||||||
m->IO_GRANT = (void *) grant;
|
m->BDEV_GRANT = grant;
|
||||||
|
m->BDEV_FLAGS = flags;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -92,15 +97,12 @@ static void bdev_rdwt_cleanup(message *m)
|
||||||
{
|
{
|
||||||
/* Clean up a single-buffer read/write request.
|
/* Clean up a single-buffer read/write request.
|
||||||
*/
|
*/
|
||||||
cp_grant_id_t grant;
|
|
||||||
|
|
||||||
grant = (cp_grant_id_t) m->IO_GRANT;
|
cpf_revoke(m->BDEV_GRANT);
|
||||||
|
|
||||||
cpf_revoke(grant);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bdev_rdwt(int req, dev_t dev, u64_t pos, char *buf, int count,
|
static ssize_t bdev_rdwt(int req, dev_t dev, u64_t pos, char *buf,
|
||||||
int flags)
|
size_t count, int flags)
|
||||||
{
|
{
|
||||||
/* Perform a read or write call using a single buffer.
|
/* Perform a read or write call using a single buffer.
|
||||||
*/
|
*/
|
||||||
|
@ -118,11 +120,11 @@ static int bdev_rdwt(int req, dev_t dev, u64_t pos, char *buf, int count,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bdev_vrdwt_setup(int req, dev_t dev, u64_t pos, iovec_t *vec,
|
static int bdev_vrdwt_setup(int req, dev_t dev, u64_t pos, iovec_t *vec,
|
||||||
int count, int UNUSED(flags), message *m, iovec_s_t *gvec,
|
int count, int flags, message *m, iovec_s_t *gvec)
|
||||||
cp_grant_id_t *grants, vir_bytes *size)
|
|
||||||
{
|
{
|
||||||
/* Set up a vectored read/write request.
|
/* Set up a vectored read/write request.
|
||||||
*/
|
*/
|
||||||
|
ssize_t size;
|
||||||
endpoint_t endpt;
|
endpoint_t endpt;
|
||||||
cp_grant_id_t grant;
|
cp_grant_id_t grant;
|
||||||
int i, access;
|
int i, access;
|
||||||
|
@ -132,154 +134,118 @@ static int bdev_vrdwt_setup(int req, dev_t dev, u64_t pos, iovec_t *vec,
|
||||||
if ((endpt = bdev_driver_get(dev)) == NONE)
|
if ((endpt = bdev_driver_get(dev)) == NONE)
|
||||||
return EDEADSRCDST;
|
return EDEADSRCDST;
|
||||||
|
|
||||||
access = (req == DEV_GATHER_S) ? CPF_WRITE : CPF_READ;
|
access = (req == BDEV_GATHER) ? CPF_WRITE : CPF_READ;
|
||||||
*size = 0;
|
size = 0;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
grants[i] = cpf_grant_direct(endpt, vec[i].iov_addr, vec[i].iov_size,
|
grant = cpf_grant_direct(endpt, vec[i].iov_addr, vec[i].iov_size,
|
||||||
access);
|
access);
|
||||||
|
|
||||||
if (!GRANT_VALID(grants[i])) {
|
if (!GRANT_VALID(grant)) {
|
||||||
printf("bdev: unable to allocate grant!\n");
|
printf("bdev: unable to allocate grant!\n");
|
||||||
|
|
||||||
for (i--; i >= 0; i--)
|
for (i--; i >= 0; i--)
|
||||||
cpf_revoke(grants[i]);
|
cpf_revoke(gvec[i].iov_grant);
|
||||||
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We keep a separate grants array to prevent local leaks if the driver
|
gvec[i].iov_grant = grant;
|
||||||
* ends up clobbering the grant vector. Future protocol updates should
|
|
||||||
* make the grant for the vector read-only.
|
|
||||||
*/
|
|
||||||
gvec[i].iov_grant = grants[i];
|
|
||||||
gvec[i].iov_size = vec[i].iov_size;
|
gvec[i].iov_size = vec[i].iov_size;
|
||||||
|
|
||||||
assert(*size + vec[i].iov_size > *size);
|
assert((ssize_t) (size + vec[i].iov_size) > size);
|
||||||
|
|
||||||
*size += vec[i].iov_size;
|
size += vec[i].iov_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
grant = cpf_grant_direct(endpt, (vir_bytes) gvec, sizeof(gvec[0]) * count,
|
grant = cpf_grant_direct(endpt, (vir_bytes) gvec, sizeof(gvec[0]) * count,
|
||||||
CPF_READ | CPF_WRITE);
|
CPF_READ);
|
||||||
|
|
||||||
if (!GRANT_VALID(grant)) {
|
if (!GRANT_VALID(grant)) {
|
||||||
printf("bdev: unable to allocate grant!\n");
|
printf("bdev: unable to allocate grant!\n");
|
||||||
|
|
||||||
for (i = count - 1; i >= 0; i--)
|
for (i = count - 1; i >= 0; i--)
|
||||||
cpf_revoke(grants[i]);
|
cpf_revoke(gvec[i].iov_grant);
|
||||||
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(m, 0, sizeof(*m));
|
||||||
m->m_type = req;
|
m->m_type = req;
|
||||||
m->DEVICE = minor(dev);
|
m->BDEV_MINOR = minor(dev);
|
||||||
m->POSITION = ex64lo(pos);
|
m->BDEV_POS_LO = ex64lo(pos);
|
||||||
m->HIGHPOS = ex64hi(pos);
|
m->BDEV_POS_HI = ex64hi(pos);
|
||||||
m->COUNT = count;
|
m->BDEV_COUNT = count;
|
||||||
m->IO_GRANT = (void *) grant;
|
m->BDEV_GRANT = grant;
|
||||||
|
m->BDEV_FLAGS = flags;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bdev_vrdwt_cleanup(message *m, cp_grant_id_t *grants)
|
static void bdev_vrdwt_cleanup(message *m, iovec_s_t *gvec)
|
||||||
{
|
{
|
||||||
/* Clean up a vectored read/write request.
|
/* Clean up a vectored read/write request.
|
||||||
*/
|
*/
|
||||||
cp_grant_id_t grant;
|
cp_grant_id_t grant;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
grant = (cp_grant_id_t) m->IO_GRANT;
|
grant = m->BDEV_GRANT;
|
||||||
|
|
||||||
cpf_revoke(grant);
|
cpf_revoke(grant);
|
||||||
|
|
||||||
for (i = m->COUNT - 1; i >= 0; i--)
|
for (i = m->BDEV_COUNT - 1; i >= 0; i--)
|
||||||
cpf_revoke(grants[i]);
|
cpf_revoke(gvec[i].iov_grant);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bdev_vrdwt_adjust(dev_t dev, iovec_s_t *gvec, int count,
|
static ssize_t bdev_vrdwt(int req, dev_t dev, u64_t pos, iovec_t *vec,
|
||||||
vir_bytes *size)
|
int count, int flags)
|
||||||
{
|
{
|
||||||
/* Adjust the number of bytes transferred, by subtracting from it the number of
|
/* Perform a read or write call using a vector of buffers.
|
||||||
* bytes *not* transferred according to the result vector.
|
|
||||||
*/
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
if (*size < gvec[i].iov_size) {
|
|
||||||
printf("bdev: driver (%d) returned bad vector\n",
|
|
||||||
bdev_driver_get(dev));
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*size -= gvec[i].iov_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bdev_vrdwt(int req, dev_t dev, u64_t pos, iovec_t *vec, int count,
|
|
||||||
int flags, vir_bytes *size)
|
|
||||||
{
|
|
||||||
/* Perform a read or write call using a vector of buffer.
|
|
||||||
*/
|
*/
|
||||||
iovec_s_t gvec[NR_IOREQS];
|
iovec_s_t gvec[NR_IOREQS];
|
||||||
cp_grant_id_t grants[NR_IOREQS];
|
|
||||||
message m;
|
message m;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = bdev_vrdwt_setup(req, dev, pos, vec, count, flags, &m, gvec,
|
if ((r = bdev_vrdwt_setup(req, dev, pos, vec, count, flags, &m, gvec)) != OK)
|
||||||
grants, size)) != OK) {
|
|
||||||
*size = 0;
|
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
|
|
||||||
r = bdev_sendrec(dev, &m);
|
r = bdev_sendrec(dev, &m);
|
||||||
|
|
||||||
bdev_vrdwt_cleanup(&m, grants);
|
bdev_vrdwt_cleanup(&m, gvec);
|
||||||
|
|
||||||
/* Also return the number of bytes transferred. */
|
|
||||||
if (!bdev_vrdwt_adjust(dev, gvec, count, size)) {
|
|
||||||
*size = 0;
|
|
||||||
r = EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdev_read(dev_t dev, u64_t pos, char *buf, int count, int flags)
|
ssize_t bdev_read(dev_t dev, u64_t pos, char *buf, size_t count, int flags)
|
||||||
{
|
{
|
||||||
/* Perform a read call into a single buffer.
|
/* Perform a read call into a single buffer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return bdev_rdwt(DEV_READ_S, dev, pos, buf, count, flags);
|
return bdev_rdwt(BDEV_READ, dev, pos, buf, count, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdev_write(dev_t dev, u64_t pos, char *buf, int count, int flags)
|
ssize_t bdev_write(dev_t dev, u64_t pos, char *buf, size_t count, int flags)
|
||||||
{
|
{
|
||||||
/* Perform a write call from a single buffer.
|
/* Perform a write call from a single buffer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return bdev_rdwt(DEV_WRITE_S, dev, pos, buf, count, flags);
|
return bdev_rdwt(BDEV_WRITE, dev, pos, buf, count, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdev_gather(dev_t dev, u64_t pos, iovec_t *vec, int count, int flags,
|
ssize_t bdev_gather(dev_t dev, u64_t pos, iovec_t *vec, int count, int flags)
|
||||||
vir_bytes *size)
|
|
||||||
{
|
{
|
||||||
/* Perform a read call into a vector of buffers.
|
/* Perform a read call into a vector of buffers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return bdev_vrdwt(DEV_GATHER_S, dev, pos, vec, count, flags, size);
|
return bdev_vrdwt(BDEV_GATHER, dev, pos, vec, count, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdev_scatter(dev_t dev, u64_t pos, iovec_t *vec, int count, int flags,
|
ssize_t bdev_scatter(dev_t dev, u64_t pos, iovec_t *vec, int count, int flags)
|
||||||
vir_bytes *size)
|
|
||||||
{
|
{
|
||||||
/* Perform a write call from a vector of buffers.
|
/* Perform a write call from a vector of buffers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return bdev_vrdwt(DEV_SCATTER_S, dev, pos, vec, count, flags, size);
|
return bdev_vrdwt(BDEV_SCATTER, dev, pos, vec, count, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bdev_ioctl_setup(dev_t dev, int request, void *buf, message *m)
|
static int bdev_ioctl_setup(dev_t dev, int request, void *buf, message *m)
|
||||||
|
@ -311,10 +277,11 @@ static int bdev_ioctl_setup(dev_t dev, int request, void *buf, message *m)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
m->m_type = DEV_IOCTL_S;
|
memset(m, 0, sizeof(*m));
|
||||||
m->DEVICE = minor(dev);
|
m->m_type = BDEV_IOCTL;
|
||||||
m->REQUEST = request;
|
m->BDEV_MINOR = minor(dev);
|
||||||
m->IO_GRANT = (void *) grant;
|
m->BDEV_REQUEST = request;
|
||||||
|
m->BDEV_GRANT = grant;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -323,11 +290,8 @@ static void bdev_ioctl_cleanup(message *m)
|
||||||
{
|
{
|
||||||
/* Clean up an I/O control request.
|
/* Clean up an I/O control request.
|
||||||
*/
|
*/
|
||||||
cp_grant_id_t grant;
|
|
||||||
|
|
||||||
grant = (cp_grant_id_t) m->IO_GRANT;
|
cpf_revoke(m->BDEV_GRANT);
|
||||||
|
|
||||||
cpf_revoke(grant);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdev_ioctl(dev_t dev, int request, void *buf)
|
int bdev_ioctl(dev_t dev, int request, void *buf)
|
||||||
|
|
|
@ -12,7 +12,8 @@ static void bdev_cancel(dev_t dev)
|
||||||
* permanently unusable, and clean up any associated calls and resources.
|
* permanently unusable, and clean up any associated calls and resources.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
printf("bdev: driver for major %d crashed\n", major(dev));
|
printf("bdev: driver for major %d (endpoint %d) crashed\n",
|
||||||
|
major(dev), bdev_driver_get(dev));
|
||||||
|
|
||||||
/* Mark the driver as unusable. */
|
/* Mark the driver as unusable. */
|
||||||
bdev_driver_clear(dev);
|
bdev_driver_clear(dev);
|
||||||
|
@ -27,18 +28,13 @@ void bdev_update(dev_t dev, endpoint_t endpt)
|
||||||
old_endpt = bdev_driver_get(dev);
|
old_endpt = bdev_driver_get(dev);
|
||||||
|
|
||||||
bdev_driver_set(dev, endpt);
|
bdev_driver_set(dev, endpt);
|
||||||
|
|
||||||
/* If updating the driver causes an endpoint change, the driver has
|
|
||||||
* restarted.
|
|
||||||
*/
|
|
||||||
if (old_endpt != NONE && old_endpt != endpt)
|
|
||||||
bdev_cancel(dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdev_sendrec(dev_t dev, const message *m_orig)
|
int bdev_sendrec(dev_t dev, const message *m_orig)
|
||||||
{
|
{
|
||||||
/* Send a request to the given device, and wait for the reply.
|
/* Send a request to the given device, and wait for the reply.
|
||||||
*/
|
*/
|
||||||
|
static long id = 0;
|
||||||
endpoint_t endpt;
|
endpoint_t endpt;
|
||||||
message m;
|
message m;
|
||||||
int r;
|
int r;
|
||||||
|
@ -49,7 +45,7 @@ int bdev_sendrec(dev_t dev, const message *m_orig)
|
||||||
|
|
||||||
/* Send the request and block until we receive a reply. */
|
/* Send the request and block until we receive a reply. */
|
||||||
m = *m_orig;
|
m = *m_orig;
|
||||||
m.USER_ENDPT = (endpoint_t) -1; /* synchronous request; no ID */
|
m.BDEV_ID = ++id;
|
||||||
|
|
||||||
r = sendrec(endpt, &m);
|
r = sendrec(endpt, &m);
|
||||||
|
|
||||||
|
@ -65,25 +61,25 @@ int bdev_sendrec(dev_t dev, const message *m_orig)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.m_type != TASK_REPLY) {
|
if (m.m_type != BDEV_REPLY) {
|
||||||
printf("bdev: driver (%d) sent weird response (%d)\n",
|
printf("bdev: driver (%d) sent weird response (%d)\n",
|
||||||
endpt, m.m_type);
|
endpt, m.m_type);
|
||||||
return EIO;
|
return EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ERESTART signifies a driver restart. Again, we do not support this yet. */
|
/* ERESTART signifies a driver restart. Again, we do not support this yet. */
|
||||||
if (m.REP_STATUS == ERESTART) {
|
if (m.BDEV_STATUS == ERESTART) {
|
||||||
bdev_cancel(dev);
|
bdev_cancel(dev);
|
||||||
|
|
||||||
return EDEADSRCDST;
|
return EDEADSRCDST;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.REP_ENDPT != (endpoint_t) -1) {
|
if (m.BDEV_ID != id) {
|
||||||
printf("bdev: driver (%d) sent invalid response (%d)\n",
|
printf("bdev: driver (%d) sent invalid response (%ld)\n",
|
||||||
endpt, m.REP_ENDPT);
|
endpt, m.BDEV_ID);
|
||||||
return EIO;
|
return EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We got a reply to our request. */
|
/* Return the result of our request. */
|
||||||
return m.REP_STATUS;
|
return m.BDEV_STATUS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Makefile for libdriver
|
# Makefile for libblockdriver
|
||||||
.include <bsd.own.mk>
|
.include <bsd.own.mk>
|
||||||
|
|
||||||
LIB= driver
|
LIB= blockdriver
|
||||||
|
|
||||||
SRCS= driver.c drvlib.c driver_st.c driver_mt.c mq.c event.c
|
SRCS= driver.c drvlib.c driver_st.c driver_mt.c mq.c event.c
|
||||||
|
|
382
lib/libblockdriver/driver.c
Normal file
382
lib/libblockdriver/driver.c
Normal file
|
@ -0,0 +1,382 @@
|
||||||
|
/* This file contains the device independent block driver interface.
|
||||||
|
*
|
||||||
|
* Block drivers support the following requests. Message format m10 is used.
|
||||||
|
* Field names are prefixed with BDEV_. Separate field names are used for the
|
||||||
|
* "access" and "request" fields.
|
||||||
|
*
|
||||||
|
* m_type MINOR COUNT GRANT FLAGS ID POS_LO POS_HI
|
||||||
|
* +--------------+--------+----------+-------+-------+------+------+------+
|
||||||
|
* | BDEV_OPEN | minor | access | | | id | | |
|
||||||
|
* |--------------+--------+----------+-------+-------+------+------+------|
|
||||||
|
* | BDEV_CLOSE | minor | | | | id | | |
|
||||||
|
* |--------------+--------+----------+-------+-------+------+------+------|
|
||||||
|
* | BDEV_READ | minor | bytes | grant | flags | id | position |
|
||||||
|
* |--------------+--------+----------+-------+-------+------+------+------|
|
||||||
|
* | BDEV_WRITE | minor | bytes | grant | flags | id | position |
|
||||||
|
* |--------------+--------+----------+-------+-------+------+------+------|
|
||||||
|
* | BDEV_GATHER | minor | elements | grant | flags | id | position |
|
||||||
|
* |--------------+--------+----------+-------+-------+------+------+------|
|
||||||
|
* | BDEV_SCATTER | minor | elements | grant | flags | id | position |
|
||||||
|
* |--------------+--------+----------+-------+-------+------+------+------|
|
||||||
|
* | BDEV_IOCTL | minor | request | grant | flags | id | | |
|
||||||
|
* -------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* The following reply message is used for all requests.
|
||||||
|
*
|
||||||
|
* m_type STATUS ID
|
||||||
|
* +--------------+--------+----------+-------+-------+------+------+------+
|
||||||
|
* | BDEV_REPLY | status | | | | id | | |
|
||||||
|
* -------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Changes:
|
||||||
|
* Oct 16, 2011 split character and block protocol (D.C. van Moolenbroek)
|
||||||
|
* Aug 27, 2011 move common functions into driver.c (A. Welzel)
|
||||||
|
* Jul 25, 2005 added SYS_SIG type for signals (Jorrit N. Herder)
|
||||||
|
* Sep 15, 2004 added SYN_ALARM type for timeouts (Jorrit N. Herder)
|
||||||
|
* Jul 23, 2004 removed kernel dependencies (Jorrit N. Herder)
|
||||||
|
* Apr 02, 1992 constructed from AT wini and floppy driver (Kees J. Bot)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <minix/drivers.h>
|
||||||
|
#include <minix/blockdriver.h>
|
||||||
|
#include <minix/ds.h>
|
||||||
|
#include <sys/ioc_disk.h>
|
||||||
|
|
||||||
|
#include "driver.h"
|
||||||
|
#include "mq.h"
|
||||||
|
|
||||||
|
/* Management data for opened devices. */
|
||||||
|
PRIVATE int open_devs[MAX_NR_OPEN_DEVICES];
|
||||||
|
PRIVATE int next_open_devs_slot = 0;
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* clear_open_devs *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE void clear_open_devs(void)
|
||||||
|
{
|
||||||
|
/* Reset the set of previously opened minor devices. */
|
||||||
|
next_open_devs_slot = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* is_open_dev *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int is_open_dev(int device)
|
||||||
|
{
|
||||||
|
/* Check whether the given minor device has previously been opened. */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < next_open_devs_slot; i++)
|
||||||
|
if (open_devs[i] == device)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* set_open_dev *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE void set_open_dev(int device)
|
||||||
|
{
|
||||||
|
/* Mark the given minor device as having been opened. */
|
||||||
|
|
||||||
|
if (next_open_devs_slot >= MAX_NR_OPEN_DEVICES)
|
||||||
|
panic("out of slots for open devices");
|
||||||
|
|
||||||
|
open_devs[next_open_devs_slot] = device;
|
||||||
|
next_open_devs_slot++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* blockdriver_announce *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC void blockdriver_announce(void)
|
||||||
|
{
|
||||||
|
/* Announce we are up after a fresh start or a restart. */
|
||||||
|
int r;
|
||||||
|
char key[DS_MAX_KEYLEN];
|
||||||
|
char label[DS_MAX_KEYLEN];
|
||||||
|
char *driver_prefix = "drv.blk.";
|
||||||
|
|
||||||
|
/* Callers are allowed to use sendrec to communicate with drivers.
|
||||||
|
* For this reason, there may blocked callers when a driver restarts.
|
||||||
|
* Ask the kernel to unblock them (if any).
|
||||||
|
*/
|
||||||
|
#if USE_STATECTL
|
||||||
|
if ((r = sys_statectl(SYS_STATE_CLEAR_IPC_REFS)) != OK)
|
||||||
|
panic("blockdriver_init: sys_statectl failed: %d", r);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Publish a driver up event. */
|
||||||
|
if ((r = ds_retrieve_label_name(label, getprocnr())) != OK)
|
||||||
|
panic("blockdriver_init: unable to get own label: %d", r);
|
||||||
|
|
||||||
|
snprintf(key, DS_MAX_KEYLEN, "%s%s", driver_prefix, label);
|
||||||
|
if ((r = ds_publish_u32(key, DS_DRIVER_UP, DSF_OVERWRITE)) != OK)
|
||||||
|
panic("blockdriver_init: unable to publish driver up event: %d", r);
|
||||||
|
|
||||||
|
/* Expect an open for any device before serving regular driver requests. */
|
||||||
|
clear_open_devs();
|
||||||
|
|
||||||
|
/* Initialize or reset the message queue. */
|
||||||
|
mq_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* blockdriver_reply *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC void blockdriver_reply(message *m_ptr, int ipc_status, int reply)
|
||||||
|
{
|
||||||
|
/* Reply to a block request sent to the driver. */
|
||||||
|
endpoint_t caller_e;
|
||||||
|
long id;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (reply == EDONTREPLY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
caller_e = m_ptr->m_source;
|
||||||
|
id = m_ptr->BDEV_ID;
|
||||||
|
|
||||||
|
memset(m_ptr, 0, sizeof(*m_ptr));
|
||||||
|
|
||||||
|
m_ptr->m_type = BDEV_REPLY;
|
||||||
|
m_ptr->BDEV_STATUS = reply;
|
||||||
|
m_ptr->BDEV_ID = id;
|
||||||
|
|
||||||
|
/* If we would block sending the message, send it asynchronously. */
|
||||||
|
if (IPC_STATUS_CALL(ipc_status) == SENDREC)
|
||||||
|
r = sendnb(caller_e, m_ptr);
|
||||||
|
else
|
||||||
|
r = asynsend(caller_e, m_ptr);
|
||||||
|
|
||||||
|
if (r != OK)
|
||||||
|
printf("blockdriver_reply: unable to send reply to %d: %d\n",
|
||||||
|
caller_e, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_open *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int do_open(struct blockdriver *bdp, message *mp)
|
||||||
|
{
|
||||||
|
/* Open a minor device. */
|
||||||
|
|
||||||
|
return (*bdp->bdr_open)(mp->BDEV_MINOR, mp->BDEV_ACCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_close *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int do_close(struct blockdriver *bdp, message *mp)
|
||||||
|
{
|
||||||
|
/* Close a minor device. */
|
||||||
|
|
||||||
|
return (*bdp->bdr_close)(mp->BDEV_MINOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_rdwt *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int do_rdwt(struct blockdriver *bdp, message *mp)
|
||||||
|
{
|
||||||
|
/* Carry out a single read or write request. */
|
||||||
|
iovec_t iovec1;
|
||||||
|
u64_t position;
|
||||||
|
int do_write;
|
||||||
|
ssize_t r;
|
||||||
|
|
||||||
|
/* Disk address? Address and length of the user buffer? */
|
||||||
|
if (mp->BDEV_COUNT < 0) return EINVAL;
|
||||||
|
|
||||||
|
/* Create a one element scatter/gather vector for the buffer. */
|
||||||
|
iovec1.iov_addr = mp->BDEV_GRANT;
|
||||||
|
iovec1.iov_size = mp->BDEV_COUNT;
|
||||||
|
|
||||||
|
/* Transfer bytes from/to the device. */
|
||||||
|
do_write = (mp->m_type == BDEV_WRITE);
|
||||||
|
position = make64(mp->BDEV_POS_LO, mp->BDEV_POS_HI);
|
||||||
|
|
||||||
|
r = (*bdp->bdr_transfer)(mp->BDEV_MINOR, do_write, position, mp->m_source,
|
||||||
|
&iovec1, 1, mp->BDEV_FLAGS);
|
||||||
|
|
||||||
|
/* Return the number of bytes transferred or an error code. */
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_vrdwt *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int do_vrdwt(struct blockdriver *bdp, message *mp)
|
||||||
|
{
|
||||||
|
/* Carry out an device read or write to/from a vector of buffers. */
|
||||||
|
iovec_t iovec[NR_IOREQS];
|
||||||
|
unsigned nr_req;
|
||||||
|
u64_t position;
|
||||||
|
int i, do_write;
|
||||||
|
ssize_t r, size;
|
||||||
|
|
||||||
|
/* Copy the vector from the caller to kernel space. */
|
||||||
|
nr_req = mp->BDEV_COUNT; /* Length of I/O vector */
|
||||||
|
if (nr_req > NR_IOREQS) nr_req = NR_IOREQS;
|
||||||
|
|
||||||
|
if (OK != sys_safecopyfrom(mp->m_source, (vir_bytes) mp->BDEV_GRANT,
|
||||||
|
0, (vir_bytes) iovec, nr_req * sizeof(iovec[0]), D)) {
|
||||||
|
printf("blockdriver: bad I/O vector by: %d\n", mp->m_source);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for overflow condition. */
|
||||||
|
for (i = size = 0; i < nr_req; i++) {
|
||||||
|
if ((ssize_t) (size + iovec[i].iov_size) < size) return EINVAL;
|
||||||
|
size += iovec[i].iov_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Transfer bytes from/to the device. */
|
||||||
|
do_write = (mp->m_type == BDEV_SCATTER);
|
||||||
|
position = make64(mp->BDEV_POS_LO, mp->BDEV_POS_HI);
|
||||||
|
|
||||||
|
r = (*bdp->bdr_transfer)(mp->BDEV_MINOR, do_write, position, mp->m_source,
|
||||||
|
iovec, nr_req, mp->BDEV_FLAGS);
|
||||||
|
|
||||||
|
/* Return the number of bytes transferred or an error code. */
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_ioctl *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int do_ioctl(struct blockdriver *bdp, message *mp)
|
||||||
|
{
|
||||||
|
/* Carry out an I/O control request. For now, we handle setting/getting
|
||||||
|
* partitions here, and let the driver handle any other requests.
|
||||||
|
*/
|
||||||
|
struct device *dv;
|
||||||
|
struct partition entry;
|
||||||
|
unsigned int request;
|
||||||
|
cp_grant_id_t grant;
|
||||||
|
dev_t minor;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
minor = mp->BDEV_MINOR;
|
||||||
|
request = mp->BDEV_REQUEST;
|
||||||
|
grant = mp->BDEV_GRANT;
|
||||||
|
|
||||||
|
switch (request) {
|
||||||
|
case DIOCSETP:
|
||||||
|
/* Copy just this one partition table entry. */
|
||||||
|
r = sys_safecopyfrom(mp->m_source, grant, 0, (vir_bytes) &entry,
|
||||||
|
sizeof(entry), D);
|
||||||
|
if (r != OK)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if ((dv = (*bdp->bdr_part)(minor)) == NULL)
|
||||||
|
return ENXIO;
|
||||||
|
dv->dv_base = entry.base;
|
||||||
|
dv->dv_size = entry.size;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DIOCGETP:
|
||||||
|
/* Return a partition table entry and the geometry of the drive. */
|
||||||
|
if ((dv = (*bdp->bdr_part)(minor)) == NULL)
|
||||||
|
return ENXIO;
|
||||||
|
entry.base = dv->dv_base;
|
||||||
|
entry.size = dv->dv_size;
|
||||||
|
if (bdp->bdr_geometry) {
|
||||||
|
(*bdp->bdr_geometry)(minor, &entry);
|
||||||
|
} else {
|
||||||
|
/* The driver doesn't care -- make up fake geometry. */
|
||||||
|
entry.cylinders = div64u(entry.size, SECTOR_SIZE);
|
||||||
|
entry.heads = 64;
|
||||||
|
entry.sectors = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sys_safecopyto(mp->m_source, grant, 0, (vir_bytes) &entry,
|
||||||
|
sizeof(entry), D);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (bdp->bdr_ioctl)
|
||||||
|
r = (*bdp->bdr_ioctl)(minor, request, mp->m_source, grant);
|
||||||
|
else
|
||||||
|
r = EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* blockdriver_handle_notify *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC void blockdriver_handle_notify(struct blockdriver *bdp, message *m_ptr)
|
||||||
|
{
|
||||||
|
/* Take care of the notifications (interrupt and clock messages) by calling
|
||||||
|
* the appropiate callback functions. Never send a reply.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Call the appropriate function for this notification. */
|
||||||
|
switch (_ENDPOINT_P(m_ptr->m_source)) {
|
||||||
|
case HARDWARE:
|
||||||
|
if (bdp->bdr_intr)
|
||||||
|
(*bdp->bdr_intr)(m_ptr->NOTIFY_ARG);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLOCK:
|
||||||
|
if (bdp->bdr_alarm)
|
||||||
|
(*bdp->bdr_alarm)(m_ptr->NOTIFY_TIMESTAMP);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (bdp->bdr_other)
|
||||||
|
(void) (*bdp->bdr_other)(m_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* blockdriver_handle_request *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int blockdriver_handle_request(struct blockdriver *bdp, message *m_ptr)
|
||||||
|
{
|
||||||
|
/* Call the appropiate driver function, based on the type of request. Return
|
||||||
|
* the result code that is to be sent back to the caller, or EDONTREPLY if no
|
||||||
|
* reply is to be sent.
|
||||||
|
*/
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* We might get spurious requests if the driver has been restarted. Deny any
|
||||||
|
* requests on devices that have not previously been opened, signaling the
|
||||||
|
* caller that something went wrong.
|
||||||
|
*/
|
||||||
|
if (IS_BDEV_RQ(m_ptr->m_type) && !is_open_dev(m_ptr->BDEV_MINOR)) {
|
||||||
|
/* Reply ERESTART to spurious requests for unopened devices. */
|
||||||
|
if (m_ptr->m_type != BDEV_OPEN)
|
||||||
|
return ERESTART;
|
||||||
|
|
||||||
|
/* Mark the device as opened otherwise. */
|
||||||
|
set_open_dev(m_ptr->BDEV_MINOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call the appropriate function(s) for this request. */
|
||||||
|
switch (m_ptr->m_type) {
|
||||||
|
case BDEV_OPEN: r = do_open(bdp, m_ptr); break;
|
||||||
|
case BDEV_CLOSE: r = do_close(bdp, m_ptr); break;
|
||||||
|
case BDEV_READ:
|
||||||
|
case BDEV_WRITE: r = do_rdwt(bdp, m_ptr); break;
|
||||||
|
case BDEV_GATHER:
|
||||||
|
case BDEV_SCATTER: r = do_vrdwt(bdp, m_ptr); break;
|
||||||
|
case BDEV_IOCTL: r = do_ioctl(bdp, m_ptr); break;
|
||||||
|
default:
|
||||||
|
if (bdp->bdr_other)
|
||||||
|
r = bdp->bdr_other(m_ptr);
|
||||||
|
else
|
||||||
|
r = EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let the driver perform any cleanup. */
|
||||||
|
if (bdp->bdr_cleanup != NULL)
|
||||||
|
(*bdp->bdr_cleanup)();
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
11
lib/libblockdriver/driver.h
Normal file
11
lib/libblockdriver/driver.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef _BLOCKDRIVER_DRIVER_H
|
||||||
|
#define _BLOCKDRIVER_DRIVER_H
|
||||||
|
|
||||||
|
_PROTOTYPE( void blockdriver_handle_notify, (struct blockdriver *bdp,
|
||||||
|
message *m_ptr) );
|
||||||
|
_PROTOTYPE( int blockdriver_handle_request, (struct blockdriver *bdp,
|
||||||
|
message *m_ptr) );
|
||||||
|
_PROTOTYPE( void blockdriver_reply, (message *m_ptr, int ipc_status,
|
||||||
|
int reply) );
|
||||||
|
|
||||||
|
#endif /* _BLOCKDRIVER_DRIVER_H */
|
|
@ -1,17 +1,17 @@
|
||||||
/* This file contains the multithreaded device independent driver interface.
|
/* This file contains the multithreaded driver interface.
|
||||||
*
|
*
|
||||||
* Changes:
|
* Changes:
|
||||||
* Aug 27, 2011 created (A. Welzel)
|
* Aug 27, 2011 created (A. Welzel)
|
||||||
*
|
*
|
||||||
* The entry points into this file are:
|
* The entry points into this file are:
|
||||||
* driver_mt_task: the main message loop of the driver
|
* blockdriver_mt_task: the main message loop of the driver
|
||||||
* driver_mt_terminate: break out of the main message loop
|
* blockdriver_mt_terminate: break out of the main message loop
|
||||||
* driver_mt_sleep: put the current thread to sleep
|
* blockdriver_mt_sleep: put the current thread to sleep
|
||||||
* driver_mt_wakeup: wake up a sleeping thread
|
* blockdriver_mt_wakeup: wake up a sleeping thread
|
||||||
* driver_mt_stop: put up the current thread for termination
|
* blockdriver_mt_stop: put up the current thread for termination
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/driver_mt.h>
|
#include <minix/blockdriver_mt.h>
|
||||||
#include <minix/mthread.h>
|
#include <minix/mthread.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
@ -35,9 +35,8 @@ typedef struct {
|
||||||
event_t sleep_event;
|
event_t sleep_event;
|
||||||
} worker_t;
|
} worker_t;
|
||||||
|
|
||||||
PRIVATE struct driver *driver_cb;
|
PRIVATE struct blockdriver *bdtab;
|
||||||
PRIVATE int driver_mt_type;
|
PRIVATE int running = FALSE;
|
||||||
PRIVATE int driver_mt_running = FALSE;
|
|
||||||
|
|
||||||
PRIVATE mthread_key_t worker_key;
|
PRIVATE mthread_key_t worker_key;
|
||||||
|
|
||||||
|
@ -57,10 +56,10 @@ PRIVATE void enqueue(worker_t *wp, const message *m_src, int ipc_status)
|
||||||
|
|
||||||
assert(wp->state == STATE_RUNNING || wp->state == STATE_STOPPING);
|
assert(wp->state == STATE_RUNNING || wp->state == STATE_STOPPING);
|
||||||
|
|
||||||
if (!driver_mq_enqueue(wp->id, m_src, ipc_status))
|
if (!mq_enqueue(wp->id, m_src, ipc_status))
|
||||||
panic("driver_mt: enqueue failed (message queue full)");
|
panic("blockdriver_mt: enqueue failed (message queue full)");
|
||||||
|
|
||||||
driver_event_fire(&wp->queue_event);
|
event_fire(&wp->queue_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -73,7 +72,7 @@ PRIVATE int try_dequeue(worker_t *wp, message *m_dst, int *ipc_status)
|
||||||
* called from a worker thread. Does not block.
|
* called from a worker thread. Does not block.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return driver_mq_dequeue(wp->id, m_dst, ipc_status);
|
return mq_dequeue(wp->id, m_dst, ipc_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -86,7 +85,7 @@ PRIVATE void dequeue(worker_t *wp, message *m_dst, int *ipc_status)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while (!try_dequeue(wp, m_dst, ipc_status))
|
while (!try_dequeue(wp, m_dst, ipc_status))
|
||||||
driver_event_wait(&wp->queue_event);
|
event_wait(&wp->queue_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -107,9 +106,9 @@ PRIVATE void *worker_thread(void *param)
|
||||||
assert(wp != NULL);
|
assert(wp != NULL);
|
||||||
|
|
||||||
if (mthread_setspecific(worker_key, wp))
|
if (mthread_setspecific(worker_key, wp))
|
||||||
panic("driver_mt: could not save local thread pointer");
|
panic("blockdriver_mt: could not save local thread pointer");
|
||||||
|
|
||||||
while (driver_mt_running) {
|
while (running) {
|
||||||
/* See if a new message is available right away. */
|
/* See if a new message is available right away. */
|
||||||
if (!try_dequeue(wp, &m, &ipc_status)) {
|
if (!try_dequeue(wp, &m, &ipc_status)) {
|
||||||
/* If not, and this thread should be stopped, stop now. */
|
/* If not, and this thread should be stopped, stop now. */
|
||||||
|
@ -119,7 +118,7 @@ PRIVATE void *worker_thread(void *param)
|
||||||
/* Otherwise, block waiting for a new message. */
|
/* Otherwise, block waiting for a new message. */
|
||||||
dequeue(wp, &m, &ipc_status);
|
dequeue(wp, &m, &ipc_status);
|
||||||
|
|
||||||
if (!driver_mt_running)
|
if (!running)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,14 +126,14 @@ PRIVATE void *worker_thread(void *param)
|
||||||
wp->state = STATE_RUNNING;
|
wp->state = STATE_RUNNING;
|
||||||
|
|
||||||
/* Handle the request, and send a reply. */
|
/* Handle the request, and send a reply. */
|
||||||
r = driver_handle_request(driver_cb, &m);
|
r = blockdriver_handle_request(bdtab, &m);
|
||||||
|
|
||||||
driver_reply(driver_mt_type, &m, ipc_status, r);
|
blockdriver_reply(&m, ipc_status, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up and terminate this thread. */
|
/* Clean up and terminate this thread. */
|
||||||
if (mthread_setspecific(worker_key, NULL))
|
if (mthread_setspecific(worker_key, NULL))
|
||||||
panic("driver_mt: could not delete local thread pointer");
|
panic("blockdriver_mt: could not delete local thread pointer");
|
||||||
|
|
||||||
wp->state = STATE_EXITED;
|
wp->state = STATE_EXITED;
|
||||||
|
|
||||||
|
@ -156,13 +155,13 @@ PRIVATE void master_create_worker(worker_t *wp, thread_id_t id)
|
||||||
wp->state = STATE_RUNNING;
|
wp->state = STATE_RUNNING;
|
||||||
|
|
||||||
/* Initialize synchronization primitives. */
|
/* Initialize synchronization primitives. */
|
||||||
driver_event_init(&wp->queue_event);
|
event_init(&wp->queue_event);
|
||||||
driver_event_init(&wp->sleep_event);
|
event_init(&wp->sleep_event);
|
||||||
|
|
||||||
r = mthread_create(&wp->mthread, NULL /*attr*/, worker_thread, (void *) wp);
|
r = mthread_create(&wp->mthread, NULL /*attr*/, worker_thread, (void *) wp);
|
||||||
|
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
panic("driver_mt: could not start thread %d (%d)", id, r);
|
panic("blockdriver_mt: could not start thread %d (%d)", id, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -177,15 +176,15 @@ PRIVATE void master_destroy_worker(worker_t *wp)
|
||||||
|
|
||||||
assert(wp != NULL);
|
assert(wp != NULL);
|
||||||
assert(wp->state == STATE_EXITED);
|
assert(wp->state == STATE_EXITED);
|
||||||
assert(!driver_mq_dequeue(wp->id, &m, &ipc_status));
|
assert(!mq_dequeue(wp->id, &m, &ipc_status));
|
||||||
|
|
||||||
/* Join the thread. */
|
/* Join the thread. */
|
||||||
if (mthread_join(wp->mthread, NULL))
|
if (mthread_join(wp->mthread, NULL))
|
||||||
panic("driver_mt: could not join thread %d", wp->id);
|
panic("blockdriver_mt: could not join thread %d", wp->id);
|
||||||
|
|
||||||
/* Destroy resources. */
|
/* Destroy resources. */
|
||||||
driver_event_destroy(&wp->sleep_event);
|
event_destroy(&wp->sleep_event);
|
||||||
driver_event_destroy(&wp->queue_event);
|
event_destroy(&wp->queue_event);
|
||||||
|
|
||||||
wp->state = STATE_DEAD;
|
wp->state = STATE_DEAD;
|
||||||
}
|
}
|
||||||
|
@ -218,26 +217,24 @@ PRIVATE void master_handle_request(message *m_ptr, int ipc_status)
|
||||||
worker_t *wp;
|
worker_t *wp;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* If this is not a request that has a minor device associated with it, we
|
/* If this is not a block driver request, we cannot get the minor device
|
||||||
* can not tell which thread should process it either. In that case, the
|
* associated with it, and thus we can not tell which thread should process
|
||||||
* master thread has to handle it instead.
|
* it either. In that case, the master thread has to handle it instead.
|
||||||
*/
|
*/
|
||||||
if (!IS_DEV_MINOR_RQ(m_ptr->m_type)) {
|
if (!IS_BDEV_RQ(m_ptr->m_type)) {
|
||||||
if (driver_cb->dr_other)
|
/* Process as 'other' message. */
|
||||||
r = (*driver_cb->dr_other)(driver_cb, m_ptr);
|
r = blockdriver_handle_request(bdtab, m_ptr);
|
||||||
else
|
|
||||||
r = EINVAL;
|
|
||||||
|
|
||||||
driver_reply(driver_mt_type, m_ptr, ipc_status, r);
|
blockdriver_reply(m_ptr, ipc_status, r);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Query the thread ID. Upon failure, send the error code to the caller. */
|
/* Query the thread ID. Upon failure, send the error code to the caller. */
|
||||||
r = driver_cb->dr_thread(m_ptr->DEVICE, &thread_id);
|
r = (*bdtab->bdr_thread)(m_ptr->DEVICE, &thread_id);
|
||||||
|
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
driver_reply(driver_mt_type, m_ptr, ipc_status, r);
|
blockdriver_reply(m_ptr, ipc_status, r);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -259,19 +256,18 @@ PRIVATE void master_handle_request(message *m_ptr, int ipc_status)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* master_init *
|
* master_init *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void master_init(struct driver *dp, int type)
|
PRIVATE void master_init(struct blockdriver *bdp)
|
||||||
{
|
{
|
||||||
/* Initialize the state of the master thread.
|
/* Initialize the state of the master thread.
|
||||||
*/
|
*/
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
assert(dp != NULL);
|
assert(bdp != NULL);
|
||||||
assert(dp->dr_thread != NULL);
|
assert(bdp->bdr_thread != NULL);
|
||||||
|
|
||||||
mthread_init();
|
mthread_init();
|
||||||
|
|
||||||
driver_mt_type = type;
|
bdtab = bdp;
|
||||||
driver_cb = dp;
|
|
||||||
|
|
||||||
for (i = 0; i < DRIVER_MT_MAX_WORKERS; i++)
|
for (i = 0; i < DRIVER_MT_MAX_WORKERS; i++)
|
||||||
worker[i].state = STATE_DEAD;
|
worker[i].state = STATE_DEAD;
|
||||||
|
@ -280,13 +276,13 @@ PRIVATE void master_init(struct driver *dp, int type)
|
||||||
* reference to the worker structure.
|
* reference to the worker structure.
|
||||||
*/
|
*/
|
||||||
if (mthread_key_create(&worker_key, NULL))
|
if (mthread_key_create(&worker_key, NULL))
|
||||||
panic("driver_mt: error initializing worker key");
|
panic("blockdriver_mt: error initializing worker key");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_mt_receive *
|
* blockdriver_mt_receive *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void driver_mt_receive(message *m_ptr, int *ipc_status)
|
PRIVATE void blockdriver_mt_receive(message *m_ptr, int *ipc_status)
|
||||||
{
|
{
|
||||||
/* Receive a message.
|
/* Receive a message.
|
||||||
*/
|
*/
|
||||||
|
@ -295,13 +291,13 @@ PRIVATE void driver_mt_receive(message *m_ptr, int *ipc_status)
|
||||||
r = sef_receive_status(ANY, m_ptr, ipc_status);
|
r = sef_receive_status(ANY, m_ptr, ipc_status);
|
||||||
|
|
||||||
if (r != OK)
|
if (r != OK)
|
||||||
panic("driver_mt: sef_receive_status() returned %d", r);
|
panic("blockdriver_mt: sef_receive_status() returned %d", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_mt_task *
|
* blockdriver_mt_task *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void driver_mt_task(struct driver *driver_p, int driver_type)
|
PUBLIC void blockdriver_mt_task(struct blockdriver *driver_tab)
|
||||||
{
|
{
|
||||||
/* The multithreaded driver task.
|
/* The multithreaded driver task.
|
||||||
*/
|
*/
|
||||||
|
@ -309,20 +305,20 @@ PUBLIC void driver_mt_task(struct driver *driver_p, int driver_type)
|
||||||
message mess;
|
message mess;
|
||||||
|
|
||||||
/* Initialize first if necessary. */
|
/* Initialize first if necessary. */
|
||||||
if (!driver_mt_running) {
|
if (!running) {
|
||||||
master_init(driver_p, driver_type);
|
master_init(driver_tab);
|
||||||
|
|
||||||
driver_mt_running = TRUE;
|
running = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The main message loop. */
|
/* The main message loop. */
|
||||||
while (driver_mt_running) {
|
while (running) {
|
||||||
/* Receive a message. */
|
/* Receive a message. */
|
||||||
driver_mt_receive(&mess, &ipc_status);
|
blockdriver_mt_receive(&mess, &ipc_status);
|
||||||
|
|
||||||
/* Dispatch the message. */
|
/* Dispatch the message. */
|
||||||
if (is_ipc_notify(ipc_status))
|
if (is_ipc_notify(ipc_status))
|
||||||
driver_handle_notify(driver_cb, &mess);
|
blockdriver_handle_notify(bdtab, &mess);
|
||||||
else
|
else
|
||||||
master_handle_request(&mess, ipc_status);
|
master_handle_request(&mess, ipc_status);
|
||||||
|
|
||||||
|
@ -336,20 +332,20 @@ PUBLIC void driver_mt_task(struct driver *driver_p, int driver_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_mt_terminate *
|
* blockdriver_mt_terminate *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void driver_mt_terminate(void)
|
PUBLIC void blockdriver_mt_terminate(void)
|
||||||
{
|
{
|
||||||
/* Instruct libdriver to shut down.
|
/* Instruct libblockdriver to shut down.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
driver_mt_running = FALSE;
|
running = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_mt_sleep *
|
* blockdriver_mt_sleep *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void driver_mt_sleep(void)
|
PUBLIC void blockdriver_mt_sleep(void)
|
||||||
{
|
{
|
||||||
/* Let the current thread sleep until it gets woken up by the master thread.
|
/* Let the current thread sleep until it gets woken up by the master thread.
|
||||||
*/
|
*/
|
||||||
|
@ -358,15 +354,15 @@ PUBLIC void driver_mt_sleep(void)
|
||||||
wp = (worker_t *) mthread_getspecific(worker_key);
|
wp = (worker_t *) mthread_getspecific(worker_key);
|
||||||
|
|
||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
panic("driver_mt: master thread cannot sleep");
|
panic("blockdriver_mt: master thread cannot sleep");
|
||||||
|
|
||||||
driver_event_wait(&wp->sleep_event);
|
event_wait(&wp->sleep_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_mt_wakeup *
|
* blockdriver_mt_wakeup *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void driver_mt_wakeup(thread_id_t id)
|
PUBLIC void blockdriver_mt_wakeup(thread_id_t id)
|
||||||
{
|
{
|
||||||
/* Wake up a sleeping worker thread from the master thread.
|
/* Wake up a sleeping worker thread from the master thread.
|
||||||
*/
|
*/
|
||||||
|
@ -378,13 +374,13 @@ PUBLIC void driver_mt_wakeup(thread_id_t id)
|
||||||
|
|
||||||
assert(wp->state == STATE_RUNNING || wp->state == STATE_STOPPING);
|
assert(wp->state == STATE_RUNNING || wp->state == STATE_STOPPING);
|
||||||
|
|
||||||
driver_event_fire(&wp->sleep_event);
|
event_fire(&wp->sleep_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_mt_stop *
|
* blockdriver_mt_stop *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void driver_mt_stop(void)
|
PUBLIC void blockdriver_mt_stop(void)
|
||||||
{
|
{
|
||||||
/* Put up the current worker thread for termination. Once the current dispatch
|
/* Put up the current worker thread for termination. Once the current dispatch
|
||||||
* call has finished, and there are no more messages in the thread's message
|
* call has finished, and there are no more messages in the thread's message
|
98
lib/libblockdriver/driver_st.c
Normal file
98
lib/libblockdriver/driver_st.c
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/* This file contains the singlethreaded device driver interface.
|
||||||
|
*
|
||||||
|
* Changes:
|
||||||
|
* Aug 27, 2011 extracted from driver.c (A. Welzel)
|
||||||
|
*
|
||||||
|
* The entry points into this file are:
|
||||||
|
* blockdriver_task: the main message loop of the driver
|
||||||
|
* blockdriver_terminate: break out of the main message loop
|
||||||
|
* blockdriver_handle_msg: handle a single received message
|
||||||
|
* blockdriver_receive_mq: message receive interface with message queueing
|
||||||
|
* blockdriver_mq_queue: queue an incoming message for later processing
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <minix/drivers.h>
|
||||||
|
#include <minix/blockdriver.h>
|
||||||
|
|
||||||
|
#include "driver.h"
|
||||||
|
#include "mq.h"
|
||||||
|
|
||||||
|
PRIVATE int running;
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* blockdriver_receive_mq *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int blockdriver_receive_mq(message *m_ptr, int *status_ptr)
|
||||||
|
{
|
||||||
|
/* receive() interface for drivers with message queueing. */
|
||||||
|
|
||||||
|
/* Any queued messages? */
|
||||||
|
if (mq_dequeue(MQ_SINGLE, m_ptr, status_ptr))
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
/* Fall back to standard receive() interface otherwise. */
|
||||||
|
return driver_receive(ANY, m_ptr, status_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* blockdriver_terminate *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC void blockdriver_terminate(void)
|
||||||
|
{
|
||||||
|
/* Break out of the main driver loop after finishing the current request. */
|
||||||
|
|
||||||
|
running = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* blockdriver_task *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC void blockdriver_task(struct blockdriver *bdp)
|
||||||
|
{
|
||||||
|
/* Main program of any block device driver task. */
|
||||||
|
int r, ipc_status;
|
||||||
|
message mess;
|
||||||
|
|
||||||
|
running = TRUE;
|
||||||
|
|
||||||
|
/* Here is the main loop of the disk task. It waits for a message, carries
|
||||||
|
* it out, and sends a reply.
|
||||||
|
*/
|
||||||
|
while (running) {
|
||||||
|
if ((r = blockdriver_receive_mq(&mess, &ipc_status)) != OK)
|
||||||
|
panic("blockdriver_receive_mq failed: %d", r);
|
||||||
|
|
||||||
|
blockdriver_process(bdp, &mess, ipc_status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* blockdriver_process *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC void blockdriver_process(struct blockdriver *bdp, message *m_ptr,
|
||||||
|
int ipc_status)
|
||||||
|
{
|
||||||
|
/* Handle the given received message. */
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Process the notification or request. */
|
||||||
|
if (is_ipc_notify(ipc_status)) {
|
||||||
|
blockdriver_handle_notify(bdp, m_ptr);
|
||||||
|
|
||||||
|
/* Do not reply to notifications. */
|
||||||
|
} else {
|
||||||
|
r = blockdriver_handle_request(bdp, m_ptr);
|
||||||
|
|
||||||
|
blockdriver_reply(m_ptr, ipc_status, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* blockdriver_mq_queue *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int blockdriver_mq_queue(message *m, int status)
|
||||||
|
{
|
||||||
|
/* Queue a message for later processing. */
|
||||||
|
|
||||||
|
return mq_enqueue(MQ_SINGLE, m, status);
|
||||||
|
}
|
|
@ -4,26 +4,26 @@
|
||||||
* partition: partition a disk to the partition table(s) on it.
|
* partition: partition a disk to the partition table(s) on it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/driver.h>
|
#include <minix/blockdriver.h>
|
||||||
#include <minix/drvlib.h>
|
#include <minix/drvlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
/* Extended partition? */
|
/* Extended partition? */
|
||||||
#define ext_part(s) ((s) == 0x05 || (s) == 0x0F)
|
#define ext_part(s) ((s) == 0x05 || (s) == 0x0F)
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( void parse_part_table, (struct driver *dp, int device,
|
FORWARD _PROTOTYPE( void parse_part_table, (struct blockdriver *bdp,
|
||||||
int style, int atapi, u8_t *tmp_buf) );
|
int device, int style, int atapi, u8_t *tmp_buf) );
|
||||||
FORWARD _PROTOTYPE( void extpartition, (struct driver *dp, int extdev,
|
FORWARD _PROTOTYPE( void extpartition, (struct blockdriver *bdp, int extdev,
|
||||||
unsigned long extbase, u8_t *tmp_buf) );
|
unsigned long extbase, u8_t *tmp_buf) );
|
||||||
FORWARD _PROTOTYPE( int get_part_table, (struct driver *dp, int device,
|
FORWARD _PROTOTYPE( int get_part_table, (struct blockdriver *bdp, int device,
|
||||||
unsigned long offset, struct part_entry *table, u8_t *tmp_buf) );
|
unsigned long offset, struct part_entry *table, u8_t *tmp_buf) );
|
||||||
FORWARD _PROTOTYPE( void sort, (struct part_entry *table) );
|
FORWARD _PROTOTYPE( void sort, (struct part_entry *table) );
|
||||||
|
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* partition *
|
* partition *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
PUBLIC void partition(dp, device, style, atapi)
|
PUBLIC void partition(bdp, device, style, atapi)
|
||||||
struct driver *dp; /* device dependent entry points */
|
struct blockdriver *bdp; /* device dependent entry points */
|
||||||
int device; /* device to partition */
|
int device; /* device to partition */
|
||||||
int style; /* partitioning style: floppy, primary, sub. */
|
int style; /* partitioning style: floppy, primary, sub. */
|
||||||
int atapi; /* atapi device */
|
int atapi; /* atapi device */
|
||||||
|
@ -33,7 +33,7 @@ int atapi; /* atapi device */
|
||||||
*/
|
*/
|
||||||
u8_t *tmp_buf;
|
u8_t *tmp_buf;
|
||||||
|
|
||||||
if ((*dp->dr_prepare)(device) == NULL)
|
if ((*bdp->bdr_part)(device) == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* For multithreaded drivers, multiple partition() calls may be made on
|
/* For multithreaded drivers, multiple partition() calls may be made on
|
||||||
|
@ -43,7 +43,7 @@ int atapi; /* atapi device */
|
||||||
if (!(tmp_buf = alloc_contig(CD_SECTOR_SIZE, AC_ALIGN4K, NULL)))
|
if (!(tmp_buf = alloc_contig(CD_SECTOR_SIZE, AC_ALIGN4K, NULL)))
|
||||||
panic("partition: unable to allocate temporary buffer");
|
panic("partition: unable to allocate temporary buffer");
|
||||||
|
|
||||||
parse_part_table(dp, device, style, atapi, tmp_buf);
|
parse_part_table(bdp, device, style, atapi, tmp_buf);
|
||||||
|
|
||||||
free_contig(tmp_buf, CD_SECTOR_SIZE);
|
free_contig(tmp_buf, CD_SECTOR_SIZE);
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,8 @@ int atapi; /* atapi device */
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* parse_part_table *
|
* parse_part_table *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
PRIVATE void parse_part_table(dp, device, style, atapi, tmp_buf)
|
PRIVATE void parse_part_table(bdp, device, style, atapi, tmp_buf)
|
||||||
struct driver *dp; /* device dependent entry points */
|
struct blockdriver *bdp; /* device dependent entry points */
|
||||||
int device; /* device to partition */
|
int device; /* device to partition */
|
||||||
int style; /* partitioning style: floppy, primary, sub. */
|
int style; /* partitioning style: floppy, primary, sub. */
|
||||||
int atapi; /* atapi device */
|
int atapi; /* atapi device */
|
||||||
|
@ -71,13 +71,13 @@ u8_t *tmp_buf; /* temporary buffer */
|
||||||
unsigned long base, limit, part_limit;
|
unsigned long base, limit, part_limit;
|
||||||
|
|
||||||
/* Get the geometry of the device to partition */
|
/* Get the geometry of the device to partition */
|
||||||
if ((dv = (*dp->dr_prepare)(device)) == NULL
|
if ((dv = (*bdp->bdr_part)(device)) == NULL
|
||||||
|| cmp64u(dv->dv_size, 0) == 0) return;
|
|| cmp64u(dv->dv_size, 0) == 0) return;
|
||||||
base = div64u(dv->dv_base, SECTOR_SIZE);
|
base = div64u(dv->dv_base, SECTOR_SIZE);
|
||||||
limit = base + div64u(dv->dv_size, SECTOR_SIZE);
|
limit = base + div64u(dv->dv_size, SECTOR_SIZE);
|
||||||
|
|
||||||
/* Read the partition table for the device. */
|
/* Read the partition table for the device. */
|
||||||
if(!get_part_table(dp, device, 0L, table, tmp_buf)) {
|
if(!get_part_table(bdp, device, 0L, table, tmp_buf)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ u8_t *tmp_buf; /* temporary buffer */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find an array of devices. */
|
/* Find an array of devices. */
|
||||||
if ((dv = (*dp->dr_prepare)(device)) == NULL) return;
|
if ((dv = (*bdp->bdr_part)(device)) == NULL) return;
|
||||||
|
|
||||||
/* Set the geometry of the partitions from the partition table. */
|
/* Set the geometry of the partitions from the partition table. */
|
||||||
for (par = 0; par < NR_PARTITIONS; par++, dv++) {
|
for (par = 0; par < NR_PARTITIONS; par++, dv++) {
|
||||||
|
@ -115,12 +115,12 @@ u8_t *tmp_buf; /* temporary buffer */
|
||||||
if (style == P_PRIMARY) {
|
if (style == P_PRIMARY) {
|
||||||
/* Each Minix primary partition can be subpartitioned. */
|
/* Each Minix primary partition can be subpartitioned. */
|
||||||
if (pe->sysind == MINIX_PART)
|
if (pe->sysind == MINIX_PART)
|
||||||
parse_part_table(dp, device + par, P_SUB, atapi,
|
parse_part_table(bdp, device + par, P_SUB, atapi,
|
||||||
tmp_buf);
|
tmp_buf);
|
||||||
|
|
||||||
/* An extended partition has logical partitions. */
|
/* An extended partition has logical partitions. */
|
||||||
if (ext_part(pe->sysind))
|
if (ext_part(pe->sysind))
|
||||||
extpartition(dp, device + par, pe->lowsec, tmp_buf);
|
extpartition(bdp, device + par, pe->lowsec, tmp_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,10 +128,10 @@ u8_t *tmp_buf; /* temporary buffer */
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* extpartition *
|
* extpartition *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
PRIVATE void extpartition(dp, extdev, extbase, tmp_buf)
|
PRIVATE void extpartition(bdp, extdev, extbase, tmp_buf)
|
||||||
struct driver *dp; /* device dependent entry points */
|
struct blockdriver *bdp; /* device dependent entry points */
|
||||||
int extdev; /* extended partition to scan */
|
int extdev; /* extended partition to scan */
|
||||||
unsigned long extbase; /* sector offset of the base extended partition */
|
unsigned long extbase; /* sector offset of the base ext. partition */
|
||||||
u8_t *tmp_buf; /* temporary buffer */
|
u8_t *tmp_buf; /* temporary buffer */
|
||||||
{
|
{
|
||||||
/* Extended partitions cannot be ignored alas, because people like to move
|
/* Extended partitions cannot be ignored alas, because people like to move
|
||||||
|
@ -148,7 +148,7 @@ u8_t *tmp_buf; /* temporary buffer */
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
do {
|
do {
|
||||||
if (!get_part_table(dp, extdev, offset, table, tmp_buf)) return;
|
if (!get_part_table(bdp, extdev, offset, table, tmp_buf)) return;
|
||||||
sort(table);
|
sort(table);
|
||||||
|
|
||||||
/* The table should contain one logical partition and optionally
|
/* The table should contain one logical partition and optionally
|
||||||
|
@ -161,7 +161,7 @@ u8_t *tmp_buf; /* temporary buffer */
|
||||||
nextoffset = pe->lowsec;
|
nextoffset = pe->lowsec;
|
||||||
} else
|
} else
|
||||||
if (pe->sysind != NO_PART) {
|
if (pe->sysind != NO_PART) {
|
||||||
if ((dv = (*dp->dr_prepare)(subdev)) == NULL) return;
|
if ((dv = (*bdp->bdr_part)(subdev)) == NULL) return;
|
||||||
|
|
||||||
dv->dv_base = mul64u(extbase + offset + pe->lowsec,
|
dv->dv_base = mul64u(extbase + offset + pe->lowsec,
|
||||||
SECTOR_SIZE);
|
SECTOR_SIZE);
|
||||||
|
@ -177,8 +177,8 @@ u8_t *tmp_buf; /* temporary buffer */
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* get_part_table *
|
* get_part_table *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
PRIVATE int get_part_table(dp, device, offset, table, tmp_buf)
|
PRIVATE int get_part_table(bdp, device, offset, table, tmp_buf)
|
||||||
struct driver *dp;
|
struct blockdriver *bdp;
|
||||||
int device;
|
int device;
|
||||||
unsigned long offset; /* sector offset to the table */
|
unsigned long offset; /* sector offset to the table */
|
||||||
struct part_entry *table; /* four entries */
|
struct part_entry *table; /* four entries */
|
||||||
|
@ -189,14 +189,14 @@ u8_t *tmp_buf; /* temporary buffer */
|
||||||
*/
|
*/
|
||||||
iovec_t iovec1;
|
iovec_t iovec1;
|
||||||
u64_t position;
|
u64_t position;
|
||||||
|
int r;
|
||||||
|
|
||||||
position = mul64u(offset, SECTOR_SIZE);
|
position = mul64u(offset, SECTOR_SIZE);
|
||||||
iovec1.iov_addr = (vir_bytes) tmp_buf;
|
iovec1.iov_addr = (vir_bytes) tmp_buf;
|
||||||
iovec1.iov_size = CD_SECTOR_SIZE;
|
iovec1.iov_size = CD_SECTOR_SIZE;
|
||||||
if ((*dp->dr_prepare)(device) != NULL) {
|
r = (*bdp->bdr_transfer)(device, FALSE /*do_write*/, position, SELF,
|
||||||
(void) (*dp->dr_transfer)(SELF, DEV_GATHER_S, position, &iovec1, 1);
|
&iovec1, 1, BDEV_NOFLAGS);
|
||||||
}
|
if (r != CD_SECTOR_SIZE) {
|
||||||
if (iovec1.iov_size != 0) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (tmp_buf[510] != 0x55 || tmp_buf[511] != 0xAA) {
|
if (tmp_buf[510] != 0x55 || tmp_buf[511] != 0xAA) {
|
|
@ -7,65 +7,65 @@
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_event_init *
|
* event_init *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void driver_event_init(event_t *event)
|
PUBLIC void event_init(event_t *event)
|
||||||
{
|
{
|
||||||
/* Initialize an event object.
|
/* Initialize an event object.
|
||||||
*/
|
*/
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = mthread_mutex_init(&event->mutex, NULL)) != 0)
|
if ((r = mthread_mutex_init(&event->mutex, NULL)) != 0)
|
||||||
panic("libdriver: error initializing mutex (%d)", r);
|
panic("libblockdriver: error initializing mutex (%d)", r);
|
||||||
if ((r = mthread_cond_init(&event->cond, NULL)) != 0)
|
if ((r = mthread_cond_init(&event->cond, NULL)) != 0)
|
||||||
panic("libdriver: error initializing condvar (%d)", r);
|
panic("libblockdriver: error initializing condvar (%d)", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_event_destroy *
|
* event_destroy *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void driver_event_destroy(event_t *event)
|
PUBLIC void event_destroy(event_t *event)
|
||||||
{
|
{
|
||||||
/* Destroy an event object.
|
/* Destroy an event object.
|
||||||
*/
|
*/
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = mthread_cond_destroy(&event->cond)) != 0)
|
if ((r = mthread_cond_destroy(&event->cond)) != 0)
|
||||||
panic("libdriver: error destroying condvar (%d)", r);
|
panic("libblockdriver: error destroying condvar (%d)", r);
|
||||||
if ((r = mthread_mutex_destroy(&event->mutex)) != 0)
|
if ((r = mthread_mutex_destroy(&event->mutex)) != 0)
|
||||||
panic("libdriver: error destroying mutex (%d)", r);
|
panic("libblockdriver: error destroying mutex (%d)", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_event_wait *
|
* event_wait *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void driver_event_wait(event_t *event)
|
PUBLIC void event_wait(event_t *event)
|
||||||
{
|
{
|
||||||
/* Wait for an event, blocking the current thread in the process.
|
/* Wait for an event, blocking the current thread in the process.
|
||||||
*/
|
*/
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = mthread_mutex_lock(&event->mutex)) != 0)
|
if ((r = mthread_mutex_lock(&event->mutex)) != 0)
|
||||||
panic("libdriver: error locking mutex (%d)", r);
|
panic("libblockdriver: error locking mutex (%d)", r);
|
||||||
if ((r = mthread_cond_wait(&event->cond, &event->mutex)) != 0)
|
if ((r = mthread_cond_wait(&event->cond, &event->mutex)) != 0)
|
||||||
panic("libdriver: error waiting for condvar (%d)", r);
|
panic("libblockdriver: error waiting for condvar (%d)", r);
|
||||||
if ((r = mthread_mutex_unlock(&event->mutex)) != 0)
|
if ((r = mthread_mutex_unlock(&event->mutex)) != 0)
|
||||||
panic("libdriver: error unlocking mutex (%d)", r);
|
panic("libblockdriver: error unlocking mutex (%d)", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_event_fire *
|
* event_fire *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void driver_event_fire(event_t *event)
|
PUBLIC void event_fire(event_t *event)
|
||||||
{
|
{
|
||||||
/* Fire an event, waking up any thread blocked on it without scheduling it.
|
/* Fire an event, waking up any thread blocked on it without scheduling it.
|
||||||
*/
|
*/
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = mthread_mutex_lock(&event->mutex)) != 0)
|
if ((r = mthread_mutex_lock(&event->mutex)) != 0)
|
||||||
panic("libdriver: error locking mutex (%d)", r);
|
panic("libblockdriver: error locking mutex (%d)", r);
|
||||||
if ((r = mthread_cond_signal(&event->cond)) != 0)
|
if ((r = mthread_cond_signal(&event->cond)) != 0)
|
||||||
panic("libdriver: error signaling condvar (%d)", r);
|
panic("libblockdriver: error signaling condvar (%d)", r);
|
||||||
if ((r = mthread_mutex_unlock(&event->mutex)) != 0)
|
if ((r = mthread_mutex_unlock(&event->mutex)) != 0)
|
||||||
panic("libdriver: error unlocking mutex (%d)", r);
|
panic("libblockdriver: error unlocking mutex (%d)", r);
|
||||||
}
|
}
|
14
lib/libblockdriver/event.h
Normal file
14
lib/libblockdriver/event.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef _BLOCKDRIVER_EVENT_H
|
||||||
|
#define _BLOCKDRIVER_EVENT_H
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mthread_mutex_t mutex;
|
||||||
|
mthread_cond_t cond;
|
||||||
|
} event_t;
|
||||||
|
|
||||||
|
_PROTOTYPE( void event_init, (event_t *event) );
|
||||||
|
_PROTOTYPE( void event_destroy, (event_t *event) );
|
||||||
|
_PROTOTYPE( void event_wait, (event_t *event) );
|
||||||
|
_PROTOTYPE( void event_fire, (event_t *event) );
|
||||||
|
|
||||||
|
#endif /* _BLOCKDRIVER_EVENT_H */
|
|
@ -3,10 +3,10 @@
|
||||||
*
|
*
|
||||||
* Changes:
|
* Changes:
|
||||||
* Oct 27, 2011 rewritten to use sys/queue.h (D.C. van Moolenbroek)
|
* Oct 27, 2011 rewritten to use sys/queue.h (D.C. van Moolenbroek)
|
||||||
* Aug 27, 2011 integrated into libdriver (A. Welzel)
|
* Aug 27, 2011 integrated into libblockdriver (A. Welzel)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/driver_mt.h>
|
#include <minix/blockdriver_mt.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
@ -26,9 +26,9 @@ PRIVATE STAILQ_HEAD(queue, mq_cell) queue[DRIVER_MT_MAX_WORKERS];
|
||||||
PRIVATE STAILQ_HEAD(free_list, mq_cell) free_list;
|
PRIVATE STAILQ_HEAD(free_list, mq_cell) free_list;
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_mq_init *
|
* mq_init *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void driver_mq_init(void)
|
PUBLIC void mq_init(void)
|
||||||
{
|
{
|
||||||
/* Initialize the message queues and message cells.
|
/* Initialize the message queues and message cells.
|
||||||
*/
|
*/
|
||||||
|
@ -44,9 +44,9 @@ PUBLIC void driver_mq_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_mq_enqueue *
|
* mq_enqueue *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int driver_mq_enqueue(thread_id_t thread_id, const message *mess,
|
PUBLIC int mq_enqueue(thread_id_t thread_id, const message *mess,
|
||||||
int ipc_status)
|
int ipc_status)
|
||||||
{
|
{
|
||||||
/* Add a message, including its IPC status, to the message queue of a thread.
|
/* Add a message, including its IPC status, to the message queue of a thread.
|
||||||
|
@ -71,10 +71,9 @@ PUBLIC int driver_mq_enqueue(thread_id_t thread_id, const message *mess,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_mq_dequeue *
|
* mq_dequeue *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int driver_mq_dequeue(thread_id_t thread_id, message *mess,
|
PUBLIC int mq_dequeue(thread_id_t thread_id, message *mess, int *ipc_status)
|
||||||
int *ipc_status)
|
|
||||||
{
|
{
|
||||||
/* Return and remove a message, including its IPC status, from the message
|
/* Return and remove a message, including its IPC status, from the message
|
||||||
* queue of a thread. Return TRUE iff a message was available.
|
* queue of a thread. Return TRUE iff a message was available.
|
12
lib/libblockdriver/mq.h
Normal file
12
lib/libblockdriver/mq.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef _BLOCKDRIVER_MQ_H
|
||||||
|
#define _BLOCKDRIVER_MQ_H
|
||||||
|
|
||||||
|
#define MQ_SINGLE 0 /* thread ID for single-threading */
|
||||||
|
|
||||||
|
_PROTOTYPE( void mq_init, (void) );
|
||||||
|
_PROTOTYPE( int mq_enqueue, (thread_id_t thread_id, const message *mess,
|
||||||
|
int ipc_status) );
|
||||||
|
_PROTOTYPE( int mq_dequeue, (thread_id_t thread_id, message *mess,
|
||||||
|
int *ipc_status) );
|
||||||
|
|
||||||
|
#endif /* _BLOCKDRIVER_MQ_H */
|
12
lib/libchardriver/Makefile
Normal file
12
lib/libchardriver/Makefile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# Makefile for libchardriver
|
||||||
|
.include <bsd.own.mk>
|
||||||
|
|
||||||
|
LIB= chardriver
|
||||||
|
|
||||||
|
SRCS= chardriver.c
|
||||||
|
|
||||||
|
.if ${USE_STATECTL} != "no"
|
||||||
|
CPPFLAGS+= -DUSE_STATECTL
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.include <bsd.lib.mk>
|
|
@ -1,6 +1,4 @@
|
||||||
/* This file contains the common part of the device driver interface.
|
/* This file contains the device independent character driver interface.
|
||||||
* In addition, callers get to choose between the singlethreaded API
|
|
||||||
* (in driver_st.c) and the multithreaded API (in driver_mt.c).
|
|
||||||
*
|
*
|
||||||
* The drivers support the following operations (using message format m2):
|
* The drivers support the following operations (using message format m2):
|
||||||
*
|
*
|
||||||
|
@ -25,8 +23,13 @@
|
||||||
* | DEV_SELECT | device | ops | | | | |
|
* | DEV_SELECT | device | ops | | | | |
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
* The entry points into this file are:
|
||||||
|
* driver_task: the main message loop of the driver
|
||||||
|
* driver_receive: message receive interface for drivers
|
||||||
|
*
|
||||||
* Changes:
|
* Changes:
|
||||||
* Aug 27, 2011 split common functions into driver_common.c (A. Welzel)
|
* Oct 16, 2011 split character and block protocol (D.C. van Moolenbroek)
|
||||||
|
* Aug 27, 2011 move common functions into driver.c (A. Welzel)
|
||||||
* Jul 25, 2005 added SYS_SIG type for signals (Jorrit N. Herder)
|
* Jul 25, 2005 added SYS_SIG type for signals (Jorrit N. Herder)
|
||||||
* Sep 15, 2004 added SYN_ALARM type for timeouts (Jorrit N. Herder)
|
* Sep 15, 2004 added SYN_ALARM type for timeouts (Jorrit N. Herder)
|
||||||
* Jul 23, 2004 removed kernel dependencies (Jorrit N. Herder)
|
* Jul 23, 2004 removed kernel dependencies (Jorrit N. Herder)
|
||||||
|
@ -34,12 +37,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <sys/ioc_disk.h>
|
#include <minix/chardriver.h>
|
||||||
#include <minix/driver.h>
|
|
||||||
#include <minix/ds.h>
|
#include <minix/ds.h>
|
||||||
|
|
||||||
#include "driver.h"
|
PRIVATE int running;
|
||||||
#include "mq.h"
|
|
||||||
|
|
||||||
/* Management data for opened devices. */
|
/* Management data for opened devices. */
|
||||||
PRIVATE int open_devs[MAX_NR_OPEN_DEVICES];
|
PRIVATE int open_devs[MAX_NR_OPEN_DEVICES];
|
||||||
|
@ -84,9 +85,41 @@ PRIVATE void set_open_dev(int device)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* asyn_reply *
|
* chardriver_announce *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void asyn_reply(message *mess, int r)
|
PUBLIC void chardriver_announce(void)
|
||||||
|
{
|
||||||
|
/* Announce we are up after a fresh start or restart. */
|
||||||
|
int r;
|
||||||
|
char key[DS_MAX_KEYLEN];
|
||||||
|
char label[DS_MAX_KEYLEN];
|
||||||
|
char *driver_prefix = "drv.chr.";
|
||||||
|
|
||||||
|
/* Callers are allowed to use sendrec to communicate with drivers.
|
||||||
|
* For this reason, there may blocked callers when a driver restarts.
|
||||||
|
* Ask the kernel to unblock them (if any).
|
||||||
|
*/
|
||||||
|
#if USE_STATECTL
|
||||||
|
if ((r = sys_statectl(SYS_STATE_CLEAR_IPC_REFS)) != OK)
|
||||||
|
panic("chardriver_init: sys_statectl failed: %d", r);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Publish a driver up event. */
|
||||||
|
if ((r = ds_retrieve_label_name(label, getprocnr())) != OK)
|
||||||
|
panic("chardriver_init: unable to get own label: %d", r);
|
||||||
|
|
||||||
|
snprintf(key, DS_MAX_KEYLEN, "%s%s", driver_prefix, label);
|
||||||
|
if ((r = ds_publish_u32(key, DS_DRIVER_UP, DSF_OVERWRITE)) != OK)
|
||||||
|
panic("chardriver_init: unable to publish driver up event: %d", r);
|
||||||
|
|
||||||
|
/* Expect a DEV_OPEN for any device before serving regular driver requests. */
|
||||||
|
clear_open_devs();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* async_reply *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE void async_reply(message *mess, int r)
|
||||||
{
|
{
|
||||||
/* Send a reply using the asynchronous character device protocol. */
|
/* Send a reply using the asynchronous character device protocol. */
|
||||||
message reply_mess;
|
message reply_mess;
|
||||||
|
@ -150,9 +183,9 @@ PRIVATE void asyn_reply(message *mess, int r)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* standard_reply *
|
* sync_reply *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void standard_reply(message *m_ptr, int ipc_status, int reply)
|
PRIVATE void sync_reply(message *m_ptr, int ipc_status, int reply)
|
||||||
{
|
{
|
||||||
/* Reply to a message sent to the driver. */
|
/* Reply to a message sent to the driver. */
|
||||||
endpoint_t caller_e, user_e;
|
endpoint_t caller_e, user_e;
|
||||||
|
@ -176,75 +209,25 @@ PRIVATE void standard_reply(message *m_ptr, int ipc_status, int reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_reply *
|
* send_reply *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void driver_reply(int driver_type, message *m_ptr, int ipc_status,
|
PRIVATE void send_reply(int type, message *m_ptr, int ipc_status, int reply)
|
||||||
int reply)
|
|
||||||
{
|
{
|
||||||
/* Prepare and send a reply message. */
|
/* Prepare and send a reply message. */
|
||||||
|
|
||||||
if (reply == EDONTREPLY)
|
if (reply == EDONTREPLY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (driver_type) {
|
if (type == CHARDRIVER_ASYNC)
|
||||||
case DRIVER_STD:
|
async_reply(m_ptr, reply);
|
||||||
standard_reply(m_ptr, ipc_status, reply);
|
else
|
||||||
|
sync_reply(m_ptr, ipc_status, reply);
|
||||||
break;
|
|
||||||
|
|
||||||
case DRIVER_ASYN:
|
|
||||||
asyn_reply(m_ptr, reply);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
panic("unknown driver type: %d", driver_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* driver_announce *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC void driver_announce(void)
|
|
||||||
{
|
|
||||||
/* Announce we are up after a fresh start or restart. */
|
|
||||||
int r;
|
|
||||||
char key[DS_MAX_KEYLEN];
|
|
||||||
char label[DS_MAX_KEYLEN];
|
|
||||||
char *driver_prefix = "drv.vfs.";
|
|
||||||
|
|
||||||
/* Callers are allowed to use sendrec to communicate with drivers.
|
|
||||||
* For this reason, there may blocked callers when a driver restarts.
|
|
||||||
* Ask the kernel to unblock them (if any).
|
|
||||||
*/
|
|
||||||
#if USE_STATECTL
|
|
||||||
r = sys_statectl(SYS_STATE_CLEAR_IPC_REFS);
|
|
||||||
if (r != OK) {
|
|
||||||
panic("driver_announce: sys_statectl failed: %d\n", r);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Publish a driver up event. */
|
|
||||||
r = ds_retrieve_label_name(label, getprocnr());
|
|
||||||
if (r != OK) {
|
|
||||||
panic("driver_announce: unable to get own label: %d\n", r);
|
|
||||||
}
|
|
||||||
snprintf(key, DS_MAX_KEYLEN, "%s%s", driver_prefix, label);
|
|
||||||
r = ds_publish_u32(key, DS_DRIVER_UP, DSF_OVERWRITE);
|
|
||||||
if (r != OK) {
|
|
||||||
panic("driver_announce: unable to publish driver up event: %d\n", r);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expect a DEV_OPEN for any device before serving regular driver requests. */
|
|
||||||
clear_open_devs();
|
|
||||||
|
|
||||||
driver_mq_init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_rdwt *
|
* do_rdwt *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int do_rdwt(struct driver *dp, message *mp)
|
PRIVATE int do_rdwt(struct chardriver *cdp, message *mp)
|
||||||
{
|
{
|
||||||
/* Carry out a single read or write request. */
|
/* Carry out a single read or write request. */
|
||||||
iovec_t iovec1;
|
iovec_t iovec1;
|
||||||
|
@ -255,7 +238,7 @@ PRIVATE int do_rdwt(struct driver *dp, message *mp)
|
||||||
if (mp->COUNT < 0) return(EINVAL);
|
if (mp->COUNT < 0) return(EINVAL);
|
||||||
|
|
||||||
/* Prepare for I/O. */
|
/* Prepare for I/O. */
|
||||||
if ((*dp->dr_prepare)(mp->DEVICE) == NULL) return(ENXIO);
|
if ((*cdp->cdr_prepare)(mp->DEVICE) == NULL) return(ENXIO);
|
||||||
|
|
||||||
/* Create a one element scatter/gather vector for the buffer. */
|
/* Create a one element scatter/gather vector for the buffer. */
|
||||||
if(mp->m_type == DEV_READ_S) opcode = DEV_GATHER_S;
|
if(mp->m_type == DEV_READ_S) opcode = DEV_GATHER_S;
|
||||||
|
@ -266,7 +249,8 @@ PRIVATE int do_rdwt(struct driver *dp, message *mp)
|
||||||
|
|
||||||
/* Transfer bytes from/to the device. */
|
/* Transfer bytes from/to the device. */
|
||||||
position= make64(mp->POSITION, mp->HIGHPOS);
|
position= make64(mp->POSITION, mp->HIGHPOS);
|
||||||
r = (*dp->dr_transfer)(mp->m_source, opcode, position, &iovec1, 1);
|
r = (*cdp->cdr_transfer)(mp->m_source, opcode, position, &iovec1, 1,
|
||||||
|
mp->USER_ENDPT);
|
||||||
|
|
||||||
/* Return the number of bytes transferred or an error code. */
|
/* Return the number of bytes transferred or an error code. */
|
||||||
return(r == OK ? (int) (mp->COUNT - iovec1.iov_size) : r);
|
return(r == OK ? (int) (mp->COUNT - iovec1.iov_size) : r);
|
||||||
|
@ -275,7 +259,7 @@ PRIVATE int do_rdwt(struct driver *dp, message *mp)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_vrdwt *
|
* do_vrdwt *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int do_vrdwt(struct driver *dp, message *mp)
|
PRIVATE int do_vrdwt(struct chardriver *cdp, message *mp)
|
||||||
{
|
{
|
||||||
/* Carry out an device read or write to/from a vector of user addresses.
|
/* Carry out an device read or write to/from a vector of user addresses.
|
||||||
* The "user addresses" are assumed to be safe, i.e. FS transferring to/from
|
* The "user addresses" are assumed to be safe, i.e. FS transferring to/from
|
||||||
|
@ -300,12 +284,13 @@ PRIVATE int do_vrdwt(struct driver *dp, message *mp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare for I/O. */
|
/* Prepare for I/O. */
|
||||||
if ((*dp->dr_prepare)(mp->DEVICE) == NULL) return(ENXIO);
|
if ((*cdp->cdr_prepare)(mp->DEVICE) == NULL) return(ENXIO);
|
||||||
|
|
||||||
/* Transfer bytes from/to the device. */
|
/* Transfer bytes from/to the device. */
|
||||||
opcode = mp->m_type;
|
opcode = mp->m_type;
|
||||||
position= make64(mp->POSITION, mp->HIGHPOS);
|
position= make64(mp->POSITION, mp->HIGHPOS);
|
||||||
r = (*dp->dr_transfer)(mp->m_source, opcode, position, iovec, nr_req);
|
r = (*cdp->cdr_transfer)(mp->m_source, opcode, position, iovec, nr_req,
|
||||||
|
mp->USER_ENDPT);
|
||||||
|
|
||||||
/* Copy the I/O vector back to the caller. */
|
/* Copy the I/O vector back to the caller. */
|
||||||
if (OK != sys_safecopyto(mp->m_source, (vir_bytes) mp->IO_GRANT,
|
if (OK != sys_safecopyto(mp->m_source, (vir_bytes) mp->IO_GRANT,
|
||||||
|
@ -318,9 +303,9 @@ PRIVATE int do_vrdwt(struct driver *dp, message *mp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_handle_notify *
|
* handle_notify *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void driver_handle_notify(struct driver *dp, message *m_ptr)
|
PRIVATE void handle_notify(struct chardriver *cdp, message *m_ptr)
|
||||||
{
|
{
|
||||||
/* Take care of the notifications (interrupt and clock messages) by calling the
|
/* Take care of the notifications (interrupt and clock messages) by calling the
|
||||||
* appropiate callback functions. Never send a reply.
|
* appropiate callback functions. Never send a reply.
|
||||||
|
@ -328,26 +313,21 @@ PUBLIC void driver_handle_notify(struct driver *dp, message *m_ptr)
|
||||||
|
|
||||||
/* Call the appropriate function for this notification. */
|
/* Call the appropriate function for this notification. */
|
||||||
switch (_ENDPOINT_P(m_ptr->m_source)) {
|
switch (_ENDPOINT_P(m_ptr->m_source)) {
|
||||||
case HARDWARE:
|
|
||||||
if (dp->dr_hw_int)
|
|
||||||
dp->dr_hw_int(dp, m_ptr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CLOCK:
|
case CLOCK:
|
||||||
if (dp->dr_alarm)
|
if (cdp->cdr_alarm)
|
||||||
dp->dr_alarm(dp, m_ptr);
|
cdp->cdr_alarm(m_ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (dp->dr_other)
|
if (cdp->cdr_other)
|
||||||
(void) dp->dr_other(dp, m_ptr);
|
(void) cdp->cdr_other(m_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* driver_handle_request *
|
* handle_request *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int driver_handle_request(struct driver *dp, message *m_ptr)
|
PRIVATE int handle_request(struct chardriver *cdp, message *m_ptr)
|
||||||
{
|
{
|
||||||
/* Call the appropiate driver function, based on the type of request. Return
|
/* Call the appropiate driver function, based on the type of request. Return
|
||||||
* the result code that is to be sent back to the caller, or EDONTREPLY if no
|
* the result code that is to be sent back to the caller, or EDONTREPLY if no
|
||||||
|
@ -359,7 +339,7 @@ PUBLIC int driver_handle_request(struct driver *dp, message *m_ptr)
|
||||||
* requests on devices that have not previously been opened, signaling the
|
* requests on devices that have not previously been opened, signaling the
|
||||||
* caller that something went wrong.
|
* caller that something went wrong.
|
||||||
*/
|
*/
|
||||||
if (IS_DEV_MINOR_RQ(m_ptr->m_type) && !is_open_dev(m_ptr->DEVICE)) {
|
if (IS_CDEV_MINOR_RQ(m_ptr->m_type) && !is_open_dev(m_ptr->DEVICE)) {
|
||||||
/* Reply ERESTART to spurious requests for unopened devices. */
|
/* Reply ERESTART to spurious requests for unopened devices. */
|
||||||
if (m_ptr->m_type != DEV_OPEN)
|
if (m_ptr->m_type != DEV_OPEN)
|
||||||
return ERESTART;
|
return ERESTART;
|
||||||
|
@ -370,63 +350,84 @@ PUBLIC int driver_handle_request(struct driver *dp, message *m_ptr)
|
||||||
|
|
||||||
/* Call the appropriate function(s) for this request. */
|
/* Call the appropriate function(s) for this request. */
|
||||||
switch (m_ptr->m_type) {
|
switch (m_ptr->m_type) {
|
||||||
case DEV_OPEN: r = (*dp->dr_open)(dp, m_ptr); break;
|
case DEV_OPEN: r = (*cdp->cdr_open)(m_ptr); break;
|
||||||
case DEV_CLOSE: r = (*dp->dr_close)(dp, m_ptr); break;
|
case DEV_CLOSE: r = (*cdp->cdr_close)(m_ptr); break;
|
||||||
case DEV_IOCTL_S: r = (*dp->dr_ioctl)(dp, m_ptr); break;
|
case DEV_IOCTL_S: r = (*cdp->cdr_ioctl)(m_ptr); break;
|
||||||
case CANCEL: r = (*dp->dr_cancel)(dp, m_ptr); break;
|
case CANCEL: r = (*cdp->cdr_cancel)(m_ptr); break;
|
||||||
case DEV_SELECT: r = (*dp->dr_select)(dp, m_ptr); break;
|
case DEV_SELECT: r = (*cdp->cdr_select)(m_ptr); break;
|
||||||
case DEV_READ_S:
|
case DEV_READ_S:
|
||||||
case DEV_WRITE_S: r = do_rdwt(dp, m_ptr); break;
|
case DEV_WRITE_S: r = do_rdwt(cdp, m_ptr); break;
|
||||||
case DEV_GATHER_S:
|
case DEV_GATHER_S:
|
||||||
case DEV_SCATTER_S: r = do_vrdwt(dp, m_ptr); break;
|
case DEV_SCATTER_S: r = do_vrdwt(cdp, m_ptr); break;
|
||||||
default:
|
default:
|
||||||
if (dp->dr_other)
|
if (cdp->cdr_other)
|
||||||
r = dp->dr_other(dp, m_ptr);
|
r = cdp->cdr_other(m_ptr);
|
||||||
else
|
else
|
||||||
r = EINVAL;
|
r = EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let the driver perform any cleanup. */
|
/* Let the driver perform any cleanup. */
|
||||||
(*dp->dr_cleanup)();
|
if (cdp->cdr_cleanup)
|
||||||
|
(*cdp->cdr_cleanup)();
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* no_name *
|
* chardriver_process *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC char *no_name(void)
|
PUBLIC void chardriver_process(struct chardriver *cdp, int driver_type,
|
||||||
|
message *m_ptr, int ipc_status)
|
||||||
{
|
{
|
||||||
/* Use this default name if there is no specific name for the device. This was
|
/* Handle the given received message. */
|
||||||
* originally done by fetching the name from the task table for this process:
|
int r;
|
||||||
* "return(tasktab[proc_number(proc_ptr) + NR_TASKS].name);", but currently a
|
|
||||||
* real "noname" is returned. Perhaps, some system information service can be
|
/* Process the notification or request. */
|
||||||
* queried for a name at a later time.
|
if (is_ipc_notify(ipc_status)) {
|
||||||
|
handle_notify(cdp, m_ptr);
|
||||||
|
|
||||||
|
/* Do not reply to notifications. */
|
||||||
|
} else {
|
||||||
|
r = handle_request(cdp, m_ptr);
|
||||||
|
|
||||||
|
send_reply(driver_type, m_ptr, ipc_status, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* chardriver_task *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC void chardriver_task(struct chardriver *cdp, int driver_type)
|
||||||
|
{
|
||||||
|
/* Main program of any device driver task. */
|
||||||
|
int r, ipc_status;
|
||||||
|
message mess;
|
||||||
|
|
||||||
|
running = TRUE;
|
||||||
|
|
||||||
|
/* Here is the main loop of the disk task. It waits for a message, carries
|
||||||
|
* it out, and sends a reply.
|
||||||
*/
|
*/
|
||||||
static char name[] = "noname";
|
while (running) {
|
||||||
return name;
|
if ((r = sef_receive_status(ANY, &mess, &ipc_status)) != OK)
|
||||||
|
panic("driver_receive failed: %d", r);
|
||||||
|
|
||||||
|
chardriver_process(cdp, driver_type, &mess, ipc_status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_nop *
|
* do_nop *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int do_nop(struct driver *UNUSED(dp), message *mp)
|
PUBLIC int do_nop(message *UNUSED(mp))
|
||||||
{
|
{
|
||||||
/* Nothing there, or nothing to do. */
|
return(OK);
|
||||||
|
|
||||||
switch (mp->m_type) {
|
|
||||||
case DEV_OPEN: return(ENODEV);
|
|
||||||
case DEV_CLOSE: return(OK);
|
|
||||||
case DEV_IOCTL_S:
|
|
||||||
default: printf("nop: ignoring code %d\n", mp->m_type);
|
|
||||||
return(EIO);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* nop_ioctl *
|
* nop_ioctl *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int nop_ioctl(struct driver *UNUSED(dp), message *UNUSED(mp))
|
PUBLIC int nop_ioctl(message *UNUSED(mp))
|
||||||
{
|
{
|
||||||
return(ENOTTY);
|
return(ENOTTY);
|
||||||
}
|
}
|
||||||
|
@ -434,20 +435,11 @@ PUBLIC int nop_ioctl(struct driver *UNUSED(dp), message *UNUSED(mp))
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* nop_alarm *
|
* nop_alarm *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void nop_alarm(struct driver *UNUSED(dp), message *UNUSED(mp))
|
PUBLIC void nop_alarm(message *UNUSED(mp))
|
||||||
{
|
{
|
||||||
/* Ignore the leftover alarm. */
|
/* Ignore the leftover alarm. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* nop_prepare *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC struct device *nop_prepare(int UNUSED(device))
|
|
||||||
{
|
|
||||||
/* Nothing to prepare for. */
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* nop_cleanup *
|
* nop_cleanup *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -459,7 +451,7 @@ PUBLIC void nop_cleanup(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* nop_cancel *
|
* nop_cancel *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int nop_cancel(struct driver *UNUSED(dr), message *UNUSED(m))
|
PUBLIC int nop_cancel(message *UNUSED(m))
|
||||||
{
|
{
|
||||||
/* Nothing to do for cancel. */
|
/* Nothing to do for cancel. */
|
||||||
return(OK);
|
return(OK);
|
||||||
|
@ -468,52 +460,8 @@ PUBLIC int nop_cancel(struct driver *UNUSED(dr), message *UNUSED(m))
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* nop_select *
|
* nop_select *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int nop_select(struct driver *UNUSED(dr), message *UNUSED(m))
|
PUBLIC int nop_select(message *UNUSED(m))
|
||||||
{
|
{
|
||||||
/* Nothing to do for select. */
|
/* Nothing to do for select. */
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_diocntl *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_diocntl(struct driver *dp, message *mp)
|
|
||||||
{
|
|
||||||
/* Carry out a partition setting/getting request. */
|
|
||||||
struct device *dv;
|
|
||||||
struct partition entry;
|
|
||||||
unsigned int request;
|
|
||||||
int s;
|
|
||||||
|
|
||||||
request = mp->REQUEST;
|
|
||||||
|
|
||||||
if (request != DIOCSETP && request != DIOCGETP) {
|
|
||||||
if(dp->dr_other)
|
|
||||||
return dp->dr_other(dp, mp);
|
|
||||||
else
|
|
||||||
return(ENOTTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode the message parameters. */
|
|
||||||
if ((dv = (*dp->dr_prepare)(mp->DEVICE)) == NULL) return(ENXIO);
|
|
||||||
|
|
||||||
if (request == DIOCSETP) {
|
|
||||||
/* Copy just this one partition table entry. */
|
|
||||||
s=sys_safecopyfrom(mp->m_source, (vir_bytes) mp->IO_GRANT,
|
|
||||||
0, (vir_bytes) &entry, sizeof(entry), D);
|
|
||||||
if(s != OK)
|
|
||||||
return s;
|
|
||||||
dv->dv_base = entry.base;
|
|
||||||
dv->dv_size = entry.size;
|
|
||||||
} else {
|
|
||||||
/* Return a partition table entry and the geometry of the drive. */
|
|
||||||
entry.base = dv->dv_base;
|
|
||||||
entry.size = dv->dv_size;
|
|
||||||
(*dp->dr_geometry)(&entry);
|
|
||||||
s=sys_safecopyto(mp->m_source, (vir_bytes) mp->IO_GRANT,
|
|
||||||
0, (vir_bytes) &entry, sizeof(entry), D);
|
|
||||||
if (OK != s)
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return(OK);
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
#ifndef _DRIVER_DRIVER_H
|
|
||||||
#define _DRIVER_DRIVER_H
|
|
||||||
|
|
||||||
_PROTOTYPE( void driver_handle_notify, (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( int driver_handle_request, (struct driver *dp, message *m_ptr) );
|
|
||||||
_PROTOTYPE( void driver_reply, (int driver_type, message *m_ptr,
|
|
||||||
int ipc_status, int reply) );
|
|
||||||
|
|
||||||
#endif /* _DRIVER_DRIVER_H */
|
|
|
@ -1,115 +0,0 @@
|
||||||
/* This file contains the singlethreaded device independent driver interface.
|
|
||||||
*
|
|
||||||
* Changes:
|
|
||||||
* Aug 27, 2011 extracted from driver.c (A. Welzel)
|
|
||||||
*
|
|
||||||
* The entry points into this file are:
|
|
||||||
* driver_task: the main message loop of the driver
|
|
||||||
* driver_terminate: break out of the main message loop
|
|
||||||
* driver_handle_msg: handle a single received message
|
|
||||||
* driver_receive: message receive interface for drivers
|
|
||||||
* driver_receive_mq: message receive interface; try the message queue first
|
|
||||||
* driver_mq_queue: queue an incoming message for later processing
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
|
||||||
#include <minix/driver.h>
|
|
||||||
|
|
||||||
#include "driver.h"
|
|
||||||
#include "mq.h"
|
|
||||||
|
|
||||||
PUBLIC endpoint_t device_endpt; /* used externally by log driver */
|
|
||||||
PRIVATE int driver_running;
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* driver_receive *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int driver_receive(endpoint_t src, message *m_ptr, int *status_ptr)
|
|
||||||
{
|
|
||||||
/* receive() interface for drivers. */
|
|
||||||
|
|
||||||
return sef_receive_status(src, m_ptr, status_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* driver_receive_mq *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int driver_receive_mq(message *m_ptr, int *status_ptr)
|
|
||||||
{
|
|
||||||
/* receive() interface for drivers with message queueing. */
|
|
||||||
|
|
||||||
/* Any queued messages? */
|
|
||||||
if (driver_mq_dequeue(DRIVER_MQ_SINGLE, m_ptr, status_ptr))
|
|
||||||
return OK;
|
|
||||||
|
|
||||||
/* Fall back to standard receive() interface otherwise. */
|
|
||||||
return driver_receive(ANY, m_ptr, status_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* driver_terminate *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC void driver_terminate(void)
|
|
||||||
{
|
|
||||||
/* Break out of the main driver loop after finishing the current request. */
|
|
||||||
|
|
||||||
driver_running = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* driver_task *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC void driver_task(dp, type)
|
|
||||||
struct driver *dp; /* Device dependent entry points. */
|
|
||||||
int type; /* Driver type (DRIVER_STD or DRIVER_ASYN) */
|
|
||||||
{
|
|
||||||
/* Main program of any device driver task. */
|
|
||||||
int r, ipc_status;
|
|
||||||
message mess;
|
|
||||||
|
|
||||||
driver_running = TRUE;
|
|
||||||
|
|
||||||
/* Here is the main loop of the disk task. It waits for a message, carries
|
|
||||||
* it out, and sends a reply.
|
|
||||||
*/
|
|
||||||
while (driver_running) {
|
|
||||||
if ((r = driver_receive_mq(&mess, &ipc_status)) != OK)
|
|
||||||
panic("driver_receive_mq failed: %d", r);
|
|
||||||
|
|
||||||
driver_handle_msg(dp, type, &mess, ipc_status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* driver_handle_msg *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC void driver_handle_msg(struct driver *dp, int driver_type,
|
|
||||||
message *m_ptr, int ipc_status)
|
|
||||||
{
|
|
||||||
/* Handle the given received message. */
|
|
||||||
int r;
|
|
||||||
|
|
||||||
/* Dirty hack: set a global variable for the log driver. */
|
|
||||||
device_endpt = m_ptr->USER_ENDPT;
|
|
||||||
|
|
||||||
/* Process the notification or request. */
|
|
||||||
if (is_ipc_notify(ipc_status)) {
|
|
||||||
driver_handle_notify(dp, m_ptr);
|
|
||||||
|
|
||||||
/* Do not reply to notifications. */
|
|
||||||
} else {
|
|
||||||
r = driver_handle_request(dp, m_ptr);
|
|
||||||
|
|
||||||
driver_reply(driver_type, m_ptr, ipc_status, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* driver_mq_queue *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int driver_mq_queue(message *m, int status)
|
|
||||||
{
|
|
||||||
/* Queue a message for later processing. */
|
|
||||||
|
|
||||||
return driver_mq_enqueue(DRIVER_MQ_SINGLE, m, status);
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
#ifndef _DRIVER_EVENT_H
|
|
||||||
#define _DRIVER_EVENT_H
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
mthread_mutex_t mutex;
|
|
||||||
mthread_cond_t cond;
|
|
||||||
} event_t;
|
|
||||||
|
|
||||||
_PROTOTYPE( void driver_event_init, (event_t *event) );
|
|
||||||
_PROTOTYPE( void driver_event_destroy, (event_t *event) );
|
|
||||||
_PROTOTYPE( void driver_event_wait, (event_t *event) );
|
|
||||||
_PROTOTYPE( void driver_event_fire, (event_t *event) );
|
|
||||||
|
|
||||||
#endif /* _DRIVER_EVENT_H */
|
|
|
@ -1,12 +0,0 @@
|
||||||
#ifndef _DRIVER_MQ_H
|
|
||||||
#define _DRIVER_MQ_H
|
|
||||||
|
|
||||||
#define DRIVER_MQ_SINGLE 0 /* thread ID for single-threading */
|
|
||||||
|
|
||||||
_PROTOTYPE( void driver_mq_init, (void) );
|
|
||||||
_PROTOTYPE( int driver_mq_enqueue, (thread_id_t thread_id, const message *mess,
|
|
||||||
int ipc_status) );
|
|
||||||
_PROTOTYPE( int driver_mq_dequeue, (thread_id_t thread_id, message *mess,
|
|
||||||
int *ipc_status) );
|
|
||||||
|
|
||||||
#endif /* _DRIVER_MQ_H */
|
|
|
@ -4,8 +4,8 @@ SRCS= open.c table.c inode.c main.c super.c link.c \
|
||||||
buffer.c read.c misc.c mount.c utility.c stadir.c \
|
buffer.c read.c misc.c mount.c utility.c stadir.c \
|
||||||
uds.c dev_uds.c
|
uds.c dev_uds.c
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS}
|
DPADD+= ${LIBSYS}
|
||||||
LDADD+= -ldriver -lsys
|
LDADD+= -lsys
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -135,8 +135,6 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||||
SELF_E = getprocnr();
|
SELF_E = getprocnr();
|
||||||
buf_pool();
|
buf_pool();
|
||||||
|
|
||||||
driver_announce();
|
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,11 @@
|
||||||
* Special character files also require I/O. The routines for these are here.
|
* Special character files also require I/O. The routines for these are here.
|
||||||
*
|
*
|
||||||
* The entry points in this file are:
|
* The entry points in this file are:
|
||||||
* dev_open: FS opens a device
|
* dev_open: open a character device
|
||||||
* dev_close: FS closes a device
|
* dev_reopen: reopen a character device after a driver crash
|
||||||
|
* dev_close: close a character device
|
||||||
|
* bdev_open: open a block device
|
||||||
|
* bdev_close: close a block device
|
||||||
* dev_io: FS does a read or write on a device
|
* dev_io: FS does a read or write on a device
|
||||||
* dev_status: FS processes callback request alert
|
* dev_status: FS processes callback request alert
|
||||||
* gen_opcl: generic call to a task to perform an open/close
|
* gen_opcl: generic call to a task to perform an open/close
|
||||||
|
@ -18,6 +21,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -52,9 +56,10 @@ PUBLIC int dev_open(
|
||||||
int flags /* mode bits and flags */
|
int flags /* mode bits and flags */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
/* Open a character device. */
|
||||||
int major, r;
|
int major, r;
|
||||||
|
|
||||||
/* Determine the major device number call the device class specific
|
/* Determine the major device number so as to call the device class specific
|
||||||
* open/close routine. (This is the only routine that must check the
|
* open/close routine. (This is the only routine that must check the
|
||||||
* device number for being in range. All others can trust this check.)
|
* device number for being in range. All others can trust this check.)
|
||||||
*/
|
*/
|
||||||
|
@ -75,7 +80,7 @@ PUBLIC int dev_reopen(
|
||||||
int flags /* mode bits and flags */
|
int flags /* mode bits and flags */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* Reopen a device after a failing device driver */
|
/* Reopen a character device after a failing device driver. */
|
||||||
|
|
||||||
int major, r;
|
int major, r;
|
||||||
struct dmap *dp;
|
struct dmap *dp;
|
||||||
|
@ -103,7 +108,7 @@ PUBLIC int dev_close(
|
||||||
int filp_no
|
int filp_no
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* Close a device */
|
/* Close a character device. */
|
||||||
int r, major;
|
int r, major;
|
||||||
|
|
||||||
/* See if driver is roughly valid. */
|
/* See if driver is roughly valid. */
|
||||||
|
@ -115,6 +120,90 @@ PUBLIC int dev_close(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* dev_open *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int bdev_open(dev_t dev, int access)
|
||||||
|
{
|
||||||
|
/* Open a block device. */
|
||||||
|
int major;
|
||||||
|
|
||||||
|
major = major(dev);
|
||||||
|
if (major < 0 || major >= NR_DEVICES) return(ENXIO);
|
||||||
|
if (dmap[major].dmap_driver == NONE) return(ENXIO);
|
||||||
|
|
||||||
|
return (*dmap[major].dmap_opcl)(BDEV_OPEN, dev, 0, access);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* bdev_close *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int bdev_close(dev_t dev)
|
||||||
|
{
|
||||||
|
/* Close a block device. */
|
||||||
|
int major;
|
||||||
|
|
||||||
|
major = major(dev);
|
||||||
|
if (major < 0 || major >= NR_DEVICES) return(ENXIO);
|
||||||
|
if (dmap[major].dmap_driver == NONE) return(ENXIO);
|
||||||
|
|
||||||
|
return (*dmap[major].dmap_opcl)(BDEV_CLOSE, dev, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* bdev_ioctl *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int bdev_ioctl(dev_t dev, endpoint_t proc_e, int req, void *buf)
|
||||||
|
{
|
||||||
|
/* Perform an I/O control operation on a block device. */
|
||||||
|
struct dmap *dp;
|
||||||
|
u32_t dummy;
|
||||||
|
cp_grant_id_t gid;
|
||||||
|
message dev_mess;
|
||||||
|
int op, major_dev, minor_dev;
|
||||||
|
|
||||||
|
major_dev = major(dev);
|
||||||
|
minor_dev = minor(dev);
|
||||||
|
|
||||||
|
/* Determine task dmap. */
|
||||||
|
dp = &dmap[major_dev];
|
||||||
|
if (dp->dmap_driver == NONE) {
|
||||||
|
printf("VFS: dev_io: no driver for major %d\n", major_dev);
|
||||||
|
return(ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up a grant if necessary. */
|
||||||
|
op = VFS_DEV_IOCTL;
|
||||||
|
(void) safe_io_conversion(dp->dmap_driver, &gid, &op, &proc_e, &buf, 0,
|
||||||
|
&dummy);
|
||||||
|
|
||||||
|
/* Set up the message passed to the task. */
|
||||||
|
memset(&dev_mess, 0, sizeof(dev_mess));
|
||||||
|
|
||||||
|
dev_mess.m_type = BDEV_IOCTL;
|
||||||
|
dev_mess.BDEV_MINOR = minor_dev;
|
||||||
|
dev_mess.BDEV_REQUEST = req;
|
||||||
|
dev_mess.BDEV_GRANT = gid;
|
||||||
|
dev_mess.BDEV_ID = 0;
|
||||||
|
|
||||||
|
/* Call the task. */
|
||||||
|
(*dp->dmap_io)(dp->dmap_driver, &dev_mess);
|
||||||
|
|
||||||
|
/* Clean up. */
|
||||||
|
if (GRANT_VALID(gid)) cpf_revoke(gid);
|
||||||
|
|
||||||
|
if (dp->dmap_driver == NONE) {
|
||||||
|
printf("VFS: block driver gone!?\n");
|
||||||
|
return(EIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the result. */
|
||||||
|
return(dev_mess.BDEV_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* find_suspended_ep *
|
* find_suspended_ep *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -418,36 +507,46 @@ PUBLIC int dev_io(
|
||||||
* gen_opcl *
|
* gen_opcl *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int gen_opcl(
|
PUBLIC int gen_opcl(
|
||||||
int op, /* operation, DEV_OPEN or DEV_CLOSE */
|
int op, /* operation, (B)DEV_OPEN or (B)DEV_CLOSE */
|
||||||
dev_t dev, /* device to open or close */
|
dev_t dev, /* device to open or close */
|
||||||
endpoint_t proc_e, /* process to open/close for */
|
endpoint_t proc_e, /* process to open/close for */
|
||||||
int flags /* mode bits and flags */
|
int flags /* mode bits and flags */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* Called from the dmap struct on opens & closes of special files.*/
|
/* Called from the dmap struct on opens & closes of special files.*/
|
||||||
int r, minor_dev, major_dev;
|
int r, minor_dev, major_dev, is_bdev;
|
||||||
struct dmap *dp;
|
struct dmap *dp;
|
||||||
message dev_mess;
|
message dev_mess;
|
||||||
|
|
||||||
/* Determine task dmap. */
|
/* Determine task dmap. */
|
||||||
major_dev = major(dev);
|
major_dev = major(dev);
|
||||||
minor_dev = minor(dev);
|
minor_dev = minor(dev);
|
||||||
if (major_dev < 0 || major_dev >= NR_DEVICES) return(ENXIO);
|
assert(major_dev >= 0 && major_dev < NR_DEVICES);
|
||||||
dp = &dmap[major_dev];
|
dp = &dmap[major_dev];
|
||||||
if (dp->dmap_driver == NONE) {
|
assert(dp->dmap_driver != NONE);
|
||||||
printf("VFS: gen_opcl: no driver for major %d\n", major_dev);
|
|
||||||
return(ENXIO);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
is_bdev = IS_BDEV_RQ(op);
|
||||||
|
|
||||||
|
if (is_bdev) {
|
||||||
|
memset(&dev_mess, 0, sizeof(dev_mess));
|
||||||
|
dev_mess.m_type = op;
|
||||||
|
dev_mess.BDEV_MINOR = minor_dev;
|
||||||
|
dev_mess.BDEV_ACCESS = flags;
|
||||||
|
dev_mess.BDEV_ID = 0;
|
||||||
|
} else {
|
||||||
dev_mess.m_type = op;
|
dev_mess.m_type = op;
|
||||||
dev_mess.DEVICE = minor_dev;
|
dev_mess.DEVICE = minor_dev;
|
||||||
dev_mess.USER_ENDPT = proc_e;
|
dev_mess.USER_ENDPT = proc_e;
|
||||||
dev_mess.COUNT = flags;
|
dev_mess.COUNT = flags;
|
||||||
|
}
|
||||||
|
|
||||||
/* Call the task. */
|
/* Call the task. */
|
||||||
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
|
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
|
||||||
if (r != OK) return(r);
|
if (r != OK) return(r);
|
||||||
|
|
||||||
|
if (is_bdev)
|
||||||
|
return(dev_mess.BDEV_STATUS);
|
||||||
|
else
|
||||||
return(dev_mess.REP_STATUS);
|
return(dev_mess.REP_STATUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,6 +565,8 @@ PUBLIC int tty_opcl(
|
||||||
int r;
|
int r;
|
||||||
register struct fproc *rfp;
|
register struct fproc *rfp;
|
||||||
|
|
||||||
|
assert(!IS_BDEV_RQ(op));
|
||||||
|
|
||||||
/* Add O_NOCTTY to the flags if this process is not a session leader, or
|
/* Add O_NOCTTY to the flags if this process is not a session leader, or
|
||||||
* if it already has a controlling tty, or if it is someone elses
|
* if it already has a controlling tty, or if it is someone elses
|
||||||
* controlling tty.
|
* controlling tty.
|
||||||
|
@ -505,6 +606,8 @@ PUBLIC int ctty_opcl(
|
||||||
* /dev/tty, the magic device that translates to the controlling tty.
|
* /dev/tty, the magic device that translates to the controlling tty.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
assert(!IS_BDEV_RQ(op));
|
||||||
|
|
||||||
return(fp->fp_tty == 0 ? ENXIO : OK);
|
return(fp->fp_tty == 0 ? ENXIO : OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,6 +655,9 @@ PUBLIC int do_ioctl()
|
||||||
suspend_reopen = (f->filp_state != FS_NORMAL);
|
suspend_reopen = (f->filp_state != FS_NORMAL);
|
||||||
dev = (dev_t) vp->v_sdev;
|
dev = (dev_t) vp->v_sdev;
|
||||||
|
|
||||||
|
if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL)
|
||||||
|
r = bdev_ioctl(dev, who_e, m_in.REQUEST, m_in.ADDRESS);
|
||||||
|
else
|
||||||
r = dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0),
|
r = dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0),
|
||||||
m_in.REQUEST, f->filp_flags, suspend_reopen);
|
m_in.REQUEST, f->filp_flags, suspend_reopen);
|
||||||
}
|
}
|
||||||
|
@ -572,13 +678,21 @@ message *mess_ptr; /* pointer to message for task */
|
||||||
/* All file system I/O ultimately comes down to I/O on major/minor device
|
/* All file system I/O ultimately comes down to I/O on major/minor device
|
||||||
* pairs. These lead to calls on the following routines via the dmap table.
|
* pairs. These lead to calls on the following routines via the dmap table.
|
||||||
*/
|
*/
|
||||||
|
int r, status, proc_e = NONE, is_bdev;
|
||||||
|
|
||||||
int r, proc_e;
|
is_bdev = IS_BDEV_RQ(mess_ptr->m_type);
|
||||||
|
|
||||||
proc_e = mess_ptr->USER_ENDPT;
|
if (!is_bdev) proc_e = mess_ptr->USER_ENDPT;
|
||||||
|
|
||||||
r = sendrec(driver_e, mess_ptr);
|
r = sendrec(driver_e, mess_ptr);
|
||||||
if (r == OK && mess_ptr->REP_STATUS == ERESTART) r = EDEADEPT;
|
if (r == OK) {
|
||||||
|
if (is_bdev)
|
||||||
|
status = mess_ptr->BDEV_STATUS;
|
||||||
|
else
|
||||||
|
status = mess_ptr->REP_STATUS;
|
||||||
|
if (status == ERESTART)
|
||||||
|
r = EDEADEPT;
|
||||||
|
}
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
if (r == EDEADSRCDST || r == EDEADEPT) {
|
if (r == EDEADSRCDST || r == EDEADEPT) {
|
||||||
printf("VFS: dead driver %d\n", driver_e);
|
printf("VFS: dead driver %d\n", driver_e);
|
||||||
|
@ -592,7 +706,7 @@ message *mess_ptr; /* pointer to message for task */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Did the process we did the sendrec() for get a result? */
|
/* Did the process we did the sendrec() for get a result? */
|
||||||
if (mess_ptr->REP_ENDPT != proc_e) {
|
if (!is_bdev && mess_ptr->REP_ENDPT != proc_e) {
|
||||||
printf("VFS: strange device reply from %d, type = %d, "
|
printf("VFS: strange device reply from %d, type = %d, "
|
||||||
"proc = %d (not %d) (2) ignored\n", mess_ptr->m_source,
|
"proc = %d (not %d) (2) ignored\n", mess_ptr->m_source,
|
||||||
mess_ptr->m_type, proc_e, mess_ptr->REP_ENDPT);
|
mess_ptr->m_type, proc_e, mess_ptr->REP_ENDPT);
|
||||||
|
@ -617,6 +731,8 @@ message *mess_ptr; /* pointer to message for task */
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(!IS_BDEV_RQ(mess_ptr->m_type));
|
||||||
|
|
||||||
fp->fp_sendrec = mess_ptr; /* Remember where result should be stored */
|
fp->fp_sendrec = mess_ptr; /* Remember where result should be stored */
|
||||||
r = asynsend3(task_nr, mess_ptr, AMF_NOREPLY);
|
r = asynsend3(task_nr, mess_ptr, AMF_NOREPLY);
|
||||||
|
|
||||||
|
@ -711,15 +827,14 @@ PUBLIC int clone_opcl(
|
||||||
int r, minor_dev, major_dev;
|
int r, minor_dev, major_dev;
|
||||||
message dev_mess;
|
message dev_mess;
|
||||||
|
|
||||||
|
assert(!IS_BDEV_RQ(op));
|
||||||
|
|
||||||
/* Determine task dmap. */
|
/* Determine task dmap. */
|
||||||
minor_dev = minor(dev);
|
minor_dev = minor(dev);
|
||||||
major_dev = major(dev);
|
major_dev = major(dev);
|
||||||
if (major_dev < 0 || major_dev >= NR_DEVICES) return(ENXIO);
|
assert(major_dev >= 0 && major_dev < NR_DEVICES);
|
||||||
dp = &dmap[major_dev];
|
dp = &dmap[major_dev];
|
||||||
if (dp->dmap_driver == NONE) {
|
assert(dp->dmap_driver != NONE);
|
||||||
printf("VFS clone_opcl: no driver for major %d\n", major_dev);
|
|
||||||
return(ENXIO);
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_mess.m_type = op;
|
dev_mess.m_type = op;
|
||||||
dev_mess.DEVICE = minor_dev;
|
dev_mess.DEVICE = minor_dev;
|
||||||
|
@ -789,23 +904,18 @@ PUBLIC int clone_opcl(
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dev_up *
|
* bdev_up *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void dev_up(int maj)
|
PUBLIC void bdev_up(int maj)
|
||||||
{
|
{
|
||||||
/* A new device driver has been mapped in. This function
|
/* A new block device driver has been mapped in. This may affect both mounted
|
||||||
* checks if any filesystems are mounted on it, and if so,
|
* file systems and open block-special files.
|
||||||
* dev_open()s them so the filesystem can be reused.
|
|
||||||
*/
|
*/
|
||||||
int r, new_driver_e, needs_reopen, fd_nr, found;
|
int r, new_driver_e, found;
|
||||||
struct filp *rfilp;
|
struct filp *rfilp;
|
||||||
struct vmnt *vmp;
|
struct vmnt *vmp;
|
||||||
struct fproc *rfp;
|
|
||||||
struct vnode *vp;
|
struct vnode *vp;
|
||||||
|
|
||||||
/* First deal with block devices. We need to consider both mounted file
|
|
||||||
* systems and open block-special files.
|
|
||||||
*/
|
|
||||||
if (maj < 0 || maj >= NR_DEVICES) panic("VFS: out-of-bound major");
|
if (maj < 0 || maj >= NR_DEVICES) panic("VFS: out-of-bound major");
|
||||||
new_driver_e = dmap[maj].dmap_driver;
|
new_driver_e = dmap[maj].dmap_driver;
|
||||||
|
|
||||||
|
@ -813,10 +923,7 @@ PUBLIC void dev_up(int maj)
|
||||||
* is currently useless, as driver endpoints do not change across restarts.
|
* is currently useless, as driver endpoints do not change across restarts.
|
||||||
*/
|
*/
|
||||||
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
|
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
|
||||||
int minor_dev, major_dev;
|
if (major(vmp->m_dev) != maj) continue;
|
||||||
major_dev = major(vmp->m_dev);
|
|
||||||
minor_dev = minor(vmp->m_dev);
|
|
||||||
if (major_dev != maj) continue;
|
|
||||||
|
|
||||||
/* Send the new driver endpoint to the mounted file system. */
|
/* Send the new driver endpoint to the mounted file system. */
|
||||||
if (OK != req_newdriver(vmp->m_fs_e, vmp->m_dev, new_driver_e))
|
if (OK != req_newdriver(vmp->m_fs_e, vmp->m_dev, new_driver_e))
|
||||||
|
@ -834,7 +941,7 @@ PUBLIC void dev_up(int maj)
|
||||||
if (!S_ISBLK(vp->v_mode)) continue;
|
if (!S_ISBLK(vp->v_mode)) continue;
|
||||||
|
|
||||||
/* Reopen the device on the driver, once per filp. */
|
/* Reopen the device on the driver, once per filp. */
|
||||||
if ((r = dev_open(vp->v_sdev, VFS_PROC_NR, rfilp->filp_mode)) != OK)
|
if ((r = bdev_open(vp->v_sdev, rfilp->filp_mode & O_ACCMODE)) != OK)
|
||||||
printf("VFS: mounted dev %d/%d re-open failed: %d.\n",
|
printf("VFS: mounted dev %d/%d re-open failed: %d.\n",
|
||||||
maj, minor(vp->v_sdev), r);
|
maj, minor(vp->v_sdev), r);
|
||||||
|
|
||||||
|
@ -851,9 +958,22 @@ PUBLIC void dev_up(int maj)
|
||||||
printf("VFSdev_up: error sending new driver endpoint."
|
printf("VFSdev_up: error sending new driver endpoint."
|
||||||
" FS_e: %d req_nr: %d\n", ROOT_FS_E, REQ_NEW_DRIVER);
|
" FS_e: %d req_nr: %d\n", ROOT_FS_E, REQ_NEW_DRIVER);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The rest of the code deals with character-special files. To start with,
|
|
||||||
* look for processes that are suspened in an OPEN call. Set FP_SUSP_REOPEN
|
/*===========================================================================*
|
||||||
|
* cdev_up *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC void cdev_up(int maj)
|
||||||
|
{
|
||||||
|
/* A new character device driver has been mapped in.
|
||||||
|
*/
|
||||||
|
int needs_reopen, fd_nr;
|
||||||
|
struct filp *rfilp;
|
||||||
|
struct fproc *rfp;
|
||||||
|
struct vnode *vp;
|
||||||
|
|
||||||
|
/* Look for processes that are suspened in an OPEN call. Set FP_SUSP_REOPEN
|
||||||
* to indicate that this process was suspended before the call to dev_up.
|
* to indicate that this process was suspended before the call to dev_up.
|
||||||
*/
|
*/
|
||||||
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
|
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
|
||||||
|
@ -884,7 +1004,6 @@ PUBLIC void dev_up(int maj)
|
||||||
|
|
||||||
if (needs_reopen)
|
if (needs_reopen)
|
||||||
restart_reopen(maj);
|
restart_reopen(maj);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
|
|
@ -232,17 +232,21 @@ PUBLIC int dmap_driver_match(endpoint_t proc, int major)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dmap_endpt_up *
|
* dmap_endpt_up *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void dmap_endpt_up(endpoint_t proc_e)
|
PUBLIC void dmap_endpt_up(endpoint_t proc_e, int is_blk)
|
||||||
{
|
{
|
||||||
/* A device driver with endpoint proc_e has been restarted. Go tell everyone
|
/* A device driver with endpoint proc_e has been restarted. Go tell everyone
|
||||||
* that might be blocking on it that this device is 'up'.
|
* that might be blocking on it that this device is 'up'.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int major;
|
int major;
|
||||||
for (major = 0; major < NR_DEVICES; major++)
|
for (major = 0; major < NR_DEVICES; major++) {
|
||||||
if (dmap_driver_match(proc_e, major))
|
if (dmap_driver_match(proc_e, major)) {
|
||||||
dev_up(major);
|
if (is_blk)
|
||||||
|
bdev_up(major);
|
||||||
|
else
|
||||||
|
cdev_up(major);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
|
|
@ -521,9 +521,15 @@ struct filp *f;
|
||||||
}
|
}
|
||||||
unlock_bsf();
|
unlock_bsf();
|
||||||
}
|
}
|
||||||
/* Do any special processing on device close. */
|
|
||||||
(void) dev_close(dev, f-filp); /* Ignore any errors, even
|
/* Do any special processing on device close.
|
||||||
* SUSPEND. */
|
* Ignore any errors, even SUSPEND.
|
||||||
|
*/
|
||||||
|
if (mode_word == I_BLOCK_SPECIAL)
|
||||||
|
(void) bdev_close(dev);
|
||||||
|
else
|
||||||
|
(void) dev_close(dev, f-filp);
|
||||||
|
|
||||||
f->filp_mode = FILP_CLOSED;
|
f->filp_mode = FILP_CLOSED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -538,10 +538,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Subscribe to driver events for VFS drivers. */
|
/* Subscribe to block and character driver events. */
|
||||||
if ((s = ds_subscribe("drv\\.vfs\\..*", DSF_INITIAL | DSF_OVERWRITE) != OK)){
|
s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE);
|
||||||
panic("VFS: can't subscribe to driver events (%d)", s);
|
if (s != OK) panic("VFS: can't subscribe to driver events (%d)", s);
|
||||||
}
|
|
||||||
|
|
||||||
#if DO_SANITYCHECKS
|
#if DO_SANITYCHECKS
|
||||||
FIXME("VFS: DO_SANITYCHECKS is on");
|
FIXME("VFS: DO_SANITYCHECKS is on");
|
||||||
|
|
|
@ -600,28 +600,35 @@ struct mem_map *seg_ptr;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* ds_event *
|
* ds_event *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void ds_event()
|
PUBLIC void ds_event(void)
|
||||||
{
|
{
|
||||||
char key[DS_MAX_KEYLEN];
|
char key[DS_MAX_KEYLEN];
|
||||||
char *drv_prefix = "drv.vfs.";
|
char *blkdrv_prefix = "drv.blk.";
|
||||||
|
char *chrdrv_prefix = "drv.chr.";
|
||||||
u32_t value;
|
u32_t value;
|
||||||
int type, r;
|
int type, r, is_blk;
|
||||||
endpoint_t owner_endpoint;
|
endpoint_t owner_endpoint;
|
||||||
|
|
||||||
/* Get the event and the owner from DS. */
|
/* Get the event and the owner from DS. */
|
||||||
if ((r = ds_check(key, &type, &owner_endpoint)) != OK) {
|
while ((r = ds_check(key, &type, &owner_endpoint)) == OK) {
|
||||||
if(r != ENOENT) printf("VFS: ds_event: ds_check failed: %d\n", r);
|
/* Only check for block and character driver up events. */
|
||||||
return;
|
if (!strncmp(key, blkdrv_prefix, strlen(blkdrv_prefix))) {
|
||||||
|
is_blk = TRUE;
|
||||||
|
} else if (!strncmp(key, chrdrv_prefix, strlen(chrdrv_prefix))) {
|
||||||
|
is_blk = FALSE;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((r = ds_retrieve_u32(key, &value)) != OK) {
|
if ((r = ds_retrieve_u32(key, &value)) != OK) {
|
||||||
printf("VFS: ds_event: ds_retrieve_u32 failed\n");
|
printf("VFS: ds_event: ds_retrieve_u32 failed\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (value != DS_DRIVER_UP) continue;
|
||||||
/* Only check for VFS driver up events. */
|
|
||||||
if (strncmp(key, drv_prefix, sizeof(drv_prefix)) || value != DS_DRIVER_UP)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Perform up. */
|
/* Perform up. */
|
||||||
dmap_endpt_up(owner_endpoint);
|
dmap_endpt_up(owner_endpoint, is_blk);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r != ENOENT) printf("VFS: ds_event: ds_check failed: %d\n", r);
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,12 +169,21 @@ PRIVATE int common_open(char path[PATH_MAX], int oflags, mode_t omode)
|
||||||
|
|
||||||
/* Invoke the driver for special processing. */
|
/* Invoke the driver for special processing. */
|
||||||
dev = (dev_t) vp->v_sdev;
|
dev = (dev_t) vp->v_sdev;
|
||||||
r = dev_open(dev, who_e, bits | (oflags & ~O_ACCMODE));
|
r = bdev_open(dev, bits);
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
unlock_bsf();
|
unlock_bsf();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
major_dev = major(vp->v_sdev);
|
||||||
|
dp = &dmap[major_dev];
|
||||||
|
if (dp->dmap_driver == NONE) {
|
||||||
|
printf("VFS: block driver disappeared!\n");
|
||||||
|
unlock_bsf();
|
||||||
|
r = ENXIO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check whether the device is mounted or not. If so,
|
/* Check whether the device is mounted or not. If so,
|
||||||
* then that FS is responsible for this device. Else
|
* then that FS is responsible for this device. Else
|
||||||
* we default to ROOT_FS. */
|
* we default to ROOT_FS. */
|
||||||
|
@ -185,29 +194,21 @@ PRIVATE int common_open(char path[PATH_MAX], int oflags, mode_t omode)
|
||||||
vp->v_bfs_e = vmp->m_fs_e;
|
vp->v_bfs_e = vmp->m_fs_e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the driver endpoint of the block spec device */
|
/* Send the driver endpoint to the file system that
|
||||||
major_dev = major(vp->v_sdev);
|
* will handle the block I/O requests (even when its
|
||||||
if (major_dev < 0 || major_dev >= NR_DEVICES)
|
* endpoint is known already), but only when it is the
|
||||||
r = ENXIO;
|
* root file system. Other file systems will already
|
||||||
else
|
* have it anyway.
|
||||||
dp = &dmap[major_dev];
|
*/
|
||||||
if (r != OK || dp->dmap_driver == NONE) {
|
if (vp->v_bfs_e != ROOT_FS_E) {
|
||||||
printf("VFS: driver not found for device %d\n",
|
|
||||||
vp->v_sdev);
|
|
||||||
r = ENXIO;
|
|
||||||
unlock_bsf();
|
unlock_bsf();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the driver endpoint (even when known already)*/
|
if (req_newdriver(vp->v_bfs_e, vp->v_sdev,
|
||||||
if (vp->v_bfs_e != ROOT_FS_E) {
|
dp->dmap_driver) != OK) {
|
||||||
/* but only when it's the ROOT_FS */
|
|
||||||
unlock_bsf();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev,
|
|
||||||
dp->dmap_driver)) != OK) {
|
|
||||||
printf("VFS: error sending driver endpoint\n");
|
printf("VFS: error sending driver endpoint\n");
|
||||||
|
bdev_close(dev);
|
||||||
r = ENXIO;
|
r = ENXIO;
|
||||||
}
|
}
|
||||||
unlock_bsf();
|
unlock_bsf();
|
||||||
|
|
|
@ -29,6 +29,8 @@ _PROTOTYPE(void send_work, (void) );
|
||||||
_PROTOTYPE( int dev_open, (dev_t dev, endpoint_t proc_e, int flags) );
|
_PROTOTYPE( int dev_open, (dev_t dev, endpoint_t proc_e, int flags) );
|
||||||
_PROTOTYPE( int dev_reopen, (dev_t dev, int filp_no, int flags) );
|
_PROTOTYPE( int dev_reopen, (dev_t dev, int filp_no, int flags) );
|
||||||
_PROTOTYPE( int dev_close, (dev_t dev, int filp_no) );
|
_PROTOTYPE( int dev_close, (dev_t dev, int filp_no) );
|
||||||
|
_PROTOTYPE( int bdev_open, (dev_t dev, int access) );
|
||||||
|
_PROTOTYPE( int bdev_close, (dev_t dev) );
|
||||||
_PROTOTYPE( int dev_io, (int op, dev_t dev, endpoint_t proc_e, void *buf,
|
_PROTOTYPE( int dev_io, (int op, dev_t dev, endpoint_t proc_e, void *buf,
|
||||||
u64_t pos, size_t bytes, int flags, int suspend_reopen) );
|
u64_t pos, size_t bytes, int flags, int suspend_reopen) );
|
||||||
_PROTOTYPE( int gen_opcl, (int op, dev_t dev, endpoint_t task_nr, int flags));
|
_PROTOTYPE( int gen_opcl, (int op, dev_t dev, endpoint_t task_nr, int flags));
|
||||||
|
@ -43,7 +45,8 @@ _PROTOTYPE( int ctty_io, (int task_nr, message *mess_ptr) );
|
||||||
_PROTOTYPE( int do_ioctl, (void) );
|
_PROTOTYPE( int do_ioctl, (void) );
|
||||||
_PROTOTYPE( void pm_setsid, (int proc_e) );
|
_PROTOTYPE( void pm_setsid, (int proc_e) );
|
||||||
_PROTOTYPE( void dev_status, (message *) );
|
_PROTOTYPE( void dev_status, (message *) );
|
||||||
_PROTOTYPE( void dev_up, (int major) );
|
_PROTOTYPE( void bdev_up, (int major) );
|
||||||
|
_PROTOTYPE( void cdev_up, (int major) );
|
||||||
_PROTOTYPE( endpoint_t find_suspended_ep, (endpoint_t driver,
|
_PROTOTYPE( endpoint_t find_suspended_ep, (endpoint_t driver,
|
||||||
cp_grant_id_t g) );
|
cp_grant_id_t g) );
|
||||||
_PROTOTYPE( void reopen_reply, (void) );
|
_PROTOTYPE( void reopen_reply, (void) );
|
||||||
|
@ -53,7 +56,7 @@ _PROTOTYPE( void open_reply, (void) );
|
||||||
_PROTOTYPE( int do_mapdriver, (void) );
|
_PROTOTYPE( int do_mapdriver, (void) );
|
||||||
_PROTOTYPE( void init_dmap, (void) );
|
_PROTOTYPE( void init_dmap, (void) );
|
||||||
_PROTOTYPE( int dmap_driver_match, (endpoint_t proc, int major) );
|
_PROTOTYPE( int dmap_driver_match, (endpoint_t proc, int major) );
|
||||||
_PROTOTYPE( void dmap_endpt_up, (int proc_nr) );
|
_PROTOTYPE( void dmap_endpt_up, (int proc_nr, int is_blk) );
|
||||||
_PROTOTYPE( void dmap_unmap_by_endpt, (int proc_nr) );
|
_PROTOTYPE( void dmap_unmap_by_endpt, (int proc_nr) );
|
||||||
_PROTOTYPE( struct dmap *get_dmap, (endpoint_t proc_e) );
|
_PROTOTYPE( struct dmap *get_dmap, (endpoint_t proc_e) );
|
||||||
_PROTOTYPE( int do_mapdriver, (void) );
|
_PROTOTYPE( int do_mapdriver, (void) );
|
||||||
|
|
|
@ -307,7 +307,7 @@ PRIVATE void rw_block(
|
||||||
printf("Ext2(%d) I/O error on device %d/%d, block %u\n",
|
printf("Ext2(%d) I/O error on device %d/%d, block %u\n",
|
||||||
SELF_E, major(dev), minor(dev), bp->b_blocknr);
|
SELF_E, major(dev), minor(dev), bp->b_blocknr);
|
||||||
op_failed = 1;
|
op_failed = 1;
|
||||||
} else if( (unsigned) r != fs_block_size) {
|
} else if (r != (ssize_t) fs_block_size) {
|
||||||
r = END_OF_FILE;
|
r = END_OF_FILE;
|
||||||
op_failed = 1;
|
op_failed = 1;
|
||||||
}
|
}
|
||||||
|
@ -387,7 +387,6 @@ PUBLIC void rw_scattered(
|
||||||
register int i;
|
register int i;
|
||||||
register iovec_t *iop;
|
register iovec_t *iop;
|
||||||
static iovec_t *iovec = NULL;
|
static iovec_t *iovec = NULL;
|
||||||
vir_bytes size;
|
|
||||||
u64_t pos;
|
u64_t pos;
|
||||||
int j, r;
|
int j, r;
|
||||||
|
|
||||||
|
@ -423,21 +422,22 @@ PUBLIC void rw_scattered(
|
||||||
}
|
}
|
||||||
pos = mul64u(bufq[0]->b_blocknr, fs_block_size);
|
pos = mul64u(bufq[0]->b_blocknr, fs_block_size);
|
||||||
if (rw_flag == READING)
|
if (rw_flag == READING)
|
||||||
r = bdev_gather(dev, pos, iovec, j, BDEV_NOFLAGS, &size);
|
r = bdev_gather(dev, pos, iovec, j, BDEV_NOFLAGS);
|
||||||
else
|
else
|
||||||
r = bdev_scatter(dev, pos, iovec, j, BDEV_NOFLAGS, &size);
|
r = bdev_scatter(dev, pos, iovec, j, BDEV_NOFLAGS);
|
||||||
|
|
||||||
/* Harvest the results. Dev_io reports the first error it may have
|
/* Harvest the results. The driver may have returned an error, or it
|
||||||
* encountered, but we only care if it's the first block that failed.
|
* may have done less than what we asked for.
|
||||||
*/
|
*/
|
||||||
for (i = 0, iop = iovec; i < j; i++, iop++) {
|
if (r < 0) {
|
||||||
|
printf("ext2: I/O error %d on device %d/%d, block %u\n",
|
||||||
|
r, major(dev), minor(dev), bufq[0]->b_blocknr);
|
||||||
|
}
|
||||||
|
for (i = 0; i < j; i++) {
|
||||||
bp = bufq[i];
|
bp = bufq[i];
|
||||||
if (size < iop->iov_size) {
|
if (r < (ssize_t) fs_block_size) {
|
||||||
/* Transfer failed. An error? Do we care? */
|
/* Transfer failed. */
|
||||||
if (r != OK && i == 0) {
|
if (i == 0) {
|
||||||
printf(
|
|
||||||
"fs: I/O error on device %d/%d, block %u\n",
|
|
||||||
major(dev), minor(dev), bp->b_blocknr);
|
|
||||||
bp->b_dev = NO_DEV; /* invalidate block */
|
bp->b_dev = NO_DEV; /* invalidate block */
|
||||||
vm_forgetblocks();
|
vm_forgetblocks();
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ PUBLIC void rw_scattered(
|
||||||
} else {
|
} else {
|
||||||
bp->b_dirt = CLEAN;
|
bp->b_dirt = CLEAN;
|
||||||
}
|
}
|
||||||
size -= iop->iov_size;
|
r -= fs_block_size;
|
||||||
}
|
}
|
||||||
bufq += i;
|
bufq += i;
|
||||||
bufqsize -= i;
|
bufqsize -= i;
|
||||||
|
|
|
@ -180,7 +180,7 @@ register struct super_block *sp; /* pointer to a superblock */
|
||||||
|
|
||||||
r = bdev_read(dev, cvu64(gdt_position), (char*) ondisk_group_descs,
|
r = bdev_read(dev, cvu64(gdt_position), (char*) ondisk_group_descs,
|
||||||
gd_size, BDEV_NOFLAGS);
|
gd_size, BDEV_NOFLAGS);
|
||||||
if (r != gd_size) {
|
if (r != (ssize_t) gd_size) {
|
||||||
printf("Can not read group descriptors\n");
|
printf("Can not read group descriptors\n");
|
||||||
return(EINVAL);
|
return(EINVAL);
|
||||||
}
|
}
|
||||||
|
@ -251,7 +251,7 @@ struct super_block *sp; /* pointer to a superblock */
|
||||||
|
|
||||||
r = bdev_write(sp->s_dev, cvu64(gdt_position),
|
r = bdev_write(sp->s_dev, cvu64(gdt_position),
|
||||||
(char*) ondisk_group_descs, gd_size, BDEV_NOFLAGS);
|
(char*) ondisk_group_descs, gd_size, BDEV_NOFLAGS);
|
||||||
if (r != gd_size) {
|
if (r != (ssize_t) gd_size) {
|
||||||
printf("Can not write group descriptors\n");
|
printf("Can not write group descriptors\n");
|
||||||
}
|
}
|
||||||
group_descriptors_dirty = CLEAN;
|
group_descriptors_dirty = CLEAN;
|
||||||
|
@ -275,7 +275,7 @@ struct group_desc* get_group_desc(unsigned int bnum)
|
||||||
PRIVATE u32_t ext2_count_dirs(struct super_block *sp)
|
PRIVATE u32_t ext2_count_dirs(struct super_block *sp)
|
||||||
{
|
{
|
||||||
u32_t count = 0;
|
u32_t count = 0;
|
||||||
int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < sp->s_groups_count; i++) {
|
for (i = 0; i < sp->s_groups_count; i++) {
|
||||||
struct group_desc *desc = get_group_desc(i);
|
struct group_desc *desc = get_group_desc(i);
|
||||||
|
@ -441,7 +441,7 @@ PRIVATE void copy_group_descriptors(
|
||||||
unsigned int ngroups
|
unsigned int ngroups
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int i;
|
unsigned int i;
|
||||||
for (i = 0; i < ngroups; i++)
|
for (i = 0; i < ngroups; i++)
|
||||||
gd_copy(&dest_array[i], &source_array[i]);
|
gd_copy(&dest_array[i], &source_array[i]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ SRCS= buf.c clock.c inet.c inet_config.c \
|
||||||
|
|
||||||
.PATH: ${.CURDIR}/generic
|
.PATH: ${.CURDIR}/generic
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBMINIXUTIL}
|
DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBMINIXUTIL}
|
||||||
LDADD+= -ldriver -lsys -lminixutil
|
LDADD+= -lchardriver -lsys -lminixutil
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ from DL_ETH:
|
||||||
#include <sys/svrctl.h>
|
#include <sys/svrctl.h>
|
||||||
#include <minix/ds.h>
|
#include <minix/ds.h>
|
||||||
#include <minix/endpoint.h>
|
#include <minix/endpoint.h>
|
||||||
#include <minix/driver.h>
|
#include <minix/chardriver.h>
|
||||||
|
|
||||||
#include "mq.h"
|
#include "mq.h"
|
||||||
#include "qp.h"
|
#include "qp.h"
|
||||||
|
@ -282,9 +282,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Announce we are up. INET announces its presence to VFS just like
|
/* Announce we are up. INET announces its presence to VFS just like
|
||||||
* any other driver.
|
* any other character driver.
|
||||||
*/
|
*/
|
||||||
driver_announce();
|
chardriver_announce();
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ register struct buf *bp; /* buffer pointer */
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
u64_t pos;
|
u64_t pos;
|
||||||
int block_size;
|
vir_bytes block_size;
|
||||||
|
|
||||||
block_size = v_pri.logical_block_size_l; /* The block size is indicated by
|
block_size = v_pri.logical_block_size_l; /* The block size is indicated by
|
||||||
* the superblock */
|
* the superblock */
|
||||||
|
@ -100,10 +100,9 @@ register struct buf *bp; /* buffer pointer */
|
||||||
|
|
||||||
pos = mul64u(bp->b_blocknr, block_size); /* get absolute position */
|
pos = mul64u(bp->b_blocknr, block_size); /* get absolute position */
|
||||||
r = bdev_read(fs_dev, pos, bp->b_data, block_size, BDEV_NOFLAGS);
|
r = bdev_read(fs_dev, pos, bp->b_data, block_size, BDEV_NOFLAGS);
|
||||||
if (r != block_size) {
|
if (r != (ssize_t) block_size) {
|
||||||
if (r >= 0) r = END_OF_FILE;
|
if (r == OK) r = END_OF_FILE;
|
||||||
if (r != END_OF_FILE)
|
else printf("ISOFS(%d) I/O error on device %d/%d, block %u\n",
|
||||||
printf("ISOFS(%d) I/O error on device %d/%d, block %u\n",
|
|
||||||
SELF_E, (fs_dev>>MAJOR)&BYTE, (fs_dev>>MINOR)&BYTE,
|
SELF_E, (fs_dev>>MAJOR)&BYTE, (fs_dev>>MINOR)&BYTE,
|
||||||
bp->b_blocknr);
|
bp->b_blocknr);
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ SRCS= lwip.c \
|
||||||
|
|
||||||
.PATH: ${.CURDIR}/generic
|
.PATH: ${.CURDIR}/generic
|
||||||
|
|
||||||
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBMINIXUTIL} ${LIBLWIP}
|
DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBMINIXUTIL} ${LIBTIMERS} ${LIBLWIP}
|
||||||
LDADD+= -ldriver -lsys -lminixutil -ltimers -llwip
|
LDADD+= -lchardriver -lsys -lminixutil -ltimers -llwip
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <minix/chardriver.h>
|
||||||
#include <minix/syslib.h>
|
#include <minix/syslib.h>
|
||||||
#include <minix/sysutil.h>
|
#include <minix/sysutil.h>
|
||||||
#include <minix/timers.h>
|
#include <minix/timers.h>
|
||||||
|
@ -29,29 +30,6 @@ static int arp_ticks, tcp_fticks, tcp_sticks;
|
||||||
|
|
||||||
static struct netif * netif_lo;
|
static struct netif * netif_lo;
|
||||||
|
|
||||||
static void driver_announce()
|
|
||||||
{
|
|
||||||
/* Announce we are up after a fresh start or restart. */
|
|
||||||
int err;
|
|
||||||
char key[DS_MAX_KEYLEN];
|
|
||||||
char label[DS_MAX_KEYLEN];
|
|
||||||
char *driver_prefix = "drv.vfs.";
|
|
||||||
|
|
||||||
/* Callers are allowed to use sendrec to communicate with drivers.
|
|
||||||
* For this reason, there may blocked callers when a driver restarts.
|
|
||||||
* Ask the kernel to unblock them (if any).
|
|
||||||
*/
|
|
||||||
if ((err = sys_statectl(SYS_STATE_CLEAR_IPC_REFS)) != OK)
|
|
||||||
panic("LWIP : sys_statectl failed: %d\n", err);
|
|
||||||
|
|
||||||
/* Publish a driver up event. */
|
|
||||||
if ((err = ds_retrieve_label_name(label, getprocnr())) != OK)
|
|
||||||
panic("LWIP : unable to get own label: %d\n", err);
|
|
||||||
snprintf(key, DS_MAX_KEYLEN, "%s%s", driver_prefix, label);
|
|
||||||
if ((err = ds_publish_u32(key, DS_DRIVER_UP, DSF_OVERWRITE)))
|
|
||||||
panic("LWIP : unable to publish driver up event: %d\n", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sys_init(void)
|
void sys_init(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -155,10 +133,10 @@ static int sef_cb_init_fresh(__unused int type, __unused sef_init_info_t *info)
|
||||||
DSF_INITIAL | DSF_OVERWRITE)) != OK)
|
DSF_INITIAL | DSF_OVERWRITE)) != OK)
|
||||||
panic(("inet: can't subscribe to driver events"));
|
panic(("inet: can't subscribe to driver events"));
|
||||||
|
|
||||||
/* Announce we are up. INET announces its presence to VFS just like
|
/* Announce we are up. LWIP announces its presence to VFS just like
|
||||||
* any other driver.
|
* any other character driver.
|
||||||
*/
|
*/
|
||||||
driver_announce();
|
chardriver_announce();
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue