siop.c revision 1.6 1 /* $NetBSD: siop.c,v 1.6 2017/06/25 12:15:04 maxv Exp $ */
2 /*
3 * Copyright (c) 2010 KIYOHARA Takashi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <lib/libsa/stand.h>
29 #include <lib/libkern/libkern.h>
30
31 #include <dev/microcode/siop/siop.out>
32
33 #include "boot.h"
34 #include "sdvar.h"
35
36 #ifdef DEBUG
37 #define DPRINTF(x) printf x
38 #else
39 #define DPRINTF(x)
40 #endif
41
42 #define ALLOC(T, A) \
43 (T *)(((uint32_t)alloc(sizeof(T) + (A)) + (A)) & ~((A) - 1))
44 #define VTOPHYS(va) (uint32_t)(va)
45 #define DEVTOV(pa) (uint32_t)(pa)
46 #define wbinv(adr, siz) _wbinv(VTOPHYS(adr), (uint32_t)(siz))
47 #define inv(adr, siz) _inv(VTOPHYS(adr), (uint32_t)(siz))
48
49 /* 53c810 supports little endian */
50 #define htoc32(x) htole32(x)
51 #define ctoh32(x) le32toh(x)
52
53 static void siop_pci_reset(int);
54
55 static void siop_setuptables(struct siop_adapter *, struct siop_xfer *,
56 struct scsi_xfer *);
57 static void siop_ma(struct siop_adapter *, struct scsi_xfer *);
58 static void siop_sdp(struct siop_adapter *, struct siop_xfer *,
59 struct scsi_xfer *, int);
60 static void siop_update_resid(struct siop_adapter *, struct siop_xfer *,
61 struct scsi_xfer *, int);
62
63 static int siop_intr(struct siop_adapter *);
64 static void siop_scsicmd_end(struct siop_adapter *, struct scsi_xfer *);
65 static int siop_scsi_request(struct siop_adapter *, struct scsi_xfer *);
66 static void siop_start(struct siop_adapter *, struct scsi_xfer *);
67 static void siop_xfer_setup(struct siop_xfer *, void *);
68
69 static int siop_add_reselsw(struct siop_adapter *, int, int);
70 static void siop_update_scntl3(struct siop_adapter *, int, int);
71
72 static int _scsi_inquire(struct siop_adapter *, int, int, int, char *);
73 static void scsi_request_sense(struct siop_adapter *, struct scsi_xfer *);
74 static int scsi_interpret_sense(struct siop_adapter *, struct scsi_xfer *);
75 static int scsi_probe(struct siop_adapter *);
76
77 static struct siop_adapter adapt;
78
79
80 static void
81 siop_pci_reset(int addr)
82 {
83 int dmode, ctest5;
84 const int maxburst = 4; /* 53c810 */
85
86 dmode = readb(addr + SIOP_DMODE);
87
88 ctest5 = readb(addr + SIOP_CTEST5);
89 writeb(addr + SIOP_CTEST4, readb(addr + SIOP_CTEST4) & ~CTEST4_BDIS);
90 ctest5 &= ~CTEST5_BBCK;
91 ctest5 |= (maxburst - 1) & CTEST5_BBCK;
92 writeb(addr + SIOP_CTEST5, ctest5);
93
94 dmode |= DMODE_ERL;
95 dmode &= ~DMODE_BL_MASK;
96 dmode |= ((maxburst - 1) << DMODE_BL_SHIFT) & DMODE_BL_MASK;
97 writeb(addr + SIOP_DMODE, dmode);
98 }
99
100
101 static void
102 siop_setuptables(struct siop_adapter *adp, struct siop_xfer *xfer,
103 struct scsi_xfer *xs)
104 {
105 int msgoffset = 1;
106
107 xfer->siop_tables.id =
108 htoc32((adp->clock_div << 24) | (xs->target << 16));
109 memset(xfer->siop_tables.msg_out, 0, sizeof(xfer->siop_tables.msg_out));
110 /* request sense doesn't disconnect */
111 if (xs->cmd->opcode == SCSI_REQUEST_SENSE)
112 xfer->siop_tables.msg_out[0] = MSG_IDENTIFY(xs->lun, 0);
113 else
114 xfer->siop_tables.msg_out[0] = MSG_IDENTIFY(xs->lun, 1);
115
116 xfer->siop_tables.t_msgout.count = htoc32(msgoffset);
117 xfer->siop_tables.status =
118 htoc32(SCSI_SIOP_NOSTATUS); /* set invalid status */
119
120 xfer->siop_tables.cmd.count = htoc32(xs->cmdlen);
121 xfer->siop_tables.cmd.addr = htoc32(local_to_PCI((u_long)xs->cmd));
122 if (xs->datalen != 0) {
123 xfer->siop_tables.data[0].count = htoc32(xs->datalen);
124 xfer->siop_tables.data[0].addr =
125 htoc32(local_to_PCI((u_long)xs->data));
126 }
127 }
128
129 static void
130 siop_ma(struct siop_adapter *adp, struct scsi_xfer *xs)
131 {
132 int offset, dbc;
133
134 /*
135 * compute how much of the current table didn't get handled when
136 * a phase mismatch occurs
137 */
138 if (xs->datalen == 0)
139 return; /* no valid data transfer */
140
141 offset = readb(adp->addr + SIOP_SCRATCHA + 1);
142 if (offset >= SIOP_NSG) {
143 printf("bad offset in siop_sdp (%d)\n", offset);
144 return;
145 }
146 dbc = readl(adp->addr + SIOP_DBC) & 0x00ffffff;
147 xs->resid = dbc;
148 }
149
150 static void
151 siop_clearfifo(struct siop_adapter *adp)
152 {
153 int timo = 0;
154 uint8_t ctest3 = readb(adp->addr + SIOP_CTEST3);
155
156 DPRINTF(("DMA FIFO not empty!\n"));
157 writeb(adp->addr + SIOP_CTEST3, ctest3 | CTEST3_CLF);
158 while ((readb(adp->addr + SIOP_CTEST3) & CTEST3_CLF) != 0) {
159 delay(1);
160 if (++timo > 1000) {
161 printf("Clear FIFO failed!\n");
162 writeb(adp->addr + SIOP_CTEST3,
163 readb(adp->addr + SIOP_CTEST3) & ~CTEST3_CLF);
164 return;
165 }
166 }
167 }
168
169 static void
170 siop_sdp(struct siop_adapter *adp, struct siop_xfer *xfer, struct scsi_xfer *xs,
171 int offset)
172 {
173
174 if (xs->datalen == 0)
175 return; /* no data pointers to save */
176
177 /*
178 * offset == SIOP_NSG may be a valid condition if we get a Save data
179 * pointer when the xfer is done. Just ignore the Save data pointer
180 * in this case
181 */
182 if (offset == SIOP_NSG)
183 return;
184 /*
185 * Save data pointer. We do this by adjusting the tables to point
186 * at the begginning of the data not yet transfered.
187 * offset points to the first table with untransfered data.
188 */
189
190 /*
191 * before doing that we decrease resid from the ammount of data which
192 * has been transfered.
193 */
194 siop_update_resid(adp, xfer, xs, offset);
195
196 #if 0
197 /*
198 * First let see if we have a resid from a phase mismatch. If so,
199 * we have to adjst the table at offset to remove transfered data.
200 */
201 if (siop_cmd->flags & CMDFL_RESID) {
202 scr_table_t *table;
203
204 siop_cmd->flags &= ~CMDFL_RESID;
205 table = &xfer->siop_tables.data[offset];
206 /* "cut" already transfered data from this table */
207 table->addr =
208 htoc32(ctoh32(table->addr) + ctoh32(table->count) -
209 siop_cmd->resid);
210 table->count = htoc32(siop_cmd->resid);
211 }
212 #endif
213
214 /*
215 * now we can remove entries which have been transfered.
216 * We just move the entries with data left at the beggining of the
217 * tables
218 */
219 memmove(xfer->siop_tables.data, &xfer->siop_tables.data[offset],
220 (SIOP_NSG - offset) * sizeof(scr_table_t));
221 }
222
223 static void
224 siop_update_resid(struct siop_adapter *adp, struct siop_xfer *xfer,
225 struct scsi_xfer *xs, int offset)
226 {
227 int i;
228
229 if (xs->datalen == 0)
230 return; /* no data to transfer */
231
232 /*
233 * update resid. First account for the table entries which have
234 * been fully completed.
235 */
236 for (i = 0; i < offset; i++)
237 xs->resid -= ctoh32(xfer->siop_tables.data[i].count);
238 #if 0
239 /*
240 * if CMDFL_RESID is set, the last table (pointed by offset) is a
241 * partial transfers. If not, offset points to the entry folloing
242 * the last full transfer.
243 */
244 if (siop_cmd->flags & CMDFL_RESID) {
245 scr_table_t *table = &xfer->siop_tables.data[offset];
246
247 xs->resid -= ctoh32(table->count) - xs->resid;
248 }
249 #endif
250 }
251
252
253 #define CALL_SCRIPT(ent) writel(adp->addr + SIOP_DSP, scriptaddr + ent);
254
255 static int
256 siop_intr(struct siop_adapter *adp)
257 {
258 struct siop_xfer *siop_xfer = NULL;
259 struct scsi_xfer *xs = NULL;
260 u_long scriptaddr = local_to_PCI((u_long)adp->script);
261 int offset, target, lun, tag, restart = 0, need_reset = 0;
262 uint32_t dsa, irqcode;
263 uint16_t sist;
264 uint8_t dstat, sstat1, istat;
265
266 istat = readb(adp->addr + SIOP_ISTAT);
267 if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)
268 return 0;
269 if (istat & ISTAT_INTF) {
270 printf("INTRF\n");
271 writeb(adp->addr + SIOP_ISTAT, ISTAT_INTF);
272 }
273 if ((istat & (ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
274 (ISTAT_DIP | ISTAT_ABRT))
275 /* clear abort */
276 writeb(adp->addr + SIOP_ISTAT, 0);
277 /* use DSA to find the current siop_cmd */
278 dsa = readl(adp->addr + SIOP_DSA);
279 if (dsa >= local_to_PCI((u_long)adp->xfer) &&
280 dsa < local_to_PCI((u_long)adp->xfer) + SIOP_TABLE_SIZE) {
281 dsa -= local_to_PCI((u_long)adp->xfer);
282 siop_xfer = adp->xfer;
283 _inv((u_long)siop_xfer, sizeof(*siop_xfer));
284
285 xs = adp->xs;
286 }
287
288 if (istat & ISTAT_DIP)
289 dstat = readb(adp->addr + SIOP_DSTAT);
290 if (istat & ISTAT_SIP) {
291 if (istat & ISTAT_DIP)
292 delay(10);
293 /*
294 * Can't read sist0 & sist1 independently, or we have to
295 * insert delay
296 */
297 sist = readw(adp->addr + SIOP_SIST0);
298 sstat1 = readb(adp->addr + SIOP_SSTAT1);
299
300 if ((sist & SIST0_MA) && need_reset == 0) {
301 if (siop_xfer) {
302 int scratcha0;
303
304 dstat = readb(adp->addr + SIOP_DSTAT);
305 /*
306 * first restore DSA, in case we were in a S/G
307 * operation.
308 */
309 writel(adp->addr + SIOP_DSA,
310 local_to_PCI((u_long)siop_xfer));
311 scratcha0 = readb(adp->addr + SIOP_SCRATCHA);
312 switch (sstat1 & SSTAT1_PHASE_MASK) {
313 case SSTAT1_PHASE_STATUS:
314 /*
315 * previous phase may be aborted for any reason
316 * ( for example, the target has less data to
317 * transfer than requested). Compute resid and
318 * just go to status, the command should
319 * terminate.
320 */
321 if (scratcha0 & A_flag_data)
322 siop_ma(adp, xs);
323 else if ((dstat & DSTAT_DFE) == 0)
324 siop_clearfifo(adp);
325 CALL_SCRIPT(Ent_status);
326 return 1;
327 case SSTAT1_PHASE_MSGIN:
328 /*
329 * target may be ready to disconnect
330 * Compute resid which would be used later
331 * if a save data pointer is needed.
332 */
333 if (scratcha0 & A_flag_data)
334 siop_ma(adp, xs);
335 else if ((dstat & DSTAT_DFE) == 0)
336 siop_clearfifo(adp);
337 writeb(adp->addr + SIOP_SCRATCHA,
338 scratcha0 & ~A_flag_data);
339 CALL_SCRIPT(Ent_msgin);
340 return 1;
341 }
342 printf("unexpected phase mismatch %d\n",
343 sstat1 & SSTAT1_PHASE_MASK);
344 } else
345 printf("phase mismatch without command\n");
346 need_reset = 1;
347 }
348 if (sist & (SIST1_STO << 8)) {
349 /* selection time out, assume there's no device here */
350 if (siop_xfer) {
351 xs->error = XS_SELTIMEOUT;
352 goto end;
353 } else
354 printf("selection timeout without command\n");
355 }
356
357 /* Else it's an unhandled exception (for now). */
358 printf("unhandled scsi interrupt,"
359 " sist=0x%x sstat1=0x%x DSA=0x%x DSP=0x%lx\n",
360 sist, sstat1, dsa,
361 readl(adp->addr + SIOP_DSP) - scriptaddr);
362 if (siop_xfer) {
363 xs->error = XS_SELTIMEOUT;
364 goto end;
365 }
366 need_reset = 1;
367 }
368 if (need_reset) {
369 reset:
370 printf("XXXXX: fatal error, need reset the bus...\n");
371 return 1;
372 }
373
374 //scintr:
375 if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
376 irqcode = readl(adp->addr + SIOP_DSPS);
377 /*
378 * no command, or an inactive command is only valid for a
379 * reselect interrupt
380 */
381 if ((irqcode & 0x80) == 0) {
382 if (siop_xfer == NULL) {
383 printf(
384 "script interrupt 0x%x with invalid DSA\n",
385 irqcode);
386 goto reset;
387 }
388 }
389 switch(irqcode) {
390 case A_int_err:
391 printf("error, DSP=0x%lx\n",
392 readl(adp->addr + SIOP_DSP) - scriptaddr);
393 if (xs) {
394 xs->error = XS_SELTIMEOUT;
395 goto end;
396 } else {
397 goto reset;
398 }
399 case A_int_reseltarg:
400 printf("reselect with invalid target\n");
401 goto reset;
402 case A_int_resellun:
403 target = readb(adp->addr + SIOP_SCRATCHA) & 0xf;
404 lun = readb(adp->addr + SIOP_SCRATCHA + 1);
405 tag = readb(adp->addr + SIOP_SCRATCHA + 2);
406 if (target != adp->xs->target ||
407 lun != adp->xs->lun ||
408 tag != 0) {
409 printf("unknwon resellun:"
410 " target %d lun %d tag %d\n",
411 target, lun, tag);
412 goto reset;
413 }
414 siop_xfer = adp->xfer;
415 dsa = local_to_PCI((u_long)siop_xfer);
416 writel(adp->addr + SIOP_DSP,
417 dsa + sizeof(struct siop_common_xfer) +
418 Ent_ldsa_reload_dsa);
419 _wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
420 return 1;
421 case A_int_reseltag:
422 printf("reselect with invalid tag\n");
423 goto reset;
424 case A_int_disc:
425 offset = readb(adp->addr + SIOP_SCRATCHA + 1);
426 siop_sdp(adp, siop_xfer, xs, offset);
427 #if 0
428 /* we start again with no offset */
429 siop_cmd->saved_offset = SIOP_NOOFFSET;
430 #endif
431 _wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
432 CALL_SCRIPT(Ent_script_sched);
433 return 1;
434 case A_int_resfail:
435 printf("reselect failed\n");
436 return 1;
437 case A_int_done:
438 if (xs == NULL) {
439 printf("done without command, DSA=0x%lx\n",
440 local_to_PCI((u_long)adp->xfer));
441 return 1;
442 }
443 /* update resid. */
444 offset = readb(adp->addr + SIOP_SCRATCHA + 1);
445 #if 0
446 /*
447 * if we got a disconnect between the last data phase
448 * and the status phase, offset will be 0. In this
449 * case, siop_cmd->saved_offset will have the proper
450 * value if it got updated by the controller
451 */
452 if (offset == 0 &&
453 siop_cmd->saved_offset != SIOP_NOOFFSET)
454 offset = siop_cmd->saved_offset;
455 #endif
456 siop_update_resid(adp, siop_xfer, xs, offset);
457 goto end;
458 default:
459 printf("unknown irqcode %x\n", irqcode);
460 if (xs) {
461 xs->error = XS_SELTIMEOUT;
462 goto end;
463 }
464 goto reset;
465 }
466 return 1;
467 }
468 /* We just should't get there */
469 panic("siop_intr: I shouldn't be there !");
470
471 return 1;
472
473 end:
474 /*
475 * restart the script now if command completed properly
476 * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the
477 * queue
478 */
479 xs->status = ctoh32(siop_xfer->siop_tables.status);
480 if (xs->status == SCSI_OK)
481 writel(adp->addr + SIOP_DSP, scriptaddr + Ent_script_sched);
482 else
483 restart = 1;
484 siop_scsicmd_end(adp, xs);
485 if (restart)
486 writel(adp->addr + SIOP_DSP, scriptaddr + Ent_script_sched);
487
488 return 1;
489 }
490
491 static void
492 siop_scsicmd_end(struct siop_adapter *adp, struct scsi_xfer *xs)
493 {
494
495 switch(xs->status) {
496 case SCSI_OK:
497 xs->error = XS_NOERROR;
498 break;
499 case SCSI_BUSY:
500 case SCSI_CHECK:
501 case SCSI_QUEUE_FULL:
502 xs->error = XS_BUSY;
503 break;
504 case SCSI_SIOP_NOCHECK:
505 /*
506 * don't check status, xs->error is already valid
507 */
508 break;
509 case SCSI_SIOP_NOSTATUS:
510 /*
511 * the status byte was not updated, cmd was
512 * aborted
513 */
514 xs->error = XS_SELTIMEOUT;
515 break;
516 default:
517 printf("invalid status code %d\n", xs->status);
518 xs->error = XS_DRIVER_STUFFUP;
519 }
520 _inv((u_long)xs->cmd, xs->cmdlen);
521 if (xs->datalen != 0)
522 _inv((u_long)xs->data, xs->datalen);
523 xs->xs_status = XS_STS_DONE;
524 }
525
526 static int
527 siop_scsi_request(struct siop_adapter *adp, struct scsi_xfer *xs)
528 {
529 void *xfer = adp->xfer;
530 int timo, error;
531
532 if (adp->sel_t != xs->target) {
533 const int free_lo = __arraycount(siop_script);
534 int i;
535 void *scriptaddr = (void *)local_to_PCI((u_long)adp->script);
536
537 if (adp->sel_t != -1)
538 adp->script[Ent_resel_targ0 / 4 + adp->sel_t * 2] =
539 htoc32(0x800c00ff);
540
541 for (i = 0; i < __arraycount(lun_switch); i++)
542 adp->script[free_lo + i] = htoc32(lun_switch[i]);
543 adp->script[free_lo + E_abs_lunsw_return_Used[0]] =
544 htoc32(scriptaddr + Ent_lunsw_return);
545
546 siop_add_reselsw(adp, xs->target, free_lo);
547
548 adp->sel_t = xs->target;
549 }
550
551 restart:
552
553 siop_setuptables(adp, xfer, xs);
554
555 /* load the DMA maps */
556 if (xs->datalen != 0)
557 _inv((u_long)xs->data, xs->datalen);
558 _wbinv((u_long)xs->cmd, xs->cmdlen);
559
560 _wbinv((u_long)xfer, sizeof(struct siop_xfer));
561 siop_start(adp, xs);
562
563 adp->xs = xs;
564 timo = 0;
565 while (!(xs->xs_status & XS_STS_DONE)) {
566 delay(1000);
567 siop_intr(adp);
568
569 if (timo++ > 3000) { /* XXXX: 3sec */
570 printf("%s: timeout\n", __func__);
571 return ETIMEDOUT;
572 }
573 }
574
575 if (xs->error != XS_NOERROR) {
576 if (xs->error == XS_BUSY || xs->status == SCSI_CHECK)
577 scsi_request_sense(adp, xs);
578
579 switch (xs->error) {
580 case XS_SENSE:
581 case XS_SHORTSENSE:
582 error = scsi_interpret_sense(adp, xs);
583 break;
584 case XS_RESOURCE_SHORTAGE:
585 printf("adapter resource shortage\n");
586
587 /* FALLTHROUGH */
588 case XS_BUSY:
589 error = EBUSY;
590 break;
591 case XS_REQUEUE:
592 printf("XXXX: requeue...\n");
593 error = ERESTART;
594 break;
595 case XS_SELTIMEOUT:
596 case XS_TIMEOUT:
597 error = EIO;
598 break;
599 case XS_RESET:
600 error = EIO;
601 break;
602 case XS_DRIVER_STUFFUP:
603 printf("generic HBA error\n");
604 error = EIO;
605 break;
606 default:
607 printf("invalid return code from adapter: %d\n",
608 xs->error);
609 error = EIO;
610 break;
611 }
612 if (error == ERESTART) {
613 xs->error = XS_NOERROR;
614 xs->status = SCSI_OK;
615 xs->xs_status &= ~XS_STS_DONE;
616 goto restart;
617 }
618 return error;
619 }
620 return 0;
621 }
622
623 static void
624 siop_start(struct siop_adapter *adp, struct scsi_xfer *xs)
625 {
626 struct siop_xfer *siop_xfer = adp->xfer;
627 uint32_t dsa, *script = adp->script;
628 int slot;
629 void *scriptaddr = (void *)local_to_PCI((u_long)script);
630 const int siop_common_xfer_size = sizeof(struct siop_common_xfer);
631
632 /*
633 * The queue management here is a bit tricky: the script always looks
634 * at the slot from first to last, so if we always use the first
635 * free slot commands can stay at the tail of the queue ~forever.
636 * The algorithm used here is to restart from the head when we know
637 * that the queue is empty, and only add commands after the last one.
638 * When we're at the end of the queue wait for the script to clear it.
639 * The best thing to do here would be to implement a circular queue,
640 * but using only 53c720 features this can be "interesting".
641 * A mid-way solution could be to implement 2 queues and swap orders.
642 */
643 slot = adp->currschedslot;
644 /*
645 * If the instruction is 0x80000000 (JUMP foo, IF FALSE) the slot is
646 * free. As this is the last used slot, all previous slots are free,
647 * we can restart from 0.
648 */
649 if (ctoh32(script[(Ent_script_sched_slot0 / 4) + slot * 2]) ==
650 0x80000000) {
651 slot = adp->currschedslot = 0;
652 } else {
653 slot++;
654 }
655 /*
656 * find a free scheduler slot and load it.
657 */
658 #define SIOP_NSLOTS 0x40
659 for (; slot < SIOP_NSLOTS; slot++) {
660 /*
661 * If cmd if 0x80000000 the slot is free
662 */
663 if (ctoh32(script[(Ent_script_sched_slot0 / 4) + slot * 2]) ==
664 0x80000000)
665 break;
666 }
667 if (slot == SIOP_NSLOTS) {
668 /*
669 * no more free slot, no need to continue. freeze the queue
670 * and requeue this command.
671 */
672 printf("no mode free slot\n");
673 return;
674 }
675
676 /* patch scripts with DSA addr */
677 dsa = local_to_PCI((u_long)siop_xfer);
678
679 /* CMD script: MOVE MEMORY addr */
680 siop_xfer->resel[E_ldsa_abs_slot_Used[0]] =
681 htoc32(scriptaddr + Ent_script_sched_slot0 + slot * 8);
682 _wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
683 /* scheduler slot: JUMP ldsa_select */
684 script[(Ent_script_sched_slot0 / 4) + slot * 2 + 1] =
685 htoc32(dsa + siop_common_xfer_size + Ent_ldsa_select);
686 /*
687 * Change JUMP cmd so that this slot will be handled
688 */
689 script[(Ent_script_sched_slot0 / 4) + slot * 2] = htoc32(0x80080000);
690 adp->currschedslot = slot;
691
692 /* make sure SCRIPT processor will read valid data */
693 _wbinv((u_long)script, SIOP_SCRIPT_SIZE);
694 /* Signal script it has some work to do */
695 writeb(adp->addr + SIOP_ISTAT, ISTAT_SIGP);
696 /* and wait for IRQ */
697 }
698
699 static void
700 siop_xfer_setup(struct siop_xfer *xfer, void *scriptaddr)
701 {
702 const int off_msg_in = offsetof(struct siop_common_xfer, msg_in);
703 const int off_status = offsetof(struct siop_common_xfer, status);
704 uint32_t dsa, *scr;
705 int i;
706
707 memset(xfer, 0, sizeof(*xfer));
708 dsa = local_to_PCI((u_long)xfer);
709 xfer->siop_tables.t_msgout.count = htoc32(1);
710 xfer->siop_tables.t_msgout.addr = htoc32(dsa);
711 xfer->siop_tables.t_msgin.count = htoc32(1);
712 xfer->siop_tables.t_msgin.addr = htoc32(dsa + off_msg_in);
713 xfer->siop_tables.t_extmsgin.count = htoc32(2);
714 xfer->siop_tables.t_extmsgin.addr = htoc32(dsa + off_msg_in + 1);
715 xfer->siop_tables.t_extmsgdata.addr = htoc32(dsa + off_msg_in + 3);
716 xfer->siop_tables.t_status.count = htoc32(1);
717 xfer->siop_tables.t_status.addr = htoc32(dsa + off_status);
718
719 /* The select/reselect script */
720 scr = xfer->resel;
721 for (i = 0; i < __arraycount(load_dsa); i++)
722 scr[i] = htoc32(load_dsa[i]);
723
724 /*
725 * 0x78000000 is a 'move data8 to reg'. data8 is the second
726 * octet, reg offset is the third.
727 */
728 scr[Ent_rdsa0 / 4] = htoc32(0x78100000 | ((dsa & 0x000000ff) << 8));
729 scr[Ent_rdsa1 / 4] = htoc32(0x78110000 | ( dsa & 0x0000ff00 ));
730 scr[Ent_rdsa2 / 4] = htoc32(0x78120000 | ((dsa & 0x00ff0000) >> 8));
731 scr[Ent_rdsa3 / 4] = htoc32(0x78130000 | ((dsa & 0xff000000) >> 16));
732 scr[E_ldsa_abs_reselected_Used[0]] =
733 htoc32(scriptaddr + Ent_reselected);
734 scr[E_ldsa_abs_reselect_Used[0]] = htoc32(scriptaddr + Ent_reselect);
735 scr[E_ldsa_abs_selected_Used[0]] = htoc32(scriptaddr + Ent_selected);
736 scr[E_ldsa_abs_data_Used[0]] =
737 htoc32(dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_data);
738 /* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */
739 scr[Ent_ldsa_data / 4] = htoc32(0x80000000);
740 }
741
742 static int
743 siop_add_reselsw(struct siop_adapter *adp, int target, int lunsw_off)
744 {
745 uint32_t *script = adp->script;
746 int reseloff;
747 void *scriptaddr = (void *)local_to_PCI((u_long)adp->script);
748
749 /*
750 * add an entry to resel switch
751 */
752 reseloff = Ent_resel_targ0 / 4 + target * 2;
753 if ((ctoh32(script[reseloff]) & 0xff) != 0xff) {
754 /* it's not free */
755 printf("siop: resel switch full\n");
756 return EBUSY;
757 }
758
759 /* JUMP abs_foo, IF target | 0x80; */
760 script[reseloff + 0] = htoc32(0x800c0080 | target);
761 script[reseloff + 1] =
762 htoc32(scriptaddr + lunsw_off * 4 + Ent_lun_switch_entry);
763
764 siop_update_scntl3(adp, target, lunsw_off);
765 return 0;
766 }
767
768 static void
769 siop_update_scntl3(struct siop_adapter *adp, int target, int lunsw_off)
770 {
771 uint32_t *script = adp->script;
772
773 /* MOVE target->id >> 24 TO SCNTL3 */
774 script[lunsw_off + (Ent_restore_scntl3 / 4)] =
775 htoc32(0x78030000 | ((adp->clock_div >> 16) & 0x0000ff00));
776 /* MOVE target->id >> 8 TO SXFER */
777 script[lunsw_off + (Ent_restore_scntl3 / 4) + 2] =
778 htoc32(0x78050000 | (0x000000000 & 0x0000ff00));
779 _wbinv((u_long)script, SIOP_SCRIPT_SIZE);
780 }
781
782
783 /*
784 * SCSI functions
785 */
786
787 static int
788 _scsi_inquire(struct siop_adapter *adp, int t, int l, int buflen, char *buf)
789 {
790 struct scsipi_inquiry *cmd = (struct scsipi_inquiry *)adp->cmd;
791 struct scsipi_inquiry_data *inqbuf =
792 (struct scsipi_inquiry_data *)adp->data;
793 struct scsi_xfer xs;
794 int error;
795
796 memset(cmd, 0, sizeof(*cmd));
797 cmd->opcode = INQUIRY;
798 cmd->length = SCSIPI_INQUIRY_LENGTH_SCSI2;
799 memset(inqbuf, 0, sizeof(*inqbuf));
800
801 memset(&xs, 0, sizeof(xs));
802 xs.target = t;
803 xs.lun = l;
804 xs.cmdlen = sizeof(*cmd);
805 xs.cmd = (void *)cmd;
806 xs.datalen = SCSIPI_INQUIRY_LENGTH_SCSI2;
807 xs.data = (void *)inqbuf;
808
809 xs.error = XS_NOERROR;
810 xs.resid = xs.datalen;
811 xs.status = SCSI_OK;
812
813 error = siop_scsi_request(adp, &xs);
814 if (error != 0)
815 return error;
816
817 memcpy(buf, inqbuf, buflen);
818 return 0;
819 }
820
821 static void
822 scsi_request_sense(struct siop_adapter *adp, struct scsi_xfer *xs)
823 {
824 struct scsi_request_sense *cmd = adp->sense;
825 struct scsi_sense_data *data = (struct scsi_sense_data *)adp->data;
826 struct scsi_xfer sense;
827 int error;
828
829 memset(cmd, 0, sizeof(struct scsi_request_sense));
830 cmd->opcode = SCSI_REQUEST_SENSE;
831 cmd->length = sizeof(struct scsi_sense_data);
832 memset(data, 0, sizeof(struct scsi_sense_data));
833
834 memset(&sense, 0, sizeof(sense));
835 sense.target = xs->target;
836 sense.lun = xs->lun;
837 sense.cmdlen = sizeof(struct scsi_request_sense);
838 sense.cmd = (void *)cmd;
839 sense.datalen = sizeof(struct scsi_sense_data);
840 sense.data = (void *)data;
841
842 sense.error = XS_NOERROR;
843 sense.resid = sense.datalen;
844 sense.status = SCSI_OK;
845
846 error = siop_scsi_request(adp, &sense);
847 switch (error) {
848 case 0:
849 /* we have a valid sense */
850 xs->error = XS_SENSE;
851 return;
852 case EINTR:
853 /* REQUEST_SENSE interrupted by bus reset. */
854 xs->error = XS_RESET;
855 return;
856 case EIO:
857 /* request sense coudn't be performed */
858 /*
859 * XXX this isn't quite right but we don't have anything
860 * better for now
861 */
862 xs->error = XS_DRIVER_STUFFUP;
863 return;
864 default:
865 /* Notify that request sense failed. */
866 xs->error = XS_DRIVER_STUFFUP;
867 printf("request sense failed with error %d\n", error);
868 return;
869 }
870 }
871
872 /*
873 * scsi_interpret_sense:
874 *
875 * Look at the returned sense and act on the error, determining
876 * the unix error number to pass back. (0 = report no error)
877 *
878 * NOTE: If we return ERESTART, we are expected to haved
879 * thawed the device!
880 *
881 * THIS IS THE DEFAULT ERROR HANDLER FOR SCSI DEVICES.
882 */
883 static int
884 scsi_interpret_sense(struct siop_adapter *adp, struct scsi_xfer *xs)
885 {
886 struct scsi_sense_data *sense;
887 u_int8_t key;
888 int error;
889 uint32_t info;
890 static const char *error_mes[] = {
891 "soft error (corrected)",
892 "not ready", "medium error",
893 "non-media hardware failure", "illegal request",
894 "unit attention", "readonly device",
895 "no data found", "vendor unique",
896 "copy aborted", "command aborted",
897 "search returned equal", "volume overflow",
898 "verify miscompare", "unknown error key"
899 };
900
901 sense = (struct scsi_sense_data *)xs->data;
902
903 DPRINTF((" sense debug information:\n"));
904 DPRINTF(("\tcode 0x%x valid %d\n",
905 SSD_RCODE(sense->response_code),
906 sense->response_code & SSD_RCODE_VALID ? 1 : 0));
907 DPRINTF(("\tseg 0x%x key 0x%x ili 0x%x eom 0x%x fmark 0x%x\n",
908 sense->segment,
909 SSD_SENSE_KEY(sense->flags),
910 sense->flags & SSD_ILI ? 1 : 0,
911 sense->flags & SSD_EOM ? 1 : 0,
912 sense->flags & SSD_FILEMARK ? 1 : 0));
913 DPRINTF(("\ninfo: 0x%x 0x%x 0x%x 0x%x followed by %d "
914 "extra bytes\n",
915 sense->info[0],
916 sense->info[1],
917 sense->info[2],
918 sense->info[3],
919 sense->extra_len));
920
921 switch (SSD_RCODE(sense->response_code)) {
922
923 /*
924 * Old SCSI-1 and SASI devices respond with
925 * codes other than 70.
926 */
927 case 0x00: /* no error (command completed OK) */
928 return 0;
929 case 0x04: /* drive not ready after it was selected */
930 if (adp->sd->sc_flags & FLAGS_REMOVABLE)
931 adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
932 /* XXX - display some sort of error here? */
933 return EIO;
934 case 0x20: /* invalid command */
935 return EINVAL;
936 case 0x25: /* invalid LUN (Adaptec ACB-4000) */
937 return EACCES;
938
939 /*
940 * If it's code 70, use the extended stuff and
941 * interpret the key
942 */
943 case 0x71: /* delayed error */
944 key = SSD_SENSE_KEY(sense->flags);
945 printf(" DEFERRED ERROR, key = 0x%x\n", key);
946 /* FALLTHROUGH */
947 case 0x70:
948 if ((sense->response_code & SSD_RCODE_VALID) != 0)
949 info = _4btol(sense->info);
950 else
951 info = 0;
952 key = SSD_SENSE_KEY(sense->flags);
953
954 switch (key) {
955 case SKEY_NO_SENSE:
956 case SKEY_RECOVERED_ERROR:
957 if (xs->resid == xs->datalen && xs->datalen) {
958 /*
959 * Why is this here?
960 */
961 xs->resid = 0; /* not short read */
962 }
963 case SKEY_EQUAL:
964 error = 0;
965 break;
966 case SKEY_NOT_READY:
967 if (adp->sd->sc_flags & FLAGS_REMOVABLE)
968 adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
969 if (sense->asc == 0x3A) {
970 error = ENODEV; /* Medium not present */
971 } else
972 error = EIO;
973 break;
974 case SKEY_ILLEGAL_REQUEST:
975 error = EINVAL;
976 break;
977 case SKEY_UNIT_ATTENTION:
978 if (sense->asc == 0x29 &&
979 sense->ascq == 0x00) {
980 /* device or bus reset */
981 return ERESTART;
982 }
983 if (adp->sd->sc_flags & FLAGS_REMOVABLE)
984 adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
985 if (!(adp->sd->sc_flags & FLAGS_REMOVABLE))
986 return ERESTART;
987 error = EIO;
988 break;
989 case SKEY_DATA_PROTECT:
990 error = EROFS;
991 break;
992 case SKEY_BLANK_CHECK:
993 error = 0;
994 break;
995 case SKEY_ABORTED_COMMAND:
996 /* XXX XXX initialize 'error' */
997 break;
998 case SKEY_VOLUME_OVERFLOW:
999 error = ENOSPC;
1000 break;
1001 default:
1002 error = EIO;
1003 break;
1004 }
1005
1006 /* Print brief(er) sense information */
1007 printf("%s", error_mes[key - 1]);
1008 if ((sense->response_code & SSD_RCODE_VALID) != 0) {
1009 switch (key) {
1010 case SKEY_NOT_READY:
1011 case SKEY_ILLEGAL_REQUEST:
1012 case SKEY_UNIT_ATTENTION:
1013 case SKEY_DATA_PROTECT:
1014 break;
1015 case SKEY_BLANK_CHECK:
1016 printf(", requested size: %d (decimal)",
1017 info);
1018 break;
1019 case SKEY_ABORTED_COMMAND:
1020 printf(", cmd 0x%x, info 0x%x",
1021 xs->cmd->opcode, info);
1022 break;
1023 default:
1024 printf(", info = %d (decimal)", info);
1025 }
1026 }
1027 if (sense->extra_len != 0) {
1028 int n;
1029 printf(", data =");
1030 for (n = 0; n < sense->extra_len; n++)
1031 printf(" %x", sense->csi[n]);
1032 }
1033 printf("\n");
1034 return error;
1035
1036 /*
1037 * Some other code, just report it
1038 */
1039 default:
1040 printf("Sense Error Code 0x%x",
1041 SSD_RCODE(sense->response_code));
1042 if ((sense->response_code & SSD_RCODE_VALID) != 0) {
1043 struct scsi_sense_data_unextended *usense =
1044 (struct scsi_sense_data_unextended *)sense;
1045 printf(" at block no. %d (decimal)",
1046 _3btol(usense->block));
1047 }
1048 printf("\n");
1049 return EIO;
1050 }
1051 }
1052
1053 static int
1054 scsi_probe(struct siop_adapter *adp)
1055 {
1056 struct scsipi_inquiry_data *inqbuf;
1057 int found, t, l;
1058 uint8_t device;
1059 char buf[SCSIPI_INQUIRY_LENGTH_SCSI2],
1060 product[sizeof(inqbuf->product) + 1];
1061
1062 found = 0;
1063 for (t = 0; t < 8; t++) {
1064 if (t == adp->id)
1065 continue;
1066 for (l = 0; l < 8; l++) {
1067 if (_scsi_inquire(adp, t, l, sizeof(buf), buf) != 0)
1068 continue;
1069
1070 inqbuf = (struct scsipi_inquiry_data *)buf;
1071 device = inqbuf->device & SID_TYPE;
1072 if (device == T_NODEVICE)
1073 continue;
1074 if (device != T_DIRECT &&
1075 device != T_OPTICAL &&
1076 device != T_SIMPLE_DIRECT)
1077 continue;
1078
1079 memset(product, 0, sizeof(product));
1080 strncpy(product, inqbuf->product, sizeof(product) - 1);
1081 printf("/dev/disk/scsi/0%d%d: <%s>\n", t, l, product);
1082 found++;
1083 }
1084 }
1085 return found;
1086 }
1087
1088 int
1089 scsi_inquire(struct sd_softc *sd, int buflen, void *buf)
1090 {
1091 struct siop_adapter *adp;
1092 int error;
1093
1094 if (sd->sc_bus != 0)
1095 return ENOTSUP;
1096 if (adapt.addr == 0)
1097 return ENOENT;
1098 adp = &adapt;
1099
1100 adp->sd = sd;
1101 error = _scsi_inquire(adp, sd->sc_target, sd->sc_lun, buflen, buf);
1102 adp->sd = NULL;
1103
1104 return error;
1105 }
1106
1107 /*
1108 * scsi_mode_sense
1109 * get a sense page from a device
1110 */
1111
1112 int
1113 scsi_mode_sense(struct sd_softc *sd, int byte2, int page,
1114 struct scsi_mode_parameter_header_6 *data, int len)
1115 {
1116 struct scsi_mode_sense_6 cmd;
1117
1118 memset(&cmd, 0, sizeof(cmd));
1119 cmd.opcode = SCSI_MODE_SENSE_6;
1120 cmd.byte2 = byte2;
1121 cmd.page = page;
1122 cmd.length = len & 0xff;
1123
1124 return scsi_command(sd, (void *)&cmd, sizeof(cmd), (void *)data, len);
1125 }
1126
1127 int
1128 scsi_command(struct sd_softc *sd, void *cmd, int cmdlen, void *data,
1129 int datalen)
1130 {
1131 struct siop_adapter *adp;
1132 struct scsi_xfer xs;
1133 int error;
1134
1135 if (sd->sc_bus != 0)
1136 return ENOTSUP;
1137 if (adapt.addr == 0)
1138 return ENOENT;
1139 adp = &adapt;
1140
1141 memcpy(adp->cmd, cmd, cmdlen);
1142 adp->sd = sd;
1143
1144 memset(&xs, 0, sizeof(xs));
1145 xs.target = sd->sc_target;
1146 xs.lun = sd->sc_lun;
1147 xs.cmdlen = cmdlen;
1148 xs.cmd = adp->cmd;
1149 xs.datalen = datalen;
1150 xs.data = adp->data;
1151
1152 xs.error = XS_NOERROR;
1153 xs.resid = datalen;
1154 xs.status = SCSI_OK;
1155
1156 error = siop_scsi_request(adp, &xs);
1157 adp->sd = NULL;
1158 if (error != 0)
1159 return error;
1160
1161 if (datalen > 0)
1162 memcpy(data, adp->data, datalen);
1163 return 0;
1164 }
1165
1166 /*
1167 * Initialize the device.
1168 */
1169 int
1170 siop_init(int bus, int dev, int func)
1171 {
1172 struct siop_adapter tmp;
1173 struct siop_xfer *xfer;
1174 struct scsipi_generic *cmd;
1175 struct scsi_request_sense *sense;
1176 uint32_t reg;
1177 u_long addr;
1178 uint32_t *script;
1179 int slot, id, i;
1180 void *scriptaddr;
1181 u_char *data;
1182 const int clock_div = 3; /* 53c810 */
1183
1184 slot = PCISlotnum(bus, dev, func);
1185 if (slot == -1)
1186 return ENOENT;
1187
1188 addr = PCIAddress(slot, 1, PCI_MAPREG_TYPE_MEM);
1189 if (addr == 0xffffffff)
1190 return EINVAL;
1191 enablePCI(slot, 0, 1, 1);
1192
1193 script = ALLOC(uint32_t, SIOP_SCRIPT_SIZE);
1194 if (script == NULL)
1195 return ENOMEM;
1196 scriptaddr = (void *)local_to_PCI((u_long)script);
1197 cmd = ALLOC(struct scsipi_generic, SIOP_SCSI_COMMAND_SIZE);
1198 if (cmd == NULL)
1199 return ENOMEM;
1200 sense = ALLOC(struct scsi_request_sense, SIOP_SCSI_COMMAND_SIZE);
1201 if (sense == NULL)
1202 return ENOMEM;
1203 data = ALLOC(u_char, SIOP_SCSI_DATA_SIZE);
1204 if (data == NULL)
1205 return ENOMEM;
1206 xfer = ALLOC(struct siop_xfer, sizeof(struct siop_xfer));
1207 if (xfer == NULL)
1208 return ENOMEM;
1209 siop_xfer_setup(xfer, scriptaddr);
1210
1211 id = readb(addr + SIOP_SCID) & SCID_ENCID_MASK;
1212
1213 /* reset bus */
1214 reg = readb(addr + SIOP_SCNTL1);
1215 writeb(addr + SIOP_SCNTL1, reg | SCNTL1_RST);
1216 delay(100);
1217 writeb(addr + SIOP_SCNTL1, reg);
1218
1219 /* reset the chip */
1220 writeb(addr + SIOP_ISTAT, ISTAT_SRST);
1221 delay(1000);
1222 writeb(addr + SIOP_ISTAT, 0);
1223
1224 /* init registers */
1225 writeb(addr + SIOP_SCNTL0, SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP);
1226 writeb(addr + SIOP_SCNTL1, 0);
1227 writeb(addr + SIOP_SCNTL3, clock_div);
1228 writeb(addr + SIOP_SXFER, 0);
1229 writeb(addr + SIOP_DIEN, 0xff);
1230 writeb(addr + SIOP_SIEN0, 0xff & ~(SIEN0_CMP | SIEN0_SEL | SIEN0_RSL));
1231 writeb(addr + SIOP_SIEN1, 0xff & ~(SIEN1_HTH | SIEN1_GEN));
1232 writeb(addr + SIOP_STEST2, 0);
1233 writeb(addr + SIOP_STEST3, STEST3_TE);
1234 writeb(addr + SIOP_STIME0, (0xb << STIME0_SEL_SHIFT));
1235 writeb(addr + SIOP_SCID, id | SCID_RRE);
1236 writeb(addr + SIOP_RESPID0, 1 << id);
1237 writeb(addr + SIOP_DCNTL, DCNTL_COM);
1238
1239 /* BeBox uses PCIC */
1240 writeb(addr + SIOP_STEST1, STEST1_SCLK);
1241
1242 siop_pci_reset(addr);
1243
1244 /* copy and patch the script */
1245 for (i = 0; i < __arraycount(siop_script); i++)
1246 script[i] = htoc32(siop_script[i]);
1247 for (i = 0; i < __arraycount(E_abs_msgin_Used); i++)
1248 script[E_abs_msgin_Used[i]] =
1249 htoc32(scriptaddr + Ent_msgin_space);
1250
1251 /* start script */
1252 _wbinv((u_long)script, SIOP_SCRIPT_SIZE);
1253 writel(addr + SIOP_DSP, (int)scriptaddr + Ent_reselect);
1254
1255 memset(&tmp, 0, sizeof(tmp));
1256 tmp.id = id;
1257 tmp.clock_div = clock_div;
1258 tmp.addr = addr;
1259 tmp.script = script;
1260 tmp.xfer = xfer;
1261 tmp.cmd = cmd;
1262 tmp.sense = sense;
1263 tmp.data = data;
1264 tmp.currschedslot = 0;
1265 tmp.sel_t = -1;
1266
1267 if (scsi_probe(&tmp) == 0)
1268 return ENXIO;
1269 adapt = tmp;
1270 return 0;
1271 }
1272