xref: /original-bsd/sys/vax/vax/mscpvar.h (revision 05bc5180)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Chris Torek.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)mscpvar.h	7.3 (Berkeley) 06/28/90
11  */
12 
13 /*
14  * MSCP generic driver configuration
15  */
16 
17 /*
18  * Enabling MSCP_PARANOIA makes the response code perform various checks
19  * on the hardware.  (Right now it verifies only the buffer pointer in
20  * mscp_cmdref.)
21  *
22  * Enabling AVOID_EMULEX_BUG selects an alternative method of identifying
23  * transfers in progress, which gets around a rather peculiar bug in the
24  * SC41/MS.  Enabling MSCP_PARANOIA instead should work, but will cause
25  * `extra' Unibus resets.
26  *
27  * Either of these flags can simply be included as an `options' line in
28  * your configuration file.
29  */
30 
31 /* #define MSCP_PARANOIA */
32 /* #define AVOID_EMULEX_BUG */
33 
34 /*
35  * Per driver information.
36  *
37  * md_ndpc sets the maximum unit number allowed in response packets.
38  * md_nunits is the number of drives attached to all controllers.
39  * md_unitshift is the divisor for converting a minor device number
40  * to a unit index for the device queues in md_utab.
41  *
42  * The routines are called from the generic response dispatcher.
43  * THE FOLLOWING IS OUT OF DATE
44  * The first three (dgram, ctlrdone, and unconf) get passed a pointer
45  * to the uba_ctlr and to the packet; the rest get a pointer to the
46  * uba_device and to the packet (`um, mp' and `ui, mp' respectively).
47  * The routines unconf, online, gotstatus, and ioerr are functions
48  * and should return one of the values given below.  In addition,
49  * the ioerr and bb routines get a third argument, `bp': a pointer
50  * to the buffer describing the transfer in error.
51  * END OUT OF DATE
52  */
53 struct mscp_driver {
54 	int	md_ndpc;		/* number of drives per ctlr */
55 	int	md_nunits;		/* total number drives (all ctlrs) */
56 	int	md_unitshift;		/* device number to unit: >> count */
57 	struct	buf *md_utab;		/* pointer to device queues */
58 	struct	disklabel *md_lab;	/* pointer to devicee disklabels */
59 	struct	uba_device **md_dinfo;	/* pointer to device info */
60 	int	(*md_dgram)();		/* error datagram */
61 	int	(*md_ctlrdone)();	/* controller operation complete */
62 	int	(*md_unconf)();		/* response from unconfigured drive */
63 	int	(*md_iodone)();		/* normal I/O is done */
64 	int	(*md_online)();		/* drive on line */
65 	int	(*md_gotstatus)();	/* got unit status */
66 	int	(*md_replace)();	/* replace done */
67 	int	(*md_ioerr)();		/* read or write failed */
68 	int	(*md_bb)();		/* B_BAD io done */
69 	char	*md_mname;		/* name of controllers */
70 	char	*md_dname;		/* name of drives */
71 };
72 
73 /*
74  * Return values from functions.
75  * MSCP_RESTARTED is peculiar to I/O errors.
76  */
77 #define	MSCP_DONE	0		/* all ok */
78 #define	MSCP_FAILED	1		/* no go */
79 #define	MSCP_RESTARTED	2		/* transfer restarted */
80 
81 /*
82  * Ring information, per ring (one each for commands and responses).
83  */
84 struct mscp_ri {
85 	int	mri_size;		/* ring size */
86 	int	mri_next;		/* next (expected|free) */
87 	long	*mri_desc;		/* base address of descriptors */
88 	struct	mscp *mri_ring;		/* base address of packets */
89 };
90 
91 /*
92  * Per device information.
93  *
94  * mi_ip is a pointer to the inverting pointers (things that get `ui's
95  * given unit numbers) FOR THIS CONTROLLER (NOT the whole set!).
96  *
97  * mi_wtab holds a queue of those transfers that were started but have
98  * not yet finished.  Other Unibus drivers do not need this as they hand
99  * out requests one at a time.  MSCP devices, however, take a slew of
100  * requests and pick their own order to execute them.  This means that
101  * we have to have a place to move transfers that were given to the
102  * controller, so we can tell those apart from those that have not yet
103  * been handed out; mi_wtab is that place.
104  */
105 struct mscp_info {
106 	struct	mscp_driver *mi_md;	/* pointer to driver info */
107 	int	mi_ctlr;		/* controller index */
108 	struct	buf *mi_tab;		/* pointer to ctlr's drive queue */
109 	struct	uba_device **mi_ip;	/* pointer to inverting pointers */
110 	struct	mscp_ri mi_cmd;		/* MSCP command ring info */
111 	struct	mscp_ri mi_rsp;		/* MSCP response ring info */
112 	short	mi_credits;		/* transfer credits */
113 	char	mi_wantcmd;		/* waiting for command packet */
114 	char	mi_wantcredits;		/* waiting for transfer credits */
115 	struct	buf mi_wtab;		/* transfer wait queue */
116 #ifdef AVOID_EMULEX_BUG
117 #define	AEB_MAX_BP	32		/* max pend xfers (power of 2) XXX */
118 	struct	buf *mi_bp[AEB_MAX_BP];	/* xfer no. to buffer */
119 	u_int	mi_nextbp;		/* generates unique xfer no's */
120 	int	mi_ok;			/* for error rate statistics */
121 #endif AVOID_EMULEX_BUG
122 };
123 
124 /*
125  * We have run out of credits when mi_credits is <= MSCP_MINCREDITS.
126  * It is still possible to issue one command in this case, but it must
127  * not be a data transfer.  E.g., `get command status' or `abort command'
128  * is legal, while `read' is not.
129  */
130 #define	MSCP_MINCREDITS	1
131 
132 /*
133  * Flags for mscp_getcp().
134  */
135 #define	MSCP_WAIT	1
136 #define	MSCP_DONTWAIT	0
137 
138 struct	mscp *mscp_getcp();	/* get a command packet */
139 
140 /*
141  * Unit flags
142  */
143 #define	UNIT_ONLINE	0x01	/* drive is on line */
144 #define	UNIT_HAVESTATUS	0x02	/* got unit status */
145 #define	UNIT_REQUEUE	0x04	/* requeue after response */
146 
147 /*
148  * Handle a command ring transition: wake up sleepers for command packets.
149  * This is too simple to bother with a function call.
150  */
151 #define	MSCP_DOCMD(mi) { \
152 	if ((mi)->mi_wantcmd) { \
153 		(mi)->mi_wantcmd = 0; \
154 		wakeup((caddr_t) &(mi)->mi_wantcmd); \
155 	} \
156 }
157 
158 /*
159  * The following macro appends a buffer to a drive queue or a drive to
160  * a controller queue, given the name of the forward link.  Use as
161  * `APPEND(dp, &um->um_tab, b_forw)' or `APPEND(bp, dp, av_forw)',
162  * where `bp' is a transfer request, `dp' is a drive queue, and `um_tab'
163  * is a controller queue.  (That is, the forward link for controller
164  * queues is `b_forw'; for drive queues, it is `av_forw'.)
165  */
166 #define	APPEND(bp, queue, link) { \
167 	(bp)->link = NULL; \
168 	if ((queue)->b_actf == NULL) \
169 		(queue)->b_actf = (bp); \
170 	else \
171 		(queue)->b_actl->link = (bp); \
172 	(queue)->b_actl = (bp); \
173 }
174