📄 i91uscsi.c
字号:
/************************************************************************** * Initio 9100 device driver for Linux. * * Copyright (c) 1994-1998 Initio Corporation * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl> * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * -------------------------------------------------------------------------- * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * Where this Software is combined with software released under the terms of * the GNU General Public License ("GPL") and the terms of the GPL would require the * combined work to also be released under the terms of the GPL, the terms * and conditions of this License will apply in addition to those of the * GPL with the exception of any terms or conditions of this License that * conflict with, or are expressly prohibited by, the GPL. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ************************************************************************ Module: i91uscsi.c Description: PCI I/F for INI-910 SCSI Bus Master Controller Revision History: 11/09/94 Tim Chen, Initiali Version 0.90A 01/17/95 TC, release ver 1.01 02/09/95 TC modify ReadPCIConfig, try both mechanisms; 02/15/95 TC add support for INI-9100W 06/04/96 HC, Change to fit LINUX from jaspci.c 11/18/96 HC, Port for tulip 07/08/98 hc, Support 0002134A 07/23/98 wh, Change the abort_srb routine. 09/16/98 hl, Support ALPHA, Rewrite the returnNumberAdapters <01> 12/09/98 bv, Removed unused code, changed tul_se2_wait to use udelay(30) and tul_do_pause to enable interrupts for >= 2.1.95 12/13/98 bv, Use spinlocks instead of cli() for serialized access to HCS_Semaph, HCS_FirstAvail and HCS_LastAvail members of the HCS structure. 01/09/98 bv, Fix a deadlock on SMP system.**********************************************************************/#define DEBUG_INTERRUPT 0#define DEBUG_QUEUE 0#define DEBUG_STATE 0#define INT_DISC 0#ifndef CVT_LINUX_VERSION#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S)#endif#ifndef LINUX_VERSION_CODE#include <linux/version.h>#endif#include <linux/sched.h>#include <linux/delay.h>#include <linux/blk.h>#include <asm/io.h>#include "i91uscsi.h"/*--- external functions --*/static void tul_se2_wait(void);/*--- forward refrence ---*/static SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun);static SCB *tul_find_done_scb(HCS * pCurHcb);static int tulip_main(HCS * pCurHcb);static int tul_next_state(HCS * pCurHcb);static int tul_state_1(HCS * pCurHcb);static int tul_state_2(HCS * pCurHcb);static int tul_state_3(HCS * pCurHcb);static int tul_state_4(HCS * pCurHcb);static int tul_state_5(HCS * pCurHcb);static int tul_state_6(HCS * pCurHcb);static int tul_state_7(HCS * pCurHcb);static int tul_xfer_data_in(HCS * pCurHcb);static int tul_xfer_data_out(HCS * pCurHcb);static int tul_xpad_in(HCS * pCurHcb);static int tul_xpad_out(HCS * pCurHcb);static int tul_status_msg(HCS * pCurHcb);static int tul_msgin(HCS * pCurHcb);static int tul_msgin_sync(HCS * pCurHcb);static int tul_msgin_accept(HCS * pCurHcb);static int tul_msgout_reject(HCS * pCurHcb);static int tul_msgin_extend(HCS * pCurHcb);static int tul_msgout_ide(HCS * pCurHcb);static int tul_msgout_abort_targ(HCS * pCurHcb);static int tul_msgout_abort_tag(HCS * pCurHcb);static int tul_bus_device_reset(HCS * pCurHcb);static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb);static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb);static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb);static int int_tul_busfree(HCS * pCurHcb);int int_tul_scsi_rst(HCS * pCurHcb);static int int_tul_bad_seq(HCS * pCurHcb);static int int_tul_resel(HCS * pCurHcb);static int tul_sync_done(HCS * pCurHcb);static int wdtr_done(HCS * pCurHcb);static int wait_tulip(HCS * pCurHcb);static int tul_wait_done_disc(HCS * pCurHcb);static int tul_wait_disc(HCS * pCurHcb);static void tulip_scsi(HCS * pCurHcb);static int tul_post_scsi_rst(HCS * pCurHcb);static void tul_se2_ew_en(WORD CurBase);static void tul_se2_ew_ds(WORD CurBase);static int tul_se2_rd_all(WORD CurBase);static void tul_se2_update_all(WORD CurBase); /* setup default pattern */static void tul_read_eeprom(WORD CurBase); /* ---- EXTERNAL VARIABLES ---- */HCS tul_hcs[MAX_SUPPORTED_ADAPTERS]; /* ---- INTERNAL VARIABLES ---- */static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS];/*NVRAM nvram, *nvramp = &nvram; */static NVRAM i91unvram;static NVRAM *i91unvramp;static UCHAR i91udftNvRam[64] ={/*----------- header -----------*/ 0x25, 0xc9, /* Signature */ 0x40, /* Size */ 0x01, /* Revision */ /* -- Host Adapter Structure -- */ 0x95, /* ModelByte0 */ 0x00, /* ModelByte1 */ 0x00, /* ModelInfo */ 0x01, /* NumOfCh */ NBC1_DEFAULT, /* BIOSConfig1 */ 0, /* BIOSConfig2 */ 0, /* HAConfig1 */ 0, /* HAConfig2 */ /* SCSI channel 0 and target Structure */ 7, /* SCSIid */ NCC1_DEFAULT, /* SCSIconfig1 */ 0, /* SCSIconfig2 */ 0x10, /* NumSCSItarget */ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, /* SCSI channel 1 and target Structure */ 7, /* SCSIid */ NCC1_DEFAULT, /* SCSIconfig1 */ 0, /* SCSIconfig2 */ 0x10, /* NumSCSItarget */ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* - CheckSum - */static UCHAR tul_rate_tbl[8] = /* fast 20 */{ /* nanosecond devide by 4 */ 12, /* 50ns, 20M */ 18, /* 75ns, 13.3M */ 25, /* 100ns, 10M */ 31, /* 125ns, 8M */ 37, /* 150ns, 6.6M */ 43, /* 175ns, 5.7M */ 50, /* 200ns, 5M */ 62 /* 250ns, 4M */};extern int tul_num_ch;static void tul_do_pause(unsigned amount){ /* Pause for amount jiffies */ unsigned long the_time = jiffies + amount;#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) while (time_before_eq(jiffies, the_time));#else while (jiffies < the_time);#endif}/*-- forward reference --*//******************************************************************* Use memeory refresh time ~ 15us * 2********************************************************************/void tul_se2_wait(){#if 1 udelay(30);#else UCHAR readByte; readByte = TUL_RD(0, 0x61); if ((readByte & 0x10) == 0x10) { for (;;) { readByte = TUL_RD(0, 0x61); if ((readByte & 0x10) == 0x10) break; } for (;;) { readByte = TUL_RD(0, 0x61); if ((readByte & 0x10) != 0x10) break; } } else { for (;;) { readByte = TUL_RD(0, 0x61); if ((readByte & 0x10) == 0x10) break; } for (;;) { readByte = TUL_RD(0, 0x61); if ((readByte & 0x10) != 0x10) break; } }#endif}/****************************************************************** Input: instruction for Serial E2PROM EX: se2_rd(0 call se2_instr() to send address and read command StartBit OP_Code Address Data --------- -------- ------------------ ------- 1 1 , 0 A5,A4,A3,A2,A1,A0 D15-D0 +----------------------------------------------------- | CS -----+ +--+ +--+ +--+ +--+ +--+ ^ | ^ | ^ | ^ | ^ | | | | | | | | | | | CLK -------+ +--+ +--+ +--+ +--+ +-- (leading edge trigger) +--1-----1--+ | SB OP | OP A5 A4 DI ----+ +--0------------------ (address and cmd sent to nvram) -------------------------------------------+ | DO +--- (data sent from nvram)******************************************************************/void tul_se2_instr(WORD CurBase, UCHAR instr){ int i; UCHAR b; TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO); /* cs+start bit */ tul_se2_wait(); TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK | SE2DO); /* +CLK */ tul_se2_wait(); for (i = 0; i < 8; i++) { if (instr & 0x80) b = SE2CS | SE2DO; /* -CLK+dataBit */ else b = SE2CS; /* -CLK */ TUL_WR(CurBase + TUL_NVRAM, b); tul_se2_wait(); TUL_WR(CurBase + TUL_NVRAM, b | SE2CLK); /* +CLK */ tul_se2_wait(); instr <<= 1; } TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ tul_se2_wait(); return;}/****************************************************************** Function name : tul_se2_ew_en Description : Enable erase/write state of serial EEPROM******************************************************************/void tul_se2_ew_en(WORD CurBase){ tul_se2_instr(CurBase, 0x30); /* EWEN */ TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ tul_se2_wait(); return;}/************************************************************************ Disable erase/write state of serial EEPROM*************************************************************************/void tul_se2_ew_ds(WORD CurBase){ tul_se2_instr(CurBase, 0); /* EWDS */ TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ tul_se2_wait(); return;}/****************************************************************** Input :address of Serial E2PROM Output :value stored in Serial E2PROM*******************************************************************/USHORT tul_se2_rd(WORD CurBase, ULONG adr){ UCHAR instr, readByte; USHORT readWord; int i; instr = (UCHAR) (adr | 0x80); tul_se2_instr(CurBase, instr); /* READ INSTR */ readWord = 0; for (i = 15; i >= 0; i--) { TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */ tul_se2_wait(); TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ /* sample data after the following edge of clock */ readByte = TUL_RD(CurBase, TUL_NVRAM); readByte &= SE2DI; readWord += (readByte << i); tul_se2_wait(); /* 6/20/95 */ } TUL_WR(CurBase + TUL_NVRAM, 0); /* no chip select */ tul_se2_wait(); return readWord;}/****************************************************************** Input: new value in Serial E2PROM, address of Serial E2PROM*******************************************************************/void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord){ UCHAR readByte; UCHAR instr; int i; instr = (UCHAR) (adr | 0x40); tul_se2_instr(CurBase, instr); /* WRITE INSTR */ for (i = 15; i >= 0; i--) { if (writeWord & 0x8000) TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO); /* -CLK+dataBit 1 */ else TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK+dataBit 0 */ tul_se2_wait(); TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */ tul_se2_wait(); writeWord <<= 1; } TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ tul_se2_wait(); TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ tul_se2_wait(); TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* +CS */ tul_se2_wait(); for (;;) { TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */ tul_se2_wait(); TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ tul_se2_wait(); if ((readByte = TUL_RD(CurBase, TUL_NVRAM)) & SE2DI) break; /* write complete */ } TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ return;}/*********************************************************************** Read SCSI H/A configuration parameters from serial EEPROM************************************************************************/int tul_se2_rd_all(WORD CurBase){ int i; ULONG chksum = 0; USHORT *np; i91unvramp = &i91unvram; np = (USHORT *) i91unvramp; for (i = 0; i < 32; i++) { *np++ = tul_se2_rd(CurBase, i); }/*--------------------Is signature "ini" ok ? ----------------*/ if (i91unvramp->NVM_Signature != INI_SIGNATURE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -