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