siop.c revision 1.12 1 /* $NetBSD: siop.c,v 1.12 2023/05/26 06:27:51 andvar 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 beginning of the data not yet transferred.
187 * offset points to the first table with untransferred data.
188 */
189
190 /*
191 * before doing that we decrease resid from the amount of data which
192 * has been transferred.
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 transferred 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 transferred 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 transferred.
216 * We just move the entries with data left at the beginning 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 following
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 couldn'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 = 0;
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 break;
965 case SKEY_NOT_READY:
966 if (adp->sd->sc_flags & FLAGS_REMOVABLE)
967 adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
968 if (sense->asc == 0x3A) {
969 error = ENODEV; /* Medium not present */
970 } else
971 error = EIO;
972 break;
973 case SKEY_ILLEGAL_REQUEST:
974 error = EINVAL;
975 break;
976 case SKEY_UNIT_ATTENTION:
977 if (sense->asc == 0x29 &&
978 sense->ascq == 0x00) {
979 /* device or bus reset */
980 return ERESTART;
981 }
982 if (adp->sd->sc_flags & FLAGS_REMOVABLE)
983 adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
984 if (!(adp->sd->sc_flags & FLAGS_REMOVABLE))
985 return ERESTART;
986 error = EIO;
987 break;
988 case SKEY_DATA_PROTECT:
989 error = EROFS;
990 break;
991 case SKEY_BLANK_CHECK:
992 break;
993 case SKEY_ABORTED_COMMAND:
994 /* XXX XXX initialize 'error' */
995 break;
996 case SKEY_VOLUME_OVERFLOW:
997 error = ENOSPC;
998 break;
999 default:
1000 error = EIO;
1001 break;
1002 }
1003
1004 /* Print brief(er) sense information */
1005 printf("%s", error_mes[key - 1]);
1006 if ((sense->response_code & SSD_RCODE_VALID) != 0) {
1007 switch (key) {
1008 case SKEY_NOT_READY:
1009 case SKEY_ILLEGAL_REQUEST:
1010 case SKEY_UNIT_ATTENTION:
1011 case SKEY_DATA_PROTECT:
1012 break;
1013 case SKEY_BLANK_CHECK:
1014 printf(", requested size: %d (decimal)",
1015 info);
1016 break;
1017 case SKEY_ABORTED_COMMAND:
1018 printf(", cmd 0x%x, info 0x%x",
1019 xs->cmd->opcode, info);
1020 break;
1021 default:
1022 printf(", info = %d (decimal)", info);
1023 }
1024 }
1025 if (sense->extra_len != 0) {
1026 int n;
1027 printf(", data =");
1028 for (n = 0; n < sense->extra_len; n++)
1029 printf(" %x", sense->csi[n]);
1030 }
1031 printf("\n");
1032 return error;
1033
1034 /*
1035 * Some other code, just report it
1036 */
1037 default:
1038 printf("Sense Error Code 0x%x",
1039 SSD_RCODE(sense->response_code));
1040 if ((sense->response_code & SSD_RCODE_VALID) != 0) {
1041 struct scsi_sense_data_unextended *usense =
1042 (struct scsi_sense_data_unextended *)sense;
1043 printf(" at block no. %d (decimal)",
1044 _3btol(usense->block));
1045 }
1046 printf("\n");
1047 return EIO;
1048 }
1049 }
1050
1051 static int
1052 scsi_probe(struct siop_adapter *adp)
1053 {
1054 struct scsipi_inquiry_data *inqbuf;
1055 int found, t, l;
1056 uint8_t device;
1057 char buf[SCSIPI_INQUIRY_LENGTH_SCSI2],
1058 product[sizeof(inqbuf->product) + 1];
1059
1060 found = 0;
1061 for (t = 0; t < 8; t++) {
1062 if (t == adp->id)
1063 continue;
1064 for (l = 0; l < 8; l++) {
1065 if (_scsi_inquire(adp, t, l, sizeof(buf), buf) != 0)
1066 continue;
1067
1068 inqbuf = (struct scsipi_inquiry_data *)buf;
1069 device = inqbuf->device & SID_TYPE;
1070 if (device == T_NODEVICE)
1071 continue;
1072 if (device != T_DIRECT &&
1073 device != T_OPTICAL &&
1074 device != T_SIMPLE_DIRECT)
1075 continue;
1076
1077 memset(product, 0, sizeof(product));
1078 strncpy(product, inqbuf->product, sizeof(product) - 1);
1079 printf("/dev/disk/scsi/0%d%d: <%s>\n", t, l, product);
1080 found++;
1081 }
1082 }
1083 return found;
1084 }
1085
1086 int
1087 scsi_inquire(struct sd_softc *sd, int buflen, void *buf)
1088 {
1089 struct siop_adapter *adp;
1090 int error;
1091
1092 if (sd->sc_bus != 0)
1093 return ENOTSUP;
1094 if (adapt.addr == 0)
1095 return ENOENT;
1096 adp = &adapt;
1097
1098 adp->sd = sd;
1099 error = _scsi_inquire(adp, sd->sc_target, sd->sc_lun, buflen, buf);
1100 adp->sd = NULL;
1101
1102 return error;
1103 }
1104
1105 /*
1106 * scsi_mode_sense
1107 * get a sense page from a device
1108 */
1109
1110 int
1111 scsi_mode_sense(struct sd_softc *sd, int byte2, int page,
1112 struct scsi_mode_parameter_header_6 *data, int len)
1113 {
1114 struct scsi_mode_sense_6 cmd;
1115
1116 memset(&cmd, 0, sizeof(cmd));
1117 cmd.opcode = SCSI_MODE_SENSE_6;
1118 cmd.byte2 = byte2;
1119 cmd.page = page;
1120 cmd.length = len & 0xff;
1121
1122 return scsi_command(sd, (void *)&cmd, sizeof(cmd), (void *)data, len);
1123 }
1124
1125 int
1126 scsi_command(struct sd_softc *sd, void *cmd, int cmdlen, void *data,
1127 int datalen)
1128 {
1129 struct siop_adapter *adp;
1130 struct scsi_xfer xs;
1131 int error;
1132
1133 if (sd->sc_bus != 0)
1134 return ENOTSUP;
1135 if (adapt.addr == 0)
1136 return ENOENT;
1137 adp = &adapt;
1138
1139 memcpy(adp->cmd, cmd, cmdlen);
1140 adp->sd = sd;
1141
1142 memset(&xs, 0, sizeof(xs));
1143 xs.target = sd->sc_target;
1144 xs.lun = sd->sc_lun;
1145 xs.cmdlen = cmdlen;
1146 xs.cmd = adp->cmd;
1147 xs.datalen = datalen;
1148 xs.data = adp->data;
1149
1150 xs.error = XS_NOERROR;
1151 xs.resid = datalen;
1152 xs.status = SCSI_OK;
1153
1154 error = siop_scsi_request(adp, &xs);
1155 adp->sd = NULL;
1156 if (error != 0)
1157 return error;
1158
1159 if (datalen > 0)
1160 memcpy(data, adp->data, datalen);
1161 return 0;
1162 }
1163
1164 /*
1165 * Initialize the device.
1166 */
1167 int
1168 siop_init(int bus, int dev, int func)
1169 {
1170 struct siop_adapter tmp;
1171 struct siop_xfer *xfer;
1172 struct scsipi_generic *cmd;
1173 struct scsi_request_sense *sense;
1174 uint32_t reg;
1175 u_long addr;
1176 uint32_t *script;
1177 int slot, id, i;
1178 void *scriptaddr;
1179 u_char *data;
1180 const int clock_div = 3; /* 53c810 */
1181
1182 slot = PCISlotnum(bus, dev, func);
1183 if (slot == -1)
1184 return ENOENT;
1185
1186 addr = PCIAddress(slot, 1, PCI_MAPREG_TYPE_MEM);
1187 if (addr == 0xffffffff)
1188 return EINVAL;
1189 enablePCI(slot, 0, 1, 1);
1190
1191 script = ALLOC(uint32_t, SIOP_SCRIPT_SIZE);
1192 if (script == NULL)
1193 return ENOMEM;
1194 scriptaddr = (void *)local_to_PCI((u_long)script);
1195 cmd = ALLOC(struct scsipi_generic, SIOP_SCSI_COMMAND_SIZE);
1196 if (cmd == NULL)
1197 return ENOMEM;
1198 sense = ALLOC(struct scsi_request_sense, SIOP_SCSI_COMMAND_SIZE);
1199 if (sense == NULL)
1200 return ENOMEM;
1201 data = ALLOC(u_char, SIOP_SCSI_DATA_SIZE);
1202 if (data == NULL)
1203 return ENOMEM;
1204 xfer = ALLOC(struct siop_xfer, sizeof(struct siop_xfer));
1205 if (xfer == NULL)
1206 return ENOMEM;
1207 siop_xfer_setup(xfer, scriptaddr);
1208
1209 id = readb(addr + SIOP_SCID) & SCID_ENCID_MASK;
1210
1211 /* reset bus */
1212 reg = readb(addr + SIOP_SCNTL1);
1213 writeb(addr + SIOP_SCNTL1, reg | SCNTL1_RST);
1214 delay(100);
1215 writeb(addr + SIOP_SCNTL1, reg);
1216
1217 /* reset the chip */
1218 writeb(addr + SIOP_ISTAT, ISTAT_SRST);
1219 delay(1000);
1220 writeb(addr + SIOP_ISTAT, 0);
1221
1222 /* init registers */
1223 writeb(addr + SIOP_SCNTL0, SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP);
1224 writeb(addr + SIOP_SCNTL1, 0);
1225 writeb(addr + SIOP_SCNTL3, clock_div);
1226 writeb(addr + SIOP_SXFER, 0);
1227 writeb(addr + SIOP_DIEN, 0xff);
1228 writeb(addr + SIOP_SIEN0, 0xff & ~(SIEN0_CMP | SIEN0_SEL | SIEN0_RSL));
1229 writeb(addr + SIOP_SIEN1, 0xff & ~(SIEN1_HTH | SIEN1_GEN));
1230 writeb(addr + SIOP_STEST2, 0);
1231 writeb(addr + SIOP_STEST3, STEST3_TE);
1232 writeb(addr + SIOP_STIME0, (0xb << STIME0_SEL_SHIFT));
1233 writeb(addr + SIOP_SCID, id | SCID_RRE);
1234 writeb(addr + SIOP_RESPID0, 1 << id);
1235 writeb(addr + SIOP_DCNTL, DCNTL_COM);
1236
1237 /* BeBox uses PCIC */
1238 writeb(addr + SIOP_STEST1, STEST1_SCLK);
1239
1240 siop_pci_reset(addr);
1241
1242 /* copy and patch the script */
1243 for (i = 0; i < __arraycount(siop_script); i++)
1244 script[i] = htoc32(siop_script[i]);
1245 for (i = 0; i < __arraycount(E_abs_msgin_Used); i++)
1246 script[E_abs_msgin_Used[i]] =
1247 htoc32(scriptaddr + Ent_msgin_space);
1248
1249 /* start script */
1250 _wbinv((u_long)script, SIOP_SCRIPT_SIZE);
1251 writel(addr + SIOP_DSP, (int)scriptaddr + Ent_reselect);
1252
1253 memset(&tmp, 0, sizeof(tmp));
1254 tmp.id = id;
1255 tmp.clock_div = clock_div;
1256 tmp.addr = addr;
1257 tmp.script = script;
1258 tmp.xfer = xfer;
1259 tmp.cmd = cmd;
1260 tmp.sense = sense;
1261 tmp.data = data;
1262 tmp.currschedslot = 0;
1263 tmp.sel_t = -1;
1264
1265 if (scsi_probe(&tmp) == 0)
1266 return ENXIO;
1267 adapt = tmp;
1268 return 0;
1269 }
1270