This source file includes following definitions.
- twe_get_ccb
- twe_put_ccb
- twe_dispose
- twe_attach
- twe_thread_create
- twe_thread
- twe_cmd
- twe_start
- twe_complete
- twe_done
- tweminphys
- twe_copy_internal_data
- twe_scsi_cmd
- twe_intr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/buf.h>
36 #include <sys/device.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/proc.h>
40 #include <sys/kthread.h>
41
42 #include <machine/bus.h>
43
44 #include <scsi/scsi_all.h>
45 #include <scsi/scsi_disk.h>
46 #include <scsi/scsiconf.h>
47
48 #include <dev/ic/twereg.h>
49 #include <dev/ic/twevar.h>
50
51 #ifdef TWE_DEBUG
52 #define TWE_DPRINTF(m,a) if (twe_debug & (m)) printf a
53 #define TWE_D_CMD 0x0001
54 #define TWE_D_INTR 0x0002
55 #define TWE_D_MISC 0x0004
56 #define TWE_D_DMA 0x0008
57 #define TWE_D_AEN 0x0010
58 int twe_debug = 0;
59 #else
60 #define TWE_DPRINTF(m,a)
61 #endif
62
63 struct cfdriver twe_cd = {
64 NULL, "twe", DV_DULL
65 };
66
67 int twe_scsi_cmd(struct scsi_xfer *);
68
69 struct scsi_adapter twe_switch = {
70 twe_scsi_cmd, tweminphys, 0, 0,
71 };
72
73 struct scsi_device twe_dev = {
74 NULL, NULL, NULL, NULL
75 };
76
77 static __inline struct twe_ccb *twe_get_ccb(struct twe_softc *sc);
78 static __inline void twe_put_ccb(struct twe_ccb *ccb);
79 void twe_dispose(struct twe_softc *sc);
80 int twe_cmd(struct twe_ccb *ccb, int flags, int wait);
81 int twe_start(struct twe_ccb *ccb, int wait);
82 int twe_complete(struct twe_ccb *ccb);
83 int twe_done(struct twe_softc *sc, struct twe_ccb *ccb);
84 void twe_copy_internal_data(struct scsi_xfer *xs, void *v, size_t size);
85 void twe_thread_create(void *v);
86 void twe_thread(void *v);
87
88
89 static __inline struct twe_ccb *
90 twe_get_ccb(sc)
91 struct twe_softc *sc;
92 {
93 struct twe_ccb *ccb;
94
95 ccb = TAILQ_LAST(&sc->sc_free_ccb, twe_queue_head);
96 if (ccb)
97 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ccb_link);
98 return ccb;
99 }
100
101 static __inline void
102 twe_put_ccb(ccb)
103 struct twe_ccb *ccb;
104 {
105 struct twe_softc *sc = ccb->ccb_sc;
106
107 ccb->ccb_state = TWE_CCB_FREE;
108 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
109 }
110
111 void
112 twe_dispose(sc)
113 struct twe_softc *sc;
114 {
115 register struct twe_ccb *ccb;
116 if (sc->sc_cmdmap != NULL) {
117 bus_dmamap_destroy(sc->dmat, sc->sc_cmdmap);
118
119 for (ccb = &sc->sc_ccbs[TWE_MAXCMDS - 1]; ccb >= sc->sc_ccbs; ccb--)
120 if (ccb->ccb_dmamap)
121 bus_dmamap_destroy(sc->dmat, ccb->ccb_dmamap);
122 }
123 bus_dmamem_unmap(sc->dmat, sc->sc_cmds,
124 sizeof(struct twe_cmd) * TWE_MAXCMDS);
125 bus_dmamem_free(sc->dmat, sc->sc_cmdseg, 1);
126 }
127
128 int
129 twe_attach(sc)
130 struct twe_softc *sc;
131 {
132 struct scsibus_attach_args saa;
133
134 u_int8_t param_buf[2 * TWE_SECTOR_SIZE + TWE_ALIGN - 1];
135 struct twe_param *pb = (void *)
136 (((u_long)param_buf + TWE_ALIGN - 1) & ~(TWE_ALIGN - 1));
137 struct twe_param *cap = (void *)((u_int8_t *)pb + TWE_SECTOR_SIZE);
138 struct twe_ccb *ccb;
139 struct twe_cmd *cmd;
140 u_int32_t status;
141 int error, i, retry, nunits, nseg;
142 const char *errstr;
143 twe_lock_t lock;
144 paddr_t pa;
145
146 error = bus_dmamem_alloc(sc->dmat, sizeof(struct twe_cmd) * TWE_MAXCMDS,
147 PAGE_SIZE, 0, sc->sc_cmdseg, 1, &nseg, BUS_DMA_NOWAIT);
148 if (error) {
149 printf(": cannot allocate commands (%d)\n", error);
150 return (1);
151 }
152
153 error = bus_dmamem_map(sc->dmat, sc->sc_cmdseg, nseg,
154 sizeof(struct twe_cmd) * TWE_MAXCMDS,
155 (caddr_t *)&sc->sc_cmds, BUS_DMA_NOWAIT);
156 if (error) {
157 printf(": cannot map commands (%d)\n", error);
158 bus_dmamem_free(sc->dmat, sc->sc_cmdseg, 1);
159 return (1);
160 }
161
162 error = bus_dmamap_create(sc->dmat,
163 sizeof(struct twe_cmd) * TWE_MAXCMDS, TWE_MAXCMDS,
164 sizeof(struct twe_cmd) * TWE_MAXCMDS, 0,
165 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_cmdmap);
166 if (error) {
167 printf(": cannot create ccb cmd dmamap (%d)\n", error);
168 twe_dispose(sc);
169 return (1);
170 }
171 error = bus_dmamap_load(sc->dmat, sc->sc_cmdmap, sc->sc_cmds,
172 sizeof(struct twe_cmd) * TWE_MAXCMDS, NULL, BUS_DMA_NOWAIT);
173 if (error) {
174 printf(": cannot load command dma map (%d)\n", error);
175 twe_dispose(sc);
176 return (1);
177 }
178
179 TAILQ_INIT(&sc->sc_ccb2q);
180 TAILQ_INIT(&sc->sc_ccbq);
181 TAILQ_INIT(&sc->sc_free_ccb);
182 TAILQ_INIT(&sc->sc_done_ccb);
183
184 lockinit(&sc->sc_lock, PWAIT, "twelk", 0, 0);
185
186 pa = sc->sc_cmdmap->dm_segs[0].ds_addr +
187 sizeof(struct twe_cmd) * (TWE_MAXCMDS - 1);
188 for (cmd = (struct twe_cmd *)sc->sc_cmds + TWE_MAXCMDS - 1;
189 cmd >= (struct twe_cmd *)sc->sc_cmds; cmd--, pa -= sizeof(*cmd)) {
190
191 cmd->cmd_index = cmd - (struct twe_cmd *)sc->sc_cmds;
192 ccb = &sc->sc_ccbs[cmd->cmd_index];
193 error = bus_dmamap_create(sc->dmat,
194 TWE_MAXFER, TWE_MAXOFFSETS, TWE_MAXFER, 0,
195 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap);
196 if (error) {
197 printf(": cannot create ccb dmamap (%d)\n", error);
198 twe_dispose(sc);
199 return (1);
200 }
201 ccb->ccb_sc = sc;
202 ccb->ccb_cmd = cmd;
203 ccb->ccb_cmdpa = pa;
204 ccb->ccb_state = TWE_CCB_FREE;
205 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
206 }
207
208 for (errstr = NULL, retry = 3; retry--; ) {
209 int veseen_srst;
210 u_int16_t aen;
211
212 if (errstr)
213 TWE_DPRINTF(TWE_D_MISC, ("%s ", errstr));
214
215 for (i = 350000; i--; DELAY(100)) {
216 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
217 if (status & TWE_STAT_CPURDY)
218 break;
219 }
220
221 if (!(status & TWE_STAT_CPURDY)) {
222 errstr = ": card CPU is not ready\n";
223 continue;
224 }
225
226
227 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
228 TWE_CTRL_SRST |
229 TWE_CTRL_CHOSTI | TWE_CTRL_CATTNI | TWE_CTRL_CERR |
230 TWE_CTRL_MCMDI | TWE_CTRL_MRDYI |
231 TWE_CTRL_MINT);
232
233 for (i = 350000; i--; DELAY(100)) {
234 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
235 if (status & TWE_STAT_ATTNI)
236 break;
237 }
238
239 if (!(status & TWE_STAT_ATTNI)) {
240 errstr = ": cannot get card's attention\n";
241 continue;
242 }
243
244
245 for (veseen_srst = 0, aen = -1; aen != TWE_AEN_QEMPTY; ) {
246
247 if ((ccb = twe_get_ccb(sc)) == NULL) {
248 errstr = ": out of ccbs\n";
249 continue;
250 }
251
252 ccb->ccb_xs = NULL;
253 ccb->ccb_data = pb;
254 ccb->ccb_length = TWE_SECTOR_SIZE;
255 ccb->ccb_state = TWE_CCB_READY;
256 cmd = ccb->ccb_cmd;
257 cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
258 cmd->cmd_op = TWE_CMD_GPARAM;
259 cmd->cmd_param.count = 1;
260
261 pb->table_id = TWE_PARAM_AEN;
262 pb->param_id = 2;
263 pb->param_size = 2;
264
265 if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {
266 errstr = ": error draining attention queue\n";
267 break;
268 }
269 aen = *(u_int16_t *)pb->data;
270 TWE_DPRINTF(TWE_D_AEN, ("aen=%x ", aen));
271 if (aen == TWE_AEN_SRST)
272 veseen_srst++;
273 }
274
275 if (!veseen_srst) {
276 errstr = ": we don't get it\n";
277 continue;
278 }
279
280 if (status & TWE_STAT_CPUERR) {
281 errstr = ": card CPU error detected\n";
282 continue;
283 }
284
285 if (status & TWE_STAT_PCIPAR) {
286 errstr = ": PCI parity error detected\n";
287 continue;
288 }
289
290 if (status & TWE_STAT_QUEUEE ) {
291 errstr = ": queuing error detected\n";
292 continue;
293 }
294
295 if (status & TWE_STAT_PCIABR) {
296 errstr = ": PCI abort\n";
297 continue;
298 }
299
300 while (!(status & TWE_STAT_RQE)) {
301 bus_space_read_4(sc->iot, sc->ioh, TWE_READYQUEUE);
302 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
303 }
304
305 break;
306 }
307
308 if (retry < 0) {
309 printf(errstr);
310 twe_dispose(sc);
311 return 1;
312 }
313
314 if ((ccb = twe_get_ccb(sc)) == NULL) {
315 printf(": out of ccbs\n");
316 twe_dispose(sc);
317 return 1;
318 }
319
320 ccb->ccb_xs = NULL;
321 ccb->ccb_data = pb;
322 ccb->ccb_length = TWE_SECTOR_SIZE;
323 ccb->ccb_state = TWE_CCB_READY;
324 cmd = ccb->ccb_cmd;
325 cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
326 cmd->cmd_op = TWE_CMD_GPARAM;
327 cmd->cmd_param.count = 1;
328
329 pb->table_id = TWE_PARAM_UC;
330 pb->param_id = TWE_PARAM_UC;
331 pb->param_size = TWE_MAX_UNITS;
332 if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {
333 printf(": failed to fetch unit parameters\n");
334 twe_dispose(sc);
335 return 1;
336 }
337
338
339 printf(": Escalade V%d.%d\n", TWE_MAJV(status), TWE_MINV(status));
340
341 for (nunits = i = 0; i < TWE_MAX_UNITS; i++) {
342 if (pb->data[i] == 0)
343 continue;
344
345 if ((ccb = twe_get_ccb(sc)) == NULL) {
346 printf(": out of ccbs\n");
347 twe_dispose(sc);
348 return 1;
349 }
350
351 ccb->ccb_xs = NULL;
352 ccb->ccb_data = cap;
353 ccb->ccb_length = TWE_SECTOR_SIZE;
354 ccb->ccb_state = TWE_CCB_READY;
355 cmd = ccb->ccb_cmd;
356 cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
357 cmd->cmd_op = TWE_CMD_GPARAM;
358 cmd->cmd_param.count = 1;
359
360 cap->table_id = TWE_PARAM_UI + i;
361 cap->param_id = 4;
362 cap->param_size = 4;
363 lock = TWE_LOCK(sc);
364 if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {
365 TWE_UNLOCK(sc, lock);
366 printf("%s: error fetching capacity for unit %d\n",
367 sc->sc_dev.dv_xname, i);
368 continue;
369 }
370 TWE_UNLOCK(sc, lock);
371
372 nunits++;
373 sc->sc_hdr[i].hd_present = 1;
374 sc->sc_hdr[i].hd_devtype = 0;
375 sc->sc_hdr[i].hd_size = letoh32(*(u_int32_t *)cap->data);
376 TWE_DPRINTF(TWE_D_MISC, ("twed%d: size=%d\n",
377 i, sc->sc_hdr[i].hd_size));
378 }
379
380 if (!nunits)
381 nunits++;
382
383
384
385 sc->sc_link.adapter_softc = sc;
386 sc->sc_link.adapter = &twe_switch;
387 sc->sc_link.adapter_target = TWE_MAX_UNITS;
388 sc->sc_link.device = &twe_dev;
389 sc->sc_link.openings = TWE_MAXCMDS / nunits;
390 sc->sc_link.adapter_buswidth = TWE_MAX_UNITS;
391
392 bzero(&saa, sizeof(saa));
393 saa.saa_sc_link = &sc->sc_link;
394
395 config_found(&sc->sc_dev, &saa, scsiprint);
396
397 kthread_create_deferred(twe_thread_create, sc);
398
399 return (0);
400 }
401
402 void
403 twe_thread_create(void *v)
404 {
405 struct twe_softc *sc = v;
406
407 if (kthread_create(twe_thread, sc, &sc->sc_thread,
408 "%s", sc->sc_dev.dv_xname)) {
409
410 printf("%s: failed to create kernel thread, disabled\n",
411 sc->sc_dev.dv_xname);
412 return;
413 }
414
415 TWE_DPRINTF(TWE_D_CMD, ("stat=%b ",
416 bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS), TWE_STAT_BITS));
417
418
419
420
421
422 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
423 TWE_CTRL_CHOSTI | TWE_CTRL_CATTNI | TWE_CTRL_CERR);
424 TWE_DPRINTF(TWE_D_CMD, ("stat=%b ",
425 bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS), TWE_STAT_BITS));
426
427 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
428 TWE_CTRL_EINT | TWE_CTRL_ERDYI |
429 TWE_CTRL_MCMDI);
430 }
431
432 void
433 twe_thread(v)
434 void *v;
435 {
436 struct twe_softc *sc = v;
437 struct twe_ccb *ccb;
438 twe_lock_t lock;
439 u_int32_t status;
440 int err;
441
442 splbio();
443 for (;;) {
444 lock = TWE_LOCK(sc);
445
446 while (!TAILQ_EMPTY(&sc->sc_done_ccb)) {
447 ccb = TAILQ_FIRST(&sc->sc_done_ccb);
448 TAILQ_REMOVE(&sc->sc_done_ccb, ccb, ccb_link);
449 if ((err = twe_done(sc, ccb)))
450 printf("%s: done failed (%d)\n",
451 sc->sc_dev.dv_xname, err);
452 }
453
454 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
455 TWE_DPRINTF(TWE_D_INTR, ("twe_thread stat=%b ",
456 status & TWE_STAT_FLAGS, TWE_STAT_BITS));
457 while (!(status & TWE_STAT_CQF) &&
458 !TAILQ_EMPTY(&sc->sc_ccb2q)) {
459
460 ccb = TAILQ_LAST(&sc->sc_ccb2q, twe_queue_head);
461 TAILQ_REMOVE(&sc->sc_ccb2q, ccb, ccb_link);
462
463 ccb->ccb_state = TWE_CCB_QUEUED;
464 TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link);
465 bus_space_write_4(sc->iot, sc->ioh, TWE_COMMANDQUEUE,
466 ccb->ccb_cmdpa);
467
468 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
469 TWE_DPRINTF(TWE_D_INTR, ("twe_thread stat=%b ",
470 status & TWE_STAT_FLAGS, TWE_STAT_BITS));
471 }
472
473 if (!TAILQ_EMPTY(&sc->sc_ccb2q))
474 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
475 TWE_CTRL_ECMDI);
476
477 TWE_UNLOCK(sc, lock);
478 sc->sc_thread_on = 1;
479 tsleep(sc, PWAIT, "twespank", 0);
480 }
481 }
482
483 int
484 twe_cmd(ccb, flags, wait)
485 struct twe_ccb *ccb;
486 int flags, wait;
487 {
488 struct twe_softc *sc = ccb->ccb_sc;
489 bus_dmamap_t dmap;
490 struct twe_cmd *cmd;
491 struct twe_segs *sgp;
492 int error, i;
493
494 if (ccb->ccb_data && ((u_long)ccb->ccb_data & (TWE_ALIGN - 1))) {
495 TWE_DPRINTF(TWE_D_DMA, ("data=%p is unaligned ",ccb->ccb_data));
496 ccb->ccb_realdata = ccb->ccb_data;
497
498 error = bus_dmamem_alloc(sc->dmat, ccb->ccb_length, PAGE_SIZE,
499 0, ccb->ccb_2bseg, TWE_MAXOFFSETS, &ccb->ccb_2nseg,
500 BUS_DMA_NOWAIT);
501 if (error) {
502 TWE_DPRINTF(TWE_D_DMA, ("2buf alloc failed(%d) ", error));
503 twe_put_ccb(ccb);
504 return (ENOMEM);
505 }
506
507 error = bus_dmamem_map(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg,
508 ccb->ccb_length, (caddr_t *)&ccb->ccb_data, BUS_DMA_NOWAIT);
509 if (error) {
510 TWE_DPRINTF(TWE_D_DMA, ("2buf map failed(%d) ", error));
511 bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg);
512 twe_put_ccb(ccb);
513 return (ENOMEM);
514 }
515 bcopy(ccb->ccb_realdata, ccb->ccb_data, ccb->ccb_length);
516 } else
517 ccb->ccb_realdata = NULL;
518
519 dmap = ccb->ccb_dmamap;
520 cmd = ccb->ccb_cmd;
521 cmd->cmd_status = 0;
522
523 if (ccb->ccb_data) {
524 error = bus_dmamap_load(sc->dmat, dmap, ccb->ccb_data,
525 ccb->ccb_length, NULL, flags);
526 if (error) {
527 if (error == EFBIG)
528 printf("more than %d dma segs\n", TWE_MAXOFFSETS);
529 else
530 printf("error %d loading dma map\n", error);
531
532 if (ccb->ccb_realdata) {
533 bus_dmamem_unmap(sc->dmat, ccb->ccb_data,
534 ccb->ccb_length);
535 bus_dmamem_free(sc->dmat, ccb->ccb_2bseg,
536 ccb->ccb_2nseg);
537 }
538 twe_put_ccb(ccb);
539 return error;
540 }
541
542 switch (cmd->cmd_op) {
543 case TWE_CMD_GPARAM:
544 case TWE_CMD_SPARAM:
545 sgp = cmd->cmd_param.segs;
546 break;
547 case TWE_CMD_READ:
548 case TWE_CMD_WRITE:
549 sgp = cmd->cmd_io.segs;
550 break;
551 default:
552
553 TWE_DPRINTF(TWE_D_DMA, ("twe_cmd: unknown sgp op=%x\n",
554 cmd->cmd_op));
555 sgp = NULL;
556 break;
557 }
558 TWE_DPRINTF(TWE_D_DMA, ("data=%p<", ccb->ccb_data));
559 if (sgp) {
560
561
562
563
564 cmd->cmd_op += (2 * dmap->dm_nsegs) << 8;
565 bzero (sgp, TWE_MAXOFFSETS * sizeof(*sgp));
566 for (i = 0; i < dmap->dm_nsegs; i++, sgp++) {
567 sgp->twes_addr = htole32(dmap->dm_segs[i].ds_addr);
568 sgp->twes_len = htole32(dmap->dm_segs[i].ds_len);
569 TWE_DPRINTF(TWE_D_DMA, ("%x[%x] ",
570 dmap->dm_segs[i].ds_addr,
571 dmap->dm_segs[i].ds_len));
572 }
573 }
574 TWE_DPRINTF(TWE_D_DMA, ("> "));
575 bus_dmamap_sync(sc->dmat, dmap, 0, dmap->dm_mapsize,
576 BUS_DMASYNC_PREWRITE);
577 }
578 bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, sc->sc_cmdmap->dm_mapsize,
579 BUS_DMASYNC_PREWRITE);
580
581 if ((error = twe_start(ccb, wait))) {
582 bus_dmamap_unload(sc->dmat, dmap);
583 if (ccb->ccb_realdata) {
584 bus_dmamem_unmap(sc->dmat, ccb->ccb_data,
585 ccb->ccb_length);
586 bus_dmamem_free(sc->dmat, ccb->ccb_2bseg,
587 ccb->ccb_2nseg);
588 }
589 twe_put_ccb(ccb);
590 return (error);
591 }
592
593 return wait? twe_complete(ccb) : 0;
594 }
595
596 int
597 twe_start(ccb, wait)
598 struct twe_ccb *ccb;
599 int wait;
600 {
601 struct twe_softc*sc = ccb->ccb_sc;
602 struct twe_cmd *cmd = ccb->ccb_cmd;
603 u_int32_t status;
604 int i;
605
606 cmd->cmd_op = htole16(cmd->cmd_op);
607
608 if (!wait) {
609
610 TWE_DPRINTF(TWE_D_CMD, ("prequeue(%d) ", cmd->cmd_index));
611 ccb->ccb_state = TWE_CCB_PREQUEUED;
612 TAILQ_INSERT_TAIL(&sc->sc_ccb2q, ccb, ccb_link);
613 wakeup(sc);
614 return 0;
615 }
616
617 for (i = 1000; i--; DELAY(10)) {
618
619 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
620 if (!(status & TWE_STAT_CQF))
621 break;
622 TWE_DPRINTF(TWE_D_CMD, ("twe_start stat=%b ",
623 status & TWE_STAT_FLAGS, TWE_STAT_BITS));
624 }
625
626 if (!(status & TWE_STAT_CQF)) {
627 bus_space_write_4(sc->iot, sc->ioh, TWE_COMMANDQUEUE,
628 ccb->ccb_cmdpa);
629
630 TWE_DPRINTF(TWE_D_CMD, ("queue(%d) ", cmd->cmd_index));
631 ccb->ccb_state = TWE_CCB_QUEUED;
632 TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link);
633 return 0;
634
635 } else {
636
637 printf("%s: twe_start(%d) timed out\n",
638 sc->sc_dev.dv_xname, cmd->cmd_index);
639
640 return 1;
641 }
642 }
643
644 int
645 twe_complete(ccb)
646 struct twe_ccb *ccb;
647 {
648 struct twe_softc *sc = ccb->ccb_sc;
649 struct scsi_xfer *xs = ccb->ccb_xs;
650 int i;
651
652 for (i = 100 * (xs? xs->timeout : 35000); i--; DELAY(10)) {
653 u_int32_t status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
654
655
656
657
658 while (!(status & TWE_STAT_RQE)) {
659 struct twe_ccb *ccb1;
660 u_int32_t ready;
661
662 ready = bus_space_read_4(sc->iot, sc->ioh,
663 TWE_READYQUEUE);
664
665 TWE_DPRINTF(TWE_D_CMD, ("ready=%x ", ready));
666
667 ccb1 = &sc->sc_ccbs[TWE_READYID(ready)];
668 TAILQ_REMOVE(&sc->sc_ccbq, ccb1, ccb_link);
669 ccb1->ccb_state = TWE_CCB_DONE;
670 if (!twe_done(sc, ccb1) && ccb1 == ccb) {
671 TWE_DPRINTF(TWE_D_CMD, ("complete\n"));
672 return 0;
673 }
674
675 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
676
677
678 }
679 }
680
681 return 1;
682 }
683
684 int
685 twe_done(sc, ccb)
686 struct twe_softc *sc;
687 struct twe_ccb *ccb;
688 {
689 struct twe_cmd *cmd = ccb->ccb_cmd;
690 struct scsi_xfer *xs = ccb->ccb_xs;
691 bus_dmamap_t dmap;
692 twe_lock_t lock;
693
694 TWE_DPRINTF(TWE_D_CMD, ("done(%d) ", cmd->cmd_index));
695
696 if (ccb->ccb_state != TWE_CCB_DONE) {
697 printf("%s: undone ccb %d ready\n",
698 sc->sc_dev.dv_xname, cmd->cmd_index);
699 return 1;
700 }
701
702 dmap = ccb->ccb_dmamap;
703 if (xs) {
704 if (xs->cmd->opcode != PREVENT_ALLOW &&
705 xs->cmd->opcode != SYNCHRONIZE_CACHE) {
706 bus_dmamap_sync(sc->dmat, dmap, 0,
707 dmap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ?
708 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
709 bus_dmamap_unload(sc->dmat, dmap);
710 }
711 } else {
712 switch (letoh16(cmd->cmd_op)) {
713 case TWE_CMD_GPARAM:
714 case TWE_CMD_READ:
715 bus_dmamap_sync(sc->dmat, dmap, 0,
716 dmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
717 bus_dmamap_unload(sc->dmat, dmap);
718 break;
719 case TWE_CMD_SPARAM:
720 case TWE_CMD_WRITE:
721 bus_dmamap_sync(sc->dmat, dmap, 0,
722 dmap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
723 bus_dmamap_unload(sc->dmat, dmap);
724 break;
725 default:
726
727 break;
728 }
729 }
730
731 if (ccb->ccb_realdata) {
732 bcopy(ccb->ccb_data, ccb->ccb_realdata, ccb->ccb_length);
733 bus_dmamem_unmap(sc->dmat, ccb->ccb_data, ccb->ccb_length);
734 bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg);
735 }
736
737 lock = TWE_LOCK(sc);
738 twe_put_ccb(ccb);
739
740 if (xs) {
741 xs->resid = 0;
742 xs->flags |= ITSDONE;
743 scsi_done(xs);
744 }
745 TWE_UNLOCK(sc, lock);
746
747 return 0;
748 }
749
750 void
751 tweminphys(bp)
752 struct buf *bp;
753 {
754 if (bp->b_bcount > TWE_MAXFER)
755 bp->b_bcount = TWE_MAXFER;
756 minphys(bp);
757 }
758
759 void
760 twe_copy_internal_data(xs, v, size)
761 struct scsi_xfer *xs;
762 void *v;
763 size_t size;
764 {
765 size_t copy_cnt;
766
767 TWE_DPRINTF(TWE_D_MISC, ("twe_copy_internal_data "));
768
769 if (!xs->datalen)
770 printf("uio move is not yet supported\n");
771 else {
772 copy_cnt = MIN(size, xs->datalen);
773 bcopy(v, xs->data, copy_cnt);
774 }
775 }
776
777 int
778 twe_scsi_cmd(xs)
779 struct scsi_xfer *xs;
780 {
781 struct scsi_link *link = xs->sc_link;
782 struct twe_softc *sc = link->adapter_softc;
783 struct twe_ccb *ccb;
784 struct twe_cmd *cmd;
785 struct scsi_inquiry_data inq;
786 struct scsi_sense_data sd;
787 struct scsi_read_cap_data rcd;
788 u_int8_t target = link->target;
789 u_int32_t blockno, blockcnt;
790 struct scsi_rw *rw;
791 struct scsi_rw_big *rwb;
792 int error, op, flags, wait;
793 twe_lock_t lock;
794
795
796 if (target >= TWE_MAX_UNITS || !sc->sc_hdr[target].hd_present ||
797 link->lun != 0) {
798 xs->error = XS_DRIVER_STUFFUP;
799 return (COMPLETE);
800 }
801
802 TWE_DPRINTF(TWE_D_CMD, ("twe_scsi_cmd "));
803
804 xs->error = XS_NOERROR;
805
806 switch (xs->cmd->opcode) {
807 case TEST_UNIT_READY:
808 case START_STOP:
809 #if 0
810 case VERIFY:
811 #endif
812 TWE_DPRINTF(TWE_D_CMD, ("opc %d tgt %d ", xs->cmd->opcode,
813 target));
814 break;
815
816 case REQUEST_SENSE:
817 TWE_DPRINTF(TWE_D_CMD, ("REQUEST SENSE tgt %d ", target));
818 bzero(&sd, sizeof sd);
819 sd.error_code = 0x70;
820 sd.segment = 0;
821 sd.flags = SKEY_NO_SENSE;
822 *(u_int32_t*)sd.info = htole32(0);
823 sd.extra_len = 0;
824 twe_copy_internal_data(xs, &sd, sizeof sd);
825 break;
826
827 case INQUIRY:
828 TWE_DPRINTF(TWE_D_CMD, ("INQUIRY tgt %d devtype %x ", target,
829 sc->sc_hdr[target].hd_devtype));
830 bzero(&inq, sizeof inq);
831 inq.device =
832 (sc->sc_hdr[target].hd_devtype & 4) ? T_CDROM : T_DIRECT;
833 inq.dev_qual2 =
834 (sc->sc_hdr[target].hd_devtype & 1) ? SID_REMOVABLE : 0;
835 inq.version = 2;
836 inq.response_format = 2;
837 inq.additional_length = 32;
838 strlcpy(inq.vendor, "3WARE ", sizeof inq.vendor);
839 snprintf(inq.product, sizeof inq.product, "Host drive #%02d",
840 target);
841 strlcpy(inq.revision, " ", sizeof inq.revision);
842 twe_copy_internal_data(xs, &inq, sizeof inq);
843 break;
844
845 case READ_CAPACITY:
846 TWE_DPRINTF(TWE_D_CMD, ("READ CAPACITY tgt %d ", target));
847 bzero(&rcd, sizeof rcd);
848 _lto4b(sc->sc_hdr[target].hd_size - 1, rcd.addr);
849 _lto4b(TWE_SECTOR_SIZE, rcd.length);
850 twe_copy_internal_data(xs, &rcd, sizeof rcd);
851 break;
852
853 case PREVENT_ALLOW:
854 TWE_DPRINTF(TWE_D_CMD, ("PREVENT/ALLOW "));
855 return (COMPLETE);
856
857 case READ_COMMAND:
858 case READ_BIG:
859 case WRITE_COMMAND:
860 case WRITE_BIG:
861 case SYNCHRONIZE_CACHE:
862 lock = TWE_LOCK(sc);
863
864 flags = 0;
865 if (xs->cmd->opcode != SYNCHRONIZE_CACHE) {
866
867 if (xs->cmdlen == 6) {
868 rw = (struct scsi_rw *)xs->cmd;
869 blockno = _3btol(rw->addr) &
870 (SRW_TOPADDR << 16 | 0xffff);
871 blockcnt = rw->length ? rw->length : 0x100;
872 } else {
873 rwb = (struct scsi_rw_big *)xs->cmd;
874 blockno = _4btol(rwb->addr);
875 blockcnt = _2btol(rwb->length);
876
877 if (xs->cmd->opcode == WRITE_BIG &&
878 rwb->byte2 & 0x18)
879 flags = TWE_FLAGS_CACHEDISABLE;
880 }
881 if (blockno >= sc->sc_hdr[target].hd_size ||
882 blockno + blockcnt > sc->sc_hdr[target].hd_size) {
883 printf("%s: out of bounds %u-%u >= %u\n",
884 sc->sc_dev.dv_xname, blockno, blockcnt,
885 sc->sc_hdr[target].hd_size);
886 xs->error = XS_DRIVER_STUFFUP;
887 scsi_done(xs);
888 TWE_UNLOCK(sc, lock);
889 return (COMPLETE);
890 }
891 }
892
893 switch (xs->cmd->opcode) {
894 case READ_COMMAND: op = TWE_CMD_READ; break;
895 case READ_BIG: op = TWE_CMD_READ; break;
896 case WRITE_COMMAND: op = TWE_CMD_WRITE; break;
897 case WRITE_BIG: op = TWE_CMD_WRITE; break;
898 default: op = TWE_CMD_NOP; break;
899 }
900
901 if ((ccb = twe_get_ccb(sc)) == NULL) {
902 xs->error = XS_DRIVER_STUFFUP;
903 scsi_done(xs);
904 TWE_UNLOCK(sc, lock);
905 return (COMPLETE);
906 }
907
908 ccb->ccb_xs = xs;
909 ccb->ccb_data = xs->data;
910 ccb->ccb_length = xs->datalen;
911 ccb->ccb_state = TWE_CCB_READY;
912 cmd = ccb->ccb_cmd;
913 cmd->cmd_unit_host = TWE_UNITHOST(target, 0);
914 cmd->cmd_op = op;
915 cmd->cmd_flags = flags;
916 cmd->cmd_io.count = htole16(blockcnt);
917 cmd->cmd_io.lba = htole32(blockno);
918 wait = xs->flags & SCSI_POLL;
919 if (!sc->sc_thread_on)
920 wait |= SCSI_POLL;
921
922 if ((error = twe_cmd(ccb, ((xs->flags & SCSI_NOSLEEP)?
923 BUS_DMA_NOWAIT : BUS_DMA_WAITOK), wait))) {
924
925 TWE_UNLOCK(sc, lock);
926 TWE_DPRINTF(TWE_D_CMD, ("failed %p ", xs));
927 if (xs->flags & SCSI_POLL) {
928 return (TRY_AGAIN_LATER);
929 } else {
930 xs->error = XS_DRIVER_STUFFUP;
931 scsi_done(xs);
932 return (COMPLETE);
933 }
934 }
935
936 TWE_UNLOCK(sc, lock);
937
938 if (wait & SCSI_POLL)
939 return (COMPLETE);
940 else
941 return (SUCCESSFULLY_QUEUED);
942
943 default:
944 TWE_DPRINTF(TWE_D_CMD, ("unsupported scsi command %#x tgt %d ",
945 xs->cmd->opcode, target));
946 xs->error = XS_DRIVER_STUFFUP;
947 }
948
949 return (COMPLETE);
950 }
951
952 int
953 twe_intr(v)
954 void *v;
955 {
956 struct twe_softc *sc = v;
957 struct twe_ccb *ccb;
958 struct twe_cmd *cmd;
959 u_int32_t status;
960 twe_lock_t lock;
961 int rv = 0;
962
963 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
964 TWE_DPRINTF(TWE_D_INTR, ("twe_intr stat=%b ",
965 status & TWE_STAT_FLAGS, TWE_STAT_BITS));
966 #if 0
967 if (status & TWE_STAT_HOSTI) {
968
969 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
970 TWE_CTRL_CHOSTI);
971 }
972 #endif
973
974 if (status & TWE_STAT_RDYI) {
975
976 while (!(status & TWE_STAT_RQE)) {
977
978 u_int32_t ready;
979
980
981
982
983
984
985
986 ready = bus_space_read_4(sc->iot, sc->ioh,
987 TWE_READYQUEUE);
988
989 ccb = &sc->sc_ccbs[TWE_READYID(ready)];
990 TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link);
991 ccb->ccb_state = TWE_CCB_DONE;
992 TAILQ_INSERT_TAIL(&sc->sc_done_ccb, ccb, ccb_link);
993 rv++;
994
995 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
996 TWE_DPRINTF(TWE_D_INTR, ("twe_intr stat=%b ",
997 status & TWE_STAT_FLAGS, TWE_STAT_BITS));
998 }
999 }
1000
1001 if (status & TWE_STAT_CMDI) {
1002 rv++;
1003 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
1004 TWE_CTRL_MCMDI);
1005 }
1006
1007 if (rv)
1008 wakeup(sc);
1009
1010 if (status & TWE_STAT_ATTNI) {
1011 u_int16_t aen;
1012
1013
1014
1015
1016
1017
1018
1019 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
1020 TWE_CTRL_CATTNI);
1021
1022 lock = TWE_LOCK(sc);
1023 for (aen = -1; aen != TWE_AEN_QEMPTY; ) {
1024 u_int8_t param_buf[2 * TWE_SECTOR_SIZE + TWE_ALIGN - 1];
1025 struct twe_param *pb = (void *) (((u_long)param_buf +
1026 TWE_ALIGN - 1) & ~(TWE_ALIGN - 1));
1027
1028 if ((ccb = twe_get_ccb(sc)) == NULL)
1029 break;
1030
1031 ccb->ccb_xs = NULL;
1032 ccb->ccb_data = pb;
1033 ccb->ccb_length = TWE_SECTOR_SIZE;
1034 ccb->ccb_state = TWE_CCB_READY;
1035 cmd = ccb->ccb_cmd;
1036 cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
1037 cmd->cmd_op = TWE_CMD_GPARAM;
1038 cmd->cmd_flags = 0;
1039 cmd->cmd_param.count = 1;
1040
1041 pb->table_id = TWE_PARAM_AEN;
1042 pb->param_id = 2;
1043 pb->param_size = 2;
1044 if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {
1045 printf(": error draining attention queue\n");
1046 break;
1047 }
1048 aen = *(u_int16_t *)pb->data;
1049 TWE_DPRINTF(TWE_D_AEN, ("aen=%x ", aen));
1050 }
1051 TWE_UNLOCK(sc, lock);
1052 }
1053
1054 return rv;
1055 }