struct is_controller {
    long garbage;
};

/*
 * Device switch.
 */
struct devsw {
	char			dv_type0;
	char			dv_type1;
	int			(*dv_strategy)();
	int			(*dv_open)();
	int			(*dv_close)();
	int			(*dv_ioctl)();
	short			dv_max;
	struct ctrl_info	*dv_ctrl_info;
};

struct dev_blk {
	short db_alive;
};

struct ctrl_blk {
	short cb_alive;
	union {
	    struct rf_controller r;
	    struct is_controller i;
	} cb_u;
};

struct ctrl_info {
	short	ct_max;
};

/*
 * Bytes / cyl = (bytes / sector) * (sectors / track) * (heads / cyl)
 */
struct srm_dkinfo {
	u_short	modelnum;	/* Model number */
	u_char	type;		/* Type of drive */
	u_char  numhead;	/* Number of heads */
	u_short	spt;		/* Sectors / track */
	u_short numcyl;		/* Number of cyls */
	u_short numalt;		/* Number of alternates */
	u_short	bps;		/* Bytes / sector */
	u_long bpc;		/* Bytes / cyl */
	u_short buff_numhead;	/* Number of heads in a buffer */
	u_short buff_numsector;	/* Number of sectors in a buffer */
	u_short buff_totcyl;	/* Total number of sectors in a buffer */
	u_short buff_tothead;	/* Total number of heads in a buffer */
	u_short buff_totsector;	/* Total number of sectors in a buffer */
	char	*name;		/* ASCII name */
};

/*
 * Limits on buffer used by bkup/rstr
 * This buffer size holds an even number of 5k, 10k, and 16k tape blocks:
 * 40 @ 16k, 64 @ 10k, 128 @ 5k
 *
 * (was 40000,180000,140000, but cant cross Meg bound:
 *     80 @ 16k, 128 @ 10k, 256 @ 5k)
 */
#define BKUPRSTR_START	0x60000
#define BKUPRSTR_SIZE	0xA0000		/* END - START */
#define BKUPRSTR_END	0x100000

/*
 * Default tape buffer size (should be in rfreg.h)
 */
#define T_BUFFSIZE	0x4000

struct devtxinfo {
	u_long	startaddr;	/* Start bus addr */
	u_long	limitaddr;	/* Limit bus address */
	u_short	cyl;		/* Start cyl */
	u_char  head;		/* Start head */
	u_char  dum;		/* Dummy */
	u_short sector;		/* Start sector */
	u_long	nbytes;		/* Size of buffer */

	u_short	limit_cyl;	/* End cyl */
	u_long	sectors;	/* Number of sectors */
	u_long	tbytes;		/* Total bytes to transfer */
};

struct devparms {
	char	dp_name[8];
	struct devsw	*dp_devsw;
	short	dp_ctrlno;
	short	dp_unitno;
	struct dev_blk *dp_dblk;
	struct ctrl_blk *dp_cblk;
	struct devtxinfo dp_txinfo;
};

/* maximum number of rimfire controllers */
#define RCMAX 2
/* maximum number of interphase controllers */
#define ICMAX 4

#define CMAX (RCMAX + ICMAX)

#define FDSTART 0x1000
#define PRIMARY (&Primary)
#define SECONDARY (&Secondary)
#define CTRLBLKSTART (FDSTART)
#define DEVBLKSTART (CTRLBLKSTART + CMAX * sizeof(struct ctrl_blk))

#define NDEVS (sizeof(devsw)/sizeof(devsw[0]))

extern struct ctrl_info r_info;
extern struct ctrl_info i_info;
extern struct devparms Primary, Secondary;

/*
 * Flags for I/O routines.
 */

#define WRITE 0
#define READ  1

#define IO_OPT_QUIET	0
#define IO_OPT_VERBOSE	1

#define IO_CMD_RESET		0x00
#define IO_CMD_STATUS		0x01
#define IO_CMD_GETINFO		0x02
#define IO_CMD_FORMAT		0x03
#define IO_CMD_SPINUP		0x04
#define IO_CMD_SPINDN		0x05
#define IO_CMD_NOOP		0x06
#define IO_CMD_WFM		0x07
#define IO_CMD_GETBRINFO	0x08
#define IO_CMD_OPENGATE		0x09
#define IO_CMD_REWIND		0x0A
#define IO_CMD_DISPLAY		0x0B
#define IO_CMD_DPB		0x0C
#define IO_CMD_TERM		0x0D
#define IO_CMD_LOCATE		0x0E
#define IO_CMD_RETENSION	0x0F
#define IO_CMD_DRSTAT		0x10

#define IOCTL_RESET	devparms, IO_CMD_RESET, IO_OPT_QUIET
#define IOCTL_V_RESET	devparms, IO_CMD_RESET, IO_OPT_VERBOSE
