1 /* $OpenBSD: aacvar.h,v 1.1 2000/11/10 09:39:36 niklas Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 Michael Smith 5 * Copyright (c) 2000 BSDi 6 * Copyright (c) 2000 Niklas Hallqvist 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $FreeBSD: /c/ncvs/src/sys/dev/aac/aacvar.h,v 1.1 2000/09/13 03:20:34 msmith Exp $ 31 */ 32 33 /* 34 * This driver would not have rewritten for OpenBSD if it was not for the 35 * hardware dontion from Nocom. I want to thank them for their support. 36 * Of course, credit should go to Mike Smith for the original work he did 37 * in the FreeBSD driver where I found lots of inspiration. 38 * - Niklas Hallqvist 39 */ 40 41 /* Debugging */ 42 #ifdef AAC_DEBUG 43 #define AAC_DPRINTF(mask, args) if (aac_debug & (mask)) printf args 44 #define AAC_D_INTR 0x01 45 #define AAC_D_MISC 0x02 46 #define AAC_D_CMD 0x04 47 #define AAC_D_QUEUE 0x08 48 #define AAC_D_IO 0x10 49 extern int aac_debug; 50 51 #define AAC_PRINT_FIB(sc, fib) aac_print_fib((sc), (fib), __FUNCTION__) 52 #else 53 #define AAC_DPRINTF(mask, args) 54 #define AAC_PRINT_FIB(sc, fib) 55 #endif 56 57 struct aac_code_lookup { 58 char *string; 59 u_int32_t code; 60 }; 61 62 struct aac_softc; 63 64 /* 65 * We allocate a small set of FIBs for the adapter to use to send us messages. 66 */ 67 #define AAC_ADAPTER_FIBS 8 68 69 /* 70 * Firmware messages are passed in the printf buffer. 71 */ 72 #define AAC_PRINTF_BUFSIZE 256 73 74 /* 75 * We wait this many seconds for the adapter to come ready if it is still 76 * booting. 77 */ 78 #define AAC_BOOT_TIMEOUT (3 * 60) 79 80 /* 81 * Wait this long for a lost interrupt to get detected. 82 */ 83 #define AAC_WATCH_TIMEOUT 10000 /* 10000 * 1ms = 10s */ 84 85 /* 86 * Timeout for immediate commands. 87 */ 88 #define AAC_IMMEDIATE_TIMEOUT 30 89 90 /* 91 * Delay 20ms after the qnotify in sync operations. Experimentally deduced. 92 */ 93 #define AAC_SYNC_DELAY 20000 94 95 /* 96 * The firmware interface allows for a 16-bit s/g list length. We limit 97 * ourselves to a reasonable maximum and ensure alignment. 98 */ 99 #define AAC_MAXSGENTRIES 64 /* max S/G entries, limit 65535 */ 100 /* 101 * We gather a number of adapter-visible items into a single structure. 102 * 103 * The ordering of this strucure may be important; we copy the Linux driver: 104 * 105 * Adapter FIBs 106 * Init struct 107 * Queue headers (Comm Area) 108 * Printf buffer 109 * 110 * In addition, we add: 111 * Sync Fib 112 */ 113 struct aac_common { 114 /* fibs for the controller to send us messages */ 115 struct aac_fib ac_fibs[AAC_ADAPTER_FIBS]; 116 117 /* the init structure */ 118 struct aac_adapter_init ac_init; 119 120 /* arena within which the queue structures are kept */ 121 u_int8_t ac_qbuf[sizeof(struct aac_queue_table) + AAC_QUEUE_ALIGN]; 122 123 /* buffer for text messages from the controller */ 124 char ac_printf[AAC_PRINTF_BUFSIZE]; 125 126 /* fib for synchronous commands */ 127 struct aac_fib ac_sync_fib; 128 }; 129 130 /* 131 * Interface operations 132 */ 133 struct aac_interface { 134 int (*aif_get_fwstatus) __P((struct aac_softc *)); 135 void (*aif_qnotify) __P((struct aac_softc *, int)); 136 int (*aif_get_istatus) __P((struct aac_softc *)); 137 void (*aif_set_istatus) __P((struct aac_softc *, int)); 138 void (*aif_set_mailbox) __P((struct aac_softc *, u_int32_t, 139 u_int32_t, u_int32_t, u_int32_t, u_int32_t)); 140 int (*aif_get_mailboxstatus) __P((struct aac_softc *)); 141 void (*aif_set_interrupts) __P((struct aac_softc *, int)); 142 }; 143 extern struct aac_interface aac_rx_interface; 144 extern struct aac_interface aac_sa_interface; 145 146 #define AAC_GET_FWSTATUS(sc) ((sc)->sc_if.aif_get_fwstatus(sc)) 147 #define AAC_QNOTIFY(sc, qbit) \ 148 ((sc)->sc_if.aif_qnotify((sc), (qbit))) 149 #define AAC_GET_ISTATUS(sc) ((sc)->sc_if.aif_get_istatus(sc)) 150 #define AAC_CLEAR_ISTATUS(sc, mask) \ 151 ((sc)->sc_if.aif_set_istatus((sc), (mask))) 152 #define AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3) \ 153 do { \ 154 ((sc)->sc_if.aif_set_mailbox((sc), (command), (arg0), \ 155 (arg1), (arg2), (arg3))); \ 156 } while(0) 157 #define AAC_GET_MAILBOXSTATUS(sc) \ 158 ((sc)->sc_if.aif_get_mailboxstatus(sc)) 159 #define AAC_MASK_INTERRUPTS(sc) \ 160 ((sc)->sc_if.aif_set_interrupts((sc), 0)) 161 #define AAC_UNMASK_INTERRUPTS(sc) \ 162 ((sc)->sc_if.aif_set_interrupts((sc), 1)) 163 164 #define AAC_SETREG4(sc, reg, val) \ 165 bus_space_write_4((sc)->sc_memt, (sc)->sc_memh, (reg), (val)) 166 #define AAC_GETREG4(sc, reg) \ 167 bus_space_read_4((sc)->sc_memt, (sc)->sc_memh, (reg)) 168 #define AAC_SETREG2(sc, reg, val) \ 169 bus_space_write_2((sc)->sc_memt, (sc)->sc_memh, (reg), (val)) 170 #define AAC_GETREG2(sc, reg) \ 171 bus_space_read_2((sc)->sc_memt, (sc)->sc_memh, (reg)) 172 #define AAC_SETREG1(sc, reg, val) \ 173 bus_space_write_1((sc)->sc_memt, (sc)->sc_memh, (reg), (val)) 174 #define AAC_GETREG1(sc, reg) \ 175 bus_space_read_1((sc)->sc_memt, (sc)->sc_memh, (reg)) 176 177 /* 178 * Per-container data structure 179 */ 180 struct aac_container 181 { 182 struct aac_mntobj co_mntobj; 183 struct device co_disk; 184 }; 185 186 /* 187 * A command contol block, one for each corresponding command index of the 188 * controller. 189 */ 190 struct aac_ccb { 191 TAILQ_ENTRY(aac_ccb) ac_chain; 192 struct scsi_xfer *ac_xs; 193 struct aac_fib *ac_fib; /* FIB associated with this command */ 194 bus_addr_t ac_fibphys; /* bus address of the FIB */ 195 bus_dmamap_t ac_dmamap_xfer; 196 struct aac_sg_table *ac_sgtable;/* pointer to s/g table in command */ 197 int ac_timeout; 198 u_int32_t ac_blockno; 199 u_int32_t ac_blockcnt; 200 u_int8_t ac_flags; 201 #define AAC_ACF_WATCHDOG 0x1 202 #define AAC_ACF_COMPLETED 0x2 203 }; 204 205 /* 206 * Per-controller structure. 207 */ 208 struct aac_softc { 209 struct device sc_dev; 210 void *sc_ih; 211 struct scsi_link sc_link; /* Virtual SCSI bus for cache devs */ 212 213 bus_space_tag_t sc_memt; 214 bus_space_handle_t sc_memh; 215 bus_dma_tag_t sc_dmat; /* parent DMA tag */ 216 217 /* controller features, limits and status */ 218 int sc_state; 219 #define AAC_STATE_SUSPEND (1<<0) 220 #define AAC_STATE_OPEN (1<<1) 221 #define AAC_STATE_INTERRUPTS_ON (1<<2) 222 #define AAC_STATE_AIF_SLEEPER (1<<3) 223 struct FsaRevision sc_revision; 224 225 int sc_hwif; /* controller hardware interface */ 226 #define AAC_HWIF_I960RX 0 227 #define AAC_HWIF_STRONGARM 1 228 229 struct aac_common *sc_common; 230 u_int32_t sc_common_busaddr; 231 struct aac_interface sc_if; 232 233 /* XXX This should really be dynamic. It is very wasteful now. */ 234 struct aac_ccb sc_ccbs[AAC_ADAP_NORM_CMD_ENTRIES]; 235 TAILQ_HEAD(, aac_ccb) sc_free_ccb, sc_ccbq; 236 /* commands on hold for controller resources */ 237 TAILQ_HEAD(, aac_ccb) sc_ready; 238 /* commands which have been returned by the controller */ 239 TAILQ_HEAD(, aac_ccb) sc_completed; 240 LIST_HEAD(, scsi_xfer) sc_queue; 241 struct scsi_xfer *sc_queuelast; 242 243 /* command management */ 244 struct aac_queue_table *sc_queues; 245 struct aac_queue_entry *sc_qentries[AAC_QUEUE_COUNT]; 246 247 struct { 248 u_int8_t hd_present; 249 u_int8_t hd_is_logdrv; 250 u_int8_t hd_is_arraydrv; 251 u_int8_t hd_is_master; 252 u_int8_t hd_is_parity; 253 u_int8_t hd_is_hotfix; 254 u_int8_t hd_master_no; 255 u_int8_t hd_lock; 256 u_int8_t hd_heads; 257 u_int8_t hd_secs; 258 u_int16_t hd_devtype; 259 u_int32_t hd_size; 260 u_int8_t hd_ldr_no; 261 u_int8_t hd_rw_attribs; 262 u_int32_t hd_start_sec; 263 } sc_hdr[AAC_MAX_CONTAINERS]; 264 }; 265 266 /* XXX These have to become spinlocks in case of SMP */ 267 #define AAC_LOCK(sc) splbio() 268 #define AAC_UNLOCK(sc, lock) splx(lock) 269 typedef int aac_lock_t; 270 271 void aacminphys __P((struct buf *)); 272 int aac_attach __P((struct aac_softc *)); 273 int aac_intr __P((void *)); 274 275 #ifdef __GNUC__ 276 /* These all require correctly aligned buffers */ 277 static __inline__ void aac_enc16 __P((u_int8_t *, u_int16_t)); 278 static __inline__ void aac_enc32 __P((u_int8_t *, u_int32_t)); 279 static __inline__ u_int16_t aac_dec16 __P((u_int8_t *)); 280 static __inline__ u_int32_t aac_dec32 __P((u_int8_t *)); 281 282 static __inline__ void 283 aac_enc16(addr, value) 284 u_int8_t *addr; 285 u_int16_t value; 286 { 287 *(u_int16_t *)addr = htole16(value); 288 } 289 290 static __inline__ void 291 aac_enc32(addr, value) 292 u_int8_t *addr; 293 u_int32_t value; 294 { 295 *(u_int32_t *)addr = htole32(value); 296 } 297 298 static __inline__ u_int16_t 299 aac_dec16(addr) 300 u_int8_t *addr; 301 { 302 return letoh16(*(u_int16_t *)addr); 303 } 304 305 static __inline__ u_int32_t 306 aac_dec32(addr) 307 u_int8_t *addr; 308 { 309 return letoh32(*(u_int32_t *)addr); 310 } 311 312 /* 313 * Queue primitives 314 * 315 * These are broken out individually to make statistics gathering easier. 316 */ 317 318 static __inline__ void 319 aac_enqueue_completed(struct aac_ccb *ccb) 320 { 321 struct aac_softc *sc = ccb->ac_xs->sc_link->adapter_softc; 322 aac_lock_t lock; 323 324 lock = AAC_LOCK(sc); 325 TAILQ_INSERT_TAIL(&sc->sc_completed, ccb, ac_chain); 326 AAC_UNLOCK(sc, lock); 327 } 328 329 static __inline__ struct aac_ccb * 330 aac_dequeue_completed(struct aac_softc *sc) 331 { 332 struct aac_ccb *ccb; 333 aac_lock_t lock; 334 335 lock = AAC_LOCK(sc); 336 if ((ccb = TAILQ_FIRST(&sc->sc_completed)) != NULL) 337 TAILQ_REMOVE(&sc->sc_completed, ccb, ac_chain); 338 AAC_UNLOCK(sc, lock); 339 return (ccb); 340 } 341 #endif 342