1/* $NetBSD: mlxvar.h,v 1.16 2016/09/27 03:33:32 pgoyette Exp $ */ 2 3/*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/*- 33 * Copyright (c) 1999 Michael Smith 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 * 57 * from FreeBSD: mlxvar.h,v 1.5.2.2 2000/04/24 19:40:50 msmith Exp 58 */ 59 60#ifndef _IC_MLXVAR_H_ 61#define _IC_MLXVAR_H_ 62 63/* Older boards allow up to 17 segments and 64kB transfers. */ 64#define MLX_MAX_SEGS 17 65#define MLX_MAX_XFER 65536 66#define MLX_SGL_SIZE (sizeof(struct mlx_sgentry) * MLX_MAX_SEGS) 67 68/* This shouldn't be ajusted lightly... */ 69#define MLX_MAX_DRIVES 32 70 71/* Maximum queue depth, matching the older controllers. */ 72#define MLX_MAX_QUEUECNT 63 73 74/* Number of CCBs to reserve for control operations. */ 75#define MLX_NCCBS_CONTROL 7 76 77/* Structure describing a system drive as attached to the controller. */ 78struct mlx_sysdrive { 79 u_int32_t ms_size; 80 u_short ms_state; 81 u_short ms_raidlevel; 82 device_t ms_dv; 83}; 84 85/* Optional per-CCB context. */ 86struct mlx_ccb; 87struct mlx_context { 88 void (*mx_handler)(struct mlx_ccb *); 89 void *mx_context; 90 device_t mx_dv; 91}; 92 93/* Command control block. */ 94struct mlx_ccb { 95 union { 96 SIMPLEQ_ENTRY(mlx_ccb) simpleq; 97 SLIST_ENTRY(mlx_ccb) slist; 98 TAILQ_ENTRY(mlx_ccb) tailq; 99 } mc_chain; 100 u_int mc_flags; 101 u_int mc_status; 102 u_int mc_ident; 103 time_t mc_expiry; 104 u_int mc_nsgent; 105 u_int mc_xfer_size; 106 bus_addr_t mc_xfer_phys; 107 bus_dmamap_t mc_xfer_map; 108 struct mlx_context mc_mx; 109 u_int8_t mc_mbox[16]; 110}; 111#define MC_XFER_IN MU_XFER_IN /* Map describes inbound xfer */ 112#define MC_XFER_OUT MU_XFER_OUT /* Map describes outbound xfer */ 113#define MC_WAITING 0x0400 /* We have waiters */ 114#define MC_CONTROL 0x0800 /* Control operation */ 115 116/* 117 * Per-controller state. 118 */ 119struct mlx_softc { 120 device_t mlx_dv; 121 bus_space_tag_t mlx_iot; 122 bus_space_handle_t mlx_ioh; 123 bus_dma_tag_t mlx_dmat; 124 bus_dmamap_t mlx_dmamap; 125 void *mlx_ih; 126 127 SLIST_HEAD(, mlx_ccb) mlx_ccb_freelist; 128 TAILQ_HEAD(, mlx_ccb) mlx_ccb_worklist; 129 SIMPLEQ_HEAD(, mlx_ccb) mlx_ccb_queue; 130 struct mlx_ccb *mlx_ccbs; 131 int mlx_nccbs; 132 int mlx_nccbs_ctrl; 133 134 void * mlx_sgls; 135 bus_addr_t mlx_sgls_paddr; 136 137 int (*mlx_submit)(struct mlx_softc *, struct mlx_ccb *); 138 int (*mlx_findcomplete)(struct mlx_softc *, u_int *, u_int *); 139 void (*mlx_intaction)(struct mlx_softc *, int); 140 int (*mlx_fw_handshake)(struct mlx_softc *, int *, int *, int *); 141 int (*mlx_reset)(struct mlx_softc *); 142 143 int mlx_max_queuecnt; 144 struct mlx_cinfo mlx_ci; 145 146 time_t mlx_lastpoll; 147 u_int mlx_lastevent; 148 u_int mlx_currevent; 149 u_int mlx_bg; 150 struct mlx_rebuild_status mlx_rebuildstat; 151 struct mlx_pause mlx_pause; 152 int mlx_flags; 153 154 struct mlx_sysdrive mlx_sysdrive[MLX_MAX_DRIVES]; 155 int mlx_numsysdrives; 156}; 157 158#define MLX_BG_CHECK 1 /* we started a check */ 159#define MLX_BG_REBUILD 2 /* we started a rebuild */ 160#define MLX_BG_SPONTANEOUS 3 /* it just happened somehow */ 161 162#define MLXF_SPINUP_REPORTED 0x0001 /* "spinning up drives" displayed */ 163#define MLXF_EVENTLOG_BUSY 0x0002 /* currently reading event log */ 164#define MLXF_FW_INITTED 0x0004 /* firmware init crap done */ 165#define MLXF_PAUSEWORKS 0x0008 /* channel pause works as expected */ 166#define MLXF_OPEN 0x0010 /* control device is open */ 167#define MLXF_INITOK 0x0020 /* controller initialised OK */ 168#define MLXF_PERIODIC_CTLR 0x0040 /* periodic check running */ 169#define MLXF_PERIODIC_DRIVE 0x0080 /* periodic check running */ 170#define MLXF_PERIODIC_REBUILD 0x0100 /* periodic check running */ 171#define MLXF_RESCANNING 0x0400 /* rescanning drive table */ 172 173struct mlx_attach_args { 174 int mlxa_unit; 175}; 176 177int mlx_flush(struct mlx_softc *, int); 178void mlx_init(struct mlx_softc *, const char *); 179int mlx_intr(void *); 180int mlx_configure(struct mlx_softc *, int); 181 182int mlx_ccb_alloc(struct mlx_softc *, struct mlx_ccb **, int); 183const char *mlx_ccb_diagnose(struct mlx_ccb *); 184void mlx_ccb_enqueue(struct mlx_softc *, struct mlx_ccb *); 185void mlx_ccb_free(struct mlx_softc *, struct mlx_ccb *); 186int mlx_ccb_map(struct mlx_softc *, struct mlx_ccb *, void *, int, int); 187int mlx_ccb_poll(struct mlx_softc *, struct mlx_ccb *, int); 188void mlx_ccb_unmap(struct mlx_softc *, struct mlx_ccb *); 189int mlx_ccb_wait(struct mlx_softc *, struct mlx_ccb *); 190 191static __inline void mlx_make_type1(struct mlx_ccb *, u_int8_t, u_int16_t, 192 u_int32_t, u_int8_t, u_int32_t, 193 u_int8_t); 194static __inline void mlx_make_type2(struct mlx_ccb *, u_int8_t, u_int8_t, 195 u_int8_t, u_int8_t, u_int8_t, 196 u_int8_t, u_int8_t, u_int32_t, 197 u_int8_t); 198static __inline void mlx_make_type3(struct mlx_ccb *, u_int8_t, u_int8_t, 199 u_int8_t, u_int16_t, u_int8_t, 200 u_int8_t, u_int32_t, u_int8_t); 201static __inline void mlx_make_type4(struct mlx_ccb *, u_int8_t, u_int16_t, 202 u_int32_t, u_int32_t, u_int8_t); 203static __inline void mlx_make_type5(struct mlx_ccb *, u_int8_t, u_int8_t, 204 u_int8_t, u_int32_t, u_int32_t, 205 u_int8_t); 206 207static __inline u_int8_t mlx_inb(struct mlx_softc *, int); 208static __inline u_int16_t mlx_inw(struct mlx_softc *, int); 209static __inline u_int32_t mlx_inl(struct mlx_softc *, int); 210static __inline void mlx_outb(struct mlx_softc *, int, u_int8_t); 211static __inline void mlx_outw(struct mlx_softc *, int, u_int16_t); 212static __inline void mlx_outl(struct mlx_softc *, int, u_int32_t); 213 214static __inline void 215mlx_make_type1(struct mlx_ccb *mc, u_int8_t code, u_int16_t f1, u_int32_t f2, 216 u_int8_t f3, u_int32_t f4, u_int8_t f5) 217{ 218 219 mc->mc_mbox[0x0] = code; 220 mc->mc_mbox[0x2] = f1; 221 mc->mc_mbox[0x3] = ((f2 >> 18) & 0xc0) | ((f1 >> 8) & 0x3f); 222 mc->mc_mbox[0x4] = f2; 223 mc->mc_mbox[0x5] = (f2 >> 8); 224 mc->mc_mbox[0x6] = (f2 >> 16); 225 mc->mc_mbox[0x7] = f3; 226 mc->mc_mbox[0x8] = f4; 227 mc->mc_mbox[0x9] = (f4 >> 8); 228 mc->mc_mbox[0xa] = (f4 >> 16); 229 mc->mc_mbox[0xb] = (f4 >> 24); 230 mc->mc_mbox[0xc] = f5; 231} 232 233static __inline void 234mlx_make_type2(struct mlx_ccb *mc, u_int8_t code, u_int8_t f1, u_int8_t f2, 235 u_int8_t f3, u_int8_t f4, u_int8_t f5, u_int8_t f6, 236 u_int32_t f7, u_int8_t f8) 237{ 238 239 mc->mc_mbox[0x0] = code; 240 mc->mc_mbox[0x2] = f1; 241 mc->mc_mbox[0x3] = f2; 242 mc->mc_mbox[0x4] = f3; 243 mc->mc_mbox[0x5] = f4; 244 mc->mc_mbox[0x6] = f5; 245 mc->mc_mbox[0x7] = f6; 246 mc->mc_mbox[0x8] = f7; 247 mc->mc_mbox[0x9] = (f7 >> 8); 248 mc->mc_mbox[0xa] = (f7 >> 16); 249 mc->mc_mbox[0xb] = (f7 >> 24); 250 mc->mc_mbox[0xc] = f8; 251} 252 253static __inline void 254mlx_make_type3(struct mlx_ccb *mc, u_int8_t code, u_int8_t f1, u_int8_t f2, 255 u_int16_t f3, u_int8_t f4, u_int8_t f5, u_int32_t f6, 256 u_int8_t f7) 257{ 258 259 mc->mc_mbox[0x0] = code; 260 mc->mc_mbox[0x2] = f1; 261 mc->mc_mbox[0x3] = f2; 262 mc->mc_mbox[0x4] = f3; 263 mc->mc_mbox[0x5] = (f3 >> 8); 264 mc->mc_mbox[0x6] = f4; 265 mc->mc_mbox[0x7] = f5; 266 mc->mc_mbox[0x8] = f6; 267 mc->mc_mbox[0x9] = (f6 >> 8); 268 mc->mc_mbox[0xa] = (f6 >> 16); 269 mc->mc_mbox[0xb] = (f6 >> 24); 270 mc->mc_mbox[0xc] = f7; 271} 272 273static __inline void 274mlx_make_type4(struct mlx_ccb *mc, u_int8_t code, u_int16_t f1, u_int32_t f2, 275 u_int32_t f3, u_int8_t f4) 276{ 277 278 mc->mc_mbox[0x0] = code; 279 mc->mc_mbox[0x2] = f1; 280 mc->mc_mbox[0x3] = (f1 >> 8); 281 mc->mc_mbox[0x4] = f2; 282 mc->mc_mbox[0x5] = (f2 >> 8); 283 mc->mc_mbox[0x6] = (f2 >> 16); 284 mc->mc_mbox[0x7] = (f2 >> 24); 285 mc->mc_mbox[0x8] = f3; 286 mc->mc_mbox[0x9] = (f3 >> 8); 287 mc->mc_mbox[0xa] = (f3 >> 16); 288 mc->mc_mbox[0xb] = (f3 >> 24); 289 mc->mc_mbox[0xc] = f4; 290} 291 292static __inline void 293mlx_make_type5(struct mlx_ccb *mc, u_int8_t code, u_int8_t f1, u_int8_t f2, 294 u_int32_t f3, u_int32_t f4, u_int8_t f5) 295{ 296 297 mc->mc_mbox[0x0] = code; 298 mc->mc_mbox[0x2] = f1; 299 mc->mc_mbox[0x3] = f2; 300 mc->mc_mbox[0x4] = f3; 301 mc->mc_mbox[0x5] = (f3 >> 8); 302 mc->mc_mbox[0x6] = (f3 >> 16); 303 mc->mc_mbox[0x7] = (f3 >> 24); 304 mc->mc_mbox[0x8] = f4; 305 mc->mc_mbox[0x9] = (f4 >> 8); 306 mc->mc_mbox[0xa] = (f4 >> 16); 307 mc->mc_mbox[0xb] = (f4 >> 24); 308 mc->mc_mbox[0xc] = f5; 309} 310 311static __inline u_int8_t 312mlx_inb(struct mlx_softc *mlx, int off) 313{ 314 315 bus_space_barrier(mlx->mlx_iot, mlx->mlx_ioh, off, 1, 316 BUS_SPACE_BARRIER_WRITE | BUS_SPACE_BARRIER_READ); 317 return (bus_space_read_1(mlx->mlx_iot, mlx->mlx_ioh, off)); 318} 319 320static __inline u_int16_t 321mlx_inw(struct mlx_softc *mlx, int off) 322{ 323 324 bus_space_barrier(mlx->mlx_iot, mlx->mlx_ioh, off, 2, 325 BUS_SPACE_BARRIER_WRITE | BUS_SPACE_BARRIER_READ); 326 return (bus_space_read_2(mlx->mlx_iot, mlx->mlx_ioh, off)); 327} 328 329static __inline u_int32_t 330mlx_inl(struct mlx_softc *mlx, int off) 331{ 332 333 bus_space_barrier(mlx->mlx_iot, mlx->mlx_ioh, off, 4, 334 BUS_SPACE_BARRIER_WRITE | BUS_SPACE_BARRIER_READ); 335 return (bus_space_read_4(mlx->mlx_iot, mlx->mlx_ioh, off)); 336} 337 338static __inline void 339mlx_outb(struct mlx_softc *mlx, int off, u_int8_t val) 340{ 341 342 bus_space_write_1(mlx->mlx_iot, mlx->mlx_ioh, off, val); 343 bus_space_barrier(mlx->mlx_iot, mlx->mlx_ioh, off, 1, 344 BUS_SPACE_BARRIER_WRITE); 345} 346 347static __inline void 348mlx_outw(struct mlx_softc *mlx, int off, u_int16_t val) 349{ 350 351 bus_space_write_2(mlx->mlx_iot, mlx->mlx_ioh, off, val); 352 bus_space_barrier(mlx->mlx_iot, mlx->mlx_ioh, off, 2, 353 BUS_SPACE_BARRIER_WRITE); 354} 355 356static __inline void 357mlx_outl(struct mlx_softc *mlx, int off, u_int32_t val) 358{ 359 360 bus_space_write_4(mlx->mlx_iot, mlx->mlx_ioh, off, val); 361 bus_space_barrier(mlx->mlx_iot, mlx->mlx_ioh, off, 4, 362 BUS_SPACE_BARRIER_WRITE); 363} 364 365#endif /* !_IC_MLXVAR_H_ */ 366