/*
 * $Header: /smsa/bsd:include/dev/st_data.h:bsd  1.10  $
 * $Source: /smsa/bsd:include/dev/st_data.h: $
 *
 * st_data.h
 *
 * Data structure definitions for the ST506 driver.
 *
 * Copyright (c) 1988 Acorn Computers Ltd., Cambridge, England
 */

#ifndef __dev_st_data_h
#define __dev_st_data_h

/*
 * Breakup of minor device number:
 *    7           4   3           0
 *  +---+---+---+---+---+---+---+---+
 *  | P |c2 |c1 |c0 | d |p2 |p1 |p0 |
 *  +---+---+---+---+---+---+---+---+
 *
 * The P bit when set selects the physical controller
 * addressed by (c2..c0) where controller numbers are
 * as follows:
 *
 *     0:   internal controller (A500/R140)
 *   1-3:   invalid do not use
 *     4:   winchester xcb controller in xcb slot 0
 *     5:   winchester xcb controller in xcb slot 1
 *     6:   winchester xcb controller in xcb slot 2
 *     7:   winchester xcb controller in xcb slot 3
 *
 * When the P bit is clear, the controller addressed according
 * to c2..c0 is determined by the machine hardware configuration
 * at boot-time.  Controllers are checked for in physical controller
 * number order, and assigned to logical controller numbers 0..3
 * as they are found.  (Hence e.g. logical controller 3 would only
 * be present on a machine with internal controller + 3 winchester
 * expansion cards in it(!!!)).
 *
 * The drive number is specified by bit d
 * This selects drive 1 or drive 2 on the controller (i.e. d+1).
 *
 * Bits p2..p0 select a partition on the drive.
 */

#define MAXDRIVE		2		/* per controller */
#define	PHYS_CONTROLLER(mindev)	((mindev) & (1 << 7))
#define	CONTROLLER(mindev)	(((mindev) >> 4) & 7)
#define DRIVENO(mindev)		(((mindev) >> 3) & 1)
#define PARTNO(mindev) 		((mindev) & 7)
#define MAXPART			8		/* per drive */
#define MAXHDC			5		/* in system */

typedef struct  {
    u_char	drive,
		tracks_per_cyl,			/* i.e. heads */
		secs_per_track;			/* HDC limit is 255 */
    int		secs_per_cyl,
		blks_per_cyl,			
		park_cyl,
		precomp_cyl;
} GeomTab, *GeomTabRef;

typedef	struct	{
	struct	{
		int	startcyl;
		int	numcyls;
	} part[MAXPART];
}  ParTab, *ParTabRef;

typedef struct 
{
    int			status;		/* after initialisation */
    HDCRef		device;		/* ->controller registers */
    volatile unsigned char *control_byte; /* for xcb winchesters */
    caddr_t		mem_addr;	/* address for pseudo-DMA */
    int			byte_count;	/* count for pseudo-DMA */
    u_char		read_op;	/* flag for pseudo-DMA direction */
    u_char		internal;	/* 1:ihd, 0: xcb hd */
    u_char		logdev;		/* 0..(MAXHDC-1) */
#define LOGDEV_NONE	255		/* for phys device not present */
} PhysDevice, *PhysDeviceRef;

/*
 * The following is used to keep track of where a split transfer got to.
 */
typedef struct
{
	int		issetup;
	int		lastcom;
	int		curcyl;
	int		nextcyl;
	int		seccnt;
	int		csector;
	int		sector;
	int		head;
	caddr_t		mem;
	struct bbmap	bad_blocks;		
	struct bb_addr *bcyl_list;
	unsigned	replacement;
	unsigned	bb_repl_cyl;		/*  Now a variable  */
	int		prev_sects;		/* for soft ECC continuation */
	int		prev_nextcyl;		/* for correct reporting of seek errors */
} DrivePos, *DrivePosRef;

typedef struct 
{
	GeomTab		dr_geom;
	ParTab		dr_ptab;
	DrivePos	dr_pos;
} Drive, *DriveRef;

typedef struct  {
	PhysDeviceRef	controller;
	struct int_hndlr int_handler;	/* interrupt handling control */
	struct devqueue wdtab;
	struct buf	rbuf;		/* for raw I/O */
	int		wdretries;	/* for current operation */
#define WDRETRY_MAX	10
	unsigned char	open_wanted;	/* Want to open drive */
	unsigned char	opening;       	/* bit for currently opening drive */
	char		dk_id;		/* unique id, index into disk info tab (for iostat) */
	GeomTab		current_geom;	/* wot controller is set to now  */
	DriveRef	drive[MAXDRIVE]; /* 1 record/drive: alloc'ed on drive open */
} LogDevice, *LogDeviceRef;


/*
 * Maximum number of ST506 controllers it is possible to have on
 * a machine.
 */
#define MAX_ST506	5

#endif/*__dev_st_data_h*/

/* EOF st_data.h */
