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