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