siop.c revision 1.1.2.3 1 1.1.2.3 yamt /* $NetBSD: siop.c,v 1.1.2.3 2014/05/22 11:40:05 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.3 yamt uint8_t dstat = 0, 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.3 yamt int 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 /*
635 1.1.2.2 yamt * find a free scheduler slot and load it.
636 1.1.2.2 yamt */
637 1.1.2.2 yamt #define SIOP_NSLOTS 0x40
638 1.1.2.2 yamt for (; slot < SIOP_NSLOTS; slot++) {
639 1.1.2.2 yamt /*
640 1.1.2.2 yamt * If cmd if 0x80000000 the slot is free
641 1.1.2.2 yamt */
642 1.1.2.2 yamt if (ctoh32(script[(Ent_script_sched_slot0 / 4) + slot * 2]) ==
643 1.1.2.2 yamt 0x80000000)
644 1.1.2.2 yamt break;
645 1.1.2.2 yamt }
646 1.1.2.2 yamt if (slot == SIOP_NSLOTS) {
647 1.1.2.2 yamt /*
648 1.1.2.2 yamt * no more free slot, no need to continue. freeze the queue
649 1.1.2.2 yamt * and requeue this command.
650 1.1.2.2 yamt */
651 1.1.2.2 yamt printf("no mode free slot\n");
652 1.1.2.2 yamt return;
653 1.1.2.2 yamt }
654 1.1.2.2 yamt
655 1.1.2.2 yamt /* patch scripts with DSA addr */
656 1.1.2.2 yamt dsa = local_to_PCI((u_long)siop_xfer);
657 1.1.2.2 yamt
658 1.1.2.2 yamt /* CMD script: MOVE MEMORY addr */
659 1.1.2.2 yamt siop_xfer->resel[E_ldsa_abs_slot_Used[0]] =
660 1.1.2.2 yamt htoc32(scriptaddr + Ent_script_sched_slot0 + slot * 8);
661 1.1.2.2 yamt _wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
662 1.1.2.2 yamt /* scheduler slot: JUMP ldsa_select */
663 1.1.2.2 yamt script[(Ent_script_sched_slot0 / 4) + slot * 2 + 1] =
664 1.1.2.2 yamt htoc32(dsa + siop_common_xfer_size + Ent_ldsa_select);
665 1.1.2.2 yamt /*
666 1.1.2.2 yamt * Change JUMP cmd so that this slot will be handled
667 1.1.2.2 yamt */
668 1.1.2.2 yamt script[(Ent_script_sched_slot0 / 4) + slot * 2] = htoc32(0x80080000);
669 1.1.2.2 yamt adp->currschedslot = slot;
670 1.1.2.2 yamt
671 1.1.2.2 yamt /* make sure SCRIPT processor will read valid data */
672 1.1.2.2 yamt _wbinv((u_long)script, SIOP_SCRIPT_SIZE);
673 1.1.2.2 yamt /* Signal script it has some work to do */
674 1.1.2.2 yamt writeb(adp->addr + SIOP_ISTAT, ISTAT_SIGP);
675 1.1.2.2 yamt /* and wait for IRQ */
676 1.1.2.2 yamt }
677 1.1.2.2 yamt
678 1.1.2.2 yamt static void
679 1.1.2.2 yamt siop_xfer_setup(struct siop_xfer *xfer, void *scriptaddr)
680 1.1.2.2 yamt {
681 1.1.2.2 yamt const int off_msg_in = offsetof(struct siop_common_xfer, msg_in);
682 1.1.2.2 yamt const int off_status = offsetof(struct siop_common_xfer, status);
683 1.1.2.2 yamt uint32_t dsa, *scr;
684 1.1.2.2 yamt int i;
685 1.1.2.2 yamt
686 1.1.2.2 yamt memset(xfer, 0, sizeof(*xfer));
687 1.1.2.2 yamt dsa = local_to_PCI((u_long)xfer);
688 1.1.2.2 yamt xfer->siop_tables.t_msgout.count = htoc32(1);
689 1.1.2.2 yamt xfer->siop_tables.t_msgout.addr = htoc32(dsa);
690 1.1.2.2 yamt xfer->siop_tables.t_msgin.count = htoc32(1);
691 1.1.2.2 yamt xfer->siop_tables.t_msgin.addr = htoc32(dsa + off_msg_in);
692 1.1.2.2 yamt xfer->siop_tables.t_extmsgin.count = htoc32(2);
693 1.1.2.2 yamt xfer->siop_tables.t_extmsgin.addr = htoc32(dsa + off_msg_in + 1);
694 1.1.2.2 yamt xfer->siop_tables.t_extmsgdata.addr = htoc32(dsa + off_msg_in + 3);
695 1.1.2.2 yamt xfer->siop_tables.t_status.count = htoc32(1);
696 1.1.2.2 yamt xfer->siop_tables.t_status.addr = htoc32(dsa + off_status);
697 1.1.2.2 yamt
698 1.1.2.2 yamt /* The select/reselect script */
699 1.1.2.2 yamt scr = xfer->resel;
700 1.1.2.2 yamt for (i = 0; i < __arraycount(load_dsa); i++)
701 1.1.2.2 yamt scr[i] = htoc32(load_dsa[i]);
702 1.1.2.2 yamt
703 1.1.2.2 yamt /*
704 1.1.2.2 yamt * 0x78000000 is a 'move data8 to reg'. data8 is the second
705 1.1.2.2 yamt * octet, reg offset is the third.
706 1.1.2.2 yamt */
707 1.1.2.2 yamt scr[Ent_rdsa0 / 4] = htoc32(0x78100000 | ((dsa & 0x000000ff) << 8));
708 1.1.2.2 yamt scr[Ent_rdsa1 / 4] = htoc32(0x78110000 | ( dsa & 0x0000ff00 ));
709 1.1.2.2 yamt scr[Ent_rdsa2 / 4] = htoc32(0x78120000 | ((dsa & 0x00ff0000) >> 8));
710 1.1.2.2 yamt scr[Ent_rdsa3 / 4] = htoc32(0x78130000 | ((dsa & 0xff000000) >> 16));
711 1.1.2.2 yamt scr[E_ldsa_abs_reselected_Used[0]] =
712 1.1.2.2 yamt htoc32(scriptaddr + Ent_reselected);
713 1.1.2.2 yamt scr[E_ldsa_abs_reselect_Used[0]] = htoc32(scriptaddr + Ent_reselect);
714 1.1.2.2 yamt scr[E_ldsa_abs_selected_Used[0]] = htoc32(scriptaddr + Ent_selected);
715 1.1.2.2 yamt scr[E_ldsa_abs_data_Used[0]] =
716 1.1.2.2 yamt htoc32(dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_data);
717 1.1.2.2 yamt /* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */
718 1.1.2.2 yamt scr[Ent_ldsa_data / 4] = htoc32(0x80000000);
719 1.1.2.2 yamt }
720 1.1.2.2 yamt
721 1.1.2.2 yamt static int
722 1.1.2.2 yamt siop_add_reselsw(struct siop_adapter *adp, int target, int lunsw_off)
723 1.1.2.2 yamt {
724 1.1.2.2 yamt uint32_t *script = adp->script;
725 1.1.2.2 yamt int reseloff;
726 1.1.2.2 yamt void *scriptaddr = (void *)local_to_PCI((u_long)adp->script);
727 1.1.2.2 yamt
728 1.1.2.2 yamt /*
729 1.1.2.2 yamt * add an entry to resel switch
730 1.1.2.2 yamt */
731 1.1.2.2 yamt reseloff = Ent_resel_targ0 / 4 + target * 2;
732 1.1.2.2 yamt if ((ctoh32(script[reseloff]) & 0xff) != 0xff) {
733 1.1.2.2 yamt /* it's not free */
734 1.1.2.2 yamt printf("siop: resel switch full\n");
735 1.1.2.2 yamt return EBUSY;
736 1.1.2.2 yamt }
737 1.1.2.2 yamt
738 1.1.2.2 yamt /* JUMP abs_foo, IF target | 0x80; */
739 1.1.2.2 yamt script[reseloff + 0] = htoc32(0x800c0080 | target);
740 1.1.2.2 yamt script[reseloff + 1] =
741 1.1.2.2 yamt htoc32(scriptaddr + lunsw_off * 4 + Ent_lun_switch_entry);
742 1.1.2.2 yamt
743 1.1.2.2 yamt siop_update_scntl3(adp, target, lunsw_off);
744 1.1.2.2 yamt return 0;
745 1.1.2.2 yamt }
746 1.1.2.2 yamt
747 1.1.2.2 yamt static void
748 1.1.2.2 yamt siop_update_scntl3(struct siop_adapter *adp, int target, int lunsw_off)
749 1.1.2.2 yamt {
750 1.1.2.2 yamt uint32_t *script = adp->script;
751 1.1.2.2 yamt
752 1.1.2.2 yamt /* MOVE target->id >> 24 TO SCNTL3 */
753 1.1.2.2 yamt script[lunsw_off + (Ent_restore_scntl3 / 4)] =
754 1.1.2.2 yamt htoc32(0x78030000 | ((adp->clock_div >> 16) & 0x0000ff00));
755 1.1.2.2 yamt /* MOVE target->id >> 8 TO SXFER */
756 1.1.2.2 yamt script[lunsw_off + (Ent_restore_scntl3 / 4) + 2] =
757 1.1.2.2 yamt htoc32(0x78050000 | (0x000000000 & 0x0000ff00));
758 1.1.2.2 yamt _wbinv((u_long)script, SIOP_SCRIPT_SIZE);
759 1.1.2.2 yamt }
760 1.1.2.2 yamt
761 1.1.2.2 yamt
762 1.1.2.2 yamt /*
763 1.1.2.2 yamt * SCSI functions
764 1.1.2.2 yamt */
765 1.1.2.2 yamt
766 1.1.2.2 yamt static int
767 1.1.2.2 yamt _scsi_inquire(struct siop_adapter *adp, int t, int l, int buflen, char *buf)
768 1.1.2.2 yamt {
769 1.1.2.2 yamt struct scsipi_inquiry *cmd = (struct scsipi_inquiry *)adp->cmd;
770 1.1.2.2 yamt struct scsipi_inquiry_data *inqbuf =
771 1.1.2.2 yamt (struct scsipi_inquiry_data *)adp->data;
772 1.1.2.2 yamt struct scsi_xfer xs;
773 1.1.2.2 yamt int error;
774 1.1.2.2 yamt
775 1.1.2.2 yamt memset(cmd, 0, sizeof(*cmd));
776 1.1.2.2 yamt cmd->opcode = INQUIRY;
777 1.1.2.2 yamt cmd->length = SCSIPI_INQUIRY_LENGTH_SCSI2;
778 1.1.2.2 yamt memset(inqbuf, 0, sizeof(*inqbuf));
779 1.1.2.2 yamt
780 1.1.2.2 yamt memset(&xs, 0, sizeof(xs));
781 1.1.2.2 yamt xs.target = t;
782 1.1.2.2 yamt xs.lun = l;
783 1.1.2.2 yamt xs.cmdlen = sizeof(*cmd);
784 1.1.2.2 yamt xs.cmd = (void *)cmd;
785 1.1.2.2 yamt xs.datalen = SCSIPI_INQUIRY_LENGTH_SCSI2;
786 1.1.2.2 yamt xs.data = (void *)inqbuf;
787 1.1.2.2 yamt
788 1.1.2.2 yamt xs.error = XS_NOERROR;
789 1.1.2.2 yamt xs.resid = xs.datalen;
790 1.1.2.2 yamt xs.status = SCSI_OK;
791 1.1.2.2 yamt
792 1.1.2.2 yamt error = siop_scsi_request(adp, &xs);
793 1.1.2.2 yamt if (error != 0)
794 1.1.2.2 yamt return error;
795 1.1.2.2 yamt
796 1.1.2.2 yamt memcpy(buf, inqbuf, buflen);
797 1.1.2.2 yamt return 0;
798 1.1.2.2 yamt }
799 1.1.2.2 yamt
800 1.1.2.2 yamt static void
801 1.1.2.2 yamt scsi_request_sense(struct siop_adapter *adp, struct scsi_xfer *xs)
802 1.1.2.2 yamt {
803 1.1.2.2 yamt struct scsi_request_sense *cmd = adp->sense;
804 1.1.2.2 yamt struct scsi_sense_data *data = (struct scsi_sense_data *)adp->data;
805 1.1.2.2 yamt struct scsi_xfer sense;
806 1.1.2.2 yamt int error;
807 1.1.2.2 yamt
808 1.1.2.2 yamt memset(cmd, 0, sizeof(struct scsi_request_sense));
809 1.1.2.2 yamt cmd->opcode = SCSI_REQUEST_SENSE;
810 1.1.2.2 yamt cmd->length = sizeof(struct scsi_sense_data);
811 1.1.2.2 yamt memset(data, 0, sizeof(struct scsi_sense_data));
812 1.1.2.2 yamt
813 1.1.2.2 yamt memset(&sense, 0, sizeof(sense));
814 1.1.2.2 yamt sense.target = xs->target;
815 1.1.2.2 yamt sense.lun = xs->lun;
816 1.1.2.2 yamt sense.cmdlen = sizeof(struct scsi_request_sense);
817 1.1.2.2 yamt sense.cmd = (void *)cmd;
818 1.1.2.2 yamt sense.datalen = sizeof(struct scsi_sense_data);
819 1.1.2.2 yamt sense.data = (void *)data;
820 1.1.2.2 yamt
821 1.1.2.2 yamt sense.error = XS_NOERROR;
822 1.1.2.2 yamt sense.resid = sense.datalen;
823 1.1.2.2 yamt sense.status = SCSI_OK;
824 1.1.2.2 yamt
825 1.1.2.2 yamt error = siop_scsi_request(adp, &sense);
826 1.1.2.2 yamt switch (error) {
827 1.1.2.2 yamt case 0:
828 1.1.2.2 yamt /* we have a valid sense */
829 1.1.2.2 yamt xs->error = XS_SENSE;
830 1.1.2.2 yamt return;
831 1.1.2.2 yamt case EINTR:
832 1.1.2.2 yamt /* REQUEST_SENSE interrupted by bus reset. */
833 1.1.2.2 yamt xs->error = XS_RESET;
834 1.1.2.2 yamt return;
835 1.1.2.2 yamt case EIO:
836 1.1.2.2 yamt /* request sense coudn't be performed */
837 1.1.2.2 yamt /*
838 1.1.2.2 yamt * XXX this isn't quite right but we don't have anything
839 1.1.2.2 yamt * better for now
840 1.1.2.2 yamt */
841 1.1.2.2 yamt xs->error = XS_DRIVER_STUFFUP;
842 1.1.2.2 yamt return;
843 1.1.2.2 yamt default:
844 1.1.2.2 yamt /* Notify that request sense failed. */
845 1.1.2.2 yamt xs->error = XS_DRIVER_STUFFUP;
846 1.1.2.2 yamt printf("request sense failed with error %d\n", error);
847 1.1.2.2 yamt return;
848 1.1.2.2 yamt }
849 1.1.2.2 yamt }
850 1.1.2.2 yamt
851 1.1.2.2 yamt /*
852 1.1.2.2 yamt * scsi_interpret_sense:
853 1.1.2.2 yamt *
854 1.1.2.2 yamt * Look at the returned sense and act on the error, determining
855 1.1.2.2 yamt * the unix error number to pass back. (0 = report no error)
856 1.1.2.2 yamt *
857 1.1.2.2 yamt * NOTE: If we return ERESTART, we are expected to haved
858 1.1.2.2 yamt * thawed the device!
859 1.1.2.2 yamt *
860 1.1.2.2 yamt * THIS IS THE DEFAULT ERROR HANDLER FOR SCSI DEVICES.
861 1.1.2.2 yamt */
862 1.1.2.2 yamt static int
863 1.1.2.2 yamt scsi_interpret_sense(struct siop_adapter *adp, struct scsi_xfer *xs)
864 1.1.2.2 yamt {
865 1.1.2.2 yamt struct scsi_sense_data *sense;
866 1.1.2.2 yamt u_int8_t key;
867 1.1.2.2 yamt int error;
868 1.1.2.2 yamt uint32_t info;
869 1.1.2.2 yamt static const char *error_mes[] = {
870 1.1.2.2 yamt "soft error (corrected)",
871 1.1.2.2 yamt "not ready", "medium error",
872 1.1.2.2 yamt "non-media hardware failure", "illegal request",
873 1.1.2.2 yamt "unit attention", "readonly device",
874 1.1.2.2 yamt "no data found", "vendor unique",
875 1.1.2.2 yamt "copy aborted", "command aborted",
876 1.1.2.2 yamt "search returned equal", "volume overflow",
877 1.1.2.2 yamt "verify miscompare", "unknown error key"
878 1.1.2.2 yamt };
879 1.1.2.2 yamt
880 1.1.2.2 yamt sense = (struct scsi_sense_data *)xs->data;
881 1.1.2.2 yamt
882 1.1.2.2 yamt /* otherwise use the default */
883 1.1.2.2 yamt switch (SSD_RCODE(sense->response_code)) {
884 1.1.2.2 yamt
885 1.1.2.2 yamt /*
886 1.1.2.2 yamt * Old SCSI-1 and SASI devices respond with
887 1.1.2.2 yamt * codes other than 70.
888 1.1.2.2 yamt */
889 1.1.2.2 yamt case 0x00: /* no error (command completed OK) */
890 1.1.2.2 yamt return 0;
891 1.1.2.2 yamt case 0x04: /* drive not ready after it was selected */
892 1.1.2.2 yamt if (adp->sd->sc_flags & FLAGS_REMOVABLE)
893 1.1.2.2 yamt adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
894 1.1.2.2 yamt /* XXX - display some sort of error here? */
895 1.1.2.2 yamt return EIO;
896 1.1.2.2 yamt case 0x20: /* invalid command */
897 1.1.2.2 yamt return EINVAL;
898 1.1.2.2 yamt case 0x25: /* invalid LUN (Adaptec ACB-4000) */
899 1.1.2.2 yamt return EACCES;
900 1.1.2.2 yamt
901 1.1.2.2 yamt /*
902 1.1.2.2 yamt * If it's code 70, use the extended stuff and
903 1.1.2.2 yamt * interpret the key
904 1.1.2.2 yamt */
905 1.1.2.2 yamt case 0x71: /* delayed error */
906 1.1.2.2 yamt key = SSD_SENSE_KEY(sense->flags);
907 1.1.2.2 yamt printf(" DEFERRED ERROR, key = 0x%x\n", key);
908 1.1.2.2 yamt /* FALLTHROUGH */
909 1.1.2.2 yamt case 0x70:
910 1.1.2.2 yamt if ((sense->response_code & SSD_RCODE_VALID) != 0)
911 1.1.2.2 yamt info = _4btol(sense->info);
912 1.1.2.2 yamt else
913 1.1.2.2 yamt info = 0;
914 1.1.2.2 yamt key = SSD_SENSE_KEY(sense->flags);
915 1.1.2.2 yamt
916 1.1.2.2 yamt switch (key) {
917 1.1.2.2 yamt case SKEY_NO_SENSE:
918 1.1.2.2 yamt case SKEY_RECOVERED_ERROR:
919 1.1.2.2 yamt if (xs->resid == xs->datalen && xs->datalen) {
920 1.1.2.2 yamt /*
921 1.1.2.2 yamt * Why is this here?
922 1.1.2.2 yamt */
923 1.1.2.2 yamt xs->resid = 0; /* not short read */
924 1.1.2.2 yamt }
925 1.1.2.2 yamt case SKEY_EQUAL:
926 1.1.2.2 yamt error = 0;
927 1.1.2.2 yamt break;
928 1.1.2.2 yamt case SKEY_NOT_READY:
929 1.1.2.2 yamt if (adp->sd->sc_flags & FLAGS_REMOVABLE)
930 1.1.2.2 yamt adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
931 1.1.2.2 yamt if (sense->asc == 0x3A) {
932 1.1.2.2 yamt error = ENODEV; /* Medium not present */
933 1.1.2.2 yamt } else
934 1.1.2.2 yamt error = EIO;
935 1.1.2.2 yamt break;
936 1.1.2.2 yamt case SKEY_ILLEGAL_REQUEST:
937 1.1.2.2 yamt error = EINVAL;
938 1.1.2.2 yamt break;
939 1.1.2.2 yamt case SKEY_UNIT_ATTENTION:
940 1.1.2.2 yamt if (sense->asc == 0x29 &&
941 1.1.2.2 yamt sense->ascq == 0x00) {
942 1.1.2.2 yamt /* device or bus reset */
943 1.1.2.2 yamt return ERESTART;
944 1.1.2.2 yamt }
945 1.1.2.2 yamt if (adp->sd->sc_flags & FLAGS_REMOVABLE)
946 1.1.2.2 yamt adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
947 1.1.2.2 yamt if (!(adp->sd->sc_flags & FLAGS_REMOVABLE))
948 1.1.2.2 yamt return ERESTART;
949 1.1.2.2 yamt error = EIO;
950 1.1.2.2 yamt break;
951 1.1.2.2 yamt case SKEY_DATA_PROTECT:
952 1.1.2.2 yamt error = EROFS;
953 1.1.2.2 yamt break;
954 1.1.2.2 yamt case SKEY_BLANK_CHECK:
955 1.1.2.2 yamt error = 0;
956 1.1.2.2 yamt break;
957 1.1.2.2 yamt case SKEY_ABORTED_COMMAND:
958 1.1.2.2 yamt break;
959 1.1.2.2 yamt case SKEY_VOLUME_OVERFLOW:
960 1.1.2.2 yamt error = ENOSPC;
961 1.1.2.2 yamt break;
962 1.1.2.2 yamt default:
963 1.1.2.2 yamt error = EIO;
964 1.1.2.2 yamt break;
965 1.1.2.2 yamt }
966 1.1.2.2 yamt
967 1.1.2.2 yamt /* Print brief(er) sense information */
968 1.1.2.2 yamt printf("%s", error_mes[key - 1]);
969 1.1.2.2 yamt if ((sense->response_code & SSD_RCODE_VALID) != 0) {
970 1.1.2.2 yamt switch (key) {
971 1.1.2.2 yamt case SKEY_NOT_READY:
972 1.1.2.2 yamt case SKEY_ILLEGAL_REQUEST:
973 1.1.2.2 yamt case SKEY_UNIT_ATTENTION:
974 1.1.2.2 yamt case SKEY_DATA_PROTECT:
975 1.1.2.2 yamt break;
976 1.1.2.2 yamt case SKEY_BLANK_CHECK:
977 1.1.2.2 yamt printf(", requested size: %d (decimal)",
978 1.1.2.2 yamt info);
979 1.1.2.2 yamt break;
980 1.1.2.2 yamt case SKEY_ABORTED_COMMAND:
981 1.1.2.2 yamt printf(", cmd 0x%x, info 0x%x",
982 1.1.2.2 yamt xs->cmd->opcode, info);
983 1.1.2.2 yamt break;
984 1.1.2.2 yamt default:
985 1.1.2.2 yamt printf(", info = %d (decimal)", info);
986 1.1.2.2 yamt }
987 1.1.2.2 yamt }
988 1.1.2.2 yamt if (sense->extra_len != 0) {
989 1.1.2.2 yamt int n;
990 1.1.2.2 yamt printf(", data =");
991 1.1.2.2 yamt for (n = 0; n < sense->extra_len; n++)
992 1.1.2.2 yamt printf(" %x", sense->csi[n]);
993 1.1.2.2 yamt }
994 1.1.2.2 yamt printf("\n");
995 1.1.2.2 yamt return error;
996 1.1.2.2 yamt
997 1.1.2.2 yamt /*
998 1.1.2.2 yamt * Some other code, just report it
999 1.1.2.2 yamt */
1000 1.1.2.2 yamt default:
1001 1.1.2.2 yamt printf("Sense Error Code 0x%x",
1002 1.1.2.2 yamt SSD_RCODE(sense->response_code));
1003 1.1.2.2 yamt if ((sense->response_code & SSD_RCODE_VALID) != 0) {
1004 1.1.2.2 yamt struct scsi_sense_data_unextended *usense =
1005 1.1.2.2 yamt (struct scsi_sense_data_unextended *)sense;
1006 1.1.2.2 yamt printf(" at block no. %d (decimal)",
1007 1.1.2.2 yamt _3btol(usense->block));
1008 1.1.2.2 yamt }
1009 1.1.2.2 yamt printf("\n");
1010 1.1.2.2 yamt return EIO;
1011 1.1.2.2 yamt }
1012 1.1.2.2 yamt }
1013 1.1.2.2 yamt
1014 1.1.2.2 yamt static int
1015 1.1.2.2 yamt scsi_probe(struct siop_adapter *adp)
1016 1.1.2.2 yamt {
1017 1.1.2.2 yamt struct scsipi_inquiry_data *inqbuf;
1018 1.1.2.2 yamt int found, t, l;
1019 1.1.2.2 yamt uint8_t device;
1020 1.1.2.2 yamt char buf[SCSIPI_INQUIRY_LENGTH_SCSI2],
1021 1.1.2.2 yamt product[sizeof(inqbuf->product) + 1];
1022 1.1.2.2 yamt
1023 1.1.2.2 yamt found = 0;
1024 1.1.2.2 yamt for (t = 0; t < 8; t++) {
1025 1.1.2.2 yamt if (t == adp->id)
1026 1.1.2.2 yamt continue;
1027 1.1.2.2 yamt for (l = 0; l < 8; l++) {
1028 1.1.2.2 yamt if (_scsi_inquire(adp, t, l, sizeof(buf), buf) != 0)
1029 1.1.2.2 yamt continue;
1030 1.1.2.2 yamt
1031 1.1.2.2 yamt inqbuf = (struct scsipi_inquiry_data *)buf;
1032 1.1.2.2 yamt device = inqbuf->device & SID_TYPE;
1033 1.1.2.2 yamt if (device == T_NODEVICE)
1034 1.1.2.2 yamt continue;
1035 1.1.2.2 yamt if (device != T_DIRECT &&
1036 1.1.2.2 yamt device != T_OPTICAL &&
1037 1.1.2.2 yamt device != T_SIMPLE_DIRECT)
1038 1.1.2.2 yamt continue;
1039 1.1.2.2 yamt
1040 1.1.2.2 yamt memset(product, 0, sizeof(product));
1041 1.1.2.2 yamt strncpy(product, inqbuf->product, sizeof(product) - 1);
1042 1.1.2.2 yamt printf("sd(%d,%d,[0-7]): <%s>\n", t, l, product);
1043 1.1.2.2 yamt found++;
1044 1.1.2.2 yamt }
1045 1.1.2.2 yamt }
1046 1.1.2.2 yamt return found;
1047 1.1.2.2 yamt }
1048 1.1.2.2 yamt
1049 1.1.2.2 yamt int
1050 1.1.2.2 yamt scsi_inquire(struct sd_softc *sd, int buflen, void *buf)
1051 1.1.2.2 yamt {
1052 1.1.2.2 yamt struct siop_adapter *adp;
1053 1.1.2.2 yamt int error;
1054 1.1.2.2 yamt
1055 1.1.2.2 yamt if (sd->sc_bus != 0)
1056 1.1.2.2 yamt return ENOTSUP;
1057 1.1.2.2 yamt if (adapt.addr == 0xffffffff)
1058 1.1.2.2 yamt return ENOENT;
1059 1.1.2.2 yamt adp = &adapt;
1060 1.1.2.2 yamt
1061 1.1.2.2 yamt adp->sd = sd;
1062 1.1.2.2 yamt error = _scsi_inquire(adp, sd->sc_target, sd->sc_lun, buflen, buf);
1063 1.1.2.2 yamt adp->sd = NULL;
1064 1.1.2.2 yamt
1065 1.1.2.2 yamt return error;
1066 1.1.2.2 yamt }
1067 1.1.2.2 yamt
1068 1.1.2.2 yamt /*
1069 1.1.2.2 yamt * scsi_mode_sense
1070 1.1.2.2 yamt * get a sense page from a device
1071 1.1.2.2 yamt */
1072 1.1.2.2 yamt
1073 1.1.2.2 yamt int
1074 1.1.2.2 yamt scsi_mode_sense(struct sd_softc *sd, int byte2, int page,
1075 1.1.2.2 yamt struct scsi_mode_parameter_header_6 *data, int len)
1076 1.1.2.2 yamt {
1077 1.1.2.2 yamt struct scsi_mode_sense_6 cmd;
1078 1.1.2.2 yamt
1079 1.1.2.2 yamt memset(&cmd, 0, sizeof(cmd));
1080 1.1.2.2 yamt cmd.opcode = SCSI_MODE_SENSE_6;
1081 1.1.2.2 yamt cmd.byte2 = byte2;
1082 1.1.2.2 yamt cmd.page = page;
1083 1.1.2.2 yamt cmd.length = len & 0xff;
1084 1.1.2.2 yamt
1085 1.1.2.2 yamt return scsi_command(sd, (void *)&cmd, sizeof(cmd), (void *)data, len);
1086 1.1.2.2 yamt }
1087 1.1.2.2 yamt
1088 1.1.2.2 yamt int
1089 1.1.2.2 yamt scsi_command(struct sd_softc *sd, void *cmd, int cmdlen, void *data,
1090 1.1.2.2 yamt int datalen)
1091 1.1.2.2 yamt {
1092 1.1.2.2 yamt struct siop_adapter *adp;
1093 1.1.2.2 yamt struct scsi_xfer xs;
1094 1.1.2.2 yamt int error;
1095 1.1.2.2 yamt
1096 1.1.2.2 yamt if (sd->sc_bus != 0)
1097 1.1.2.2 yamt return ENOTSUP;
1098 1.1.2.2 yamt if (adapt.addr == 0xffffffff)
1099 1.1.2.2 yamt return ENOENT;
1100 1.1.2.2 yamt adp = &adapt;
1101 1.1.2.2 yamt
1102 1.1.2.2 yamt memcpy(adp->cmd, cmd, cmdlen);
1103 1.1.2.2 yamt adp->sd = sd;
1104 1.1.2.2 yamt
1105 1.1.2.2 yamt memset(&xs, 0, sizeof(xs));
1106 1.1.2.2 yamt xs.target = sd->sc_target;
1107 1.1.2.2 yamt xs.lun = sd->sc_lun;
1108 1.1.2.2 yamt xs.cmdlen = cmdlen;
1109 1.1.2.2 yamt xs.cmd = adp->cmd;
1110 1.1.2.2 yamt xs.datalen = datalen;
1111 1.1.2.2 yamt xs.data = adp->data;
1112 1.1.2.2 yamt
1113 1.1.2.2 yamt xs.error = XS_NOERROR;
1114 1.1.2.2 yamt xs.resid = datalen;
1115 1.1.2.2 yamt xs.status = SCSI_OK;
1116 1.1.2.2 yamt
1117 1.1.2.2 yamt error = siop_scsi_request(adp, &xs);
1118 1.1.2.2 yamt adp->sd = NULL;
1119 1.1.2.2 yamt if (error != 0)
1120 1.1.2.2 yamt return error;
1121 1.1.2.2 yamt
1122 1.1.2.2 yamt if (datalen > 0)
1123 1.1.2.2 yamt memcpy(data, adp->data, datalen);
1124 1.1.2.2 yamt return 0;
1125 1.1.2.2 yamt }
1126 1.1.2.2 yamt
1127 1.1.2.2 yamt /*
1128 1.1.2.2 yamt * Initialize the device.
1129 1.1.2.2 yamt */
1130 1.1.2.2 yamt int
1131 1.1.2.2 yamt siop_init(int bus, int dev, int func)
1132 1.1.2.2 yamt {
1133 1.1.2.2 yamt struct siop_adapter tmp;
1134 1.1.2.2 yamt struct siop_xfer *xfer;
1135 1.1.2.2 yamt struct scsipi_generic *cmd;
1136 1.1.2.2 yamt struct scsi_request_sense *sense;
1137 1.1.2.2 yamt uint32_t reg;
1138 1.1.2.2 yamt u_long addr;
1139 1.1.2.2 yamt uint32_t *script;
1140 1.1.2.2 yamt int slot, id, i;
1141 1.1.2.2 yamt void *scriptaddr;
1142 1.1.2.2 yamt u_char *data;
1143 1.1.2.2 yamt const int clock_div = 3; /* 53c810 */
1144 1.1.2.2 yamt
1145 1.1.2.2 yamt slot = PCISlotnum(bus, dev, func);
1146 1.1.2.2 yamt if (slot == -1)
1147 1.1.2.2 yamt return ENOENT;
1148 1.1.2.2 yamt
1149 1.1.2.2 yamt addr = PCIAddress(slot, 1, PCI_MAPREG_TYPE_MEM);
1150 1.1.2.2 yamt if (addr == 0xffffffff)
1151 1.1.2.2 yamt return EINVAL;
1152 1.1.2.2 yamt enablePCI(slot, 0, 1, 1);
1153 1.1.2.2 yamt
1154 1.1.2.2 yamt script = ALLOC(uint32_t, SIOP_SCRIPT_SIZE);
1155 1.1.2.2 yamt if (script == NULL)
1156 1.1.2.2 yamt return ENOMEM;
1157 1.1.2.2 yamt scriptaddr = (void *)local_to_PCI((u_long)script);
1158 1.1.2.2 yamt cmd = ALLOC(struct scsipi_generic, SIOP_SCSI_COMMAND_SIZE);
1159 1.1.2.2 yamt if (cmd == NULL)
1160 1.1.2.2 yamt return ENOMEM;
1161 1.1.2.2 yamt sense = ALLOC(struct scsi_request_sense, SIOP_SCSI_COMMAND_SIZE);
1162 1.1.2.2 yamt if (sense == NULL)
1163 1.1.2.2 yamt return ENOMEM;
1164 1.1.2.2 yamt data = ALLOC(u_char, SIOP_SCSI_DATA_SIZE);
1165 1.1.2.2 yamt if (data == NULL)
1166 1.1.2.2 yamt return ENOMEM;
1167 1.1.2.2 yamt xfer = ALLOC(struct siop_xfer, sizeof(struct siop_xfer));
1168 1.1.2.2 yamt if (xfer == NULL)
1169 1.1.2.2 yamt return ENOMEM;
1170 1.1.2.2 yamt siop_xfer_setup(xfer, scriptaddr);
1171 1.1.2.2 yamt
1172 1.1.2.2 yamt id = readb(addr + SIOP_SCID) & SCID_ENCID_MASK;
1173 1.1.2.2 yamt
1174 1.1.2.2 yamt /* reset bus */
1175 1.1.2.2 yamt reg = readb(addr + SIOP_SCNTL1);
1176 1.1.2.2 yamt writeb(addr + SIOP_SCNTL1, reg | SCNTL1_RST);
1177 1.1.2.2 yamt delay(100);
1178 1.1.2.2 yamt writeb(addr + SIOP_SCNTL1, reg);
1179 1.1.2.2 yamt
1180 1.1.2.2 yamt /* reset the chip */
1181 1.1.2.2 yamt writeb(addr + SIOP_ISTAT, ISTAT_SRST);
1182 1.1.2.2 yamt delay(1000);
1183 1.1.2.2 yamt writeb(addr + SIOP_ISTAT, 0);
1184 1.1.2.2 yamt
1185 1.1.2.2 yamt /* init registers */
1186 1.1.2.2 yamt writeb(addr + SIOP_SCNTL0, SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP);
1187 1.1.2.2 yamt writeb(addr + SIOP_SCNTL1, 0);
1188 1.1.2.2 yamt writeb(addr + SIOP_SCNTL3, clock_div);
1189 1.1.2.2 yamt writeb(addr + SIOP_SXFER, 0);
1190 1.1.2.2 yamt writeb(addr + SIOP_DIEN, 0xff);
1191 1.1.2.2 yamt writeb(addr + SIOP_SIEN0, 0xff & ~(SIEN0_CMP | SIEN0_SEL | SIEN0_RSL));
1192 1.1.2.2 yamt writeb(addr + SIOP_SIEN1, 0xff & ~(SIEN1_HTH | SIEN1_GEN));
1193 1.1.2.2 yamt writeb(addr + SIOP_STEST2, 0);
1194 1.1.2.2 yamt writeb(addr + SIOP_STEST3, STEST3_TE);
1195 1.1.2.2 yamt writeb(addr + SIOP_STIME0, (0xb << STIME0_SEL_SHIFT));
1196 1.1.2.2 yamt writeb(addr + SIOP_SCID, id | SCID_RRE);
1197 1.1.2.2 yamt writeb(addr + SIOP_RESPID0, 1 << id);
1198 1.1.2.2 yamt writeb(addr + SIOP_DCNTL, DCNTL_COM);
1199 1.1.2.2 yamt
1200 1.1.2.2 yamt siop_pci_reset(addr);
1201 1.1.2.2 yamt
1202 1.1.2.2 yamt /* copy and patch the script */
1203 1.1.2.2 yamt for (i = 0; i < __arraycount(siop_script); i++)
1204 1.1.2.2 yamt script[i] = htoc32(siop_script[i]);
1205 1.1.2.2 yamt for (i = 0; i < __arraycount(E_abs_msgin_Used); i++)
1206 1.1.2.2 yamt script[E_abs_msgin_Used[i]] =
1207 1.1.2.2 yamt htoc32(scriptaddr + Ent_msgin_space);
1208 1.1.2.2 yamt
1209 1.1.2.2 yamt /* start script */
1210 1.1.2.2 yamt _wbinv((u_long)script, SIOP_SCRIPT_SIZE);
1211 1.1.2.2 yamt writel(addr + SIOP_DSP, (int)scriptaddr + Ent_reselect);
1212 1.1.2.2 yamt
1213 1.1.2.2 yamt memset(&tmp, 0, sizeof(tmp));
1214 1.1.2.2 yamt tmp.id = id;
1215 1.1.2.2 yamt tmp.clock_div = clock_div;
1216 1.1.2.2 yamt tmp.addr = addr;
1217 1.1.2.2 yamt tmp.script = script;
1218 1.1.2.2 yamt tmp.xfer = xfer;
1219 1.1.2.2 yamt tmp.cmd = cmd;
1220 1.1.2.2 yamt tmp.sense = sense;
1221 1.1.2.2 yamt tmp.data = data;
1222 1.1.2.2 yamt tmp.currschedslot = 0;
1223 1.1.2.2 yamt tmp.sel_t = -1;
1224 1.1.2.2 yamt
1225 1.1.2.2 yamt if (scsi_probe(&tmp) == 0) {
1226 1.1.2.2 yamt adapt.addr = 0xffffffff;
1227 1.1.2.2 yamt return ENXIO;
1228 1.1.2.2 yamt }
1229 1.1.2.2 yamt adapt = tmp;
1230 1.1.2.2 yamt return 0;
1231 1.1.2.2 yamt }
1232