diff options
| author | Jordan K. Hubbard <jkh@FreeBSD.org> | 1994-11-22 10:58:58 +0000 |
|---|---|---|
| committer | Jordan K. Hubbard <jkh@FreeBSD.org> | 1994-11-22 10:58:58 +0000 |
| commit | 140932d6d85b561ad06abe5006a5e973a7713c45 (patch) | |
| tree | be1d2469fd1ab2ab0df6164fbc91fb7bbbdd80f5 /sys/pci | |
| parent | 324ec40db3d437d18da21aa07a7ae4d4ecd9c157 (diff) | |
Diffstat (limited to 'sys/pci')
| -rw-r--r-- | sys/pci/README.de | 48 | ||||
| -rw-r--r-- | sys/pci/README.de-le | 33 | ||||
| -rw-r--r-- | sys/pci/dc21040.h | 214 | ||||
| -rw-r--r-- | sys/pci/if_de.c | 1158 | ||||
| -rw-r--r-- | sys/pci/ncr.c | 6499 | ||||
| -rw-r--r-- | sys/pci/ncrreg.h | 547 | ||||
| -rw-r--r-- | sys/pci/pci.c | 778 | ||||
| -rw-r--r-- | sys/pci/pcireg.h | 423 | ||||
| -rw-r--r-- | sys/pci/pcisupport.c | 394 |
9 files changed, 0 insertions, 10094 deletions
diff --git a/sys/pci/README.de b/sys/pci/README.de deleted file mode 100644 index fb81945c4d73..000000000000 --- a/sys/pci/README.de +++ /dev/null @@ -1,48 +0,0 @@ -$Id: README.de,v 1.3 1994/10/12 11:19:36 se Exp $ - ----------------- - -The enclosed driver should be considered as beta-test software. It -has run on exactly one machine. Therefore testing has been limited. -This driver is in no way supported by Digital Equipment. See the -disclaimers in the sources for more. - -This driver the DEC DE435 PCI NIC. It should also work with other PCI -boards that use the DC21040-AA chip (also known as TULIP). This -driver requires the DC21040-AA to be pass 2.3 or later. If you are -using a eariler pass chip, you may encounter undetected transmit -corruptions. This driver also requires that DC21040-AA use a serial -Ethernet address ROM as described in the DC21040 specification. - -The DEC DE425 EISA NIC based on the DC21040-AA is not support at -this time. A future update will include support for it. - -The driver includes full support for both BPF and IP Multicast. -If the autosensing of the driver fails, you can use ifconfig(8) to -switch the driver to the correct port. - - ifconfig de0 altphys Thinwire/AUI port - ifconfig de0 -altphys 10baseT/UTP port - -To enable this driver, you first need to add the following lines to -your config file (in i386/conf): - - controller pci0 - device de0 - -The PCI support code will automatically determine and enable the -correct IRQ. - -Now you are ready to rebuild your kernel, reboot, and see if the -driver can configure your board. When the system boots, you will -hopefully something close to: - - de0 <digital dc21040 ethernet> int a irq 9 on pci0:7 - reg20: virtual=0xf290a000 physical=0xc0001000 - de0: enabling Thinwire/AUI port - de0: DC21040 [10Mb/s] pass 2.3 ethernet address 08:00:2b:e2:1e:09 - bpf: de0 attached - -in the startup log. If so, the board configured properly and -should be ready to use. - diff --git a/sys/pci/README.de-le b/sys/pci/README.de-le deleted file mode 100644 index 60cd2e2750e0..000000000000 --- a/sys/pci/README.de-le +++ /dev/null @@ -1,33 +0,0 @@ -$Id: README.de-le,v 1.1 1994/10/01 20:16:44 wollman Exp $ - ----------------- - -The enclosed drivers should be considered beta-test software. These -drivers are in no way supported by Digital Equipment. See the -disclaimers in the sources for more information. Please be aware that -Digital does not employee me to write drivers for FreeBSD. - -This kit contains one driver: - - de DEC DE435 PCI NIC or compatible - -See README.de for information and installation instruction specific to this -driver. - -Could you please send me the startup messages in the boot -long along with the type of your PC once the driver configures? - -If you have any problems, comments, suggestions, rant or raves, don't -hesitate to send me mail @ thomas@lkg.dec.com. - -Lastly, if you change or modify the code, I want context diffs of your -changes. I want this to the canonical DEC EtherWORKS driver kit for -FreeBSD, NetBSD, BSD/386, and any other BSD based O/S. Please make -sure your diffs are approriate conditionalized. - -Thanks, -Matt Thomas --- -Mail: thomas@lkg.dec.com -URL: http://ftp.digital.com/~thomas/ - diff --git a/sys/pci/dc21040.h b/sys/pci/dc21040.h deleted file mode 100644 index 4afa27418865..000000000000 --- a/sys/pci/dc21040.h +++ /dev/null @@ -1,214 +0,0 @@ -/*- - * Copyright (c) 1994 Matt Thomas (thomas@lkg.dec.com) - * All rights reserved. - * - * 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. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software withough specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. - * - * $Id: dc21040.h,v 1.2 1994/08/15 20:42:25 thomas Exp thomas $ - * - * $Log: dc21040.h,v $ - * Revision 1.2 1994/08/15 20:42:25 thomas - * misc additions - * - * Revision 1.1 1994/08/12 21:02:46 thomas - * Initial revision - * - * Revision 1.8 1994/08/05 20:20:54 thomas - * Enable change log - * - * Revision 1.7 1994/08/05 20:20:14 thomas - * *** empty log message *** - * - */ - -#if !defined(_DC21040_H) -#define _DC21040_H - -typedef signed int tulip_sint32_t; -typedef unsigned int tulip_uint32_t; - -#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN -#define TULIP_BITFIELD2(a, b) b, a -#define TULIP_BITFIELD3(a, b, c) c, b, a -#define TULIP_BITFIELD4(a, b, c, d) d, c, b, a -#else -#define TULIP_BITFIELD2(a, b) a, b -#define TULIP_BITFIELD3(a, b, c) a, b, c -#define TULIP_BITFIELD4(a, b, c, d) a, b, c, d -#endif - -typedef struct { - tulip_uint32_t d_status; - tulip_uint32_t TULIP_BITFIELD3(d_length1 : 11, - d_length2 : 11, - d_flag : 10); - tulip_uint32_t d_addr1; - tulip_uint32_t d_addr2; -} tulip_desc_t; - -#define TULIP_DSTS_OWNER 0x80000000 /* Owner (1 = DC21040) */ -#define TULIP_DSTS_ERRSUM 0x00008000 /* Error Summary */ -/* - * Transmit Status - */ -#define TULIP_DSTS_TxBABBLE 0x00004000 /* Transmitter Babbled */ -#define TULIP_DSTS_TxCARRLOSS 0x00000800 /* Carrier Loss */ -#define TULIP_DSTS_TxNOCARR 0x00000400 /* No Carrier */ -#define TULIP_DSTS_TxLATECOLL 0x00000200 /* Late Collision */ -#define TULIP_DSTS_TxEXCCOLL 0x00000100 /* Excessive Collisions */ -#define TULIP_DSTS_TxNOHRTBT 0x00000080 /* No Heartbeat */ -#define TULIP_DSTS_TxCOLLMASK 0x00000078 /* Collision Count (mask) */ -#define TULIP_DSTS_V_TxCOLLCNT 0x00000003 /* Collision Count (bit) */ -#define TULIP_DSTS_TxLINKFAIL 0x00000004 /* Link Failure */ -#define TULIP_DSTS_TxUNDERFLOW 0x00000002 /* Underflow Error */ -#define TULIP_DSTS_TxDEFERRED 0x00000001 /* Initially Deferred */ -/* - * Receive Status - */ -#define TULIP_DSTS_RxBADLENGTH 0x00004000 /* Length Error */ -#define TULIP_DSTS_RxDATATYPE 0x00003000 /* Data Type */ -#define TULIP_DSTS_RxRUNT 0x00000800 /* Runt Frame */ -#define TULIP_DSTS_RxMULTICAST 0x00000400 /* Multicast Frame */ -#define TULIP_DSTS_RxFIRSTDESC 0x00000200 /* First Descriptor */ -#define TULIP_DSTS_RxLASTDESC 0x00000100 /* Last Descriptor */ -#define TULIP_DSTS_RxTOOLONG 0x00000080 /* Frame Too Long */ -#define TULIP_DSTS_RxCOLLSEEN 0x00000040 /* Collision Seen */ -#define TULIP_DSTS_RxFRAMETYPE 0x00000020 /* Frame Type */ -#define TULIP_DSTS_RxWATCHDOG 0x00000010 /* Receive Watchdog */ -#define TULIP_DSTS_RxDRBBLBIT 0x00000004 /* Dribble Bit */ -#define TULIP_DSTS_RxBADCRC 0x00000002 /* CRC Error */ -#define TULIP_DSTS_RxOVERFLOW 0x00000001 /* Overflow */ - - -#define TULIP_DFLAG_ENDRING 0x0008 /* End of Transmit Ring */ -#define TULIP_DFLAG_CHAIN 0x0004 /* Chain using d_addr2 */ - -#define TULIP_DFLAG_TxWANTINTR 0x0200 /* Signal Interrupt on Completion */ -#define TULIP_DFLAG_TxLASTSEG 0x0100 /* Last Segment */ -#define TULIP_DFLAG_TxFIRSTSEG 0x0080 /* First Segment */ -#define TULIP_DFLAG_TxINVRSFILT 0x0040 /* Inverse Filtering */ -#define TULIP_DFLAG_TxSETUPPKT 0x0020 /* Setup Packet */ -#define TULIP_DFLAG_TxHASCRC 0x0010 /* Don't Append the CRC */ -#define TULIP_DFLAG_TxNOPADDING 0x0002 /* Don't AutoPad */ -#define TULIP_DFLAG_TxHASHFILT 0x0001 /* Hash/Perfect Filtering */ - -/* - * The DC21040 Registers (IO Space Addresses) - */ -#define TULIP_REG_BUSMODE 0x00 /* CSR0 -- Bus Mode */ -#define TULIP_REG_TXPOLL 0x08 /* CSR1 -- Transmit Poll Demand */ -#define TULIP_REG_RXPOLL 0x10 /* CSR2 -- Receive Poll Demand */ -#define TULIP_REG_RXLIST 0x18 /* CSR3 -- Receive List Base Addr */ -#define TULIP_REG_TXLIST 0x20 /* CSR4 -- Transmit List Base Addr */ -#define TULIP_REG_STATUS 0x28 /* CSR5 -- Status */ -#define TULIP_REG_CMD 0x30 /* CSR6 -- Command */ -#define TULIP_REG_INTR 0x38 /* CSR7 -- Interrupt Control */ -#define TULIP_REG_MISSES 0x40 /* CSR8 -- Missed Frame Counter */ -#define TULIP_REG_ADDRROM 0x48 /* CSR9 -- ENET ROM Register */ -#define TULIP_REG_RSRVD 0x50 /* CSR10 -- Reserved */ -#define TULIP_REG_FULL_DUPLEX 0x58 /* CSR11 -- Full Duplex */ -#define TULIP_REG_SIA_STATUS 0x60 /* CSR12 -- SIA Status */ -#define TULIP_REG_SIA_CONN 0x68 /* CSR13 -- SIA Connectivity */ -#define TULIP_REG_SIA_TXRX 0x70 /* CSR14 -- SIA Tx Rx */ -#define TULIP_REG_SIA_GEN 0x78 /* CSR15 -- SIA General */ - -/* - * CSR5 -- Status Register - * CSR7 -- Interrupt Control - */ -#define TULIP_STS_ERRORMASK 0x03800000L /* ( R) Error Bits (Valid when SYSERROR is set) */ -#define TULIP_STS_ERR_PARITY 0x00000000L /* 000 - Parity Error (Perform Reset) */ -#define TULIP_STS_ERR_MASTER 0x00800000L /* 001 - Master Abort */ -#define TULIP_STS_ERR_TARGET 0x01000000L /* 010 - Target Abort */ -#define TULIP_STS_TXSTATEMASK 0x00700000L /* ( R) Transmission Process State */ -#define TULIP_STS_TXS_RESET 0x00000000L /* 000 - Rset or transmit jabber expired */ -#define TULIP_STS_TXS_FETCH 0x00100000L /* 001 - Fetching transmit descriptor */ -#define TULIP_STS_TXS_WAITEND 0x00200000L /* 010 - Wait for end of transmission */ -#define TULIP_STS_TXS_READING 0x00300000L /* 011 - Read buffer and enqueue data */ -#define TULIP_STS_TXS_RSRVD 0x00400000L /* 100 - Reserved */ -#define TULIP_STS_TXS_SETUP 0x00500000L /* 101 - Setup Packet */ -#define TULIP_STS_TXS_SUSPEND 0x00600000L /* 110 - Transmit FIFO underflow or an - unavailable transmit descriptor */ -#define TULIP_STS_TXS_CLOSE 0x00700000L /* 111 - Close transmit descriptor */ -#define TULIP_STS_RXSTATEMASK 0x000E0000L /* ( R) Receive Process State*/ -#define TULIP_STS_RXS_STOPPED 0x00000000L /* 000 - Stopped */ -#define TULIP_STS_RXS_FETCH 0x00020000L /* 001 - Running -- Fetch receive descriptor */ -#define TULIP_STS_RXS_ENDCHECK 0x00040000L /* 010 - Running -- Check for end of receive - packet before prefetch of next descriptor */ -#define TULIP_STS_RXS_WAIT 0x00060000L /* 011 - Running -- Wait for receive packet */ -#define TULIP_STS_RXS_SUSPEND 0x00080000L /* 100 - Suspended -- As a result of - unavailable receive buffers */ -#define TULIP_STS_RXS_CLOSE 0x000A0000L /* 101 - Running -- Close receive descriptor */ -#define TULIP_STS_RXS_FLUSH 0x000C0000L /* 110 - Running -- Flush the current frame - from the receive FIFO as a result of - an unavailable receive buffer */ -#define TULIP_STS_RXS_DEQUEUE 0x000E0000L /* 111 - Running -- Dequeue the receive frame - from the receive FIFO into the receive - buffer. */ -#define TULIP_STS_NORMALINTR 0x00010000L /* (RW) Normal Interrupt */ -#define TULIP_STS_ABNRMLINTR 0x00008000L /* (RW) Abnormal Interrupt */ -#define TULIP_STS_SYSERROR 0x00002000L /* (RW) System Error */ -#define TULIP_STS_LINKFAIL 0x00001000L /* (RW) Link Failure */ -#define TULIP_STS_FULDPLXSHRT 0x00000800L /* (RW) Full Duplex Short Fram Rcvd */ -#define TULIP_STS_AUI 0x00000400L /* (RW) AUI/TP Switch */ -#define TULIP_STS_RXTIMEOUT 0x00000200L /* (RW) Receive Watchbog Timeout */ -#define TULIP_STS_RXSTOPPED 0x00000100L /* (RW) Receive Process Stopped */ -#define TULIP_STS_RXNOBUF 0x00000080L /* (RW) Receive Buffer Unavailable */ -#define TULIP_STS_RXINTR 0x00000040L /* (RW) Receive Interrupt */ -#define TULIP_STS_TXUNDERFLOW 0x00000020L /* (RW) Transmit Underflow */ -#define TULIP_STS_TXBABBLE 0x00000008L /* (RW) Transmit Jabber Timeout */ -#define TULIP_STS_TXNOBUF 0x00000004L /* (RW) Transmit Buffer Unavailable */ -#define TULIP_STS_TXSTOPPED 0x00000002L /* (RW) Transmit Process Stopped */ -#define TULIP_STS_TXINTR 0x00000001L /* (RW) Transmit Interrupt */ - -/* - * CSR6 -- Command (Operation Mode) Register - */ -#define TULIP_CMD_CAPTREFFCT 0x00020000L /* (RW) Capture Effect (!802.3) */ -#define TULIP_CMD_BACKPRESSURE 0x00010000L /* (RW) Back Pressure (!802.3) */ -#define TULIP_CMD_THRESHOLDCTL 0x0000C000L /* (RW) Threshold Control */ -#define TULIP_CMD_THRSHLD72 0x00000000L /* 00 - 72 Bytes */ -#define TULIP_CMD_THRSHLD96 0x00004000L /* 01 - 96 Bytes */ -#define TULIP_CMD_THRSHLD128 0x00008000L /* 10 - 128 bytes */ -#define TULIP_CMD_THRSHLD160 0x0000C000L /* 11 - 160 Bytes */ -#define TULIP_CMD_TXRUN 0x00002000L /* (RW) Start/Stop Transmitter */ -#define TULIP_CMD_FORCECOLL 0x00001000L /* (RW) Force Collisions */ -#define TULIP_CMD_OPERMODE 0x00000C00L /* (RW) Operating Mode */ -#define TULIP_CMD_FULLDULPEX 0x00000200L /* (RW) Full Duplex Mode */ -#define TULIP_CMD_FLAKYOSCDIS 0x00000100L /* (RW) Flakey Oscillator Disable */ -#define TULIP_CMD_ALLMULTI 0x00000080L /* (RW) Pass All Multicasts */ -#define TULIP_CMD_PROMISCUOUS 0x00000040L /* (RW) Promiscuous Mode */ -#define TULIP_CMD_BACKOFFCTR 0x00000020L /* (RW) Start/Stop Backoff Counter (!802.3) */ -#define TULIP_CMD_INVFILTER 0x00000010L /* (R ) Inverse Filtering */ -#define TULIP_CMD_PASSBADPKT 0x00000008L /* (RW) Pass Bad Frames */ -#define TULIP_CMD_HASHONLYFLTR 0x00000004L /* (R ) Hash Only Filtering */ -#define TULIP_CMD_RXRUN 0x00000002L /* (RW) Start/Stop Receive Filtering */ -#define TULIP_CMD_HASHPRFCTFLTR 0x00000001L /* (R ) Hash/Perfect Receive Filtering */ - - -#define TULIP_SIASTS_LINKFAIL 0x00000004L -#define TULIP_SIACONN_RESET 0x00000000L - -#define TULIP_SIACONN_AUI 0x0000000DL -#define TULIP_SIACONN_10BASET 0x00000005L - -#define TULIP_BUSMODE_SWRESET 0x00000001L - -#endif /* !defined(_DC21040_H) */ diff --git a/sys/pci/if_de.c b/sys/pci/if_de.c deleted file mode 100644 index 9e6a26b56ea7..000000000000 --- a/sys/pci/if_de.c +++ /dev/null @@ -1,1158 +0,0 @@ -/*- - * Copyright (c) 1994 Matt Thomas (thomas@lkg.dec.com) - * All rights reserved. - * - * 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. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software withough specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. - * - * $Id: if_de.c,v 1.6 1994/11/13 12:39:38 davidg Exp $ - * - */ - -/* - * DEC DC21040 PCI Ethernet Controller - * - * Written by Matt Thomas - * BPF support code stolen directly from if_ec.c - * - * This driver supports the DEC DE435 or any other PCI - * board which support DC21040. - */ - -#include "de.h" -#if NDE > 0 - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/errno.h> -#include <sys/malloc.h> - -#include <net/if.h> -#include <net/if_types.h> -#include <net/if_dl.h> -#include <net/route.h> - -#include "bpfilter.h" -#if NBPFILTER > 0 -#include <net/bpf.h> -#include <net/bpfdesc.h> -#endif - -#ifdef INET -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> -#include <netinet/if_ether.h> -#endif - -#ifdef NS -#include <netns/ns.h> -#include <netns/ns_if.h> -#endif - -#include <vm/vm.h> -#include <vm/vm_kern.h> -#include <vm/vm_param.h> - - -#include <pci.h> -#if NPCI > 0 -#include <i386/pci/pcireg.h> -#endif -#include <i386/isa/icu.h> -#include <i386/pci/dc21040.h> - -/* - * This module supports the DEC DC21040 PCI Ethernet Controller. - */ - -typedef struct { - unsigned long addr; - unsigned long length; -} tulip_addrvec_t; - -typedef struct { - tulip_desc_t *ri_first; - tulip_desc_t *ri_last; - tulip_desc_t *ri_nextin; - tulip_desc_t *ri_nextout; - int ri_max; - int ri_free; -} tulip_ringinfo_t; - -typedef struct { - volatile tulip_uint32_t *csr_busmode; /* CSR0 */ - volatile tulip_uint32_t *csr_txpoll; /* CSR1 */ - volatile tulip_uint32_t *csr_rxpoll; /* CSR2 */ - volatile tulip_uint32_t *csr_rxlist; /* CSR3 */ - volatile tulip_uint32_t *csr_txlist; /* CSR4 */ - volatile tulip_uint32_t *csr_status; /* CSR5 */ - volatile tulip_uint32_t *csr_command; /* CSR6 */ - volatile tulip_uint32_t *csr_intr; /* CSR7 */ - volatile tulip_uint32_t *csr_missed_frame; /* CSR8 */ - volatile tulip_sint32_t *csr_enetrom; /* CSR9 */ - volatile tulip_uint32_t *csr_reserved; /* CSR10 */ - volatile tulip_uint32_t *csr_full_duplex; /* CSR11 */ - volatile tulip_uint32_t *csr_sia_status; /* CSR12 */ - volatile tulip_uint32_t *csr_sia_connectivity; /* CSR13 */ - volatile tulip_uint32_t *csr_sia_tx_rx; /* CSR14 */ - volatile tulip_uint32_t *csr_sia_general; /* CSR15 */ -} tulip_regfile_t; - -/* - * The DC21040 has a stupid restriction in that the receive - * buffers must be longword aligned. But since Ethernet - * headers are not a multiple of longwords in size this forces - * the data to non-longword aligned. Since IP requires the - * data to be longword aligned, we need to copy it after it has - * been DMA'ed in our memory. - * - * Since we have to copy it anyways, we might as well as allocate - * dedicated receive space for the input. This allows to use a - * small receive buffer size and more ring entries to be able to - * better keep with a flood of tiny Ethernet packets. - * - * The receive space MUST ALWAYS be a multiple of the page size. - * And the number of receive descriptors multiplied by the size - * of the receive buffers must equal the recevive space. This - * is so that we can manipulate the page tables so that even if a - * packet wraps around the end of the receive space, we can - * treat it as virtually contiguous. - */ -#define TULIP_RXBUFSIZE 512 -#define TULIP_RXDESCS 128 -#define TULIP_RXSPACE (TULIP_RXBUFSIZE * TULIP_RXDESCS) -#define TULIP_TXDESCS 128 - -typedef struct { - struct arpcom tulip_ac; - tulip_regfile_t tulip_csrs; - vm_offset_t tulip_rxspace; - unsigned tulip_flags; -#define TULIP_WANTSETUP 0x01 -#define TULIP_WANTHASH 0x02 -#define TULIP_DOINGSETUP 0x04 -#define TULIP_ALTPHYS 0x08 /* use AUI */ - unsigned char tulip_rombuf[32]; - tulip_uint32_t tulip_setupbuf[192/sizeof(tulip_uint32_t)]; - tulip_uint32_t tulip_setupdata[192/sizeof(tulip_uint32_t)]; - tulip_uint32_t tulip_intrmask; - tulip_uint32_t tulip_cmdmode; - tulip_uint32_t tulip_revinfo; -#if NBPFILTER > 0 - caddr_t tulip_bpf; /* BPF context */ -#endif - struct ifqueue tulip_txq; - tulip_ringinfo_t tulip_rxinfo; - tulip_ringinfo_t tulip_txinfo; -} tulip_softc_t; - -#ifndef IFF_ALTPHYS -#define IFF_ALTPHYS IFF_LINK0 /* In case it isn't defined */ -#endif -typedef enum { TULIP_DC21040, TULIP_DC21140 } tulip_chipid_t; -const char *tulip_chipdescs[] = { - "DC21040 [10Mb/s]", - "DC21140 [100Mb/s]", -}; - -tulip_softc_t *tulips[NDE]; -tulip_chipid_t tulip_chipids[NDE]; - -#define tulip_if tulip_ac.ac_if -#define tulip_unit tulip_ac.ac_if.if_unit -#define tulip_name tulip_ac.ac_if.if_name -#define tulip_hwaddr tulip_ac.ac_enaddr - -#define TULIP_CRC32_POLY 0xEDB88320UL /* CRC-32 Poly -- Little Endian */ -#define TULIP_CHECK_RXCRC 0 -#define TULIP_MAX_TXSEG 30 - -#define TULIP_ADDREQUAL(a1, a2) \ - (((u_short *)a1)[0] == ((u_short *)a2)[0] \ - && ((u_short *)a1)[1] == ((u_short *)a2)[1] \ - && ((u_short *)a1)[2] == ((u_short *)a2)[2]) -#define TULIP_ADDRBRDCST(a1) \ - (((u_short *)a1)[0] == 0xFFFFU \ - && ((u_short *)a1)[1] == 0xFFFFU \ - && ((u_short *)a1)[2] == 0xFFFFU) - -static void tulip_start(struct ifnet *ifp); -static void tulip_addr_filter(tulip_softc_t *sc); - -#if __FreeBSD__ > 1 -#define TULIP_IFRESET_ARGS int unit -#define TULIP_RESET(sc) tulip_reset((sc)->tulip_unit) -#else -#define TULIP_IFRESET_ARGS int unit, int uban -#define TULIP_RESET(sc) tulip_reset((sc)->tulip_unit, 0) -#endif - -static void -tulip_reset( - TULIP_IFRESET_ARGS) -{ - tulip_softc_t *sc = tulips[unit]; - tulip_ringinfo_t *ri; - tulip_desc_t *di; - vm_offset_t vmoff; - - *sc->tulip_csrs.csr_busmode = TULIP_BUSMODE_SWRESET; - DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at - 33MHz that comes to two microseconds but wait a - bit longer anyways) */ - - /* - * Use the - */ - *sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_RESET; - if (sc->tulip_if.if_flags & IFF_ALTPHYS) { - if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) - printf("%s%d: enabling Thinwire/AUI port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); - *sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_AUI; - sc->tulip_flags |= TULIP_ALTPHYS; - } else { - if (sc->tulip_flags & TULIP_ALTPHYS) - printf("%s%d: enabling 10baseT/UTP port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); - *sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_10BASET; - sc->tulip_flags &= ~TULIP_ALTPHYS; - } - *sc->tulip_csrs.csr_txlist = vtophys(&sc->tulip_txinfo.ri_first[0]); - *sc->tulip_csrs.csr_rxlist = vtophys(&sc->tulip_rxinfo.ri_first[0]); - *sc->tulip_csrs.csr_intr = 0; - *sc->tulip_csrs.csr_busmode = 0x4800; - - sc->tulip_txq.ifq_maxlen = TULIP_TXDESCS; - /* - * Free all the mbufs that were on the transmit ring. - */ - for (;;) { - struct mbuf *m; - IF_DEQUEUE(&sc->tulip_txq, m); - if (m == NULL) - break; - m_freem(m); - } - - ri = &sc->tulip_txinfo; - ri->ri_nextin = ri->ri_nextout = ri->ri_first; - ri->ri_free = ri->ri_max; - for (di = ri->ri_first; di < ri->ri_last; di++) - di->d_status = 0; - - /* - * We need to collect all the mbufs were on the - * receive ring before we reinit it either to put - * them back on or to know if we have to allocate - * more. - */ - ri = &sc->tulip_rxinfo; - ri->ri_nextin = ri->ri_nextout = ri->ri_first; - ri->ri_free = ri->ri_max; - for (vmoff = vtophys(sc->tulip_rxspace), di = ri->ri_first; - di < ri->ri_last; di++, vmoff += TULIP_RXBUFSIZE) { - di->d_status |= TULIP_DSTS_OWNER; - di->d_length1 = TULIP_RXBUFSIZE; di->d_addr1 = vmoff; - di->d_length2 = 0; di->d_addr2 = 0; - } - - sc->tulip_intrmask = TULIP_STS_NORMALINTR|TULIP_STS_RXINTR|TULIP_STS_TXINTR - |TULIP_STS_ABNRMLINTR|TULIP_STS_SYSERROR|TULIP_STS_TXSTOPPED - |TULIP_STS_TXBABBLE|TULIP_STS_LINKFAIL|TULIP_STS_RXSTOPPED; - sc->tulip_flags &= ~(TULIP_DOINGSETUP|TULIP_WANTSETUP); - tulip_addr_filter(sc); -} - -static void -tulip_init( - int unit) -{ - tulip_softc_t *sc = tulips[unit]; - - if (sc->tulip_if.if_flags & IFF_UP) { - sc->tulip_if.if_flags |= IFF_RUNNING; - if (sc->tulip_if.if_flags & IFF_PROMISC) { - sc->tulip_cmdmode |= TULIP_CMD_PROMISCUOUS; - } else { - sc->tulip_cmdmode &= ~TULIP_CMD_PROMISCUOUS; - if (sc->tulip_if.if_flags & IFF_ALLMULTI) { - sc->tulip_cmdmode |= TULIP_CMD_ALLMULTI; - } else { - sc->tulip_cmdmode &= ~TULIP_CMD_ALLMULTI; - } - } - sc->tulip_cmdmode |= TULIP_CMD_TXRUN; - if ((sc->tulip_flags & TULIP_WANTSETUP) == 0) { - sc->tulip_cmdmode |= TULIP_CMD_RXRUN; - sc->tulip_intrmask |= TULIP_STS_RXSTOPPED; - } else { - sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED; - tulip_start(&sc->tulip_if); - } - sc->tulip_cmdmode |= TULIP_CMD_THRSHLD160; - *sc->tulip_csrs.csr_intr = sc->tulip_intrmask; - *sc->tulip_csrs.csr_command = sc->tulip_cmdmode; - } else { - TULIP_RESET(sc); - sc->tulip_if.if_flags &= ~IFF_RUNNING; - } -} - - -#if TULIP_CHECK_RXCRC -static unsigned -tulip_crc32( - u_char *addr, - int len) -{ - unsigned int crc = 0xFFFFFFFF; - static unsigned int crctbl[256]; - int idx; - static int done; - /* - * initialize the multicast address CRC table - */ - for (idx = 0; !done && idx < 256; idx++) { - unsigned int tmp = idx; - tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ - tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ - tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ - tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ - tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ - tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ - tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ - tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ - crctbl[idx] = tmp; - } - done = 1; - - while (len-- > 0) - crc = (crc >> 8) ^ crctbl[*addr++] ^ crctbl[crc & 0xFF]; - - return crc; -} -#endif - -static void -tulip_rx_intr( - tulip_softc_t *sc) -{ - tulip_ringinfo_t *ri = &sc->tulip_rxinfo; - struct ifnet *ifp = &sc->tulip_if; - - for (;;) { - tulip_desc_t *eop; - int total_len, ndescs; - caddr_t bufaddr = (caddr_t) sc->tulip_rxspace; - - for (ndescs = 1, eop = ri->ri_nextin;; ndescs++) { - if (((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_OWNER) - return; - - if (eop->d_status & TULIP_DSTS_RxLASTDESC) - break; - if (++eop == ri->ri_last) - eop = ri->ri_first; - } - - bufaddr += TULIP_RXBUFSIZE * (ri->ri_nextin - ri->ri_first); - total_len = ((eop->d_status >> 16) & 0x7FF) - 4; - - if ((eop->d_status & TULIP_DSTS_ERRSUM) == 0) { - struct ether_header eh; - struct mbuf *m; - -#if TULIP_CHECK_RXCRC - unsigned crc = tulip_crc32(bufaddr, total_len); - if (~crc != *((unsigned *) &bufaddr[total_len])) { - printf("de0: bad rx crc: %08x [rx] != %08x\n", - *((unsigned *) &bufaddr[total_len]), ~crc); - goto next; - } -#endif - eh = *(struct ether_header *) bufaddr; - eh.ether_type = ntohs(eh.ether_type); -#if NBPFILTER > 0 - if (sc->tulip_bpf != NULL) { - bpf_tap(sc->tulip_bpf, bufaddr, total_len); - if (eh.ether_type != ETHERTYPE_IP && eh.ether_type != ETHERTYPE_ARP) - goto next; - if ((eh.ether_dhost[0] & 1) == 0 && - !TULIP_ADDREQUAL(eh.ether_dhost, sc->tulip_ac.ac_enaddr)) - goto next; - } else if (!TULIP_ADDREQUAL(eh.ether_dhost, sc->tulip_ac.ac_enaddr) - && !TULIP_ADDRBRDCST(eh.ether_dhost)) { - goto next; - } -#endif - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m != NULL) { - m->m_pkthdr.rcvif = ifp; - total_len -= sizeof(eh); - if (total_len > MHLEN) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - m_freem(m); - ifp->if_ierrors++; - goto next; - } - } - bcopy(bufaddr + sizeof(eh), mtod(m, caddr_t), total_len); - m->m_len = m->m_pkthdr.len = total_len; - ether_input(ifp, &eh, m); - } else { - ifp->if_ierrors++; - } - } else { - ifp->if_ierrors++; - } -next: - ifp->if_ipackets++; - while (ndescs-- > 0) { - ri->ri_nextin->d_status |= TULIP_DSTS_OWNER; - if (++ri->ri_nextin == ri->ri_last) - ri->ri_nextin = ri->ri_first; - } - } -} - -static int -tulip_tx_intr( - tulip_softc_t *sc) -{ - tulip_ringinfo_t *ri = &sc->tulip_txinfo; - struct mbuf *m; - int xmits = 0; - - while (ri->ri_free < ri->ri_max) { - if (((volatile tulip_desc_t *) ri->ri_nextin)->d_status & TULIP_DSTS_OWNER) - break; - - if (ri->ri_nextin->d_flag & TULIP_DFLAG_TxLASTSEG) { - if (ri->ri_nextin->d_flag & TULIP_DFLAG_TxSETUPPKT) { - /* - * We've just finished processing a setup packet. - * Mark that we can finished it. If there's not - * another pending, startup the TULIP receiver. - * Make sure we ack the RXSTOPPED so we won't get - * an abormal interrupt indication. - */ - sc->tulip_flags &= ~TULIP_DOINGSETUP; - if ((sc->tulip_flags & TULIP_WANTSETUP) == 0) { - sc->tulip_cmdmode |= TULIP_CMD_RXRUN; - sc->tulip_intrmask |= TULIP_STS_RXSTOPPED; - *sc->tulip_csrs.csr_status = TULIP_STS_RXSTOPPED; - *sc->tulip_csrs.csr_command = sc->tulip_cmdmode; - *sc->tulip_csrs.csr_intr = sc->tulip_intrmask; - } - } else { - IF_DEQUEUE(&sc->tulip_txq, m); - m_freem(m); - sc->tulip_if.if_collisions += - (ri->ri_nextin->d_status & TULIP_DSTS_TxCOLLMASK) - >> TULIP_DSTS_V_TxCOLLCNT; - if (ri->ri_nextin->d_status & TULIP_DSTS_ERRSUM) - sc->tulip_if.if_oerrors++; - xmits++; - } - } - - if (++ri->ri_nextin == ri->ri_last) - ri->ri_nextin = ri->ri_first; - ri->ri_free++; - sc->tulip_if.if_flags &= ~IFF_OACTIVE; - } - sc->tulip_if.if_opackets += xmits; - return xmits; -} - -static int -tulip_txsegment( - tulip_softc_t *sc, - struct mbuf *m, - tulip_addrvec_t *avp, - size_t maxseg) -{ - int segcnt; - - for (segcnt = 0; m; m = m->m_next) { - int len = m->m_len; - caddr_t addr = mtod(m, caddr_t); - unsigned clsize = CLBYTES - (((u_long) addr) & (CLBYTES-1)); - - while (len > 0) { - unsigned slen = min(len, clsize); - if (segcnt < maxseg) { - avp->addr = vtophys(addr); - avp->length = slen; - } - len -= slen; - addr += slen; - clsize = CLBYTES; - avp++; - segcnt++; - } - } - if (segcnt >= maxseg) { - printf("%s%d: tulip_txsegment: extremely fragmented packet encountered (%d segments)\n", - sc->tulip_name, sc->tulip_unit, segcnt); - return -1; - } - avp->addr = 0; - avp->length = 0; - return segcnt; -} - -static void -tulip_start( - struct ifnet *ifp) -{ - tulip_softc_t *sc = (tulip_softc_t *) ifp; - struct ifqueue *ifq = &ifp->if_snd; - tulip_ringinfo_t *ri = &sc->tulip_txinfo; - tulip_desc_t *sop, *eop; - struct mbuf *m; - tulip_addrvec_t addrvec[TULIP_MAX_TXSEG+1], *avp; - int segcnt; - tulip_uint32_t d_status; - - if ((ifp->if_flags & IFF_RUNNING) == 0) - return; - - for (;;) { - if (sc->tulip_flags & TULIP_WANTSETUP) { - if ((sc->tulip_flags & TULIP_DOINGSETUP) || ri->ri_free == 1) { - ifp->if_flags |= IFF_OACTIVE; - return; - } - bcopy(sc->tulip_setupdata, sc->tulip_setupbuf, - sizeof(sc->tulip_setupbuf)); - sc->tulip_flags &= ~TULIP_WANTSETUP; - sc->tulip_flags |= TULIP_DOINGSETUP; - ri->ri_free--; - ri->ri_nextout->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; - ri->ri_nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG|TULIP_DFLAG_TxLASTSEG - |TULIP_DFLAG_TxSETUPPKT|TULIP_DFLAG_TxWANTINTR; - if (sc->tulip_flags & TULIP_WANTHASH) - ri->ri_nextout->d_flag |= TULIP_DFLAG_TxHASHFILT; - ri->ri_nextout->d_length1 = sizeof(sc->tulip_setupbuf); - ri->ri_nextout->d_addr1 = vtophys(sc->tulip_setupbuf); - ri->ri_nextout->d_length2 = 0; - ri->ri_nextout->d_addr2 = 0; - ri->ri_nextout->d_status = TULIP_DSTS_OWNER; - *sc->tulip_csrs.csr_txpoll = 1; - /* - * Advance the ring for the next transmit packet. - */ - if (++ri->ri_nextout == ri->ri_last) - ri->ri_nextout = ri->ri_first; - } - - IF_DEQUEUE(ifq, m); - if (m == NULL) - break; - - /* - * First find out how many and which different pages - * the mbuf data occupies. Then check to see if we - * have enough descriptor space in our transmit ring - * to actually send it. - */ - segcnt = tulip_txsegment(sc, m, addrvec, - min(ri->ri_max - 1, TULIP_MAX_TXSEG)); - if (segcnt < 0) { - struct mbuf *m0; - MGETHDR(m0, M_DONTWAIT, MT_DATA); - if (m0 != NULL) { - if (m->m_pkthdr.len > MHLEN) { - MCLGET(m0, M_DONTWAIT); - if ((m0->m_flags & M_EXT) == 0) { - m_freem(m); - continue; - } - } - m_copydata(m, 0, m0->m_pkthdr.len, mtod(m0, caddr_t)); - m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len; - m_freem(m); - IF_PREPEND(ifq, m0); - continue; - } else { - m_freem(m); - continue; - } - } - if (ri->ri_free - 2 <= (segcnt + 1) >> 1) - break; - - ri->ri_free -= (segcnt + 1) >> 1; - /* - * Now we fill in our transmit descriptors. This is - * a bit reminiscent of going on the Ark two by two - * since each descriptor for the TULIP can describe - * two buffers. So we advance through the address - * vector two entries at a time to to fill each - * descriptor. Clear the first and last segment bits - * in each descriptor (actually just clear everything - * but the end-of-ring or chain bits) to make sure - * we don't get messed up by previously sent packets. - */ - sop = ri->ri_nextout; - d_status = 0; - avp = addrvec; - do { - eop = ri->ri_nextout; - eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; - eop->d_status = d_status; - eop->d_addr1 = avp->addr; eop->d_length1 = avp->length; avp++; - eop->d_addr2 = avp->addr; eop->d_length2 = avp->length; avp++; - d_status = TULIP_DSTS_OWNER; - if (++ri->ri_nextout == ri->ri_last) - ri->ri_nextout = ri->ri_first; - } while ((segcnt -= 2) > 0); -#if NBPFILTER > 0 - if (sc->tulip_bpf != NULL) - bpf_mtap(sc->tulip_bpf, m); -#endif - /* - * The descriptors have been filled in. Mark the first - * and last segments, indicate we want a transmit complete - * interrupt, give the descriptors to the TULIP, and tell - * it to transmit! - */ - - IF_ENQUEUE(&sc->tulip_txq, m); - eop->d_flag |= TULIP_DFLAG_TxLASTSEG|TULIP_DFLAG_TxWANTINTR; - sop->d_flag |= TULIP_DFLAG_TxFIRSTSEG; - sop->d_status = TULIP_DSTS_OWNER; - - *sc->tulip_csrs.csr_txpoll = 1; - } - if (m != NULL) { - ifp->if_flags |= IFF_OACTIVE; - IF_PREPEND(ifq, m); - } -} - -static int -tulip_intr( - tulip_softc_t *sc) -{ - tulip_uint32_t csr; - - while ((csr = *sc->tulip_csrs.csr_status) & (TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR)) { - *sc->tulip_csrs.csr_status = csr & sc->tulip_intrmask; - - if (csr & TULIP_STS_SYSERROR) { - if ((csr & TULIP_STS_ERRORMASK) == TULIP_STS_ERR_PARITY) { - TULIP_RESET(sc); - tulip_init(sc->tulip_unit); - return 1; - } - } - if (csr & TULIP_STS_ABNRMLINTR) { - printf("%s%d: abnormal interrupt: 0x%05x [0x%05x]\n", - sc->tulip_name, sc->tulip_unit, csr, csr & sc->tulip_intrmask); - *sc->tulip_csrs.csr_command = sc->tulip_cmdmode; - } - if (csr & TULIP_STS_RXINTR) - tulip_rx_intr(sc); - if (sc->tulip_txinfo.ri_free < sc->tulip_txinfo.ri_max) { - tulip_tx_intr(sc); - tulip_start(&sc->tulip_if); - } - } - return 1; -} - -/* - * This is the standard method of reading the DEC Address ROMS. - */ -static int -tulip_read_macaddr( - tulip_softc_t *sc) -{ - int cksum, rom_cksum, idx; - tulip_sint32_t csr; - unsigned char tmpbuf[8]; - static u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA }; - - *sc->tulip_csrs.csr_enetrom = 1; - for (idx = 0; idx < 32; idx++) { - int cnt = 0; - while ((csr = *sc->tulip_csrs.csr_enetrom) < 0 && cnt < 10000) - cnt++; - sc->tulip_rombuf[idx] = csr & 0xFF; - } - - if (bcmp(&sc->tulip_rombuf[0], &sc->tulip_rombuf[16], 8) != 0) { - /* - * Some folks don't use the standard ethernet rom format - * but instead just put the address in the first 6 bytes - * of the rom and let the rest be all 0xffs. (Can we say - * ZNYX???) - */ - for (idx = 6; idx < 32; idx++) { - if (sc->tulip_rombuf[idx] != 0xFF) - return -4; - } - /* - * Make sure the address is not multicast or locally assigned - * that the OUI is not 00-00-00. - */ - if ((sc->tulip_rombuf[0] & 3) != 0) - return -4; - if (sc->tulip_rombuf[0] == 0 && sc->tulip_rombuf[1] == 0 - && sc->tulip_rombuf[2] == 0) - return -4; - bcopy(sc->tulip_rombuf, sc->tulip_hwaddr, 6); - return 0; - } - if (bcmp(&sc->tulip_rombuf[24], testpat, 8) != 0) - return -3; - - tmpbuf[0] = sc->tulip_rombuf[15]; tmpbuf[1] = sc->tulip_rombuf[14]; - tmpbuf[2] = sc->tulip_rombuf[13]; tmpbuf[3] = sc->tulip_rombuf[12]; - tmpbuf[4] = sc->tulip_rombuf[11]; tmpbuf[5] = sc->tulip_rombuf[10]; - tmpbuf[6] = sc->tulip_rombuf[9]; tmpbuf[7] = sc->tulip_rombuf[8]; - if (bcmp(&sc->tulip_rombuf[0], tmpbuf, 8) != 0) - return -2; - - bcopy(sc->tulip_rombuf, sc->tulip_hwaddr, 6); - - cksum = *(u_short *) &sc->tulip_hwaddr[0]; - cksum *= 2; - if (cksum > 65535) cksum -= 65535; - cksum += *(u_short *) &sc->tulip_hwaddr[2]; - if (cksum > 65535) cksum -= 65535; - cksum *= 2; - if (cksum > 65535) cksum -= 65535; - cksum += *(u_short *) &sc->tulip_hwaddr[4]; - if (cksum >= 65535) cksum -= 65535; - - rom_cksum = *(u_short *) &sc->tulip_rombuf[6]; - - if (cksum != rom_cksum) - return -1; - return 0; -} - -static unsigned -tulip_mchash( - unsigned char *mca) -{ - u_int idx, bit, data, crc = 0xFFFFFFFFUL; - -#ifdef __alpha - for (data = *(__unaligned u_long *) mca, bit = 0; bit < 48; bit++, data >>= -1) - crc = (crc >> 1) ^ (((crc ^ data) & 1) ? TULIP_CRC32_POLY : 0); -#else - for (idx = 0; idx < 6; idx++) - for (data = *mca++, bit = 0; bit < 8; bit++, data >>= 1) - crc = (crc >> 1) ^ (((crc ^ data) & 1) ? TULIP_CRC32_POLY : 0); -#endif - return crc & 0x1FF; -} - -static void -tulip_addr_filter( - tulip_softc_t *sc) -{ - tulip_uint32_t *sp = sc->tulip_setupdata; - struct ether_multistep step; - struct ether_multi *enm; - int i; - - sc->tulip_flags &= ~TULIP_WANTHASH; - sc->tulip_flags |= TULIP_WANTSETUP; - sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN; - sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED; - if (sc->tulip_ac.ac_multicnt > 14) { - unsigned hash; - /* - * If we have more than 14 multicasts, we have - * go into hash perfect mode (512 bit multicast - * hash and one perfect hardware). - */ - - bzero(sc->tulip_setupdata, sizeof(sc->tulip_setupdata)); - hash = tulip_mchash(etherbroadcastaddr); - sp[hash >> 4] |= 1 << (hash & 0xF); - ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm); - while (enm != NULL) { - hash = tulip_mchash(enm->enm_addrlo); - sp[hash >> 4] |= 1 << (hash & 0xF); - ETHER_NEXT_MULTI(step, enm); - } - sc->tulip_cmdmode |= TULIP_WANTHASH; - sp[40] = ((u_short *) sc->tulip_ac.ac_enaddr)[0]; - sp[41] = ((u_short *) sc->tulip_ac.ac_enaddr)[1]; - sp[42] = ((u_short *) sc->tulip_ac.ac_enaddr)[2]; - } else { - /* - * Else can get perfect filtering for 16 addresses. - */ - i = 0; - ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm); - for (; enm != NULL; i++) { - *sp++ = ((u_short *) enm->enm_addrlo)[0]; - *sp++ = ((u_short *) enm->enm_addrlo)[1]; - *sp++ = ((u_short *) enm->enm_addrlo)[2]; - ETHER_NEXT_MULTI(step, enm); - } - /* - * If an IP address is enabled, turn on broadcast - */ - if (sc->tulip_ac.ac_ipaddr.s_addr != 0) { - i++; - *sp++ = 0xFFFF; - *sp++ = 0xFFFF; - *sp++ = 0xFFFF; - } - /* - * Pad the rest with our hardware address - */ - for (; i < 16; i++) { - *sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[0]; - *sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[1]; - *sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[2]; - } - } -} - -static int -tulip_ioctl( - struct ifnet *ifp, - int cmd, - caddr_t data) -{ - tulip_softc_t *sc = tulips[ifp->if_unit]; - struct ifaddr *ifa = (struct ifaddr *)data; - struct ifreq *ifr = (struct ifreq *) data; - int s, error = 0; - - s = splimp(); - - switch (cmd) { - case SIOCSIFADDR: { - - ifp->if_flags |= IFF_UP; - switch(ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: { - ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; - tulip_addr_filter(sc); /* reset multicast filtering */ - (*ifp->if_init)(ifp->if_unit); - arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); - break; - } -#endif /* INET */ - -#ifdef NS - /* This magic copied from if_is.c; I don't use XNS, - * so I have no way of telling if this actually - * works or not. - */ - case AF_NS: { - struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); - if (ns_nullhost(*ina)) { - ina->x_host = *(union ns_host *)(sc->tulip_ac.ac_enaddr); - } else { - ifp->if_flags &= ~IFF_RUNNING; - bcopy((caddr_t)ina->x_host.c_host, - (caddr_t)sc->tulip_ac.ac_enaddr, - sizeof sc->tulip_ac.ac_enaddr); - } - - (*ifp->if_init)(ifp->if_unit); - break; - } -#endif /* NS */ - - default: { - (*ifp->if_init)(ifp->if_unit); - break; - } - } - break; - } - - case SIOCSIFFLAGS: { - /* - * Changing the connection forces a reset. - */ - if (sc->tulip_flags & TULIP_ALTPHYS) { - if ((ifp->if_flags & IFF_ALTPHYS) == 0) - TULIP_RESET(sc); - } else { - if (ifp->if_flags & IFF_ALTPHYS) - TULIP_RESET(sc); - } - (*ifp->if_init)(ifp->if_unit); - break; - } - - case SIOCADDMULTI: - case SIOCDELMULTI: { - /* - * Update multicast listeners - */ - if (cmd == SIOCADDMULTI) - error = ether_addmulti(ifr, &sc->tulip_ac); - else - error = ether_delmulti(ifr, &sc->tulip_ac); - - if (error == ENETRESET) { - tulip_addr_filter(sc); /* reset multicast filtering */ - (*ifp->if_init)(ifp->if_unit); - error = 0; - } - break; - } - case SIOCSIFMTU: - /* - * Set the interface MTU. - */ - if (ifr->ifr_mtu > ETHERMTU) { - error = EINVAL; - } else { - ifp->if_mtu = ifr->ifr_mtu; - } - break; - - default: { - error = EINVAL; - break; - } - } - - splx(s); - return error; -} - -static void -tulip_attach( - tulip_softc_t *sc) -{ - struct ifnet *ifp = &sc->tulip_if; - int cnt; - - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; - - *sc->tulip_csrs.csr_sia_connectivity = 0; - *sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_10BASET; - for (cnt = 0; cnt < 240000; cnt++) { - if ((*sc->tulip_csrs.csr_sia_status & TULIP_SIASTS_LINKFAIL) == 0) - break; - DELAY(10); - } - if (*sc->tulip_csrs.csr_sia_status & TULIP_SIASTS_LINKFAIL) { - ifp->if_flags |= IFF_ALTPHYS; - } else { - sc->tulip_flags |= TULIP_ALTPHYS; - } - TULIP_RESET(sc); - - ifp->if_init = tulip_init; - ifp->if_ioctl = tulip_ioctl; - ifp->if_output = ether_output; - ifp->if_reset = tulip_reset; - ifp->if_start = tulip_start; - - printf("%s%d: %s pass %d.%d ethernet address %s\n", - sc->tulip_name, sc->tulip_unit, - tulip_chipdescs[tulip_chipids[sc->tulip_unit]], - (sc->tulip_revinfo & 0xF0) >> 4, - sc->tulip_revinfo & 0x0F, - ether_sprintf(sc->tulip_hwaddr)); - - if_attach(ifp); - -#if NBPFILTER > 0 - bpfattach(&sc->tulip_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); -#endif -} - -static void -tulip_initcsrs( - tulip_softc_t *sc, - volatile tulip_uint32_t *va_csrs, - size_t csr_size) -{ - sc->tulip_csrs.csr_busmode = va_csrs + 0 * csr_size; - sc->tulip_csrs.csr_txpoll = va_csrs + 1 * csr_size; - sc->tulip_csrs.csr_rxpoll = va_csrs + 2 * csr_size; - sc->tulip_csrs.csr_rxlist = va_csrs + 3 * csr_size; - sc->tulip_csrs.csr_txlist = va_csrs + 4 * csr_size; - sc->tulip_csrs.csr_status = va_csrs + 5 * csr_size; - sc->tulip_csrs.csr_command = va_csrs + 6 * csr_size; - sc->tulip_csrs.csr_intr = va_csrs + 7 * csr_size; - sc->tulip_csrs.csr_missed_frame = va_csrs + 8 * csr_size; - sc->tulip_csrs.csr_enetrom = va_csrs + 9 * csr_size; - sc->tulip_csrs.csr_reserved = va_csrs + 10 * csr_size; - sc->tulip_csrs.csr_full_duplex = va_csrs + 11 * csr_size; - sc->tulip_csrs.csr_sia_status = va_csrs + 12 * csr_size; - sc->tulip_csrs.csr_sia_connectivity = va_csrs + 13 * csr_size; - sc->tulip_csrs.csr_sia_tx_rx = va_csrs + 14 * csr_size; - sc->tulip_csrs.csr_sia_general = va_csrs + 15 * csr_size; -} - -static void -tulip_initring( - tulip_softc_t *sc, - tulip_ringinfo_t *ri, - tulip_desc_t *descs, - int ndescs) -{ - ri->ri_max = ndescs; - ri->ri_first = descs; - ri->ri_last = ri->ri_first + ri->ri_max; - bzero((caddr_t) ri->ri_first, sizeof(ri->ri_first[0]) * ri->ri_max); - ri->ri_last[-1].d_flag = TULIP_DFLAG_ENDRING; -} - -#if NPCI > 0 -/* - * This is the PCI configuration support. Since the DC21040 is available - * on both EISA and PCI boards, one must be careful in how defines the - * DC21040 in the config file. - */ -static char* tulip_pci_probe (pcici_t config_id, pcidi_t device_id); -static void tulip_pci_attach(pcici_t config_id, int unit); -static u_long tulip_count; - -struct pci_driver dedevice = { - tulip_pci_probe, - tulip_pci_attach, - &tulip_count, -}; - -#define PCI_CFID 0x00 /* Configuration ID */ -#define PCI_CFCS 0x04 /* Configurtion Command/Status */ -#define PCI_CFRV 0x08 /* Configuration Revision */ -#define PCI_CFLT 0x0c /* Configuration Latency Timer */ -#define PCI_CBIO 0x10 /* Configuration Base IO Address */ -#define PCI_CBMA 0x14 /* Configuration Base Memory Address */ -#define PCI_CFIT 0x3c /* Configuration Interrupt */ -#define PCI_CFDA 0x40 /* Configuration Driver Area */ - -#define TULIP_PCI_CSRSIZE (8 / sizeof(tulip_uint32_t)) -static char* -tulip_pci_probe( - pcici_t config_id, - pcidi_t device_id) -{ - int idx; - for (idx = 0; idx < NDE; idx++) { - if (tulips[idx] == NULL) { - if (device_id == 0x00021011ul) { - tulip_chipids[idx] = TULIP_DC21040; - return "Digital DC21040 Ethernet"; - } - if (device_id == 0x00091011ul) { - tulip_chipids[idx] = TULIP_DC21140; - return "Digital DC21140 Fast Ethernet"; - } - return NULL; - } - } - return NULL; -} - -static void -tulip_pci_attach( - pcici_t config_id, - int unit) -{ - tulip_softc_t *sc; - int retval, idx; - vm_offset_t va_csrs, pa_csrs; - tulip_desc_t *rxdescs, *txdescs; - - sc = (tulip_softc_t *) malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); - if (sc == NULL) - return; - - rxdescs = (tulip_desc_t *) - malloc(sizeof(tulip_desc_t) * TULIP_RXDESCS, M_DEVBUF, M_NOWAIT); - if (rxdescs == NULL) { - free((caddr_t) sc, M_DEVBUF); - return; - } - - txdescs = (tulip_desc_t *) - malloc(sizeof(tulip_desc_t) * TULIP_TXDESCS, M_DEVBUF, M_NOWAIT); - if (txdescs == NULL) { - free((caddr_t) rxdescs, M_DEVBUF); - free((caddr_t) sc, M_DEVBUF); - return; - } - - bzero(sc, sizeof(sc)); /* Zero out the softc*/ - sc->tulip_rxspace = kmem_alloc(kernel_map, TULIP_RXSPACE + NBPG); - /* - * We've allocated an extra page of receive space so we can double map - * the first page of the receive space into the page after the last page - * of the receive space. This means that even if a receive wraps around - * the end of the receive space, it will still virtually contiguous and - * that greatly simplifies the recevie logic. - */ - pmap_enter(pmap_kernel(), sc->tulip_rxspace + TULIP_RXSPACE, - vtophys(sc->tulip_rxspace), VM_PROT_READ, TRUE); - - sc->tulip_unit = unit; - sc->tulip_name = "de"; - retval = pci_map_mem(config_id, PCI_CBMA, &va_csrs, &pa_csrs); - if (!retval) { - kmem_free(kernel_map, sc->tulip_rxspace, TULIP_RXSPACE + NBPG); - free((caddr_t) txdescs, M_DEVBUF); - free((caddr_t) rxdescs, M_DEVBUF); - free((caddr_t) sc, M_DEVBUF); - return; - } - tulips[unit] = sc; - tulip_initcsrs(sc, (volatile tulip_uint32_t *) va_csrs, TULIP_PCI_CSRSIZE); - tulip_initring(sc, &sc->tulip_rxinfo, rxdescs, TULIP_RXDESCS); - tulip_initring(sc, &sc->tulip_txinfo, txdescs, TULIP_TXDESCS); - sc->tulip_revinfo = pci_conf_read(config_id, PCI_CFRV); - if ((retval = tulip_read_macaddr(sc)) < 0) { - printf("de%d: can't read ENET ROM (why=%d) (", sc->tulip_unit, retval); - for (idx = 0; idx < 32; idx++) - printf("%02x", sc->tulip_rombuf[idx]); - printf("\n"); - printf("%s%d: %s pass %d.%d ethernet address %s\n", - sc->tulip_name, sc->tulip_unit, - tulip_chipdescs[tulip_chipids[sc->tulip_unit]], - (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F, - "unknown"); - } else { - TULIP_RESET(sc); - tulip_attach(sc); - pci_map_int (config_id, tulip_intr, (void*) sc, &net_imask); - } -} -#endif /* NPCI > 0 */ -#endif /* NDE > 0 */ diff --git a/sys/pci/ncr.c b/sys/pci/ncr.c deleted file mode 100644 index 80c8a3dae7bc..000000000000 --- a/sys/pci/ncr.c +++ /dev/null @@ -1,6499 +0,0 @@ -/************************************************************************** -** -** $Id: ncr.c,v 1.11 1994/10/27 20:12:46 se Exp $ -** -** Device driver for the NCR 53C810 PCI-SCSI-Controller. -** -** 386bsd / FreeBSD / NetBSD -** -**------------------------------------------------------------------------- -** -** Written for 386bsd and FreeBSD by -** Wolfgang Stanglmeier <wolf@dentaro.gun.de> -** Stefan Esser <se@mi.Uni-Koeln.de> -** -** Ported to NetBSD by -** Charles M. Hannum <mycroft@gnu.ai.mit.edu> -** -**------------------------------------------------------------------------- -** -** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. -** -** 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. -** 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. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. -** -*************************************************************************** -*/ - -#define NCR_VERSION (2) -#define MAX_UNITS (16) - - -/*========================================================== -** -** Configuration and Debugging -** -** May be overwritten in <i386/conf/XXXXX> -** -**========================================================== -*/ - -/* -** SCSI address of this device. -** The boot routines should have set it. -** If not, use this. -*/ - -#ifndef SCSI_NCR_MYADDR -#define SCSI_NCR_MYADDR (7) -#endif /* SCSI_NCR_MYADDR */ - -/* -** The maximal synchronous frequency in kHz. -** (0=asynchronous) -*/ - -#ifndef SCSI_NCR_MAX_SYNC -#define SCSI_NCR_MAX_SYNC (10000) -#endif /* SCSI_NCR_MAX_SYNC */ - -/* -** The maximal bus with (in log2 byte) -** (0=8 bit, 1=16 bit) -*/ - -#ifndef SCSI_NCR_MAX_WIDE -#define SCSI_NCR_MAX_WIDE (1) -#endif /* SCSI_NCR_MAX_WIDE */ - -/* -** The maximum number of tags per logic unit. -** Used only for disk devices that support tags. -*/ - -#ifndef SCSI_NCR_MAX_TAGS -#define SCSI_NCR_MAX_TAGS (4) -#endif /* SCSI_NCR_MAX_TAGS */ - -/*========================================================== -** -** Configuration and Debugging -** -**========================================================== -*/ - -/* -** Number of targets supported by the driver. -** n permits target numbers 0..n-1. -** Default is 7, meaning targets #0..#6. -** #7 .. is myself. -*/ - -#define MAX_TARGET (7) - -/* -** Number of logic units supported by the driver. -** n enables logic unit numbers 0..n-1. -** The common SCSI devices require only -** one lun, so take 1 as the default. -*/ - -#define MAX_LUN (1) - -/* -** The maximum number of jobs scheduled for starting. -** There should be one slot per target, and one slot -** for each tag of each target. -*/ - -#define MAX_START (7 * SCSI_NCR_MAX_TAGS) - -/* -** The maximum number of segments a transfer is split into. -*/ - -#define MAX_SCATTER (33) - -/* -** The maximum transfer length (should be >= 64k). -** MUST NOT be greater than (MAX_SCATTER-1) * NBPG. -*/ - -#define MAX_SIZE ((MAX_SCATTER-1) * NBPG) - -/* -** Write disk status information to dkstat ? -*/ - -#define DK 0 - -/*========================================================== -** -** Include files -** -**========================================================== -*/ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/proc.h> - -#ifdef KERNEL -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/buf.h> -#include <sys/kernel.h> -#ifdef DK -#include <sys/dkstat.h> -#endif /* DK */ -#include <vm/vm.h> -#endif /* KERNEL */ - -#include <i386/pci/ncrreg.h> - -#ifdef __NetBSD__ -#include <sys/device.h> -#include <i386/pci/pcivar.h> -#endif /* __NetBSD */ -#include <i386/pci/pcireg.h> - -#include <scsi/scsi_all.h> -#include <scsi/scsiconf.h> - - -/*========================================================== -** -** Debugging tags -** -**========================================================== -*/ - -#define DEBUG_ALLOC (0x0001) -#define DEBUG_PHASE (0x0002) -#define DEBUG_POLL (0x0004) -#define DEBUG_QUEUE (0x0008) -#define DEBUG_RESULT (0x0010) -#define DEBUG_SCATTER (0x0020) -#define DEBUG_SCRIPT (0x0040) -#define DEBUG_TINY (0x0080) -#define DEBUG_TIMING (0x0100) -#define DEBUG_NEGO (0x0200) -#define DEBUG_TAGS (0x0400) -#define DEBUG_FREEZE (0x0800) -#define DEBUG_RESTART (0x1000) - -/* -** Enable/Disable debug messages. -** Can be changed at runtime too. -*/ - -#ifdef SCSI_DEBUG_FLAGS - #define DEBUG_FLAGS ncr_debug; -#else /* SCSI_DEBUG_FLAGS */ - #define SCSI_DEBUG_FLAGS 0 - #define DEBUG_FLAGS 0 -#endif /* SCSI_DEBUG_FLAGS */ - - - -/*========================================================== -** -** assert () -** -**========================================================== -** -** modified copy from 386bsd:/usr/include/sys/assert.h -** -**---------------------------------------------------------- -*/ - -#define assert(expression) { \ - if (!(expression)) { \ - (void)printf(\ - "assertion \"%s\" failed: file \"%s\", line %d\n", \ - #expression, \ - __FILE__, __LINE__); \ - } \ -} - -/*========================================================== -** -** Access to the controller chip. -** -**========================================================== -*/ - -#define INB(r) (np->reg->r) -#define INW(r) (np->reg->r) -#define INL(r) (np->reg->r) - -#define OUTB(r, val) np->reg->r = val -#define OUTW(r, val) np->reg->r = val -#define OUTL(r, val) np->reg->r = val - -/*========================================================== -** -** Command control block states. -** -**========================================================== -*/ - -#define HS_IDLE (0) -#define HS_BUSY (1) -#define HS_NEGOTIATE (2) /* sync/wide data transfer*/ -#define HS_DISCONNECT (3) /* Disconnected by target */ - -#define HS_COMPLETE (4) -#define HS_SEL_TIMEOUT (5) /* Selection timeout */ -#define HS_RESET (6) /* SCSI reset */ -#define HS_ABORTED (7) /* Transfer aborted */ -#define HS_TIMEOUT (8) /* Software timeout */ -#define HS_FAIL (9) /* SCSI or PCI bus errors */ -#define HS_UNEXPECTED (10) /* Unexpected disconnect */ - -#define HS_DONEMASK (0xfc) - -/*========================================================== -** -** Software Interrupt Codes -** -**========================================================== -*/ - -#define SIR_SENSE_RESTART (1) -#define SIR_SENSE_FAILED (2) -#define SIR_STALL_RESTART (3) -#define SIR_STALL_QUEUE (4) -#define SIR_NEGO_SYNC (5) -#define SIR_NEGO_WIDE (6) -#define SIR_NEGO_FAILED (7) -#define SIR_NEGO_PROTO (8) -#define SIR_REJECT_RECEIVED (9) -#define SIR_REJECT_SENT (10) -#define SIR_IGN_RESIDUE (11) -#define SIR_MISSING_SAVE (12) -#define SIR_MAX (12) - -/*========================================================== -** -** Extended error codes. -** xerr_status field of struct ccb. -** -**========================================================== -*/ - -#define XE_OK (0) -#define XE_EXTRA_DATA (1) /* unexpected data phase */ -#define XE_BAD_PHASE (2) /* illegal phase (4/5) */ - -/*========================================================== -** -** Negotiation status. -** nego_status field of struct ccb. -** -**========================================================== -*/ - -#define NS_SYNC (1) -#define NS_WIDE (2) - -/*========================================================== -** -** "Special features" of targets. -** quirks field of struct tcb. -** actualquirks field of struct ccb. -** -**========================================================== -*/ - -#define QUIRK_AUTOSAVE (0x01) -#define QUIRK_NOMSG (0x02) -#define QUIRK_UPDATE (0x80) - -/*========================================================== -** -** Capability bits in Inquire response byte 7. -** -**========================================================== -*/ - -#define INQ7_QUEUE (0x02) -#define INQ7_SYNC (0x10) -#define INQ7_WIDE16 (0x20) - -/*========================================================== -** -** Misc. -** -**========================================================== -*/ - -#define CCB_MAGIC (0xf2691ad2) -#define MAX_TAGS (16) /* hard limit */ - -/*========================================================== -** -** OS dependencies. -** -**========================================================== -*/ - -#ifndef __FreeBSD__ -#ifndef __NetBSD__ - #define ANCIENT -#endif /*__NetBSD__*/ -#endif /*__FreeBSD__*/ - -#ifdef ANCIENT -#ifdef KERNEL - extern int splbio(void); - extern void splx(int level); - extern int wakeup(void* channel); - extern int tsleep(); - extern int DELAY(); - extern int scsi_attachdevs(); - extern void timeout(); - extern void untimeout(); -#endif /* KERNEL */ - #define bio_imask biomask - #define LUN lu - #define TARGET targ - #define PRINT_ADDR(xp) printf ("ncr0: targ %d lun %d ",xp->targ,xp->lu) - #define INT32 int - #define U_INT32 long - #define TIMEOUT -#else /* !ANCIENT */ - #define LUN sc_link->lun - #define TARGET sc_link->target - #define PRINT_ADDR(xp) sc_print_addr(xp->sc_link) -#ifdef __NetBSD__ - #define INT32 int - #define U_INT32 u_int - #define TIMEOUT (void*) -#else /*__NetBSD__*/ - #define INT32 int32 - #define U_INT32 u_int32 - #define TIMEOUT (timeout_func_t) -#endif /*__NetBSD__*/ -#endif /* ANCIENT */ - -/*========================================================== -** -** Declaration of structs. -** -**========================================================== -*/ - -struct tcb; -struct lcb; -struct ccb; -struct ncb; -struct script; - -typedef struct ncb * ncb_p; -typedef struct tcb * tcb_p; -typedef struct lcb * lcb_p; -typedef struct ccb * ccb_p; - -struct link { - u_long l_cmd; - u_long l_paddr; -}; - -struct usrcmd { - u_long target; - u_long lun; - u_long data; - u_long cmd; -}; - -#define UC_SETSYNC 10 -#define UC_SETTAGS 11 -#define UC_SETDEBUG 12 -#define UC_SETORDER 13 -#define UC_SETWIDE 14 -#define UC_SETFLAG 15 - -#define UF_TRACE (0x01) - - -/*========================================================== -** -** Access to fields of structs. -** -**========================================================== -*/ - -#define offsetof(type, member) ((size_t)(&((type *)0)->member)) - -/*--------------------------------------- -** -** Timestamps for profiling -** -**--------------------------------------- -*/ - -struct tstamp { - struct timeval start; - struct timeval end; - struct timeval select; - struct timeval command; - struct timeval data; - struct timeval status; - struct timeval disconnect; - struct timeval reselect; -}; - -/* -** profiling data (per device) -*/ - -struct profile { - u_long num_trans; - u_long num_bytes; - u_long num_disc; - u_long num_break; - u_long num_int; - u_long num_fly; - u_long ms_setup; - u_long ms_data; - u_long ms_disc; - u_long ms_post; -}; - -/*========================================================== -** -** Declaration of structs: TARGET control block -** -**========================================================== -*/ - -struct tcb { - /* - ** during reselection the ncr jumps to this point - ** with SFBR set to the encoded TARGET number - ** with bit 7 set. - ** if it's not this target, jump to the next. - ** - ** JUMP IF (SFBR != #TARGET#) - ** @(next tcb) - */ - - struct link jump_tcb; - - /* - ** load the actual values for the sxfer and the scntl3 - ** register (sync/wide mode). - ** - ** SCR_COPY (1); - ** @(sval field of this tcb) - ** @(sxfer register) - ** SCR_COPY (1); - ** @(wval field of this tcb) - ** @(scntl3 register) - */ - - ncrcmd getscr[6]; - - /* - ** if next message is "identify" - ** then load the message to SFBR, - ** else load 0 to SFBR. - ** - ** CALL - ** <RESEL_LUN> - */ - - struct link call_lun; - - /* - ** now look for the right lun. - ** - ** JUMP - ** @(first ccb of this lun) - */ - - struct link jump_lcb; - - /* - ** pointer to interrupted getcc ccb - */ - - ccb_p hold_cp; - - /* - ** statistical data - */ - - u_long transfers; - u_long bytes; - - /* - ** user settable limits for sync transfer - ** and tagged commands. - */ - - u_char usrsync; - u_char usrtags; - u_char usrwide; - u_char usrflag; - - /* - ** negotiation of wide and synch transfer. - ** device quirks. - */ - -/*0*/ u_char minsync; -/*1*/ u_char sval; -/*2*/ u_short period; -/*0*/ u_char maxoffs; - -/*1*/ u_char quirks; - -/*2*/ u_char widedone; -/*3*/ u_char wval; - /* - ** inquire data - */ -#define MAX_INQUIRE 36 - u_char inqdata[MAX_INQUIRE]; - - /* - ** the lcb's of this tcb - */ - - lcb_p lp[MAX_LUN]; -}; - -/*========================================================== -** -** Declaration of structs: LUN control block -** -**========================================================== -*/ - -struct lcb { - /* - ** during reselection the ncr jumps to this point - ** with SFBR set to the "Identify" message. - ** if it's not this lun, jump to the next. - ** - ** JUMP IF (SFBR == #LUN#) - ** @(next lcb of this target) - */ - - struct link jump_lcb; - - /* - ** if next message is "simple tag", - ** then load the tag to SFBR, - ** else load 0 to SFBR. - ** - ** CALL - ** <RESEL_TAG> - */ - - struct link call_tag; - - /* - ** now look for the right ccb. - ** - ** JUMP - ** @(first ccb of this lun) - */ - - struct link jump_ccb; - - /* - ** start of the ccb chain - */ - - ccb_p next_ccb; - - /* - ** Control of tagged queueing - */ - - u_char reqccbs; - u_char actccbs; - u_char reqlink; - u_char actlink; - u_char usetags; - u_char lasttag; -}; - -/*========================================================== -** -** Declaration of structs: COMMAND control block -** -**========================================================== -** -** This substructure is copied from the ccb to a -** global address after selection (or reselection) -** and copied back before disconnect. -** -** These fields are accessible to the script processor. -** -**---------------------------------------------------------- -*/ - -struct head { - /* - ** Execution of a ccb starts at this point. - ** It's a jump to the "SELECT" label - ** of the script. - ** - ** After successful selection the script - ** processor overwrites it with a jump to - ** the IDLE label of the script. - */ - - struct link launch; - - /* - ** Saved data pointer. - ** Points to the position in the script - ** responsible for the actual transfer - ** of data. - ** It's written after reception of a - ** "SAVE_DATA_POINTER" message. - ** The goalpointer points after - ** the last transfer command. - */ - - u_long savep; - u_long lastp; - u_long goalp; - - /* - ** The virtual address of the ccb - ** containing this header. - */ - - ccb_p cp; - - /* - ** space for some timestamps to gather - ** profiling data about devices and this driver. - */ - - struct tstamp stamp; - - /* - ** status fields. - */ - - u_char status[8]; -}; - -/* -** The status bytes are used by the host and the script processor. -** -** The first four byte are copied to the scratchb register -** (declared as scr0..scr3 in ncr_reg.h) just after the select/reselect, -** and copied back just after disconnecting. -** Inside the script the XX_REG are used. -** -** The last four bytes are used inside the script by "COPY" commands. -** Because source and destination must have the same alignment -** in a longword, the fields HAVE to be on the selected offsets. -** xerr_st (4) 0 (0x34) scratcha -** sync_st (5) 1 (0x05) sxfer -** wide_st (7) 3 (0x03) scntl3 -*/ - -/* -** First four bytes (script) -*/ -#define QU_REG scr0 -#define HS_REG scr1 -#define HS_PRT nc_scr1 -#define SS_REG scr2 -#define PS_REG scr3 - -/* -** First four bytes (host) -*/ -#define actualquirks phys.header.status[0] -#define host_status phys.header.status[1] -#define scsi_status phys.header.status[2] -#define parity_status phys.header.status[3] - -/* -** Last four bytes (script) -*/ -#define xerr_st header.status[4] /* MUST be ==0 mod 4 */ -#define sync_st header.status[5] /* MUST be ==1 mod 4 */ -#define nego_st header.status[6] -#define wide_st header.status[7] /* MUST be ==3 mod 4 */ - -/* -** Last four bytes (host) -*/ -#define xerr_status phys.xerr_st -#define sync_status phys.sync_st -#define nego_status phys.nego_st -#define wide_status phys.wide_st - -/*========================================================== -** -** Declaration of structs: Data structure block -** -**========================================================== -** -** During execution of a ccb by the script processor, -** the DSA (data structure address) register points -** to this substructure of the ccb. -** This substructure contains the header with -** the script-processor-changable data and -** data blocks for the indirect move commands. -** -**---------------------------------------------------------- -*/ - -struct dsb { - - /* - ** Header. - ** Has to be the first entry, - ** because it's jumped to by the - ** script processor - */ - - struct head header; - - /* - ** Table data for Script - */ - - struct scr_tblsel select; - struct scr_tblmove smsg ; - struct scr_tblmove smsg2 ; - struct scr_tblmove cmd ; - struct scr_tblmove sense ; - struct scr_tblmove data [MAX_SCATTER]; -}; - -/*========================================================== -** -** Declaration of structs: Command control block. -** -**========================================================== -** -** During execution of a ccb by the script processor, -** the DSA (data structure address) register points -** to this substructure of the ccb. -** This substructure contains the header with -** the script-processor-changable data and then -** data blocks for the indirect move commands. -** -**---------------------------------------------------------- -*/ - - -struct ccb { - /* - ** during reselection the ncr jumps to this point. - ** If a "SIMPLE_TAG" message was received, - ** then SFBR is set to the tag. - ** else SFBR is set to 0 - ** If looking for another tag, jump to the next ccb. - ** - ** JUMP IF (SFBR != #TAG#) - ** @(next ccb of this lun) - */ - - struct link jump_ccb; - - /* - ** After execution of this call, the return address - ** (in the TEMP register) points to the following - ** data structure block. - ** So copy it to the DSA register, and start - ** processing of this data structure. - ** - ** CALL - ** <RESEL_TMP> - */ - - struct link call_tmp; - - /* - ** This is the data structure which is - ** to be executed by the script processor. - */ - - struct dsb phys; - - /* - ** If a data transfer phase is terminated too early - ** (after reception of a message (i.e. DISCONNECT)), - ** we have to prepare a mini script to transfer - ** the rest of the data. - */ - - u_long patch[8]; - - /* - ** The general SCSI driver provides a - ** pointer to a control block. - */ - - struct scsi_xfer *xfer; - -#ifdef ANCIENT - /* - ** We copy the SCSI command, because it - ** may be volatile (on the stack). - ** - */ - struct scsi_generic cmd; -#endif /* ANCIENT */ - - /* - ** We prepare a message to be sent after selection, - ** and a second one to be sent after getcc selection. - ** Contents are IDENTIFY and SIMPLE_TAG. - ** While negotiating sync or wide transfer, - ** a SDTM or WDTM message is appended. - */ - - u_char scsi_smsg [8]; - u_char scsi_smsg2[8]; - - /* - ** Lock this ccb. - ** Flag is used while looking for a free ccb. - */ - - u_long magic; - - /* - ** Completion time out for this job. - ** It's set to time of start + allowed number of seconds. - */ - - u_long tlimit; - - /* - ** All ccbs of one hostadapter are linked. - */ - - ccb_p link_ccb; - - /* - ** All ccbs of one target/lun are linked. - */ - - ccb_p next_ccb; - - /* - ** Tag for this transfer. - ** It's patched into jump_ccb. - ** If it's not zero, a SIMPLE_TAG - ** message is included in smsg. - */ - - u_char tag; -}; - -/*========================================================== -** -** Declaration of structs: NCR device descriptor -** -**========================================================== -*/ - -struct ncb { -#ifdef __NetBSD__ - struct device sc_dev; - struct intrhand sc_ih; -#else /* !__NetBSD__ */ - int unit; -#endif /* __NetBSD__ */ - - /*----------------------------------------------- - ** Scripts .. - **----------------------------------------------- - ** - ** During reselection the ncr jumps to this point. - ** The SFBR register is loaded with the encoded target id. - ** - ** Jump to the first target. - ** - ** JUMP - ** @(next tcb) - */ - struct link jump_tcb; - - /*----------------------------------------------- - ** Configuration .. - **----------------------------------------------- - ** - ** virtual and physical addresses - ** of the 53c810 chip. - */ - vm_offset_t vaddr; - vm_offset_t paddr; - - /* - ** pointer to the chip's registers. - */ - volatile - struct ncr_reg* reg; - - /* - ** A copy of the script, relocated for this ncb. - */ - struct script *script; - u_long p_script; - - /* - ** The SCSI address of the host adapter. - */ - u_char myaddr; - - /* - ** timing parameters - */ - u_char ns_async; - u_char ns_sync; - u_char rv_scntl3; - -#ifndef ANCIENT - /*----------------------------------------------- - ** Link to the generic SCSI driver - **----------------------------------------------- - */ - - struct scsi_link sc_link; -#endif /* ANCIENT */ - - /*----------------------------------------------- - ** Job control - **----------------------------------------------- - ** - ** Commands from user - */ - struct usrcmd user; - u_char order; - - /* - ** Target data - */ - struct tcb target[MAX_TARGET]; - - /* - ** Start queue. - */ - u_long squeue [MAX_START]; - u_short squeueput; - u_short actccbs; - - /* - ** Timeout handler - */ - u_long heartbeat; - u_short ticks; - u_short latetime; - u_long lasttime; - - /*----------------------------------------------- - ** Debug and profiling - **----------------------------------------------- - ** - ** register dump - */ - struct ncr_reg regdump; - struct timeval regtime; - - /* - ** Profiling data - */ - struct profile profile; - u_long disc_phys; - u_long disc_ref; - - /* - ** The global header. - ** Accessible to both the host and the - ** script-processor. - */ - struct head header; - - /* - ** The global control block. - ** It's used only during the configuration phase. - ** A target control block will be created - ** after the first successful transfer. - */ - struct ccb ccb; - - /* - ** message buffers. - ** Should be longword aligned, - ** because they're written with a - ** COPY script command. - */ - u_char msgout[8]; - u_char msgin [8]; - u_long lastmsg; - - /* - ** Buffer for STATUS_IN phase. - */ - u_char scratch; - - /* - ** controller chip dependent maximal transfer width. - */ - u_char maxwide; - - /* - ** lockout of execption handler call while starting command. - */ - u_char lock; -}; - -/*========================================================== -** -** -** Script for NCR-Processor. -** -** Use ncr_script_fill() to create the variable parts. -** Use ncr_script_copy_and_bind() to make a copy and -** bind to physical addresses. -** -** -**========================================================== -** -** We have to know the offsets of all labels before -** we reach them (for forward jumps). -** Therefore we declare a struct here. -** If you make changes inside the script, -** DONT FORGET TO CHANGE THE LENGTHS HERE! -** -**---------------------------------------------------------- -*/ - -struct script { - ncrcmd start [ 7]; - ncrcmd start0 [ 2]; - ncrcmd start1 [ 3]; - ncrcmd startpos [ 1]; - ncrcmd tryloop [MAX_START*5+2]; - ncrcmd trysel [ 8]; - ncrcmd skip [ 8]; - ncrcmd skip2 [ 3]; - ncrcmd idle [ 2]; - ncrcmd select [ 24]; - ncrcmd prepare [ 4]; - ncrcmd loadpos [ 14]; - ncrcmd prepare2 [ 24]; - ncrcmd setmsg [ 5]; - ncrcmd clrack [ 2]; - ncrcmd dispatch [ 31]; - ncrcmd no_data [ 17]; - ncrcmd checkatn [ 10]; - ncrcmd command [ 15]; - ncrcmd status [ 27]; - ncrcmd msg_in [ 26]; - ncrcmd msg_bad [ 6]; - ncrcmd msg_parity [ 6]; - ncrcmd msg_reject [ 8]; - ncrcmd msg_ign_residue [ 32]; - ncrcmd msg_extended [ 18]; - ncrcmd msg_ext_2 [ 18]; - ncrcmd msg_wdtr [ 27]; - ncrcmd msg_ext_3 [ 18]; - ncrcmd msg_sdtr [ 27]; - ncrcmd complete [ 13]; - ncrcmd cleanup [ 12]; - ncrcmd cleanup0 [ 11]; - ncrcmd signal [ 10]; - ncrcmd save_dp [ 5]; - ncrcmd restore_dp [ 5]; - ncrcmd disconnect [ 12]; - ncrcmd disconnect0 [ 5]; - ncrcmd disconnect1 [ 23]; - ncrcmd msg_out [ 9]; - ncrcmd msg_out_done [ 7]; - ncrcmd msg_out_abort [ 10]; - ncrcmd getcc [ 4]; - ncrcmd getcc1 [ 5]; - ncrcmd getcc2 [ 33]; - ncrcmd getcc3 [ 10]; - ncrcmd badgetcc [ 6]; - ncrcmd reselect [ 12]; - ncrcmd reselect2 [ 6]; - ncrcmd resel_tmp [ 5]; - ncrcmd resel_lun [ 18]; - ncrcmd resel_tag [ 24]; - ncrcmd data_in [MAX_SCATTER * 4 + 7]; - ncrcmd data_out [MAX_SCATTER * 4 + 7]; - ncrcmd aborttag [ 4]; - ncrcmd abort [ 20]; - ncrcmd snooptest [ 11]; -}; - -/*========================================================== -** -** -** Function headers. -** -** -**========================================================== -*/ - -#ifdef KERNEL -static void ncr_alloc_ccb (ncb_p np, struct scsi_xfer * xp); -static void ncr_complete (ncb_p np, ccb_p cp); -static int ncr_delta (struct timeval * from, struct timeval * to); -static void ncr_exception (ncb_p np); -static void ncr_free_ccb (ncb_p np, ccb_p cp, int flags); -static void ncr_getclock (ncb_p np); -static ccb_p ncr_get_ccb (ncb_p np, u_long flags, u_long t,u_long l); -static U_INT32 ncr_info (int unit); -static void ncr_init (ncb_p np, char * msg, u_long code); -static int ncr_intr (ncb_p np); -static void ncr_int_ma (ncb_p np); -static void ncr_int_sir (ncb_p np); -static void ncr_int_sto (ncb_p np); -#ifndef NEW_SCSICONF -static u_long ncr_lookup (char* id); -#endif /* NEW_SCSICONF */ -static void ncr_min_phys (struct buf *bp); -static void ncr_negotiate (struct ncb* np, struct tcb* tp); -static void ncr_opennings (ncb_p np, lcb_p lp, struct scsi_xfer * xp); -static void ncb_profile (ncb_p np, ccb_p cp); -static void ncr_script_copy_and_bind - (struct script * script, ncb_p np); -static void ncr_script_fill (struct script * scr); -static int ncr_scatter (struct dsb* phys,u_long vaddr,u_long datalen); -static void ncr_setmaxtags (tcb_p tp, u_long usrtags); -static void ncr_setsync (ncb_p np, ccb_p cp, u_char sxfer); -static void ncr_settags (tcb_p tp, lcb_p lp); -static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide); -static int ncr_show_msg (u_char * msg); -static int ncr_snooptest (ncb_p np); -static INT32 ncr_start (struct scsi_xfer *xp); -static void ncr_timeout (ncb_p np); -static void ncr_usercmd (ncb_p np); -static void ncr_wakeup (ncb_p np, u_long code); - -#ifdef __NetBSD__ -static int ncr_probe (struct device *, struct device *, void *); -static void ncr_attach (struct device *, struct device *, void *); -#else /* !__NetBSD */ -static char* ncr_probe (pcici_t tag, pcidi_t type); -static void ncr_attach (pcici_t tag, int unit); -#endif /* __NetBSD__ */ - -#endif /* KERNEL */ - -/*========================================================== -** -** -** Global static data. -** -** -**========================================================== -*/ - - -static char ident[] = - "\n$Id: ncr.c,v 1.11 1994/10/27 20:12:46 se Exp $\n"; - -u_long ncr_version = NCR_VERSION - + (u_long) sizeof (struct ncb) - * (u_long) sizeof (struct ccb) - * (u_long) sizeof (struct lcb) - * (u_long) sizeof (struct tcb); - -#ifdef KERNEL - -#ifndef __NetBSD__ -u_long nncr=MAX_UNITS; -ncb_p ncrp [MAX_UNITS]; -#endif - -static int ncr_debug = SCSI_DEBUG_FLAGS; - -int ncr_cache; /* to be alligned _NOT_ static */ - -/* -** SCSI cmd to get the SCSI sense data -*/ - -static u_char rs_cmd [6] = - { 0x03, 0, 0, 0, sizeof (struct scsi_sense_data), 0 }; - -/*========================================================== -** -** -** Global static data: auto configure -** -** -**========================================================== -*/ - -#define NCR_810_ID (0x00011000ul) -#define NCR_825_ID (0x00031000ul) - -#ifdef __NetBSD__ - -struct cfdriver ncrcd = { - NULL, "ncr", ncr_probe, ncr_attach, DV_DISK, sizeof(struct ncb) -}; - -#else /* !__NetBSD__ */ - -static u_long ncr_count; - -struct pci_driver ncr_device = { - ncr_probe, - ncr_attach, - &ncr_count -}; - -#endif /* !__NetBSD__ */ - -#ifndef ANCIENT -struct scsi_adapter ncr_switch = -{ - ncr_start, - ncr_min_phys, - 0, - 0, - ncr_info, - "ncr", -}; - -struct scsi_device ncr_dev = -{ - NULL, /* Use default error handler */ - NULL, /* have a queue, served by this */ - NULL, /* have no async handler */ - NULL, /* Use default 'done' routine */ - "ncr", -}; -#else /* ANCIENT */ -struct scsi_switch ncr_switch = -{ - ncr_start, - ncr_min_phys, - 0, - 0, - ncr_info, - 0,0,0 -}; -#endif /* ANCIENT */ - -#ifdef __NetBSD__ - -#define ncr_name(np) (np->sc_dev.dv_xname) - -#else /* !__NetBSD__ */ - -static char *ncr_name (ncb_p np) -{ - static char name[10]; - sprintf(name, "ncr%d", np->unit); - return (name); -} -#endif - -/*========================================================== -** -** -** Scripts for NCR-Processor. -** -** Use ncr_script_bind for binding to physical addresses. -** -** -**========================================================== -** -** NADDR generates a reference to a field of the controller data. -** PADDR generates a reference to another part of the script. -** RADDR generates a reference to a script processor register. -** FADDR generates a reference to a script processor register -** with offset. -** -**---------------------------------------------------------- -*/ - -#define RELOC_SOFTC 0x40000000 -#define RELOC_LABEL 0x50000000 -#define RELOC_REGISTER 0x60000000 -#define RELOC_MASK 0xf0000000 - -#define NADDR(label) (RELOC_SOFTC | offsetof(struct ncb, label)) -#define PADDR(label) (RELOC_LABEL | offsetof(struct script, label)) -#define RADDR(label) (RELOC_REGISTER | REG(label)) -#define FADDR(label,ofs)(RELOC_REGISTER | ((REG(label))+(ofs))) - -static struct script script0 = { -/*--------------------------< START >-----------------------*/ { - /* - ** Claim to be still alive ... - */ - SCR_COPY (sizeof (((struct ncb *)0)->heartbeat)), - (ncrcmd) &time.tv_sec, - NADDR (heartbeat), - /* - ** Make data structure address invalid. - ** clear SIGP. - */ - SCR_LOAD_REG (dsa, 0xff), - 0, - SCR_FROM_REG (ctest2), - 0, -}/*-------------------------< START0 >----------------------*/,{ - /* - ** Hook for interrupted GetConditionCode. - ** Will be patched to ... IFTRUE by - ** the interrupt handler. - */ - SCR_INT ^ IFFALSE (0), - SIR_SENSE_RESTART, - -}/*-------------------------< START1 >----------------------*/,{ - /* - ** Hook for stalled start queue. - ** Will be patched to IFTRUE by the interrupt handler. - */ - SCR_INT ^ IFFALSE (0), - SIR_STALL_RESTART, - /* - ** Then jump to a certain point in tryloop. - ** Due to the lack of indirect addressing the code - ** is self modifying here. - */ - SCR_JUMP, -}/*-------------------------< STARTPOS >--------------------*/,{ - PADDR(tryloop), -}/*-------------------------< TRYLOOP >---------------------*/,{ -/* -** Load an entry of the start queue into dsa -** and try to start it by jumping to TRYSEL. -** -** Because the size depends on the -** #define MAX_START parameter, it is filled -** in at runtime. -** -**----------------------------------------------------------- -** -** ##===========< I=0; i<MAX_START >=========== -** || SCR_COPY (4), -** || NADDR (squeue[i]), -** || RADDR (dsa), -** || SCR_CALL, -** || PADDR (trysel), -** ##========================================== -** -** SCR_JUMP, -** PADDR(tryloop), -** -**----------------------------------------------------------- -*/ -0 - -}/*-------------------------< TRYSEL >----------------------*/,{ - /* - ** Now: - ** DSA: Address of a Data Structure - ** or Address of the IDLE-Label. - ** - ** TEMP: Address of a script, which tries to - ** start the NEXT entry. - ** - ** Save the TEMP register into the SCRATCHA register. - ** Then copy the DSA to TEMP and RETURN. - ** This is kind of an indirect jump. - ** (The script processor has NO stack, so the - ** CALL is actually a jump and link, and the - ** RETURN is an indirect jump.) - ** - ** If the slot was empty, DSA contains the address - ** of the IDLE part of this script. The processor - ** jumps to IDLE and waits for a reselect. - ** It will wake up and try the same slot again - ** after the SIGP bit becomes set by the host. - ** - ** If the slot was not empty, DSA contains - ** the address of the phys-part of a ccb. - ** The processor jumps to this address. - ** phys starts with head, - ** head starts with launch, - ** so actually the processor jumps to - ** the lauch part. - ** If the entry is scheduled to be executed, - ** then launch contains a jump to SELECT. - ** If it's not scheduled, it contains a jump to IDLE. - */ - SCR_COPY (4), - RADDR (temp), - RADDR (scratcha), - SCR_COPY (4), - RADDR (dsa), - RADDR (temp), - SCR_RETURN, - 0 - -}/*-------------------------< SKIP >------------------------*/,{ - /* - ** This entry has been canceled. - ** Next time use the next slot. - */ - SCR_COPY (4), - RADDR (scratcha), - PADDR (startpos), - /* - ** patch the launch field. - ** should look like an idle process. - */ - SCR_COPY (4), - RADDR (dsa), - PADDR (skip2), - SCR_COPY (8), - PADDR (idle), -}/*-------------------------< SKIP2 >-----------------------*/,{ - 0, - SCR_JUMP, - PADDR(start), -}/*-------------------------< IDLE >------------------------*/,{ - /* - ** Nothing to do? - ** Wait for reselect. - */ - SCR_JUMP, - PADDR(reselect), - -}/*-------------------------< SELECT >----------------------*/,{ - /* - ** DSA contains the address of a scheduled - ** data structure. - ** - ** SCRATCHA contains the address of the script, - ** which starts the next entry. - ** - ** Set Initiator mode. - ** - ** (Target mode is left as an exercise for the student) - */ - - SCR_CLR (SCR_TRG), - 0, - SCR_LOAD_REG (HS_REG, 0xff), - 0, - - /* - ** And try to select this target. - */ - SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select), - PADDR (reselect), - - /* - ** Now there are 4 possibilities: - ** - ** (1) The ncr looses arbitration. - ** This is ok, because it will try again, - ** when the bus becomes idle. - ** (But beware of the timeout function!) - ** - ** (2) The ncr is reselected. - ** Then the script processor takes the jump - ** to the RESELECT label. - ** - ** (3) The ncr completes the selection. - ** Then it will execute the next statement. - ** - ** (4) There is a selection timeout. - ** Then the ncr should interrupt the host and stop. - ** Unfortunately, it seems to continue execution - ** of the script. But it will fail with an - ** IID-interrupt on the next WHEN. - */ - - SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)), - 0, - - /* - ** Save target id to ctest0 register - */ - - SCR_FROM_REG (sdid), - 0, - SCR_TO_REG (ctest0), - 0, - /* - ** Send the IDENTIFY and SIMPLE_TAG messages - ** (and the M_X_SYNC_REQ message) - */ - SCR_MOVE_TBL ^ SCR_MSG_OUT, - offsetof (struct dsb, smsg), - SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_OUT)), - -16, - SCR_CLR (SCR_ATN), - 0, - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - /* - ** Selection complete. - ** Next time use the next slot. - */ - SCR_COPY (4), - RADDR (scratcha), - PADDR (startpos), -}/*-------------------------< PREPARE >----------------------*/,{ - /* - ** The ncr doesn't have an indirect load - ** or store command. So we have to - ** copy part of the control block to a - ** fixed place, where we can access it. - ** - ** We patch the address part of a - ** COPY command with the DSA-register. - */ - SCR_COPY (4), - RADDR (dsa), - PADDR (loadpos), - /* - ** then we do the actual copy. - */ - SCR_COPY (sizeof (struct head)), - /* - ** continued after the next label ... - */ - -}/*-------------------------< LOADPOS >---------------------*/,{ - 0, - NADDR (header), - /* - ** Mark this ccb as not scheduled. - */ - SCR_COPY (8), - PADDR (idle), - NADDR (header.launch), - /* - ** Set a time stamp for this selection - */ - SCR_COPY (sizeof (struct timeval)), - (ncrcmd) &time, - NADDR (header.stamp.select), - /* - ** load the savep (saved pointer) into - ** the TEMP register (actual pointer) - */ - SCR_COPY (4), - NADDR (header.savep), - RADDR (temp), - /* - ** Initialize the status registers - */ - SCR_COPY (4), - NADDR (header.status), - RADDR (scr0), - -}/*-------------------------< PREPARE2 >---------------------*/,{ - /* - ** Load the synchronous mode register - */ - SCR_COPY (1), - NADDR (sync_st), - RADDR (sxfer), - /* - ** Load the wide mode and timing register - */ - SCR_COPY (1), - NADDR (wide_st), - RADDR (scntl3), - /* - ** Initialize the msgout buffer with a NOOP message. - */ - SCR_LOAD_REG (scratcha, M_NOOP), - 0, - SCR_COPY (1), - RADDR (scratcha), - NADDR (msgout), - SCR_COPY (1), - RADDR (scratcha), - NADDR (msgin), - /* - ** Message in phase ? - */ - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** Extended or reject message ? - */ - SCR_FROM_REG (sbdl), - 0, - SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), - PADDR (msg_in), - SCR_JUMP ^ IFTRUE (DATA (M_REJECT)), - PADDR (msg_reject), - /* - ** normal processing - */ - SCR_JUMP, - PADDR (dispatch), -}/*-------------------------< SETMSG >----------------------*/,{ - SCR_COPY (1), - RADDR (scratcha), - NADDR (msgout), - SCR_SET (SCR_ATN), - 0, -}/*-------------------------< CLRACK >----------------------*/,{ - /* - ** Terminate possible pending message phase. - */ - SCR_CLR (SCR_ACK), - 0, - -}/*-----------------------< DISPATCH >----------------------*/,{ - SCR_FROM_REG (HS_REG), - 0, - SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), - SIR_NEGO_FAILED, - SCR_RETURN ^ IFTRUE (WHEN (SCR_DATA_OUT)), - 0, - SCR_RETURN ^ IFTRUE (IF (SCR_DATA_IN)), - 0, - SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)), - PADDR (msg_out), - SCR_JUMP ^ IFTRUE (IF (SCR_MSG_IN)), - PADDR (msg_in), - SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)), - PADDR (command), - SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)), - PADDR (status), - /* - ** Discard one illegal phase byte, if required. - */ - SCR_LOAD_REG (scratcha, XE_BAD_PHASE), - 0, - SCR_COPY (1), - RADDR (scratcha), - NADDR (xerr_st), - SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_OUT)), - 8, - SCR_MOVE_ABS (1) ^ SCR_ILG_OUT, - NADDR (scratch), - SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_IN)), - 8, - SCR_MOVE_ABS (1) ^ SCR_ILG_IN, - NADDR (scratch), - SCR_JUMP, - PADDR (dispatch), - -}/*-------------------------< NO_DATA >--------------------*/,{ - /* - ** The target wants to tranfer too much data - ** or in the wrong direction. - ** Remember that in extended error. - */ - SCR_LOAD_REG (scratcha, XE_EXTRA_DATA), - 0, - SCR_COPY (1), - RADDR (scratcha), - NADDR (xerr_st), - /* - ** Discard one data byte, if required. - */ - SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)), - 8, - SCR_MOVE_ABS (1) ^ SCR_DATA_OUT, - NADDR (scratch), - SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)), - 8, - SCR_MOVE_ABS (1) ^ SCR_DATA_IN, - NADDR (scratch), - /* - ** .. and repeat as required. - */ - SCR_CALL, - PADDR (dispatch), - SCR_JUMP, - PADDR (no_data), -}/*-------------------------< CHECKATN >--------------------*/,{ - /* - ** If AAP (bit 1 of scntl0 register) is set - ** and a parity error is detected, - ** the script processor asserts ATN. - ** - ** The target should switch to a MSG_OUT phase - ** to get the message. - */ - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFFALSE (MASK (CATN, CATN)), - PADDR (dispatch), - /* - ** count it - */ - SCR_REG_REG (PS_REG, SCR_ADD, 1), - 0, - /* - ** Prepare a M_ID_ERROR message - ** (initiator detected error). - ** The target should retry the transfer. - */ - SCR_LOAD_REG (scratcha, M_ID_ERROR), - 0, - SCR_JUMP, - PADDR (setmsg), - -}/*-------------------------< COMMAND >--------------------*/,{ - /* - ** If this is not a GETCC transfer ... - */ - SCR_FROM_REG (SS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (S_CHECK_COND)), - 28, - /* - ** ... set a timestamp ... - */ - SCR_COPY (sizeof (struct timeval)), - (ncrcmd) &time, - NADDR (header.stamp.command), - /* - ** ... and send the command - */ - SCR_MOVE_TBL ^ SCR_COMMAND, - offsetof (struct dsb, cmd), - SCR_JUMP, - PADDR (dispatch), - /* - ** Send the GETCC command - */ -/*>>>*/ SCR_MOVE_ABS (6) ^ SCR_COMMAND, - (ncrcmd) &rs_cmd, - SCR_JUMP, - PADDR (dispatch), - -}/*-------------------------< STATUS >--------------------*/,{ - /* - ** set the timestamp. - */ - SCR_COPY (sizeof (struct timeval)), - (ncrcmd) &time, - NADDR (header.stamp.status), - /* - ** If this is a GETCC transfer, - */ - SCR_FROM_REG (SS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (S_CHECK_COND)), - 40, - /* - ** get the status - */ - SCR_MOVE_ABS (1) ^ SCR_STATUS, - NADDR (scratch), - /* - ** Save status to scsi_status. - ** Mark as complete. - ** And wait for disconnect. - */ - SCR_TO_REG (SS_REG), - 0, - SCR_REG_REG (SS_REG, SCR_OR, S_SENSE), - 0, - SCR_LOAD_REG (HS_REG, HS_COMPLETE), - 0, - SCR_JUMP, - PADDR (checkatn), - /* - ** If it was no GETCC transfer, - ** save the status to scsi_status. - */ -/*>>>*/ SCR_MOVE_ABS (1) ^ SCR_STATUS, - NADDR (scratch), - SCR_TO_REG (SS_REG), - 0, - /* - ** if it was no check condition ... - */ - SCR_JUMP ^ IFTRUE (DATA (S_CHECK_COND)), - PADDR (checkatn), - /* - ** ... mark as complete. - */ - SCR_LOAD_REG (HS_REG, HS_COMPLETE), - 0, - SCR_JUMP, - PADDR (checkatn), - -}/*-------------------------< MSG_IN >--------------------*/,{ - /* - ** Get the first byte of the message - ** and save it to SCRATCHA. - ** - ** The script processor doesn't negate the - ** ACK signal after this transfer. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[0]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), - SCR_FROM_REG (scratcha), - 0, - /* - ** Parity was ok, handle this message. - */ - SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)), - PADDR (complete), - SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)), - PADDR (save_dp), - SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)), - PADDR (restore_dp), - SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)), - PADDR (disconnect), - SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), - PADDR (msg_extended), - SCR_JUMP ^ IFTRUE (DATA (M_NOOP)), - PADDR (clrack), - SCR_JUMP ^ IFTRUE (DATA (M_REJECT)), - PADDR (msg_reject), - SCR_JUMP ^ IFTRUE (DATA (M_IGN_RESIDUE)), - PADDR (msg_ign_residue), - /* - ** Rest of the messages left as - ** an exercise ... - ** - ** Unimplemented messages: - ** fall through to MSG_BAD. - */ -}/*-------------------------< MSG_BAD >------------------*/,{ - /* - ** unimplemented message - reject it. - */ - SCR_INT, - SIR_REJECT_SENT, - SCR_LOAD_REG (scratcha, M_REJECT), - 0, - SCR_JUMP, - PADDR (setmsg), - -}/*-------------------------< MSG_PARITY >---------------*/,{ - /* - ** count it - */ - SCR_REG_REG (PS_REG, SCR_ADD, 0x01), - 0, - /* - ** send a "message parity error" message. - */ - SCR_LOAD_REG (scratcha, M_PARITY), - 0, - SCR_JUMP, - PADDR (setmsg), -}/*-------------------------< MSG_REJECT >---------------*/,{ - /* - ** If a negotiation was in progress, - ** negotiation failed. - */ - SCR_FROM_REG (HS_REG), - 0, - SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), - SIR_NEGO_FAILED, - /* - ** else make host log this message - */ - SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)), - SIR_REJECT_RECEIVED, - SCR_JUMP, - PADDR (clrack), - -}/*-------------------------< MSG_IGN_RESIDUE >----------*/,{ - /* - ** Terminate cycle - */ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get residue size. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[1]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), - SCR_FROM_REG (scratcha), - 0, - /* - ** Size is 0 .. ignore message. - */ - SCR_JUMP ^ IFTRUE (DATA (0)), - PADDR (clrack), - /* - ** Size is not 1 .. have to interrupt. - */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (1)), - 40, - /* - ** Check for residue byte in swide register - */ - SCR_FROM_REG (scntl2), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)), - 16, - /* - ** There IS data in the swide register. - ** Discard it. - */ - SCR_REG_REG (scntl2, SCR_OR, WSR), - 0, - SCR_JUMP, - PADDR (clrack), - /* - ** Load again the size to the sfbr register. - */ -/*>>>*/ SCR_FROM_REG (scratcha), - 0, -/*>>>*/ SCR_INT, - SIR_IGN_RESIDUE, - SCR_JUMP, - PADDR (clrack), - -}/*-------------------------< MSG_EXTENDED >-------------*/,{ - /* - ** Terminate cycle - */ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get length. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[1]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), - SCR_FROM_REG (scratcha), - 0, - /* - */ - SCR_JUMP ^ IFTRUE (DATA (3)), - PADDR (msg_ext_3), - SCR_JUMP ^ IFFALSE (DATA (2)), - PADDR (msg_bad), -}/*-------------------------< MSG_EXT_2 >----------------*/,{ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get extended message code. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[2]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), - SCR_FROM_REG (scratcha), - 0, - SCR_JUMP ^ IFTRUE (DATA (M_X_WIDE_REQ)), - PADDR (msg_wdtr), - /* - ** unknown extended message - */ - SCR_JUMP, - PADDR (msg_bad) -}/*-------------------------< MSG_WDTR >-----------------*/,{ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get data bus width - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[3]), - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), - /* - ** let the host do the real work. - */ - SCR_INT, - SIR_NEGO_WIDE, - /* - ** let the target fetch our answer. - */ - SCR_SET (SCR_ATN), - 0, - SCR_CLR (SCR_ACK), - 0, - - SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), - SIR_NEGO_PROTO, - /* - ** Send the M_X_WIDE_REQ - */ - SCR_MOVE_ABS (4) ^ SCR_MSG_OUT, - NADDR (msgout), - SCR_CLR (SCR_ATN), - 0, - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - SCR_JUMP, - PADDR (msg_out_done), - -}/*-------------------------< MSG_EXT_3 >----------------*/,{ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get extended message code. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[2]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), - SCR_FROM_REG (scratcha), - 0, - SCR_JUMP ^ IFTRUE (DATA (M_X_SYNC_REQ)), - PADDR (msg_sdtr), - /* - ** unknown extended message - */ - SCR_JUMP, - PADDR (msg_bad) - -}/*-------------------------< MSG_SDTR >-----------------*/,{ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get period and offset - */ - SCR_MOVE_ABS (2) ^ SCR_MSG_IN, - NADDR (msgin[3]), - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), - /* - ** let the host do the real work. - */ - SCR_INT, - SIR_NEGO_SYNC, - /* - ** let the target fetch our answer. - */ - SCR_SET (SCR_ATN), - 0, - SCR_CLR (SCR_ACK), - 0, - - SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), - SIR_NEGO_PROTO, - /* - ** Send the M_X_SYNC_REQ - */ - SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, - NADDR (msgout), - SCR_CLR (SCR_ATN), - 0, - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - SCR_JUMP, - PADDR (msg_out_done), - -}/*-------------------------< COMPLETE >-----------------*/,{ - /* - ** Complete message. - ** - ** If it's not the get condition code, - ** copy TEMP register to LASTP in header. - */ - SCR_FROM_REG (SS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFTRUE (MASK (S_SENSE, S_SENSE)), - 12, - SCR_COPY (4), - RADDR (temp), - NADDR (header.lastp), -/*>>>*/ /* - ** When we terminate the cycle by clearing ACK, - ** the target may disconnect immediately. - ** - ** We don't want to be told of an - ** "unexpected disconnect", - ** so we disable this feature. - */ - SCR_REG_REG (scntl2, SCR_AND, 0x7f), - 0, - /* - ** Terminate cycle ... - */ - SCR_CLR (SCR_ACK), - 0, - /* - ** ... and wait for the disconnect. - */ - SCR_WAIT_DISC, - 0, -}/*-------------------------< CLEANUP >-------------------*/,{ - /* - ** dsa: Pointer to ccb - ** or xxxxxxFF (no ccb) - ** - ** HS_REG: Host-Status (<>0!) - */ - SCR_FROM_REG (dsa), - 0, - SCR_JUMP ^ IFTRUE (DATA (0xff)), - PADDR (signal), - /* - ** dsa is valid. - ** save the status registers - */ - SCR_COPY (4), - RADDR (scr0), - NADDR (header.status), - /* - ** and copy back the header to the ccb. - */ - SCR_COPY (4), - RADDR (dsa), - PADDR (cleanup0), - SCR_COPY (sizeof (struct head)), - NADDR (header), -}/*-------------------------< CLEANUP0 >--------------------*/,{ - 0, - - /* - ** If command resulted in "check condition" - ** status and is not yet completed, - ** try to get the condition code. - */ - SCR_FROM_REG (HS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (0, HS_DONEMASK)), - 16, - SCR_FROM_REG (SS_REG), - 0, - SCR_JUMP ^ IFTRUE (DATA (S_CHECK_COND)), - PADDR(getcc2), - /* - ** And make the DSA register invalid. - */ -/*>>>*/ SCR_LOAD_REG (dsa, 0xff), /* invalid */ - 0, -}/*-------------------------< SIGNAL >----------------------*/,{ - /* - ** if status = queue full, - ** reinsert in startqueue and stall queue. - */ - SCR_FROM_REG (SS_REG), - 0, - SCR_INT ^ IFTRUE (DATA (S_QUEUE_FULL)), - SIR_STALL_QUEUE, - /* - ** if job completed ... - */ - SCR_FROM_REG (HS_REG), - 0, - /* - ** ... signal completion to the host - */ - SCR_INT_FLY ^ IFFALSE (MASK (0, HS_DONEMASK)), - 0, - /* - ** Auf zu neuen Schandtaten! - */ - SCR_JUMP, - PADDR(start), - -}/*-------------------------< SAVE_DP >------------------*/,{ - /* - ** SAVE_DP message: - ** Copy TEMP register to SAVEP in header. - */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), - SCR_JUMP, - PADDR (clrack), -}/*-------------------------< RESTORE_DP >---------------*/,{ - /* - ** RESTORE_DP message: - ** Copy SAVEP in header to TEMP register. - */ - SCR_COPY (4), - NADDR (header.savep), - RADDR (temp), - SCR_JUMP, - PADDR (clrack), - -}/*-------------------------< DISCONNECT >---------------*/,{ - /* - ** If QUIRK_AUTOSAVE is set, - ** do an "save pointer" operation. - */ - SCR_FROM_REG (QU_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)), - 12, - /* - ** like SAVE_DP message: - ** Copy TEMP register to SAVEP in header. - */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), -/*>>>*/ /* - ** Check if temp==savep or temp==goalp: - ** if not, log a missing save pointer message. - ** In fact, it's a comparation mod 256. - ** - ** Hmmm, I hadn't thought that I would be urged to - ** write this kind of ugly self modifying code. - ** - ** It's unbelievable, but the ncr53c8xx isn't able - ** to subtract one register from another. - */ - SCR_FROM_REG (temp), - 0, - /* - ** You are not expected to understand this .. - */ - SCR_COPY (1), - NADDR (header.savep), - PADDR (disconnect0), -}/*-------------------------< DISCONNECT0 >--------------*/,{ -/*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (1)), - 20, - /* - ** neither this - */ - SCR_COPY (1), - NADDR (header.goalp), - PADDR (disconnect1), -}/*-------------------------< DISCONNECT1 >--------------*/,{ - SCR_INT ^ IFFALSE (DATA (1)), - SIR_MISSING_SAVE, -/*>>>*/ - - /* - ** DISCONNECTing ... - ** - ** Disable the "unexpected disconnect" feature. - */ - SCR_REG_REG (scntl2, SCR_AND, 0x7f), - 0, - SCR_CLR (SCR_ACK), - 0, - /* - ** Wait for the disconnect. - */ - SCR_WAIT_DISC, - 0, - /* - ** Profiling: - ** Set a time stamp, - ** and count the disconnects. - */ - SCR_COPY (sizeof (struct timeval)), - (ncrcmd) &time, - NADDR (header.stamp.disconnect), - SCR_COPY (4), - NADDR (disc_phys), - RADDR (temp), - SCR_REG_REG (temp, SCR_ADD, 0x01), - 0, - SCR_COPY (4), - RADDR (temp), - NADDR (disc_phys), - /* - ** Status is: DISCONNECTED. - */ - SCR_LOAD_REG (HS_REG, HS_DISCONNECT), - 0, - SCR_JUMP, - PADDR (cleanup), - -}/*-------------------------< MSG_OUT >-------------------*/,{ - /* - ** The target requests a message. - ** First remove ATN so the target will - ** not continue fetching messages. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, - NADDR (msgout), - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - /* - ** If it was no ABORT message ... - */ - SCR_JUMP ^ IFTRUE (DATA (M_ABORT)), - PADDR (msg_out_abort), - /* - ** ... wait for the next phase - ** if it's a message out, send it again, ... - */ - SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)), - PADDR (msg_out), -}/*-------------------------< MSG_OUT_DONE >--------------*/,{ - /* - ** ... else clear the message ... - */ - SCR_LOAD_REG (scratcha, M_NOOP), - 0, - SCR_COPY (4), - RADDR (scratcha), - NADDR (msgout), - /* - ** ... and process the next phase - */ - SCR_JUMP, - PADDR (dispatch), -}/*-------------------------< MSG_OUT_ABORT >-------------*/,{ - /* - ** After ABORT message, - ** - ** expect an immediate disconnect, ... - */ - SCR_REG_REG (scntl2, SCR_AND, 0x7f), - 0, - SCR_CLR (SCR_ACK), - 0, - SCR_WAIT_DISC, - 0, - /* - ** ... and set the status to "ABORTED" - */ - SCR_LOAD_REG (HS_REG, HS_ABORTED), - 0, - SCR_JUMP, - PADDR (cleanup), - -}/*-------------------------< GETCC >-----------------------*/,{ - /* - ** The ncr doesn't have an indirect load - ** or store command. So we have to - ** copy part of the control block to a - ** fixed place, where we can modify it. - ** - ** We patch the address part of a COPY command - ** with the address of the dsa register ... - */ - SCR_COPY (4), - RADDR (dsa), - PADDR (getcc1), - /* - ** ... then we do the actual copy. - */ - SCR_COPY (sizeof (struct head)), -}/*-------------------------< GETCC1 >----------------------*/,{ - 0, - NADDR (header), - /* - ** Initialize the status registers - */ - SCR_COPY (4), - NADDR (header.status), - RADDR (scr0), -}/*-------------------------< GETCC2 >----------------------*/,{ - /* - ** Get the condition code from a target. - ** - ** DSA points to a data structure. - ** Set TEMP to the script location - ** that receives the condition code. - ** - ** Because there is no script command - ** to load a longword into a register, - ** we use a CALL command. - */ -/*<<<*/ SCR_CALLR, - 24, - /* - ** Get the condition code. - */ - SCR_MOVE_TBL ^ SCR_DATA_IN, - offsetof (struct dsb, sense), - /* - ** No data phase may follow! - */ - SCR_CALL, - PADDR (checkatn), - SCR_JUMP, - PADDR (no_data), -/*>>>*/ - - /* - ** The CALL jumps to this point. - ** Prepare for a RESTORE_POINTER message. - ** Save the TEMP register into the saved pointer. - */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), - /* - ** Load scratcha, because in case of a selection timeout, - ** the host will expect a new value for startpos in - ** the scratcha register. - */ - SCR_COPY (4), - PADDR (startpos), - RADDR (scratcha), - /* - ** If QUIRK_NOMSG is set, select without ATN. - ** and don't send a message. - */ - SCR_FROM_REG (QU_REG), - 0, - SCR_JUMP ^ IFTRUE (MASK (QUIRK_NOMSG, QUIRK_NOMSG)), - PADDR(getcc3), - /* - ** Then try to connect to the target. - ** If we are reselected, special treatment - ** of the current job is required before - ** accepting the reselection. - */ - SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select), - PADDR(badgetcc), - /* - ** save target id. - */ - SCR_FROM_REG (sdid), - 0, - SCR_TO_REG (ctest0), - 0, - /* - ** Send the IDENTIFY message. - ** In case of short transfer, remove ATN. - */ - SCR_MOVE_TBL ^ SCR_MSG_OUT, - offsetof (struct dsb, smsg2), - SCR_CLR (SCR_ATN), - 0, - /* - ** save the first byte of the message. - */ - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - SCR_JUMP, - PADDR (prepare2), - -}/*-------------------------< GETCC3 >----------------------*/,{ - /* - ** Try to connect to the target. - ** If we are reselected, special treatment - ** of the current job is required before - ** accepting the reselection. - ** - ** Silly target won't accept a message. - ** Select without ATN. - */ - SCR_SEL_TBL ^ offsetof (struct dsb, select), - PADDR(badgetcc), - /* - ** save target id. - */ - SCR_FROM_REG (sdid), - 0, - SCR_TO_REG (ctest0), - 0, - /* - ** Force error if selection timeout - */ - SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)), - 0, - /* - ** don't negotiate. - */ - SCR_JUMP, - PADDR (prepare2), - -}/*------------------------< BADGETCC >---------------------*/,{ - /* - ** If SIGP was set, clear it and try again. - */ - SCR_FROM_REG (ctest2), - 0, - SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), - PADDR (getcc2), - SCR_INT, - SIR_SENSE_FAILED, -}/*-------------------------< RESELECT >--------------------*/,{ - /* - ** make the DSA invalid. - */ - SCR_LOAD_REG (dsa, 0xff), - 0, - SCR_CLR (SCR_TRG), - 0, - /* - ** Sleep waiting for a reselection. - ** If SIGP is set, special treatment. - ** - ** Zu allem bereit .. - */ - SCR_WAIT_RESEL, - PADDR(reselect2), - /* - ** ... zu nichts zu gebrauchen ? - ** - ** load the target id into the SFBR - ** and jump to the control block. - ** - ** Look at the declarations of - ** - struct ncb - ** - struct tcb - ** - struct lcb - ** - struct ccb - ** to understand what's going on. - */ - SCR_REG_SFBR (ssid, SCR_AND, 0x87), - 0, - SCR_TO_REG (ctest0), - 0, - SCR_JUMP, - NADDR (jump_tcb), -}/*-------------------------< RESELECT2 >-------------------*/,{ - /* - ** If it's not connected :( - ** -> interrupted by SIGP bit. - ** Jump to start. - */ - SCR_FROM_REG (ctest2), - 0, - SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), - PADDR (start), - SCR_JUMP, - PADDR (reselect), - -}/*-------------------------< RESEL_TMP >-------------------*/,{ - /* - ** The return address in TEMP - ** is in fact the data structure address, - ** so copy it to the DSA register. - */ - SCR_COPY (4), - RADDR (temp), - RADDR (dsa), - SCR_JUMP, - PADDR (prepare), - -}/*-------------------------< RESEL_LUN >-------------------*/,{ - /* - ** come back to this point - ** to get an IDENTIFY message - ** Wait for a msg_in phase. - */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), - 48, - /* - ** message phase - ** It's not a sony, it's a trick: - ** read the data without acknowledging it. - */ - SCR_FROM_REG (sbdl), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (M_IDENTIFY, 0x98)), - 32, - /* - ** It WAS an Identify message. - ** get it and ack it! - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - SCR_CLR (SCR_ACK), - 0, - /* - ** Mask out the LUN. - */ - SCR_REG_REG (sfbr, SCR_AND, 0x07), - 0, - SCR_RETURN, - 0, - /* - ** No message phase or no IDENTIFY message: - ** return 0. - */ -/*>>>*/ SCR_LOAD_SFBR (0), - 0, - SCR_RETURN, - 0, - -}/*-------------------------< RESEL_TAG >-------------------*/,{ - /* - ** come back to this point - ** to get a SIMPLE_TAG message - ** Wait for a MSG_IN phase. - */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), - 64, - /* - ** message phase - ** It's a trick - read the data - ** without acknowledging it. - */ - SCR_FROM_REG (sbdl), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (M_SIMPLE_TAG)), - 48, - /* - ** It WAS a SIMPLE_TAG message. - ** get it and ack it! - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - SCR_CLR (SCR_ACK), - 0, - /* - ** Wait for the second byte (the tag) - */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), - 24, - /* - ** Get it and ack it! - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - SCR_CLR (SCR_ACK|SCR_CARRY), - 0, - SCR_RETURN, - 0, - /* - ** No message phase or no SIMPLE_TAG message - ** or no second byte: return 0. - */ -/*>>>*/ SCR_LOAD_SFBR (0), - 0, - SCR_SET (SCR_CARRY), - 0, - SCR_RETURN, - 0, - -}/*-------------------------< DATA_IN >--------------------*/,{ -/* -** Because the size depends on the -** #define MAX_SCATTER parameter, -** it is filled in at runtime. -** -** SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), -** PADDR (no_data), -** SCR_COPY (sizeof (struct timeval)), -** (ncrcmd) &time, -** NADDR (header.stamp.data), -** SCR_MOVE_TBL ^ SCR_DATA_IN, -** offsetof (struct dsb, data[ 0]), -** -** ##===========< i=1; i<MAX_SCATTER >========= -** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)), -** || PADDR (checkatn), -** || SCR_MOVE_TBL ^ SCR_DATA_IN, -** || offsetof (struct dsb, data[ i]), -** ##========================================== -** -** SCR_CALL, -** PADDR (checkatn), -** SCR_JUMP, -** PADDR (no_data), -*/ -0 -}/*-------------------------< DATA_OUT >-------------------*/,{ -/* -** Because the size depends on the -** #define MAX_SCATTER parameter, -** it is filled in at runtime. -** -** SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), -** PADDR (no_data), -** SCR_COPY (sizeof (struct timeval)), -** (ncrcmd) &time, -** NADDR (header.stamp.data), -** SCR_MOVE_TBL ^ SCR_DATA_OUT, -** offsetof (struct dsb, data[ 0]), -** -** ##===========< i=1; i<MAX_SCATTER >========= -** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)), -** || PADDR (dispatch), -** || SCR_MOVE_TBL ^ SCR_DATA_OUT, -** || offsetof (struct dsb, data[ i]), -** ##========================================== -** -** SCR_CALL, -** PADDR (dispatch), -** SCR_JUMP, -** PADDR (no_data), -** -**--------------------------------------------------------- -*/ -(u_long)&ident - -}/*-------------------------< ABORTTAG >-------------------*/,{ - /* - ** Abort a bad reselection. - ** Set the message to ABORT vs. ABORT_TAG - */ - SCR_LOAD_REG (scratcha, M_ABORT_TAG), - 0, - SCR_JUMPR ^ IFFALSE (CARRYSET), - 8, -}/*-------------------------< ABORT >----------------------*/,{ - SCR_LOAD_REG (scratcha, M_ABORT), - 0, - SCR_COPY (1), - RADDR (scratcha), - NADDR (msgout), - SCR_SET (SCR_ATN), - 0, - SCR_CLR (SCR_ACK), - 0, - /* - ** and send it. - ** we expect an immediate disconnect - */ - SCR_REG_REG (scntl2, SCR_AND, 0x7f), - 0, - SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, - NADDR (msgout), - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - SCR_WAIT_DISC, - 0, - SCR_JUMP, - PADDR (start), -}/*-------------------------< SNOOPTEST >-------------------*/,{ - /* - ** Read the variable. - */ - SCR_COPY (4), - (ncrcmd) &ncr_cache, - RADDR (scratcha), - /* - ** Write the variable. - */ - SCR_COPY (4), - RADDR (temp), - (ncrcmd) &ncr_cache, - /* - ** Read back the variable. - */ - SCR_COPY (4), - (ncrcmd) &ncr_cache, - RADDR (temp), - /* - ** And stop. - */ - SCR_INT, - 99, -}/*--------------------------------------------------------*/ -}; - -/*========================================================== -** -** -** Fill in #define dependent parts of the script -** -** -**========================================================== -*/ - -void ncr_script_fill (struct script * scr) -{ - int i; - ncrcmd *p; - - p = scr->tryloop; - for (i=0; i<MAX_START; i++) { - *p++ =SCR_COPY (4); - *p++ =NADDR (squeue[i]); - *p++ =RADDR (dsa); - *p++ =SCR_CALL; - *p++ =PADDR (trysel); - }; - *p++ =SCR_JUMP; - *p++ =PADDR(tryloop); - - assert ((u_long)p == (u_long)&scr->tryloop + sizeof (scr->tryloop)); - - p = scr->data_in; - - *p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)); - *p++ =PADDR (no_data); - *p++ =SCR_COPY (sizeof (struct timeval)); - *p++ =(ncrcmd) &time; - *p++ =NADDR (header.stamp.data); - *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; - *p++ =offsetof (struct dsb, data[ 0]); - - for (i=1; i<MAX_SCATTER; i++) { - *p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)); - *p++ =PADDR (checkatn); - *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; - *p++ =offsetof (struct dsb, data[i]); - }; - - *p++ =SCR_CALL; - *p++ =PADDR (checkatn); - *p++ =SCR_JUMP; - *p++ =PADDR (no_data); - - assert ((u_long)p == (u_long)&scr->data_in + sizeof (scr->data_in)); - - p = scr->data_out; - - *p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_OUT)); - *p++ =PADDR (no_data); - *p++ =SCR_COPY (sizeof (struct timeval)); - *p++ =(ncrcmd) &time; - *p++ =NADDR (header.stamp.data); - *p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT; - *p++ =offsetof (struct dsb, data[ 0]); - - for (i=1; i<MAX_SCATTER; i++) { - *p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)); - *p++ =PADDR (dispatch); - *p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT; - *p++ =offsetof (struct dsb, data[i]); - }; - - *p++ =SCR_CALL; - *p++ =PADDR (dispatch); - *p++ =SCR_JUMP; - *p++ =PADDR (no_data); - - assert ((u_long)p == (u_long)&scr->data_out + sizeof (scr->data_out)); -} - -/*========================================================== -** -** -** Copy and rebind a script. -** -** -**========================================================== -*/ - -static void ncr_script_copy_and_bind (struct script *script, ncb_p np) -{ - ncrcmd opcode, new, old; - ncrcmd *src, *dst, *start, *end; - int relocs; - - np->script = (struct script *) - malloc (sizeof (struct script), M_DEVBUF, M_WAITOK); - np->p_script = vtophys(np->script); - - src = script->start; - dst = np->script->start; - - start = src; - end = src + (sizeof(struct script) / 4); - - while (src < end) { - - *dst++ = opcode = *src++; - - /* - ** If we forget to change the length - ** in struct script, a field will be - ** padded with 0. This is an illegal - ** command. - */ - - if (opcode == 0) { - printf ("%s: ERROR0 IN SCRIPT at %d.\n", - ncr_name(np), src-start-1); - DELAY (1000000); - }; - - if (DEBUG_FLAGS & DEBUG_SCRIPT) - printf ("%x: <%x>\n", - (unsigned)(src-1), (unsigned)opcode); - - /* - ** We don't have to decode ALL commands - */ - switch (opcode >> 28) { - - case 0xc: - /* - ** COPY has TWO arguments. - */ - relocs = 2; - if ((src[0] ^ src[1]) & 3) { - printf ("%s: ERROR1 IN SCRIPT at %d.\n", - ncr_name(np), src-start-1); - DELAY (1000000); - }; - break; - - case 0x0: - /* - ** MOVE (absolute address) - */ - relocs = 1; - break; - - case 0x8: - /* - ** JUMP / CALL - ** dont't relocate if relative :-) - */ - if (opcode & 0x00800000) - relocs = 0; - else - relocs = 1; - break; - - case 0x4: - case 0x5: - case 0x6: - case 0x7: - relocs = 1; - break; - - default: - relocs = 0; - break; - }; - - if (relocs) { - while (relocs--) { - old = *src++; - - switch (old & RELOC_MASK) { - case RELOC_REGISTER: - new = (old & ~RELOC_MASK) + np->paddr; - break; - case RELOC_LABEL: - new = (old & ~RELOC_MASK) + vtophys(np->script); - break; - case RELOC_SOFTC: - new = (old & ~RELOC_MASK) + vtophys(np); - break; - case 0: - /* Don't relocate a 0 address. */ - if (old == 0) { - new = old; - break; - } - /* fall through */ - default: - new = vtophys(old); - break; - } - - *dst++ = new; - } - } else - *dst++ = *src++; - - }; -} - -/*========================================================== -** -** -** Auto configuration. -** -** -**========================================================== -*/ - -/*---------------------------------------------------------- -** -** Reduce the transfer length to the max value -** we can transfer safely. -** -** Reading a block greater then MAX_SIZE from the -** raw (character) device exercises a memory leak -** in the vm subsystem. This is common to ALL devices. -** We have submitted a description of this bug to -** <FreeBSD-bugs@freefall.cdrom.com>. -** It should be fixed in the current release. -** -**---------------------------------------------------------- -*/ - -void ncr_min_phys (struct buf *bp) -{ - if (bp->b_bcount > MAX_SIZE) bp->b_bcount = MAX_SIZE; -} - -/*---------------------------------------------------------- -** -** Maximal number of outstanding requests per target. -** -**---------------------------------------------------------- -*/ - -U_INT32 ncr_info (int unit) -{ - return (1); /* may be changed later */ -} - -/*---------------------------------------------------------- -** -** Probe the hostadapter. -** -**---------------------------------------------------------- -*/ - -#ifdef __NetBSD__ - -int -ncr_probe(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct cfdata *cf = self->dv_cfdata; - struct pci_attach_args *pa = aux; - - if (!pci_targmatch(cf, pa)) - return 0; - if (pa->pa_id != NCR_810_ID && - pa->pa_id != NCR_825_ID) - return 0; - - return 1; -} - -#else /* !__NetBSD__ */ - - -static char* ncr_probe (pcici_t tag, pcidi_t type) -{ - switch (type) { - - case NCR_810_ID: - return ("ncr 53c810 scsi"); - - case NCR_825_ID: - return ("ncr 53c825 wide scsi"); - } - return (0); -} - -#endif /* !__NetBSD__ */ - - -/*========================================================== -** -** -** Auto configuration: attach and init a host adapter. -** -** -**========================================================== -*/ - -#define MIN_ASYNC_PD 40 -#define MIN_SYNC_PD 20 - -#ifdef __NetBSD__ - -int -ncr_print() -{ -} - -void -ncr_attach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct pci_attach_args *pa = aux; - int retval; - ncb_p np = (void *)self; - - /* - ** XXX - ** Perhaps try to figure what which model chip it is and print that - ** out. - */ - printf("\n"); - - /* - ** Try to map the controller chip to - ** virtual and physical memory. - */ - - retval = pci_map_mem(pa->pa_tag, 0x14, &np->vaddr, &np->paddr); - if (retval) - return; - - np->sc_ih.ih_fun = ncr_intr; - np->sc_ih.ih_arg = np; - np->sc_ih.ih_level = IPL_BIO; - - retval = pci_map_int(pa->pa_tag, &np->sc_ih); - if (retval) - return; - -#else /* !__NetBSD__ */ - -static void ncr_attach (pcici_t config_id, int unit) -{ - ncb_p np; -#if ! (__FreeBSD__ >= 2) - extern unsigned bio_imask; -#endif - - - /* - ** allocate structure - */ - - np = (ncb_p) malloc (sizeof (struct ncb), M_DEVBUF, M_WAITOK); - if (!np) return; - ncrp[unit]=np; - - /* - ** initialize structure. - */ - - bzero (np, sizeof (*np)); - np->unit = unit; - - /* - ** Try to map the controller chip to - ** virtual and physical memory. - */ - - if (!pci_map_mem (config_id, 0x14, &np->vaddr, &np->paddr)) - return; - -#endif /* !__NetBSD__ */ - - /* - ** Do chip dependent initialization. - */ - -#ifdef __NetBSD__ - switch (pa->pa_id) { -#else - switch (pci_conf_read (config_id, PCI_ID_REG)) { -#endif - case NCR_810_ID: - np->maxwide = 0; - break; - case NCR_825_ID: - np->maxwide = 1; - break; - } - - /* - ** Patch script to physical addresses - */ - - ncr_script_fill (&script0); - ncr_script_copy_and_bind (&script0, np); - - /* - ** init data structure - */ - - np -> jump_tcb.l_cmd = SCR_JUMP ; - np -> jump_tcb.l_paddr = vtophys (&np->script->abort); - - /* - ** Make the controller's registers available. - ** Now the INB INW INL OUTB OUTW OUTL macros - ** can be used safely. - */ - - np->reg = (struct ncr_reg*) np->vaddr; - - /* - ** Get SCSI addr of host adapter (set by bios?). - */ - - np->myaddr = INB(nc_scid) & 0x07; - if (!np->myaddr) np->myaddr = SCSI_NCR_MYADDR; - - /* - ** Get the value of the chip's clock. - ** Find the right value for scntl3. - */ - - ncr_getclock (np); - - /* - ** Reset chip. - */ - - OUTB (nc_istat, SRST); - OUTB (nc_istat, 0 ); - - /* - ** Now check the cache handling of the pci chipset. - */ - - if (ncr_snooptest (np)) { - printf ("CACHE INCORRECTLY CONFIGURED.\n"); - return; - }; - -#ifndef __NetBSD__ - /* - ** Install the interrupt handler. - */ - - if (!pci_map_int (config_id, ncr_intr, np, &bio_imask)) - printf ("\tinterruptless mode: reduced performance.\n"); -#endif - - /* - ** After SCSI devices have been opened, we cannot - ** reset the bus safely, so we do it here. - ** Interrupt handler does the real work. - */ - - OUTB (nc_scntl1, CRST); - - /* - ** process the reset exception, - ** if interrupts are not enabled yet. - */ - ncr_exception (np); - -#ifdef ANCIENT - printf ("%s: waiting for scsi devices to settle\n", - ncr_name (np)); - DELAY (1000000); -#endif - printf ("%s scanning for targets 0..%d ($Revision: 1.11 $)\n", - ncr_name (np), MAX_TARGET-1); - - /* - ** Now let the generic SCSI driver - ** look for the SCSI devices on the bus .. - */ - -#ifndef ANCIENT -#ifdef __NetBSD__ - np->sc_link.adapter_softc = np; -#else /* !__NetBSD__ */ - np->sc_link.adapter_unit = unit; -#endif /* !__NetBSD__ */ - np->sc_link.adapter_targ = np->myaddr; - np->sc_link.adapter = &ncr_switch; - np->sc_link.device = &ncr_dev; - -#ifdef __NetBSD__ - config_found(self, &np->sc_link, ncr_print); -#else /* !__NetBSD__ */ - scsi_attachdevs (&np->sc_link); -#endif /* !__NetBSD__ */ -#else /* ANCIENT */ - scsi_attachdevs (unit, np->myaddr, &ncr_switch); -#endif /* ANCIENT */ - - /* - ** start the timeout daemon - */ - ncr_timeout (np); - np->lasttime=0; - - /* - ** Done. - */ - - return; -} - -/*========================================================== -** -** -** Process pending device interrupts. -** -** -**========================================================== -*/ - -int -ncr_intr(np) - ncb_p np; -{ - int n = 0; - - if (DEBUG_FLAGS & DEBUG_TINY) printf ("["); - - if (INB(nc_istat) & (INTF|SIP|DIP)) { - /* - ** Repeat until no outstanding ints - */ - do { - ncr_exception (np); - } while (INB(nc_istat) & (INTF|SIP|DIP)); - - n=1; - np->ticks = 100; - }; - - if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n"); - - return (n); -} - -/*========================================================== -** -** -** Start execution of a SCSI command. -** This is called from the generic SCSI driver. -** -** -**========================================================== -*/ - -static INT32 ncr_start (struct scsi_xfer * xp) -{ -#ifndef ANCIENT -#ifdef __NetBSD__ - ncb_p np = xp->sc_link->adapter_softc; -#else /*__NetBSD__*/ - ncb_p np = ncrp[xp->sc_link->adapter_unit]; -#endif/*__NetBSD__*/ -#else /* ANCIENT */ - ncb_p np = ncrp[xp->adapter]; -#endif /* ANCIENT */ - - struct scsi_generic * cmd = xp->cmd; - ccb_p cp; - lcb_p lp; - tcb_p tp = &np->target[xp->TARGET]; - - int i, oldspl, segments, flags = xp->flags; - u_char ptr, nego, idmsg; - u_long msglen, msglen2; - - - - /*--------------------------------------------- - ** - ** Reset SCSI bus - ** - ** Interrupt handler does the real work. - ** - **--------------------------------------------- - */ - - if (flags & SCSI_RESET) { - OUTB (nc_scntl1, CRST); - return(COMPLETE); - }; - - /*--------------------------------------------- - ** - ** Some shortcuts ... - ** - **--------------------------------------------- - */ - - if ((xp->TARGET == np->myaddr ) || - (xp->TARGET >= MAX_TARGET) || - (xp->LUN >= MAX_LUN ) || - (flags & SCSI_DATA_UIO)) { - xp->error = XS_DRIVER_STUFFUP; - return(HAD_ERROR); - }; - - /*--------------------------------------------- - ** - ** Diskaccess to partial blocks? - ** - **--------------------------------------------- - */ - - if ((xp->datalen & 0x1ff) && !(tp->inqdata[0] & 0x1f)) { - switch (cmd->opcode) { - case 0x28: /* READ_BIG (10) */ - case 0xa8: /* READ_HUGE (12) */ - case 0x2a: /* WRITE_BIG (10) */ - case 0xaa: /* WRITE_HUGE(12) */ - PRINT_ADDR(xp); - printf ("access to partial disk block refused.\n"); - xp->error = XS_DRIVER_STUFFUP; - return(HAD_ERROR); - }; - }; - -#ifdef ANCIENT - /*--------------------------------------------- - ** Ancient version of <sys/scsi/sd.c> - ** doesn't set the DATA_IN/DATA_OUT bits. - ** So we have to fix it .. - **--------------------------------------------- - */ - - switch (cmd->opcode) { - case 0x1a: /* MODE_SENSE */ - case 0x25: /* READ_CAPACITY */ - case 0x28: /* READ_BIG (10) */ - xp->flags |= SCSI_DATA_IN; - break; - case 0x2a: /* WRITE_BIG(10) */ - xp->flags |= SCSI_DATA_OUT; - break; - }; -#endif /* ANCIENT */ - - if (DEBUG_FLAGS & DEBUG_TINY) { - PRINT_ADDR(xp); - printf ("CMD=%x F=%x L=%x ", cmd->opcode, - (unsigned)xp->flags, (unsigned) xp->datalen); - } - - /*-------------------------------------------- - ** - ** Sanity checks ... - ** copied from Elischer's Adaptec driver. - ** - **-------------------------------------------- - */ - - flags = xp->flags; - if (!(flags & INUSE)) { - printf("%s: ?INUSE?\n", ncr_name (np)); - xp->flags |= INUSE; - }; - - if(flags & ITSDONE) { - printf("%s: ?ITSDONE?\n", ncr_name (np)); - xp->flags &= ~ITSDONE; - }; - - if (xp->bp) - flags |= (SCSI_NOSLEEP); /* just to be sure */ - - /*--------------------------------------------------- - ** - ** Assign a ccb / bind xp - ** - **---------------------------------------------------- - */ - - if (!(cp=ncr_get_ccb (np, flags, xp->TARGET, xp->LUN))) { - printf ("%s: no ccb.\n", ncr_name (np)); - xp->error = XS_DRIVER_STUFFUP; - return(TRY_AGAIN_LATER); - }; - cp->xfer = xp; - - /*--------------------------------------------------- - ** - ** timestamp - ** - **---------------------------------------------------- - */ - - bzero (&cp->phys.header.stamp, sizeof (struct tstamp)); - cp->phys.header.stamp.start = time; - - /*---------------------------------------------------- - ** - ** Get device quirks from a speciality table. - ** - ** @GENSCSI@ - ** This should be a part of the device table - ** in "scsi_conf.c". - ** - **---------------------------------------------------- - */ - - if (tp->quirks & QUIRK_UPDATE) { -#ifdef NEW_SCSICONF - tp->quirks = xp->sc_link->quirks; -#else - tp->quirks = ncr_lookup ((char*) &tp->inqdata[0]); -#endif - if (tp->quirks) { - PRINT_ADDR(xp); - printf ("quirks=%x.\n", tp->quirks); - }; - }; - - /*--------------------------------------------------- - ** - ** negotiation required? - ** - **---------------------------------------------------- - */ - - nego = 0; - - if (tp->inqdata[7]) { - /* - ** negotiate synchronous transfers? - */ - - if (!tp->period) { - if (tp->inqdata[7] & INQ7_SYNC) { - nego = NS_SYNC; - } else { - tp->period =0xffff; - tp->sval = 0xe0; - PRINT_ADDR(xp); - printf ("asynchronous.\n"); - }; - }; - - /* - ** negotiate wide transfers ? - */ - - if (!tp->widedone) { - if (tp->inqdata[7] & INQ7_WIDE16) { - if (!nego) nego = NS_WIDE; - } else - tp->widedone=1; - }; - }; - - /*--------------------------------------------------- - ** - ** choose a new tag ... - ** - **---------------------------------------------------- - */ - - if ((lp = tp->lp[xp->LUN]) && (lp->usetags)) { - /* - ** assign a tag to this ccb! - */ - while (!cp->tag) { - ccb_p cp2 = lp->next_ccb; - lp->lasttag = lp->lasttag % 255 + 1; - while (cp2 && cp2->tag != lp->lasttag) - cp2 = cp2->next_ccb; - if (cp2) continue; - cp->tag=lp->lasttag; - if (DEBUG_FLAGS & DEBUG_TAGS) { - PRINT_ADDR(xp); - printf ("using tag #%d.\n", cp->tag); - }; - }; - } else { - cp->tag=0; -#if !defined(ANCIENT) && !defined(__NetBSD__) && !(__FreeBSD__ >= 2) - /* - ** @GENSCSI@ Bug in "/sys/scsi/cd.c" - ** - ** /sys/scsi/cd.c initializes opennings with 2. - ** Our info value of 1 is not respected. - */ - if (xp->sc_link && xp->sc_link->opennings) { - PRINT_ADDR(xp); - printf ("opennings set to 0.\n"); - xp->sc_link->opennings = 0; - }; -#endif - }; - - /*---------------------------------------------------- - ** - ** Build the identify / tag / sdtr message - ** - **---------------------------------------------------- - */ - - idmsg = (cp==&np->ccb ? 0x80 : 0xc0) | xp->LUN; - - cp -> scsi_smsg [0] = idmsg; - msglen=1; - - if (cp->tag) { - - /* - ** Ordered write ops, unordered read ops. - */ - switch (cmd->opcode) { - case 0x08: /* READ_SMALL (6) */ - case 0x28: /* READ_BIG (10) */ - case 0xa8: /* READ_HUGE (12) */ - cp -> scsi_smsg [msglen] = M_SIMPLE_TAG; - break; - default: - cp -> scsi_smsg [msglen] = M_ORDERED_TAG; - } - - /* - ** can be overwritten by ncrcontrol - */ - switch (np->order) { - case M_SIMPLE_TAG: - case M_ORDERED_TAG: - cp -> scsi_smsg [msglen] = np->order; - }; - msglen++; - cp -> scsi_smsg [msglen++] = cp -> tag; - } - - switch (nego) { - case NS_SYNC: - cp -> scsi_smsg [msglen++] = M_EXTENDED; - cp -> scsi_smsg [msglen++] = 3; - cp -> scsi_smsg [msglen++] = M_X_SYNC_REQ; - cp -> scsi_smsg [msglen++] = tp->minsync; - cp -> scsi_smsg [msglen++] = tp->maxoffs; - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - printf ("sync msgout: "); - ncr_show_msg (&cp->scsi_smsg [msglen-5]); - printf (".\n"); - }; - break; - case NS_WIDE: - cp -> scsi_smsg [msglen++] = M_EXTENDED; - cp -> scsi_smsg [msglen++] = 2; - cp -> scsi_smsg [msglen++] = M_X_WIDE_REQ; - cp -> scsi_smsg [msglen++] = tp->usrwide; - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - printf ("wide msgout: "); - ncr_show_msg (&cp->scsi_smsg [msglen-4]); - printf (".\n"); - }; - break; - }; - - /*---------------------------------------------------- - ** - ** Build the identify message for getcc. - ** - **---------------------------------------------------- - */ - - cp -> scsi_smsg2 [0] = idmsg; - msglen2 = 1; - - /*---------------------------------------------------- - ** - ** Build the data descriptors - ** - **---------------------------------------------------- - */ - - segments = ncr_scatter (&cp->phys, (vm_offset_t) xp->data, - (vm_size_t) xp->datalen); - - if (segments < 0) { - xp->error = XS_DRIVER_STUFFUP; - ncr_free_ccb(np, cp, flags); - return(HAD_ERROR); - }; - - /*---------------------------------------------------- - ** - ** Set the SAVED_POINTER. - ** - **---------------------------------------------------- - */ - - if (flags & SCSI_DATA_IN) { - cp->phys.header.savep = vtophys (&np->script->data_in); - cp->phys.header.goalp = cp->phys.header.savep +20 +segments*16; - } else if (flags & SCSI_DATA_OUT) { - cp->phys.header.savep = vtophys (&np->script->data_out); - cp->phys.header.goalp = cp->phys.header.savep +20 +segments*16; - } else { - cp->phys.header.savep = vtophys (&np->script->no_data); - cp->phys.header.goalp = cp->phys.header.savep; - }; - cp->phys.header.lastp = cp->phys.header.savep; - - - /*---------------------------------------------------- - ** - ** fill ccb - ** - **---------------------------------------------------- - ** - ** - ** physical -> virtual backlink - ** Generic SCSI command - */ - cp->phys.header.cp = cp; - /* - ** Startqueue - */ - cp->phys.header.launch.l_paddr = vtophys (&np->script->select); - cp->phys.header.launch.l_cmd = SCR_JUMP; - /* - ** select - */ - cp->phys.select.sel_id = xp->TARGET; - cp->phys.select.sel_scntl3 = tp->wval; - cp->phys.select.sel_sxfer = tp->sval; - /* - ** message - */ - cp->phys.smsg.addr = vtophys (&cp->scsi_smsg ); - cp->phys.smsg.size = msglen; - cp->phys.smsg2.addr = vtophys (&cp->scsi_smsg2); - cp->phys.smsg2.size = msglen2; - /* - ** command - */ -#ifdef ANCIENT - bcopy (cmd, &cp->cmd, sizeof (cp->cmd)); - cp->phys.cmd.addr = vtophys (&cp->cmd); -#else /* ANCIENT */ - cp->phys.cmd.addr = vtophys (cmd); -#endif /* ANCIENT */ - cp->phys.cmd.size = xp->cmdlen; - /* - ** sense data - */ - cp->phys.sense.addr = vtophys (&cp->xfer->sense); - cp->phys.sense.size = sizeof(struct scsi_sense_data); - /* - ** status - */ - cp->actualquirks = tp->quirks; - cp->host_status = nego ? HS_NEGOTIATE : HS_BUSY; - cp->scsi_status = S_ILLEGAL; - cp->parity_status = 0; - - cp->xerr_status = XE_OK; - cp->sync_status = tp->sval; - cp->nego_status = nego; - cp->wide_status = tp->wval; - - /*---------------------------------------------------- - ** - ** Critical region: starting this job. - ** - **---------------------------------------------------- - */ - - oldspl = 0; /* for the sake of gcc */ - if (!(flags & SCSI_NOMASK)) oldspl = splbio(); - np->lock++; - - /* - ** reselect pattern and activate this job. - */ - - cp->jump_ccb.l_cmd = (SCR_JUMP ^ IFFALSE (DATA (cp->tag))); - cp->tlimit = time.tv_sec + xp->timeout / 1000 + 2; - cp->magic = CCB_MAGIC; - - /* - ** insert into startqueue. - */ - - ptr = np->squeueput + 1; - if (ptr >= MAX_START) ptr=0; - np->squeue [ptr ] = vtophys(&np->script->idle); - np->squeue [np->squeueput] = vtophys(&cp->phys); - np->squeueput = ptr; - - if(DEBUG_FLAGS & DEBUG_QUEUE) - printf ("%s: queuepos=%d tryoffset=%d.\n", ncr_name (np), - np->squeueput, - (unsigned)(np->script->startpos[0]- - (vtophys(&np->script->tryloop)))); - - /* - ** Script processor may be waiting for reconnect. - ** Wake it up. - */ - OUTB (nc_istat, SIGP); - - /* - ** If interrupts are enabled, return now. - ** Command is successfully queued. - */ - - np->lock--; - if (!(flags & SCSI_NOMASK)) { - splx (oldspl); - if (np->lasttime) { - if(DEBUG_FLAGS & DEBUG_TINY) printf ("Q"); - return(SUCCESSFULLY_QUEUED); - }; - }; - - /*---------------------------------------------------- - ** - ** Interrupts not yet enabled - have to poll. - ** - **---------------------------------------------------- - */ - - if (DEBUG_FLAGS & DEBUG_POLL) printf("P"); - - for (i=xp->timeout; i && !(xp->flags & ITSDONE);i--) { - if ((DEBUG_FLAGS & DEBUG_POLL) && (cp->host_status)) - printf ("%c", (cp->host_status & 0xf) + '0'); - DELAY (1000); - ncr_exception (np); - }; - - /* - ** Abort if command not done. - */ - if (!(xp->flags & ITSDONE)) { - printf ("%s: aborting job ...\n", ncr_name (np)); - OUTB (nc_istat, CABRT); - DELAY (100000); - OUTB (nc_istat, SIGP); - ncr_exception (np); - }; - - if (!(xp->flags & ITSDONE)) { - printf ("%s: abortion failed at %x.\n", - ncr_name (np), (unsigned) INL(nc_dsp)); - ncr_init (np, "timeout", HS_TIMEOUT); - }; - - if (!(xp->flags & ITSDONE)) { - cp-> host_status = HS_SEL_TIMEOUT; - ncr_complete (np, cp); - }; - - if (DEBUG_FLAGS & DEBUG_RESULT) { - printf ("%s: result: %x %x.\n", - ncr_name (np), cp->host_status, cp->scsi_status); - }; - if (!(flags & SCSI_NOMASK)) - return (SUCCESSFULLY_QUEUED); - switch (xp->error) { - case 0 : return (COMPLETE); - case XS_BUSY: return (TRY_AGAIN_LATER); - }; - return (HAD_ERROR); -} - -/*========================================================== -** -** -** Complete execution of a SCSI command. -** Signal completion to the generic SCSI driver. -** -** -**========================================================== -*/ - -void ncr_complete (ncb_p np, ccb_p cp) -{ - struct scsi_xfer * xp; - tcb_p tp; - lcb_p lp; - - /* - ** Sanity check - */ - - if (!cp || !cp->magic || !cp->xfer) return; - cp->magic = 1; - cp->tlimit= 0; - - /* - ** No Reselect anymore. - */ - cp->jump_ccb.l_cmd = (SCR_JUMP); - - /* - ** No starting. - */ - cp->phys.header.launch.l_paddr= vtophys (&np->script->idle); - - /* - ** timestamp - */ - ncb_profile (np, cp); - - if (DEBUG_FLAGS & DEBUG_TINY) - printf ("CCB=%x STAT=%x/%x\n", (unsigned)cp & 0xfff, - cp->host_status,cp->scsi_status); - - xp = cp->xfer; - cp->xfer = NULL; - tp = &np->target[xp->TARGET]; - lp = tp->lp[xp->LUN]; - - /* - ** Check for parity errors. - */ - - if (cp->parity_status) { - PRINT_ADDR(xp); - printf ("%d parity error(s), fallback.\n", cp->parity_status); - /* - ** fallback to asynch transfer. - */ - tp->usrsync=255; - tp->period = 0; - }; - - /* - ** Check for extended errors. - */ - - if (cp->xerr_status != XE_OK) { - PRINT_ADDR(xp); - switch (cp->xerr_status) { - case XE_EXTRA_DATA: - printf ("extraneous data discarded.\n"); - break; - case XE_BAD_PHASE: - printf ("illegal scsi phase (4/5).\n"); - break; - default: - printf ("extended error %d.\n", cp->xerr_status); - break; - }; - if (cp->host_status==HS_COMPLETE) - cp->host_status = HS_FAIL; - }; - - /* - ** Check the status. - */ - if ( (cp->host_status == HS_COMPLETE) - && (cp->scsi_status == S_GOOD)) { - - /* - ** All went well. - */ - - xp->resid = 0; - - /* - ** if (cp->phys.header.lastp != cp->phys.header.goalp)... - ** - ** @RESID@ - ** Could dig out the correct value for resid, - ** but it would be quite complicated. - ** - ** The ah1542.c driver sets it to 0 too ... - */ - - /* - ** Try to assign a ccb to this nexus - */ - ncr_alloc_ccb (np, xp); - - /* - ** On inquire cmd (0x12) save some data. - */ -#ifdef ANCIENT - if (cp->cmd.opcode == 0x12) { -#else /* ANCIENT */ - if (xp->cmd->opcode == 0x12) { -#endif /* ANCIENT */ - bcopy ( xp->data, - &tp->inqdata, - sizeof (tp->inqdata)); - - /* - ** set number of tags - */ - ncr_setmaxtags (tp, tp->usrtags); - - /* - ** prepare negotiation of synch and wide. - */ - ncr_negotiate (np, tp); - - /* - ** force quirks update before next command start - */ - tp->quirks |= QUIRK_UPDATE; - }; - - /* - ** Announce changes to the generic driver - */ - if (lp) { - ncr_settags (tp, lp); - if (lp->reqlink != lp->actlink) - ncr_opennings (np, lp, xp); - }; - -#ifdef DK - dk_xfer[DK] ++; - dk_wds [DK] += xp->datalen/64; - dk_wpms[DK] = 1000000; -#endif /* DK */ - - tp->bytes += xp->datalen; - tp->transfers ++; - - } else if (xp->flags & SCSI_ERR_OK) { - - /* - ** Not correct, but errors expected. - */ - xp->resid = 0; - - } else if ((cp->host_status == HS_COMPLETE) - && (cp->scsi_status == (S_SENSE|S_GOOD))) { - - /* - ** Check condition code - */ - xp->error = XS_SENSE; - - if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) { - u_char * p = (u_char*) & xp->sense; - int i; - printf ("\n%s: sense data:", ncr_name (np)); - for (i=0; i<14; i++) printf (" %x", *p++); - printf (".\n"); - }; - - } else if ((cp->host_status == HS_COMPLETE) - && (cp->scsi_status == S_BUSY)) { - - /* - ** Target is busy. - */ - xp->error = XS_BUSY; - - } else if ((cp->host_status == HS_SEL_TIMEOUT) - || (cp->host_status == HS_TIMEOUT)) { - - /* - ** No response - */ - xp->error = XS_TIMEOUT; - - } else { - - /* - ** Other protocol messes - */ - PRINT_ADDR(xp); - printf ("COMMAND FAILED (%x %x) @%x.\n", - cp->host_status, cp->scsi_status, (unsigned)cp); - - xp->error = XS_DRIVER_STUFFUP; - } - - xp->flags |= ITSDONE; - - /* - ** trace output - */ - - if (tp->usrflag & UF_TRACE) { - u_char * p; - int i; - PRINT_ADDR(xp); - printf (" CMD:"); -#ifdef ANCIENT - p = (u_char*) &cp->cmd.opcode; -#else /* ANCIENT */ - p = (u_char*) &xp->cmd->opcode; -#endif /* ANCIENT */ - for (i=0; i<xp->cmdlen; i++) printf (" %x", *p++); - - if (cp->host_status==HS_COMPLETE) { - switch (cp->scsi_status) { - case S_GOOD: - printf (" GOOD"); - break; - case S_CHECK_COND: - printf (" SENSE:"); - p = (u_char*) &xp->sense; -#ifdef ANCIENT - for (i=0; i<sizeof(xp->sense); i++) -#else /* ANCIENT */ - for (i=0; i<xp->req_sense_length; i++) -#endif /* ANCIENT */ - printf (" %x", *p++); - break; - default: - printf (" STAT: %x\n", cp->scsi_status); - break; - }; - } else printf (" HOSTERROR: %x", cp->host_status); - printf ("\n"); - }; - - /* - ** Free this ccb - */ - ncr_free_ccb (np, cp, xp->flags); - - /* - ** signal completion to generic driver. - */ -#ifdef ANCIENT - if (xp->when_done) - (*(xp->when_done))(xp->done_arg,xp->done_arg2); -#else /* ANCIENT */ - scsi_done (xp); -#endif /* ANCIENT */ -} - -/*========================================================== -** -** -** Signal all (or one) control block done. -** -** -**========================================================== -*/ - -void ncr_wakeup (ncb_p np, u_long code) -{ - /* - ** Starting at the default ccb and following - ** the links, complete all jobs with a - ** host_status greater than "disconnect". - ** - ** If the "code" parameter is not zero, - ** complete all jobs that are not IDLE. - */ - - int s=splbio(); - - ccb_p cp = &np->ccb; - while (cp) { - switch (cp->host_status) { - - case HS_IDLE: - break; - - case HS_DISCONNECT: - if(DEBUG_FLAGS & DEBUG_TINY) printf ("D"); - /* fall through */ - - case HS_BUSY: - case HS_NEGOTIATE: - if (!code) break; - cp->host_status = code; - - /* fall through */ - - default: - ncr_complete (np, cp); - break; - }; - cp = cp -> link_ccb; - }; - splx (s); -} - -/*========================================================== -** -** -** Start NCR chip. -** -** -**========================================================== -*/ - -void ncr_init (ncb_p np, char * msg, u_long code) -{ - int i; - u_long usrsync; - u_char usrwide; - - /* - ** Reset chip. - */ - - OUTB (nc_istat, SRST ); - - /* - ** Message. - */ - - if (msg) printf ("%s: restart (%s).\n", ncr_name (np), msg); - - /* - ** Clear Start Queue - */ - - for (i=0;i<MAX_START;i++) - np -> squeue [i] = vtophys (&np->script->idle); - - /* - ** Start at first entry. - */ - - np->squeueput = 0; - np->script->startpos[0] = vtophys (&np->script->tryloop); - np->script->start0 [0] = SCR_INT ^ IFFALSE (0); - - /* - ** Wakeup all pending jobs. - */ - - ncr_wakeup (np, code); - - /* - ** Init chip. - */ - - OUTB (nc_istat, 0 ); /* Remove Reset, abort ... */ - OUTB (nc_scntl0, 0xca ); /* full arb., ena parity, par->ATN */ - OUTB (nc_scntl1, 0x00 ); /* odd parity, and remove CRST!! */ - OUTB (nc_scntl3, np->rv_scntl3);/* timing prescaler */ - OUTB (nc_scid , 0x40|np->myaddr);/* host adapter SCSI address */ - OUTW (nc_respid, 1ul<<np->myaddr);/* id to respond to */ - OUTB (nc_istat , SIGP ); /* Signal Process */ - OUTB (nc_dmode , 0xc0 ); /* Burst length = 16 transfer */ - OUTB (nc_dcntl , NOCOM ); /* no single step mode, protect SFBR*/ - OUTB (nc_ctest4, 0x08 ); /* enable master parity checking */ - OUTB (nc_stest2, EXT ); /* Extended Sreq/Sack filtering */ - OUTB (nc_stest3, TE ); /* TolerANT enable */ - OUTB (nc_stime0, 0xfb ); /* HTH = 1.6sec STO = 0.1 sec. */ - - /* - ** Reinitialize usrsync. - ** Have to renegotiate synch mode. - */ - - usrsync = 255; - if (SCSI_NCR_MAX_SYNC) { - u_long period; - period =1000000/SCSI_NCR_MAX_SYNC; /* ns = 10e6 / kHz */ - if (period <= 11 * np->ns_sync) { - if (period < 4 * np->ns_sync) - usrsync = np->ns_sync; - else - usrsync = period / 4; - }; - }; - - /* - ** Reinitialize usrwide. - ** Have to renegotiate wide mode. - */ - - usrwide = (SCSI_NCR_MAX_WIDE); - if (usrwide > np->maxwide) usrwide=np->maxwide; - - /* - ** Fill in target structure. - */ - - for (i=0;i<MAX_TARGET;i++) { - tcb_p tp = &np->target[i]; - - tp->sval = 0; - tp->wval = np->rv_scntl3; - - tp->usrsync = usrsync; - tp->usrwide = usrwide; - - ncr_negotiate (np, tp); - } - - /* - ** enable ints - */ - - OUTW (nc_sien , STO|HTH|MA|SGE|UDC|RST); - OUTB (nc_dien , MDPE|BF|ABRT|SSI|SIR|IID); - - /* - ** Start script processor. - */ - - OUTL (nc_dsp, vtophys (&np->script->start)); -} - -/*========================================================== -** -** Prepare the negotiation values for wide and -** synchronous transfers. -** -**========================================================== -*/ - -static void ncr_negotiate (struct ncb* np, struct tcb* tp) -{ - /* - ** minsync unit is 4ns ! - */ - - u_long minsync = tp->usrsync; - - if (minsync < 25) minsync=25; - - /* - ** if not scsi 2 - ** don't believe FAST! - */ - - if ((minsync < 50) && (tp->inqdata[2] & 0x0f) < 2) - minsync=50; - - /* - ** our limit .. - */ - - if (minsync < np->ns_sync) - minsync = np->ns_sync; - - /* - ** divider limit - */ - - if (minsync > (np->ns_sync * 11) / 4) - minsync = 255; - - tp->minsync = minsync; - tp->maxoffs = (minsync<255 ? 8 : 0); - - /* - ** period=0: has to negotiate sync transfer - */ - - tp->period=0; - - /* - ** widedone=0: has to negotiate wide transfer - */ - tp->widedone=0; -} - -/*========================================================== -** -** Switch sync mode for current job and it's target -** -**========================================================== -*/ - -static void ncr_setsync (ncb_p np, ccb_p cp, u_char sxfer) -{ - struct scsi_xfer *xp; - tcb_p tp; - u_char target = INB (nc_ctest0)&7; - - assert (cp); - if (!cp) return; - - xp = cp->xfer; - assert (xp); - if (!xp) return; - assert (target == xp->TARGET & 7); - - tp = &np->target[target]; - tp->period= sxfer&0xf ? ((sxfer>>5)+4) * np->ns_sync : 0xffff; - - if (tp->sval == sxfer) return; - tp->sval = sxfer; - - /* - ** Bells and whistles ;-) - */ - PRINT_ADDR(xp); - if (sxfer & 0x0f) { - /* - ** Disable extended Sreq/Sack filtering - */ - if (tp->period <= 200) OUTB (nc_stest2, 0); - printf ("%s%dns (%d Mb/sec) offset %d.\n", - tp->period<200 ? "FAST SCSI-2 ":"", - tp->period, (1000+tp->period/2)/tp->period, - sxfer & 0x0f); - } else printf ("asynchronous.\n"); - - /* - ** set actual value and sync_status - */ - OUTB (nc_sxfer, sxfer); - np->sync_st = sxfer; - - /* - ** patch ALL ccbs of this target. - */ - for (cp = &np->ccb; cp; cp = cp->link_ccb) { - if (!cp->xfer) continue; - if (cp->xfer->TARGET != target) continue; - cp->sync_status = sxfer; - }; -} - -/*========================================================== -** -** Switch wide mode for current job and it's target -** -**========================================================== -*/ - -static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide) -{ - struct scsi_xfer *xp; - u_short target = INB (nc_ctest0)&7; - tcb_p tp; - u_char scntl3 = np->rv_scntl3 | (wide ? EWS : 0); - - assert (cp); - if (!cp) return; - - xp = cp->xfer; - assert (xp); - if (!xp) return; - assert (target == xp->TARGET & 7); - - tp = &np->target[target]; - tp->widedone = wide+1; - if (tp->wval == scntl3) return; - tp->wval = scntl3; - - /* - ** Bells and whistles ;-) - */ - PRINT_ADDR(xp); - if (scntl3 & EWS) - printf ("WIDE SCSI (16 bit) enabled.\n"); - else - printf ("WIDE SCSI disabled.\n"); - - /* - ** set actual value and sync_status - */ - OUTB (nc_scntl3, scntl3); - np->wide_st = scntl3; - - /* - ** patch ALL ccbs of this target. - */ - for (cp = &np->ccb; cp; cp = cp->link_ccb) { - if (!cp->xfer) continue; - if (cp->xfer->TARGET != target) continue; - cp->wide_status = scntl3; - }; -} - -/*========================================================== -** -** Switch tagged mode for a target. -** -**========================================================== -*/ - -static void ncr_setmaxtags (tcb_p tp, u_long usrtags) -{ - int l; - tp->usrtags = usrtags; - for (l=0; l<MAX_LUN; l++) { - lcb_p lp; - if (!tp) break; - lp=tp->lp[l]; - if (!lp) continue; - ncr_settags (tp, lp); - }; -} - -static void ncr_settags (tcb_p tp, lcb_p lp) -{ - u_char reqtags, tmp; - - if ((!tp) || (!lp)) return; - - /* - ** only devices capable of tagges commands - ** only disk devices - ** only if enabled by user .. - */ - if (( tp->inqdata[7] & INQ7_QUEUE) && ((tp->inqdata[0] & 0x1f)==0x00) - && tp->usrtags) { - reqtags = tp->usrtags; - if (lp->actlink <= 1) - lp->usetags=reqtags; - } else { - reqtags = 1; - if (lp->actlink <= 1) - lp->usetags=0; - }; - - /* - ** don't announce more than available. - */ - tmp = lp->actccbs; - if (tmp > reqtags) tmp = reqtags; - lp->reqlink = tmp; - - /* - ** don't discard if announced. - */ - tmp = lp->actlink; - if (tmp < reqtags) tmp = reqtags; - lp->reqccbs = tmp; -} - -/*---------------------------------------------------- -** -** handle user commands -** -**---------------------------------------------------- -*/ - -static void ncr_usercmd (ncb_p np) -{ - u_char t; - tcb_p tp; - - switch (np->user.cmd) { - - case 0: return; - - case UC_SETSYNC: - for (t=0; t<MAX_TARGET; t++) { - if (!((np->user.target>>t)&1)) continue; - tp = &np->target[t]; - tp->usrsync = np->user.data; - ncr_negotiate (np, tp); - }; - break; - - case UC_SETTAGS: - if (np->user.data > MAX_TAGS) - break; - for (t=0; t<MAX_TARGET; t++) { - if (!((np->user.target>>t)&1)) continue; - ncr_setmaxtags (&np->target[t], np->user.data); - }; - break; - - case UC_SETDEBUG: - ncr_debug = np->user.data; - break; - - case UC_SETORDER: - np->order = np->user.data; - break; - - case UC_SETWIDE: - for (t=0; t<MAX_TARGET; t++) { - u_long size; - if (!((np->user.target>>t)&1)) continue; - tp = &np->target[t]; - size = np->user.data; - if (size > np->maxwide) size=np->maxwide; - tp->usrwide = size; - ncr_negotiate (np, tp); - }; - break; - - case UC_SETFLAG: - for (t=0; t<MAX_TARGET; t++) { - if (!((np->user.target>>t)&1)) continue; - tp = &np->target[t]; - tp->usrflag = np->user.data; - }; - break; - } - np->user.cmd=0; -} - - - - -/*========================================================== -** -** -** ncr timeout handler. -** -** -**========================================================== -** -** Misused to keep the driver running when -** interrupts are not configured correctly. -** -**---------------------------------------------------------- -*/ - -static void ncr_timeout (ncb_p np) -{ - u_long thistime = time.tv_sec; - u_long step = np->ticks; - u_long count = 0; - long signed t; - ccb_p cp; - - if (np->lasttime != thistime) { - np->lasttime = thistime; - - ncr_usercmd (np); - - /*---------------------------------------------------- - ** - ** handle ncr chip timeouts - ** - ** Assumption: - ** We have a chance to arbitrate for the - ** SCSI bus at least every 10 seconds. - ** - **---------------------------------------------------- - */ - - t = thistime - np->heartbeat; - - if (t<2) np->latetime=0; else np->latetime++; - - if (np->latetime>2) { - /* - ** If there are no requests, the script - ** processor will sleep on SEL_WAIT_RESEL. - ** But we have to check whether it died. - ** Let's wake it up. - */ - OUTB (nc_istat, SIGP); - }; - - if (np->latetime>10) { - /* - ** Although we tried to wakeup it, - ** the script processor didn't answer. - ** - ** May be a target is hanging, - ** or another initator lets a tape device - ** rewind with disconnect disabled :-( - ** - ** We won't accept that. - */ - printf ("%s: reset by timeout.\n", ncr_name (np)); - OUTB (nc_istat, SRST); - OUTB (nc_istat, 0); - if (INB (nc_sbcl) & CBSY) - OUTB (nc_scntl1, CRST); - ncr_init (np, NULL, HS_TIMEOUT); - np->heartbeat = thistime; - }; - - /*---------------------------------------------------- - ** - ** handle ccb timeouts - ** - **---------------------------------------------------- - */ - - for (cp=&np->ccb; cp; cp=cp->link_ccb) { - /* - ** look for timed out ccbs. - */ - if (!cp->host_status) continue; - count++; - if (cp->tlimit > thistime) continue; - - /* - ** Disable reselect. - ** Remove it from startqueue. - */ - cp->jump_ccb.l_cmd = (SCR_JUMP); - if (cp->phys.header.launch.l_paddr == - vtophys (&np->script->select)) { - printf ("%s: timeout ccb=%x (skip)\n", - ncr_name (np), (unsigned)cp); - cp->phys.header.launch.l_paddr - = vtophys (&np->script->skip); - }; - - switch (cp->host_status) { - - case HS_BUSY: - case HS_NEGOTIATE: - /* - ** still in start queue ? - */ - if (cp->phys.header.launch.l_paddr == - vtophys (&np->script->skip)) - continue; - - /* fall through */ - case HS_DISCONNECT: - cp->host_status=HS_TIMEOUT; - }; - cp->tag = 0; - - /* - ** wakeup this ccb. - */ - { - int oldspl = splbio(); - ncr_complete (np, cp); - splx (oldspl); - }; - }; - } - - timeout (TIMEOUT ncr_timeout, (caddr_t) np, step ? step : 1); - - if ((INB(nc_istat) & (INTF|SIP|DIP)) && !np->lock) { - - /* - ** Process pending interrupts. - */ - - int oldspl = splbio (); - if (DEBUG_FLAGS & DEBUG_TINY) printf ("{"); - ncr_exception (np); - if (DEBUG_FLAGS & DEBUG_TINY) printf ("}"); - splx (oldspl); - }; -} - -/*========================================================== -** -** -** ncr chip exception handler. -** -** -**========================================================== -*/ - -void ncr_exception (ncb_p np) -{ - u_char istat, dstat; - u_short sist; - u_long dsp; - - /* - ** interrupt on the fly ? - */ - while ((istat = INB (nc_istat)) & INTF) { - if (DEBUG_FLAGS & DEBUG_TINY) printf ("F"); - OUTB (nc_istat, INTF); - np->profile.num_fly++; - ncr_wakeup (np, 0); - }; - - if (!(istat & (SIP|DIP))) return; - - /* - ** Steinbach's Guideline for Systems Programming: - ** Never test for an error condition you don't know how to handle. - */ - - dstat = INB (nc_dstat); - sist = INW (nc_sist) ; - np->profile.num_int++; - - if (DEBUG_FLAGS & DEBUG_TINY) - printf ("<%d|%x:%x|%x:%x>", - INB(nc_scr0), - dstat,sist, - (unsigned)INL(nc_dsp), - (unsigned)INL(nc_dbc)); - if ((dstat==DFE) && (sist==PAR)) return; - -/*========================================================== -** -** First the normal cases. -** -**========================================================== -*/ - /*------------------------------------------- - ** SCSI reset - **------------------------------------------- - */ - - if (sist & RST) { - ncr_init (np, "scsi reset", HS_RESET); - return; - }; - - /*------------------------------------------- - ** selection timeout - ** - ** IID excluded from dstat mask! - ** (chip bug) - **------------------------------------------- - */ - - if ((sist & STO) && - !(sist & (GEN|HTH|MA|SGE|UDC|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|SIR))) { - ncr_int_sto (np); - return; - }; - - /*------------------------------------------- - ** Phase mismatch. - **------------------------------------------- - */ - - if ((sist & MA) && - !(sist & (STO|GEN|HTH|SGE|UDC|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|SIR|IID))) { - ncr_int_ma (np); - return; - }; - - /*---------------------------------------- - ** move command with length 0 - **---------------------------------------- - */ - - if ((dstat & IID) && - !(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|SIR)) && - ((INL(nc_dbc) & 0xf8000000) == SCR_MOVE_TBL)) { - /* - ** Target wants more data than available. - ** The "no_data" script will do it. - */ - OUTL (nc_dsp, vtophys(&np->script->no_data)); - return; - }; - - /*------------------------------------------- - ** Programmed interrupt - **------------------------------------------- - */ - - if ((dstat & SIR) && - !(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|IID)) && - (INB(nc_dsps) <= SIR_MAX)) { - ncr_int_sir (np); - return; - }; - - /*======================================== - ** do the register dump - **======================================== - */ - - if (time.tv_sec - np->regtime.tv_sec>10) { - int i; - np->regtime = time; - for (i=0; i<sizeof(np->regdump); i++) - ((char*)&np->regdump)[i] = ((char*)np->reg)[i]; - np->regdump.nc_dstat = dstat; - np->regdump.nc_sist = sist; - }; - - printf ("%s targ %d?: ERROR (%x:%x:%x) (%x/%x) @ (%x:%x).\n", - ncr_name (np), INB (nc_ctest0)&7, dstat, sist, - INB (nc_sbcl), - INB (nc_sxfer),INB (nc_scntl3), - (unsigned) (dsp = INL (nc_dsp)), - (unsigned) INL (nc_dbc)); - - /*---------------------------------------- - ** clean up the dma fifo - **---------------------------------------- - */ - - if ( (INB(nc_sstat0) & (ILF|ORF|OLF) ) || - (INB(nc_sstat1) & (FF3210) ) || - (INB(nc_sstat2) & (ILF1|ORF1|OLF1)) || /* wide .. */ - !(dstat & DFE)) { - printf ("%s: have to clear fifos.\n", ncr_name (np)); - OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */ - OUTB (nc_ctest3, CLF); /* clear dma fifo */ - } - - /*---------------------------------------- - ** unexpected disconnect - **---------------------------------------- - */ - - if ((sist & UDC) && - !(sist & (STO|GEN|HTH|MA|SGE|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|SIR|IID))) { - OUTB (nc_scr0, HS_UNEXPECTED); - OUTL (nc_dsp, vtophys(&np->script->cleanup)); - return; - }; - - /*---------------------------------------- - ** cannot disconnect - **---------------------------------------- - */ - - if ((dstat & IID) && - !(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|SIR)) && - ((INL(nc_dbc) & 0xf8000000) == SCR_WAIT_DISC)) { - /* - ** Data cycles while waiting for disconnect. - ** Force disconnect. - */ - OUTB (nc_scntl1, 0); - /* - ** System may hang, but timeout will handle that. - ** In fact, timeout can handle ALL problems :-) - */ - OUTB (nc_dcntl, (STD|NOCOM)); - return; - }; - - /*---------------------------------------- - ** single step - **---------------------------------------- - */ - - if ((dstat & SSI) && - !(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|SIR|IID))) { - OUTB (nc_dcntl, (STD|NOCOM)); - return; - }; - -/* -** @RECOVER@ HTH, SGE, ABRT. -** -** We should try to recover from these interrupts. -** They may occur if there are problems with synch transfers, -** or if targets are powerswitched while the driver is running. -*/ - - if (sist & SGE) { - OUTB (nc_ctest3, CLF); /* clear scsi offsets */ - } - - /* - ** Freeze controller to be able to read the messages. - */ - - if (DEBUG_FLAGS & DEBUG_FREEZE) { - int i; - unsigned char val; - for (i=0; i<0x60; i++) { - switch (i%16) { - - case 0: - printf ("%s: reg[%d0]: ", - ncr_name(np),i/16); - break; - case 4: - case 8: - case 12: - printf (" "); - break; - }; - val = ((unsigned char*) np->vaddr) [i]; - printf (" %x%x", val/16, val%16); - if (i%16==15) printf (".\n"); - }; - - untimeout (TIMEOUT ncr_timeout, (caddr_t) np); - - printf ("%s: halted!\n", ncr_name(np)); - /* - ** don't restart controller ... - */ - OUTB (nc_istat, SRST); - return; - }; - - /* - ** sorry, have to kill ALL jobs ... - */ - - ncr_init (np, "fatal error", HS_FAIL); -} - -/*========================================================== -** -** ncr chip exception handler for selection timeout -** -**========================================================== -** -** There seems to be a bug in the 53c810. -** Although a STO-interrupt is pending, -** it continues executing script commands. -** But it will fail and interrupt (IID) on -** the next instruction where it's looking -** for a valid phase. -** -**---------------------------------------------------------- -*/ - -void ncr_int_sto (ncb_p np) -{ - u_long dsa, scratcha, diff; - ccb_p cp; - if (DEBUG_FLAGS & DEBUG_TINY) printf ("T"); - - /* - ** look for ccb and set the status. - */ - - dsa = INL (nc_dsa); - cp = &np->ccb; - while (cp && (vtophys(&cp->phys) != dsa)) - cp = cp->link_ccb; - - if (cp) { - cp-> host_status = HS_SEL_TIMEOUT; - ncr_complete (np, cp); - }; - - /* - ** repair start queue - */ - - scratcha = INL (nc_scratcha); - diff = scratcha - vtophys(&np->script->tryloop); - - assert ((diff <= MAX_START * 20) && !(diff % 20)); - - if ((diff <= MAX_START * 20) && !(diff % 20)) { - np->script->startpos[0] = scratcha; - OUTL (nc_dsp, vtophys (&np->script->start)); - return; - }; - ncr_init (np, "selection timeout", HS_FAIL); -} - -/*========================================================== -** -** -** ncr chip exception handler for phase errors. -** -** -**========================================================== -** -** We have to construct a new transfer descriptor, -** to transfer the rest of the current block. -** -**---------------------------------------------------------- -*/ - -static void ncr_int_ma (ncb_p np) -{ - u_long dbc; - u_long rest; - u_long dsa; - u_long dsp; - u_long nxtdsp; - u_long *vdsp; - u_long oadr, olen; - u_long *tblp, *newcmd; - u_char cmd, sbcl, delta, ss0, ss2; - ccb_p cp; - - dsp = INL (nc_dsp); - dsa = INL (nc_dsa); - dbc = INL (nc_dbc); - ss0 = INB (nc_sstat0); - ss2 = INB (nc_sstat2); - sbcl= INB (nc_sbcl); - - cmd = dbc >> 24; - rest= dbc & 0xffffff; - delta=(INB (nc_dfifo) - rest) & 0x7f; - - /* - ** The data in the dma fifo has not been transfered to - ** the target -> add the amount to the rest - ** and clear the data. - ** Check the sstat2 register in case of wide transfer. - */ - - if (! (INB(nc_dstat) & DFE)) rest += delta; - if (ss0 & OLF) rest++; - if (ss0 & ORF) rest++; - if (INB(nc_scntl3) & EWS) { - if (ss2 & OLF1) rest++; - if (ss2 & ORF1) rest++; - }; - OUTB (nc_ctest3, CLF ); /* clear dma fifo */ - OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */ - - /* - ** verify cp - */ - dsa = INL (nc_dsa); - cp = &np->ccb; - while (cp && (vtophys(&cp->phys) != dsa)) - cp = cp->link_ccb; - - assert (cp == np->header.cp); - assert (cp); - if (!cp) - return; - - /* - ** find the interrupted script command, - ** and the address at where to continue. - */ - - if (dsp == vtophys (&cp->patch[2])) { - vdsp = &cp->patch[0]; - nxtdsp = vdsp[3]; - } else if (dsp == vtophys (&cp->patch[6])) { - vdsp = &cp->patch[4]; - nxtdsp = vdsp[3]; - } else { - vdsp = (u_long*) ((char*)np->script - vtophys(np->script) + dsp -8); - nxtdsp = dsp; - }; - - /* - ** log the information - */ - if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE)) { - printf ("P%d%d ",cmd&7, sbcl&7); - printf ("RL=%d D=%d SS0=%x ", - (unsigned) rest, (unsigned) delta, ss0); - }; - if (DEBUG_FLAGS & DEBUG_PHASE) { - printf ("\nCP=%x CP2=%x DSP=%x NXT=%x VDSP=%x CMD=%x ", - (unsigned)cp, (unsigned)np->header.cp, - (unsigned)dsp, - (unsigned)nxtdsp, (unsigned)vdsp, cmd); - }; - - /* - ** get old startaddress and old length. - */ - - oadr = vdsp[1]; - - if (cmd & 0x10) { /* Table indirect */ - tblp = (u_long*) ((char*) &cp->phys + oadr); - olen = tblp[0]; - oadr = tblp[1]; - } else { - tblp = (u_long*) 0; - olen = vdsp[0] & 0xffffff; - }; - - if (DEBUG_FLAGS & DEBUG_PHASE) { - printf ("OCMD=%x\nTBLP=%x OLEN=%x OADR=%x\n", - (unsigned) (vdsp[0] >> 24), - (unsigned) tblp, - (unsigned) olen, - (unsigned) oadr); - }; - - /* - ** if old phase not dataphase, leave here. - */ - - assert (cmd == (vdsp[0] >> 24)); - if (cmd & 0x06) { - PRINT_ADDR(cp->xfer); - printf ("phase change %d-%d %d@%x resid=%d.\n", - cmd&7, sbcl&7, (unsigned)olen, - (unsigned)oadr, (unsigned)rest); - - OUTB (nc_dcntl, (STD|NOCOM)); - return; - }; - - /* - ** choose the correct patch area. - ** if savep points to one, choose the other. - */ - - newcmd = cp->patch; - if (cp->phys.header.savep == vtophys (newcmd)) newcmd+=4; - - /* - ** fillin the commands - */ - - newcmd[0] = ((cmd & 0x0f) << 24) | rest; - newcmd[1] = oadr + olen - rest; - newcmd[2] = SCR_JUMP; - newcmd[3] = nxtdsp; - - if (DEBUG_FLAGS & DEBUG_PHASE) { - PRINT_ADDR(cp->xfer); - printf ("newcmd[%d] %x %x %x %x.\n", - newcmd - cp->patch, - (unsigned)newcmd[0], - (unsigned)newcmd[1], - (unsigned)newcmd[2], - (unsigned)newcmd[3]); - } - /* - ** fake the return address (to the patch). - ** and restart script processor at dispatcher. - */ - np->profile.num_break++; - OUTL (nc_temp, vtophys (newcmd)); - OUTL (nc_dsp, vtophys (&np->script->dispatch)); -} - -/*========================================================== -** -** -** ncr chip exception handler for programmed interrupts. -** -** -**========================================================== -*/ - -static int ncr_show_msg (u_char * msg) -{ - u_char i; - printf ("%x",*msg); - if (*msg==M_EXTENDED) { - for (i=1;i<8;i++) { - if (i-1>msg[1]) break; - printf ("-%x",msg[i]); - }; - return (i+1); - } else if ((*msg & 0xf0) == 0x20) { - printf ("-%x",msg[1]); - return (2); - }; - return (1); -} - -void ncr_int_sir (ncb_p np) -{ - u_char chg, ofs, per, fak, wide; - u_char num = INB (nc_dsps); - ccb_p cp=0; - u_long dsa; - u_char target = INB (nc_ctest0) & 7; - tcb_p tp = &np->target[target]; - int i; - if (DEBUG_FLAGS & DEBUG_TINY) printf ("I#%d", num); - - switch (num) { - case SIR_SENSE_RESTART: - case SIR_STALL_RESTART: - break; - - default: - /* - ** lookup the ccb - */ - dsa = INL (nc_dsa); - cp = &np->ccb; - while (cp && (vtophys(&cp->phys) != dsa)) - cp = cp->link_ccb; - - assert (cp == np->header.cp); - assert (cp); - if (!cp) - goto out; - } - - switch (num) { - -/*-------------------------------------------------------------------- -** -** Processing of interrupted getcc selects -** -**-------------------------------------------------------------------- -*/ - - case SIR_SENSE_RESTART: - /*------------------------------------------ - ** Script processor is idle. - ** Look for interrupted "check cond" - **------------------------------------------ - */ - - if (DEBUG_FLAGS & DEBUG_RESTART) - printf ("%s: int#%d",ncr_name (np),num); - cp = (ccb_p) 0; - for (i=0; i<MAX_TARGET; i++) { - if (DEBUG_FLAGS & DEBUG_RESTART) printf (" t%d", i); - tp = &np->target[i]; - if (DEBUG_FLAGS & DEBUG_RESTART) printf ("+"); - cp = tp->hold_cp; - if (!cp) continue; - if (DEBUG_FLAGS & DEBUG_RESTART) printf ("+"); - if ((cp->host_status==HS_BUSY) && - (cp->scsi_status==S_CHECK_COND)) - break; - if (DEBUG_FLAGS & DEBUG_RESTART) printf ("- (remove)"); - tp->hold_cp = cp = (ccb_p) 0; - }; - - if (cp) { - if (DEBUG_FLAGS & DEBUG_RESTART) - printf ("+ restart job ..\n"); - OUTL (nc_dsa, vtophys (&cp->phys)); - OUTL (nc_dsp, vtophys (&np->script->getcc)); - return; - }; - - /* - ** no job, resume normal processing - */ - if (DEBUG_FLAGS & DEBUG_RESTART) printf (" -- remove trap\n"); - np->script->start0[0] = SCR_INT ^ IFFALSE (0); - break; - - case SIR_SENSE_FAILED: - /*------------------------------------------- - ** While trying to reselect for - ** getting the condition code, - ** a target reselected us. - **------------------------------------------- - */ - PRINT_ADDR(cp->xfer); - if (DEBUG_FLAGS & DEBUG_RESTART) - printf ("in getcc reselect by t%d.\n", - INB(nc_ssid)&7); - - /* - ** Mark this job - */ - cp->host_status = HS_BUSY; - cp->scsi_status = S_CHECK_COND; - np->target[cp->xfer->TARGET].hold_cp = cp; - - /* - ** And patch code to restart it. - */ - np->script->start0[0] = SCR_INT; - break; - -/*----------------------------------------------------------------------------- -** -** Was Sie schon immer ueber transfermode negotiation wissen wollten ... -** -** We try to negotiate sync and wide transfer only after -** a successfull inquire command. We look to byte 7 of the -** inquire data to determine the capabilities if the target. -** -** When we try to negotiate, we append the negotiation message -** to the identify and (maybe) simpletag message. -** The host status field is set to HS_NEGOTIATE to mark this -** situation. -** -** If the target doesn't answer this message immidiately -** (as required by the standard), the SIR_NEGO_FAIL interrupt -** will be raised eventually. -** The handler removes the HS_NEGOTIATE status, and sets the -** negotiated value to the default (async / nowide). -** -** If we receive a matching answer immediately, we check it -** for validity, and set the values. -** -** If we receive a Reject message immediately, we assume the -** negotiation has failed, and set to the standard values. -** -** If we receive a negotiation message while not in HS_NEGOTIATE -** state, it's a target initiated negotiation. We prepare a -** (hopefully) valid answer, set the values, and send this -** answer back to the target. -** -** If the target doesn't fetch the answer (no message out phase), -** we assume the negotiation has failed, and set the values to -** the default. -** -** When we set the values, we set in all ccbs belonging to this -** target, in the controllers register, and in the "phys" -** field of the controllers struct ncb. -** -** Possible cases: hs sir msg_in value send goto -** We try try to negotiate: -** -> target doesnt't msgin NEG FAIL noop defa. - dispatch -** -> target rejected our msg NEG FAIL reject defa. - dispatch -** -> target answered (ok) NEG SYNC sdtr set - clrack -** -> target answered (!ok) NEG SYNC sdtr defa. REJ--->msg_bad -** -> target answered (ok) NEG WIDE wdtr set - clrack -** -> target answered (!ok) NEG WIDE wdtr defa. REJ--->msg_bad -** -> any other msgin NEG FAIL noop defa - dispatch -** -** Target tries to negotiate: -** -> incoming message --- SYNC sdtr set SDTR - -** -> incoming message --- WIDE wdtr set WDTR - -** We sent our answer: -** -> target doesn't msgout --- PROTO ? defa. - dispatch -** -**----------------------------------------------------------------------------- -*/ - - case SIR_NEGO_FAILED: - /*------------------------------------------------------- - ** - ** Negotiation failed. - ** Target doesn't send an answer message, - ** or target rejected our message. - ** - ** Remove negotiation request. - ** - **------------------------------------------------------- - */ - OUTB (HS_PRT, HS_BUSY); - - /* fall through */ - - case SIR_NEGO_PROTO: - /*------------------------------------------------------- - ** - ** Negotiation failed. - ** Target doesn't fetch the answer message. - ** - **------------------------------------------------------- - */ - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - printf ("negotiation failed sir=%x status=%x.\n", - num, cp->nego_status); - }; - - /* - ** any error in negotiation: - ** fall back to default mode. - */ - switch (cp->nego_status) { - - case NS_SYNC: - ncr_setsync (np, cp, 0xe0); - break; - - case NS_WIDE: - ncr_setwide (np, cp, 0); - break; - - }; - np->msgin [0] = M_NOOP; - np->msgout[0] = M_NOOP; - cp->nego_status = 0; - OUTL (nc_dsp,vtophys (&np->script->dispatch)); - break; - - case SIR_NEGO_SYNC: - /* - ** Synchronous request message received. - */ - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - printf ("sync msgin: "); - (void) ncr_show_msg (np->msgin); - printf (".\n"); - }; - - /* - ** get requested values. - */ - - chg = 0; - per = np->msgin[3]; - ofs = np->msgin[4]; - if (ofs==0) per=255; - - /* - ** if target sends SDTR message, - ** it CAN transfer synch. - */ - - if (ofs) - tp->inqdata[7] |= INQ7_SYNC; - - /* - ** check values against driver limits. - */ - - if (per < np->ns_sync) - {chg = 1; per = np->ns_sync;} - if (per < tp->minsync) - {chg = 1; per = tp->minsync;} - if (ofs > tp->maxoffs) - {chg = 1; ofs = tp->maxoffs;} - - /* - ** Check against controller limits. - */ - fak = (4ul * per - 1) / np->ns_sync - 3; - if (ofs && (fak>7)) {chg = 1; ofs = 0;} - if (!ofs) fak=7; - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - printf ("sync: per=%d ofs=%d fak=%d chg=%d.\n", - per, ofs, fak, chg); - } - - if (INB (HS_PRT) == HS_NEGOTIATE) { - OUTB (HS_PRT, HS_BUSY); - switch (cp->nego_status) { - - case NS_SYNC: - /* - ** This was an answer message - */ - if (chg) { - /* - ** Answer wasn't acceptable. - */ - ncr_setsync (np, cp, 0xe0); - OUTL (nc_dsp,vtophys (&np->script->msg_bad)); - } else { - /* - ** Answer is ok. - */ - ncr_setsync (np, cp, (fak<<5)|ofs); - OUTL (nc_dsp,vtophys (&np->script->clrack)); - }; - return; - - case NS_WIDE: - ncr_setwide (np, cp, 0); - break; - }; - }; - - /* - ** It was a request. Set value and - ** prepare an answer message - */ - - ncr_setsync (np, cp, (fak<<5)|ofs); - - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 3; - np->msgout[2] = M_X_SYNC_REQ; - np->msgout[3] = per; - np->msgout[4] = ofs; - - np->msgin [0] = M_NOOP; - - cp->nego_status = NS_SYNC; - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - printf ("sync msgout: "); - (void) ncr_show_msg (np->msgin); - printf (".\n"); - } - break; - - case SIR_NEGO_WIDE: - /* - ** Wide request message received. - */ - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - printf ("wide msgin: "); - (void) ncr_show_msg (np->msgin); - printf (".\n"); - }; - - /* - ** get requested values. - */ - - chg = 0; - wide = np->msgin[3]; - - /* - ** if target sends WDTR message, - ** it CAN transfer wide. - */ - - if (wide) - tp->inqdata[7] |= INQ7_WIDE16; - - /* - ** check values against driver limits. - */ - - if (wide > tp->usrwide) - {chg = 1; wide = tp->usrwide;} - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - printf ("wide: wide=%d chg=%d.\n", wide, chg); - } - - if (INB (HS_PRT) == HS_NEGOTIATE) { - OUTB (HS_PRT, HS_BUSY); - switch (cp->nego_status) { - - case NS_WIDE: - /* - ** This was an answer message - */ - if (chg) { - /* - ** Answer wasn't acceptable. - */ - ncr_setwide (np, cp, 0); - OUTL (nc_dsp,vtophys (&np->script->msg_bad)); - } else { - /* - ** Answer is ok. - */ - ncr_setwide (np, cp, wide); - OUTL (nc_dsp,vtophys (&np->script->clrack)); - }; - return; - - case NS_SYNC: - ncr_setsync (np, cp, 0xe0); - break; - }; - }; - - /* - ** It was a request, set value and - ** prepare an answer message - */ - - ncr_setwide (np, cp, wide); - - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 2; - np->msgout[2] = M_X_WIDE_REQ; - np->msgout[3] = wide; - - np->msgin [0] = M_NOOP; - - cp->nego_status = NS_WIDE; - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - printf ("wide msgout: "); - (void) ncr_show_msg (np->msgin); - printf (".\n"); - } - break; - -/*-------------------------------------------------------------------- -** -** Processing of special messages -** -**-------------------------------------------------------------------- -*/ - - case SIR_REJECT_RECEIVED: - /*----------------------------------------------- - ** - ** We received a M_REJECT message. - ** - **----------------------------------------------- - */ - - PRINT_ADDR(cp->xfer); - printf ("M_REJECT received (%x:%x).\n", - (unsigned)np->lastmsg, np->msgout[0]); - break; - - case SIR_REJECT_SENT: - /*----------------------------------------------- - ** - ** We received an unknown message - ** - **----------------------------------------------- - */ - - PRINT_ADDR(cp->xfer); - printf ("M_REJECT sent for "); - (void) ncr_show_msg (np->msgin); - printf (".\n"); - break; - -/*-------------------------------------------------------------------- -** -** Processing of special messages -** -**-------------------------------------------------------------------- -*/ - - case SIR_IGN_RESIDUE: - /*----------------------------------------------- - ** - ** We received an IGNORE RESIDUE message, - ** which couldn't be handled by the script. - ** - **----------------------------------------------- - */ - - PRINT_ADDR(cp->xfer); - printf ("M_IGN_RESIDUE received, but not yet implemented.\n"); - break; - - case SIR_MISSING_SAVE: - /*----------------------------------------------- - ** - ** We received an DISCONNECT message, - ** but the datapointer wasn't saved before. - ** - **----------------------------------------------- - */ - - PRINT_ADDR(cp->xfer); - printf ("M_DISCONNECT received, but datapointer not saved:\n" - "\tdata=%x save=%x goal=%x.\n", - (unsigned) INL (nc_temp), - (unsigned) np->header.savep, - (unsigned) np->header.goalp); - break; - -/*-------------------------------------------------------------------- -** -** Processing of a "S_QUEUE_FULL" status. -** -** The current command has been rejected, -** because there are too many in the command queue. -** We have started too many commands for that target. -** -** If possible, reinsert at head of queue. -** Stall queue until there are no disconnected jobs -** (ncr is REALLY idle). Then restart processing. -** -** We should restart the current job after the controller -** has become idle. But this is not yet implemented. -** -**-------------------------------------------------------------------- -*/ - case SIR_STALL_QUEUE: - /*----------------------------------------------- - ** - ** Stall the start queue. - ** - **----------------------------------------------- - */ - PRINT_ADDR(cp->xfer); - printf ("queue full.\n"); - - np->script->start1[0] = SCR_INT; - - /* - ** Try to disable tagged transfers. - */ - ncr_setmaxtags (&np->target[target], 0); - - /* - ** @QUEUE@ - ** - ** Should update the launch field of the - ** current job to be able to restart it. - ** Then prepend it to the start queue. - */ - - /* fall through */ - - case SIR_STALL_RESTART: - /*----------------------------------------------- - ** - ** Enable selecting again, - ** if NO disconnected jobs. - ** - **----------------------------------------------- - */ - /* - ** Look for a disconnected job. - */ - cp = &np->ccb; - while (cp && cp->host_status != HS_DISCONNECT) - cp = cp->link_ccb; - - /* - ** if there is one, ... - */ - if (cp) { - /* - ** wait for reselection - */ - OUTL (nc_dsp, vtophys (&np->script->reselect)); - return; - }; - - /* - ** else remove the interrupt. - */ - - printf ("%s: queue empty.\n", ncr_name (np)); - np->script->start1[0] = SCR_INT ^ IFFALSE (0); - break; - }; - -out: - OUTB (nc_dcntl, (STD|NOCOM)); -} - -/*========================================================== -** -** -** Aquire a control block -** -** -**========================================================== -*/ - -static ccb_p ncr_get_ccb - (ncb_p np, u_long flags, u_long target, u_long lun) -{ - lcb_p lp; - ccb_p cp = (ccb_p ) 0; - - /* - ** Lun structure available ? - */ - - lp = np->target[target].lp[lun]; - if (lp) - cp = lp->next_ccb; - - /* - ** Look for free CCB - */ - - while (cp && cp->magic) cp = cp->next_ccb; - - /* - ** if nothing available, take the default. - */ - - if (!cp) cp = &np->ccb; - - /* - ** Wait until available. - */ - - while (cp->magic) { - if (flags & SCSI_NOSLEEP) break; - if (tsleep ((caddr_t)cp, PZERO|PCATCH, "ncr", 0)) - break; - }; - - if (cp->magic) - return ((ccb_p) 0); - - cp->magic = 1; - return (cp); -} - -/*========================================================== -** -** -** Release one control block -** -** -**========================================================== -*/ - -void ncr_free_ccb (ncb_p np, ccb_p cp, int flags) -{ - /* - ** sanity - */ - - if (!cp) return; - - cp -> host_status = HS_IDLE; - cp -> magic = 0; - if (cp == &np->ccb) - wakeup ((caddr_t) cp); -} - -/*========================================================== -** -** -** Allocation of resources for Targets/Luns/Tags. -** -** -**========================================================== -*/ - -static void ncr_alloc_ccb (ncb_p np, struct scsi_xfer * xp) -{ - tcb_p tp; - lcb_p lp; - ccb_p cp; - - u_long target; - u_long lun; - - if (!np) return; - if (!xp) return; - - target = xp->TARGET; - lun = xp->LUN; - - if (target>=MAX_TARGET) return; - if (lun >=MAX_LUN ) return; - - tp=&np->target[target]; - - if (!tp->jump_tcb.l_cmd) { - - /* - ** initialize it. - */ - tp->jump_tcb.l_cmd = (SCR_JUMP^IFFALSE (DATA (0x80 + target))); - tp->jump_tcb.l_paddr = np->jump_tcb.l_paddr; - - tp->getscr[0] = SCR_COPY (1); - tp->getscr[1] = vtophys (&tp->sval); - tp->getscr[2] = np->paddr + offsetof (struct ncr_reg, nc_sxfer); - tp->getscr[3] = SCR_COPY (1); - tp->getscr[4] = vtophys (&tp->wval); - tp->getscr[5] = np->paddr + offsetof (struct ncr_reg, nc_scntl3); - - assert (( (offsetof(struct ncr_reg, nc_sxfer) ^ - offsetof(struct tcb , sval )) &3) == 0); - assert (( (offsetof(struct ncr_reg, nc_scntl3) ^ - offsetof(struct tcb , wval )) &3) == 0); - - tp->call_lun.l_cmd = (SCR_CALL); - tp->call_lun.l_paddr = vtophys (&np->script->resel_lun); - - tp->jump_lcb.l_cmd = (SCR_JUMP); - tp->jump_lcb.l_paddr = vtophys (&np->script->abort); - np->jump_tcb.l_paddr = vtophys (&tp->jump_tcb); - - ncr_setmaxtags (tp, SCSI_NCR_MAX_TAGS); - } - - /* - ** Logic unit control block - */ - lp = tp->lp[lun]; - if (!lp) { - /* - ** Allocate a lcb - */ - lp = (lcb_p) malloc (sizeof (struct lcb), M_DEVBUF, M_NOWAIT); - if (!lp) return; - - /* - ** Initialize it - */ - bzero (lp, sizeof (*lp)); - lp->jump_lcb.l_cmd = (SCR_JUMP ^ IFFALSE (DATA (lun))); - lp->jump_lcb.l_paddr = tp->jump_lcb.l_paddr; - - lp->call_tag.l_cmd = (SCR_CALL); - lp->call_tag.l_paddr = vtophys (&np->script->resel_tag); - - lp->jump_ccb.l_cmd = (SCR_JUMP); - lp->jump_ccb.l_paddr = vtophys (&np->script->aborttag); - - lp->actlink = 1; - /* - ** Link into Lun-Chain - */ - - tp->jump_lcb.l_paddr = vtophys (&lp->jump_lcb); - tp->lp[lun] = lp; - - } - - /* - ** Limit possible number of ccbs. - ** - ** If tagged command queueing is enabled, - ** can use more than one ccb. - */ - - if (np->actccbs >= MAX_START-2) return; - if (lp->actccbs && (lp->actccbs >= lp->reqccbs)) - return; - - /* - ** Allocate a ccb - */ - cp = (ccb_p) malloc (sizeof (struct ccb), M_DEVBUF, M_NOWAIT); - - if (!cp) - return; - - if (DEBUG_FLAGS & DEBUG_ALLOC) { - PRINT_ADDR(xp); - printf ("new ccb @%x.\n", (unsigned) cp); - } - - /* - ** Count it - */ - lp->actccbs++; - np->actccbs++; - - /* - ** Initialize it. - */ - bzero (cp, sizeof (*cp)); - - /* - ** link in reselect chain. - */ - cp->jump_ccb.l_cmd = SCR_JUMP; - cp->jump_ccb.l_paddr = lp->jump_ccb.l_paddr; - lp->jump_ccb.l_paddr = vtophys(&cp->jump_ccb); - cp->call_tmp.l_cmd = SCR_CALL; - cp->call_tmp.l_paddr = vtophys(&np->script->resel_tmp); - - /* - ** link in wakeup chain - */ - cp->link_ccb = np->ccb.link_ccb; - np->ccb.link_ccb = cp; - - /* - ** Link into CCB-Chain - */ - cp->next_ccb = lp->next_ccb; - lp->next_ccb = cp; -} - -/*========================================================== -** -** -** Announce the number of ccbs/tags to the scsi driver. -** -** -**========================================================== -*/ - -static void ncr_opennings (ncb_p np, lcb_p lp, struct scsi_xfer * xp) -{ -#ifndef ANCIENT - /* - ** want to reduce the number ... - */ - if (lp->actlink > lp->reqlink) { - - /* - ** Try to reduce the count. - ** We assume to run at splbio .. - */ - u_char diff = lp->actlink - lp->reqlink; - - if (!diff) return; - - if (diff > xp->sc_link->opennings) - diff = xp->sc_link->opennings; - - xp->sc_link->opennings -= diff; - lp->actlink -= diff; - if (DEBUG_FLAGS & DEBUG_TAGS) - printf ("%s: actlink: diff=%d, new=%d, req=%d\n", - ncr_name(np), diff, lp->actlink, lp->reqlink); - return; - }; - - /* - ** want to increase the number ? - */ - if (lp->reqlink > lp->actlink) { - u_char diff = lp->reqlink - lp->actlink; - - xp->sc_link->opennings += diff; - lp->actlink += diff; - wakeup ((caddr_t) xp->sc_link); - if (DEBUG_FLAGS & DEBUG_TAGS) - printf ("%s: actlink: diff=%d, new=%d, req=%d\n", - ncr_name(np), diff, lp->actlink, lp->reqlink); - }; -#endif -} - -/*========================================================== -** -** -** Build Scatter Gather Block -** -** -**========================================================== -** -** The transfer area may be scattered among -** several non adjacent physical pages. -** -** We may use MAX_SCATTER blocks. -** -**---------------------------------------------------------- -*/ - -static int ncr_scatter - (struct dsb* phys, vm_offset_t vaddr, vm_size_t datalen) -{ - u_long paddr, pnext; - - u_short segment = 0; - u_long segsize, segaddr; - u_long size, csize = 0; - u_long chunk = MAX_SIZE; - int free; - - bzero (&phys->data, sizeof (phys->data)); - if (!datalen) return (0); - - paddr = vtophys (vaddr); - - /* - ** insert extra break points at a distance of chunk. - ** We try to reduce the number of interrupts due to - ** unexpected phase changes due to disconnects. - ** A typical harddisk may disconnect before ANY block. - ** If we want to avoid unexpected phase changes at all - ** we have to use a break point every 512 bytes. - ** Of course the number of scatter/gather blocks is - ** limited. - */ - - free = MAX_SCATTER - 1; - - if (vaddr & (NBPG-1)) free -= datalen / NBPG; - - if (free>1) - while ((chunk * free >= 2 * datalen) && (chunk>=1024)) - chunk /= 2; - - if(DEBUG_FLAGS & DEBUG_SCATTER) - printf("ncr?:\tscattering virtual=0x%x size=%d chunk=%d.\n", - (unsigned) vaddr, (unsigned) datalen, (unsigned) chunk); - - /* - ** Build data descriptors. - */ - while (datalen && (segment < MAX_SCATTER)) { - - /* - ** this segment is empty - */ - segsize = 0; - segaddr = paddr; - pnext = paddr; - - if (!csize) csize = chunk; - - while ((datalen) && (paddr == pnext) && (csize)) { - - /* - ** continue this segment - */ - pnext = (paddr & (~(NBPG - 1))) + NBPG; - - /* - ** Compute max size - */ - - size = pnext - paddr; /* page size */ - if (size > datalen) size = datalen; /* data size */ - if (size > csize ) size = csize ; /* chunksize */ - - segsize += size; - vaddr += size; - csize -= size; - datalen -= size; - paddr = vtophys (vaddr); - }; - - if(DEBUG_FLAGS & DEBUG_SCATTER) - printf ("\tseg #%d addr=%x size=%d (rest=%d).\n", - segment, - (unsigned) segaddr, - (unsigned) segsize, - (unsigned) datalen); - - phys->data[segment].addr = segaddr; - phys->data[segment].size = segsize; - segment++; - } - - if (datalen) { - printf("ncr?: scatter/gather failed (residue=%d).\n", - (unsigned) datalen); - return (-1); - }; - - return (segment); -} - -/*========================================================== -** -** -** Test the pci bus snoop logic :-( -** -** Has to be called with interrupts disabled. -** -** -**========================================================== -*/ - -static int ncr_snooptest (struct ncb* np) -{ - u_long ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc, err=0; - /* - ** init - */ - pc = vtophys (&np->script->snooptest); - host_wr = 1; - ncr_wr = 2; - /* - ** Set memory and register. - */ - ncr_cache = host_wr; - OUTL (nc_temp, ncr_wr); - /* - ** Start script (exchange values) - */ - OUTL (nc_dsp, pc); - /* - ** Wait 'til done - */ - while (!(INB(nc_istat) & (INTF|SIP|DIP))); - /* - ** Read memory and register. - */ - host_rd = ncr_cache; - ncr_rd = INL (nc_scratcha); - ncr_bk = INL (nc_temp); - /* - ** Reset ncr chip - */ - OUTB (nc_istat, SRST); - OUTB (nc_istat, 0 ); - /* - ** Show results. - */ - if (host_wr != ncr_rd) { - printf ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n", - (int) host_wr, (int) ncr_rd); - err |= 1; - }; - if (host_rd != ncr_wr) { - printf ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n", - (int) ncr_wr, (int) host_rd); - err |= 2; - }; - if (ncr_bk != ncr_wr) { - printf ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n", - (int) ncr_wr, (int) ncr_bk); - err |= 4; - }; - return (err); -} - -/*========================================================== -** -** -** Profiling the drivers and targets performance. -** -** -**========================================================== -*/ - -/* -** Compute the difference in milliseconds. -**/ - -static int ncr_delta (struct timeval * from, struct timeval * to) -{ - if (!from->tv_sec) return (-1); - if (!to ->tv_sec) return (-2); - return ( (to->tv_sec - from->tv_sec - 2)*1000+ - +(to->tv_usec - from->tv_usec + 2000000)/1000); -} - -#define PROFILE cp->phys.header.stamp -static void ncb_profile (ncb_p np, ccb_p cp) -{ - int co, da, st, en, di, se, post,work,disc; - u_long diff; - - PROFILE.end = time; - - st = ncr_delta (&PROFILE.start,&PROFILE.status); - if (st<0) return; /* status not reached */ - - da = ncr_delta (&PROFILE.start,&PROFILE.data); - if (da<0) return; /* No data transfer phase */ - - co = ncr_delta (&PROFILE.start,&PROFILE.command); - if (co<0) return; /* command not executed */ - - en = ncr_delta (&PROFILE.start,&PROFILE.end), - di = ncr_delta (&PROFILE.start,&PROFILE.disconnect), - se = ncr_delta (&PROFILE.start,&PROFILE.select); - post = en - st; - - /* - ** @PROFILE@ Disconnect time invalid if multiple disconnects - */ - - if (di>=0) disc = se-di; else disc = 0; - - work = (st - co) - disc; - - diff = (np->disc_phys - np->disc_ref) & 0xff; - np->disc_ref += diff; - - np->profile.num_trans += 1; - if (cp->xfer) - np->profile.num_bytes += cp->xfer->datalen; - np->profile.num_disc += diff; - np->profile.ms_setup += co; - np->profile.ms_data += work; - np->profile.ms_disc += disc; - np->profile.ms_post += post; -} -#undef PROFILE - -/*========================================================== -** -** -** Device lookup. -** -** @GENSCSI@ should be integrated to scsiconf.c -** -** -**========================================================== -*/ - -#ifndef NEW_SCSICONF - -struct table_entry { - char * manufacturer; - char * model; - char * version; - u_long info; -}; - -static struct table_entry device_tab[] = -{ - {"SONY", "SDT-5000", "3.17", QUIRK_NOMSG}, - {"WangDAT", "Model 2600", "01.7", QUIRK_NOMSG}, - {"WangDAT", "Model 3200", "02.2", QUIRK_NOMSG}, - {"WangDAT", "Model 1300", "02.4", QUIRK_NOMSG}, - {"", "", "", 0} /* catch all: must be last entry. */ -}; - -static u_long ncr_lookup(char * id) -{ - struct table_entry * p = device_tab; - char *d, *r, c; - - for (;;p++) { - - d = id+8; - r = p->manufacturer; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - d = id+16; - r = p->model; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - d = id+32; - r = p->version; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - return (p->info); - } -} -#endif - -/*========================================================== -** -** Determine the ncr's clock frequency. -** This is important for the negotiation -** of the synchronous transfer rate. -** -**========================================================== -** -** Note: we have to return the correct value. -** THERE IS NO SAVE DEFAULT VALUE. -** -** We assume that all NCR based boards are delivered -** with a 40Mhz clock. Because we have to divide -** by an integer value greater than 3, only clock -** frequencies of 40Mhz (/4) or 50MHz (/5) permit -** the FAST-SCSI rate of 10MHz. -** -**---------------------------------------------------------- -*/ - -#ifndef NCR_CLOCK -# define NCR_CLOCK 40 -#endif /* NCR_CLOCK */ - - -static void ncr_getclock (ncb_p np) -{ - u_char tbl[5] = {6,2,3,4,6}; - u_char f; - u_char ns_clock = (1000/NCR_CLOCK); - - /* - ** Compute the best value for scntl3. - */ - - f = (2 * MIN_SYNC_PD - 1) / ns_clock; - if (!f ) f=1; - if (f>4) f=4; - np -> ns_sync = (ns_clock * tbl[f]) / 2; - np -> rv_scntl3 = f<<4; - - f = (2 * MIN_ASYNC_PD - 1) / ns_clock; - if (!f ) f=1; - if (f>4) f=4; - np -> ns_async = (ns_clock * tbl[f]) / 2; - np -> rv_scntl3 |= f; - if (DEBUG_FLAGS & DEBUG_TIMING) - printf ("%s: sclk=%d async=%d sync=%d (ns) scntl3=0x%x\n", - ncr_name (np), ns_clock, np->ns_async, np->ns_sync, np->rv_scntl3); -} - -/*=========================================================================*/ -#endif /* KERNEL */ - - diff --git a/sys/pci/ncrreg.h b/sys/pci/ncrreg.h deleted file mode 100644 index 1a22aee38d24..000000000000 --- a/sys/pci/ncrreg.h +++ /dev/null @@ -1,547 +0,0 @@ -/************************************************************************** -** -** $Id: ncrreg.h,v 2.3 94/10/09 21:10:34 wolf Oct11 $ -** -** Device driver for the NCR 53C810 PCI-SCSI-Controller. -** -** 386bsd / FreeBSD / NetBSD -** -**------------------------------------------------------------------------- -** -** Written for 386bsd and FreeBSD by -** wolf@dentaro.gun.de Wolfgang Stanglmeier -** se@mi.Uni-Koeln.de Stefan Esser -** -** Ported to NetBSD by -** mycroft@gnu.ai.mit.edu -** -**------------------------------------------------------------------------- -** -** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. -** -** 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. -** 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. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. -** -*************************************************************************** -*/ - -#ifndef __NCR_REG_H__ -#define __NCR_REG_H__ - - -/*----------------------------------------------------------------- -** -** The ncr 53c810 register structure. -** -**----------------------------------------------------------------- -*/ - -struct ncr_reg { -/*00*/ u_char nc_scntl0; /* full arb., ena parity, par->ATN */ - -/*01*/ u_char nc_scntl1; /* no reset */ - #define ISCON 0x10 /* connected to scsi */ - #define CRST 0x08 /* force reset */ - -/*02*/ u_char nc_scntl2; /* no disconnect expected */ - #define SDU 0x80 /* cmd: disconnect will raise error */ - #define CHM 0x40 /* sta: chained mode */ - #define WSS 0x08 /* sta: wide scsi send [W]*/ - #define WSR 0x01 /* sta: wide scsi received [W]*/ - -/*03*/ u_char nc_scntl3; /* cnf system clock dependent */ - #define EWS 0x08 /* cmd: enable wide scsi [W]*/ - -/*04*/ u_char nc_scid; /* cnf host adapter scsi address */ - #define RRE 0x40 /* r/w:e enable response to resel. */ - #define SRE 0x20 /* r/w:e enable response to select */ - -/*05*/ u_char nc_sxfer; /* ### Sync speed and count */ - -/*06*/ u_char nc_sdid; /* ### Destination-ID */ - -/*07*/ u_char nc_gpreg; /* ??? IO-Pins */ - -/*08*/ u_char nc_sfbr; /* ### First byte in phase */ - -/*09*/ u_char nc_socl; - #define CREQ 0x80 /* r/w: SCSI-REQ */ - #define CACK 0x40 /* r/w: SCSI-ACK */ - #define CBSY 0x20 /* r/w: SCSI-BSY */ - #define CSEL 0x10 /* r/w: SCSI-SEL */ - #define CATN 0x08 /* r/w: SCSI-ATN */ - #define CMSG 0x04 /* r/w: SCSI-MSG */ - #define CC_D 0x02 /* r/w: SCSI-C_D */ - #define CI_O 0x01 /* r/w: SCSI-I_O */ - -/*0a*/ u_char nc_ssid; - -/*0b*/ u_char nc_sbcl; - -/*0c*/ u_char nc_dstat; - #define DFE 0x80 /* sta: dma fifo empty */ - #define MDPE 0x40 /* int: master data parity error */ - #define BF 0x20 /* int: script: bus fault */ - #define ABRT 0x10 /* int: script: command aborted */ - #define SSI 0x08 /* int: script: single step */ - #define SIR 0x04 /* int: script: interrupt instruct. */ - #define IID 0x01 /* int: script: illegal instruct. */ - -/*0d*/ u_char nc_sstat0; - #define ILF 0x80 /* sta: data in SIDL register lsb */ - #define ORF 0x40 /* sta: data in SODR register lsb */ - #define OLF 0x20 /* sta: data in SODL register lsb */ - #define AIP 0x10 /* sta: arbitration in progress */ - #define LOA 0x08 /* sta: arbitration lost */ - #define WOA 0x04 /* sta: arbitration won */ - #define IRST 0x02 /* sta: scsi reset signal */ - #define SDP 0x01 /* sta: scsi parity signal */ - -/*0e*/ u_char nc_sstat1; - #define FF3210 0xf0 /* sta: bytes in the scsi fifo */ - -/*0f*/ u_char nc_sstat2; - #define ILF1 0x80 /* sta: data in SIDL register msb[W]*/ - #define ORF1 0x40 /* sta: data in SODR register msb[W]*/ - #define OLF1 0x20 /* sta: data in SODL register msb[W]*/ - -/*10*/ u_long nc_dsa; /* --> Base page */ - -/*14*/ u_char nc_istat; /* --> Main Command and status */ - #define CABRT 0x80 /* cmd: abort current operation */ - #define SRST 0x40 /* mod: reset chip */ - #define SIGP 0x20 /* r/w: message from host to ncr */ - #define SEM 0x10 /* r/w: message between host + ncr */ - #define CON 0x08 /* sta: connected to scsi */ - #define INTF 0x04 /* sta: int on the fly (reset by wr)*/ - #define SIP 0x02 /* sta: scsi-interrupt */ - #define DIP 0x01 /* sta: host/script interrupt */ - -/*15*/ u_char nc_15_; -/*16*/ u_char nc_16_; -/*17*/ u_char nc_17_; - -/*18*/ u_char nc_ctest0; -/*19*/ u_char nc_ctest1; - -/*1a*/ u_char nc_ctest2; - #define CSIGP 0x40 - -/*1b*/ u_char nc_ctest3; - #define CLF 0x04 /* clear scsi fifo */ - -/*1c*/ u_long nc_temp; /* ### Temporary stack */ - -/*20*/ u_char nc_dfifo; -/*21*/ u_char nc_ctest4; -/*22*/ u_char nc_ctest5; -/*23*/ u_char nc_ctest6; - -/*24*/ u_long nc_dbc; /* ### Byte count and command */ -/*28*/ u_long nc_dnad; /* ### Next command register */ -/*2c*/ u_long nc_dsp; /* --> Script Pointer */ -/*30*/ u_long nc_dsps; /* --> Script pointer save/opcode#2 */ -/*34*/ u_long nc_scratcha; /* ??? Temporary register a */ - -/*38*/ u_char nc_dmode; -/*39*/ u_char nc_dien; -/*3a*/ u_char nc_dwt; - -/*3b*/ u_char nc_dcntl; /* --> Script execution control */ - #define SSM 0x10 /* mod: single step mode */ - #define STD 0x04 /* cmd: start dma mode */ - #define NOCOM 0x01 /* cmd: protect sfbr while reselect */ - -/*3c*/ u_long nc_adder; - -/*40*/ u_short nc_sien; /* -->: interrupt enable */ -/*42*/ u_short nc_sist; /* <--: interrupt status */ - #define STO 0x0400/* sta: timeout (select) */ - #define GEN 0x0200/* sta: timeout (general) */ - #define HTH 0x0100/* sta: timeout (handshake) */ - #define MA 0x80 /* sta: phase mismatch */ - #define CMP 0x40 /* sta: arbitration complete */ - #define SEL 0x20 /* sta: selected by another device */ - #define RSL 0x10 /* sta: reselected by another device*/ - #define SGE 0x08 /* sta: gross error (over/underflow)*/ - #define UDC 0x04 /* sta: unexpected disconnect */ - #define RST 0x02 /* sta: scsi bus reset detected */ - #define PAR 0x01 /* sta: scsi parity error */ - -/*44*/ u_char nc_slpar; -/*45*/ u_char nc_swide; -/*46*/ u_char nc_macntl; -/*47*/ u_char nc_gpcntl; -/*48*/ u_char nc_stime0; /* cmd: timeout for select&handshake*/ -/*49*/ u_char nc_stime1; /* cmd: timeout user defined */ -/*4a*/ u_short nc_respid; /* sta: Reselect-IDs */ - -/*4c*/ u_char nc_stest0; - -/*4d*/ u_char nc_stest1; - -/*4e*/ u_char nc_stest2; - #define ROF 0x40 /* reset scsi offset (after gross error!) */ - #define EXT 0x02 /* extended filtering */ - -/*4f*/ u_char nc_stest3; - #define TE 0x80 /* c: tolerAnt enable */ - #define CSF 0x02 /* c: clear scsi fifo */ - -/*50*/ u_short nc_sidl; /* Lowlevel: latched from scsi data */ -/*52*/ u_short nc_52_; -/*54*/ u_short nc_sodl; /* Lowlevel: data out to scsi data */ -/*56*/ u_short nc_56_; -/*58*/ u_short nc_sbdl; /* Lowlevel: data from scsi data */ -/*5a*/ u_short nc_5a_; -/*5c*/ u_char nc_scr0; /* Working register B */ -/*5d*/ u_char nc_scr1; /* */ -/*5e*/ u_char nc_scr2; /* */ -/*5f*/ u_char nc_scr3; /* */ -/*60*/ -}; - -/*----------------------------------------------------------- -** -** Utility macros for the script. -** -**----------------------------------------------------------- -*/ - -#define REGJ(p,r) (offsetof(struct ncr_reg, p ## r)) -#define REG(r) REGJ (nc_, r) - -#ifndef TARGET_MODE -#define TARGET_MODE 0 -#endif - -typedef unsigned long ncrcmd; - -/*----------------------------------------------------------- -** -** SCSI phases -** -**----------------------------------------------------------- -*/ - -#define SCR_DATA_OUT 0x00000000 -#define SCR_DATA_IN 0x01000000 -#define SCR_COMMAND 0x02000000 -#define SCR_STATUS 0x03000000 -#define SCR_ILG_OUT 0x04000000 -#define SCR_ILG_IN 0x05000000 -#define SCR_MSG_OUT 0x06000000 -#define SCR_MSG_IN 0x07000000 - -/*----------------------------------------------------------- -** -** Data transfer via SCSI. -** -**----------------------------------------------------------- -** -** MOVE_ABS (LEN) -** <<start address>> -** -** MOVE_IND (LEN) -** <<dnad_offset>> -** -** MOVE_TBL -** <<dnad_offset>> -** -**----------------------------------------------------------- -*/ - -#define SCR_MOVE_ABS(l) ((0x08000000 ^ (TARGET_MODE << 1ul)) | (l)) -#define SCR_MOVE_IND(l) ((0x28000000 ^ (TARGET_MODE << 1ul)) | (l)) -#define SCR_MOVE_TBL (0x18000000 ^ (TARGET_MODE << 1ul)) - -struct scr_tblmove { - u_long size; - u_long addr; -}; - -/*----------------------------------------------------------- -** -** Selection -** -**----------------------------------------------------------- -** -** SEL_ABS | SCR_ID (0..7) [ | REL_JMP] -** <<alternate_address>> -** -** SEL_TBL | << dnad_offset>> [ | REL_JMP] -** <<alternate_address>> -** -**----------------------------------------------------------- -*/ - -#define SCR_SEL_ABS 0x40000000 -#define SCR_SEL_ABS_ATN 0x41000000 -#define SCR_SEL_TBL 0x42000000 -#define SCR_SEL_TBL_ATN 0x43000000 - -struct scr_tblsel { - u_char sel_0; - u_char sel_sxfer; - u_char sel_id; - u_char sel_scntl3; -}; - -#define SCR_JMP_REL 0x04000000 -#define SCR_ID(id) (((u_long)(id)) << 16) - -/*----------------------------------------------------------- -** -** Waiting for Disconnect or Reselect -** -**----------------------------------------------------------- -** -** WAIT_DISC -** dummy: <<alternate_address>> -** -** WAIT_RESEL -** <<alternate_address>> -** -**----------------------------------------------------------- -*/ - -#define SCR_WAIT_DISC 0x48000000 -#define SCR_WAIT_RESEL 0x50000000 - -/*----------------------------------------------------------- -** -** Bit Set / Reset -** -**----------------------------------------------------------- -** -** SET (flags {|.. }) -** -** CLR (flags {|.. }) -** -**----------------------------------------------------------- -*/ - -#define SCR_SET(f) (0x58000000 | (f)) -#define SCR_CLR(f) (0x60000000 | (f)) - -#define SCR_CARRY 0x00000400 -#define SCR_TRG 0x00000200 -#define SCR_ACK 0x00000040 -#define SCR_ATN 0x00000008 - - - - -/*----------------------------------------------------------- -** -** Memory to memory move -** -**----------------------------------------------------------- -** -** COPY (bytecount) -** << source_address >> -** << destination_address >> -** -**----------------------------------------------------------- -*/ - -#define SCR_COPY(n) (0xc0000000 | (n)) - -/*----------------------------------------------------------- -** -** Register move and binary operations -** -**----------------------------------------------------------- -** -** SFBR_REG (reg, op, data) reg = SFBR op data -** << 0 >> -** -** REG_SFBR (reg, op, data) SFBR = reg op data -** << 0 >> -** -** REG_REG (reg, op, data) reg = reg op data -** << 0 >> -** -**----------------------------------------------------------- -*/ - -#define SCR_REG_OFS(ofs) ((ofs) << 16ul) - -#define SCR_SFBR_REG(reg,op,data) \ - (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul)) - -#define SCR_REG_SFBR(reg,op,data) \ - (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul)) - -#define SCR_REG_REG(reg,op,data) \ - (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul)) - - -#define SCR_LOAD 0x00000000 -#define SCR_SHL 0x01000000 -#define SCR_OR 0x02000000 -#define SCR_XOR 0x03000000 -#define SCR_AND 0x04000000 -#define SCR_SHR 0x05000000 -#define SCR_ADD 0x06000000 -#define SCR_ADDC 0x07000000 - -/*----------------------------------------------------------- -** -** FROM_REG (reg) reg = SFBR -** << 0 >> -** -** TO_REG (reg) SFBR = reg -** << 0 >> -** -** LOAD_REG (reg, data) reg = <data> -** << 0 >> -** -** LOAD_SFBR(data) SFBR = <data> -** << 0 >> -** -**----------------------------------------------------------- -*/ - -#define SCR_FROM_REG(reg) \ - SCR_REG_SFBR(reg,SCR_OR,0) - -#define SCR_TO_REG(reg) \ - SCR_SFBR_REG(reg,SCR_OR,0) - -#define SCR_LOAD_REG(reg,data) \ - SCR_REG_REG(reg,SCR_LOAD,data) - -#define SCR_LOAD_SFBR(data) \ - (SCR_REG_SFBR (gpreg, SCR_LOAD, data)) - -/*----------------------------------------------------------- -** -** Waiting for Disconnect or Reselect -** -**----------------------------------------------------------- -** -** JUMP [ | IFTRUE/IFFALSE ( ... ) ] -** <<address>> -** -** JUMPR [ | IFTRUE/IFFALSE ( ... ) ] -** <<distance>> -** -** CALL [ | IFTRUE/IFFALSE ( ... ) ] -** <<address>> -** -** CALLR [ | IFTRUE/IFFALSE ( ... ) ] -** <<distance>> -** -** RETURN [ | IFTRUE/IFFALSE ( ... ) ] -** <<dummy>> -** -** INT [ | IFTRUE/IFFALSE ( ... ) ] -** <<ident>> -** -** INT_FLY [ | IFTRUE/IFFALSE ( ... ) ] -** <<ident>> -** -** Conditions: -** WHEN (phase) -** IF (phase) -** CARRY -** DATA (data, mask) -** -**----------------------------------------------------------- -*/ - -#define SCR_JUMP 0x80080000 -#define SCR_JUMPR 0x80880000 -#define SCR_CALL 0x88080000 -#define SCR_CALLR 0x88880000 -#define SCR_RETURN 0x90080000 -#define SCR_INT 0x98080000 -#define SCR_INT_FLY 0x98180000 - -#define IFFALSE(arg) (0x00080000 | (arg)) -#define IFTRUE(arg) (0x00000000 | (arg)) - -#define WHEN(phase) (0x00030000 | (phase)) -#define IF(phase) (0x00020000 | (phase)) - -#define DATA(D) (0x00040000 | ((D) & 0xff)) -#define MASK(D,M) (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff)) - -#define CARRYSET (0x00200000) - -/*----------------------------------------------------------- -** -** SCSI constants. -** -**----------------------------------------------------------- -*/ - -/* -** Messages -*/ - -#define M_COMPLETE (0x00) -#define M_EXTENDED (0x01) -#define M_SAVE_DP (0x02) -#define M_RESTORE_DP (0x03) -#define M_DISCONNECT (0x04) -#define M_ID_ERROR (0x05) -#define M_ABORT (0x06) -#define M_REJECT (0x07) -#define M_NOOP (0x08) -#define M_PARITY (0x09) -#define M_LCOMPLETE (0x0a) -#define M_FCOMPLETE (0x0b) -#define M_RESET (0x0c) -#define M_ABORT_TAG (0x0d) -#define M_CLEAR_QUEUE (0x0e) -#define M_INIT_REC (0x0f) -#define M_REL_REC (0x10) -#define M_TERMINATE (0x11) -#define M_SIMPLE_TAG (0x20) -#define M_HEAD_TAG (0x21) -#define M_ORDERED_TAG (0x22) -#define M_IGN_RESIDUE (0x23) -#define M_IDENTIFY (0x80) - -#define M_X_MODIFY_DP (0x00) -#define M_X_SYNC_REQ (0x01) -#define M_X_WIDE_REQ (0x03) - -/* -** Status -*/ - -#define S_GOOD (0x00) -#define S_CHECK_COND (0x02) -#define S_COND_MET (0x04) -#define S_BUSY (0x08) -#define S_INT (0x10) -#define S_INT_COND_MET (0x14) -#define S_CONFLICT (0x18) -#define S_TERMINATED (0x20) -#define S_QUEUE_FULL (0x28) -#define S_ILLEGAL (0xff) -#define S_SENSE (0x80) - -#endif /*__NCR_REG_H__*/ diff --git a/sys/pci/pci.c b/sys/pci/pci.c deleted file mode 100644 index 6ef71637bf56..000000000000 --- a/sys/pci/pci.c +++ /dev/null @@ -1,778 +0,0 @@ -/************************************************************************** -** -** $Id: pci.c,v 1.8 1994/10/25 23:09:08 se Exp $ -** -** General subroutines for the PCI bus on 80*86 systems. -** pci_configure () -** -** 386bsd / FreeBSD -** -**------------------------------------------------------------------------- -** -** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. -** -** 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. -** 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. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. -** -*************************************************************************** -*/ - -#include <pci.h> -#if NPCI > 0 - -#ifndef __FreeBSD2__ -#if __FreeBSD__ >= 2 -#define __FreeBSD2__ -#endif -#endif - -/*======================================================== -** -** #includes and declarations -** -**======================================================== -*/ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/errno.h> - -#include <vm/vm.h> -#include <vm/vm_param.h> - -#include <i386/isa/isa.h> -#include <i386/isa/isa_device.h> -#include <i386/isa/icu.h> -#include <i386/pci/pcireg.h> - -#ifdef __FreeBSD2__ -#include <sys/devconf.h> - -struct pci_devconf { - struct kern_devconf pdc_kdc; - struct pci_info pdc_pi; -}; -#endif - -/* -** Function prototypes missing in system headers -*/ - -#ifndef __FreeBSD2__ -extern pmap_t pmap_kernel(void); -static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize); - -/* - * Type of the first (asm) part of an interrupt handler. - */ -typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss)); - -/* - * Usual type of the second (C) part of an interrupt handler. Some bogus - * ones need the arg to be the interrupt frame (and not a copy of it, which - * is all that is possible in C). - */ -typedef void inthand2_t __P((int unit)); - -/* -** XXX @FreeBSD2@ -** -** Unfortunately, the mptr argument is _no_ pointer in 2.0 FreeBSD. -** We would prefer a pointer because it enables us to install -** new interrupt handlers at any time. -** (This is just going to be changed ... <se> :) -** In 2.0 FreeBSD later installed interrupt handlers may change -** the xyz_imask, but this would not be recognized by handlers -** which are installed before. -*/ - -static int -register_intr __P((int intr, int device_id, unsigned int flags, - inthand2_t *handler, unsigned int * mptr, int unit)); -extern unsigned intr_mask[ICU_LEN]; - -#endif /* !__FreeBSD2__ */ - -/*======================================================== -** -** Autoconfiguration of pci devices. -** -** This is reverse to the isa configuration. -** (1) find a pci device. -** (2) look for a driver. -** -**======================================================== -*/ - -/*-------------------------------------------------------- -** -** The pci devices can be mapped to any address. -** As default we start at the last gigabyte. -** -**-------------------------------------------------------- -*/ - -#ifndef PCI_PMEM_START -#define PCI_PMEM_START 0xc0000000 -#endif - -static vm_offset_t pci_paddr = PCI_PMEM_START; - -/*-------------------------------------------------------- -** -** The pci device interrupt lines should have been -** assigned by the bios. But if the bios failed to -** to it, we set it. -** -**-------------------------------------------------------- -*/ - -#ifndef PCI_IRQ -#define PCI_IRQ 0 -#endif - -static u_long pci_irq = PCI_IRQ; - -/*--------------------------------------------------------- -** -** pci_configure () -** -** Probe all devices on pci bus and attach them. -** -** May be called more than once. -** Any device is attached only once. -** (Attached devices are remembered in pci_seen.) -** -**--------------------------------------------------------- -*/ - -static void not_supported (pcici_t tag, u_long type); - -static unsigned long pci_seen[NPCI]; - -static int pci_conf_count; - -#ifdef __FreeBSD2__ -static int -pci_externalize (struct proc *, struct kern_devconf *, void *, size_t); - -static int -pci_internalize (struct proc *, struct kern_devconf *, void *, size_t); - -#endif /* __FreeBSD2__ */ - -void pci_configure() -{ - u_char device,last_device; - u_short bus; - pcici_t tag; - pcidi_t type; - u_long data; - int unit; - int pci_mechanism; - int pciint; - int irq; - char* name=0; - vm_offset_t old_addr=pci_paddr; - - struct pci_driver *drp=0; - struct pci_device *dvp; - -#ifdef __FreeBSD2__ - struct pci_devconf *pdcp; -#endif - - /* - ** check pci bus present - */ - - pci_mechanism = pci_conf_mode (); - if (!pci_mechanism) return; - last_device = pci_mechanism==1 ? 31 : 15; - - /* - ** hello world .. - */ - - - for (bus=0;bus<NPCI;bus++) { -#ifndef PCI_QUIET - printf ("pci%d: scanning device 0..%d, mechanism=%d.\n", - bus, last_device, pci_mechanism); -#endif - for (device=0; device<=last_device; device ++) { - - if (pci_seen[bus] & (1ul << device)) - continue; - - tag = pcitag (bus, device, 0); - type = pci_conf_read (tag, PCI_ID_REG); - - if ((!type) || (type==0xfffffffful)) continue; - - /* - ** lookup device in ioconfiguration: - */ - - for (dvp = pci_devtab; dvp->pd_name; dvp++) { - drp = dvp->pd_driver; - if (!drp) - continue; - if ((name=(*drp->probe)(tag, type))) - break; - }; - - if (!dvp->pd_name) { -#ifndef PCI_QUIET - if (pci_conf_count) - continue; - printf("pci%d:%d: ", bus, device); - not_supported (tag, type); -#endif - continue; - }; - - pci_seen[bus] |= (1ul << device); - /* - ** Get and increment the unit. - */ - - unit = (*drp->count)++; - - /* - ** ignore device ? - */ - - if (!*name) continue; - - /* - ** Announce this device - */ - - printf ("%s%d <%s>", dvp->pd_name, unit, name); - - /* - ** Get the int pin number (pci interrupt number a-d) - ** from the pci configuration space. - */ - - data = pci_conf_read (tag, PCI_INTERRUPT_REG); - pciint = PCI_INTERRUPT_PIN_EXTRACT(data); - - if (pciint) { - - printf (" int %c", 0x60+pciint); - - /* - ** If the interrupt line register is not set, - ** set it now from PCI_IRQ. - */ - - if (!(PCI_INTERRUPT_LINE_EXTRACT(data))) { - - irq = pci_irq & 0x0f; - pci_irq >>= 4; - - data = PCI_INTERRUPT_LINE_INSERT(data, irq); - printf (" (config)"); - pci_conf_write (tag, PCI_INTERRUPT_REG, data); - }; - - irq = PCI_INTERRUPT_LINE_EXTRACT(data); - - /* - ** If it's zero, the isa irq number is unknown, - ** and we cannot bind the pci interrupt to isa. - */ - - if (irq) - printf (" irq %d", irq); - else - printf (" not bound"); - }; - - /* - ** enable memory access - */ - - data = (pci_conf_read (tag, PCI_COMMAND_STATUS_REG) - & 0xffff) | PCI_COMMAND_MEM_ENABLE; - - pci_conf_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data); - - /* - ** show pci slot. - */ - - printf (" on pci%d:%d\n", bus, device); - -#ifdef __FreeBSD2__ - - /* - ** Allocate a devconf structure - */ - - pdcp = (struct pci_devconf *) - malloc (sizeof (struct pci_devconf),M_DEVBUF,M_WAITOK); - - /* - ** Fill in. - ** - ** Sorry, this is not yet complete. - ** We should, and eventually will, set the - ** parent pointer to a pci bus devconf structure, - ** and arrange to set the state field dynamically. - ** - ** But I'll go to vacation today, and after all, - ** wasn't there a new feature freeze on Oct 1.? - */ - - pdcp -> pdc_pi.pi_bus = bus; - pdcp -> pdc_pi.pi_device = device; - - pdcp -> pdc_kdc.kdc_name = dvp->pd_name; - pdcp -> pdc_kdc.kdc_unit = unit; - - pdcp -> pdc_kdc.kdc_md.mddc_devtype = MDDT_PCI; - - pdcp -> pdc_kdc.kdc_externalize = pci_externalize; - pdcp -> pdc_kdc.kdc_internalize = pci_internalize; - - pdcp -> pdc_kdc.kdc_datalen = PCI_EXTERNAL_LEN; - pdcp -> pdc_kdc.kdc_parentdata = &pdcp->pdc_pi; - pdcp -> pdc_kdc.kdc_state = DC_UNKNOWN; - pdcp -> pdc_kdc.kdc_description = name; - - /* - ** And register this device - */ - - dev_attach (&pdcp->pdc_kdc); - -#endif /* __FreeBSD2__ */ - - - /* - ** attach device - ** may produce additional log messages, - ** i.e. when installing subdevices. - */ - - (*drp->attach) (tag, unit); - }; - }; - -#ifndef PCI_QUIET - if (pci_paddr != old_addr) - printf ("pci uses physical addresses from 0x%lx to 0x%lx\n", - (u_long)PCI_PMEM_START, (u_long)pci_paddr); -#endif - pci_conf_count++; -} - -/*----------------------------------------------------------------------- -** -** Map device into port space. -** -** PCI-Specification: 6.2.5.1: address maps -** -**----------------------------------------------------------------------- -*/ - -int pci_map_port (pcici_t tag, u_long reg, u_short* pa) -{ - /* - ** @MAPIO@ not yet implemented. - */ - printf ("pci_map_port failed: not yet implemented\n"); - return (0); -} - -/*----------------------------------------------------------------------- -** -** Map device into virtual and physical space -** -** PCI-Specification: 6.2.5.1: address maps -** -**----------------------------------------------------------------------- -*/ - -int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa) -{ - u_long data; - vm_size_t vsize; - vm_offset_t vaddr; - - /* - ** sanity check - */ - - if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) { - printf ("pci_map_mem failed: bad register=0x%x\n", - (unsigned)reg); - return (0); - }; - - /* - ** get size and type of memory - ** - ** type is in the lowest four bits. - ** If device requires 2^n bytes, the next - ** n-4 bits are read as 0. - */ - - pci_conf_write (tag, reg, 0xfffffffful); - data = pci_conf_read (tag, reg); - - switch (data & 0x0f) { - - case PCI_MAP_MEMORY_TYPE_32BIT: /* 32 bit non cachable */ - break; - - default: /* unknown */ - printf ("pci_map_mem failed: bad memory type=0x%x\n", - (unsigned) data); - return (0); - }; - - /* - ** mask out the type, - ** and round up to a page size - */ - - vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK)); - - if (!vsize) return (0); - - /* - ** align physical address to virtual size - */ - - if ((data = pci_paddr % vsize)) - pci_paddr += vsize - data; - - vaddr = (vm_offset_t) pmap_mapdev (pci_paddr, vsize); - - - if (!vaddr) return (0); - -#ifndef PCI_QUIET - /* - ** display values. - */ - - printf ("\treg%d: virtual=0x%lx physical=0x%lx\n", - (unsigned) reg, (u_long)vaddr, (u_long)pci_paddr); -#endif - - /* - ** return them to the driver - */ - - *va = vaddr; - *pa = pci_paddr; - - /* - ** set device address - */ - - pci_conf_write (tag, reg, pci_paddr); - - /* - ** and don't forget to increment pci_paddr - */ - - pci_paddr += vsize; - - return (1); -} - -/*------------------------------------------------------------ -** -** Interface functions for the devconf module. -** -**------------------------------------------------------------ -*/ - -static int -pci_externalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t l) -{ - struct pci_externalize_buffer buffer; - struct pci_info * pip = kdcp->kdc_parentdata; - pcici_t tag; - int i; - - if (l < sizeof buffer) { - return ENOMEM; - }; - - tag = pcitag (pip->pi_bus, pip->pi_device, 0); - - buffer.peb_pci_info = *pip; - - for (i=0; i<PCI_EXT_CONF_LEN; i++) { - buffer.peb_config[i] = pci_conf_read (tag, i*4); - }; - - return copyout(&buffer, u, sizeof buffer); -} - - -static int -pci_internalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t s) -{ - return EOPNOTSUPP; -} - -/*----------------------------------------------------------------------- -** -** Map pci interrupts to isa interrupts. -** -**----------------------------------------------------------------------- -*/ - -static unsigned int pci_int_mask [16]; - -int pci_map_int (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr) -{ - int irq; - unsigned mask; - - irq = PCI_INTERRUPT_LINE_EXTRACT( - pci_conf_read (tag, PCI_INTERRUPT_REG)); - - if (irq >= 16 || irq <= 0) { - printf ("pci_map_int failed: no int line set.\n"); - return (0); - } - - mask = 1ul << irq; - - if (!maskptr) - maskptr = &pci_int_mask[irq]; - - INTRMASK (*maskptr, mask); - - register_intr( - irq, /* isa irq */ - 0, /* deviced?? */ - 0, /* flags? */ - (inthand2_t*) func, /* handler */ - maskptr, /* mask pointer */ - (int) arg); /* handler arg */ - -#ifdef __FreeBSD2__ - /* - ** XXX See comment at beginning of file. - ** - ** Have to update all the interrupt masks ... Grrrrr!!! - */ - { - unsigned * mp = &intr_mask[0]; - /* - ** update the isa interrupt masks. - */ - for (mp=&intr_mask[0]; mp<&intr_mask[ICU_LEN]; mp++) - if (*mp & *maskptr) - *mp |= mask; - /* - ** update the pci interrupt masks. - */ - for (mp=&pci_int_mask[0]; mp<&pci_int_mask[16]; mp++) - if (*mp & *maskptr) - *mp |= mask; - }; -#endif - - INTREN (mask); - - return (1); -} - -/*----------------------------------------------------------- -** -** Display of unknown devices. -** -**----------------------------------------------------------- -*/ -struct vt { - u_short ident; - char* name; -}; - -static struct vt VendorTable[] = { - {0x1002, "ATI TECHNOLOGIES INC"}, - {0x1011, "DIGITAL EQUIPMENT CORPORATION"}, - {0x101A, "NCR"}, - {0x102B, "MATROX"}, - {0x1045, "OPTI"}, - {0x5333, "S3 INC."}, - {0x8086, "INTEL CORPORATION"}, - {0,0} -}; - -static const char *const majclasses[] = { - "old", "storage", "network", "display", - "multimedia", "memory", "bridge" -}; - -void not_supported (pcici_t tag, u_long type) -{ - u_char reg; - u_long data; - struct vt * vp; - - /* - ** lookup the names. - */ - - for (vp=VendorTable; vp->ident; vp++) - if (vp->ident == (type & 0xffff)) - break; - - /* - ** and display them. - */ - - if (vp->ident) printf (vp->name); - else printf ("vendor=0x%lx", type & 0xffff); - - printf (", device=0x%lx", type >> 16); - - data = (pci_conf_read(tag, PCI_CLASS_REG) >> 24) & 0xff; - if (data < sizeof(majclasses) / sizeof(majclasses[0])) - printf(", class=%s", majclasses[data]); - - printf (" [not supported]\n"); - - for (reg=PCI_MAP_REG_START; reg<PCI_MAP_REG_END; reg+=4) { - data = pci_conf_read (tag, reg); - if (!data) continue; - switch (data&7) { - - case 1: - case 5: - printf (" map(%x): io(%lx)\n", - reg, data & ~3); - break; - case 0: - printf (" map(%x): mem32(%lx)\n", - reg, data & ~7); - break; - case 2: - printf (" map(%x): mem20(%lx)\n", - reg, data & ~7); - break; - case 4: - printf (" map(%x): mem64(%lx)\n", - reg, data & ~7); - break; - } - } -} - -#ifndef __FreeBSD2__ -/*----------------------------------------------------------- -** -** Mapping of physical to virtual memory -** -**----------------------------------------------------------- -*/ - -extern vm_map_t kernel_map; - -static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize) -{ - vm_offset_t vaddr,value; - u_long result; - - vaddr = vm_map_min (kernel_map); - - result = vm_map_find (kernel_map, (void*)0, (vm_offset_t) 0, - &vaddr, vsize, TRUE); - - if (result != KERN_SUCCESS) { - printf (" vm_map_find failed(%d)\n", result); - return (0); - }; - - /* - ** map physical - */ - - value = vaddr; - while (vsize >= NBPG) { - pmap_enter (pmap_kernel(), vaddr, paddr, - VM_PROT_READ|VM_PROT_WRITE, TRUE); - vaddr += NBPG; - paddr += NBPG; - vsize -= NBPG; - }; - return (value); -} - -/*------------------------------------------------------------ -** -** Emulate the register_intr() function of FreeBSD 2.0 -** -** requires a patch: -** FreeBSD 2.0: "/sys/i386/isa/vector.s" -** 386bsd0.1: "/sys/i386/isa/icu.s" -** 386bsd1.0: Please ask Jesus Monroy Jr. -** -**------------------------------------------------------------ -*/ - -#include <machine/segments.h> - -int pci_int_unit [16]; -inthand2_t* (pci_int_hdlr [16]); -unsigned int * pci_int_mptr [16]; -unsigned int pci_int_count[16]; - -extern void - Vpci3(), Vpci4(), Vpci5(), Vpci6(), Vpci7(), Vpci8(), Vpci9(), - Vpci10(), Vpci11(), Vpci12(), Vpci13(), Vpci14(), Vpci15(); - -static inthand_t* pci_int_glue[16] = { - 0, 0, 0, Vpci3, Vpci4, Vpci5, Vpci6, Vpci7, Vpci8, - Vpci9, Vpci10, Vpci11, Vpci12, Vpci13, Vpci14, Vpci15 }; - -static int -register_intr __P((int intr, int device_id, unsigned int flags, - inthand2_t *handler, unsigned int* mptr, int unit)) -{ - if (intr >= 16 || intr <= 2) - return (EINVAL); - if (pci_int_hdlr [intr]) - return (EBUSY); - - pci_int_hdlr [intr] = handler; - pci_int_unit [intr] = unit; - pci_int_mptr [intr] = mptr; - - setidt(NRSVIDT + intr, pci_int_glue[intr], SDT_SYS386IGT, SEL_KPL); - return (0); -} -#endif /* __FreeBSD2__ */ -#endif /* NPCI */ diff --git a/sys/pci/pcireg.h b/sys/pci/pcireg.h deleted file mode 100644 index dd1f1ccf3280..000000000000 --- a/sys/pci/pcireg.h +++ /dev/null @@ -1,423 +0,0 @@ -/************************************************************************** -** -** $Id: pcireg.h,v 1.1 1994/10/12 02:25:03 se Exp $ -** -** Declarations for pci bus drivers. -** -** 386bsd / FreeBSD -** -**------------------------------------------------------------------------- -** -** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. -** -** 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. -** 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. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. -** -*************************************************************************** -*/ - -#ifndef __PCI_REG_H__ -#define __PCI_REG_H__ - -/*----------------------------------------------------------------- -** -** main pci initialization function. -** called at boot time from autoconf.c -** -**----------------------------------------------------------------- -*/ - -void pci_configure (void); - -/*----------------------------------------------------------------- -** -** The pci configuration id describes a pci device on the bus. -** It is constructed from: bus, device & function numbers. -** -**----------------------------------------------------------------- -*/ - -typedef union { - u_long cfg1; - struct { - u_char enable; - u_char forward; - u_short port; - } cfg2; - } pcici_t; - -/*----------------------------------------------------------------- -** -** Each pci device has an unique device id. -** It is used to find a matching driver. -** -**----------------------------------------------------------------- -*/ - -typedef u_long pcidi_t; - -/*----------------------------------------------------------------- -** -** The pci driver structure. -** -** probe: Checks if the driver can support a device -** with this type. The tag may be used to get -** more info with pci_read_conf(). See below. -** It returns a string with the devices name, -** or a NULL pointer, if the driver cannot -** support this device. -** -** attach: Allocate a control structure and prepare -** it. This function may use the pci mapping -** functions. See below. -** (configuration id) or type. -** -** count: A pointer to a unit counter. -** It's used by the pci configurator to -** allocate unit numbers. -** -**----------------------------------------------------------------- -*/ - -struct pci_driver { - char* (*probe ) (pcici_t tag, pcidi_t type); - void (*attach) (pcici_t tag, int unit); - u_long *count; -}; - -/*----------------------------------------------------------------- -** -** The pci-devconf interface. -** -**----------------------------------------------------------------- -*/ - -struct pci_info { - u_short pi_bus; - u_short pi_device; -}; - -#define PCI_EXT_CONF_LEN (16) -#define PCI_EXTERNAL_LEN (sizeof(struct pci_externalize_buffer)) - -struct pci_externalize_buffer { - struct pci_info peb_pci_info; - u_long peb_config[PCI_EXT_CONF_LEN]; -}; - - -/*----------------------------------------------------------------- -** -** Per device structure. -** -** An array of this structure should be created by the -** config utility and live in "ioconf.c". -** -** At the moment it's created by hand and lives in -** pci_config.c -** -** pd_driver: -** a pointer to the driver structure. -** -** pd_name: -** the name of the devices which are supported -** by this driver for kernel messages. -** -** pd_flags: -** for further study. -** -**----------------------------------------------------------------- -*/ - -struct pci_device { - struct - pci_driver* pd_driver; - const char * pd_name; - int pd_flags; -}; - -/*----------------------------------------------------------------- -** -** This table should be generated in file "ioconf.c" -** by the config program. -** It is used at boot time by the configuration function -** pci_configure() -** -**----------------------------------------------------------------- -*/ - -extern struct pci_device pci_devtab[]; - -/*----------------------------------------------------------------- -** -** Map a pci device to physical and virtual memory. -** -** The va and pa addresses are "in/out" parameters. -** If they are 0 on entry, the function assigns an address. -** -** Entry selects the register in the pci configuration -** space, which supplies the size of the region, and -** receives the physical address. -** -** If there is any error, a message is written, and -** the function returns with zero. -** Else it returns with a value different to zero. -** -**----------------------------------------------------------------- -*/ - -int pci_map_mem (pcici_t tag, u_long entry, u_long * va, u_long * pa); - -/*----------------------------------------------------------------- -** -** Map a pci device to an io port area. -** -** *pa is an "in/out" parameter. -** If it's 0 on entry, the function assigns an port number.. -** -** Entry selects the register in the pci configuration -** space, which supplies the size of the region, and -** receives the port number. -** -** If there is any error, a message is written, and -** the function returns with zero. -** Else it returns with a value different to zero. -** -**----------------------------------------------------------------- -*/ - -int pci_map_port(pcici_t tag, u_long entry, u_short * pa); - -/*----------------------------------------------------------------- -** -** Map a pci interrupt to an isa irq line, -** and enable the interrupt. -** -** func is the interrupt handler, arg is the argument -** to this function. -** -** The maskptr argument should be &bio_imask, -** &net_imask etc. or NULL. -** -** If there is any error, a message is written, and -** the function returns with zero. -** Else it returns with a value different to zero. -** -** A word of caution for FreeBSD 2.0: -** -** We use the register_intr() function. -** -** The interrupt line of the selected device is included -** into the supplied mask: after the corresponding splXXX -** this drivers interrupts are blocked. -** -** But in the interrupt handlers startup code ONLY -** the interrupt of the driver is blocked, and NOT -** all interrupts of the spl group. -** -** It may be required to additional block the group -** interrupts by splXXX() inside the interrupt handler. -** -** In pre 2.0 kernels we emulate the register_intr -** function. The emulating function blocks all interrupts -** of the group in the interrupt handler prefix code. -** -**----------------------------------------------------------------- -*/ - -int pci_map_int (pcici_t tag, int (*func)(), void* arg, unsigned * maskptr); - -/*----------------------------------------------------------------- -** -** The following functions are provided by the pci bios. -** They are used only by the pci configuration. -** -** pci_conf_mode(): -** Probes for a pci system. -** Returns 1 or 2 for pci configuration mechanism. -** Returns 0 if no pci system. -** -** pcitag(): -** Gets a handle for accessing the pci configuration -** space. -** This handle is given to the mapping functions (see -** above) or to the read/write functions. -** -** pci_conf_read(): -** Read a long word from the pci configuration space. -** Requires a tag (from pcitag) and the register -** number (should be a long word alligned one). -** -** pci_conf_write(): -** Writes a long word to the pci configuration space. -** Requires a tag (from pcitag), the register number -** (should be a long word alligned one), and a value. -** -**----------------------------------------------------------------- -*/ - -int pci_conf_mode (void); - -pcici_t pcitag (unsigned char bus, - unsigned char device, - unsigned char func); - -u_long pci_conf_read (pcici_t tag, u_long reg ); -void pci_conf_write (pcici_t tag, u_long reg, u_long data); - - -/*------------------------------------------------------------------ -** -** Names for PCI configuration space registers. -** -** Copyright (c) 1994 Charles Hannum. All rights reserved. -** -**------------------------------------------------------------------ -*/ - -/* - * Device identification register; contains a vendor ID and a device ID. - * We have little need to distinguish the two parts. - */ -#define PCI_ID_REG 0x00 - -/* - * Command and status register. - */ -#define PCI_COMMAND_STATUS_REG 0x04 - -#define PCI_COMMAND_IO_ENABLE 0x00000001 -#define PCI_COMMAND_MEM_ENABLE 0x00000002 -#define PCI_COMMAND_MASTER_ENABLE 0x00000004 -#define PCI_COMMAND_SPECIAL_ENABLE 0x00000008 -#define PCI_COMMAND_INVALIDATE_ENABLE 0x00000010 -#define PCI_COMMAND_PALETTE_ENABLE 0x00000020 -#define PCI_COMMAND_PARITY_ENABLE 0x00000040 -#define PCI_COMMAND_STEPPING_ENABLE 0x00000080 -#define PCI_COMMAND_SERR_ENABLE 0x00000100 -#define PCI_COMMAND_BACKTOBACK_ENABLE 0x00000200 - -#define PCI_STATUS_BACKTOBACK_OKAY 0x00800000 -#define PCI_STATUS_PARITY_ERROR 0x01000000 -#define PCI_STATUS_DEVSEL_FAST 0x00000000 -#define PCI_STATUS_DEVSEL_MEDIUM 0x02000000 -#define PCI_STATUS_DEVSEL_SLOW 0x04000000 -#define PCI_STATUS_DEVSEL_MASK 0x06000000 -#define PCI_STATUS_TARGET_TARGET_ABORT 0x08000000 -#define PCI_STATUS_MASTER_TARGET_ABORT 0x10000000 -#define PCI_STATUS_MASTER_ABORT 0x20000000 -#define PCI_STATUS_SPECIAL_ERROR 0x40000000 -#define PCI_STATUS_PARITY_DETECT 0x80000000 - -/* - * Class register; defines basic type of device. - */ -#define PCI_CLASS_REG 0x08 - -#define PCI_CLASS_MASK 0xff000000 -#define PCI_SUBCLASS_MASK 0x00ff0000 - -/* base classes */ -#define PCI_CLASS_PREHISTORIC 0x00000000 -#define PCI_CLASS_MASS_STORAGE 0x01000000 -#define PCI_CLASS_NETWORK 0x02000000 -#define PCI_CLASS_DISPLAY 0x03000000 -#define PCI_CLASS_MULTIMEDIA 0x04000000 -#define PCI_CLASS_MEMORY 0x05000000 -#define PCI_CLASS_BRIDGE 0x06000000 -#define PCI_CLASS_UNDEFINED 0xff000000 - -/* 0x00 prehistoric subclasses */ -#define PCI_SUBCLASS_PREHISTORIC_MISC 0x00000000 -#define PCI_SUBCLASS_PREHISTORIC_VGA 0x00010000 - -/* 0x01 mass storage subclasses */ -#define PCI_SUBCLASS_MASS_STORAGE_SCSI 0x00000000 -#define PCI_SUBCLASS_MASS_STORAGE_IDE 0x00010000 -#define PCI_SUBCLASS_MASS_STORAGE_FLOPPY 0x00020000 -#define PCI_SUBCLASS_MASS_STORAGE_IPI 0x00030000 -#define PCI_SUBCLASS_MASS_STORAGE_MISC 0x00800000 - -/* 0x02 network subclasses */ -#define PCI_SUBCLASS_NETWORK_ETHERNET 0x00000000 -#define PCI_SUBCLASS_NETWORK_TOKENRING 0x00010000 -#define PCI_SUBCLASS_NETWORK_FDDI 0x00020000 -#define PCI_SUBCLASS_NETWORK_MISC 0x00800000 - -/* 0x03 display subclasses */ -#define PCI_SUBCLASS_DISPLAY_VGA 0x00000000 -#define PCI_SUBCLASS_DISPLAY_XGA 0x00010000 -#define PCI_SUBCLASS_DISPLAY_MISC 0x00800000 - -/* 0x04 multimedia subclasses */ -#define PCI_SUBCLASS_MULTIMEDIA_VIDEO 0x00000000 -#define PCI_SUBCLASS_MULTIMEDIA_AUDIO 0x00010000 -#define PCI_SUBCLASS_MULTIMEDIA_MISC 0x00800000 - -/* 0x05 memory subclasses */ -#define PCI_SUBCLASS_MEMORY_RAM 0x00000000 -#define PCI_SUBCLASS_MEMORY_FLASH 0x00010000 -#define PCI_SUBCLASS_MEMORY_MISC 0x00800000 - -/* 0x06 bridge subclasses */ -#define PCI_SUBCLASS_BRIDGE_HOST 0x00000000 -#define PCI_SUBCLASS_BRIDGE_ISA 0x00010000 -#define PCI_SUBCLASS_BRIDGE_EISA 0x00020000 -#define PCI_SUBCLASS_BRIDGE_MC 0x00030000 -#define PCI_SUBCLASS_BRIDGE_PCI 0x00040000 -#define PCI_SUBCLASS_BRIDGE_PCMCIA 0x00050000 -#define PCI_SUBCLASS_BRIDGE_MISC 0x00800000 - -/* - * Mapping registers - */ -#define PCI_MAP_REG_START 0x10 -#define PCI_MAP_REG_END 0x28 - -#define PCI_MAP_MEMORY 0x00000000 -#define PCI_MAP_IO 0x00000001 - -#define PCI_MAP_MEMORY_TYPE_32BIT 0x00000000 -#define PCI_MAP_MEMORY_TYPE_32BIT_1M 0x00000002 -#define PCI_MAP_MEMORY_TYPE_64BIT 0x00000004 -#define PCI_MAP_MEMORY_TYPE_MASK 0x00000006 -#define PCI_MAP_MEMORY_CACHABLE 0x00000008 -#define PCI_MAP_MEMORY_ADDRESS_MASK 0xfffffff0 - -/* - * Interrupt configuration register - */ -#define PCI_INTERRUPT_REG 0x3c - -#define PCI_INTERRUPT_PIN_MASK 0x0000ff00 -#define PCI_INTERRUPT_PIN_EXTRACT(x) ((((x) & PCI_INTERRUPT_PIN_MASK) >> 8) & 0xff) -#define PCI_INTERRUPT_PIN_NONE 0x00 -#define PCI_INTERRUPT_PIN_A 0x01 -#define PCI_INTERRUPT_PIN_B 0x02 -#define PCI_INTERRUPT_PIN_C 0x03 -#define PCI_INTERRUPT_PIN_D 0x04 - -#define PCI_INTERRUPT_LINE_MASK 0x000000ff -#define PCI_INTERRUPT_LINE_EXTRACT(x) ((((x) & PCI_INTERRUPT_LINE_MASK) >> 0) & 0xff) -#define PCI_INTERRUPT_LINE_INSERT(x,v) (((x) & ~PCI_INTERRUPT_LINE_MASK) | ((v) << 0)) - -#endif /* __PCI_REG_H__ */ diff --git a/sys/pci/pcisupport.c b/sys/pci/pcisupport.c deleted file mode 100644 index 6b8a9fec38f6..000000000000 --- a/sys/pci/pcisupport.c +++ /dev/null @@ -1,394 +0,0 @@ -/************************************************************************** -** -** $Id: pcisupport.c,v 1.4 1994/10/17 21:11:31 phk Exp $ -** -** Device driver for INTEL PCI chipsets. -** -** 386bsd / FreeBSD -** -**------------------------------------------------------------------------- -** -** Written for 386bsd and FreeBSD by -** wolf@dentaro.gun.de Wolfgang Stanglmeier -** se@mi.Uni-Koeln.de Stefan Esser -** -**------------------------------------------------------------------------- -** -** Copyright (c) 1994 Stefan Esser. All rights reserved. -** -** 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. -** 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. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. -** -*************************************************************************** -*/ - - -/*========================================================== -** -** Include files -** -**========================================================== -*/ - -#include <sys/types.h> - -#include <i386/pci/pcireg.h> - -extern void printf(); - -/*--------------------------------------------------------- -** -** Intel chipsets for 486 / Pentium processor -** -**--------------------------------------------------------- -*/ - -static char* chipset_probe (pcici_t tag, pcidi_t type); -static void chipset_attach(pcici_t tag, int unit); -static u_long chipset_count; - -struct pci_driver chipset_device = { - chipset_probe, - chipset_attach, - &chipset_count -}; - -static char confread(pcici_t config_id, int port); - -struct condmsg { - unsigned char port; - unsigned char mask; - unsigned char value; - char flags; - char *text; -}; - -#define M_EQ 0 /* mask and return true if equal */ -#define M_NE 1 /* mask and return true if not equal */ -#define TRUE 2 /* don't read config, always true */ - -static char* chipset_probe (pcici_t tag, pcidi_t type) -{ - switch (type) { - case 0x04848086: - return ("intel 82378IB pci-isa bridge"); - case 0x04838086: - return ("intel 82424ZX cache dram controller"); - case 0x04828086: - return ("intel 82375EB pci-eisa bridge"); - case 0x04a38086: - return ("intel 82434LX pci cache memory controller"); - }; - return ((char*)0); -} - -struct condmsg conf82424zx[] = -{ - { 0x00, 0x00, 0x00, TRUE, "\tCPU: " }, - { 0x50, 0xe0, 0x00, M_EQ, "486DX" }, - { 0x50, 0xe0, 0x20, M_EQ, "486SX" }, - { 0x50, 0xe0, 0x40, M_EQ, "486DX2 or 486DX4" }, - { 0x50, 0xe0, 0x80, M_EQ, "Overdrive (writeback)" }, - - { 0x00, 0x00, 0x00, TRUE, ", bus=" }, - { 0x50, 0x03, 0x00, M_EQ, "25MHz" }, - { 0x50, 0x03, 0x01, M_EQ, "33MHz" }, - { 0x53, 0x01, 0x01, TRUE, ", CPU->Memory posting "}, - { 0x53, 0x01, 0x00, M_EQ, "OFF" }, - { 0x53, 0x01, 0x01, M_EQ, "ON" }, - - { 0x56, 0x30, 0x00, M_NE, "\n\tWarning:" }, - { 0x56, 0x20, 0x00, M_NE, " NO cache parity!" }, - { 0x56, 0x10, 0x00, M_NE, " NO DRAM parity!" }, - { 0x55, 0x04, 0x04, M_EQ, "\n\tWarning: refresh OFF! " }, - - { 0x00, 0x00, 0x00, TRUE, "\n\tCache: " }, - { 0x52, 0x01, 0x00, M_EQ, "None" }, - { 0x52, 0xc1, 0x01, M_EQ, "64KB" }, - { 0x52, 0xc1, 0x41, M_EQ, "128KB" }, - { 0x52, 0xc1, 0x81, M_EQ, "256KB" }, - { 0x52, 0xc1, 0xc1, M_EQ, "512KB" }, - { 0x52, 0x03, 0x01, M_EQ, " writethrough" }, - { 0x52, 0x03, 0x03, M_EQ, " writeback" }, - - { 0x52, 0x01, 0x01, M_EQ, ", cache clocks=" }, - { 0x52, 0x05, 0x01, M_EQ, "3-1-1-1" }, - { 0x52, 0x05, 0x05, M_EQ, "2-1-1-1" }, - - { 0x00, 0x00, 0x00, TRUE, "\n\tDRAM:" }, - { 0x55, 0x43, 0x00, M_NE, " page mode" }, - { 0x55, 0x02, 0x02, M_EQ, " code fetch" }, - { 0x55, 0x43, 0x43, M_EQ, "," }, - { 0x55, 0x43, 0x42, M_EQ, " and" }, - { 0x55, 0x40, 0x40, M_EQ, " read" }, - { 0x55, 0x03, 0x03, M_EQ, " and" }, - { 0x55, 0x43, 0x41, M_EQ, " and" }, - { 0x55, 0x01, 0x01, M_EQ, " write" }, - { 0x55, 0x43, 0x00, M_NE, "," }, - - { 0x00, 0x00, 0x00, TRUE, " memory clocks=" }, - { 0x55, 0x20, 0x00, M_EQ, "X-2-2-2" }, - { 0x55, 0x20, 0x20, M_EQ, "X-1-2-1" }, - - { 0x00, 0x00, 0x00, TRUE, "\n\tCPU->PCI: posting " }, - { 0x53, 0x02, 0x00, M_NE, "ON" }, - { 0x53, 0x02, 0x00, M_EQ, "OFF" }, - { 0x00, 0x00, 0x00, TRUE, ", burst mode " }, - { 0x54, 0x02, 0x00, M_NE, "ON" }, - { 0x54, 0x02, 0x00, M_EQ, "OFF" }, - { 0x00, 0x00, 0x00, TRUE, "\n\tPCI->Memory: posting " }, - { 0x54, 0x01, 0x00, M_NE, "ON" }, - { 0x54, 0x01, 0x00, M_EQ, "OFF" }, - - { 0x00, 0x00, 0x00, TRUE, "\n" }, - -/* end marker */ - { 0 } -}; - -struct condmsg conf82434lx[] = -{ - { 0x00, 0x00, 0x00, TRUE, "\tCPU: " }, - { 0x50, 0xe3, 0x82, M_EQ, "Pentium, 60MHz" }, - { 0x50, 0xe3, 0x83, M_EQ, "Pentium, 66MHz" }, - { 0x50, 0xe3, 0xa2, M_EQ, "Pentium, 90MHz" }, - { 0x50, 0xe3, 0xa3, M_EQ, "Pentium, 100MHz" }, - { 0x50, 0xc2, 0x82, M_NE, "(unknown)" }, - { 0x50, 0x04, 0x00, M_EQ, " (primary cache OFF)" }, - - { 0x53, 0x01, 0x01, TRUE, ", CPU->Memory posting "}, - { 0x53, 0x01, 0x01, M_NE, "OFF" }, - { 0x53, 0x01, 0x01, M_EQ, "ON" }, - - { 0x53, 0x04, 0x00, M_NE, ", read around write"}, - - { 0x71, 0xc0, 0x00, M_NE, "\n\tWarning: NO cache parity!" }, - { 0x57, 0x20, 0x00, M_NE, "\n\tWarning: NO DRAM parity!" }, - { 0x55, 0x01, 0x01, M_EQ, "\n\tWarning: refresh OFF! " }, - - { 0x00, 0x00, 0x00, TRUE, "\n\tCache: " }, - { 0x52, 0x01, 0x00, M_EQ, "None" }, - { 0x52, 0x81, 0x01, M_EQ, "" }, - { 0x52, 0xc1, 0x81, M_EQ, "256KB" }, - { 0x52, 0xc1, 0xc1, M_EQ, "512KB" }, - { 0x52, 0x03, 0x01, M_EQ, " writethrough" }, - { 0x52, 0x03, 0x03, M_EQ, " writeback" }, - - { 0x52, 0x01, 0x01, M_EQ, ", cache clocks=" }, - { 0x52, 0x20, 0x00, M_EQ, "3-2-2-2/4-2-2-2" }, - { 0x52, 0x20, 0x00, M_NE, "3-1-1-1" }, - - { 0x00, 0x00, 0x00, TRUE, "\n\tDRAM:" }, - { 0x57, 0x10, 0x00, M_EQ, " page mode" }, - - { 0x00, 0x00, 0x00, TRUE, " memory clocks=" }, - { 0x57, 0xc0, 0x00, M_EQ, "X-4-4-4 (70ns)" }, - { 0x57, 0xc0, 0x40, M_EQ, "X-4-4-4/X-3-3-3 (60ns)" }, - { 0x57, 0xc0, 0x80, M_EQ, "???" }, - { 0x57, 0xc0, 0xc0, M_EQ, "X-3-3-3 (50ns)" }, - - { 0x00, 0x00, 0x00, TRUE, "\n\tCPU->PCI: posting " }, - { 0x53, 0x02, 0x02, M_EQ, "ON" }, - { 0x53, 0x02, 0x00, M_EQ, "OFF" }, - { 0x00, 0x00, 0x00, TRUE, ", burst mode " }, - { 0x54, 0x02, 0x00, M_NE, "ON" }, - { 0x54, 0x02, 0x00, M_EQ, "OFF" }, - { 0x54, 0x04, 0x00, TRUE, ", PCI clocks=" }, - { 0x54, 0x04, 0x00, M_EQ, "2-2-2-2" }, - { 0x54, 0x04, 0x00, M_NE, "2-1-1-1" }, - { 0x00, 0x00, 0x00, TRUE, "\n\tPCI->Memory: posting " }, - { 0x54, 0x01, 0x00, M_NE, "ON" }, - { 0x54, 0x01, 0x00, M_EQ, "OFF" }, - - { 0x00, 0x00, 0x00, TRUE, "\n" }, - -/* end marker */ - { 0 } -}; - -static char confread (pcici_t config_id, int port) -{ - unsigned long portw = port & ~3; - unsigned long ports = (port - portw) << 3; - - unsigned long l = pci_conf_read (config_id, portw); - return (l >> ports); -} - -static void writeconfig(pcici_t config_id, struct condmsg *tbl) -{ - while (tbl->text) { - int cond = 0; - if (tbl->flags == TRUE) { - cond = 1; - } else { - unsigned char v = (unsigned char) confread(config_id, tbl->port); - switch (tbl->flags) { - case M_EQ: - if ((v & tbl->mask) == tbl->value) cond = 1; - break; - case M_NE: - if ((v & tbl->mask) != tbl->value) cond = 1; - break; - } - } - if (cond) printf ("%s", tbl->text); - tbl++; - } -} - -void chipset_attach(pcici_t config_id, int unit) -{ -#ifdef PROBE_VERBOSE - switch (pci_conf_read (config_id, 0)) { - - case 0x04838086: - writeconfig (config_id, conf82424zx); - break; - case 0x04a38086: - writeconfig (config_id, conf82434lx); - break; - case 0x04848086: - case 0x04828086: - printf ("\t[40] %lx [50] %lx [54] %lx\n", - pci_conf_read (config_id, 0x40), - pci_conf_read (config_id, 0x50), - pci_conf_read (config_id, 0x54)); - break; - }; -#endif -} - -/*--------------------------------------------------------- -** -** Catchall driver for VGA devices -** -** -** By Garrett Wollman -** <wollman@halloran-eldar.lcs.mit.edu> -** -**--------------------------------------------------------- -*/ - -static char* vga_probe (pcici_t tag, pcidi_t type); -static void vga_attach(pcici_t tag, int unit); -static u_long vga_count; - -struct pci_driver vga_device = { - vga_probe, - vga_attach, - &vga_count -}; - -static char* vga_probe (pcici_t tag, pcidi_t type) -{ - int data = pci_conf_read(tag, PCI_CLASS_REG); - - switch (data & PCI_CLASS_MASK) { - - case PCI_CLASS_PREHISTORIC: - if ((data & PCI_SUBCLASS_MASK) - != PCI_SUBCLASS_PREHISTORIC_VGA) - break; - - case PCI_CLASS_DISPLAY: - return ("display device"); - }; - return ((char*)0); -} - -static void vga_attach(pcici_t tag, int unit) -{ -/* -** Breaks some systems. -** The assigned adresses _have_ to be announced to the console driver. -*/ -#if 0 - vm_offset_t va; - vm_offset_t pa; - int reg; - for (reg = PCI_MAP_REG_START; reg < PCI_MAP_REG_END; reg += 4) - (void) pci_map_mem (tag, reg, &va, &pa); -#endif -} - -/*--------------------------------------------------------- -** -** Hook for loadable pci drivers -** -**--------------------------------------------------------- -*/ - -static char* lkm_probe (pcici_t tag, pcidi_t type); -static void lkm_attach(pcici_t tag, int unit); -static u_long lkm_count; - -struct pci_driver lkm_device = { - lkm_probe, - lkm_attach, - &lkm_count -}; - -static char* lkm_probe (pcici_t tag, pcidi_t type) -{ - /* - ** Should try to load a matching driver. - ** XXX Not yet! - */ - return ((char*)0); -} - -static void lkm_attach(pcici_t tag, int unit) -{ -} - -/*--------------------------------------------------------- -** -** Devices to ignore -** -**--------------------------------------------------------- -*/ - -static char* ign_probe (pcici_t tag, pcidi_t type); -static void ign_attach(pcici_t tag, int unit); -static u_long ign_count; - -struct pci_driver ign_device = { - ign_probe, - ign_attach, - &ign_count -}; - -static char* ign_probe (pcici_t tag, pcidi_t type) -{ - switch (type) { - - case 0x10001042ul: /* wd */ - return (""); - - }; - return ((char*)0); -} - -static void ign_attach(pcici_t tag, int unit) -{ -} |
