Deleted Added
full compact
mlx.c (59136) mlx.c (59249)
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 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
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 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
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 59136 2000-04-11 02:52:46Z msmith $
26 * $FreeBSD: head/sys/dev/mlx/mlx.c 59249 2000-04-15 05:54:02Z phk $
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>
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
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
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);
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);
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);
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);
100static void mlx_periodic_rebuild(struct mlx_command *mc);
101
102/*
103 * Channel Pause
104 */
105static void mlx_pause_action(struct mlx_softc *sc);
106static void mlx_pause_done(struct mlx_command *mc);
107
108/*
109 * Command submission.
110 */
111static void *mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize,
112 void (*complete)(struct mlx_command *mc));
113static int mlx_flush(struct mlx_softc *sc);
114static int mlx_check(struct mlx_softc *sc, int drive);
115static int mlx_rebuild(struct mlx_softc *sc, int channel, int target);
116static int mlx_wait_command(struct mlx_command *mc);
117static int mlx_poll_command(struct mlx_command *mc);
118static void mlx_startio(struct mlx_softc *sc);
119static void mlx_completeio(struct mlx_command *mc);
120static int mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu);
121
122/*
123 * Command buffer allocation.
124 */
125static struct mlx_command *mlx_alloccmd(struct mlx_softc *sc);
126static void mlx_releasecmd(struct mlx_command *mc);
127static void mlx_freecmd(struct mlx_command *mc);
128
129/*
130 * Command management.
131 */
132static int mlx_getslot(struct mlx_command *mc);
133static void mlx_mapcmd(struct mlx_command *mc);
134static void mlx_unmapcmd(struct mlx_command *mc);
135static int mlx_start(struct mlx_command *mc);
136static int mlx_done(struct mlx_softc *sc);
137static void mlx_complete(struct mlx_softc *sc);
138
139/*
140 * Debugging.
141 */
142static char *mlx_diagnose_command(struct mlx_command *mc);
143static void mlx_describe_controller(struct mlx_softc *sc);
144static int mlx_fw_message(struct mlx_softc *sc, int status, int param1, int param2);
145
146/*
147 * Utility functions.
148 */
149static struct mlx_sysdrive *mlx_findunit(struct mlx_softc *sc, int unit);
150
151/********************************************************************************
152 ********************************************************************************
153 Public Interfaces
154 ********************************************************************************
155 ********************************************************************************/
156
157/********************************************************************************
158 * Free all of the resources associated with (sc)
159 *
160 * Should not be called if the controller is active.
161 */
162void
163mlx_free(struct mlx_softc *sc)
164{
165 struct mlx_command *mc;
166
167 debug_called(1);
168
169 /* cancel status timeout */
170 untimeout(mlx_periodic, sc, sc->mlx_timeout);
171
172 /* throw away any command buffers */
173 while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) {
174 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
175 mlx_freecmd(mc);
176 }
177
178 /* destroy data-transfer DMA tag */
179 if (sc->mlx_buffer_dmat)
180 bus_dma_tag_destroy(sc->mlx_buffer_dmat);
181
182 /* free and destroy DMA memory and tag for s/g lists */
183 if (sc->mlx_sgtable)
184 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
185 if (sc->mlx_sg_dmat)
186 bus_dma_tag_destroy(sc->mlx_sg_dmat);
187
188 /* disconnect the interrupt handler */
189 if (sc->mlx_intr)
190 bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr);
191 if (sc->mlx_irq != NULL)
192 bus_release_resource(sc->mlx_dev, SYS_RES_IRQ, 0, sc->mlx_irq);
193
194 /* destroy the parent DMA tag */
195 if (sc->mlx_parent_dmat)
196 bus_dma_tag_destroy(sc->mlx_parent_dmat);
197
198 /* release the register window mapping */
199 if (sc->mlx_mem != NULL)
200 bus_release_resource(sc->mlx_dev, SYS_RES_MEMORY,
201 (sc->mlx_iftype == MLX_IFTYPE_3) ? MLX_CFG_BASE1 : MLX_CFG_BASE0, sc->mlx_mem);
202
203 /* free controller enquiry data */
204 if (sc->mlx_enq2 != NULL)
205 free(sc->mlx_enq2, M_DEVBUF);
206
207 /* destroy control device */
208 if (sc->mlx_dev_t != (dev_t)NULL)
209 destroy_dev(sc->mlx_dev_t);
210}
211
212/********************************************************************************
213 * Map the scatter/gather table into bus space
214 */
215static void
216mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
217{
218 struct mlx_softc *sc = (struct mlx_softc *)arg;
219
220 debug_called(1);
221
222 /* save base of s/g table's address in bus space */
223 sc->mlx_sgbusaddr = segs->ds_addr;
224}
225
226static int
227mlx_sglist_map(struct mlx_softc *sc)
228{
229 size_t segsize;
230 int error;
231
232 debug_called(1);
233
234 /* destroy any existing mappings */
235 if (sc->mlx_sgtable)
236 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
237 if (sc->mlx_sg_dmat)
238 bus_dma_tag_destroy(sc->mlx_sg_dmat);
239
240 /*
241 * Create a single tag describing a region large enough to hold all of
242 * the s/g lists we will need.
243 */
244 segsize = sizeof(struct mlx_sgentry) * sc->mlx_sg_nseg * sc->mlx_maxiop;
245 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */
246 1, 0, /* alignment, boundary */
247 BUS_SPACE_MAXADDR, /* lowaddr */
248 BUS_SPACE_MAXADDR, /* highaddr */
249 NULL, NULL, /* filter, filterarg */
250 segsize, 1, /* maxsize, nsegments */
251 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
252 0, /* flags */
253 &sc->mlx_sg_dmat);
254 if (error != 0) {
255 device_printf(sc->mlx_dev, "can't allocate scatter/gather DMA tag\n");
256 return(ENOMEM);
257 }
258
259 /*
260 * Allocate enough s/g maps for all commands and permanently map them into
261 * controller-visible space.
262 *
263 * XXX this assumes we can get enough space for all the s/g maps in one
264 * contiguous slab. We may need to switch to a more complex arrangement where
265 * we allocate in smaller chunks and keep a lookup table from slot to bus address.
266 */
267 error = bus_dmamem_alloc(sc->mlx_sg_dmat, (void **)&sc->mlx_sgtable, BUS_DMA_NOWAIT, &sc->mlx_sg_dmamap);
268 if (error) {
269 device_printf(sc->mlx_dev, "can't allocate s/g table\n");
270 return(ENOMEM);
271 }
272 bus_dmamap_load(sc->mlx_sg_dmat, sc->mlx_sg_dmamap, sc->mlx_sgtable, segsize, mlx_dma_map_sg, sc, 0);
273 return(0);
274}
275
276/********************************************************************************
277 * Initialise the controller and softc
278 */
279int
280mlx_attach(struct mlx_softc *sc)
281{
282 struct mlx_enquiry_old *meo;
283 int rid, error, fwminor, hscode, hserror, hsparam1, hsparam2, hsmsg;
284
285 debug_called(1);
286
287 /*
288 * Initialise per-controller queues.
289 */
290 TAILQ_INIT(&sc->mlx_work);
291 TAILQ_INIT(&sc->mlx_freecmds);
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>
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
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
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);
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);
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);
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);
100static void mlx_periodic_rebuild(struct mlx_command *mc);
101
102/*
103 * Channel Pause
104 */
105static void mlx_pause_action(struct mlx_softc *sc);
106static void mlx_pause_done(struct mlx_command *mc);
107
108/*
109 * Command submission.
110 */
111static void *mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize,
112 void (*complete)(struct mlx_command *mc));
113static int mlx_flush(struct mlx_softc *sc);
114static int mlx_check(struct mlx_softc *sc, int drive);
115static int mlx_rebuild(struct mlx_softc *sc, int channel, int target);
116static int mlx_wait_command(struct mlx_command *mc);
117static int mlx_poll_command(struct mlx_command *mc);
118static void mlx_startio(struct mlx_softc *sc);
119static void mlx_completeio(struct mlx_command *mc);
120static int mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu);
121
122/*
123 * Command buffer allocation.
124 */
125static struct mlx_command *mlx_alloccmd(struct mlx_softc *sc);
126static void mlx_releasecmd(struct mlx_command *mc);
127static void mlx_freecmd(struct mlx_command *mc);
128
129/*
130 * Command management.
131 */
132static int mlx_getslot(struct mlx_command *mc);
133static void mlx_mapcmd(struct mlx_command *mc);
134static void mlx_unmapcmd(struct mlx_command *mc);
135static int mlx_start(struct mlx_command *mc);
136static int mlx_done(struct mlx_softc *sc);
137static void mlx_complete(struct mlx_softc *sc);
138
139/*
140 * Debugging.
141 */
142static char *mlx_diagnose_command(struct mlx_command *mc);
143static void mlx_describe_controller(struct mlx_softc *sc);
144static int mlx_fw_message(struct mlx_softc *sc, int status, int param1, int param2);
145
146/*
147 * Utility functions.
148 */
149static struct mlx_sysdrive *mlx_findunit(struct mlx_softc *sc, int unit);
150
151/********************************************************************************
152 ********************************************************************************
153 Public Interfaces
154 ********************************************************************************
155 ********************************************************************************/
156
157/********************************************************************************
158 * Free all of the resources associated with (sc)
159 *
160 * Should not be called if the controller is active.
161 */
162void
163mlx_free(struct mlx_softc *sc)
164{
165 struct mlx_command *mc;
166
167 debug_called(1);
168
169 /* cancel status timeout */
170 untimeout(mlx_periodic, sc, sc->mlx_timeout);
171
172 /* throw away any command buffers */
173 while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) {
174 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
175 mlx_freecmd(mc);
176 }
177
178 /* destroy data-transfer DMA tag */
179 if (sc->mlx_buffer_dmat)
180 bus_dma_tag_destroy(sc->mlx_buffer_dmat);
181
182 /* free and destroy DMA memory and tag for s/g lists */
183 if (sc->mlx_sgtable)
184 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
185 if (sc->mlx_sg_dmat)
186 bus_dma_tag_destroy(sc->mlx_sg_dmat);
187
188 /* disconnect the interrupt handler */
189 if (sc->mlx_intr)
190 bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr);
191 if (sc->mlx_irq != NULL)
192 bus_release_resource(sc->mlx_dev, SYS_RES_IRQ, 0, sc->mlx_irq);
193
194 /* destroy the parent DMA tag */
195 if (sc->mlx_parent_dmat)
196 bus_dma_tag_destroy(sc->mlx_parent_dmat);
197
198 /* release the register window mapping */
199 if (sc->mlx_mem != NULL)
200 bus_release_resource(sc->mlx_dev, SYS_RES_MEMORY,
201 (sc->mlx_iftype == MLX_IFTYPE_3) ? MLX_CFG_BASE1 : MLX_CFG_BASE0, sc->mlx_mem);
202
203 /* free controller enquiry data */
204 if (sc->mlx_enq2 != NULL)
205 free(sc->mlx_enq2, M_DEVBUF);
206
207 /* destroy control device */
208 if (sc->mlx_dev_t != (dev_t)NULL)
209 destroy_dev(sc->mlx_dev_t);
210}
211
212/********************************************************************************
213 * Map the scatter/gather table into bus space
214 */
215static void
216mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
217{
218 struct mlx_softc *sc = (struct mlx_softc *)arg;
219
220 debug_called(1);
221
222 /* save base of s/g table's address in bus space */
223 sc->mlx_sgbusaddr = segs->ds_addr;
224}
225
226static int
227mlx_sglist_map(struct mlx_softc *sc)
228{
229 size_t segsize;
230 int error;
231
232 debug_called(1);
233
234 /* destroy any existing mappings */
235 if (sc->mlx_sgtable)
236 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
237 if (sc->mlx_sg_dmat)
238 bus_dma_tag_destroy(sc->mlx_sg_dmat);
239
240 /*
241 * Create a single tag describing a region large enough to hold all of
242 * the s/g lists we will need.
243 */
244 segsize = sizeof(struct mlx_sgentry) * sc->mlx_sg_nseg * sc->mlx_maxiop;
245 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */
246 1, 0, /* alignment, boundary */
247 BUS_SPACE_MAXADDR, /* lowaddr */
248 BUS_SPACE_MAXADDR, /* highaddr */
249 NULL, NULL, /* filter, filterarg */
250 segsize, 1, /* maxsize, nsegments */
251 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
252 0, /* flags */
253 &sc->mlx_sg_dmat);
254 if (error != 0) {
255 device_printf(sc->mlx_dev, "can't allocate scatter/gather DMA tag\n");
256 return(ENOMEM);
257 }
258
259 /*
260 * Allocate enough s/g maps for all commands and permanently map them into
261 * controller-visible space.
262 *
263 * XXX this assumes we can get enough space for all the s/g maps in one
264 * contiguous slab. We may need to switch to a more complex arrangement where
265 * we allocate in smaller chunks and keep a lookup table from slot to bus address.
266 */
267 error = bus_dmamem_alloc(sc->mlx_sg_dmat, (void **)&sc->mlx_sgtable, BUS_DMA_NOWAIT, &sc->mlx_sg_dmamap);
268 if (error) {
269 device_printf(sc->mlx_dev, "can't allocate s/g table\n");
270 return(ENOMEM);
271 }
272 bus_dmamap_load(sc->mlx_sg_dmat, sc->mlx_sg_dmamap, sc->mlx_sgtable, segsize, mlx_dma_map_sg, sc, 0);
273 return(0);
274}
275
276/********************************************************************************
277 * Initialise the controller and softc
278 */
279int
280mlx_attach(struct mlx_softc *sc)
281{
282 struct mlx_enquiry_old *meo;
283 int rid, error, fwminor, hscode, hserror, hsparam1, hsparam2, hsmsg;
284
285 debug_called(1);
286
287 /*
288 * Initialise per-controller queues.
289 */
290 TAILQ_INIT(&sc->mlx_work);
291 TAILQ_INIT(&sc->mlx_freecmds);
292 bufq_init(&sc->mlx_bufq);
292 bioq_init(&sc->mlx_bioq);
293
294 /*
295 * Select accessor methods based on controller interface type.
296 */
297 switch(sc->mlx_iftype) {
298 case MLX_IFTYPE_2:
299 case MLX_IFTYPE_3:
300 sc->mlx_tryqueue = mlx_v3_tryqueue;
301 sc->mlx_findcomplete = mlx_v3_findcomplete;
302 sc->mlx_intaction = mlx_v3_intaction;
303 sc->mlx_fw_handshake = mlx_v3_fw_handshake;
304 sc->mlx_sg_nseg = MLX_NSEG_OLD;
305 break;
306 case MLX_IFTYPE_4:
307 sc->mlx_tryqueue = mlx_v4_tryqueue;
308 sc->mlx_findcomplete = mlx_v4_findcomplete;
309 sc->mlx_intaction = mlx_v4_intaction;
310 sc->mlx_fw_handshake = mlx_v4_fw_handshake;
311 sc->mlx_sg_nseg = MLX_NSEG_NEW;
312 break;
313 case MLX_IFTYPE_5:
314 sc->mlx_tryqueue = mlx_v5_tryqueue;
315 sc->mlx_findcomplete = mlx_v5_findcomplete;
316 sc->mlx_intaction = mlx_v5_intaction;
317 sc->mlx_fw_handshake = mlx_v5_fw_handshake;
318 sc->mlx_sg_nseg = MLX_NSEG_NEW;
319 break;
320 default:
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 /*
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, "can'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, "can'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 */
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 */
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.
389 */
390 sc->mlx_maxiop = 8;
391 error = mlx_sglist_map(sc);
392 if (error != 0) {
393 device_printf(sc->mlx_dev, "can't make initial s/g list mapping\n");
394 return(error);
395 }
396
397 /* send an ENQUIRY2 to the controller */
398 if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) {
399 device_printf(sc->mlx_dev, "ENQUIRY2 failed\n");
400 return(ENXIO);
401 }
402
403 /*
404 * We don't (yet) know where the event log is up to.
405 */
406 sc->mlx_currevent = -1;
407
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;
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:
436 /* XXX certify firmware versions? */
437 if (fwminor < 6) {
438 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
439 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
440 }
441 break;
442 case MLX_IFTYPE_5:
443 if (fwminor < 7) {
444 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
445 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n");
446 }
447 break;
448 default:
449 return(ENXIO); /* should never happen */
450 }
451
452 /*
453 * Create the final set of s/g mappings now that we know how many commands
454 * the controller actually supports.
455 */
456 sc->mlx_maxiop = sc->mlx_enq2->me_max_commands;
457 error = mlx_sglist_map(sc);
458 if (error != 0) {
459 device_printf(sc->mlx_dev, "can't make permanent s/g list mapping\n");
460 return(error);
461 }
462
463 /*
464 * No user-requested background operation is in progress.
465 */
466 sc->mlx_background = 0;
467 sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
468
469 /*
470 * Create the control device.
471 */
472 sc->mlx_dev_t = make_dev(&mlx_cdevsw, device_get_unit(sc->mlx_dev), UID_ROOT, GID_OPERATOR,
473 S_IRUSR | S_IWUSR, "mlx%d", device_get_unit(sc->mlx_dev));
474
475 /*
476 * Start the timeout routine.
477 */
478 sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
479
480 /* print a little information about the controller */
481 mlx_describe_controller(sc);
482
483 return(0);
484}
485
486/********************************************************************************
487 * Locate disk resources and attach children to them.
488 */
489void
490mlx_startup(struct mlx_softc *sc)
491{
492 struct mlx_enq_sys_drive *mes;
493 struct mlx_sysdrive *dr;
494 int i, error;
495
496 debug_called(1);
497
498 /*
499 * Scan all the system drives and attach children for those that
500 * don't currently have them.
501 */
502 mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL);
503 if (mes == NULL) {
504 device_printf(sc->mlx_dev, "error fetching drive status\n");
505 return;
506 }
507
508 /* iterate over drives returned */
509 for (i = 0, dr = &sc->mlx_sysdrive[0];
510 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
511 i++, dr++) {
512 /* are we already attached to this drive? */
513 if (dr->ms_disk == 0) {
514 /* pick up drive information */
515 dr->ms_size = mes[i].sd_size;
516 dr->ms_raidlevel = mes[i].sd_raidlevel & 0xf;
517 dr->ms_state = mes[i].sd_state;
518
519 /* generate geometry information */
520 if (sc->mlx_geom == MLX_GEOM_128_32) {
521 dr->ms_heads = 128;
522 dr->ms_sectors = 32;
523 dr->ms_cylinders = dr->ms_size / (128 * 32);
524 } else { /* MLX_GEOM_255/63 */
525 dr->ms_heads = 255;
526 dr->ms_sectors = 63;
527 dr->ms_cylinders = dr->ms_size / (255 * 63);
528 }
529 dr->ms_disk = device_add_child(sc->mlx_dev, /*"mlxd"*/NULL, -1);
530 if (dr->ms_disk == 0)
531 device_printf(sc->mlx_dev, "device_add_child failed\n");
532 device_set_ivars(dr->ms_disk, dr);
533 }
534 }
535 free(mes, M_DEVBUF);
536 if ((error = bus_generic_attach(sc->mlx_dev)) != 0)
537 device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error);
538
539 /* mark controller back up */
540 sc->mlx_state &= ~MLX_STATE_SHUTDOWN;
541
542 /* enable interrupts */
543 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
544}
545
546/********************************************************************************
547 * Disconnect from the controller completely, in preparation for unload.
548 */
549int
550mlx_detach(device_t dev)
551{
552 struct mlx_softc *sc = device_get_softc(dev);
553 struct mlxd_softc *mlxd;
554 int i, s, error;
555
556 debug_called(1);
557
558 error = EBUSY;
559 s = splbio();
560 if (sc->mlx_state & MLX_STATE_OPEN)
561 goto out;
562
563 for (i = 0; i < MLX_MAXDRIVES; i++) {
564 if (sc->mlx_sysdrive[i].ms_disk != 0) {
565 mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk);
566 if (mlxd->mlxd_flags & MLXD_OPEN) { /* drive is mounted, abort detach */
567 device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't detach\n");
568 goto out;
569 }
570 }
571 }
572 if ((error = mlx_shutdown(dev)))
573 goto out;
574
575 mlx_free(sc);
576
577 error = 0;
578 out:
579 splx(s);
580 return(error);
581}
582
583/********************************************************************************
584 * Bring the controller down to a dormant state and detach all child devices.
585 *
586 * This function is called before detach, system shutdown, or before performing
587 * an operation which may add or delete system disks. (Call mlx_startup to
588 * resume normal operation.)
589 *
293
294 /*
295 * Select accessor methods based on controller interface type.
296 */
297 switch(sc->mlx_iftype) {
298 case MLX_IFTYPE_2:
299 case MLX_IFTYPE_3:
300 sc->mlx_tryqueue = mlx_v3_tryqueue;
301 sc->mlx_findcomplete = mlx_v3_findcomplete;
302 sc->mlx_intaction = mlx_v3_intaction;
303 sc->mlx_fw_handshake = mlx_v3_fw_handshake;
304 sc->mlx_sg_nseg = MLX_NSEG_OLD;
305 break;
306 case MLX_IFTYPE_4:
307 sc->mlx_tryqueue = mlx_v4_tryqueue;
308 sc->mlx_findcomplete = mlx_v4_findcomplete;
309 sc->mlx_intaction = mlx_v4_intaction;
310 sc->mlx_fw_handshake = mlx_v4_fw_handshake;
311 sc->mlx_sg_nseg = MLX_NSEG_NEW;
312 break;
313 case MLX_IFTYPE_5:
314 sc->mlx_tryqueue = mlx_v5_tryqueue;
315 sc->mlx_findcomplete = mlx_v5_findcomplete;
316 sc->mlx_intaction = mlx_v5_intaction;
317 sc->mlx_fw_handshake = mlx_v5_fw_handshake;
318 sc->mlx_sg_nseg = MLX_NSEG_NEW;
319 break;
320 default:
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 /*
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, "can'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, "can'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 */
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 */
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.
389 */
390 sc->mlx_maxiop = 8;
391 error = mlx_sglist_map(sc);
392 if (error != 0) {
393 device_printf(sc->mlx_dev, "can't make initial s/g list mapping\n");
394 return(error);
395 }
396
397 /* send an ENQUIRY2 to the controller */
398 if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) {
399 device_printf(sc->mlx_dev, "ENQUIRY2 failed\n");
400 return(ENXIO);
401 }
402
403 /*
404 * We don't (yet) know where the event log is up to.
405 */
406 sc->mlx_currevent = -1;
407
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;
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:
436 /* XXX certify firmware versions? */
437 if (fwminor < 6) {
438 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
439 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
440 }
441 break;
442 case MLX_IFTYPE_5:
443 if (fwminor < 7) {
444 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
445 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n");
446 }
447 break;
448 default:
449 return(ENXIO); /* should never happen */
450 }
451
452 /*
453 * Create the final set of s/g mappings now that we know how many commands
454 * the controller actually supports.
455 */
456 sc->mlx_maxiop = sc->mlx_enq2->me_max_commands;
457 error = mlx_sglist_map(sc);
458 if (error != 0) {
459 device_printf(sc->mlx_dev, "can't make permanent s/g list mapping\n");
460 return(error);
461 }
462
463 /*
464 * No user-requested background operation is in progress.
465 */
466 sc->mlx_background = 0;
467 sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
468
469 /*
470 * Create the control device.
471 */
472 sc->mlx_dev_t = make_dev(&mlx_cdevsw, device_get_unit(sc->mlx_dev), UID_ROOT, GID_OPERATOR,
473 S_IRUSR | S_IWUSR, "mlx%d", device_get_unit(sc->mlx_dev));
474
475 /*
476 * Start the timeout routine.
477 */
478 sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
479
480 /* print a little information about the controller */
481 mlx_describe_controller(sc);
482
483 return(0);
484}
485
486/********************************************************************************
487 * Locate disk resources and attach children to them.
488 */
489void
490mlx_startup(struct mlx_softc *sc)
491{
492 struct mlx_enq_sys_drive *mes;
493 struct mlx_sysdrive *dr;
494 int i, error;
495
496 debug_called(1);
497
498 /*
499 * Scan all the system drives and attach children for those that
500 * don't currently have them.
501 */
502 mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL);
503 if (mes == NULL) {
504 device_printf(sc->mlx_dev, "error fetching drive status\n");
505 return;
506 }
507
508 /* iterate over drives returned */
509 for (i = 0, dr = &sc->mlx_sysdrive[0];
510 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
511 i++, dr++) {
512 /* are we already attached to this drive? */
513 if (dr->ms_disk == 0) {
514 /* pick up drive information */
515 dr->ms_size = mes[i].sd_size;
516 dr->ms_raidlevel = mes[i].sd_raidlevel & 0xf;
517 dr->ms_state = mes[i].sd_state;
518
519 /* generate geometry information */
520 if (sc->mlx_geom == MLX_GEOM_128_32) {
521 dr->ms_heads = 128;
522 dr->ms_sectors = 32;
523 dr->ms_cylinders = dr->ms_size / (128 * 32);
524 } else { /* MLX_GEOM_255/63 */
525 dr->ms_heads = 255;
526 dr->ms_sectors = 63;
527 dr->ms_cylinders = dr->ms_size / (255 * 63);
528 }
529 dr->ms_disk = device_add_child(sc->mlx_dev, /*"mlxd"*/NULL, -1);
530 if (dr->ms_disk == 0)
531 device_printf(sc->mlx_dev, "device_add_child failed\n");
532 device_set_ivars(dr->ms_disk, dr);
533 }
534 }
535 free(mes, M_DEVBUF);
536 if ((error = bus_generic_attach(sc->mlx_dev)) != 0)
537 device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error);
538
539 /* mark controller back up */
540 sc->mlx_state &= ~MLX_STATE_SHUTDOWN;
541
542 /* enable interrupts */
543 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
544}
545
546/********************************************************************************
547 * Disconnect from the controller completely, in preparation for unload.
548 */
549int
550mlx_detach(device_t dev)
551{
552 struct mlx_softc *sc = device_get_softc(dev);
553 struct mlxd_softc *mlxd;
554 int i, s, error;
555
556 debug_called(1);
557
558 error = EBUSY;
559 s = splbio();
560 if (sc->mlx_state & MLX_STATE_OPEN)
561 goto out;
562
563 for (i = 0; i < MLX_MAXDRIVES; i++) {
564 if (sc->mlx_sysdrive[i].ms_disk != 0) {
565 mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk);
566 if (mlxd->mlxd_flags & MLXD_OPEN) { /* drive is mounted, abort detach */
567 device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't detach\n");
568 goto out;
569 }
570 }
571 }
572 if ((error = mlx_shutdown(dev)))
573 goto out;
574
575 mlx_free(sc);
576
577 error = 0;
578 out:
579 splx(s);
580 return(error);
581}
582
583/********************************************************************************
584 * Bring the controller down to a dormant state and detach all child devices.
585 *
586 * This function is called before detach, system shutdown, or before performing
587 * an operation which may add or delete system disks. (Call mlx_startup to
588 * resume normal operation.)
589 *
590 * Note that we can assume that the bufq on the controller is empty, as we won't
590 * Note that we can assume that the bioq on the controller is empty, as we won't
591 * allow shutdown if any device is open.
592 */
593int
594mlx_shutdown(device_t dev)
595{
596 struct mlx_softc *sc = device_get_softc(dev);
597 int i, s, error;
598
599 debug_called(1);
600
601 s = splbio();
602 error = 0;
603
604 sc->mlx_state |= MLX_STATE_SHUTDOWN;
605 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
606
607 /* flush controller */
608 device_printf(sc->mlx_dev, "flushing cache...");
609 if (mlx_flush(sc)) {
610 printf("failed\n");
611 } else {
612 printf("done\n");
613 }
614
615 /* delete all our child devices */
616 for (i = 0; i < MLX_MAXDRIVES; i++) {
617 if (sc->mlx_sysdrive[i].ms_disk != 0) {
618 if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0)
619 goto out;
620 sc->mlx_sysdrive[i].ms_disk = 0;
621 }
622 }
623
624 out:
625 splx(s);
626 return(error);
627}
628
629/********************************************************************************
630 * Bring the controller to a quiescent state, ready for system suspend.
631 */
632int
633mlx_suspend(device_t dev)
634{
635 struct mlx_softc *sc = device_get_softc(dev);
636 int s;
637
638 debug_called(1);
639
640 s = splbio();
641 sc->mlx_state |= MLX_STATE_SUSPEND;
642
643 /* flush controller */
644 device_printf(sc->mlx_dev, "flushing cache...");
645 printf("%s\n", mlx_flush(sc) ? "failed" : "done");
646
647 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
648 splx(s);
649
650 return(0);
651}
652
653/********************************************************************************
654 * Bring the controller back to a state ready for operation.
655 */
656int
657mlx_resume(device_t dev)
658{
659 struct mlx_softc *sc = device_get_softc(dev);
660
661 debug_called(1);
662
663 sc->mlx_state &= ~MLX_STATE_SUSPEND;
664 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
665
666 return(0);
667}
668
669/*******************************************************************************
670 * Take an interrupt, or be poked by other code to look for interrupt-worthy
671 * status.
672 */
673void
674mlx_intr(void *arg)
675{
676 struct mlx_softc *sc = (struct mlx_softc *)arg;
677
678 debug_called(1);
679
680 /* collect finished commands, queue anything waiting */
681 mlx_done(sc);
682};
683
684/*******************************************************************************
685 * Receive a buf structure from a child device and queue it on a particular
686 * disk resource, then poke the disk resource to start as much work as it can.
687 */
688int
591 * allow shutdown if any device is open.
592 */
593int
594mlx_shutdown(device_t dev)
595{
596 struct mlx_softc *sc = device_get_softc(dev);
597 int i, s, error;
598
599 debug_called(1);
600
601 s = splbio();
602 error = 0;
603
604 sc->mlx_state |= MLX_STATE_SHUTDOWN;
605 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
606
607 /* flush controller */
608 device_printf(sc->mlx_dev, "flushing cache...");
609 if (mlx_flush(sc)) {
610 printf("failed\n");
611 } else {
612 printf("done\n");
613 }
614
615 /* delete all our child devices */
616 for (i = 0; i < MLX_MAXDRIVES; i++) {
617 if (sc->mlx_sysdrive[i].ms_disk != 0) {
618 if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0)
619 goto out;
620 sc->mlx_sysdrive[i].ms_disk = 0;
621 }
622 }
623
624 out:
625 splx(s);
626 return(error);
627}
628
629/********************************************************************************
630 * Bring the controller to a quiescent state, ready for system suspend.
631 */
632int
633mlx_suspend(device_t dev)
634{
635 struct mlx_softc *sc = device_get_softc(dev);
636 int s;
637
638 debug_called(1);
639
640 s = splbio();
641 sc->mlx_state |= MLX_STATE_SUSPEND;
642
643 /* flush controller */
644 device_printf(sc->mlx_dev, "flushing cache...");
645 printf("%s\n", mlx_flush(sc) ? "failed" : "done");
646
647 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
648 splx(s);
649
650 return(0);
651}
652
653/********************************************************************************
654 * Bring the controller back to a state ready for operation.
655 */
656int
657mlx_resume(device_t dev)
658{
659 struct mlx_softc *sc = device_get_softc(dev);
660
661 debug_called(1);
662
663 sc->mlx_state &= ~MLX_STATE_SUSPEND;
664 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
665
666 return(0);
667}
668
669/*******************************************************************************
670 * Take an interrupt, or be poked by other code to look for interrupt-worthy
671 * status.
672 */
673void
674mlx_intr(void *arg)
675{
676 struct mlx_softc *sc = (struct mlx_softc *)arg;
677
678 debug_called(1);
679
680 /* collect finished commands, queue anything waiting */
681 mlx_done(sc);
682};
683
684/*******************************************************************************
685 * Receive a buf structure from a child device and queue it on a particular
686 * disk resource, then poke the disk resource to start as much work as it can.
687 */
688int
689mlx_submit_buf(struct mlx_softc *sc, struct buf *bp)
689mlx_submit_buf(struct mlx_softc *sc, struct bio *bp)
690{
691 int s;
692
693 debug_called(1);
694
695 s = splbio();
690{
691 int s;
692
693 debug_called(1);
694
695 s = splbio();
696 bufq_insert_tail(&sc->mlx_bufq, bp);
696 bioq_insert_tail(&sc->mlx_bioq, bp);
697 sc->mlx_waitbufs++;
698 splx(s);
699 mlx_startio(sc);
700 return(0);
701}
702
703/********************************************************************************
704 * Accept an open operation on the control device.
705 */
706int
707mlx_open(dev_t dev, int flags, int fmt, struct proc *p)
708{
709 int unit = minor(dev);
710 struct mlx_softc *sc = devclass_get_softc(mlx_devclass, unit);
711
712 sc->mlx_state |= MLX_STATE_OPEN;
713 return(0);
714}
715
716/********************************************************************************
717 * Accept the last close on the control device.
718 */
719int
720mlx_close(dev_t dev, int flags, int fmt, struct proc *p)
721{
722 int unit = minor(dev);
723 struct mlx_softc *sc = devclass_get_softc(mlx_devclass, unit);
724
725 sc->mlx_state &= ~MLX_STATE_OPEN;
726 return (0);
727}
728
729/********************************************************************************
730 * Handle controller-specific control operations.
731 */
732int
733mlx_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
734{
735 int unit = minor(dev);
736 struct mlx_softc *sc = devclass_get_softc(mlx_devclass, unit);
737 struct mlx_rebuild_request *rb = (struct mlx_rebuild_request *)addr;
738 struct mlx_rebuild_status *rs = (struct mlx_rebuild_status *)addr;
739 int *arg = (int *)addr;
740 struct mlx_pause *mp;
741 struct mlx_sysdrive *dr;
742 struct mlxd_softc *mlxd;
743 int i, error;
744
745 switch(cmd) {
746 /*
747 * Enumerate connected system drives; returns the first system drive's
748 * unit number if *arg is -1, or the next unit after *arg if it's
749 * a valid unit on this controller.
750 */
751 case MLX_NEXT_CHILD:
752 /* search system drives */
753 for (i = 0; i < MLX_MAXDRIVES; i++) {
754 /* is this one attached? */
755 if (sc->mlx_sysdrive[i].ms_disk != 0) {
756 /* looking for the next one we come across? */
757 if (*arg == -1) {
758 *arg = device_get_unit(sc->mlx_sysdrive[0].ms_disk);
759 return(0);
760 }
761 /* we want the one after this one */
762 if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
763 *arg = -1;
764 }
765 }
766 return(ENOENT);
767
768 /*
769 * Scan the controller to see whether new drives have appeared.
770 */
771 case MLX_RESCAN_DRIVES:
772 mlx_startup(sc);
773 return(0);
774
775 /*
776 * Disconnect from the specified drive; it may be about to go
777 * away.
778 */
779 case MLX_DETACH_DRIVE: /* detach one drive */
780
781 if (((dr = mlx_findunit(sc, *arg)) == NULL) ||
782 ((mlxd = device_get_softc(dr->ms_disk)) == NULL))
783 return(ENOENT);
784
785 device_printf(dr->ms_disk, "detaching...");
786 error = 0;
787 if (mlxd->mlxd_flags & MLXD_OPEN) {
788 error = EBUSY;
789 goto detach_out;
790 }
791
792 /* flush controller */
793 if (mlx_flush(sc)) {
794 error = EBUSY;
795 goto detach_out;
796 }
797
798 /* nuke drive */
799 if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0)
800 goto detach_out;
801 dr->ms_disk = 0;
802
803 detach_out:
804 if (error) {
805 printf("failed\n");
806 } else {
807 printf("done\n");
808 }
809 return(error);
810
811 /*
812 * Pause one or more SCSI channels for a period of time, to assist
813 * in the process of hot-swapping devices.
814 *
815 * Note that at least the 3.51 firmware on the DAC960PL doesn't seem
816 * to do this right.
817 */
818 case MLX_PAUSE_CHANNEL: /* schedule a channel pause */
819 /* Does this command work on this firmware? */
820 if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS))
821 return(EOPNOTSUPP);
822
823 mp = (struct mlx_pause *)addr;
824 if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) {
825 /* cancel a pending pause operation */
826 sc->mlx_pause.mp_which = 0;
827 } else {
828 /* fix for legal channels */
829 mp->mp_which &= ((1 << sc->mlx_enq2->me_actual_channels) -1);
830 /* check time values */
831 if ((mp->mp_when < 0) || (mp->mp_when > 3600))
832 return(EINVAL);
833 if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30)))
834 return(EINVAL);
835
836 /* check for a pause currently running */
837 if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0))
838 return(EBUSY);
839
840 /* looks ok, go with it */
841 sc->mlx_pause.mp_which = mp->mp_which;
842 sc->mlx_pause.mp_when = time_second + mp->mp_when;
843 sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong;
844 }
845 return(0);
846
847 /*
848 * Accept a command passthrough-style.
849 */
850 case MLX_COMMAND:
851 return(mlx_user_command(sc, (struct mlx_usercommand *)addr));
852
853 /*
854 * Start a rebuild on a given SCSI disk
855 */
856 case MLX_REBUILDASYNC:
857 if (sc->mlx_background != 0) {
858 rb->rr_status = 0x0106;
859 return(EBUSY);
860 }
861 rb->rr_status = mlx_rebuild(sc, rb->rr_channel, rb->rr_target);
862 switch (rb->rr_status) {
863 case 0:
864 error = 0;
865 break;
866 case 0x10000:
867 error = ENOMEM; /* couldn't set up the command */
868 break;
869 case 0x0002:
870 error = EBUSY;
871 break;
872 case 0x0104:
873 error = EIO;
874 break;
875 case 0x0105:
876 error = ERANGE;
877 break;
878 case 0x0106:
879 error = EBUSY;
880 break;
881 default:
882 error = EINVAL;
883 break;
884 }
885 if (error == 0)
886 sc->mlx_background = MLX_BACKGROUND_REBUILD;
887 return(error);
888
889 /*
890 * Get the status of the current rebuild or consistency check.
891 */
892 case MLX_REBUILDSTAT:
893 *rs = sc->mlx_rebuildstat;
894 return(0);
895
896 /*
897 * Return the per-controller system drive number matching the
898 * disk device number in (arg), if it happens to belong to us.
899 */
900 case MLX_GET_SYSDRIVE:
901 error = ENOENT;
902 mlxd = (struct mlxd_softc *)devclass_get_softc(mlxd_devclass, *arg);
903 if ((mlxd != NULL) && (mlxd->mlxd_drive >= sc->mlx_sysdrive) &&
904 (mlxd->mlxd_drive < (sc->mlx_sysdrive + MLX_MAXDRIVES))) {
905 error = 0;
906 *arg = mlxd->mlxd_drive - sc->mlx_sysdrive;
907 }
908 return(error);
909
910 default:
911 return(ENOTTY);
912 }
913}
914
915/********************************************************************************
916 * Handle operations requested by a System Drive connected to this controller.
917 */
918int
919mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_long cmd,
920 caddr_t addr, int32_t flag, struct proc *p)
921{
922 int *arg = (int *)addr;
923 int error, result;
924
925 switch(cmd) {
926 /*
927 * Return the current status of this drive.
928 */
929 case MLXD_STATUS:
930 *arg = drive->ms_state;
931 return(0);
932
933 /*
934 * Start a background consistency check on this drive.
935 */
936 case MLXD_CHECKASYNC: /* start a background consistency check */
937 if (sc->mlx_background != 0) {
938 *arg = 0x0106;
939 return(EBUSY);
940 }
941 result = mlx_check(sc, drive - &sc->mlx_sysdrive[0]);
942 switch (result) {
943 case 0:
944 error = 0;
945 break;
946 case 0x10000:
947 error = ENOMEM; /* couldn't set up the command */
948 break;
949 case 0x0002:
950 error = EIO;
951 break;
952 case 0x0105:
953 error = ERANGE;
954 break;
955 case 0x0106:
956 error = EBUSY;
957 break;
958 default:
959 error = EINVAL;
960 break;
961 }
962 if (error == 0)
963 sc->mlx_background = MLX_BACKGROUND_CHECK;
964 *arg = result;
965 return(error);
966
967 }
968 return(ENOIOCTL);
969}
970
971
972/********************************************************************************
973 ********************************************************************************
974 Status Monitoring
975 ********************************************************************************
976 ********************************************************************************/
977
978/********************************************************************************
979 * Fire off commands to periodically check the status of connected drives.
980 */
981static void
982mlx_periodic(void *data)
983{
984 struct mlx_softc *sc = (struct mlx_softc *)data;
985
986 debug_called(1);
987
988 /*
989 * Run a bus pause?
990 */
991 if ((sc->mlx_pause.mp_which != 0) &&
992 (sc->mlx_pause.mp_when > 0) &&
993 (time_second >= sc->mlx_pause.mp_when)){
994
995 mlx_pause_action(sc); /* pause is running */
996 sc->mlx_pause.mp_when = 0;
997 sysbeep(500, hz);
998
999 /*
1000 * Bus pause still running?
1001 */
1002 } else if ((sc->mlx_pause.mp_which != 0) &&
1003 (sc->mlx_pause.mp_when == 0)) {
1004
1005 /* time to stop bus pause? */
1006 if (time_second >= sc->mlx_pause.mp_howlong) {
1007 mlx_pause_action(sc);
1008 sc->mlx_pause.mp_which = 0; /* pause is complete */
1009 sysbeep(500, hz);
1010 } else {
1011 sysbeep((time_second % 5) * 100 + 500, hz/8);
1012 }
1013
1014 /*
1015 * Run normal periodic activities?
1016 */
1017 } else if (time_second > (sc->mlx_lastpoll + 10)) {
1018 sc->mlx_lastpoll = time_second;
1019
1020 /*
1021 * Check controller status.
1022 *
1023 * XXX Note that this may not actually launch a command in situations of high load.
1024 */
1025 mlx_enquire(sc, (sc->mlx_iftype == MLX_IFTYPE_2) ? MLX_CMD_ENQUIRY_OLD : MLX_CMD_ENQUIRY,
1026 imax(sizeof(struct mlx_enquiry), sizeof(struct mlx_enquiry_old)), mlx_periodic_enquiry);
1027
1028 /*
1029 * Check system drive status.
1030 *
1031 * XXX This might be better left to event-driven detection, eg. I/O to an offline
1032 * drive will detect it's offline, rebuilds etc. should detect the drive is back
1033 * online.
1034 */
1035 mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES,
1036 mlx_periodic_enquiry);
1037
1038 }
1039
1040 /* get drive rebuild/check status */
1041 /* XXX should check sc->mlx_background if this is only valid while in progress */
1042 mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild);
1043
1044 /* deal with possibly-missed interrupts and timed-out commands */
1045 mlx_done(sc);
1046
1047 /* reschedule another poll next second or so */
1048 sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
1049}
1050
1051/********************************************************************************
1052 * Handle the result of an ENQUIRY command instigated by periodic status polling.
1053 */
1054static void
1055mlx_periodic_enquiry(struct mlx_command *mc)
1056{
1057 struct mlx_softc *sc = mc->mc_sc;
1058
1059 debug_called(1);
1060
1061 /* Command completed OK? */
1062 if (mc->mc_status != 0) {
1063 device_printf(sc->mlx_dev, "periodic enquiry failed - %s\n", mlx_diagnose_command(mc));
1064 goto out;
1065 }
1066
1067 /* respond to command */
1068 switch(mc->mc_mailbox[0]) {
1069 /*
1070 * This is currently a bit fruitless, as we don't know how to extract the eventlog
1071 * pointer yet.
1072 */
1073 case MLX_CMD_ENQUIRY_OLD:
1074 {
1075 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data;
1076 struct mlx_enquiry_old *meo = (struct mlx_enquiry_old *)mc->mc_data;
1077 int i;
1078
1079 /* convert data in-place to new format */
1080 for (i = (sizeof(me->me_dead) / sizeof(me->me_dead[0])) - 1; i >= 0; i--) {
1081 me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan;
1082 me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ;
1083 }
1084 me->me_misc_flags = 0;
1085 me->me_rebuild_count = meo->me_rebuild_count;
1086 me->me_dead_count = meo->me_dead_count;
1087 me->me_critical_sd_count = meo->me_critical_sd_count;
1088 me->me_event_log_seq_num = 0;
1089 me->me_offline_sd_count = meo->me_offline_sd_count;
1090 me->me_max_commands = meo->me_max_commands;
1091 me->me_rebuild_flag = meo->me_rebuild_flag;
1092 me->me_fwmajor = meo->me_fwmajor;
1093 me->me_fwminor = meo->me_fwminor;
1094 me->me_status_flags = meo->me_status_flags;
1095 me->me_flash_age = meo->me_flash_age;
1096 for (i = (sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0])) - 1; i >= 0; i--) {
1097 if (i > ((sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0])) - 1)) {
1098 me->me_drvsize[i] = 0; /* drive beyond supported range */
1099 } else {
1100 me->me_drvsize[i] = meo->me_drvsize[i];
1101 }
1102 }
1103 me->me_num_sys_drvs = meo->me_num_sys_drvs;
1104 }
1105 /* FALLTHROUGH */
1106
1107 /*
1108 * Generic controller status update. We could do more with this than just
1109 * checking the event log.
1110 */
1111 case MLX_CMD_ENQUIRY:
1112 {
1113 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data;
1114
1115 if (sc->mlx_currevent == -1) {
1116 /* initialise our view of the event log */
1117 sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num;
1118 } else if (me->me_event_log_seq_num != sc->mlx_lastevent) {
1119 /* record where current events are up to */
1120 sc->mlx_currevent = me->me_event_log_seq_num;
1121 debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent);
1122
1123 /* drain new eventlog entries */
1124 mlx_periodic_eventlog_poll(sc);
1125 }
1126 break;
1127 }
1128 case MLX_CMD_ENQSYSDRIVE:
1129 {
1130 struct mlx_enq_sys_drive *mes = (struct mlx_enq_sys_drive *)mc->mc_data;
1131 struct mlx_sysdrive *dr;
1132 int i;
1133
1134 for (i = 0, dr = &sc->mlx_sysdrive[0];
1135 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
1136 i++) {
1137
1138 /* has state been changed by controller? */
1139 if (dr->ms_state != mes[i].sd_state) {
1140 switch(mes[i].sd_state) {
1141 case MLX_SYSD_OFFLINE:
1142 device_printf(dr->ms_disk, "drive offline\n");
1143 break;
1144 case MLX_SYSD_ONLINE:
1145 device_printf(dr->ms_disk, "drive online\n");
1146 break;
1147 case MLX_SYSD_CRITICAL:
1148 device_printf(dr->ms_disk, "drive critical\n");
1149 break;
1150 }
1151 /* save new state */
1152 dr->ms_state = mes[i].sd_state;
1153 }
1154 }
1155 break;
1156 }
1157 default:
1158 device_printf(sc->mlx_dev, "%s: unknown command 0x%x", __FUNCTION__, mc->mc_mailbox[0]);
1159 break;
1160 }
1161
1162 out:
1163 free(mc->mc_data, M_DEVBUF);
1164 mlx_releasecmd(mc);
1165}
1166
1167/********************************************************************************
1168 * Instigate a poll for one event log message on (sc).
1169 * We only poll for one message at a time, to keep our command usage down.
1170 */
1171static void
1172mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1173{
1174 struct mlx_command *mc;
1175 void *result = NULL;
1176 int error;
1177
1178 debug_called(1);
1179
1180 /* get ourselves a command buffer */
1181 error = 1;
1182 if ((mc = mlx_alloccmd(sc)) == NULL)
1183 goto out;
1184 /* allocate the response structure */
1185 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL)
1186 goto out;
1187 /* get a command slot */
1188 if (mlx_getslot(mc))
1189 goto out;
1190
1191 /* map the command so the controller can see it */
1192 mc->mc_data = result;
1193 mc->mc_length = /*sizeof(struct mlx_eventlog_entry)*/1024;
1194 mlx_mapcmd(mc);
1195
1196 /* build the command to get one entry */
1197 mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1, sc->mlx_lastevent, 0, 0, mc->mc_dataphys, 0);
1198 mc->mc_complete = mlx_periodic_eventlog_respond;
1199 mc->mc_private = mc;
1200
1201 /* start the command */
1202 if ((error = mlx_start(mc)) != 0)
1203 goto out;
1204
1205 error = 0; /* success */
1206 out:
1207 if (error != 0) {
1208 if (mc != NULL)
1209 mlx_releasecmd(mc);
1210 if (result != NULL)
1211 free(result, M_DEVBUF);
1212 }
1213}
1214
1215/********************************************************************************
1216 * Handle the result of polling for a log message, generate diagnostic output.
1217 * If this wasn't the last message waiting for us, we'll go collect another.
1218 */
1219static char *mlx_sense_messages[] = {
1220 "because write recovery failed",
1221 "because of SCSI bus reset failure",
1222 "because of double check condition",
1223 "because it was removed",
1224 "because of gross error on SCSI chip",
1225 "because of bad tag returned from drive",
1226 "because of timeout on SCSI command",
1227 "because of reset SCSI command issued from system",
1228 "because busy or parity error count exceeded limit",
1229 "because of 'kill drive' command from system",
1230 "because of selection timeout",
1231 "due to SCSI phase sequence error",
1232 "due to unknown status"
1233};
1234
1235static void
1236mlx_periodic_eventlog_respond(struct mlx_command *mc)
1237{
1238 struct mlx_softc *sc = mc->mc_sc;
1239 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data;
1240 char *reason;
1241
1242 debug_called(1);
1243
1244 sc->mlx_lastevent++; /* next message... */
1245 if (mc->mc_status == 0) {
1246
1247 /* handle event log message */
1248 switch(el->el_type) {
1249 /*
1250 * This is the only sort of message we understand at the moment.
1251 * The tests here are probably incomplete.
1252 */
1253 case MLX_LOGMSG_SENSE: /* sense data */
1254 /* Mylex vendor-specific message indicating a drive was killed? */
1255 if ((el->el_sensekey == 9) &&
1256 (el->el_asc == 0x80)) {
1257 if (el->el_asq < (sizeof(mlx_sense_messages) / sizeof(mlx_sense_messages[0]))) {
1258 reason = mlx_sense_messages[el->el_asq];
1259 } else {
1260 reason = "for unknown reason";
1261 }
1262 device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n",
1263 el->el_channel, el->el_target, reason);
1264 }
1265 /* SCSI drive was reset? */
1266 if ((el->el_sensekey == 6) && (el->el_asc == 0x29)) {
1267 device_printf(sc->mlx_dev, "physical drive %d:%d reset\n",
1268 el->el_channel, el->el_target);
1269 }
1270 /* SCSI drive error? */
1271 if (!((el->el_sensekey == 0) ||
1272 ((el->el_sensekey == 2) &&
1273 (el->el_asc == 0x04) &&
1274 ((el->el_asq == 0x01) ||
1275 (el->el_asq == 0x02))))) {
1276 device_printf(sc->mlx_dev, "physical drive %d:%d error log: sense = %d asc = %x asq = %x\n",
1277 el->el_channel, el->el_target, el->el_sensekey, el->el_asc, el->el_asq);
1278 device_printf(sc->mlx_dev, " info %4D csi %4D\n", el->el_information, ":", el->el_csi, ":");
1279 }
1280 break;
1281
1282 default:
1283 device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type);
1284 break;
1285 }
1286 } else {
1287 device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc));
1288 panic("log operation failed: lastevent = %d, currevent = %d",
1289 sc->mlx_lastevent, sc->mlx_currevent);
1290 }
1291
1292 /* dispose of command and data */
1293 free(mc->mc_data, M_DEVBUF);
1294 mlx_releasecmd(mc);
1295
1296 /* is there another message to obtain? */
1297 if (sc->mlx_lastevent != sc->mlx_currevent)
1298 mlx_periodic_eventlog_poll(sc);
1299}
1300
1301/********************************************************************************
1302 * Handle check/rebuild operations in progress.
1303 */
1304static void
1305mlx_periodic_rebuild(struct mlx_command *mc)
1306{
1307 struct mlx_softc *sc = mc->mc_sc;
1308 struct mlx_rebuild_status *mr = (struct mlx_rebuild_status *)mc->mc_data;
1309
1310 switch(mc->mc_status) {
1311 case 0: /* operation running, update stats */
1312 sc->mlx_rebuildstat = *mr;
1313
1314 /* spontaneous rebuild/check? */
1315 if (sc->mlx_background == 0) {
1316 sc->mlx_background = MLX_BACKGROUND_SPONTANEOUS;
1317 device_printf(sc->mlx_dev, "background check/rebuild operation started\n");
1318 }
1319 break;
1320
1321 case 0x0105: /* nothing running, finalise stats and report */
1322 switch(sc->mlx_background) {
1323 case MLX_BACKGROUND_CHECK:
1324 device_printf(sc->mlx_dev, "consistency check completed\n"); /* XXX print drive? */
1325 break;
1326 case MLX_BACKGROUND_REBUILD:
1327 device_printf(sc->mlx_dev, "drive rebuild completed\n"); /* XXX print channel/target? */
1328 break;
1329 case MLX_BACKGROUND_SPONTANEOUS:
1330 default:
1331 /* if we have previously been non-idle, report the transition */
1332 if (sc->mlx_rebuildstat.rs_code != MLX_REBUILDSTAT_IDLE) {
1333 device_printf(sc->mlx_dev, "background check/rebuild operation completed\n");
1334 }
1335 }
1336 sc->mlx_background = 0;
1337 sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
1338 break;
1339 }
1340 free(mc->mc_data, M_DEVBUF);
1341 mlx_releasecmd(mc);
1342}
1343
1344/********************************************************************************
1345 ********************************************************************************
1346 Channel Pause
1347 ********************************************************************************
1348 ********************************************************************************/
1349
1350/********************************************************************************
1351 * It's time to perform a channel pause action for (sc), either start or stop
1352 * the pause.
1353 */
1354static void
1355mlx_pause_action(struct mlx_softc *sc)
1356{
1357 struct mlx_command *mc;
1358 int failsafe, i, command;
1359
1360 /* What are we doing here? */
1361 if (sc->mlx_pause.mp_when == 0) {
1362 command = MLX_CMD_STARTCHANNEL;
1363 failsafe = 0;
1364
1365 } else {
1366 command = MLX_CMD_STOPCHANNEL;
1367
1368 /*
1369 * Channels will always start again after the failsafe period,
1370 * which is specified in multiples of 30 seconds.
1371 * This constrains us to a maximum pause of 450 seconds.
1372 */
1373 failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30;
1374 if (failsafe > 0xf) {
1375 failsafe = 0xf;
1376 sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5;
1377 }
1378 }
1379
1380 /* build commands for every channel requested */
1381 for (i = 0; i < sc->mlx_enq2->me_actual_channels; i++) {
1382 if ((1 << i) & sc->mlx_pause.mp_which) {
1383
1384 /* get ourselves a command buffer */
1385 if ((mc = mlx_alloccmd(sc)) == NULL)
1386 goto fail;
1387 /* get a command slot */
1388 mc->mc_flags |= MLX_CMD_PRIORITY;
1389 if (mlx_getslot(mc))
1390 goto fail;
1391
1392 /* build the command */
1393 mlx_make_type2(mc, command, (failsafe << 4) | i, 0, 0, 0, 0, 0, 0, 0);
1394 mc->mc_complete = mlx_pause_done;
1395 mc->mc_private = sc; /* XXX not needed */
1396 if (mlx_start(mc))
1397 goto fail;
1398 /* command submitted OK */
1399 return;
1400
1401 fail:
1402 device_printf(sc->mlx_dev, "%s failed for channel %d\n",
1403 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i);
1404 if (mc != NULL)
1405 mlx_releasecmd(mc);
1406 }
1407 }
1408}
1409
1410static void
1411mlx_pause_done(struct mlx_command *mc)
1412{
1413 struct mlx_softc *sc = mc->mc_sc;
1414 int command = mc->mc_mailbox[0];
1415 int channel = mc->mc_mailbox[2] & 0xf;
1416
1417 if (mc->mc_status != 0) {
1418 device_printf(sc->mlx_dev, "%s command failed - %s\n",
1419 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc));
1420 } else if (command == MLX_CMD_STOPCHANNEL) {
1421 device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n",
1422 channel, (long)(sc->mlx_pause.mp_howlong - time_second));
1423 } else {
1424 device_printf(sc->mlx_dev, "channel %d resuming\n", channel);
1425 }
1426 mlx_releasecmd(mc);
1427}
1428
1429/********************************************************************************
1430 ********************************************************************************
1431 Command Submission
1432 ********************************************************************************
1433 ********************************************************************************/
1434
1435/********************************************************************************
1436 * Perform an Enquiry command using a type-3 command buffer and a return a single
1437 * linear result buffer. If the completion function is specified, it will
1438 * be called with the completed command (and the result response will not be
1439 * valid until that point). Otherwise, the command will either be busy-waited
1440 * for (interrupts not enabled), or slept for.
1441 */
1442static void *
1443mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1444{
1445 struct mlx_command *mc;
1446 void *result;
1447 int error;
1448
1449 debug_called(1);
1450
1451 /* get ourselves a command buffer */
1452 error = 1;
1453 result = NULL;
1454 if ((mc = mlx_alloccmd(sc)) == NULL)
1455 goto out;
1456 /* allocate the response structure */
1457 if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
1458 goto out;
1459 /* get a command slot */
1460 mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT;
1461 if (mlx_getslot(mc))
1462 goto out;
1463
1464 /* map the command so the controller can see it */
1465 mc->mc_data = result;
1466 mc->mc_length = bufsize;
1467 mlx_mapcmd(mc);
1468
1469 /* build an enquiry command */
1470 mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0);
1471
1472 /* do we want a completion callback? */
1473 if (complete != NULL) {
1474 mc->mc_complete = complete;
1475 mc->mc_private = mc;
1476 if ((error = mlx_start(mc)) != 0)
1477 goto out;
1478 } else {
1479 /* run the command in either polled or wait mode */
1480 if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1481 goto out;
1482
1483 /* command completed OK? */
1484 if (mc->mc_status != 0) {
1485 device_printf(sc->mlx_dev, "ENQUIRY failed - %s\n", mlx_diagnose_command(mc));
1486 goto out;
1487 }
1488 }
1489 error = 0; /* success */
1490 out:
1491 /* we got a command, but nobody else will free it */
1492 if ((complete == NULL) && (mc != NULL))
1493 mlx_releasecmd(mc);
1494 /* we got an error, and we allocated a result */
1495 if ((error != 0) && (result != NULL)) {
1496 free(result, M_DEVBUF);
1497 result = NULL;
1498 }
1499 return(result);
1500}
1501
1502
1503/********************************************************************************
1504 * Perform a Flush command on the nominated controller.
1505 *
1506 * May be called with interrupts enabled or disabled; will not return until
1507 * the flush operation completes or fails.
1508 */
1509static int
1510mlx_flush(struct mlx_softc *sc)
1511{
1512 struct mlx_command *mc;
1513 int error;
1514
1515 debug_called(1);
1516
1517 /* get ourselves a command buffer */
1518 error = 1;
1519 if ((mc = mlx_alloccmd(sc)) == NULL)
1520 goto out;
1521 /* get a command slot */
1522 if (mlx_getslot(mc))
1523 goto out;
1524
1525 /* build a flush command */
1526 mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1527
1528 /* can't assume that interrupts are going to work here, so play it safe */
1529 if (mlx_poll_command(mc))
1530 goto out;
1531
1532 /* command completed OK? */
1533 if (mc->mc_status != 0) {
1534 device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1535 goto out;
1536 }
1537
1538 error = 0; /* success */
1539 out:
1540 if (mc != NULL)
1541 mlx_releasecmd(mc);
1542 return(error);
1543}
1544
1545/********************************************************************************
1546 * Start a background consistency check on (drive).
1547 *
1548 * May be called with interrupts enabled or disabled; will return as soon as the
1549 * operation has started or been refused.
1550 */
1551static int
1552mlx_check(struct mlx_softc *sc, int drive)
1553{
1554 struct mlx_command *mc;
1555 int error;
1556
1557 debug_called(1);
1558
1559 /* get ourselves a command buffer */
1560 error = 0x10000;
1561 if ((mc = mlx_alloccmd(sc)) == NULL)
1562 goto out;
1563 /* get a command slot */
1564 if (mlx_getslot(mc))
1565 goto out;
1566
1567 /* build a checkasync command, set the "fix it" flag */
1568 mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80, 0, 0);
1569
1570 /* start the command and wait for it to be returned */
1571 if (mlx_wait_command(mc))
1572 goto out;
1573
1574 /* command completed OK? */
1575 if (mc->mc_status != 0) {
1576 device_printf(sc->mlx_dev, "CHECK ASYNC failed - %s\n", mlx_diagnose_command(mc));
1577 } else {
1578 device_printf(sc->mlx_sysdrive[drive].ms_disk, "consistency check started");
1579 }
1580 error = mc->mc_status;
1581
1582 out:
1583 if (mc != NULL)
1584 mlx_releasecmd(mc);
1585 return(error);
1586}
1587
1588/********************************************************************************
1589 * Start a background rebuild of the physical drive at (channel),(target).
1590 *
1591 * May be called with interrupts enabled or disabled; will return as soon as the
1592 * operation has started or been refused.
1593 */
1594static int
1595mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1596{
1597 struct mlx_command *mc;
1598 int error;
1599
1600 debug_called(1);
1601
1602 /* get ourselves a command buffer */
1603 error = 0x10000;
1604 if ((mc = mlx_alloccmd(sc)) == NULL)
1605 goto out;
1606 /* get a command slot */
1607 if (mlx_getslot(mc))
1608 goto out;
1609
1610 /* build a checkasync command, set the "fix it" flag */
1611 mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 0, 0);
1612
1613 /* start the command and wait for it to be returned */
1614 if (mlx_wait_command(mc))
1615 goto out;
1616
1617 /* command completed OK? */
1618 if (mc->mc_status != 0) {
1619 device_printf(sc->mlx_dev, "REBUILD ASYNC failed - %s\n", mlx_diagnose_command(mc));
1620 } else {
1621 device_printf(sc->mlx_dev, "drive rebuild started for %d:%d\n", channel, target);
1622 }
1623 error = mc->mc_status;
1624
1625 out:
1626 if (mc != NULL)
1627 mlx_releasecmd(mc);
1628 return(error);
1629}
1630
1631/********************************************************************************
1632 * Run the command (mc) and return when it completes.
1633 *
1634 * Interrupts need to be enabled; returns nonzero on error.
1635 */
1636static int
1637mlx_wait_command(struct mlx_command *mc)
1638{
1639 struct mlx_softc *sc = mc->mc_sc;
1640 int error, count;
1641
1642 debug_called(1);
1643
1644 mc->mc_complete = NULL;
1645 mc->mc_private = mc; /* wake us when you're done */
1646 if ((error = mlx_start(mc)) != 0)
1647 return(error);
1648
1649 count = 0;
1650 /* XXX better timeout? */
1651 while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
1652 tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz);
1653 }
1654
1655 if (mc->mc_status != 0) {
1656 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1657 return(EIO);
1658 }
1659 return(0);
1660}
1661
1662
1663/********************************************************************************
1664 * Start the command (mc) and busy-wait for it to complete.
1665 *
1666 * Should only be used when interrupts can't be relied upon. Returns 0 on
1667 * success, nonzero on error.
1668 * Successfully completed commands are dequeued.
1669 */
1670static int
1671mlx_poll_command(struct mlx_command *mc)
1672{
1673 struct mlx_softc *sc = mc->mc_sc;
1674 int error, count, s;
1675
1676 debug_called(1);
1677
1678 mc->mc_complete = NULL;
1679 mc->mc_private = NULL; /* we will poll for it */
1680 if ((error = mlx_start(mc)) != 0)
1681 return(error);
1682
1683 count = 0;
1684 do {
1685 /* poll for completion */
1686 mlx_done(mc->mc_sc);
1687
1688 } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000));
1689 if (mc->mc_status != MLX_STATUS_BUSY) {
1690 s = splbio();
1691 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1692 splx(s);
1693 return(0);
1694 }
1695 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1696 return(EIO);
1697}
1698
1699/********************************************************************************
1700 * Pull as much work off the softc's work queue as possible and give it to the
1701 * controller. Leave a couple of slots free for emergencies.
1702 *
1703 * Must be called at splbio or in an equivalent fashion that prevents
697 sc->mlx_waitbufs++;
698 splx(s);
699 mlx_startio(sc);
700 return(0);
701}
702
703/********************************************************************************
704 * Accept an open operation on the control device.
705 */
706int
707mlx_open(dev_t dev, int flags, int fmt, struct proc *p)
708{
709 int unit = minor(dev);
710 struct mlx_softc *sc = devclass_get_softc(mlx_devclass, unit);
711
712 sc->mlx_state |= MLX_STATE_OPEN;
713 return(0);
714}
715
716/********************************************************************************
717 * Accept the last close on the control device.
718 */
719int
720mlx_close(dev_t dev, int flags, int fmt, struct proc *p)
721{
722 int unit = minor(dev);
723 struct mlx_softc *sc = devclass_get_softc(mlx_devclass, unit);
724
725 sc->mlx_state &= ~MLX_STATE_OPEN;
726 return (0);
727}
728
729/********************************************************************************
730 * Handle controller-specific control operations.
731 */
732int
733mlx_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
734{
735 int unit = minor(dev);
736 struct mlx_softc *sc = devclass_get_softc(mlx_devclass, unit);
737 struct mlx_rebuild_request *rb = (struct mlx_rebuild_request *)addr;
738 struct mlx_rebuild_status *rs = (struct mlx_rebuild_status *)addr;
739 int *arg = (int *)addr;
740 struct mlx_pause *mp;
741 struct mlx_sysdrive *dr;
742 struct mlxd_softc *mlxd;
743 int i, error;
744
745 switch(cmd) {
746 /*
747 * Enumerate connected system drives; returns the first system drive's
748 * unit number if *arg is -1, or the next unit after *arg if it's
749 * a valid unit on this controller.
750 */
751 case MLX_NEXT_CHILD:
752 /* search system drives */
753 for (i = 0; i < MLX_MAXDRIVES; i++) {
754 /* is this one attached? */
755 if (sc->mlx_sysdrive[i].ms_disk != 0) {
756 /* looking for the next one we come across? */
757 if (*arg == -1) {
758 *arg = device_get_unit(sc->mlx_sysdrive[0].ms_disk);
759 return(0);
760 }
761 /* we want the one after this one */
762 if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
763 *arg = -1;
764 }
765 }
766 return(ENOENT);
767
768 /*
769 * Scan the controller to see whether new drives have appeared.
770 */
771 case MLX_RESCAN_DRIVES:
772 mlx_startup(sc);
773 return(0);
774
775 /*
776 * Disconnect from the specified drive; it may be about to go
777 * away.
778 */
779 case MLX_DETACH_DRIVE: /* detach one drive */
780
781 if (((dr = mlx_findunit(sc, *arg)) == NULL) ||
782 ((mlxd = device_get_softc(dr->ms_disk)) == NULL))
783 return(ENOENT);
784
785 device_printf(dr->ms_disk, "detaching...");
786 error = 0;
787 if (mlxd->mlxd_flags & MLXD_OPEN) {
788 error = EBUSY;
789 goto detach_out;
790 }
791
792 /* flush controller */
793 if (mlx_flush(sc)) {
794 error = EBUSY;
795 goto detach_out;
796 }
797
798 /* nuke drive */
799 if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0)
800 goto detach_out;
801 dr->ms_disk = 0;
802
803 detach_out:
804 if (error) {
805 printf("failed\n");
806 } else {
807 printf("done\n");
808 }
809 return(error);
810
811 /*
812 * Pause one or more SCSI channels for a period of time, to assist
813 * in the process of hot-swapping devices.
814 *
815 * Note that at least the 3.51 firmware on the DAC960PL doesn't seem
816 * to do this right.
817 */
818 case MLX_PAUSE_CHANNEL: /* schedule a channel pause */
819 /* Does this command work on this firmware? */
820 if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS))
821 return(EOPNOTSUPP);
822
823 mp = (struct mlx_pause *)addr;
824 if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) {
825 /* cancel a pending pause operation */
826 sc->mlx_pause.mp_which = 0;
827 } else {
828 /* fix for legal channels */
829 mp->mp_which &= ((1 << sc->mlx_enq2->me_actual_channels) -1);
830 /* check time values */
831 if ((mp->mp_when < 0) || (mp->mp_when > 3600))
832 return(EINVAL);
833 if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30)))
834 return(EINVAL);
835
836 /* check for a pause currently running */
837 if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0))
838 return(EBUSY);
839
840 /* looks ok, go with it */
841 sc->mlx_pause.mp_which = mp->mp_which;
842 sc->mlx_pause.mp_when = time_second + mp->mp_when;
843 sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong;
844 }
845 return(0);
846
847 /*
848 * Accept a command passthrough-style.
849 */
850 case MLX_COMMAND:
851 return(mlx_user_command(sc, (struct mlx_usercommand *)addr));
852
853 /*
854 * Start a rebuild on a given SCSI disk
855 */
856 case MLX_REBUILDASYNC:
857 if (sc->mlx_background != 0) {
858 rb->rr_status = 0x0106;
859 return(EBUSY);
860 }
861 rb->rr_status = mlx_rebuild(sc, rb->rr_channel, rb->rr_target);
862 switch (rb->rr_status) {
863 case 0:
864 error = 0;
865 break;
866 case 0x10000:
867 error = ENOMEM; /* couldn't set up the command */
868 break;
869 case 0x0002:
870 error = EBUSY;
871 break;
872 case 0x0104:
873 error = EIO;
874 break;
875 case 0x0105:
876 error = ERANGE;
877 break;
878 case 0x0106:
879 error = EBUSY;
880 break;
881 default:
882 error = EINVAL;
883 break;
884 }
885 if (error == 0)
886 sc->mlx_background = MLX_BACKGROUND_REBUILD;
887 return(error);
888
889 /*
890 * Get the status of the current rebuild or consistency check.
891 */
892 case MLX_REBUILDSTAT:
893 *rs = sc->mlx_rebuildstat;
894 return(0);
895
896 /*
897 * Return the per-controller system drive number matching the
898 * disk device number in (arg), if it happens to belong to us.
899 */
900 case MLX_GET_SYSDRIVE:
901 error = ENOENT;
902 mlxd = (struct mlxd_softc *)devclass_get_softc(mlxd_devclass, *arg);
903 if ((mlxd != NULL) && (mlxd->mlxd_drive >= sc->mlx_sysdrive) &&
904 (mlxd->mlxd_drive < (sc->mlx_sysdrive + MLX_MAXDRIVES))) {
905 error = 0;
906 *arg = mlxd->mlxd_drive - sc->mlx_sysdrive;
907 }
908 return(error);
909
910 default:
911 return(ENOTTY);
912 }
913}
914
915/********************************************************************************
916 * Handle operations requested by a System Drive connected to this controller.
917 */
918int
919mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_long cmd,
920 caddr_t addr, int32_t flag, struct proc *p)
921{
922 int *arg = (int *)addr;
923 int error, result;
924
925 switch(cmd) {
926 /*
927 * Return the current status of this drive.
928 */
929 case MLXD_STATUS:
930 *arg = drive->ms_state;
931 return(0);
932
933 /*
934 * Start a background consistency check on this drive.
935 */
936 case MLXD_CHECKASYNC: /* start a background consistency check */
937 if (sc->mlx_background != 0) {
938 *arg = 0x0106;
939 return(EBUSY);
940 }
941 result = mlx_check(sc, drive - &sc->mlx_sysdrive[0]);
942 switch (result) {
943 case 0:
944 error = 0;
945 break;
946 case 0x10000:
947 error = ENOMEM; /* couldn't set up the command */
948 break;
949 case 0x0002:
950 error = EIO;
951 break;
952 case 0x0105:
953 error = ERANGE;
954 break;
955 case 0x0106:
956 error = EBUSY;
957 break;
958 default:
959 error = EINVAL;
960 break;
961 }
962 if (error == 0)
963 sc->mlx_background = MLX_BACKGROUND_CHECK;
964 *arg = result;
965 return(error);
966
967 }
968 return(ENOIOCTL);
969}
970
971
972/********************************************************************************
973 ********************************************************************************
974 Status Monitoring
975 ********************************************************************************
976 ********************************************************************************/
977
978/********************************************************************************
979 * Fire off commands to periodically check the status of connected drives.
980 */
981static void
982mlx_periodic(void *data)
983{
984 struct mlx_softc *sc = (struct mlx_softc *)data;
985
986 debug_called(1);
987
988 /*
989 * Run a bus pause?
990 */
991 if ((sc->mlx_pause.mp_which != 0) &&
992 (sc->mlx_pause.mp_when > 0) &&
993 (time_second >= sc->mlx_pause.mp_when)){
994
995 mlx_pause_action(sc); /* pause is running */
996 sc->mlx_pause.mp_when = 0;
997 sysbeep(500, hz);
998
999 /*
1000 * Bus pause still running?
1001 */
1002 } else if ((sc->mlx_pause.mp_which != 0) &&
1003 (sc->mlx_pause.mp_when == 0)) {
1004
1005 /* time to stop bus pause? */
1006 if (time_second >= sc->mlx_pause.mp_howlong) {
1007 mlx_pause_action(sc);
1008 sc->mlx_pause.mp_which = 0; /* pause is complete */
1009 sysbeep(500, hz);
1010 } else {
1011 sysbeep((time_second % 5) * 100 + 500, hz/8);
1012 }
1013
1014 /*
1015 * Run normal periodic activities?
1016 */
1017 } else if (time_second > (sc->mlx_lastpoll + 10)) {
1018 sc->mlx_lastpoll = time_second;
1019
1020 /*
1021 * Check controller status.
1022 *
1023 * XXX Note that this may not actually launch a command in situations of high load.
1024 */
1025 mlx_enquire(sc, (sc->mlx_iftype == MLX_IFTYPE_2) ? MLX_CMD_ENQUIRY_OLD : MLX_CMD_ENQUIRY,
1026 imax(sizeof(struct mlx_enquiry), sizeof(struct mlx_enquiry_old)), mlx_periodic_enquiry);
1027
1028 /*
1029 * Check system drive status.
1030 *
1031 * XXX This might be better left to event-driven detection, eg. I/O to an offline
1032 * drive will detect it's offline, rebuilds etc. should detect the drive is back
1033 * online.
1034 */
1035 mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES,
1036 mlx_periodic_enquiry);
1037
1038 }
1039
1040 /* get drive rebuild/check status */
1041 /* XXX should check sc->mlx_background if this is only valid while in progress */
1042 mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild);
1043
1044 /* deal with possibly-missed interrupts and timed-out commands */
1045 mlx_done(sc);
1046
1047 /* reschedule another poll next second or so */
1048 sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
1049}
1050
1051/********************************************************************************
1052 * Handle the result of an ENQUIRY command instigated by periodic status polling.
1053 */
1054static void
1055mlx_periodic_enquiry(struct mlx_command *mc)
1056{
1057 struct mlx_softc *sc = mc->mc_sc;
1058
1059 debug_called(1);
1060
1061 /* Command completed OK? */
1062 if (mc->mc_status != 0) {
1063 device_printf(sc->mlx_dev, "periodic enquiry failed - %s\n", mlx_diagnose_command(mc));
1064 goto out;
1065 }
1066
1067 /* respond to command */
1068 switch(mc->mc_mailbox[0]) {
1069 /*
1070 * This is currently a bit fruitless, as we don't know how to extract the eventlog
1071 * pointer yet.
1072 */
1073 case MLX_CMD_ENQUIRY_OLD:
1074 {
1075 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data;
1076 struct mlx_enquiry_old *meo = (struct mlx_enquiry_old *)mc->mc_data;
1077 int i;
1078
1079 /* convert data in-place to new format */
1080 for (i = (sizeof(me->me_dead) / sizeof(me->me_dead[0])) - 1; i >= 0; i--) {
1081 me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan;
1082 me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ;
1083 }
1084 me->me_misc_flags = 0;
1085 me->me_rebuild_count = meo->me_rebuild_count;
1086 me->me_dead_count = meo->me_dead_count;
1087 me->me_critical_sd_count = meo->me_critical_sd_count;
1088 me->me_event_log_seq_num = 0;
1089 me->me_offline_sd_count = meo->me_offline_sd_count;
1090 me->me_max_commands = meo->me_max_commands;
1091 me->me_rebuild_flag = meo->me_rebuild_flag;
1092 me->me_fwmajor = meo->me_fwmajor;
1093 me->me_fwminor = meo->me_fwminor;
1094 me->me_status_flags = meo->me_status_flags;
1095 me->me_flash_age = meo->me_flash_age;
1096 for (i = (sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0])) - 1; i >= 0; i--) {
1097 if (i > ((sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0])) - 1)) {
1098 me->me_drvsize[i] = 0; /* drive beyond supported range */
1099 } else {
1100 me->me_drvsize[i] = meo->me_drvsize[i];
1101 }
1102 }
1103 me->me_num_sys_drvs = meo->me_num_sys_drvs;
1104 }
1105 /* FALLTHROUGH */
1106
1107 /*
1108 * Generic controller status update. We could do more with this than just
1109 * checking the event log.
1110 */
1111 case MLX_CMD_ENQUIRY:
1112 {
1113 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data;
1114
1115 if (sc->mlx_currevent == -1) {
1116 /* initialise our view of the event log */
1117 sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num;
1118 } else if (me->me_event_log_seq_num != sc->mlx_lastevent) {
1119 /* record where current events are up to */
1120 sc->mlx_currevent = me->me_event_log_seq_num;
1121 debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent);
1122
1123 /* drain new eventlog entries */
1124 mlx_periodic_eventlog_poll(sc);
1125 }
1126 break;
1127 }
1128 case MLX_CMD_ENQSYSDRIVE:
1129 {
1130 struct mlx_enq_sys_drive *mes = (struct mlx_enq_sys_drive *)mc->mc_data;
1131 struct mlx_sysdrive *dr;
1132 int i;
1133
1134 for (i = 0, dr = &sc->mlx_sysdrive[0];
1135 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
1136 i++) {
1137
1138 /* has state been changed by controller? */
1139 if (dr->ms_state != mes[i].sd_state) {
1140 switch(mes[i].sd_state) {
1141 case MLX_SYSD_OFFLINE:
1142 device_printf(dr->ms_disk, "drive offline\n");
1143 break;
1144 case MLX_SYSD_ONLINE:
1145 device_printf(dr->ms_disk, "drive online\n");
1146 break;
1147 case MLX_SYSD_CRITICAL:
1148 device_printf(dr->ms_disk, "drive critical\n");
1149 break;
1150 }
1151 /* save new state */
1152 dr->ms_state = mes[i].sd_state;
1153 }
1154 }
1155 break;
1156 }
1157 default:
1158 device_printf(sc->mlx_dev, "%s: unknown command 0x%x", __FUNCTION__, mc->mc_mailbox[0]);
1159 break;
1160 }
1161
1162 out:
1163 free(mc->mc_data, M_DEVBUF);
1164 mlx_releasecmd(mc);
1165}
1166
1167/********************************************************************************
1168 * Instigate a poll for one event log message on (sc).
1169 * We only poll for one message at a time, to keep our command usage down.
1170 */
1171static void
1172mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1173{
1174 struct mlx_command *mc;
1175 void *result = NULL;
1176 int error;
1177
1178 debug_called(1);
1179
1180 /* get ourselves a command buffer */
1181 error = 1;
1182 if ((mc = mlx_alloccmd(sc)) == NULL)
1183 goto out;
1184 /* allocate the response structure */
1185 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL)
1186 goto out;
1187 /* get a command slot */
1188 if (mlx_getslot(mc))
1189 goto out;
1190
1191 /* map the command so the controller can see it */
1192 mc->mc_data = result;
1193 mc->mc_length = /*sizeof(struct mlx_eventlog_entry)*/1024;
1194 mlx_mapcmd(mc);
1195
1196 /* build the command to get one entry */
1197 mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1, sc->mlx_lastevent, 0, 0, mc->mc_dataphys, 0);
1198 mc->mc_complete = mlx_periodic_eventlog_respond;
1199 mc->mc_private = mc;
1200
1201 /* start the command */
1202 if ((error = mlx_start(mc)) != 0)
1203 goto out;
1204
1205 error = 0; /* success */
1206 out:
1207 if (error != 0) {
1208 if (mc != NULL)
1209 mlx_releasecmd(mc);
1210 if (result != NULL)
1211 free(result, M_DEVBUF);
1212 }
1213}
1214
1215/********************************************************************************
1216 * Handle the result of polling for a log message, generate diagnostic output.
1217 * If this wasn't the last message waiting for us, we'll go collect another.
1218 */
1219static char *mlx_sense_messages[] = {
1220 "because write recovery failed",
1221 "because of SCSI bus reset failure",
1222 "because of double check condition",
1223 "because it was removed",
1224 "because of gross error on SCSI chip",
1225 "because of bad tag returned from drive",
1226 "because of timeout on SCSI command",
1227 "because of reset SCSI command issued from system",
1228 "because busy or parity error count exceeded limit",
1229 "because of 'kill drive' command from system",
1230 "because of selection timeout",
1231 "due to SCSI phase sequence error",
1232 "due to unknown status"
1233};
1234
1235static void
1236mlx_periodic_eventlog_respond(struct mlx_command *mc)
1237{
1238 struct mlx_softc *sc = mc->mc_sc;
1239 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data;
1240 char *reason;
1241
1242 debug_called(1);
1243
1244 sc->mlx_lastevent++; /* next message... */
1245 if (mc->mc_status == 0) {
1246
1247 /* handle event log message */
1248 switch(el->el_type) {
1249 /*
1250 * This is the only sort of message we understand at the moment.
1251 * The tests here are probably incomplete.
1252 */
1253 case MLX_LOGMSG_SENSE: /* sense data */
1254 /* Mylex vendor-specific message indicating a drive was killed? */
1255 if ((el->el_sensekey == 9) &&
1256 (el->el_asc == 0x80)) {
1257 if (el->el_asq < (sizeof(mlx_sense_messages) / sizeof(mlx_sense_messages[0]))) {
1258 reason = mlx_sense_messages[el->el_asq];
1259 } else {
1260 reason = "for unknown reason";
1261 }
1262 device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n",
1263 el->el_channel, el->el_target, reason);
1264 }
1265 /* SCSI drive was reset? */
1266 if ((el->el_sensekey == 6) && (el->el_asc == 0x29)) {
1267 device_printf(sc->mlx_dev, "physical drive %d:%d reset\n",
1268 el->el_channel, el->el_target);
1269 }
1270 /* SCSI drive error? */
1271 if (!((el->el_sensekey == 0) ||
1272 ((el->el_sensekey == 2) &&
1273 (el->el_asc == 0x04) &&
1274 ((el->el_asq == 0x01) ||
1275 (el->el_asq == 0x02))))) {
1276 device_printf(sc->mlx_dev, "physical drive %d:%d error log: sense = %d asc = %x asq = %x\n",
1277 el->el_channel, el->el_target, el->el_sensekey, el->el_asc, el->el_asq);
1278 device_printf(sc->mlx_dev, " info %4D csi %4D\n", el->el_information, ":", el->el_csi, ":");
1279 }
1280 break;
1281
1282 default:
1283 device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type);
1284 break;
1285 }
1286 } else {
1287 device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc));
1288 panic("log operation failed: lastevent = %d, currevent = %d",
1289 sc->mlx_lastevent, sc->mlx_currevent);
1290 }
1291
1292 /* dispose of command and data */
1293 free(mc->mc_data, M_DEVBUF);
1294 mlx_releasecmd(mc);
1295
1296 /* is there another message to obtain? */
1297 if (sc->mlx_lastevent != sc->mlx_currevent)
1298 mlx_periodic_eventlog_poll(sc);
1299}
1300
1301/********************************************************************************
1302 * Handle check/rebuild operations in progress.
1303 */
1304static void
1305mlx_periodic_rebuild(struct mlx_command *mc)
1306{
1307 struct mlx_softc *sc = mc->mc_sc;
1308 struct mlx_rebuild_status *mr = (struct mlx_rebuild_status *)mc->mc_data;
1309
1310 switch(mc->mc_status) {
1311 case 0: /* operation running, update stats */
1312 sc->mlx_rebuildstat = *mr;
1313
1314 /* spontaneous rebuild/check? */
1315 if (sc->mlx_background == 0) {
1316 sc->mlx_background = MLX_BACKGROUND_SPONTANEOUS;
1317 device_printf(sc->mlx_dev, "background check/rebuild operation started\n");
1318 }
1319 break;
1320
1321 case 0x0105: /* nothing running, finalise stats and report */
1322 switch(sc->mlx_background) {
1323 case MLX_BACKGROUND_CHECK:
1324 device_printf(sc->mlx_dev, "consistency check completed\n"); /* XXX print drive? */
1325 break;
1326 case MLX_BACKGROUND_REBUILD:
1327 device_printf(sc->mlx_dev, "drive rebuild completed\n"); /* XXX print channel/target? */
1328 break;
1329 case MLX_BACKGROUND_SPONTANEOUS:
1330 default:
1331 /* if we have previously been non-idle, report the transition */
1332 if (sc->mlx_rebuildstat.rs_code != MLX_REBUILDSTAT_IDLE) {
1333 device_printf(sc->mlx_dev, "background check/rebuild operation completed\n");
1334 }
1335 }
1336 sc->mlx_background = 0;
1337 sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
1338 break;
1339 }
1340 free(mc->mc_data, M_DEVBUF);
1341 mlx_releasecmd(mc);
1342}
1343
1344/********************************************************************************
1345 ********************************************************************************
1346 Channel Pause
1347 ********************************************************************************
1348 ********************************************************************************/
1349
1350/********************************************************************************
1351 * It's time to perform a channel pause action for (sc), either start or stop
1352 * the pause.
1353 */
1354static void
1355mlx_pause_action(struct mlx_softc *sc)
1356{
1357 struct mlx_command *mc;
1358 int failsafe, i, command;
1359
1360 /* What are we doing here? */
1361 if (sc->mlx_pause.mp_when == 0) {
1362 command = MLX_CMD_STARTCHANNEL;
1363 failsafe = 0;
1364
1365 } else {
1366 command = MLX_CMD_STOPCHANNEL;
1367
1368 /*
1369 * Channels will always start again after the failsafe period,
1370 * which is specified in multiples of 30 seconds.
1371 * This constrains us to a maximum pause of 450 seconds.
1372 */
1373 failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30;
1374 if (failsafe > 0xf) {
1375 failsafe = 0xf;
1376 sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5;
1377 }
1378 }
1379
1380 /* build commands for every channel requested */
1381 for (i = 0; i < sc->mlx_enq2->me_actual_channels; i++) {
1382 if ((1 << i) & sc->mlx_pause.mp_which) {
1383
1384 /* get ourselves a command buffer */
1385 if ((mc = mlx_alloccmd(sc)) == NULL)
1386 goto fail;
1387 /* get a command slot */
1388 mc->mc_flags |= MLX_CMD_PRIORITY;
1389 if (mlx_getslot(mc))
1390 goto fail;
1391
1392 /* build the command */
1393 mlx_make_type2(mc, command, (failsafe << 4) | i, 0, 0, 0, 0, 0, 0, 0);
1394 mc->mc_complete = mlx_pause_done;
1395 mc->mc_private = sc; /* XXX not needed */
1396 if (mlx_start(mc))
1397 goto fail;
1398 /* command submitted OK */
1399 return;
1400
1401 fail:
1402 device_printf(sc->mlx_dev, "%s failed for channel %d\n",
1403 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i);
1404 if (mc != NULL)
1405 mlx_releasecmd(mc);
1406 }
1407 }
1408}
1409
1410static void
1411mlx_pause_done(struct mlx_command *mc)
1412{
1413 struct mlx_softc *sc = mc->mc_sc;
1414 int command = mc->mc_mailbox[0];
1415 int channel = mc->mc_mailbox[2] & 0xf;
1416
1417 if (mc->mc_status != 0) {
1418 device_printf(sc->mlx_dev, "%s command failed - %s\n",
1419 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc));
1420 } else if (command == MLX_CMD_STOPCHANNEL) {
1421 device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n",
1422 channel, (long)(sc->mlx_pause.mp_howlong - time_second));
1423 } else {
1424 device_printf(sc->mlx_dev, "channel %d resuming\n", channel);
1425 }
1426 mlx_releasecmd(mc);
1427}
1428
1429/********************************************************************************
1430 ********************************************************************************
1431 Command Submission
1432 ********************************************************************************
1433 ********************************************************************************/
1434
1435/********************************************************************************
1436 * Perform an Enquiry command using a type-3 command buffer and a return a single
1437 * linear result buffer. If the completion function is specified, it will
1438 * be called with the completed command (and the result response will not be
1439 * valid until that point). Otherwise, the command will either be busy-waited
1440 * for (interrupts not enabled), or slept for.
1441 */
1442static void *
1443mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1444{
1445 struct mlx_command *mc;
1446 void *result;
1447 int error;
1448
1449 debug_called(1);
1450
1451 /* get ourselves a command buffer */
1452 error = 1;
1453 result = NULL;
1454 if ((mc = mlx_alloccmd(sc)) == NULL)
1455 goto out;
1456 /* allocate the response structure */
1457 if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
1458 goto out;
1459 /* get a command slot */
1460 mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT;
1461 if (mlx_getslot(mc))
1462 goto out;
1463
1464 /* map the command so the controller can see it */
1465 mc->mc_data = result;
1466 mc->mc_length = bufsize;
1467 mlx_mapcmd(mc);
1468
1469 /* build an enquiry command */
1470 mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0);
1471
1472 /* do we want a completion callback? */
1473 if (complete != NULL) {
1474 mc->mc_complete = complete;
1475 mc->mc_private = mc;
1476 if ((error = mlx_start(mc)) != 0)
1477 goto out;
1478 } else {
1479 /* run the command in either polled or wait mode */
1480 if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1481 goto out;
1482
1483 /* command completed OK? */
1484 if (mc->mc_status != 0) {
1485 device_printf(sc->mlx_dev, "ENQUIRY failed - %s\n", mlx_diagnose_command(mc));
1486 goto out;
1487 }
1488 }
1489 error = 0; /* success */
1490 out:
1491 /* we got a command, but nobody else will free it */
1492 if ((complete == NULL) && (mc != NULL))
1493 mlx_releasecmd(mc);
1494 /* we got an error, and we allocated a result */
1495 if ((error != 0) && (result != NULL)) {
1496 free(result, M_DEVBUF);
1497 result = NULL;
1498 }
1499 return(result);
1500}
1501
1502
1503/********************************************************************************
1504 * Perform a Flush command on the nominated controller.
1505 *
1506 * May be called with interrupts enabled or disabled; will not return until
1507 * the flush operation completes or fails.
1508 */
1509static int
1510mlx_flush(struct mlx_softc *sc)
1511{
1512 struct mlx_command *mc;
1513 int error;
1514
1515 debug_called(1);
1516
1517 /* get ourselves a command buffer */
1518 error = 1;
1519 if ((mc = mlx_alloccmd(sc)) == NULL)
1520 goto out;
1521 /* get a command slot */
1522 if (mlx_getslot(mc))
1523 goto out;
1524
1525 /* build a flush command */
1526 mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1527
1528 /* can't assume that interrupts are going to work here, so play it safe */
1529 if (mlx_poll_command(mc))
1530 goto out;
1531
1532 /* command completed OK? */
1533 if (mc->mc_status != 0) {
1534 device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1535 goto out;
1536 }
1537
1538 error = 0; /* success */
1539 out:
1540 if (mc != NULL)
1541 mlx_releasecmd(mc);
1542 return(error);
1543}
1544
1545/********************************************************************************
1546 * Start a background consistency check on (drive).
1547 *
1548 * May be called with interrupts enabled or disabled; will return as soon as the
1549 * operation has started or been refused.
1550 */
1551static int
1552mlx_check(struct mlx_softc *sc, int drive)
1553{
1554 struct mlx_command *mc;
1555 int error;
1556
1557 debug_called(1);
1558
1559 /* get ourselves a command buffer */
1560 error = 0x10000;
1561 if ((mc = mlx_alloccmd(sc)) == NULL)
1562 goto out;
1563 /* get a command slot */
1564 if (mlx_getslot(mc))
1565 goto out;
1566
1567 /* build a checkasync command, set the "fix it" flag */
1568 mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80, 0, 0);
1569
1570 /* start the command and wait for it to be returned */
1571 if (mlx_wait_command(mc))
1572 goto out;
1573
1574 /* command completed OK? */
1575 if (mc->mc_status != 0) {
1576 device_printf(sc->mlx_dev, "CHECK ASYNC failed - %s\n", mlx_diagnose_command(mc));
1577 } else {
1578 device_printf(sc->mlx_sysdrive[drive].ms_disk, "consistency check started");
1579 }
1580 error = mc->mc_status;
1581
1582 out:
1583 if (mc != NULL)
1584 mlx_releasecmd(mc);
1585 return(error);
1586}
1587
1588/********************************************************************************
1589 * Start a background rebuild of the physical drive at (channel),(target).
1590 *
1591 * May be called with interrupts enabled or disabled; will return as soon as the
1592 * operation has started or been refused.
1593 */
1594static int
1595mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1596{
1597 struct mlx_command *mc;
1598 int error;
1599
1600 debug_called(1);
1601
1602 /* get ourselves a command buffer */
1603 error = 0x10000;
1604 if ((mc = mlx_alloccmd(sc)) == NULL)
1605 goto out;
1606 /* get a command slot */
1607 if (mlx_getslot(mc))
1608 goto out;
1609
1610 /* build a checkasync command, set the "fix it" flag */
1611 mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 0, 0);
1612
1613 /* start the command and wait for it to be returned */
1614 if (mlx_wait_command(mc))
1615 goto out;
1616
1617 /* command completed OK? */
1618 if (mc->mc_status != 0) {
1619 device_printf(sc->mlx_dev, "REBUILD ASYNC failed - %s\n", mlx_diagnose_command(mc));
1620 } else {
1621 device_printf(sc->mlx_dev, "drive rebuild started for %d:%d\n", channel, target);
1622 }
1623 error = mc->mc_status;
1624
1625 out:
1626 if (mc != NULL)
1627 mlx_releasecmd(mc);
1628 return(error);
1629}
1630
1631/********************************************************************************
1632 * Run the command (mc) and return when it completes.
1633 *
1634 * Interrupts need to be enabled; returns nonzero on error.
1635 */
1636static int
1637mlx_wait_command(struct mlx_command *mc)
1638{
1639 struct mlx_softc *sc = mc->mc_sc;
1640 int error, count;
1641
1642 debug_called(1);
1643
1644 mc->mc_complete = NULL;
1645 mc->mc_private = mc; /* wake us when you're done */
1646 if ((error = mlx_start(mc)) != 0)
1647 return(error);
1648
1649 count = 0;
1650 /* XXX better timeout? */
1651 while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
1652 tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz);
1653 }
1654
1655 if (mc->mc_status != 0) {
1656 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1657 return(EIO);
1658 }
1659 return(0);
1660}
1661
1662
1663/********************************************************************************
1664 * Start the command (mc) and busy-wait for it to complete.
1665 *
1666 * Should only be used when interrupts can't be relied upon. Returns 0 on
1667 * success, nonzero on error.
1668 * Successfully completed commands are dequeued.
1669 */
1670static int
1671mlx_poll_command(struct mlx_command *mc)
1672{
1673 struct mlx_softc *sc = mc->mc_sc;
1674 int error, count, s;
1675
1676 debug_called(1);
1677
1678 mc->mc_complete = NULL;
1679 mc->mc_private = NULL; /* we will poll for it */
1680 if ((error = mlx_start(mc)) != 0)
1681 return(error);
1682
1683 count = 0;
1684 do {
1685 /* poll for completion */
1686 mlx_done(mc->mc_sc);
1687
1688 } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000));
1689 if (mc->mc_status != MLX_STATUS_BUSY) {
1690 s = splbio();
1691 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1692 splx(s);
1693 return(0);
1694 }
1695 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1696 return(EIO);
1697}
1698
1699/********************************************************************************
1700 * Pull as much work off the softc's work queue as possible and give it to the
1701 * controller. Leave a couple of slots free for emergencies.
1702 *
1703 * Must be called at splbio or in an equivalent fashion that prevents
1704 * reentry or activity on the bufq.
1704 * reentry or activity on the bioq.
1705 */
1706static void
1707mlx_startio(struct mlx_softc *sc)
1708{
1709 struct mlx_command *mc;
1710 struct mlxd_softc *mlxd;
1705 */
1706static void
1707mlx_startio(struct mlx_softc *sc)
1708{
1709 struct mlx_command *mc;
1710 struct mlxd_softc *mlxd;
1711 struct buf *bp;
1711 struct bio *bp;
1712 int blkcount;
1713 int driveno;
1714 int cmd;
1715 int s;
1716
1717 /* avoid reentrancy */
1718 if (mlx_lock_tas(sc, MLX_LOCK_STARTING))
1719 return;
1720
1721 /* spin until something prevents us from doing any work */
1722 s = splbio();
1723 for (;;) {
1724
1725 /* see if there's work to be done */
1712 int blkcount;
1713 int driveno;
1714 int cmd;
1715 int s;
1716
1717 /* avoid reentrancy */
1718 if (mlx_lock_tas(sc, MLX_LOCK_STARTING))
1719 return;
1720
1721 /* spin until something prevents us from doing any work */
1722 s = splbio();
1723 for (;;) {
1724
1725 /* see if there's work to be done */
1726 if ((bp = bufq_first(&sc->mlx_bufq)) == NULL)
1726 if ((bp = bioq_first(&sc->mlx_bioq)) == NULL)
1727 break;
1728 /* get a command */
1729 if ((mc = mlx_alloccmd(sc)) == NULL)
1730 break;
1731 /* get a slot for the command */
1732 if (mlx_getslot(mc) != 0) {
1733 mlx_releasecmd(mc);
1734 break;
1735 }
1736 /* get the buf containing our work */
1727 break;
1728 /* get a command */
1729 if ((mc = mlx_alloccmd(sc)) == NULL)
1730 break;
1731 /* get a slot for the command */
1732 if (mlx_getslot(mc) != 0) {
1733 mlx_releasecmd(mc);
1734 break;
1735 }
1736 /* get the buf containing our work */
1737 bufq_remove(&sc->mlx_bufq, bp);
1737 bioq_remove(&sc->mlx_bioq, bp);
1738 sc->mlx_waitbufs--;
1739 splx(s);
1740
1741 /* connect the buf to the command */
1742 mc->mc_complete = mlx_completeio;
1743 mc->mc_private = bp;
1738 sc->mlx_waitbufs--;
1739 splx(s);
1740
1741 /* connect the buf to the command */
1742 mc->mc_complete = mlx_completeio;
1743 mc->mc_private = bp;
1744 mc->mc_data = bp->b_data;
1745 mc->mc_length = bp->b_bcount;
1746 if (bp->b_iocmd == BIO_READ) {
1744 mc->mc_data = bp->bio_data;
1745 mc->mc_length = bp->bio_bcount;
1746 if (bp->bio_cmd == BIO_READ) {
1747 mc->mc_flags |= MLX_CMD_DATAIN;
1748 cmd = MLX_CMD_READSG;
1749 } else {
1750 mc->mc_flags |= MLX_CMD_DATAOUT;
1751 cmd = MLX_CMD_WRITESG;
1752 }
1753
1754 /* map the command so the controller can work with it */
1755 mlx_mapcmd(mc);
1756
1757 /* build a suitable I/O command (assumes 512-byte rounded transfers) */
1747 mc->mc_flags |= MLX_CMD_DATAIN;
1748 cmd = MLX_CMD_READSG;
1749 } else {
1750 mc->mc_flags |= MLX_CMD_DATAOUT;
1751 cmd = MLX_CMD_WRITESG;
1752 }
1753
1754 /* map the command so the controller can work with it */
1755 mlx_mapcmd(mc);
1756
1757 /* build a suitable I/O command (assumes 512-byte rounded transfers) */
1758 mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
1758 mlxd = (struct mlxd_softc *)bp->bio_dev->si_drv1;
1759 driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
1759 driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
1760 blkcount = (bp->b_bcount + MLX_BLKSIZE - 1) / MLX_BLKSIZE;
1760 blkcount = (bp->bio_bcount + MLX_BLKSIZE - 1) / MLX_BLKSIZE;
1761
1761
1762 if ((bp->b_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1762 if ((bp->bio_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1763 device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n",
1763 device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n",
1764 bp->b_pblkno, blkcount, sc->mlx_sysdrive[driveno].ms_size);
1764 bp->bio_pblkno, blkcount, sc->mlx_sysdrive[driveno].ms_size);
1765
1766 /*
1767 * Build the I/O command. Note that the SG list type bits are set to zero,
1768 * denoting the format of SG list that we are using.
1769 */
1770 if (sc->mlx_iftype == MLX_IFTYPE_2) {
1771 mlx_make_type1(mc, (cmd == MLX_CMD_WRITESG) ? MLX_CMD_WRITESG_OLD : MLX_CMD_READSG_OLD,
1772 blkcount & 0xff, /* xfer length low byte */
1765
1766 /*
1767 * Build the I/O command. Note that the SG list type bits are set to zero,
1768 * denoting the format of SG list that we are using.
1769 */
1770 if (sc->mlx_iftype == MLX_IFTYPE_2) {
1771 mlx_make_type1(mc, (cmd == MLX_CMD_WRITESG) ? MLX_CMD_WRITESG_OLD : MLX_CMD_READSG_OLD,
1772 blkcount & 0xff, /* xfer length low byte */
1773 bp->b_pblkno, /* physical block number */
1773 bp->bio_pblkno, /* physical block number */
1774 driveno, /* target drive number */
1775 mc->mc_sgphys, /* location of SG list */
1776 mc->mc_nsgent & 0x3f); /* size of SG list (top 3 bits clear) */
1777 } else {
1778 mlx_make_type5(mc, cmd,
1779 blkcount & 0xff, /* xfer length low byte */
1780 (driveno << 3) | ((blkcount >> 8) & 0x07), /* target and length high 3 bits */
1774 driveno, /* target drive number */
1775 mc->mc_sgphys, /* location of SG list */
1776 mc->mc_nsgent & 0x3f); /* size of SG list (top 3 bits clear) */
1777 } else {
1778 mlx_make_type5(mc, cmd,
1779 blkcount & 0xff, /* xfer length low byte */
1780 (driveno << 3) | ((blkcount >> 8) & 0x07), /* target and length high 3 bits */
1781 bp->b_pblkno, /* physical block number */
1781 bp->bio_pblkno, /* physical block number */
1782 mc->mc_sgphys, /* location of SG list */
1783 mc->mc_nsgent & 0x3f); /* size of SG list (top 3 bits clear) */
1784 }
1785
1786 /* try to give command to controller */
1787 if (mlx_start(mc) != 0) {
1788 /* fail the command */
1789 mc->mc_status = MLX_STATUS_WEDGED;
1790 mlx_completeio(mc);
1791 }
1792 s = splbio();
1793 }
1794 splx(s);
1795 mlx_lock_clr(sc, MLX_LOCK_STARTING);
1796}
1797
1798/********************************************************************************
1799 * Handle completion of an I/O command.
1800 */
1801static void
1802mlx_completeio(struct mlx_command *mc)
1803{
1804 struct mlx_softc *sc = mc->mc_sc;
1782 mc->mc_sgphys, /* location of SG list */
1783 mc->mc_nsgent & 0x3f); /* size of SG list (top 3 bits clear) */
1784 }
1785
1786 /* try to give command to controller */
1787 if (mlx_start(mc) != 0) {
1788 /* fail the command */
1789 mc->mc_status = MLX_STATUS_WEDGED;
1790 mlx_completeio(mc);
1791 }
1792 s = splbio();
1793 }
1794 splx(s);
1795 mlx_lock_clr(sc, MLX_LOCK_STARTING);
1796}
1797
1798/********************************************************************************
1799 * Handle completion of an I/O command.
1800 */
1801static void
1802mlx_completeio(struct mlx_command *mc)
1803{
1804 struct mlx_softc *sc = mc->mc_sc;
1805 struct buf *bp = (struct buf *)mc->mc_private;
1806 struct mlxd_softc *mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
1805 struct bio *bp = (struct bio *)mc->mc_private;
1806 struct mlxd_softc *mlxd = (struct mlxd_softc *)bp->bio_dev->si_drv1;
1807
1808 if (mc->mc_status != MLX_STATUS_OK) { /* could be more verbose here? */
1807
1808 if (mc->mc_status != MLX_STATUS_OK) { /* could be more verbose here? */
1809 bp->b_error = EIO;
1810 bp->b_ioflags |= BIO_ERROR;
1809 bp->bio_error = EIO;
1810 bp->bio_flags |= BIO_ERROR;
1811
1812 switch(mc->mc_status) {
1813 case MLX_STATUS_RDWROFFLINE: /* system drive has gone offline */
1814 device_printf(mlxd->mlxd_dev, "drive offline\n");
1815 /* should signal this with a return code */
1816 mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE;
1817 break;
1818
1819 default: /* other I/O error */
1820 device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc));
1821#if 0
1822 device_printf(sc->mlx_dev, " b_bcount %ld blkcount %ld b_pblkno %d\n",
1811
1812 switch(mc->mc_status) {
1813 case MLX_STATUS_RDWROFFLINE: /* system drive has gone offline */
1814 device_printf(mlxd->mlxd_dev, "drive offline\n");
1815 /* should signal this with a return code */
1816 mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE;
1817 break;
1818
1819 default: /* other I/O error */
1820 device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc));
1821#if 0
1822 device_printf(sc->mlx_dev, " b_bcount %ld blkcount %ld b_pblkno %d\n",
1823 bp->b_bcount, bp->b_bcount / MLX_BLKSIZE, bp->b_pblkno);
1823 bp->bio_bcount, bp->bio_bcount / MLX_BLKSIZE, bp->bio_pblkno);
1824 device_printf(sc->mlx_dev, " %13D\n", mc->mc_mailbox, " ");
1825#endif
1826 break;
1827 }
1828 }
1829 mlx_releasecmd(mc);
1830 mlxd_intr(bp);
1831}
1832
1833/********************************************************************************
1834 * Take a command from user-space and try to run it.
1835 *
1836 * XXX Note that this can't perform very much in the way of error checking, and
1837 * as such, applications _must_ be considered trustworthy.
1838 * XXX Commands using S/G for data are not supported.
1839 */
1840static int
1841mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
1842{
1843 struct mlx_command *mc;
1844 struct mlx_dcdb *dcdb;
1845 void *kbuf;
1846 int error;
1847
1848 debug_called(0);
1849
1850 kbuf = NULL;
1851 mc = NULL;
1852 dcdb = NULL;
1853 error = ENOMEM;
1854
1855 /* get ourselves a command and copy in from user space */
1856 if ((mc = mlx_alloccmd(sc)) == NULL)
1857 goto out;
1858 bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
1859 debug(0, "got command buffer");
1860
1861 /* if we need a buffer for data transfer, allocate one and copy in its initial contents */
1862 if (mu->mu_datasize > 0) {
1863 if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) ||
1864 (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize)))
1865 goto out;
1866 debug(0, "got kernel buffer");
1867 }
1868
1869 /* get a command slot */
1870 if (mlx_getslot(mc))
1871 goto out;
1872 debug(0, "got a slot");
1873
1874 /* map the command so the controller can see it */
1875 mc->mc_data = kbuf;
1876 mc->mc_length = mu->mu_datasize;
1877 mlx_mapcmd(mc);
1878 debug(0, "mapped");
1879
1880 /*
1881 * If this is a passthrough SCSI command, the DCDB is packed at the
1882 * beginning of the data area. Fix up the DCDB to point to the correct physical
1883 * address and override any bufptr supplied by the caller since we know
1884 * what it's meant to be.
1885 */
1886 if (mc->mc_mailbox[0] == MLX_CMD_DIRECT_CDB) {
1887 dcdb = (struct mlx_dcdb *)kbuf;
1888 dcdb->dcdb_physaddr = mc->mc_dataphys + sizeof(*dcdb);
1889 mu->mu_bufptr = 8;
1890 }
1891
1892 /*
1893 * If there's a data buffer, fix up the command's buffer pointer.
1894 */
1895 if (mu->mu_datasize > 0) {
1896
1897 /* range check the pointer to physical buffer address */
1898 if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) - sizeof(u_int32_t)))) {
1899 error = EINVAL;
1900 goto out;
1901 }
1902 mc->mc_mailbox[mu->mu_bufptr ] = mc->mc_dataphys & 0xff;
1903 mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_dataphys >> 8) & 0xff;
1904 mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_dataphys >> 16) & 0xff;
1905 mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_dataphys >> 24) & 0xff;
1906 }
1907 debug(0, "command fixup");
1908
1909 /* submit the command and wait */
1910 if ((error = mlx_wait_command(mc)) != 0)
1911 goto out;
1912
1913 /* copy out status and data */
1914 mu->mu_status = mc->mc_status;
1915 if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize))))
1916 goto out;
1917 error = 0;
1918
1919 out:
1920 mlx_releasecmd(mc);
1921 if (kbuf != NULL)
1922 free(kbuf, M_DEVBUF);
1923 return(error);
1924}
1925
1926/********************************************************************************
1927 ********************************************************************************
1928 Command I/O to Controller
1929 ********************************************************************************
1930 ********************************************************************************/
1931
1932/********************************************************************************
1933 * Find a free command slot for (mc).
1934 *
1935 * Don't hand out a slot to a normal-priority command unless there are at least
1936 * 4 slots free for priority commands.
1937 */
1938static int
1939mlx_getslot(struct mlx_command *mc)
1940{
1941 struct mlx_softc *sc = mc->mc_sc;
1942 int s, slot;
1943
1944 debug_called(1);
1945
1946 /* enforce slot-usage limit */
1947 if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ?
1948 sc->mlx_maxiop : sc->mlx_maxiop - 4))
1949 return(EBUSY);
1950
1951 /*
1952 * Allocate an outstanding command slot
1953 *
1954 * XXX linear search is slow
1955 */
1956 s = splbio();
1957 for (slot = 0; slot < sc->mlx_maxiop; slot++) {
1958 debug(2, "try slot %d", slot);
1959 if (sc->mlx_busycmd[slot] == NULL)
1960 break;
1961 }
1962 if (slot < sc->mlx_maxiop) {
1963 sc->mlx_busycmd[slot] = mc;
1964 sc->mlx_busycmds++;
1965 }
1966 splx(s);
1967
1968 /* out of slots? */
1969 if (slot >= sc->mlx_maxiop)
1970 return(EBUSY);
1971
1972 debug(2, "got slot %d", slot);
1973 mc->mc_slot = slot;
1974 return(0);
1975}
1976
1977/********************************************************************************
1978 * Map/unmap (mc)'s data in the controller's addressable space.
1979 */
1980static void
1981mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1982{
1983 struct mlx_command *mc = (struct mlx_command *)arg;
1984 struct mlx_softc *sc = mc->mc_sc;
1985 struct mlx_sgentry *sg;
1986 int i;
1987
1988 debug_called(1);
1989
1990 /* get base address of s/g table */
1991 sg = sc->mlx_sgtable + (mc->mc_slot * sc->mlx_sg_nseg);
1992
1993 /* save s/g table information in command */
1994 mc->mc_nsgent = nsegments;
1995 mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * sc->mlx_sg_nseg * sizeof(struct mlx_sgentry));
1996 mc->mc_dataphys = segs[0].ds_addr;
1997
1998 /* populate s/g table */
1999 for (i = 0; i < nsegments; i++, sg++) {
2000 sg->sg_addr = segs[i].ds_addr;
2001 sg->sg_count = segs[i].ds_len;
2002 }
2003}
2004
2005static void
2006mlx_mapcmd(struct mlx_command *mc)
2007{
2008 struct mlx_softc *sc = mc->mc_sc;
2009
2010 debug_called(1);
2011
2012 /* if the command involves data at all */
2013 if (mc->mc_data != NULL) {
2014
2015 /* map the data buffer into bus space and build the s/g list */
2016 bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length,
2017 mlx_setup_dmamap, mc, 0);
2018 if (mc->mc_flags & MLX_CMD_DATAIN)
2019 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD);
2020 if (mc->mc_flags & MLX_CMD_DATAOUT)
2021 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE);
2022 }
2023}
2024
2025static void
2026mlx_unmapcmd(struct mlx_command *mc)
2027{
2028 struct mlx_softc *sc = mc->mc_sc;
2029
2030 debug_called(1);
2031
2032 /* if the command involved data at all */
2033 if (mc->mc_data != NULL) {
2034
2035 if (mc->mc_flags & MLX_CMD_DATAIN)
2036 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
2037 if (mc->mc_flags & MLX_CMD_DATAOUT)
2038 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
2039
2040 bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap);
2041 }
2042}
2043
2044/********************************************************************************
2045 * Try to deliver (mc) to the controller.
2046 *
2047 * Can be called at any interrupt level, with or without interrupts enabled.
2048 */
2049static int
2050mlx_start(struct mlx_command *mc)
2051{
2052 struct mlx_softc *sc = mc->mc_sc;
2053 int i, s, done;
2054
2055 debug_called(1);
2056
2057 /* save the slot number as ident so we can handle this command when complete */
2058 mc->mc_mailbox[0x1] = mc->mc_slot;
2059
2060 /* mark the command as currently being processed */
2061 mc->mc_status = MLX_STATUS_BUSY;
2062
2063 /* set a default 60-second timeout XXX tunable? XXX not currently used */
2064 mc->mc_timeout = time_second + 60;
2065
2066 /* spin waiting for the mailbox */
2067 for (i = 100000, done = 0; (i > 0) && !done; i--) {
2068 s = splbio();
2069 if (sc->mlx_tryqueue(sc, mc)) {
2070 done = 1;
2071 /* move command to work queue */
2072 TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
2073 }
2074 splx(s); /* drop spl to allow completion interrupts */
2075 }
2076
2077 /* command is enqueued */
2078 if (done)
2079 return(0);
2080
2081 /*
2082 * We couldn't get the controller to take the command. Revoke the slot
2083 * that the command was given and return it with a bad status.
2084 */
2085 sc->mlx_busycmd[mc->mc_slot] = NULL;
2086 device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
2087 mc->mc_status = MLX_STATUS_WEDGED;
2088 mlx_complete(sc);
2089 return(EIO);
2090}
2091
2092/********************************************************************************
2093 * Poll the controller (sc) for completed commands.
2094 * Update command status and free slots for reuse. If any slots were freed,
2095 * new commands may be posted.
2096 *
2097 * Returns nonzero if one or more commands were completed.
2098 */
2099static int
2100mlx_done(struct mlx_softc *sc)
2101{
2102 struct mlx_command *mc;
2103 int s, result;
2104 u_int8_t slot;
2105 u_int16_t status;
2106
2107 debug_called(2);
2108
2109 result = 0;
2110
2111 /* loop collecting completed commands */
2112 s = splbio();
2113 for (;;) {
2114 /* poll for a completed command's identifier and status */
2115 if (sc->mlx_findcomplete(sc, &slot, &status)) {
2116 result = 1;
2117 mc = sc->mlx_busycmd[slot]; /* find command */
2118 if (mc != NULL) { /* paranoia */
2119 if (mc->mc_status == MLX_STATUS_BUSY) {
2120 mc->mc_status = status; /* save status */
2121
2122 /* free slot for reuse */
2123 sc->mlx_busycmd[slot] = NULL;
2124 sc->mlx_busycmds--;
2125 } else {
2126 device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
2127 }
2128 } else {
2129 device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
2130 }
2131 } else {
2132 break;
2133 }
2134 }
2135
2136 /* if we've completed any commands, try posting some more */
2137 if (result)
2138 mlx_startio(sc);
2139
2140 /* handle completion and timeouts */
2141 mlx_complete(sc);
2142
2143 return(result);
2144}
2145
2146/********************************************************************************
2147 * Perform post-completion processing for commands on (sc).
2148 */
2149static void
2150mlx_complete(struct mlx_softc *sc)
2151{
2152 struct mlx_command *mc, *nc;
2153 int s, count;
2154
2155 debug_called(2);
2156
2157 /* avoid reentrancy XXX might want to signal and request a restart */
2158 if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING))
2159 return;
2160
2161 s = splbio();
2162 count = 0;
2163
2164 /* scan the list of busy/done commands */
2165 mc = TAILQ_FIRST(&sc->mlx_work);
2166 while (mc != NULL) {
2167 nc = TAILQ_NEXT(mc, mc_link);
2168
2169 /* Command has been completed in some fashion */
2170 if (mc->mc_status != MLX_STATUS_BUSY) {
2171
2172 /* unmap the command's data buffer */
2173 mlx_unmapcmd(mc);
2174 /*
2175 * Does the command have a completion handler?
2176 */
2177 if (mc->mc_complete != NULL) {
2178 /* remove from list and give to handler */
2179 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2180 mc->mc_complete(mc);
2181
2182 /*
2183 * Is there a sleeper waiting on this command?
2184 */
2185 } else if (mc->mc_private != NULL) { /* sleeping caller wants to know about it */
2186
2187 /* remove from list and wake up sleeper */
2188 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2189 wakeup_one(mc->mc_private);
2190
2191 /*
2192 * Leave the command for a caller that's polling for it.
2193 */
2194 } else {
2195 }
2196 }
2197 mc = nc;
2198 }
2199 splx(s);
2200
2201 mlx_lock_clr(sc, MLX_LOCK_COMPLETING);
2202}
2203
2204/********************************************************************************
2205 ********************************************************************************
2206 Command Buffer Management
2207 ********************************************************************************
2208 ********************************************************************************/
2209
2210/********************************************************************************
2211 * Get a new command buffer.
2212 *
2213 * This may return NULL in low-memory cases.
2214 *
2215 * Note that using malloc() is expensive (the command buffer is << 1 page) but
2216 * necessary if we are to be a loadable module before the zone allocator is fixed.
2217 *
2218 * If possible, we recycle a command buffer that's been used before.
2219 *
2220 * XXX Note that command buffers are not cleaned out - it is the caller's
2221 * responsibility to ensure that all required fields are filled in before
2222 * using a buffer.
2223 */
2224static struct mlx_command *
2225mlx_alloccmd(struct mlx_softc *sc)
2226{
2227 struct mlx_command *mc;
2228 int error;
2229 int s;
2230
2231 debug_called(1);
2232
2233 s = splbio();
2234 if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2235 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2236 splx(s);
2237
2238 /* allocate a new command buffer? */
2239 if (mc == NULL) {
2240 mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT);
2241 if (mc != NULL) {
2242 bzero(mc, sizeof(*mc));
2243 mc->mc_sc = sc;
2244 error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap);
2245 if (error) {
2246 free(mc, M_DEVBUF);
2247 return(NULL);
2248 }
2249 }
2250 }
2251 return(mc);
2252}
2253
2254/********************************************************************************
2255 * Release a command buffer for recycling.
2256 *
2257 * XXX It might be a good idea to limit the number of commands we save for reuse
2258 * if it's shown that this list bloats out massively.
2259 */
2260static void
2261mlx_releasecmd(struct mlx_command *mc)
2262{
2263 int s;
2264
2265 debug_called(1);
2266
2267 s = splbio();
2268 TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
2269 splx(s);
2270}
2271
2272/********************************************************************************
2273 * Permanently discard a command buffer.
2274 */
2275static void
2276mlx_freecmd(struct mlx_command *mc)
2277{
2278 struct mlx_softc *sc = mc->mc_sc;
2279
2280 debug_called(1);
2281 bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
2282 free(mc, M_DEVBUF);
2283}
2284
2285
2286/********************************************************************************
2287 ********************************************************************************
2288 Type 3 interface accessor methods
2289 ********************************************************************************
2290 ********************************************************************************/
2291
2292/********************************************************************************
2293 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2294 * (the controller is not ready to take a command).
2295 *
2296 * Must be called at splbio or in a fashion that prevents reentry.
2297 */
2298static int
2299mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2300{
2301 int i;
2302
2303 debug_called(2);
2304
2305 /* ready for our command? */
2306 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) {
2307 /* copy mailbox data to window */
2308 for (i = 0; i < 13; i++)
2309 MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2310
2311 /* post command */
2312 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL);
2313 return(1);
2314 }
2315 return(0);
2316}
2317
2318/********************************************************************************
2319 * See if a command has been completed, if so acknowledge its completion
2320 * and recover the slot number and status code.
2321 *
2322 * Must be called at splbio or in a fashion that prevents reentry.
2323 */
2324static int
2325mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2326{
2327
2328 debug_called(2);
2329
2330 /* status available? */
2331 if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) {
2332 *slot = MLX_V3_GET_STATUS_IDENT(sc); /* get command identifier */
2333 *status = MLX_V3_GET_STATUS(sc); /* get status */
2334
2335 /* acknowledge completion */
2336 MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);
2337 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2338 return(1);
2339 }
2340 return(0);
2341}
2342
2343/********************************************************************************
2344 * Enable/disable interrupts as requested. (No acknowledge required)
2345 *
2346 * Must be called at splbio or in a fashion that prevents reentry.
2347 */
2348static void
2349mlx_v3_intaction(struct mlx_softc *sc, int action)
2350{
2351 debug_called(1);
2352
2353 switch(action) {
2354 case MLX_INTACTION_DISABLE:
2355 MLX_V3_PUT_IER(sc, 0);
2356 sc->mlx_state &= ~MLX_STATE_INTEN;
2357 break;
2358 case MLX_INTACTION_ENABLE:
2359 MLX_V3_PUT_IER(sc, 1);
2360 sc->mlx_state |= MLX_STATE_INTEN;
2361 break;
2362 }
2363}
2364
2365/********************************************************************************
2366 * Poll for firmware error codes during controller initialisation.
2367 * Returns 0 if initialisation is complete, 1 if still in progress but no
2368 * error has been fetched, 2 if an error has been retrieved.
2369 */
2370static int
2371mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2372{
2373 u_int8_t fwerror;
2374 static int initted = 0;
2375
2376 debug_called(2);
2377
2378 /* first time around, clear any hardware completion status */
2379 if (!initted) {
2380 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2381 DELAY(1000);
2382 initted = 1;
2383 }
2384
2385 /* init in progress? */
2386 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY))
2387 return(0);
2388
2389 /* test error value */
2390 fwerror = MLX_V3_GET_FWERROR(sc);
2391 if (!(fwerror & MLX_V3_FWERROR_PEND))
2392 return(1);
2393
2394 /* mask status pending bit, fetch status */
2395 *error = fwerror & ~MLX_V3_FWERROR_PEND;
2396 *param1 = MLX_V3_GET_FWERROR_PARAM1(sc);
2397 *param2 = MLX_V3_GET_FWERROR_PARAM2(sc);
2398
2399 /* acknowledge */
2400 MLX_V3_PUT_FWERROR(sc, 0);
2401
2402 return(2);
2403}
2404
2405/********************************************************************************
2406 ********************************************************************************
2407 Type 4 interface accessor methods
2408 ********************************************************************************
2409 ********************************************************************************/
2410
2411/********************************************************************************
2412 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2413 * (the controller is not ready to take a command).
2414 *
2415 * Must be called at splbio or in a fashion that prevents reentry.
2416 */
2417static int
2418mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2419{
2420 int i;
2421
2422 debug_called(2);
2423
2424 /* ready for our command? */
2425 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
2426 /* copy mailbox data to window */
2427 for (i = 0; i < 13; i++)
2428 MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2429
2430 /* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */
2431 bus_space_barrier(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH,
2432 BUS_SPACE_BARRIER_WRITE);
2433
2434 /* post command */
2435 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
2436 return(1);
2437 }
2438 return(0);
2439}
2440
2441/********************************************************************************
2442 * See if a command has been completed, if so acknowledge its completion
2443 * and recover the slot number and status code.
2444 *
2445 * Must be called at splbio or in a fashion that prevents reentry.
2446 */
2447static int
2448mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2449{
2450
2451 debug_called(2);
2452
2453 /* status available? */
2454 if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
2455 *slot = MLX_V4_GET_STATUS_IDENT(sc); /* get command identifier */
2456 *status = MLX_V4_GET_STATUS(sc); /* get status */
2457
2458 /* acknowledge completion */
2459 MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);
2460 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2461 return(1);
2462 }
2463 return(0);
2464}
2465
2466/********************************************************************************
2467 * Enable/disable interrupts as requested.
2468 *
2469 * Must be called at splbio or in a fashion that prevents reentry.
2470 */
2471static void
2472mlx_v4_intaction(struct mlx_softc *sc, int action)
2473{
2474 debug_called(1);
2475
2476 switch(action) {
2477 case MLX_INTACTION_DISABLE:
2478 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT);
2479 sc->mlx_state &= ~MLX_STATE_INTEN;
2480 break;
2481 case MLX_INTACTION_ENABLE:
2482 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT);
2483 sc->mlx_state |= MLX_STATE_INTEN;
2484 break;
2485 }
2486}
2487
2488/********************************************************************************
2489 * Poll for firmware error codes during controller initialisation.
2490 * Returns 0 if initialisation is complete, 1 if still in progress but no
2491 * error has been fetched, 2 if an error has been retrieved.
2492 */
2493static int
2494mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2495{
2496 u_int8_t fwerror;
2497 static int initted = 0;
2498
2499 debug_called(2);
2500
2501 /* first time around, clear any hardware completion status */
2502 if (!initted) {
2503 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2504 DELAY(1000);
2505 initted = 1;
2506 }
2507
2508 /* init in progress? */
2509 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY))
2510 return(0);
2511
2512 /* test error value */
2513 fwerror = MLX_V4_GET_FWERROR(sc);
2514 if (!(fwerror & MLX_V4_FWERROR_PEND))
2515 return(1);
2516
2517 /* mask status pending bit, fetch status */
2518 *error = fwerror & ~MLX_V4_FWERROR_PEND;
2519 *param1 = MLX_V4_GET_FWERROR_PARAM1(sc);
2520 *param2 = MLX_V4_GET_FWERROR_PARAM2(sc);
2521
2522 /* acknowledge */
2523 MLX_V4_PUT_FWERROR(sc, 0);
2524
2525 return(2);
2526}
2527
2528/********************************************************************************
2529 ********************************************************************************
2530 Type 5 interface accessor methods
2531 ********************************************************************************
2532 ********************************************************************************/
2533
2534/********************************************************************************
2535 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2536 * (the controller is not ready to take a command).
2537 *
2538 * Must be called at splbio or in a fashion that prevents reentry.
2539 */
2540static int
2541mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2542{
2543 int i;
2544
2545 debug_called(2);
2546
2547 /* ready for our command? */
2548 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) {
2549 /* copy mailbox data to window */
2550 for (i = 0; i < 13; i++)
2551 MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2552
2553 /* post command */
2554 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
2555 return(1);
2556 }
2557 return(0);
2558}
2559
2560/********************************************************************************
2561 * See if a command has been completed, if so acknowledge its completion
2562 * and recover the slot number and status code.
2563 *
2564 * Must be called at splbio or in a fashion that prevents reentry.
2565 */
2566static int
2567mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2568{
2569
2570 debug_called(2);
2571
2572 /* status available? */
2573 if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) {
2574 *slot = MLX_V5_GET_STATUS_IDENT(sc); /* get command identifier */
2575 *status = MLX_V5_GET_STATUS(sc); /* get status */
2576
2577 /* acknowledge completion */
2578 MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK);
2579 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2580 return(1);
2581 }
2582 return(0);
2583}
2584
2585/********************************************************************************
2586 * Enable/disable interrupts as requested.
2587 *
2588 * Must be called at splbio or in a fashion that prevents reentry.
2589 */
2590static void
2591mlx_v5_intaction(struct mlx_softc *sc, int action)
2592{
2593 debug_called(1);
2594
2595 switch(action) {
2596 case MLX_INTACTION_DISABLE:
2597 MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT);
2598 sc->mlx_state &= ~MLX_STATE_INTEN;
2599 break;
2600 case MLX_INTACTION_ENABLE:
2601 MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT);
2602 sc->mlx_state |= MLX_STATE_INTEN;
2603 break;
2604 }
2605}
2606
2607/********************************************************************************
2608 * Poll for firmware error codes during controller initialisation.
2609 * Returns 0 if initialisation is complete, 1 if still in progress but no
2610 * error has been fetched, 2 if an error has been retrieved.
2611 */
2612static int
2613mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2614{
2615 u_int8_t fwerror;
2616 static int initted = 0;
2617
2618 debug_called(2);
2619
2620 /* first time around, clear any hardware completion status */
2621 if (!initted) {
2622 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2623 DELAY(1000);
2624 initted = 1;
2625 }
2626
2627 /* init in progress? */
2628 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE)
2629 return(0);
2630
2631 /* test for error value */
2632 fwerror = MLX_V5_GET_FWERROR(sc);
2633 if (!(fwerror & MLX_V5_FWERROR_PEND))
2634 return(1);
2635
2636 /* mask status pending bit, fetch status */
2637 *error = fwerror & ~MLX_V5_FWERROR_PEND;
2638 *param1 = MLX_V5_GET_FWERROR_PARAM1(sc);
2639 *param2 = MLX_V5_GET_FWERROR_PARAM2(sc);
2640
2641 /* acknowledge */
2642 MLX_V5_PUT_FWERROR(sc, 0xff);
2643
2644 return(2);
2645}
2646
2647/********************************************************************************
2648 ********************************************************************************
2649 Debugging
2650 ********************************************************************************
2651 ********************************************************************************/
2652
2653/********************************************************************************
2654 * Return a status message describing (mc)
2655 */
2656static char *mlx_status_messages[] = {
2657 "normal completion", /* 00 */
2658 "irrecoverable data error", /* 01 */
2659 "drive does not exist, or is offline", /* 02 */
2660 "attempt to write beyond end of drive", /* 03 */
2661 "bad data encountered", /* 04 */
2662 "invalid log entry request", /* 05 */
2663 "attempt to rebuild online drive", /* 06 */
2664 "new disk failed during rebuild", /* 07 */
2665 "invalid channel/target", /* 08 */
2666 "rebuild/check already in progress", /* 09 */
2667 "one or more disks are dead", /* 10 */
2668 "invalid or non-redundant drive", /* 11 */
2669 "channel is busy", /* 12 */
2670 "channel is not stopped", /* 13 */
2671 "rebuild successfully terminated", /* 14 */
2672 "unsupported command", /* 15 */
2673 "check condition received", /* 16 */
2674 "device is busy", /* 17 */
2675 "selection or command timeout", /* 18 */
2676 "command terminated abnormally", /* 19 */
2677 ""
2678};
2679
2680static struct
2681{
2682 int command;
2683 u_int16_t status;
2684 int msg;
2685} mlx_messages[] = {
2686 {MLX_CMD_READSG, 0x0001, 1},
2687 {MLX_CMD_READSG, 0x0002, 1},
2688 {MLX_CMD_READSG, 0x0105, 3},
2689 {MLX_CMD_READSG, 0x010c, 4},
2690 {MLX_CMD_WRITESG, 0x0001, 1},
2691 {MLX_CMD_WRITESG, 0x0002, 1},
2692 {MLX_CMD_WRITESG, 0x0105, 3},
2693 {MLX_CMD_READSG_OLD, 0x0001, 1},
2694 {MLX_CMD_READSG_OLD, 0x0002, 1},
2695 {MLX_CMD_READSG_OLD, 0x0105, 3},
2696 {MLX_CMD_WRITESG_OLD, 0x0001, 1},
2697 {MLX_CMD_WRITESG_OLD, 0x0002, 1},
2698 {MLX_CMD_WRITESG_OLD, 0x0105, 3},
2699 {MLX_CMD_LOGOP, 0x0105, 5},
2700 {MLX_CMD_REBUILDASYNC, 0x0002, 6},
2701 {MLX_CMD_REBUILDASYNC, 0x0004, 7},
2702 {MLX_CMD_REBUILDASYNC, 0x0105, 8},
2703 {MLX_CMD_REBUILDASYNC, 0x0106, 9},
2704 {MLX_CMD_REBUILDASYNC, 0x0107, 14},
2705 {MLX_CMD_CHECKASYNC, 0x0002, 10},
2706 {MLX_CMD_CHECKASYNC, 0x0105, 11},
2707 {MLX_CMD_CHECKASYNC, 0x0106, 9},
2708 {MLX_CMD_STOPCHANNEL, 0x0106, 12},
2709 {MLX_CMD_STOPCHANNEL, 0x0105, 8},
2710 {MLX_CMD_STARTCHANNEL, 0x0005, 13},
2711 {MLX_CMD_STARTCHANNEL, 0x0105, 8},
2712 {MLX_CMD_DIRECT_CDB, 0x0002, 16},
2713 {MLX_CMD_DIRECT_CDB, 0x0008, 17},
2714 {MLX_CMD_DIRECT_CDB, 0x000e, 18},
2715 {MLX_CMD_DIRECT_CDB, 0x000f, 19},
2716 {MLX_CMD_DIRECT_CDB, 0x0105, 8},
2717
2718 {0, 0x0104, 14},
2719 {-1, 0, 0}
2720};
2721
2722static char *
2723mlx_diagnose_command(struct mlx_command *mc)
2724{
2725 static char unkmsg[80];
2726 int i;
2727
2728 /* look up message in table */
2729 for (i = 0; mlx_messages[i].command != -1; i++)
2730 if (((mc->mc_mailbox[0] == mlx_messages[i].command) || (mlx_messages[i].command == 0)) &&
2731 (mc->mc_status == mlx_messages[i].status))
2732 return(mlx_status_messages[mlx_messages[i].msg]);
2733
2734 sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2735 return(unkmsg);
2736}
2737
2738/*******************************************************************************
2739 * Print a string describing the controller (sc)
2740 */
2741static struct
2742{
2743 int hwid;
2744 char *name;
2745} mlx_controller_names[] = {
2746 {0x01, "960P/PD"},
2747 {0x02, "960PL"},
2748 {0x10, "960PG"},
2749 {0x11, "960PJ"},
2750 {0x12, "960PR"},
2751 {0x13, "960PT"},
2752 {0x14, "960PTL0"},
2753 {0x15, "960PRL"},
2754 {0x16, "960PTL1"},
2755 {0x20, "1164PVX"},
2756 {-1, NULL}
2757};
2758
2759static void
2760mlx_describe_controller(struct mlx_softc *sc)
2761{
2762 static char buf[80];
2763 char *model;
2764 int i;
2765
2766 for (i = 0, model = NULL; mlx_controller_names[i].name != NULL; i++) {
2767 if ((sc->mlx_enq2->me_hardware_id & 0xff) == mlx_controller_names[i].hwid) {
2768 model = mlx_controller_names[i].name;
2769 break;
2770 }
2771 }
2772 if (model == NULL) {
2773 sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff);
2774 model = buf;
2775 }
2776 device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%02d, %dMB RAM\n",
2777 model,
2778 sc->mlx_enq2->me_actual_channels,
2779 sc->mlx_enq2->me_actual_channels > 1 ? "s" : "",
2780 sc->mlx_enq2->me_firmware_id & 0xff,
2781 (sc->mlx_enq2->me_firmware_id >> 8) & 0xff,
2782 (sc->mlx_enq2->me_firmware_id >> 24) & 0xff,
2783 (sc->mlx_enq2->me_firmware_id >> 16) & 0xff,
2784 sc->mlx_enq2->me_mem_size / (1024 * 1024));
2785
2786 if (bootverbose) {
2787 device_printf(sc->mlx_dev, " Hardware ID 0x%08x\n", sc->mlx_enq2->me_hardware_id);
2788 device_printf(sc->mlx_dev, " Firmware ID 0x%08x\n", sc->mlx_enq2->me_firmware_id);
2789 device_printf(sc->mlx_dev, " Configured/Actual channels %d/%d\n", sc->mlx_enq2->me_configured_channels,
2790 sc->mlx_enq2->me_actual_channels);
2791 device_printf(sc->mlx_dev, " Max Targets %d\n", sc->mlx_enq2->me_max_targets);
2792 device_printf(sc->mlx_dev, " Max Tags %d\n", sc->mlx_enq2->me_max_tags);
2793 device_printf(sc->mlx_dev, " Max System Drives %d\n", sc->mlx_enq2->me_max_sys_drives);
2794 device_printf(sc->mlx_dev, " Max Arms %d\n", sc->mlx_enq2->me_max_arms);
2795 device_printf(sc->mlx_dev, " Max Spans %d\n", sc->mlx_enq2->me_max_spans);
2796 device_printf(sc->mlx_dev, " DRAM/cache/flash/NVRAM size %d/%d/%d/%d\n", sc->mlx_enq2->me_mem_size,
2797 sc->mlx_enq2->me_cache_size, sc->mlx_enq2->me_flash_size, sc->mlx_enq2->me_nvram_size);
2798 device_printf(sc->mlx_dev, " DRAM type %d\n", sc->mlx_enq2->me_mem_type);
2799 device_printf(sc->mlx_dev, " Clock Speed %dns\n", sc->mlx_enq2->me_clock_speed);
2800 device_printf(sc->mlx_dev, " Hardware Speed %dns\n", sc->mlx_enq2->me_hardware_speed);
2801 device_printf(sc->mlx_dev, " Max Commands %d\n", sc->mlx_enq2->me_max_commands);
2802 device_printf(sc->mlx_dev, " Max SG Entries %d\n", sc->mlx_enq2->me_max_sg);
2803 device_printf(sc->mlx_dev, " Max DP %d\n", sc->mlx_enq2->me_max_dp);
2804 device_printf(sc->mlx_dev, " Max IOD %d\n", sc->mlx_enq2->me_max_iod);
2805 device_printf(sc->mlx_dev, " Max Comb %d\n", sc->mlx_enq2->me_max_comb);
2806 device_printf(sc->mlx_dev, " Latency %ds\n", sc->mlx_enq2->me_latency);
2807 device_printf(sc->mlx_dev, " SCSI Timeout %ds\n", sc->mlx_enq2->me_scsi_timeout);
2808 device_printf(sc->mlx_dev, " Min Free Lines %d\n", sc->mlx_enq2->me_min_freelines);
2809 device_printf(sc->mlx_dev, " Rate Constant %d\n", sc->mlx_enq2->me_rate_const);
2810 device_printf(sc->mlx_dev, " MAXBLK %d\n", sc->mlx_enq2->me_maxblk);
2811 device_printf(sc->mlx_dev, " Blocking Factor %d sectors\n", sc->mlx_enq2->me_blocking_factor);
2812 device_printf(sc->mlx_dev, " Cache Line Size %d blocks\n", sc->mlx_enq2->me_cacheline);
2813 device_printf(sc->mlx_dev, " SCSI Capability %s%dMHz, %d bit\n",
2814 sc->mlx_enq2->me_scsi_cap & (1<<4) ? "differential " : "",
2815 (1 << ((sc->mlx_enq2->me_scsi_cap >> 2) & 3)) * 10,
2816 8 << (sc->mlx_enq2->me_scsi_cap & 0x3));
2817 device_printf(sc->mlx_dev, " Firmware Build Number %d\n", sc->mlx_enq2->me_firmware_build);
2818 device_printf(sc->mlx_dev, " Fault Management Type %d\n", sc->mlx_enq2->me_fault_mgmt_type);
2819 device_printf(sc->mlx_dev, " Features %b\n", sc->mlx_enq2->me_firmware_features,
2820 "\20\4Background Init\3Read Ahead\2MORE\1Cluster\n");
2821
2822 }
2823}
2824
2825/*******************************************************************************
2826 * Emit a string describing the firmware handshake status code, and return a flag
2827 * indicating whether the code represents a fatal error.
2828 *
2829 * Error code interpretations are from the Linux driver, and don't directly match
2830 * the messages printed by Mylex's BIOS. This may change if documentation on the
2831 * codes is forthcoming.
2832 */
2833static int
2834mlx_fw_message(struct mlx_softc *sc, int error, int param1, int param2)
2835{
2836 switch(error) {
2837 case 0x00:
2838 device_printf(sc->mlx_dev, "physical drive %d:%d not responding\n", param2, param1);
2839 break;
2840 case 0x08:
2841 /* we could be neater about this and give some indication when we receive more of them */
2842 if (!(sc->mlx_flags & MLX_SPINUP_REPORTED)) {
2843 device_printf(sc->mlx_dev, "spinning up drives...\n");
2844 sc->mlx_flags |= MLX_SPINUP_REPORTED;
2845 }
2846 break;
2847 case 0x30:
2848 device_printf(sc->mlx_dev, "configuration checksum error\n");
2849 break;
2850 case 0x60:
2851 device_printf(sc->mlx_dev, "mirror race recovery failed\n");
2852 break;
2853 case 0x70:
2854 device_printf(sc->mlx_dev, "mirror race recovery in progress\n");
2855 break;
2856 case 0x90:
2857 device_printf(sc->mlx_dev, "physical drive %d:%d COD mismatch\n", param2, param1);
2858 break;
2859 case 0xa0:
2860 device_printf(sc->mlx_dev, "logical drive installation aborted\n");
2861 break;
2862 case 0xb0:
2863 device_printf(sc->mlx_dev, "mirror race on a critical system drive\n");
2864 break;
2865 case 0xd0:
2866 device_printf(sc->mlx_dev, "new controller configuration found\n");
2867 break;
2868 case 0xf0:
2869 device_printf(sc->mlx_dev, "FATAL MEMORY PARITY ERROR\n");
2870 return(1);
2871 default:
2872 device_printf(sc->mlx_dev, "unknown firmware initialisation error %02x:%02x:%02x\n", error, param1, param2);
2873 break;
2874 }
2875 return(0);
2876}
2877
2878/********************************************************************************
2879 ********************************************************************************
2880 Utility Functions
2881 ********************************************************************************
2882 ********************************************************************************/
2883
2884/********************************************************************************
2885 * Find the disk whose unit number is (unit) on this controller
2886 */
2887static struct mlx_sysdrive *
2888mlx_findunit(struct mlx_softc *sc, int unit)
2889{
2890 int i;
2891
2892 /* search system drives */
2893 for (i = 0; i < MLX_MAXDRIVES; i++) {
2894 /* is this one attached? */
2895 if (sc->mlx_sysdrive[i].ms_disk != 0) {
2896 /* is this the one? */
2897 if (unit == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
2898 return(&sc->mlx_sysdrive[i]);
2899 }
2900 }
2901 return(NULL);
2902}
1824 device_printf(sc->mlx_dev, " %13D\n", mc->mc_mailbox, " ");
1825#endif
1826 break;
1827 }
1828 }
1829 mlx_releasecmd(mc);
1830 mlxd_intr(bp);
1831}
1832
1833/********************************************************************************
1834 * Take a command from user-space and try to run it.
1835 *
1836 * XXX Note that this can't perform very much in the way of error checking, and
1837 * as such, applications _must_ be considered trustworthy.
1838 * XXX Commands using S/G for data are not supported.
1839 */
1840static int
1841mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
1842{
1843 struct mlx_command *mc;
1844 struct mlx_dcdb *dcdb;
1845 void *kbuf;
1846 int error;
1847
1848 debug_called(0);
1849
1850 kbuf = NULL;
1851 mc = NULL;
1852 dcdb = NULL;
1853 error = ENOMEM;
1854
1855 /* get ourselves a command and copy in from user space */
1856 if ((mc = mlx_alloccmd(sc)) == NULL)
1857 goto out;
1858 bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
1859 debug(0, "got command buffer");
1860
1861 /* if we need a buffer for data transfer, allocate one and copy in its initial contents */
1862 if (mu->mu_datasize > 0) {
1863 if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) ||
1864 (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize)))
1865 goto out;
1866 debug(0, "got kernel buffer");
1867 }
1868
1869 /* get a command slot */
1870 if (mlx_getslot(mc))
1871 goto out;
1872 debug(0, "got a slot");
1873
1874 /* map the command so the controller can see it */
1875 mc->mc_data = kbuf;
1876 mc->mc_length = mu->mu_datasize;
1877 mlx_mapcmd(mc);
1878 debug(0, "mapped");
1879
1880 /*
1881 * If this is a passthrough SCSI command, the DCDB is packed at the
1882 * beginning of the data area. Fix up the DCDB to point to the correct physical
1883 * address and override any bufptr supplied by the caller since we know
1884 * what it's meant to be.
1885 */
1886 if (mc->mc_mailbox[0] == MLX_CMD_DIRECT_CDB) {
1887 dcdb = (struct mlx_dcdb *)kbuf;
1888 dcdb->dcdb_physaddr = mc->mc_dataphys + sizeof(*dcdb);
1889 mu->mu_bufptr = 8;
1890 }
1891
1892 /*
1893 * If there's a data buffer, fix up the command's buffer pointer.
1894 */
1895 if (mu->mu_datasize > 0) {
1896
1897 /* range check the pointer to physical buffer address */
1898 if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) - sizeof(u_int32_t)))) {
1899 error = EINVAL;
1900 goto out;
1901 }
1902 mc->mc_mailbox[mu->mu_bufptr ] = mc->mc_dataphys & 0xff;
1903 mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_dataphys >> 8) & 0xff;
1904 mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_dataphys >> 16) & 0xff;
1905 mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_dataphys >> 24) & 0xff;
1906 }
1907 debug(0, "command fixup");
1908
1909 /* submit the command and wait */
1910 if ((error = mlx_wait_command(mc)) != 0)
1911 goto out;
1912
1913 /* copy out status and data */
1914 mu->mu_status = mc->mc_status;
1915 if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize))))
1916 goto out;
1917 error = 0;
1918
1919 out:
1920 mlx_releasecmd(mc);
1921 if (kbuf != NULL)
1922 free(kbuf, M_DEVBUF);
1923 return(error);
1924}
1925
1926/********************************************************************************
1927 ********************************************************************************
1928 Command I/O to Controller
1929 ********************************************************************************
1930 ********************************************************************************/
1931
1932/********************************************************************************
1933 * Find a free command slot for (mc).
1934 *
1935 * Don't hand out a slot to a normal-priority command unless there are at least
1936 * 4 slots free for priority commands.
1937 */
1938static int
1939mlx_getslot(struct mlx_command *mc)
1940{
1941 struct mlx_softc *sc = mc->mc_sc;
1942 int s, slot;
1943
1944 debug_called(1);
1945
1946 /* enforce slot-usage limit */
1947 if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ?
1948 sc->mlx_maxiop : sc->mlx_maxiop - 4))
1949 return(EBUSY);
1950
1951 /*
1952 * Allocate an outstanding command slot
1953 *
1954 * XXX linear search is slow
1955 */
1956 s = splbio();
1957 for (slot = 0; slot < sc->mlx_maxiop; slot++) {
1958 debug(2, "try slot %d", slot);
1959 if (sc->mlx_busycmd[slot] == NULL)
1960 break;
1961 }
1962 if (slot < sc->mlx_maxiop) {
1963 sc->mlx_busycmd[slot] = mc;
1964 sc->mlx_busycmds++;
1965 }
1966 splx(s);
1967
1968 /* out of slots? */
1969 if (slot >= sc->mlx_maxiop)
1970 return(EBUSY);
1971
1972 debug(2, "got slot %d", slot);
1973 mc->mc_slot = slot;
1974 return(0);
1975}
1976
1977/********************************************************************************
1978 * Map/unmap (mc)'s data in the controller's addressable space.
1979 */
1980static void
1981mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1982{
1983 struct mlx_command *mc = (struct mlx_command *)arg;
1984 struct mlx_softc *sc = mc->mc_sc;
1985 struct mlx_sgentry *sg;
1986 int i;
1987
1988 debug_called(1);
1989
1990 /* get base address of s/g table */
1991 sg = sc->mlx_sgtable + (mc->mc_slot * sc->mlx_sg_nseg);
1992
1993 /* save s/g table information in command */
1994 mc->mc_nsgent = nsegments;
1995 mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * sc->mlx_sg_nseg * sizeof(struct mlx_sgentry));
1996 mc->mc_dataphys = segs[0].ds_addr;
1997
1998 /* populate s/g table */
1999 for (i = 0; i < nsegments; i++, sg++) {
2000 sg->sg_addr = segs[i].ds_addr;
2001 sg->sg_count = segs[i].ds_len;
2002 }
2003}
2004
2005static void
2006mlx_mapcmd(struct mlx_command *mc)
2007{
2008 struct mlx_softc *sc = mc->mc_sc;
2009
2010 debug_called(1);
2011
2012 /* if the command involves data at all */
2013 if (mc->mc_data != NULL) {
2014
2015 /* map the data buffer into bus space and build the s/g list */
2016 bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length,
2017 mlx_setup_dmamap, mc, 0);
2018 if (mc->mc_flags & MLX_CMD_DATAIN)
2019 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD);
2020 if (mc->mc_flags & MLX_CMD_DATAOUT)
2021 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE);
2022 }
2023}
2024
2025static void
2026mlx_unmapcmd(struct mlx_command *mc)
2027{
2028 struct mlx_softc *sc = mc->mc_sc;
2029
2030 debug_called(1);
2031
2032 /* if the command involved data at all */
2033 if (mc->mc_data != NULL) {
2034
2035 if (mc->mc_flags & MLX_CMD_DATAIN)
2036 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
2037 if (mc->mc_flags & MLX_CMD_DATAOUT)
2038 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
2039
2040 bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap);
2041 }
2042}
2043
2044/********************************************************************************
2045 * Try to deliver (mc) to the controller.
2046 *
2047 * Can be called at any interrupt level, with or without interrupts enabled.
2048 */
2049static int
2050mlx_start(struct mlx_command *mc)
2051{
2052 struct mlx_softc *sc = mc->mc_sc;
2053 int i, s, done;
2054
2055 debug_called(1);
2056
2057 /* save the slot number as ident so we can handle this command when complete */
2058 mc->mc_mailbox[0x1] = mc->mc_slot;
2059
2060 /* mark the command as currently being processed */
2061 mc->mc_status = MLX_STATUS_BUSY;
2062
2063 /* set a default 60-second timeout XXX tunable? XXX not currently used */
2064 mc->mc_timeout = time_second + 60;
2065
2066 /* spin waiting for the mailbox */
2067 for (i = 100000, done = 0; (i > 0) && !done; i--) {
2068 s = splbio();
2069 if (sc->mlx_tryqueue(sc, mc)) {
2070 done = 1;
2071 /* move command to work queue */
2072 TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
2073 }
2074 splx(s); /* drop spl to allow completion interrupts */
2075 }
2076
2077 /* command is enqueued */
2078 if (done)
2079 return(0);
2080
2081 /*
2082 * We couldn't get the controller to take the command. Revoke the slot
2083 * that the command was given and return it with a bad status.
2084 */
2085 sc->mlx_busycmd[mc->mc_slot] = NULL;
2086 device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
2087 mc->mc_status = MLX_STATUS_WEDGED;
2088 mlx_complete(sc);
2089 return(EIO);
2090}
2091
2092/********************************************************************************
2093 * Poll the controller (sc) for completed commands.
2094 * Update command status and free slots for reuse. If any slots were freed,
2095 * new commands may be posted.
2096 *
2097 * Returns nonzero if one or more commands were completed.
2098 */
2099static int
2100mlx_done(struct mlx_softc *sc)
2101{
2102 struct mlx_command *mc;
2103 int s, result;
2104 u_int8_t slot;
2105 u_int16_t status;
2106
2107 debug_called(2);
2108
2109 result = 0;
2110
2111 /* loop collecting completed commands */
2112 s = splbio();
2113 for (;;) {
2114 /* poll for a completed command's identifier and status */
2115 if (sc->mlx_findcomplete(sc, &slot, &status)) {
2116 result = 1;
2117 mc = sc->mlx_busycmd[slot]; /* find command */
2118 if (mc != NULL) { /* paranoia */
2119 if (mc->mc_status == MLX_STATUS_BUSY) {
2120 mc->mc_status = status; /* save status */
2121
2122 /* free slot for reuse */
2123 sc->mlx_busycmd[slot] = NULL;
2124 sc->mlx_busycmds--;
2125 } else {
2126 device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
2127 }
2128 } else {
2129 device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
2130 }
2131 } else {
2132 break;
2133 }
2134 }
2135
2136 /* if we've completed any commands, try posting some more */
2137 if (result)
2138 mlx_startio(sc);
2139
2140 /* handle completion and timeouts */
2141 mlx_complete(sc);
2142
2143 return(result);
2144}
2145
2146/********************************************************************************
2147 * Perform post-completion processing for commands on (sc).
2148 */
2149static void
2150mlx_complete(struct mlx_softc *sc)
2151{
2152 struct mlx_command *mc, *nc;
2153 int s, count;
2154
2155 debug_called(2);
2156
2157 /* avoid reentrancy XXX might want to signal and request a restart */
2158 if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING))
2159 return;
2160
2161 s = splbio();
2162 count = 0;
2163
2164 /* scan the list of busy/done commands */
2165 mc = TAILQ_FIRST(&sc->mlx_work);
2166 while (mc != NULL) {
2167 nc = TAILQ_NEXT(mc, mc_link);
2168
2169 /* Command has been completed in some fashion */
2170 if (mc->mc_status != MLX_STATUS_BUSY) {
2171
2172 /* unmap the command's data buffer */
2173 mlx_unmapcmd(mc);
2174 /*
2175 * Does the command have a completion handler?
2176 */
2177 if (mc->mc_complete != NULL) {
2178 /* remove from list and give to handler */
2179 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2180 mc->mc_complete(mc);
2181
2182 /*
2183 * Is there a sleeper waiting on this command?
2184 */
2185 } else if (mc->mc_private != NULL) { /* sleeping caller wants to know about it */
2186
2187 /* remove from list and wake up sleeper */
2188 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2189 wakeup_one(mc->mc_private);
2190
2191 /*
2192 * Leave the command for a caller that's polling for it.
2193 */
2194 } else {
2195 }
2196 }
2197 mc = nc;
2198 }
2199 splx(s);
2200
2201 mlx_lock_clr(sc, MLX_LOCK_COMPLETING);
2202}
2203
2204/********************************************************************************
2205 ********************************************************************************
2206 Command Buffer Management
2207 ********************************************************************************
2208 ********************************************************************************/
2209
2210/********************************************************************************
2211 * Get a new command buffer.
2212 *
2213 * This may return NULL in low-memory cases.
2214 *
2215 * Note that using malloc() is expensive (the command buffer is << 1 page) but
2216 * necessary if we are to be a loadable module before the zone allocator is fixed.
2217 *
2218 * If possible, we recycle a command buffer that's been used before.
2219 *
2220 * XXX Note that command buffers are not cleaned out - it is the caller's
2221 * responsibility to ensure that all required fields are filled in before
2222 * using a buffer.
2223 */
2224static struct mlx_command *
2225mlx_alloccmd(struct mlx_softc *sc)
2226{
2227 struct mlx_command *mc;
2228 int error;
2229 int s;
2230
2231 debug_called(1);
2232
2233 s = splbio();
2234 if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2235 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2236 splx(s);
2237
2238 /* allocate a new command buffer? */
2239 if (mc == NULL) {
2240 mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT);
2241 if (mc != NULL) {
2242 bzero(mc, sizeof(*mc));
2243 mc->mc_sc = sc;
2244 error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap);
2245 if (error) {
2246 free(mc, M_DEVBUF);
2247 return(NULL);
2248 }
2249 }
2250 }
2251 return(mc);
2252}
2253
2254/********************************************************************************
2255 * Release a command buffer for recycling.
2256 *
2257 * XXX It might be a good idea to limit the number of commands we save for reuse
2258 * if it's shown that this list bloats out massively.
2259 */
2260static void
2261mlx_releasecmd(struct mlx_command *mc)
2262{
2263 int s;
2264
2265 debug_called(1);
2266
2267 s = splbio();
2268 TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
2269 splx(s);
2270}
2271
2272/********************************************************************************
2273 * Permanently discard a command buffer.
2274 */
2275static void
2276mlx_freecmd(struct mlx_command *mc)
2277{
2278 struct mlx_softc *sc = mc->mc_sc;
2279
2280 debug_called(1);
2281 bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
2282 free(mc, M_DEVBUF);
2283}
2284
2285
2286/********************************************************************************
2287 ********************************************************************************
2288 Type 3 interface accessor methods
2289 ********************************************************************************
2290 ********************************************************************************/
2291
2292/********************************************************************************
2293 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2294 * (the controller is not ready to take a command).
2295 *
2296 * Must be called at splbio or in a fashion that prevents reentry.
2297 */
2298static int
2299mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2300{
2301 int i;
2302
2303 debug_called(2);
2304
2305 /* ready for our command? */
2306 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) {
2307 /* copy mailbox data to window */
2308 for (i = 0; i < 13; i++)
2309 MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2310
2311 /* post command */
2312 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL);
2313 return(1);
2314 }
2315 return(0);
2316}
2317
2318/********************************************************************************
2319 * See if a command has been completed, if so acknowledge its completion
2320 * and recover the slot number and status code.
2321 *
2322 * Must be called at splbio or in a fashion that prevents reentry.
2323 */
2324static int
2325mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2326{
2327
2328 debug_called(2);
2329
2330 /* status available? */
2331 if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) {
2332 *slot = MLX_V3_GET_STATUS_IDENT(sc); /* get command identifier */
2333 *status = MLX_V3_GET_STATUS(sc); /* get status */
2334
2335 /* acknowledge completion */
2336 MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);
2337 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2338 return(1);
2339 }
2340 return(0);
2341}
2342
2343/********************************************************************************
2344 * Enable/disable interrupts as requested. (No acknowledge required)
2345 *
2346 * Must be called at splbio or in a fashion that prevents reentry.
2347 */
2348static void
2349mlx_v3_intaction(struct mlx_softc *sc, int action)
2350{
2351 debug_called(1);
2352
2353 switch(action) {
2354 case MLX_INTACTION_DISABLE:
2355 MLX_V3_PUT_IER(sc, 0);
2356 sc->mlx_state &= ~MLX_STATE_INTEN;
2357 break;
2358 case MLX_INTACTION_ENABLE:
2359 MLX_V3_PUT_IER(sc, 1);
2360 sc->mlx_state |= MLX_STATE_INTEN;
2361 break;
2362 }
2363}
2364
2365/********************************************************************************
2366 * Poll for firmware error codes during controller initialisation.
2367 * Returns 0 if initialisation is complete, 1 if still in progress but no
2368 * error has been fetched, 2 if an error has been retrieved.
2369 */
2370static int
2371mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2372{
2373 u_int8_t fwerror;
2374 static int initted = 0;
2375
2376 debug_called(2);
2377
2378 /* first time around, clear any hardware completion status */
2379 if (!initted) {
2380 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2381 DELAY(1000);
2382 initted = 1;
2383 }
2384
2385 /* init in progress? */
2386 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY))
2387 return(0);
2388
2389 /* test error value */
2390 fwerror = MLX_V3_GET_FWERROR(sc);
2391 if (!(fwerror & MLX_V3_FWERROR_PEND))
2392 return(1);
2393
2394 /* mask status pending bit, fetch status */
2395 *error = fwerror & ~MLX_V3_FWERROR_PEND;
2396 *param1 = MLX_V3_GET_FWERROR_PARAM1(sc);
2397 *param2 = MLX_V3_GET_FWERROR_PARAM2(sc);
2398
2399 /* acknowledge */
2400 MLX_V3_PUT_FWERROR(sc, 0);
2401
2402 return(2);
2403}
2404
2405/********************************************************************************
2406 ********************************************************************************
2407 Type 4 interface accessor methods
2408 ********************************************************************************
2409 ********************************************************************************/
2410
2411/********************************************************************************
2412 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2413 * (the controller is not ready to take a command).
2414 *
2415 * Must be called at splbio or in a fashion that prevents reentry.
2416 */
2417static int
2418mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2419{
2420 int i;
2421
2422 debug_called(2);
2423
2424 /* ready for our command? */
2425 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
2426 /* copy mailbox data to window */
2427 for (i = 0; i < 13; i++)
2428 MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2429
2430 /* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */
2431 bus_space_barrier(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH,
2432 BUS_SPACE_BARRIER_WRITE);
2433
2434 /* post command */
2435 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
2436 return(1);
2437 }
2438 return(0);
2439}
2440
2441/********************************************************************************
2442 * See if a command has been completed, if so acknowledge its completion
2443 * and recover the slot number and status code.
2444 *
2445 * Must be called at splbio or in a fashion that prevents reentry.
2446 */
2447static int
2448mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2449{
2450
2451 debug_called(2);
2452
2453 /* status available? */
2454 if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
2455 *slot = MLX_V4_GET_STATUS_IDENT(sc); /* get command identifier */
2456 *status = MLX_V4_GET_STATUS(sc); /* get status */
2457
2458 /* acknowledge completion */
2459 MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);
2460 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2461 return(1);
2462 }
2463 return(0);
2464}
2465
2466/********************************************************************************
2467 * Enable/disable interrupts as requested.
2468 *
2469 * Must be called at splbio or in a fashion that prevents reentry.
2470 */
2471static void
2472mlx_v4_intaction(struct mlx_softc *sc, int action)
2473{
2474 debug_called(1);
2475
2476 switch(action) {
2477 case MLX_INTACTION_DISABLE:
2478 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT);
2479 sc->mlx_state &= ~MLX_STATE_INTEN;
2480 break;
2481 case MLX_INTACTION_ENABLE:
2482 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT);
2483 sc->mlx_state |= MLX_STATE_INTEN;
2484 break;
2485 }
2486}
2487
2488/********************************************************************************
2489 * Poll for firmware error codes during controller initialisation.
2490 * Returns 0 if initialisation is complete, 1 if still in progress but no
2491 * error has been fetched, 2 if an error has been retrieved.
2492 */
2493static int
2494mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2495{
2496 u_int8_t fwerror;
2497 static int initted = 0;
2498
2499 debug_called(2);
2500
2501 /* first time around, clear any hardware completion status */
2502 if (!initted) {
2503 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2504 DELAY(1000);
2505 initted = 1;
2506 }
2507
2508 /* init in progress? */
2509 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY))
2510 return(0);
2511
2512 /* test error value */
2513 fwerror = MLX_V4_GET_FWERROR(sc);
2514 if (!(fwerror & MLX_V4_FWERROR_PEND))
2515 return(1);
2516
2517 /* mask status pending bit, fetch status */
2518 *error = fwerror & ~MLX_V4_FWERROR_PEND;
2519 *param1 = MLX_V4_GET_FWERROR_PARAM1(sc);
2520 *param2 = MLX_V4_GET_FWERROR_PARAM2(sc);
2521
2522 /* acknowledge */
2523 MLX_V4_PUT_FWERROR(sc, 0);
2524
2525 return(2);
2526}
2527
2528/********************************************************************************
2529 ********************************************************************************
2530 Type 5 interface accessor methods
2531 ********************************************************************************
2532 ********************************************************************************/
2533
2534/********************************************************************************
2535 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2536 * (the controller is not ready to take a command).
2537 *
2538 * Must be called at splbio or in a fashion that prevents reentry.
2539 */
2540static int
2541mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2542{
2543 int i;
2544
2545 debug_called(2);
2546
2547 /* ready for our command? */
2548 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) {
2549 /* copy mailbox data to window */
2550 for (i = 0; i < 13; i++)
2551 MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2552
2553 /* post command */
2554 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
2555 return(1);
2556 }
2557 return(0);
2558}
2559
2560/********************************************************************************
2561 * See if a command has been completed, if so acknowledge its completion
2562 * and recover the slot number and status code.
2563 *
2564 * Must be called at splbio or in a fashion that prevents reentry.
2565 */
2566static int
2567mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2568{
2569
2570 debug_called(2);
2571
2572 /* status available? */
2573 if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) {
2574 *slot = MLX_V5_GET_STATUS_IDENT(sc); /* get command identifier */
2575 *status = MLX_V5_GET_STATUS(sc); /* get status */
2576
2577 /* acknowledge completion */
2578 MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK);
2579 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2580 return(1);
2581 }
2582 return(0);
2583}
2584
2585/********************************************************************************
2586 * Enable/disable interrupts as requested.
2587 *
2588 * Must be called at splbio or in a fashion that prevents reentry.
2589 */
2590static void
2591mlx_v5_intaction(struct mlx_softc *sc, int action)
2592{
2593 debug_called(1);
2594
2595 switch(action) {
2596 case MLX_INTACTION_DISABLE:
2597 MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT);
2598 sc->mlx_state &= ~MLX_STATE_INTEN;
2599 break;
2600 case MLX_INTACTION_ENABLE:
2601 MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT);
2602 sc->mlx_state |= MLX_STATE_INTEN;
2603 break;
2604 }
2605}
2606
2607/********************************************************************************
2608 * Poll for firmware error codes during controller initialisation.
2609 * Returns 0 if initialisation is complete, 1 if still in progress but no
2610 * error has been fetched, 2 if an error has been retrieved.
2611 */
2612static int
2613mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2614{
2615 u_int8_t fwerror;
2616 static int initted = 0;
2617
2618 debug_called(2);
2619
2620 /* first time around, clear any hardware completion status */
2621 if (!initted) {
2622 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2623 DELAY(1000);
2624 initted = 1;
2625 }
2626
2627 /* init in progress? */
2628 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE)
2629 return(0);
2630
2631 /* test for error value */
2632 fwerror = MLX_V5_GET_FWERROR(sc);
2633 if (!(fwerror & MLX_V5_FWERROR_PEND))
2634 return(1);
2635
2636 /* mask status pending bit, fetch status */
2637 *error = fwerror & ~MLX_V5_FWERROR_PEND;
2638 *param1 = MLX_V5_GET_FWERROR_PARAM1(sc);
2639 *param2 = MLX_V5_GET_FWERROR_PARAM2(sc);
2640
2641 /* acknowledge */
2642 MLX_V5_PUT_FWERROR(sc, 0xff);
2643
2644 return(2);
2645}
2646
2647/********************************************************************************
2648 ********************************************************************************
2649 Debugging
2650 ********************************************************************************
2651 ********************************************************************************/
2652
2653/********************************************************************************
2654 * Return a status message describing (mc)
2655 */
2656static char *mlx_status_messages[] = {
2657 "normal completion", /* 00 */
2658 "irrecoverable data error", /* 01 */
2659 "drive does not exist, or is offline", /* 02 */
2660 "attempt to write beyond end of drive", /* 03 */
2661 "bad data encountered", /* 04 */
2662 "invalid log entry request", /* 05 */
2663 "attempt to rebuild online drive", /* 06 */
2664 "new disk failed during rebuild", /* 07 */
2665 "invalid channel/target", /* 08 */
2666 "rebuild/check already in progress", /* 09 */
2667 "one or more disks are dead", /* 10 */
2668 "invalid or non-redundant drive", /* 11 */
2669 "channel is busy", /* 12 */
2670 "channel is not stopped", /* 13 */
2671 "rebuild successfully terminated", /* 14 */
2672 "unsupported command", /* 15 */
2673 "check condition received", /* 16 */
2674 "device is busy", /* 17 */
2675 "selection or command timeout", /* 18 */
2676 "command terminated abnormally", /* 19 */
2677 ""
2678};
2679
2680static struct
2681{
2682 int command;
2683 u_int16_t status;
2684 int msg;
2685} mlx_messages[] = {
2686 {MLX_CMD_READSG, 0x0001, 1},
2687 {MLX_CMD_READSG, 0x0002, 1},
2688 {MLX_CMD_READSG, 0x0105, 3},
2689 {MLX_CMD_READSG, 0x010c, 4},
2690 {MLX_CMD_WRITESG, 0x0001, 1},
2691 {MLX_CMD_WRITESG, 0x0002, 1},
2692 {MLX_CMD_WRITESG, 0x0105, 3},
2693 {MLX_CMD_READSG_OLD, 0x0001, 1},
2694 {MLX_CMD_READSG_OLD, 0x0002, 1},
2695 {MLX_CMD_READSG_OLD, 0x0105, 3},
2696 {MLX_CMD_WRITESG_OLD, 0x0001, 1},
2697 {MLX_CMD_WRITESG_OLD, 0x0002, 1},
2698 {MLX_CMD_WRITESG_OLD, 0x0105, 3},
2699 {MLX_CMD_LOGOP, 0x0105, 5},
2700 {MLX_CMD_REBUILDASYNC, 0x0002, 6},
2701 {MLX_CMD_REBUILDASYNC, 0x0004, 7},
2702 {MLX_CMD_REBUILDASYNC, 0x0105, 8},
2703 {MLX_CMD_REBUILDASYNC, 0x0106, 9},
2704 {MLX_CMD_REBUILDASYNC, 0x0107, 14},
2705 {MLX_CMD_CHECKASYNC, 0x0002, 10},
2706 {MLX_CMD_CHECKASYNC, 0x0105, 11},
2707 {MLX_CMD_CHECKASYNC, 0x0106, 9},
2708 {MLX_CMD_STOPCHANNEL, 0x0106, 12},
2709 {MLX_CMD_STOPCHANNEL, 0x0105, 8},
2710 {MLX_CMD_STARTCHANNEL, 0x0005, 13},
2711 {MLX_CMD_STARTCHANNEL, 0x0105, 8},
2712 {MLX_CMD_DIRECT_CDB, 0x0002, 16},
2713 {MLX_CMD_DIRECT_CDB, 0x0008, 17},
2714 {MLX_CMD_DIRECT_CDB, 0x000e, 18},
2715 {MLX_CMD_DIRECT_CDB, 0x000f, 19},
2716 {MLX_CMD_DIRECT_CDB, 0x0105, 8},
2717
2718 {0, 0x0104, 14},
2719 {-1, 0, 0}
2720};
2721
2722static char *
2723mlx_diagnose_command(struct mlx_command *mc)
2724{
2725 static char unkmsg[80];
2726 int i;
2727
2728 /* look up message in table */
2729 for (i = 0; mlx_messages[i].command != -1; i++)
2730 if (((mc->mc_mailbox[0] == mlx_messages[i].command) || (mlx_messages[i].command == 0)) &&
2731 (mc->mc_status == mlx_messages[i].status))
2732 return(mlx_status_messages[mlx_messages[i].msg]);
2733
2734 sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2735 return(unkmsg);
2736}
2737
2738/*******************************************************************************
2739 * Print a string describing the controller (sc)
2740 */
2741static struct
2742{
2743 int hwid;
2744 char *name;
2745} mlx_controller_names[] = {
2746 {0x01, "960P/PD"},
2747 {0x02, "960PL"},
2748 {0x10, "960PG"},
2749 {0x11, "960PJ"},
2750 {0x12, "960PR"},
2751 {0x13, "960PT"},
2752 {0x14, "960PTL0"},
2753 {0x15, "960PRL"},
2754 {0x16, "960PTL1"},
2755 {0x20, "1164PVX"},
2756 {-1, NULL}
2757};
2758
2759static void
2760mlx_describe_controller(struct mlx_softc *sc)
2761{
2762 static char buf[80];
2763 char *model;
2764 int i;
2765
2766 for (i = 0, model = NULL; mlx_controller_names[i].name != NULL; i++) {
2767 if ((sc->mlx_enq2->me_hardware_id & 0xff) == mlx_controller_names[i].hwid) {
2768 model = mlx_controller_names[i].name;
2769 break;
2770 }
2771 }
2772 if (model == NULL) {
2773 sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff);
2774 model = buf;
2775 }
2776 device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%02d, %dMB RAM\n",
2777 model,
2778 sc->mlx_enq2->me_actual_channels,
2779 sc->mlx_enq2->me_actual_channels > 1 ? "s" : "",
2780 sc->mlx_enq2->me_firmware_id & 0xff,
2781 (sc->mlx_enq2->me_firmware_id >> 8) & 0xff,
2782 (sc->mlx_enq2->me_firmware_id >> 24) & 0xff,
2783 (sc->mlx_enq2->me_firmware_id >> 16) & 0xff,
2784 sc->mlx_enq2->me_mem_size / (1024 * 1024));
2785
2786 if (bootverbose) {
2787 device_printf(sc->mlx_dev, " Hardware ID 0x%08x\n", sc->mlx_enq2->me_hardware_id);
2788 device_printf(sc->mlx_dev, " Firmware ID 0x%08x\n", sc->mlx_enq2->me_firmware_id);
2789 device_printf(sc->mlx_dev, " Configured/Actual channels %d/%d\n", sc->mlx_enq2->me_configured_channels,
2790 sc->mlx_enq2->me_actual_channels);
2791 device_printf(sc->mlx_dev, " Max Targets %d\n", sc->mlx_enq2->me_max_targets);
2792 device_printf(sc->mlx_dev, " Max Tags %d\n", sc->mlx_enq2->me_max_tags);
2793 device_printf(sc->mlx_dev, " Max System Drives %d\n", sc->mlx_enq2->me_max_sys_drives);
2794 device_printf(sc->mlx_dev, " Max Arms %d\n", sc->mlx_enq2->me_max_arms);
2795 device_printf(sc->mlx_dev, " Max Spans %d\n", sc->mlx_enq2->me_max_spans);
2796 device_printf(sc->mlx_dev, " DRAM/cache/flash/NVRAM size %d/%d/%d/%d\n", sc->mlx_enq2->me_mem_size,
2797 sc->mlx_enq2->me_cache_size, sc->mlx_enq2->me_flash_size, sc->mlx_enq2->me_nvram_size);
2798 device_printf(sc->mlx_dev, " DRAM type %d\n", sc->mlx_enq2->me_mem_type);
2799 device_printf(sc->mlx_dev, " Clock Speed %dns\n", sc->mlx_enq2->me_clock_speed);
2800 device_printf(sc->mlx_dev, " Hardware Speed %dns\n", sc->mlx_enq2->me_hardware_speed);
2801 device_printf(sc->mlx_dev, " Max Commands %d\n", sc->mlx_enq2->me_max_commands);
2802 device_printf(sc->mlx_dev, " Max SG Entries %d\n", sc->mlx_enq2->me_max_sg);
2803 device_printf(sc->mlx_dev, " Max DP %d\n", sc->mlx_enq2->me_max_dp);
2804 device_printf(sc->mlx_dev, " Max IOD %d\n", sc->mlx_enq2->me_max_iod);
2805 device_printf(sc->mlx_dev, " Max Comb %d\n", sc->mlx_enq2->me_max_comb);
2806 device_printf(sc->mlx_dev, " Latency %ds\n", sc->mlx_enq2->me_latency);
2807 device_printf(sc->mlx_dev, " SCSI Timeout %ds\n", sc->mlx_enq2->me_scsi_timeout);
2808 device_printf(sc->mlx_dev, " Min Free Lines %d\n", sc->mlx_enq2->me_min_freelines);
2809 device_printf(sc->mlx_dev, " Rate Constant %d\n", sc->mlx_enq2->me_rate_const);
2810 device_printf(sc->mlx_dev, " MAXBLK %d\n", sc->mlx_enq2->me_maxblk);
2811 device_printf(sc->mlx_dev, " Blocking Factor %d sectors\n", sc->mlx_enq2->me_blocking_factor);
2812 device_printf(sc->mlx_dev, " Cache Line Size %d blocks\n", sc->mlx_enq2->me_cacheline);
2813 device_printf(sc->mlx_dev, " SCSI Capability %s%dMHz, %d bit\n",
2814 sc->mlx_enq2->me_scsi_cap & (1<<4) ? "differential " : "",
2815 (1 << ((sc->mlx_enq2->me_scsi_cap >> 2) & 3)) * 10,
2816 8 << (sc->mlx_enq2->me_scsi_cap & 0x3));
2817 device_printf(sc->mlx_dev, " Firmware Build Number %d\n", sc->mlx_enq2->me_firmware_build);
2818 device_printf(sc->mlx_dev, " Fault Management Type %d\n", sc->mlx_enq2->me_fault_mgmt_type);
2819 device_printf(sc->mlx_dev, " Features %b\n", sc->mlx_enq2->me_firmware_features,
2820 "\20\4Background Init\3Read Ahead\2MORE\1Cluster\n");
2821
2822 }
2823}
2824
2825/*******************************************************************************
2826 * Emit a string describing the firmware handshake status code, and return a flag
2827 * indicating whether the code represents a fatal error.
2828 *
2829 * Error code interpretations are from the Linux driver, and don't directly match
2830 * the messages printed by Mylex's BIOS. This may change if documentation on the
2831 * codes is forthcoming.
2832 */
2833static int
2834mlx_fw_message(struct mlx_softc *sc, int error, int param1, int param2)
2835{
2836 switch(error) {
2837 case 0x00:
2838 device_printf(sc->mlx_dev, "physical drive %d:%d not responding\n", param2, param1);
2839 break;
2840 case 0x08:
2841 /* we could be neater about this and give some indication when we receive more of them */
2842 if (!(sc->mlx_flags & MLX_SPINUP_REPORTED)) {
2843 device_printf(sc->mlx_dev, "spinning up drives...\n");
2844 sc->mlx_flags |= MLX_SPINUP_REPORTED;
2845 }
2846 break;
2847 case 0x30:
2848 device_printf(sc->mlx_dev, "configuration checksum error\n");
2849 break;
2850 case 0x60:
2851 device_printf(sc->mlx_dev, "mirror race recovery failed\n");
2852 break;
2853 case 0x70:
2854 device_printf(sc->mlx_dev, "mirror race recovery in progress\n");
2855 break;
2856 case 0x90:
2857 device_printf(sc->mlx_dev, "physical drive %d:%d COD mismatch\n", param2, param1);
2858 break;
2859 case 0xa0:
2860 device_printf(sc->mlx_dev, "logical drive installation aborted\n");
2861 break;
2862 case 0xb0:
2863 device_printf(sc->mlx_dev, "mirror race on a critical system drive\n");
2864 break;
2865 case 0xd0:
2866 device_printf(sc->mlx_dev, "new controller configuration found\n");
2867 break;
2868 case 0xf0:
2869 device_printf(sc->mlx_dev, "FATAL MEMORY PARITY ERROR\n");
2870 return(1);
2871 default:
2872 device_printf(sc->mlx_dev, "unknown firmware initialisation error %02x:%02x:%02x\n", error, param1, param2);
2873 break;
2874 }
2875 return(0);
2876}
2877
2878/********************************************************************************
2879 ********************************************************************************
2880 Utility Functions
2881 ********************************************************************************
2882 ********************************************************************************/
2883
2884/********************************************************************************
2885 * Find the disk whose unit number is (unit) on this controller
2886 */
2887static struct mlx_sysdrive *
2888mlx_findunit(struct mlx_softc *sc, int unit)
2889{
2890 int i;
2891
2892 /* search system drives */
2893 for (i = 0; i < MLX_MAXDRIVES; i++) {
2894 /* is this one attached? */
2895 if (sc->mlx_sysdrive[i].ms_disk != 0) {
2896 /* is this the one? */
2897 if (unit == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
2898 return(&sc->mlx_sysdrive[i]);
2899 }
2900 }
2901 return(NULL);
2902}