Deleted Added
full compact
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}