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