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:
David van Moolenbroek 2011-11-22 13:27:53 +01:00
parent 7643f2b25e
commit b4d909d415
114 changed files with 2682 additions and 2148 deletions

View file

@ -5,11 +5,11 @@
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 \
minix/bdev.h \
minix/callnr.h minix/com.h minix/compiler.h minix/config.h \
minix/const.h minix/cpufeature.h minix/crtso.h minix/debug.h \
minix/devio.h minix/devman.h minix/dmap.h minix/driver.h \
minix/driver_mt.h minix/drivers.h minix/drvlib.h minix/ds.h \
minix/bdev.h minix/blockdriver.h minix/blockdriver_mt.h \
minix/callnr.h minix/chardriver.h minix/com.h minix/compiler.h \
minix/config.h minix/const.h minix/cpufeature.h minix/crtso.h \
minix/debug.h minix/devio.h minix/devman.h minix/dmap.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/ioctl.h minix/input.h minix/ipc.h minix/ipcconst.h \
minix/keymap.h minix/limits.h minix/mthread.h minix/minlib.h \

View file

@ -2,7 +2,7 @@
#define AUDIO_FW_H
#include <minix/drivers.h>
#include <minix/driver.h>
#include <minix/chardriver.h>
#include <sys/ioc_sound.h>

View file

@ -1,19 +1,19 @@
#ifndef __MINIX_BDEV_H
#define __MINIX_BDEV_H
#define BDEV_NOFLAGS 0
extern void bdev_driver(dev_t dev, endpoint_t endpt);
extern int bdev_open(dev_t dev, int access);
extern int bdev_close(dev_t dev);
extern int bdev_read(dev_t dev, u64_t pos, char *buf, int count, int flags);
extern int bdev_write(dev_t dev, u64_t pos, char *buf, int count, int flags);
extern int bdev_gather(dev_t dev, u64_t pos, iovec_t *vec, int count,
int flags, vir_bytes *size);
extern int bdev_scatter(dev_t dev, u64_t pos, iovec_t *vec, int count,
int flags, vir_bytes *size);
extern ssize_t bdev_read(dev_t dev, u64_t pos, char *buf, size_t count,
int flags);
extern ssize_t bdev_write(dev_t dev, u64_t pos, char *buf, size_t count,
int flags);
extern ssize_t bdev_gather(dev_t dev, u64_t pos, iovec_t *vec, int count,
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);
#endif /* __MINIX_BDEV_H */

View 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 */

View 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 */

View 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 */

View file

@ -8,8 +8,8 @@
* 1 - 0xFF POSIX requests (see callnr.h)
* 0x200 - 0x2FF Data link layer requests and responses
* 0x300 - 0x3FF Bus controller requests and responses
* 0x400 - 0x4FF Block and character device requests
* 0x500 - 0x5FF Block and character device responses
* 0x400 - 0x4FF Character device requests
* 0x500 - 0x5FF Character device responses
* 0x600 - 0x6FF Kernel calls to SYSTEM task
* 0x700 - 0x7FF Reincarnation Server (RS) requests
* 0x800 - 0x8FF Data Store (DS) requests
@ -25,6 +25,7 @@
* 0x1200 - 0x12FF Devman
* 0x1300 - 0x13FF TTY Input
* 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.
*/
@ -182,12 +183,12 @@
/*===========================================================================*
* Messages for BLOCK and CHARACTER device drivers *
* Messages for CHARACTER device drivers *
*===========================================================================*/
/* Message types for device drivers. */
#define DEV_RQ_BASE 0x400 /* base for device request types */
#define DEV_RS_BASE 0x500 /* base for device response types */
/* Message types for character device drivers. */
#define DEV_RQ_BASE 0x400 /* base for character device request types */
#define DEV_RS_BASE 0x500 /* base for character device response types */
#define CANCEL (DEV_RQ_BASE + 0) /* force a task to cancel */
#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)
/* 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 USER_ENDPT m2_i2 /* which endpoint initiated this call? */
#define COUNT m2_i3 /* how many bytes to transfer */
@ -225,7 +226,7 @@
#define ADDRESS m2_p1 /* core buffer address */
#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_SEL_OPS m2_i2 /* which select operations are requested */
@ -1216,4 +1217,43 @@
#define VFS_TRANSID (VFS_TRANSACTION_BASE + 1)
#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 */

View file

@ -28,8 +28,8 @@ typedef struct { u16_t port; u32_t value; } pvl_pair_t;
(pv).port = _p; \
(pv).value = _v; \
if((pv).port != _p || (pv).value != _v) { \
printf("%s:%d: actual port: 0x%x != 0x%lx || " \
"actual value: 0x%x != 0x%lx\n", \
printf("%s:%d: actual port: 0x%x != 0x%x || " \
"actual value: 0x%x != 0x%x\n", \
__FILE__, __LINE__, (pv).port, _p, (pv).value, _v); \
panic("pv_set(" #pv ", " #p ", " #v ")"); \
} \

View file

@ -1,9 +1,7 @@
#ifndef __MINIX_DRIVER_H__
#define __MINIX_DRIVER_H__
#ifndef _MINIX_DRIVER_H
#define _MINIX_DRIVER_H
/* Types and constants shared between the generic and device dependent
* device driver code.
*/
/* Types and constants shared between block and character drivers. */
#define _POSIX_SOURCE 1 /* tell headers to include POSIX stuff */
#define _MINIX 1 /* tell headers to include MINIX stuff */
@ -21,36 +19,13 @@
#include <minix/syslib.h>
#include <minix/sysutil.h>
#include <minix/endpoint.h>
#include <string.h>
#include <limits.h>
#include <stddef.h>
#include <errno.h>
#include <sys/param.h>
#include <minix/partition.h>
#include <minix/u64.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) );
};
#include <minix/partition.h>
/* Base and size of a partition in bytes. */
struct device {
@ -58,52 +33,12 @@ struct device {
u64_t dv_size;
};
#define DRIVER_STD 0 /* Use the standard reply protocol */
#define DRIVER_ASYN 1 /* Use the new asynchronous protocol */
/* Generic receive function for all drivers. */
#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 IS_DEV_MINOR_RQ(type) (IS_DEV_RQ(type) && (type) != DEV_STATUS)
/* 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__ */
#endif /* _MINIX_DRIVER_H */

View file

@ -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 */

View file

@ -4,19 +4,9 @@
#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 MINOR_t0 64
#define MINOR_r0 120

View file

@ -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 {long m9l1, m9l2, m9l3, m9l4, m9l5;
short m9s1, m9s2, m9s3, m9s4; } mess_9;
typedef struct {int m10i1, m10i2, m10i3, m10i4;
long m10l1, m10l2, m10l3; } mess_10;
typedef struct {
endpoint_t m_source; /* who sent the message */
@ -43,6 +45,7 @@ typedef struct {
mess_8 m_m8;
mess_6 m_m6;
mess_9 m_m9;
mess_10 m_m10;
} m_u;
} message;
@ -118,6 +121,14 @@ typedef struct {
#define m9_s3 m_u.m_m9.m9s3
#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). *
*==========================================================================*/

View file

@ -138,8 +138,8 @@ ACPICA_SRCS= \
SRCS+=${ACPICA_SRCS}
DPADD+= ${LIBDRIVER} ${LIBSYS}
LDADD+= -ldriver -lsys
DPADD+= ${LIBSYS}
LDADD+= -lsys
CPPFLAGS += -I${.CURDIR}/include
CFLAGS += -DACPI_LIBRARY

View file

@ -2,8 +2,12 @@
PROG= ahci
SRCS= ahci.c
DPADD+= ${LIBDRIVER} ${LIBSYS}
LDADD+= -ldriver -lsys -ltimers -lmthread
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS} ${LIBTIMERS} ${LIBMTHREAD}
LDADD+= -lblockdriver -lsys -ltimers -lmthread
.if ${COMPILER_TYPE} == "gnu"
LDADD+= -lc
.endif
MAN=

View file

@ -104,7 +104,7 @@
* vectors completely filled with 64KB-blocks.
*/
#include <minix/drivers.h>
#include <minix/driver_mt.h>
#include <minix/blockdriver_mt.h>
#include <minix/drvlib.h>
#include <machine/pci.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 struct port_state *current_port; /* currently selected port */
PRIVATE struct device *current_dev; /* currently selected device */
#define dprintf(v,s) do { \
if (ahci_verbose >= (v)) \
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_disconnect(struct port_state *ps);
PRIVATE char *ahci_name(void);
PRIVATE char *ahci_portname(struct port_state *ps);
PRIVATE int ahci_open(struct driver *UNUSED(dp), message *m);
PRIVATE int ahci_close(struct driver *UNUSED(dp), message *m);
PRIVATE struct device *ahci_prepare(int minor);
PRIVATE int ahci_transfer(endpoint_t endpt, int opcode, u64_t position,
iovec_t *iovec, unsigned int nr_req);
PRIVATE void ahci_geometry(struct partition *part);
PRIVATE void ahci_alarm(struct driver *UNUSED(dp), message *m);
PRIVATE int ahci_other(struct driver *UNUSED(dp), message *m);
PRIVATE void ahci_intr(struct driver *UNUSED(dp), message *m);
PRIVATE int ahci_open(dev_t minor, int access);
PRIVATE int ahci_close(dev_t minor);
PRIVATE ssize_t ahci_transfer(dev_t minor, int do_write, u64_t position,
endpoint_t endpt, iovec_t *iovec, unsigned int count,
int flags);
PRIVATE struct device *ahci_part(dev_t minor);
PRIVATE void ahci_alarm(clock_t stamp);
PRIVATE int ahci_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
cp_grant_id_t grant);
PRIVATE void ahci_intr(unsigned int irqs);
PRIVATE int ahci_thread(dev_t minor, thread_id_t *id);
PRIVATE struct port_state *ahci_get_port(dev_t minor);
/* AHCI driver table. */
PRIVATE struct driver ahci_dtab = {
ahci_name,
PRIVATE struct blockdriver ahci_dtab = {
ahci_open,
ahci_close,
do_diocntl,
ahci_prepare,
ahci_transfer,
nop_cleanup,
ahci_geometry,
ahci_alarm,
nop_cancel,
nop_select,
ahci_other,
ahci_ioctl,
NULL, /* bdr_cleanup */
ahci_part,
NULL, /* bdr_geometry */
ahci_intr,
ahci_alarm,
NULL, /* bdr_other */
ahci_thread
};
@ -950,16 +944,16 @@ PRIVATE int setup_prdt(struct port_state *ps, endpoint_t endpt,
/*===========================================================================*
* port_transfer *
*===========================================================================*/
PRIVATE int port_transfer(struct port_state *ps, int cmd, u64_t pos, u64_t eof,
endpoint_t endpt, iovec_s_t *iovec, int nr_req, int write)
PRIVATE ssize_t port_transfer(struct port_state *ps, int cmd, u64_t pos,
u64_t eof, endpoint_t endpt, iovec_s_t *iovec, int nr_req, int write)
{
/* Perform an I/O transfer on a port.
*/
prd_t prdt[NR_PRDS];
vir_bytes size, lead, chunk;
vir_bytes size, lead;
unsigned int count, nr_prds;
u64_t start_lba;
int i, r;
int r;
/* Get the total request size from the I/O vector. */
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)) {
dprintf(V_ERR, ("%s: unaligned position from %d\n",
ahci_portname(ps), endpt));
return EIO;
return EINVAL;
}
/* 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) {
dprintf(V_ERR, ("%s: unaligned size %lu from %d\n",
ahci_portname(ps), size, endpt));
return EIO;
return EINVAL;
}
/* 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,
nr_prds);
if (r < 0) return r;
if (r != OK) return r;
/* The entire operation succeeded; update the original vector. */
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;
return size;
}
/*===========================================================================*
@ -1478,7 +1464,7 @@ PRIVATE void port_timeout(struct timer *tp)
* is 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
* 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;
while (ps->flags & FLAG_BUSY)
driver_mt_sleep();
blockdriver_mt_sleep();
ps->flags &= ~FLAG_SUSPENDED;
}
@ -1865,9 +1851,9 @@ PRIVATE void ahci_init(int devind)
hba_state.nr_cmds = MIN(NR_CMDS,
((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",
ahci_name(),
ahci_instance,
(int) (hba_state.base[AHCI_HBA_VS] >> 16),
(int) ((hba_state.base[AHCI_HBA_VS] >> 8) & 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_SNCQ) ? "supports" : "no",
hba_state.irq));
dprintf(V_INFO, ("%s: CAP %08x, CAP2 %08x, PI %08x\n",
ahci_name(), cap, hba_state.base[AHCI_HBA_CAP2],
dprintf(V_INFO, ("AHCI%u: CAP %08x, CAP2 %08x, PI %08x\n",
ahci_instance, cap, hba_state.base[AHCI_HBA_CAP2],
hba_state.base[AHCI_HBA_PI]));
/* Initialize each of the implemented ports. We ignore CAP.NP. */
@ -1924,19 +1910,19 @@ PRIVATE void ahci_stop(void)
/*===========================================================================*
* ahci_alarm *
*===========================================================================*/
PRIVATE void ahci_alarm(struct driver *UNUSED(dp), message *m)
PRIVATE void ahci_alarm(clock_t stamp)
{
/* Process an alarm.
*/
/* Call the port-specific handler for each port that timed out. */
expire_timers(m->NOTIFY_TIMESTAMP);
expire_timers(stamp);
}
/*===========================================================================*
* ahci_intr *
*===========================================================================*/
PRIVATE void ahci_intr(struct driver *UNUSED(dr), message *UNUSED(m))
PRIVATE void ahci_intr(unsigned int UNUSED(irqs))
{
/* 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)) ==
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. */
ahci_set_mapping();
/* Announce we are up. */
driver_announce();
/* Announce that we are up. */
blockdriver_announce();
return OK;
}
@ -2145,21 +2131,6 @@ PRIVATE void sef_local_startup(void)
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 *
*===========================================================================*/
@ -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
* the given minor device number and the device-to-port mapping.
/* Map a minor device number to a port and a pointer to the partition's
* device structure. Return NULL if this minor device number does not
* identify an actual device.
*/
struct port_state *ps;
int port;
current_port = NULL;
current_dev = NULL;
ps = NULL;
if (minor < NR_MINORS) {
port = ahci_map[minor / DEV_PER_DRIVE];
@ -2206,8 +2178,8 @@ PRIVATE struct device *ahci_prepare(int minor)
if (port == NO_PORT)
return NULL;
current_port = &port_state[port];
current_dev = &current_port->part[minor % DEV_PER_DRIVE];
ps = &port_state[port];
*dvp = &ps->part[minor % DEV_PER_DRIVE];
}
else if ((unsigned) (minor -= MINOR_d0p0s0) < NR_SUBDEVS) {
port = ahci_map[minor / SUB_PER_DRIVE];
@ -2215,24 +2187,40 @@ PRIVATE struct device *ahci_prepare(int minor)
if (port == NO_PORT)
return NULL;
current_port = &port_state[port];
current_dev = &current_port->subpart[minor % SUB_PER_DRIVE];
ps = &port_state[port];
*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 *
*===========================================================================*/
PRIVATE int ahci_open(struct driver *UNUSED(dp), message *m)
PRIVATE int ahci_open(dev_t minor, int access)
{
/* Open a device.
*/
struct port_state *ps;
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,
* 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. */
if ((ps->flags & FLAG_READONLY) && (m->COUNT & W_BIT)) {
if ((ps->flags & FLAG_READONLY) && (access & W_BIT)) {
r = EACCES;
goto err_stop;
}
@ -2290,7 +2278,7 @@ PRIVATE int ahci_open(struct driver *UNUSED(dp), message *m)
err_stop:
/* Stop the thread if the device is now fully closed. */
if (ps->open_count == 0)
driver_mt_stop();
blockdriver_mt_stop();
return r;
}
@ -2298,14 +2286,14 @@ err_stop:
/*===========================================================================*
* ahci_close *
*===========================================================================*/
PRIVATE int ahci_close(struct driver *UNUSED(dp), message *m)
PRIVATE int ahci_close(dev_t minor)
{
/* Close a device.
*/
struct port_state *ps;
int port;
ps = ahci_get_port(m->DEVICE);
ps = ahci_get_port(minor);
/* Decrease the open count. */
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
* this device is not needed anymore.
*/
driver_mt_stop();
blockdriver_mt_stop();
if (ps->state == STATE_GOOD_DEV && !(ps->flags & FLAG_BARRIER)) {
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
* devices are now closed. If so, tell libdriver to quit after replying
* to the close request.
* devices are now closed. If so, tell libblockdriver to quit after
* replying to the close request.
*/
if (ahci_exiting) {
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) {
ahci_stop();
driver_mt_terminate();
blockdriver_mt_terminate();
}
}
@ -2354,76 +2342,53 @@ PRIVATE int ahci_close(struct driver *UNUSED(dp), message *m)
/*===========================================================================*
* ahci_transfer *
*===========================================================================*/
PRIVATE int ahci_transfer(endpoint_t endpt, int opcode, u64_t position,
iovec_t *iovec, unsigned int nr_req)
PRIVATE ssize_t ahci_transfer(dev_t minor, int do_write, u64_t position,
endpoint_t endpt, iovec_t *iovec, unsigned int count,
int UNUSED(flags))
{
/* Perform data transfer on the selected device.
*/
struct port_state *ps;
struct device *dv;
u64_t pos, eof;
/* We can safely use current_port, as we won't get interrupted until
* the call to port_transfer(), after which it is no longer used.
* Nonpreemptive threading guarantees that we will not be descheduled
* before then.
*/
assert(current_port != NULL);
assert(current_dev != NULL);
ps = ahci_get_port(minor);
dv = ahci_part(minor);
if (current_port->state != STATE_GOOD_DEV ||
(current_port->flags & FLAG_BARRIER))
if (ps->state != STATE_GOOD_DEV || (ps->flags & FLAG_BARRIER))
return EIO;
if (nr_req > NR_IOREQS)
if (count > NR_IOREQS)
return EINVAL;
/* Check for basic end-of-partition condition: if the start position of
* the request is outside the partition, return success immediately.
* 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;
pos = add64(current_dev->dv_base, position);
eof = add64(current_dev->dv_base, current_dev->dv_size);
pos = add64(dv->dv_base, position);
eof = add64(dv->dv_base, dv->dv_size);
return port_transfer(current_port, 0, pos, eof, endpt,
(iovec_s_t *) iovec, nr_req, opcode == DEV_SCATTER_S);
return port_transfer(ps, 0, pos, eof, endpt, (iovec_s_t *) iovec,
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
* 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.
/* Process I/O control requests.
*/
struct port_state *ps;
int r, val;
if (m->m_type != DEV_IOCTL_S)
return EINVAL;
ps = ahci_get_port(minor);
ps = ahci_get_port(m->DEVICE);
switch (m->REQUEST) {
switch (request) {
case DIOCEJECT:
if (ps->state != STATE_GOOD_DEV || (ps->flags & FLAG_BARRIER))
return EIO;
@ -2434,9 +2399,8 @@ PRIVATE int ahci_other(struct driver *UNUSED(dp), message *m)
return atapi_load_eject(ps, 0, FALSE /*load*/);
case DIOCOPENCT:
return sys_safecopyto(m->m_source, (cp_grant_id_t) m->IO_GRANT,
0, (vir_bytes) &ps->open_count, sizeof(ps->open_count),
D);
return sys_safecopyto(endpt, grant, 0,
(vir_bytes) &ps->open_count, sizeof(ps->open_count), D);
case DIOCFLUSH:
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))
return EIO;
if ((r = sys_safecopyfrom(m->m_source,
(cp_grant_id_t) m->IO_GRANT, 0, (vir_bytes) &val,
if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &val,
sizeof(val), D)) != OK)
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)
return r;
return sys_safecopyto(m->m_source, (cp_grant_id_t) m->IO_GRANT,
0, (vir_bytes) &val, sizeof(val), D);
return sys_safecopyto(endpt, grant, 0, (vir_bytes) &val,
sizeof(val), D);
}
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.
*/
struct port_state *ps;
struct device *dv;
if (ahci_prepare(minor) == NULL)
if ((ps = ahci_map_minor(minor, &dv)) == NULL)
return ENXIO;
*id = current_port->device;
*id = ps->device;
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
* 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);
return current_port;
return ps;
}
/*===========================================================================*
@ -2512,7 +2479,7 @@ PUBLIC int main(int argc, char **argv)
env_setargs(argc, argv);
sef_local_startup();
driver_mt_task(&ahci_dtab, DRIVER_STD);
blockdriver_mt_task(&ahci_dtab);
return 0;
}

View file

@ -2,8 +2,8 @@
PROG= amddev
SRCS= amddev.c
DPADD+= ${LIBDRIVER} ${LIBSYS}
LDADD+= -ldriver -lsys
DPADD+= ${LIBSYS}
LDADD+= -lsys
MAN=

View file

@ -113,7 +113,7 @@ PRIVATE void sef_local_startup()
/*===========================================================================*
* 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. */
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));
/* Announce we are up! */
driver_announce();
return(OK);
}
@ -184,7 +181,7 @@ PRIVATE void sef_cb_signal_handler(int signo)
}
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);
del_range(base, size);
r= deldma(proc_e, base, size);
@ -302,7 +299,7 @@ static void init_domain(int index)
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_LO, index, busaddr | 3);
@ -387,12 +384,12 @@ static int do_add4pci(const message *m)
pci_func= m->m1_i3;
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);
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);
return EINVAL;
}
@ -409,7 +406,7 @@ static int do_add4pci(const message *m)
if (r != OK)
{
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);
return r;
}
@ -419,7 +416,7 @@ static int do_add4pci(const message *m)
{
r= -errno;
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);
return r;
}

View file

@ -2,8 +2,8 @@
PROG= at_wini
SRCS= at_wini.c liveupdate.c
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -ldriver -lsys -ltimers
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -lblockdriver -lsys -ltimers
MAN=

View file

@ -133,7 +133,7 @@ PRIVATE struct quirk
{ 0x01, 0x04, 0x00, 0x1106, 0x3149 }, /* VIA VT6420 */
{ 0x01, 0x04, 0x00, 0x1095, 0x3512 },
{ 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) );
@ -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 drive) );
FORWARD _PROTOTYPE( void init_params_pci, (int) );
FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( struct device *w_prepare, (int dev) );
FORWARD _PROTOTYPE( int w_do_open, (dev_t minor, int access) );
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( char *w_name, (void) );
FORWARD _PROTOTYPE( int w_specify, (void) );
FORWARD _PROTOTYPE( int w_io_test, (void) );
FORWARD _PROTOTYPE( int w_transfer, (endpoint_t proc_nr, int opcode,
u64_t position, iovec_t *iov, unsigned nr_req) );
FORWARD _PROTOTYPE( ssize_t w_transfer, (dev_t minor, int do_write,
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_ext, (struct command *cmd) );
FORWARD _PROTOTYPE( int setup_dma, (unsigned *sizep, endpoint_t proc_nr,
iovec_t *iov, size_t addr_offset, int do_write) );
FORWARD _PROTOTYPE( void w_need_reset, (void) );
FORWARD _PROTOTYPE( void ack_irqs, (unsigned int) );
FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( void w_hw_int, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int w_do_close, (dev_t minor) );
FORWARD _PROTOTYPE( int w_ioctl, (dev_t minor, unsigned int request,
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( void w_timeout, (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 w_waitfor, (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
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_open, (void) );
FORWARD _PROTOTYPE( void atapi_close, (void) );
FORWARD _PROTOTYPE( int atapi_transfer, (int proc_nr, int opcode,
u64_t position, iovec_t *iov, unsigned nr_req) );
FORWARD _PROTOTYPE( int atapi_transfer, (int do_write, u64_t position,
endpoint_t endpt, iovec_t *iov, unsigned int nr_req) );
#endif
#define sys_voutb(out, n) at_voutb(__LINE__, (out), (n))
FORWARD _PROTOTYPE( int at_voutb, (int line, pvb_pair_t *, int n));
#define sys_vinb(in, n) at_vinb(__LINE__, (in), (n))
FORWARD _PROTOTYPE( int at_vinb, (int line, pvb_pair_t *, int n));
#define sys_voutb(out, n) at_voutb((out), (n))
FORWARD _PROTOTYPE( int at_voutb, (pvb_pair_t *, int n));
#define sys_vinb(in, n) at_vinb((in), (n))
FORWARD _PROTOTYPE( int at_vinb, (pvb_pair_t *, int n));
#undef sys_outb
#undef sys_inb
#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));
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));
#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)
/* Entry points to this driver. */
PRIVATE struct driver w_dtab = {
w_name, /* current device's name */
PRIVATE struct blockdriver w_dtab = {
w_do_open, /* open or mount request, initialize device */
w_do_close, /* release device */
do_diocntl, /* get or set a partition's geometry */
w_prepare, /* prepare for I/O on a given minor device */
w_transfer, /* do the I/O */
nop_cleanup, /* 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 */
nop_alarm, /* ignore leftover alarms */
nop_cancel, /* ignore CANCELs */
nop_select, /* ignore selects */
w_other, /* catch-all for unrecognized commands and ioctls */
w_hw_int /* leftover hardware interrupts */
w_hw_int, /* leftover hardware interrupts */
NULL, /* ignore leftover alarms */
NULL, /* ignore unrecognized messages */
NULL /* no multithreading support */
};
/* SEF functions and variables. */
@ -227,7 +230,7 @@ PUBLIC int main(int argc, char *argv[])
sef_local_startup();
/* Call the generic receive loop. */
driver_task(&w_dtab, DRIVER_STD);
blockdriver_task(&w_dtab);
return(OK);
}
@ -235,7 +238,7 @@ PUBLIC int main(int argc, char *argv[])
/*===========================================================================*
* sef_local_startup *
*===========================================================================*/
PRIVATE void sef_local_startup()
PRIVATE void sef_local_startup(void)
{
/* Register init callbacks. */
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();
/* Announce we are up! */
driver_announce();
blockdriver_announce();
return(OK);
}
@ -277,7 +280,7 @@ PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
/*===========================================================================*
* init_params *
*===========================================================================*/
PRIVATE void init_params()
PRIVATE void init_params(void)
{
/* This routine is called at startup to initialize the drive parameters. */
@ -304,20 +307,20 @@ PRIVATE void init_params()
panic("atapi_debug");
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;
}
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 {
/* Ask for anonymous memory for DMA, that is physically contiguous. */
dma_buf = alloc_contig(ATA_DMA_BUF_SIZE, 0, &dma_buf_phys);
prdt = alloc_contig(PRDT_BYTES, 0, &prdt_phys);
if(!dma_buf || !prdt) {
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_dma = base_dma;
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->irq = irq;
w->irq_need_ack = ack;
@ -471,7 +474,7 @@ PRIVATE void init_params_pci(int skip)
continue;
}
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",
w_instance, devind);
continue;
@ -502,9 +505,10 @@ PRIVATE void init_params_pci(int skip)
base_cmd, base_ctl+PCI_CTL_OFF,
base_dma, irq, 1, irq_hook, 1);
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;
} 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
{
@ -514,7 +518,7 @@ PRIVATE void init_params_pci(int skip)
if (wini[i].base_cmd == REG_CMD_BASE0) {
wini[i].base_dma= base_dma;
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);
pci_compat = 1;
}
@ -537,10 +541,10 @@ PRIVATE void init_params_pci(int skip)
base_cmd, base_ctl+PCI_CTL_OFF, base_dma,
irq, 1, irq_hook, 3);
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_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);
}
else
@ -551,7 +555,7 @@ PRIVATE void init_params_pci(int skip)
if (wini[i].base_cmd == REG_CMD_BASE1 && base_dma != 0) {
wini[i].base_dma= base_dma+PCI_DMA_2ND_OFF;
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);
pci_compat = 1;
}
@ -560,7 +564,7 @@ PRIVATE void init_params_pci(int skip)
if(pci_compat) {
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);
}
}
@ -570,13 +574,13 @@ PRIVATE void init_params_pci(int skip)
/*===========================================================================*
* 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. */
struct wini *wn;
if (w_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
if (w_prepare(minor) == NULL) return(ENXIO);
wn = w_wn;
@ -613,7 +617,7 @@ PRIVATE int w_do_open(struct driver *dp, message *m_ptr)
}
#if ENABLE_ATAPI
if ((wn->state & ATAPI) && (m_ptr->COUNT & W_BIT))
if ((wn->state & ATAPI) && (access & W_BIT))
return(EACCES);
#endif
@ -629,7 +633,8 @@ PRIVATE int w_do_open(struct driver *dp, message *m_ptr)
#endif
/* 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++;
return(OK);
@ -638,10 +643,10 @@ PRIVATE int w_do_open(struct driver *dp, message *m_ptr)
/*===========================================================================*
* w_prepare *
*===========================================================================*/
PRIVATE struct device *w_prepare(int device)
PRIVATE struct device *w_prepare(dev_t device)
{
/* Prepare for I/O on a device. */
w_device = device;
w_device = (int) device;
if (device < NR_MINORS) { /* d0, d0p[0-3], d1, ... */
w_drive = device / DEV_PER_DRIVE; /* save drive number */
@ -659,6 +664,16 @@ PRIVATE struct device *w_prepare(int device)
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_word(n) (((u16_t) id_byte(n)[0] << 0) \
|((u16_t) id_byte(n)[1] << 8))
@ -754,7 +769,7 @@ check_dma(struct wini *wn)
/*===========================================================================*
* 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
* drive, a removable media device, etc.
@ -906,7 +921,7 @@ PRIVATE int w_identify()
/*===========================================================================*
* w_name *
*===========================================================================*/
PRIVATE char *w_name()
PRIVATE char *w_name(void)
{
/* Return a name for the current device. */
static char name[] = "AT0-D0";
@ -921,10 +936,11 @@ PRIVATE char *w_name()
*===========================================================================*/
PRIVATE int w_io_test(void)
{
int r, save_dev;
int save_dev;
int save_timeout, save_errors, save_wakeup;
iovec_t iov;
static char *buf;
ssize_t r;
#ifdef CD_SECTOR_SIZE
#define BUFSIZE CD_SECTOR_SIZE
@ -951,10 +967,8 @@ PRIVATE int w_io_test(void)
w_testing = 1;
/* Try I/O on the actual drive (not any (sub)partition). */
if (w_prepare(w_drive * DEV_PER_DRIVE) == NULL)
panic("Couldn't switch devices");
r = w_transfer(SELF, DEV_GATHER_S, cvu64(0), &iov, 1);
r = w_transfer(w_drive * DEV_PER_DRIVE, FALSE /*do_write*/, cvu64(0),
SELF, &iov, 1, BDEV_NOFLAGS);
/* Switch back. */
if (w_prepare(save_dev) == NULL)
@ -967,19 +981,18 @@ PRIVATE int w_io_test(void)
w_testing = 0;
/* Test if everything worked. */
if (r != OK || iov.iov_size != 0) {
if (r != BUFSIZE) {
return ERR;
}
/* Everything worked. */
return OK;
}
/*===========================================================================*
* w_specify *
*===========================================================================*/
PRIVATE int w_specify()
PRIVATE int w_specify(void)
{
/* 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,
unsigned int count, unsigned int sector,
unsigned int opcode, int do_dma)
unsigned int do_write, int do_dma)
{
struct command cmd;
unsigned int sector_high;
@ -1045,21 +1058,20 @@ PRIVATE int do_transfer(const struct wini *wn, unsigned int precomp,
cmd.count = count;
if (do_dma)
{
cmd.command = opcode == DEV_SCATTER_S ? CMD_WRITE_DMA :
CMD_READ_DMA;
cmd.command = do_write ? CMD_WRITE_DMA : CMD_READ_DMA;
}
else
cmd.command = opcode == DEV_SCATTER_S ? CMD_WRITE : CMD_READ;
cmd.command = do_write ? CMD_WRITE : CMD_READ;
if (do_lba48) {
if (do_dma)
{
cmd.command = ((opcode == DEV_SCATTER_S) ?
cmd.command = (do_write ?
CMD_WRITE_DMA_EXT : CMD_READ_DMA_EXT);
}
else
{
cmd.command = ((opcode == DEV_SCATTER_S) ?
cmd.command = (do_write ?
CMD_WRITE_EXT : CMD_READ_EXT);
}
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)
{
int r;
u32_t v;
unsigned long v;
#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); \
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); \
return 1; \
@ -1151,25 +1163,34 @@ PRIVATE int error_dma(const struct wini *wn)
/*===========================================================================*
* w_transfer *
*===========================================================================*/
PRIVATE int w_transfer(proc_nr, opcode, position, iov, nr_req)
endpoint_t proc_nr; /* process doing the request */
int opcode; /* DEV_GATHER_S or DEV_SCATTER_S */
u64_t position; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
PRIVATE ssize_t w_transfer(
dev_t minor, /* minor device to perform the transfer on */
int do_write, /* 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 */
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;
int n, r, s, errors, do_dma, do_write;
int n, r, s, errors, do_dma;
unsigned long block, w_status;
u64_t dv_size = w_dv->dv_size;
u64_t dv_size;
unsigned nbytes;
unsigned dma_buf_offset;
ssize_t total = 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 (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
@ -1185,12 +1206,11 @@ unsigned nr_req; /* length of request vector */
if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
/* 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)
nbytes = diff64(dv_size, position);
block = div64u(add64(w_dv->dv_base, position), SECTOR_SIZE);
do_write= (opcode == DEV_SCATTER_S);
do_dma= wn->dma;
if (nbytes >= wn->max_count) {
@ -1213,12 +1233,12 @@ unsigned nr_req; /* length of request vector */
/* Tell the controller to transfer nbytes bytes. */
r = do_transfer(wn, wn->precomp, (nbytes >> SECTOR_SHIFT),
block, opcode, do_dma);
block, do_write, do_dma);
if (do_dma)
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.
* Reading the alternate status register is the suggested
* way to implement this wait.
@ -1268,6 +1288,7 @@ unsigned nr_req; /* length of request vector */
/* Book the bytes successfully transferred. */
nbytes -= n;
position= add64ul(position, n);
total += n;
addr_offset += n;
if ((iov->iov_size -= n) == 0) {
iov++; nr_req--; addr_offset = 0;
@ -1282,7 +1303,7 @@ unsigned nr_req; /* length of request vector */
* interrupt (write).
*/
if (opcode == DEV_GATHER_S) {
if (!do_write) {
/* First an interrupt, then data. */
if ((r = at_intr_wait()) != OK) {
/* 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; }
/* Copy bytes to or from the device's buffer. */
if (opcode == DEV_GATHER_S) {
if (!do_write) {
if(proc_nr != SELF) {
s=sys_safe_insw(wn->base_cmd + REG_DATA, proc_nr,
(void *) (iov->iov_addr), addr_offset,
@ -1340,6 +1361,7 @@ unsigned nr_req; /* length of request vector */
nbytes -= SECTOR_SIZE;
position= add64u(position, SECTOR_SIZE);
addr_offset += SECTOR_SIZE;
total += SECTOR_SIZE;
if ((iov->iov_size -= SECTOR_SIZE) == 0) {
iov++;
nr_req--;
@ -1358,7 +1380,7 @@ unsigned nr_req; /* length of request vector */
}
w_command = CMD_IDLE;
return(OK);
return(total);
}
/*===========================================================================*
@ -1469,12 +1491,13 @@ struct command *cmd; /* Command block */
/*===========================================================================*
* setup_dma *
*===========================================================================*/
PRIVATE int setup_dma(sizep, proc_nr, iov, addr_offset, do_write)
unsigned *sizep;
endpoint_t proc_nr;
iovec_t *iov;
size_t addr_offset;
int do_write;
PRIVATE int setup_dma(
unsigned *sizep,
endpoint_t proc_nr,
iovec_t *iov,
size_t addr_offset,
int UNUSED(do_write)
)
{
phys_bytes user_phys;
unsigned n, offset, size;
@ -1494,11 +1517,11 @@ int do_write;
while (size > 0)
{
if(verbose) {
printf(
"at_wini: setup_dma: iov[%d]: addr 0x%x, size %d offset %d, size %d\n",
if(verbose) {
printf(
"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);
}
}
n= iov[i].iov_size-offset;
if (n > size)
@ -1557,18 +1580,18 @@ int do_write;
size -= n;
}
if (j <= 0 || j > N_PRDTE)
panic("bad prdt index: %d", j);
prdt[j-1].prdte_flags |= PRDTE_FL_EOT;
if (j <= 0 || j > N_PRDTE)
panic("bad prdt index: %d", j);
prdt[j-1].prdte_flags |= PRDTE_FL_EOT;
if(verbose) {
if(verbose) {
printf("dma not bad\n");
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,
prdt[i].prdte_flags);
}
}
}
/* Verify that the bus master is not active */
r= sys_inb(wn->base_dma + DMA_STATUS, &v);
@ -1592,7 +1615,7 @@ int do_write;
/*===========================================================================*
* w_need_reset *
*===========================================================================*/
PRIVATE void w_need_reset()
PRIVATE void w_need_reset(void)
{
/* The controller needs to be reset. */
struct wini *wn;
@ -1608,10 +1631,10 @@ PRIVATE void w_need_reset()
/*===========================================================================*
* 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. */
if (w_prepare(m_ptr->DEVICE) == NULL)
if (w_prepare(minor) == NULL)
return(ENXIO);
w_wn->open_ct--;
#if ENABLE_ATAPI
@ -1672,7 +1695,7 @@ PRIVATE void w_timeout(void)
/*===========================================================================*
* w_reset *
*===========================================================================*/
PRIVATE int w_reset()
PRIVATE int w_reset(void)
{
/* Issue a reset to the controller. This is done after any catastrophe,
* like the controller refusing to respond.
@ -1718,7 +1741,7 @@ PRIVATE int w_reset()
/*===========================================================================*
* w_intr_wait *
*===========================================================================*/
PRIVATE void w_intr_wait()
PRIVATE void w_intr_wait(void)
{
/* Wait for a task completion interrupt. */
@ -1753,17 +1776,17 @@ PRIVATE void w_intr_wait()
default:
/*
* 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 {
/*
* 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 {
@ -1775,7 +1798,7 @@ PRIVATE void w_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. */
int r, s;
@ -1850,10 +1873,13 @@ int value; /* required status */
/*===========================================================================*
* w_geometry *
*===========================================================================*/
PRIVATE void w_geometry(entry)
struct partition *entry;
PRIVATE void w_geometry(dev_t minor, 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. */
entry->cylinders = div64u(wn->part[0].dv_size, SECTOR_SIZE) / (64*32);
@ -1870,7 +1896,7 @@ struct partition *entry;
/*===========================================================================*
* 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
* size of the device to something big. What is really needed is a generic
@ -1883,7 +1909,7 @@ PRIVATE int atapi_open()
/*===========================================================================*
* atapi_close *
*===========================================================================*/
PRIVATE void atapi_close()
PRIVATE void atapi_close(void)
{
/* Should unlock the device. For now do nothing. (XXX) */
}
@ -1921,12 +1947,13 @@ PRIVATE void sense_request(void)
/*===========================================================================*
* atapi_transfer *
*===========================================================================*/
PRIVATE int atapi_transfer(proc_nr, opcode, position, iov, nr_req)
int proc_nr; /* process doing the request */
int opcode; /* DEV_GATHER_S or DEV_SCATTER_S */
u64_t position; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
PRIVATE int atapi_transfer(
int do_write, /* 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 */
unsigned int nr_req /* length of request vector */
)
{
struct wini *wn = w_wn;
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];
size_t addr_offset = 0;
int dmabytes = 0, piobytes = 0;
ssize_t total = 0;
if (do_write) return(EINVAL);
errors = fresh = 0;
@ -1965,7 +1995,7 @@ unsigned nr_req; /* length of request vector */
if ((before | nbytes) & 1) return(EINVAL);
/* 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)
nbytes = diff64(dv_size, position);
@ -2023,6 +2053,7 @@ unsigned nr_req; /* length of request vector */
chunk = iov->iov_size;
position= add64ul(position, chunk);
nbytes -= chunk;
total += chunk;
if ((iov->iov_size -= chunk) == 0) {
iov++;
nr_req--;
@ -2069,6 +2100,7 @@ unsigned nr_req; /* length of request vector */
addr_offset += chunk;
piobytes += chunk;
fresh = 0;
total += chunk;
if ((iov->iov_size -= chunk) == 0) {
iov++;
nr_req--;
@ -2107,7 +2139,7 @@ unsigned nr_req; /* length of request vector */
#endif
w_command = CMD_IDLE;
return(OK);
return(total);
}
/*===========================================================================*
@ -2174,21 +2206,18 @@ int do_dma;
#endif /* ENABLE_ATAPI */
/*===========================================================================*
* w_other *
* w_ioctl *
*===========================================================================*/
PRIVATE int w_other(dr, m)
struct driver *dr;
message *m;
PRIVATE int w_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
cp_grant_id_t grant)
{
int r, timeout, prev;
int r, timeout, prev, count;
struct command cmd;
if (m->m_type != DEV_IOCTL_S )
return EINVAL;
if (m->REQUEST == DIOCTIMEOUT) {
r= sys_safecopyfrom(m->m_source, (cp_grant_id_t) m->IO_GRANT,
0, (vir_bytes)&timeout, sizeof(timeout), D);
switch (request) {
case DIOCTIMEOUT:
r= sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&timeout,
sizeof(timeout), D);
if(r != OK)
return r;
@ -2218,28 +2247,28 @@ message *m;
timeout_usecs = timeout;
}
r= sys_safecopyto(m->m_source,
(cp_grant_id_t) m->IO_GRANT,
0, (vir_bytes)&prev, sizeof(prev), D);
r= sys_safecopyto(endpt, grant, 0, (vir_bytes)&prev,
sizeof(prev), D);
if(r != OK)
return r;
}
return OK;
} else if (m->REQUEST == DIOCOPENCT) {
int count;
if (w_prepare(m->DEVICE) == NULL) return ENXIO;
case DIOCOPENCT:
if (w_prepare(minor) == 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);
r= sys_safecopyto(endpt, grant, 0, (vir_bytes)&count,
sizeof(count), D);
if(r != OK)
return r;
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;
@ -2253,18 +2282,17 @@ message *m;
return (w_wn->w_status & (STATUS_ERR|STATUS_WF)) ? EIO : OK;
}
return EINVAL;
}
/*===========================================================================*
* w_hw_int *
*===========================================================================*/
PRIVATE void w_hw_int(dr, m)
struct driver *dr;
message *m;
PRIVATE void w_hw_int(unsigned int irqs)
{
/* 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 *
*===========================================================================*/
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
* 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_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;
if ((s=sys_voutb(pvb,n)) == 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++)
printf("%2d: %4x -> %4x\n", i, pvb[i].value, pvb[i].port);
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;
if ((s=sys_vinb(pvb,n)) == 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++)
printf("%2d: %4x\n", i, pvb[i].port);
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)
{
int s;
s = sys_out(port, value, type);
if(s == 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);
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)
{
int s;
s = sys_in(port, value, type);
if(s == 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);
panic("sys_in failed");
}

View file

@ -1,5 +1,5 @@
#include <minix/drivers.h>
#include <minix/driver.h>
#include <minix/blockdriver.h>
#include <minix/drvlib.h>
#define VERBOSE 0 /* display identify messages during boot */
@ -217,3 +217,8 @@
#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])

View file

@ -1,7 +1,7 @@
.include <bsd.own.mk>
DPADD+= ${LIBAUDIODRIVER} ${LIBDRIVER} ${LIBSYS}
LDADD+= -laudiodriver -ldriver -lsys
DPADD+= ${LIBAUDIODRIVER} ${LIBCHARDRIVER} ${LIBSYS}
LDADD+= -laudiodriver -lchardriver -lsys
.if exists(${.CURDIR}/../../Makefile.inc)
.include "${.CURDIR}/../../Makefile.inc"

View file

@ -4,8 +4,6 @@ SRCS= es1370.c ak4531.c pci_helper.c
MAN=
LIBS += -ldriver
BINDIR?= /usr/sbin
.include <bsd.prog.mk>

View file

@ -70,7 +70,7 @@ PRIVATE int ak4531_write (u8_t address, u8_t data) {
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);

View file

@ -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;
/* 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;
}

View file

@ -15,7 +15,7 @@
* helper functions for I/O *
*===========================================================================*/
PUBLIC unsigned pci_inb(u16_t port) {
u32_t value;
unsigned long value;
int s;
if ((s=sys_inb(port, &value)) !=OK)
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) {
u32_t value;
unsigned long value;
int s;
if ((s=sys_inw(port, &value)) !=OK)
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) {
u32_t value;
unsigned long value;
int s;
if ((s=sys_inl(port, &value)) !=OK)
printf("%s: warning, sys_inl failed: %d\n", DRIVER_NAME, s);

View file

@ -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;
/* 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;
}

View file

@ -15,7 +15,7 @@
* helper functions for I/O *
*===========================================================================*/
PUBLIC unsigned pci_inb(u16_t port) {
u32_t value;
unsigned long value;
int s;
if ((s=sys_inb(port, &value)) !=OK)
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) {
u32_t value;
unsigned long value;
int s;
if ((s=sys_inw(port, &value)) !=OK)
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) {
u32_t value;
unsigned long value;
int s;
if ((s=sys_inl(port, &value)) !=OK)
printf("%s: warning, sys_inl failed: %d\n", DRIVER_NAME, s);

View file

@ -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,
(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);
@ -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_write(DSP, base + SRC_INT_REGS_OFF,
(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);
/* un-freeze the channel */

View file

@ -13,7 +13,7 @@ FORWARD _PROTOTYPE( int get_set_output, (struct inout_ctrl *output, int flag));
/*=========================================================================*
* 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;
switch(request) {

View file

@ -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"));
DmaPhys = dma;
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"));
sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));
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));
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"));
*frag_size = DspFragmentSize;
return OK;

View file

@ -2,8 +2,8 @@
PROG= bios_wini
SRCS= bios_wini.c
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -ldriver -lsys -ltimers
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -lblockdriver -lsys -ltimers
MAN=

View file

@ -21,7 +21,7 @@
*/
#include <minix/drivers.h>
#include <minix/driver.h>
#include <minix/blockdriver.h>
#include <minix/drvlib.h>
#include <minix/sysutil.h>
#include <minix/safecopies.h>
@ -29,8 +29,6 @@
#include <machine/int86.h>
#include <assert.h>
#define ME "BIOS_WINI"
/* Parameters for the disk drive. */
#define MAX_DRIVES 8 /* this driver supports 8 drives (d0 - d7)*/
#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
_PROTOTYPE(int main, (void) );
FORWARD _PROTOTYPE( struct device *w_prepare, (int device) );
FORWARD _PROTOTYPE( char *w_name, (void) );
FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, u64_t position,
iovec_t *iov, unsigned nr_req) );
FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( struct device *w_prepare, (dev_t device) );
FORWARD _PROTOTYPE( struct device *w_part, (dev_t minor) );
FORWARD _PROTOTYPE( ssize_t w_transfer, (dev_t minor, int do_write,
u64_t position, endpoint_t endpt, iovec_t *iov, unsigned int nr_req,
int flags) );
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_geometry, (struct partition *entry));
FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( void w_geometry, (dev_t minor, struct partition *entry));
FORWARD _PROTOTYPE( int w_ioctl, (dev_t minor, unsigned int request,
endpoint_t endpt, cp_grant_id_t grant) );
/* Entry points to this driver. */
PRIVATE struct driver w_dtab = {
w_name, /* current device's name */
PRIVATE struct blockdriver w_dtab = {
w_do_open, /* open or mount request, initialize device */
w_do_close, /* release device */
do_diocntl, /* get or set a partition's geometry */
w_prepare, /* prepare for I/O on a given minor device */
w_transfer, /* do the I/O */
nop_cleanup, /* no cleanup needed */
w_ioctl, /* I/O control */
NULL, /* no cleanup needed */
w_part, /* return partition information structure */
w_geometry, /* tell the geometry of the disk */
nop_alarm, /* ignore leftover alarms */
nop_cancel, /* ignore CANCELs */
nop_select, /* ignore selects */
w_other, /* catch-all for unrecognized commands and ioctls */
NULL /* leftover hardware interrupts */
NULL, /* leftover hardware interrupts */
NULL, /* ignore leftover alarms */
NULL, /* catch-all for unrecognized commands */
NULL /* no threading support */
};
/* 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 *
*===========================================================================*/
PUBLIC int main()
PUBLIC int main(void)
{
/* SEF local startup. */
sef_local_startup();
/* Call the generic receive loop. */
driver_task(&w_dtab, DRIVER_STD);
blockdriver_task(&w_dtab);
return(OK);
}
@ -106,7 +104,7 @@ PUBLIC int main()
/*===========================================================================*
* sef_local_startup *
*===========================================================================*/
PRIVATE void sef_local_startup()
PRIVATE void sef_local_startup(void)
{
/* Register init callbacks. */
sef_setcb_init_fresh(sef_cb_init_fresh);
@ -124,7 +122,7 @@ PRIVATE void sef_local_startup()
/*===========================================================================*
* 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. */
long v;
@ -134,7 +132,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
remap_first = v;
/* Announce we are up! */
driver_announce();
blockdriver_announce();
return(OK);
}
@ -142,8 +140,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
/*===========================================================================*
* w_prepare *
*===========================================================================*/
PRIVATE struct device *w_prepare(device)
int device;
PRIVATE struct device *w_prepare(dev_t 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. */
static char name[] = "bios-d0";
/* Return a pointer to the partition information of the given minor device. */
name[6] = '0' + w_drive;
return name;
return w_prepare(minor);
}
/*===========================================================================*
* w_transfer *
*===========================================================================*/
PRIVATE int w_transfer(proc_nr, opcode, pos64, iov, nr_req)
int proc_nr; /* process doing the request */
int opcode; /* DEV_GATHER or DEV_SCATTER */
u64_t pos64; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
PRIVATE ssize_t w_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 proc_nr, /* 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 */
)
{
struct wini *wn = w_wn;
struct wini *wn;
iovec_t *iop, *iov_end = iov + nr_req;
int r, errors;
unsigned count;
vir_bytes chunk, nbytes;
unsigned long block;
vir_bytes i13e_rw_off, rem_buf_size;
unsigned secspcyl = wn->heads * wn->sectors;
unsigned secspcyl;
struct int13ext_rw {
u8_t len;
u8_t res1;
@ -203,12 +201,19 @@ unsigned nr_req; /* length of request vector */
} *i13e_rw;
struct reg86u reg86;
u32_t lopos;
ssize_t total;
if (w_prepare(minor) == NULL) return(ENXIO);
wn = w_wn;
secspcyl = wn->heads * wn->sectors;
lopos= ex64lo(pos64);
/* Check disk address. */
if ((lopos & SECTOR_MASK) != 0) return(EINVAL);
total = 0;
errors = 0;
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);
/* 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) {
u64_t n;
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. */
if (errors > 0) nbytes = SECTOR_SIZE;
if (opcode == DEV_SCATTER_S) {
if (do_write) {
/* Copy from user space to the DMA buffer. */
count = 0;
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. */
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.w.si = (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;
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.w.bx = 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;
}
if (opcode == DEV_GATHER_S) {
if (!do_write) {
/* Copy from the DMA buffer to user space. */
count = 0;
for (iop = iov; count < nbytes; iop++) {
@ -333,7 +338,8 @@ unsigned nr_req; /* length of request vector */
/* Book the bytes successfully transferred. */
pos64 = add64ul(pos64, nbytes);
for (;;) {
total += nbytes;
while (nbytes > 0) {
if (nbytes < iov->iov_size) {
/* Not done with this one yet. */
iov->iov_size -= nbytes;
@ -341,25 +347,17 @@ unsigned nr_req; /* length of request vector */
}
nbytes -= iov->iov_size;
iov->iov_size = 0;
if (nbytes == 0) {
/* The rest is optional, so we return to give FS a
* chance to think it over.
*/
return(OK);
}
iov++;
nr_req--;
}
}
return(OK);
return(total);
}
/*============================================================================*
* w_do_open *
*============================================================================*/
PRIVATE int w_do_open(dp, m_ptr)
struct driver *dp;
message *m_ptr;
PRIVATE int w_do_open(dev_t minor, int UNUSED(access))
{
/* 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 (w_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
if (w_prepare(minor) == NULL) return(ENXIO);
if (w_wn->open_ct++ == 0) {
/* Partition the disk. */
@ -379,13 +377,11 @@ message *m_ptr;
/*============================================================================*
* w_do_close *
*============================================================================*/
PRIVATE int w_do_close(dp, m_ptr)
struct driver *dp;
message *m_ptr;
PRIVATE int w_do_close(dev_t minor)
{
/* 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--;
return(OK);
}
@ -393,7 +389,7 @@ message *m_ptr;
/*===========================================================================*
* w_init *
*===========================================================================*/
PRIVATE void w_init()
PRIVATE void w_init(void)
{
/* This routine is called at startup to initialize the drive parameters. */
@ -490,10 +486,11 @@ PRIVATE void w_init()
}
if (wn->int13ext) {
printf("%s: %lu sectors\n", w_name(), capacity);
printf("bios-d%u: %lu sectors\n", w_drive, capacity);
} else {
printf("%s: %d cylinders, %d heads, %d sectors per track\n",
w_name(), wn->cylinders, wn->heads, wn->sectors);
printf("bios-d%u: %d cylinders, %d heads, "
"%d sectors per track\n",
w_drive, wn->cylinders, wn->heads, wn->sectors);
}
wn->part[0].dv_size = mul64u(capacity, SECTOR_SIZE);
}
@ -502,37 +499,30 @@ PRIVATE void w_init()
/*============================================================================*
* w_geometry *
*============================================================================*/
PRIVATE void w_geometry(entry)
struct partition *entry;
PRIVATE void w_geometry(dev_t minor, struct partition *entry)
{
if (w_prepare(minor) == NULL) return;
entry->cylinders = w_wn->cylinders;
entry->heads = w_wn->heads;
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;
int count;
if (m->m_type != DEV_IOCTL_S )
return EINVAL;
if (w_prepare(minor) == NULL) return ENXIO;
if (m->REQUEST == DIOCOPENCT) {
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 (request == DIOCOPENCT) {
count = w_wn->open_ct;
return sys_safecopyto(endpt, grant, 0, (vir_bytes)&count,
sizeof(count), D);
}
if(r != OK)
return r;
return OK;
}
return EINVAL;
return EINVAL;
}

View file

@ -2,8 +2,8 @@
PROG= filter
SRCS= main.c sum.c driver.c util.c crc.c md5.c
DPADD+= ${LIBDRIVER} ${LIBSYS}
LDADD+= -ldriver -lsys
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS}
LDADD+= -lblockdriver -lsys
MAN=

View file

@ -77,7 +77,7 @@ unsigned long compute_crc(const unsigned char *b, size_t n)
/* Replace an intermediate zero with the next value
* from the sequence */
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 */

View file

@ -6,7 +6,6 @@
static struct driverinfo driver[2];
/* State variables. */
static endpoint_t self_ep;
static asynmsg_t amsgtable[2];
static int size_known = 0;
@ -29,9 +28,11 @@ static int driver_open(int which)
sector_t sectors;
int r;
msg.m_type = DEV_OPEN;
msg.DEVICE = driver[which].minor;
msg.USER_ENDPT = self_ep;
memset(&msg, 0, sizeof(msg));
msg.m_type = BDEV_OPEN;
msg.BDEV_MINOR = driver[which].minor;
msg.BDEV_ACCESS = R_BIT | W_BIT;
msg.BDEV_ID = 0;
r = sendrec(driver[which].endpt, &msg);
if (r != OK) {
@ -41,9 +42,9 @@ static int driver_open(int which)
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",
msg.m_type, msg.REP_STATUS);
msg.m_type, msg.BDEV_STATUS);
return RET_REDO;
}
@ -54,17 +55,18 @@ static int driver_open(int which)
if(!GRANT_VALID(gid))
panic("invalid grant: %d", gid);
msg.m_type = DEV_IOCTL_S;
msg.REQUEST = DIOCGETP;
msg.DEVICE = driver[which].minor;
msg.USER_ENDPT = self_ep;
msg.IO_GRANT = (char *) gid;
memset(&msg, 0, sizeof(msg));
msg.m_type = BDEV_IOCTL;
msg.BDEV_MINOR = driver[which].minor;
msg.BDEV_REQUEST = DIOCGETP;
msg.BDEV_GRANT = gid;
msg.BDEV_ID = 0;
r = sendrec(driver[which].endpt, &msg);
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. */
printf("Filter: ioctl(DIOCGETP) returned (%d, %d)\n",
r, msg.m_type);
@ -105,9 +107,10 @@ static int driver_close(int which)
message msg;
int r;
msg.m_type = DEV_CLOSE;
msg.DEVICE = driver[which].minor;
msg.USER_ENDPT = self_ep;
memset(&msg, 0, sizeof(msg));
msg.m_type = BDEV_CLOSE;
msg.BDEV_MINOR = driver[which].minor;
msg.BDEV_ID = 0;
r = sendrec(driver[which].endpt, &msg);
if (r != OK) {
@ -117,9 +120,9 @@ static int driver_close(int which)
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",
msg.m_type, msg.REP_STATUS);
msg.m_type, msg.BDEV_STATUS);
return RET_REDO;
}
@ -135,8 +138,6 @@ void driver_init(void)
/* Initialize the driver layer. */
int r;
self_ep = getprocnr();
memset(driver, 0, sizeof(driver));
/* Endpoints unknown. */
@ -200,11 +201,11 @@ void driver_shutdown(void)
#endif
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(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;
/* Fill in the last bits of the message. */
mess->DEVICE = driver[which].minor;
mess->USER_ENDPT = self_ep;
mess->BDEV_MINOR = driver[which].minor;
mess->BDEV_ID = 0;
/* Send the message asynchronously. */
amp = &amsgtable[which];
@ -745,7 +746,7 @@ static int do_sendrec_both(message *m1, message *m2)
/*===========================================================================*
* 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
* be fixed elsewhere.
@ -768,14 +769,14 @@ static int paired_sendrec(message *m1, message *m2, int both)
#if DEBUG2
printf("paired_sendrec(%d) - <%d,%x:%x,%d> - %x,%x\n",
both, m1->m_type, m1->HIGHPOS, m1->POSITION, m1->COUNT,
m1->IO_GRANT, m2->IO_GRANT);
both, m1->m_type, m1->BDEV_POS_HI, m1->BDEV_POS_LO,
m1->BDEV_COUNT, m1->BDEV_GRANT, m2->BDEV_GRANT);
#endif
if (both)
r = do_sendrec_both(m1, m2);
else
r = do_sendrec_one(m1, m2);
r = do_sendrec_one(m1);
#if DEBUG2
if (r != OK)
@ -789,16 +790,14 @@ static int paired_sendrec(message *m1, message *m2, int both)
* single_grant *
*===========================================================================*/
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.
*/
cp_grant_id_t grant;
size_t size, chunk;
size_t chunk;
int count;
size = *sizep;
/* Split up the request into chunks, if requested. This makes no
* difference at all, except that this works around a weird performance
* 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. */
*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))
panic("invalid grant: %d", *gid);
@ -837,7 +836,7 @@ static int single_grant(endpoint_t endpt, vir_bytes buf, int access,
* paired_grant *
*===========================================================================*/
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)
{
/* 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) {
count = single_grant(driver[DRIVER_MAIN].endpt,
(vir_bytes) buf1, access, &gids[0], vectors[0],
&sizes[0]);
(vir_bytes) buf1, access, &gids[0], vectors[0], size);
}
if (both) {
if(driver[DRIVER_BACKUP].endpt > 0) {
count = single_grant(driver[DRIVER_BACKUP].endpt,
(vir_bytes) buf2, access, &gids[1],
vectors[1], &sizes[1]);
vectors[1], size);
}
}
return count;
@ -866,8 +864,8 @@ static int paired_grant(char *buf1, char *buf2, int request,
/*===========================================================================*
* single_revoke *
*===========================================================================*/
PRIVATE void single_revoke(cp_grant_id_t gid, const iovec_s_t vector[NR_IOREQS],
size_t *sizep, int count)
PRIVATE void single_revoke(cp_grant_id_t gid,
const iovec_s_t vector[NR_IOREQS], int count)
{
/* Revoke all grants associated with a request to a single driver.
* 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;
/* 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);
*sizep -= vector[i].iov_size;
}
/* Then revoke the grant for the vector itself. */
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 *
*===========================================================================*/
static void paired_revoke(const cp_grant_id_t *gids,
iovec_s_t vectors[2][NR_IOREQS],
size_t *sizes, int count, int both)
iovec_s_t vectors[2][NR_IOREQS], int count, int both)
{
/* 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)
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];
message m1, m2;
cp_grant_id_t gids[2];
size_t sizes[2];
int r, both, count;
gids[0] = gids[1] = GRANT_INVALID;
sizes[0] = sizes[1] = *sizep;
/* Send two requests only if mirroring is enabled and the given request
* is either FLT_READ2 or FLT_WRITE.
*/
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;
m1.COUNT = count;
m1.POSITION = ex64lo(pos);
m1.HIGHPOS = ex64hi(pos);
memset(&m1, 0, sizeof(m1));
m1.m_type = (request == FLT_WRITE) ? BDEV_SCATTER : BDEV_GATHER;
m1.BDEV_COUNT = count;
m1.BDEV_POS_LO = ex64lo(pos);
m1.BDEV_POS_HI = ex64hi(pos);
m2 = m1;
m1.IO_GRANT = (char *) gids[0];
m2.IO_GRANT = (char *) gids[1];
m1.BDEV_GRANT = gids[0];
m2.BDEV_GRANT = gids[1];
r = paired_sendrec(&m1, &m2, both);
paired_revoke(gids, vectors, sizes, count, both);
paired_revoke(gids, vectors, count, both);
if(r != OK) {
#if DEBUG
@ -943,51 +937,52 @@ int read_write(u64_t pos, char *bufa, char *bufb, size_t *sizep, int request)
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: "
"(%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,
(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");
/* If the driver returned a value *larger* than we requested,
* OR if we did NOT exceed the disk size, then we should
* report the driver for acting strangely!
*/
if (sizes[0] > *sizep ||
cmp64(add64u(pos, sizes[0]), disk_size) < 0)
if (m1.BDEV_STATUS > (ssize_t) *sizep ||
cmp64(add64u(pos, m1.BDEV_STATUS), disk_size) < 0)
return bad_driver(DRIVER_MAIN, BD_PROTO, EFAULT);
/* Return the actual size. */
*sizep = sizes[0];
*sizep = m1.BDEV_STATUS;
}
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 "
"backup driver (%x, %d)\n",
m2.m_type, m2.REP_STATUS);
m2.m_type, m2.BDEV_STATUS);
return bad_driver(DRIVER_BACKUP, BD_PROTO,
m2.m_type == TASK_REPLY ? m2.REP_STATUS :
m2.m_type == BDEV_REPLY ? m2.BDEV_STATUS :
EFAULT);
}
if (sizes[1] != *sizep) {
if (m2.BDEV_STATUS != (ssize_t) *sizep) {
printf("Filter: truncated reply from backup driver\n");
/* As above */
if (sizes[1] > *sizep ||
cmp64(add64u(pos, sizes[1]), disk_size) < 0)
if (m2.BDEV_STATUS > (ssize_t) *sizep ||
cmp64(add64u(pos, m2.BDEV_STATUS),
disk_size) < 0)
return bad_driver(DRIVER_BACKUP, BD_PROTO,
EFAULT);
/* Return the actual size. */
if (*sizep >= sizes[1])
*sizep = sizes[1];
if ((ssize_t) *sizep >= m2.BDEV_STATUS)
*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()
{
char key[DS_MAX_KEYLEN];
char *driver_prefix = "drv.vfs.";
char *blkdriver_prefix = "drv.blk.";
u32_t value;
int type;
endpoint_t owner_endpoint;
@ -1021,7 +1016,7 @@ void ds_event()
}
/* 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) {
return;
}

View file

@ -12,7 +12,7 @@
#include <minix/partition.h>
#include <minix/ds.h>
#include <minix/callnr.h>
#include <minix/driver.h>
#include <minix/blockdriver.h>
#include <minix/optset.h>
#include <unistd.h>
#include <stdio.h>

View file

@ -60,14 +60,14 @@ PRIVATE struct optset optset_table[] = {
{ "timeout", OPT_INT, &DRIVER_TIMEOUT, 10 },
{ "T", OPT_INT, &DRIVER_TIMEOUT, 10 },
{ "chunk", OPT_INT, &CHUNK_SIZE, 10 },
{ NULL }
{ NULL, 0, NULL, 0 }
};
/* Request message. */
static message m_in;
static endpoint_t who_e; /* m_source */
static endpoint_t proc_e; /* USER_ENDPT */
static cp_grant_id_t grant_id; /* IO_GRANT */
static long req_id; /* BDEV_ID */
static cp_grant_id_t grant_id; /* BDEV_GRANT */
/* Data buffers. */
static char *buf_array, *buffer; /* contiguous buffer */
@ -136,8 +136,8 @@ static int do_rdwt(int flag_rw)
u64_t pos;
int r;
pos = make64(m_in.POSITION, m_in.HIGHPOS);
size = m_in.COUNT;
pos = make64(m_in.BDEV_POS_LO, m_in.BDEV_POS_HI);
size = m_in.BDEV_COUNT;
if (rem64u(pos, SECTOR_SIZE) != 0 || size % SECTOR_SIZE != 0) {
printf("Filter: unaligned request from caller!\n");
@ -169,7 +169,11 @@ static int do_rdwt(int flag_rw)
carry(size_ret, flag_rw);
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)
{
size_t size, size_ret, bytes;
size_t size, size_ret;
int grants;
int r, i;
u64_t pos;
iovec_t iov_proc[NR_IOREQS];
/* Extract informations. */
grants = m_in.COUNT;
grants = m_in.BDEV_COUNT;
if((r = sys_safecopyfrom(who_e, grant_id, 0, (vir_bytes) iov_proc,
grants * sizeof(iovec_t), D)) != OK) {
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++)
size += iov_proc[i].iov_size;
@ -227,22 +231,9 @@ static int do_vrdwt(int flag_rw)
if(flag_rw == FLT_READ)
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);
return OK;
return size_ret;
}
/*===========================================================================*
@ -252,7 +243,7 @@ static int do_ioctl(message *m)
{
struct partition sizepart;
switch(m->REQUEST) {
switch(m->BDEV_REQUEST) {
case DIOCSETP:
case DIOCTIMEOUT:
case DIOCOPENCT:
@ -276,7 +267,8 @@ static int do_ioctl(message *m)
break;
default:
printf("Filter: unknown ioctl request: %d!\n", m->REQUEST);
printf("Filter: unknown ioctl request: %d!\n",
m->BDEV_REQUEST);
return EINVAL;
}
@ -372,8 +364,8 @@ static int parse_arguments(int argc, char *argv[])
int main(int argc, char *argv[])
{
message m_out;
int ipc_status;
int r;
int r, ipc_status;
size_t size;
/* SEF local startup. */
env_setargs(argc, argv);
@ -396,18 +388,19 @@ int main(int argc, char *argv[])
}
who_e = m_in.m_source;
proc_e = m_in.USER_ENDPT;
grant_id = (cp_grant_id_t) m_in.IO_GRANT;
req_id = m_in.BDEV_ID;
grant_id = m_in.BDEV_GRANT;
size = 0;
/* Forword the request message to the drivers. */
switch(m_in.m_type) {
case DEV_OPEN: /* open/close is a noop for filter. */
case DEV_CLOSE: r = OK; break;
case DEV_READ_S: r = do_rdwt(FLT_READ); break;
case DEV_WRITE_S: r = do_rdwt(FLT_WRITE); break;
case DEV_GATHER_S: r = do_vrdwt(FLT_READ); break;
case DEV_SCATTER_S: r = do_vrdwt(FLT_WRITE); break;
case DEV_IOCTL_S: r = do_ioctl(&m_in); break;
case BDEV_OPEN: /* open/close is a noop for filter. */
case BDEV_CLOSE: r = OK; break;
case BDEV_READ: r = do_rdwt(FLT_READ); break;
case BDEV_WRITE: r = do_rdwt(FLT_WRITE); break;
case BDEV_GATHER: r = do_vrdwt(FLT_READ); break;
case BDEV_SCATTER: r = do_vrdwt(FLT_WRITE); break;
case BDEV_IOCTL: r = do_ioctl(&m_in); break;
default:
printf("Filter: ignoring unknown request %d from %d\n",
@ -420,9 +413,9 @@ int main(int argc, char *argv[])
#endif
/* Send back reply message. */
m_out.m_type = TASK_REPLY;
m_out.REP_ENDPT = proc_e;
m_out.REP_STATUS = r;
m_out.m_type = BDEV_REPLY;
m_out.BDEV_ID = req_id;
m_out.BDEV_STATUS = r;
send(who_e, &m_out);
}
@ -450,7 +443,7 @@ PRIVATE void sef_local_startup(void)
/*===========================================================================*
* 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. */
int r;
@ -468,14 +461,14 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
driver_init();
/* Subscribe to driver events for VFS drivers. */
r = ds_subscribe("drv\\.vfs\\..*", DSF_INITIAL | DSF_OVERWRITE);
/* Subscribe to block driver events. */
r = ds_subscribe("drv\\.blk\\..*", DSF_INITIAL | DSF_OVERWRITE);
if(r != OK) {
panic("Filter: can't subscribe to driver events");
}
/* Announce we are up! */
driver_announce();
blockdriver_announce();
return(OK);
}

View file

@ -59,7 +59,7 @@ static void calc_sum(unsigned sector, char *data, char *sum)
memset(sum, 0, SUM_SIZE);
for(i = 0; i < SECTOR_SIZE / SUM_SIZE; i++) {
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++;

View file

@ -48,8 +48,8 @@ char *print64(u64_t p)
static char buf[NB][100];
u32_t lo = ex64lo(p), hi = ex64hi(p);
n = (n+1) % NB;
if(!hi) sprintf(buf[n], "%lx", lo);
else sprintf(buf[n], "%lx%08lx", hi, lo);
if(!hi) sprintf(buf[n], "%x", lo);
else sprintf(buf[n], "%x%08x", hi, lo);
return buf[n];
}

View file

@ -2,8 +2,8 @@
PROG= floppy
SRCS= floppy.c liveupdate.c
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -ldriver -lsys -ltimers
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -lblockdriver -lsys -ltimers
MAN=

View file

@ -135,7 +135,7 @@
#define UNCALIBRATED 0 /* drive needs to be calibrated at next use */
#define CALIBRATED 1 /* no calibration needed */
#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_DENS 100 /* current media unknown */
#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 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 f_timeout, (timer_t *tp) );
FORWARD _PROTOTYPE( struct device *f_prepare, (int device) );
FORWARD _PROTOTYPE( char *f_name, (void) );
FORWARD _PROTOTYPE( struct device *f_prepare, (dev_t device) );
FORWARD _PROTOTYPE( struct device *f_part, (dev_t minor) );
FORWARD _PROTOTYPE( void f_cleanup, (void) );
FORWARD _PROTOTYPE( int f_transfer, (int proc_nr, int opcode, u64_t position,
iovec_t *iov, unsigned nr_req) );
FORWARD _PROTOTYPE( int dma_setup, (int opcode) );
FORWARD _PROTOTYPE( ssize_t f_transfer, (dev_t minor, int do_write,
u64_t position, endpoint_t proc_nr, iovec_t *iov,
unsigned int nr_req, int flags) );
FORWARD _PROTOTYPE( int dma_setup, (int do_write) );
FORWARD _PROTOTYPE( void start_motor, (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_command, (const u8_t *cmd, int len) );
FORWARD _PROTOTYPE( void fdc_out, (int val) );
@ -258,25 +259,25 @@ FORWARD _PROTOTYPE( int recalibrate, (void) );
FORWARD _PROTOTYPE( void f_reset, (void) );
FORWARD _PROTOTYPE( int f_intr_wait, (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( void f_geometry, (struct partition *entry) );
FORWARD _PROTOTYPE( void f_geometry, (dev_t minor,
struct partition *entry) );
/* Entry points to this driver. */
PRIVATE struct driver f_dtab = {
f_name, /* current device's name */
PRIVATE struct blockdriver f_dtab = {
f_do_open, /* open or mount request, sense type of diskette */
do_nop, /* nothing on a close */
do_diocntl, /* get or set a partitions geometry */
f_prepare, /* prepare for I/O on a given minor device */
f_do_close, /* nothing on a close */
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_part, /* return partition information structure */
f_geometry, /* tell the geometry of the diskette */
NULL, /* no processing of hardware interrupts */
f_expire_tmrs,/* expire all alarm timers */
nop_cancel,
nop_select,
NULL,
NULL
NULL, /* no processing of other messages */
NULL /* no threading support */
};
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_state_isvalid, (int state) );
EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
PUBLIC int last_transfer_opcode;
PUBLIC int last_was_write;
/*===========================================================================*
* floppy_task *
@ -300,7 +301,7 @@ PUBLIC int main(void)
sef_local_startup();
/* Call the generic receive loop. */
driver_task(&f_dtab, DRIVER_STD);
blockdriver_task(&f_dtab);
return(OK);
}
@ -330,7 +331,7 @@ PRIVATE void sef_local_startup(void)
/*===========================================================================*
* 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. */
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);
/* Announce we are up! */
driver_announce();
blockdriver_announce();
return(OK);
}
@ -386,25 +387,25 @@ PRIVATE void sef_cb_signal_handler(int signo)
/*===========================================================================*
* 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
* each expired timer, if any.
*/
expire_timers(m_ptr->NOTIFY_TIMESTAMP);
expire_timers(stamp);
}
/*===========================================================================*
* f_prepare *
*===========================================================================*/
PRIVATE struct device *f_prepare(int device)
PRIVATE struct device *f_prepare(dev_t device)
{
/* Prepare for I/O on a device. */
f_device = device;
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_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. */
static char name[] = "fd0";
/* Return a pointer to the partition information of the given minor device. */
name[2] = '0' + f_drive;
return name;
return f_prepare(minor);
}
/*===========================================================================*
@ -449,32 +448,41 @@ PRIVATE void f_cleanup(void)
/*===========================================================================*
* f_transfer *
*===========================================================================*/
PRIVATE int f_transfer(proc_nr, opcode, pos64, iov, nr_req)
int proc_nr; /* process doing the request */
int opcode; /* DEV_GATHER_S or DEV_SCATTER_S */
u64_t pos64; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
PRIVATE ssize_t f_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 proc_nr, /* 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 */
)
{
#define NO_OFFSET -1
struct floppy *fp = f_fp;
struct floppy *fp;
iovec_t *iop, *iov_end = iov + nr_req;
int s, r, errors, nr;
unsigned block; /* Seen any 32M floppies lately? */
unsigned nbytes, count, chunk, sector;
unsigned long dv_size = cv64ul(f_dv->dv_size);
unsigned block, nbytes, count, chunk, sector;
unsigned long dv_size;
vir_bytes user_offset, iov_offset = 0, iop_offset;
off_t position;
unsigned long position;
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];
ssize_t total;
if (f_prepare(minor) == NULL) return(ENXIO);
fp = f_fp;
dv_size = cv64ul(f_dv->dv_size);
if (ex64hi(pos64) != 0)
return OK; /* Way beyond EOF */
position= cv64ul(pos64);
total = 0;
/* Record the opcode of the last transfer performed. */
last_transfer_opcode = opcode;
/* Record the direction of the last transfer performed. */
last_was_write = do_write;
/* Check disk address. */
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;
/* 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;
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? */
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))
return(EINVAL);
@ -607,7 +615,7 @@ unsigned nr_req; /* length of request vector */
fp->fl_sector++;
}
if (opcode == DEV_SCATTER_S) {
if (do_write) {
/* Copy the user bytes to the DMA buffer. */
if(proc_nr != SELF) {
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. */
if (r == OK) {
if (dma_setup(opcode) != OK) {
if (dma_setup(do_write) != OK) {
/* This can only fail for addresses above 16MB
* that cannot be handled by the controller,
* because it uses 24-bit addressing.
*/
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. */
if(proc_nr != SELF) {
s=sys_safecopyto(proc_nr, *ug, *up,
@ -663,7 +671,8 @@ unsigned nr_req; /* length of request vector */
/* Book the bytes successfully transferred. */
position += nbytes;
for (;;) {
total += nbytes;
while (nbytes > 0) {
if (nbytes < iov->iov_size) {
/* Not done with this one yet. */
iov_offset += nbytes;
@ -673,25 +682,17 @@ unsigned nr_req; /* length of request vector */
iov_offset = 0;
nbytes -= iov->iov_size;
iov->iov_size = 0;
if (nbytes == 0) {
/* The rest is optional, so we return to give FS a
* chance to think it over.
*/
return(OK);
}
iov++;
nr_req--;
}
}
return(OK);
return(total);
}
/*===========================================================================*
* dma_setup *
*===========================================================================*/
PRIVATE int dma_setup(
int opcode /* DEV_GATHER_S or DEV_SCATTER_S */
)
PRIVATE int dma_setup(int do_write)
{
/* 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
@ -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[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[4], DMA_ADDR, (unsigned) (floppy_buf_phys >> 8) & 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)) {
switch (_ENDPOINT_P(mess.m_source)) {
case CLOCK:
f_expire_tmrs(NULL, &mess);
f_expire_tmrs(mess.NOTIFY_TIMESTAMP);
break;
default :
f_busy = BSY_IDLE;
@ -848,7 +849,7 @@ PRIVATE int seek(void)
if (is_ipc_notify(ipc_status)) {
switch (_ENDPOINT_P(mess.m_source)) {
case CLOCK:
f_expire_tmrs(NULL, &mess);
f_expire_tmrs(mess.NOTIFY_TIMESTAMP);
break;
default :
f_busy = BSY_IDLE;
@ -867,9 +868,7 @@ PRIVATE int seek(void)
/*===========================================================================*
* fdc_transfer *
*===========================================================================*/
PRIVATE int fdc_transfer(
int opcode /* DEV_GATHER_S or DEV_SCATTER_S */
)
PRIVATE int fdc_transfer(int do_write)
{
/* 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;
if (fdc_command(cmd, 6) != OK) return(ERR_TRANSFER);
} 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[2] = fp->fl_cylinder;
cmd[3] = fp->fl_head;
@ -906,7 +905,7 @@ PRIVATE int fdc_transfer(
/* Block, waiting for disk interrupt. */
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);
}
@ -915,7 +914,7 @@ PRIVATE int fdc_transfer(
if (r != OK) return(r);
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);
}
@ -1127,7 +1126,7 @@ PRIVATE void f_reset(void)
if (is_ipc_notify(ipc_status)) {
switch (_ENDPOINT_P(mess.m_source)) {
case CLOCK:
f_expire_tmrs(NULL, &mess);
f_expire_tmrs(mess.NOTIFY_TIMESTAMP);
break;
default :
f_busy = BSY_IDLE;
@ -1177,7 +1176,7 @@ PRIVATE int f_intr_wait(void)
if (is_ipc_notify(ipc_status)) {
switch (_ENDPOINT_P(mess.m_source)) {
case CLOCK:
f_expire_tmrs(NULL, &mess);
f_expire_tmrs(mess.NOTIFY_TIMESTAMP);
break;
default :
f_busy = BSY_IDLE;
@ -1202,7 +1201,7 @@ PRIVATE int f_intr_wait(void)
/*===========================================================================*
* 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
* 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 *
*===========================================================================*/
PRIVATE int f_do_open(dp, m_ptr)
struct driver *dp;
message *m_ptr; /* pointer to open message */
PRIVATE int f_do_open(dev_t minor, int UNUSED(access))
{
/* 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;
/* 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 */
if (dtype >= MINOR_fd0p0) dtype = 0;
@ -1308,6 +1305,16 @@ message *m_ptr; /* pointer to open message */
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 *
*===========================================================================*/
@ -1320,7 +1327,7 @@ PRIVATE int test_read(int density)
int device;
off_t position;
iovec_t iovec1;
int result;
ssize_t result;
f_fp->fl_density = density;
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;
iovec1.iov_addr = (vir_bytes) floppy_buf;
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);
return(OK);
@ -1340,11 +1348,11 @@ PRIVATE int test_read(int density)
/*===========================================================================*
* 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->heads = NR_HEADS;
entry->sectors = f_sectors;
}

View file

@ -1,4 +1,4 @@
#include <minix/drivers.h>
#include <minix/driver.h>
#include <minix/blockdriver.h>
#include <minix/drvlib.h>

View file

@ -4,7 +4,7 @@
EXTERN u16_t f_busy;
EXTERN int motor_status;
EXTERN unsigned f_drive;
EXTERN int last_transfer_opcode;
EXTERN int last_was_write;
#define BSY_IO 1 /* busy doing I/O */
/* 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: motor_status = 0x%02X\n", motor_status);
sef_lu_dprint("floppy: f_drive = %d\n", f_drive);
sef_lu_dprint("floppy: last_transfer_opcode = 0x%02X\n",
last_transfer_opcode);
sef_lu_dprint("floppy: last_was_write = %d\n", last_was_write);
sef_lu_dprint("floppy: SEF_LU_STATE_WORK_FREE(%d) reached = %d\n",
SEF_LU_STATE_WORK_FREE, TRUE);

View file

@ -2,8 +2,8 @@
PROG= hello
SRCS= hello.c
DPADD+= ${LIBDRIVER} ${LIBSYS}
LDADD+= -ldriver -lsys
DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
LDADD+= -lchardriver -lsys
MAN=

View file

@ -1,5 +1,5 @@
#include <minix/drivers.h>
#include <minix/driver.h>
#include <minix/chardriver.h>
#include <stdio.h>
#include <stdlib.h>
#include <minix/ds.h>
@ -8,14 +8,13 @@
/*
* Function prototypes for the hello driver.
*/
FORWARD _PROTOTYPE( char * hello_name, (void) );
FORWARD _PROTOTYPE( int hello_open, (struct driver *d, message *m) );
FORWARD _PROTOTYPE( int hello_close, (struct driver *d, message *m) );
FORWARD _PROTOTYPE( struct device * hello_prepare, (int device) );
FORWARD _PROTOTYPE( int hello_transfer, (int procnr, int opcode,
FORWARD _PROTOTYPE( int hello_open, (message *m) );
FORWARD _PROTOTYPE( int hello_close, (message *m) );
FORWARD _PROTOTYPE( struct device * hello_prepare, (dev_t device) );
FORWARD _PROTOTYPE( int hello_transfer, (endpoint_t endpt, int opcode,
u64_t position, iovec_t *iov,
unsigned nr_req) );
FORWARD _PROTOTYPE( void hello_geometry, (struct partition *entry) );
unsigned int nr_req,
endpoint_t user_endpt) );
/* SEF functions and variables. */
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) );
/* Entry points to the hello driver. */
PRIVATE struct driver hello_tab =
PRIVATE struct chardriver hello_tab =
{
hello_name,
hello_open,
hello_close,
nop_ioctl,
hello_prepare,
hello_transfer,
nop_cleanup,
hello_geometry,
nop_alarm,
nop_cancel,
nop_select,
nop_ioctl,
NULL,
NULL
};
@ -48,47 +43,38 @@ PRIVATE struct device hello_device;
/** State variable to count the number of times the device has been opened. */
PRIVATE int open_counter;
PRIVATE char * hello_name(void)
{
printf("hello_name()\n");
return "hello";
}
PRIVATE int hello_open(d, m)
struct driver *d;
message *m;
PRIVATE int hello_open(message *UNUSED(m))
{
printf("hello_open(). Called %d time(s).\n", ++open_counter);
return OK;
}
PRIVATE int hello_close(d, m)
struct driver *d;
message *m;
PRIVATE int hello_close(message *UNUSED(m))
{
printf("hello_close()\n");
return OK;
}
PRIVATE struct device * hello_prepare(dev)
int dev;
PRIVATE struct device * hello_prepare(dev_t UNUSED(dev))
{
hello_device.dv_base = make64(0, 0);
hello_device.dv_size = make64(strlen(HELLO_MESSAGE), 0);
return &hello_device;
}
PRIVATE int hello_transfer(proc_nr, opcode, position, iov, nr_req)
int proc_nr;
int opcode;
u64_t position;
iovec_t *iov;
unsigned nr_req;
PRIVATE int hello_transfer(endpoint_t endpt, int opcode, u64_t position,
iovec_t *iov, unsigned nr_req, endpoint_t UNUSED(user_endpt))
{
int bytes, ret;
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 ?
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)
{
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)),
bytes, D);
iov->iov_size -= bytes;
@ -111,16 +97,7 @@ PRIVATE int hello_transfer(proc_nr, opcode, position, iov, nr_req)
return ret;
}
PRIVATE void hello_geometry(entry)
struct partition *entry;
{
printf("hello_geometry()\n");
entry->cylinders = 0;
entry->heads = 0;
entry->sectors = 0;
}
PRIVATE int sef_cb_lu_state_save(int state) {
PRIVATE int sef_cb_lu_state_save(int UNUSED(state)) {
/* Save the state. */
ds_publish_u32("open_counter", open_counter, DSF_OVERWRITE);
@ -161,7 +138,7 @@ PRIVATE void sef_local_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. */
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. */
if (do_announce_driver) {
driver_announce();
chardriver_announce();
}
/* Initialization completed successfully. */
return OK;
}
PUBLIC int main(int argc, char **argv)
PUBLIC int main(void)
{
/*
* Perform initialization.
@ -204,7 +181,7 @@ PUBLIC int main(int argc, char **argv)
/*
* Run the main loop.
*/
driver_task(&hello_tab, DRIVER_STD);
chardriver_task(&hello_tab, CHARDRIVER_SYNC);
return OK;
}

View file

@ -2,8 +2,8 @@
PROG= log
SRCS= log.c diag.c liveupdate.c
DPADD+= ${LIBDRIVER} ${LIBSYS}
LDADD+= -ldriver -lsys
DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
LDADD+= -lchardriver -lsys
MAN=

View file

@ -22,36 +22,31 @@ PUBLIC struct logdevice logdevices[NR_DEVS];
PRIVATE struct device log_geom[NR_DEVS]; /* base and size of devices */
PRIVATE int log_device = -1; /* current device */
FORWARD _PROTOTYPE( char *log_name, (void) );
FORWARD _PROTOTYPE( struct device *log_prepare, (int device) );
FORWARD _PROTOTYPE( int log_transfer, (int proc_nr, int opcode, u64_t position,
iovec_t *iov, unsigned nr_req) );
FORWARD _PROTOTYPE( int log_do_open, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int log_cancel, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int log_select, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int log_other, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( void log_geometry, (struct partition *entry) );
FORWARD _PROTOTYPE( int subread, (struct logdevice *log, int count, int proc_nr, cp_grant_id_t grant, size_t) );
FORWARD _PROTOTYPE( struct device *log_prepare, (dev_t device) );
FORWARD _PROTOTYPE( int log_transfer, (endpoint_t endpt, int opcode,
u64_t position, iovec_t *iov, unsigned int nr_req,
endpoint_t user_endpt) );
FORWARD _PROTOTYPE( int log_do_open, (message *m_ptr) );
FORWARD _PROTOTYPE( int log_cancel, (message *m_ptr) );
FORWARD _PROTOTYPE( int log_select, (message *m_ptr) );
FORWARD _PROTOTYPE( int log_other, (message *m_ptr) );
FORWARD _PROTOTYPE( int subread, (struct logdevice *log, int count,
endpoint_t endpt, cp_grant_id_t grant, size_t) );
/* Entry points to this driver. */
PRIVATE struct driver log_dtab = {
log_name, /* current device's name */
PRIVATE struct chardriver log_dtab = {
log_do_open, /* open or mount */
do_nop, /* nothing on a close */
nop_ioctl, /* ioctl nop */
log_prepare, /* prepare for I/O on a given minor device */
log_transfer, /* do the I/O */
nop_cleanup, /* no need to clean up */
log_geometry, /* geometry */
nop_alarm, /* no alarm */
nop_alarm, /* no alarm */
log_cancel, /* CANCEL request */
log_select, /* DEV_SELECT request */
log_other, /* Unrecognized messages */
NULL /* HW int */
log_other /* Unrecognized messages */
};
extern int device_endpt;
/* SEF functions and variables. */
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
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();
/* Call the generic receive loop. */
driver_task(&log_dtab, DRIVER_ASYN);
chardriver_task(&log_dtab, CHARDRIVER_ASYNC);
return(OK);
}
@ -99,7 +94,7 @@ PRIVATE void sef_local_startup()
/*===========================================================================*
* 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. */
int i;
@ -131,26 +126,15 @@ PRIVATE void sef_cb_signal_handler(int signo)
do_new_kmess();
}
/*===========================================================================*
* log_name *
*===========================================================================*/
PRIVATE char *log_name()
{
/* Return a name for the current device. */
static char name[] = "log";
return name;
}
/*===========================================================================*
* log_prepare *
*===========================================================================*/
PRIVATE struct device *log_prepare(device)
int device;
PRIVATE struct device *log_prepare(dev_t device)
{
/* Prepare for I/O on a device: check if the minor device number is ok. */
if (device < 0 || device >= NR_DEVS) return(NULL);
log_device = device;
if (device >= NR_DEVS) return(NULL);
log_device = (int) device;
return(&log_geom[device]);
}
@ -159,7 +143,7 @@ int device;
* subwrite *
*===========================================================================*/
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)
{
int d, r;
@ -174,7 +158,7 @@ subwrite(struct logdevice *log, int count, int proc_nr,
memcpy(buf, localbuf, count);
}
else {
if((r=sys_safecopyfrom(proc_nr, grant, offset,
if((r=sys_safecopyfrom(endpt, grant, offset,
(vir_bytes)buf, count, D)) != OK)
return r;
}
@ -267,7 +251,7 @@ log_append(char *buf, int count)
* subread *
*===========================================================================*/
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)
{
char *buf;
@ -278,7 +262,7 @@ subread(struct logdevice *log, int count, int proc_nr,
count = LOG_SIZE - 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)
return r;
@ -291,12 +275,14 @@ subread(struct logdevice *log, int count, int proc_nr,
/*===========================================================================*
* log_transfer *
*===========================================================================*/
PRIVATE int log_transfer(proc_nr, opcode, position, iov, nr_req)
int proc_nr; /* process doing the request */
int opcode; /* DEV_GATHER_S or DEV_SCATTER_S */
u64_t position; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
PRIVATE int log_transfer(
endpoint_t endpt, /* endpoint of grant owner */
int opcode, /* DEV_GATHER_S or DEV_SCATTER_S */
u64_t UNUSED(position), /* offset on device to read or write */
iovec_t *iov, /* pointer to read or write 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. */
int count;
@ -331,27 +317,25 @@ unsigned nr_req; /* length of request vector */
if(accumulated_read)
return OK;
/* No data available; let caller block. */
log->log_source = proc_nr;
log->log_source = endpt;
log->log_iosize = count;
log->log_user_grant = grant;
log->log_user_offset = 0;
log->log_revive_alerted = 0;
/* device_endpt is a global in drivers library. */
log->log_proc_nr = device_endpt;
log->log_proc_nr = user_endpt;
#if LOG_DEBUG
printf("blocked %d (%d)\n",
log->log_source, log->log_proc_nr);
#endif
return(EDONTREPLY);
}
count = subread(log, count, proc_nr, grant, vir_offset);
count = subread(log, count, endpt, grant, vir_offset);
if(count < 0) {
return count;
}
accumulated_read += count;
} else {
count = subwrite(log, count, proc_nr, grant, vir_offset, NULL);
count = subwrite(log, count, endpt, grant, vir_offset, NULL);
if(count < 0)
return count;
}
@ -371,33 +355,16 @@ unsigned nr_req; /* length of request vector */
/*============================================================================*
* log_do_open *
*============================================================================*/
PRIVATE int log_do_open(dp, m_ptr)
struct driver *dp;
message *m_ptr;
PRIVATE int log_do_open(message *m_ptr)
{
if (log_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
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 *
*============================================================================*/
PRIVATE int log_cancel(dp, m_ptr)
struct driver *dp;
message *m_ptr;
PRIVATE int log_cancel(message *m_ptr)
{
int d;
d = m_ptr->TTY_LINE;
@ -411,9 +378,7 @@ message *m_ptr;
/*============================================================================*
* log_other *
*============================================================================*/
PRIVATE int log_other(dp, m_ptr)
struct driver *dp;
message *m_ptr;
PRIVATE int log_other(message *m_ptr)
{
int r;
@ -440,9 +405,7 @@ message *m_ptr;
/*============================================================================*
* log_select *
*============================================================================*/
PRIVATE int log_select(dp, m_ptr)
struct driver *dp;
message *m_ptr;
PRIVATE int log_select(message *m_ptr)
{
int d, ready_ops = 0, ops = 0;
d = m_ptr->TTY_LINE;
@ -455,15 +418,15 @@ message *m_ptr;
ops = m_ptr->USER_ENDPT & (SEL_RD|SEL_WR|SEL_ERR);
/* Read blocks when there is no log. */
/* Read blocks when there is no log. */
if((m_ptr->USER_ENDPT & SEL_RD) && logdevices[d].log_size > 0) {
#if LOG_DEBUG
printf("log can read; size %d\n", logdevices[d].log_size);
#endif
ready_ops |= SEL_RD; /* writes never block */
}
}
/* Write never blocks. */
/* Write never blocks. */
if(m_ptr->USER_ENDPT & SEL_WR) ready_ops |= SEL_WR;
/* Enable select calback if no operations were

View file

@ -1,6 +1,6 @@
/* Includes. */
#include <minix/drivers.h>
#include <minix/driver.h>
#include <minix/chardriver.h>
#include <minix/type.h>
#include <minix/const.h>
#include <minix/com.h>

View file

@ -2,8 +2,8 @@
PROG= memory
SRCS= memory.c imgrd.c
DPADD+= ${LIBDRIVER} ${LIBSYS}
LDADD+= -ldriver -lsys
DPADD+= ${LIBBLOCKDRIVER} ${LIBCHARDRIVER} ${LIBSYS}
LDADD+= -lblockdriver -lchardriver -lsys
MAN=

View file

@ -16,7 +16,8 @@
*/
#include <minix/drivers.h>
#include <minix/driver.h>
#include <minix/chardriver.h>
#include <minix/blockdriver.h>
#include <sys/ioc_memory.h>
#include <minix/ds.h>
#include <minix/vm.h>
@ -39,41 +40,57 @@
PRIVATE struct device m_geom[NR_DEVS]; /* base and size of each device */
PRIVATE vir_bytes m_vaddrs[NR_DEVS];
PRIVATE int m_device; /* current device */
PRIVATE struct kinfo kinfo; /* kernel information */
extern int errno; /* error number for PM calls */
PRIVATE dev_t m_device; /* current minor character device */
PRIVATE int openct[NR_DEVS];
FORWARD _PROTOTYPE( char *m_name, (void) );
FORWARD _PROTOTYPE( struct device *m_prepare, (int device) );
FORWARD _PROTOTYPE( int m_transfer, (int proc_nr, int opcode,
u64_t position, iovec_t *iov, unsigned nr_req) );
FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int m_do_close, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int m_ioctl, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) );
FORWARD _PROTOTYPE( struct device *m_prepare, (dev_t device) );
FORWARD _PROTOTYPE( int m_transfer, (endpoint_t endpt, int opcode,
u64_t position, iovec_t *iov, unsigned int nr_req,
endpoint_t user_endpt) );
FORWARD _PROTOTYPE( int m_do_open, (message *m_ptr) );
FORWARD _PROTOTYPE( int m_do_close, (message *m_ptr) );
/* Entry points to this driver. */
PRIVATE struct driver m_dtab = {
m_name, /* current device's name */
FORWARD _PROTOTYPE( struct device *m_block_part, (dev_t minor) );
FORWARD _PROTOTYPE( int m_block_transfer, (dev_t minor, int do_write,
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_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_transfer, /* do the I/O */
nop_cleanup, /* no need to clean up */
m_geometry, /* memory device "geometry" */
nop_alarm,
nop_cancel,
nop_select,
NULL,
NULL
nop_alarm, /* no alarms */
nop_cancel, /* no blocking operations */
nop_select, /* select not supported */
NULL /* other messages not supported */
};
/* 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. */
#define ZERO_BUF_SIZE 1024
#define ZERO_BUF_SIZE 1024
PRIVATE char dev_zero[ZERO_BUF_SIZE];
#define click_to_round_k(n) \
@ -88,11 +105,23 @@ FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
*===========================================================================*/
PUBLIC int main(void)
{
message msg;
int r, ipc_status;
/* SEF local startup. */
sef_local_startup();
/* Call the generic receive loop. */
driver_task(&m_dtab, DRIVER_STD);
/* The receive loop. */
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);
}
@ -118,17 +147,18 @@ PRIVATE void sef_local_startup()
/*===========================================================================*
* 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. */
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))) {
panic("Couldn't get kernel information: %d", s);
}
#if 0
/* Map in kernel memory for /dev/kmem. */
m_geom[KMEM_DEV].dv_base = cvul64(kinfo.kmem_base);
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. */
static char name[] = "memory";
return name;
/* Return TRUE iff the given minor device number is for a block device. */
switch (minor) {
case MEM_DEV:
case KMEM_DEV:
case NULL_DEV:
case ZERO_DEV:
return FALSE;
default:
return TRUE;
}
}
/*===========================================================================*
* m_prepare *
*===========================================================================*/
PRIVATE struct device *m_prepare(device)
int device;
PRIVATE struct device *m_prepare(dev_t device)
{
/* 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;
return(&m_geom[device]);
@ -186,20 +224,23 @@ int device;
/*===========================================================================*
* m_transfer *
*===========================================================================*/
PRIVATE int m_transfer(proc_nr, opcode, pos64, iov, nr_req)
int proc_nr; /* process doing the request */
int opcode; /* DEV_GATHER_S or DEV_SCATTER_S */
u64_t pos64; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
PRIVATE int m_transfer(
endpoint_t endpt, /* endpoint of grant owner */
int opcode, /* DEV_GATHER_S or DEV_SCATTER_S */
u64_t pos64, /* offset on device to read or write */
iovec_t *iov, /* pointer to read or write 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;
vir_bytes user_vir, vir_offset = 0;
vir_bytes vir_offset = 0;
struct device *dv;
unsigned long dv_size;
int s, r;
off_t position;
cp_grant_id_t grant;
vir_bytes dev_vaddr;
/* 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. */
count = iov->iov_size;
user_vir = iov->iov_addr;
grant = (cp_grant_id_t) iov->iov_addr;
switch (m_device) {
@ -225,27 +266,21 @@ unsigned nr_req; /* length of request vector */
if (opcode == DEV_GATHER_S) return(OK); /* always at EOF */
break;
/* Virtual copying. For RAM disks, kernel memory and internal FS. */
/* Virtual copying. For kernel memory. */
default:
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);
return EIO;
}
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 (opcode == DEV_GATHER_S) { /* copy actual data */
r=sys_safecopyto(proc_nr, user_vir, vir_offset,
dev_vaddr + position, count, D);
r=sys_safecopyto(endpt, grant, vir_offset,
dev_vaddr + position, count, D);
} else {
r=sys_safecopyfrom(proc_nr, user_vir, vir_offset,
dev_vaddr + position, count, D);
r=sys_safecopyfrom(endpt, grant, vir_offset,
dev_vaddr + position, count, D);
}
if(r != OK) {
panic("I/O copy failed: %d", r);
@ -263,10 +298,10 @@ unsigned nr_req; /* length of request vector */
static char *vaddr;
int r;
u32_t subcount;
phys_bytes mem_phys;
phys_bytes mem_phys;
if (position >= dv_size)
return(OK); /* check for EOF */
return(OK); /* check for EOF */
if (position + count > dv_size)
count = dv_size - position;
mem_phys = position;
@ -280,7 +315,7 @@ unsigned nr_req; /* length of request vector */
if(!any_mapped || pagestart_mapped != pagestart) {
if(any_mapped) {
if(vm_unmap_phys(SELF, vaddr, I386_PAGE_SIZE) != OK)
panic("vm_unmap_phys failed");
panic("vm_unmap_phys failed");
any_mapped = 0;
}
vaddr = vm_map_phys(SELF, (void *) pagestart, I386_PAGE_SIZE);
@ -302,10 +337,10 @@ unsigned nr_req; /* length of request vector */
subcount = count;
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);
} else {
s=sys_safecopyfrom(proc_nr, user_vir,
s=sys_safecopyfrom(endpt, grant,
vir_offset, (vir_bytes) vaddr+page_off, subcount, D);
}
if(s != OK)
@ -319,15 +354,15 @@ unsigned nr_req; /* length of request vector */
if (opcode == DEV_GATHER_S) {
size_t suboffset = 0;
left = count;
while (left > 0) {
chunk = (left > ZERO_BUF_SIZE) ? ZERO_BUF_SIZE : left;
s=sys_safecopyto(proc_nr, user_vir,
while (left > 0) {
chunk = (left > ZERO_BUF_SIZE) ? ZERO_BUF_SIZE : left;
s=sys_safecopyto(endpt, grant,
vir_offset+suboffset, (vir_bytes) dev_zero, chunk, D);
if(s != OK)
return s;
left -= chunk;
suboffset += chunk;
}
return s;
left -= chunk;
suboffset += chunk;
}
}
break;
@ -336,7 +371,7 @@ unsigned nr_req; /* length of request vector */
/* Book the number of bytes transferred. */
position += count;
vir_offset += count;
if ((iov->iov_size -= count) == 0) { iov++; nr_req--; vir_offset = 0; }
if ((iov->iov_size -= count) == 0) { iov++; nr_req--; vir_offset = 0; }
}
return(OK);
@ -345,10 +380,9 @@ unsigned nr_req; /* length of request vector */
/*===========================================================================*
* m_do_open *
*===========================================================================*/
PRIVATE int m_do_open(dp, m_ptr)
struct driver *dp;
message *m_ptr;
PRIVATE int m_do_open(message *m_ptr)
{
/* Open a memory character device. */
int r;
/* 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]++;
return(OK);
@ -376,24 +406,128 @@ message *m_ptr;
/*===========================================================================*
* m_do_close *
*===========================================================================*/
PRIVATE int m_do_close(dp, m_ptr)
struct driver *dp;
message *m_ptr;
PRIVATE int m_do_close(message *m_ptr)
{
/* Close a memory character device. */
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) {
panic("closed too often");
printf("MEMORY: closing unopened device %d\n", m_device);
return(EINVAL);
}
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. */
if(m_device == IMGRD_DEV && openct[m_device] == 0 && m_vaddrs[IMGRD_DEV]) {
vir_bytes vaddr, vlen;
if(minor == IMGRD_DEV && openct[minor] == 0 && m_vaddrs[IMGRD_DEV]) {
vir_bytes vaddr, vlen;
vaddr = m_vaddrs[IMGRD_DEV];
vlen = imgrd_size;
/* Align `inwards' so as to not unmap more than the initial
@ -417,91 +551,70 @@ message *m_ptr;
}
/*===========================================================================*
* m_ioctl *
* m_block_ioctl *
*===========================================================================*/
PRIVATE int m_ioctl(dp, m_ptr)
struct driver *dp; /* pointer to driver structure */
message *m_ptr; /* pointer to control message */
PRIVATE int m_block_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
cp_grant_id_t grant)
{
/* 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.
*/
struct device *dv;
u32_t ramdev_size;
int s;
void *mem;
switch (m_ptr->REQUEST) {
case MIOCRAMSIZE: {
/* Someone wants to create a new RAM disk with the given size. */
u32_t ramdev_size;
int s, dev;
void *mem;
if (request != MIOCRAMSIZE)
return EINVAL;
/* A ramdisk can be created only once, and only on RAM disk device. */
dev = m_ptr->DEVICE;
if(dev < 0 || dev >= NR_DEVS) {
printf("MEM: MIOCRAMSIZE: %d not a valid device\n", dev);
}
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);
/* 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;
}
/* Get request structure */
s= sys_safecopyfrom(m_ptr->m_source, (vir_bytes)m_ptr->IO_GRANT,
0, (vir_bytes)&ramdev_size, sizeof(ramdev_size), D);
if (s != OK)
return s;
if(m_vaddrs[dev] && !cmp64(dv->dv_size, cvul64(ramdev_size))) {
return(OK);
}
/* openct is 1 for the ioctl(). */
if(openct[dev] != 1) {
printf("MEM: MIOCRAMSIZE: %d in use (count %d)\n",
dev, openct[dev]);
return(EBUSY);
}
if(m_vaddrs[dev]) {
u32_t size;
if(ex64hi(dv->dv_size)) {
panic("huge old ramdisk");
}
size = ex64lo(dv->dv_size);
minix_munmap((void *) m_vaddrs[dev], size);
m_vaddrs[dev] = (vir_bytes) NULL;
/* Get request structure */
s= sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&ramdev_size,
sizeof(ramdev_size), D);
if (s != OK)
return s;
if(m_vaddrs[minor] && !cmp64(dv->dv_size, cvul64(ramdev_size))) {
return(OK);
}
/* openct is 1 for the ioctl(). */
if(openct[minor] != 1) {
printf("MEM: MIOCRAMSIZE: %d in use (count %d)\n",
minor, openct[minor]);
return(EBUSY);
}
if(m_vaddrs[minor]) {
u32_t size;
if(ex64hi(dv->dv_size)) {
panic("huge old ramdisk");
}
size = ex64lo(dv->dv_size);
minix_munmap((void *) m_vaddrs[minor], size);
m_vaddrs[minor] = (vir_bytes) NULL;
}
#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
/* Try to allocate a piece of memory for the RAM disk. */
if((mem = minix_mmap(NULL, ramdev_size, PROT_READ|PROT_WRITE,
MAP_PREALLOC|MAP_ANON, -1, 0)) == MAP_FAILED) {
printf("MEM: failed to get memory for ramdisk\n");
return(ENOMEM);
}
m_vaddrs[dev] = (vir_bytes) mem;
dv->dv_size = cvul64(ramdev_size);
break;
}
default:
return(do_diocntl(&m_dtab, m_ptr));
/* Try to allocate a piece of memory for the RAM disk. */
if((mem = minix_mmap(NULL, ramdev_size, PROT_READ|PROT_WRITE,
MAP_PREALLOC|MAP_ANON, -1, 0)) == MAP_FAILED) {
printf("MEM: failed to get memory for ramdisk\n");
return(ENOMEM);
}
m_vaddrs[minor] = (vir_bytes) mem;
dv->dv_size = cvul64(ramdev_size);
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;
}

View file

@ -2,8 +2,8 @@
PROG= pci
SRCS= main.c pci.c pci_table.c
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -ldriver -lsys -ltimers
DPADD+= ${LIBSYS} ${LIBTIMERS}
LDADD+= -lsys -ltimers
MAN=

View file

@ -2,8 +2,8 @@
PROG= printer
SRCS= printer.c liveupdate.c
DPADD+= ${LIBDRIVER} ${LIBSYS}
LDADD+= -ldriver -lsys
DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
LDADD+= -lchardriver -lsys
MAN=

View file

@ -34,7 +34,7 @@
#include <minix/endpoint.h>
#include <minix/drivers.h>
#include <minix/driver.h>
#include <minix/chardriver.h>
/* Control bits (in port_base + 2). "+" means positive logic and "-" means
* 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 *
*===========================================================================*/
PUBLIC int main(int argc, char *argv[])
PUBLIC int main(void)
{
/* Main routine of the printer task. */
message pr_mess; /* buffer for all incoming messages */
@ -190,11 +190,11 @@ PRIVATE void sef_local_startup()
/*===========================================================================*
* 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. */
/* Announce we are up! */
driver_announce();
chardriver_announce();
return OK;
}

View file

@ -4,8 +4,8 @@ SRCS= main.c random.c rijndael_api.c rijndael_alg.c
.PATH: ${.CURDIR}/aes
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBMINIXUTIL}
LDADD+= -ldriver -lsys -lminixutil
DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBMINIXUTIL}
LDADD+= -lchardriver -lsys -lminixutil
MAN=

View file

@ -4,7 +4,7 @@
*/
#include <minix/drivers.h>
#include <minix/driver.h>
#include <minix/chardriver.h>
#include <minix/type.h>
#include "assert.h"
@ -16,35 +16,31 @@
#define KRANDOM_PERIOD 1 /* ticks between krandom calls */
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 */
FORWARD _PROTOTYPE( char *r_name, (void) );
FORWARD _PROTOTYPE( struct device *r_prepare, (int device) );
FORWARD _PROTOTYPE( int r_transfer, (int proc_nr, int opcode, u64_t position,
iovec_t *iov, unsigned nr_req) );
FORWARD _PROTOTYPE( int r_do_open, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int r_ioctl, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( void r_geometry, (struct partition *entry) );
FORWARD _PROTOTYPE( void r_random, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( void r_updatebin, (int source, struct k_randomness_bin *rb));
FORWARD _PROTOTYPE( struct device *r_prepare, (dev_t device) );
FORWARD _PROTOTYPE( int r_transfer, (endpoint_t endpt, int opcode,
u64_t position, iovec_t *iov, unsigned int nr_req,
endpoint_t user_endpt) );
FORWARD _PROTOTYPE( int r_do_open, (message *m_ptr) );
FORWARD _PROTOTYPE( void r_random, (message *m_ptr) );
FORWARD _PROTOTYPE( void r_updatebin, (int source,
struct k_randomness_bin *rb) );
/* Entry points to this driver. */
PRIVATE struct driver r_dtab = {
r_name, /* current device's name */
PRIVATE struct chardriver r_dtab = {
r_do_open, /* open or mount */
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_transfer, /* do the I/O */
nop_cleanup, /* no need to clean up */
r_geometry, /* device "geometry" */
r_random, /* get randomness from kernel (alarm) */
nop_cancel,
nop_select,
NULL,
NULL
nop_cancel, /* cancel not supported */
nop_select, /* select not supported */
NULL, /* other messages not supported */
};
/* Buffer for the /dev/random number generator. */
@ -64,7 +60,7 @@ PUBLIC int main(void)
sef_local_startup();
/* Call the generic receive loop. */
driver_task(&r_dtab, DRIVER_ASYN);
chardriver_task(&r_dtab, CHARDRIVER_ASYNC);
return(OK);
}
@ -90,14 +86,14 @@ PRIVATE void sef_local_startup()
/*===========================================================================*
* 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. */
static struct k_randomness krandom;
int i, s;
random_init();
r_random(NULL, NULL); /* also set periodic timer */
r_random(NULL); /* also set periodic timer */
/* Retrieve first randomness buffer with parameters. */
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]);
/* Announce we are up! */
driver_announce();
chardriver_announce();
return(OK);
}
/*===========================================================================*
* r_name *
*===========================================================================*/
PRIVATE char *r_name()
{
/* Return a name for the current device. */
static char name[] = "random";
return name;
}
/*===========================================================================*
* r_prepare *
*===========================================================================*/
PRIVATE struct device *r_prepare(device)
int device;
PRIVATE struct device *r_prepare(dev_t device)
{
/* 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;
return(&m_geom[device]);
@ -151,16 +136,18 @@ int device;
/*===========================================================================*
* r_transfer *
*===========================================================================*/
PRIVATE int r_transfer(proc_nr, opcode, position, iov, nr_req)
int proc_nr; /* process doing the request */
int opcode; /* DEV_GATHER or DEV_SCATTER */
u64_t position; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
PRIVATE int r_transfer(
endpoint_t endpt, /* endpoint of grant owner */
int opcode, /* DEV_GATHER or DEV_SCATTER */
u64_t position, /* offset on device to read or write */
iovec_t *iov, /* pointer to read or write 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. */
unsigned count, left, chunk;
vir_bytes user_vir;
cp_grant_id_t grant;
struct device *dv;
int r;
size_t vir_offset = 0;
@ -172,7 +159,7 @@ unsigned nr_req; /* length of request vector */
/* How much to transfer and where to / from. */
count = iov->iov_size;
user_vir = iov->iov_addr;
grant = (cp_grant_id_t) iov->iov_addr;
switch (m_device) {
@ -185,23 +172,21 @@ unsigned nr_req; /* length of request vector */
chunk = (left > RANDOM_BUF_SIZE) ? RANDOM_BUF_SIZE : left;
if (opcode == DEV_GATHER_S) {
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);
if (r != OK)
{
printf(
"random: sys_safecopyto failed for proc %d, grant %d\n",
proc_nr, user_vir);
printf("random: sys_safecopyto failed for proc %d, "
"grant %d\n", endpt, grant);
return r;
}
} 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);
if (r != OK)
{
printf(
"random: sys_safecopyfrom failed for proc %d, grant %d\n",
proc_nr, user_vir);
printf("random: sys_safecopyfrom failed for proc %d, "
"grant %d\n", endpt, grant);
return r;
}
random_putbytes(random_buf, chunk);
@ -224,37 +209,18 @@ unsigned nr_req; /* length of request vector */
return(OK);
}
/*============================================================================*
* r_do_open *
*============================================================================*/
PRIVATE int r_do_open(dp, m_ptr)
struct driver *dp;
message *m_ptr;
/*===========================================================================*
* r_do_open *
*===========================================================================*/
PRIVATE int r_do_open(message *m_ptr)
{
/* Check device number on open.
/* Check device number on open.
*/
if (r_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
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) { \
rand_t *r; \
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)
{
int r_next, r_size, r_high;
@ -293,12 +262,10 @@ PRIVATE void r_updatebin(int source, struct k_randomness_bin *rb)
return;
}
/*============================================================================*
* r_random *
*============================================================================*/
PRIVATE void r_random(dp, m_ptr)
struct driver *dp; /* pointer to driver structure */
message *m_ptr; /* pointer to alarm message */
/*===========================================================================*
* r_random *
*===========================================================================*/
PRIVATE void r_random(message *UNUSED(m_ptr))
{
/* Fetch random information from the kernel to update /dev/random. */
int s;
@ -322,14 +289,3 @@ message *m_ptr; /* pointer to alarm message */
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;
}

View file

@ -2,8 +2,8 @@
PROG= readclock.drv
SRCS= readclock.c
DPADD+= ${LIBDRIVER} ${LIBSYS}
LDADD+= -ldriver -lsys
DPADD+= ${LIBSYS}
LDADD+= -lsys
MAN=

View file

@ -2,8 +2,8 @@
PROG= ti1225
SRCS= ti1225.c
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -ldriver -lsys -ltimers
DPADD+= ${LIBSYS}
LDADD+= -lsys
MAN=

View file

@ -104,7 +104,7 @@ PRIVATE void sef_local_startup()
/*===========================================================================*
* 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. */
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]);
}
/* Announce we are up! */
driver_announce();
return(OK);
}

View file

@ -3,8 +3,8 @@
PROG= tty
SRCS= tty.c console.c keyboard.c pty.c rs232.c
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -ldriver -lsys -ltimers
DPADD+= ${LIBSYS} ${LIBTIMERS}
LDADD+= -lsys -ltimers
MAN=

View file

@ -896,8 +896,7 @@ clock_t dur;
/*===========================================================================*
* stop_beep *
*===========================================================================*/
PRIVATE void stop_beep(tmrp)
timer_t *tmrp;
PRIVATE void stop_beep(timer_t *UNUSED(tmrp))
{
/* Turn off the beeper by turning off bits 0 and 1 in PORT_B. */
unsigned long port_b_val;
@ -1234,9 +1233,7 @@ struct sequence *seq;
/*===========================================================================*
* cons_ioctl *
*===========================================================================*/
PRIVATE int cons_ioctl(tp, try)
tty_t *tp;
int try;
PRIVATE int cons_ioctl(tty_t *tp, int UNUSED(try))
{
/* Set the screen dimensions. */

View file

@ -481,8 +481,7 @@ int scode;
/*===========================================================================*
* kbd_interrupt *
*===========================================================================*/
PUBLIC void kbd_interrupt(m_ptr)
message *m_ptr;
PUBLIC void kbd_interrupt(message *UNUSED(m_ptr))
{
/* A keyboard interrupt has occurred. Process it. */
int o, isaux;
@ -911,9 +910,9 @@ PRIVATE int kbc_read()
if(sys_inb(KEYBD, &byte) != OK)
printf("kbc_read: 2 sys_inb failed\n");
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
printf("keyboard`kbc_read: returning byte 0x%x\n",
printf("keyboard`kbc_read: returning byte 0x%lx\n",
byte);
#endif
return byte;
@ -1296,8 +1295,7 @@ int *isauxp;
/*===========================================================================*
* kbd_watchdog *
*===========================================================================*/
PRIVATE void kbd_watchdog(tmrp)
timer_t *tmrp;
PRIVATE void kbd_watchdog(timer_t *UNUSED(tmrp))
{
kbd_watchdog_set= 0;

View file

@ -405,7 +405,7 @@ PRIVATE int pty_read(tty_t *tp, int try)
/*===========================================================================*
* 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. */
pty_t *pp = tp->tty_priv;
@ -430,7 +430,7 @@ PRIVATE int pty_close(tty_t *tp, int try)
/*===========================================================================*
* pty_icancel *
*===========================================================================*/
PRIVATE int pty_icancel(tty_t *tp, int try)
PRIVATE int pty_icancel(tty_t *tp, int UNUSED(try))
{
/* Discard waiting input. */
pty_t *pp = tp->tty_priv;
@ -447,7 +447,7 @@ PRIVATE int pty_icancel(tty_t *tp, int try)
/*===========================================================================*
* 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. */
pty_t *pp = tp->tty_priv;

View file

@ -324,7 +324,7 @@ int c; /* character to echo */
/*===========================================================================*
* rs_ioctl *
*===========================================================================*/
PRIVATE int rs_ioctl(tty_t *tp, int dummy)
PRIVATE int rs_ioctl(tty_t *tp, int UNUSED(dummy))
/* tp; which TTY */
{
/* Reconfigure the line as soon as the output has drained. */
@ -544,7 +544,7 @@ PUBLIC void rs_interrupt(message *m)
/*===========================================================================*
* rs_icancel *
*===========================================================================*/
PRIVATE int rs_icancel(tty_t *tp, int dummy)
PRIVATE int rs_icancel(tty_t *tp, int UNUSED(dummy))
{
/* Cancel waiting input. */
rs232_t *rs = tp->tty_priv;
@ -561,7 +561,7 @@ PRIVATE int rs_icancel(tty_t *tp, int dummy)
/*===========================================================================*
* rs_ocancel *
*===========================================================================*/
PRIVATE int rs_ocancel(tty_t *tp, int dummy)
PRIVATE int rs_ocancel(tty_t *tp, int UNUSED(dummy))
{
/* Cancel pending output. */
rs232_t *rs = tp->tty_priv;
@ -636,7 +636,7 @@ PRIVATE void rs_ostart(rs232_t *rs)
/*===========================================================================*
* 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. */
rs232_t *rs = tp->tty_priv;
@ -654,7 +654,7 @@ PRIVATE int rs_break(tty_t *tp, int dummy)
/*===========================================================================*
* 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. */
rs232_t *rs = tp->tty_priv;

View file

@ -309,7 +309,7 @@ PRIVATE void sef_local_startup()
/*===========================================================================*
* 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. */
int r;
@ -1524,7 +1524,7 @@ register tty_t *tp;
/*===========================================================================*
* 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. */
return 0;

View file

@ -16,9 +16,9 @@ LIBCOMPAT_DIR?=
LIBMINLIB_DIR?=
LIBASYN_DIR?=
SUBDIR= csu ${LIBCOMPAT_DIR} ${LIBC_DIR} libdriver libnetdriver \
libedit ${LIBM_DIR} libsys libtimers ${LIBUTIL_DIR} libl libhgfs \
libz libfetch libvtreefs libaudiodriver libmthread \
SUBDIR= csu ${LIBCOMPAT_DIR} ${LIBC_DIR} libblockdriver libchardriver \
libnetdriver libedit ${LIBM_DIR} libsys libtimers ${LIBUTIL_DIR} \
libl libhgfs libz libfetch libvtreefs libaudiodriver libmthread \
libexec libdevman libusb ${LIBMINLIB_DIR} ${LIBASYN_DIR} \
libddekit libminixfs libbdev

View file

@ -83,7 +83,7 @@ EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) );
EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
PUBLIC int is_status_msg_expected = FALSE;
PUBLIC int main(int argc, char *argv[])
PUBLIC int main(void)
{
int r, caller;
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*/
/* Announce we are up! */
driver_announce();
chardriver_announce();
return OK;
}

View file

@ -32,9 +32,10 @@ static int bdev_opcl(int req, dev_t dev, int access)
*/
message m;
memset(&m, 0, sizeof(m));
m.m_type = req;
m.DEVICE = minor(dev);
m.COUNT = access;
m.BDEV_MINOR = minor(dev);
m.BDEV_ACCESS = access;
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.
*/
return bdev_opcl(DEV_OPEN, dev, access);
return bdev_opcl(BDEV_OPEN, dev, access);
}
int bdev_close(dev_t dev)
@ -54,11 +55,11 @@ int bdev_close(dev_t dev)
* 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,
int UNUSED(flags), message *m)
static int bdev_rdwt_setup(int req, dev_t dev, u64_t pos, char *buf,
size_t count, int flags, message *m)
{
/* 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;
int access;
assert((ssize_t) count >= 0);
if ((endpt = bdev_driver_get(dev)) == NONE)
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);
@ -78,12 +81,14 @@ static int bdev_rdwt_setup(int req, dev_t dev, u64_t pos, char *buf, int count,
return EINVAL;
}
memset(m, 0, sizeof(*m));
m->m_type = req;
m->DEVICE = minor(dev);
m->POSITION = ex64lo(pos);
m->HIGHPOS = ex64hi(pos);
m->COUNT = count;
m->IO_GRANT = (void *) grant;
m->BDEV_MINOR = minor(dev);
m->BDEV_POS_LO = ex64lo(pos);
m->BDEV_POS_HI = ex64hi(pos);
m->BDEV_COUNT = count;
m->BDEV_GRANT = grant;
m->BDEV_FLAGS = flags;
return OK;
}
@ -92,15 +97,12 @@ static void bdev_rdwt_cleanup(message *m)
{
/* Clean up a single-buffer read/write request.
*/
cp_grant_id_t grant;
grant = (cp_grant_id_t) m->IO_GRANT;
cpf_revoke(grant);
cpf_revoke(m->BDEV_GRANT);
}
static int bdev_rdwt(int req, dev_t dev, u64_t pos, char *buf, int count,
int flags)
static ssize_t bdev_rdwt(int req, dev_t dev, u64_t pos, char *buf,
size_t count, int flags)
{
/* 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,
int count, int UNUSED(flags), message *m, iovec_s_t *gvec,
cp_grant_id_t *grants, vir_bytes *size)
int count, int flags, message *m, iovec_s_t *gvec)
{
/* Set up a vectored read/write request.
*/
ssize_t size;
endpoint_t endpt;
cp_grant_id_t grant;
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)
return EDEADSRCDST;
access = (req == DEV_GATHER_S) ? CPF_WRITE : CPF_READ;
*size = 0;
access = (req == BDEV_GATHER) ? CPF_WRITE : CPF_READ;
size = 0;
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);
if (!GRANT_VALID(grants[i])) {
if (!GRANT_VALID(grant)) {
printf("bdev: unable to allocate grant!\n");
for (i--; i >= 0; i--)
cpf_revoke(grants[i]);
cpf_revoke(gvec[i].iov_grant);
return EINVAL;
}
/* We keep a separate grants array to prevent local leaks if the driver
* 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_grant = grant;
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,
CPF_READ | CPF_WRITE);
CPF_READ);
if (!GRANT_VALID(grant)) {
printf("bdev: unable to allocate grant!\n");
for (i = count - 1; i >= 0; i--)
cpf_revoke(grants[i]);
cpf_revoke(gvec[i].iov_grant);
return EINVAL;
}
memset(m, 0, sizeof(*m));
m->m_type = req;
m->DEVICE = minor(dev);
m->POSITION = ex64lo(pos);
m->HIGHPOS = ex64hi(pos);
m->COUNT = count;
m->IO_GRANT = (void *) grant;
m->BDEV_MINOR = minor(dev);
m->BDEV_POS_LO = ex64lo(pos);
m->BDEV_POS_HI = ex64hi(pos);
m->BDEV_COUNT = count;
m->BDEV_GRANT = grant;
m->BDEV_FLAGS = flags;
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.
*/
cp_grant_id_t grant;
int i;
grant = (cp_grant_id_t) m->IO_GRANT;
grant = m->BDEV_GRANT;
cpf_revoke(grant);
for (i = m->COUNT - 1; i >= 0; i--)
cpf_revoke(grants[i]);
for (i = m->BDEV_COUNT - 1; i >= 0; i--)
cpf_revoke(gvec[i].iov_grant);
}
static int bdev_vrdwt_adjust(dev_t dev, iovec_s_t *gvec, int count,
vir_bytes *size)
static ssize_t bdev_vrdwt(int req, dev_t dev, u64_t pos, iovec_t *vec,
int count, int flags)
{
/* Adjust the number of bytes transferred, by subtracting from it the number of
* 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.
/* Perform a read or write call using a vector of buffers.
*/
iovec_s_t gvec[NR_IOREQS];
cp_grant_id_t grants[NR_IOREQS];
message m;
int r;
if ((r = bdev_vrdwt_setup(req, dev, pos, vec, count, flags, &m, gvec,
grants, size)) != OK) {
*size = 0;
if ((r = bdev_vrdwt_setup(req, dev, pos, vec, count, flags, &m, gvec)) != OK)
return r;
}
r = bdev_sendrec(dev, &m);
bdev_vrdwt_cleanup(&m, grants);
/* Also return the number of bytes transferred. */
if (!bdev_vrdwt_adjust(dev, gvec, count, size)) {
*size = 0;
r = EIO;
}
bdev_vrdwt_cleanup(&m, gvec);
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.
*/
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.
*/
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,
vir_bytes *size)
ssize_t bdev_gather(dev_t dev, u64_t pos, iovec_t *vec, int count, int flags)
{
/* 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,
vir_bytes *size)
ssize_t bdev_scatter(dev_t dev, u64_t pos, iovec_t *vec, int count, int flags)
{
/* 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)
@ -311,10 +277,11 @@ static int bdev_ioctl_setup(dev_t dev, int request, void *buf, message *m)
return EINVAL;
}
m->m_type = DEV_IOCTL_S;
m->DEVICE = minor(dev);
m->REQUEST = request;
m->IO_GRANT = (void *) grant;
memset(m, 0, sizeof(*m));
m->m_type = BDEV_IOCTL;
m->BDEV_MINOR = minor(dev);
m->BDEV_REQUEST = request;
m->BDEV_GRANT = grant;
return OK;
}
@ -323,11 +290,8 @@ static void bdev_ioctl_cleanup(message *m)
{
/* Clean up an I/O control request.
*/
cp_grant_id_t grant;
grant = (cp_grant_id_t) m->IO_GRANT;
cpf_revoke(grant);
cpf_revoke(m->BDEV_GRANT);
}
int bdev_ioctl(dev_t dev, int request, void *buf)

View file

@ -12,7 +12,8 @@ static void bdev_cancel(dev_t dev)
* 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. */
bdev_driver_clear(dev);
@ -27,18 +28,13 @@ void bdev_update(dev_t dev, endpoint_t endpt)
old_endpt = bdev_driver_get(dev);
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)
{
/* Send a request to the given device, and wait for the reply.
*/
static long id = 0;
endpoint_t endpt;
message m;
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. */
m = *m_orig;
m.USER_ENDPT = (endpoint_t) -1; /* synchronous request; no ID */
m.BDEV_ID = ++id;
r = sendrec(endpt, &m);
@ -65,25 +61,25 @@ int bdev_sendrec(dev_t dev, const message *m_orig)
return r;
}
if (m.m_type != TASK_REPLY) {
if (m.m_type != BDEV_REPLY) {
printf("bdev: driver (%d) sent weird response (%d)\n",
endpt, m.m_type);
return EIO;
}
/* 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);
return EDEADSRCDST;
}
if (m.REP_ENDPT != (endpoint_t) -1) {
printf("bdev: driver (%d) sent invalid response (%d)\n",
endpt, m.REP_ENDPT);
if (m.BDEV_ID != id) {
printf("bdev: driver (%d) sent invalid response (%ld)\n",
endpt, m.BDEV_ID);
return EIO;
}
/* We got a reply to our request. */
return m.REP_STATUS;
/* Return the result of our request. */
return m.BDEV_STATUS;
}

View file

@ -1,7 +1,7 @@
# Makefile for libdriver
# Makefile for libblockdriver
.include <bsd.own.mk>
LIB= driver
LIB= blockdriver
SRCS= driver.c drvlib.c driver_st.c driver_mt.c mq.c event.c

382
lib/libblockdriver/driver.c Normal file
View 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;
}

View 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 */

View file

@ -1,17 +1,17 @@
/* This file contains the multithreaded device independent driver interface.
/* This file contains the multithreaded driver interface.
*
* Changes:
* Aug 27, 2011 created (A. Welzel)
*
* The entry points into this file are:
* driver_mt_task: the main message loop of the driver
* driver_mt_terminate: break out of the main message loop
* driver_mt_sleep: put the current thread to sleep
* driver_mt_wakeup: wake up a sleeping thread
* driver_mt_stop: put up the current thread for termination
* blockdriver_mt_task: the main message loop of the driver
* blockdriver_mt_terminate: break out of the main message loop
* blockdriver_mt_sleep: put the current thread to sleep
* blockdriver_mt_wakeup: wake up a sleeping thread
* 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 <assert.h>
@ -35,9 +35,8 @@ typedef struct {
event_t sleep_event;
} worker_t;
PRIVATE struct driver *driver_cb;
PRIVATE int driver_mt_type;
PRIVATE int driver_mt_running = FALSE;
PRIVATE struct blockdriver *bdtab;
PRIVATE int running = FALSE;
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);
if (!driver_mq_enqueue(wp->id, m_src, ipc_status))
panic("driver_mt: enqueue failed (message queue full)");
if (!mq_enqueue(wp->id, m_src, ipc_status))
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.
*/
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))
driver_event_wait(&wp->queue_event);
event_wait(&wp->queue_event);
}
/*===========================================================================*
@ -102,14 +101,14 @@ PRIVATE void *worker_thread(void *param)
worker_t *wp;
message m;
int ipc_status, r;
wp = (worker_t *) param;
assert(wp != NULL);
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. */
if (!try_dequeue(wp, &m, &ipc_status)) {
/* 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. */
dequeue(wp, &m, &ipc_status);
if (!driver_mt_running)
if (!running)
break;
}
@ -127,14 +126,14 @@ PRIVATE void *worker_thread(void *param)
wp->state = STATE_RUNNING;
/* 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. */
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;
@ -156,13 +155,13 @@ PRIVATE void master_create_worker(worker_t *wp, thread_id_t id)
wp->state = STATE_RUNNING;
/* Initialize synchronization primitives. */
driver_event_init(&wp->queue_event);
driver_event_init(&wp->sleep_event);
event_init(&wp->queue_event);
event_init(&wp->sleep_event);
r = mthread_create(&wp->mthread, NULL /*attr*/, worker_thread, (void *) wp);
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->state == STATE_EXITED);
assert(!driver_mq_dequeue(wp->id, &m, &ipc_status));
assert(!mq_dequeue(wp->id, &m, &ipc_status));
/* Join the thread. */
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. */
driver_event_destroy(&wp->sleep_event);
driver_event_destroy(&wp->queue_event);
event_destroy(&wp->sleep_event);
event_destroy(&wp->queue_event);
wp->state = STATE_DEAD;
}
@ -218,26 +217,24 @@ PRIVATE void master_handle_request(message *m_ptr, int ipc_status)
worker_t *wp;
int r;
/* If this is not a request that has a minor device associated with it, we
* can not tell which thread should process it either. In that case, the
* master thread has to handle it instead.
/* If this is not a block driver request, we cannot get the minor device
* associated with it, and thus we can not tell which thread should process
* it either. In that case, the master thread has to handle it instead.
*/
if (!IS_DEV_MINOR_RQ(m_ptr->m_type)) {
if (driver_cb->dr_other)
r = (*driver_cb->dr_other)(driver_cb, m_ptr);
else
r = EINVAL;
if (!IS_BDEV_RQ(m_ptr->m_type)) {
/* Process as 'other' message. */
r = blockdriver_handle_request(bdtab, m_ptr);
driver_reply(driver_mt_type, m_ptr, ipc_status, r);
blockdriver_reply(m_ptr, ipc_status, r);
return;
}
/* 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) {
driver_reply(driver_mt_type, m_ptr, ipc_status, r);
blockdriver_reply(m_ptr, ipc_status, r);
return;
}
@ -259,19 +256,18 @@ PRIVATE void master_handle_request(message *m_ptr, int ipc_status)
/*===========================================================================*
* 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.
*/
int i;
assert(dp != NULL);
assert(dp->dr_thread != NULL);
assert(bdp != NULL);
assert(bdp->bdr_thread != NULL);
mthread_init();
driver_mt_type = type;
driver_cb = dp;
bdtab = bdp;
for (i = 0; i < DRIVER_MT_MAX_WORKERS; i++)
worker[i].state = STATE_DEAD;
@ -280,13 +276,13 @@ PRIVATE void master_init(struct driver *dp, int type)
* reference to the worker structure.
*/
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.
*/
@ -295,13 +291,13 @@ PRIVATE void driver_mt_receive(message *m_ptr, int *ipc_status)
r = sef_receive_status(ANY, m_ptr, ipc_status);
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.
*/
@ -309,20 +305,20 @@ PUBLIC void driver_mt_task(struct driver *driver_p, int driver_type)
message mess;
/* Initialize first if necessary. */
if (!driver_mt_running) {
master_init(driver_p, driver_type);
if (!running) {
master_init(driver_tab);
driver_mt_running = TRUE;
running = TRUE;
}
/* The main message loop. */
while (driver_mt_running) {
while (running) {
/* Receive a message. */
driver_mt_receive(&mess, &ipc_status);
blockdriver_mt_receive(&mess, &ipc_status);
/* Dispatch the message. */
if (is_ipc_notify(ipc_status))
driver_handle_notify(driver_cb, &mess);
blockdriver_handle_notify(bdtab, &mess);
else
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.
*/
@ -358,15 +354,15 @@ PUBLIC void driver_mt_sleep(void)
wp = (worker_t *) mthread_getspecific(worker_key);
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.
*/
@ -378,13 +374,13 @@ PUBLIC void driver_mt_wakeup(thread_id_t id)
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
* call has finished, and there are no more messages in the thread's message
@ -392,7 +388,7 @@ PUBLIC void driver_mt_stop(void)
* the effect of this call.
*/
worker_t *wp;
wp = (worker_t *) mthread_getspecific(worker_key);
assert(wp != NULL);

View 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);
}

View file

@ -4,36 +4,36 @@
* partition: partition a disk to the partition table(s) on it.
*/
#include <minix/driver.h>
#include <minix/blockdriver.h>
#include <minix/drvlib.h>
#include <unistd.h>
/* Extended partition? */
#define ext_part(s) ((s) == 0x05 || (s) == 0x0F)
FORWARD _PROTOTYPE( void parse_part_table, (struct driver *dp, int device,
int style, int atapi, u8_t *tmp_buf) );
FORWARD _PROTOTYPE( void extpartition, (struct driver *dp, int extdev,
unsigned long extbase, u8_t *tmp_buf) );
FORWARD _PROTOTYPE( int get_part_table, (struct driver *dp, int device,
FORWARD _PROTOTYPE( void parse_part_table, (struct blockdriver *bdp,
int device, int style, int atapi, u8_t *tmp_buf) );
FORWARD _PROTOTYPE( void extpartition, (struct blockdriver *bdp, int extdev,
unsigned long extbase, u8_t *tmp_buf) );
FORWARD _PROTOTYPE( int get_part_table, (struct blockdriver *bdp, int device,
unsigned long offset, struct part_entry *table, u8_t *tmp_buf) );
FORWARD _PROTOTYPE( void sort, (struct part_entry *table) );
/*============================================================================*
* partition *
*============================================================================*/
PUBLIC void partition(dp, device, style, atapi)
struct driver *dp; /* device dependent entry points */
int device; /* device to partition */
int style; /* partitioning style: floppy, primary, sub. */
int atapi; /* atapi device */
PUBLIC void partition(bdp, device, style, atapi)
struct blockdriver *bdp; /* device dependent entry points */
int device; /* device to partition */
int style; /* partitioning style: floppy, primary, sub. */
int atapi; /* atapi device */
{
/* This routine is called on first open to initialize the partition tables
* of a device.
*/
u8_t *tmp_buf;
if ((*dp->dr_prepare)(device) == NULL)
if ((*bdp->bdr_part)(device) == NULL)
return;
/* 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)))
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);
}
@ -51,12 +51,12 @@ int atapi; /* atapi device */
/*============================================================================*
* parse_part_table *
*============================================================================*/
PRIVATE void parse_part_table(dp, device, style, atapi, tmp_buf)
struct driver *dp; /* device dependent entry points */
int device; /* device to partition */
int style; /* partitioning style: floppy, primary, sub. */
int atapi; /* atapi device */
u8_t *tmp_buf; /* temporary buffer */
PRIVATE void parse_part_table(bdp, device, style, atapi, tmp_buf)
struct blockdriver *bdp; /* device dependent entry points */
int device; /* device to partition */
int style; /* partitioning style: floppy, primary, sub. */
int atapi; /* atapi device */
u8_t *tmp_buf; /* temporary buffer */
{
/* This routine reads and parses a partition table. It may be called
* recursively. It makes sure that each partition falls safely within the
@ -71,13 +71,13 @@ u8_t *tmp_buf; /* temporary buffer */
unsigned long base, limit, part_limit;
/* 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;
base = div64u(dv->dv_base, SECTOR_SIZE);
limit = base + div64u(dv->dv_size, SECTOR_SIZE);
/* 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;
}
@ -97,7 +97,7 @@ u8_t *tmp_buf; /* temporary buffer */
}
/* 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. */
for (par = 0; par < NR_PARTITIONS; par++, dv++) {
@ -115,12 +115,12 @@ u8_t *tmp_buf; /* temporary buffer */
if (style == P_PRIMARY) {
/* Each Minix primary partition can be subpartitioned. */
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);
/* An extended partition has logical partitions. */
if (ext_part(pe->sysind))
extpartition(dp, device + par, pe->lowsec, tmp_buf);
extpartition(bdp, device + par, pe->lowsec, tmp_buf);
}
}
}
@ -128,11 +128,11 @@ u8_t *tmp_buf; /* temporary buffer */
/*============================================================================*
* extpartition *
*============================================================================*/
PRIVATE void extpartition(dp, extdev, extbase, tmp_buf)
struct driver *dp; /* device dependent entry points */
int extdev; /* extended partition to scan */
unsigned long extbase; /* sector offset of the base extended partition */
u8_t *tmp_buf; /* temporary buffer */
PRIVATE void extpartition(bdp, extdev, extbase, tmp_buf)
struct blockdriver *bdp; /* device dependent entry points */
int extdev; /* extended partition to scan */
unsigned long extbase; /* sector offset of the base ext. partition */
u8_t *tmp_buf; /* temporary buffer */
{
/* Extended partitions cannot be ignored alas, because people like to move
* files to and from DOS partitions. Avoid reading this code, it's no fun.
@ -148,7 +148,7 @@ u8_t *tmp_buf; /* temporary buffer */
offset = 0;
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);
/* The table should contain one logical partition and optionally
@ -161,7 +161,7 @@ u8_t *tmp_buf; /* temporary buffer */
nextoffset = pe->lowsec;
} else
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,
SECTOR_SIZE);
@ -177,8 +177,8 @@ u8_t *tmp_buf; /* temporary buffer */
/*============================================================================*
* get_part_table *
*============================================================================*/
PRIVATE int get_part_table(dp, device, offset, table, tmp_buf)
struct driver *dp;
PRIVATE int get_part_table(bdp, device, offset, table, tmp_buf)
struct blockdriver *bdp;
int device;
unsigned long offset; /* sector offset to the table */
struct part_entry *table; /* four entries */
@ -189,14 +189,14 @@ u8_t *tmp_buf; /* temporary buffer */
*/
iovec_t iovec1;
u64_t position;
int r;
position = mul64u(offset, SECTOR_SIZE);
iovec1.iov_addr = (vir_bytes) tmp_buf;
iovec1.iov_size = CD_SECTOR_SIZE;
if ((*dp->dr_prepare)(device) != NULL) {
(void) (*dp->dr_transfer)(SELF, DEV_GATHER_S, position, &iovec1, 1);
}
if (iovec1.iov_size != 0) {
r = (*bdp->bdr_transfer)(device, FALSE /*do_write*/, position, SELF,
&iovec1, 1, BDEV_NOFLAGS);
if (r != CD_SECTOR_SIZE) {
return 0;
}
if (tmp_buf[510] != 0x55 || tmp_buf[511] != 0xAA) {

View file

@ -7,65 +7,65 @@
#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.
*/
int r;
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)
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.
*/
int r;
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)
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.
*/
int r;
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)
panic("libdriver: error waiting for condvar (%d)", r);
panic("libblockdriver: error waiting for condvar (%d)", r);
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.
*/
int r;
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)
panic("libdriver: error signaling condvar (%d)", r);
panic("libblockdriver: error signaling condvar (%d)", r);
if ((r = mthread_mutex_unlock(&event->mutex)) != 0)
panic("libdriver: error unlocking mutex (%d)", r);
panic("libblockdriver: error unlocking mutex (%d)", r);
}

View 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 */

View file

@ -3,10 +3,10 @@
*
* Changes:
* 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 <assert.h>
@ -26,11 +26,11 @@ PRIVATE STAILQ_HEAD(queue, mq_cell) queue[DRIVER_MT_MAX_WORKERS];
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.
*/
int i;
@ -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)
{
/* 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,
int *ipc_status)
PUBLIC int mq_dequeue(thread_id_t thread_id, message *mess, int *ipc_status)
{
/* Return and remove a message, including its IPC status, from the message
* queue of a thread. Return TRUE iff a message was available.

12
lib/libblockdriver/mq.h Normal file
View 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 */

View 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>

View file

@ -1,6 +1,4 @@
/* This file contains the common part of the device driver interface.
* In addition, callers get to choose between the singlethreaded API
* (in driver_st.c) and the multithreaded API (in driver_mt.c).
/* This file contains the device independent character driver interface.
*
* The drivers support the following operations (using message format m2):
*
@ -25,8 +23,13 @@
* | 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:
* 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)
* Sep 15, 2004 added SYN_ALARM type for timeouts (Jorrit N. Herder)
* Jul 23, 2004 removed kernel dependencies (Jorrit N. Herder)
@ -34,12 +37,10 @@
*/
#include <minix/drivers.h>
#include <sys/ioc_disk.h>
#include <minix/driver.h>
#include <minix/chardriver.h>
#include <minix/ds.h>
#include "driver.h"
#include "mq.h"
PRIVATE int running;
/* Management data for opened 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. */
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. */
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,
int reply)
PRIVATE void send_reply(int type, message *m_ptr, int ipc_status, int reply)
{
/* Prepare and send a reply message. */
if (reply == EDONTREPLY)
return;
switch (driver_type) {
case DRIVER_STD:
standard_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();
if (type == CHARDRIVER_ASYNC)
async_reply(m_ptr, reply);
else
sync_reply(m_ptr, ipc_status, reply);
}
/*===========================================================================*
* 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. */
iovec_t iovec1;
@ -255,7 +238,7 @@ PRIVATE int do_rdwt(struct driver *dp, message *mp)
if (mp->COUNT < 0) return(EINVAL);
/* 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. */
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. */
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(r == OK ? (int) (mp->COUNT - iovec1.iov_size) : r);
@ -275,7 +259,7 @@ PRIVATE int do_rdwt(struct driver *dp, message *mp)
/*===========================================================================*
* 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.
* The "user addresses" are assumed to be safe, i.e. FS transferring to/from
@ -293,22 +277,23 @@ PRIVATE int do_vrdwt(struct driver *dp, message *mp)
if (nr_req > NR_IOREQS) nr_req = NR_IOREQS;
iovec_size = (phys_bytes) (nr_req * sizeof(iovec[0]));
if (OK != sys_safecopyfrom(mp->m_source, (vir_bytes) mp->IO_GRANT,
if (OK != sys_safecopyfrom(mp->m_source, (vir_bytes) mp->IO_GRANT,
0, (vir_bytes) iovec, iovec_size, D)) {
printf("bad I/O vector by: %d\n", mp->m_source);
return(EINVAL);
}
/* 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. */
opcode = mp->m_type;
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. */
if (OK != sys_safecopyto(mp->m_source, (vir_bytes) mp->IO_GRANT,
if (OK != sys_safecopyto(mp->m_source, (vir_bytes) mp->IO_GRANT,
0, (vir_bytes) iovec, iovec_size, D)) {
printf("couldn't return I/O vector: %d\n", mp->m_source);
return(EINVAL);
@ -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
* 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. */
switch (_ENDPOINT_P(m_ptr->m_source)) {
case HARDWARE:
if (dp->dr_hw_int)
dp->dr_hw_int(dp, m_ptr);
break;
case CLOCK:
if (dp->dr_alarm)
dp->dr_alarm(dp, m_ptr);
if (cdp->cdr_alarm)
cdp->cdr_alarm(m_ptr);
break;
default:
if (dp->dr_other)
(void) dp->dr_other(dp, m_ptr);
if (cdp->cdr_other)
(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
* 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
* 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. */
if (m_ptr->m_type != DEV_OPEN)
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. */
switch (m_ptr->m_type) {
case DEV_OPEN: r = (*dp->dr_open)(dp, m_ptr); break;
case DEV_CLOSE: r = (*dp->dr_close)(dp, m_ptr); break;
case DEV_IOCTL_S: r = (*dp->dr_ioctl)(dp, m_ptr); break;
case CANCEL: r = (*dp->dr_cancel)(dp, m_ptr); break;
case DEV_SELECT: r = (*dp->dr_select)(dp, m_ptr); break;
case DEV_OPEN: r = (*cdp->cdr_open)(m_ptr); break;
case DEV_CLOSE: r = (*cdp->cdr_close)(m_ptr); break;
case DEV_IOCTL_S: r = (*cdp->cdr_ioctl)(m_ptr); break;
case CANCEL: r = (*cdp->cdr_cancel)(m_ptr); break;
case DEV_SELECT: r = (*cdp->cdr_select)(m_ptr); break;
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_SCATTER_S: r = do_vrdwt(dp, m_ptr); break;
case DEV_SCATTER_S: r = do_vrdwt(cdp, m_ptr); break;
default:
if (dp->dr_other)
r = dp->dr_other(dp, m_ptr);
if (cdp->cdr_other)
r = cdp->cdr_other(m_ptr);
else
r = EINVAL;
}
/* Let the driver perform any cleanup. */
(*dp->dr_cleanup)();
if (cdp->cdr_cleanup)
(*cdp->cdr_cleanup)();
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
* originally done by fetching the name from the task table for this process:
* "return(tasktab[proc_number(proc_ptr) + NR_TASKS].name);", but currently a
* real "noname" is returned. Perhaps, some system information service can be
* queried for a name at a later time.
*/
static char name[] = "noname";
return name;
/* Handle the given received message. */
int r;
/* Process the notification or request. */
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.
*/
while (running) {
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 *
*===========================================================================*/
PUBLIC int do_nop(struct driver *UNUSED(dp), message *mp)
PUBLIC int do_nop(message *UNUSED(mp))
{
/* Nothing there, or nothing to do. */
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);
}
return(OK);
}
/*===========================================================================*
* nop_ioctl *
*===========================================================================*/
PUBLIC int nop_ioctl(struct driver *UNUSED(dp), message *UNUSED(mp))
PUBLIC int nop_ioctl(message *UNUSED(mp))
{
return(ENOTTY);
}
@ -434,20 +435,11 @@ PUBLIC int nop_ioctl(struct driver *UNUSED(dp), message *UNUSED(mp))
/*===========================================================================*
* nop_alarm *
*===========================================================================*/
PUBLIC void nop_alarm(struct driver *UNUSED(dp), message *UNUSED(mp))
PUBLIC void nop_alarm(message *UNUSED(mp))
{
/* Ignore the leftover alarm. */
}
/*===========================================================================*
* nop_prepare *
*===========================================================================*/
PUBLIC struct device *nop_prepare(int UNUSED(device))
{
/* Nothing to prepare for. */
return(NULL);
}
/*===========================================================================*
* nop_cleanup *
*===========================================================================*/
@ -459,7 +451,7 @@ PUBLIC void nop_cleanup(void)
/*===========================================================================*
* 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. */
return(OK);
@ -468,52 +460,8 @@ PUBLIC int nop_cancel(struct driver *UNUSED(dr), message *UNUSED(m))
/*===========================================================================*
* 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. */
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);
}

View file

@ -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 */

View file

@ -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);
}

View file

@ -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 */

View file

@ -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 */

View file

@ -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 \
uds.c dev_uds.c
DPADD+= ${LIBDRIVER} ${LIBSYS}
LDADD+= -ldriver -lsys
DPADD+= ${LIBSYS}
LDADD+= -lsys
MAN=

View file

@ -135,8 +135,6 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
SELF_E = getprocnr();
buf_pool();
driver_announce();
return(OK);
}

View file

@ -2,8 +2,11 @@
* Special character files also require I/O. The routines for these are here.
*
* The entry points in this file are:
* dev_open: FS opens a device
* dev_close: FS closes a device
* dev_open: open a character 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_status: FS processes callback request alert
* gen_opcl: generic call to a task to perform an open/close
@ -18,6 +21,7 @@
*/
#include "fs.h"
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/stat.h>
@ -52,9 +56,10 @@ PUBLIC int dev_open(
int flags /* mode bits and flags */
)
{
/* Open a character device. */
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
* 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 */
)
{
/* Reopen a device after a failing device driver */
/* Reopen a character device after a failing device driver. */
int major, r;
struct dmap *dp;
@ -103,7 +108,7 @@ PUBLIC int dev_close(
int filp_no
)
{
/* Close a device */
/* Close a character device. */
int r, major;
/* 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 *
*===========================================================================*/
@ -418,37 +507,47 @@ PUBLIC int dev_io(
* 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 */
endpoint_t proc_e, /* process to open/close for */
int flags /* mode bits and flags */
)
{
/* 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;
message dev_mess;
/* Determine task dmap. */
major_dev = major(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];
if (dp->dmap_driver == NONE) {
printf("VFS: gen_opcl: no driver for major %d\n", major_dev);
return(ENXIO);
}
assert(dp->dmap_driver != NONE);
dev_mess.m_type = op;
dev_mess.DEVICE = minor_dev;
dev_mess.USER_ENDPT = proc_e;
dev_mess.COUNT = flags;
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.DEVICE = minor_dev;
dev_mess.USER_ENDPT = proc_e;
dev_mess.COUNT = flags;
}
/* Call the task. */
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
if (r != OK) return(r);
return(dev_mess.REP_STATUS);
if (is_bdev)
return(dev_mess.BDEV_STATUS);
else
return(dev_mess.REP_STATUS);
}
/*===========================================================================*
@ -466,6 +565,8 @@ PUBLIC int tty_opcl(
int r;
register struct fproc *rfp;
assert(!IS_BDEV_RQ(op));
/* 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
* controlling tty.
@ -505,6 +606,8 @@ PUBLIC int ctty_opcl(
* /dev/tty, the magic device that translates to the controlling tty.
*/
assert(!IS_BDEV_RQ(op));
return(fp->fp_tty == 0 ? ENXIO : OK);
}
@ -552,7 +655,10 @@ PUBLIC int do_ioctl()
suspend_reopen = (f->filp_state != FS_NORMAL);
dev = (dev_t) vp->v_sdev;
r = dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0),
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),
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
* 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);
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 == EDEADSRCDST || r == EDEADEPT) {
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? */
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, "
"proc = %d (not %d) (2) ignored\n", mess_ptr->m_source,
mess_ptr->m_type, proc_e, mess_ptr->REP_ENDPT);
@ -617,6 +731,8 @@ message *mess_ptr; /* pointer to message for task */
int r;
assert(!IS_BDEV_RQ(mess_ptr->m_type));
fp->fp_sendrec = mess_ptr; /* Remember where result should be stored */
r = asynsend3(task_nr, mess_ptr, AMF_NOREPLY);
@ -711,15 +827,14 @@ PUBLIC int clone_opcl(
int r, minor_dev, major_dev;
message dev_mess;
assert(!IS_BDEV_RQ(op));
/* Determine task dmap. */
minor_dev = minor(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];
if (dp->dmap_driver == NONE) {
printf("VFS clone_opcl: no driver for major %d\n", major_dev);
return(ENXIO);
}
assert(dp->dmap_driver != NONE);
dev_mess.m_type = op;
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
* checks if any filesystems are mounted on it, and if so,
* dev_open()s them so the filesystem can be reused.
*/
int r, new_driver_e, needs_reopen, fd_nr, found;
/* A new block device driver has been mapped in. This may affect both mounted
* file systems and open block-special files.
*/
int r, new_driver_e, found;
struct filp *rfilp;
struct vmnt *vmp;
struct fproc *rfp;
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");
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.
*/
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
int minor_dev, major_dev;
major_dev = major(vmp->m_dev);
minor_dev = minor(vmp->m_dev);
if (major_dev != maj) continue;
if (major(vmp->m_dev) != maj) continue;
/* Send the new driver endpoint to the mounted file system. */
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;
/* 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",
maj, minor(vp->v_sdev), r);
@ -851,9 +958,22 @@ PUBLIC void dev_up(int maj)
printf("VFSdev_up: error sending new driver endpoint."
" 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.
*/
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
@ -884,7 +1004,6 @@ PUBLIC void dev_up(int maj)
if (needs_reopen)
restart_reopen(maj);
}
/*===========================================================================*

View file

@ -232,17 +232,21 @@ PUBLIC int dmap_driver_match(endpoint_t proc, int major)
/*===========================================================================*
* 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
* that might be blocking on it that this device is 'up'.
*/
int major;
for (major = 0; major < NR_DEVICES; major++)
if (dmap_driver_match(proc_e, major))
dev_up(major);
for (major = 0; major < NR_DEVICES; major++) {
if (dmap_driver_match(proc_e, major)) {
if (is_blk)
bdev_up(major);
else
cdev_up(major);
}
}
}
/*===========================================================================*

View file

@ -521,9 +521,15 @@ struct filp *f;
}
unlock_bsf();
}
/* Do any special processing on device close. */
(void) dev_close(dev, f-filp); /* Ignore any errors, even
* SUSPEND. */
/* Do any special processing on device close.
* 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;
}
}

View file

@ -538,10 +538,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
}
}
/* Subscribe to driver events for VFS drivers. */
if ((s = ds_subscribe("drv\\.vfs\\..*", DSF_INITIAL | DSF_OVERWRITE) != OK)){
panic("VFS: can't subscribe to driver events (%d)", s);
}
/* Subscribe to block and character driver events. */
s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE);
if (s != OK) panic("VFS: can't subscribe to driver events (%d)", s);
#if DO_SANITYCHECKS
FIXME("VFS: DO_SANITYCHECKS is on");

View file

@ -600,28 +600,35 @@ struct mem_map *seg_ptr;
/*===========================================================================*
* ds_event *
*===========================================================================*/
PUBLIC void ds_event()
PUBLIC void ds_event(void)
{
char key[DS_MAX_KEYLEN];
char *drv_prefix = "drv.vfs.";
char *blkdrv_prefix = "drv.blk.";
char *chrdrv_prefix = "drv.chr.";
u32_t value;
int type, r;
int type, r, is_blk;
endpoint_t owner_endpoint;
/* Get the event and the owner from DS. */
if ((r = ds_check(key, &type, &owner_endpoint)) != OK) {
if(r != ENOENT) printf("VFS: ds_event: ds_check failed: %d\n", r);
return;
}
if ((r = ds_retrieve_u32(key, &value)) != OK) {
printf("VFS: ds_event: ds_retrieve_u32 failed\n");
return;
while ((r = ds_check(key, &type, &owner_endpoint)) == OK) {
/* Only check for block and character driver up events. */
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) {
printf("VFS: ds_event: ds_retrieve_u32 failed\n");
return;
}
if (value != DS_DRIVER_UP) continue;
/* Perform up. */
dmap_endpt_up(owner_endpoint, is_blk);
}
/* Only check for VFS driver up events. */
if (strncmp(key, drv_prefix, sizeof(drv_prefix)) || value != DS_DRIVER_UP)
return;
/* Perform up. */
dmap_endpt_up(owner_endpoint);
if (r != ENOENT) printf("VFS: ds_event: ds_check failed: %d\n", r);
}

View file

@ -169,12 +169,21 @@ PRIVATE int common_open(char path[PATH_MAX], int oflags, mode_t omode)
/* Invoke the driver for special processing. */
dev = (dev_t) vp->v_sdev;
r = dev_open(dev, who_e, bits | (oflags & ~O_ACCMODE));
r = bdev_open(dev, bits);
if (r != OK) {
unlock_bsf();
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,
* then that FS is responsible for this device. Else
* 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;
}
/* Get the driver endpoint of the block spec device */
major_dev = major(vp->v_sdev);
if (major_dev < 0 || major_dev >= NR_DEVICES)
r = ENXIO;
else
dp = &dmap[major_dev];
if (r != OK || dp->dmap_driver == NONE) {
printf("VFS: driver not found for device %d\n",
vp->v_sdev);
r = ENXIO;
/* Send the driver endpoint to the file system that
* will handle the block I/O requests (even when its
* endpoint is known already), but only when it is the
* root file system. Other file systems will already
* have it anyway.
*/
if (vp->v_bfs_e != ROOT_FS_E) {
unlock_bsf();
break;
}
/* Send the driver endpoint (even when known already)*/
if (vp->v_bfs_e != ROOT_FS_E) {
/* 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) {
if (req_newdriver(vp->v_bfs_e, vp->v_sdev,
dp->dmap_driver) != OK) {
printf("VFS: error sending driver endpoint\n");
bdev_close(dev);
r = ENXIO;
}
unlock_bsf();

View file

@ -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_reopen, (dev_t dev, int filp_no, int flags) );
_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,
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));
@ -43,7 +45,8 @@ _PROTOTYPE( int ctty_io, (int task_nr, message *mess_ptr) );
_PROTOTYPE( int do_ioctl, (void) );
_PROTOTYPE( void pm_setsid, (int proc_e) );
_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,
cp_grant_id_t g) );
_PROTOTYPE( void reopen_reply, (void) );
@ -53,7 +56,7 @@ _PROTOTYPE( void open_reply, (void) );
_PROTOTYPE( int do_mapdriver, (void) );
_PROTOTYPE( void init_dmap, (void) );
_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( struct dmap *get_dmap, (endpoint_t proc_e) );
_PROTOTYPE( int do_mapdriver, (void) );

View file

@ -307,7 +307,7 @@ PRIVATE void rw_block(
printf("Ext2(%d) I/O error on device %d/%d, block %u\n",
SELF_E, major(dev), minor(dev), bp->b_blocknr);
op_failed = 1;
} else if( (unsigned) r != fs_block_size) {
} else if (r != (ssize_t) fs_block_size) {
r = END_OF_FILE;
op_failed = 1;
}
@ -387,7 +387,6 @@ PUBLIC void rw_scattered(
register int i;
register iovec_t *iop;
static iovec_t *iovec = NULL;
vir_bytes size;
u64_t pos;
int j, r;
@ -423,21 +422,22 @@ PUBLIC void rw_scattered(
}
pos = mul64u(bufq[0]->b_blocknr, fs_block_size);
if (rw_flag == READING)
r = bdev_gather(dev, pos, iovec, j, BDEV_NOFLAGS, &size);
r = bdev_gather(dev, pos, iovec, j, BDEV_NOFLAGS);
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
* encountered, but we only care if it's the first block that failed.
/* Harvest the results. The driver may have returned an error, or it
* 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];
if (size < iop->iov_size) {
/* Transfer failed. An error? Do we care? */
if (r != OK && i == 0) {
printf(
"fs: I/O error on device %d/%d, block %u\n",
major(dev), minor(dev), bp->b_blocknr);
if (r < (ssize_t) fs_block_size) {
/* Transfer failed. */
if (i == 0) {
bp->b_dev = NO_DEV; /* invalidate block */
vm_forgetblocks();
}
@ -449,7 +449,7 @@ PUBLIC void rw_scattered(
} else {
bp->b_dirt = CLEAN;
}
size -= iop->iov_size;
r -= fs_block_size;
}
bufq += i;
bufqsize -= i;

View file

@ -180,7 +180,7 @@ register struct super_block *sp; /* pointer to a superblock */
r = bdev_read(dev, cvu64(gdt_position), (char*) ondisk_group_descs,
gd_size, BDEV_NOFLAGS);
if (r != gd_size) {
if (r != (ssize_t) gd_size) {
printf("Can not read group descriptors\n");
return(EINVAL);
}
@ -251,7 +251,7 @@ struct super_block *sp; /* pointer to a superblock */
r = bdev_write(sp->s_dev, cvu64(gdt_position),
(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");
}
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)
{
u32_t count = 0;
int i;
unsigned int i;
for (i = 0; i < sp->s_groups_count; i++) {
struct group_desc *desc = get_group_desc(i);
@ -441,7 +441,7 @@ PRIVATE void copy_group_descriptors(
unsigned int ngroups
)
{
int i;
unsigned int i;
for (i = 0; i < ngroups; i++)
gd_copy(&dest_array[i], &source_array[i]);
}

View file

@ -12,8 +12,8 @@ SRCS= buf.c clock.c inet.c inet_config.c \
.PATH: ${.CURDIR}/generic
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBMINIXUTIL}
LDADD+= -ldriver -lsys -lminixutil
DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBMINIXUTIL}
LDADD+= -lchardriver -lsys -lminixutil
MAN=

View file

@ -42,7 +42,7 @@ from DL_ETH:
#include <sys/svrctl.h>
#include <minix/ds.h>
#include <minix/endpoint.h>
#include <minix/driver.h>
#include <minix/chardriver.h>
#include "mq.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
* any other driver.
* any other character driver.
*/
driver_announce();
chardriver_announce();
return(OK);
}

View file

@ -92,7 +92,7 @@ register struct buf *bp; /* buffer pointer */
{
int r;
u64_t pos;
int block_size;
vir_bytes block_size;
block_size = v_pri.logical_block_size_l; /* The block size is indicated by
* the superblock */
@ -100,10 +100,9 @@ register struct buf *bp; /* buffer pointer */
pos = mul64u(bp->b_blocknr, block_size); /* get absolute position */
r = bdev_read(fs_dev, pos, bp->b_data, block_size, BDEV_NOFLAGS);
if (r != block_size) {
if (r >= 0) r = END_OF_FILE;
if (r != END_OF_FILE)
printf("ISOFS(%d) I/O error on device %d/%d, block %u\n",
if (r != (ssize_t) block_size) {
if (r == OK) r = END_OF_FILE;
else printf("ISOFS(%d) I/O error on device %d/%d, block %u\n",
SELF_E, (fs_dev>>MAJOR)&BYTE, (fs_dev>>MINOR)&BYTE,
bp->b_blocknr);

View file

@ -11,8 +11,8 @@ SRCS= lwip.c \
.PATH: ${.CURDIR}/generic
DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBMINIXUTIL} ${LIBLWIP}
LDADD+= -ldriver -lsys -lminixutil -ltimers -llwip
DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBMINIXUTIL} ${LIBTIMERS} ${LIBLWIP}
LDADD+= -lchardriver -lsys -lminixutil -ltimers -llwip
MAN=

View file

@ -8,6 +8,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <minix/chardriver.h>
#include <minix/syslib.h>
#include <minix/sysutil.h>
#include <minix/timers.h>
@ -29,29 +30,6 @@ static int arp_ticks, tcp_fticks, tcp_sticks;
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)
{
}
@ -155,10 +133,10 @@ static int sef_cb_init_fresh(__unused int type, __unused sef_init_info_t *info)
DSF_INITIAL | DSF_OVERWRITE)) != OK)
panic(("inet: can't subscribe to driver events"));
/* Announce we are up. INET announces its presence to VFS just like
* any other driver.
/* Announce we are up. LWIP announces its presence to VFS just like
* any other character driver.
*/
driver_announce();
chardriver_announce();
return(OK);
}

Some files were not shown because too many files have changed in this diff Show more