This source file includes following definitions.
- ciss_get_ccb
- ciss_put_ccb
- ciss_attach
- ciss_shutdown
- cissminphys
- ciss_cmd
- ciss_done
- ciss_error
- ciss_inq
- ciss_ldmap
- ciss_sync
- ciss_scsi_raw_cmd
- ciss_scsi_cmd
- ciss_intr
- ciss_heartbeat
- ciss_kthread
- ciss_scsi_ioctl
- ciss_ioctl
- ciss_sensors
- ciss_ldid
- ciss_ldstat
- ciss_pdid
- ciss_pdscan
- ciss_blink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include "bio.h"
21
22
23
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <sys/buf.h>
27 #include <sys/ioctl.h>
28 #include <sys/device.h>
29 #include <sys/kernel.h>
30 #include <sys/malloc.h>
31 #include <sys/proc.h>
32 #include <sys/kthread.h>
33
34 #include <machine/bus.h>
35
36 #include <scsi/scsi_all.h>
37 #include <scsi/scsi_disk.h>
38 #include <scsi/scsiconf.h>
39
40 #include <dev/ic/cissreg.h>
41 #include <dev/ic/cissvar.h>
42
43 #if NBIO > 0
44 #include <dev/biovar.h>
45 #endif
46 #include <sys/sensors.h>
47
48 #ifdef CISS_DEBUG
49 #define CISS_DPRINTF(m,a) if (ciss_debug & (m)) printf a
50 #define CISS_D_CMD 0x0001
51 #define CISS_D_INTR 0x0002
52 #define CISS_D_MISC 0x0004
53 #define CISS_D_DMA 0x0008
54 #define CISS_D_IOCTL 0x0010
55 #define CISS_D_ERR 0x0020
56 int ciss_debug = 0
57
58
59
60
61
62
63 ;
64 #else
65 #define CISS_DPRINTF(m,a)
66 #endif
67
68 struct cfdriver ciss_cd = {
69 NULL, "ciss", DV_DULL
70 };
71
72 int ciss_scsi_cmd(struct scsi_xfer *xs);
73 int ciss_scsi_ioctl(struct scsi_link *link, u_long cmd,
74 caddr_t addr, int flag, struct proc *p);
75 void cissminphys(struct buf *bp);
76
77 struct scsi_adapter ciss_switch = {
78 ciss_scsi_cmd, cissminphys, NULL, NULL, ciss_scsi_ioctl
79 };
80
81 struct scsi_device ciss_dev = {
82 NULL, NULL, NULL, NULL
83 };
84
85 int ciss_scsi_raw_cmd(struct scsi_xfer *xs);
86
87 struct scsi_adapter ciss_raw_switch = {
88 ciss_scsi_raw_cmd, cissminphys, NULL, NULL,
89 };
90
91 struct scsi_device ciss_raw_dev = {
92 NULL, NULL, NULL, NULL
93 };
94
95 #if NBIO > 0
96 int ciss_ioctl(struct device *, u_long, caddr_t);
97 #endif
98 int ciss_sync(struct ciss_softc *sc);
99 void ciss_heartbeat(void *v);
100 void ciss_shutdown(void *v);
101 void ciss_kthread(void *v);
102 #ifndef SMALL_KERNEL
103 void ciss_sensors(void *);
104 #endif
105
106 struct ciss_ccb *ciss_get_ccb(struct ciss_softc *sc);
107 void ciss_put_ccb(struct ciss_ccb *ccb);
108 int ciss_cmd(struct ciss_ccb *ccb, int flags, int wait);
109 int ciss_done(struct ciss_ccb *ccb);
110 int ciss_error(struct ciss_ccb *ccb);
111
112 struct ciss_ld *ciss_pdscan(struct ciss_softc *sc, int ld);
113 int ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq);
114 int ciss_ldmap(struct ciss_softc *sc);
115 int ciss_ldid(struct ciss_softc *, int, struct ciss_ldid *);
116 int ciss_ldstat(struct ciss_softc *, int, struct ciss_ldstat *);
117 int ciss_pdid(struct ciss_softc *, u_int8_t, struct ciss_pdid *, int);
118 int ciss_blink(struct ciss_softc *, int, int, int, struct ciss_blink *);
119
120 struct ciss_ccb *
121 ciss_get_ccb(struct ciss_softc *sc)
122 {
123 struct ciss_ccb *ccb;
124
125 if ((ccb = TAILQ_LAST(&sc->sc_free_ccb, ciss_queue_head))) {
126 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ccb_link);
127 ccb->ccb_state = CISS_CCB_READY;
128 }
129 return ccb;
130 }
131
132 void
133 ciss_put_ccb(struct ciss_ccb *ccb)
134 {
135 struct ciss_softc *sc = ccb->ccb_sc;
136
137 ccb->ccb_state = CISS_CCB_FREE;
138 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
139 }
140
141 int
142 ciss_attach(struct ciss_softc *sc)
143 {
144 struct scsibus_attach_args saa;
145 struct scsibus_softc *scsibus;
146 struct ciss_ccb *ccb;
147 struct ciss_cmd *cmd;
148 struct ciss_inquiry *inq;
149 bus_dma_segment_t seg[1];
150 int error, i, total, rseg, maxfer;
151 ciss_lock_t lock;
152 paddr_t pa;
153
154 bus_space_read_region_4(sc->iot, sc->cfg_ioh, sc->cfgoff,
155 (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4);
156
157 if (sc->cfg.signature != CISS_SIGNATURE) {
158 printf(": bad sign 0x%08x\n", sc->cfg.signature);
159 return -1;
160 }
161
162 if (!(sc->cfg.methods & CISS_METH_SIMPL)) {
163 printf(": not simple 0x%08x\n", sc->cfg.methods);
164 return -1;
165 }
166
167 sc->cfg.rmethod = CISS_METH_SIMPL;
168 sc->cfg.paddr_lim = 0;
169 sc->cfg.int_delay = 0;
170 sc->cfg.int_count = 0;
171 strlcpy(sc->cfg.hostname, "HUMPPA", sizeof(sc->cfg.hostname));
172 sc->cfg.driverf |= CISS_DRV_PRF;
173 if (!sc->cfg.maxsg)
174 sc->cfg.maxsg = MAXPHYS / PAGE_SIZE;
175
176 bus_space_write_region_4(sc->iot, sc->cfg_ioh, sc->cfgoff,
177 (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4);
178 bus_space_barrier(sc->iot, sc->cfg_ioh, sc->cfgoff, sizeof(sc->cfg),
179 BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
180
181 bus_space_write_4(sc->iot, sc->ioh, CISS_IDB, CISS_IDB_CFG);
182 bus_space_barrier(sc->iot, sc->ioh, CISS_IDB, 4,
183 BUS_SPACE_BARRIER_WRITE);
184 for (i = 1000; i--; DELAY(1000)) {
185
186 (void)bus_space_read_4(sc->iot, sc->ioh, CISS_IDB + 4);
187 if (!(bus_space_read_4(sc->iot, sc->ioh, CISS_IDB) & CISS_IDB_CFG))
188 break;
189 bus_space_barrier(sc->iot, sc->ioh, CISS_IDB, 4,
190 BUS_SPACE_BARRIER_READ);
191 }
192
193 if (bus_space_read_4(sc->iot, sc->ioh, CISS_IDB) & CISS_IDB_CFG) {
194 printf(": cannot set config\n");
195 return -1;
196 }
197
198 bus_space_read_region_4(sc->iot, sc->cfg_ioh, sc->cfgoff,
199 (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4);
200
201 if (!(sc->cfg.amethod & CISS_METH_SIMPL)) {
202 printf(": cannot simplify 0x%08x\n", sc->cfg.amethod);
203 return -1;
204 }
205
206
207 for (i = 30000; i--; DELAY(1000)) {
208 if (bus_space_read_4(sc->iot, sc->cfg_ioh, sc->cfgoff +
209 offsetof(struct ciss_config, amethod)) & CISS_METH_READY)
210 break;
211 bus_space_barrier(sc->iot, sc->cfg_ioh, sc->cfgoff +
212 offsetof(struct ciss_config, amethod), 4,
213 BUS_SPACE_BARRIER_READ);
214 }
215
216 if (!(bus_space_read_4(sc->iot, sc->cfg_ioh, sc->cfgoff +
217 offsetof(struct ciss_config, amethod)) & CISS_METH_READY)) {
218 printf(": she never came ready for me 0x%08x\n",
219 sc->cfg.amethod);
220 return -1;
221 }
222
223 sc->maxcmd = sc->cfg.maxcmd;
224 sc->maxsg = sc->cfg.maxsg;
225 if (sc->maxsg > MAXPHYS / PAGE_SIZE)
226 sc->maxsg = MAXPHYS / PAGE_SIZE;
227 i = sizeof(struct ciss_ccb) +
228 sizeof(ccb->ccb_cmd.sgl[0]) * (sc->maxsg - 1);
229 for (sc->ccblen = 0x10; sc->ccblen < i; sc->ccblen <<= 1);
230
231 total = sc->ccblen * sc->maxcmd;
232 if ((error = bus_dmamem_alloc(sc->dmat, total, PAGE_SIZE, 0,
233 sc->cmdseg, 1, &rseg, BUS_DMA_NOWAIT))) {
234 printf(": cannot allocate CCBs (%d)\n", error);
235 return -1;
236 }
237
238 if ((error = bus_dmamem_map(sc->dmat, sc->cmdseg, rseg, total,
239 (caddr_t *)&sc->ccbs, BUS_DMA_NOWAIT))) {
240 printf(": cannot map CCBs (%d)\n", error);
241 return -1;
242 }
243 bzero(sc->ccbs, total);
244
245 if ((error = bus_dmamap_create(sc->dmat, total, 1,
246 total, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->cmdmap))) {
247 printf(": cannot create CCBs dmamap (%d)\n", error);
248 bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
249 return -1;
250 }
251
252 if ((error = bus_dmamap_load(sc->dmat, sc->cmdmap, sc->ccbs, total,
253 NULL, BUS_DMA_NOWAIT))) {
254 printf(": cannot load CCBs dmamap (%d)\n", error);
255 bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
256 bus_dmamap_destroy(sc->dmat, sc->cmdmap);
257 return -1;
258 }
259
260 TAILQ_INIT(&sc->sc_ccbq);
261 TAILQ_INIT(&sc->sc_ccbdone);
262 TAILQ_INIT(&sc->sc_free_ccb);
263
264 maxfer = sc->maxsg * PAGE_SIZE;
265 for (i = 0; total; i++, total -= sc->ccblen) {
266 ccb = sc->ccbs + i * sc->ccblen;
267 cmd = &ccb->ccb_cmd;
268 pa = sc->cmdseg[0].ds_addr + i * sc->ccblen;
269
270 ccb->ccb_sc = sc;
271 ccb->ccb_cmdpa = pa + offsetof(struct ciss_ccb, ccb_cmd);
272 ccb->ccb_state = CISS_CCB_FREE;
273
274 cmd->id = htole32(i << 2);
275 cmd->id_hi = htole32(0);
276 cmd->sgin = sc->maxsg;
277 cmd->sglen = htole16((u_int16_t)cmd->sgin);
278 cmd->err_len = htole32(sizeof(ccb->ccb_err));
279 pa += offsetof(struct ciss_ccb, ccb_err);
280 cmd->err_pa = htole64((u_int64_t)pa);
281
282 if ((error = bus_dmamap_create(sc->dmat, maxfer, sc->maxsg,
283 maxfer, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
284 &ccb->ccb_dmamap)))
285 break;
286
287 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
288 }
289
290 if (i < sc->maxcmd) {
291 printf(": cannot create ccb#%d dmamap (%d)\n", i, error);
292 if (i == 0) {
293
294 bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
295 bus_dmamap_destroy(sc->dmat, sc->cmdmap);
296 return -1;
297 }
298 }
299
300 if ((error = bus_dmamem_alloc(sc->dmat, PAGE_SIZE, PAGE_SIZE, 0,
301 seg, 1, &rseg, BUS_DMA_NOWAIT))) {
302 printf(": cannot allocate scratch buffer (%d)\n", error);
303 return -1;
304 }
305
306 if ((error = bus_dmamem_map(sc->dmat, seg, rseg, PAGE_SIZE,
307 (caddr_t *)&sc->scratch, BUS_DMA_NOWAIT))) {
308 printf(": cannot map scratch buffer (%d)\n", error);
309 return -1;
310 }
311 bzero(sc->scratch, PAGE_SIZE);
312
313 lock = CISS_LOCK_SCRATCH(sc);
314 inq = sc->scratch;
315 if (ciss_inq(sc, inq)) {
316 printf(": adapter inquiry failed\n");
317 CISS_UNLOCK_SCRATCH(sc, lock);
318 bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
319 bus_dmamap_destroy(sc->dmat, sc->cmdmap);
320 return -1;
321 }
322
323 if (!(inq->flags & CISS_INQ_BIGMAP)) {
324 printf(": big map is not supported, flags=%b\n",
325 inq->flags, CISS_INQ_BITS);
326 CISS_UNLOCK_SCRATCH(sc, lock);
327 bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
328 bus_dmamap_destroy(sc->dmat, sc->cmdmap);
329 return -1;
330 }
331
332 sc->maxunits = inq->numld;
333 sc->nbus = inq->nscsi_bus;
334 sc->ndrives = inq->buswidth;
335 printf(": %d LD%s, HW rev %d, FW %4.4s/%4.4s\n",
336 inq->numld, inq->numld == 1? "" : "s",
337 inq->hw_rev, inq->fw_running, inq->fw_stored);
338
339 CISS_UNLOCK_SCRATCH(sc, lock);
340
341 timeout_set(&sc->sc_hb, ciss_heartbeat, sc);
342 timeout_add(&sc->sc_hb, hz * 3);
343
344
345 if (ciss_ldmap(sc)) {
346 printf("%s: adapter LD map failed\n", sc->sc_dev.dv_xname);
347 bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
348 bus_dmamap_destroy(sc->dmat, sc->cmdmap);
349 return -1;
350 }
351
352 if (!(sc->sc_lds = malloc(sc->maxunits * sizeof(*sc->sc_lds),
353 M_DEVBUF, M_NOWAIT))) {
354 bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
355 bus_dmamap_destroy(sc->dmat, sc->cmdmap);
356 return -1;
357 }
358 bzero(sc->sc_lds, sc->maxunits * sizeof(*sc->sc_lds));
359
360 sc->sc_flush = CISS_FLUSH_ENABLE;
361 if (!(sc->sc_sh = shutdownhook_establish(ciss_shutdown, sc))) {
362 printf(": unable to establish shutdown hook\n");
363 bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
364 bus_dmamap_destroy(sc->dmat, sc->cmdmap);
365 return -1;
366 }
367
368 #if 0
369 if (kthread_create(ciss_kthread, sc, NULL, "%s", sc->sc_dev.dv_xname)) {
370 printf(": unable to create kernel thread\n");
371 shutdownhook_disestablish(sc->sc_sh);
372 bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
373 bus_dmamap_destroy(sc->dmat, sc->cmdmap);
374 return -1;
375 }
376 #endif
377
378 sc->sc_link.device = &ciss_dev;
379 sc->sc_link.adapter_softc = sc;
380 sc->sc_link.openings = sc->maxcmd / (sc->maxunits? sc->maxunits : 1);
381 #if NBIO > 0
382
383 if (sc->maxunits < 2 && sc->sc_link.openings > 2)
384 sc->sc_link.openings -= 2;
385 #endif
386 sc->sc_link.adapter = &ciss_switch;
387 sc->sc_link.adapter_target = sc->maxunits;
388 sc->sc_link.adapter_buswidth = sc->maxunits;
389 bzero(&saa, sizeof(saa));
390 saa.saa_sc_link = &sc->sc_link;
391 scsibus = (struct scsibus_softc *)config_found_sm(&sc->sc_dev,
392 &saa, scsiprint, NULL);
393
394 #if 0
395 sc->sc_link_raw.device = &ciss_raw_dev;
396 sc->sc_link_raw.adapter_softc = sc;
397 sc->sc_link.openings = sc->maxcmd / (sc->maxunits? sc->maxunits : 1);
398 sc->sc_link_raw.adapter = &ciss_raw_switch;
399 sc->sc_link_raw.adapter_target = sc->ndrives;
400 sc->sc_link_raw.adapter_buswidth = sc->ndrives;
401 bzero(&saa, sizeof(saa));
402 saa.saa_sc_link = &sc->sc_link_raw;
403 rawbus = (struct scsibus_softc *)config_found_sm(&sc->sc_dev,
404 &saa, scsiprint, NULL);
405 #endif
406
407 #if NBIO > 0
408
409 if (!scsibus || sc->maxunits > 1 || sc->sc_link.openings == sc->maxcmd)
410 return 0;
411
412
413
414 for (i = 0; i < sc->maxunits; i++)
415 if (!(sc->sc_lds[i] = ciss_pdscan(sc, i)))
416 return 0;
417
418 if (bio_register(&sc->sc_dev, ciss_ioctl) != 0)
419 printf("%s: controller registration failed",
420 sc->sc_dev.dv_xname);
421
422 sc->sc_flags |= CISS_BIO;
423 #ifndef SMALL_KERNEL
424 sc->sensors = malloc(sizeof(struct ksensor) * sc->maxunits,
425 M_DEVBUF, M_NOWAIT);
426 if (sc->sensors) {
427 bzero(sc->sensors, sizeof(struct ksensor) * sc->maxunits);
428 strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
429 sizeof(sc->sensordev.xname));
430 for (i = 0; i < sc->maxunits;
431 sensor_attach(&sc->sensordev, &sc->sensors[i++])) {
432 sc->sensors[i].type = SENSOR_DRIVE;
433 sc->sensors[i].status = SENSOR_S_UNKNOWN;
434 strlcpy(sc->sensors[i].desc, ((struct device *)
435 scsibus->sc_link[i][0]->device_softc)->dv_xname,
436 sizeof(sc->sensors[i].desc));
437 strlcpy(sc->sc_lds[i]->xname, ((struct device *)
438 scsibus->sc_link[i][0]->device_softc)->dv_xname,
439 sizeof(sc->sc_lds[i]->xname));
440 }
441 if (sensor_task_register(sc, ciss_sensors, 10) == NULL)
442 free(sc->sensors, M_DEVBUF);
443 else
444 sensordev_install(&sc->sensordev);
445 }
446 #endif
447 #endif
448
449 return 0;
450 }
451
452 void
453 ciss_shutdown(void *v)
454 {
455 struct ciss_softc *sc = v;
456
457 sc->sc_flush = CISS_FLUSH_DISABLE;
458 timeout_del(&sc->sc_hb);
459 ciss_sync(sc);
460 }
461
462 void
463 cissminphys(struct buf *bp)
464 {
465 #if 0
466 #define CISS_MAXFER (PAGE_SIZE * (sc->maxsg + 1))
467 if (bp->b_bcount > CISS_MAXFER)
468 bp->b_bcount = CISS_MAXFER;
469 #endif
470 minphys(bp);
471 }
472
473
474
475
476
477
478
479 int
480 ciss_cmd(struct ciss_ccb *ccb, int flags, int wait)
481 {
482 struct ciss_softc *sc = ccb->ccb_sc;
483 struct ciss_cmd *cmd = &ccb->ccb_cmd;
484 struct ciss_ccb *ccb1;
485 bus_dmamap_t dmap = ccb->ccb_dmamap;
486 u_int32_t id;
487 int i, tohz, error = 0;
488
489 if (ccb->ccb_state != CISS_CCB_READY) {
490 printf("%s: ccb %d not ready state=%b\n", sc->sc_dev.dv_xname,
491 cmd->id, ccb->ccb_state, CISS_CCB_BITS);
492 return (EINVAL);
493 }
494
495 if (ccb->ccb_data) {
496 bus_dma_segment_t *sgd;
497
498 if ((error = bus_dmamap_load(sc->dmat, dmap, ccb->ccb_data,
499 ccb->ccb_len, NULL, flags))) {
500 if (error == EFBIG)
501 printf("more than %d dma segs\n", sc->maxsg);
502 else
503 printf("error %d loading dma map\n", error);
504 ciss_put_ccb(ccb);
505 return (error);
506 }
507 cmd->sgin = dmap->dm_nsegs;
508
509 sgd = dmap->dm_segs;
510 CISS_DPRINTF(CISS_D_DMA, ("data=%p/%u<0x%lx/%u",
511 ccb->ccb_data, ccb->ccb_len, sgd->ds_addr, sgd->ds_len));
512
513 for (i = 0; i < dmap->dm_nsegs; sgd++, i++) {
514 cmd->sgl[i].addr_lo = htole32(sgd->ds_addr);
515 cmd->sgl[i].addr_hi =
516 htole32((u_int64_t)sgd->ds_addr >> 32);
517 cmd->sgl[i].len = htole32(sgd->ds_len);
518 cmd->sgl[i].flags = htole32(0);
519 if (i)
520 CISS_DPRINTF(CISS_D_DMA,
521 (",0x%lx/%u", sgd->ds_addr, sgd->ds_len));
522 }
523
524 CISS_DPRINTF(CISS_D_DMA, ("> "));
525
526 bus_dmamap_sync(sc->dmat, dmap, 0, dmap->dm_mapsize,
527 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
528 } else
529 cmd->sgin = 0;
530 cmd->sglen = htole16((u_int16_t)cmd->sgin);
531 bzero(&ccb->ccb_err, sizeof(ccb->ccb_err));
532
533 bus_dmamap_sync(sc->dmat, sc->cmdmap, 0, sc->cmdmap->dm_mapsize,
534 BUS_DMASYNC_PREWRITE);
535
536 if ((wait & (SCSI_POLL|SCSI_NOSLEEP)) == (SCSI_POLL|SCSI_NOSLEEP))
537 bus_space_write_4(sc->iot, sc->ioh, CISS_IMR,
538 bus_space_read_4(sc->iot, sc->ioh, CISS_IMR) | sc->iem);
539
540 TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link);
541 ccb->ccb_state = CISS_CCB_ONQ;
542 CISS_DPRINTF(CISS_D_CMD, ("submit=0x%x ", cmd->id));
543 bus_space_write_4(sc->iot, sc->ioh, CISS_INQ, ccb->ccb_cmdpa);
544
545 if (wait & SCSI_POLL) {
546 struct timeval tv;
547 int etick;
548 CISS_DPRINTF(CISS_D_CMD, ("waiting "));
549
550 i = ccb->ccb_xs? ccb->ccb_xs->timeout : 60000;
551 tv.tv_sec = i / 1000;
552 tv.tv_usec = (i % 1000) * 1000;
553 tohz = tvtohz(&tv);
554 if (tohz == 0)
555 tohz = 1;
556 for (i *= 100, etick = tick + tohz; i--; ) {
557 if (!(wait & SCSI_NOSLEEP)) {
558 ccb->ccb_state = CISS_CCB_POLL;
559 CISS_DPRINTF(CISS_D_CMD, ("tsleep(%d) ", tohz));
560 if (tsleep(ccb, PRIBIO + 1, "ciss_cmd",
561 tohz) == EWOULDBLOCK) {
562 break;
563 }
564 if (ccb->ccb_state != CISS_CCB_ONQ) {
565 tohz = etick - tick;
566 if (tohz <= 0)
567 break;
568 CISS_DPRINTF(CISS_D_CMD, ("T"));
569 continue;
570 }
571 ccb1 = ccb;
572 } else {
573 DELAY(10);
574
575 if (!(bus_space_read_4(sc->iot, sc->ioh,
576 CISS_ISR) & sc->iem)) {
577 CISS_DPRINTF(CISS_D_CMD, ("N"));
578 continue;
579 }
580
581 if ((id = bus_space_read_4(sc->iot, sc->ioh,
582 CISS_OUTQ)) == 0xffffffff) {
583 CISS_DPRINTF(CISS_D_CMD, ("Q"));
584 continue;
585 }
586
587 CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id));
588 ccb1 = sc->ccbs + (id >> 2) * sc->ccblen;
589 ccb1->ccb_cmd.id = htole32(id);
590 }
591
592 error = ciss_done(ccb1);
593 if (ccb1 == ccb)
594 break;
595 }
596
597
598 if (ccb->ccb_state != CISS_CCB_FREE) {
599 ccb->ccb_err.cmd_stat = CISS_ERR_TMO;
600 error = ciss_done(ccb);
601 }
602
603 CISS_DPRINTF(CISS_D_CMD, ("done %d:%d",
604 ccb->ccb_err.cmd_stat, ccb->ccb_err.scsi_stat));
605 }
606
607 if ((wait & (SCSI_POLL|SCSI_NOSLEEP)) == (SCSI_POLL|SCSI_NOSLEEP))
608 bus_space_write_4(sc->iot, sc->ioh, CISS_IMR,
609 bus_space_read_4(sc->iot, sc->ioh, CISS_IMR) & ~sc->iem);
610
611 return (error);
612 }
613
614 int
615 ciss_done(struct ciss_ccb *ccb)
616 {
617 struct ciss_softc *sc = ccb->ccb_sc;
618 struct scsi_xfer *xs = ccb->ccb_xs;
619 ciss_lock_t lock;
620 int error = 0;
621
622 CISS_DPRINTF(CISS_D_CMD, ("ciss_done(%p) ", ccb));
623
624 if (ccb->ccb_state != CISS_CCB_ONQ) {
625 printf("%s: unqueued ccb %p ready, state=%b\n",
626 sc->sc_dev.dv_xname, ccb, ccb->ccb_state, CISS_CCB_BITS);
627 return 1;
628 }
629
630 lock = CISS_LOCK(sc);
631 ccb->ccb_state = CISS_CCB_READY;
632 TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link);
633
634 if (ccb->ccb_cmd.id & CISS_CMD_ERR)
635 error = ciss_error(ccb);
636
637 if (ccb->ccb_data) {
638 bus_dmamap_sync(sc->dmat, ccb->ccb_dmamap, 0,
639 ccb->ccb_dmamap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ?
640 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
641 bus_dmamap_unload(sc->dmat, ccb->ccb_dmamap);
642 ccb->ccb_xs = NULL;
643 ccb->ccb_data = NULL;
644 }
645
646 ciss_put_ccb(ccb);
647
648 if (xs) {
649 xs->resid = 0;
650 xs->flags |= ITSDONE;
651 CISS_DPRINTF(CISS_D_CMD, ("scsi_done(%p) ", xs));
652 scsi_done(xs);
653 }
654 CISS_UNLOCK(sc, lock);
655
656 return error;
657 }
658
659 int
660 ciss_error(struct ciss_ccb *ccb)
661 {
662 struct ciss_softc *sc = ccb->ccb_sc;
663 struct ciss_error *err = &ccb->ccb_err;
664 struct scsi_xfer *xs = ccb->ccb_xs;
665 int rv;
666
667 switch ((rv = letoh16(err->cmd_stat))) {
668 case CISS_ERR_OK:
669 rv = 0;
670 break;
671
672 case CISS_ERR_INVCMD:
673 printf("%s: invalid cmd 0x%x: 0x%x is not valid @ 0x%x[%d]\n",
674 sc->sc_dev.dv_xname, ccb->ccb_cmd.id,
675 err->err_info, err->err_type[3], err->err_type[2]);
676 if (xs) {
677 bzero(&xs->sense, sizeof(xs->sense));
678 xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
679 xs->sense.flags = SKEY_ILLEGAL_REQUEST;
680 xs->sense.add_sense_code = 0x24;
681 xs->error = XS_SENSE;
682 }
683 rv = EIO;
684 break;
685
686 case CISS_ERR_TMO:
687 xs->error = XS_TIMEOUT;
688 rv = ETIMEDOUT;
689 break;
690
691 default:
692 if (xs) {
693 switch (err->scsi_stat) {
694 case SCSI_CHECK:
695 xs->error = XS_SENSE;
696 bcopy(&err->sense[0], &xs->sense,
697 sizeof(xs->sense));
698 rv = EIO;
699 break;
700
701 case SCSI_BUSY:
702 xs->error = XS_BUSY;
703 rv = EBUSY;
704 break;
705
706 default:
707 CISS_DPRINTF(CISS_D_ERR, ("%s: "
708 "cmd_stat %x scsi_stat 0x%x\n",
709 sc->sc_dev.dv_xname, rv, err->scsi_stat));
710 xs->error = XS_DRIVER_STUFFUP;
711 rv = EIO;
712 break;
713 }
714 xs->resid = letoh32(err->resid);
715 } else
716 rv = EIO;
717 }
718 ccb->ccb_cmd.id &= htole32(~3);
719
720 return rv;
721 }
722
723 int
724 ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq)
725 {
726 struct ciss_ccb *ccb;
727 struct ciss_cmd *cmd;
728
729 ccb = ciss_get_ccb(sc);
730 ccb->ccb_len = sizeof(*inq);
731 ccb->ccb_data = inq;
732 cmd = &ccb->ccb_cmd;
733 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
734 cmd->tgt2 = 0;
735 cmd->cdblen = 10;
736 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
737 cmd->tmo = htole16(0);
738 bzero(&cmd->cdb[0], sizeof(cmd->cdb));
739 cmd->cdb[0] = CISS_CMD_CTRL_GET;
740 cmd->cdb[6] = CISS_CMS_CTRL_CTRL;
741 cmd->cdb[7] = sizeof(*inq) >> 8;
742 cmd->cdb[8] = sizeof(*inq) & 0xff;
743
744 return ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL|SCSI_NOSLEEP);
745 }
746
747 int
748 ciss_ldmap(struct ciss_softc *sc)
749 {
750 struct ciss_ccb *ccb;
751 struct ciss_cmd *cmd;
752 struct ciss_ldmap *lmap;
753 ciss_lock_t lock;
754 int total, rv;
755
756 lock = CISS_LOCK_SCRATCH(sc);
757 lmap = sc->scratch;
758 lmap->size = htobe32(sc->maxunits * sizeof(lmap->map));
759 total = sizeof(*lmap) + (sc->maxunits - 1) * sizeof(lmap->map);
760
761 ccb = ciss_get_ccb(sc);
762 ccb->ccb_len = total;
763 ccb->ccb_data = lmap;
764 cmd = &ccb->ccb_cmd;
765 cmd->tgt = CISS_CMD_MODE_PERIPH;
766 cmd->tgt2 = 0;
767 cmd->cdblen = 12;
768 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
769 cmd->tmo = htole16(30);
770 bzero(&cmd->cdb[0], sizeof(cmd->cdb));
771 cmd->cdb[0] = CISS_CMD_LDMAP;
772 cmd->cdb[8] = total >> 8;
773 cmd->cdb[9] = total & 0xff;
774
775 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL|SCSI_NOSLEEP);
776 CISS_UNLOCK_SCRATCH(sc, lock);
777
778 if (rv)
779 return rv;
780
781 CISS_DPRINTF(CISS_D_MISC, ("lmap %x:%x\n",
782 lmap->map[0].tgt, lmap->map[0].tgt2));
783
784 return 0;
785 }
786
787 int
788 ciss_sync(struct ciss_softc *sc)
789 {
790 struct ciss_ccb *ccb;
791 struct ciss_cmd *cmd;
792 struct ciss_flush *flush;
793 ciss_lock_t lock;
794 int rv;
795
796 lock = CISS_LOCK_SCRATCH(sc);
797 flush = sc->scratch;
798 bzero(flush, sizeof(*flush));
799 flush->flush = sc->sc_flush;
800
801 ccb = ciss_get_ccb(sc);
802 ccb->ccb_len = sizeof(*flush);
803 ccb->ccb_data = flush;
804 cmd = &ccb->ccb_cmd;
805 cmd->tgt = CISS_CMD_MODE_PERIPH;
806 cmd->tgt2 = 0;
807 cmd->cdblen = 10;
808 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT;
809 cmd->tmo = htole16(0);
810 bzero(&cmd->cdb[0], sizeof(cmd->cdb));
811 cmd->cdb[0] = CISS_CMD_CTRL_SET;
812 cmd->cdb[6] = CISS_CMS_CTRL_FLUSH;
813 cmd->cdb[7] = sizeof(*flush) >> 8;
814 cmd->cdb[8] = sizeof(*flush) & 0xff;
815
816 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL|SCSI_NOSLEEP);
817 CISS_UNLOCK_SCRATCH(sc, lock);
818
819 return rv;
820 }
821
822 int
823 ciss_scsi_raw_cmd(struct scsi_xfer *xs)
824 {
825 struct scsi_link *link = xs->sc_link;
826 struct ciss_rawsoftc *rsc = link->adapter_softc;
827 struct ciss_softc *sc = rsc->sc_softc;
828 struct ciss_ccb *ccb;
829 struct ciss_cmd *cmd;
830 ciss_lock_t lock;
831 int error;
832
833 CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_raw_cmd "));
834
835 if (xs->cmdlen > CISS_MAX_CDB) {
836 CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs));
837 bzero(&xs->sense, sizeof(xs->sense));
838 xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
839 xs->sense.flags = SKEY_ILLEGAL_REQUEST;
840 xs->sense.add_sense_code = 0x20;
841 xs->error = XS_SENSE;
842 scsi_done(xs);
843 return (COMPLETE);
844 }
845
846 lock = CISS_LOCK(sc);
847 error = 0;
848 xs->error = XS_NOERROR;
849
850
851
852 ccb = ciss_get_ccb(sc);
853 cmd = &ccb->ccb_cmd;
854 ccb->ccb_len = xs->datalen;
855 ccb->ccb_data = xs->data;
856 ccb->ccb_xs = xs;
857
858
859
860 cmd->cdblen = xs->cmdlen;
861 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL;
862 if (xs->flags & SCSI_DATA_IN)
863 cmd->flags |= CISS_CDB_IN;
864 else if (xs->flags & SCSI_DATA_OUT)
865 cmd->flags |= CISS_CDB_OUT;
866 cmd->tmo = htole16(xs->timeout < 1000? 1 : xs->timeout / 1000);
867 bzero(&cmd->cdb[0], sizeof(cmd->cdb));
868 bcopy(xs->cmd, &cmd->cdb[0], CISS_MAX_CDB);
869
870 if (ciss_cmd(ccb, BUS_DMA_WAITOK,
871 xs->flags & (SCSI_POLL|SCSI_NOSLEEP))) {
872 xs->error = XS_DRIVER_STUFFUP;
873 scsi_done(xs);
874 CISS_UNLOCK(sc, lock);
875 return (COMPLETE);
876 }
877
878 CISS_UNLOCK(sc, lock);
879 return xs->flags & SCSI_POLL? COMPLETE : SUCCESSFULLY_QUEUED;
880 }
881
882 int
883 ciss_scsi_cmd(struct scsi_xfer *xs)
884 {
885 struct scsi_link *link = xs->sc_link;
886 struct ciss_softc *sc = link->adapter_softc;
887 u_int8_t target = link->target;
888 struct ciss_ccb *ccb;
889 struct ciss_cmd *cmd;
890 int error;
891 ciss_lock_t lock;
892
893 CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_cmd "));
894
895 if (xs->cmdlen > CISS_MAX_CDB) {
896 CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs));
897 bzero(&xs->sense, sizeof(xs->sense));
898 xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
899 xs->sense.flags = SKEY_ILLEGAL_REQUEST;
900 xs->sense.add_sense_code = 0x20;
901 xs->error = XS_SENSE;
902 scsi_done(xs);
903 return (COMPLETE);
904 }
905
906 lock = CISS_LOCK(sc);
907 error = 0;
908 xs->error = XS_NOERROR;
909
910
911
912 ccb = ciss_get_ccb(sc);
913 cmd = &ccb->ccb_cmd;
914 ccb->ccb_len = xs->datalen;
915 ccb->ccb_data = xs->data;
916 ccb->ccb_xs = xs;
917 cmd->tgt = CISS_CMD_MODE_LD | target;
918 cmd->tgt2 = 0;
919 cmd->cdblen = xs->cmdlen;
920 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL;
921 if (xs->flags & SCSI_DATA_IN)
922 cmd->flags |= CISS_CDB_IN;
923 else if (xs->flags & SCSI_DATA_OUT)
924 cmd->flags |= CISS_CDB_OUT;
925 cmd->tmo = htole16(xs->timeout < 1000? 1 : xs->timeout / 1000);
926 bzero(&cmd->cdb[0], sizeof(cmd->cdb));
927 bcopy(xs->cmd, &cmd->cdb[0], CISS_MAX_CDB);
928
929 if (ciss_cmd(ccb, BUS_DMA_WAITOK,
930 xs->flags & (SCSI_POLL|SCSI_NOSLEEP))) {
931 xs->error = XS_DRIVER_STUFFUP;
932 scsi_done(xs);
933 CISS_UNLOCK(sc, lock);
934 return (COMPLETE);
935 }
936
937 CISS_UNLOCK(sc, lock);
938 return xs->flags & SCSI_POLL? COMPLETE : SUCCESSFULLY_QUEUED;
939 }
940
941 int
942 ciss_intr(void *v)
943 {
944 struct ciss_softc *sc = v;
945 struct ciss_ccb *ccb;
946 ciss_lock_t lock;
947 u_int32_t id;
948 int hit = 0;
949
950 CISS_DPRINTF(CISS_D_INTR, ("intr "));
951
952 if (!(bus_space_read_4(sc->iot, sc->ioh, CISS_ISR) & sc->iem))
953 return 0;
954
955 lock = CISS_LOCK(sc);
956 while ((id = bus_space_read_4(sc->iot, sc->ioh, CISS_OUTQ)) !=
957 0xffffffff) {
958
959 ccb = sc->ccbs + (id >> 2) * sc->ccblen;
960 ccb->ccb_cmd.id = htole32(id);
961 if (ccb->ccb_state == CISS_CCB_POLL) {
962 ccb->ccb_state = CISS_CCB_ONQ;
963 wakeup(ccb);
964 } else
965 ciss_done(ccb);
966
967 hit = 1;
968 }
969 CISS_UNLOCK(sc, lock);
970
971 CISS_DPRINTF(CISS_D_INTR, ("exit "));
972 return hit;
973 }
974
975 void
976 ciss_heartbeat(void *v)
977 {
978 struct ciss_softc *sc = v;
979 u_int32_t hb;
980
981 hb = bus_space_read_4(sc->iot, sc->cfg_ioh,
982 sc->cfgoff + offsetof(struct ciss_config, heartbeat));
983 if (hb == sc->heartbeat)
984 panic("%s: dead", sc->sc_dev.dv_xname);
985 else
986 sc->heartbeat = hb;
987
988 timeout_add(&sc->sc_hb, hz * 3);
989 }
990
991 void
992 ciss_kthread(void *v)
993 {
994 struct ciss_softc *sc = v;
995 ciss_lock_t lock;
996
997 for (;;) {
998 tsleep(sc, PRIBIO, sc->sc_dev.dv_xname, 0);
999
1000 lock = CISS_LOCK(sc);
1001
1002
1003
1004 CISS_UNLOCK(sc, lock);
1005 }
1006 }
1007
1008 int
1009 ciss_scsi_ioctl(struct scsi_link *link, u_long cmd,
1010 caddr_t addr, int flag, struct proc *p)
1011 {
1012 #if NBIO > 0
1013 return ciss_ioctl(link->adapter_softc, cmd, addr);
1014 #else
1015 return ENOTTY;
1016 #endif
1017 }
1018
1019 #if NBIO > 0
1020 const int ciss_level[] = { 0, 4, 1, 5, 51, 7 };
1021 const int ciss_stat[] = { BIOC_SVONLINE, BIOC_SVOFFLINE, BIOC_SVOFFLINE,
1022 BIOC_SVDEGRADED, BIOC_SVREBUILD, BIOC_SVREBUILD, BIOC_SVDEGRADED,
1023 BIOC_SVDEGRADED, BIOC_SVINVALID, BIOC_SVINVALID, BIOC_SVBUILDING,
1024 BIOC_SVOFFLINE, BIOC_SVBUILDING };
1025
1026 int
1027 ciss_ioctl(struct device *dev, u_long cmd, caddr_t addr)
1028 {
1029 struct ciss_softc *sc = (struct ciss_softc *)dev;
1030 struct bioc_inq *bi;
1031 struct bioc_vol *bv;
1032 struct bioc_disk *bd;
1033 struct bioc_blink *bb;
1034
1035
1036 struct ciss_ldid *ldid;
1037 struct ciss_ldstat *ldstat;
1038 struct ciss_pdid *pdid;
1039 struct ciss_blink *blink;
1040 struct ciss_ld *ldp;
1041 ciss_lock_t lock;
1042 int ld, pd, error = 0;
1043 u_int blks;
1044
1045 if (!(sc->sc_flags & CISS_BIO))
1046 return ENOTTY;
1047
1048 lock = CISS_LOCK(sc);
1049 switch (cmd) {
1050 case BIOCINQ:
1051 bi = (struct bioc_inq *)addr;
1052 strlcpy(bi->bi_dev, sc->sc_dev.dv_xname, sizeof(bi->bi_dev));
1053 bi->bi_novol = sc->maxunits;
1054 bi->bi_nodisk = sc->ndrives;
1055 break;
1056
1057 case BIOCVOL:
1058 bv = (struct bioc_vol *)addr;
1059 if (bv->bv_volid > sc->maxunits) {
1060 error = EINVAL;
1061 break;
1062 }
1063 ldp = sc->sc_lds[bv->bv_volid];
1064 if (!ldp)
1065 return EINVAL;
1066 ldid = sc->scratch;
1067 if ((error = ciss_ldid(sc, bv->bv_volid, ldid)))
1068 break;
1069
1070 bv->bv_status = BIOC_SVINVALID;
1071 blks = (u_int)letoh16(ldid->nblocks[1]) << 16 |
1072 letoh16(ldid->nblocks[0]);
1073 bv->bv_size = blks * (u_quad_t)letoh16(ldid->blksize);
1074 bv->bv_level = ciss_level[ldid->type];
1075 bv->bv_nodisk = ldp->ndrives;
1076 strlcpy(bv->bv_dev, ldp->xname, sizeof(bv->bv_dev));
1077 strlcpy(bv->bv_vendor, "CISS", sizeof(bv->bv_vendor));
1078 ldstat = sc->scratch;
1079 bzero(ldstat, sizeof(*ldstat));
1080 if ((error = ciss_ldstat(sc, bv->bv_volid, ldstat)))
1081 break;
1082 bv->bv_percent = -1;
1083 bv->bv_seconds = 0;
1084 if (ldstat->stat < sizeof(ciss_stat)/sizeof(ciss_stat[0]))
1085 bv->bv_status = ciss_stat[ldstat->stat];
1086 if (bv->bv_status == BIOC_SVREBUILD ||
1087 bv->bv_status == BIOC_SVBUILDING)
1088 bv->bv_percent = (blks -
1089 (((u_int)ldstat->prog[3] << 24) |
1090 ((u_int)ldstat->prog[2] << 16) |
1091 ((u_int)ldstat->prog[1] << 8) |
1092 (u_int)ldstat->prog[0])) * 100ULL / blks;
1093 break;
1094
1095 case BIOCDISK:
1096 bd = (struct bioc_disk *)addr;
1097 if (bd->bd_volid > sc->maxunits) {
1098 error = EINVAL;
1099 break;
1100 }
1101 ldp = sc->sc_lds[bd->bd_volid];
1102 if (!ldp || (pd = bd->bd_diskid) > ldp->ndrives) {
1103 error = EINVAL;
1104 break;
1105 }
1106 ldstat = sc->scratch;
1107 if ((error = ciss_ldstat(sc, bd->bd_volid, ldstat)))
1108 break;
1109 bd->bd_status = -1;
1110 if (ldstat->bigrebuild == ldp->tgts[pd])
1111 bd->bd_status = BIOC_SDREBUILD;
1112 if (ciss_bitset(ldp->tgts[pd] & (~CISS_BIGBIT),
1113 ldstat->bigfailed)) {
1114 bd->bd_status = BIOC_SDFAILED;
1115 bd->bd_size = 0;
1116 bd->bd_channel = (ldp->tgts[pd] & (~CISS_BIGBIT)) /
1117 sc->ndrives;
1118 bd->bd_target = ldp->tgts[pd] % sc->ndrives;
1119 bd->bd_lun = 0;
1120 bd->bd_vendor[0] = '\0';
1121 bd->bd_serial[0] = '\0';
1122 bd->bd_procdev[0] = '\0';
1123 } else {
1124 pdid = sc->scratch;
1125 if ((error = ciss_pdid(sc, ldp->tgts[pd], pdid,
1126 SCSI_POLL)))
1127 break;
1128 if (bd->bd_status < 0) {
1129 if (pdid->config & CISS_PD_SPARE)
1130 bd->bd_status = BIOC_SDHOTSPARE;
1131 else if (pdid->present & CISS_PD_PRESENT)
1132 bd->bd_status = BIOC_SDONLINE;
1133 else
1134 bd->bd_status = BIOC_SDINVALID;
1135 }
1136 bd->bd_size = (u_int64_t)letoh32(pdid->nblocks) *
1137 letoh16(pdid->blksz);
1138 bd->bd_channel = pdid->bus;
1139 bd->bd_target = pdid->target;
1140 bd->bd_lun = 0;
1141 strlcpy(bd->bd_vendor, pdid->model,
1142 sizeof(bd->bd_vendor));
1143 strlcpy(bd->bd_serial, pdid->serial,
1144 sizeof(bd->bd_serial));
1145 bd->bd_procdev[0] = '\0';
1146 }
1147 break;
1148
1149 case BIOCBLINK:
1150 bb = (struct bioc_blink *)addr;
1151 blink = sc->scratch;
1152 error = EINVAL;
1153
1154 for (ld = 0; ld < sc->maxunits; ld++) {
1155 ldp = sc->sc_lds[ld];
1156 if (!ldp)
1157 continue;
1158 for (pd = 0; pd < ldp->ndrives; pd++)
1159 if (ldp->tgts[pd] == (CISS_BIGBIT +
1160 bb->bb_channel * sc->ndrives +
1161 bb->bb_target))
1162 error = ciss_blink(sc, ld, pd,
1163 bb->bb_status, blink);
1164 }
1165 break;
1166
1167 case BIOCALARM:
1168 case BIOCSETSTATE:
1169 default:
1170 CISS_DPRINTF(CISS_D_IOCTL, ("%s: invalid ioctl\n",
1171 sc->sc_dev.dv_xname));
1172 error = ENOTTY;
1173 }
1174 CISS_UNLOCK(sc, lock);
1175
1176 return error;
1177 }
1178
1179 #ifndef SMALL_KERNEL
1180 void
1181 ciss_sensors(void *v)
1182 {
1183 struct ciss_softc *sc = v;
1184 struct ciss_ldstat *ldstat;
1185 int i, error;
1186
1187 for (i = 0; i < sc->maxunits; i++) {
1188 ldstat = sc->scratch;
1189 if ((error = ciss_ldstat(sc, i, ldstat))) {
1190 sc->sensors[i].value = 0;
1191 sc->sensors[i].status = SENSOR_S_UNKNOWN;
1192 continue;
1193 }
1194
1195 switch (ldstat->stat) {
1196 case CISS_LD_OK:
1197 sc->sensors[i].value = SENSOR_DRIVE_ONLINE;
1198 sc->sensors[i].status = SENSOR_S_OK;
1199 break;
1200
1201 case CISS_LD_DEGRAD:
1202 sc->sensors[i].value = SENSOR_DRIVE_PFAIL;
1203 sc->sensors[i].status = SENSOR_S_WARN;
1204 break;
1205
1206 case CISS_LD_EXPND:
1207 case CISS_LD_QEXPND:
1208 case CISS_LD_RBLDRD:
1209 case CISS_LD_REBLD:
1210 sc->sensors[i].value = SENSOR_DRIVE_REBUILD;
1211 sc->sensors[i].status = SENSOR_S_WARN;
1212 break;
1213
1214 case CISS_LD_NORDY:
1215 case CISS_LD_PDINV:
1216 case CISS_LD_PDUNC:
1217 case CISS_LD_FAILED:
1218 case CISS_LD_UNCONF:
1219 sc->sensors[i].value = SENSOR_DRIVE_FAIL;
1220 sc->sensors[i].status = SENSOR_S_CRIT;
1221 break;
1222
1223 default:
1224 sc->sensors[i].value = 0;
1225 sc->sensors[i].status = SENSOR_S_UNKNOWN;
1226 }
1227 }
1228 }
1229 #endif
1230
1231 int
1232 ciss_ldid(struct ciss_softc *sc, int target, struct ciss_ldid *id)
1233 {
1234 struct ciss_ccb *ccb;
1235 struct ciss_cmd *cmd;
1236
1237 ccb = ciss_get_ccb(sc);
1238 if (ccb == NULL)
1239 return ENOMEM;
1240 ccb->ccb_len = sizeof(*id);
1241 ccb->ccb_data = id;
1242 ccb->ccb_xs = NULL;
1243 cmd = &ccb->ccb_cmd;
1244 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
1245 cmd->tgt2 = 0;
1246 cmd->cdblen = 10;
1247 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
1248 cmd->tmo = htole16(0);
1249 bzero(&cmd->cdb[0], sizeof(cmd->cdb));
1250 cmd->cdb[0] = CISS_CMD_CTRL_GET;
1251 cmd->cdb[5] = target;
1252 cmd->cdb[6] = CISS_CMS_CTRL_LDIDEXT;
1253 cmd->cdb[7] = sizeof(*id) >> 8;
1254 cmd->cdb[8] = sizeof(*id) & 0xff;
1255
1256 return ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL);
1257 }
1258
1259 int
1260 ciss_ldstat(struct ciss_softc *sc, int target, struct ciss_ldstat *stat)
1261 {
1262 struct ciss_ccb *ccb;
1263 struct ciss_cmd *cmd;
1264
1265 ccb = ciss_get_ccb(sc);
1266 if (ccb == NULL)
1267 return ENOMEM;
1268 ccb->ccb_len = sizeof(*stat);
1269 ccb->ccb_data = stat;
1270 ccb->ccb_xs = NULL;
1271 cmd = &ccb->ccb_cmd;
1272 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
1273 cmd->tgt2 = 0;
1274 cmd->cdblen = 10;
1275 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
1276 cmd->tmo = htole16(0);
1277 bzero(&cmd->cdb[0], sizeof(cmd->cdb));
1278 cmd->cdb[0] = CISS_CMD_CTRL_GET;
1279 cmd->cdb[5] = target;
1280 cmd->cdb[6] = CISS_CMS_CTRL_LDSTAT;
1281 cmd->cdb[7] = sizeof(*stat) >> 8;
1282 cmd->cdb[8] = sizeof(*stat) & 0xff;
1283
1284 return ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL);
1285 }
1286
1287 int
1288 ciss_pdid(struct ciss_softc *sc, u_int8_t drv, struct ciss_pdid *id, int wait)
1289 {
1290 struct ciss_ccb *ccb;
1291 struct ciss_cmd *cmd;
1292
1293 ccb = ciss_get_ccb(sc);
1294 if (ccb == NULL)
1295 return ENOMEM;
1296 ccb->ccb_len = sizeof(*id);
1297 ccb->ccb_data = id;
1298 ccb->ccb_xs = NULL;
1299 cmd = &ccb->ccb_cmd;
1300 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
1301 cmd->tgt2 = 0;
1302 cmd->cdblen = 10;
1303 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
1304 cmd->tmo = htole16(0);
1305 bzero(&cmd->cdb[0], sizeof(cmd->cdb));
1306 cmd->cdb[0] = CISS_CMD_CTRL_GET;
1307 cmd->cdb[2] = drv;
1308 cmd->cdb[6] = CISS_CMS_CTRL_PDID;
1309 cmd->cdb[7] = sizeof(*id) >> 8;
1310 cmd->cdb[8] = sizeof(*id) & 0xff;
1311
1312 return ciss_cmd(ccb, BUS_DMA_NOWAIT, wait);
1313 }
1314
1315
1316 struct ciss_ld *
1317 ciss_pdscan(struct ciss_softc *sc, int ld)
1318 {
1319 struct ciss_pdid *pdid;
1320 struct ciss_ld *ldp;
1321 u_int8_t drv, buf[128];
1322 int i, j, k = 0;
1323
1324 pdid = sc->scratch;
1325 for (i = 0; i < sc->nbus; i++)
1326 for (j = 0; j < sc->ndrives; j++) {
1327 drv = CISS_BIGBIT + i * sc->ndrives + j;
1328 if (!ciss_pdid(sc, drv, pdid, SCSI_NOSLEEP|SCSI_POLL))
1329 buf[k++] = drv;
1330 }
1331
1332 if (!k)
1333 return NULL;
1334
1335 ldp = malloc(sizeof(*ldp) + (k-1), M_DEVBUF, M_NOWAIT);
1336 if (!ldp)
1337 return NULL;
1338
1339 bzero(&ldp->bling, sizeof(ldp->bling));
1340 ldp->ndrives = k;
1341 bcopy(buf, ldp->tgts, k);
1342 return ldp;
1343 }
1344
1345 int
1346 ciss_blink(struct ciss_softc *sc, int ld, int pd, int stat,
1347 struct ciss_blink *blink)
1348 {
1349 struct ciss_ccb *ccb;
1350 struct ciss_cmd *cmd;
1351 struct ciss_ld *ldp;
1352
1353 if (ld > sc->maxunits)
1354 return EINVAL;
1355
1356 ldp = sc->sc_lds[ld];
1357 if (!ldp || pd > ldp->ndrives)
1358 return EINVAL;
1359
1360 ldp->bling.pdtab[ldp->tgts[pd]] = stat == BIOC_SBUNBLINK? 0 :
1361 CISS_BLINK_ALL;
1362 bcopy(&ldp->bling, blink, sizeof(*blink));
1363
1364 ccb = ciss_get_ccb(sc);
1365 if (ccb == NULL)
1366 return ENOMEM;
1367 ccb->ccb_len = sizeof(*blink);
1368 ccb->ccb_data = blink;
1369 ccb->ccb_xs = NULL;
1370 cmd = &ccb->ccb_cmd;
1371 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
1372 cmd->tgt2 = 0;
1373 cmd->cdblen = 10;
1374 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT;
1375 cmd->tmo = htole16(0);
1376 bzero(&cmd->cdb[0], sizeof(cmd->cdb));
1377 cmd->cdb[0] = CISS_CMD_CTRL_SET;
1378 cmd->cdb[6] = CISS_CMS_CTRL_PDBLINK;
1379 cmd->cdb[7] = sizeof(*blink) >> 8;
1380 cmd->cdb[8] = sizeof(*blink) & 0xff;
1381
1382 return ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL);
1383 }
1384 #endif