Sun Mar 28 20:30:14 2021 UTC ()
Correct the names of the arguments passed to cac_rescan(), and update
a local variable to avoid a name collision.  Also, no need to be explcit
about our interface attribute, since we carry only one.


(thorpej)
diff -r1.61.10.2 -r1.61.10.3 src/sys/dev/ic/cac.c

cvs diff -r1.61.10.2 -r1.61.10.3 src/sys/dev/ic/cac.c (switch to unified diff)

--- src/sys/dev/ic/cac.c 2021/03/22 16:23:45 1.61.10.2
+++ src/sys/dev/ic/cac.c 2021/03/28 20:30:14 1.61.10.3
@@ -1,775 +1,774 @@ @@ -1,775 +1,774 @@
1/* $NetBSD: cac.c,v 1.61.10.2 2021/03/22 16:23:45 thorpej Exp $ */ 1/* $NetBSD: cac.c,v 1.61.10.3 2021/03/28 20:30:14 thorpej Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2000, 2006, 2007 The NetBSD Foundation, Inc. 4 * Copyright (c) 2000, 2006, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran. 8 * by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Driver for Compaq array controllers. 33 * Driver for Compaq array controllers.
34 */ 34 */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD: cac.c,v 1.61.10.2 2021/03/22 16:23:45 thorpej Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: cac.c,v 1.61.10.3 2021/03/28 20:30:14 thorpej Exp $");
38 38
39#if defined(_KERNEL_OPT) 39#if defined(_KERNEL_OPT)
40#include "bio.h" 40#include "bio.h"
41#endif 41#endif
42 42
43#include <sys/param.h> 43#include <sys/param.h>
44#include <sys/systm.h> 44#include <sys/systm.h>
45#include <sys/kernel.h> 45#include <sys/kernel.h>
46#include <sys/device.h> 46#include <sys/device.h>
47#include <sys/queue.h> 47#include <sys/queue.h>
48#include <sys/proc.h> 48#include <sys/proc.h>
49#include <sys/buf.h> 49#include <sys/buf.h>
50#include <sys/endian.h> 50#include <sys/endian.h>
51#include <sys/malloc.h> 51#include <sys/malloc.h>
52#include <sys/pool.h> 52#include <sys/pool.h>
53#include <sys/module.h> 53#include <sys/module.h>
54#include <sys/bswap.h> 54#include <sys/bswap.h>
55#include <sys/bus.h> 55#include <sys/bus.h>
56 56
57#include <dev/ic/cacreg.h> 57#include <dev/ic/cacreg.h>
58#include <dev/ic/cacvar.h> 58#include <dev/ic/cacvar.h>
59 59
60#if NBIO > 0 60#if NBIO > 0
61#include <dev/biovar.h> 61#include <dev/biovar.h>
62#endif /* NBIO > 0 */ 62#endif /* NBIO > 0 */
63 63
64#include "ioconf.h" 64#include "ioconf.h"
65#include "locators.h" 65#include "locators.h"
66 66
67static struct cac_ccb *cac_ccb_alloc(struct cac_softc *, int); 67static struct cac_ccb *cac_ccb_alloc(struct cac_softc *, int);
68static void cac_ccb_done(struct cac_softc *, struct cac_ccb *); 68static void cac_ccb_done(struct cac_softc *, struct cac_ccb *);
69static void cac_ccb_free(struct cac_softc *, struct cac_ccb *); 69static void cac_ccb_free(struct cac_softc *, struct cac_ccb *);
70static int cac_ccb_poll(struct cac_softc *, struct cac_ccb *, int); 70static int cac_ccb_poll(struct cac_softc *, struct cac_ccb *, int);
71static int cac_ccb_start(struct cac_softc *, struct cac_ccb *); 71static int cac_ccb_start(struct cac_softc *, struct cac_ccb *);
72static int cac_print(void *, const char *); 72static int cac_print(void *, const char *);
73static void cac_shutdown(void *); 73static void cac_shutdown(void *);
74 74
75static struct cac_ccb *cac_l0_completed(struct cac_softc *); 75static struct cac_ccb *cac_l0_completed(struct cac_softc *);
76static int cac_l0_fifo_full(struct cac_softc *); 76static int cac_l0_fifo_full(struct cac_softc *);
77static void cac_l0_intr_enable(struct cac_softc *, int); 77static void cac_l0_intr_enable(struct cac_softc *, int);
78static int cac_l0_intr_pending(struct cac_softc *); 78static int cac_l0_intr_pending(struct cac_softc *);
79static void cac_l0_submit(struct cac_softc *, struct cac_ccb *); 79static void cac_l0_submit(struct cac_softc *, struct cac_ccb *);
80 80
81static void *cac_sdh; /* shutdown hook */ 81static void *cac_sdh; /* shutdown hook */
82 82
83#if NBIO > 0 83#if NBIO > 0
84int cac_ioctl(device_t, u_long, void *); 84int cac_ioctl(device_t, u_long, void *);
85int cac_ioctl_vol(struct cac_softc *, struct bioc_vol *); 85int cac_ioctl_vol(struct cac_softc *, struct bioc_vol *);
86int cac_create_sensors(struct cac_softc *); 86int cac_create_sensors(struct cac_softc *);
87void cac_sensor_refresh(struct sysmon_envsys *, envsys_data_t *); 87void cac_sensor_refresh(struct sysmon_envsys *, envsys_data_t *);
88#endif /* NBIO > 0 */ 88#endif /* NBIO > 0 */
89 89
90const struct cac_linkage cac_l0 = { 90const struct cac_linkage cac_l0 = {
91 cac_l0_completed, 91 cac_l0_completed,
92 cac_l0_fifo_full, 92 cac_l0_fifo_full,
93 cac_l0_intr_enable, 93 cac_l0_intr_enable,
94 cac_l0_intr_pending, 94 cac_l0_intr_pending,
95 cac_l0_submit 95 cac_l0_submit
96}; 96};
97 97
98/* 98/*
99 * Initialise our interface to the controller. 99 * Initialise our interface to the controller.
100 */ 100 */
101int 101int
102cac_init(struct cac_softc *sc, const char *intrstr, int startfw) 102cac_init(struct cac_softc *sc, const char *intrstr, int startfw)
103{ 103{
104 struct cac_controller_info cinfo; 104 struct cac_controller_info cinfo;
105 int error, rseg, size, i; 105 int error, rseg, size, i;
106 bus_dma_segment_t seg; 106 bus_dma_segment_t seg;
107 struct cac_ccb *ccb; 107 struct cac_ccb *ccb;
108 char firm[8]; 108 char firm[8];
109 109
110 if (intrstr != NULL) 110 if (intrstr != NULL)
111 aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); 111 aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
112 112
113 SIMPLEQ_INIT(&sc->sc_ccb_free); 113 SIMPLEQ_INIT(&sc->sc_ccb_free);
114 SIMPLEQ_INIT(&sc->sc_ccb_queue); 114 SIMPLEQ_INIT(&sc->sc_ccb_queue);
115 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM); 115 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM);
116 cv_init(&sc->sc_ccb_cv, "cacccb"); 116 cv_init(&sc->sc_ccb_cv, "cacccb");
117 117
118 size = sizeof(struct cac_ccb) * CAC_MAX_CCBS; 118 size = sizeof(struct cac_ccb) * CAC_MAX_CCBS;
119 119
120 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &seg, 1, 120 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &seg, 1,
121 &rseg, BUS_DMA_NOWAIT)) != 0) { 121 &rseg, BUS_DMA_NOWAIT)) != 0) {
122 aprint_error_dev(sc->sc_dev, "unable to allocate CCBs, error = %d\n", 122 aprint_error_dev(sc->sc_dev, "unable to allocate CCBs, error = %d\n",
123 error); 123 error);
124 return (-1); 124 return (-1);
125 } 125 }
126 126
127 if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, size, 127 if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
128 (void **)&sc->sc_ccbs, 128 (void **)&sc->sc_ccbs,
129 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 129 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
130 aprint_error_dev(sc->sc_dev, "unable to map CCBs, error = %d\n", 130 aprint_error_dev(sc->sc_dev, "unable to map CCBs, error = %d\n",
131 error); 131 error);
132 return (-1); 132 return (-1);
133 } 133 }
134 134
135 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 135 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
136 BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) { 136 BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
137 aprint_error_dev(sc->sc_dev, "unable to create CCB DMA map, error = %d\n", 137 aprint_error_dev(sc->sc_dev, "unable to create CCB DMA map, error = %d\n",
138 error); 138 error);
139 return (-1); 139 return (-1);
140 } 140 }
141 141
142 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_ccbs, 142 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_ccbs,
143 size, NULL, BUS_DMA_NOWAIT)) != 0) { 143 size, NULL, BUS_DMA_NOWAIT)) != 0) {
144 aprint_error_dev(sc->sc_dev, "unable to load CCB DMA map, error = %d\n", 144 aprint_error_dev(sc->sc_dev, "unable to load CCB DMA map, error = %d\n",
145 error); 145 error);
146 return (-1); 146 return (-1);
147 } 147 }
148 148
149 sc->sc_ccbs_paddr = sc->sc_dmamap->dm_segs[0].ds_addr; 149 sc->sc_ccbs_paddr = sc->sc_dmamap->dm_segs[0].ds_addr;
150 memset(sc->sc_ccbs, 0, size); 150 memset(sc->sc_ccbs, 0, size);
151 ccb = (struct cac_ccb *)sc->sc_ccbs; 151 ccb = (struct cac_ccb *)sc->sc_ccbs;
152 152
153 for (i = 0; i < CAC_MAX_CCBS; i++, ccb++) { 153 for (i = 0; i < CAC_MAX_CCBS; i++, ccb++) {
154 /* Create the DMA map for this CCB's data */ 154 /* Create the DMA map for this CCB's data */
155 error = bus_dmamap_create(sc->sc_dmat, CAC_MAX_XFER, 155 error = bus_dmamap_create(sc->sc_dmat, CAC_MAX_XFER,
156 CAC_SG_SIZE, CAC_MAX_XFER, 0, 156 CAC_SG_SIZE, CAC_MAX_XFER, 0,
157 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 157 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
158 &ccb->ccb_dmamap_xfer); 158 &ccb->ccb_dmamap_xfer);
159 159
160 if (error) { 160 if (error) {
161 aprint_error_dev(sc->sc_dev, "can't create ccb dmamap (%d)\n", 161 aprint_error_dev(sc->sc_dev, "can't create ccb dmamap (%d)\n",
162 error); 162 error);
163 break; 163 break;
164 } 164 }
165 165
166 ccb->ccb_flags = 0; 166 ccb->ccb_flags = 0;
167 ccb->ccb_paddr = sc->sc_ccbs_paddr + i * sizeof(struct cac_ccb); 167 ccb->ccb_paddr = sc->sc_ccbs_paddr + i * sizeof(struct cac_ccb);
168 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_chain); 168 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_chain);
169 } 169 }
170 170
171 /* Start firmware background tasks, if needed. */ 171 /* Start firmware background tasks, if needed. */
172 if (startfw) { 172 if (startfw) {
173 if (cac_cmd(sc, CAC_CMD_START_FIRMWARE, &cinfo, sizeof(cinfo), 173 if (cac_cmd(sc, CAC_CMD_START_FIRMWARE, &cinfo, sizeof(cinfo),
174 0, 0, CAC_CCB_DATA_IN, NULL)) { 174 0, 0, CAC_CCB_DATA_IN, NULL)) {
175 aprint_error_dev(sc->sc_dev, "CAC_CMD_START_FIRMWARE failed\n"); 175 aprint_error_dev(sc->sc_dev, "CAC_CMD_START_FIRMWARE failed\n");
176 return (-1); 176 return (-1);
177 } 177 }
178 } 178 }
179 179
180 if (cac_cmd(sc, CAC_CMD_GET_CTRL_INFO, &cinfo, sizeof(cinfo), 0, 0, 180 if (cac_cmd(sc, CAC_CMD_GET_CTRL_INFO, &cinfo, sizeof(cinfo), 0, 0,
181 CAC_CCB_DATA_IN, NULL)) { 181 CAC_CCB_DATA_IN, NULL)) {
182 aprint_error_dev(sc->sc_dev, "CAC_CMD_GET_CTRL_INFO failed\n"); 182 aprint_error_dev(sc->sc_dev, "CAC_CMD_GET_CTRL_INFO failed\n");
183 return (-1); 183 return (-1);
184 } 184 }
185 185
186 strlcpy(firm, cinfo.firm_rev, 4+1); 186 strlcpy(firm, cinfo.firm_rev, 4+1);
187 printf("%s: %d channels, firmware <%s>\n", device_xname(sc->sc_dev), 187 printf("%s: %d channels, firmware <%s>\n", device_xname(sc->sc_dev),
188 cinfo.scsi_chips, firm); 188 cinfo.scsi_chips, firm);
189 189
190 /* Limit number of units to size of our sc_unitmask */ 190 /* Limit number of units to size of our sc_unitmask */
191 sc->sc_nunits = cinfo.num_drvs; 191 sc->sc_nunits = cinfo.num_drvs;
192 if (sc->sc_nunits > sizeof(sc->sc_unitmask) * NBBY) 192 if (sc->sc_nunits > sizeof(sc->sc_unitmask) * NBBY)
193 sc->sc_nunits = sizeof(sc->sc_unitmask) * NBBY; 193 sc->sc_nunits = sizeof(sc->sc_unitmask) * NBBY;
194 194
195 /* Attach our units */ 195 /* Attach our units */
196 sc->sc_unitmask = 0; 196 sc->sc_unitmask = 0;
197 cac_rescan(sc->sc_dev, NULL, NULL); 197 cac_rescan(sc->sc_dev, NULL, NULL);
198 198
199 /* Set our `shutdownhook' before we start any device activity. */ 199 /* Set our `shutdownhook' before we start any device activity. */
200 if (cac_sdh == NULL) 200 if (cac_sdh == NULL)
201 cac_sdh = shutdownhook_establish(cac_shutdown, NULL); 201 cac_sdh = shutdownhook_establish(cac_shutdown, NULL);
202 202
203 mutex_enter(&sc->sc_mutex); 203 mutex_enter(&sc->sc_mutex);
204 (*sc->sc_cl.cl_intr_enable)(sc, CAC_INTR_ENABLE); 204 (*sc->sc_cl.cl_intr_enable)(sc, CAC_INTR_ENABLE);
205 mutex_exit(&sc->sc_mutex); 205 mutex_exit(&sc->sc_mutex);
206 206
207#if NBIO > 0 207#if NBIO > 0
208 if (bio_register(sc->sc_dev, cac_ioctl) != 0) 208 if (bio_register(sc->sc_dev, cac_ioctl) != 0)
209 aprint_error_dev(sc->sc_dev, "controller registration failed"); 209 aprint_error_dev(sc->sc_dev, "controller registration failed");
210 else 210 else
211 sc->sc_ioctl = cac_ioctl; 211 sc->sc_ioctl = cac_ioctl;
212 if (cac_create_sensors(sc) != 0) 212 if (cac_create_sensors(sc) != 0)
213 aprint_error_dev(sc->sc_dev, "unable to create sensors\n"); 213 aprint_error_dev(sc->sc_dev, "unable to create sensors\n");
214#endif 214#endif
215 215
216 return (0); 216 return (0);
217} 217}
218 218
219int 219int
220cac_rescan(device_t self, const char *attr, const int *flags) 220cac_rescan(device_t self, const char *attr, const int *locs)
221{ 221{
222 struct cac_softc *sc; 222 struct cac_softc *sc;
223 struct cac_attach_args caca; 223 struct cac_attach_args caca;
224 int locs[CACCF_NLOCS]; 224 int mlocs[CACCF_NLOCS];
225 int i; 225 int i;
226 226
227 sc = device_private(self); 227 sc = device_private(self);
228 for (i = 0; i < sc->sc_nunits; i++) { 228 for (i = 0; i < sc->sc_nunits; i++) {
229 if (sc->sc_unitmask & (1 << i)) 229 if (sc->sc_unitmask & (1 << i))
230 continue; 230 continue;
231 caca.caca_unit = i; 231 caca.caca_unit = i;
232 232
233 locs[CACCF_UNIT] = i; 233 mlocs[CACCF_UNIT] = i;
234 234
235 if (config_found(self, &caca, cac_print, 235 if (config_found(self, &caca, cac_print,
236 CFARG_SUBMATCH, config_stdsubmatch, 236 CFARG_SUBMATCH, config_stdsubmatch,
237 CFARG_IATTR, attr, 237 CFARG_LOCATORS, mlocs,
238 CFARG_LOCATORS, locs, 
239 CFARG_EOL) != NULL) 238 CFARG_EOL) != NULL)
240 sc->sc_unitmask |= 1 << i; 239 sc->sc_unitmask |= 1 << i;
241 } 240 }
242 return 0; 241 return 0;
243} 242}
244 243
245/* 244/*
246 * Shut down all `cac' controllers. 245 * Shut down all `cac' controllers.
247 */ 246 */
248static void 247static void
249cac_shutdown(void *cookie) 248cac_shutdown(void *cookie)
250{ 249{
251 struct cac_softc *sc; 250 struct cac_softc *sc;
252 u_int8_t tbuf[512]; 251 u_int8_t tbuf[512];
253 int i; 252 int i;
254 253
255 for (i = 0; i < cac_cd.cd_ndevs; i++) { 254 for (i = 0; i < cac_cd.cd_ndevs; i++) {
256 if ((sc = device_lookup_private(&cac_cd, i)) == NULL) 255 if ((sc = device_lookup_private(&cac_cd, i)) == NULL)
257 continue; 256 continue;
258 memset(tbuf, 0, sizeof(tbuf)); 257 memset(tbuf, 0, sizeof(tbuf));
259 tbuf[0] = 1; 258 tbuf[0] = 1;
260 cac_cmd(sc, CAC_CMD_FLUSH_CACHE, tbuf, sizeof(tbuf), 0, 0, 259 cac_cmd(sc, CAC_CMD_FLUSH_CACHE, tbuf, sizeof(tbuf), 0, 0,
261 CAC_CCB_DATA_OUT, NULL); 260 CAC_CCB_DATA_OUT, NULL);
262 } 261 }
263} 262}
264 263
265/* 264/*
266 * Print autoconfiguration message for a sub-device. 265 * Print autoconfiguration message for a sub-device.
267 */ 266 */
268static int 267static int
269cac_print(void *aux, const char *pnp) 268cac_print(void *aux, const char *pnp)
270{ 269{
271 struct cac_attach_args *caca; 270 struct cac_attach_args *caca;
272 271
273 caca = (struct cac_attach_args *)aux; 272 caca = (struct cac_attach_args *)aux;
274 273
275 if (pnp != NULL) 274 if (pnp != NULL)
276 aprint_normal("block device at %s", pnp); 275 aprint_normal("block device at %s", pnp);
277 aprint_normal(" unit %d", caca->caca_unit); 276 aprint_normal(" unit %d", caca->caca_unit);
278 return (UNCONF); 277 return (UNCONF);
279} 278}
280 279
281/* 280/*
282 * Handle an interrupt from the controller: process finished CCBs and 281 * Handle an interrupt from the controller: process finished CCBs and
283 * dequeue any waiting CCBs. 282 * dequeue any waiting CCBs.
284 */ 283 */
285int 284int
286cac_intr(void *cookie) 285cac_intr(void *cookie)
287{ 286{
288 struct cac_softc *sc; 287 struct cac_softc *sc;
289 struct cac_ccb *ccb; 288 struct cac_ccb *ccb;
290 int rv; 289 int rv;
291 290
292 sc = cookie; 291 sc = cookie;
293 292
294 mutex_enter(&sc->sc_mutex); 293 mutex_enter(&sc->sc_mutex);
295 294
296 if ((*sc->sc_cl.cl_intr_pending)(sc)) { 295 if ((*sc->sc_cl.cl_intr_pending)(sc)) {
297 while ((ccb = (*sc->sc_cl.cl_completed)(sc)) != NULL) { 296 while ((ccb = (*sc->sc_cl.cl_completed)(sc)) != NULL) {
298 cac_ccb_done(sc, ccb); 297 cac_ccb_done(sc, ccb);
299 cac_ccb_start(sc, NULL); 298 cac_ccb_start(sc, NULL);
300 } 299 }
301 rv = 1; 300 rv = 1;
302 } else 301 } else
303 rv = 0; 302 rv = 0;
304 303
305 mutex_exit(&sc->sc_mutex); 304 mutex_exit(&sc->sc_mutex);
306 305
307 return (rv); 306 return (rv);
308} 307}
309 308
310/* 309/*
311 * Execute a [polled] command. 310 * Execute a [polled] command.
312 */ 311 */
313int 312int
314cac_cmd(struct cac_softc *sc, int command, void *data, int datasize, 313cac_cmd(struct cac_softc *sc, int command, void *data, int datasize,
315 int drive, int blkno, int flags, struct cac_context *context) 314 int drive, int blkno, int flags, struct cac_context *context)
316{ 315{
317 struct cac_ccb *ccb; 316 struct cac_ccb *ccb;
318 struct cac_sgb *sgb; 317 struct cac_sgb *sgb;
319 int i, rv, size, nsegs; 318 int i, rv, size, nsegs;
320 319
321 size = 0; 320 size = 0;
322 321
323 if ((ccb = cac_ccb_alloc(sc, 1)) == NULL) { 322 if ((ccb = cac_ccb_alloc(sc, 1)) == NULL) {
324 aprint_error_dev(sc->sc_dev, "unable to alloc CCB"); 323 aprint_error_dev(sc->sc_dev, "unable to alloc CCB");
325 return (EAGAIN); 324 return (EAGAIN);
326 } 325 }
327 326
328 if ((flags & (CAC_CCB_DATA_IN | CAC_CCB_DATA_OUT)) != 0) { 327 if ((flags & (CAC_CCB_DATA_IN | CAC_CCB_DATA_OUT)) != 0) {
329 bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap_xfer, 328 bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap_xfer,
330 (void *)data, datasize, NULL, BUS_DMA_NOWAIT | 329 (void *)data, datasize, NULL, BUS_DMA_NOWAIT |
331 BUS_DMA_STREAMING | ((flags & CAC_CCB_DATA_IN) ? 330 BUS_DMA_STREAMING | ((flags & CAC_CCB_DATA_IN) ?
332 BUS_DMA_READ : BUS_DMA_WRITE)); 331 BUS_DMA_READ : BUS_DMA_WRITE));
333 332
334 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap_xfer, 0, datasize, 333 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap_xfer, 0, datasize,
335 (flags & CAC_CCB_DATA_IN) != 0 ? BUS_DMASYNC_PREREAD : 334 (flags & CAC_CCB_DATA_IN) != 0 ? BUS_DMASYNC_PREREAD :
336 BUS_DMASYNC_PREWRITE); 335 BUS_DMASYNC_PREWRITE);
337 336
338 sgb = ccb->ccb_seg; 337 sgb = ccb->ccb_seg;
339 nsegs = uimin(ccb->ccb_dmamap_xfer->dm_nsegs, CAC_SG_SIZE); 338 nsegs = uimin(ccb->ccb_dmamap_xfer->dm_nsegs, CAC_SG_SIZE);
340 339
341 for (i = 0; i < nsegs; i++, sgb++) { 340 for (i = 0; i < nsegs; i++, sgb++) {
342 size += ccb->ccb_dmamap_xfer->dm_segs[i].ds_len; 341 size += ccb->ccb_dmamap_xfer->dm_segs[i].ds_len;
343 sgb->length = 342 sgb->length =
344 htole32(ccb->ccb_dmamap_xfer->dm_segs[i].ds_len); 343 htole32(ccb->ccb_dmamap_xfer->dm_segs[i].ds_len);
345 sgb->addr = 344 sgb->addr =
346 htole32(ccb->ccb_dmamap_xfer->dm_segs[i].ds_addr); 345 htole32(ccb->ccb_dmamap_xfer->dm_segs[i].ds_addr);
347 } 346 }
348 } else { 347 } else {
349 size = datasize; 348 size = datasize;
350 nsegs = 0; 349 nsegs = 0;
351 } 350 }
352 351
353 ccb->ccb_hdr.drive = drive; 352 ccb->ccb_hdr.drive = drive;
354 ccb->ccb_hdr.priority = 0; 353 ccb->ccb_hdr.priority = 0;
355 ccb->ccb_hdr.size = htole16((sizeof(struct cac_req) + 354 ccb->ccb_hdr.size = htole16((sizeof(struct cac_req) +
356 sizeof(struct cac_sgb) * CAC_SG_SIZE) >> 2); 355 sizeof(struct cac_sgb) * CAC_SG_SIZE) >> 2);
357 356
358 ccb->ccb_req.next = 0; 357 ccb->ccb_req.next = 0;
359 ccb->ccb_req.error = 0; 358 ccb->ccb_req.error = 0;
360 ccb->ccb_req.reserved = 0; 359 ccb->ccb_req.reserved = 0;
361 ccb->ccb_req.bcount = htole16(howmany(size, DEV_BSIZE)); 360 ccb->ccb_req.bcount = htole16(howmany(size, DEV_BSIZE));
362 ccb->ccb_req.command = command; 361 ccb->ccb_req.command = command;
363 ccb->ccb_req.sgcount = nsegs; 362 ccb->ccb_req.sgcount = nsegs;
364 ccb->ccb_req.blkno = htole32(blkno); 363 ccb->ccb_req.blkno = htole32(blkno);
365 364
366 ccb->ccb_flags = flags; 365 ccb->ccb_flags = flags;
367 ccb->ccb_datasize = size; 366 ccb->ccb_datasize = size;
368 367
369 mutex_enter(&sc->sc_mutex); 368 mutex_enter(&sc->sc_mutex);
370 369
371 if (context == NULL) { 370 if (context == NULL) {
372 memset(&ccb->ccb_context, 0, sizeof(struct cac_context)); 371 memset(&ccb->ccb_context, 0, sizeof(struct cac_context));
373 372
374 /* Synchronous commands musn't wait. */ 373 /* Synchronous commands musn't wait. */
375 if ((*sc->sc_cl.cl_fifo_full)(sc)) { 374 if ((*sc->sc_cl.cl_fifo_full)(sc)) {
376 cac_ccb_free(sc, ccb); 375 cac_ccb_free(sc, ccb);
377 rv = EAGAIN; 376 rv = EAGAIN;
378 } else { 377 } else {
379#ifdef DIAGNOSTIC 378#ifdef DIAGNOSTIC
380 ccb->ccb_flags |= CAC_CCB_ACTIVE; 379 ccb->ccb_flags |= CAC_CCB_ACTIVE;
381#endif 380#endif
382 (*sc->sc_cl.cl_submit)(sc, ccb); 381 (*sc->sc_cl.cl_submit)(sc, ccb);
383 rv = cac_ccb_poll(sc, ccb, 2000); 382 rv = cac_ccb_poll(sc, ccb, 2000);
384 cac_ccb_free(sc, ccb); 383 cac_ccb_free(sc, ccb);
385 } 384 }
386 } else { 385 } else {
387 memcpy(&ccb->ccb_context, context, sizeof(struct cac_context)); 386 memcpy(&ccb->ccb_context, context, sizeof(struct cac_context));
388 (void)cac_ccb_start(sc, ccb); 387 (void)cac_ccb_start(sc, ccb);
389 rv = 0; 388 rv = 0;
390 } 389 }
391 390
392 mutex_exit(&sc->sc_mutex); 391 mutex_exit(&sc->sc_mutex);
393 return (rv); 392 return (rv);
394} 393}
395 394
396/* 395/*
397 * Wait for the specified CCB to complete. 396 * Wait for the specified CCB to complete.
398 */ 397 */
399static int 398static int
400cac_ccb_poll(struct cac_softc *sc, struct cac_ccb *wantccb, int timo) 399cac_ccb_poll(struct cac_softc *sc, struct cac_ccb *wantccb, int timo)
401{ 400{
402 struct cac_ccb *ccb; 401 struct cac_ccb *ccb;
403 402
404 KASSERT(mutex_owned(&sc->sc_mutex)); 403 KASSERT(mutex_owned(&sc->sc_mutex));
405 404
406 timo *= 1000; 405 timo *= 1000;
407 406
408 do { 407 do {
409 for (; timo != 0; timo--) { 408 for (; timo != 0; timo--) {
410 ccb = (*sc->sc_cl.cl_completed)(sc); 409 ccb = (*sc->sc_cl.cl_completed)(sc);
411 if (ccb != NULL) 410 if (ccb != NULL)
412 break; 411 break;
413 DELAY(1); 412 DELAY(1);
414 } 413 }
415 414
416 if (timo == 0) { 415 if (timo == 0) {
417 printf("%s: timeout\n", device_xname(sc->sc_dev)); 416 printf("%s: timeout\n", device_xname(sc->sc_dev));
418 return (EBUSY); 417 return (EBUSY);
419 } 418 }
420 cac_ccb_done(sc, ccb); 419 cac_ccb_done(sc, ccb);
421 } while (ccb != wantccb); 420 } while (ccb != wantccb);
422 421
423 return (0); 422 return (0);
424} 423}
425 424
426/* 425/*
427 * Enqueue the specified command (if any) and attempt to start all enqueued 426 * Enqueue the specified command (if any) and attempt to start all enqueued
428 * commands. 427 * commands.
429 */ 428 */
430static int 429static int
431cac_ccb_start(struct cac_softc *sc, struct cac_ccb *ccb) 430cac_ccb_start(struct cac_softc *sc, struct cac_ccb *ccb)
432{ 431{
433 432
434 KASSERT(mutex_owned(&sc->sc_mutex)); 433 KASSERT(mutex_owned(&sc->sc_mutex));
435 434
436 if (ccb != NULL) 435 if (ccb != NULL)
437 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ccb, ccb_chain); 436 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ccb, ccb_chain);
438 437
439 while ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) { 438 while ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) {
440 if ((*sc->sc_cl.cl_fifo_full)(sc)) 439 if ((*sc->sc_cl.cl_fifo_full)(sc))
441 return (EAGAIN); 440 return (EAGAIN);
442 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ccb_chain); 441 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ccb_chain);
443#ifdef DIAGNOSTIC 442#ifdef DIAGNOSTIC
444 ccb->ccb_flags |= CAC_CCB_ACTIVE; 443 ccb->ccb_flags |= CAC_CCB_ACTIVE;
445#endif 444#endif
446 (*sc->sc_cl.cl_submit)(sc, ccb); 445 (*sc->sc_cl.cl_submit)(sc, ccb);
447 } 446 }
448 447
449 return (0); 448 return (0);
450} 449}
451 450
452/* 451/*
453 * Process a finished CCB. 452 * Process a finished CCB.
454 */ 453 */
455static void 454static void
456cac_ccb_done(struct cac_softc *sc, struct cac_ccb *ccb) 455cac_ccb_done(struct cac_softc *sc, struct cac_ccb *ccb)
457{ 456{
458 device_t dv; 457 device_t dv;
459 void *context; 458 void *context;
460 int error; 459 int error;
461 460
462 error = 0; 461 error = 0;
463 462
464 KASSERT(mutex_owned(&sc->sc_mutex)); 463 KASSERT(mutex_owned(&sc->sc_mutex));
465 464
466#ifdef DIAGNOSTIC 465#ifdef DIAGNOSTIC
467 if ((ccb->ccb_flags & CAC_CCB_ACTIVE) == 0) 466 if ((ccb->ccb_flags & CAC_CCB_ACTIVE) == 0)
468 panic("cac_ccb_done: CCB not active"); 467 panic("cac_ccb_done: CCB not active");
469 ccb->ccb_flags &= ~CAC_CCB_ACTIVE; 468 ccb->ccb_flags &= ~CAC_CCB_ACTIVE;
470#endif 469#endif
471 470
472 if ((ccb->ccb_flags & (CAC_CCB_DATA_IN | CAC_CCB_DATA_OUT)) != 0) { 471 if ((ccb->ccb_flags & (CAC_CCB_DATA_IN | CAC_CCB_DATA_OUT)) != 0) {
473 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap_xfer, 0, 472 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap_xfer, 0,
474 ccb->ccb_datasize, ccb->ccb_flags & CAC_CCB_DATA_IN ? 473 ccb->ccb_datasize, ccb->ccb_flags & CAC_CCB_DATA_IN ?
475 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 474 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
476 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap_xfer); 475 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap_xfer);
477 } 476 }
478 477
479 error = ccb->ccb_req.error; 478 error = ccb->ccb_req.error;
480 if (ccb->ccb_context.cc_handler != NULL) { 479 if (ccb->ccb_context.cc_handler != NULL) {
481 dv = ccb->ccb_context.cc_dv; 480 dv = ccb->ccb_context.cc_dv;
482 context = ccb->ccb_context.cc_context; 481 context = ccb->ccb_context.cc_context;
483 cac_ccb_free(sc, ccb); 482 cac_ccb_free(sc, ccb);
484 (*ccb->ccb_context.cc_handler)(dv, context, error); 483 (*ccb->ccb_context.cc_handler)(dv, context, error);
485 } else { 484 } else {
486 if ((error & CAC_RET_SOFT_ERROR) != 0) 485 if ((error & CAC_RET_SOFT_ERROR) != 0)
487 aprint_error_dev(sc->sc_dev, "soft error; array may be degraded\n"); 486 aprint_error_dev(sc->sc_dev, "soft error; array may be degraded\n");
488 if ((error & CAC_RET_HARD_ERROR) != 0) 487 if ((error & CAC_RET_HARD_ERROR) != 0)
489 aprint_error_dev(sc->sc_dev, "hard error\n"); 488 aprint_error_dev(sc->sc_dev, "hard error\n");
490 if ((error & CAC_RET_CMD_REJECTED) != 0) { 489 if ((error & CAC_RET_CMD_REJECTED) != 0) {
491 error = 1; 490 error = 1;
492 aprint_error_dev(sc->sc_dev, "invalid request\n"); 491 aprint_error_dev(sc->sc_dev, "invalid request\n");
493 } 492 }
494 } 493 }
495} 494}
496 495
497/* 496/*
498 * Allocate a CCB. 497 * Allocate a CCB.
499 */ 498 */
500static struct cac_ccb * 499static struct cac_ccb *
501cac_ccb_alloc(struct cac_softc *sc, int nosleep) 500cac_ccb_alloc(struct cac_softc *sc, int nosleep)
502{ 501{
503 struct cac_ccb *ccb; 502 struct cac_ccb *ccb;
504 503
505 mutex_enter(&sc->sc_mutex); 504 mutex_enter(&sc->sc_mutex);
506 505
507 for (;;) { 506 for (;;) {
508 if ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free)) != NULL) { 507 if ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free)) != NULL) {
509 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ccb_chain); 508 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ccb_chain);
510 break; 509 break;
511 } 510 }
512 if (nosleep) { 511 if (nosleep) {
513 ccb = NULL; 512 ccb = NULL;
514 break; 513 break;
515 } 514 }
516 cv_wait(&sc->sc_ccb_cv, &sc->sc_mutex); 515 cv_wait(&sc->sc_ccb_cv, &sc->sc_mutex);
517 } 516 }
518 517
519 mutex_exit(&sc->sc_mutex); 518 mutex_exit(&sc->sc_mutex);
520 return (ccb); 519 return (ccb);
521} 520}
522 521
523/* 522/*
524 * Put a CCB onto the freelist. 523 * Put a CCB onto the freelist.
525 */ 524 */
526static void 525static void
527cac_ccb_free(struct cac_softc *sc, struct cac_ccb *ccb) 526cac_ccb_free(struct cac_softc *sc, struct cac_ccb *ccb)
528{ 527{
529 528
530 KASSERT(mutex_owned(&sc->sc_mutex)); 529 KASSERT(mutex_owned(&sc->sc_mutex));
531 530
532 ccb->ccb_flags = 0; 531 ccb->ccb_flags = 0;
533 if (SIMPLEQ_EMPTY(&sc->sc_ccb_free)) 532 if (SIMPLEQ_EMPTY(&sc->sc_ccb_free))
534 cv_signal(&sc->sc_ccb_cv); 533 cv_signal(&sc->sc_ccb_cv);
535 SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_chain); 534 SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_chain);
536} 535}
537 536
538/* 537/*
539 * Board specific linkage shared between multiple bus types. 538 * Board specific linkage shared between multiple bus types.
540 */ 539 */
541 540
542static int 541static int
543cac_l0_fifo_full(struct cac_softc *sc) 542cac_l0_fifo_full(struct cac_softc *sc)
544{ 543{
545 544
546 KASSERT(mutex_owned(&sc->sc_mutex)); 545 KASSERT(mutex_owned(&sc->sc_mutex));
547 546
548 return (cac_inl(sc, CAC_REG_CMD_FIFO) == 0); 547 return (cac_inl(sc, CAC_REG_CMD_FIFO) == 0);
549} 548}
550 549
551static void 550static void
552cac_l0_submit(struct cac_softc *sc, struct cac_ccb *ccb) 551cac_l0_submit(struct cac_softc *sc, struct cac_ccb *ccb)
553{ 552{
554 553
555 KASSERT(mutex_owned(&sc->sc_mutex)); 554 KASSERT(mutex_owned(&sc->sc_mutex));
556 555
557 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 556 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
558 (char *)ccb - (char *)sc->sc_ccbs, 557 (char *)ccb - (char *)sc->sc_ccbs,
559 sizeof(struct cac_ccb), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 558 sizeof(struct cac_ccb), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
560 cac_outl(sc, CAC_REG_CMD_FIFO, ccb->ccb_paddr); 559 cac_outl(sc, CAC_REG_CMD_FIFO, ccb->ccb_paddr);
561} 560}
562 561
563static struct cac_ccb * 562static struct cac_ccb *
564cac_l0_completed(struct cac_softc *sc) 563cac_l0_completed(struct cac_softc *sc)
565{ 564{
566 struct cac_ccb *ccb; 565 struct cac_ccb *ccb;
567 paddr_t off; 566 paddr_t off;
568 567
569 KASSERT(mutex_owned(&sc->sc_mutex)); 568 KASSERT(mutex_owned(&sc->sc_mutex));
570 569
571 if ((off = cac_inl(sc, CAC_REG_DONE_FIFO)) == 0) 570 if ((off = cac_inl(sc, CAC_REG_DONE_FIFO)) == 0)
572 return (NULL); 571 return (NULL);
573 572
574 if ((off & 3) != 0) 573 if ((off & 3) != 0)
575 aprint_error_dev(sc->sc_dev, "failed command list returned: %lx\n", 574 aprint_error_dev(sc->sc_dev, "failed command list returned: %lx\n",
576 (long)off); 575 (long)off);
577 576
578 off = (off & ~3) - sc->sc_ccbs_paddr; 577 off = (off & ~3) - sc->sc_ccbs_paddr;
579 ccb = (struct cac_ccb *)((char *)sc->sc_ccbs + off); 578 ccb = (struct cac_ccb *)((char *)sc->sc_ccbs + off);
580 579
581 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, off, sizeof(struct cac_ccb), 580 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, off, sizeof(struct cac_ccb),
582 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 581 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
583 582
584 if ((off & 3) != 0 && ccb->ccb_req.error == 0) 583 if ((off & 3) != 0 && ccb->ccb_req.error == 0)
585 ccb->ccb_req.error = CAC_RET_CMD_REJECTED; 584 ccb->ccb_req.error = CAC_RET_CMD_REJECTED;
586 585
587 return (ccb); 586 return (ccb);
588} 587}
589 588
590static int 589static int
591cac_l0_intr_pending(struct cac_softc *sc) 590cac_l0_intr_pending(struct cac_softc *sc)
592{ 591{
593 592
594 KASSERT(mutex_owned(&sc->sc_mutex)); 593 KASSERT(mutex_owned(&sc->sc_mutex));
595 594
596 return (cac_inl(sc, CAC_REG_INTR_PENDING) & CAC_INTR_ENABLE); 595 return (cac_inl(sc, CAC_REG_INTR_PENDING) & CAC_INTR_ENABLE);
597} 596}
598 597
599static void 598static void
600cac_l0_intr_enable(struct cac_softc *sc, int state) 599cac_l0_intr_enable(struct cac_softc *sc, int state)
601{ 600{
602 601
603 KASSERT(mutex_owned(&sc->sc_mutex)); 602 KASSERT(mutex_owned(&sc->sc_mutex));
604 603
605 cac_outl(sc, CAC_REG_INTR_MASK, 604 cac_outl(sc, CAC_REG_INTR_MASK,
606 state ? CAC_INTR_ENABLE : CAC_INTR_DISABLE); 605 state ? CAC_INTR_ENABLE : CAC_INTR_DISABLE);
607} 606}
608 607
609#if NBIO > 0 608#if NBIO > 0
610const int cac_level[] = { 0, 4, 1, 5, 51, 7 }; 609const int cac_level[] = { 0, 4, 1, 5, 51, 7 };
611const int cac_stat[] = { BIOC_SVONLINE, BIOC_SVOFFLINE, BIOC_SVOFFLINE, 610const int cac_stat[] = { BIOC_SVONLINE, BIOC_SVOFFLINE, BIOC_SVOFFLINE,
612 BIOC_SVDEGRADED, BIOC_SVREBUILD, BIOC_SVREBUILD, BIOC_SVDEGRADED, 611 BIOC_SVDEGRADED, BIOC_SVREBUILD, BIOC_SVREBUILD, BIOC_SVDEGRADED,
613 BIOC_SVDEGRADED, BIOC_SVINVALID, BIOC_SVINVALID, BIOC_SVBUILDING, 612 BIOC_SVDEGRADED, BIOC_SVINVALID, BIOC_SVINVALID, BIOC_SVBUILDING,
614 BIOC_SVOFFLINE, BIOC_SVBUILDING }; 613 BIOC_SVOFFLINE, BIOC_SVBUILDING };
615 614
616int 615int
617cac_ioctl(device_t dev, u_long cmd, void *addr) 616cac_ioctl(device_t dev, u_long cmd, void *addr)
618{ 617{
619 struct cac_softc *sc = device_private(dev); 618 struct cac_softc *sc = device_private(dev);
620 struct bioc_inq *bi; 619 struct bioc_inq *bi;
621 struct bioc_disk *bd; 620 struct bioc_disk *bd;
622 cac_lock_t lock; 621 cac_lock_t lock;
623 int error = 0; 622 int error = 0;
624 623
625 lock = CAC_LOCK(sc); 624 lock = CAC_LOCK(sc);
626 switch (cmd) { 625 switch (cmd) {
627 case BIOCINQ: 626 case BIOCINQ:
628 bi = (struct bioc_inq *)addr; 627 bi = (struct bioc_inq *)addr;
629 strlcpy(bi->bi_dev, device_xname(sc->sc_dev), sizeof(bi->bi_dev)); 628 strlcpy(bi->bi_dev, device_xname(sc->sc_dev), sizeof(bi->bi_dev));
630 bi->bi_novol = sc->sc_nunits; 629 bi->bi_novol = sc->sc_nunits;
631 bi->bi_nodisk = 0; 630 bi->bi_nodisk = 0;
632 break; 631 break;
633 632
634 case BIOCVOL: 633 case BIOCVOL:
635 error = cac_ioctl_vol(sc, (struct bioc_vol *)addr); 634 error = cac_ioctl_vol(sc, (struct bioc_vol *)addr);
636 break; 635 break;
637 636
638 case BIOCDISK: 637 case BIOCDISK:
639 case BIOCDISK_NOVOL: 638 case BIOCDISK_NOVOL:
640 bd = (struct bioc_disk *)addr; 639 bd = (struct bioc_disk *)addr;
641 if (bd->bd_volid > sc->sc_nunits) { 640 if (bd->bd_volid > sc->sc_nunits) {
642 error = EINVAL; 641 error = EINVAL;
643 break; 642 break;
644 } 643 }
645 /* No disk information yet */ 644 /* No disk information yet */
646 break; 645 break;
647 646
648 default: 647 default:
649 error = EINVAL; 648 error = EINVAL;
650 } 649 }
651 CAC_UNLOCK(sc, lock); 650 CAC_UNLOCK(sc, lock);
652 651
653 return (error); 652 return (error);
654} 653}
655 654
656int 655int
657cac_ioctl_vol(struct cac_softc *sc, struct bioc_vol *bv) 656cac_ioctl_vol(struct cac_softc *sc, struct bioc_vol *bv)
658{ 657{
659 struct cac_drive_info dinfo; 658 struct cac_drive_info dinfo;
660 struct cac_drive_status dstatus; 659 struct cac_drive_status dstatus;
661 u_int32_t blks; 660 u_int32_t blks;
662 661
663 if (bv->bv_volid > sc->sc_nunits) { 662 if (bv->bv_volid > sc->sc_nunits) {
664 return EINVAL; 663 return EINVAL;
665 } 664 }
666 if (cac_cmd(sc, CAC_CMD_GET_LOG_DRV_INFO, &dinfo, sizeof(dinfo), 665 if (cac_cmd(sc, CAC_CMD_GET_LOG_DRV_INFO, &dinfo, sizeof(dinfo),
667 bv->bv_volid, 0, CAC_CCB_DATA_IN, NULL)) { 666 bv->bv_volid, 0, CAC_CCB_DATA_IN, NULL)) {
668 return EIO; 667 return EIO;
669 } 668 }
670 if (cac_cmd(sc, CAC_CMD_SENSE_DRV_STATUS, &dstatus, sizeof(dstatus), 669 if (cac_cmd(sc, CAC_CMD_SENSE_DRV_STATUS, &dstatus, sizeof(dstatus),
671 bv->bv_volid, 0, CAC_CCB_DATA_IN, NULL)) { 670 bv->bv_volid, 0, CAC_CCB_DATA_IN, NULL)) {
672 return EIO; 671 return EIO;
673 } 672 }
674 blks = CAC_GET2(dinfo.ncylinders) * CAC_GET1(dinfo.nheads) * 673 blks = CAC_GET2(dinfo.ncylinders) * CAC_GET1(dinfo.nheads) *
675 CAC_GET1(dinfo.nsectors); 674 CAC_GET1(dinfo.nsectors);
676 bv->bv_size = (off_t)blks * CAC_GET2(dinfo.secsize); 675 bv->bv_size = (off_t)blks * CAC_GET2(dinfo.secsize);
677 bv->bv_level = cac_level[CAC_GET1(dinfo.mirror)]; /*XXX limit check */ 676 bv->bv_level = cac_level[CAC_GET1(dinfo.mirror)]; /*XXX limit check */
678 bv->bv_nodisk = 0; /* XXX */ 677 bv->bv_nodisk = 0; /* XXX */
679 bv->bv_status = 0; /* XXX */ 678 bv->bv_status = 0; /* XXX */
680 bv->bv_percent = -1; 679 bv->bv_percent = -1;
681 bv->bv_seconds = 0; 680 bv->bv_seconds = 0;
682 if (dstatus.stat < sizeof(cac_stat)/sizeof(cac_stat[0])) 681 if (dstatus.stat < sizeof(cac_stat)/sizeof(cac_stat[0]))
683 bv->bv_status = cac_stat[dstatus.stat]; 682 bv->bv_status = cac_stat[dstatus.stat];
684 if (bv->bv_status == BIOC_SVREBUILD || 683 if (bv->bv_status == BIOC_SVREBUILD ||
685 bv->bv_status == BIOC_SVBUILDING) 684 bv->bv_status == BIOC_SVBUILDING)
686 bv->bv_percent = ((blks - CAC_GET4(dstatus.prog)) * 1000ULL) / 685 bv->bv_percent = ((blks - CAC_GET4(dstatus.prog)) * 1000ULL) /
687 blks; 686 blks;
688 return 0; 687 return 0;
689} 688}
690 689
691int 690int
692cac_create_sensors(struct cac_softc *sc) 691cac_create_sensors(struct cac_softc *sc)
693{ 692{
694 int i; 693 int i;
695 int nsensors = sc->sc_nunits; 694 int nsensors = sc->sc_nunits;
696 695
697 sc->sc_sme = sysmon_envsys_create(); 696 sc->sc_sme = sysmon_envsys_create();
698 sc->sc_sensor = malloc(sizeof(envsys_data_t) * nsensors, 697 sc->sc_sensor = malloc(sizeof(envsys_data_t) * nsensors,
699 M_DEVBUF, M_WAITOK | M_ZERO); 698 M_DEVBUF, M_WAITOK | M_ZERO);
700 for (i = 0; i < nsensors; i++) { 699 for (i = 0; i < nsensors; i++) {
701 sc->sc_sensor[i].units = ENVSYS_DRIVE; 700 sc->sc_sensor[i].units = ENVSYS_DRIVE;
702 sc->sc_sensor[i].state = ENVSYS_SINVALID; 701 sc->sc_sensor[i].state = ENVSYS_SINVALID;
703 sc->sc_sensor[i].value_cur = ENVSYS_DRIVE_EMPTY; 702 sc->sc_sensor[i].value_cur = ENVSYS_DRIVE_EMPTY;
704 /* Enable monitoring for drive state changes */ 703 /* Enable monitoring for drive state changes */
705 sc->sc_sensor[i].flags |= ENVSYS_FMONSTCHANGED; 704 sc->sc_sensor[i].flags |= ENVSYS_FMONSTCHANGED;
706 /* logical drives */ 705 /* logical drives */
707 snprintf(sc->sc_sensor[i].desc, 706 snprintf(sc->sc_sensor[i].desc,
708 sizeof(sc->sc_sensor[i].desc), "%s:%d", 707 sizeof(sc->sc_sensor[i].desc), "%s:%d",
709 device_xname(sc->sc_dev), i); 708 device_xname(sc->sc_dev), i);
710 if (sysmon_envsys_sensor_attach(sc->sc_sme, 709 if (sysmon_envsys_sensor_attach(sc->sc_sme,
711 &sc->sc_sensor[i])) 710 &sc->sc_sensor[i]))
712 goto out; 711 goto out;
713 } 712 }
714 sc->sc_sme->sme_name = device_xname(sc->sc_dev); 713 sc->sc_sme->sme_name = device_xname(sc->sc_dev);
715 sc->sc_sme->sme_cookie = sc; 714 sc->sc_sme->sme_cookie = sc;
716 sc->sc_sme->sme_refresh = cac_sensor_refresh; 715 sc->sc_sme->sme_refresh = cac_sensor_refresh;
717 if (sysmon_envsys_register(sc->sc_sme)) { 716 if (sysmon_envsys_register(sc->sc_sme)) {
718 aprint_error_dev(sc->sc_dev, "unable to register with sysmon\n"); 717 aprint_error_dev(sc->sc_dev, "unable to register with sysmon\n");
719 return(1); 718 return(1);
720 } 719 }
721 return (0); 720 return (0);
722 721
723out: 722out:
724 free(sc->sc_sensor, M_DEVBUF); 723 free(sc->sc_sensor, M_DEVBUF);
725 sysmon_envsys_destroy(sc->sc_sme); 724 sysmon_envsys_destroy(sc->sc_sme);
726 return EINVAL; 725 return EINVAL;
727} 726}
728 727
729void 728void
730cac_sensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 729cac_sensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
731{ 730{
732 struct cac_softc *sc = sme->sme_cookie; 731 struct cac_softc *sc = sme->sme_cookie;
733 struct bioc_vol bv; 732 struct bioc_vol bv;
734 int s; 733 int s;
735 734
736 if (edata->sensor >= sc->sc_nunits) 735 if (edata->sensor >= sc->sc_nunits)
737 return; 736 return;
738 737
739 memset(&bv, 0, sizeof(bv)); 738 memset(&bv, 0, sizeof(bv));
740 bv.bv_volid = edata->sensor; 739 bv.bv_volid = edata->sensor;
741 s = splbio(); 740 s = splbio();
742 if (cac_ioctl_vol(sc, &bv)) 741 if (cac_ioctl_vol(sc, &bv))
743 bv.bv_status = BIOC_SVINVALID; 742 bv.bv_status = BIOC_SVINVALID;
744 splx(s); 743 splx(s);
745 744
746 bio_vol_to_envsys(edata, &bv); 745 bio_vol_to_envsys(edata, &bv);
747} 746}
748#endif /* NBIO > 0 */ 747#endif /* NBIO > 0 */
749 748
750MODULE(MODULE_CLASS_DRIVER, cac, NULL); 749MODULE(MODULE_CLASS_DRIVER, cac, NULL);
751 750
752#ifdef _MODULE 751#ifdef _MODULE
753CFDRIVER_DECL(cac, DV_DISK, NULL); 752CFDRIVER_DECL(cac, DV_DISK, NULL);
754#endif 753#endif
755 754
756static int 755static int
757cac_modcmd(modcmd_t cmd, void *opaque) 756cac_modcmd(modcmd_t cmd, void *opaque)
758{ 757{
759 int error = 0; 758 int error = 0;
760 759
761#ifdef _MODULE 760#ifdef _MODULE
762 switch (cmd) { 761 switch (cmd) {
763 case MODULE_CMD_INIT: 762 case MODULE_CMD_INIT:
764 error = config_cfdriver_attach(&cac_cd); 763 error = config_cfdriver_attach(&cac_cd);
765 break; 764 break;
766 case MODULE_CMD_FINI: 765 case MODULE_CMD_FINI:
767 error = config_cfdriver_detach(&cac_cd); 766 error = config_cfdriver_detach(&cac_cd);
768 break; 767 break;
769 default: 768 default:
770 error = ENOTTY; 769 error = ENOTTY;
771 break; 770 break;
772 } 771 }
773#endif 772#endif
774 return error; 773 return error;
775} 774}