1 /**************************************************************************
2 * Initio A100 device driver for Linux.
3 *
4 * Copyright (c) 1994-1998 Initio Corporation
5 * All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING. If not, write to
19 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * --------------------------------------------------------------------------
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions, and the following disclaimer,
28 * without modification, immediately at the beginning of the file.
29 * 2. Redistributions in binary form must reproduce the above copyright
30 * notice, this list of conditions and the following disclaimer in the
31 * documentation and/or other materials provided with the distribution.
32 * 3. The name of the author may not be used to endorse or promote products
33 * derived from this software without specific prior written permission.
34 *
35 * Where this Software is combined with software released under the terms of
36 * the GNU General Public License ("GPL") and the terms of the GPL would require the
37 * combined work to also be released under the terms of the GPL, the terms
38 * and conditions of this License will apply in addition to those of the
39 * GPL with the exception of any terms or conditions of this License that
40 * conflict with, or are expressly prohibited by, the GPL.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
46 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 *
54 *************************************************************************
55 *
56 * module: i60uscsi.c
57 * DESCRIPTION:
58 * This is the Linux low-level SCSI driver for Initio INIA100 SCSI host
59 * adapters
60 *
61 * 07/02/98 hl - v.91n Initial drivers.
62 * 09/14/98 hl - v1.01 Support new Kernel.
63 * 09/22/98 hl - v1.01a Support reset.
64 * 09/24/98 hl - v1.01b Fixed reset.
65 * 10/05/98 hl - v1.02 split the source code and release.
66 * 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up
67 * 01/31/99 bv - v1.02b Use mdelay instead of waitForPause
68 * 08/08/99 bv - v1.02c Use waitForPause again.
69 **************************************************************************/
70
71 #include <linux/version.h>
72 #include <linux/sched.h>
73 #include <asm/io.h>
74 #include "i60uscsi.h"
75
76 #define JIFFIES_TO_MS(t) ((t) * 1000 / HZ)
77 #define MS_TO_JIFFIES(j) ((j * HZ) / 1000)
78
79 /* ---- INTERNAL FUNCTIONS ---- */
80 static UCHAR waitChipReady(ORC_HCS * hcsp);
81 static UCHAR waitFWReady(ORC_HCS * hcsp);
82 static UCHAR waitFWReady(ORC_HCS * hcsp);
83 static UCHAR waitSCSIRSTdone(ORC_HCS * hcsp);
84 static UCHAR waitHDOoff(ORC_HCS * hcsp);
85 static UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData);
86 static unsigned short get_FW_version(ORC_HCS * hcsp);
87 static UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value);
88 static UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn);
89 static int se2_rd_all(ORC_HCS * hcsp);
90 static void se2_update_all(ORC_HCS * hcsp); /* setup default pattern */
91 static void read_eeprom(ORC_HCS * hcsp);
92 static UCHAR load_FW(ORC_HCS * hcsp);
93 static void setup_SCBs(ORC_HCS * hcsp);
94 static void initAFlag(ORC_HCS * hcsp);
95 ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
96
97 /* ---- EXTERNAL FUNCTIONS ---- */
98 extern void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
99
100 /* ---- INTERNAL VARIABLES ---- */
101 ORC_HCS orc_hcs[MAX_SUPPORTED_ADAPTERS];
102 static INIA100_ADPT_STRUCT inia100_adpt[MAX_SUPPORTED_ADAPTERS];
103 /* set by inia100_setup according to the command line */
104 int orc_num_scb;
105
106 NVRAM nvram, *nvramp = &nvram;
107 static UCHAR dftNvRam[64] =
108 {
109 /*----------header -------------*/
110 0x01, /* 0x00: Sub System Vendor ID 0 */
111 0x11, /* 0x01: Sub System Vendor ID 1 */
112 0x60, /* 0x02: Sub System ID 0 */
113 0x10, /* 0x03: Sub System ID 1 */
114 0x00, /* 0x04: SubClass */
115 0x01, /* 0x05: Vendor ID 0 */
116 0x11, /* 0x06: Vendor ID 1 */
117 0x60, /* 0x07: Device ID 0 */
118 0x10, /* 0x08: Device ID 1 */
119 0x00, /* 0x09: Reserved */
120 0x00, /* 0x0A: Reserved */
121 0x01, /* 0x0B: Revision of Data Structure */
122 /* -- Host Adapter Structure --- */
123 0x01, /* 0x0C: Number Of SCSI Channel */
124 0x01, /* 0x0D: BIOS Configuration 1 */
125 0x00, /* 0x0E: BIOS Configuration 2 */
126 0x00, /* 0x0F: BIOS Configuration 3 */
127 /* --- SCSI Channel 0 Configuration --- */
128 0x07, /* 0x10: H/A ID */
129 0x83, /* 0x11: Channel Configuration */
130 0x20, /* 0x12: MAX TAG per target */
131 0x0A, /* 0x13: SCSI Reset Recovering time */
132 0x00, /* 0x14: Channel Configuration4 */
133 0x00, /* 0x15: Channel Configuration5 */
134 /* SCSI Channel 0 Target Configuration */
135 /* 0x16-0x25 */
136 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
137 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
138 /* --- SCSI Channel 1 Configuration --- */
139 0x07, /* 0x26: H/A ID */
140 0x83, /* 0x27: Channel Configuration */
141 0x20, /* 0x28: MAX TAG per target */
142 0x0A, /* 0x29: SCSI Reset Recovering time */
143 0x00, /* 0x2A: Channel Configuration4 */
144 0x00, /* 0x2B: Channel Configuration5 */
145 /* SCSI Channel 1 Target Configuration */
146 /* 0x2C-0x3B */
147 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
148 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
149 0x00, /* 0x3C: Reserved */
150 0x00, /* 0x3D: Reserved */
151 0x00, /* 0x3E: Reserved */
152 0x00 /* 0x3F: Checksum */
153 };
154
155
156 /***************************************************************************/
waitForPause(unsigned amount)157 static void waitForPause(unsigned amount)
158 {
159 ULONG the_time = jiffies + MS_TO_JIFFIES(amount);
160 while (time_before_eq(jiffies, the_time))
161 cpu_relax();
162 }
163
164 /***************************************************************************/
waitChipReady(ORC_HCS * hcsp)165 UCHAR waitChipReady(ORC_HCS * hcsp)
166 {
167 int i;
168
169 for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */
170 if (ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HOSTSTOP) /* Wait HOSTSTOP set */
171 return (TRUE);
172 waitForPause(100); /* wait 100ms before try again */
173 }
174 return (FALSE);
175 }
176
177 /***************************************************************************/
waitFWReady(ORC_HCS * hcsp)178 UCHAR waitFWReady(ORC_HCS * hcsp)
179 {
180 int i;
181
182 for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */
183 if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) /* Wait READY set */
184 return (TRUE);
185 waitForPause(100); /* wait 100ms before try again */
186 }
187 return (FALSE);
188 }
189
190 /***************************************************************************/
waitSCSIRSTdone(ORC_HCS * hcsp)191 UCHAR waitSCSIRSTdone(ORC_HCS * hcsp)
192 {
193 int i;
194
195 for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */
196 if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & SCSIRST)) /* Wait SCSIRST done */
197 return (TRUE);
198 waitForPause(100); /* wait 100ms before try again */
199 }
200 return (FALSE);
201 }
202
203 /***************************************************************************/
waitHDOoff(ORC_HCS * hcsp)204 UCHAR waitHDOoff(ORC_HCS * hcsp)
205 {
206 int i;
207
208 for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */
209 if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HDO)) /* Wait HDO off */
210 return (TRUE);
211 waitForPause(100); /* wait 100ms before try again */
212 }
213 return (FALSE);
214 }
215
216 /***************************************************************************/
waitHDIset(ORC_HCS * hcsp,UCHAR * pData)217 UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData)
218 {
219 int i;
220
221 for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */
222 if ((*pData = ORC_RD(hcsp->HCS_Base, ORC_HSTUS)) & HDI)
223 return (TRUE); /* Wait HDI set */
224 waitForPause(100); /* wait 100ms before try again */
225 }
226 return (FALSE);
227 }
228
229 /***************************************************************************/
get_FW_version(ORC_HCS * hcsp)230 unsigned short get_FW_version(ORC_HCS * hcsp)
231 {
232 UCHAR bData;
233 union {
234 unsigned short sVersion;
235 unsigned char cVersion[2];
236 } Version;
237
238 ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_VERSION);
239 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
240 if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
241 return (FALSE);
242
243 if (waitHDIset(hcsp, &bData) == FALSE) /* Wait HDI set */
244 return (FALSE);
245 Version.cVersion[0] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
246 ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */
247
248 if (waitHDIset(hcsp, &bData) == FALSE) /* Wait HDI set */
249 return (FALSE);
250 Version.cVersion[1] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
251 ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */
252
253 return (Version.sVersion);
254 }
255
256 /***************************************************************************/
set_NVRAM(ORC_HCS * hcsp,unsigned char address,unsigned char value)257 UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value)
258 {
259 ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_SET_NVM); /* Write command */
260 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
261 if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
262 return (FALSE);
263
264 ORC_WR(hcsp->HCS_Base + ORC_HDATA, address); /* Write address */
265 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
266 if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
267 return (FALSE);
268
269 ORC_WR(hcsp->HCS_Base + ORC_HDATA, value); /* Write value */
270 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
271 if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
272 return (FALSE);
273
274 return (TRUE);
275 }
276
277 /***************************************************************************/
get_NVRAM(ORC_HCS * hcsp,unsigned char address,unsigned char * pDataIn)278 UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn)
279 {
280 unsigned char bData;
281
282 ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_GET_NVM); /* Write command */
283 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
284 if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
285 return (FALSE);
286
287 ORC_WR(hcsp->HCS_Base + ORC_HDATA, address); /* Write address */
288 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
289 if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
290 return (FALSE);
291
292 if (waitHDIset(hcsp, &bData) == FALSE) /* Wait HDI set */
293 return (FALSE);
294 *pDataIn = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
295 ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */
296
297 return (TRUE);
298 }
299
300 /***************************************************************************/
orc_exec_scb(ORC_HCS * hcsp,ORC_SCB * scbp)301 void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
302 {
303 scbp->SCB_Status = SCB_POST;
304 ORC_WR(hcsp->HCS_Base + ORC_PQUEUE, scbp->SCB_ScbIdx);
305 return;
306 }
307
308
309 /***********************************************************************
310 Read SCSI H/A configuration parameters from serial EEPROM
311 ************************************************************************/
se2_rd_all(ORC_HCS * hcsp)312 int se2_rd_all(ORC_HCS * hcsp)
313 {
314 int i;
315 UCHAR *np, chksum = 0;
316
317 np = (UCHAR *) nvramp;
318 for (i = 0; i < 64; i++, np++) { /* <01> */
319 if (get_NVRAM(hcsp, (unsigned char) i, np) == FALSE)
320 return -1;
321 // *np++ = get_NVRAM(hcsp, (unsigned char ) i);
322 }
323
324 /*------ Is ckecksum ok ? ------*/
325 np = (UCHAR *) nvramp;
326 for (i = 0; i < 63; i++)
327 chksum += *np++;
328
329 if (nvramp->CheckSum != (UCHAR) chksum)
330 return -1;
331 return 1;
332 }
333
334 /************************************************************************
335 Update SCSI H/A configuration parameters from serial EEPROM
336 *************************************************************************/
se2_update_all(ORC_HCS * hcsp)337 void se2_update_all(ORC_HCS * hcsp)
338 { /* setup default pattern */
339 int i;
340 UCHAR *np, *np1, chksum = 0;
341
342 /* Calculate checksum first */
343 np = (UCHAR *) dftNvRam;
344 for (i = 0; i < 63; i++)
345 chksum += *np++;
346 *np = chksum;
347
348 np = (UCHAR *) dftNvRam;
349 np1 = (UCHAR *) nvramp;
350 for (i = 0; i < 64; i++, np++, np1++) {
351 if (*np != *np1) {
352 set_NVRAM(hcsp, (unsigned char) i, *np);
353 }
354 }
355 return;
356 }
357
358 /*************************************************************************
359 Function name : read_eeprom
360 **************************************************************************/
read_eeprom(ORC_HCS * hcsp)361 void read_eeprom(ORC_HCS * hcsp)
362 {
363 if (se2_rd_all(hcsp) != 1) {
364 se2_update_all(hcsp); /* setup default pattern */
365 se2_rd_all(hcsp); /* load again */
366 }
367 }
368
369
370 /***************************************************************************/
load_FW(ORC_HCS * hcsp)371 UCHAR load_FW(ORC_HCS * hcsp)
372 {
373 U32 dData;
374 USHORT wBIOSAddress;
375 USHORT i;
376 UCHAR *pData, bData;
377
378
379 bData = ORC_RD(hcsp->HCS_Base, ORC_GCFG);
380 ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData | EEPRG); /* Enable EEPROM programming */
381 ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, 0x00);
382 ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x00);
383 if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0x55) {
384 ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /* Disable EEPROM programming */
385 return (FALSE);
386 }
387 ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x01);
388 if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0xAA) {
389 ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /* Disable EEPROM programming */
390 return (FALSE);
391 }
392 ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD); /* Enable SRAM programming */
393 pData = (UCHAR *) & dData;
394 dData = 0; /* Initial FW address to 0 */
395 ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x10);
396 *pData = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */
397 ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x11);
398 *(pData + 1) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */
399 ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x12);
400 *(pData + 2) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */
401 ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, *(pData + 2));
402 ORC_WRLONG(hcsp->HCS_Base + ORC_FWBASEADR, dData); /* Write FW address */
403
404 wBIOSAddress = (USHORT) dData; /* FW code locate at BIOS address + ? */
405 for (i = 0, pData = (UCHAR *) & dData; /* Download the code */
406 i < 0x1000; /* Firmware code size = 4K */
407 i++, wBIOSAddress++) {
408 ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
409 *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */
410 if ((i % 4) == 3) {
411 ORC_WRLONG(hcsp->HCS_Base + ORC_RISCRAM, dData); /* Write every 4 bytes */
412 pData = (UCHAR *) & dData;
413 }
414 }
415
416 ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD); /* Reset program count 0 */
417 wBIOSAddress -= 0x1000; /* Reset the BIOS adddress */
418 for (i = 0, pData = (UCHAR *) & dData; /* Check the code */
419 i < 0x1000; /* Firmware code size = 4K */
420 i++, wBIOSAddress++) {
421 ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
422 *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */
423 if ((i % 4) == 3) {
424 if (ORC_RDLONG(hcsp->HCS_Base, ORC_RISCRAM) != dData) {
425 ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST); /* Reset program to 0 */
426 ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /*Disable EEPROM programming */
427 return (FALSE);
428 }
429 pData = (UCHAR *) & dData;
430 }
431 }
432 ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST); /* Reset program to 0 */
433 ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /* Disable EEPROM programming */
434 return (TRUE);
435 }
436
437 /***************************************************************************/
setup_SCBs(ORC_HCS * hcsp)438 void setup_SCBs(ORC_HCS * hcsp)
439 {
440 ORC_SCB *pVirScb;
441 int i;
442 UCHAR j;
443 ESCB *pVirEscb;
444 PVOID pPhysEscb;
445 PVOID tPhysEscb;
446
447 j = 0;
448 pVirScb = NULL;
449 tPhysEscb = (PVOID) NULL;
450 pPhysEscb = (PVOID) NULL;
451 /* Setup SCB HCS_Base and SCB Size registers */
452 ORC_WR(hcsp->HCS_Base + ORC_SCBSIZE, orc_num_scb); /* Total number of SCBs */
453 /* SCB HCS_Base address 0 */
454 ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE0, hcsp->HCS_physScbArray);
455 /* SCB HCS_Base address 1 */
456 ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE1, hcsp->HCS_physScbArray);
457
458 /* setup scatter list address with one buffer */
459 pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
460 pVirEscb = (ESCB *) hcsp->HCS_virEscbArray;
461
462 for (i = 0; i < orc_num_scb; i++) {
463 pPhysEscb = (PVOID) (hcsp->HCS_physEscbArray + (sizeof(ESCB) * i));
464 pVirScb->SCB_SGPAddr = (U32) pPhysEscb;
465 pVirScb->SCB_SensePAddr = (U32) pPhysEscb;
466 pVirScb->SCB_EScb = pVirEscb;
467 pVirScb->SCB_ScbIdx = i;
468 pVirScb++;
469 pVirEscb++;
470 }
471
472 return;
473 }
474
475 /***************************************************************************/
initAFlag(ORC_HCS * hcsp)476 static void initAFlag(ORC_HCS * hcsp)
477 {
478 UCHAR i, j;
479
480 for (i = 0; i < MAX_CHANNELS; i++) {
481 for (j = 0; j < 8; j++) {
482 hcsp->BitAllocFlag[i][j] = 0xffffffff;
483 }
484 }
485 }
486
487 /***************************************************************************/
init_orchid(ORC_HCS * hcsp)488 int init_orchid(ORC_HCS * hcsp)
489 {
490 UBYTE *readBytep;
491 USHORT revision;
492 UCHAR i;
493
494 initAFlag(hcsp);
495 ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFF); /* Disable all interrupt */
496 if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) { /* Orchid is ready */
497 revision = get_FW_version(hcsp);
498 if (revision == 0xFFFF) {
499 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST); /* Reset Host Adapter */
500 if (waitChipReady(hcsp) == FALSE)
501 return (-1);
502 load_FW(hcsp); /* Download FW */
503 setup_SCBs(hcsp); /* Setup SCB HCS_Base and SCB Size registers */
504 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, 0); /* clear HOSTSTOP */
505 if (waitFWReady(hcsp) == FALSE)
506 return (-1);
507 /* Wait for firmware ready */
508 } else {
509 setup_SCBs(hcsp); /* Setup SCB HCS_Base and SCB Size registers */
510 }
511 } else { /* Orchid is not Ready */
512 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST); /* Reset Host Adapter */
513 if (waitChipReady(hcsp) == FALSE)
514 return (-1);
515 load_FW(hcsp); /* Download FW */
516 setup_SCBs(hcsp); /* Setup SCB HCS_Base and SCB Size registers */
517 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); /* Do Hardware Reset & */
518
519 /* clear HOSTSTOP */
520 if (waitFWReady(hcsp) == FALSE) /* Wait for firmware ready */
521 return (-1);
522 }
523
524 /*------------- get serial EEProm settting -------*/
525
526 read_eeprom(hcsp);
527
528 if (nvramp->Revision != 1)
529 return (-1);
530
531 hcsp->HCS_SCSI_ID = nvramp->SCSI0Id;
532 hcsp->HCS_BIOS = nvramp->BIOSConfig1;
533 hcsp->HCS_MaxTar = MAX_TARGETS;
534 readBytep = (UCHAR *) & (nvramp->Target00Config);
535 for (i = 0; i < 16; readBytep++, i++) {
536 hcsp->TargetFlag[i] = *readBytep;
537 hcsp->MaximumTags[i] = orc_num_scb;
538 } /* for */
539
540 if (nvramp->SCSI0Config & NCC_BUSRESET) { /* Reset SCSI bus */
541 hcsp->HCS_Flags |= HCF_SCSI_RESET;
542 }
543 ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFB); /* enable RP FIFO interrupt */
544 return (0);
545 }
546
547 /*****************************************************************************
548 Function name : orc_reset_scsi_bus
549 Description : Reset registers, reset a hanging bus and
550 kill active and disconnected commands for target w/o soft reset
551 Input : pHCB - Pointer to host adapter structure
552 Output : None.
553 Return : pSRB - Pointer to SCSI request block.
554 *****************************************************************************/
orc_reset_scsi_bus(ORC_HCS * pHCB)555 int orc_reset_scsi_bus(ORC_HCS * pHCB)
556 { /* I need Host Control Block Information */
557 ULONG flags;
558
559 spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
560
561 initAFlag(pHCB);
562 /* reset scsi bus */
563 ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST);
564 if (waitSCSIRSTdone(pHCB) == FALSE) {
565 spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
566 return (SCSI_RESET_ERROR);
567 } else {
568 spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
569 return (SCSI_RESET_SUCCESS);
570 }
571 }
572
573 /*****************************************************************************
574 Function name : orc_device_reset
575 Description : Reset registers, reset a hanging bus and
576 kill active and disconnected commands for target w/o soft reset
577 Input : pHCB - Pointer to host adapter structure
578 Output : None.
579 Return : pSRB - Pointer to SCSI request block.
580 *****************************************************************************/
orc_device_reset(ORC_HCS * pHCB,ULONG SCpnt,unsigned int target,unsigned int ResetFlags)581 int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned int ResetFlags)
582 { /* I need Host Control Block Information */
583 ORC_SCB *pScb;
584 ESCB *pVirEscb;
585 ORC_SCB *pVirScb;
586 UCHAR i;
587 ULONG flags;
588
589 spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
590 pScb = (ORC_SCB *) NULL;
591 pVirEscb = (ESCB *) NULL;
592
593 /* setup scatter list address with one buffer */
594 pVirScb = (ORC_SCB *) pHCB->HCS_virScbArray;
595
596 initAFlag(pHCB);
597 /* device reset */
598 for (i = 0; i < orc_num_scb; i++) {
599 pVirEscb = pVirScb->SCB_EScb;
600 if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt))
601 break;
602 pVirScb++;
603 }
604
605 if (i == orc_num_scb) {
606 printk("Unable to Reset - No SCB Found\n");
607 spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
608 return (SCSI_RESET_NOT_RUNNING);
609 }
610 if ((pScb = orc_alloc_scb(pHCB)) == NULL) {
611 spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
612 return (SCSI_RESET_NOT_RUNNING);
613 }
614 pScb->SCB_Opcode = ORC_BUSDEVRST;
615 pScb->SCB_Target = target;
616 pScb->SCB_HaStat = 0;
617 pScb->SCB_TaStat = 0;
618 pScb->SCB_Status = 0x0;
619 pScb->SCB_Link = 0xFF;
620 pScb->SCB_Reserved0 = 0;
621 pScb->SCB_Reserved1 = 0;
622 pScb->SCB_XferLen = 0;
623 pScb->SCB_SGLen = 0;
624
625 pVirEscb->SCB_Srb = 0;
626 if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
627 pVirEscb->SCB_Srb = (unsigned char *) SCpnt;
628 }
629 orc_exec_scb(pHCB, pScb); /* Start execute SCB */
630 spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
631 return SCSI_RESET_PENDING;
632 }
633
634
635 /***************************************************************************/
__orc_alloc_scb(ORC_HCS * hcsp)636 ORC_SCB *__orc_alloc_scb(ORC_HCS * hcsp)
637 {
638 ORC_SCB *pTmpScb;
639 UCHAR Ch;
640 ULONG idx;
641 UCHAR index;
642 UCHAR i;
643
644 Ch = hcsp->HCS_Index;
645 for (i = 0; i < 8; i++) {
646 for (index = 0; index < 32; index++) {
647 if ((hcsp->BitAllocFlag[Ch][i] >> index) & 0x01) {
648 hcsp->BitAllocFlag[Ch][i] &= ~(1 << index);
649 break;
650 }
651 }
652 idx = index + 32 * i;
653 pTmpScb = (PVOID) ((ULONG) hcsp->HCS_virScbArray + (idx * sizeof(ORC_SCB)));
654 return (pTmpScb);
655 }
656 return (NULL);
657 }
658
orc_alloc_scb(ORC_HCS * hcsp)659 ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp)
660 {
661 ORC_SCB *pTmpScb;
662 ULONG flags;
663
664 spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
665 pTmpScb = __orc_alloc_scb(hcsp);
666 spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
667 return (pTmpScb);
668 }
669
670
671 /***************************************************************************/
orc_release_scb(ORC_HCS * hcsp,ORC_SCB * scbp)672 void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
673 {
674 ULONG flags;
675 UCHAR Index;
676 UCHAR i;
677 UCHAR Ch;
678
679 spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
680 Ch = hcsp->HCS_Index;
681 Index = scbp->SCB_ScbIdx;
682 i = Index / 32;
683 Index %= 32;
684 hcsp->BitAllocFlag[Ch][i] |= (1 << Index);
685 spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
686 }
687
688
689 /*****************************************************************************
690 Function name : Addinia100_into_Adapter_table
691 Description : This function will scan PCI bus to get all Orchid card
692 Input : None.
693 Output : None.
694 Return : SUCCESSFUL - Successful scan
695 ohterwise - No drives founded
696 *****************************************************************************/
Addinia100_into_Adapter_table(WORD wBIOS,WORD wBASE,BYTE bInterrupt,BYTE bBus,BYTE bDevice)697 int Addinia100_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
698 BYTE bBus, BYTE bDevice)
699 {
700 unsigned int i, j;
701
702 for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
703 if (inia100_adpt[i].ADPT_BIOS < wBIOS)
704 continue;
705 if (inia100_adpt[i].ADPT_BIOS == wBIOS) {
706 if (inia100_adpt[i].ADPT_BASE == wBASE) {
707 if (inia100_adpt[i].ADPT_Bus != 0xFF)
708 return (FAILURE);
709 } else if (inia100_adpt[i].ADPT_BASE < wBASE)
710 continue;
711 }
712 for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
713 inia100_adpt[j].ADPT_BASE = inia100_adpt[j - 1].ADPT_BASE;
714 inia100_adpt[j].ADPT_INTR = inia100_adpt[j - 1].ADPT_INTR;
715 inia100_adpt[j].ADPT_BIOS = inia100_adpt[j - 1].ADPT_BIOS;
716 inia100_adpt[j].ADPT_Bus = inia100_adpt[j - 1].ADPT_Bus;
717 inia100_adpt[j].ADPT_Device = inia100_adpt[j - 1].ADPT_Device;
718 }
719 inia100_adpt[i].ADPT_BASE = wBASE;
720 inia100_adpt[i].ADPT_INTR = bInterrupt;
721 inia100_adpt[i].ADPT_BIOS = wBIOS;
722 inia100_adpt[i].ADPT_Bus = bBus;
723 inia100_adpt[i].ADPT_Device = bDevice;
724 return (SUCCESSFUL);
725 }
726 return (FAILURE);
727 }
728
729
730 /*****************************************************************************
731 Function name : init_inia100Adapter_table
732 Description : This function will scan PCI bus to get all Orchid card
733 Input : None.
734 Output : None.
735 Return : SUCCESSFUL - Successful scan
736 ohterwise - No drives founded
737 *****************************************************************************/
init_inia100Adapter_table(void)738 void init_inia100Adapter_table(void)
739 {
740 int i;
741
742 for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { /* Initialize adapter structure */
743 inia100_adpt[i].ADPT_BIOS = 0xffff;
744 inia100_adpt[i].ADPT_BASE = 0xffff;
745 inia100_adpt[i].ADPT_INTR = 0xff;
746 inia100_adpt[i].ADPT_Bus = 0xff;
747 inia100_adpt[i].ADPT_Device = 0xff;
748 }
749 }
750
751 /*****************************************************************************
752 Function name : get_orcPCIConfig
753 Description :
754 Input : pHCB - Pointer to host adapter structure
755 Output : None.
756 Return : pSRB - Pointer to SCSI request block.
757 *****************************************************************************/
get_orcPCIConfig(ORC_HCS * pCurHcb,int ch_idx)758 void get_orcPCIConfig(ORC_HCS * pCurHcb, int ch_idx)
759 {
760 pCurHcb->HCS_Base = inia100_adpt[ch_idx].ADPT_BASE; /* Supply base address */
761 pCurHcb->HCS_BIOS = inia100_adpt[ch_idx].ADPT_BIOS; /* Supply BIOS address */
762 pCurHcb->HCS_Intr = inia100_adpt[ch_idx].ADPT_INTR; /* Supply interrupt line */
763 return;
764 }
765
766
767 /*****************************************************************************
768 Function name : abort_SCB
769 Description : Abort a queued command.
770 (commands that are on the bus can't be aborted easily)
771 Input : pHCB - Pointer to host adapter structure
772 Output : None.
773 Return : pSRB - Pointer to SCSI request block.
774 *****************************************************************************/
abort_SCB(ORC_HCS * hcsp,ORC_SCB * pScb)775 int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb)
776 {
777 unsigned char bData, bStatus;
778
779 ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_ABORT_SCB); /* Write command */
780 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
781 if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
782 return (FALSE);
783
784 ORC_WR(hcsp->HCS_Base + ORC_HDATA, pScb->SCB_ScbIdx); /* Write address */
785 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
786 if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
787 return (FALSE);
788
789 if (waitHDIset(hcsp, &bData) == FALSE) /* Wait HDI set */
790 return (FALSE);
791 bStatus = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
792 ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */
793
794 if (bStatus == 1) /* 0 - Successfully */
795 return (FALSE); /* 1 - Fail */
796 return (TRUE);
797 }
798
799 /*****************************************************************************
800 Function name : inia100_abort
801 Description : Abort a queued command.
802 (commands that are on the bus can't be aborted easily)
803 Input : pHCB - Pointer to host adapter structure
804 Output : None.
805 Return : pSRB - Pointer to SCSI request block.
806 *****************************************************************************/
orc_abort_srb(ORC_HCS * hcsp,ULONG SCpnt)807 int orc_abort_srb(ORC_HCS * hcsp, ULONG SCpnt)
808 {
809 ESCB *pVirEscb;
810 ORC_SCB *pVirScb;
811 UCHAR i;
812 ULONG flags;
813
814 spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
815
816 pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
817
818 for (i = 0; i < orc_num_scb; i++, pVirScb++) {
819 pVirEscb = pVirScb->SCB_EScb;
820 if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt)) {
821 if (pVirScb->SCB_TagMsg == 0) {
822 spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
823 return (SCSI_ABORT_BUSY);
824 } else {
825 if (abort_SCB(hcsp, pVirScb)) {
826 pVirEscb->SCB_Srb = NULL;
827 spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
828 return (SCSI_ABORT_SUCCESS);
829 } else {
830 spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
831 return (SCSI_ABORT_NOT_RUNNING);
832 }
833 }
834 }
835 }
836 spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
837 return (SCSI_ABORT_NOT_RUNNING);
838 }
839
840 /***********************************************************************
841 Routine Description:
842 This is the interrupt service routine for the Orchid SCSI adapter.
843 It reads the interrupt register to determine if the adapter is indeed
844 the source of the interrupt and clears the interrupt at the device.
845 Arguments:
846 HwDeviceExtension - HBA miniport driver's adapter data storage
847 Return Value:
848 ***********************************************************************/
orc_interrupt(ORC_HCS * hcsp)849 void orc_interrupt(
850 ORC_HCS * hcsp
851 )
852 {
853 BYTE bScbIdx;
854 ORC_SCB *pScb;
855
856 if (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT) == 0) {
857 return; // (FALSE);
858
859 }
860 do {
861 bScbIdx = ORC_RD(hcsp->HCS_Base, ORC_RQUEUE);
862
863 pScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (ULONG) (sizeof(ORC_SCB) * bScbIdx));
864 pScb->SCB_Status = 0x0;
865
866 inia100SCBPost((BYTE *) hcsp, (BYTE *) pScb);
867 } while (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT));
868 return; //(TRUE);
869
870 } /* End of I1060Interrupt() */
871