mlx.c (232219) | mlx.c (240608) |
---|---|
1/*- 2 * Copyright (c) 1999 Michael Smith 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 1999 Michael Smith 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/sys/dev/mlx/mlx.c 232219 2012-02-27 16:10:26Z kevlo $ | 26 * $FreeBSD: head/sys/dev/mlx/mlx.c 240608 2012-09-17 15:27:30Z jhb $ |
27 */ 28 29/* 30 * Driver for the Mylex DAC960 family of RAID controllers. 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> | 27 */ 28 29/* 30 * Driver for the Mylex DAC960 family of RAID controllers. 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> |
35#include <sys/lock.h> |
|
35#include <sys/malloc.h> | 36#include <sys/malloc.h> |
37#include <sys/mutex.h> |
|
36#include <sys/kernel.h> | 38#include <sys/kernel.h> |
39#include <sys/sx.h> |
|
37 38#include <sys/bus.h> 39#include <sys/conf.h> 40#include <sys/stat.h> 41 42#include <machine/resource.h> 43#include <machine/bus.h> 44#include <machine/clock.h> 45#include <sys/rman.h> 46 47#include <geom/geom_disk.h> 48 49#include <dev/mlx/mlx_compat.h> 50#include <dev/mlx/mlxio.h> 51#include <dev/mlx/mlxvar.h> 52#include <dev/mlx/mlxreg.h> 53 54static struct cdevsw mlx_cdevsw = { 55 .d_version = D_VERSION, | 40 41#include <sys/bus.h> 42#include <sys/conf.h> 43#include <sys/stat.h> 44 45#include <machine/resource.h> 46#include <machine/bus.h> 47#include <machine/clock.h> 48#include <sys/rman.h> 49 50#include <geom/geom_disk.h> 51 52#include <dev/mlx/mlx_compat.h> 53#include <dev/mlx/mlxio.h> 54#include <dev/mlx/mlxvar.h> 55#include <dev/mlx/mlxreg.h> 56 57static struct cdevsw mlx_cdevsw = { 58 .d_version = D_VERSION, |
56 .d_flags = D_NEEDGIANT, | |
57 .d_open = mlx_open, 58 .d_close = mlx_close, 59 .d_ioctl = mlx_ioctl, 60 .d_name = "mlx", 61}; 62 63devclass_t mlx_devclass; 64 65/* 66 * Per-interface accessor methods 67 */ 68static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 69static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 70static void mlx_v3_intaction(struct mlx_softc *sc, int action); | 59 .d_open = mlx_open, 60 .d_close = mlx_close, 61 .d_ioctl = mlx_ioctl, 62 .d_name = "mlx", 63}; 64 65devclass_t mlx_devclass; 66 67/* 68 * Per-interface accessor methods 69 */ 70static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 71static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 72static void mlx_v3_intaction(struct mlx_softc *sc, int action); |
71static int mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2); | 73static int mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, int first); |
72 73static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 74static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 75static void mlx_v4_intaction(struct mlx_softc *sc, int action); | 74 75static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 76static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 77static void mlx_v4_intaction(struct mlx_softc *sc, int action); |
76static int mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2); | 78static int mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, int first); |
77 78static int mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 79static int mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 80static void mlx_v5_intaction(struct mlx_softc *sc, int action); | 79 80static int mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 81static int mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 82static void mlx_v5_intaction(struct mlx_softc *sc, int action); |
81static int mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2); | 83static int mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, int first); |
82 83/* 84 * Status monitoring 85 */ 86static void mlx_periodic(void *data); 87static void mlx_periodic_enquiry(struct mlx_command *mc); 88static void mlx_periodic_eventlog_poll(struct mlx_softc *sc); 89static void mlx_periodic_eventlog_respond(struct mlx_command *mc); --- 35 unchanged lines hidden (view full) --- 125/* 126 * Command management. 127 */ 128static int mlx_getslot(struct mlx_command *mc); 129static void mlx_setup_dmamap(struct mlx_command *mc, 130 bus_dma_segment_t *segs, 131 int nsegments, int error); 132static void mlx_unmapcmd(struct mlx_command *mc); | 84 85/* 86 * Status monitoring 87 */ 88static void mlx_periodic(void *data); 89static void mlx_periodic_enquiry(struct mlx_command *mc); 90static void mlx_periodic_eventlog_poll(struct mlx_softc *sc); 91static void mlx_periodic_eventlog_respond(struct mlx_command *mc); --- 35 unchanged lines hidden (view full) --- 127/* 128 * Command management. 129 */ 130static int mlx_getslot(struct mlx_command *mc); 131static void mlx_setup_dmamap(struct mlx_command *mc, 132 bus_dma_segment_t *segs, 133 int nsegments, int error); 134static void mlx_unmapcmd(struct mlx_command *mc); |
135static int mlx_shutdown_locked(struct mlx_softc *sc); |
|
133static int mlx_start(struct mlx_command *mc); | 136static int mlx_start(struct mlx_command *mc); |
134static int mlx_done(struct mlx_softc *sc); | 137static int mlx_done(struct mlx_softc *sc, int startio); |
135static void mlx_complete(struct mlx_softc *sc); 136 137/* 138 * Debugging. 139 */ 140static char *mlx_diagnose_command(struct mlx_command *mc); 141static void mlx_describe_controller(struct mlx_softc *sc); 142static int mlx_fw_message(struct mlx_softc *sc, int status, int param1, int param2); --- 16 unchanged lines hidden (view full) --- 159 */ 160void 161mlx_free(struct mlx_softc *sc) 162{ 163 struct mlx_command *mc; 164 165 debug_called(1); 166 | 138static void mlx_complete(struct mlx_softc *sc); 139 140/* 141 * Debugging. 142 */ 143static char *mlx_diagnose_command(struct mlx_command *mc); 144static void mlx_describe_controller(struct mlx_softc *sc); 145static int mlx_fw_message(struct mlx_softc *sc, int status, int param1, int param2); --- 16 unchanged lines hidden (view full) --- 162 */ 163void 164mlx_free(struct mlx_softc *sc) 165{ 166 struct mlx_command *mc; 167 168 debug_called(1); 169 |
170 /* destroy control device */ 171 if (sc->mlx_dev_t != NULL) 172 destroy_dev(sc->mlx_dev_t); 173 174 if (sc->mlx_intr) 175 bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr); 176 |
|
167 /* cancel status timeout */ | 177 /* cancel status timeout */ |
168 untimeout(mlx_periodic, sc, sc->mlx_timeout); | 178 MLX_IO_LOCK(sc); 179 callout_stop(&sc->mlx_timeout); |
169 170 /* throw away any command buffers */ 171 while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) { 172 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link); 173 mlx_freecmd(mc); 174 } | 180 181 /* throw away any command buffers */ 182 while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) { 183 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link); 184 mlx_freecmd(mc); 185 } |
186 MLX_IO_UNLOCK(sc); 187 callout_drain(&sc->mlx_timeout); |
|
175 176 /* destroy data-transfer DMA tag */ 177 if (sc->mlx_buffer_dmat) 178 bus_dma_tag_destroy(sc->mlx_buffer_dmat); 179 180 /* free and destroy DMA memory and tag for s/g lists */ 181 if (sc->mlx_sgtable) 182 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap); 183 if (sc->mlx_sg_dmat) 184 bus_dma_tag_destroy(sc->mlx_sg_dmat); 185 186 /* disconnect the interrupt handler */ | 188 189 /* destroy data-transfer DMA tag */ 190 if (sc->mlx_buffer_dmat) 191 bus_dma_tag_destroy(sc->mlx_buffer_dmat); 192 193 /* free and destroy DMA memory and tag for s/g lists */ 194 if (sc->mlx_sgtable) 195 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap); 196 if (sc->mlx_sg_dmat) 197 bus_dma_tag_destroy(sc->mlx_sg_dmat); 198 199 /* disconnect the interrupt handler */ |
187 if (sc->mlx_intr) 188 bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr); | |
189 if (sc->mlx_irq != NULL) 190 bus_release_resource(sc->mlx_dev, SYS_RES_IRQ, 0, sc->mlx_irq); 191 192 /* destroy the parent DMA tag */ 193 if (sc->mlx_parent_dmat) 194 bus_dma_tag_destroy(sc->mlx_parent_dmat); 195 196 /* release the register window mapping */ 197 if (sc->mlx_mem != NULL) 198 bus_release_resource(sc->mlx_dev, sc->mlx_mem_type, sc->mlx_mem_rid, sc->mlx_mem); 199 200 /* free controller enquiry data */ 201 if (sc->mlx_enq2 != NULL) 202 free(sc->mlx_enq2, M_DEVBUF); 203 | 200 if (sc->mlx_irq != NULL) 201 bus_release_resource(sc->mlx_dev, SYS_RES_IRQ, 0, sc->mlx_irq); 202 203 /* destroy the parent DMA tag */ 204 if (sc->mlx_parent_dmat) 205 bus_dma_tag_destroy(sc->mlx_parent_dmat); 206 207 /* release the register window mapping */ 208 if (sc->mlx_mem != NULL) 209 bus_release_resource(sc->mlx_dev, sc->mlx_mem_type, sc->mlx_mem_rid, sc->mlx_mem); 210 211 /* free controller enquiry data */ 212 if (sc->mlx_enq2 != NULL) 213 free(sc->mlx_enq2, M_DEVBUF); 214 |
204 /* destroy control device */ 205 if (sc->mlx_dev_t != (struct cdev *)NULL) 206 destroy_dev(sc->mlx_dev_t); | 215 sx_destroy(&sc->mlx_config_lock); 216 mtx_destroy(&sc->mlx_io_lock); |
207} 208 209/******************************************************************************** 210 * Map the scatter/gather table into bus space 211 */ 212static void 213mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) 214{ --- 107 unchanged lines hidden (view full) --- 322 sc->mlx_intaction = mlx_v5_intaction; 323 sc->mlx_fw_handshake = mlx_v5_fw_handshake; 324 break; 325 default: 326 return(ENXIO); /* should never happen */ 327 } 328 329 /* disable interrupts before we start talking to the controller */ | 217} 218 219/******************************************************************************** 220 * Map the scatter/gather table into bus space 221 */ 222static void 223mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) 224{ --- 107 unchanged lines hidden (view full) --- 332 sc->mlx_intaction = mlx_v5_intaction; 333 sc->mlx_fw_handshake = mlx_v5_fw_handshake; 334 break; 335 default: 336 return(ENXIO); /* should never happen */ 337 } 338 339 /* disable interrupts before we start talking to the controller */ |
340 MLX_IO_LOCK(sc); |
|
330 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); | 341 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); |
342 MLX_IO_UNLOCK(sc); |
|
331 332 /* 333 * Wait for the controller to come ready, handshake with the firmware if required. 334 * This is typically only necessary on platforms where the controller BIOS does not 335 * run. 336 */ 337 hsmsg = 0; 338 DELAY(1000); | 343 344 /* 345 * Wait for the controller to come ready, handshake with the firmware if required. 346 * This is typically only necessary on platforms where the controller BIOS does not 347 * run. 348 */ 349 hsmsg = 0; 350 DELAY(1000); |
339 while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2)) != 0) { | 351 while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2, 352 hsmsg == 0)) != 0) { |
340 /* report first time around... */ 341 if (hsmsg == 0) { 342 device_printf(sc->mlx_dev, "controller initialisation in progress...\n"); 343 hsmsg = 1; 344 } 345 /* did we get a real message? */ 346 if (hscode == 2) { 347 hscode = mlx_fw_message(sc, hserror, hsparam1, hsparam2); --- 11 unchanged lines hidden (view full) --- 359 */ 360 rid = 0; 361 sc->mlx_irq = bus_alloc_resource_any(sc->mlx_dev, SYS_RES_IRQ, &rid, 362 RF_SHAREABLE | RF_ACTIVE); 363 if (sc->mlx_irq == NULL) { 364 device_printf(sc->mlx_dev, "can't allocate interrupt\n"); 365 return(ENXIO); 366 } | 353 /* report first time around... */ 354 if (hsmsg == 0) { 355 device_printf(sc->mlx_dev, "controller initialisation in progress...\n"); 356 hsmsg = 1; 357 } 358 /* did we get a real message? */ 359 if (hscode == 2) { 360 hscode = mlx_fw_message(sc, hserror, hsparam1, hsparam2); --- 11 unchanged lines hidden (view full) --- 372 */ 373 rid = 0; 374 sc->mlx_irq = bus_alloc_resource_any(sc->mlx_dev, SYS_RES_IRQ, &rid, 375 RF_SHAREABLE | RF_ACTIVE); 376 if (sc->mlx_irq == NULL) { 377 device_printf(sc->mlx_dev, "can't allocate interrupt\n"); 378 return(ENXIO); 379 } |
367 error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO | INTR_ENTROPY, NULL, mlx_intr, sc, &sc->mlx_intr); | 380 error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO | 381 INTR_ENTROPY | INTR_MPSAFE, NULL, mlx_intr, sc, &sc->mlx_intr); |
368 if (error) { 369 device_printf(sc->mlx_dev, "can't set up interrupt\n"); 370 return(ENXIO); 371 } 372 373 /* 374 * Create DMA tag for mapping buffers into controller-addressable space. 375 */ 376 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */ 377 1, 0, /* align, boundary */ 378 BUS_SPACE_MAXADDR, /* lowaddr */ 379 BUS_SPACE_MAXADDR, /* highaddr */ 380 NULL, NULL, /* filter, filterarg */ 381 MAXBSIZE, MLX_NSEG, /* maxsize, nsegments */ 382 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 383 0, /* flags */ 384 busdma_lock_mutex, /* lockfunc */ | 382 if (error) { 383 device_printf(sc->mlx_dev, "can't set up interrupt\n"); 384 return(ENXIO); 385 } 386 387 /* 388 * Create DMA tag for mapping buffers into controller-addressable space. 389 */ 390 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */ 391 1, 0, /* align, boundary */ 392 BUS_SPACE_MAXADDR, /* lowaddr */ 393 BUS_SPACE_MAXADDR, /* highaddr */ 394 NULL, NULL, /* filter, filterarg */ 395 MAXBSIZE, MLX_NSEG, /* maxsize, nsegments */ 396 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 397 0, /* flags */ 398 busdma_lock_mutex, /* lockfunc */ |
385 &Giant, /* lockarg */ | 399 &sc->mlx_io_lock, /* lockarg */ |
386 &sc->mlx_buffer_dmat); 387 if (error != 0) { 388 device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n"); 389 return(ENOMEM); 390 } 391 392 /* 393 * Create some initial scatter/gather mappings so we can run the probe --- 8 unchanged lines hidden (view full) --- 402 /* 403 * We don't (yet) know where the event log is up to. 404 */ 405 sc->mlx_currevent = -1; 406 407 /* 408 * Obtain controller feature information 409 */ | 400 &sc->mlx_buffer_dmat); 401 if (error != 0) { 402 device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n"); 403 return(ENOMEM); 404 } 405 406 /* 407 * Create some initial scatter/gather mappings so we can run the probe --- 8 unchanged lines hidden (view full) --- 416 /* 417 * We don't (yet) know where the event log is up to. 418 */ 419 sc->mlx_currevent = -1; 420 421 /* 422 * Obtain controller feature information 423 */ |
424 MLX_IO_LOCK(sc); |
|
410 if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) { | 425 if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) { |
426 MLX_IO_UNLOCK(sc); |
|
411 device_printf(sc->mlx_dev, "ENQUIRY2 failed\n"); 412 return(ENXIO); 413 } 414 415 /* 416 * Do quirk/feature related things. 417 */ 418 fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff; 419 switch(sc->mlx_iftype) { 420 case MLX_IFTYPE_2: 421 /* These controllers don't report the firmware version in the ENQUIRY2 response */ 422 if ((meo = mlx_enquire(sc, MLX_CMD_ENQUIRY_OLD, sizeof(struct mlx_enquiry_old), NULL)) == NULL) { | 427 device_printf(sc->mlx_dev, "ENQUIRY2 failed\n"); 428 return(ENXIO); 429 } 430 431 /* 432 * Do quirk/feature related things. 433 */ 434 fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff; 435 switch(sc->mlx_iftype) { 436 case MLX_IFTYPE_2: 437 /* These controllers don't report the firmware version in the ENQUIRY2 response */ 438 if ((meo = mlx_enquire(sc, MLX_CMD_ENQUIRY_OLD, sizeof(struct mlx_enquiry_old), NULL)) == NULL) { |
439 MLX_IO_UNLOCK(sc); |
|
423 device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n"); 424 return(ENXIO); 425 } 426 sc->mlx_enq2->me_firmware_id = ('0' << 24) | (0 << 16) | (meo->me_fwminor << 8) | meo->me_fwmajor; 427 428 /* XXX require 2.42 or better (PCI) or 2.14 or better (EISA) */ 429 if (meo->me_fwminor < 42) { 430 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); --- 17 unchanged lines hidden (view full) --- 448 break; 449 case MLX_IFTYPE_5: 450 if (fwminor < 7) { 451 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); 452 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n"); 453 } 454 break; 455 default: | 440 device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n"); 441 return(ENXIO); 442 } 443 sc->mlx_enq2->me_firmware_id = ('0' << 24) | (0 << 16) | (meo->me_fwminor << 8) | meo->me_fwmajor; 444 445 /* XXX require 2.42 or better (PCI) or 2.14 or better (EISA) */ 446 if (meo->me_fwminor < 42) { 447 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); --- 17 unchanged lines hidden (view full) --- 465 break; 466 case MLX_IFTYPE_5: 467 if (fwminor < 7) { 468 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); 469 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n"); 470 } 471 break; 472 default: |
473 MLX_IO_UNLOCK(sc); |
|
456 return(ENXIO); /* should never happen */ 457 } | 474 return(ENXIO); /* should never happen */ 475 } |
476 MLX_IO_UNLOCK(sc); |
|
458 459 /* 460 * Create the final scatter/gather mappings now that we have characterised the controller. 461 */ 462 error = mlx_sglist_map(sc); 463 if (error != 0) { 464 device_printf(sc->mlx_dev, "can't make final s/g list mapping\n"); 465 return(error); --- 10 unchanged lines hidden (view full) --- 476 */ 477 sc->mlx_dev_t = make_dev(&mlx_cdevsw, 0, UID_ROOT, GID_OPERATOR, 478 S_IRUSR | S_IWUSR, "mlx%d", device_get_unit(sc->mlx_dev)); 479 sc->mlx_dev_t->si_drv1 = sc; 480 481 /* 482 * Start the timeout routine. 483 */ | 477 478 /* 479 * Create the final scatter/gather mappings now that we have characterised the controller. 480 */ 481 error = mlx_sglist_map(sc); 482 if (error != 0) { 483 device_printf(sc->mlx_dev, "can't make final s/g list mapping\n"); 484 return(error); --- 10 unchanged lines hidden (view full) --- 495 */ 496 sc->mlx_dev_t = make_dev(&mlx_cdevsw, 0, UID_ROOT, GID_OPERATOR, 497 S_IRUSR | S_IWUSR, "mlx%d", device_get_unit(sc->mlx_dev)); 498 sc->mlx_dev_t->si_drv1 = sc; 499 500 /* 501 * Start the timeout routine. 502 */ |
484 sc->mlx_timeout = timeout(mlx_periodic, sc, hz); | 503 callout_reset(&sc->mlx_timeout, hz, mlx_periodic, sc); |
485 486 /* print a little information about the controller */ 487 mlx_describe_controller(sc); 488 489 return(0); 490} 491 492/******************************************************************************** --- 7 unchanged lines hidden (view full) --- 500 int i, error; 501 502 debug_called(1); 503 504 /* 505 * Scan all the system drives and attach children for those that 506 * don't currently have them. 507 */ | 504 505 /* print a little information about the controller */ 506 mlx_describe_controller(sc); 507 508 return(0); 509} 510 511/******************************************************************************** --- 7 unchanged lines hidden (view full) --- 519 int i, error; 520 521 debug_called(1); 522 523 /* 524 * Scan all the system drives and attach children for those that 525 * don't currently have them. 526 */ |
527 MLX_IO_LOCK(sc); |
|
508 mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL); | 528 mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL); |
529 MLX_IO_UNLOCK(sc); |
|
509 if (mes == NULL) { 510 device_printf(sc->mlx_dev, "error fetching drive status\n"); 511 return; 512 } 513 514 /* iterate over drives returned */ | 530 if (mes == NULL) { 531 device_printf(sc->mlx_dev, "error fetching drive status\n"); 532 return; 533 } 534 535 /* iterate over drives returned */ |
536 MLX_CONFIG_LOCK(sc); |
|
515 for (i = 0, dr = &sc->mlx_sysdrive[0]; 516 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff); 517 i++, dr++) { 518 /* are we already attached to this drive? */ 519 if (dr->ms_disk == 0) { 520 /* pick up drive information */ 521 dr->ms_size = mes[i].sd_size; 522 dr->ms_raidlevel = mes[i].sd_raidlevel & 0xf; --- 15 unchanged lines hidden (view full) --- 538 device_set_ivars(dr->ms_disk, dr); 539 } 540 } 541 free(mes, M_DEVBUF); 542 if ((error = bus_generic_attach(sc->mlx_dev)) != 0) 543 device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error); 544 545 /* mark controller back up */ | 537 for (i = 0, dr = &sc->mlx_sysdrive[0]; 538 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff); 539 i++, dr++) { 540 /* are we already attached to this drive? */ 541 if (dr->ms_disk == 0) { 542 /* pick up drive information */ 543 dr->ms_size = mes[i].sd_size; 544 dr->ms_raidlevel = mes[i].sd_raidlevel & 0xf; --- 15 unchanged lines hidden (view full) --- 560 device_set_ivars(dr->ms_disk, dr); 561 } 562 } 563 free(mes, M_DEVBUF); 564 if ((error = bus_generic_attach(sc->mlx_dev)) != 0) 565 device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error); 566 567 /* mark controller back up */ |
568 MLX_IO_LOCK(sc); |
|
546 sc->mlx_state &= ~MLX_STATE_SHUTDOWN; 547 548 /* enable interrupts */ 549 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE); | 569 sc->mlx_state &= ~MLX_STATE_SHUTDOWN; 570 571 /* enable interrupts */ 572 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE); |
573 MLX_IO_UNLOCK(sc); 574 MLX_CONFIG_UNLOCK(sc); |
|
550} 551 552/******************************************************************************** 553 * Disconnect from the controller completely, in preparation for unload. 554 */ 555int 556mlx_detach(device_t dev) 557{ 558 struct mlx_softc *sc = device_get_softc(dev); 559 struct mlxd_softc *mlxd; | 575} 576 577/******************************************************************************** 578 * Disconnect from the controller completely, in preparation for unload. 579 */ 580int 581mlx_detach(device_t dev) 582{ 583 struct mlx_softc *sc = device_get_softc(dev); 584 struct mlxd_softc *mlxd; |
560 int i, s, error; | 585 int i, error; |
561 562 debug_called(1); 563 564 error = EBUSY; | 586 587 debug_called(1); 588 589 error = EBUSY; |
565 s = splbio(); | 590 MLX_CONFIG_LOCK(sc); |
566 if (sc->mlx_state & MLX_STATE_OPEN) 567 goto out; 568 569 for (i = 0; i < MLX_MAXDRIVES; i++) { 570 if (sc->mlx_sysdrive[i].ms_disk != 0) { 571 mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk); 572 if (mlxd->mlxd_flags & MLXD_OPEN) { /* drive is mounted, abort detach */ 573 device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't detach\n"); 574 goto out; 575 } 576 } 577 } 578 if ((error = mlx_shutdown(dev))) 579 goto out; | 591 if (sc->mlx_state & MLX_STATE_OPEN) 592 goto out; 593 594 for (i = 0; i < MLX_MAXDRIVES; i++) { 595 if (sc->mlx_sysdrive[i].ms_disk != 0) { 596 mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk); 597 if (mlxd->mlxd_flags & MLXD_OPEN) { /* drive is mounted, abort detach */ 598 device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't detach\n"); 599 goto out; 600 } 601 } 602 } 603 if ((error = mlx_shutdown(dev))) 604 goto out; |
605 MLX_CONFIG_UNLOCK(sc); |
|
580 581 mlx_free(sc); 582 | 606 607 mlx_free(sc); 608 |
583 error = 0; | 609 return (0); |
584 out: | 610 out: |
585 splx(s); | 611 MLX_CONFIG_UNLOCK(sc); |
586 return(error); 587} 588 589/******************************************************************************** 590 * Bring the controller down to a dormant state and detach all child devices. 591 * 592 * This function is called before detach, system shutdown, or before performing 593 * an operation which may add or delete system disks. (Call mlx_startup to 594 * resume normal operation.) 595 * 596 * Note that we can assume that the bioq on the controller is empty, as we won't 597 * allow shutdown if any device is open. 598 */ 599int 600mlx_shutdown(device_t dev) 601{ 602 struct mlx_softc *sc = device_get_softc(dev); | 612 return(error); 613} 614 615/******************************************************************************** 616 * Bring the controller down to a dormant state and detach all child devices. 617 * 618 * This function is called before detach, system shutdown, or before performing 619 * an operation which may add or delete system disks. (Call mlx_startup to 620 * resume normal operation.) 621 * 622 * Note that we can assume that the bioq on the controller is empty, as we won't 623 * allow shutdown if any device is open. 624 */ 625int 626mlx_shutdown(device_t dev) 627{ 628 struct mlx_softc *sc = device_get_softc(dev); |
603 int i, s, error; | 629 int error; |
604 | 630 |
631 MLX_CONFIG_LOCK(sc); 632 error = mlx_shutdown_locked(sc); 633 MLX_CONFIG_UNLOCK(sc); 634 return (error); 635} 636 637static int 638mlx_shutdown_locked(struct mlx_softc *sc) 639{ 640 int i, error; 641 |
|
605 debug_called(1); 606 | 642 debug_called(1); 643 |
607 s = splbio(); 608 error = 0; | 644 MLX_CONFIG_ASSERT_LOCKED(sc); |
609 | 645 |
646 MLX_IO_LOCK(sc); |
|
610 sc->mlx_state |= MLX_STATE_SHUTDOWN; 611 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); 612 613 /* flush controller */ 614 device_printf(sc->mlx_dev, "flushing cache..."); 615 if (mlx_flush(sc)) { 616 printf("failed\n"); 617 } else { 618 printf("done\n"); 619 } | 647 sc->mlx_state |= MLX_STATE_SHUTDOWN; 648 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); 649 650 /* flush controller */ 651 device_printf(sc->mlx_dev, "flushing cache..."); 652 if (mlx_flush(sc)) { 653 printf("failed\n"); 654 } else { 655 printf("done\n"); 656 } |
657 MLX_IO_UNLOCK(sc); |
|
620 621 /* delete all our child devices */ 622 for (i = 0; i < MLX_MAXDRIVES; i++) { 623 if (sc->mlx_sysdrive[i].ms_disk != 0) { 624 if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0) | 658 659 /* delete all our child devices */ 660 for (i = 0; i < MLX_MAXDRIVES; i++) { 661 if (sc->mlx_sysdrive[i].ms_disk != 0) { 662 if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0) |
625 goto out; | 663 return (error); |
626 sc->mlx_sysdrive[i].ms_disk = 0; 627 } 628 } 629 | 664 sc->mlx_sysdrive[i].ms_disk = 0; 665 } 666 } 667 |
630 out: 631 splx(s); 632 return(error); | 668 return (0); |
633} 634 635/******************************************************************************** 636 * Bring the controller to a quiescent state, ready for system suspend. 637 */ 638int 639mlx_suspend(device_t dev) 640{ 641 struct mlx_softc *sc = device_get_softc(dev); | 669} 670 671/******************************************************************************** 672 * Bring the controller to a quiescent state, ready for system suspend. 673 */ 674int 675mlx_suspend(device_t dev) 676{ 677 struct mlx_softc *sc = device_get_softc(dev); |
642 int s; | |
643 644 debug_called(1); 645 | 678 679 debug_called(1); 680 |
646 s = splbio(); | 681 MLX_IO_LOCK(sc); |
647 sc->mlx_state |= MLX_STATE_SUSPEND; 648 649 /* flush controller */ 650 device_printf(sc->mlx_dev, "flushing cache..."); 651 printf("%s\n", mlx_flush(sc) ? "failed" : "done"); 652 653 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); | 682 sc->mlx_state |= MLX_STATE_SUSPEND; 683 684 /* flush controller */ 685 device_printf(sc->mlx_dev, "flushing cache..."); 686 printf("%s\n", mlx_flush(sc) ? "failed" : "done"); 687 688 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); |
654 splx(s); | 689 MLX_IO_UNLOCK(sc); |
655 656 return(0); 657} 658 659/******************************************************************************** 660 * Bring the controller back to a state ready for operation. 661 */ 662int 663mlx_resume(device_t dev) 664{ 665 struct mlx_softc *sc = device_get_softc(dev); 666 667 debug_called(1); 668 | 690 691 return(0); 692} 693 694/******************************************************************************** 695 * Bring the controller back to a state ready for operation. 696 */ 697int 698mlx_resume(device_t dev) 699{ 700 struct mlx_softc *sc = device_get_softc(dev); 701 702 debug_called(1); 703 |
704 MLX_IO_LOCK(sc); |
|
669 sc->mlx_state &= ~MLX_STATE_SUSPEND; 670 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE); | 705 sc->mlx_state &= ~MLX_STATE_SUSPEND; 706 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE); |
707 MLX_IO_UNLOCK(sc); |
|
671 672 return(0); 673} 674 675/******************************************************************************* 676 * Take an interrupt, or be poked by other code to look for interrupt-worthy 677 * status. 678 */ 679void 680mlx_intr(void *arg) 681{ 682 struct mlx_softc *sc = (struct mlx_softc *)arg; 683 684 debug_called(1); 685 686 /* collect finished commands, queue anything waiting */ | 708 709 return(0); 710} 711 712/******************************************************************************* 713 * Take an interrupt, or be poked by other code to look for interrupt-worthy 714 * status. 715 */ 716void 717mlx_intr(void *arg) 718{ 719 struct mlx_softc *sc = (struct mlx_softc *)arg; 720 721 debug_called(1); 722 723 /* collect finished commands, queue anything waiting */ |
687 mlx_done(sc); | 724 MLX_IO_LOCK(sc); 725 mlx_done(sc, 1); 726 MLX_IO_UNLOCK(sc); |
688}; 689 690/******************************************************************************* 691 * Receive a buf structure from a child device and queue it on a particular 692 * disk resource, then poke the disk resource to start as much work as it can. 693 */ 694int 695mlx_submit_buf(struct mlx_softc *sc, mlx_bio *bp) 696{ | 727}; 728 729/******************************************************************************* 730 * Receive a buf structure from a child device and queue it on a particular 731 * disk resource, then poke the disk resource to start as much work as it can. 732 */ 733int 734mlx_submit_buf(struct mlx_softc *sc, mlx_bio *bp) 735{ |
697 int s; | |
698 699 debug_called(1); 700 | 736 737 debug_called(1); 738 |
701 s = splbio(); | 739 MLX_IO_ASSERT_LOCKED(sc); |
702 MLX_BIO_QINSERT(sc->mlx_bioq, bp); 703 sc->mlx_waitbufs++; | 740 MLX_BIO_QINSERT(sc->mlx_bioq, bp); 741 sc->mlx_waitbufs++; |
704 splx(s); | |
705 mlx_startio(sc); 706 return(0); 707} 708 709/******************************************************************************** 710 * Accept an open operation on the control device. 711 */ 712int 713mlx_open(struct cdev *dev, int flags, int fmt, struct thread *td) 714{ 715 struct mlx_softc *sc = dev->si_drv1; 716 | 742 mlx_startio(sc); 743 return(0); 744} 745 746/******************************************************************************** 747 * Accept an open operation on the control device. 748 */ 749int 750mlx_open(struct cdev *dev, int flags, int fmt, struct thread *td) 751{ 752 struct mlx_softc *sc = dev->si_drv1; 753 |
754 MLX_CONFIG_LOCK(sc); 755 MLX_IO_LOCK(sc); |
|
717 sc->mlx_state |= MLX_STATE_OPEN; | 756 sc->mlx_state |= MLX_STATE_OPEN; |
757 MLX_IO_UNLOCK(sc); 758 MLX_CONFIG_UNLOCK(sc); |
|
718 return(0); 719} 720 721/******************************************************************************** 722 * Accept the last close on the control device. 723 */ 724int 725mlx_close(struct cdev *dev, int flags, int fmt, struct thread *td) 726{ 727 struct mlx_softc *sc = dev->si_drv1; 728 | 759 return(0); 760} 761 762/******************************************************************************** 763 * Accept the last close on the control device. 764 */ 765int 766mlx_close(struct cdev *dev, int flags, int fmt, struct thread *td) 767{ 768 struct mlx_softc *sc = dev->si_drv1; 769 |
770 MLX_CONFIG_LOCK(sc); 771 MLX_IO_LOCK(sc); |
|
729 sc->mlx_state &= ~MLX_STATE_OPEN; | 772 sc->mlx_state &= ~MLX_STATE_OPEN; |
773 MLX_IO_UNLOCK(sc); 774 MLX_CONFIG_UNLOCK(sc); |
|
730 return (0); 731} 732 733/******************************************************************************** 734 * Handle controller-specific control operations. 735 */ 736int 737mlx_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) --- 10 unchanged lines hidden (view full) --- 748 switch(cmd) { 749 /* 750 * Enumerate connected system drives; returns the first system drive's 751 * unit number if *arg is -1, or the next unit after *arg if it's 752 * a valid unit on this controller. 753 */ 754 case MLX_NEXT_CHILD: 755 /* search system drives */ | 775 return (0); 776} 777 778/******************************************************************************** 779 * Handle controller-specific control operations. 780 */ 781int 782mlx_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) --- 10 unchanged lines hidden (view full) --- 793 switch(cmd) { 794 /* 795 * Enumerate connected system drives; returns the first system drive's 796 * unit number if *arg is -1, or the next unit after *arg if it's 797 * a valid unit on this controller. 798 */ 799 case MLX_NEXT_CHILD: 800 /* search system drives */ |
801 MLX_CONFIG_LOCK(sc); |
|
756 for (i = 0; i < MLX_MAXDRIVES; i++) { 757 /* is this one attached? */ 758 if (sc->mlx_sysdrive[i].ms_disk != 0) { 759 /* looking for the next one we come across? */ 760 if (*arg == -1) { 761 *arg = device_get_unit(sc->mlx_sysdrive[i].ms_disk); | 802 for (i = 0; i < MLX_MAXDRIVES; i++) { 803 /* is this one attached? */ 804 if (sc->mlx_sysdrive[i].ms_disk != 0) { 805 /* looking for the next one we come across? */ 806 if (*arg == -1) { 807 *arg = device_get_unit(sc->mlx_sysdrive[i].ms_disk); |
808 MLX_CONFIG_UNLOCK(sc); |
|
762 return(0); 763 } 764 /* we want the one after this one */ 765 if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk)) 766 *arg = -1; 767 } 768 } | 809 return(0); 810 } 811 /* we want the one after this one */ 812 if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk)) 813 *arg = -1; 814 } 815 } |
816 MLX_CONFIG_UNLOCK(sc); |
|
769 return(ENOENT); 770 771 /* 772 * Scan the controller to see whether new drives have appeared. 773 */ 774 case MLX_RESCAN_DRIVES: | 817 return(ENOENT); 818 819 /* 820 * Scan the controller to see whether new drives have appeared. 821 */ 822 case MLX_RESCAN_DRIVES: |
823 mtx_lock(&Giant); |
|
775 mlx_startup(sc); | 824 mlx_startup(sc); |
825 mtx_unlock(&Giant); |
|
776 return(0); 777 778 /* 779 * Disconnect from the specified drive; it may be about to go 780 * away. 781 */ 782 case MLX_DETACH_DRIVE: /* detach one drive */ | 826 return(0); 827 828 /* 829 * Disconnect from the specified drive; it may be about to go 830 * away. 831 */ 832 case MLX_DETACH_DRIVE: /* detach one drive */ |
783 | 833 MLX_CONFIG_LOCK(sc); |
784 if (((dr = mlx_findunit(sc, *arg)) == NULL) || | 834 if (((dr = mlx_findunit(sc, *arg)) == NULL) || |
785 ((mlxd = device_get_softc(dr->ms_disk)) == NULL)) | 835 ((mlxd = device_get_softc(dr->ms_disk)) == NULL)) { 836 MLX_CONFIG_UNLOCK(sc); |
786 return(ENOENT); | 837 return(ENOENT); |
838 } |
|
787 788 device_printf(dr->ms_disk, "detaching..."); 789 error = 0; 790 if (mlxd->mlxd_flags & MLXD_OPEN) { 791 error = EBUSY; 792 goto detach_out; 793 } 794 795 /* flush controller */ | 839 840 device_printf(dr->ms_disk, "detaching..."); 841 error = 0; 842 if (mlxd->mlxd_flags & MLXD_OPEN) { 843 error = EBUSY; 844 goto detach_out; 845 } 846 847 /* flush controller */ |
848 MLX_IO_LOCK(sc); |
|
796 if (mlx_flush(sc)) { | 849 if (mlx_flush(sc)) { |
850 MLX_IO_UNLOCK(sc); |
|
797 error = EBUSY; 798 goto detach_out; 799 } | 851 error = EBUSY; 852 goto detach_out; 853 } |
854 MLX_IO_UNLOCK(sc); |
|
800 801 /* nuke drive */ 802 if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0) 803 goto detach_out; 804 dr->ms_disk = 0; 805 806 detach_out: | 855 856 /* nuke drive */ 857 if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0) 858 goto detach_out; 859 dr->ms_disk = 0; 860 861 detach_out: |
862 MLX_CONFIG_UNLOCK(sc); |
|
807 if (error) { 808 printf("failed\n"); 809 } else { 810 printf("done\n"); 811 } 812 return(error); 813 814 /* 815 * Pause one or more SCSI channels for a period of time, to assist 816 * in the process of hot-swapping devices. 817 * 818 * Note that at least the 3.51 firmware on the DAC960PL doesn't seem 819 * to do this right. 820 */ 821 case MLX_PAUSE_CHANNEL: /* schedule a channel pause */ 822 /* Does this command work on this firmware? */ 823 if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS)) 824 return(EOPNOTSUPP); 825 | 863 if (error) { 864 printf("failed\n"); 865 } else { 866 printf("done\n"); 867 } 868 return(error); 869 870 /* 871 * Pause one or more SCSI channels for a period of time, to assist 872 * in the process of hot-swapping devices. 873 * 874 * Note that at least the 3.51 firmware on the DAC960PL doesn't seem 875 * to do this right. 876 */ 877 case MLX_PAUSE_CHANNEL: /* schedule a channel pause */ 878 /* Does this command work on this firmware? */ 879 if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS)) 880 return(EOPNOTSUPP); 881 |
882 /* check time values */ |
|
826 mp = (struct mlx_pause *)addr; | 883 mp = (struct mlx_pause *)addr; |
884 if ((mp->mp_when < 0) || (mp->mp_when > 3600)) 885 return(EINVAL); 886 if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30))) 887 return(EINVAL); 888 889 MLX_IO_LOCK(sc); |
|
827 if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) { 828 /* cancel a pending pause operation */ 829 sc->mlx_pause.mp_which = 0; 830 } else { 831 /* fix for legal channels */ 832 mp->mp_which &= ((1 << sc->mlx_enq2->me_actual_channels) -1); | 890 if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) { 891 /* cancel a pending pause operation */ 892 sc->mlx_pause.mp_which = 0; 893 } else { 894 /* fix for legal channels */ 895 mp->mp_which &= ((1 << sc->mlx_enq2->me_actual_channels) -1); |
833 /* check time values */ 834 if ((mp->mp_when < 0) || (mp->mp_when > 3600)) 835 return(EINVAL); 836 if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30))) 837 return(EINVAL); | |
838 839 /* check for a pause currently running */ | 896 897 /* check for a pause currently running */ |
840 if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0)) | 898 if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0)) { 899 MLX_IO_UNLOCK(sc); |
841 return(EBUSY); | 900 return(EBUSY); |
901 } |
|
842 843 /* looks ok, go with it */ 844 sc->mlx_pause.mp_which = mp->mp_which; 845 sc->mlx_pause.mp_when = time_second + mp->mp_when; 846 sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong; 847 } | 902 903 /* looks ok, go with it */ 904 sc->mlx_pause.mp_which = mp->mp_which; 905 sc->mlx_pause.mp_when = time_second + mp->mp_when; 906 sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong; 907 } |
908 MLX_IO_UNLOCK(sc); |
|
848 return(0); 849 850 /* 851 * Accept a command passthrough-style. 852 */ 853 case MLX_COMMAND: 854 return(mlx_user_command(sc, (struct mlx_usercommand *)addr)); 855 856 /* 857 * Start a rebuild on a given SCSI disk 858 */ 859 case MLX_REBUILDASYNC: | 909 return(0); 910 911 /* 912 * Accept a command passthrough-style. 913 */ 914 case MLX_COMMAND: 915 return(mlx_user_command(sc, (struct mlx_usercommand *)addr)); 916 917 /* 918 * Start a rebuild on a given SCSI disk 919 */ 920 case MLX_REBUILDASYNC: |
921 MLX_IO_LOCK(sc); |
|
860 if (sc->mlx_background != 0) { | 922 if (sc->mlx_background != 0) { |
923 MLX_IO_UNLOCK(sc); |
|
861 rb->rr_status = 0x0106; 862 return(EBUSY); 863 } 864 rb->rr_status = mlx_rebuild(sc, rb->rr_channel, rb->rr_target); 865 switch (rb->rr_status) { 866 case 0: 867 error = 0; 868 break; --- 13 unchanged lines hidden (view full) --- 882 error = EBUSY; 883 break; 884 default: 885 error = EINVAL; 886 break; 887 } 888 if (error == 0) 889 sc->mlx_background = MLX_BACKGROUND_REBUILD; | 924 rb->rr_status = 0x0106; 925 return(EBUSY); 926 } 927 rb->rr_status = mlx_rebuild(sc, rb->rr_channel, rb->rr_target); 928 switch (rb->rr_status) { 929 case 0: 930 error = 0; 931 break; --- 13 unchanged lines hidden (view full) --- 945 error = EBUSY; 946 break; 947 default: 948 error = EINVAL; 949 break; 950 } 951 if (error == 0) 952 sc->mlx_background = MLX_BACKGROUND_REBUILD; |
953 MLX_IO_UNLOCK(sc); |
|
890 return(error); 891 892 /* 893 * Get the status of the current rebuild or consistency check. 894 */ 895 case MLX_REBUILDSTAT: | 954 return(error); 955 956 /* 957 * Get the status of the current rebuild or consistency check. 958 */ 959 case MLX_REBUILDSTAT: |
960 MLX_IO_LOCK(sc); |
|
896 *rs = sc->mlx_rebuildstat; | 961 *rs = sc->mlx_rebuildstat; |
962 MLX_IO_UNLOCK(sc); |
|
897 return(0); 898 899 /* 900 * Return the per-controller system drive number matching the 901 * disk device number in (arg), if it happens to belong to us. 902 */ 903 case MLX_GET_SYSDRIVE: 904 error = ENOENT; | 963 return(0); 964 965 /* 966 * Return the per-controller system drive number matching the 967 * disk device number in (arg), if it happens to belong to us. 968 */ 969 case MLX_GET_SYSDRIVE: 970 error = ENOENT; |
971 MLX_CONFIG_LOCK(sc); 972 mtx_lock(&Giant); |
|
905 mlxd = (struct mlxd_softc *)devclass_get_softc(mlxd_devclass, *arg); | 973 mlxd = (struct mlxd_softc *)devclass_get_softc(mlxd_devclass, *arg); |
974 mtx_unlock(&Giant); |
|
906 if ((mlxd != NULL) && (mlxd->mlxd_drive >= sc->mlx_sysdrive) && 907 (mlxd->mlxd_drive < (sc->mlx_sysdrive + MLX_MAXDRIVES))) { 908 error = 0; 909 *arg = mlxd->mlxd_drive - sc->mlx_sysdrive; 910 } | 975 if ((mlxd != NULL) && (mlxd->mlxd_drive >= sc->mlx_sysdrive) && 976 (mlxd->mlxd_drive < (sc->mlx_sysdrive + MLX_MAXDRIVES))) { 977 error = 0; 978 *arg = mlxd->mlxd_drive - sc->mlx_sysdrive; 979 } |
980 MLX_CONFIG_UNLOCK(sc); |
|
911 return(error); 912 913 default: 914 return(ENOTTY); 915 } 916} 917 918/******************************************************************************** --- 6 unchanged lines hidden (view full) --- 925 int *arg = (int *)addr; 926 int error, result; 927 928 switch(cmd) { 929 /* 930 * Return the current status of this drive. 931 */ 932 case MLXD_STATUS: | 981 return(error); 982 983 default: 984 return(ENOTTY); 985 } 986} 987 988/******************************************************************************** --- 6 unchanged lines hidden (view full) --- 995 int *arg = (int *)addr; 996 int error, result; 997 998 switch(cmd) { 999 /* 1000 * Return the current status of this drive. 1001 */ 1002 case MLXD_STATUS: |
1003 MLX_IO_LOCK(sc); |
|
933 *arg = drive->ms_state; | 1004 *arg = drive->ms_state; |
1005 MLX_IO_UNLOCK(sc); |
|
934 return(0); 935 936 /* 937 * Start a background consistency check on this drive. 938 */ 939 case MLXD_CHECKASYNC: /* start a background consistency check */ | 1006 return(0); 1007 1008 /* 1009 * Start a background consistency check on this drive. 1010 */ 1011 case MLXD_CHECKASYNC: /* start a background consistency check */ |
1012 MLX_IO_LOCK(sc); |
|
940 if (sc->mlx_background != 0) { | 1013 if (sc->mlx_background != 0) { |
1014 MLX_IO_UNLOCK(sc); |
|
941 *arg = 0x0106; 942 return(EBUSY); 943 } 944 result = mlx_check(sc, drive - &sc->mlx_sysdrive[0]); 945 switch (result) { 946 case 0: 947 error = 0; 948 break; --- 10 unchanged lines hidden (view full) --- 959 error = EBUSY; 960 break; 961 default: 962 error = EINVAL; 963 break; 964 } 965 if (error == 0) 966 sc->mlx_background = MLX_BACKGROUND_CHECK; | 1015 *arg = 0x0106; 1016 return(EBUSY); 1017 } 1018 result = mlx_check(sc, drive - &sc->mlx_sysdrive[0]); 1019 switch (result) { 1020 case 0: 1021 error = 0; 1022 break; --- 10 unchanged lines hidden (view full) --- 1033 error = EBUSY; 1034 break; 1035 default: 1036 error = EINVAL; 1037 break; 1038 } 1039 if (error == 0) 1040 sc->mlx_background = MLX_BACKGROUND_CHECK; |
1041 MLX_IO_UNLOCK(sc); |
|
967 *arg = result; 968 return(error); 969 970 } 971 return(ENOIOCTL); 972} 973 974 --- 7 unchanged lines hidden (view full) --- 982 * Fire off commands to periodically check the status of connected drives. 983 */ 984static void 985mlx_periodic(void *data) 986{ 987 struct mlx_softc *sc = (struct mlx_softc *)data; 988 989 debug_called(1); | 1042 *arg = result; 1043 return(error); 1044 1045 } 1046 return(ENOIOCTL); 1047} 1048 1049 --- 7 unchanged lines hidden (view full) --- 1057 * Fire off commands to periodically check the status of connected drives. 1058 */ 1059static void 1060mlx_periodic(void *data) 1061{ 1062 struct mlx_softc *sc = (struct mlx_softc *)data; 1063 1064 debug_called(1); |
1065 MLX_IO_ASSERT_LOCKED(sc); |
|
990 991 /* 992 * Run a bus pause? 993 */ 994 if ((sc->mlx_pause.mp_which != 0) && 995 (sc->mlx_pause.mp_when > 0) && 996 (time_second >= sc->mlx_pause.mp_when)){ 997 --- 42 unchanged lines hidden (view full) --- 1040 1041 } 1042 1043 /* get drive rebuild/check status */ 1044 /* XXX should check sc->mlx_background if this is only valid while in progress */ 1045 mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild); 1046 1047 /* deal with possibly-missed interrupts and timed-out commands */ | 1066 1067 /* 1068 * Run a bus pause? 1069 */ 1070 if ((sc->mlx_pause.mp_which != 0) && 1071 (sc->mlx_pause.mp_when > 0) && 1072 (time_second >= sc->mlx_pause.mp_when)){ 1073 --- 42 unchanged lines hidden (view full) --- 1116 1117 } 1118 1119 /* get drive rebuild/check status */ 1120 /* XXX should check sc->mlx_background if this is only valid while in progress */ 1121 mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild); 1122 1123 /* deal with possibly-missed interrupts and timed-out commands */ |
1048 mlx_done(sc); | 1124 mlx_done(sc, 1); |
1049 1050 /* reschedule another poll next second or so */ | 1125 1126 /* reschedule another poll next second or so */ |
1051 sc->mlx_timeout = timeout(mlx_periodic, sc, hz); | 1127 callout_reset(&sc->mlx_timeout, hz, mlx_periodic, sc); |
1052} 1053 1054/******************************************************************************** 1055 * Handle the result of an ENQUIRY command instigated by periodic status polling. 1056 */ 1057static void 1058mlx_periodic_enquiry(struct mlx_command *mc) 1059{ 1060 struct mlx_softc *sc = mc->mc_sc; 1061 1062 debug_called(1); | 1128} 1129 1130/******************************************************************************** 1131 * Handle the result of an ENQUIRY command instigated by periodic status polling. 1132 */ 1133static void 1134mlx_periodic_enquiry(struct mlx_command *mc) 1135{ 1136 struct mlx_softc *sc = mc->mc_sc; 1137 1138 debug_called(1); |
1139 MLX_IO_ASSERT_LOCKED(sc); |
|
1063 1064 /* Command completed OK? */ 1065 if (mc->mc_status != 0) { 1066 device_printf(sc->mlx_dev, "periodic enquiry failed - %s\n", mlx_diagnose_command(mc)); 1067 goto out; 1068 } 1069 1070 /* respond to command */ --- 48 unchanged lines hidden (view full) --- 1119 /* initialise our view of the event log */ 1120 sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num; 1121 } else if ((me->me_event_log_seq_num != sc->mlx_lastevent) && !(sc->mlx_flags & MLX_EVENTLOG_BUSY)) { 1122 /* record where current events are up to */ 1123 sc->mlx_currevent = me->me_event_log_seq_num; 1124 debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent); 1125 1126 /* mark the event log as busy */ | 1140 1141 /* Command completed OK? */ 1142 if (mc->mc_status != 0) { 1143 device_printf(sc->mlx_dev, "periodic enquiry failed - %s\n", mlx_diagnose_command(mc)); 1144 goto out; 1145 } 1146 1147 /* respond to command */ --- 48 unchanged lines hidden (view full) --- 1196 /* initialise our view of the event log */ 1197 sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num; 1198 } else if ((me->me_event_log_seq_num != sc->mlx_lastevent) && !(sc->mlx_flags & MLX_EVENTLOG_BUSY)) { 1199 /* record where current events are up to */ 1200 sc->mlx_currevent = me->me_event_log_seq_num; 1201 debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent); 1202 1203 /* mark the event log as busy */ |
1127 atomic_set_int(&sc->mlx_flags, MLX_EVENTLOG_BUSY); | 1204 sc->mlx_flags |= MLX_EVENTLOG_BUSY; |
1128 1129 /* drain new eventlog entries */ 1130 mlx_periodic_eventlog_poll(sc); 1131 } 1132 break; 1133 } 1134 case MLX_CMD_ENQSYSDRIVE: 1135 { --- 64 unchanged lines hidden (view full) --- 1200static void 1201mlx_periodic_eventlog_poll(struct mlx_softc *sc) 1202{ 1203 struct mlx_command *mc; 1204 void *result = NULL; 1205 int error = 0; 1206 1207 debug_called(1); | 1205 1206 /* drain new eventlog entries */ 1207 mlx_periodic_eventlog_poll(sc); 1208 } 1209 break; 1210 } 1211 case MLX_CMD_ENQSYSDRIVE: 1212 { --- 64 unchanged lines hidden (view full) --- 1277static void 1278mlx_periodic_eventlog_poll(struct mlx_softc *sc) 1279{ 1280 struct mlx_command *mc; 1281 void *result = NULL; 1282 int error = 0; 1283 1284 debug_called(1); |
1285 MLX_IO_ASSERT_LOCKED(sc); |
|
1208 1209 /* get ourselves a command buffer */ 1210 error = 1; 1211 if ((mc = mlx_alloccmd(sc)) == NULL) 1212 goto out; 1213 1214 /* allocate the response structure */ 1215 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, --- 42 unchanged lines hidden (view full) --- 1258static void 1259mlx_periodic_eventlog_respond(struct mlx_command *mc) 1260{ 1261 struct mlx_softc *sc = mc->mc_sc; 1262 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data; 1263 char *reason; 1264 1265 debug_called(1); | 1286 1287 /* get ourselves a command buffer */ 1288 error = 1; 1289 if ((mc = mlx_alloccmd(sc)) == NULL) 1290 goto out; 1291 1292 /* allocate the response structure */ 1293 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, --- 42 unchanged lines hidden (view full) --- 1336static void 1337mlx_periodic_eventlog_respond(struct mlx_command *mc) 1338{ 1339 struct mlx_softc *sc = mc->mc_sc; 1340 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data; 1341 char *reason; 1342 1343 debug_called(1); |
1344 MLX_IO_ASSERT_LOCKED(sc); |
|
1266 1267 sc->mlx_lastevent++; /* next message... */ 1268 if (mc->mc_status == 0) { 1269 1270 /* handle event log message */ 1271 switch(el->el_type) { 1272 /* 1273 * This is the only sort of message we understand at the moment. --- 42 unchanged lines hidden (view full) --- 1316 free(mc->mc_data, M_DEVBUF); 1317 mlx_releasecmd(mc); 1318 1319 /* is there another message to obtain? */ 1320 if (sc->mlx_lastevent != sc->mlx_currevent) { 1321 mlx_periodic_eventlog_poll(sc); 1322 } else { 1323 /* clear log-busy status */ | 1345 1346 sc->mlx_lastevent++; /* next message... */ 1347 if (mc->mc_status == 0) { 1348 1349 /* handle event log message */ 1350 switch(el->el_type) { 1351 /* 1352 * This is the only sort of message we understand at the moment. --- 42 unchanged lines hidden (view full) --- 1395 free(mc->mc_data, M_DEVBUF); 1396 mlx_releasecmd(mc); 1397 1398 /* is there another message to obtain? */ 1399 if (sc->mlx_lastevent != sc->mlx_currevent) { 1400 mlx_periodic_eventlog_poll(sc); 1401 } else { 1402 /* clear log-busy status */ |
1324 atomic_clear_int(&sc->mlx_flags, MLX_EVENTLOG_BUSY); | 1403 sc->mlx_flags &= ~MLX_EVENTLOG_BUSY; |
1325 } 1326} 1327 1328/******************************************************************************** 1329 * Handle check/rebuild operations in progress. 1330 */ 1331static void 1332mlx_periodic_rebuild(struct mlx_command *mc) 1333{ 1334 struct mlx_softc *sc = mc->mc_sc; 1335 struct mlx_rebuild_status *mr = (struct mlx_rebuild_status *)mc->mc_data; 1336 | 1404 } 1405} 1406 1407/******************************************************************************** 1408 * Handle check/rebuild operations in progress. 1409 */ 1410static void 1411mlx_periodic_rebuild(struct mlx_command *mc) 1412{ 1413 struct mlx_softc *sc = mc->mc_sc; 1414 struct mlx_rebuild_status *mr = (struct mlx_rebuild_status *)mc->mc_data; 1415 |
1416 MLX_IO_ASSERT_LOCKED(sc); |
|
1337 switch(mc->mc_status) { 1338 case 0: /* operation running, update stats */ 1339 sc->mlx_rebuildstat = *mr; 1340 1341 /* spontaneous rebuild/check? */ 1342 if (sc->mlx_background == 0) { 1343 sc->mlx_background = MLX_BACKGROUND_SPONTANEOUS; 1344 device_printf(sc->mlx_dev, "background check/rebuild operation started\n"); --- 34 unchanged lines hidden (view full) --- 1379 * the pause. 1380 */ 1381static void 1382mlx_pause_action(struct mlx_softc *sc) 1383{ 1384 struct mlx_command *mc; 1385 int failsafe, i, command; 1386 | 1417 switch(mc->mc_status) { 1418 case 0: /* operation running, update stats */ 1419 sc->mlx_rebuildstat = *mr; 1420 1421 /* spontaneous rebuild/check? */ 1422 if (sc->mlx_background == 0) { 1423 sc->mlx_background = MLX_BACKGROUND_SPONTANEOUS; 1424 device_printf(sc->mlx_dev, "background check/rebuild operation started\n"); --- 34 unchanged lines hidden (view full) --- 1459 * the pause. 1460 */ 1461static void 1462mlx_pause_action(struct mlx_softc *sc) 1463{ 1464 struct mlx_command *mc; 1465 int failsafe, i, command; 1466 |
1467 MLX_IO_ASSERT_LOCKED(sc); 1468 |
|
1387 /* What are we doing here? */ 1388 if (sc->mlx_pause.mp_when == 0) { 1389 command = MLX_CMD_STARTCHANNEL; 1390 failsafe = 0; 1391 1392 } else { 1393 command = MLX_CMD_STOPCHANNEL; 1394 --- 40 unchanged lines hidden (view full) --- 1435} 1436 1437static void 1438mlx_pause_done(struct mlx_command *mc) 1439{ 1440 struct mlx_softc *sc = mc->mc_sc; 1441 int command = mc->mc_mailbox[0]; 1442 int channel = mc->mc_mailbox[2] & 0xf; | 1469 /* What are we doing here? */ 1470 if (sc->mlx_pause.mp_when == 0) { 1471 command = MLX_CMD_STARTCHANNEL; 1472 failsafe = 0; 1473 1474 } else { 1475 command = MLX_CMD_STOPCHANNEL; 1476 --- 40 unchanged lines hidden (view full) --- 1517} 1518 1519static void 1520mlx_pause_done(struct mlx_command *mc) 1521{ 1522 struct mlx_softc *sc = mc->mc_sc; 1523 int command = mc->mc_mailbox[0]; 1524 int channel = mc->mc_mailbox[2] & 0xf; |
1443 | 1525 1526 MLX_IO_ASSERT_LOCKED(sc); |
1444 if (mc->mc_status != 0) { 1445 device_printf(sc->mlx_dev, "%s command failed - %s\n", 1446 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc)); 1447 } else if (command == MLX_CMD_STOPCHANNEL) { 1448 device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n", 1449 channel, (long)(sc->mlx_pause.mp_howlong - time_second)); 1450 } else { 1451 device_printf(sc->mlx_dev, "channel %d resuming\n", channel); --- 52 unchanged lines hidden (view full) --- 1504static void * 1505mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc)) 1506{ 1507 struct mlx_command *mc; 1508 void *result; 1509 int error; 1510 1511 debug_called(1); | 1527 if (mc->mc_status != 0) { 1528 device_printf(sc->mlx_dev, "%s command failed - %s\n", 1529 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc)); 1530 } else if (command == MLX_CMD_STOPCHANNEL) { 1531 device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n", 1532 channel, (long)(sc->mlx_pause.mp_howlong - time_second)); 1533 } else { 1534 device_printf(sc->mlx_dev, "channel %d resuming\n", channel); --- 52 unchanged lines hidden (view full) --- 1587static void * 1588mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc)) 1589{ 1590 struct mlx_command *mc; 1591 void *result; 1592 int error; 1593 1594 debug_called(1); |
1595 MLX_IO_ASSERT_LOCKED(sc); |
|
1512 1513 /* get ourselves a command buffer */ 1514 error = 1; 1515 result = NULL; 1516 if ((mc = mlx_alloccmd(sc)) == NULL) 1517 goto out; 1518 /* allocate the response structure */ 1519 if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL) --- 37 unchanged lines hidden (view full) --- 1557 */ 1558static int 1559mlx_flush(struct mlx_softc *sc) 1560{ 1561 struct mlx_command *mc; 1562 int error; 1563 1564 debug_called(1); | 1596 1597 /* get ourselves a command buffer */ 1598 error = 1; 1599 result = NULL; 1600 if ((mc = mlx_alloccmd(sc)) == NULL) 1601 goto out; 1602 /* allocate the response structure */ 1603 if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL) --- 37 unchanged lines hidden (view full) --- 1641 */ 1642static int 1643mlx_flush(struct mlx_softc *sc) 1644{ 1645 struct mlx_command *mc; 1646 int error; 1647 1648 debug_called(1); |
1649 MLX_IO_ASSERT_LOCKED(sc); |
|
1565 1566 /* get ourselves a command buffer */ 1567 error = 1; 1568 if ((mc = mlx_alloccmd(sc)) == NULL) 1569 goto out; 1570 /* get a command slot */ 1571 if (mlx_getslot(mc)) 1572 goto out; --- 26 unchanged lines hidden (view full) --- 1599 */ 1600static int 1601mlx_check(struct mlx_softc *sc, int drive) 1602{ 1603 struct mlx_command *mc; 1604 int error; 1605 1606 debug_called(1); | 1650 1651 /* get ourselves a command buffer */ 1652 error = 1; 1653 if ((mc = mlx_alloccmd(sc)) == NULL) 1654 goto out; 1655 /* get a command slot */ 1656 if (mlx_getslot(mc)) 1657 goto out; --- 26 unchanged lines hidden (view full) --- 1684 */ 1685static int 1686mlx_check(struct mlx_softc *sc, int drive) 1687{ 1688 struct mlx_command *mc; 1689 int error; 1690 1691 debug_called(1); |
1692 MLX_IO_ASSERT_LOCKED(sc); |
|
1607 1608 /* get ourselves a command buffer */ 1609 error = 0x10000; 1610 if ((mc = mlx_alloccmd(sc)) == NULL) 1611 goto out; 1612 /* get a command slot */ 1613 if (mlx_getslot(mc)) 1614 goto out; --- 27 unchanged lines hidden (view full) --- 1642 */ 1643static int 1644mlx_rebuild(struct mlx_softc *sc, int channel, int target) 1645{ 1646 struct mlx_command *mc; 1647 int error; 1648 1649 debug_called(1); | 1693 1694 /* get ourselves a command buffer */ 1695 error = 0x10000; 1696 if ((mc = mlx_alloccmd(sc)) == NULL) 1697 goto out; 1698 /* get a command slot */ 1699 if (mlx_getslot(mc)) 1700 goto out; --- 27 unchanged lines hidden (view full) --- 1728 */ 1729static int 1730mlx_rebuild(struct mlx_softc *sc, int channel, int target) 1731{ 1732 struct mlx_command *mc; 1733 int error; 1734 1735 debug_called(1); |
1736 MLX_IO_ASSERT_LOCKED(sc); |
|
1650 1651 /* get ourselves a command buffer */ 1652 error = 0x10000; 1653 if ((mc = mlx_alloccmd(sc)) == NULL) 1654 goto out; 1655 /* get a command slot */ 1656 if (mlx_getslot(mc)) 1657 goto out; --- 26 unchanged lines hidden (view full) --- 1684 */ 1685static int 1686mlx_wait_command(struct mlx_command *mc) 1687{ 1688 struct mlx_softc *sc = mc->mc_sc; 1689 int error, count; 1690 1691 debug_called(1); | 1737 1738 /* get ourselves a command buffer */ 1739 error = 0x10000; 1740 if ((mc = mlx_alloccmd(sc)) == NULL) 1741 goto out; 1742 /* get a command slot */ 1743 if (mlx_getslot(mc)) 1744 goto out; --- 26 unchanged lines hidden (view full) --- 1771 */ 1772static int 1773mlx_wait_command(struct mlx_command *mc) 1774{ 1775 struct mlx_softc *sc = mc->mc_sc; 1776 int error, count; 1777 1778 debug_called(1); |
1779 MLX_IO_ASSERT_LOCKED(sc); |
|
1692 1693 mc->mc_complete = NULL; 1694 mc->mc_private = mc; /* wake us when you're done */ 1695 if ((error = mlx_start(mc)) != 0) 1696 return(error); 1697 1698 count = 0; 1699 /* XXX better timeout? */ 1700 while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) { | 1780 1781 mc->mc_complete = NULL; 1782 mc->mc_private = mc; /* wake us when you're done */ 1783 if ((error = mlx_start(mc)) != 0) 1784 return(error); 1785 1786 count = 0; 1787 /* XXX better timeout? */ 1788 while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) { |
1701 tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz); | 1789 mtx_sleep(mc->mc_private, &sc->mlx_io_lock, PRIBIO | PCATCH, "mlxwcmd", hz); |
1702 } 1703 1704 if (mc->mc_status != 0) { 1705 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc)); 1706 return(EIO); 1707 } 1708 return(0); 1709} --- 5 unchanged lines hidden (view full) --- 1715 * Should only be used when interrupts can't be relied upon. Returns 0 on 1716 * success, nonzero on error. 1717 * Successfully completed commands are dequeued. 1718 */ 1719static int 1720mlx_poll_command(struct mlx_command *mc) 1721{ 1722 struct mlx_softc *sc = mc->mc_sc; | 1790 } 1791 1792 if (mc->mc_status != 0) { 1793 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc)); 1794 return(EIO); 1795 } 1796 return(0); 1797} --- 5 unchanged lines hidden (view full) --- 1803 * Should only be used when interrupts can't be relied upon. Returns 0 on 1804 * success, nonzero on error. 1805 * Successfully completed commands are dequeued. 1806 */ 1807static int 1808mlx_poll_command(struct mlx_command *mc) 1809{ 1810 struct mlx_softc *sc = mc->mc_sc; |
1723 int error, count, s; | 1811 int error, count; |
1724 1725 debug_called(1); | 1812 1813 debug_called(1); |
1814 MLX_IO_ASSERT_LOCKED(sc); |
|
1726 1727 mc->mc_complete = NULL; 1728 mc->mc_private = NULL; /* we will poll for it */ 1729 if ((error = mlx_start(mc)) != 0) 1730 return(error); 1731 1732 count = 0; 1733 do { 1734 /* poll for completion */ | 1815 1816 mc->mc_complete = NULL; 1817 mc->mc_private = NULL; /* we will poll for it */ 1818 if ((error = mlx_start(mc)) != 0) 1819 return(error); 1820 1821 count = 0; 1822 do { 1823 /* poll for completion */ |
1735 mlx_done(mc->mc_sc); | 1824 mlx_done(mc->mc_sc, 1); |
1736 1737 } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000)); 1738 if (mc->mc_status != MLX_STATUS_BUSY) { | 1825 1826 } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000)); 1827 if (mc->mc_status != MLX_STATUS_BUSY) { |
1739 s = splbio(); | |
1740 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link); | 1828 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link); |
1741 splx(s); | |
1742 return(0); 1743 } 1744 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc)); 1745 return(EIO); 1746} 1747 1748void 1749mlx_startio_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error) --- 54 unchanged lines hidden (view full) --- 1804 } 1805 1806 /* try to give command to controller */ 1807 if (mlx_start(mc) != 0) { 1808 /* fail the command */ 1809 mc->mc_status = MLX_STATUS_WEDGED; 1810 mlx_completeio(mc); 1811 } | 1829 return(0); 1830 } 1831 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc)); 1832 return(EIO); 1833} 1834 1835void 1836mlx_startio_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error) --- 54 unchanged lines hidden (view full) --- 1891 } 1892 1893 /* try to give command to controller */ 1894 if (mlx_start(mc) != 0) { 1895 /* fail the command */ 1896 mc->mc_status = MLX_STATUS_WEDGED; 1897 mlx_completeio(mc); 1898 } |
1899 1900 sc->mlx_state &= ~MLX_STATE_QFROZEN; |
|
1812} 1813 1814/******************************************************************************** 1815 * Pull as much work off the softc's work queue as possible and give it to the 1816 * controller. Leave a couple of slots free for emergencies. | 1901} 1902 1903/******************************************************************************** 1904 * Pull as much work off the softc's work queue as possible and give it to the 1905 * controller. Leave a couple of slots free for emergencies. |
1817 * 1818 * Must be called at splbio or in an equivalent fashion that prevents 1819 * reentry or activity on the bioq. | |
1820 */ 1821static void 1822mlx_startio(struct mlx_softc *sc) 1823{ 1824 struct mlx_command *mc; 1825 mlx_bio *bp; | 1906 */ 1907static void 1908mlx_startio(struct mlx_softc *sc) 1909{ 1910 struct mlx_command *mc; 1911 mlx_bio *bp; |
1826 int s; | |
1827 int error; 1828 | 1912 int error; 1913 |
1829 /* avoid reentrancy */ 1830 if (mlx_lock_tas(sc, MLX_LOCK_STARTING)) 1831 return; | 1914 MLX_IO_ASSERT_LOCKED(sc); |
1832 1833 /* spin until something prevents us from doing any work */ | 1915 1916 /* spin until something prevents us from doing any work */ |
1834 s = splbio(); | |
1835 for (;;) { | 1917 for (;;) { |
1918 if (sc->mlx_state & MLX_STATE_QFROZEN) 1919 break; |
|
1836 1837 /* see if there's work to be done */ 1838 if ((bp = MLX_BIO_QFIRST(sc->mlx_bioq)) == NULL) 1839 break; 1840 /* get a command */ 1841 if ((mc = mlx_alloccmd(sc)) == NULL) 1842 break; 1843 /* get a slot for the command */ 1844 if (mlx_getslot(mc) != 0) { 1845 mlx_releasecmd(mc); 1846 break; 1847 } 1848 /* get the buf containing our work */ 1849 MLX_BIO_QREMOVE(sc->mlx_bioq, bp); 1850 sc->mlx_waitbufs--; | 1920 1921 /* see if there's work to be done */ 1922 if ((bp = MLX_BIO_QFIRST(sc->mlx_bioq)) == NULL) 1923 break; 1924 /* get a command */ 1925 if ((mc = mlx_alloccmd(sc)) == NULL) 1926 break; 1927 /* get a slot for the command */ 1928 if (mlx_getslot(mc) != 0) { 1929 mlx_releasecmd(mc); 1930 break; 1931 } 1932 /* get the buf containing our work */ 1933 MLX_BIO_QREMOVE(sc->mlx_bioq, bp); 1934 sc->mlx_waitbufs--; |
1851 splx(s); | |
1852 1853 /* connect the buf to the command */ 1854 mc->mc_complete = mlx_completeio; 1855 mc->mc_private = bp; 1856 mc->mc_data = MLX_BIO_DATA(bp); 1857 mc->mc_length = MLX_BIO_LENGTH(bp); 1858 1859 /* map the command so the controller can work with it */ 1860 error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, 1861 mc->mc_length, mlx_startio_cb, mc, 0); | 1935 1936 /* connect the buf to the command */ 1937 mc->mc_complete = mlx_completeio; 1938 mc->mc_private = bp; 1939 mc->mc_data = MLX_BIO_DATA(bp); 1940 mc->mc_length = MLX_BIO_LENGTH(bp); 1941 1942 /* map the command so the controller can work with it */ 1943 error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, 1944 mc->mc_length, mlx_startio_cb, mc, 0); |
1862 if (error == EINPROGRESS) { 1863 break; | 1945 if (error == EINPROGRESS) { 1946 sc->mlx_state |= MLX_STATE_QFROZEN; 1947 break; |
1864 } | 1948 } |
1865 1866 s = splbio(); | |
1867 } | 1949 } |
1868 splx(s); 1869 mlx_lock_clr(sc, MLX_LOCK_STARTING); | |
1870} 1871 1872/******************************************************************************** 1873 * Handle completion of an I/O command. 1874 */ 1875static void 1876mlx_completeio(struct mlx_command *mc) 1877{ 1878 struct mlx_softc *sc = mc->mc_sc; 1879 mlx_bio *bp = (mlx_bio *)mc->mc_private; 1880 struct mlxd_softc *mlxd = (struct mlxd_softc *)MLX_BIO_SOFTC(bp); | 1950} 1951 1952/******************************************************************************** 1953 * Handle completion of an I/O command. 1954 */ 1955static void 1956mlx_completeio(struct mlx_command *mc) 1957{ 1958 struct mlx_softc *sc = mc->mc_sc; 1959 mlx_bio *bp = (mlx_bio *)mc->mc_private; 1960 struct mlxd_softc *mlxd = (struct mlxd_softc *)MLX_BIO_SOFTC(bp); |
1881 | 1961 1962 MLX_IO_ASSERT_LOCKED(sc); |
1882 if (mc->mc_status != MLX_STATUS_OK) { /* could be more verbose here? */ 1883 MLX_BIO_SET_ERROR(bp, EIO); 1884 1885 switch(mc->mc_status) { 1886 case MLX_STATUS_RDWROFFLINE: /* system drive has gone offline */ 1887 device_printf(mlxd->mlxd_dev, "drive offline\n"); 1888 /* should signal this with a return code */ 1889 mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE; --- 74 unchanged lines hidden (view full) --- 1964 1965 debug_called(0); 1966 1967 kbuf = NULL; 1968 mc = NULL; 1969 error = ENOMEM; 1970 1971 /* get ourselves a command and copy in from user space */ | 1963 if (mc->mc_status != MLX_STATUS_OK) { /* could be more verbose here? */ 1964 MLX_BIO_SET_ERROR(bp, EIO); 1965 1966 switch(mc->mc_status) { 1967 case MLX_STATUS_RDWROFFLINE: /* system drive has gone offline */ 1968 device_printf(mlxd->mlxd_dev, "drive offline\n"); 1969 /* should signal this with a return code */ 1970 mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE; --- 74 unchanged lines hidden (view full) --- 2045 2046 debug_called(0); 2047 2048 kbuf = NULL; 2049 mc = NULL; 2050 error = ENOMEM; 2051 2052 /* get ourselves a command and copy in from user space */ |
1972 if ((mc = mlx_alloccmd(sc)) == NULL) | 2053 MLX_IO_LOCK(sc); 2054 if ((mc = mlx_alloccmd(sc)) == NULL) { 2055 MLX_IO_UNLOCK(sc); |
1973 return(error); | 2056 return(error); |
2057 } |
|
1974 bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox)); 1975 debug(0, "got command buffer"); 1976 1977 /* 1978 * if we need a buffer for data transfer, allocate one and copy in its 1979 * initial contents 1980 */ 1981 if (mu->mu_datasize > 0) { 1982 if (mu->mu_datasize > MLX_MAXPHYS) { 1983 error = EINVAL; 1984 goto out; 1985 } | 2058 bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox)); 2059 debug(0, "got command buffer"); 2060 2061 /* 2062 * if we need a buffer for data transfer, allocate one and copy in its 2063 * initial contents 2064 */ 2065 if (mu->mu_datasize > 0) { 2066 if (mu->mu_datasize > MLX_MAXPHYS) { 2067 error = EINVAL; 2068 goto out; 2069 } |
2070 MLX_IO_UNLOCK(sc); |
|
1986 if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) || | 2071 if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) || |
1987 (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))) | 2072 (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))) { 2073 MLX_IO_LOCK(sc); |
1988 goto out; | 2074 goto out; |
2075 } 2076 MLX_IO_LOCK(sc); |
|
1989 debug(0, "got kernel buffer"); 1990 } 1991 1992 /* get a command slot */ 1993 if (mlx_getslot(mc)) 1994 goto out; 1995 debug(0, "got a slot"); 1996 --- 8 unchanged lines hidden (view full) --- 2005 } 2006 2007 /* map the command so the controller can see it */ 2008 mc->mc_data = kbuf; 2009 mc->mc_length = mu->mu_datasize; 2010 mc->mc_private = mu; 2011 error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, 2012 mc->mc_length, mlx_user_cb, mc, BUS_DMA_NOWAIT); | 2077 debug(0, "got kernel buffer"); 2078 } 2079 2080 /* get a command slot */ 2081 if (mlx_getslot(mc)) 2082 goto out; 2083 debug(0, "got a slot"); 2084 --- 8 unchanged lines hidden (view full) --- 2093 } 2094 2095 /* map the command so the controller can see it */ 2096 mc->mc_data = kbuf; 2097 mc->mc_length = mu->mu_datasize; 2098 mc->mc_private = mu; 2099 error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, 2100 mc->mc_length, mlx_user_cb, mc, BUS_DMA_NOWAIT); |
2101 if (error) 2102 goto out; |
|
2013 2014 /* copy out status and data */ 2015 mu->mu_status = mc->mc_status; | 2103 2104 /* copy out status and data */ 2105 mu->mu_status = mc->mc_status; |
2016 if ((mu->mu_datasize > 0) && 2017 ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize)))) 2018 goto out; | 2106 if (mu->mu_datasize > 0) { 2107 MLX_IO_UNLOCK(sc); 2108 error = copyout(kbuf, mu->mu_buf, mu->mu_datasize); 2109 MLX_IO_LOCK(sc); 2110 } |
2019 | 2111 |
2020 error = 0; 2021 | |
2022 out: 2023 mlx_releasecmd(mc); | 2112 out: 2113 mlx_releasecmd(mc); |
2114 MLX_IO_UNLOCK(sc); |
|
2024 if (kbuf != NULL) 2025 free(kbuf, M_DEVBUF); 2026 return(error); 2027} 2028 2029/******************************************************************************** 2030 ******************************************************************************** 2031 Command I/O to Controller --- 5 unchanged lines hidden (view full) --- 2037 * 2038 * Don't hand out a slot to a normal-priority command unless there are at least 2039 * 4 slots free for priority commands. 2040 */ 2041static int 2042mlx_getslot(struct mlx_command *mc) 2043{ 2044 struct mlx_softc *sc = mc->mc_sc; | 2115 if (kbuf != NULL) 2116 free(kbuf, M_DEVBUF); 2117 return(error); 2118} 2119 2120/******************************************************************************** 2121 ******************************************************************************** 2122 Command I/O to Controller --- 5 unchanged lines hidden (view full) --- 2128 * 2129 * Don't hand out a slot to a normal-priority command unless there are at least 2130 * 4 slots free for priority commands. 2131 */ 2132static int 2133mlx_getslot(struct mlx_command *mc) 2134{ 2135 struct mlx_softc *sc = mc->mc_sc; |
2045 int s, slot, limit; | 2136 int slot, limit; |
2046 2047 debug_called(1); 2048 | 2137 2138 debug_called(1); 2139 |
2140 MLX_IO_ASSERT_LOCKED(sc); 2141 |
|
2049 /* 2050 * Enforce slot-usage limit, if we have the required information. 2051 */ 2052 if (sc->mlx_enq2 != NULL) { 2053 limit = sc->mlx_enq2->me_max_commands; 2054 } else { 2055 limit = 2; 2056 } 2057 if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? limit : limit - 4)) 2058 return(EBUSY); 2059 2060 /* 2061 * Allocate an outstanding command slot 2062 * 2063 * XXX linear search is slow 2064 */ | 2142 /* 2143 * Enforce slot-usage limit, if we have the required information. 2144 */ 2145 if (sc->mlx_enq2 != NULL) { 2146 limit = sc->mlx_enq2->me_max_commands; 2147 } else { 2148 limit = 2; 2149 } 2150 if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? limit : limit - 4)) 2151 return(EBUSY); 2152 2153 /* 2154 * Allocate an outstanding command slot 2155 * 2156 * XXX linear search is slow 2157 */ |
2065 s = splbio(); | |
2066 for (slot = 0; slot < limit; slot++) { 2067 debug(2, "try slot %d", slot); 2068 if (sc->mlx_busycmd[slot] == NULL) 2069 break; 2070 } 2071 if (slot < limit) { 2072 sc->mlx_busycmd[slot] = mc; 2073 sc->mlx_busycmds++; 2074 } | 2158 for (slot = 0; slot < limit; slot++) { 2159 debug(2, "try slot %d", slot); 2160 if (sc->mlx_busycmd[slot] == NULL) 2161 break; 2162 } 2163 if (slot < limit) { 2164 sc->mlx_busycmd[slot] = mc; 2165 sc->mlx_busycmds++; 2166 } |
2075 splx(s); | |
2076 2077 /* out of slots? */ 2078 if (slot >= limit) 2079 return(EBUSY); 2080 2081 debug(2, "got slot %d", slot); 2082 mc->mc_slot = slot; 2083 return(0); --- 64 unchanged lines hidden (view full) --- 2148 * Try to deliver (mc) to the controller. 2149 * 2150 * Can be called at any interrupt level, with or without interrupts enabled. 2151 */ 2152static int 2153mlx_start(struct mlx_command *mc) 2154{ 2155 struct mlx_softc *sc = mc->mc_sc; | 2167 2168 /* out of slots? */ 2169 if (slot >= limit) 2170 return(EBUSY); 2171 2172 debug(2, "got slot %d", slot); 2173 mc->mc_slot = slot; 2174 return(0); --- 64 unchanged lines hidden (view full) --- 2239 * Try to deliver (mc) to the controller. 2240 * 2241 * Can be called at any interrupt level, with or without interrupts enabled. 2242 */ 2243static int 2244mlx_start(struct mlx_command *mc) 2245{ 2246 struct mlx_softc *sc = mc->mc_sc; |
2156 int i, s, done; | 2247 int i; |
2157 2158 debug_called(1); 2159 2160 /* save the slot number as ident so we can handle this command when complete */ 2161 mc->mc_mailbox[0x1] = mc->mc_slot; 2162 2163 /* mark the command as currently being processed */ 2164 mc->mc_status = MLX_STATUS_BUSY; 2165 2166 /* set a default 60-second timeout XXX tunable? XXX not currently used */ 2167 mc->mc_timeout = time_second + 60; | 2248 2249 debug_called(1); 2250 2251 /* save the slot number as ident so we can handle this command when complete */ 2252 mc->mc_mailbox[0x1] = mc->mc_slot; 2253 2254 /* mark the command as currently being processed */ 2255 mc->mc_status = MLX_STATUS_BUSY; 2256 2257 /* set a default 60-second timeout XXX tunable? XXX not currently used */ 2258 mc->mc_timeout = time_second + 60; |
2168 | 2259 |
2169 /* spin waiting for the mailbox */ | 2260 /* spin waiting for the mailbox */ |
2170 for (i = 100000, done = 0; (i > 0) && !done; i--) { 2171 s = splbio(); | 2261 for (i = 100000; i > 0; i--) { |
2172 if (sc->mlx_tryqueue(sc, mc)) { | 2262 if (sc->mlx_tryqueue(sc, mc)) { |
2173 done = 1; | |
2174 /* move command to work queue */ 2175 TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link); | 2263 /* move command to work queue */ 2264 TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link); |
2176 } 2177 splx(s); /* drop spl to allow completion interrupts */ | 2265 return (0); 2266 } else if (i > 1) 2267 mlx_done(sc, 0); |
2178 } 2179 | 2268 } 2269 |
2180 /* command is enqueued */ 2181 if (done) 2182 return(0); 2183 | |
2184 /* 2185 * We couldn't get the controller to take the command. Revoke the slot 2186 * that the command was given and return it with a bad status. 2187 */ 2188 sc->mlx_busycmd[mc->mc_slot] = NULL; 2189 device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n"); 2190 mc->mc_status = MLX_STATUS_WEDGED; 2191 mlx_complete(sc); 2192 return(EIO); 2193} 2194 2195/******************************************************************************** 2196 * Poll the controller (sc) for completed commands. 2197 * Update command status and free slots for reuse. If any slots were freed, 2198 * new commands may be posted. 2199 * 2200 * Returns nonzero if one or more commands were completed. 2201 */ 2202static int | 2270 /* 2271 * We couldn't get the controller to take the command. Revoke the slot 2272 * that the command was given and return it with a bad status. 2273 */ 2274 sc->mlx_busycmd[mc->mc_slot] = NULL; 2275 device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n"); 2276 mc->mc_status = MLX_STATUS_WEDGED; 2277 mlx_complete(sc); 2278 return(EIO); 2279} 2280 2281/******************************************************************************** 2282 * Poll the controller (sc) for completed commands. 2283 * Update command status and free slots for reuse. If any slots were freed, 2284 * new commands may be posted. 2285 * 2286 * Returns nonzero if one or more commands were completed. 2287 */ 2288static int |
2203mlx_done(struct mlx_softc *sc) | 2289mlx_done(struct mlx_softc *sc, int startio) |
2204{ 2205 struct mlx_command *mc; | 2290{ 2291 struct mlx_command *mc; |
2206 int s, result; | 2292 int result; |
2207 u_int8_t slot; 2208 u_int16_t status; 2209 2210 debug_called(2); | 2293 u_int8_t slot; 2294 u_int16_t status; 2295 2296 debug_called(2); |
2297 MLX_IO_ASSERT_LOCKED(sc); |
|
2211 2212 result = 0; 2213 2214 /* loop collecting completed commands */ | 2298 2299 result = 0; 2300 2301 /* loop collecting completed commands */ |
2215 s = splbio(); | |
2216 for (;;) { 2217 /* poll for a completed command's identifier and status */ 2218 if (sc->mlx_findcomplete(sc, &slot, &status)) { 2219 result = 1; 2220 mc = sc->mlx_busycmd[slot]; /* find command */ 2221 if (mc != NULL) { /* paranoia */ 2222 if (mc->mc_status == MLX_STATUS_BUSY) { 2223 mc->mc_status = status; /* save status */ --- 6 unchanged lines hidden (view full) --- 2230 } 2231 } else { 2232 device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot); 2233 } 2234 } else { 2235 break; 2236 } 2237 } | 2302 for (;;) { 2303 /* poll for a completed command's identifier and status */ 2304 if (sc->mlx_findcomplete(sc, &slot, &status)) { 2305 result = 1; 2306 mc = sc->mlx_busycmd[slot]; /* find command */ 2307 if (mc != NULL) { /* paranoia */ 2308 if (mc->mc_status == MLX_STATUS_BUSY) { 2309 mc->mc_status = status; /* save status */ --- 6 unchanged lines hidden (view full) --- 2316 } 2317 } else { 2318 device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot); 2319 } 2320 } else { 2321 break; 2322 } 2323 } |
2238 splx(s); | |
2239 2240 /* if we've completed any commands, try posting some more */ | 2324 2325 /* if we've completed any commands, try posting some more */ |
2241 if (result) | 2326 if (result && startio) |
2242 mlx_startio(sc); 2243 2244 /* handle completion and timeouts */ 2245 mlx_complete(sc); 2246 2247 return(result); 2248} 2249 2250/******************************************************************************** 2251 * Perform post-completion processing for commands on (sc). 2252 */ 2253static void 2254mlx_complete(struct mlx_softc *sc) 2255{ 2256 struct mlx_command *mc, *nc; | 2327 mlx_startio(sc); 2328 2329 /* handle completion and timeouts */ 2330 mlx_complete(sc); 2331 2332 return(result); 2333} 2334 2335/******************************************************************************** 2336 * Perform post-completion processing for commands on (sc). 2337 */ 2338static void 2339mlx_complete(struct mlx_softc *sc) 2340{ 2341 struct mlx_command *mc, *nc; |
2257 int s; | |
2258 2259 debug_called(2); | 2342 2343 debug_called(2); |
2344 MLX_IO_ASSERT_LOCKED(sc); |
|
2260 | 2345 |
2261 /* avoid reentrancy XXX might want to signal and request a restart */ 2262 if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING)) 2263 return; 2264 2265 s = splbio(); 2266 | |
2267 /* scan the list of busy/done commands */ 2268 mc = TAILQ_FIRST(&sc->mlx_work); 2269 while (mc != NULL) { 2270 nc = TAILQ_NEXT(mc, mc_link); 2271 2272 /* Command has been completed in some fashion */ 2273 if (mc->mc_status != MLX_STATUS_BUSY) { 2274 --- 19 unchanged lines hidden (view full) --- 2294 /* 2295 * Leave the command for a caller that's polling for it. 2296 */ 2297 } else { 2298 } 2299 } 2300 mc = nc; 2301 } | 2346 /* scan the list of busy/done commands */ 2347 mc = TAILQ_FIRST(&sc->mlx_work); 2348 while (mc != NULL) { 2349 nc = TAILQ_NEXT(mc, mc_link); 2350 2351 /* Command has been completed in some fashion */ 2352 if (mc->mc_status != MLX_STATUS_BUSY) { 2353 --- 19 unchanged lines hidden (view full) --- 2373 /* 2374 * Leave the command for a caller that's polling for it. 2375 */ 2376 } else { 2377 } 2378 } 2379 mc = nc; 2380 } |
2302 splx(s); 2303 2304 mlx_lock_clr(sc, MLX_LOCK_COMPLETING); | |
2305} 2306 2307/******************************************************************************** 2308 ******************************************************************************** 2309 Command Buffer Management 2310 ******************************************************************************** 2311 ********************************************************************************/ 2312 --- 11 unchanged lines hidden (view full) --- 2324 * responsibility to ensure that all required fields are filled in before 2325 * using a buffer. 2326 */ 2327static struct mlx_command * 2328mlx_alloccmd(struct mlx_softc *sc) 2329{ 2330 struct mlx_command *mc; 2331 int error; | 2381} 2382 2383/******************************************************************************** 2384 ******************************************************************************** 2385 Command Buffer Management 2386 ******************************************************************************** 2387 ********************************************************************************/ 2388 --- 11 unchanged lines hidden (view full) --- 2400 * responsibility to ensure that all required fields are filled in before 2401 * using a buffer. 2402 */ 2403static struct mlx_command * 2404mlx_alloccmd(struct mlx_softc *sc) 2405{ 2406 struct mlx_command *mc; 2407 int error; |
2332 int s; | |
2333 2334 debug_called(1); 2335 | 2408 2409 debug_called(1); 2410 |
2336 s = splbio(); | 2411 MLX_IO_ASSERT_LOCKED(sc); |
2337 if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) 2338 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link); | 2412 if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) 2413 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link); |
2339 splx(s); | |
2340 2341 /* allocate a new command buffer? */ 2342 if (mc == NULL) { 2343 mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT | M_ZERO); 2344 if (mc != NULL) { 2345 mc->mc_sc = sc; 2346 error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap); 2347 if (error) { --- 9 unchanged lines hidden (view full) --- 2357 * Release a command buffer for recycling. 2358 * 2359 * XXX It might be a good idea to limit the number of commands we save for reuse 2360 * if it's shown that this list bloats out massively. 2361 */ 2362static void 2363mlx_releasecmd(struct mlx_command *mc) 2364{ | 2414 2415 /* allocate a new command buffer? */ 2416 if (mc == NULL) { 2417 mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT | M_ZERO); 2418 if (mc != NULL) { 2419 mc->mc_sc = sc; 2420 error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap); 2421 if (error) { --- 9 unchanged lines hidden (view full) --- 2431 * Release a command buffer for recycling. 2432 * 2433 * XXX It might be a good idea to limit the number of commands we save for reuse 2434 * if it's shown that this list bloats out massively. 2435 */ 2436static void 2437mlx_releasecmd(struct mlx_command *mc) 2438{ |
2365 int s; | |
2366 2367 debug_called(1); 2368 | 2439 2440 debug_called(1); 2441 |
2369 s = splbio(); | 2442 MLX_IO_ASSERT_LOCKED(mc->mc_sc); |
2370 TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link); | 2443 TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link); |
2371 splx(s); | |
2372} 2373 2374/******************************************************************************** 2375 * Permanently discard a command buffer. 2376 */ 2377static void 2378mlx_freecmd(struct mlx_command *mc) 2379{ --- 9 unchanged lines hidden (view full) --- 2389 ******************************************************************************** 2390 Type 3 interface accessor methods 2391 ******************************************************************************** 2392 ********************************************************************************/ 2393 2394/******************************************************************************** 2395 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2396 * (the controller is not ready to take a command). | 2444} 2445 2446/******************************************************************************** 2447 * Permanently discard a command buffer. 2448 */ 2449static void 2450mlx_freecmd(struct mlx_command *mc) 2451{ --- 9 unchanged lines hidden (view full) --- 2461 ******************************************************************************** 2462 Type 3 interface accessor methods 2463 ******************************************************************************** 2464 ********************************************************************************/ 2465 2466/******************************************************************************** 2467 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2468 * (the controller is not ready to take a command). |
2397 * 2398 * Must be called at splbio or in a fashion that prevents reentry. | |
2399 */ 2400static int 2401mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2402{ 2403 int i; 2404 2405 debug_called(2); | 2469 */ 2470static int 2471mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2472{ 2473 int i; 2474 2475 debug_called(2); |
2476 MLX_IO_ASSERT_LOCKED(sc); |
|
2406 2407 /* ready for our command? */ 2408 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) { 2409 /* copy mailbox data to window */ 2410 for (i = 0; i < 13; i++) 2411 MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2412 2413 /* post command */ 2414 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL); 2415 return(1); 2416 } 2417 return(0); 2418} 2419 2420/******************************************************************************** 2421 * See if a command has been completed, if so acknowledge its completion 2422 * and recover the slot number and status code. | 2477 2478 /* ready for our command? */ 2479 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) { 2480 /* copy mailbox data to window */ 2481 for (i = 0; i < 13; i++) 2482 MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2483 2484 /* post command */ 2485 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL); 2486 return(1); 2487 } 2488 return(0); 2489} 2490 2491/******************************************************************************** 2492 * See if a command has been completed, if so acknowledge its completion 2493 * and recover the slot number and status code. |
2423 * 2424 * Must be called at splbio or in a fashion that prevents reentry. | |
2425 */ 2426static int 2427mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2428{ 2429 2430 debug_called(2); | 2494 */ 2495static int 2496mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2497{ 2498 2499 debug_called(2); |
2500 MLX_IO_ASSERT_LOCKED(sc); |
|
2431 2432 /* status available? */ 2433 if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) { 2434 *slot = MLX_V3_GET_STATUS_IDENT(sc); /* get command identifier */ 2435 *status = MLX_V3_GET_STATUS(sc); /* get status */ 2436 2437 /* acknowledge completion */ 2438 MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL); 2439 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK); 2440 return(1); 2441 } 2442 return(0); 2443} 2444 2445/******************************************************************************** 2446 * Enable/disable interrupts as requested. (No acknowledge required) | 2501 2502 /* status available? */ 2503 if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) { 2504 *slot = MLX_V3_GET_STATUS_IDENT(sc); /* get command identifier */ 2505 *status = MLX_V3_GET_STATUS(sc); /* get status */ 2506 2507 /* acknowledge completion */ 2508 MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL); 2509 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK); 2510 return(1); 2511 } 2512 return(0); 2513} 2514 2515/******************************************************************************** 2516 * Enable/disable interrupts as requested. (No acknowledge required) |
2447 * 2448 * Must be called at splbio or in a fashion that prevents reentry. | |
2449 */ 2450static void 2451mlx_v3_intaction(struct mlx_softc *sc, int action) 2452{ 2453 debug_called(1); | 2517 */ 2518static void 2519mlx_v3_intaction(struct mlx_softc *sc, int action) 2520{ 2521 debug_called(1); |
2522 MLX_IO_ASSERT_LOCKED(sc); |
|
2454 2455 switch(action) { 2456 case MLX_INTACTION_DISABLE: 2457 MLX_V3_PUT_IER(sc, 0); 2458 sc->mlx_state &= ~MLX_STATE_INTEN; 2459 break; 2460 case MLX_INTACTION_ENABLE: 2461 MLX_V3_PUT_IER(sc, 1); 2462 sc->mlx_state |= MLX_STATE_INTEN; 2463 break; 2464 } 2465} 2466 2467/******************************************************************************** 2468 * Poll for firmware error codes during controller initialisation. 2469 * Returns 0 if initialisation is complete, 1 if still in progress but no 2470 * error has been fetched, 2 if an error has been retrieved. 2471 */ 2472static int | 2523 2524 switch(action) { 2525 case MLX_INTACTION_DISABLE: 2526 MLX_V3_PUT_IER(sc, 0); 2527 sc->mlx_state &= ~MLX_STATE_INTEN; 2528 break; 2529 case MLX_INTACTION_ENABLE: 2530 MLX_V3_PUT_IER(sc, 1); 2531 sc->mlx_state |= MLX_STATE_INTEN; 2532 break; 2533 } 2534} 2535 2536/******************************************************************************** 2537 * Poll for firmware error codes during controller initialisation. 2538 * Returns 0 if initialisation is complete, 1 if still in progress but no 2539 * error has been fetched, 2 if an error has been retrieved. 2540 */ 2541static int |
2473mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2) | 2542mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, 2543 int first) |
2474{ 2475 u_int8_t fwerror; | 2544{ 2545 u_int8_t fwerror; |
2476 static int initted = 0; | |
2477 2478 debug_called(2); 2479 2480 /* first time around, clear any hardware completion status */ | 2546 2547 debug_called(2); 2548 2549 /* first time around, clear any hardware completion status */ |
2481 if (!initted) { | 2550 if (first) { |
2482 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK); 2483 DELAY(1000); | 2551 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK); 2552 DELAY(1000); |
2484 initted = 1; | |
2485 } 2486 2487 /* init in progress? */ 2488 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY)) 2489 return(0); 2490 2491 /* test error value */ 2492 fwerror = MLX_V3_GET_FWERROR(sc); --- 15 unchanged lines hidden (view full) --- 2508 ******************************************************************************** 2509 Type 4 interface accessor methods 2510 ******************************************************************************** 2511 ********************************************************************************/ 2512 2513/******************************************************************************** 2514 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2515 * (the controller is not ready to take a command). | 2553 } 2554 2555 /* init in progress? */ 2556 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY)) 2557 return(0); 2558 2559 /* test error value */ 2560 fwerror = MLX_V3_GET_FWERROR(sc); --- 15 unchanged lines hidden (view full) --- 2576 ******************************************************************************** 2577 Type 4 interface accessor methods 2578 ******************************************************************************** 2579 ********************************************************************************/ 2580 2581/******************************************************************************** 2582 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2583 * (the controller is not ready to take a command). |
2516 * 2517 * Must be called at splbio or in a fashion that prevents reentry. | |
2518 */ 2519static int 2520mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2521{ 2522 int i; 2523 2524 debug_called(2); | 2584 */ 2585static int 2586mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2587{ 2588 int i; 2589 2590 debug_called(2); |
2591 MLX_IO_ASSERT_LOCKED(sc); |
|
2525 2526 /* ready for our command? */ 2527 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) { 2528 /* copy mailbox data to window */ 2529 for (i = 0; i < 13; i++) 2530 MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2531 2532 /* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */ | 2592 2593 /* ready for our command? */ 2594 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) { 2595 /* copy mailbox data to window */ 2596 for (i = 0; i < 13; i++) 2597 MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2598 2599 /* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */ |
2533 bus_space_barrier(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH, | 2600 bus_barrier(sc->mlx_mem, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH, |
2534 BUS_SPACE_BARRIER_WRITE); 2535 2536 /* post command */ 2537 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD); 2538 return(1); 2539 } 2540 return(0); 2541} 2542 2543/******************************************************************************** 2544 * See if a command has been completed, if so acknowledge its completion 2545 * and recover the slot number and status code. | 2601 BUS_SPACE_BARRIER_WRITE); 2602 2603 /* post command */ 2604 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD); 2605 return(1); 2606 } 2607 return(0); 2608} 2609 2610/******************************************************************************** 2611 * See if a command has been completed, if so acknowledge its completion 2612 * and recover the slot number and status code. |
2546 * 2547 * Must be called at splbio or in a fashion that prevents reentry. | |
2548 */ 2549static int 2550mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2551{ 2552 2553 debug_called(2); | 2613 */ 2614static int 2615mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2616{ 2617 2618 debug_called(2); |
2619 MLX_IO_ASSERT_LOCKED(sc); |
|
2554 2555 /* status available? */ 2556 if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) { 2557 *slot = MLX_V4_GET_STATUS_IDENT(sc); /* get command identifier */ 2558 *status = MLX_V4_GET_STATUS(sc); /* get status */ 2559 2560 /* acknowledge completion */ 2561 MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK); 2562 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK); 2563 return(1); 2564 } 2565 return(0); 2566} 2567 2568/******************************************************************************** 2569 * Enable/disable interrupts as requested. | 2620 2621 /* status available? */ 2622 if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) { 2623 *slot = MLX_V4_GET_STATUS_IDENT(sc); /* get command identifier */ 2624 *status = MLX_V4_GET_STATUS(sc); /* get status */ 2625 2626 /* acknowledge completion */ 2627 MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK); 2628 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK); 2629 return(1); 2630 } 2631 return(0); 2632} 2633 2634/******************************************************************************** 2635 * Enable/disable interrupts as requested. |
2570 * 2571 * Must be called at splbio or in a fashion that prevents reentry. | |
2572 */ 2573static void 2574mlx_v4_intaction(struct mlx_softc *sc, int action) 2575{ 2576 debug_called(1); | 2636 */ 2637static void 2638mlx_v4_intaction(struct mlx_softc *sc, int action) 2639{ 2640 debug_called(1); |
2641 MLX_IO_ASSERT_LOCKED(sc); |
|
2577 2578 switch(action) { 2579 case MLX_INTACTION_DISABLE: 2580 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT); 2581 sc->mlx_state &= ~MLX_STATE_INTEN; 2582 break; 2583 case MLX_INTACTION_ENABLE: 2584 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT); 2585 sc->mlx_state |= MLX_STATE_INTEN; 2586 break; 2587 } 2588} 2589 2590/******************************************************************************** 2591 * Poll for firmware error codes during controller initialisation. 2592 * Returns 0 if initialisation is complete, 1 if still in progress but no 2593 * error has been fetched, 2 if an error has been retrieved. 2594 */ 2595static int | 2642 2643 switch(action) { 2644 case MLX_INTACTION_DISABLE: 2645 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT); 2646 sc->mlx_state &= ~MLX_STATE_INTEN; 2647 break; 2648 case MLX_INTACTION_ENABLE: 2649 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT); 2650 sc->mlx_state |= MLX_STATE_INTEN; 2651 break; 2652 } 2653} 2654 2655/******************************************************************************** 2656 * Poll for firmware error codes during controller initialisation. 2657 * Returns 0 if initialisation is complete, 1 if still in progress but no 2658 * error has been fetched, 2 if an error has been retrieved. 2659 */ 2660static int |
2596mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2) | 2661mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, 2662 int first) |
2597{ 2598 u_int8_t fwerror; | 2663{ 2664 u_int8_t fwerror; |
2599 static int initted = 0; | |
2600 2601 debug_called(2); 2602 2603 /* first time around, clear any hardware completion status */ | 2665 2666 debug_called(2); 2667 2668 /* first time around, clear any hardware completion status */ |
2604 if (!initted) { | 2669 if (first) { |
2605 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK); 2606 DELAY(1000); | 2670 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK); 2671 DELAY(1000); |
2607 initted = 1; | |
2608 } 2609 2610 /* init in progress? */ 2611 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY)) 2612 return(0); 2613 2614 /* test error value */ 2615 fwerror = MLX_V4_GET_FWERROR(sc); --- 15 unchanged lines hidden (view full) --- 2631 ******************************************************************************** 2632 Type 5 interface accessor methods 2633 ******************************************************************************** 2634 ********************************************************************************/ 2635 2636/******************************************************************************** 2637 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2638 * (the controller is not ready to take a command). | 2672 } 2673 2674 /* init in progress? */ 2675 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY)) 2676 return(0); 2677 2678 /* test error value */ 2679 fwerror = MLX_V4_GET_FWERROR(sc); --- 15 unchanged lines hidden (view full) --- 2695 ******************************************************************************** 2696 Type 5 interface accessor methods 2697 ******************************************************************************** 2698 ********************************************************************************/ 2699 2700/******************************************************************************** 2701 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2702 * (the controller is not ready to take a command). |
2639 * 2640 * Must be called at splbio or in a fashion that prevents reentry. | |
2641 */ 2642static int 2643mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2644{ 2645 int i; 2646 2647 debug_called(2); | 2703 */ 2704static int 2705mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2706{ 2707 int i; 2708 2709 debug_called(2); |
2710 MLX_IO_ASSERT_LOCKED(sc); |
|
2648 2649 /* ready for our command? */ 2650 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) { 2651 /* copy mailbox data to window */ 2652 for (i = 0; i < 13; i++) 2653 MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2654 2655 /* post command */ 2656 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD); 2657 return(1); 2658 } 2659 return(0); 2660} 2661 2662/******************************************************************************** 2663 * See if a command has been completed, if so acknowledge its completion 2664 * and recover the slot number and status code. | 2711 2712 /* ready for our command? */ 2713 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) { 2714 /* copy mailbox data to window */ 2715 for (i = 0; i < 13; i++) 2716 MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2717 2718 /* post command */ 2719 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD); 2720 return(1); 2721 } 2722 return(0); 2723} 2724 2725/******************************************************************************** 2726 * See if a command has been completed, if so acknowledge its completion 2727 * and recover the slot number and status code. |
2665 * 2666 * Must be called at splbio or in a fashion that prevents reentry. | |
2667 */ 2668static int 2669mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2670{ 2671 2672 debug_called(2); | 2728 */ 2729static int 2730mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2731{ 2732 2733 debug_called(2); |
2734 MLX_IO_ASSERT_LOCKED(sc); |
|
2673 2674 /* status available? */ 2675 if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) { 2676 *slot = MLX_V5_GET_STATUS_IDENT(sc); /* get command identifier */ 2677 *status = MLX_V5_GET_STATUS(sc); /* get status */ 2678 2679 /* acknowledge completion */ 2680 MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK); 2681 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK); 2682 return(1); 2683 } 2684 return(0); 2685} 2686 2687/******************************************************************************** 2688 * Enable/disable interrupts as requested. | 2735 2736 /* status available? */ 2737 if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) { 2738 *slot = MLX_V5_GET_STATUS_IDENT(sc); /* get command identifier */ 2739 *status = MLX_V5_GET_STATUS(sc); /* get status */ 2740 2741 /* acknowledge completion */ 2742 MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK); 2743 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK); 2744 return(1); 2745 } 2746 return(0); 2747} 2748 2749/******************************************************************************** 2750 * Enable/disable interrupts as requested. |
2689 * 2690 * Must be called at splbio or in a fashion that prevents reentry. | |
2691 */ 2692static void 2693mlx_v5_intaction(struct mlx_softc *sc, int action) 2694{ 2695 debug_called(1); | 2751 */ 2752static void 2753mlx_v5_intaction(struct mlx_softc *sc, int action) 2754{ 2755 debug_called(1); |
2756 MLX_IO_ASSERT_LOCKED(sc); |
|
2696 2697 switch(action) { 2698 case MLX_INTACTION_DISABLE: 2699 MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT); 2700 sc->mlx_state &= ~MLX_STATE_INTEN; 2701 break; 2702 case MLX_INTACTION_ENABLE: 2703 MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT); 2704 sc->mlx_state |= MLX_STATE_INTEN; 2705 break; 2706 } 2707} 2708 2709/******************************************************************************** 2710 * Poll for firmware error codes during controller initialisation. 2711 * Returns 0 if initialisation is complete, 1 if still in progress but no 2712 * error has been fetched, 2 if an error has been retrieved. 2713 */ 2714static int | 2757 2758 switch(action) { 2759 case MLX_INTACTION_DISABLE: 2760 MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT); 2761 sc->mlx_state &= ~MLX_STATE_INTEN; 2762 break; 2763 case MLX_INTACTION_ENABLE: 2764 MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT); 2765 sc->mlx_state |= MLX_STATE_INTEN; 2766 break; 2767 } 2768} 2769 2770/******************************************************************************** 2771 * Poll for firmware error codes during controller initialisation. 2772 * Returns 0 if initialisation is complete, 1 if still in progress but no 2773 * error has been fetched, 2 if an error has been retrieved. 2774 */ 2775static int |
2715mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2) | 2776mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, 2777 int first) |
2716{ 2717 u_int8_t fwerror; | 2778{ 2779 u_int8_t fwerror; |
2718 static int initted = 0; | |
2719 2720 debug_called(2); 2721 2722 /* first time around, clear any hardware completion status */ | 2780 2781 debug_called(2); 2782 2783 /* first time around, clear any hardware completion status */ |
2723 if (!initted) { | 2784 if (first) { |
2724 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK); 2725 DELAY(1000); | 2785 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK); 2786 DELAY(1000); |
2726 initted = 1; | |
2727 } 2728 2729 /* init in progress? */ 2730 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE) 2731 return(0); 2732 2733 /* test for error value */ 2734 fwerror = MLX_V5_GET_FWERROR(sc); --- 252 unchanged lines hidden (view full) --- 2987 * Find the disk whose unit number is (unit) on this controller 2988 */ 2989static struct mlx_sysdrive * 2990mlx_findunit(struct mlx_softc *sc, int unit) 2991{ 2992 int i; 2993 2994 /* search system drives */ | 2787 } 2788 2789 /* init in progress? */ 2790 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE) 2791 return(0); 2792 2793 /* test for error value */ 2794 fwerror = MLX_V5_GET_FWERROR(sc); --- 252 unchanged lines hidden (view full) --- 3047 * Find the disk whose unit number is (unit) on this controller 3048 */ 3049static struct mlx_sysdrive * 3050mlx_findunit(struct mlx_softc *sc, int unit) 3051{ 3052 int i; 3053 3054 /* search system drives */ |
3055 MLX_CONFIG_ASSERT_LOCKED(sc); |
|
2995 for (i = 0; i < MLX_MAXDRIVES; i++) { 2996 /* is this one attached? */ 2997 if (sc->mlx_sysdrive[i].ms_disk != 0) { 2998 /* is this the one? */ 2999 if (unit == device_get_unit(sc->mlx_sysdrive[i].ms_disk)) 3000 return(&sc->mlx_sysdrive[i]); 3001 } 3002 } 3003 return(NULL); 3004} | 3056 for (i = 0; i < MLX_MAXDRIVES; i++) { 3057 /* is this one attached? */ 3058 if (sc->mlx_sysdrive[i].ms_disk != 0) { 3059 /* is this the one? */ 3060 if (unit == device_get_unit(sc->mlx_sysdrive[i].ms_disk)) 3061 return(&sc->mlx_sysdrive[i]); 3062 } 3063 } 3064 return(NULL); 3065} |