Deleted Added
full compact
mlx.c (55093) mlx.c (58188)
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 55093 1999-12-25 01:45:22Z msmith $
26 * $FreeBSD: head/sys/dev/mlx/mlx.c 58188 2000-03-18 02:01:37Z msmith $
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/malloc.h>
36#include <sys/kernel.h>
37
38#include <sys/buf.h>
39#include <sys/bus.h>
40#include <sys/conf.h>
41#include <sys/devicestat.h>
42#include <sys/disk.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/malloc.h>
36#include <sys/kernel.h>
37
38#include <sys/buf.h>
39#include <sys/bus.h>
40#include <sys/conf.h>
41#include <sys/devicestat.h>
42#include <sys/disk.h>
43#include <sys/stat.h>
43
44#include <machine/resource.h>
45#include <machine/bus.h>
46#include <machine/clock.h>
47#include <sys/rman.h>
48
49#include <dev/mlx/mlxio.h>
50#include <dev/mlx/mlxvar.h>
51#include <dev/mlx/mlxreg.h>
52
44
45#include <machine/resource.h>
46#include <machine/bus.h>
47#include <machine/clock.h>
48#include <sys/rman.h>
49
50#include <dev/mlx/mlxio.h>
51#include <dev/mlx/mlxvar.h>
52#include <dev/mlx/mlxreg.h>
53
53#if 0
54#define debug(fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args)
55#else
56#define debug(fmt, args...)
57#endif
58
59#define MLX_CDEV_MAJOR 130
60
61static struct cdevsw mlx_cdevsw = {
62 /* open */ mlx_open,
63 /* close */ mlx_close,
64 /* read */ noread,
65 /* write */ nowrite,
66 /* ioctl */ mlx_ioctl,
67 /* poll */ nopoll,
68 /* mmap */ nommap,
69 /* strategy */ nostrategy,
70 /* name */ "mlx",
71 /* maj */ MLX_CDEV_MAJOR,
72 /* dump */ nodump,
73 /* psize */ nopsize,
74 /* flags */ 0,
75 /* bmaj */ -1
76};
77
54#define MLX_CDEV_MAJOR 130
55
56static struct cdevsw mlx_cdevsw = {
57 /* open */ mlx_open,
58 /* close */ mlx_close,
59 /* read */ noread,
60 /* write */ nowrite,
61 /* ioctl */ mlx_ioctl,
62 /* poll */ nopoll,
63 /* mmap */ nommap,
64 /* strategy */ nostrategy,
65 /* name */ "mlx",
66 /* maj */ MLX_CDEV_MAJOR,
67 /* dump */ nodump,
68 /* psize */ nopsize,
69 /* flags */ 0,
70 /* bmaj */ -1
71};
72
78static int cdev_registered = 0;
79devclass_t mlx_devclass;
80
81/*
82 * Per-interface accessor methods
83 */
84static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
85static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
86static void mlx_v3_intaction(struct mlx_softc *sc, int action);
73devclass_t mlx_devclass;
74
75/*
76 * Per-interface accessor methods
77 */
78static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
79static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
80static void mlx_v3_intaction(struct mlx_softc *sc, int action);
81static int mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2);
87
88static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
89static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
90static void mlx_v4_intaction(struct mlx_softc *sc, int action);
82
83static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
84static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
85static void mlx_v4_intaction(struct mlx_softc *sc, int action);
86static int mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2);
91
92static int mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
93static int mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
94static void mlx_v5_intaction(struct mlx_softc *sc, int action);
87
88static int mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
89static int mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
90static void mlx_v5_intaction(struct mlx_softc *sc, int action);
91static int mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2);
95
96/*
97 * Status monitoring
98 */
99static void mlx_periodic(void *data);
100static void mlx_periodic_enquiry(struct mlx_command *mc);
101static void mlx_periodic_eventlog_poll(struct mlx_softc *sc);
102static void mlx_periodic_eventlog_respond(struct mlx_command *mc);

--- 35 unchanged lines hidden (view full) ---

138static int mlx_done(struct mlx_softc *sc);
139static void mlx_complete(struct mlx_softc *sc);
140
141/*
142 * Debugging.
143 */
144static char *mlx_diagnose_command(struct mlx_command *mc);
145static void mlx_describe_controller(struct mlx_softc *sc);
92
93/*
94 * Status monitoring
95 */
96static void mlx_periodic(void *data);
97static void mlx_periodic_enquiry(struct mlx_command *mc);
98static void mlx_periodic_eventlog_poll(struct mlx_softc *sc);
99static void mlx_periodic_eventlog_respond(struct mlx_command *mc);

--- 35 unchanged lines hidden (view full) ---

135static int mlx_done(struct mlx_softc *sc);
136static void mlx_complete(struct mlx_softc *sc);
137
138/*
139 * Debugging.
140 */
141static char *mlx_diagnose_command(struct mlx_command *mc);
142static void mlx_describe_controller(struct mlx_softc *sc);
143static int mlx_fw_message(struct mlx_softc *sc, int status, int param1, int param2);
146
144
147
148/*
149 * Utility functions.
150 */
151static struct mlx_sysdrive *mlx_findunit(struct mlx_softc *sc, int unit);
152
153/********************************************************************************
154 ********************************************************************************
155 Public Interfaces

--- 5 unchanged lines hidden (view full) ---

161 *
162 * Should not be called if the controller is active.
163 */
164void
165mlx_free(struct mlx_softc *sc)
166{
167 struct mlx_command *mc;
168
145/*
146 * Utility functions.
147 */
148static struct mlx_sysdrive *mlx_findunit(struct mlx_softc *sc, int unit);
149
150/********************************************************************************
151 ********************************************************************************
152 Public Interfaces

--- 5 unchanged lines hidden (view full) ---

158 *
159 * Should not be called if the controller is active.
160 */
161void
162mlx_free(struct mlx_softc *sc)
163{
164 struct mlx_command *mc;
165
169 debug("called");
166 debug_called(1);
170
171 /* cancel status timeout */
172 untimeout(mlx_periodic, sc, sc->mlx_timeout);
173
174 /* throw away any command buffers */
175 while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) {
176 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
177 mlx_freecmd(mc);

--- 22 unchanged lines hidden (view full) ---

200 /* release the register window mapping */
201 if (sc->mlx_mem != NULL)
202 bus_release_resource(sc->mlx_dev, SYS_RES_MEMORY,
203 (sc->mlx_iftype == MLX_IFTYPE_3) ? MLX_CFG_BASE1 : MLX_CFG_BASE0, sc->mlx_mem);
204
205 /* free controller enquiry data */
206 if (sc->mlx_enq2 != NULL)
207 free(sc->mlx_enq2, M_DEVBUF);
167
168 /* cancel status timeout */
169 untimeout(mlx_periodic, sc, sc->mlx_timeout);
170
171 /* throw away any command buffers */
172 while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) {
173 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
174 mlx_freecmd(mc);

--- 22 unchanged lines hidden (view full) ---

197 /* release the register window mapping */
198 if (sc->mlx_mem != NULL)
199 bus_release_resource(sc->mlx_dev, SYS_RES_MEMORY,
200 (sc->mlx_iftype == MLX_IFTYPE_3) ? MLX_CFG_BASE1 : MLX_CFG_BASE0, sc->mlx_mem);
201
202 /* free controller enquiry data */
203 if (sc->mlx_enq2 != NULL)
204 free(sc->mlx_enq2, M_DEVBUF);
205
206 /* destroy control device */
207 if (sc->mlx_dev_t != (dev_t)NULL)
208 destroy_dev(sc->mlx_dev_t);
208}
209
210/********************************************************************************
211 * Map the scatter/gather table into bus space
212 */
213static void
214mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
215{
216 struct mlx_softc *sc = (struct mlx_softc *)arg;
217
209}
210
211/********************************************************************************
212 * Map the scatter/gather table into bus space
213 */
214static void
215mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
216{
217 struct mlx_softc *sc = (struct mlx_softc *)arg;
218
218 debug("called");
219 debug_called(1);
219
220 /* save base of s/g table's address in bus space */
221 sc->mlx_sgbusaddr = segs->ds_addr;
222}
223
224static int
225mlx_sglist_map(struct mlx_softc *sc)
226{
227 size_t segsize;
228 int error;
229
220
221 /* save base of s/g table's address in bus space */
222 sc->mlx_sgbusaddr = segs->ds_addr;
223}
224
225static int
226mlx_sglist_map(struct mlx_softc *sc)
227{
228 size_t segsize;
229 int error;
230
230 debug("called");
231 debug_called(1);
231
232 /* destroy any existing mappings */
233 if (sc->mlx_sgtable)
234 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
235 if (sc->mlx_sg_dmat)
236 bus_dma_tag_destroy(sc->mlx_sg_dmat);
237
238 /*
239 * Create a single tag describing a region large enough to hold all of
240 * the s/g lists we will need.
241 */
232
233 /* destroy any existing mappings */
234 if (sc->mlx_sgtable)
235 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
236 if (sc->mlx_sg_dmat)
237 bus_dma_tag_destroy(sc->mlx_sg_dmat);
238
239 /*
240 * Create a single tag describing a region large enough to hold all of
241 * the s/g lists we will need.
242 */
242 segsize = sizeof(struct mlx_sgentry) * MLX_NSEG * sc->mlx_maxiop;
243 segsize = sizeof(struct mlx_sgentry) * sc->mlx_sg_nseg * sc->mlx_maxiop;
243 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */
244 1, 0, /* alignment, boundary */
245 BUS_SPACE_MAXADDR, /* lowaddr */
246 BUS_SPACE_MAXADDR, /* highaddr */
247 NULL, NULL, /* filter, filterarg */
248 segsize, 1, /* maxsize, nsegments */
249 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
250 0, /* flags */

--- 21 unchanged lines hidden (view full) ---

272}
273
274/********************************************************************************
275 * Initialise the controller and softc
276 */
277int
278mlx_attach(struct mlx_softc *sc)
279{
244 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */
245 1, 0, /* alignment, boundary */
246 BUS_SPACE_MAXADDR, /* lowaddr */
247 BUS_SPACE_MAXADDR, /* highaddr */
248 NULL, NULL, /* filter, filterarg */
249 segsize, 1, /* maxsize, nsegments */
250 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
251 0, /* flags */

--- 21 unchanged lines hidden (view full) ---

273}
274
275/********************************************************************************
276 * Initialise the controller and softc
277 */
278int
279mlx_attach(struct mlx_softc *sc)
280{
280 int rid, error, fwminor;
281 struct mlx_enquiry_old *meo;
282 int rid, error, fwminor, hscode, hserror, hsparam1, hsparam2, hsmsg;
281
283
282 debug("called");
284 debug_called(1);
283
284 /*
285 * Initialise per-controller queues.
286 */
287 TAILQ_INIT(&sc->mlx_work);
288 TAILQ_INIT(&sc->mlx_freecmds);
289 bufq_init(&sc->mlx_bufq);
290
291 /*
292 * Select accessor methods based on controller interface type.
293 */
294 switch(sc->mlx_iftype) {
285
286 /*
287 * Initialise per-controller queues.
288 */
289 TAILQ_INIT(&sc->mlx_work);
290 TAILQ_INIT(&sc->mlx_freecmds);
291 bufq_init(&sc->mlx_bufq);
292
293 /*
294 * Select accessor methods based on controller interface type.
295 */
296 switch(sc->mlx_iftype) {
297 case MLX_IFTYPE_2:
295 case MLX_IFTYPE_3:
296 sc->mlx_tryqueue = mlx_v3_tryqueue;
297 sc->mlx_findcomplete = mlx_v3_findcomplete;
298 sc->mlx_intaction = mlx_v3_intaction;
298 case MLX_IFTYPE_3:
299 sc->mlx_tryqueue = mlx_v3_tryqueue;
300 sc->mlx_findcomplete = mlx_v3_findcomplete;
301 sc->mlx_intaction = mlx_v3_intaction;
302 sc->mlx_fw_handshake = mlx_v3_fw_handshake;
303 sc->mlx_sg_nseg = MLX_NSEG_OLD;
299 break;
300 case MLX_IFTYPE_4:
301 sc->mlx_tryqueue = mlx_v4_tryqueue;
302 sc->mlx_findcomplete = mlx_v4_findcomplete;
303 sc->mlx_intaction = mlx_v4_intaction;
304 break;
305 case MLX_IFTYPE_4:
306 sc->mlx_tryqueue = mlx_v4_tryqueue;
307 sc->mlx_findcomplete = mlx_v4_findcomplete;
308 sc->mlx_intaction = mlx_v4_intaction;
309 sc->mlx_fw_handshake = mlx_v4_fw_handshake;
310 sc->mlx_sg_nseg = MLX_NSEG_NEW;
304 break;
305 case MLX_IFTYPE_5:
306 sc->mlx_tryqueue = mlx_v5_tryqueue;
307 sc->mlx_findcomplete = mlx_v5_findcomplete;
308 sc->mlx_intaction = mlx_v5_intaction;
311 break;
312 case MLX_IFTYPE_5:
313 sc->mlx_tryqueue = mlx_v5_tryqueue;
314 sc->mlx_findcomplete = mlx_v5_findcomplete;
315 sc->mlx_intaction = mlx_v5_intaction;
316 sc->mlx_fw_handshake = mlx_v5_fw_handshake;
317 sc->mlx_sg_nseg = MLX_NSEG_NEW;
309 break;
310 default:
311 device_printf(sc->mlx_dev, "attaching unsupported interface version %d\n", sc->mlx_iftype);
312 return(ENXIO); /* should never happen */
313 }
314
315 /* disable interrupts before we start talking to the controller */
316 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
317
318 /*
318 break;
319 default:
320 device_printf(sc->mlx_dev, "attaching unsupported interface version %d\n", sc->mlx_iftype);
321 return(ENXIO); /* should never happen */
322 }
323
324 /* disable interrupts before we start talking to the controller */
325 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
326
327 /*
328 * Wait for the controller to come ready, handshake with the firmware if required.
329 * This is typically only necessary on platforms where the controller BIOS does not
330 * run.
331 */
332 hsmsg = 0;
333 DELAY(1000);
334 while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2)) != 0) {
335 /* report first time around... */
336 if (hsmsg == 0) {
337 device_printf(sc->mlx_dev, "controller initialisation in progress...\n");
338 hsmsg = 1;
339 }
340 /* did we get a real message? */
341 if (hscode == 2) {
342 hscode = mlx_fw_message(sc, hserror, hsparam1, hsparam2);
343 /* fatal initialisation error? */
344 if (hscode != 0) {
345 mlx_free(sc);
346 return(ENXIO);
347 }
348 }
349 }
350 if (hsmsg == 1)
351 device_printf(sc->mlx_dev, "initialisation complete.\n");
352
353 /*
319 * Allocate and connect our interrupt.
320 */
321 rid = 0;
322 sc->mlx_irq = bus_alloc_resource(sc->mlx_dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
323 if (sc->mlx_irq == NULL) {
324 device_printf(sc->mlx_dev, "couldn't allocate interrupt\n");
325 mlx_free(sc);
326 return(ENXIO);
327 }
328 error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO, mlx_intr, sc, &sc->mlx_intr);
329 if (error) {
330 device_printf(sc->mlx_dev, "couldn't set up interrupt\n");
331 mlx_free(sc);
332 return(ENXIO);
333 }
334
335 /*
336 * Create DMA tag for mapping buffers into controller-addressable space.
337 */
354 * Allocate and connect our interrupt.
355 */
356 rid = 0;
357 sc->mlx_irq = bus_alloc_resource(sc->mlx_dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
358 if (sc->mlx_irq == NULL) {
359 device_printf(sc->mlx_dev, "couldn't allocate interrupt\n");
360 mlx_free(sc);
361 return(ENXIO);
362 }
363 error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO, mlx_intr, sc, &sc->mlx_intr);
364 if (error) {
365 device_printf(sc->mlx_dev, "couldn't set up interrupt\n");
366 mlx_free(sc);
367 return(ENXIO);
368 }
369
370 /*
371 * Create DMA tag for mapping buffers into controller-addressable space.
372 */
338 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */
339 1, 0, /* alignment, boundary */
340 BUS_SPACE_MAXADDR, /* lowaddr */
341 BUS_SPACE_MAXADDR, /* highaddr */
342 NULL, NULL, /* filter, filterarg */
343 MAXBSIZE, MLX_NSEG, /* maxsize, nsegments */
344 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
345 0, /* flags */
373 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */
374 1, 0, /* alignment, boundary */
375 BUS_SPACE_MAXADDR, /* lowaddr */
376 BUS_SPACE_MAXADDR, /* highaddr */
377 NULL, NULL, /* filter, filterarg */
378 MAXBSIZE, sc->mlx_sg_nseg, /* maxsize, nsegments */
379 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
380 0, /* flags */
346 &sc->mlx_buffer_dmat);
347 if (error != 0) {
348 device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n");
349 return(ENOMEM);
350 }
351
352 /*
353 * Create an initial set of s/g mappings.

--- 11 unchanged lines hidden (view full) ---

365 return(ENXIO);
366 }
367
368 /*
369 * We don't (yet) know where the event log is up to.
370 */
371 sc->mlx_lastevent = -1;
372
381 &sc->mlx_buffer_dmat);
382 if (error != 0) {
383 device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n");
384 return(ENOMEM);
385 }
386
387 /*
388 * Create an initial set of s/g mappings.

--- 11 unchanged lines hidden (view full) ---

400 return(ENXIO);
401 }
402
403 /*
404 * We don't (yet) know where the event log is up to.
405 */
406 sc->mlx_lastevent = -1;
407
373 /* print a little information about the controller */
374 mlx_describe_controller(sc);
375
376 /*
377 * Do quirk/feature related things.
378 */
379 fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff;
380 switch(sc->mlx_iftype) {
408 /*
409 * Do quirk/feature related things.
410 */
411 fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff;
412 switch(sc->mlx_iftype) {
413 case MLX_IFTYPE_2:
414 /* These controllers don't report the firmware version in the ENQUIRY2 response */
415 if ((meo = mlx_enquire(sc, MLX_CMD_ENQUIRY_OLD, sizeof(struct mlx_enquiry_old), NULL)) == NULL) {
416 device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n");
417 return(ENXIO);
418 }
419 sc->mlx_enq2->me_firmware_id = ('0' << 24) | (0 << 16) | (meo->me_fwminor << 8) | meo->me_fwmajor;
420 free(meo, M_DEVBUF);
421
422 /* XXX require 2.42 or better (PCI) or 2.14 or better (EISA) */
423 if (meo->me_fwminor < 42) {
424 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
425 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 2.42 or later\n");
426 }
427 break;
381 case MLX_IFTYPE_3:
382 /* XXX certify 3.52? */
383 if (fwminor < 51) {
384 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
385 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n");
386 }
387 break;
388 case MLX_IFTYPE_4:

--- 27 unchanged lines hidden (view full) ---

416
417 /*
418 * No rebuild or check is in progress.
419 */
420 sc->mlx_rebuild = -1;
421 sc->mlx_check = -1;
422
423 /*
428 case MLX_IFTYPE_3:
429 /* XXX certify 3.52? */
430 if (fwminor < 51) {
431 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
432 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n");
433 }
434 break;
435 case MLX_IFTYPE_4:

--- 27 unchanged lines hidden (view full) ---

463
464 /*
465 * No rebuild or check is in progress.
466 */
467 sc->mlx_rebuild = -1;
468 sc->mlx_check = -1;
469
470 /*
424 * Register the control device on first attach.
471 * Create the control device.
425 */
472 */
426 if (cdev_registered++ == 0)
427 cdevsw_add(&mlx_cdevsw);
473 sc->mlx_dev_t = make_dev(&mlx_cdevsw, device_get_unit(sc->mlx_dev), UID_ROOT, GID_OPERATOR,
474 S_IRUSR | S_IWUSR, "mlx%d", device_get_unit(sc->mlx_dev));
428
429 /*
430 * Start the timeout routine.
431 */
432 sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
433
475
476 /*
477 * Start the timeout routine.
478 */
479 sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
480
481 /* print a little information about the controller */
482 mlx_describe_controller(sc);
483
434 return(0);
435}
436
437/********************************************************************************
438 * Locate disk resources and attach children to them.
439 */
440void
441mlx_startup(struct mlx_softc *sc)
442{
443 struct mlx_enq_sys_drive *mes;
444 struct mlx_sysdrive *dr;
445 int i, error;
446
484 return(0);
485}
486
487/********************************************************************************
488 * Locate disk resources and attach children to them.
489 */
490void
491mlx_startup(struct mlx_softc *sc)
492{
493 struct mlx_enq_sys_drive *mes;
494 struct mlx_sysdrive *dr;
495 int i, error;
496
447 debug("called");
497 debug_called(1);
448
449 /*
450 * Scan all the system drives and attach children for those that
451 * don't currently have them.
452 */
453 mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL);
454 if (mes == NULL) {
455 device_printf(sc->mlx_dev, "error fetching drive status\n");

--- 43 unchanged lines hidden (view full) ---

499 */
500int
501mlx_detach(device_t dev)
502{
503 struct mlx_softc *sc = device_get_softc(dev);
504 struct mlxd_softc *mlxd;
505 int i, s, error;
506
498
499 /*
500 * Scan all the system drives and attach children for those that
501 * don't currently have them.
502 */
503 mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL);
504 if (mes == NULL) {
505 device_printf(sc->mlx_dev, "error fetching drive status\n");

--- 43 unchanged lines hidden (view full) ---

549 */
550int
551mlx_detach(device_t dev)
552{
553 struct mlx_softc *sc = device_get_softc(dev);
554 struct mlxd_softc *mlxd;
555 int i, s, error;
556
507 debug("called");
557 debug_called(1);
508
509 error = EBUSY;
510 s = splbio();
511 if (sc->mlx_state & MLX_STATE_OPEN)
512 goto out;
513
514 for (i = 0; i < MLX_MAXDRIVES; i++) {
515 if (sc->mlx_sysdrive[i].ms_disk != 0) {

--- 4 unchanged lines hidden (view full) ---

520 }
521 }
522 }
523 if ((error = mlx_shutdown(dev)))
524 goto out;
525
526 mlx_free(sc);
527
558
559 error = EBUSY;
560 s = splbio();
561 if (sc->mlx_state & MLX_STATE_OPEN)
562 goto out;
563
564 for (i = 0; i < MLX_MAXDRIVES; i++) {
565 if (sc->mlx_sysdrive[i].ms_disk != 0) {

--- 4 unchanged lines hidden (view full) ---

570 }
571 }
572 }
573 if ((error = mlx_shutdown(dev)))
574 goto out;
575
576 mlx_free(sc);
577
528 /*
529 * Deregister the control device on last detach.
530 */
531 if (--cdev_registered == 0)
532 cdevsw_remove(&mlx_cdevsw);
533 error = 0;
534 out:
535 splx(s);
536 return(error);
537}
538
539/********************************************************************************
540 * Bring the controller down to a dormant state and detach all child devices.

--- 6 unchanged lines hidden (view full) ---

547 * allow shutdown if any device is open.
548 */
549int
550mlx_shutdown(device_t dev)
551{
552 struct mlx_softc *sc = device_get_softc(dev);
553 int i, s, error;
554
578 error = 0;
579 out:
580 splx(s);
581 return(error);
582}
583
584/********************************************************************************
585 * Bring the controller down to a dormant state and detach all child devices.

--- 6 unchanged lines hidden (view full) ---

592 * allow shutdown if any device is open.
593 */
594int
595mlx_shutdown(device_t dev)
596{
597 struct mlx_softc *sc = device_get_softc(dev);
598 int i, s, error;
599
555 debug("called");
600 debug_called(1);
556
557 s = splbio();
558 error = 0;
559
560 sc->mlx_state |= MLX_STATE_SHUTDOWN;
561 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
562
563 /* flush controller */

--- 22 unchanged lines hidden (view full) ---

586 * Bring the controller to a quiescent state, ready for system suspend.
587 */
588int
589mlx_suspend(device_t dev)
590{
591 struct mlx_softc *sc = device_get_softc(dev);
592 int s;
593
601
602 s = splbio();
603 error = 0;
604
605 sc->mlx_state |= MLX_STATE_SHUTDOWN;
606 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
607
608 /* flush controller */

--- 22 unchanged lines hidden (view full) ---

631 * Bring the controller to a quiescent state, ready for system suspend.
632 */
633int
634mlx_suspend(device_t dev)
635{
636 struct mlx_softc *sc = device_get_softc(dev);
637 int s;
638
594 debug("called");
639 debug_called(1);
595
596 s = splbio();
597 sc->mlx_state |= MLX_STATE_SUSPEND;
598
599 /* flush controller */
600 device_printf(sc->mlx_dev, "flushing cache...");
601 printf("%s\n", mlx_flush(sc) ? "failed" : "done");
602

--- 6 unchanged lines hidden (view full) ---

609/********************************************************************************
610 * Bring the controller back to a state ready for operation.
611 */
612int
613mlx_resume(device_t dev)
614{
615 struct mlx_softc *sc = device_get_softc(dev);
616
640
641 s = splbio();
642 sc->mlx_state |= MLX_STATE_SUSPEND;
643
644 /* flush controller */
645 device_printf(sc->mlx_dev, "flushing cache...");
646 printf("%s\n", mlx_flush(sc) ? "failed" : "done");
647

--- 6 unchanged lines hidden (view full) ---

654/********************************************************************************
655 * Bring the controller back to a state ready for operation.
656 */
657int
658mlx_resume(device_t dev)
659{
660 struct mlx_softc *sc = device_get_softc(dev);
661
617 debug("called");
662 debug_called(1);
618
619 sc->mlx_state &= ~MLX_STATE_SUSPEND;
620 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
621
622 return(0);
623}
624
625/*******************************************************************************
626 * Take an interrupt, or be poked by other code to look for interrupt-worthy
627 * status.
628 */
629void
630mlx_intr(void *arg)
631{
632 struct mlx_softc *sc = (struct mlx_softc *)arg;
633
663
664 sc->mlx_state &= ~MLX_STATE_SUSPEND;
665 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
666
667 return(0);
668}
669
670/*******************************************************************************
671 * Take an interrupt, or be poked by other code to look for interrupt-worthy
672 * status.
673 */
674void
675mlx_intr(void *arg)
676{
677 struct mlx_softc *sc = (struct mlx_softc *)arg;
678
634 debug("called");
679 debug_called(1);
635
636 /* collect finished commands, queue anything waiting */
637 mlx_done(sc);
638};
639
640/*******************************************************************************
641 * Receive a buf structure from a child device and queue it on a particular
642 * disk resource, then poke the disk resource to start as much work as it can.
643 */
644int
645mlx_submit_buf(struct mlx_softc *sc, struct buf *bp)
646{
647 int s;
648
680
681 /* collect finished commands, queue anything waiting */
682 mlx_done(sc);
683};
684
685/*******************************************************************************
686 * Receive a buf structure from a child device and queue it on a particular
687 * disk resource, then poke the disk resource to start as much work as it can.
688 */
689int
690mlx_submit_buf(struct mlx_softc *sc, struct buf *bp)
691{
692 int s;
693
649 debug("called");
694 debug_called(1);
650
651 s = splbio();
652 bufq_insert_tail(&sc->mlx_bufq, bp);
653 sc->mlx_waitbufs++;
654 splx(s);
655 mlx_startio(sc);
656 return(0);
657}

--- 244 unchanged lines hidden (view full) ---

902/********************************************************************************
903 * Fire off commands to periodically check the status of connected drives.
904 */
905static void
906mlx_periodic(void *data)
907{
908 struct mlx_softc *sc = (struct mlx_softc *)data;
909
695
696 s = splbio();
697 bufq_insert_tail(&sc->mlx_bufq, bp);
698 sc->mlx_waitbufs++;
699 splx(s);
700 mlx_startio(sc);
701 return(0);
702}

--- 244 unchanged lines hidden (view full) ---

947/********************************************************************************
948 * Fire off commands to periodically check the status of connected drives.
949 */
950static void
951mlx_periodic(void *data)
952{
953 struct mlx_softc *sc = (struct mlx_softc *)data;
954
910 debug("called");
955 debug_called(1);
911
912 /*
913 * Run a bus pause?
914 */
915 if ((sc->mlx_pause.mp_which != 0) &&
916 (sc->mlx_pause.mp_when > 0) &&
917 (time_second >= sc->mlx_pause.mp_when)){
918

--- 22 unchanged lines hidden (view full) ---

941 } else if (time_second > (sc->mlx_lastpoll + 10)) {
942 sc->mlx_lastpoll = time_second;
943
944 /*
945 * Check controller status.
946 *
947 * XXX Note that this may not actually launch a command in situations of high load.
948 */
956
957 /*
958 * Run a bus pause?
959 */
960 if ((sc->mlx_pause.mp_which != 0) &&
961 (sc->mlx_pause.mp_when > 0) &&
962 (time_second >= sc->mlx_pause.mp_when)){
963

--- 22 unchanged lines hidden (view full) ---

986 } else if (time_second > (sc->mlx_lastpoll + 10)) {
987 sc->mlx_lastpoll = time_second;
988
989 /*
990 * Check controller status.
991 *
992 * XXX Note that this may not actually launch a command in situations of high load.
993 */
949 mlx_enquire(sc, MLX_CMD_ENQUIRY, sizeof(struct mlx_enquiry), mlx_periodic_enquiry);
994 mlx_enquire(sc, (sc->mlx_iftype == MLX_IFTYPE_2) ? MLX_CMD_ENQUIRY_OLD : MLX_CMD_ENQUIRY,
995 imax(sizeof(struct mlx_enquiry), sizeof(struct mlx_enquiry_old)), mlx_periodic_enquiry);
950
951 /*
952 * Check system drive status.
953 *
954 * XXX This might be better left to event-driven detection, eg. I/O to an offline
955 * drive will detect it's offline, rebuilds etc. should detect the drive is back
956 * online.
957 */

--- 17 unchanged lines hidden (view full) ---

975/********************************************************************************
976 * Handle the result of an ENQUIRY command instigated by periodic status polling.
977 */
978static void
979mlx_periodic_enquiry(struct mlx_command *mc)
980{
981 struct mlx_softc *sc = mc->mc_sc;
982
996
997 /*
998 * Check system drive status.
999 *
1000 * XXX This might be better left to event-driven detection, eg. I/O to an offline
1001 * drive will detect it's offline, rebuilds etc. should detect the drive is back
1002 * online.
1003 */

--- 17 unchanged lines hidden (view full) ---

1021/********************************************************************************
1022 * Handle the result of an ENQUIRY command instigated by periodic status polling.
1023 */
1024static void
1025mlx_periodic_enquiry(struct mlx_command *mc)
1026{
1027 struct mlx_softc *sc = mc->mc_sc;
1028
983 debug("called");
1029 debug_called(1);
984
985 /* Command completed OK? */
986 if (mc->mc_status != 0) {
1030
1031 /* Command completed OK? */
1032 if (mc->mc_status != 0) {
987 device_printf(sc->mlx_dev, "periodic enquiry failed\n");
1033 device_printf(sc->mlx_dev, "periodic enquiry failed - %s\n", mlx_diagnose_command(mc));
988 goto out;
989 }
990
991 /* respond to command */
992 switch(mc->mc_mailbox[0]) {
993 /*
1034 goto out;
1035 }
1036
1037 /* respond to command */
1038 switch(mc->mc_mailbox[0]) {
1039 /*
1040 * This is currently a bit fruitless, as we don't know how to extract the eventlog
1041 * pointer yet.
1042 */
1043 case MLX_CMD_ENQUIRY_OLD:
1044 {
1045 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data;
1046 struct mlx_enquiry_old *meo = (struct mlx_enquiry_old *)mc->mc_data;
1047 int i;
1048
1049 /* convert data in-place to new format */
1050 for (i = (sizeof(me->me_dead) / sizeof(me->me_dead[0])) - 1; i >= 0; i--) {
1051 me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan;
1052 me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ;
1053 }
1054 me->me_misc_flags = 0;
1055 me->me_rebuild_count = meo->me_rebuild_count;
1056 me->me_dead_count = meo->me_dead_count;
1057 me->me_critical_sd_count = meo->me_critical_sd_count;
1058 me->me_event_log_seq_num = 0;
1059 me->me_offline_sd_count = meo->me_offline_sd_count;
1060 me->me_max_commands = meo->me_max_commands;
1061 me->me_rebuild_flag = meo->me_rebuild_flag;
1062 me->me_fwmajor = meo->me_fwmajor;
1063 me->me_fwminor = meo->me_fwminor;
1064 me->me_status_flags = meo->me_status_flags;
1065 me->me_flash_age = meo->me_flash_age;
1066 for (i = (sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0])) - 1; i >= 0; i--) {
1067 if (i > ((sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0])) - 1)) {
1068 me->me_drvsize[i] = 0; /* drive beyond supported range */
1069 } else {
1070 me->me_drvsize[i] = meo->me_drvsize[i];
1071 }
1072 }
1073 me->me_num_sys_drvs = meo->me_num_sys_drvs;
1074 }
1075 /* FALLTHROUGH */
1076
1077 /*
994 * Generic controller status update. We could do more with this than just
995 * checking the event log.
996 */
997 case MLX_CMD_ENQUIRY:
998 {
999 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data;
1000
1001 if (sc->mlx_lastevent == -1) {
1002 /* initialise our view of the event log */
1003 sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num;
1004 } else if (me->me_event_log_seq_num != sc->mlx_lastevent) {
1005 /* record where current events are up to */
1006 sc->mlx_currevent = me->me_event_log_seq_num;
1078 * Generic controller status update. We could do more with this than just
1079 * checking the event log.
1080 */
1081 case MLX_CMD_ENQUIRY:
1082 {
1083 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data;
1084
1085 if (sc->mlx_lastevent == -1) {
1086 /* initialise our view of the event log */
1087 sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num;
1088 } else if (me->me_event_log_seq_num != sc->mlx_lastevent) {
1089 /* record where current events are up to */
1090 sc->mlx_currevent = me->me_event_log_seq_num;
1007 device_printf(sc->mlx_dev, "event log pointer was %d, now %d\n",
1008 sc->mlx_lastevent, sc->mlx_currevent);
1091 debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent);
1009
1010 /* drain new eventlog entries */
1011 mlx_periodic_eventlog_poll(sc);
1012 }
1013 break;
1014 }
1015 case MLX_CMD_ENQSYSDRIVE:
1016 {

--- 43 unchanged lines hidden (view full) ---

1060 */
1061static void
1062mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1063{
1064 struct mlx_command *mc;
1065 void *result = NULL;
1066 int error;
1067
1092
1093 /* drain new eventlog entries */
1094 mlx_periodic_eventlog_poll(sc);
1095 }
1096 break;
1097 }
1098 case MLX_CMD_ENQSYSDRIVE:
1099 {

--- 43 unchanged lines hidden (view full) ---

1143 */
1144static void
1145mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1146{
1147 struct mlx_command *mc;
1148 void *result = NULL;
1149 int error;
1150
1068 debug("called");
1151 debug_called(1);
1069
1070 /* get ourselves a command buffer */
1071 error = 1;
1072 if ((mc = mlx_alloccmd(sc)) == NULL)
1073 goto out;
1074 /* allocate the response structure */
1075 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL)
1076 goto out;

--- 47 unchanged lines hidden (view full) ---

1124
1125static void
1126mlx_periodic_eventlog_respond(struct mlx_command *mc)
1127{
1128 struct mlx_softc *sc = mc->mc_sc;
1129 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data;
1130 char *reason;
1131
1152
1153 /* get ourselves a command buffer */
1154 error = 1;
1155 if ((mc = mlx_alloccmd(sc)) == NULL)
1156 goto out;
1157 /* allocate the response structure */
1158 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL)
1159 goto out;

--- 47 unchanged lines hidden (view full) ---

1207
1208static void
1209mlx_periodic_eventlog_respond(struct mlx_command *mc)
1210{
1211 struct mlx_softc *sc = mc->mc_sc;
1212 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data;
1213 char *reason;
1214
1132 debug("called");
1215 debug_called(1);
1133
1134 sc->mlx_lastevent++; /* next message... */
1135 if (mc->mc_status == 0) {
1136
1137 /* handle event log message */
1138 switch(el->el_type) {
1139 /*
1140 * This is the only sort of message we understand at the moment.

--- 175 unchanged lines hidden (view full) ---

1316 */
1317static void *
1318mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1319{
1320 struct mlx_command *mc;
1321 void *result;
1322 int error;
1323
1216
1217 sc->mlx_lastevent++; /* next message... */
1218 if (mc->mc_status == 0) {
1219
1220 /* handle event log message */
1221 switch(el->el_type) {
1222 /*
1223 * This is the only sort of message we understand at the moment.

--- 175 unchanged lines hidden (view full) ---

1399 */
1400static void *
1401mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1402{
1403 struct mlx_command *mc;
1404 void *result;
1405 int error;
1406
1324 debug("called");
1407 debug_called(1);
1325
1326 /* get ourselves a command buffer */
1327 error = 1;
1328 result = NULL;
1329 if ((mc = mlx_alloccmd(sc)) == NULL)
1330 goto out;
1331 /* allocate the response structure */
1332 if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)

--- 49 unchanged lines hidden (view full) ---

1382 * the flush operation completes or fails.
1383 */
1384static int
1385mlx_flush(struct mlx_softc *sc)
1386{
1387 struct mlx_command *mc;
1388 int error;
1389
1408
1409 /* get ourselves a command buffer */
1410 error = 1;
1411 result = NULL;
1412 if ((mc = mlx_alloccmd(sc)) == NULL)
1413 goto out;
1414 /* allocate the response structure */
1415 if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)

--- 49 unchanged lines hidden (view full) ---

1465 * the flush operation completes or fails.
1466 */
1467static int
1468mlx_flush(struct mlx_softc *sc)
1469{
1470 struct mlx_command *mc;
1471 int error;
1472
1390 debug("called");
1473 debug_called(1);
1391
1392 /* get ourselves a command buffer */
1393 error = 1;
1394 if ((mc = mlx_alloccmd(sc)) == NULL)
1395 goto out;
1396 /* get a command slot */
1397 if (mlx_getslot(mc))
1398 goto out;

--- 25 unchanged lines hidden (view full) ---

1424 * operation has started or been refused.
1425 */
1426static int
1427mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1428{
1429 struct mlx_command *mc;
1430 int error;
1431
1474
1475 /* get ourselves a command buffer */
1476 error = 1;
1477 if ((mc = mlx_alloccmd(sc)) == NULL)
1478 goto out;
1479 /* get a command slot */
1480 if (mlx_getslot(mc))
1481 goto out;

--- 25 unchanged lines hidden (view full) ---

1507 * operation has started or been refused.
1508 */
1509static int
1510mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1511{
1512 struct mlx_command *mc;
1513 int error;
1514
1432 debug("called");
1515 debug_called(1);
1433
1434 /* get ourselves a command buffer */
1435 error = 0x10000;
1436 if ((mc = mlx_alloccmd(sc)) == NULL)
1437 goto out;
1438 /* get a command slot */
1439 if (mlx_getslot(mc))
1440 goto out;

--- 25 unchanged lines hidden (view full) ---

1466 * Interrupts need to be enabled; returns nonzero on error.
1467 */
1468static int
1469mlx_wait_command(struct mlx_command *mc)
1470{
1471 struct mlx_softc *sc = mc->mc_sc;
1472 int error, count;
1473
1516
1517 /* get ourselves a command buffer */
1518 error = 0x10000;
1519 if ((mc = mlx_alloccmd(sc)) == NULL)
1520 goto out;
1521 /* get a command slot */
1522 if (mlx_getslot(mc))
1523 goto out;

--- 25 unchanged lines hidden (view full) ---

1549 * Interrupts need to be enabled; returns nonzero on error.
1550 */
1551static int
1552mlx_wait_command(struct mlx_command *mc)
1553{
1554 struct mlx_softc *sc = mc->mc_sc;
1555 int error, count;
1556
1474 debug("called");
1557 debug_called(1);
1475
1476 mc->mc_complete = NULL;
1477 mc->mc_private = mc; /* wake us when you're done */
1478 if ((error = mlx_start(mc)) != 0)
1479 return(error);
1480
1481 count = 0;
1482 /* XXX better timeout? */
1483 while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
1484 tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz);
1485 }
1486
1487 if (mc->mc_status != 0) {
1558
1559 mc->mc_complete = NULL;
1560 mc->mc_private = mc; /* wake us when you're done */
1561 if ((error = mlx_start(mc)) != 0)
1562 return(error);
1563
1564 count = 0;
1565 /* XXX better timeout? */
1566 while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
1567 tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz);
1568 }
1569
1570 if (mc->mc_status != 0) {
1488 device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status);
1571 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1489 return(EIO);
1490 }
1491 return(0);
1492}
1493
1494
1495/********************************************************************************
1496 * Start the command (mc) and busy-wait for it to complete.
1497 *
1572 return(EIO);
1573 }
1574 return(0);
1575}
1576
1577
1578/********************************************************************************
1579 * Start the command (mc) and busy-wait for it to complete.
1580 *
1498 * Should only be used when interrupts are not available. Returns 0 on
1581 * Should only be used when interrupts can't be relied upon. Returns 0 on
1499 * success, nonzero on error.
1500 * Successfully completed commands are dequeued.
1501 */
1502static int
1503mlx_poll_command(struct mlx_command *mc)
1504{
1505 struct mlx_softc *sc = mc->mc_sc;
1506 int error, count, s;
1507
1582 * success, nonzero on error.
1583 * Successfully completed commands are dequeued.
1584 */
1585static int
1586mlx_poll_command(struct mlx_command *mc)
1587{
1588 struct mlx_softc *sc = mc->mc_sc;
1589 int error, count, s;
1590
1508 debug("called");
1591 debug_called(1);
1509
1510 mc->mc_complete = NULL;
1511 mc->mc_private = NULL; /* we will poll for it */
1512 if ((error = mlx_start(mc)) != 0)
1513 return(error);
1514
1515 count = 0;
1516 do {
1517 /* poll for completion */
1518 mlx_done(mc->mc_sc);
1592
1593 mc->mc_complete = NULL;
1594 mc->mc_private = NULL; /* we will poll for it */
1595 if ((error = mlx_start(mc)) != 0)
1596 return(error);
1597
1598 count = 0;
1599 do {
1600 /* poll for completion */
1601 mlx_done(mc->mc_sc);
1519 } while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 10000));
1602
1603 } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000));
1520 if (mc->mc_status != MLX_STATUS_BUSY) {
1521 s = splbio();
1522 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1523 splx(s);
1524 return(0);
1525 }
1526 device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status);
1527 return(EIO);
1528}
1529
1530/********************************************************************************
1531 * Pull as much work off the softc's work queue as possible and give it to the
1532 * controller. Leave a couple of slots free for emergencies.
1533 *
1534 * Must be called at splbio or in an equivalent fashion that prevents
1604 if (mc->mc_status != MLX_STATUS_BUSY) {
1605 s = splbio();
1606 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1607 splx(s);
1608 return(0);
1609 }
1610 device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status);
1611 return(EIO);
1612}
1613
1614/********************************************************************************
1615 * Pull as much work off the softc's work queue as possible and give it to the
1616 * controller. Leave a couple of slots free for emergencies.
1617 *
1618 * Must be called at splbio or in an equivalent fashion that prevents
1535 * reentry or activity on the bufq..
1619 * reentry or activity on the bufq.
1536 */
1537static void
1538mlx_startio(struct mlx_softc *sc)
1539{
1540 struct mlx_command *mc;
1541 struct mlxd_softc *mlxd;
1542 struct buf *bp;
1543 int blkcount;

--- 27 unchanged lines hidden (view full) ---

1571
1572 /* connect the buf to the command */
1573 mc->mc_complete = mlx_completeio;
1574 mc->mc_private = bp;
1575 mc->mc_data = bp->b_data;
1576 mc->mc_length = bp->b_bcount;
1577 if (bp->b_flags & B_READ) {
1578 mc->mc_flags |= MLX_CMD_DATAIN;
1620 */
1621static void
1622mlx_startio(struct mlx_softc *sc)
1623{
1624 struct mlx_command *mc;
1625 struct mlxd_softc *mlxd;
1626 struct buf *bp;
1627 int blkcount;

--- 27 unchanged lines hidden (view full) ---

1655
1656 /* connect the buf to the command */
1657 mc->mc_complete = mlx_completeio;
1658 mc->mc_private = bp;
1659 mc->mc_data = bp->b_data;
1660 mc->mc_length = bp->b_bcount;
1661 if (bp->b_flags & B_READ) {
1662 mc->mc_flags |= MLX_CMD_DATAIN;
1579 cmd = MLX_CMD_READOLDSG;
1663 cmd = MLX_CMD_READSG;
1580 } else {
1581 mc->mc_flags |= MLX_CMD_DATAOUT;
1664 } else {
1665 mc->mc_flags |= MLX_CMD_DATAOUT;
1582 cmd = MLX_CMD_WRITEOLDSG;
1666 cmd = MLX_CMD_WRITESG;
1583 }
1584
1585 /* map the command so the controller can work with it */
1586 mlx_mapcmd(mc);
1587
1588 /* build a suitable I/O command (assumes 512-byte rounded transfers) */
1589 mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
1590 driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
1591 blkcount = (bp->b_bcount + MLX_BLKSIZE - 1) / MLX_BLKSIZE;
1592
1593 if ((bp->b_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1594 device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n",
1595 bp->b_pblkno, blkcount, sc->mlx_sysdrive[driveno].ms_size);
1596
1597 /*
1598 * Build the I/O command. Note that the SG list type bits are set to zero,
1599 * denoting the format of SG list that we are using.
1600 */
1667 }
1668
1669 /* map the command so the controller can work with it */
1670 mlx_mapcmd(mc);
1671
1672 /* build a suitable I/O command (assumes 512-byte rounded transfers) */
1673 mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
1674 driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
1675 blkcount = (bp->b_bcount + MLX_BLKSIZE - 1) / MLX_BLKSIZE;
1676
1677 if ((bp->b_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1678 device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n",
1679 bp->b_pblkno, blkcount, sc->mlx_sysdrive[driveno].ms_size);
1680
1681 /*
1682 * Build the I/O command. Note that the SG list type bits are set to zero,
1683 * denoting the format of SG list that we are using.
1684 */
1601 mlx_make_type5(mc, cmd,
1602 blkcount & 0xff, /* xfer length low byte */
1603 (driveno << 3) | ((blkcount >> 8) & 0x07), /* target and length high 3 bits */
1604 bp->b_pblkno, /* physical block number */
1605 mc->mc_sgphys, /* location of SG list */
1606 mc->mc_nsgent & 0x3f); /* size of SG list (top 2 bits clear) */
1685 if (sc->mlx_iftype == MLX_IFTYPE_2) {
1686 mlx_make_type1(mc, (cmd == MLX_CMD_WRITESG) ? MLX_CMD_WRITESG_OLD : MLX_CMD_READSG_OLD,
1687 blkcount & 0xff, /* xfer length low byte */
1688 bp->b_pblkno, /* physical block number */
1689 driveno, /* target drive number */
1690 mc->mc_sgphys, /* location of SG list */
1691 mc->mc_nsgent & 0x3f); /* size of SG list (top 3 bits clear) */
1692 } else {
1693 mlx_make_type5(mc, cmd,
1694 blkcount & 0xff, /* xfer length low byte */
1695 (driveno << 3) | ((blkcount >> 8) & 0x07), /* target and length high 3 bits */
1696 bp->b_pblkno, /* physical block number */
1697 mc->mc_sgphys, /* location of SG list */
1698 mc->mc_nsgent & 0x3f); /* size of SG list (top 3 bits clear) */
1699 }
1607
1700
1608
1609 /* try to give command to controller */
1610 if (mlx_start(mc) != 0) {
1611 /* fail the command */
1612 mc->mc_status = MLX_STATUS_WEDGED;
1613 mlx_completeio(mc);
1614 }
1615 s = splbio();
1616 }

--- 33 unchanged lines hidden (view full) ---

1650 }
1651 }
1652 mlx_releasecmd(mc);
1653 mlxd_intr(bp);
1654}
1655
1656/********************************************************************************
1657 * Take a command from user-space and try to run it.
1701 /* try to give command to controller */
1702 if (mlx_start(mc) != 0) {
1703 /* fail the command */
1704 mc->mc_status = MLX_STATUS_WEDGED;
1705 mlx_completeio(mc);
1706 }
1707 s = splbio();
1708 }

--- 33 unchanged lines hidden (view full) ---

1742 }
1743 }
1744 mlx_releasecmd(mc);
1745 mlxd_intr(bp);
1746}
1747
1748/********************************************************************************
1749 * Take a command from user-space and try to run it.
1750 *
1751 * XXX Note that this can't perform very much in the way of error checking, and
1752 * as such, applications _must_ be considered trustworthy.
1753 * XXX Commands using S/G for data are not supported.
1658 */
1659static int
1660mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
1661{
1662 struct mlx_command *mc;
1754 */
1755static int
1756mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
1757{
1758 struct mlx_command *mc;
1759 struct mlx_dcdb *dcdb;
1663 void *kbuf;
1664 int error;
1665
1760 void *kbuf;
1761 int error;
1762
1763 debug_called(0);
1764
1666 kbuf = NULL;
1667 mc = NULL;
1765 kbuf = NULL;
1766 mc = NULL;
1767 dcdb = NULL;
1668 error = ENOMEM;
1768 error = ENOMEM;
1669 /* get a kernel buffer for the transfer */
1670 if (mu->mu_datasize > 0) {
1671 if ((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL)
1672 goto out;
1673 if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) < sizeof(u_int32_t)))) {
1674 error = EINVAL;
1675 goto out;
1676 }
1677 }
1678 /* get ourselves a command buffer */
1769
1770 /* get ourselves a command and copy in from user space */
1679 if ((mc = mlx_alloccmd(sc)) == NULL)
1680 goto out;
1771 if ((mc = mlx_alloccmd(sc)) == NULL)
1772 goto out;
1681
1682 /* copy the command and data */
1683 bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
1773 bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
1684 if ((mu->mu_datasize > 0) && ((error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))))
1685 goto out;
1774 debug(0, "got command buffer");
1686
1775
1776 /* if we need a buffer for data transfer, allocate one and copy in its initial contents */
1777 if (mu->mu_datasize > 0) {
1778 if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) ||
1779 (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize)))
1780 goto out;
1781 debug(0, "got kernel buffer");
1782 }
1783
1687 /* get a command slot */
1688 if (mlx_getslot(mc))
1689 goto out;
1784 /* get a command slot */
1785 if (mlx_getslot(mc))
1786 goto out;
1690
1787 debug(0, "got a slot");
1788
1691 /* map the command so the controller can see it */
1692 mc->mc_data = kbuf;
1693 mc->mc_length = mu->mu_datasize;
1694 mlx_mapcmd(mc);
1789 /* map the command so the controller can see it */
1790 mc->mc_data = kbuf;
1791 mc->mc_length = mu->mu_datasize;
1792 mlx_mapcmd(mc);
1793 debug(0, "mapped");
1695
1794
1696 /* if there's a data buffer, fix up the command */
1795 /*
1796 * If this is a passthrough SCSI command, the DCDB is packed at the
1797 * beginning of the data area. Fix up the DCDB to point to the correct physical
1798 * address and override any bufptr supplied by the caller since we know
1799 * what it's meant to be.
1800 */
1801 if (mc->mc_mailbox[0] == MLX_CMD_DIRECT_CDB) {
1802 dcdb = (struct mlx_dcdb *)kbuf;
1803 dcdb->dcdb_physaddr = mc->mc_dataphys + sizeof(*dcdb);
1804 mu->mu_bufptr = 8;
1805 }
1806
1807 /*
1808 * If there's a data buffer, fix up the command's buffer pointer.
1809 */
1697 if (mu->mu_datasize > 0) {
1810 if (mu->mu_datasize > 0) {
1698 mc->mc_mailbox[mu->mu_bufptr ] = mc->mc_length & 0xff;
1699 mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_length >> 8) & 0xff;
1700 mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_length >> 16) & 0xff;
1701 mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_length >> 24) & 0xff;
1811
1812 /* range check the pointer to physical buffer address */
1813 if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) - sizeof(u_int32_t)))) {
1814 error = EINVAL;
1815 goto out;
1816 }
1817 mc->mc_mailbox[mu->mu_bufptr ] = mc->mc_dataphys & 0xff;
1818 mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_dataphys >> 8) & 0xff;
1819 mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_dataphys >> 16) & 0xff;
1820 mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_dataphys >> 24) & 0xff;
1702 }
1821 }
1822 debug(0, "command fixup");
1703
1704 /* submit the command and wait */
1705 if ((error = mlx_wait_command(mc)) != 0)
1706 goto out;
1707
1708 /* copy out status and data */
1709 mu->mu_status = mc->mc_status;
1710 if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize))))

--- 20 unchanged lines hidden (view full) ---

1731 * 4 slots free for priority commands.
1732 */
1733static int
1734mlx_getslot(struct mlx_command *mc)
1735{
1736 struct mlx_softc *sc = mc->mc_sc;
1737 int s, slot;
1738
1823
1824 /* submit the command and wait */
1825 if ((error = mlx_wait_command(mc)) != 0)
1826 goto out;
1827
1828 /* copy out status and data */
1829 mu->mu_status = mc->mc_status;
1830 if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize))))

--- 20 unchanged lines hidden (view full) ---

1851 * 4 slots free for priority commands.
1852 */
1853static int
1854mlx_getslot(struct mlx_command *mc)
1855{
1856 struct mlx_softc *sc = mc->mc_sc;
1857 int s, slot;
1858
1739 debug("called mc %p sc %p", mc, sc);
1859 debug_called(1);
1740
1741 /* enforce slot-usage limit */
1742 if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ?
1743 sc->mlx_maxiop : sc->mlx_maxiop - 4))
1744 return(EBUSY);
1745
1746 /*
1747 * Allocate an outstanding command slot
1748 *
1749 * XXX linear search is slow
1750 */
1751 s = splbio();
1752 for (slot = 0; slot < sc->mlx_maxiop; slot++) {
1860
1861 /* enforce slot-usage limit */
1862 if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ?
1863 sc->mlx_maxiop : sc->mlx_maxiop - 4))
1864 return(EBUSY);
1865
1866 /*
1867 * Allocate an outstanding command slot
1868 *
1869 * XXX linear search is slow
1870 */
1871 s = splbio();
1872 for (slot = 0; slot < sc->mlx_maxiop; slot++) {
1753 debug("try slot %d", slot);
1873 debug(2, "try slot %d", slot);
1754 if (sc->mlx_busycmd[slot] == NULL)
1755 break;
1756 }
1757 if (slot < sc->mlx_maxiop) {
1758 sc->mlx_busycmd[slot] = mc;
1759 sc->mlx_busycmds++;
1760 }
1761 splx(s);
1762
1763 /* out of slots? */
1764 if (slot >= sc->mlx_maxiop)
1765 return(EBUSY);
1766
1874 if (sc->mlx_busycmd[slot] == NULL)
1875 break;
1876 }
1877 if (slot < sc->mlx_maxiop) {
1878 sc->mlx_busycmd[slot] = mc;
1879 sc->mlx_busycmds++;
1880 }
1881 splx(s);
1882
1883 /* out of slots? */
1884 if (slot >= sc->mlx_maxiop)
1885 return(EBUSY);
1886
1767 debug("got slot %d", slot);
1887 debug(2, "got slot %d", slot);
1768 mc->mc_slot = slot;
1769 return(0);
1770}
1771
1772/********************************************************************************
1773 * Map/unmap (mc)'s data in the controller's addressable space.
1774 */
1775static void
1776mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1777{
1778 struct mlx_command *mc = (struct mlx_command *)arg;
1779 struct mlx_softc *sc = mc->mc_sc;
1780 struct mlx_sgentry *sg;
1781 int i;
1782
1888 mc->mc_slot = slot;
1889 return(0);
1890}
1891
1892/********************************************************************************
1893 * Map/unmap (mc)'s data in the controller's addressable space.
1894 */
1895static void
1896mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1897{
1898 struct mlx_command *mc = (struct mlx_command *)arg;
1899 struct mlx_softc *sc = mc->mc_sc;
1900 struct mlx_sgentry *sg;
1901 int i;
1902
1783 debug("called");
1903 debug_called(1);
1784
1785 /* get base address of s/g table */
1904
1905 /* get base address of s/g table */
1786 sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG);
1906 sg = sc->mlx_sgtable + (mc->mc_slot * sc->mlx_sg_nseg);
1787
1788 /* save s/g table information in command */
1789 mc->mc_nsgent = nsegments;
1907
1908 /* save s/g table information in command */
1909 mc->mc_nsgent = nsegments;
1790 mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry));
1910 mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * sc->mlx_sg_nseg * sizeof(struct mlx_sgentry));
1791 mc->mc_dataphys = segs[0].ds_addr;
1792
1793 /* populate s/g table */
1794 for (i = 0; i < nsegments; i++, sg++) {
1795 sg->sg_addr = segs[i].ds_addr;
1796 sg->sg_count = segs[i].ds_len;
1797 }
1798}
1799
1800static void
1801mlx_mapcmd(struct mlx_command *mc)
1802{
1803 struct mlx_softc *sc = mc->mc_sc;
1804
1911 mc->mc_dataphys = segs[0].ds_addr;
1912
1913 /* populate s/g table */
1914 for (i = 0; i < nsegments; i++, sg++) {
1915 sg->sg_addr = segs[i].ds_addr;
1916 sg->sg_count = segs[i].ds_len;
1917 }
1918}
1919
1920static void
1921mlx_mapcmd(struct mlx_command *mc)
1922{
1923 struct mlx_softc *sc = mc->mc_sc;
1924
1805 debug("called");
1925 debug_called(1);
1806
1807 /* if the command involves data at all */
1808 if (mc->mc_data != NULL) {
1809
1810 /* map the data buffer into bus space and build the s/g list */
1811 bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length,
1812 mlx_setup_dmamap, mc, 0);
1813 if (mc->mc_flags & MLX_CMD_DATAIN)
1814 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD);
1815 if (mc->mc_flags & MLX_CMD_DATAOUT)
1816 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE);
1817 }
1818}
1819
1820static void
1821mlx_unmapcmd(struct mlx_command *mc)
1822{
1823 struct mlx_softc *sc = mc->mc_sc;
1824
1926
1927 /* if the command involves data at all */
1928 if (mc->mc_data != NULL) {
1929
1930 /* map the data buffer into bus space and build the s/g list */
1931 bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length,
1932 mlx_setup_dmamap, mc, 0);
1933 if (mc->mc_flags & MLX_CMD_DATAIN)
1934 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD);
1935 if (mc->mc_flags & MLX_CMD_DATAOUT)
1936 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE);
1937 }
1938}
1939
1940static void
1941mlx_unmapcmd(struct mlx_command *mc)
1942{
1943 struct mlx_softc *sc = mc->mc_sc;
1944
1825 debug("called");
1945 debug_called(1);
1826
1827 /* if the command involved data at all */
1828 if (mc->mc_data != NULL) {
1829
1830 if (mc->mc_flags & MLX_CMD_DATAIN)
1831 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
1832 if (mc->mc_flags & MLX_CMD_DATAOUT)
1833 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);

--- 8 unchanged lines hidden (view full) ---

1842 * Can be called at any interrupt level, with or without interrupts enabled.
1843 */
1844static int
1845mlx_start(struct mlx_command *mc)
1846{
1847 struct mlx_softc *sc = mc->mc_sc;
1848 int i, s, done;
1849
1946
1947 /* if the command involved data at all */
1948 if (mc->mc_data != NULL) {
1949
1950 if (mc->mc_flags & MLX_CMD_DATAIN)
1951 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
1952 if (mc->mc_flags & MLX_CMD_DATAOUT)
1953 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);

--- 8 unchanged lines hidden (view full) ---

1962 * Can be called at any interrupt level, with or without interrupts enabled.
1963 */
1964static int
1965mlx_start(struct mlx_command *mc)
1966{
1967 struct mlx_softc *sc = mc->mc_sc;
1968 int i, s, done;
1969
1850 debug("called");
1970 debug_called(1);
1851
1852 /* save the slot number as ident so we can handle this command when complete */
1853 mc->mc_mailbox[0x1] = mc->mc_slot;
1854
1855 /* mark the command as currently being processed */
1856 mc->mc_status = MLX_STATUS_BUSY;
1857
1858 /* set a default 60-second timeout XXX tunable? XXX not currently used */

--- 35 unchanged lines hidden (view full) ---

1894static int
1895mlx_done(struct mlx_softc *sc)
1896{
1897 struct mlx_command *mc;
1898 int s, result;
1899 u_int8_t slot;
1900 u_int16_t status;
1901
1971
1972 /* save the slot number as ident so we can handle this command when complete */
1973 mc->mc_mailbox[0x1] = mc->mc_slot;
1974
1975 /* mark the command as currently being processed */
1976 mc->mc_status = MLX_STATUS_BUSY;
1977
1978 /* set a default 60-second timeout XXX tunable? XXX not currently used */

--- 35 unchanged lines hidden (view full) ---

2014static int
2015mlx_done(struct mlx_softc *sc)
2016{
2017 struct mlx_command *mc;
2018 int s, result;
2019 u_int8_t slot;
2020 u_int16_t status;
2021
1902 debug("called");
2022 debug_called(2);
1903
1904 result = 0;
1905
1906 /* loop collecting completed commands */
1907 s = splbio();
1908 for (;;) {
1909 /* poll for a completed command's identifier and status */
1910 if (sc->mlx_findcomplete(sc, &slot, &status)) {

--- 31 unchanged lines hidden (view full) ---

1942 * Perform post-completion processing for commands on (sc).
1943 */
1944static void
1945mlx_complete(struct mlx_softc *sc)
1946{
1947 struct mlx_command *mc, *nc;
1948 int s, count;
1949
2023
2024 result = 0;
2025
2026 /* loop collecting completed commands */
2027 s = splbio();
2028 for (;;) {
2029 /* poll for a completed command's identifier and status */
2030 if (sc->mlx_findcomplete(sc, &slot, &status)) {

--- 31 unchanged lines hidden (view full) ---

2062 * Perform post-completion processing for commands on (sc).
2063 */
2064static void
2065mlx_complete(struct mlx_softc *sc)
2066{
2067 struct mlx_command *mc, *nc;
2068 int s, count;
2069
1950 debug("called");
2070 debug_called(2);
1951
1952 /* avoid reentrancy XXX might want to signal and request a restart */
1953 if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING))
1954 return;
1955
1956 s = splbio();
1957 count = 0;
1958

--- 59 unchanged lines hidden (view full) ---

2018 */
2019static struct mlx_command *
2020mlx_alloccmd(struct mlx_softc *sc)
2021{
2022 struct mlx_command *mc;
2023 int error;
2024 int s;
2025
2071
2072 /* avoid reentrancy XXX might want to signal and request a restart */
2073 if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING))
2074 return;
2075
2076 s = splbio();
2077 count = 0;
2078

--- 59 unchanged lines hidden (view full) ---

2138 */
2139static struct mlx_command *
2140mlx_alloccmd(struct mlx_softc *sc)
2141{
2142 struct mlx_command *mc;
2143 int error;
2144 int s;
2145
2026 debug("called");
2146 debug_called(1);
2027
2028 s = splbio();
2029 if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2030 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2031 splx(s);
2032
2033 /* allocate a new command buffer? */
2034 if (mc == NULL) {

--- 17 unchanged lines hidden (view full) ---

2052 * XXX It might be a good idea to limit the number of commands we save for reuse
2053 * if it's shown that this list bloats out massively.
2054 */
2055static void
2056mlx_releasecmd(struct mlx_command *mc)
2057{
2058 int s;
2059
2147
2148 s = splbio();
2149 if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2150 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2151 splx(s);
2152
2153 /* allocate a new command buffer? */
2154 if (mc == NULL) {

--- 17 unchanged lines hidden (view full) ---

2172 * XXX It might be a good idea to limit the number of commands we save for reuse
2173 * if it's shown that this list bloats out massively.
2174 */
2175static void
2176mlx_releasecmd(struct mlx_command *mc)
2177{
2178 int s;
2179
2060 debug("called");
2180 debug_called(1);
2061
2062 s = splbio();
2063 TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
2064 splx(s);
2065}
2066
2067/********************************************************************************
2068 * Permanently discard a command buffer.
2069 */
2070static void
2071mlx_freecmd(struct mlx_command *mc)
2072{
2073 struct mlx_softc *sc = mc->mc_sc;
2074
2181
2182 s = splbio();
2183 TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
2184 splx(s);
2185}
2186
2187/********************************************************************************
2188 * Permanently discard a command buffer.
2189 */
2190static void
2191mlx_freecmd(struct mlx_command *mc)
2192{
2193 struct mlx_softc *sc = mc->mc_sc;
2194
2075 debug("called");
2076
2195 debug_called(1);
2077 bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
2078 free(mc, M_DEVBUF);
2079}
2080
2081
2082/********************************************************************************
2083 ********************************************************************************
2084 Type 3 interface accessor methods

--- 6 unchanged lines hidden (view full) ---

2091 *
2092 * Must be called at splbio or in a fashion that prevents reentry.
2093 */
2094static int
2095mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2096{
2097 int i;
2098
2196 bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
2197 free(mc, M_DEVBUF);
2198}
2199
2200
2201/********************************************************************************
2202 ********************************************************************************
2203 Type 3 interface accessor methods

--- 6 unchanged lines hidden (view full) ---

2210 *
2211 * Must be called at splbio or in a fashion that prevents reentry.
2212 */
2213static int
2214mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2215{
2216 int i;
2217
2099 debug("called");
2218 debug_called(2);
2100
2101 /* ready for our command? */
2102 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) {
2103 /* copy mailbox data to window */
2104 for (i = 0; i < 13; i++)
2105 MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2106
2107 /* post command */

--- 8 unchanged lines hidden (view full) ---

2116 * and recover the slot number and status code.
2117 *
2118 * Must be called at splbio or in a fashion that prevents reentry.
2119 */
2120static int
2121mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2122{
2123
2219
2220 /* ready for our command? */
2221 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) {
2222 /* copy mailbox data to window */
2223 for (i = 0; i < 13; i++)
2224 MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2225
2226 /* post command */

--- 8 unchanged lines hidden (view full) ---

2235 * and recover the slot number and status code.
2236 *
2237 * Must be called at splbio or in a fashion that prevents reentry.
2238 */
2239static int
2240mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2241{
2242
2124 debug("called");
2243 debug_called(2);
2125
2126 /* status available? */
2127 if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) {
2128 *slot = MLX_V3_GET_STATUS_IDENT(sc); /* get command identifier */
2129 *status = MLX_V3_GET_STATUS(sc); /* get status */
2130
2131 /* acknowledge completion */
2132 MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);

--- 6 unchanged lines hidden (view full) ---

2139/********************************************************************************
2140 * Enable/disable interrupts as requested. (No acknowledge required)
2141 *
2142 * Must be called at splbio or in a fashion that prevents reentry.
2143 */
2144static void
2145mlx_v3_intaction(struct mlx_softc *sc, int action)
2146{
2244
2245 /* status available? */
2246 if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) {
2247 *slot = MLX_V3_GET_STATUS_IDENT(sc); /* get command identifier */
2248 *status = MLX_V3_GET_STATUS(sc); /* get status */
2249
2250 /* acknowledge completion */
2251 MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);

--- 6 unchanged lines hidden (view full) ---

2258/********************************************************************************
2259 * Enable/disable interrupts as requested. (No acknowledge required)
2260 *
2261 * Must be called at splbio or in a fashion that prevents reentry.
2262 */
2263static void
2264mlx_v3_intaction(struct mlx_softc *sc, int action)
2265{
2147 debug("called");
2266 debug_called(1);
2148
2149 switch(action) {
2150 case MLX_INTACTION_DISABLE:
2151 MLX_V3_PUT_IER(sc, 0);
2152 sc->mlx_state &= ~MLX_STATE_INTEN;
2153 break;
2154 case MLX_INTACTION_ENABLE:
2155 MLX_V3_PUT_IER(sc, 1);
2156 sc->mlx_state |= MLX_STATE_INTEN;
2157 break;
2158 }
2159}
2160
2267
2268 switch(action) {
2269 case MLX_INTACTION_DISABLE:
2270 MLX_V3_PUT_IER(sc, 0);
2271 sc->mlx_state &= ~MLX_STATE_INTEN;
2272 break;
2273 case MLX_INTACTION_ENABLE:
2274 MLX_V3_PUT_IER(sc, 1);
2275 sc->mlx_state |= MLX_STATE_INTEN;
2276 break;
2277 }
2278}
2279
2280/********************************************************************************
2281 * Poll for firmware error codes during controller initialisation.
2282 * Returns 0 if initialisation is complete, 1 if still in progress but no
2283 * error has been fetched, 2 if an error has been retrieved.
2284 */
2285static int
2286mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2287{
2288 u_int8_t fwerror;
2289 static int initted = 0;
2161
2290
2291 debug_called(2);
2292
2293 /* first time around, clear any hardware completion status */
2294 if (!initted) {
2295 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2296 DELAY(1000);
2297 initted = 1;
2298 }
2299
2300 /* init in progress? */
2301 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY))
2302 return(0);
2303
2304 /* test error value */
2305 fwerror = MLX_V3_GET_FWERROR(sc);
2306 if (!(fwerror & MLX_V3_FWERROR_PEND))
2307 return(1);
2308
2309 /* mask status pending bit, fetch status */
2310 *error = fwerror & ~MLX_V3_FWERROR_PEND;
2311 *param1 = MLX_V3_GET_FWERROR_PARAM1(sc);
2312 *param2 = MLX_V3_GET_FWERROR_PARAM2(sc);
2313
2314 /* acknowledge */
2315 MLX_V3_PUT_FWERROR(sc, 0);
2316
2317 return(2);
2318}
2319
2162/********************************************************************************
2163 ********************************************************************************
2164 Type 4 interface accessor methods
2165 ********************************************************************************
2166 ********************************************************************************/
2167
2168/********************************************************************************
2169 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2170 * (the controller is not ready to take a command).
2171 *
2172 * Must be called at splbio or in a fashion that prevents reentry.
2173 */
2174static int
2175mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2176{
2177 int i;
2178
2320/********************************************************************************
2321 ********************************************************************************
2322 Type 4 interface accessor methods
2323 ********************************************************************************
2324 ********************************************************************************/
2325
2326/********************************************************************************
2327 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2328 * (the controller is not ready to take a command).
2329 *
2330 * Must be called at splbio or in a fashion that prevents reentry.
2331 */
2332static int
2333mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2334{
2335 int i;
2336
2179 debug("called");
2337 debug_called(2);
2180
2181 /* ready for our command? */
2182 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
2183 /* copy mailbox data to window */
2184 for (i = 0; i < 13; i++)
2185 MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2186
2338
2339 /* ready for our command? */
2340 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
2341 /* copy mailbox data to window */
2342 for (i = 0; i < 13; i++)
2343 MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2344
2345 /* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */
2346 bus_space_barrier(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH,
2347 BUS_SPACE_BARRIER_WRITE);
2348
2187 /* post command */
2188 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
2189 return(1);
2190 }
2191 return(0);
2192}
2193
2194/********************************************************************************
2195 * See if a command has been completed, if so acknowledge its completion
2196 * and recover the slot number and status code.
2197 *
2198 * Must be called at splbio or in a fashion that prevents reentry.
2199 */
2200static int
2201mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2202{
2203
2349 /* post command */
2350 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
2351 return(1);
2352 }
2353 return(0);
2354}
2355
2356/********************************************************************************
2357 * See if a command has been completed, if so acknowledge its completion
2358 * and recover the slot number and status code.
2359 *
2360 * Must be called at splbio or in a fashion that prevents reentry.
2361 */
2362static int
2363mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2364{
2365
2204 debug("called");
2366 debug_called(2);
2205
2206 /* status available? */
2207 if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
2208 *slot = MLX_V4_GET_STATUS_IDENT(sc); /* get command identifier */
2209 *status = MLX_V4_GET_STATUS(sc); /* get status */
2210
2211 /* acknowledge completion */
2212 MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);

--- 6 unchanged lines hidden (view full) ---

2219/********************************************************************************
2220 * Enable/disable interrupts as requested.
2221 *
2222 * Must be called at splbio or in a fashion that prevents reentry.
2223 */
2224static void
2225mlx_v4_intaction(struct mlx_softc *sc, int action)
2226{
2367
2368 /* status available? */
2369 if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
2370 *slot = MLX_V4_GET_STATUS_IDENT(sc); /* get command identifier */
2371 *status = MLX_V4_GET_STATUS(sc); /* get status */
2372
2373 /* acknowledge completion */
2374 MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);

--- 6 unchanged lines hidden (view full) ---

2381/********************************************************************************
2382 * Enable/disable interrupts as requested.
2383 *
2384 * Must be called at splbio or in a fashion that prevents reentry.
2385 */
2386static void
2387mlx_v4_intaction(struct mlx_softc *sc, int action)
2388{
2227 debug("called");
2389 debug_called(1);
2228
2229 switch(action) {
2230 case MLX_INTACTION_DISABLE:
2231 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT);
2232 sc->mlx_state &= ~MLX_STATE_INTEN;
2233 break;
2234 case MLX_INTACTION_ENABLE:
2235 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT);
2236 sc->mlx_state |= MLX_STATE_INTEN;
2237 break;
2238 }
2239}
2240
2390
2391 switch(action) {
2392 case MLX_INTACTION_DISABLE:
2393 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT);
2394 sc->mlx_state &= ~MLX_STATE_INTEN;
2395 break;
2396 case MLX_INTACTION_ENABLE:
2397 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT);
2398 sc->mlx_state |= MLX_STATE_INTEN;
2399 break;
2400 }
2401}
2402
2403/********************************************************************************
2404 * Poll for firmware error codes during controller initialisation.
2405 * Returns 0 if initialisation is complete, 1 if still in progress but no
2406 * error has been fetched, 2 if an error has been retrieved.
2407 */
2408static int
2409mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2410{
2411 u_int8_t fwerror;
2412 static int initted = 0;
2241
2413
2414 debug_called(2);
2415
2416 /* first time around, clear any hardware completion status */
2417 if (!initted) {
2418 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2419 DELAY(1000);
2420 initted = 1;
2421 }
2422
2423 /* init in progress? */
2424 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY))
2425 return(0);
2426
2427 /* test error value */
2428 fwerror = MLX_V4_GET_FWERROR(sc);
2429 if (!(fwerror & MLX_V4_FWERROR_PEND))
2430 return(1);
2431
2432 /* mask status pending bit, fetch status */
2433 *error = fwerror & ~MLX_V4_FWERROR_PEND;
2434 *param1 = MLX_V4_GET_FWERROR_PARAM1(sc);
2435 *param2 = MLX_V4_GET_FWERROR_PARAM2(sc);
2436
2437 /* acknowledge */
2438 MLX_V4_PUT_FWERROR(sc, 0);
2439
2440 return(2);
2441}
2442
2242/********************************************************************************
2243 ********************************************************************************
2244 Type 5 interface accessor methods
2245 ********************************************************************************
2246 ********************************************************************************/
2247
2248/********************************************************************************
2249 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2250 * (the controller is not ready to take a command).
2251 *
2252 * Must be called at splbio or in a fashion that prevents reentry.
2253 */
2254static int
2255mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2256{
2257 int i;
2443/********************************************************************************
2444 ********************************************************************************
2445 Type 5 interface accessor methods
2446 ********************************************************************************
2447 ********************************************************************************/
2448
2449/********************************************************************************
2450 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2451 * (the controller is not ready to take a command).
2452 *
2453 * Must be called at splbio or in a fashion that prevents reentry.
2454 */
2455static int
2456mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2457{
2458 int i;
2258
2259 debug("called");
2260
2459
2460 debug_called(2);
2461
2261 /* ready for our command? */
2262 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) {
2263 /* copy mailbox data to window */
2264 for (i = 0; i < 13; i++)
2265 MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2462 /* ready for our command? */
2463 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) {
2464 /* copy mailbox data to window */
2465 for (i = 0; i < 13; i++)
2466 MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2266
2467
2267 /* post command */
2268 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
2269 return(1);
2270 }
2271 return(0);
2272}
2273
2274/********************************************************************************
2275 * See if a command has been completed, if so acknowledge its completion
2276 * and recover the slot number and status code.
2277 *
2278 * Must be called at splbio or in a fashion that prevents reentry.
2279 */
2280static int
2281mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2282{
2283
2468 /* post command */
2469 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
2470 return(1);
2471 }
2472 return(0);
2473}
2474
2475/********************************************************************************
2476 * See if a command has been completed, if so acknowledge its completion
2477 * and recover the slot number and status code.
2478 *
2479 * Must be called at splbio or in a fashion that prevents reentry.
2480 */
2481static int
2482mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2483{
2484
2284 debug("called");
2485 debug_called(2);
2285
2286 /* status available? */
2287 if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) {
2288 *slot = MLX_V5_GET_STATUS_IDENT(sc); /* get command identifier */
2289 *status = MLX_V5_GET_STATUS(sc); /* get status */
2290
2291 /* acknowledge completion */
2292 MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK);

--- 6 unchanged lines hidden (view full) ---

2299/********************************************************************************
2300 * Enable/disable interrupts as requested.
2301 *
2302 * Must be called at splbio or in a fashion that prevents reentry.
2303 */
2304static void
2305mlx_v5_intaction(struct mlx_softc *sc, int action)
2306{
2486
2487 /* status available? */
2488 if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) {
2489 *slot = MLX_V5_GET_STATUS_IDENT(sc); /* get command identifier */
2490 *status = MLX_V5_GET_STATUS(sc); /* get status */
2491
2492 /* acknowledge completion */
2493 MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK);

--- 6 unchanged lines hidden (view full) ---

2500/********************************************************************************
2501 * Enable/disable interrupts as requested.
2502 *
2503 * Must be called at splbio or in a fashion that prevents reentry.
2504 */
2505static void
2506mlx_v5_intaction(struct mlx_softc *sc, int action)
2507{
2307 debug("called");
2508 debug_called(1);
2308
2309 switch(action) {
2310 case MLX_INTACTION_DISABLE:
2509
2510 switch(action) {
2511 case MLX_INTACTION_DISABLE:
2311 MLX_V5_PUT_IER(sc, MLX_V5_IER_DISINT);
2512 MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT);
2312 sc->mlx_state &= ~MLX_STATE_INTEN;
2313 break;
2314 case MLX_INTACTION_ENABLE:
2513 sc->mlx_state &= ~MLX_STATE_INTEN;
2514 break;
2515 case MLX_INTACTION_ENABLE:
2315 MLX_V5_PUT_IER(sc, 0);
2516 MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT);
2316 sc->mlx_state |= MLX_STATE_INTEN;
2317 break;
2318 }
2319}
2320
2517 sc->mlx_state |= MLX_STATE_INTEN;
2518 break;
2519 }
2520}
2521
2522/********************************************************************************
2523 * Poll for firmware error codes during controller initialisation.
2524 * Returns 0 if initialisation is complete, 1 if still in progress but no
2525 * error has been fetched, 2 if an error has been retrieved.
2526 */
2527static int
2528mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2529{
2530 u_int8_t fwerror;
2531 static int initted = 0;
2321
2532
2533 debug_called(2);
2534
2535 /* first time around, clear any hardware completion status */
2536 if (!initted) {
2537 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2538 DELAY(1000);
2539 initted = 1;
2540 }
2541
2542 /* init in progress? */
2543 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE)
2544 return(0);
2545
2546 /* test for error value */
2547 fwerror = MLX_V5_GET_FWERROR(sc);
2548 if (!(fwerror & MLX_V5_FWERROR_PEND))
2549 return(1);
2550
2551 /* mask status pending bit, fetch status */
2552 *error = fwerror & ~MLX_V5_FWERROR_PEND;
2553 *param1 = MLX_V5_GET_FWERROR_PARAM1(sc);
2554 *param2 = MLX_V5_GET_FWERROR_PARAM2(sc);
2555
2556 /* acknowledge */
2557 MLX_V5_PUT_FWERROR(sc, 0xff);
2558
2559 return(2);
2560}
2561
2322/********************************************************************************
2323 ********************************************************************************
2324 Debugging
2325 ********************************************************************************
2326 ********************************************************************************/
2327
2328/********************************************************************************
2329 * Return a status message describing (mc)

--- 8 unchanged lines hidden (view full) ---

2338 "attempt to rebuild online drive", /* 06 */
2339 "new disk failed during rebuild", /* 07 */
2340 "invalid channel/target", /* 08 */
2341 "rebuild/check already in progress", /* 09 */
2342 "one or more disks are dead", /* 10 */
2343 "invalid or non-redundant drive", /* 11 */
2344 "channel is busy", /* 12 */
2345 "channel is not stopped", /* 13 */
2562/********************************************************************************
2563 ********************************************************************************
2564 Debugging
2565 ********************************************************************************
2566 ********************************************************************************/
2567
2568/********************************************************************************
2569 * Return a status message describing (mc)

--- 8 unchanged lines hidden (view full) ---

2578 "attempt to rebuild online drive", /* 06 */
2579 "new disk failed during rebuild", /* 07 */
2580 "invalid channel/target", /* 08 */
2581 "rebuild/check already in progress", /* 09 */
2582 "one or more disks are dead", /* 10 */
2583 "invalid or non-redundant drive", /* 11 */
2584 "channel is busy", /* 12 */
2585 "channel is not stopped", /* 13 */
2586 "rebuild successfully terminated", /* 14 */
2587 "unsupported command", /* 15 */
2588 "check condition received", /* 16 */
2589 "device is busy", /* 17 */
2590 "selection or command timeout", /* 18 */
2591 "command terminated abnormally", /* 19 */
2592 ""
2346};
2347
2348static struct
2349{
2350 int command;
2351 u_int16_t status;
2352 int msg;
2353} mlx_messages[] = {
2593};
2594
2595static struct
2596{
2597 int command;
2598 u_int16_t status;
2599 int msg;
2600} mlx_messages[] = {
2354 {MLX_CMD_READOLDSG, 0x0001, 1},
2355 {MLX_CMD_READOLDSG, 0x0002, 1},
2356 {MLX_CMD_READOLDSG, 0x0105, 3},
2357 {MLX_CMD_READOLDSG, 0x010c, 4},
2358 {MLX_CMD_WRITEOLDSG, 0x0001, 1},
2359 {MLX_CMD_WRITEOLDSG, 0x0002, 1},
2360 {MLX_CMD_WRITEOLDSG, 0x0105, 3},
2601 {MLX_CMD_READSG, 0x0001, 1},
2602 {MLX_CMD_READSG, 0x0002, 1},
2603 {MLX_CMD_READSG, 0x0105, 3},
2604 {MLX_CMD_READSG, 0x010c, 4},
2605 {MLX_CMD_WRITESG, 0x0001, 1},
2606 {MLX_CMD_WRITESG, 0x0002, 1},
2607 {MLX_CMD_WRITESG, 0x0105, 3},
2608 {MLX_CMD_READSG_OLD, 0x0001, 1},
2609 {MLX_CMD_READSG_OLD, 0x0002, 1},
2610 {MLX_CMD_READSG_OLD, 0x0105, 3},
2611 {MLX_CMD_WRITESG_OLD, 0x0001, 1},
2612 {MLX_CMD_WRITESG_OLD, 0x0002, 1},
2613 {MLX_CMD_WRITESG_OLD, 0x0105, 3},
2361 {MLX_CMD_LOGOP, 0x0105, 5},
2362 {MLX_CMD_REBUILDASYNC, 0x0002, 6},
2363 {MLX_CMD_REBUILDASYNC, 0x0004, 7},
2364 {MLX_CMD_REBUILDASYNC, 0x0105, 8},
2365 {MLX_CMD_REBUILDASYNC, 0x0106, 9},
2614 {MLX_CMD_LOGOP, 0x0105, 5},
2615 {MLX_CMD_REBUILDASYNC, 0x0002, 6},
2616 {MLX_CMD_REBUILDASYNC, 0x0004, 7},
2617 {MLX_CMD_REBUILDASYNC, 0x0105, 8},
2618 {MLX_CMD_REBUILDASYNC, 0x0106, 9},
2619 {MLX_CMD_REBUILDASYNC, 0x0107, 14},
2366 {MLX_CMD_CHECKASYNC, 0x0002, 10},
2367 {MLX_CMD_CHECKASYNC, 0x0105, 11},
2368 {MLX_CMD_CHECKASYNC, 0x0106, 9},
2369 {MLX_CMD_STOPCHANNEL, 0x0106, 12},
2370 {MLX_CMD_STOPCHANNEL, 0x0105, 8},
2371 {MLX_CMD_STARTCHANNEL, 0x0005, 13},
2372 {MLX_CMD_STARTCHANNEL, 0x0105, 8},
2620 {MLX_CMD_CHECKASYNC, 0x0002, 10},
2621 {MLX_CMD_CHECKASYNC, 0x0105, 11},
2622 {MLX_CMD_CHECKASYNC, 0x0106, 9},
2623 {MLX_CMD_STOPCHANNEL, 0x0106, 12},
2624 {MLX_CMD_STOPCHANNEL, 0x0105, 8},
2625 {MLX_CMD_STARTCHANNEL, 0x0005, 13},
2626 {MLX_CMD_STARTCHANNEL, 0x0105, 8},
2627 {MLX_CMD_DIRECT_CDB, 0x0002, 16},
2628 {MLX_CMD_DIRECT_CDB, 0x0008, 17},
2629 {MLX_CMD_DIRECT_CDB, 0x000e, 18},
2630 {MLX_CMD_DIRECT_CDB, 0x000f, 19},
2631 {MLX_CMD_DIRECT_CDB, 0x0105, 8},
2632
2633 {0, 0x0104, 14},
2373 {-1, 0, 0}
2374};
2375
2376static char *
2377mlx_diagnose_command(struct mlx_command *mc)
2378{
2379 static char unkmsg[80];
2380 int i;
2381
2382 /* look up message in table */
2383 for (i = 0; mlx_messages[i].command != -1; i++)
2634 {-1, 0, 0}
2635};
2636
2637static char *
2638mlx_diagnose_command(struct mlx_command *mc)
2639{
2640 static char unkmsg[80];
2641 int i;
2642
2643 /* look up message in table */
2644 for (i = 0; mlx_messages[i].command != -1; i++)
2384 if ((mc->mc_mailbox[0] == mlx_messages[i].command) &&
2645 if (((mc->mc_mailbox[0] == mlx_messages[i].command) || (mlx_messages[i].command == 0)) &&
2385 (mc->mc_status == mlx_messages[i].status))
2386 return(mlx_status_messages[mlx_messages[i].msg]);
2387
2388 sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2389 return(unkmsg);
2390}
2391
2392/*******************************************************************************
2646 (mc->mc_status == mlx_messages[i].status))
2647 return(mlx_status_messages[mlx_messages[i].msg]);
2648
2649 sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2650 return(unkmsg);
2651}
2652
2653/*******************************************************************************
2393 * Return a string describing the controller (hwid)
2654 * Print a string describing the controller (sc)
2394 */
2395static struct
2396{
2397 int hwid;
2398 char *name;
2399} mlx_controller_names[] = {
2400 {0x01, "960P/PD"},
2401 {0x02, "960PL"},

--- 20 unchanged lines hidden (view full) ---

2422 model = mlx_controller_names[i].name;
2423 break;
2424 }
2425 }
2426 if (model == NULL) {
2427 sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff);
2428 model = buf;
2429 }
2655 */
2656static struct
2657{
2658 int hwid;
2659 char *name;
2660} mlx_controller_names[] = {
2661 {0x01, "960P/PD"},
2662 {0x02, "960PL"},

--- 20 unchanged lines hidden (view full) ---

2683 model = mlx_controller_names[i].name;
2684 break;
2685 }
2686 }
2687 if (model == NULL) {
2688 sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff);
2689 model = buf;
2690 }
2430 device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%d, %dMB RAM\n",
2691 device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%02d, %dMB RAM\n",
2431 model,
2432 sc->mlx_enq2->me_actual_channels,
2433 sc->mlx_enq2->me_actual_channels > 1 ? "s" : "",
2434 sc->mlx_enq2->me_firmware_id & 0xff,
2435 (sc->mlx_enq2->me_firmware_id >> 8) & 0xff,
2436 (sc->mlx_enq2->me_firmware_id >> 24) & 0xff,
2437 (sc->mlx_enq2->me_firmware_id >> 16) & 0xff,
2438 sc->mlx_enq2->me_mem_size / (1024 * 1024));

--- 32 unchanged lines hidden (view full) ---

2471 device_printf(sc->mlx_dev, " Firmware Build Number %d\n", sc->mlx_enq2->me_firmware_build);
2472 device_printf(sc->mlx_dev, " Fault Management Type %d\n", sc->mlx_enq2->me_fault_mgmt_type);
2473 device_printf(sc->mlx_dev, " Features %b\n", sc->mlx_enq2->me_firmware_features,
2474 "\20\4Background Init\3Read Ahead\2MORE\1Cluster\n");
2475
2476 }
2477}
2478
2692 model,
2693 sc->mlx_enq2->me_actual_channels,
2694 sc->mlx_enq2->me_actual_channels > 1 ? "s" : "",
2695 sc->mlx_enq2->me_firmware_id & 0xff,
2696 (sc->mlx_enq2->me_firmware_id >> 8) & 0xff,
2697 (sc->mlx_enq2->me_firmware_id >> 24) & 0xff,
2698 (sc->mlx_enq2->me_firmware_id >> 16) & 0xff,
2699 sc->mlx_enq2->me_mem_size / (1024 * 1024));

--- 32 unchanged lines hidden (view full) ---

2732 device_printf(sc->mlx_dev, " Firmware Build Number %d\n", sc->mlx_enq2->me_firmware_build);
2733 device_printf(sc->mlx_dev, " Fault Management Type %d\n", sc->mlx_enq2->me_fault_mgmt_type);
2734 device_printf(sc->mlx_dev, " Features %b\n", sc->mlx_enq2->me_firmware_features,
2735 "\20\4Background Init\3Read Ahead\2MORE\1Cluster\n");
2736
2737 }
2738}
2739
2740/*******************************************************************************
2741 * Emit a string describing the firmware handshake status code, and return a flag
2742 * indicating whether the code represents a fatal error.
2743 *
2744 * Error code interpretations are from the Linux driver, and don't directly match
2745 * the messages printed by Mylex's BIOS. This may change if documentation on the
2746 * codes is forthcoming.
2747 */
2748static int
2749mlx_fw_message(struct mlx_softc *sc, int error, int param1, int param2)
2750{
2751 switch(error) {
2752 case 0x00:
2753 device_printf(sc->mlx_dev, "physical drive %d:%d not responding\n", param2, param1);
2754 break;
2755 case 0x08:
2756 /* we could be neater about this and give some indication when we receive more of them */
2757 if (!(sc->mlx_flags & MLX_SPINUP_REPORTED)) {
2758 device_printf(sc->mlx_dev, "spinning up drives...\n");
2759 sc->mlx_flags |= MLX_SPINUP_REPORTED;
2760 }
2761 break;
2762 case 0x30:
2763 device_printf(sc->mlx_dev, "configuration checksum error\n");
2764 break;
2765 case 0x60:
2766 device_printf(sc->mlx_dev, "mirror race recovery failed\n");
2767 break;
2768 case 0x70:
2769 device_printf(sc->mlx_dev, "mirror race recovery in progress\n");
2770 break;
2771 case 0x90:
2772 device_printf(sc->mlx_dev, "physical drive %d:%d COD mismatch\n", param2, param1);
2773 break;
2774 case 0xa0:
2775 device_printf(sc->mlx_dev, "logical drive installation aborted\n");
2776 break;
2777 case 0xb0:
2778 device_printf(sc->mlx_dev, "mirror race on a critical system drive\n");
2779 break;
2780 case 0xd0:
2781 device_printf(sc->mlx_dev, "new controller configuration found\n");
2782 break;
2783 case 0xf0:
2784 device_printf(sc->mlx_dev, "FATAL MEMORY PARITY ERROR\n");
2785 return(1);
2786 default:
2787 device_printf(sc->mlx_dev, "unknown firmware initialisation error %02x:%02x:%02x\n", error, param1, param2);
2788 break;
2789 }
2790 return(0);
2791}
2792
2479/********************************************************************************
2480 ********************************************************************************
2481 Utility Functions
2482 ********************************************************************************
2483 ********************************************************************************/
2484
2485/********************************************************************************
2486 * Find the disk whose unit number is (unit) on this controller

--- 17 unchanged lines hidden ---
2793/********************************************************************************
2794 ********************************************************************************
2795 Utility Functions
2796 ********************************************************************************
2797 ********************************************************************************/
2798
2799/********************************************************************************
2800 * Find the disk whose unit number is (unit) on this controller

--- 17 unchanged lines hidden ---