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 \
#define AUDIO_FW_H
#include <minix/drivers.h>
-#include <minix/driver.h>
+#include <minix/chardriver.h>
#include <sys/ioc_sound.h>
#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
* 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
* 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.
*/
/*===========================================================================*
- * 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 */
#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 */
#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 */
#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 */
(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 ")"); \
} \
-#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 */
#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 {
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 */
+++ /dev/null
-#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 */
#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
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 */
mess_8 m_m8;
mess_6 m_m6;
mess_9 m_m9;
+ mess_10 m_m10;
} m_u;
} message;
#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). *
*==========================================================================*/
SRCS+=${ACPICA_SRCS}
-DPADD+= ${LIBDRIVER} ${LIBSYS}
-LDADD+= -ldriver -lsys
+DPADD+= ${LIBSYS}
+LDADD+= -lsys
CPPFLAGS += -I${.CURDIR}/include
CFLAGS += -DACPI_LIBRARY
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=
* 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>
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; \
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
};
/*===========================================================================*
* 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)
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
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. */
r = ata_transfer(ps, cmd, start_lba, count, write, prdt,
nr_prds);
- if (r < 0) 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;
- }
+ if (r != OK) return r;
- return OK;
+ return size;
}
/*===========================================================================*
* 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.
ps->flags |= FLAG_SUSPENDED;
while (ps->flags & FLAG_BUSY)
- driver_mt_sleep();
+ blockdriver_mt_sleep();
ps->flags &= ~FLAG_SUSPENDED;
}
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),
((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. */
/*===========================================================================*
* 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.
*/
*/
if ((ps->flags & (FLAG_SUSPENDED | FLAG_BUSY)) ==
FLAG_SUSPENDED)
- driver_mt_wakeup(ps->device);
+ blockdriver_mt_wakeup(ps->device);
}
}
/* 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;
}
sef_startup();
}
-/*===========================================================================*
- * ahci_name *
- *===========================================================================*/
-PRIVATE char *ahci_name(void)
-{
- /* Return a printable name for the controller. We avoid the use of the
- * currently selected port, as it may not be accurate.
- */
- static char name[] = "AHCI0";
-
- name[4] = '0' + ahci_instance;
-
- return name;
-}
-
/*===========================================================================*
* ahci_portname *
*===========================================================================*/
}
/*===========================================================================*
- * ahci_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];
if (port == NO_PORT)
return NULL;
- current_port = &port_state[port];
- current_dev = ¤t_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];
if (port == NO_PORT)
return NULL;
- current_port = &port_state[port];
- current_dev = ¤t_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.
}
/* 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;
}
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;
}
/*===========================================================================*
* 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) {
/* 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",
}
/* 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++)
if (port == hba_state.nr_ports) {
ahci_stop();
- driver_mt_terminate();
+ blockdriver_mt_terminate();
}
}
/*===========================================================================*
* 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(m->DEVICE);
+ ps = ahci_get_port(minor);
- switch (m->REQUEST) {
+ switch (request) {
case DIOCEJECT:
if (ps->state != STATE_GOOD_DEV || (ps->flags & FLAG_BARRIER))
return EIO;
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))
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;
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;
{
/* 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;
}
* 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;
}
/*===========================================================================*
env_setargs(argc, argv);
sef_local_startup();
- driver_mt_task(&ahci_dtab, DRIVER_STD);
+ blockdriver_mt_task(&ahci_dtab);
return 0;
}
PROG= amddev
SRCS= amddev.c
-DPADD+= ${LIBDRIVER} ${LIBSYS}
-LDADD+= -ldriver -lsys
+DPADD+= ${LIBSYS}
+LDADD+= -lsys
MAN=
/*===========================================================================*
* 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;
printf("after write: DEVF_CR: 0x%x\n", read_reg(DEVF_CR, 0));
- /* Announce we are up! */
- driver_announce();
-
return(OK);
}
}
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);
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);
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;
}
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;
}
{
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;
}
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=
{ 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) );
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) );
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)
#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. */
sef_local_startup();
/* Call the generic receive loop. */
- driver_task(&w_dtab, DRIVER_STD);
+ blockdriver_task(&w_dtab);
return(OK);
}
/*===========================================================================*
* 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);
init_params();
/* Announce we are up! */
- driver_announce();
+ blockdriver_announce();
return(OK);
}
/*===========================================================================*
* init_params *
*===========================================================================*/
-PRIVATE void init_params()
+PRIVATE void init_params(void)
{
/* This routine is called at startup to initialize the drive parameters. */
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);
}
}
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;
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;
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
{
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;
}
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
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;
}
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);
}
}
/*===========================================================================*
* 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;
}
#if ENABLE_ATAPI
- if ((wn->state & ATAPI) && (m_ptr->COUNT & W_BIT))
+ if ((wn->state & ATAPI) && (access & W_BIT))
return(EACCES);
#endif
#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);
/*===========================================================================*
* 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 */
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))
/*===========================================================================*
* 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.
/*===========================================================================*
* w_name *
*===========================================================================*/
-PRIVATE char *w_name()
+PRIVATE char *w_name(void)
{
/* Return a name for the current device. */
static char name[] = "AT0-D0";
*===========================================================================*/
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
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)
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. */
*===========================================================================*/
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;
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);
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; \
/*===========================================================================*
* 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
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) {
/* 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.
/* 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;
* 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. */
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,
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--;
}
w_command = CMD_IDLE;
- return(OK);
+ return(total);
}
/*===========================================================================*
/*===========================================================================*
* 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;
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)
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);
/*===========================================================================*
* w_need_reset *
*===========================================================================*/
-PRIVATE void w_need_reset()
+PRIVATE void w_need_reset(void)
{
/* The controller needs to be reset. */
struct wini *wn;
/*===========================================================================*
* 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
/*===========================================================================*
* 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.
/*===========================================================================*
* w_intr_wait *
*===========================================================================*/
-PRIVATE void w_intr_wait()
+PRIVATE void w_intr_wait(void)
{
/* Wait for a task completion interrupt. */
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 {
/*===========================================================================*
* 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;
/*===========================================================================*
* 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);
/*===========================================================================*
* 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
/*===========================================================================*
* atapi_close *
*===========================================================================*/
-PRIVATE void atapi_close()
+PRIVATE void atapi_close(void)
{
/* Should unlock the device. For now do nothing. (XXX) */
}
/*===========================================================================*
* 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;
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;
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);
chunk = iov->iov_size;
position= add64ul(position, chunk);
nbytes -= chunk;
+ total += chunk;
if ((iov->iov_size -= chunk) == 0) {
iov++;
nr_req--;
addr_offset += chunk;
piobytes += chunk;
fresh = 0;
+ total += chunk;
if ((iov->iov_size -= chunk) == 0) {
iov++;
nr_req--;
#endif
w_command = CMD_IDLE;
- return(OK);
+ return(total);
}
/*===========================================================================*
#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;
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;
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);
}
/*===========================================================================*
* 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.
#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");
}
#include <minix/drivers.h>
-#include <minix/driver.h>
+#include <minix/blockdriver.h>
#include <minix/drvlib.h>
#define VERBOSE 0 /* display identify messages during boot */
#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])
.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"
MAN=
-LIBS += -ldriver
-
BINDIR?= /usr/sbin
.include <bsd.prog.mk>
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);
}
-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.
}
-PRIVATE int set_sign(u32_t val, int sub_dev) {
+PRIVATE int set_sign(u32_t UNUSED(val), int UNUSED(sub_dev)) {
return OK;
}
* 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);
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);
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);
}
-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.
}
-PRIVATE int set_sign(u32_t val, int sub_dev) {
+PRIVATE int set_sign(u32_t UNUSED(val), int UNUSED(sub_dev)) {
return OK;
}
* 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);
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);
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);
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);
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 */
/*=========================================================================*
* 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) {
-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;
-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;
-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;
}
-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;
PROG= bios_wini
SRCS= bios_wini.c
-DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
-LDADD+= -ldriver -lsys -ltimers
+DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS} ${LIBTIMERS}
+LDADD+= -lblockdriver -lsys -ltimers
MAN=
*/
#include <minix/drivers.h>
-#include <minix/driver.h>
+#include <minix/blockdriver.h>
#include <minix/drvlib.h>
#include <minix/sysutil.h>
#include <minix/safecopies.h>
#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)
#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. */
/*===========================================================================*
* 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);
}
/*===========================================================================*
* 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);
/*===========================================================================*
* 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;
remap_first = v;
/* Announce we are up! */
- driver_announce();
+ blockdriver_announce();
return(OK);
}
/*===========================================================================*
* 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. */
}
/*===========================================================================*
- * 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;
} *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);
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);
/* 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++) {
/* 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;
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;
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++) {
/* 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;
}
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. */
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. */
/*============================================================================*
* 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);
}
/*===========================================================================*
* w_init *
*===========================================================================*/
-PRIVATE void w_init()
+PRIVATE void w_init(void)
{
/* This routine is called at startup to initialize the drive parameters. */
}
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);
}
/*============================================================================*
* 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;
-
- if (m->m_type != DEV_IOCTL_S )
- return EINVAL;
+ int count;
- 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 (w_prepare(minor) == NULL) return ENXIO;
- if(r != OK)
- return r;
- return OK;
- }
+ if (request == DIOCOPENCT) {
+ count = w_wn->open_ct;
+ return sys_safecopyto(endpt, grant, 0, (vir_bytes)&count,
+ sizeof(count), D);
+ }
- return EINVAL;
+ return EINVAL;
}
-
-
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=
/* 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 */
static struct driverinfo driver[2];
/* State variables. */
-static endpoint_t self_ep;
static asynmsg_t amsgtable[2];
static int size_known = 0;
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) {
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;
}
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);
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) {
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;
}
/* Initialize the driver layer. */
int r;
- self_ep = getprocnr();
-
memset(driver, 0, sizeof(driver));
/* Endpoints unknown. */
#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");
}
/*===========================================================================*
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];
/*===========================================================================*
* 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.
#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)
* 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.
/* 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);
* 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.
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;
/*===========================================================================*
* 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.
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);
* 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);
}
/*===========================================================================*
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
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;
}
}
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;
}
/* 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;
}
#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>
{ "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 */
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");
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;
}
/*===========================================================================*
*===========================================================================*/
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;
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;
}
/*===========================================================================*
{
struct partition sizepart;
- switch(m->REQUEST) {
+ switch(m->BDEV_REQUEST) {
case DIOCSETP:
case DIOCTIMEOUT:
case DIOCOPENCT:
break;
default:
- printf("Filter: unknown ioctl request: %d!\n", m->REQUEST);
+ printf("Filter: unknown ioctl request: %d!\n",
+ m->BDEV_REQUEST);
return EINVAL;
}
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);
}
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",
#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);
}
/*===========================================================================*
* 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;
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);
}
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++;
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];
}
PROG= floppy
SRCS= floppy.c liveupdate.c
-DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
-LDADD+= -ldriver -lsys -ltimers
+DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS} ${LIBTIMERS}
+LDADD+= -lblockdriver -lsys -ltimers
MAN=
#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 */
*/
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) );
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;
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 *
sef_local_startup();
/* Call the generic receive loop. */
- driver_task(&f_dtab, DRIVER_STD);
+ blockdriver_task(&f_dtab);
return(OK);
}
/*===========================================================================*
* 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;
panic("Couldn't enable IRQs: %d", s);
/* Announce we are up! */
- driver_announce();
+ blockdriver_announce();
return(OK);
}
/*===========================================================================*
* 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;
}
/*===========================================================================*
- * 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);
}
/*===========================================================================*
/*===========================================================================*
* 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);
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);
/* 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);
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,
/* 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,
/* 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;
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
*/
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);
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;
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;
/*===========================================================================*
* 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. */
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;
/* 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);
}
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);
}
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;
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;
/*===========================================================================*
* 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
/*===========================================================================*
* 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. */
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;
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 *
*===========================================================================*/
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;
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);
/*===========================================================================*
* 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;
}
-
-
#include <minix/drivers.h>
-#include <minix/driver.h>
+#include <minix/blockdriver.h>
#include <minix/drvlib.h>
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. */
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);
PROG= hello
SRCS= hello.c
-DPADD+= ${LIBDRIVER} ${LIBSYS}
-LDADD+= -ldriver -lsys
+DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
+LDADD+= -lchardriver -lsys
MAN=
#include <minix/drivers.h>
-#include <minix/driver.h>
+#include <minix/chardriver.h>
#include <stdio.h>
#include <stdlib.h>
#include <minix/ds.h>
/*
* Function prototypes for the hello driver.
*/
-FORWARD _PROTOTYPE( char * hello_name, (void) );
-FORWARD _PROTOTYPE( int hello_open, (struct driver *d, message *m) );
-FORWARD _PROTOTYPE( int hello_close, (struct driver *d, message *m) );
-FORWARD _PROTOTYPE( struct device * hello_prepare, (int device) );
-FORWARD _PROTOTYPE( int hello_transfer, (int procnr, int opcode,
+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) );
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
};
/** 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;
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;
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);
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;
/* 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.
/*
* Run the main loop.
*/
- driver_task(&hello_tab, DRIVER_STD);
+ chardriver_task(&hello_tab, CHARDRIVER_SYNC);
return OK;
}
PROG= log
SRCS= log.c diag.c liveupdate.c
-DPADD+= ${LIBDRIVER} ${LIBSYS}
-LDADD+= -ldriver -lsys
+DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
+LDADD+= -lchardriver -lsys
MAN=
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) );
sef_local_startup();
/* Call the generic receive loop. */
- driver_task(&log_dtab, DRIVER_ASYN);
+ chardriver_task(&log_dtab, CHARDRIVER_ASYNC);
return(OK);
}
/*===========================================================================*
* 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;
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]);
}
* 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;
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;
}
* 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;
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;
/*===========================================================================*
* 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;
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;
}
/*============================================================================*
* 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;
/*============================================================================*
* log_other *
*============================================================================*/
-PRIVATE int log_other(dp, m_ptr)
-struct driver *dp;
-message *m_ptr;
+PRIVATE int log_other(message *m_ptr)
{
int r;
/*============================================================================*
* 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;
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
/* 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>
PROG= memory
SRCS= memory.c imgrd.c
-DPADD+= ${LIBDRIVER} ${LIBSYS}
-LDADD+= -ldriver -lsys
+DPADD+= ${LIBBLOCKDRIVER} ${LIBCHARDRIVER} ${LIBSYS}
+LDADD+= -lblockdriver -lchardriver -lsys
MAN=
*/
#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>
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) );
-
-/* Entry points to this driver. */
-PRIVATE struct driver m_dtab = {
- m_name, /* current device's name */
+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) );
+
+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) \
*===========================================================================*/
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);
}
/*===========================================================================*
* 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);
}
/*===========================================================================*
- * 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]);
/*===========================================================================*
* 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. */
/* 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) {
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);
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;
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);
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)
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;
/* 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);
/*===========================================================================*
* 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. */
}
}
- if(m_device < 0 || m_device >= NR_DEVS) {
- panic("wrong m_device: %d", m_device);
- }
-
openct[m_device]++;
return(OK);
/*===========================================================================*
* 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
}
/*===========================================================================*
- * 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;
+
+ if (request != MIOCRAMSIZE)
+ return EINVAL;
+
+ /* 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;
+ }
- 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;
-
- /* 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);
-
- /* 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;
+ /* 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);
+ }
- dv->dv_size = cvul64(ramdev_size);
+ m_vaddrs[minor] = (vir_bytes) mem;
- break;
- }
+ dv->dv_size = cvul64(ramdev_size);
- default:
- return(do_diocntl(&m_dtab, m_ptr));
- }
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;
-}
-
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=
PROG= printer
SRCS= printer.c liveupdate.c
-DPADD+= ${LIBDRIVER} ${LIBSYS}
-LDADD+= -ldriver -lsys
+DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
+LDADD+= -lchardriver -lsys
MAN=
#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
/*===========================================================================*
* 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 */
/*===========================================================================*
* 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;
}
.PATH: ${.CURDIR}/aes
-DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBMINIXUTIL}
-LDADD+= -ldriver -lsys -lminixutil
+DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBMINIXUTIL}
+LDADD+= -lchardriver -lsys -lminixutil
MAN=
*/
#include <minix/drivers.h>
-#include <minix/driver.h>
+#include <minix/chardriver.h>
#include <minix/type.h>
#include "assert.h"
#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. */
sef_local_startup();
/* Call the generic receive loop. */
- driver_task(&r_dtab, DRIVER_ASYN);
+ chardriver_task(&r_dtab, CHARDRIVER_ASYNC);
return(OK);
}
/*===========================================================================*
* 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))) {
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]);
/*===========================================================================*
* 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;
/* 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) {
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);
return(OK);
}
-/*============================================================================*
- * r_do_open *
- *============================================================================*/
-PRIVATE int r_do_open(dp, m_ptr)
-struct driver *dp;
-message *m_ptr;
-{
-/* Check device number on open.
- */
- if (r_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
-
- return(OK);
-}
-
/*===========================================================================*
- * r_ioctl *
+ * r_do_open *
*===========================================================================*/
-PRIVATE int r_ioctl(dp, m_ptr)
-struct driver *dp; /* pointer to driver structure */
-message *m_ptr; /* pointer to control message */
+PRIVATE int r_do_open(message *m_ptr)
{
+/* Check device number on open.
+ */
if (r_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
- switch (m_ptr->REQUEST) {
-
- default:
- return(do_diocntl(&r_dtab, m_ptr));
- }
return(OK);
}
} \
}
+/*===========================================================================*
+ * r_updatebin *
+ *===========================================================================*/
PRIVATE void r_updatebin(int source, struct k_randomness_bin *rb)
{
int r_next, r_size, r_high;
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;
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;
-}
-
PROG= readclock.drv
SRCS= readclock.c
-DPADD+= ${LIBDRIVER} ${LIBSYS}
-LDADD+= -ldriver -lsys
+DPADD+= ${LIBSYS}
+LDADD+= -lsys
MAN=
PROG= ti1225
SRCS= ti1225.c
-DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBTIMERS}
-LDADD+= -ldriver -lsys -ltimers
+DPADD+= ${LIBSYS}
+LDADD+= -lsys
MAN=
/*===========================================================================*
* 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;
hw_init(&ports[i]);
}
- /* Announce we are up! */
- driver_announce();
-
return(OK);
}
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=
/*===========================================================================*
* 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;
/*===========================================================================*
* 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. */
/*===========================================================================*
* 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;
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;
/*===========================================================================*
* kbd_watchdog *
*===========================================================================*/
-PRIVATE void kbd_watchdog(tmrp)
-timer_t *tmrp;
+PRIVATE void kbd_watchdog(timer_t *UNUSED(tmrp))
{
kbd_watchdog_set= 0;
/*===========================================================================*
* 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;
/*===========================================================================*
* 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;
/*===========================================================================*
* 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;
/*===========================================================================*
* 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. */
/*===========================================================================*
* 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;
/*===========================================================================*
* 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;
/*===========================================================================*
* 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;
/*===========================================================================*
* 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;
/*===========================================================================*
* 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;
/*===========================================================================*
* 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;
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
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;
irq_hook_set = TRUE; /* now signal handler knows it must unregister policy*/
/* Announce we are up! */
- driver_announce();
+ chardriver_announce();
return OK;
}
*/
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);
}
* 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)
* 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.
*/
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);
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;
}
{
/* 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.
*/
}
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;
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]);
-}
-
-static int bdev_vrdwt_adjust(dev_t dev, iovec_s_t *gvec, int count,
- vir_bytes *size)
-{
-/* 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;
+ for (i = m->BDEV_COUNT - 1; i >= 0; i--)
+ cpf_revoke(gvec[i].iov_grant);
}
-static int bdev_vrdwt(int req, dev_t dev, u64_t pos, iovec_t *vec, int count,
- int flags, vir_bytes *size)
+static ssize_t bdev_vrdwt(int req, dev_t dev, u64_t pos, iovec_t *vec,
+ int count, int flags)
{
-/* 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)
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;
}
{
/* 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)
* 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);
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;
/* 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);
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;
}
-# 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
--- /dev/null
+/* 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;
+}
--- /dev/null
+#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 */
-/* 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>
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;
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);
}
/*===========================================================================*
* 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);
}
/*===========================================================================*
*/
while (!try_dequeue(wp, m_dst, ipc_status))
- driver_event_wait(&wp->queue_event);
+ event_wait(&wp->queue_event);
}
/*===========================================================================*
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. */
/* Otherwise, block waiting for a new message. */
dequeue(wp, &m, &ipc_status);
- if (!driver_mt_running)
+ if (!running)
break;
}
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;
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);
}
/*===========================================================================*
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;
}
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;
}
/*===========================================================================*
* 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;
* 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.
*/
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.
*/
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);
}
/*===========================================================================*
- * 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.
*/
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.
*/
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
* the effect of this call.
*/
worker_t *wp;
-
+
wp = (worker_t *) mthread_getspecific(worker_key);
assert(wp != NULL);
--- /dev/null
+/* 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);
+}
* 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
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);
}
/*============================================================================*
* 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
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;
}
}
/* 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++) {
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);
}
}
}
/*============================================================================*
* 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.
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
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);
/*============================================================================*
* 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 */
*/
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) {
#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);
}
--- /dev/null
+#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 */
*
* 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>
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;
}
/*===========================================================================*
- * 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.
}
/*===========================================================================*
- * 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.
--- /dev/null
+#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 */
--- /dev/null
+# Makefile for libchardriver
+.include <bsd.own.mk>
+
+LIB= chardriver
+
+SRCS= chardriver.c
+
+.if ${USE_STATECTL} != "no"
+CPPFLAGS+= -DUSE_STATECTL
+.endif
+
+.include <bsd.lib.mk>
-/* 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):
*
* | 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)
*/
#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];
}
/*===========================================================================*
- * asyn_reply *
+ * chardriver_announce *
+ *===========================================================================*/
+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 asyn_reply(message *mess, int r)
+PRIVATE void async_reply(message *mess, int r)
{
/* Send a reply using the asynchronous character device protocol. */
message reply_mess;
}
/*===========================================================================*
- * 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;
}
/*===========================================================================*
- * 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;
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;
/* 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);
/*===========================================================================*
* 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
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);
}
/*===========================================================================*
- * 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.
/* 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
* 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;
/* 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);
+ }
}
/*===========================================================================*
- * do_nop *
+ * chardriver_task *
*===========================================================================*/
-PUBLIC int do_nop(struct driver *UNUSED(dp), message *mp)
+PUBLIC void chardriver_task(struct chardriver *cdp, int driver_type)
{
-/* 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);
+/* 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);
}
}
/*===========================================================================*
- * nop_ioctl *
+ * do_nop *
*===========================================================================*/
-PUBLIC int nop_ioctl(struct driver *UNUSED(dp), message *UNUSED(mp))
+PUBLIC int do_nop(message *UNUSED(mp))
{
- return(ENOTTY);
+ return(OK);
}
/*===========================================================================*
- * nop_alarm *
+ * nop_ioctl *
*===========================================================================*/
-PUBLIC void nop_alarm(struct driver *UNUSED(dp), message *UNUSED(mp))
+PUBLIC int nop_ioctl(message *UNUSED(mp))
{
-/* Ignore the leftover alarm. */
+ return(ENOTTY);
}
/*===========================================================================*
- * nop_prepare *
+ * nop_alarm *
*===========================================================================*/
-PUBLIC struct device *nop_prepare(int UNUSED(device))
+PUBLIC void nop_alarm(message *UNUSED(mp))
{
-/* Nothing to prepare for. */
- return(NULL);
+/* Ignore the leftover alarm. */
}
/*===========================================================================*
/*===========================================================================*
* 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);
/*===========================================================================*
* 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);
-}
+++ /dev/null
-#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 */
+++ /dev/null
-/* 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);
-}
+++ /dev/null
-#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 */
+++ /dev/null
-#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 */
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=
SELF_E = getprocnr();
buf_pool();
- driver_announce();
-
return(OK);
}
* 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
*/
#include "fs.h"
+#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/stat.h>
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.)
*/
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;
int filp_no
)
{
-/* Close a device */
+/* Close a character device. */
int r, major;
/* See if driver is roughly valid. */
}
+/*===========================================================================*
+ * 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 *
*===========================================================================*/
* 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);
}
/*===========================================================================*
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.
* /dev/tty, the magic device that translates to the controlling tty.
*/
+ assert(!IS_BDEV_RQ(op));
+
return(fp->fp_tty == 0 ? ENXIO : OK);
}
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);
}
/* 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);
}
/* 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);
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);
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;
/*===========================================================================*
- * 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;
* 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))
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);
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++) {
if (needs_reopen)
restart_reopen(maj);
-
}
/*===========================================================================*
/*===========================================================================*
* 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);
+ }
+ }
}
/*===========================================================================*
}
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;
}
}
}
}
- /* 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");
/*===========================================================================*
* 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;
+ }
- /* Only check for VFS driver up events. */
- if (strncmp(key, drv_prefix, sizeof(drv_prefix)) || value != DS_DRIVER_UP)
- return;
+ 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);
+ }
- /* Perform up. */
- dmap_endpt_up(owner_endpoint);
+ if (r != ENOENT) printf("VFS: ds_event: ds_check failed: %d\n", r);
}
/* 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. */
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;
- unlock_bsf();
- break;
- }
-
- /* Send the driver endpoint (even when known already)*/
+ /* 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) {
- /* 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();
_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));
_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) );
_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) );
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;
}
register int i;
register iovec_t *iop;
static iovec_t *iovec = NULL;
- vir_bytes size;
u64_t pos;
int j, r;
}
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();
}
} else {
bp->b_dirt = CLEAN;
}
- size -= iop->iov_size;
+ r -= fs_block_size;
}
bufq += i;
bufqsize -= i;
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);
}
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;
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);
unsigned int ngroups
)
{
- int i;
+ unsigned int i;
for (i = 0; i < ngroups; i++)
gd_copy(&dest_array[i], &source_array[i]);
}
.PATH: ${.CURDIR}/generic
-DPADD+= ${LIBDRIVER} ${LIBSYS} ${LIBMINIXUTIL}
-LDADD+= -ldriver -lsys -lminixutil
+DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBMINIXUTIL}
+LDADD+= -lchardriver -lsys -lminixutil
MAN=
#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"
}
/* 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);
}
{
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 */
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);
.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=
#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>
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)
{
}
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);
}
printf("MFS(%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;
}
register int i;
register iovec_t *iop;
static iovec_t *iovec = NULL;
- vir_bytes size;
u64_t pos;
int j, r;
}
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. libbdev 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("MFS: 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(
- "MFS: I/O error on device %d/%d, block %u\n",
- major(dev), minor(dev), bp->b_blocknr);
- bp->b_dev = NO_DEV; /* invalidate block */
- vm_forgetblocks();
+ if (r < (ssize_t) fs_block_size) {
+ /* Transfer failed. */
+ if (i == 0) {
+ bp->b_dev = NO_DEV; /* Invalidate block */
+ vm_forgetblocks();
}
break;
}
} else {
bp->b_dirt = CLEAN;
}
- size -= iop->iov_size;
+ r -= fs_block_size;
}
bufq += i;
bufqsize -= i;
/*===========================================================================*
* 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 Minix file server. */
int i;
r = bdev_read(dev, cvu64(SUPER_BLOCK_BYTES), sbbuf, _MIN_BLOCK_SIZE,
BDEV_NOFLAGS);
- if (r != _MIN_BLOCK_SIZE)
+ if (r != _MIN_BLOCK_SIZE)
return(EINVAL);
memcpy(sp, sbbuf, sizeof(*sp));
buffer.c read.c misc.c utility.c stadir.c \
uds.c dev_uds.c
-DPADD+= ${LIBDRIVER} ${LIBSYS}
-LDADD+= -ldriver -lsys
+DPADD+= ${LIBSYS}
+LDADD+= -lsys
MAN=
SELF_E = getprocnr();
buf_pool();
- driver_announce();
-
return(OK);
}
* 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
*/
#include "fs.h"
+#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/stat.h>
int flags /* mode bits and flags */
)
{
+/* Open a character device. */
int major, r;
struct dmap *dp;
- /* 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.)
*/
int flags /* mode bits and flags */
)
{
+/* Reopen a character device after a failing device driver. */
int major, r;
struct dmap *dp;
int filp_no
)
{
+/* Close a character device. */
int r;
/* See if driver is roughly valid. */
}
+/*===========================================================================*
+ * bdev_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, safe, major_dev, minor_dev, vec_grants;
+
+ 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;
+ safe = safe_io_conversion(dp->dmap_driver, &gid, &op, NULL, 0, &proc_e, &buf,
+ &vec_grants, 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 (safe) safe_io_cleanup(gid, NULL, vec_grants);
+
+ if (dp->dmap_driver == NONE) {
+ printf("VFS: block driver gone!?\n");
+ return(EIO);
+ }
+
+ /* Return the result. */
+ return dev_mess.BDEV_STATUS;
+}
+
+
/*===========================================================================*
* suspended_ep *
*===========================================================================*/
* 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 */
int proc_e, /* process to open/close for */
int flags /* mode bits and flags */
)
{
/* Called from the dmap struct in table.c on opens & closes of special files.*/
- int r;
+ int r, is_bdev;
struct dmap *dp;
message dev_mess;
/* Determine task dmap. */
- dp = &dmap[(dev >> MAJOR) & BYTE];
+ dp = &dmap[major(dev)];
- dev_mess.m_type = op;
- dev_mess.DEVICE = (dev >> MINOR) & BYTE;
- 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;
+ }
if (dp->dmap_driver == NONE) {
printf("FS: gen_opcl: no driver for dev %x\n", dev);
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);
}
/*===========================================================================*
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.
* /dev/tty, the magic device that translates to the controlling tty.
*/
+ assert(!IS_BDEV_RQ(op));
+
return(fp->fp_tty == 0 ? ENXIO : OK);
}
suspend_reopen= (f->filp_state != FS_NORMAL);
dev = (dev_t) vp->v_sdev;
+ if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL)
+ return bdev_ioctl(dev, who_e, m_in.REQUEST, m_in.ADDRESS);
+
return dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0),
m_in.REQUEST, f->filp_flags, suspend_reopen);
}
* pairs. These lead to calls on the following routines via the dmap table.
*/
- int r, proc_e;
+ int r, status, proc_e, is_bdev;
if(task_nr == SYSTEM) {
printf("VFS: sending %d to SYSTEM\n", mess_ptr->m_type);
}
- proc_e = mess_ptr->USER_ENDPT;
+ is_bdev = IS_BDEV_RQ(mess_ptr->m_type);
+
+ if (!is_bdev) proc_e = mess_ptr->USER_ENDPT;
for (;;) {
r = sendrec(task_nr, 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("fs: dead driver %d\n", task_nr);
}
/* Did the process we did the sendrec() for get a result? */
- if (mess_ptr->REP_ENDPT != proc_e && VFS_PROC_NR != proc_e) {
+ if (!is_bdev &&
+ mess_ptr->REP_ENDPT != proc_e && VFS_PROC_NR != proc_e) {
printf("fs: strange device reply from %d, type = %d, "
"proc = %d (not %d) (2) ignored\n", mess_ptr->m_source,
if (mess_ptr->m_type == TASK_REPLY ||
IS_DEV_RS(mess_ptr->m_type) ||
+ IS_BDEV_RS(mess_ptr->m_type) ||
mess_ptr->m_type <= 0) {
break; /* reply */
int r;
+ assert(!IS_BDEV_RQ(mess_ptr->m_type));
+
r = asynsend(task_nr, mess_ptr);
if (r != OK) panic("asyn_io: asynsend failed: %d", r);
int r, minor;
message dev_mess;
+ assert(!IS_BDEV_RQ(op));
+
/* Determine task dmap. */
dp = &dmap[(dev >> MAJOR) & BYTE];
minor = (dev >> MINOR) & BYTE;
/*===========================================================================*
- * 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 *fp;
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.
- */
new_driver_e = dmap[maj].dmap_driver;
/* Tell each affected mounted file system about the new endpoint. This code
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, fp->filp_mode)) != OK)
+ if ((r = bdev_open(vp->v_sdev, fp->filp_mode & O_ACCMODE)) != OK)
printf("VFS: mounted dev %d/%d re-open failed: %d.\n",
maj, minor(vp->v_sdev), r);
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 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 *fp;
+ struct fproc *rfp;
+ struct vnode *vp;
+
+ /* Look for processes that are suspened in an OPEN call. Set SUSP_REOPEN
* to indicate that this process was suspended before the call to dev_up.
*/
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
if (needs_reopen)
restart_reopen(maj);
-
}
/*===========================================================================*
* dmap_endpt_up *
*===========================================================================*/
-PUBLIC void dmap_endpt_up(int proc_e)
+PUBLIC void dmap_endpt_up(int proc_e, int is_blk)
{
int i;
for (i=0; i<NR_DEVICES; i++) {
if(dmap[i].dmap_driver != NONE
&& dmap[i].dmap_driver == proc_e) {
- dev_up(i);
+
+ if (is_blk)
+ bdev_up(i);
+ else
+ cdev_up(i);
}
}
- return;
}
/*===========================================================================*
req_flush(vp->v_bfs_e, dev);
}
}
- /* Do any special processing on device close. */
- (void) dev_close(dev, fp-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, fp-filp);
fp->filp_mode = FILP_CLOSED;
}
system_hz = sys_hz();
- /* Subscribe to driver events for VFS drivers. */
- s = ds_subscribe("drv\\.vfs\\..*", DSF_INITIAL | DSF_OVERWRITE);
+ /* 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");
}
/*===========================================================================*
* ds_event *
*===========================================================================*/
-PUBLIC void ds_event()
+PUBLIC void ds_event(void)
{
char key[DS_MAX_KEYLEN];
- char *driver_prefix = "drv.vfs.";
+ char *blkdrv_prefix = "drv.blk.";
+ char *chrdrv_prefix = "drv.chr.";
u32_t value;
int type;
endpoint_t owner_endpoint;
- int r;
+ int r, is_blk;
/* Get the event and the owner from DS. */
r = ds_check(key, &type, &owner_endpoint);
printf("vfs: ds_event: ds_check failed: %d\n", r);
return;
}
+
+ /* 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 {
+ return; /* neither block nor character driver */
+ }
+
r = ds_retrieve_u32(key, &value);
if(r != OK) {
printf("vfs: ds_event: ds_retrieve_u32 failed\n");
return;
}
-
- /* Only check for VFS driver up events. */
- if(strncmp(key, driver_prefix, sizeof(driver_prefix))
- || value != DS_DRIVER_UP) {
- return;
- }
+ if (value != DS_DRIVER_UP) return;
/* Perform up. */
- dmap_endpt_up(owner_endpoint);
+ dmap_endpt_up(owner_endpoint, is_blk);
}
case I_BLOCK_SPECIAL:
/* 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) break;
/* Check whether the device is mounted or not. If so,
vp->v_bfs_e = vmp->m_fs_e;
/* Get the driver endpoint of the block spec device */
- dp = &dmap[(vp->v_sdev >> MAJOR) & BYTE];
- if (dp->dmap_driver == NONE) {
- printf("VFS: driver not found for device %d\n",
- vp->v_sdev);
- r = ENXIO;
- break;
- }
+ dp = &dmap[major(vp->v_sdev)];
- /* Send the driver endpoint (even when known already)*/
+ /* Send the driver endpoint to the file system (even
+ * when known already).
+ */
if ((r = 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;
}
break;
_PROTOTYPE( int dev_open, (dev_t dev, int proc, 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 flags) );
+_PROTOTYPE( int bdev_close, (dev_t dev) );
_PROTOTYPE( int dev_io, (int op, dev_t dev, int proc, void *buf,
u64_t pos, int bytes, int flags, int suspend_reopen) );
_PROTOTYPE( int gen_opcl, (int op, dev_t dev, int proc, int flags) );
_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 suspended_ep, (endpoint_t driver,
cp_grant_id_t g) );
_PROTOTYPE( void reopen_reply, (void) );
_PROTOTYPE( void build_dmap, (void) );
_PROTOTYPE( int do_mapdriver, (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 map_driver, (const char *label, int major, endpoint_t proc_nr,
# rumpfs_lfs rumpfs_msdosfs rumpfs_nfs rumpfs_ntfs rumpfs_syspuffs \
# rumpfs_tmpfs rumpfs_udf rumpfs_ufs
.for _lib in \
- c curses driver netdriver edit end m sys timers util bz2 l hgfs \
- audiodriver exec ddekit devman usb elf
+ c curses blockdriver chardriver netdriver edit end m sys timers util \
+ bz2 l hgfs audiodriver exec ddekit devman usb elf bdev
.ifndef LIB${_lib:tu}
LIB${_lib:tu}= ${DESTDIR}/usr/lib/lib${_lib}.a
.if ${COMPILER_TYPE} == "ack"
/* Block Device Driver Test driver, by D.C. van Moolenbroek */
#include <stdlib.h>
#include <sys/stat.h>
-#include <minix/driver.h>
+#include <minix/blockdriver.h>
#include <minix/drvlib.h>
#include <minix/dmap.h>
#include <minix/sysinfo.h>
RESULT_OK, /* exactly as expected */
RESULT_COMMFAIL, /* communication failed */
RESULT_BADTYPE, /* bad type in message */
- RESULT_BADENDPT, /* bad endpoint in message */
+ RESULT_BADID, /* bad request ID in message */
RESULT_BADSTATUS, /* bad/unexpected status in message */
RESULT_TRUNC, /* request truncated unexpectedly */
- RESULT_TOUCHED, /* result iovec changed unexpectedly */
RESULT_CORRUPT, /* buffer touched erroneously */
RESULT_MISSING, /* buffer left untouched erroneously */
RESULT_OVERFLOW, /* area around buffer touched */
PRIVATE char driver_label[LABEL_MAX]; /* driver DS label */
PRIVATE dev_t driver_minor; /* driver's partition minor to use */
PRIVATE endpoint_t driver_endpt; /* driver endpoint */
-PRIVATE endpoint_t my_endpt; /* this process's endpoint */
PRIVATE int may_write = FALSE; /* may we write to the device? */
PRIVATE int sector_size = 512; /* size of a single disk sector */
case RESULT_BADTYPE:
printf("- bad type %d in reply message\n", res->value);
break;
- case RESULT_BADENDPT:
- printf("- bad endpoint %u in reply message\n", res->value);
+ case RESULT_BADID:
+ printf("- mismatched ID %d in reply message\n", res->value);
break;
case RESULT_BADSTATUS:
printf("- bad or unexpected status %d in reply message\n",
printf("- result size not as expected (%u bytes left)\n",
res->value);
break;
- case RESULT_TOUCHED:
- printf("- resulting I/O vector changed unexpectedly\n");
- break;
case RESULT_CORRUPT:
printf("- buffer has been modified erroneously\n");
break;
*/
message m;
- m.m_type = DEV_OPEN;
- m.DEVICE = minor;
- m.USER_ENDPT = my_endpt;
- m.COUNT = (may_write) ? (R_BIT | W_BIT) : R_BIT;
+ memset(&m, 0, sizeof(m));
+ m.m_type = BDEV_OPEN;
+ m.BDEV_MINOR = minor;
+ m.BDEV_ACCESS = (may_write) ? (R_BIT | W_BIT) : R_BIT;
+ m.BDEV_ID = 0;
(void) sendrec(driver_endpt, &m);
}
if (r != OK)
return set_result(res, RESULT_COMMFAIL, r);
- if (m_ptr->m_type != TASK_REPLY)
+ if (m_ptr->m_type != BDEV_REPLY)
return set_result(res, RESULT_BADTYPE, m_ptr->m_type);
- if (m_ptr->REP_ENDPT != m_orig.USER_ENDPT)
- return set_result(res, RESULT_BADENDPT,
- m_ptr->REP_ENDPT);
+ if (m_ptr->BDEV_ID != m_orig.BDEV_ID)
+ return set_result(res, RESULT_BADID, m_ptr->BDEV_ID);
- if (m_ptr->REP_STATUS != ERESTART) break;
+ if (m_ptr->BDEV_STATUS != ERESTART) break;
/* The driver has died. Reopen all devices that we opened
* earlier, and resend the request. Up to three times.
exit(1);
}
- if ((exp < 0 && m_ptr->REP_STATUS == 0) ||
- (exp >= 0 && m_ptr->REP_STATUS != 0))
- return set_result(res, RESULT_BADSTATUS, m_ptr->REP_STATUS);
+ if ((exp < 0 && m_ptr->BDEV_STATUS >= 0) ||
+ (exp >= 0 && m_ptr->BDEV_STATUS < 0))
+ return set_result(res, RESULT_BADSTATUS, m_ptr->BDEV_STATUS);
return set_result(res, RESULT_OK, 0);
}
/* Perform a transfer with a safecopy iovec already supplied.
*/
cp_grant_id_t grant;
- iovec_s_t iov_orig[NR_IOREQS];
message m;
- ssize_t left;
- int i, r;
+ int r;
assert(nr_req <= NR_IOREQS);
assert(!write || may_write);
- memcpy(iov_orig, iovec, sizeof(*iovec) * nr_req);
-
if ((grant = cpf_grant_direct(driver_endpt, (vir_bytes) iovec,
- sizeof(*iovec) * nr_req, CPF_READ | CPF_WRITE)) ==
- GRANT_INVALID)
+ sizeof(*iovec) * nr_req, CPF_READ)) == GRANT_INVALID)
panic("unable to allocate grant");
memset(&m, 0, sizeof(m));
- m.m_type = write ? DEV_SCATTER_S : DEV_GATHER_S;
- m.DEVICE = minor;
- m.POSITION = ex64lo(pos);
- m.HIGHPOS = ex64hi(pos);
- m.COUNT = nr_req;
- m.USER_ENDPT = my_endpt;
- m.IO_GRANT = (void *) grant;
+ m.m_type = write ? BDEV_SCATTER : BDEV_GATHER;
+ m.BDEV_MINOR = minor;
+ m.BDEV_POS_LO = ex64lo(pos);
+ m.BDEV_POS_HI = ex64hi(pos);
+ m.BDEV_COUNT = nr_req;
+ m.BDEV_GRANT = grant;
+ m.BDEV_ID = rand();
r = sendrec_driver(&m, exp, res);
if (r != RESULT_OK)
return r;
- if (exp >= 0) {
- left = exp;
-
- for (i = 0; i < nr_req; i++) {
- if (iov_orig[i].iov_grant != iovec[i].iov_grant) {
- /* Don't panic because we can't free them. */
- for ( ; i < nr_req; i++)
- iovec[i].iov_grant =
- iov_orig[i].iov_grant;
-
- return set_result(res, RESULT_TOUCHED, 0);
- }
-
- if ((left == 0 &&
- iov_orig[i].iov_size != iovec[i].iov_size) ||
- ((vir_bytes) left >= iov_orig[i].iov_size &&
- iovec[i].iov_size != 0) ||
- ((vir_bytes) left < iov_orig[i].iov_size &&
- iov_orig[i].iov_size - iovec[i].iov_size >
- (vir_bytes) left)) {
-
- return set_result(res, RESULT_TRUNC, left);
- }
-
- left -= iov_orig[i].iov_size - iovec[i].iov_size;
- }
-
- /* do we need this? */
- if (left != 0) return set_result(res, RESULT_TRUNC, left);
- }
- else if (memcmp(iovec, iov_orig, sizeof(*iovec) * nr_req))
- return set_result(res, RESULT_TOUCHED, 0);
+ if (m.BDEV_STATUS != exp)
+ return set_result(res, RESULT_TRUNC, exp - m.BDEV_STATUS);
return r;
}
alloc_buf_and_grant(&buf_ptr, &grant2, buf_size, CPF_WRITE);
if ((grant = cpf_grant_direct(driver_endpt, (vir_bytes) &iov,
- sizeof(iov), CPF_READ | CPF_WRITE)) == GRANT_INVALID)
+ sizeof(iov), CPF_READ)) == GRANT_INVALID)
panic("unable to allocate grant");
/* Initialize the defaults for some of the tests.
* This is a legitimate request for the first block of the partition.
*/
memset(&mt, 0, sizeof(mt));
- mt.m_type = DEV_GATHER_S;
- mt.DEVICE = driver_minor;
- mt.POSITION = 0L;
- mt.HIGHPOS = 0L;
- mt.COUNT = 1;
- mt.USER_ENDPT = my_endpt;
- mt.IO_GRANT = (void *) grant;
+ mt.m_type = BDEV_GATHER;
+ mt.BDEV_MINOR = driver_minor;
+ mt.BDEV_POS_LO = 0L;
+ mt.BDEV_POS_HI = 0L;
+ mt.BDEV_COUNT = 1;
+ mt.BDEV_GRANT = grant;
+ mt.BDEV_ID = rand();
memset(&iovt, 0, sizeof(iovt));
iovt.iov_grant = grant2;
sendrec_driver(&m, OK, &res);
- if (res.type == RESULT_OK && iov.iov_size != 0) {
+ if (res.type == RESULT_OK && m.BDEV_STATUS != (ssize_t) iov.iov_size) {
res.type = RESULT_TRUNC;
- res.value = iov.iov_size;
+ res.value = m.BDEV_STATUS;
}
got_result(&res, "normal request");
m = mt;
iov = iovt;
- m.COUNT = 0;
+ m.BDEV_COUNT = 0;
sendrec_driver(&m, EINVAL, &res);
/* Test bad iovec grant. */
m = mt;
- m.IO_GRANT = (void *) GRANT_INVALID;
+ m.BDEV_GRANT = GRANT_INVALID;
sendrec_driver(&m, EINVAL, &res);
iov = iovt;
if ((grant3 = cpf_grant_direct(driver_endpt, (vir_bytes) &iov,
- sizeof(iov), CPF_READ | CPF_WRITE)) == GRANT_INVALID)
+ sizeof(iov), CPF_READ)) == GRANT_INVALID)
panic("unable to allocate grant");
cpf_revoke(grant3);
- m.IO_GRANT = (void *) grant3;
+ m.BDEV_GRANT = grant3;
sendrec_driver(&m, EINVAL, &res);
got_result(&res, "revoked iovec grant");
- /* Test read-only iovec grant. */
- m = mt;
- iov = iovt;
-
- if ((grant3 = cpf_grant_direct(driver_endpt, (vir_bytes) &iov,
- sizeof(iov), CPF_READ)) == GRANT_INVALID)
- panic("unable to allocate grant");
-
- m.IO_GRANT = (void *) grant3;
-
- sendrec_driver(&m, EINVAL, &res);
-
- got_result(&res, "read-only iovec grant");
-
- cpf_revoke(grant3);
-
/* Test normal request (final check). */
m = mt;
iov = iovt;
sendrec_driver(&m, OK, &res);
- if (res.type == RESULT_OK && iov.iov_size != 0) {
+ if (res.type == RESULT_OK && m.BDEV_STATUS != (ssize_t) iov.iov_size) {
res.type = RESULT_TRUNC;
- res.value = iov.iov_size;
+ res.value = m.BDEV_STATUS;
}
got_result(&res, "normal request");
message m;
result_t res;
- m.m_type = DEV_OPEN;
- m.DEVICE = minor;
- m.USER_ENDPT = my_endpt;
- m.COUNT = (may_write) ? (R_BIT | W_BIT) : R_BIT;
+ memset(&m, 0, sizeof(m));
+ m.m_type = BDEV_OPEN;
+ m.BDEV_MINOR = minor;
+ m.BDEV_ACCESS = may_write ? (R_BIT | W_BIT) : R_BIT;
+ m.BDEV_ID = rand();
sendrec_driver(&m, OK, &res);
result_t res;
int i;
- m.m_type = DEV_CLOSE;
- m.DEVICE = minor;
- m.USER_ENDPT = my_endpt;
- m.COUNT = 0;
+ memset(&m, 0, sizeof(m));
+ m.m_type = BDEV_CLOSE;
+ m.BDEV_MINOR = minor;
+ m.BDEV_ID = rand();
sendrec_driver(&m, OK, &res);
_MINIX_IOCTL_SIZE(req), perm)) == GRANT_INVALID)
panic("unable to allocate grant");
- m.m_type = DEV_IOCTL_S;
- m.DEVICE = minor;
- m.POSITION = 0L;
- m.HIGHPOS = 0L;
- m.REQUEST = req;
- m.USER_ENDPT = my_endpt;
- m.IO_GRANT = (void *) grant;
+ memset(&m, 0, sizeof(m));
+ m.m_type = BDEV_IOCTL;
+ m.BDEV_MINOR = minor;
+ m.BDEV_POS_LO = 0L;
+ m.BDEV_POS_HI = 0L;
+ m.BDEV_REQUEST = req;
+ m.BDEV_GRANT = grant;
+ m.BDEV_ID = rand();
r = sendrec_driver(&m, exp, res);
{
/* Initialize.
*/
- char name[32];
- int r, flags;
+ int r;
clock_t now;
- /* Get my own endpoint, to use as grant owner. This means that we
- * cannot test whether a driver correctly distinguishes between senders
- * and grant holders.
- */
- if ((r = sys_whoami(&my_endpt, name, sizeof(name), &flags)) != OK)
- panic("whoami failed: %d", r);
-
if (env_argc > 1)
optset_parse(optset_table, env_argv[1]);