1 1.70 thorpej /* $NetBSD: mlx.c,v 1.70 2021/08/07 16:19:12 thorpej Exp $ */ 2 1.1 ad 3 1.1 ad /*- 4 1.1 ad * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 1.1 ad * All rights reserved. 6 1.1 ad * 7 1.1 ad * This code is derived from software contributed to The NetBSD Foundation 8 1.1 ad * by Andrew Doran. 9 1.1 ad * 10 1.1 ad * Redistribution and use in source and binary forms, with or without 11 1.1 ad * modification, are permitted provided that the following conditions 12 1.1 ad * are met: 13 1.1 ad * 1. Redistributions of source code must retain the above copyright 14 1.1 ad * notice, this list of conditions and the following disclaimer. 15 1.1 ad * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 ad * notice, this list of conditions and the following disclaimer in the 17 1.1 ad * documentation and/or other materials provided with the distribution. 18 1.1 ad * 19 1.1 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 ad * POSSIBILITY OF SUCH DAMAGE. 30 1.1 ad */ 31 1.1 ad 32 1.1 ad /*- 33 1.1 ad * Copyright (c) 1999 Michael Smith 34 1.1 ad * All rights reserved. 35 1.1 ad * 36 1.1 ad * Redistribution and use in source and binary forms, with or without 37 1.1 ad * modification, are permitted provided that the following conditions 38 1.1 ad * are met: 39 1.1 ad * 1. Redistributions of source code must retain the above copyright 40 1.1 ad * notice, this list of conditions and the following disclaimer. 41 1.1 ad * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 ad * notice, this list of conditions and the following disclaimer in the 43 1.1 ad * documentation and/or other materials provided with the distribution. 44 1.1 ad * 45 1.1 ad * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46 1.1 ad * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 1.1 ad * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 1.1 ad * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 49 1.1 ad * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 1.1 ad * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 1.1 ad * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 1.1 ad * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 1.1 ad * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 1.1 ad * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 1.1 ad * SUCH DAMAGE. 56 1.1 ad * 57 1.1 ad * from FreeBSD: mlx.c,v 1.14.2.3 2000/08/04 06:52:50 msmith Exp 58 1.1 ad */ 59 1.1 ad 60 1.1 ad /* 61 1.1 ad * Driver for the Mylex DAC960 family of RAID controllers. 62 1.1 ad * 63 1.1 ad * TODO: 64 1.1 ad * 65 1.1 ad * o Test and enable channel pause. 66 1.1 ad * o SCSI pass-through. 67 1.1 ad */ 68 1.15 lukem 69 1.15 lukem #include <sys/cdefs.h> 70 1.70 thorpej __KERNEL_RCSID(0, "$NetBSD: mlx.c,v 1.70 2021/08/07 16:19:12 thorpej Exp $"); 71 1.1 ad 72 1.65 pgoyette #if defined(_KERNEL_OPT) 73 1.1 ad #include "ld.h" 74 1.65 pgoyette #endif 75 1.1 ad 76 1.1 ad #include <sys/param.h> 77 1.1 ad #include <sys/systm.h> 78 1.1 ad #include <sys/kernel.h> 79 1.1 ad #include <sys/device.h> 80 1.1 ad #include <sys/queue.h> 81 1.1 ad #include <sys/proc.h> 82 1.1 ad #include <sys/buf.h> 83 1.31 yamt #include <sys/bufq.h> 84 1.1 ad #include <sys/endian.h> 85 1.1 ad #include <sys/malloc.h> 86 1.1 ad #include <sys/conf.h> 87 1.1 ad #include <sys/kthread.h> 88 1.1 ad #include <sys/disk.h> 89 1.47 elad #include <sys/kauth.h> 90 1.65 pgoyette #include <sys/module.h> 91 1.1 ad #include <machine/vmparam.h> 92 1.53 ad #include <sys/bus.h> 93 1.2 enami 94 1.1 ad #include <dev/ldvar.h> 95 1.1 ad 96 1.1 ad #include <dev/ic/mlxreg.h> 97 1.1 ad #include <dev/ic/mlxio.h> 98 1.1 ad #include <dev/ic/mlxvar.h> 99 1.1 ad 100 1.66 riastrad #include "ioconf.h" 101 1.30 drochner #include "locators.h" 102 1.30 drochner 103 1.1 ad #define MLX_TIMEOUT 60 104 1.1 ad 105 1.1 ad #ifdef DIAGNOSTIC 106 1.1 ad #define DPRINTF(x) printf x 107 1.1 ad #else 108 1.1 ad #define DPRINTF(x) 109 1.1 ad #endif 110 1.1 ad 111 1.1 ad static void mlx_adjqparam(struct mlx_softc *, int, int); 112 1.1 ad static int mlx_ccb_submit(struct mlx_softc *, struct mlx_ccb *); 113 1.1 ad static int mlx_check(struct mlx_softc *, int); 114 1.1 ad static void mlx_describe(struct mlx_softc *); 115 1.1 ad static void *mlx_enquire(struct mlx_softc *, int, size_t, 116 1.1 ad void (*)(struct mlx_ccb *), int); 117 1.1 ad static int mlx_fw_message(struct mlx_softc *, int, int, int); 118 1.1 ad static void mlx_pause_action(struct mlx_softc *); 119 1.1 ad static void mlx_pause_done(struct mlx_ccb *); 120 1.1 ad static void mlx_periodic(struct mlx_softc *); 121 1.1 ad static void mlx_periodic_enquiry(struct mlx_ccb *); 122 1.1 ad static void mlx_periodic_eventlog_poll(struct mlx_softc *); 123 1.1 ad static void mlx_periodic_eventlog_respond(struct mlx_ccb *); 124 1.1 ad static void mlx_periodic_rebuild(struct mlx_ccb *); 125 1.1 ad static void mlx_periodic_thread(void *); 126 1.1 ad static int mlx_print(void *, const char *); 127 1.1 ad static int mlx_rebuild(struct mlx_softc *, int, int); 128 1.1 ad static void mlx_shutdown(void *); 129 1.1 ad static int mlx_user_command(struct mlx_softc *, struct mlx_usercommand *); 130 1.1 ad 131 1.20 gehenna dev_type_open(mlxopen); 132 1.20 gehenna dev_type_close(mlxclose); 133 1.20 gehenna dev_type_ioctl(mlxioctl); 134 1.20 gehenna 135 1.20 gehenna const struct cdevsw mlx_cdevsw = { 136 1.61 dholland .d_open = mlxopen, 137 1.61 dholland .d_close = mlxclose, 138 1.61 dholland .d_read = noread, 139 1.61 dholland .d_write = nowrite, 140 1.61 dholland .d_ioctl = mlxioctl, 141 1.61 dholland .d_stop = nostop, 142 1.61 dholland .d_tty = notty, 143 1.61 dholland .d_poll = nopoll, 144 1.61 dholland .d_mmap = nommap, 145 1.61 dholland .d_kqfilter = nokqfilter, 146 1.62 dholland .d_discard = nodiscard, 147 1.61 dholland .d_flag = D_OTHER 148 1.20 gehenna }; 149 1.1 ad 150 1.52 ad static struct lwp *mlx_periodic_lwp; 151 1.1 ad static void *mlx_sdh; 152 1.1 ad 153 1.45 christos static struct { 154 1.1 ad int hwid; 155 1.1 ad const char *name; 156 1.45 christos } const mlx_cname[] = { 157 1.18 ad { 0x00, "960E/960M" }, 158 1.1 ad { 0x01, "960P/PD" }, 159 1.1 ad { 0x02, "960PL" }, 160 1.1 ad { 0x10, "960PG" }, 161 1.1 ad { 0x11, "960PJ" }, 162 1.1 ad { 0x12, "960PR" }, 163 1.1 ad { 0x13, "960PT" }, 164 1.1 ad { 0x14, "960PTL0" }, 165 1.1 ad { 0x15, "960PRL" }, 166 1.1 ad { 0x16, "960PTL1" }, 167 1.1 ad { 0x20, "1164PVX" }, 168 1.1 ad }; 169 1.1 ad 170 1.1 ad static const char * const mlx_sense_msgs[] = { 171 1.1 ad "because write recovery failed", 172 1.1 ad "because of SCSI bus reset failure", 173 1.1 ad "because of double check condition", 174 1.1 ad "because it was removed", 175 1.1 ad "because of gross error on SCSI chip", 176 1.1 ad "because of bad tag returned from drive", 177 1.1 ad "because of timeout on SCSI command", 178 1.1 ad "because of reset SCSI command issued from system", 179 1.1 ad "because busy or parity error count exceeded limit", 180 1.1 ad "because of 'kill drive' command from system", 181 1.1 ad "because of selection timeout", 182 1.1 ad "due to SCSI phase sequence error", 183 1.1 ad "due to unknown status" 184 1.1 ad }; 185 1.1 ad 186 1.1 ad static const char * const mlx_status_msgs[] = { 187 1.1 ad "normal completion", /* 0 */ 188 1.1 ad "irrecoverable data error", /* 1 */ 189 1.1 ad "drive does not exist, or is offline", /* 2 */ 190 1.1 ad "attempt to write beyond end of drive", /* 3 */ 191 1.1 ad "bad data encountered", /* 4 */ 192 1.1 ad "invalid log entry request", /* 5 */ 193 1.1 ad "attempt to rebuild online drive", /* 6 */ 194 1.1 ad "new disk failed during rebuild", /* 7 */ 195 1.1 ad "invalid channel/target", /* 8 */ 196 1.1 ad "rebuild/check already in progress", /* 9 */ 197 1.1 ad "one or more disks are dead", /* 10 */ 198 1.1 ad "invalid or non-redundant drive", /* 11 */ 199 1.1 ad "channel is busy", /* 12 */ 200 1.1 ad "channel is not stopped", /* 13 */ 201 1.1 ad "rebuild successfully terminated", /* 14 */ 202 1.1 ad "unsupported command", /* 15 */ 203 1.1 ad "check condition received", /* 16 */ 204 1.1 ad "device is busy", /* 17 */ 205 1.1 ad "selection or command timeout", /* 18 */ 206 1.1 ad "command terminated abnormally", /* 19 */ 207 1.1 ad "controller wedged", /* 20 */ 208 1.1 ad "software timeout", /* 21 */ 209 1.7 lukem "command busy (?)", /* 22 */ 210 1.1 ad }; 211 1.1 ad 212 1.45 christos static struct { 213 1.1 ad u_char command; 214 1.1 ad u_char msg; /* Index into mlx_status_msgs[]. */ 215 1.1 ad u_short status; 216 1.45 christos } const mlx_msgs[] = { 217 1.1 ad { MLX_CMD_READSG, 1, 0x0001 }, 218 1.1 ad { MLX_CMD_READSG, 1, 0x0002 }, 219 1.1 ad { MLX_CMD_READSG, 3, 0x0105 }, 220 1.1 ad { MLX_CMD_READSG, 4, 0x010c }, 221 1.1 ad { MLX_CMD_WRITESG, 1, 0x0001 }, 222 1.1 ad { MLX_CMD_WRITESG, 1, 0x0002 }, 223 1.1 ad { MLX_CMD_WRITESG, 3, 0x0105 }, 224 1.1 ad { MLX_CMD_READSG_OLD, 1, 0x0001 }, 225 1.1 ad { MLX_CMD_READSG_OLD, 1, 0x0002 }, 226 1.1 ad { MLX_CMD_READSG_OLD, 3, 0x0105 }, 227 1.1 ad { MLX_CMD_WRITESG_OLD, 1, 0x0001 }, 228 1.1 ad { MLX_CMD_WRITESG_OLD, 1, 0x0002 }, 229 1.1 ad { MLX_CMD_WRITESG_OLD, 3, 0x0105 }, 230 1.1 ad { MLX_CMD_LOGOP, 5, 0x0105 }, 231 1.1 ad { MLX_CMD_REBUILDASYNC, 6, 0x0002 }, 232 1.1 ad { MLX_CMD_REBUILDASYNC, 7, 0x0004 }, 233 1.1 ad { MLX_CMD_REBUILDASYNC, 8, 0x0105 }, 234 1.1 ad { MLX_CMD_REBUILDASYNC, 9, 0x0106 }, 235 1.1 ad { MLX_CMD_REBUILDASYNC, 14, 0x0107 }, 236 1.1 ad { MLX_CMD_CHECKASYNC, 10, 0x0002 }, 237 1.1 ad { MLX_CMD_CHECKASYNC, 11, 0x0105 }, 238 1.1 ad { MLX_CMD_CHECKASYNC, 9, 0x0106 }, 239 1.1 ad { MLX_CMD_STOPCHANNEL, 12, 0x0106 }, 240 1.1 ad { MLX_CMD_STOPCHANNEL, 8, 0x0105 }, 241 1.1 ad { MLX_CMD_STARTCHANNEL, 13, 0x0005 }, 242 1.1 ad { MLX_CMD_STARTCHANNEL, 8, 0x0105 }, 243 1.1 ad { MLX_CMD_DIRECT_CDB, 16, 0x0002 }, 244 1.1 ad { MLX_CMD_DIRECT_CDB, 17, 0x0008 }, 245 1.1 ad { MLX_CMD_DIRECT_CDB, 18, 0x000e }, 246 1.1 ad { MLX_CMD_DIRECT_CDB, 19, 0x000f }, 247 1.1 ad { MLX_CMD_DIRECT_CDB, 8, 0x0105 }, 248 1.1 ad 249 1.1 ad { 0, 20, MLX_STATUS_WEDGED }, 250 1.1 ad { 0, 21, MLX_STATUS_LOST }, 251 1.1 ad { 0, 22, MLX_STATUS_BUSY }, 252 1.1 ad 253 1.1 ad { 0, 14, 0x0104 }, 254 1.1 ad }; 255 1.1 ad 256 1.1 ad /* 257 1.1 ad * Initialise the controller and our interface. 258 1.1 ad */ 259 1.1 ad void 260 1.1 ad mlx_init(struct mlx_softc *mlx, const char *intrstr) 261 1.1 ad { 262 1.1 ad struct mlx_ccb *mc; 263 1.1 ad struct mlx_enquiry_old *meo; 264 1.18 ad struct mlx_enquiry2 *me2; 265 1.18 ad struct mlx_cinfo *ci; 266 1.1 ad int rv, fwminor, hscode, hserr, hsparam1, hsparam2, hsmsg; 267 1.1 ad int size, i, rseg; 268 1.1 ad const char *wantfwstr; 269 1.1 ad bus_dma_segment_t seg; 270 1.1 ad 271 1.1 ad SIMPLEQ_INIT(&mlx->mlx_ccb_queue); 272 1.1 ad SLIST_INIT(&mlx->mlx_ccb_freelist); 273 1.1 ad TAILQ_INIT(&mlx->mlx_ccb_worklist); 274 1.1 ad 275 1.1 ad if (intrstr != NULL) 276 1.60 chs printf("%s: interrupting at %s\n", device_xname(mlx->mlx_dv), 277 1.1 ad intrstr); 278 1.1 ad 279 1.1 ad /* 280 1.1 ad * Allocate the scatter/gather lists. 281 1.1 ad */ 282 1.1 ad size = MLX_SGL_SIZE * MLX_MAX_QUEUECNT; 283 1.1 ad 284 1.1 ad if ((rv = bus_dmamem_alloc(mlx->mlx_dmat, size, PAGE_SIZE, 0, &seg, 1, 285 1.1 ad &rseg, BUS_DMA_NOWAIT)) != 0) { 286 1.63 msaitoh aprint_error_dev(mlx->mlx_dv, 287 1.63 msaitoh "unable to allocate sglists, rv = %d\n", rv); 288 1.1 ad return; 289 1.1 ad } 290 1.1 ad 291 1.32 perry if ((rv = bus_dmamem_map(mlx->mlx_dmat, &seg, rseg, size, 292 1.51 christos (void **)&mlx->mlx_sgls, 293 1.1 ad BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 294 1.63 msaitoh aprint_error_dev(mlx->mlx_dv, 295 1.63 msaitoh "unable to map sglists, rv = %d\n", rv); 296 1.1 ad return; 297 1.1 ad } 298 1.1 ad 299 1.32 perry if ((rv = bus_dmamap_create(mlx->mlx_dmat, size, 1, size, 0, 300 1.50 tsutsui BUS_DMA_NOWAIT, &mlx->mlx_dmamap)) != 0) { 301 1.63 msaitoh aprint_error_dev(mlx->mlx_dv, 302 1.63 msaitoh "unable to create sglist DMA map, rv = %d\n", rv); 303 1.1 ad return; 304 1.1 ad } 305 1.1 ad 306 1.1 ad if ((rv = bus_dmamap_load(mlx->mlx_dmat, mlx->mlx_dmamap, 307 1.1 ad mlx->mlx_sgls, size, NULL, BUS_DMA_NOWAIT)) != 0) { 308 1.63 msaitoh aprint_error_dev(mlx->mlx_dv, 309 1.63 msaitoh "unable to load sglist DMA map, rv = %d\n", rv); 310 1.1 ad return; 311 1.1 ad } 312 1.1 ad 313 1.1 ad mlx->mlx_sgls_paddr = mlx->mlx_dmamap->dm_segs[0].ds_addr; 314 1.1 ad memset(mlx->mlx_sgls, 0, size); 315 1.1 ad 316 1.1 ad /* 317 1.14 wiz * Allocate and initialize the CCBs. 318 1.1 ad */ 319 1.68 chs mc = malloc(sizeof(*mc) * MLX_MAX_QUEUECNT, M_DEVBUF, M_WAITOK); 320 1.1 ad mlx->mlx_ccbs = mc; 321 1.1 ad 322 1.1 ad for (i = 0; i < MLX_MAX_QUEUECNT; i++, mc++) { 323 1.1 ad mc->mc_ident = i; 324 1.1 ad rv = bus_dmamap_create(mlx->mlx_dmat, MLX_MAX_XFER, 325 1.9 ad MLX_MAX_SEGS, MLX_MAX_XFER, 0, 326 1.1 ad BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 327 1.1 ad &mc->mc_xfer_map); 328 1.1 ad if (rv != 0) 329 1.1 ad break; 330 1.1 ad mlx->mlx_nccbs++; 331 1.1 ad mlx_ccb_free(mlx, mc); 332 1.1 ad } 333 1.1 ad if (mlx->mlx_nccbs != MLX_MAX_QUEUECNT) 334 1.60 chs printf("%s: %d/%d CCBs usable\n", device_xname(mlx->mlx_dv), 335 1.1 ad mlx->mlx_nccbs, MLX_MAX_QUEUECNT); 336 1.1 ad 337 1.1 ad /* Disable interrupts before we start talking to the controller */ 338 1.1 ad (*mlx->mlx_intaction)(mlx, 0); 339 1.1 ad 340 1.8 ad /* If we've got a reset routine, then reset the controller now. */ 341 1.8 ad if (mlx->mlx_reset != NULL) { 342 1.63 msaitoh printf("%s: resetting controller...\n", 343 1.63 msaitoh device_xname(mlx->mlx_dv)); 344 1.8 ad if ((*mlx->mlx_reset)(mlx) != 0) { 345 1.60 chs aprint_error_dev(mlx->mlx_dv, "reset failed\n"); 346 1.8 ad return; 347 1.8 ad } 348 1.8 ad } 349 1.8 ad 350 1.32 perry /* 351 1.1 ad * Wait for the controller to come ready, handshaking with the 352 1.1 ad * firmware if required. This is typically only necessary on 353 1.1 ad * platforms where the controller BIOS does not run. 354 1.1 ad */ 355 1.1 ad hsmsg = 0; 356 1.1 ad 357 1.1 ad for (;;) { 358 1.1 ad hscode = (*mlx->mlx_fw_handshake)(mlx, &hserr, &hsparam1, 359 1.1 ad &hsparam2); 360 1.1 ad if (hscode == 0) { 361 1.1 ad if (hsmsg != 0) 362 1.1 ad printf("%s: initialization complete\n", 363 1.60 chs device_xname(mlx->mlx_dv)); 364 1.1 ad break; 365 1.1 ad } 366 1.1 ad 367 1.1 ad /* Report first time around... */ 368 1.1 ad if (hsmsg == 0) { 369 1.1 ad printf("%s: initializing (may take some time)...\n", 370 1.60 chs device_xname(mlx->mlx_dv)); 371 1.1 ad hsmsg = 1; 372 1.1 ad } 373 1.1 ad 374 1.1 ad /* Did we get a real message? */ 375 1.1 ad if (hscode == 2) { 376 1.1 ad hscode = mlx_fw_message(mlx, hserr, hsparam1, hsparam2); 377 1.1 ad 378 1.1 ad /* Fatal initialisation error? */ 379 1.1 ad if (hscode != 0) 380 1.1 ad return; 381 1.1 ad } 382 1.1 ad } 383 1.1 ad 384 1.1 ad /* 385 1.1 ad * Do quirk/feature related things. 386 1.1 ad */ 387 1.18 ad ci = &mlx->mlx_ci; 388 1.18 ad 389 1.18 ad if (ci->ci_iftype > 1) { 390 1.18 ad me2 = mlx_enquire(mlx, MLX_CMD_ENQUIRY2, 391 1.18 ad sizeof(struct mlx_enquiry2), NULL, 0); 392 1.18 ad if (me2 == NULL) { 393 1.60 chs aprint_error_dev(mlx->mlx_dv, "ENQUIRY2 failed\n"); 394 1.18 ad return; 395 1.18 ad } 396 1.18 ad 397 1.18 ad ci->ci_firmware_id[0] = me2->me_firmware_id[0]; 398 1.18 ad ci->ci_firmware_id[1] = me2->me_firmware_id[1]; 399 1.18 ad ci->ci_firmware_id[2] = me2->me_firmware_id[2]; 400 1.18 ad ci->ci_firmware_id[3] = me2->me_firmware_id[3]; 401 1.18 ad ci->ci_hardware_id = me2->me_hardware_id[0]; 402 1.18 ad ci->ci_mem_size = le32toh(me2->me_mem_size); 403 1.18 ad ci->ci_max_sg = le16toh(me2->me_max_sg); 404 1.18 ad ci->ci_max_commands = le16toh(me2->me_max_commands); 405 1.18 ad ci->ci_nchan = me2->me_actual_channels; 406 1.18 ad 407 1.18 ad free(me2, M_DEVBUF); 408 1.18 ad } 409 1.18 ad 410 1.18 ad if (ci->ci_iftype <= 2) { 411 1.1 ad /* 412 1.1 ad * These controllers may not report the firmware version in 413 1.18 ad * the ENQUIRY2 response, or may not even support it. 414 1.1 ad */ 415 1.1 ad meo = mlx_enquire(mlx, MLX_CMD_ENQUIRY_OLD, 416 1.1 ad sizeof(struct mlx_enquiry_old), NULL, 0); 417 1.1 ad if (meo == NULL) { 418 1.60 chs aprint_error_dev(mlx->mlx_dv, "ENQUIRY_OLD failed\n"); 419 1.1 ad return; 420 1.1 ad } 421 1.18 ad ci->ci_firmware_id[0] = meo->me_fwmajor; 422 1.18 ad ci->ci_firmware_id[1] = meo->me_fwminor; 423 1.18 ad ci->ci_firmware_id[2] = 0; 424 1.18 ad ci->ci_firmware_id[3] = '0'; 425 1.18 ad 426 1.18 ad if (ci->ci_iftype == 1) { 427 1.18 ad ci->ci_hardware_id = 0; /* XXX */ 428 1.18 ad ci->ci_mem_size = 0; /* XXX */ 429 1.18 ad ci->ci_max_sg = 17; /* XXX */ 430 1.18 ad ci->ci_max_commands = meo->me_max_commands; 431 1.18 ad } 432 1.18 ad 433 1.1 ad free(meo, M_DEVBUF); 434 1.1 ad } 435 1.1 ad 436 1.1 ad wantfwstr = NULL; 437 1.18 ad fwminor = ci->ci_firmware_id[1]; 438 1.1 ad 439 1.18 ad switch (ci->ci_firmware_id[0]) { 440 1.1 ad case 2: 441 1.18 ad if (ci->ci_iftype == 1) { 442 1.1 ad if (fwminor < 14) 443 1.1 ad wantfwstr = "2.14"; 444 1.1 ad } else if (fwminor < 42) 445 1.1 ad wantfwstr = "2.42"; 446 1.1 ad break; 447 1.1 ad 448 1.1 ad case 3: 449 1.1 ad if (fwminor < 51) 450 1.1 ad wantfwstr = "3.51"; 451 1.1 ad break; 452 1.1 ad 453 1.1 ad case 4: 454 1.1 ad if (fwminor < 6) 455 1.1 ad wantfwstr = "4.06"; 456 1.1 ad break; 457 1.1 ad 458 1.1 ad case 5: 459 1.1 ad if (fwminor < 7) 460 1.1 ad wantfwstr = "5.07"; 461 1.1 ad break; 462 1.1 ad } 463 1.1 ad 464 1.1 ad /* Print a little information about the controller. */ 465 1.1 ad mlx_describe(mlx); 466 1.1 ad 467 1.1 ad if (wantfwstr != NULL) { 468 1.1 ad printf("%s: WARNING: this f/w revision is not recommended\n", 469 1.60 chs device_xname(mlx->mlx_dv)); 470 1.1 ad printf("%s: WARNING: use revision %s or later\n", 471 1.60 chs device_xname(mlx->mlx_dv), wantfwstr); 472 1.1 ad } 473 1.1 ad 474 1.1 ad /* We don't (yet) know where the event log is up to. */ 475 1.1 ad mlx->mlx_currevent = -1; 476 1.1 ad 477 1.1 ad /* No user-requested background operation is in progress. */ 478 1.1 ad mlx->mlx_bg = 0; 479 1.1 ad mlx->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE; 480 1.1 ad 481 1.1 ad /* Set maximum number of queued commands for `regular' operations. */ 482 1.1 ad mlx->mlx_max_queuecnt = 483 1.67 riastrad uimin(ci->ci_max_commands, MLX_MAX_QUEUECNT) - 484 1.21 ad MLX_NCCBS_CONTROL; 485 1.1 ad #ifdef DIAGNOSTIC 486 1.21 ad if (mlx->mlx_max_queuecnt < MLX_NCCBS_CONTROL + MLX_MAX_DRIVES) 487 1.1 ad printf("%s: WARNING: few CCBs available\n", 488 1.60 chs device_xname(mlx->mlx_dv)); 489 1.18 ad if (ci->ci_max_sg < MLX_MAX_SEGS) { 490 1.63 msaitoh aprint_error_dev(mlx->mlx_dv, 491 1.63 msaitoh "oops, not enough S/G segments\n"); 492 1.1 ad return; 493 1.1 ad } 494 1.1 ad #endif 495 1.1 ad 496 1.52 ad /* Attach child devices and enable interrupts. */ 497 1.52 ad mlx_configure(mlx, 0); 498 1.52 ad (*mlx->mlx_intaction)(mlx, 1); 499 1.52 ad mlx->mlx_flags |= MLXF_INITOK; 500 1.52 ad 501 1.1 ad if (mlx_sdh == NULL) { 502 1.1 ad /* 503 1.1 ad * Set our `shutdownhook' before we start any device 504 1.1 ad * activity. 505 1.1 ad */ 506 1.1 ad mlx_sdh = shutdownhook_establish(mlx_shutdown, NULL); 507 1.1 ad 508 1.52 ad /* Create a status monitoring thread. */ 509 1.52 ad rv = kthread_create(PRI_NONE, 0, NULL, mlx_periodic_thread, 510 1.52 ad NULL, &mlx_periodic_lwp, "mlxtask"); 511 1.52 ad if (rv != 0) 512 1.64 msaitoh aprint_error_dev(mlx->mlx_dv, 513 1.64 msaitoh "mlx_init: unable to create thread (%d)\n", rv); 514 1.1 ad } 515 1.1 ad } 516 1.1 ad 517 1.1 ad /* 518 1.1 ad * Tell the world about the controller. 519 1.1 ad */ 520 1.1 ad static void 521 1.1 ad mlx_describe(struct mlx_softc *mlx) 522 1.1 ad { 523 1.18 ad struct mlx_cinfo *ci; 524 1.33 christos static char tbuf[80]; 525 1.1 ad const char *model; 526 1.1 ad int i; 527 1.1 ad 528 1.1 ad model = NULL; 529 1.18 ad ci = &mlx->mlx_ci; 530 1.1 ad 531 1.1 ad for (i = 0; i < sizeof(mlx_cname) / sizeof(mlx_cname[0]); i++) 532 1.18 ad if (ci->ci_hardware_id == mlx_cname[i].hwid) { 533 1.1 ad model = mlx_cname[i].name; 534 1.1 ad break; 535 1.1 ad } 536 1.1 ad 537 1.1 ad if (model == NULL) { 538 1.33 christos snprintf(tbuf, sizeof(tbuf), " model 0x%x", ci->ci_hardware_id); 539 1.33 christos model = tbuf; 540 1.1 ad } 541 1.1 ad 542 1.18 ad printf("%s: DAC%s, %d channel%s, firmware %d.%02d-%c-%02d", 543 1.60 chs device_xname(mlx->mlx_dv), model, ci->ci_nchan, 544 1.18 ad ci->ci_nchan > 1 ? "s" : "", 545 1.18 ad ci->ci_firmware_id[0], ci->ci_firmware_id[1], 546 1.18 ad ci->ci_firmware_id[3], ci->ci_firmware_id[2]); 547 1.18 ad if (ci->ci_mem_size != 0) 548 1.18 ad printf(", %dMB RAM", ci->ci_mem_size >> 20); 549 1.18 ad printf("\n"); 550 1.1 ad } 551 1.1 ad 552 1.1 ad /* 553 1.1 ad * Locate disk resources and attach children to them. 554 1.1 ad */ 555 1.65 pgoyette int 556 1.1 ad mlx_configure(struct mlx_softc *mlx, int waitok) 557 1.1 ad { 558 1.6 ad struct mlx_enquiry *me; 559 1.10 ad struct mlx_enquiry_old *meo; 560 1.1 ad struct mlx_enq_sys_drive *mes; 561 1.1 ad struct mlx_sysdrive *ms; 562 1.1 ad struct mlx_attach_args mlxa; 563 1.1 ad int i, nunits; 564 1.1 ad u_int size; 565 1.35 drochner int locs[MLXCF_NLOCS]; 566 1.1 ad 567 1.12 ad mlx->mlx_flags |= MLXF_RESCANNING; 568 1.12 ad 569 1.18 ad if (mlx->mlx_ci.ci_iftype <= 2) { 570 1.10 ad meo = mlx_enquire(mlx, MLX_CMD_ENQUIRY_OLD, 571 1.10 ad sizeof(struct mlx_enquiry_old), NULL, waitok); 572 1.10 ad if (meo == NULL) { 573 1.60 chs aprint_error_dev(mlx->mlx_dv, "ENQUIRY_OLD failed\n"); 574 1.12 ad goto out; 575 1.10 ad } 576 1.10 ad mlx->mlx_numsysdrives = meo->me_num_sys_drvs; 577 1.10 ad free(meo, M_DEVBUF); 578 1.10 ad } else { 579 1.10 ad me = mlx_enquire(mlx, MLX_CMD_ENQUIRY, 580 1.10 ad sizeof(struct mlx_enquiry), NULL, waitok); 581 1.10 ad if (me == NULL) { 582 1.60 chs aprint_error_dev(mlx->mlx_dv, "ENQUIRY failed\n"); 583 1.12 ad goto out; 584 1.10 ad } 585 1.10 ad mlx->mlx_numsysdrives = me->me_num_sys_drvs; 586 1.10 ad free(me, M_DEVBUF); 587 1.6 ad } 588 1.6 ad 589 1.1 ad mes = mlx_enquire(mlx, MLX_CMD_ENQSYSDRIVE, 590 1.1 ad sizeof(*mes) * MLX_MAX_DRIVES, NULL, waitok); 591 1.1 ad if (mes == NULL) { 592 1.60 chs aprint_error_dev(mlx->mlx_dv, "error fetching drive status\n"); 593 1.12 ad goto out; 594 1.1 ad } 595 1.1 ad 596 1.1 ad /* Allow 1 queued command per unit while re-configuring. */ 597 1.1 ad mlx_adjqparam(mlx, 1, 0); 598 1.1 ad 599 1.1 ad ms = &mlx->mlx_sysdrive[0]; 600 1.6 ad nunits = 0; 601 1.1 ad for (i = 0; i < MLX_MAX_DRIVES; i++, ms++) { 602 1.1 ad size = le32toh(mes[i].sd_size); 603 1.6 ad ms->ms_state = mes[i].sd_state; 604 1.6 ad 605 1.1 ad /* 606 1.1 ad * If an existing device has changed in some way (e.g. no 607 1.1 ad * longer present) then detach it. 608 1.1 ad */ 609 1.1 ad if (ms->ms_dv != NULL && (size != ms->ms_size || 610 1.1 ad (mes[i].sd_raidlevel & 0xf) != ms->ms_raidlevel)) 611 1.1 ad config_detach(ms->ms_dv, DETACH_FORCE); 612 1.1 ad 613 1.1 ad ms->ms_size = size; 614 1.1 ad ms->ms_raidlevel = mes[i].sd_raidlevel & 0xf; 615 1.1 ad ms->ms_state = mes[i].sd_state; 616 1.1 ad ms->ms_dv = NULL; 617 1.1 ad 618 1.10 ad if (i >= mlx->mlx_numsysdrives) 619 1.10 ad continue; 620 1.1 ad if (size == 0xffffffffU || size == 0) 621 1.1 ad continue; 622 1.1 ad 623 1.1 ad /* 624 1.1 ad * Attach a new device. 625 1.1 ad */ 626 1.1 ad mlxa.mlxa_unit = i; 627 1.30 drochner 628 1.35 drochner locs[MLXCF_UNIT] = i; 629 1.30 drochner 630 1.69 thorpej ms->ms_dv = config_found(mlx->mlx_dv, &mlxa, mlx_print, 631 1.70 thorpej CFARGS(.submatch = config_stdsubmatch, 632 1.70 thorpej .locators = locs)); 633 1.6 ad nunits += (ms->ms_dv != NULL); 634 1.1 ad } 635 1.1 ad 636 1.1 ad free(mes, M_DEVBUF); 637 1.6 ad 638 1.6 ad if (nunits != 0) 639 1.6 ad mlx_adjqparam(mlx, mlx->mlx_max_queuecnt / nunits, 640 1.6 ad mlx->mlx_max_queuecnt % nunits); 641 1.12 ad out: 642 1.12 ad mlx->mlx_flags &= ~MLXF_RESCANNING; 643 1.65 pgoyette 644 1.65 pgoyette return 0; 645 1.1 ad } 646 1.1 ad 647 1.1 ad /* 648 1.1 ad * Print autoconfiguration message for a sub-device. 649 1.1 ad */ 650 1.1 ad static int 651 1.1 ad mlx_print(void *aux, const char *pnp) 652 1.1 ad { 653 1.1 ad struct mlx_attach_args *mlxa; 654 1.1 ad 655 1.1 ad mlxa = (struct mlx_attach_args *)aux; 656 1.1 ad 657 1.1 ad if (pnp != NULL) 658 1.26 thorpej aprint_normal("block device at %s", pnp); 659 1.26 thorpej aprint_normal(" unit %d", mlxa->mlxa_unit); 660 1.1 ad return (UNCONF); 661 1.1 ad } 662 1.1 ad 663 1.1 ad /* 664 1.1 ad * Shut down all configured `mlx' devices. 665 1.1 ad */ 666 1.1 ad static void 667 1.48 christos mlx_shutdown(void *cookie) 668 1.1 ad { 669 1.1 ad struct mlx_softc *mlx; 670 1.1 ad int i; 671 1.1 ad 672 1.1 ad for (i = 0; i < mlx_cd.cd_ndevs; i++) 673 1.56 tsutsui if ((mlx = device_lookup_private(&mlx_cd, i)) != NULL) 674 1.1 ad mlx_flush(mlx, 0); 675 1.1 ad } 676 1.1 ad 677 1.1 ad /* 678 1.1 ad * Adjust queue parameters for all child devices. 679 1.1 ad */ 680 1.1 ad static void 681 1.1 ad mlx_adjqparam(struct mlx_softc *mlx, int mpu, int slop) 682 1.1 ad { 683 1.1 ad #if NLD > 0 684 1.1 ad struct ld_softc *ld; 685 1.1 ad int i; 686 1.1 ad 687 1.1 ad for (i = 0; i < ld_cd.cd_ndevs; i++) { 688 1.56 tsutsui if ((ld = device_lookup_private(&ld_cd, i)) == NULL) 689 1.1 ad continue; 690 1.60 chs if (device_parent(ld->sc_dv) != mlx->mlx_dv) 691 1.1 ad continue; 692 1.1 ad ldadjqparam(ld, mpu + (slop-- > 0)); 693 1.1 ad } 694 1.1 ad #endif 695 1.1 ad } 696 1.1 ad 697 1.1 ad /* 698 1.1 ad * Accept an open operation on the control device. 699 1.1 ad */ 700 1.1 ad int 701 1.48 christos mlxopen(dev_t dev, int flag, int mode, struct lwp *l) 702 1.1 ad { 703 1.1 ad struct mlx_softc *mlx; 704 1.1 ad 705 1.56 tsutsui if ((mlx = device_lookup_private(&mlx_cd, minor(dev))) == NULL) 706 1.1 ad return (ENXIO); 707 1.1 ad if ((mlx->mlx_flags & MLXF_INITOK) == 0) 708 1.1 ad return (ENXIO); 709 1.1 ad if ((mlx->mlx_flags & MLXF_OPEN) != 0) 710 1.1 ad return (EBUSY); 711 1.1 ad 712 1.1 ad mlx->mlx_flags |= MLXF_OPEN; 713 1.1 ad return (0); 714 1.1 ad } 715 1.1 ad 716 1.1 ad /* 717 1.1 ad * Accept the last close on the control device. 718 1.1 ad */ 719 1.1 ad int 720 1.64 msaitoh mlxclose(dev_t dev, int flag, int mode, struct lwp *l) 721 1.1 ad { 722 1.1 ad struct mlx_softc *mlx; 723 1.1 ad 724 1.56 tsutsui mlx = device_lookup_private(&mlx_cd, minor(dev)); 725 1.1 ad mlx->mlx_flags &= ~MLXF_OPEN; 726 1.1 ad return (0); 727 1.1 ad } 728 1.1 ad 729 1.1 ad /* 730 1.1 ad * Handle control operations. 731 1.1 ad */ 732 1.1 ad int 733 1.64 msaitoh mlxioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 734 1.1 ad { 735 1.1 ad struct mlx_softc *mlx; 736 1.1 ad struct mlx_rebuild_request *rb; 737 1.1 ad struct mlx_rebuild_status *rs; 738 1.1 ad struct mlx_pause *mp; 739 1.1 ad struct mlx_sysdrive *ms; 740 1.1 ad int i, rv, *arg, result; 741 1.1 ad 742 1.56 tsutsui mlx = device_lookup_private(&mlx_cd, minor(dev)); 743 1.1 ad 744 1.1 ad rb = (struct mlx_rebuild_request *)data; 745 1.1 ad rs = (struct mlx_rebuild_status *)data; 746 1.1 ad arg = (int *)data; 747 1.1 ad rv = 0; 748 1.1 ad 749 1.1 ad switch (cmd) { 750 1.1 ad case MLX_RESCAN_DRIVES: 751 1.1 ad /* 752 1.1 ad * Scan the controller to see whether new drives have 753 1.1 ad * appeared, or old ones disappeared. 754 1.1 ad */ 755 1.1 ad mlx_configure(mlx, 1); 756 1.1 ad return (0); 757 1.1 ad 758 1.1 ad case MLX_PAUSE_CHANNEL: 759 1.1 ad /* 760 1.1 ad * Pause one or more SCSI channels for a period of time, to 761 1.1 ad * assist in the process of hot-swapping devices. 762 1.1 ad * 763 1.1 ad * Note that at least the 3.51 firmware on the DAC960PL 764 1.1 ad * doesn't seem to do this right. 765 1.1 ad */ 766 1.1 ad if ((mlx->mlx_flags & MLXF_PAUSEWORKS) == 0) 767 1.1 ad return (EOPNOTSUPP); 768 1.1 ad 769 1.1 ad mp = (struct mlx_pause *)data; 770 1.1 ad 771 1.1 ad if ((mp->mp_which == MLX_PAUSE_CANCEL) && 772 1.1 ad (mlx->mlx_pause.mp_when != 0)) { 773 1.1 ad /* Cancel a pending pause operation. */ 774 1.1 ad mlx->mlx_pause.mp_which = 0; 775 1.1 ad break; 776 1.1 ad } 777 1.1 ad 778 1.1 ad /* Fix for legal channels. */ 779 1.18 ad mp->mp_which &= ((1 << mlx->mlx_ci.ci_nchan) -1); 780 1.1 ad 781 1.1 ad /* Check time values. */ 782 1.1 ad if (mp->mp_when < 0 || mp->mp_when > 3600 || 783 1.1 ad mp->mp_howlong < 1 || mp->mp_howlong > (0xf * 30)) { 784 1.1 ad rv = EINVAL; 785 1.1 ad break; 786 1.1 ad } 787 1.1 ad 788 1.1 ad /* Check for a pause currently running. */ 789 1.1 ad if ((mlx->mlx_pause.mp_which != 0) && 790 1.1 ad (mlx->mlx_pause.mp_when == 0)) { 791 1.1 ad rv = EBUSY; 792 1.1 ad break; 793 1.1 ad } 794 1.1 ad 795 1.1 ad /* Looks ok, go with it. */ 796 1.1 ad mlx->mlx_pause.mp_which = mp->mp_which; 797 1.43 kardel mlx->mlx_pause.mp_when = time_second + mp->mp_when; 798 1.1 ad mlx->mlx_pause.mp_howlong = 799 1.1 ad mlx->mlx_pause.mp_when + mp->mp_howlong; 800 1.1 ad 801 1.1 ad return (0); 802 1.1 ad 803 1.1 ad case MLX_COMMAND: 804 1.49 elad rv = kauth_authorize_device_passthru(l->l_cred, dev, 805 1.49 elad KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL, data); 806 1.47 elad if (rv) 807 1.47 elad return (rv); 808 1.44 christos 809 1.1 ad /* 810 1.1 ad * Accept a command passthrough-style. 811 1.1 ad */ 812 1.1 ad return (mlx_user_command(mlx, (struct mlx_usercommand *)data)); 813 1.1 ad 814 1.1 ad case MLX_REBUILDASYNC: 815 1.1 ad /* 816 1.1 ad * Start a rebuild on a given SCSI disk 817 1.1 ad */ 818 1.1 ad if (mlx->mlx_bg != 0) { 819 1.1 ad rb->rr_status = 0x0106; 820 1.1 ad rv = EBUSY; 821 1.1 ad break; 822 1.1 ad } 823 1.1 ad 824 1.1 ad rb->rr_status = mlx_rebuild(mlx, rb->rr_channel, rb->rr_target); 825 1.1 ad switch (rb->rr_status) { 826 1.1 ad case 0: 827 1.1 ad rv = 0; 828 1.1 ad break; 829 1.1 ad case 0x10000: 830 1.1 ad rv = ENOMEM; /* Couldn't set up the command. */ 831 1.1 ad break; 832 1.32 perry case 0x0002: 833 1.1 ad rv = EBUSY; 834 1.1 ad break; 835 1.1 ad case 0x0104: 836 1.1 ad rv = EIO; 837 1.1 ad break; 838 1.1 ad case 0x0105: 839 1.1 ad rv = ERANGE; 840 1.1 ad break; 841 1.1 ad case 0x0106: 842 1.1 ad rv = EBUSY; 843 1.1 ad break; 844 1.1 ad default: 845 1.1 ad rv = EINVAL; 846 1.1 ad break; 847 1.1 ad } 848 1.1 ad 849 1.1 ad if (rv == 0) 850 1.1 ad mlx->mlx_bg = MLX_BG_REBUILD; 851 1.1 ad 852 1.1 ad return (0); 853 1.1 ad 854 1.1 ad case MLX_REBUILDSTAT: 855 1.1 ad /* 856 1.1 ad * Get the status of the current rebuild or consistency check. 857 1.1 ad */ 858 1.1 ad *rs = mlx->mlx_rebuildstat; 859 1.1 ad return (0); 860 1.1 ad 861 1.1 ad case MLX_GET_SYSDRIVE: 862 1.1 ad /* 863 1.1 ad * Return the system drive number matching the `ld' device 864 1.1 ad * unit in (arg), if it happens to belong to us. 865 1.1 ad */ 866 1.1 ad for (i = 0; i < MLX_MAX_DRIVES; i++) { 867 1.1 ad ms = &mlx->mlx_sysdrive[i]; 868 1.1 ad if (ms->ms_dv != NULL) 869 1.54 cegger if (device_xname(ms->ms_dv)[2] == '0' + *arg) { 870 1.16 ad *arg = i; 871 1.16 ad return (0); 872 1.16 ad } 873 1.1 ad } 874 1.1 ad return (ENOENT); 875 1.19 ad 876 1.19 ad case MLX_GET_CINFO: 877 1.19 ad /* 878 1.19 ad * Return controller info. 879 1.19 ad */ 880 1.19 ad memcpy(arg, &mlx->mlx_ci, sizeof(mlx->mlx_ci)); 881 1.19 ad return (0); 882 1.1 ad } 883 1.1 ad 884 1.1 ad switch (cmd) { 885 1.1 ad case MLXD_DETACH: 886 1.1 ad case MLXD_STATUS: 887 1.1 ad case MLXD_CHECKASYNC: 888 1.1 ad if ((u_int)*arg >= MLX_MAX_DRIVES) 889 1.1 ad return (EINVAL); 890 1.1 ad ms = &mlx->mlx_sysdrive[*arg]; 891 1.1 ad if (*arg > MLX_MAX_DRIVES || ms->ms_dv == NULL) 892 1.1 ad return (ENOENT); 893 1.1 ad break; 894 1.1 ad 895 1.1 ad default: 896 1.1 ad return (ENOTTY); 897 1.1 ad } 898 1.1 ad 899 1.1 ad switch (cmd) { 900 1.1 ad case MLXD_DETACH: 901 1.1 ad /* 902 1.32 perry * Disconnect from the specified drive; it may be about to go 903 1.1 ad * away. 904 1.1 ad */ 905 1.1 ad return (config_detach(ms->ms_dv, 0)); 906 1.1 ad 907 1.1 ad case MLXD_STATUS: 908 1.1 ad /* 909 1.1 ad * Return the current status of this drive. 910 1.1 ad */ 911 1.1 ad *arg = ms->ms_state; 912 1.1 ad return (0); 913 1.1 ad 914 1.1 ad case MLXD_CHECKASYNC: 915 1.1 ad /* 916 1.1 ad * Start a background consistency check on this drive. 917 1.1 ad */ 918 1.1 ad if (mlx->mlx_bg != 0) { 919 1.1 ad *arg = 0x0106; 920 1.1 ad return (EBUSY); 921 1.1 ad } 922 1.1 ad 923 1.1 ad switch (result = mlx_check(mlx, *arg)) { 924 1.1 ad case 0: 925 1.1 ad rv = 0; 926 1.1 ad break; 927 1.1 ad case 0x10000: 928 1.1 ad rv = ENOMEM; /* Couldn't set up the command. */ 929 1.1 ad break; 930 1.32 perry case 0x0002: 931 1.1 ad rv = EIO; 932 1.1 ad break; 933 1.1 ad case 0x0105: 934 1.1 ad rv = ERANGE; 935 1.1 ad break; 936 1.1 ad case 0x0106: 937 1.1 ad rv = EBUSY; 938 1.1 ad break; 939 1.1 ad default: 940 1.1 ad rv = EINVAL; 941 1.1 ad break; 942 1.1 ad } 943 1.1 ad 944 1.1 ad if (rv == 0) 945 1.1 ad mlx->mlx_bg = MLX_BG_CHECK; 946 1.1 ad *arg = result; 947 1.1 ad return (rv); 948 1.1 ad } 949 1.1 ad 950 1.1 ad return (ENOTTY); /* XXX shut up gcc */ 951 1.1 ad } 952 1.1 ad 953 1.1 ad static void 954 1.48 christos mlx_periodic_thread(void *cookie) 955 1.1 ad { 956 1.1 ad struct mlx_softc *mlx; 957 1.1 ad int i; 958 1.1 ad 959 1.1 ad for (;;) { 960 1.1 ad for (i = 0; i < mlx_cd.cd_ndevs; i++) 961 1.56 tsutsui if ((mlx = device_lookup_private(&mlx_cd, i)) != NULL) 962 1.18 ad if (mlx->mlx_ci.ci_iftype > 1) 963 1.18 ad mlx_periodic(mlx); 964 1.1 ad 965 1.21 ad tsleep(mlx_periodic_thread, PWAIT, "mlxzzz", hz * 2); 966 1.1 ad } 967 1.1 ad } 968 1.1 ad 969 1.1 ad static void 970 1.1 ad mlx_periodic(struct mlx_softc *mlx) 971 1.1 ad { 972 1.1 ad struct mlx_ccb *mc, *nmc; 973 1.1 ad int etype, s; 974 1.1 ad 975 1.1 ad if ((mlx->mlx_pause.mp_which != 0) && 976 1.1 ad (mlx->mlx_pause.mp_when > 0) && 977 1.43 kardel (time_second >= mlx->mlx_pause.mp_when)) { 978 1.1 ad /* 979 1.1 ad * Start bus pause. 980 1.1 ad */ 981 1.1 ad mlx_pause_action(mlx); 982 1.1 ad mlx->mlx_pause.mp_when = 0; 983 1.1 ad } else if ((mlx->mlx_pause.mp_which != 0) && 984 1.1 ad (mlx->mlx_pause.mp_when == 0)) { 985 1.1 ad /* 986 1.1 ad * Stop pause if required. 987 1.1 ad */ 988 1.43 kardel if (time_second >= mlx->mlx_pause.mp_howlong) { 989 1.1 ad mlx_pause_action(mlx); 990 1.1 ad mlx->mlx_pause.mp_which = 0; 991 1.1 ad } 992 1.43 kardel } else if (time_second > (mlx->mlx_lastpoll + 10)) { 993 1.32 perry /* 994 1.1 ad * Run normal periodic activities... 995 1.1 ad */ 996 1.43 kardel mlx->mlx_lastpoll = time_second; 997 1.1 ad 998 1.32 perry /* 999 1.1 ad * Check controller status. 1000 1.1 ad */ 1001 1.1 ad if ((mlx->mlx_flags & MLXF_PERIODIC_CTLR) == 0) { 1002 1.1 ad mlx->mlx_flags |= MLXF_PERIODIC_CTLR; 1003 1.1 ad 1004 1.18 ad if (mlx->mlx_ci.ci_iftype <= 2) 1005 1.1 ad etype = MLX_CMD_ENQUIRY_OLD; 1006 1.1 ad else 1007 1.1 ad etype = MLX_CMD_ENQUIRY; 1008 1.1 ad 1009 1.67 riastrad mlx_enquire(mlx, etype, uimax(sizeof(struct mlx_enquiry), 1010 1.1 ad sizeof(struct mlx_enquiry_old)), 1011 1.1 ad mlx_periodic_enquiry, 1); 1012 1.1 ad } 1013 1.1 ad 1014 1.1 ad /* 1015 1.1 ad * Check system drive status. 1016 1.1 ad */ 1017 1.1 ad if ((mlx->mlx_flags & MLXF_PERIODIC_DRIVE) == 0) { 1018 1.1 ad mlx->mlx_flags |= MLXF_PERIODIC_DRIVE; 1019 1.1 ad mlx_enquire(mlx, MLX_CMD_ENQSYSDRIVE, 1020 1.1 ad sizeof(struct mlx_enq_sys_drive) * MLX_MAX_DRIVES, 1021 1.1 ad mlx_periodic_enquiry, 1); 1022 1.1 ad } 1023 1.1 ad } 1024 1.1 ad 1025 1.1 ad /* 1026 1.1 ad * Get drive rebuild/check status. 1027 1.1 ad */ 1028 1.1 ad if ((mlx->mlx_flags & MLXF_PERIODIC_REBUILD) == 0) { 1029 1.1 ad mlx->mlx_flags |= MLXF_PERIODIC_REBUILD; 1030 1.1 ad mlx_enquire(mlx, MLX_CMD_REBUILDSTAT, 1031 1.1 ad sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild, 1); 1032 1.1 ad } 1033 1.1 ad 1034 1.1 ad /* 1035 1.1 ad * Time-out busy CCBs. 1036 1.1 ad */ 1037 1.1 ad s = splbio(); 1038 1.1 ad for (mc = TAILQ_FIRST(&mlx->mlx_ccb_worklist); mc != NULL; mc = nmc) { 1039 1.1 ad nmc = TAILQ_NEXT(mc, mc_chain.tailq); 1040 1.43 kardel if (mc->mc_expiry > time_second) { 1041 1.1 ad /* 1042 1.1 ad * The remaining CCBs will expire after this one, so 1043 1.1 ad * there's no point in going further. 1044 1.1 ad */ 1045 1.1 ad break; 1046 1.1 ad } 1047 1.32 perry TAILQ_REMOVE(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq); 1048 1.1 ad mc->mc_status = MLX_STATUS_LOST; 1049 1.1 ad if (mc->mc_mx.mx_handler != NULL) 1050 1.1 ad (*mc->mc_mx.mx_handler)(mc); 1051 1.1 ad else if ((mc->mc_flags & MC_WAITING) != 0) 1052 1.1 ad wakeup(mc); 1053 1.1 ad } 1054 1.1 ad splx(s); 1055 1.1 ad } 1056 1.1 ad 1057 1.1 ad /* 1058 1.1 ad * Handle the result of an ENQUIRY command instigated by periodic status 1059 1.1 ad * polling. 1060 1.1 ad */ 1061 1.1 ad static void 1062 1.1 ad mlx_periodic_enquiry(struct mlx_ccb *mc) 1063 1.1 ad { 1064 1.1 ad struct mlx_softc *mlx; 1065 1.1 ad struct mlx_enquiry *me; 1066 1.1 ad struct mlx_enquiry_old *meo; 1067 1.1 ad struct mlx_enq_sys_drive *mes; 1068 1.1 ad struct mlx_sysdrive *dr; 1069 1.1 ad const char *statestr; 1070 1.1 ad int i, j; 1071 1.1 ad u_int lsn; 1072 1.1 ad 1073 1.60 chs mlx = device_private(mc->mc_mx.mx_dv); 1074 1.34 mhitch mlx_ccb_unmap(mlx, mc); 1075 1.1 ad 1076 1.1 ad /* 1077 1.1 ad * Command completed OK? 1078 1.1 ad */ 1079 1.1 ad if (mc->mc_status != 0) { 1080 1.60 chs aprint_error_dev(mlx->mlx_dv, "periodic enquiry failed - %s\n", 1081 1.54 cegger mlx_ccb_diagnose(mc)); 1082 1.1 ad goto out; 1083 1.1 ad } 1084 1.1 ad 1085 1.1 ad /* 1086 1.1 ad * Respond to command. 1087 1.1 ad */ 1088 1.1 ad switch (mc->mc_mbox[0]) { 1089 1.1 ad case MLX_CMD_ENQUIRY_OLD: 1090 1.1 ad /* 1091 1.1 ad * This is currently a bit fruitless, as we don't know how 1092 1.1 ad * to extract the eventlog pointer yet. 1093 1.1 ad */ 1094 1.1 ad me = (struct mlx_enquiry *)mc->mc_mx.mx_context; 1095 1.1 ad meo = (struct mlx_enquiry_old *)mc->mc_mx.mx_context; 1096 1.1 ad 1097 1.1 ad /* Convert data in-place to new format */ 1098 1.1 ad i = sizeof(me->me_dead) / sizeof(me->me_dead[0]); 1099 1.1 ad while (--i >= 0) { 1100 1.1 ad me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan; 1101 1.1 ad me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ; 1102 1.1 ad } 1103 1.1 ad 1104 1.1 ad me->me_misc_flags = 0; 1105 1.1 ad me->me_rebuild_count = meo->me_rebuild_count; 1106 1.1 ad me->me_dead_count = meo->me_dead_count; 1107 1.1 ad me->me_critical_sd_count = meo->me_critical_sd_count; 1108 1.1 ad me->me_event_log_seq_num = 0; 1109 1.1 ad me->me_offline_sd_count = meo->me_offline_sd_count; 1110 1.1 ad me->me_max_commands = meo->me_max_commands; 1111 1.1 ad me->me_rebuild_flag = meo->me_rebuild_flag; 1112 1.1 ad me->me_fwmajor = meo->me_fwmajor; 1113 1.1 ad me->me_fwminor = meo->me_fwminor; 1114 1.1 ad me->me_status_flags = meo->me_status_flags; 1115 1.1 ad me->me_flash_age = meo->me_flash_age; 1116 1.1 ad 1117 1.1 ad i = sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0]); 1118 1.1 ad j = sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0]); 1119 1.1 ad 1120 1.1 ad while (--i >= 0) { 1121 1.1 ad if (i >= j) 1122 1.1 ad me->me_drvsize[i] = 0; 1123 1.1 ad else 1124 1.1 ad me->me_drvsize[i] = meo->me_drvsize[i]; 1125 1.1 ad } 1126 1.1 ad 1127 1.1 ad me->me_num_sys_drvs = meo->me_num_sys_drvs; 1128 1.1 ad 1129 1.1 ad /* FALLTHROUGH */ 1130 1.1 ad 1131 1.1 ad case MLX_CMD_ENQUIRY: 1132 1.1 ad /* 1133 1.1 ad * Generic controller status update. We could do more with 1134 1.1 ad * this than just checking the event log. 1135 1.1 ad */ 1136 1.1 ad me = (struct mlx_enquiry *)mc->mc_mx.mx_context; 1137 1.1 ad lsn = le16toh(me->me_event_log_seq_num); 1138 1.1 ad 1139 1.1 ad if (mlx->mlx_currevent == -1) { 1140 1.1 ad /* Initialise our view of the event log. */ 1141 1.1 ad mlx->mlx_currevent = lsn; 1142 1.1 ad mlx->mlx_lastevent = lsn; 1143 1.1 ad } else if (lsn != mlx->mlx_lastevent && 1144 1.1 ad (mlx->mlx_flags & MLXF_EVENTLOG_BUSY) == 0) { 1145 1.1 ad /* Record where current events are up to */ 1146 1.1 ad mlx->mlx_currevent = lsn; 1147 1.1 ad 1148 1.1 ad /* Mark the event log as busy. */ 1149 1.1 ad mlx->mlx_flags |= MLXF_EVENTLOG_BUSY; 1150 1.1 ad 1151 1.1 ad /* Drain new eventlog entries. */ 1152 1.1 ad mlx_periodic_eventlog_poll(mlx); 1153 1.1 ad } 1154 1.1 ad break; 1155 1.1 ad 1156 1.1 ad case MLX_CMD_ENQSYSDRIVE: 1157 1.12 ad /* 1158 1.32 perry * Perform drive status comparison to see if something 1159 1.12 ad * has failed. Don't perform the comparison if we're 1160 1.12 ad * reconfiguring, since the system drive table will be 1161 1.12 ad * changing. 1162 1.12 ad */ 1163 1.12 ad if ((mlx->mlx_flags & MLXF_RESCANNING) != 0) 1164 1.12 ad break; 1165 1.12 ad 1166 1.1 ad mes = (struct mlx_enq_sys_drive *)mc->mc_mx.mx_context; 1167 1.1 ad dr = &mlx->mlx_sysdrive[0]; 1168 1.1 ad 1169 1.58 mhitch for (i = 0; i < mlx->mlx_numsysdrives; i++, dr++) { 1170 1.1 ad /* Has state been changed by controller? */ 1171 1.1 ad if (dr->ms_state != mes[i].sd_state) { 1172 1.1 ad switch (mes[i].sd_state) { 1173 1.1 ad case MLX_SYSD_OFFLINE: 1174 1.1 ad statestr = "offline"; 1175 1.1 ad break; 1176 1.1 ad 1177 1.1 ad case MLX_SYSD_ONLINE: 1178 1.1 ad statestr = "online"; 1179 1.1 ad break; 1180 1.1 ad 1181 1.1 ad case MLX_SYSD_CRITICAL: 1182 1.1 ad statestr = "critical"; 1183 1.10 ad break; 1184 1.32 perry 1185 1.10 ad default: 1186 1.10 ad statestr = "unknown"; 1187 1.1 ad break; 1188 1.1 ad } 1189 1.1 ad 1190 1.63 msaitoh printf("%s: unit %d %s\n", 1191 1.63 msaitoh device_xname(mlx->mlx_dv), i, statestr); 1192 1.1 ad 1193 1.1 ad /* Save new state. */ 1194 1.1 ad dr->ms_state = mes[i].sd_state; 1195 1.1 ad } 1196 1.1 ad } 1197 1.1 ad break; 1198 1.1 ad 1199 1.1 ad #ifdef DIAGNOSTIC 1200 1.1 ad default: 1201 1.1 ad printf("%s: mlx_periodic_enquiry: eh?\n", 1202 1.60 chs device_xname(mlx->mlx_dv)); 1203 1.1 ad break; 1204 1.1 ad #endif 1205 1.1 ad } 1206 1.1 ad 1207 1.3 ad out: 1208 1.1 ad if (mc->mc_mbox[0] == MLX_CMD_ENQSYSDRIVE) 1209 1.1 ad mlx->mlx_flags &= ~MLXF_PERIODIC_DRIVE; 1210 1.1 ad else 1211 1.1 ad mlx->mlx_flags &= ~MLXF_PERIODIC_CTLR; 1212 1.1 ad 1213 1.1 ad free(mc->mc_mx.mx_context, M_DEVBUF); 1214 1.1 ad mlx_ccb_free(mlx, mc); 1215 1.1 ad } 1216 1.1 ad 1217 1.1 ad /* 1218 1.1 ad * Instigate a poll for one event log message on (mlx). We only poll for 1219 1.1 ad * one message at a time, to keep our command usage down. 1220 1.1 ad */ 1221 1.1 ad static void 1222 1.1 ad mlx_periodic_eventlog_poll(struct mlx_softc *mlx) 1223 1.1 ad { 1224 1.1 ad struct mlx_ccb *mc; 1225 1.1 ad void *result; 1226 1.1 ad int rv; 1227 1.1 ad 1228 1.1 ad result = NULL; 1229 1.1 ad 1230 1.1 ad if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0) 1231 1.1 ad goto out; 1232 1.1 ad 1233 1.1 ad if ((result = malloc(1024, M_DEVBUF, M_WAITOK)) == NULL) { 1234 1.1 ad rv = ENOMEM; 1235 1.1 ad goto out; 1236 1.1 ad } 1237 1.1 ad if ((rv = mlx_ccb_map(mlx, mc, result, 1024, MC_XFER_IN)) != 0) 1238 1.1 ad goto out; 1239 1.6 ad if (mc->mc_nsgent != 1) { 1240 1.6 ad mlx_ccb_unmap(mlx, mc); 1241 1.6 ad printf("mlx_periodic_eventlog_poll: too many segs\n"); 1242 1.6 ad goto out; 1243 1.6 ad } 1244 1.1 ad 1245 1.1 ad /* Build the command to get one log entry. */ 1246 1.1 ad mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1, 1247 1.1 ad mlx->mlx_lastevent, 0, 0, mc->mc_xfer_phys, 0); 1248 1.1 ad 1249 1.1 ad mc->mc_mx.mx_handler = mlx_periodic_eventlog_respond; 1250 1.60 chs mc->mc_mx.mx_dv = mlx->mlx_dv; 1251 1.1 ad mc->mc_mx.mx_context = result; 1252 1.1 ad 1253 1.1 ad /* Start the command. */ 1254 1.1 ad mlx_ccb_enqueue(mlx, mc); 1255 1.1 ad 1256 1.3 ad out: 1257 1.1 ad if (rv != 0) { 1258 1.1 ad if (mc != NULL) 1259 1.1 ad mlx_ccb_free(mlx, mc); 1260 1.1 ad if (result != NULL) 1261 1.1 ad free(result, M_DEVBUF); 1262 1.1 ad } 1263 1.1 ad } 1264 1.1 ad 1265 1.1 ad /* 1266 1.1 ad * Handle the result of polling for a log message, generate diagnostic 1267 1.1 ad * output. If this wasn't the last message waiting for us, we'll go collect 1268 1.1 ad * another. 1269 1.1 ad */ 1270 1.1 ad static void 1271 1.1 ad mlx_periodic_eventlog_respond(struct mlx_ccb *mc) 1272 1.1 ad { 1273 1.1 ad struct mlx_softc *mlx; 1274 1.1 ad struct mlx_eventlog_entry *el; 1275 1.1 ad const char *reason; 1276 1.1 ad u_int8_t sensekey, chan, targ; 1277 1.1 ad 1278 1.60 chs mlx = device_private(mc->mc_mx.mx_dv); 1279 1.1 ad el = mc->mc_mx.mx_context; 1280 1.1 ad mlx_ccb_unmap(mlx, mc); 1281 1.1 ad 1282 1.1 ad mlx->mlx_lastevent++; 1283 1.1 ad 1284 1.1 ad if (mc->mc_status == 0) { 1285 1.1 ad switch (el->el_type) { 1286 1.1 ad case MLX_LOGMSG_SENSE: /* sense data */ 1287 1.1 ad sensekey = el->el_sense & 0x0f; 1288 1.1 ad chan = (el->el_target >> 4) & 0x0f; 1289 1.1 ad targ = el->el_target & 0x0f; 1290 1.1 ad 1291 1.1 ad /* 1292 1.1 ad * This is the only sort of message we understand at 1293 1.1 ad * the moment. The tests here are probably 1294 1.1 ad * incomplete. 1295 1.1 ad */ 1296 1.1 ad 1297 1.1 ad /* 1298 1.1 ad * Mylex vendor-specific message indicating a drive 1299 1.1 ad * was killed? 1300 1.1 ad */ 1301 1.1 ad if (sensekey == 9 && el->el_asc == 0x80) { 1302 1.1 ad if (el->el_asq < sizeof(mlx_sense_msgs) / 1303 1.1 ad sizeof(mlx_sense_msgs[0])) 1304 1.1 ad reason = mlx_sense_msgs[el->el_asq]; 1305 1.1 ad else 1306 1.1 ad reason = "for unknown reason"; 1307 1.1 ad 1308 1.1 ad printf("%s: physical drive %d:%d killed %s\n", 1309 1.63 msaitoh device_xname(mlx->mlx_dv), chan, targ, 1310 1.63 msaitoh reason); 1311 1.1 ad } 1312 1.1 ad 1313 1.1 ad /* 1314 1.1 ad * SCSI drive was reset? 1315 1.1 ad */ 1316 1.1 ad if (sensekey == 6 && el->el_asc == 0x29) 1317 1.1 ad printf("%s: physical drive %d:%d reset\n", 1318 1.60 chs device_xname(mlx->mlx_dv), chan, targ); 1319 1.1 ad 1320 1.1 ad /* 1321 1.1 ad * SCSI drive error? 1322 1.1 ad */ 1323 1.1 ad if (!(sensekey == 0 || 1324 1.1 ad (sensekey == 2 && 1325 1.1 ad el->el_asc == 0x04 && 1326 1.1 ad (el->el_asq == 0x01 || el->el_asq == 0x02)))) { 1327 1.1 ad printf("%s: physical drive %d:%d error log: " 1328 1.1 ad "sense = %d asc = %x asq = %x\n", 1329 1.63 msaitoh device_xname(mlx->mlx_dv), chan, targ, 1330 1.63 msaitoh sensekey, el->el_asc, el->el_asq); 1331 1.1 ad printf("%s: info = %d:%d:%d:%d " 1332 1.12 ad " csi = %d:%d:%d:%d\n", 1333 1.60 chs device_xname(mlx->mlx_dv), 1334 1.12 ad el->el_information[0], 1335 1.12 ad el->el_information[1], 1336 1.12 ad el->el_information[2], 1337 1.12 ad el->el_information[3], 1338 1.1 ad el->el_csi[0], el->el_csi[1], 1339 1.1 ad el->el_csi[2], el->el_csi[3]); 1340 1.1 ad } 1341 1.1 ad 1342 1.1 ad break; 1343 1.32 perry 1344 1.1 ad default: 1345 1.63 msaitoh aprint_error_dev(mlx->mlx_dv, 1346 1.63 msaitoh "unknown log message type 0x%x\n", el->el_type); 1347 1.1 ad break; 1348 1.1 ad } 1349 1.1 ad } else { 1350 1.63 msaitoh aprint_error_dev(mlx->mlx_dv, 1351 1.63 msaitoh "error reading message log - %s\n", mlx_ccb_diagnose(mc)); 1352 1.1 ad 1353 1.1 ad /* 1354 1.1 ad * Give up on all the outstanding messages, as we may have 1355 1.1 ad * come unsynched. 1356 1.1 ad */ 1357 1.1 ad mlx->mlx_lastevent = mlx->mlx_currevent; 1358 1.1 ad } 1359 1.1 ad 1360 1.1 ad free(mc->mc_mx.mx_context, M_DEVBUF); 1361 1.1 ad mlx_ccb_free(mlx, mc); 1362 1.1 ad 1363 1.1 ad /* 1364 1.1 ad * Is there another message to obtain? 1365 1.1 ad */ 1366 1.1 ad if (mlx->mlx_lastevent != mlx->mlx_currevent) 1367 1.1 ad mlx_periodic_eventlog_poll(mlx); 1368 1.1 ad else 1369 1.1 ad mlx->mlx_flags &= ~MLXF_EVENTLOG_BUSY; 1370 1.1 ad } 1371 1.1 ad 1372 1.1 ad /* 1373 1.1 ad * Handle check/rebuild operations in progress. 1374 1.1 ad */ 1375 1.1 ad static void 1376 1.1 ad mlx_periodic_rebuild(struct mlx_ccb *mc) 1377 1.1 ad { 1378 1.1 ad struct mlx_softc *mlx; 1379 1.1 ad const char *opstr; 1380 1.1 ad struct mlx_rebuild_status *mr; 1381 1.1 ad 1382 1.60 chs mlx = device_private(mc->mc_mx.mx_dv); 1383 1.1 ad mr = mc->mc_mx.mx_context; 1384 1.1 ad mlx_ccb_unmap(mlx, mc); 1385 1.1 ad 1386 1.1 ad switch (mc->mc_status) { 1387 1.1 ad case 0: 1388 1.1 ad /* 1389 1.1 ad * Operation running, update stats. 1390 1.1 ad */ 1391 1.1 ad mlx->mlx_rebuildstat = *mr; 1392 1.1 ad 1393 1.1 ad /* Spontaneous rebuild/check? */ 1394 1.1 ad if (mlx->mlx_bg == 0) { 1395 1.1 ad mlx->mlx_bg = MLX_BG_SPONTANEOUS; 1396 1.1 ad printf("%s: background check/rebuild started\n", 1397 1.60 chs device_xname(mlx->mlx_dv)); 1398 1.1 ad } 1399 1.1 ad break; 1400 1.1 ad 1401 1.1 ad case 0x0105: 1402 1.1 ad /* 1403 1.1 ad * Nothing running, finalise stats and report. 1404 1.1 ad */ 1405 1.1 ad switch (mlx->mlx_bg) { 1406 1.1 ad case MLX_BG_CHECK: 1407 1.1 ad /* XXX Print drive? */ 1408 1.1 ad opstr = "consistency check"; 1409 1.1 ad break; 1410 1.1 ad 1411 1.1 ad case MLX_BG_REBUILD: 1412 1.1 ad /* XXX Print channel:target? */ 1413 1.1 ad opstr = "drive rebuild"; 1414 1.1 ad break; 1415 1.1 ad 1416 1.1 ad case MLX_BG_SPONTANEOUS: 1417 1.1 ad default: 1418 1.1 ad /* 1419 1.1 ad * If we have previously been non-idle, report the 1420 1.1 ad * transition 1421 1.1 ad */ 1422 1.1 ad if (mlx->mlx_rebuildstat.rs_code != 1423 1.1 ad MLX_REBUILDSTAT_IDLE) 1424 1.1 ad opstr = "background check/rebuild"; 1425 1.1 ad else 1426 1.1 ad opstr = NULL; 1427 1.1 ad } 1428 1.1 ad 1429 1.1 ad if (opstr != NULL) 1430 1.60 chs printf("%s: %s completed\n", device_xname(mlx->mlx_dv), 1431 1.1 ad opstr); 1432 1.1 ad 1433 1.1 ad mlx->mlx_bg = 0; 1434 1.1 ad mlx->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE; 1435 1.1 ad break; 1436 1.1 ad } 1437 1.1 ad 1438 1.1 ad free(mc->mc_mx.mx_context, M_DEVBUF); 1439 1.1 ad mlx_ccb_free(mlx, mc); 1440 1.1 ad mlx->mlx_flags &= ~MLXF_PERIODIC_REBUILD; 1441 1.1 ad } 1442 1.1 ad 1443 1.1 ad /* 1444 1.1 ad * It's time to perform a channel pause action for (mlx), either start or 1445 1.1 ad * stop the pause. 1446 1.1 ad */ 1447 1.1 ad static void 1448 1.1 ad mlx_pause_action(struct mlx_softc *mlx) 1449 1.1 ad { 1450 1.1 ad struct mlx_ccb *mc; 1451 1.1 ad int failsafe, i, cmd; 1452 1.1 ad 1453 1.1 ad /* What are we doing here? */ 1454 1.1 ad if (mlx->mlx_pause.mp_when == 0) { 1455 1.1 ad cmd = MLX_CMD_STARTCHANNEL; 1456 1.1 ad failsafe = 0; 1457 1.1 ad } else { 1458 1.1 ad cmd = MLX_CMD_STOPCHANNEL; 1459 1.1 ad 1460 1.32 perry /* 1461 1.1 ad * Channels will always start again after the failsafe 1462 1.32 perry * period, which is specified in multiples of 30 seconds. 1463 1.1 ad * This constrains us to a maximum pause of 450 seconds. 1464 1.1 ad */ 1465 1.43 kardel failsafe = ((mlx->mlx_pause.mp_howlong - time_second) + 5) / 30; 1466 1.1 ad 1467 1.1 ad if (failsafe > 0xf) { 1468 1.1 ad failsafe = 0xf; 1469 1.43 kardel mlx->mlx_pause.mp_howlong = 1470 1.43 kardel time_second + (0xf * 30) - 5; 1471 1.1 ad } 1472 1.1 ad } 1473 1.1 ad 1474 1.1 ad /* Build commands for every channel requested. */ 1475 1.18 ad for (i = 0; i < mlx->mlx_ci.ci_nchan; i++) { 1476 1.1 ad if ((1 << i) & mlx->mlx_pause.mp_which) { 1477 1.1 ad if (mlx_ccb_alloc(mlx, &mc, 1) != 0) { 1478 1.63 msaitoh aprint_error_dev(mlx->mlx_dv, 1479 1.63 msaitoh "%s failed for channel %d\n", 1480 1.1 ad cmd == MLX_CMD_STOPCHANNEL ? 1481 1.1 ad "pause" : "resume", i); 1482 1.1 ad continue; 1483 1.1 ad } 1484 1.1 ad 1485 1.1 ad /* Build the command. */ 1486 1.1 ad mlx_make_type2(mc, cmd, (failsafe << 4) | i, 0, 0, 1487 1.1 ad 0, 0, 0, 0, 0); 1488 1.1 ad mc->mc_mx.mx_handler = mlx_pause_done; 1489 1.60 chs mc->mc_mx.mx_dv = mlx->mlx_dv; 1490 1.1 ad 1491 1.1 ad mlx_ccb_enqueue(mlx, mc); 1492 1.1 ad } 1493 1.1 ad } 1494 1.1 ad } 1495 1.1 ad 1496 1.1 ad static void 1497 1.1 ad mlx_pause_done(struct mlx_ccb *mc) 1498 1.1 ad { 1499 1.1 ad struct mlx_softc *mlx; 1500 1.1 ad int command, channel; 1501 1.1 ad 1502 1.60 chs mlx = device_private(mc->mc_mx.mx_dv); 1503 1.1 ad command = mc->mc_mbox[0]; 1504 1.1 ad channel = mc->mc_mbox[2] & 0xf; 1505 1.1 ad 1506 1.1 ad if (mc->mc_status != 0) 1507 1.60 chs aprint_error_dev(mlx->mlx_dv, "%s command failed - %s\n", 1508 1.1 ad command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", 1509 1.1 ad mlx_ccb_diagnose(mc)); 1510 1.1 ad else if (command == MLX_CMD_STOPCHANNEL) 1511 1.1 ad printf("%s: channel %d pausing for %ld seconds\n", 1512 1.60 chs device_xname(mlx->mlx_dv), channel, 1513 1.43 kardel (long)(mlx->mlx_pause.mp_howlong - time_second)); 1514 1.1 ad else 1515 1.60 chs printf("%s: channel %d resuming\n", device_xname(mlx->mlx_dv), 1516 1.1 ad channel); 1517 1.1 ad 1518 1.1 ad mlx_ccb_free(mlx, mc); 1519 1.1 ad } 1520 1.1 ad 1521 1.1 ad /* 1522 1.1 ad * Perform an Enquiry command using a type-3 command buffer and a return a 1523 1.1 ad * single linear result buffer. If the completion function is specified, it 1524 1.1 ad * will be called with the completed command (and the result response will 1525 1.1 ad * not be valid until that point). Otherwise, the command will either be 1526 1.1 ad * busy-waited for (interrupts must be blocked), or slept for. 1527 1.1 ad */ 1528 1.1 ad static void * 1529 1.1 ad mlx_enquire(struct mlx_softc *mlx, int command, size_t bufsize, 1530 1.1 ad void (*handler)(struct mlx_ccb *mc), int waitok) 1531 1.1 ad { 1532 1.1 ad struct mlx_ccb *mc; 1533 1.1 ad void *result; 1534 1.1 ad int rv, mapped; 1535 1.1 ad 1536 1.1 ad result = NULL; 1537 1.1 ad mapped = 0; 1538 1.1 ad 1539 1.1 ad if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0) 1540 1.1 ad goto out; 1541 1.1 ad 1542 1.1 ad result = malloc(bufsize, M_DEVBUF, waitok ? M_WAITOK : M_NOWAIT); 1543 1.1 ad if (result == NULL) { 1544 1.1 ad printf("mlx_enquire: malloc() failed\n"); 1545 1.1 ad goto out; 1546 1.1 ad } 1547 1.1 ad if ((rv = mlx_ccb_map(mlx, mc, result, bufsize, MC_XFER_IN)) != 0) 1548 1.1 ad goto out; 1549 1.1 ad mapped = 1; 1550 1.6 ad if (mc->mc_nsgent != 1) { 1551 1.6 ad printf("mlx_enquire: too many segs\n"); 1552 1.6 ad goto out; 1553 1.6 ad } 1554 1.1 ad 1555 1.1 ad /* Build an enquiry command. */ 1556 1.1 ad mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_xfer_phys, 0); 1557 1.1 ad 1558 1.1 ad /* Do we want a completion callback? */ 1559 1.1 ad if (handler != NULL) { 1560 1.1 ad mc->mc_mx.mx_context = result; 1561 1.60 chs mc->mc_mx.mx_dv = mlx->mlx_dv; 1562 1.1 ad mc->mc_mx.mx_handler = handler; 1563 1.1 ad mlx_ccb_enqueue(mlx, mc); 1564 1.1 ad } else { 1565 1.1 ad /* Run the command in either polled or wait mode. */ 1566 1.9 ad if (waitok) 1567 1.9 ad rv = mlx_ccb_wait(mlx, mc); 1568 1.9 ad else 1569 1.9 ad rv = mlx_ccb_poll(mlx, mc, 5000); 1570 1.1 ad } 1571 1.1 ad 1572 1.3 ad out: 1573 1.1 ad /* We got a command, but nobody else will free it. */ 1574 1.1 ad if (handler == NULL && mc != NULL) { 1575 1.1 ad if (mapped) 1576 1.1 ad mlx_ccb_unmap(mlx, mc); 1577 1.1 ad mlx_ccb_free(mlx, mc); 1578 1.1 ad } 1579 1.1 ad 1580 1.1 ad /* We got an error, and we allocated a result. */ 1581 1.1 ad if (rv != 0 && result != NULL) { 1582 1.42 christos if (mc != NULL) 1583 1.1 ad mlx_ccb_free(mlx, mc); 1584 1.1 ad free(result, M_DEVBUF); 1585 1.1 ad result = NULL; 1586 1.1 ad } 1587 1.1 ad 1588 1.1 ad return (result); 1589 1.1 ad } 1590 1.1 ad 1591 1.1 ad /* 1592 1.1 ad * Perform a Flush command on the nominated controller. 1593 1.1 ad * 1594 1.1 ad * May be called with interrupts enabled or disabled; will not return until 1595 1.1 ad * the flush operation completes or fails. 1596 1.1 ad */ 1597 1.1 ad int 1598 1.1 ad mlx_flush(struct mlx_softc *mlx, int async) 1599 1.1 ad { 1600 1.1 ad struct mlx_ccb *mc; 1601 1.1 ad int rv; 1602 1.1 ad 1603 1.1 ad if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0) 1604 1.1 ad goto out; 1605 1.1 ad 1606 1.1 ad /* Build a flush command and fire it off. */ 1607 1.1 ad mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0); 1608 1.1 ad 1609 1.1 ad if (async) 1610 1.1 ad rv = mlx_ccb_wait(mlx, mc); 1611 1.1 ad else 1612 1.1 ad rv = mlx_ccb_poll(mlx, mc, MLX_TIMEOUT * 1000); 1613 1.1 ad if (rv != 0) 1614 1.1 ad goto out; 1615 1.1 ad 1616 1.1 ad /* Command completed OK? */ 1617 1.1 ad if (mc->mc_status != 0) { 1618 1.60 chs aprint_error_dev(mlx->mlx_dv, "FLUSH failed - %s\n", 1619 1.1 ad mlx_ccb_diagnose(mc)); 1620 1.1 ad rv = EIO; 1621 1.1 ad } 1622 1.3 ad out: 1623 1.1 ad if (mc != NULL) 1624 1.1 ad mlx_ccb_free(mlx, mc); 1625 1.1 ad 1626 1.1 ad return (rv); 1627 1.1 ad } 1628 1.1 ad 1629 1.1 ad /* 1630 1.1 ad * Start a background consistency check on (drive). 1631 1.1 ad */ 1632 1.1 ad static int 1633 1.1 ad mlx_check(struct mlx_softc *mlx, int drive) 1634 1.1 ad { 1635 1.1 ad struct mlx_ccb *mc; 1636 1.1 ad int rv; 1637 1.1 ad 1638 1.1 ad /* Get ourselves a command buffer. */ 1639 1.1 ad rv = 0x10000; 1640 1.1 ad 1641 1.1 ad if (mlx_ccb_alloc(mlx, &mc, 1) != 0) 1642 1.1 ad goto out; 1643 1.1 ad 1644 1.1 ad /* Build a checkasync command, set the "fix it" flag. */ 1645 1.1 ad mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80, 1646 1.1 ad 0, 0); 1647 1.1 ad 1648 1.1 ad /* Start the command and wait for it to be returned. */ 1649 1.1 ad if (mlx_ccb_wait(mlx, mc) != 0) 1650 1.1 ad goto out; 1651 1.1 ad 1652 1.1 ad /* Command completed OK? */ 1653 1.1 ad if (mc->mc_status != 0) 1654 1.60 chs aprint_error_dev(mlx->mlx_dv, "CHECK ASYNC failed - %s\n", 1655 1.1 ad mlx_ccb_diagnose(mc)); 1656 1.1 ad else 1657 1.1 ad printf("%s: consistency check started", 1658 1.54 cegger device_xname(mlx->mlx_sysdrive[drive].ms_dv)); 1659 1.1 ad 1660 1.1 ad rv = mc->mc_status; 1661 1.3 ad out: 1662 1.1 ad if (mc != NULL) 1663 1.1 ad mlx_ccb_free(mlx, mc); 1664 1.1 ad 1665 1.1 ad return (rv); 1666 1.1 ad } 1667 1.1 ad 1668 1.1 ad /* 1669 1.1 ad * Start a background rebuild of the physical drive at (channel),(target). 1670 1.1 ad * 1671 1.1 ad * May be called with interrupts enabled or disabled; will return as soon as 1672 1.1 ad * the operation has started or been refused. 1673 1.1 ad */ 1674 1.1 ad static int 1675 1.1 ad mlx_rebuild(struct mlx_softc *mlx, int channel, int target) 1676 1.1 ad { 1677 1.1 ad struct mlx_ccb *mc; 1678 1.1 ad int error; 1679 1.1 ad 1680 1.1 ad error = 0x10000; 1681 1.1 ad if (mlx_ccb_alloc(mlx, &mc, 1) != 0) 1682 1.1 ad goto out; 1683 1.1 ad 1684 1.1 ad /* Build a rebuildasync command, set the "fix it" flag. */ 1685 1.1 ad mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 1686 1.1 ad 0, 0); 1687 1.1 ad 1688 1.1 ad /* Start the command and wait for it to be returned. */ 1689 1.1 ad if (mlx_ccb_wait(mlx, mc) != 0) 1690 1.1 ad goto out; 1691 1.1 ad 1692 1.1 ad /* Command completed OK? */ 1693 1.1 ad if (mc->mc_status != 0) 1694 1.65 pgoyette aprint_normal_dev(mlx->mlx_dv, "REBUILD ASYNC failed - %s\n", 1695 1.65 pgoyette mlx_ccb_diagnose(mc)); 1696 1.1 ad else 1697 1.65 pgoyette aprint_normal_dev(mlx->mlx_dv, "rebuild started for %d:%d\n", 1698 1.65 pgoyette channel, target); 1699 1.1 ad 1700 1.1 ad error = mc->mc_status; 1701 1.1 ad 1702 1.3 ad out: 1703 1.1 ad if (mc != NULL) 1704 1.1 ad mlx_ccb_free(mlx, mc); 1705 1.1 ad 1706 1.1 ad return (error); 1707 1.1 ad } 1708 1.1 ad 1709 1.1 ad /* 1710 1.1 ad * Take a command from user-space and try to run it. 1711 1.1 ad * 1712 1.1 ad * XXX Note that this can't perform very much in the way of error checking, 1713 1.1 ad * XXX and as such, applications _must_ be considered trustworthy. 1714 1.1 ad * 1715 1.1 ad * XXX Commands using S/G for data are not supported. 1716 1.1 ad */ 1717 1.1 ad static int 1718 1.1 ad mlx_user_command(struct mlx_softc *mlx, struct mlx_usercommand *mu) 1719 1.1 ad { 1720 1.1 ad struct mlx_ccb *mc; 1721 1.1 ad struct mlx_dcdb *dcdb; 1722 1.1 ad void *kbuf; 1723 1.1 ad int rv, mapped; 1724 1.1 ad 1725 1.1 ad if ((mu->mu_bufdir & ~MU_XFER_MASK) != 0) 1726 1.1 ad return (EINVAL); 1727 1.1 ad 1728 1.1 ad kbuf = NULL; 1729 1.1 ad dcdb = NULL; 1730 1.1 ad mapped = 0; 1731 1.1 ad 1732 1.1 ad /* Get ourselves a command and copy in from user space. */ 1733 1.1 ad if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0) { 1734 1.1 ad DPRINTF(("mlx_user_command: mlx_ccb_alloc = %d\n", rv)); 1735 1.1 ad goto out; 1736 1.1 ad } 1737 1.1 ad 1738 1.1 ad memcpy(mc->mc_mbox, mu->mu_command, sizeof(mc->mc_mbox)); 1739 1.1 ad 1740 1.1 ad /* 1741 1.1 ad * If we need a buffer for data transfer, allocate one and copy in 1742 1.1 ad * its initial contents. 1743 1.1 ad */ 1744 1.1 ad if (mu->mu_datasize > 0) { 1745 1.13 jdolecek if (mu->mu_datasize > MAXPHYS) 1746 1.13 jdolecek return (EINVAL); 1747 1.13 jdolecek 1748 1.1 ad kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK); 1749 1.1 ad if (kbuf == NULL) { 1750 1.1 ad DPRINTF(("mlx_user_command: malloc = NULL\n")); 1751 1.1 ad rv = ENOMEM; 1752 1.1 ad goto out; 1753 1.1 ad } 1754 1.1 ad 1755 1.1 ad if ((mu->mu_bufdir & MU_XFER_OUT) != 0) { 1756 1.1 ad rv = copyin(mu->mu_buf, kbuf, mu->mu_datasize); 1757 1.1 ad if (rv != 0) { 1758 1.1 ad DPRINTF(("mlx_user_command: copyin = %d\n", 1759 1.1 ad rv)); 1760 1.1 ad goto out; 1761 1.1 ad } 1762 1.1 ad } 1763 1.1 ad 1764 1.1 ad /* Map the buffer so the controller can see it. */ 1765 1.1 ad rv = mlx_ccb_map(mlx, mc, kbuf, mu->mu_datasize, mu->mu_bufdir); 1766 1.1 ad if (rv != 0) { 1767 1.1 ad DPRINTF(("mlx_user_command: mlx_ccb_map = %d\n", rv)); 1768 1.1 ad goto out; 1769 1.1 ad } 1770 1.1 ad if (mc->mc_nsgent > 1) { 1771 1.1 ad DPRINTF(("mlx_user_command: too many s/g entries\n")); 1772 1.1 ad rv = EFBIG; 1773 1.1 ad goto out; 1774 1.1 ad } 1775 1.1 ad mapped = 1; 1776 1.41 christos /* 1777 1.41 christos * If this is a passthrough SCSI command, the DCDB is packed at 1778 1.41 christos * the beginning of the data area. Fix up the DCDB to point to 1779 1.41 christos * the correct physical address and override any bufptr 1780 1.41 christos * supplied by the caller since we know what it's meant to be. 1781 1.41 christos */ 1782 1.41 christos if (mc->mc_mbox[0] == MLX_CMD_DIRECT_CDB) { 1783 1.41 christos dcdb = (struct mlx_dcdb *)kbuf; 1784 1.41 christos dcdb->dcdb_physaddr = mc->mc_xfer_phys + sizeof(*dcdb); 1785 1.41 christos mu->mu_bufptr = 8; 1786 1.41 christos } 1787 1.1 ad } 1788 1.1 ad 1789 1.1 ad 1790 1.32 perry /* 1791 1.1 ad * If there's a data buffer, fix up the command's buffer pointer. 1792 1.1 ad */ 1793 1.1 ad if (mu->mu_datasize > 0) { 1794 1.1 ad /* Range check the pointer to physical buffer address. */ 1795 1.1 ad if (mu->mu_bufptr < 0 || 1796 1.1 ad mu->mu_bufptr > sizeof(mu->mu_command) - 4) { 1797 1.1 ad DPRINTF(("mlx_user_command: bufptr botch\n")); 1798 1.1 ad rv = EINVAL; 1799 1.1 ad goto out; 1800 1.1 ad } 1801 1.1 ad 1802 1.1 ad mc->mc_mbox[mu->mu_bufptr] = mc->mc_xfer_phys; 1803 1.1 ad mc->mc_mbox[mu->mu_bufptr+1] = mc->mc_xfer_phys >> 8; 1804 1.1 ad mc->mc_mbox[mu->mu_bufptr+2] = mc->mc_xfer_phys >> 16; 1805 1.1 ad mc->mc_mbox[mu->mu_bufptr+3] = mc->mc_xfer_phys >> 24; 1806 1.1 ad } 1807 1.1 ad 1808 1.1 ad /* Submit the command and wait. */ 1809 1.1 ad if ((rv = mlx_ccb_wait(mlx, mc)) != 0) { 1810 1.1 ad #ifdef DEBUG 1811 1.1 ad printf("mlx_user_command: mlx_ccb_wait = %d\n", rv); 1812 1.1 ad #endif 1813 1.1 ad } 1814 1.1 ad 1815 1.3 ad out: 1816 1.1 ad if (mc != NULL) { 1817 1.40 christos /* Copy out status and data */ 1818 1.40 christos mu->mu_status = mc->mc_status; 1819 1.1 ad if (mapped) 1820 1.1 ad mlx_ccb_unmap(mlx, mc); 1821 1.1 ad mlx_ccb_free(mlx, mc); 1822 1.1 ad } 1823 1.1 ad 1824 1.1 ad if (kbuf != NULL) { 1825 1.1 ad if (mu->mu_datasize > 0 && (mu->mu_bufdir & MU_XFER_IN) != 0) { 1826 1.1 ad rv = copyout(kbuf, mu->mu_buf, mu->mu_datasize); 1827 1.1 ad #ifdef DIAGNOSTIC 1828 1.1 ad if (rv != 0) 1829 1.1 ad printf("mlx_user_command: copyout = %d\n", rv); 1830 1.1 ad #endif 1831 1.1 ad } 1832 1.1 ad } 1833 1.1 ad if (kbuf != NULL) 1834 1.1 ad free(kbuf, M_DEVBUF); 1835 1.1 ad 1836 1.1 ad return (rv); 1837 1.1 ad } 1838 1.1 ad 1839 1.1 ad /* 1840 1.1 ad * Allocate and initialise a CCB. 1841 1.1 ad */ 1842 1.1 ad int 1843 1.21 ad mlx_ccb_alloc(struct mlx_softc *mlx, struct mlx_ccb **mcp, int control) 1844 1.1 ad { 1845 1.1 ad struct mlx_ccb *mc; 1846 1.1 ad int s; 1847 1.1 ad 1848 1.1 ad s = splbio(); 1849 1.24 ad mc = SLIST_FIRST(&mlx->mlx_ccb_freelist); 1850 1.21 ad if (control) { 1851 1.21 ad if (mlx->mlx_nccbs_ctrl >= MLX_NCCBS_CONTROL) { 1852 1.21 ad splx(s); 1853 1.21 ad *mcp = NULL; 1854 1.21 ad return (EAGAIN); 1855 1.21 ad } 1856 1.21 ad mc->mc_flags |= MC_CONTROL; 1857 1.21 ad mlx->mlx_nccbs_ctrl++; 1858 1.1 ad } 1859 1.1 ad SLIST_REMOVE_HEAD(&mlx->mlx_ccb_freelist, mc_chain.slist); 1860 1.1 ad splx(s); 1861 1.1 ad 1862 1.1 ad *mcp = mc; 1863 1.1 ad return (0); 1864 1.1 ad } 1865 1.1 ad 1866 1.1 ad /* 1867 1.1 ad * Free a CCB. 1868 1.1 ad */ 1869 1.1 ad void 1870 1.1 ad mlx_ccb_free(struct mlx_softc *mlx, struct mlx_ccb *mc) 1871 1.1 ad { 1872 1.1 ad int s; 1873 1.1 ad 1874 1.1 ad s = splbio(); 1875 1.21 ad if ((mc->mc_flags & MC_CONTROL) != 0) 1876 1.21 ad mlx->mlx_nccbs_ctrl--; 1877 1.1 ad mc->mc_flags = 0; 1878 1.1 ad SLIST_INSERT_HEAD(&mlx->mlx_ccb_freelist, mc, mc_chain.slist); 1879 1.1 ad splx(s); 1880 1.1 ad } 1881 1.1 ad 1882 1.1 ad /* 1883 1.1 ad * If a CCB is specified, enqueue it. Pull CCBs off the software queue in 1884 1.1 ad * the order that they were enqueued and try to submit their mailboxes to 1885 1.1 ad * the controller for execution. 1886 1.1 ad */ 1887 1.1 ad void 1888 1.1 ad mlx_ccb_enqueue(struct mlx_softc *mlx, struct mlx_ccb *mc) 1889 1.1 ad { 1890 1.1 ad int s; 1891 1.1 ad 1892 1.1 ad s = splbio(); 1893 1.1 ad 1894 1.1 ad if (mc != NULL) 1895 1.1 ad SIMPLEQ_INSERT_TAIL(&mlx->mlx_ccb_queue, mc, mc_chain.simpleq); 1896 1.1 ad 1897 1.1 ad while ((mc = SIMPLEQ_FIRST(&mlx->mlx_ccb_queue)) != NULL) { 1898 1.1 ad if (mlx_ccb_submit(mlx, mc) != 0) 1899 1.1 ad break; 1900 1.17 lukem SIMPLEQ_REMOVE_HEAD(&mlx->mlx_ccb_queue, mc_chain.simpleq); 1901 1.12 ad TAILQ_INSERT_TAIL(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq); 1902 1.1 ad } 1903 1.1 ad 1904 1.1 ad splx(s); 1905 1.1 ad } 1906 1.1 ad 1907 1.1 ad /* 1908 1.1 ad * Map the specified CCB's data buffer onto the bus, and fill the 1909 1.1 ad * scatter-gather list. 1910 1.1 ad */ 1911 1.1 ad int 1912 1.1 ad mlx_ccb_map(struct mlx_softc *mlx, struct mlx_ccb *mc, void *data, int size, 1913 1.1 ad int dir) 1914 1.1 ad { 1915 1.1 ad struct mlx_sgentry *sge; 1916 1.1 ad int nsegs, i, rv, sgloff; 1917 1.1 ad bus_dmamap_t xfer; 1918 1.1 ad 1919 1.1 ad xfer = mc->mc_xfer_map; 1920 1.1 ad 1921 1.1 ad rv = bus_dmamap_load(mlx->mlx_dmat, xfer, data, size, NULL, 1922 1.11 thorpej BUS_DMA_NOWAIT | BUS_DMA_STREAMING | 1923 1.11 thorpej ((dir & MC_XFER_IN) ? BUS_DMA_READ : BUS_DMA_WRITE)); 1924 1.1 ad if (rv != 0) 1925 1.1 ad return (rv); 1926 1.1 ad 1927 1.1 ad nsegs = xfer->dm_nsegs; 1928 1.1 ad mc->mc_xfer_size = size; 1929 1.1 ad mc->mc_flags |= dir; 1930 1.1 ad mc->mc_nsgent = nsegs; 1931 1.1 ad mc->mc_xfer_phys = xfer->dm_segs[0].ds_addr; 1932 1.1 ad 1933 1.1 ad sgloff = MLX_SGL_SIZE * mc->mc_ident; 1934 1.51 christos sge = (struct mlx_sgentry *)((char *)mlx->mlx_sgls + sgloff); 1935 1.1 ad 1936 1.1 ad for (i = 0; i < nsegs; i++, sge++) { 1937 1.1 ad sge->sge_addr = htole32(xfer->dm_segs[i].ds_addr); 1938 1.1 ad sge->sge_count = htole32(xfer->dm_segs[i].ds_len); 1939 1.1 ad } 1940 1.1 ad 1941 1.1 ad if ((dir & MC_XFER_OUT) != 0) 1942 1.1 ad i = BUS_DMASYNC_PREWRITE; 1943 1.1 ad else 1944 1.1 ad i = 0; 1945 1.1 ad if ((dir & MC_XFER_IN) != 0) 1946 1.1 ad i |= BUS_DMASYNC_PREREAD; 1947 1.1 ad 1948 1.1 ad bus_dmamap_sync(mlx->mlx_dmat, xfer, 0, mc->mc_xfer_size, i); 1949 1.1 ad bus_dmamap_sync(mlx->mlx_dmat, mlx->mlx_dmamap, sgloff, 1950 1.1 ad MLX_SGL_SIZE, BUS_DMASYNC_PREWRITE); 1951 1.1 ad 1952 1.1 ad return (0); 1953 1.1 ad } 1954 1.1 ad 1955 1.1 ad /* 1956 1.1 ad * Unmap the specified CCB's data buffer. 1957 1.1 ad */ 1958 1.1 ad void 1959 1.1 ad mlx_ccb_unmap(struct mlx_softc *mlx, struct mlx_ccb *mc) 1960 1.1 ad { 1961 1.1 ad int i; 1962 1.1 ad 1963 1.1 ad bus_dmamap_sync(mlx->mlx_dmat, mlx->mlx_dmamap, 1964 1.1 ad MLX_SGL_SIZE * mc->mc_ident, MLX_SGL_SIZE, 1965 1.1 ad BUS_DMASYNC_POSTWRITE); 1966 1.1 ad 1967 1.1 ad if ((mc->mc_flags & MC_XFER_OUT) != 0) 1968 1.6 ad i = BUS_DMASYNC_POSTWRITE; 1969 1.1 ad else 1970 1.1 ad i = 0; 1971 1.1 ad if ((mc->mc_flags & MC_XFER_IN) != 0) 1972 1.6 ad i |= BUS_DMASYNC_POSTREAD; 1973 1.1 ad 1974 1.1 ad bus_dmamap_sync(mlx->mlx_dmat, mc->mc_xfer_map, 0, mc->mc_xfer_size, i); 1975 1.1 ad bus_dmamap_unload(mlx->mlx_dmat, mc->mc_xfer_map); 1976 1.1 ad } 1977 1.1 ad 1978 1.1 ad /* 1979 1.1 ad * Submit the CCB, and busy-wait for it to complete. Return non-zero on 1980 1.1 ad * timeout or submission error. Must be called with interrupts blocked. 1981 1.1 ad */ 1982 1.1 ad int 1983 1.1 ad mlx_ccb_poll(struct mlx_softc *mlx, struct mlx_ccb *mc, int timo) 1984 1.1 ad { 1985 1.1 ad int rv; 1986 1.1 ad 1987 1.1 ad mc->mc_mx.mx_handler = NULL; 1988 1.1 ad 1989 1.1 ad if ((rv = mlx_ccb_submit(mlx, mc)) != 0) 1990 1.1 ad return (rv); 1991 1.32 perry TAILQ_INSERT_TAIL(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq); 1992 1.1 ad 1993 1.1 ad for (timo *= 10; timo != 0; timo--) { 1994 1.1 ad mlx_intr(mlx); 1995 1.1 ad if (mc->mc_status != MLX_STATUS_BUSY) 1996 1.1 ad break; 1997 1.1 ad DELAY(100); 1998 1.1 ad } 1999 1.1 ad 2000 1.1 ad if (timo != 0) { 2001 1.1 ad if (mc->mc_status != 0) { 2002 1.60 chs aprint_error_dev(mlx->mlx_dv, "command failed - %s\n", 2003 1.54 cegger mlx_ccb_diagnose(mc)); 2004 1.1 ad rv = EIO; 2005 1.1 ad } else 2006 1.1 ad rv = 0; 2007 1.1 ad } else { 2008 1.60 chs printf("%s: command timed out\n", device_xname(mlx->mlx_dv)); 2009 1.1 ad rv = EIO; 2010 1.1 ad } 2011 1.1 ad 2012 1.1 ad return (rv); 2013 1.1 ad } 2014 1.1 ad 2015 1.1 ad /* 2016 1.1 ad * Enqueue the CCB, and sleep until it completes. Return non-zero on 2017 1.1 ad * timeout or error. 2018 1.1 ad */ 2019 1.1 ad int 2020 1.1 ad mlx_ccb_wait(struct mlx_softc *mlx, struct mlx_ccb *mc) 2021 1.1 ad { 2022 1.1 ad int s; 2023 1.1 ad 2024 1.1 ad mc->mc_flags |= MC_WAITING; 2025 1.1 ad mc->mc_mx.mx_handler = NULL; 2026 1.1 ad 2027 1.1 ad s = splbio(); 2028 1.1 ad mlx_ccb_enqueue(mlx, mc); 2029 1.1 ad tsleep(mc, PRIBIO, "mlxwccb", 0); 2030 1.1 ad splx(s); 2031 1.1 ad 2032 1.1 ad if (mc->mc_status != 0) { 2033 1.60 chs aprint_error_dev(mlx->mlx_dv, "command failed - %s\n", 2034 1.1 ad mlx_ccb_diagnose(mc)); 2035 1.1 ad return (EIO); 2036 1.1 ad } 2037 1.1 ad 2038 1.1 ad return (0); 2039 1.1 ad } 2040 1.1 ad 2041 1.1 ad /* 2042 1.1 ad * Try to submit a CCB's mailbox to the controller for execution. Return 2043 1.1 ad * non-zero on timeout or error. Must be called with interrupts blocked. 2044 1.1 ad */ 2045 1.1 ad static int 2046 1.1 ad mlx_ccb_submit(struct mlx_softc *mlx, struct mlx_ccb *mc) 2047 1.1 ad { 2048 1.1 ad int i, s, r; 2049 1.1 ad 2050 1.1 ad /* Save the ident so we can handle this command when complete. */ 2051 1.21 ad mc->mc_mbox[1] = (u_int8_t)(mc->mc_ident + 1); 2052 1.1 ad 2053 1.1 ad /* Mark the command as currently being processed. */ 2054 1.1 ad mc->mc_status = MLX_STATUS_BUSY; 2055 1.43 kardel mc->mc_expiry = time_second + MLX_TIMEOUT; 2056 1.1 ad 2057 1.1 ad /* Spin waiting for the mailbox. */ 2058 1.1 ad for (i = 100; i != 0; i--) { 2059 1.1 ad s = splbio(); 2060 1.1 ad r = (*mlx->mlx_submit)(mlx, mc); 2061 1.1 ad splx(s); 2062 1.1 ad if (r != 0) 2063 1.1 ad break; 2064 1.1 ad DELAY(100); 2065 1.1 ad } 2066 1.4 ad if (i != 0) 2067 1.1 ad return (0); 2068 1.1 ad 2069 1.1 ad DPRINTF(("mlx_ccb_submit: rejected; queueing\n")); 2070 1.1 ad mc->mc_status = MLX_STATUS_WEDGED; 2071 1.1 ad return (EIO); 2072 1.1 ad } 2073 1.1 ad 2074 1.1 ad /* 2075 1.1 ad * Return a string that describes why a command has failed. 2076 1.1 ad */ 2077 1.1 ad const char * 2078 1.1 ad mlx_ccb_diagnose(struct mlx_ccb *mc) 2079 1.1 ad { 2080 1.33 christos static char tbuf[80]; 2081 1.1 ad int i; 2082 1.1 ad 2083 1.1 ad for (i = 0; i < sizeof(mlx_msgs) / sizeof(mlx_msgs[0]); i++) 2084 1.1 ad if ((mc->mc_mbox[0] == mlx_msgs[i].command || 2085 1.1 ad mlx_msgs[i].command == 0) && 2086 1.1 ad mc->mc_status == mlx_msgs[i].status) { 2087 1.33 christos snprintf(tbuf, sizeof(tbuf), "%s (0x%x)", 2088 1.1 ad mlx_status_msgs[mlx_msgs[i].msg], mc->mc_status); 2089 1.33 christos return (tbuf); 2090 1.1 ad } 2091 1.1 ad 2092 1.33 christos snprintf(tbuf, sizeof(tbuf), "unknown response 0x%x for command 0x%x", 2093 1.1 ad (int)mc->mc_status, (int)mc->mc_mbox[0]); 2094 1.1 ad 2095 1.33 christos return (tbuf); 2096 1.1 ad } 2097 1.1 ad 2098 1.1 ad /* 2099 1.1 ad * Poll the controller for completed commands. Returns non-zero if one or 2100 1.1 ad * more commands were completed. Must be called with interrupts blocked. 2101 1.1 ad */ 2102 1.1 ad int 2103 1.1 ad mlx_intr(void *cookie) 2104 1.1 ad { 2105 1.1 ad struct mlx_softc *mlx; 2106 1.1 ad struct mlx_ccb *mc; 2107 1.1 ad int result; 2108 1.1 ad u_int ident, status; 2109 1.1 ad 2110 1.1 ad mlx = cookie; 2111 1.1 ad result = 0; 2112 1.1 ad 2113 1.1 ad while ((*mlx->mlx_findcomplete)(mlx, &ident, &status) != 0) { 2114 1.1 ad result = 1; 2115 1.21 ad ident--; 2116 1.1 ad 2117 1.1 ad if (ident >= MLX_MAX_QUEUECNT) { 2118 1.63 msaitoh aprint_error_dev(mlx->mlx_dv, 2119 1.63 msaitoh "bad completion returned\n"); 2120 1.1 ad continue; 2121 1.1 ad } 2122 1.1 ad 2123 1.1 ad mc = mlx->mlx_ccbs + ident; 2124 1.1 ad 2125 1.1 ad if (mc->mc_status != MLX_STATUS_BUSY) { 2126 1.63 msaitoh aprint_error_dev(mlx->mlx_dv, 2127 1.63 msaitoh "bad completion returned\n"); 2128 1.1 ad continue; 2129 1.1 ad } 2130 1.1 ad 2131 1.32 perry TAILQ_REMOVE(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq); 2132 1.1 ad 2133 1.1 ad /* Record status and notify the initiator, if requested. */ 2134 1.1 ad mc->mc_status = status; 2135 1.1 ad if (mc->mc_mx.mx_handler != NULL) 2136 1.1 ad (*mc->mc_mx.mx_handler)(mc); 2137 1.1 ad else if ((mc->mc_flags & MC_WAITING) != 0) 2138 1.1 ad wakeup(mc); 2139 1.1 ad } 2140 1.1 ad 2141 1.1 ad /* If we've completed any commands, try posting some more. */ 2142 1.1 ad if (result) 2143 1.1 ad mlx_ccb_enqueue(mlx, NULL); 2144 1.1 ad 2145 1.1 ad return (result); 2146 1.1 ad } 2147 1.1 ad 2148 1.1 ad /* 2149 1.1 ad * Emit a string describing the firmware handshake status code, and return a 2150 1.1 ad * flag indicating whether the code represents a fatal error. 2151 1.1 ad * 2152 1.1 ad * Error code interpretations are from the Linux driver, and don't directly 2153 1.1 ad * match the messages printed by Mylex's BIOS. This may change if 2154 1.1 ad * documentation on the codes is forthcoming. 2155 1.1 ad */ 2156 1.1 ad static int 2157 1.1 ad mlx_fw_message(struct mlx_softc *mlx, int error, int param1, int param2) 2158 1.1 ad { 2159 1.1 ad const char *fmt; 2160 1.1 ad 2161 1.1 ad switch (error) { 2162 1.1 ad case 0x00: 2163 1.1 ad fmt = "physical drive %d:%d not responding"; 2164 1.1 ad break; 2165 1.1 ad 2166 1.1 ad case 0x08: 2167 1.1 ad /* 2168 1.1 ad * We could be neater about this and give some indication 2169 1.1 ad * when we receive more of them. 2170 1.1 ad */ 2171 1.1 ad if ((mlx->mlx_flags & MLXF_SPINUP_REPORTED) == 0) { 2172 1.1 ad printf("%s: spinning up drives...\n", 2173 1.60 chs device_xname(mlx->mlx_dv)); 2174 1.1 ad mlx->mlx_flags |= MLXF_SPINUP_REPORTED; 2175 1.1 ad } 2176 1.23 kristerw return (0); 2177 1.1 ad 2178 1.1 ad case 0x30: 2179 1.1 ad fmt = "configuration checksum error"; 2180 1.1 ad break; 2181 1.1 ad 2182 1.1 ad case 0x60: 2183 1.1 ad fmt = "mirror race recovery failed"; 2184 1.1 ad break; 2185 1.1 ad 2186 1.1 ad case 0x70: 2187 1.1 ad fmt = "mirror race recovery in progress"; 2188 1.1 ad break; 2189 1.1 ad 2190 1.1 ad case 0x90: 2191 1.1 ad fmt = "physical drive %d:%d COD mismatch"; 2192 1.1 ad break; 2193 1.1 ad 2194 1.1 ad case 0xa0: 2195 1.1 ad fmt = "logical drive installation aborted"; 2196 1.1 ad break; 2197 1.1 ad 2198 1.1 ad case 0xb0: 2199 1.1 ad fmt = "mirror race on a critical system drive"; 2200 1.1 ad break; 2201 1.1 ad 2202 1.1 ad case 0xd0: 2203 1.1 ad fmt = "new controller configuration found"; 2204 1.1 ad break; 2205 1.1 ad 2206 1.1 ad case 0xf0: 2207 1.60 chs aprint_error_dev(mlx->mlx_dv, "FATAL MEMORY PARITY ERROR\n"); 2208 1.1 ad return (1); 2209 1.1 ad 2210 1.1 ad default: 2211 1.63 msaitoh aprint_error_dev(mlx->mlx_dv, 2212 1.63 msaitoh "unknown firmware init error %02x:%02x:%02x\n", 2213 1.54 cegger error, param1, param2); 2214 1.1 ad return (0); 2215 1.1 ad } 2216 1.1 ad 2217 1.65 pgoyette aprint_normal_dev(mlx->mlx_dv, fmt, param2, param1); 2218 1.54 cegger aprint_normal("\n"); 2219 1.1 ad 2220 1.1 ad return (0); 2221 1.1 ad } 2222 1.65 pgoyette 2223 1.65 pgoyette MODULE(MODULE_CLASS_DRIVER, mlx, NULL); 2224 1.65 pgoyette 2225 1.65 pgoyette #ifdef _MODULE 2226 1.65 pgoyette CFDRIVER_DECL(cac, DV_DISK, NULL); 2227 1.65 pgoyette #endif 2228 1.65 pgoyette 2229 1.65 pgoyette static int 2230 1.65 pgoyette mlx_modcmd(modcmd_t cmd, void *opaque) 2231 1.65 pgoyette { 2232 1.65 pgoyette int error = 0; 2233 1.65 pgoyette 2234 1.65 pgoyette #ifdef _MODULE 2235 1.65 pgoyette switch (cmd) { 2236 1.65 pgoyette case MODULE_CMD_INIT: 2237 1.65 pgoyette error = config_cfdriver_attach(&mlx_cd); 2238 1.65 pgoyette break; 2239 1.65 pgoyette case MODULE_CMD_FINI: 2240 1.65 pgoyette error = config_cfdriver_detach(&mlx_cd); 2241 1.65 pgoyette break; 2242 1.65 pgoyette default: 2243 1.65 pgoyette error = ENOTTY; 2244 1.65 pgoyette break; 2245 1.65 pgoyette } 2246 1.65 pgoyette #endif 2247 1.65 pgoyette return error; 2248 1.65 pgoyette } 2249