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