12432Sse/************************************************************************** 22432Sse** 32432Sse** 439247Sgibbs** Device driver for the NCR 53C8XX PCI-SCSI-Controller Family. 52432Sse** 62432Sse**------------------------------------------------------------------------- 72432Sse** 82432Sse** Written for 386bsd and FreeBSD by 97228Sse** Wolfgang Stanglmeier <wolf@cologne.de> 103533Sse** Stefan Esser <se@mi.Uni-Koeln.de> 112432Sse** 122432Sse**------------------------------------------------------------------------- 13139834Sscottl*/ 14139825Simp/*- 152432Sse** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. 162432Sse** 172432Sse** Redistribution and use in source and binary forms, with or without 182432Sse** modification, are permitted provided that the following conditions 192432Sse** are met: 202432Sse** 1. Redistributions of source code must retain the above copyright 212432Sse** notice, this list of conditions and the following disclaimer. 222432Sse** 2. Redistributions in binary form must reproduce the above copyright 232432Sse** notice, this list of conditions and the following disclaimer in the 242432Sse** documentation and/or other materials provided with the distribution. 252432Sse** 3. The name of the author may not be used to endorse or promote products 262432Sse** derived from this software without specific prior written permission. 272432Sse** 282432Sse** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 292432Sse** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 302432Sse** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 312432Sse** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 322432Sse** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 332432Sse** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 342432Sse** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 352432Sse** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 362432Sse** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 372432Sse** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 382432Sse** 393533Sse*************************************************************************** 402432Sse*/ 412432Sse 42116192Sobrien#include <sys/cdefs.h> 43116192Sobrien__FBSDID("$FreeBSD$"); 44116192Sobrien 45116192Sobrien 4639247Sgibbs#define NCR_DATE "pl30 98/1/1" 476132Sdg 482432Sse#define NCR_VERSION (2) 493533Sse#define MAX_UNITS (16) 502432Sse 519429Sse#define NCR_GETCC_WITHMSG 527228Sse 5355206Speter#if defined (__FreeBSD__) && defined(_KERNEL) 5420535Sse#include "opt_ncr.h" 5555206Speter#endif 5620517Sse 572432Sse/*========================================================== 582432Sse** 592432Sse** Configuration and Debugging 602432Sse** 616460Sse** May be overwritten in <arch/conf/xxxx> 622432Sse** 632432Sse**========================================================== 642432Sse*/ 652432Sse 662432Sse/* 672432Sse** SCSI address of this device. 682432Sse** The boot routines should have set it. 692432Sse** If not, use this. 702432Sse*/ 712432Sse 722432Sse#ifndef SCSI_NCR_MYADDR 732432Sse#define SCSI_NCR_MYADDR (7) 742432Sse#endif /* SCSI_NCR_MYADDR */ 752432Sse 762432Sse/* 7727684Sse** The default synchronous period factor 782432Sse** (0=asynchronous) 7927684Sse** If maximum synchronous frequency is defined, use it instead. 802432Sse*/ 812432Sse 8227684Sse#ifndef SCSI_NCR_MAX_SYNC 832432Sse 8427684Sse#ifndef SCSI_NCR_DFLT_SYNC 8527684Sse#define SCSI_NCR_DFLT_SYNC (12) 8627684Sse#endif /* SCSI_NCR_DFLT_SYNC */ 8727684Sse 8827684Sse#else 8927684Sse 9027684Sse#if SCSI_NCR_MAX_SYNC == 0 9127684Sse#define SCSI_NCR_DFLT_SYNC 0 9227684Sse#else 9327684Sse#define SCSI_NCR_DFLT_SYNC (250000 / SCSI_NCR_MAX_SYNC) 9427684Sse#endif 9527684Sse 9627684Sse#endif 9727684Sse 982432Sse/* 9927684Sse** The minimal asynchronous pre-scaler period (ns) 10027684Sse** Shall be 40. 10127684Sse*/ 10227684Sse 10327684Sse#ifndef SCSI_NCR_MIN_ASYNC 10427684Sse#define SCSI_NCR_MIN_ASYNC (40) 10527684Sse#endif /* SCSI_NCR_MIN_ASYNC */ 10627684Sse 10727684Sse/* 1082814Sse** The maximal bus with (in log2 byte) 1092814Sse** (0=8 bit, 1=16 bit) 1102814Sse*/ 1112814Sse 1122814Sse#ifndef SCSI_NCR_MAX_WIDE 1133939Sse#define SCSI_NCR_MAX_WIDE (1) 1142814Sse#endif /* SCSI_NCR_MAX_WIDE */ 1152814Sse 1162432Sse/*========================================================== 1172432Sse** 1182432Sse** Configuration and Debugging 1192432Sse** 1202432Sse**========================================================== 1212432Sse*/ 1222432Sse 1232432Sse/* 1242432Sse** Number of targets supported by the driver. 1252432Sse** n permits target numbers 0..n-1. 1262432Sse** Default is 7, meaning targets #0..#6. 1272432Sse** #7 .. is myself. 1282432Sse*/ 1292432Sse 13010605Sse#define MAX_TARGET (16) 1312432Sse 1322432Sse/* 1332432Sse** Number of logic units supported by the driver. 1342432Sse** n enables logic unit numbers 0..n-1. 1352432Sse** The common SCSI devices require only 1362432Sse** one lun, so take 1 as the default. 1372432Sse*/ 1382432Sse 13914556Sse#ifndef MAX_LUN 14013481Sse#define MAX_LUN (8) 14114556Sse#endif /* MAX_LUN */ 1422432Sse 1432432Sse/* 1442432Sse** The maximum number of jobs scheduled for starting. 1452432Sse** There should be one slot per target, and one slot 14610605Sse** for each tag of each target in use. 1472432Sse*/ 1482432Sse 14939247Sgibbs#define MAX_START (256) 1502432Sse 1512432Sse/* 1522432Sse** The maximum number of segments a transfer is split into. 1532432Sse*/ 1542432Sse 1552432Sse#define MAX_SCATTER (33) 1562432Sse 1572432Sse/* 1582432Sse** The maximum transfer length (should be >= 64k). 15915543Sphk** MUST NOT be greater than (MAX_SCATTER-1) * PAGE_SIZE. 1602432Sse*/ 1612432Sse 16215543Sphk#define MAX_SIZE ((MAX_SCATTER-1) * (long) PAGE_SIZE) 1636526Sse 1646526Sse/* 1656526Sse** other 1666526Sse*/ 1676526Sse 1686526Sse#define NCR_SNOOP_TIMEOUT (1000000) 1697228Sse 1702432Sse/*========================================================== 1712432Sse** 1722432Sse** Include files 1732432Sse** 1742432Sse**========================================================== 1752432Sse*/ 1762432Sse 1772432Sse#include <sys/param.h> 1782432Sse#include <sys/time.h> 1792432Sse 18055206Speter#ifdef _KERNEL 1812432Sse#include <sys/systm.h> 1822432Sse#include <sys/malloc.h> 1832432Sse#include <sys/kernel.h> 184129878Sphk#include <sys/module.h> 18512820Sphk#include <sys/sysctl.h> 186168752Sscottl#include <sys/lock.h> 187168752Sscottl#include <sys/mutex.h> 18860974Sdfr#include <sys/bus.h> 18948424Speter#include <machine/md_var.h> 19060974Sdfr#include <machine/bus.h> 19160974Sdfr#include <machine/resource.h> 19260974Sdfr#include <sys/rman.h> 1932432Sse#include <vm/vm.h> 19412662Sdg#include <vm/pmap.h> 19510605Sse#include <vm/vm_extern.h> 19655206Speter#endif 1972432Sse 198119288Simp#include <dev/pci/pcivar.h> 199119288Simp#include <dev/pci/pcireg.h> 200119343Smarcel#include <pci/ncrreg.h> 2012432Sse 20239247Sgibbs#include <cam/cam.h> 20339247Sgibbs#include <cam/cam_ccb.h> 20439247Sgibbs#include <cam/cam_sim.h> 20539247Sgibbs#include <cam/cam_xpt_sim.h> 20639247Sgibbs#include <cam/cam_debug.h> 2072432Sse 20839247Sgibbs#include <cam/scsi/scsi_all.h> 20939247Sgibbs#include <cam/scsi/scsi_message.h> 2107228Sse 2112432Sse/*========================================================== 2122432Sse** 2132432Sse** Debugging tags 2142432Sse** 2152432Sse**========================================================== 2162432Sse*/ 2172432Sse 2182432Sse#define DEBUG_ALLOC (0x0001) 2192432Sse#define DEBUG_PHASE (0x0002) 2202432Sse#define DEBUG_POLL (0x0004) 2212432Sse#define DEBUG_QUEUE (0x0008) 2222432Sse#define DEBUG_RESULT (0x0010) 2232432Sse#define DEBUG_SCATTER (0x0020) 2242432Sse#define DEBUG_SCRIPT (0x0040) 2252432Sse#define DEBUG_TINY (0x0080) 2262432Sse#define DEBUG_TIMING (0x0100) 2272814Sse#define DEBUG_NEGO (0x0200) 2282432Sse#define DEBUG_TAGS (0x0400) 2292432Sse#define DEBUG_FREEZE (0x0800) 2302814Sse#define DEBUG_RESTART (0x1000) 2312432Sse 2323552Sse/* 2333552Sse** Enable/Disable debug messages. 2343552Sse** Can be changed at runtime too. 2353552Sse*/ 23620549Sse#ifdef SCSI_NCR_DEBUG 2376766Sse #define DEBUG_FLAGS ncr_debug 23820549Sse#else /* SCSI_NCR_DEBUG */ 23920549Sse #define SCSI_NCR_DEBUG 0 2403552Sse #define DEBUG_FLAGS 0 24120549Sse#endif /* SCSI_NCR_DEBUG */ 2422432Sse 2432432Sse 2443552Sse 2452432Sse/*========================================================== 2462432Sse** 2472432Sse** assert () 2482432Sse** 2492432Sse**========================================================== 2502432Sse** 2512432Sse** modified copy from 386bsd:/usr/include/sys/assert.h 2522432Sse** 2532432Sse**---------------------------------------------------------- 2542432Sse*/ 2552432Sse 25639247Sgibbs#ifdef DIAGNOSTIC 25739247Sgibbs#define assert(expression) { \ 258170027Srwatson KASSERT(expression, ("%s", #expression)); \ 2592432Sse} 26039247Sgibbs#else 26139247Sgibbs#define assert(expression) { \ 26239247Sgibbs if (!(expression)) { \ 26339247Sgibbs (void)printf("assertion \"%s\" failed: " \ 26439247Sgibbs "file \"%s\", line %d\n", \ 26539247Sgibbs #expression, __FILE__, __LINE__); \ 26639247Sgibbs } \ 26739247Sgibbs} 26839247Sgibbs#endif 2697228Sse 2702432Sse/*========================================================== 2712432Sse** 2722432Sse** Access to the controller chip. 2732432Sse** 2742432Sse**========================================================== 2752432Sse*/ 2762432Sse 27760974Sdfr#define INB(r) bus_space_read_1(np->bst, np->bsh, offsetof(struct ncr_reg, r)) 27860974Sdfr#define INW(r) bus_space_read_2(np->bst, np->bsh, offsetof(struct ncr_reg, r)) 27960974Sdfr#define INL(r) bus_space_read_4(np->bst, np->bsh, offsetof(struct ncr_reg, r)) 2806401Sse 28160974Sdfr#define OUTB(r, val) bus_space_write_1(np->bst, np->bsh, \ 28260974Sdfr offsetof(struct ncr_reg, r), val) 28360974Sdfr#define OUTW(r, val) bus_space_write_2(np->bst, np->bsh, \ 28460974Sdfr offsetof(struct ncr_reg, r), val) 28560974Sdfr#define OUTL(r, val) bus_space_write_4(np->bst, np->bsh, \ 28660974Sdfr offsetof(struct ncr_reg, r), val) 28760974Sdfr#define OUTL_OFF(o, val) bus_space_write_4(np->bst, np->bsh, o, val) 2886401Sse 28960974Sdfr#define INB_OFF(o) bus_space_read_1(np->bst, np->bsh, o) 29060974Sdfr#define INW_OFF(o) bus_space_read_2(np->bst, np->bsh, o) 29160974Sdfr#define INL_OFF(o) bus_space_read_4(np->bst, np->bsh, o) 2926401Sse 29360974Sdfr#define READSCRIPT_OFF(base, off) \ 29460974Sdfr (base ? *((volatile u_int32_t *)((volatile char *)base + (off))) : \ 29560974Sdfr bus_space_read_4(np->bst2, np->bsh2, off)) 29627744Sse 29760974Sdfr#define WRITESCRIPT_OFF(base, off, val) \ 29860974Sdfr do { \ 29960974Sdfr if (base) \ 30060974Sdfr *((volatile u_int32_t *) \ 30160974Sdfr ((volatile char *)base + (off))) = (val); \ 30260974Sdfr else \ 30360974Sdfr bus_space_write_4(np->bst2, np->bsh2, off, val); \ 30439532Sken } while (0) 30539532Sken 30639532Sken#define READSCRIPT(r) \ 30739532Sken READSCRIPT_OFF(np->script, offsetof(struct script, r)) 30839532Sken 30939532Sken#define WRITESCRIPT(r, val) \ 31039532Sken WRITESCRIPT_OFF(np->script, offsetof(struct script, r), val) 31139532Sken 31227684Sse/* 31327684Sse** Set bit field ON, OFF 31427684Sse*/ 31527684Sse 31627684Sse#define OUTONB(r, m) OUTB(r, INB(r) | (m)) 31727684Sse#define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m)) 31827684Sse#define OUTONW(r, m) OUTW(r, INW(r) | (m)) 31927684Sse#define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m)) 32027684Sse#define OUTONL(r, m) OUTL(r, INL(r) | (m)) 32127684Sse#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m)) 32227684Sse 3232432Sse/*========================================================== 3242432Sse** 3252432Sse** Command control block states. 3262432Sse** 3272432Sse**========================================================== 3282432Sse*/ 3292432Sse 33010567Sse#define HS_IDLE (0) 33110567Sse#define HS_BUSY (1) 33210567Sse#define HS_NEGOTIATE (2) /* sync/wide data transfer*/ 33310567Sse#define HS_DISCONNECT (3) /* Disconnected by target */ 3342432Sse 33510567Sse#define HS_COMPLETE (4) 33610567Sse#define HS_SEL_TIMEOUT (5) /* Selection timeout */ 3377228Sse#define HS_RESET (6) /* SCSI reset */ 33810567Sse#define HS_ABORTED (7) /* Transfer aborted */ 33910567Sse#define HS_TIMEOUT (8) /* Software timeout */ 34010567Sse#define HS_FAIL (9) /* SCSI or PCI bus errors */ 34110567Sse#define HS_UNEXPECTED (10) /* Unexpected disconnect */ 34239247Sgibbs#define HS_STALL (11) /* QUEUE FULL or BUSY */ 3432432Sse 3442814Sse#define HS_DONEMASK (0xfc) 3452814Sse 3462432Sse/*========================================================== 3472432Sse** 3486705Sse** Software Interrupt Codes 3492432Sse** 3502432Sse**========================================================== 3512432Sse*/ 3522432Sse 3532814Sse#define SIR_SENSE_RESTART (1) 3542814Sse#define SIR_SENSE_FAILED (2) 3552814Sse#define SIR_STALL_RESTART (3) 3562814Sse#define SIR_STALL_QUEUE (4) 3572814Sse#define SIR_NEGO_SYNC (5) 3582814Sse#define SIR_NEGO_WIDE (6) 3592814Sse#define SIR_NEGO_FAILED (7) 3602814Sse#define SIR_NEGO_PROTO (8) 3612814Sse#define SIR_REJECT_RECEIVED (9) 3622814Sse#define SIR_REJECT_SENT (10) 3632814Sse#define SIR_IGN_RESIDUE (11) 3642814Sse#define SIR_MISSING_SAVE (12) 3652814Sse#define SIR_MAX (12) 3667228Sse 3672814Sse/*========================================================== 3682814Sse** 3692814Sse** Extended error codes. 37039247Sgibbs** xerr_status field of struct nccb. 3712814Sse** 3722814Sse**========================================================== 3732814Sse*/ 3742432Sse 3752814Sse#define XE_OK (0) 3762814Sse#define XE_EXTRA_DATA (1) /* unexpected data phase */ 3772814Sse#define XE_BAD_PHASE (2) /* illegal phase (4/5) */ 3782814Sse 3792432Sse/*========================================================== 3802432Sse** 3812814Sse** Negotiation status. 38239247Sgibbs** nego_status field of struct nccb. 3832432Sse** 3842432Sse**========================================================== 3852432Sse*/ 3862432Sse 3872814Sse#define NS_SYNC (1) 3882814Sse#define NS_WIDE (2) 3892814Sse 3902814Sse/*========================================================== 3912814Sse** 39239247Sgibbs** XXX These are no longer used. Remove once the 39339247Sgibbs** script is updated. 3942814Sse** "Special features" of targets. 39539247Sgibbs** quirks field of struct tcb. 39639247Sgibbs** actualquirks field of struct nccb. 3972814Sse** 3982814Sse**========================================================== 3992814Sse*/ 4002814Sse 4012814Sse#define QUIRK_AUTOSAVE (0x01) 4022814Sse#define QUIRK_NOMSG (0x02) 40339247Sgibbs#define QUIRK_NOSYNC (0x10) 40439247Sgibbs#define QUIRK_NOWIDE16 (0x20) 40539247Sgibbs#define QUIRK_NOTAGS (0x40) 4062814Sse#define QUIRK_UPDATE (0x80) 4072814Sse 4082814Sse/*========================================================== 4092814Sse** 4102814Sse** Misc. 4112814Sse** 4122814Sse**========================================================== 4132814Sse*/ 4142814Sse 4152814Sse#define CCB_MAGIC (0xf2691ad2) 41639247Sgibbs#define MAX_TAGS (32) /* hard limit */ 4177228Sse 4182432Sse/*========================================================== 4192432Sse** 4202432Sse** OS dependencies. 4212432Sse** 4222432Sse**========================================================== 4232432Sse*/ 4242432Sse 42539247Sgibbs#define PRINT_ADDR(ccb) xpt_print_path((ccb)->ccb_h.path) 4267228Sse 4272432Sse/*========================================================== 4282432Sse** 4292432Sse** Declaration of structs. 4302432Sse** 4312432Sse**========================================================== 4322432Sse*/ 4332432Sse 4342432Ssestruct tcb; 4352432Ssestruct lcb; 43639247Sgibbsstruct nccb; 4372432Ssestruct ncb; 4382432Ssestruct script; 4392432Sse 4402432Ssetypedef struct ncb * ncb_p; 4412432Ssetypedef struct tcb * tcb_p; 4422432Ssetypedef struct lcb * lcb_p; 44339247Sgibbstypedef struct nccb * nccb_p; 4442432Sse 4452432Ssestruct link { 44628960Sse ncrcmd l_cmd; 44728960Sse ncrcmd l_paddr; 4482432Sse}; 4492432Sse 4502432Ssestruct usrcmd { 4512432Sse u_long target; 4522432Sse u_long lun; 4532432Sse u_long data; 4542432Sse u_long cmd; 4552432Sse}; 4562432Sse 4572432Sse#define UC_SETSYNC 10 4582432Sse#define UC_SETTAGS 11 4592432Sse#define UC_SETDEBUG 12 4602432Sse#define UC_SETORDER 13 4612435Sse#define UC_SETWIDE 14 4622435Sse#define UC_SETFLAG 15 4632432Sse 4642814Sse#define UF_TRACE (0x01) 4652814Sse 4662432Sse/*--------------------------------------- 4672432Sse** 4682432Sse** Timestamps for profiling 4692432Sse** 4702432Sse**--------------------------------------- 4712432Sse*/ 4722432Sse 47339554Sgibbs/* Type of the kernel variable `ticks'. XXX should be declared with the var. */ 47439554Sgibbstypedef int ticks_t; 47539554Sgibbs 4762432Ssestruct tstamp { 47739554Sgibbs ticks_t start; 47839554Sgibbs ticks_t end; 47939554Sgibbs ticks_t select; 48039554Sgibbs ticks_t command; 48139554Sgibbs ticks_t data; 48239554Sgibbs ticks_t status; 48339554Sgibbs ticks_t disconnect; 4842432Sse}; 4852432Sse 4862432Sse/* 4872432Sse** profiling data (per device) 4882432Sse*/ 4892432Sse 4902432Ssestruct profile { 4912432Sse u_long num_trans; 4922432Sse u_long num_bytes; 4932432Sse u_long num_disc; 4942432Sse u_long num_break; 4952432Sse u_long num_int; 4962432Sse u_long num_fly; 4972432Sse u_long ms_setup; 4982432Sse u_long ms_data; 4992432Sse u_long ms_disc; 5002432Sse u_long ms_post; 5012432Sse}; 5027228Sse 5032432Sse/*========================================================== 5042432Sse** 5057228Sse** Declaration of structs: target control block 5062432Sse** 5072432Sse**========================================================== 5082432Sse*/ 5092432Sse 51039247Sgibbs#define NCR_TRANS_CUR 0x01 /* Modify current neogtiation status */ 51139247Sgibbs#define NCR_TRANS_ACTIVE 0x03 /* Assume this is the active target */ 51239247Sgibbs#define NCR_TRANS_GOAL 0x04 /* Modify negotiation goal */ 51339247Sgibbs#define NCR_TRANS_USER 0x08 /* Modify user negotiation settings */ 51439247Sgibbs 51539247Sgibbsstruct ncr_transinfo { 51639247Sgibbs u_int8_t width; 51739247Sgibbs u_int8_t period; 51839247Sgibbs u_int8_t offset; 51939247Sgibbs}; 52039247Sgibbs 52139247Sgibbsstruct ncr_target_tinfo { 52239247Sgibbs /* Hardware version of our sync settings */ 52339247Sgibbs u_int8_t disc_tag; 52439247Sgibbs#define NCR_CUR_DISCENB 0x01 52539247Sgibbs#define NCR_CUR_TAGENB 0x02 52639247Sgibbs#define NCR_USR_DISCENB 0x04 52739247Sgibbs#define NCR_USR_TAGENB 0x08 52839247Sgibbs u_int8_t sval; 52939247Sgibbs struct ncr_transinfo current; 53039247Sgibbs struct ncr_transinfo goal; 53139247Sgibbs struct ncr_transinfo user; 53239247Sgibbs /* Hardware version of our wide settings */ 53339247Sgibbs u_int8_t wval; 53439247Sgibbs}; 53539247Sgibbs 5362432Ssestruct tcb { 5372432Sse /* 5382432Sse ** during reselection the ncr jumps to this point 5397228Sse ** with SFBR set to the encoded target number 5402432Sse ** with bit 7 set. 5412432Sse ** if it's not this target, jump to the next. 5422432Sse ** 5437228Sse ** JUMP IF (SFBR != #target#) 5442432Sse ** @(next tcb) 5452432Sse */ 5462432Sse 5472432Sse struct link jump_tcb; 5482432Sse 5492432Sse /* 5502814Sse ** load the actual values for the sxfer and the scntl3 5512814Sse ** register (sync/wide mode). 5522432Sse ** 5532432Sse ** SCR_COPY (1); 5542432Sse ** @(sval field of this tcb) 5552432Sse ** @(sxfer register) 5562814Sse ** SCR_COPY (1); 5572814Sse ** @(wval field of this tcb) 5582814Sse ** @(scntl3 register) 5592432Sse */ 5602432Sse 5612814Sse ncrcmd getscr[6]; 5622432Sse 5632432Sse /* 5642432Sse ** if next message is "identify" 5652432Sse ** then load the message to SFBR, 5662432Sse ** else load 0 to SFBR. 5672432Sse ** 5682432Sse ** CALL 5692432Sse ** <RESEL_LUN> 5702432Sse */ 5712432Sse 5722432Sse struct link call_lun; 5732432Sse 5742432Sse /* 5752432Sse ** now look for the right lun. 5762432Sse ** 5772432Sse ** JUMP 57839247Sgibbs ** @(first nccb of this lun) 5792432Sse */ 5802432Sse 5812432Sse struct link jump_lcb; 5827228Sse 5832432Sse /* 58439247Sgibbs ** pointer to interrupted getcc nccb 5852432Sse */ 5862432Sse 58739247Sgibbs nccb_p hold_cp; 5882432Sse 5892432Sse /* 59039247Sgibbs ** pointer to nccb used for negotiating. 59127684Sse ** Avoid to start a nego for all queued commands 59227684Sse ** when tagged command queuing is enabled. 59327684Sse */ 59427684Sse 59539247Sgibbs nccb_p nego_cp; 59627684Sse 59727684Sse /* 5982432Sse ** statistical data 5992432Sse */ 6002432Sse 6012432Sse u_long transfers; 6022432Sse u_long bytes; 6032432Sse 6042432Sse /* 6052432Sse ** user settable limits for sync transfer 6062432Sse ** and tagged commands. 6072432Sse */ 6082432Sse 60939247Sgibbs struct ncr_target_tinfo tinfo; 6102432Sse 6112432Sse /* 6122432Sse ** the lcb's of this tcb 6132432Sse */ 6142432Sse 6152432Sse lcb_p lp[MAX_LUN]; 6162432Sse}; 6177228Sse 6182432Sse/*========================================================== 6192432Sse** 6207228Sse** Declaration of structs: lun control block 6212432Sse** 6222432Sse**========================================================== 6232432Sse*/ 6242432Sse 6252432Ssestruct lcb { 6262432Sse /* 6272432Sse ** during reselection the ncr jumps to this point 6282432Sse ** with SFBR set to the "Identify" message. 6292432Sse ** if it's not this lun, jump to the next. 6302432Sse ** 63110567Sse ** JUMP IF (SFBR != #lun#) 6322432Sse ** @(next lcb of this target) 6332432Sse */ 6342432Sse 6352432Sse struct link jump_lcb; 6362432Sse 6372432Sse /* 6382432Sse ** if next message is "simple tag", 6392432Sse ** then load the tag to SFBR, 6402432Sse ** else load 0 to SFBR. 6412432Sse ** 6422432Sse ** CALL 6432432Sse ** <RESEL_TAG> 6442432Sse */ 6452432Sse 6462432Sse struct link call_tag; 6472432Sse 6482432Sse /* 64939247Sgibbs ** now look for the right nccb. 6502432Sse ** 6512432Sse ** JUMP 65239247Sgibbs ** @(first nccb of this lun) 6532432Sse */ 6542432Sse 65539247Sgibbs struct link jump_nccb; 6562432Sse 6572432Sse /* 65839247Sgibbs ** start of the nccb chain 6592432Sse */ 6602432Sse 66139247Sgibbs nccb_p next_nccb; 6622432Sse 6632432Sse /* 6642432Sse ** Control of tagged queueing 6652432Sse */ 6662432Sse 66739247Sgibbs u_char reqnccbs; 6682432Sse u_char reqlink; 6692432Sse u_char actlink; 6702432Sse u_char usetags; 6712432Sse u_char lasttag; 6722432Sse}; 6737228Sse 6742432Sse/*========================================================== 6752432Sse** 6762432Sse** Declaration of structs: COMMAND control block 6772432Sse** 6782432Sse**========================================================== 6792432Sse** 68039247Sgibbs** This substructure is copied from the nccb to a 6812432Sse** global address after selection (or reselection) 6822432Sse** and copied back before disconnect. 6832432Sse** 6842432Sse** These fields are accessible to the script processor. 6852432Sse** 6862432Sse**---------------------------------------------------------- 6872432Sse*/ 6882432Sse 6892432Ssestruct head { 6902432Sse /* 69139247Sgibbs ** Execution of a nccb starts at this point. 6922432Sse ** It's a jump to the "SELECT" label 6932432Sse ** of the script. 6942432Sse ** 6952432Sse ** After successful selection the script 6962432Sse ** processor overwrites it with a jump to 6972432Sse ** the IDLE label of the script. 6982432Sse */ 6992432Sse 7002432Sse struct link launch; 7012432Sse 7022432Sse /* 7032432Sse ** Saved data pointer. 7042432Sse ** Points to the position in the script 7052432Sse ** responsible for the actual transfer 7062432Sse ** of data. 7072432Sse ** It's written after reception of a 7082432Sse ** "SAVE_DATA_POINTER" message. 7092814Sse ** The goalpointer points after 7102814Sse ** the last transfer command. 7112432Sse */ 7122432Sse 71328960Sse u_int32_t savep; 71428960Sse u_int32_t lastp; 71528960Sse u_int32_t goalp; 7162432Sse 7172432Sse /* 71839247Sgibbs ** The virtual address of the nccb 7192432Sse ** containing this header. 7202432Sse */ 7212432Sse 72239247Sgibbs nccb_p cp; 7232432Sse 7242432Sse /* 7252432Sse ** space for some timestamps to gather 7262432Sse ** profiling data about devices and this driver. 7272432Sse */ 7282432Sse 7292432Sse struct tstamp stamp; 7307228Sse 7312432Sse /* 7322432Sse ** status fields. 7332432Sse */ 7342432Sse 7352432Sse u_char status[8]; 7362432Sse}; 7372435Sse 7382814Sse/* 7392814Sse** The status bytes are used by the host and the script processor. 7402814Sse** 7412814Sse** The first four byte are copied to the scratchb register 7422814Sse** (declared as scr0..scr3 in ncr_reg.h) just after the select/reselect, 7432814Sse** and copied back just after disconnecting. 7442814Sse** Inside the script the XX_REG are used. 7452814Sse** 7462814Sse** The last four bytes are used inside the script by "COPY" commands. 7472814Sse** Because source and destination must have the same alignment 74810567Sse** in a longword, the fields HAVE to be at the choosen offsets. 7492814Sse** xerr_st (4) 0 (0x34) scratcha 7502814Sse** sync_st (5) 1 (0x05) sxfer 7512814Sse** wide_st (7) 3 (0x03) scntl3 7522814Sse*/ 7532814Sse 7542814Sse/* 7552814Sse** First four bytes (script) 7562814Sse*/ 7572814Sse#define QU_REG scr0 7582814Sse#define HS_REG scr1 7592814Sse#define HS_PRT nc_scr1 7602814Sse#define SS_REG scr2 7612814Sse#define PS_REG scr3 7622814Sse 7632814Sse/* 7642814Sse** First four bytes (host) 7652814Sse*/ 7662814Sse#define actualquirks phys.header.status[0] 7672814Sse#define host_status phys.header.status[1] 76839247Sgibbs#define s_status phys.header.status[2] 7692814Sse#define parity_status phys.header.status[3] 7702814Sse 7712814Sse/* 7722814Sse** Last four bytes (script) 7732814Sse*/ 7742814Sse#define xerr_st header.status[4] /* MUST be ==0 mod 4 */ 7752814Sse#define sync_st header.status[5] /* MUST be ==1 mod 4 */ 7762814Sse#define nego_st header.status[6] 7772814Sse#define wide_st header.status[7] /* MUST be ==3 mod 4 */ 7782814Sse 7792814Sse/* 7802814Sse** Last four bytes (host) 7812814Sse*/ 7822814Sse#define xerr_status phys.xerr_st 7832814Sse#define sync_status phys.sync_st 7842814Sse#define nego_status phys.nego_st 7852814Sse#define wide_status phys.wide_st 7867228Sse 7872432Sse/*========================================================== 7882432Sse** 7892432Sse** Declaration of structs: Data structure block 7902432Sse** 7912432Sse**========================================================== 7922432Sse** 79339247Sgibbs** During execution of a nccb by the script processor, 7942432Sse** the DSA (data structure address) register points 79539247Sgibbs** to this substructure of the nccb. 7962432Sse** This substructure contains the header with 7972432Sse** the script-processor-changable data and 7982432Sse** data blocks for the indirect move commands. 7992432Sse** 8002432Sse**---------------------------------------------------------- 8012432Sse*/ 8022432Sse 8032432Ssestruct dsb { 8042432Sse 8052432Sse /* 8062432Sse ** Header. 8072432Sse ** Has to be the first entry, 8082432Sse ** because it's jumped to by the 8092432Sse ** script processor 8102432Sse */ 8112432Sse 8127228Sse struct head header; 8132432Sse 8142432Sse /* 8152432Sse ** Table data for Script 8162432Sse */ 8172432Sse 8182432Sse struct scr_tblsel select; 8192432Sse struct scr_tblmove smsg ; 8202432Sse struct scr_tblmove smsg2 ; 8212432Sse struct scr_tblmove cmd ; 8227250Sse struct scr_tblmove scmd ; 8232432Sse struct scr_tblmove sense ; 8242432Sse struct scr_tblmove data [MAX_SCATTER]; 8252432Sse}; 8267228Sse 8272432Sse/*========================================================== 8282432Sse** 8292432Sse** Declaration of structs: Command control block. 8302432Sse** 8312432Sse**========================================================== 8322432Sse** 83339247Sgibbs** During execution of a nccb by the script processor, 8342432Sse** the DSA (data structure address) register points 83539247Sgibbs** to this substructure of the nccb. 8362432Sse** This substructure contains the header with 8372432Sse** the script-processor-changable data and then 8382432Sse** data blocks for the indirect move commands. 8392432Sse** 8402432Sse**---------------------------------------------------------- 8412432Sse*/ 8422432Sse 8432432Sse 84439247Sgibbsstruct nccb { 8452432Sse /* 84628636Sse ** This filler ensures that the global header is 84727684Sse ** cache line size aligned. 84827684Sse */ 84928634Sse ncrcmd filler[4]; 85027684Sse 85127684Sse /* 8522432Sse ** during reselection the ncr jumps to this point. 8532432Sse ** If a "SIMPLE_TAG" message was received, 8542432Sse ** then SFBR is set to the tag. 8552432Sse ** else SFBR is set to 0 85639247Sgibbs ** If looking for another tag, jump to the next nccb. 8572432Sse ** 8582432Sse ** JUMP IF (SFBR != #TAG#) 85939247Sgibbs ** @(next nccb of this lun) 8602432Sse */ 8612432Sse 86239247Sgibbs struct link jump_nccb; 8632432Sse 8642432Sse /* 8652432Sse ** After execution of this call, the return address 8662432Sse ** (in the TEMP register) points to the following 8672432Sse ** data structure block. 8682432Sse ** So copy it to the DSA register, and start 8692432Sse ** processing of this data structure. 8702432Sse ** 8712432Sse ** CALL 8722432Sse ** <RESEL_TMP> 8732432Sse */ 8742432Sse 8752432Sse struct link call_tmp; 8762432Sse 8772432Sse /* 8782432Sse ** This is the data structure which is 8792432Sse ** to be executed by the script processor. 8802432Sse */ 8812432Sse 8822432Sse struct dsb phys; 8837228Sse 8842432Sse /* 8852432Sse ** If a data transfer phase is terminated too early 8862432Sse ** (after reception of a message (i.e. DISCONNECT)), 8872432Sse ** we have to prepare a mini script to transfer 8882432Sse ** the rest of the data. 8892432Sse */ 8902432Sse 89128960Sse ncrcmd patch[8]; 8922432Sse 8932432Sse /* 8942432Sse ** The general SCSI driver provides a 8952432Sse ** pointer to a control block. 8962432Sse */ 8972432Sse 89839247Sgibbs union ccb *ccb; 8992432Sse 9002432Sse /* 9012432Sse ** We prepare a message to be sent after selection, 9022432Sse ** and a second one to be sent after getcc selection. 9032432Sse ** Contents are IDENTIFY and SIMPLE_TAG. 9042814Sse ** While negotiating sync or wide transfer, 9052814Sse ** a SDTM or WDTM message is appended. 9062432Sse */ 9072432Sse 9082432Sse u_char scsi_smsg [8]; 9092432Sse u_char scsi_smsg2[8]; 9102432Sse 9112432Sse /* 91239247Sgibbs ** Lock this nccb. 91339247Sgibbs ** Flag is used while looking for a free nccb. 91410639Sse */ 91510639Sse 91610677Sse u_long magic; 91710639Sse 91810639Sse /* 91939247Sgibbs ** Physical address of this instance of nccb 9202432Sse */ 9212432Sse 92239247Sgibbs u_long p_nccb; 9232814Sse 9242814Sse /* 9252814Sse ** Completion time out for this job. 9262814Sse ** It's set to time of start + allowed number of seconds. 9272814Sse */ 9282814Sse 92939554Sgibbs time_t tlimit; 9307228Sse 9312432Sse /* 93239247Sgibbs ** All nccbs of one hostadapter are chained. 9332432Sse */ 9342432Sse 93539247Sgibbs nccb_p link_nccb; 9362432Sse 9372432Sse /* 93839247Sgibbs ** All nccbs of one target/lun are chained. 9392432Sse */ 9402432Sse 94139247Sgibbs nccb_p next_nccb; 9422432Sse 9432432Sse /* 9447250Sse ** Sense command 9457250Sse */ 9467250Sse 9477250Sse u_char sensecmd[6]; 9487250Sse 9497250Sse /* 9502432Sse ** Tag for this transfer. 95139247Sgibbs ** It's patched into jump_nccb. 9522432Sse ** If it's not zero, a SIMPLE_TAG 9532432Sse ** message is included in smsg. 9542432Sse */ 9552432Sse 9562432Sse u_char tag; 9572432Sse}; 9587228Sse 95939247Sgibbs#define CCB_PHYS(cp,lbl) (cp->p_nccb + offsetof(struct nccb, lbl)) 96010677Sse 9612432Sse/*========================================================== 9622432Sse** 9632432Sse** Declaration of structs: NCR device descriptor 9642432Sse** 9652432Sse**========================================================== 9662432Sse*/ 9672432Sse 9682432Ssestruct ncb { 96927684Sse /* 97027684Sse ** The global header. 97127684Sse ** Accessible to both the host and the 97227684Sse ** script-processor. 97327684Sse ** We assume it is cache line size aligned. 97427684Sse */ 97527684Sse struct head header; 97627684Sse 9773533Sse int unit; 9782432Sse 9792432Sse /*----------------------------------------------- 9802432Sse ** Scripts .. 9812432Sse **----------------------------------------------- 9822432Sse ** 9832432Sse ** During reselection the ncr jumps to this point. 9842432Sse ** The SFBR register is loaded with the encoded target id. 9852432Sse ** 9862432Sse ** Jump to the first target. 9872432Sse ** 9882432Sse ** JUMP 9892432Sse ** @(next tcb) 9902432Sse */ 9912432Sse struct link jump_tcb; 9922432Sse 9932432Sse /*----------------------------------------------- 9942432Sse ** Configuration .. 9952432Sse **----------------------------------------------- 9962432Sse ** 9972432Sse ** virtual and physical addresses 9982432Sse ** of the 53c810 chip. 9992432Sse */ 100060974Sdfr int reg_rid; 100160974Sdfr struct resource *reg_res; 100260974Sdfr bus_space_tag_t bst; 100360974Sdfr bus_space_handle_t bsh; 10042432Sse 100560974Sdfr int sram_rid; 100660974Sdfr struct resource *sram_res; 100760974Sdfr bus_space_tag_t bst2; 100860974Sdfr bus_space_handle_t bsh2; 100927744Sse 101060974Sdfr struct resource *irq_res; 101160974Sdfr void *irq_handle; 10122432Sse 10132432Sse /* 101427744Sse ** Scripts instance virtual address. 101527744Sse */ 10162432Sse struct script *script; 101727744Sse struct scripth *scripth; 101810677Sse 101910677Sse /* 102027744Sse ** Scripts instance physical address. 102110677Sse */ 102210673Sse u_long p_script; 102327744Sse u_long p_scripth; 10247228Sse 10252432Sse /* 10262432Sse ** The SCSI address of the host adapter. 10272432Sse */ 102820435Sse u_char myaddr; 10292432Sse 10302432Sse /* 10312432Sse ** timing parameters 10322432Sse */ 103327684Sse u_char minsync; /* Minimum sync period factor */ 103427684Sse u_char maxsync; /* Maximum sync period factor */ 103527684Sse u_char maxoffs; /* Max scsi offset */ 103627684Sse u_char clock_divn; /* Number of clock divisors */ 103727684Sse u_long clock_khz; /* SCSI clock frequency in KHz */ 103827684Sse u_long features; /* Chip features map */ 103927684Sse u_char multiplier; /* Clock multiplier (1,2,4) */ 104020435Sse 104127684Sse u_char maxburst; /* log base 2 of dwords burst */ 104227684Sse 104320435Sse /* 104420435Sse ** BIOS supplied PCI bus options 104520435Sse */ 10462432Sse u_char rv_scntl3; 104720435Sse u_char rv_dcntl; 104820435Sse u_char rv_dmode; 104920435Sse u_char rv_ctest3; 105027684Sse u_char rv_ctest4; 105120435Sse u_char rv_ctest5; 105227684Sse u_char rv_gpcntl; 105327684Sse u_char rv_stest2; 10542814Sse 10552432Sse /*----------------------------------------------- 105639247Sgibbs ** CAM SIM information for this instance 10572432Sse **----------------------------------------------- 10582432Sse */ 10592432Sse 106039247Sgibbs struct cam_sim *sim; 106139247Sgibbs struct cam_path *path; 10622432Sse 10632432Sse /*----------------------------------------------- 10642432Sse ** Job control 10652432Sse **----------------------------------------------- 10662432Sse ** 10672432Sse ** Commands from user 10682432Sse */ 10692432Sse struct usrcmd user; 10702432Sse 10712432Sse /* 10722432Sse ** Target data 10732432Sse */ 10742432Sse struct tcb target[MAX_TARGET]; 10752432Sse 10762432Sse /* 10772432Sse ** Start queue. 10782432Sse */ 107928960Sse u_int32_t squeue [MAX_START]; 10802432Sse u_short squeueput; 10812432Sse 10822432Sse /* 10832432Sse ** Timeout handler 10842432Sse */ 108539554Sgibbs time_t heartbeat; 10862432Sse u_short ticks; 10872432Sse u_short latetime; 108839554Sgibbs time_t lasttime; 108929681Sgibbs struct callout_handle timeout_ch; 10907228Sse 10912432Sse /*----------------------------------------------- 10922432Sse ** Debug and profiling 10932432Sse **----------------------------------------------- 10942432Sse ** 10952432Sse ** register dump 10962432Sse */ 10972432Sse struct ncr_reg regdump; 109839554Sgibbs time_t regtime; 10992432Sse 11002432Sse /* 11012432Sse ** Profiling data 11022432Sse */ 11032432Sse struct profile profile; 11042432Sse u_long disc_phys; 11052432Sse u_long disc_ref; 11062814Sse 11072814Sse /* 110839247Sgibbs ** Head of list of all nccbs for this controller. 11092432Sse */ 111039247Sgibbs nccb_p link_nccb; 111139247Sgibbs 11122432Sse /* 11132432Sse ** message buffers. 11142432Sse ** Should be longword aligned, 11152432Sse ** because they're written with a 11162432Sse ** COPY script command. 11172432Sse */ 11189364Sse u_char msgout[8]; 11199364Sse u_char msgin [8]; 112028960Sse u_int32_t lastmsg; 11212432Sse 11222432Sse /* 11232432Sse ** Buffer for STATUS_IN phase. 11242432Sse */ 11252814Sse u_char scratch; 11262432Sse 11272814Sse /* 11282814Sse ** controller chip dependent maximal transfer width. 11292814Sse */ 11302814Sse u_char maxwide; 11312814Sse 11326460Sse#ifdef NCR_IOMAPPED 11336136Sse /* 11346460Sse ** address of the ncr control registers in io space 11352814Sse */ 113639532Sken pci_port_t port; 11376460Sse#endif 11382432Sse}; 11397228Sse 114010677Sse#define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl)) 114127744Sse#define NCB_SCRIPTH_PHYS(np,lbl) (np->p_scripth + offsetof (struct scripth,lbl)) 114210677Sse 11432432Sse/*========================================================== 11442432Sse** 11452432Sse** 11462432Sse** Script for NCR-Processor. 11472432Sse** 11482432Sse** Use ncr_script_fill() to create the variable parts. 11492432Sse** Use ncr_script_copy_and_bind() to make a copy and 11502432Sse** bind to physical addresses. 11512432Sse** 11522432Sse** 11532432Sse**========================================================== 11542432Sse** 11552432Sse** We have to know the offsets of all labels before 11562432Sse** we reach them (for forward jumps). 11572432Sse** Therefore we declare a struct here. 11582432Sse** If you make changes inside the script, 11592432Sse** DONT FORGET TO CHANGE THE LENGTHS HERE! 11602432Sse** 11612432Sse**---------------------------------------------------------- 11622432Sse*/ 11637228Sse 116427744Sse/* 116527744Sse** Script fragments which are loaded into the on-board RAM 116627744Sse** of 825A, 875 and 895 chips. 116727744Sse*/ 11682432Ssestruct script { 11692432Sse ncrcmd start [ 7]; 11702432Sse ncrcmd start0 [ 2]; 11712432Sse ncrcmd start1 [ 3]; 11722432Sse ncrcmd startpos [ 1]; 11732432Sse ncrcmd trysel [ 8]; 11742432Sse ncrcmd skip [ 8]; 11752432Sse ncrcmd skip2 [ 3]; 11762432Sse ncrcmd idle [ 2]; 117746843Sse ncrcmd select [ 18]; 11782432Sse ncrcmd prepare [ 4]; 11792814Sse ncrcmd loadpos [ 14]; 11802814Sse ncrcmd prepare2 [ 24]; 11812432Sse ncrcmd setmsg [ 5]; 11822814Sse ncrcmd clrack [ 2]; 11836179Sse ncrcmd dispatch [ 33]; 11842814Sse ncrcmd no_data [ 17]; 11857228Sse ncrcmd checkatn [ 10]; 11862432Sse ncrcmd command [ 15]; 11872814Sse ncrcmd status [ 27]; 11882814Sse ncrcmd msg_in [ 26]; 11892432Sse ncrcmd msg_bad [ 6]; 11902814Sse ncrcmd complete [ 13]; 11912432Sse ncrcmd cleanup [ 12]; 119239247Sgibbs ncrcmd cleanup0 [ 9]; 119339247Sgibbs ncrcmd signal [ 12]; 11949364Sse ncrcmd save_dp [ 5]; 11952432Sse ncrcmd restore_dp [ 5]; 11962814Sse ncrcmd disconnect [ 12]; 11972814Sse ncrcmd disconnect0 [ 5]; 11982814Sse ncrcmd disconnect1 [ 23]; 11992432Sse ncrcmd msg_out [ 9]; 12002432Sse ncrcmd msg_out_done [ 7]; 120127744Sse ncrcmd badgetcc [ 6]; 120227744Sse ncrcmd reselect [ 8]; 120327744Sse ncrcmd reselect1 [ 8]; 120427744Sse ncrcmd reselect2 [ 8]; 120527744Sse ncrcmd resel_tmp [ 5]; 120627744Sse ncrcmd resel_lun [ 18]; 120727744Sse ncrcmd resel_tag [ 24]; 120827744Sse ncrcmd data_in [MAX_SCATTER * 4 + 7]; 120927744Sse ncrcmd data_out [MAX_SCATTER * 4 + 7]; 121027744Sse}; 121127744Sse 121227744Sse/* 121327744Sse** Script fragments which stay in main memory for all chips. 121427744Sse*/ 121527744Ssestruct scripth { 121627744Sse ncrcmd tryloop [MAX_START*5+2]; 121727744Sse ncrcmd msg_parity [ 6]; 121827744Sse ncrcmd msg_reject [ 8]; 121927744Sse ncrcmd msg_ign_residue [ 32]; 122027744Sse ncrcmd msg_extended [ 18]; 122127744Sse ncrcmd msg_ext_2 [ 18]; 122227744Sse ncrcmd msg_wdtr [ 27]; 122327744Sse ncrcmd msg_ext_3 [ 18]; 122427744Sse ncrcmd msg_sdtr [ 27]; 12252432Sse ncrcmd msg_out_abort [ 10]; 12262432Sse ncrcmd getcc [ 4]; 12272432Sse ncrcmd getcc1 [ 5]; 12289364Sse#ifdef NCR_GETCC_WITHMSG 122946843Sse ncrcmd getcc2 [ 29]; 12309364Sse#else 12319364Sse ncrcmd getcc2 [ 14]; 12329364Sse#endif 123346843Sse ncrcmd getcc3 [ 6]; 12342432Sse ncrcmd aborttag [ 4]; 12356132Sdg ncrcmd abort [ 22]; 12366526Sse ncrcmd snooptest [ 9]; 12376526Sse ncrcmd snoopend [ 2]; 12382432Sse}; 12397228Sse 12402432Sse/*========================================================== 12412432Sse** 12422432Sse** 12432814Sse** Function headers. 12442432Sse** 12452432Sse** 12462432Sse**========================================================== 12472432Sse*/ 12482432Sse 124955206Speter#ifdef _KERNEL 1250142407Simpstatic nccb_p ncr_alloc_nccb(ncb_p np, u_long target, u_long lun); 1251142407Simpstatic void ncr_complete(ncb_p np, nccb_p cp); 1252142407Simpstatic int ncr_delta(int * from, int * to); 1253142407Simpstatic void ncr_exception(ncb_p np); 1254142407Simpstatic void ncr_free_nccb(ncb_p np, nccb_p cp); 1255142407Simpstatic void ncr_freeze_devq(ncb_p np, struct cam_path *path); 1256142407Simpstatic void ncr_selectclock(ncb_p np, u_char scntl3); 1257142407Simpstatic void ncr_getclock(ncb_p np, u_char multiplier); 1258142407Simpstatic nccb_p ncr_get_nccb(ncb_p np, u_long t,u_long l); 125943309Sdillon#if 0 1260142407Simpstatic u_int32_t ncr_info(int unit); 126143309Sdillon#endif 1262142407Simpstatic void ncr_init(ncb_p np, char * msg, u_long code); 1263142407Simpstatic void ncr_intr(void *vnp); 1264142407Simpstatic void ncr_int_ma(ncb_p np, u_char dstat); 1265142407Simpstatic void ncr_int_sir(ncb_p np); 1266142407Simpstatic void ncr_int_sto(ncb_p np); 126743309Sdillon#if 0 1268142407Simpstatic void ncr_min_phys(struct buf *bp); 126943309Sdillon#endif 1270142407Simpstatic void ncr_poll(struct cam_sim *sim); 1271142407Simpstatic void ncb_profile(ncb_p np, nccb_p cp); 1272142418Simpstatic void ncr_script_copy_and_bind(ncb_p np, ncrcmd *src, ncrcmd *dst, 1273142407Simp int len); 1274142407Simpstatic void ncr_script_fill(struct script * scr, struct scripth *scrh); 1275142407Simpstatic int ncr_scatter(struct dsb* phys, vm_offset_t vaddr, 1276142407Simp vm_size_t datalen); 1277142407Simpstatic void ncr_getsync(ncb_p np, u_char sfac, u_char *fakp, 1278142407Simp u_char *scntl3p); 1279142407Simpstatic void ncr_setsync(ncb_p np, nccb_p cp,u_char scntl3,u_char sxfer, 1280142407Simp u_char period); 1281142407Simpstatic void ncr_setwide(ncb_p np, nccb_p cp, u_char wide, u_char ack); 1282142407Simpstatic int ncr_show_msg(u_char * msg); 1283142407Simpstatic int ncr_snooptest(ncb_p np); 1284142407Simpstatic void ncr_action(struct cam_sim *sim, union ccb *ccb); 1285142407Simpstatic void ncr_timeout(void *arg); 1286142407Simpstatic void ncr_wakeup(ncb_p np, u_long code); 12872432Sse 1288142407Simpstatic int ncr_probe(device_t dev); 1289142407Simpstatic int ncr_attach(device_t dev); 12902432Sse 129155206Speter#endif /* _KERNEL */ 12927228Sse 12932432Sse/*========================================================== 12942432Sse** 12952432Sse** 12962432Sse** Global static data. 12972432Sse** 12982432Sse** 12992432Sse**========================================================== 13002432Sse*/ 13012432Sse 130216322Sgpalmerstatic const u_long ncr_version = NCR_VERSION * 11 130310605Sse + (u_long) sizeof (struct ncb) * 7 130439247Sgibbs + (u_long) sizeof (struct nccb) * 5 130510605Sse + (u_long) sizeof (struct lcb) * 3 130610605Sse + (u_long) sizeof (struct tcb) * 2; 13072432Sse 130855206Speter#ifdef _KERNEL 13092432Sse 131020549Ssestatic int ncr_debug = SCSI_NCR_DEBUG; 131112820SphkSYSCTL_INT(_debug, OID_AUTO, ncr_debug, CTLFLAG_RW, &ncr_debug, 0, ""); 13123166Sse 131312820Sphkstatic int ncr_cache; /* to be aligned _NOT_ static */ 13143552Sse 13152432Sse/*========================================================== 13162432Sse** 13172432Sse** 13182432Sse** Global static data: auto configure 13192432Sse** 13202432Sse** 13212432Sse**========================================================== 13222432Sse*/ 13232432Sse 13243166Sse#define NCR_810_ID (0x00011000ul) 13256401Sse#define NCR_815_ID (0x00041000ul) 132626568Sse#define NCR_820_ID (0x00021000ul) 13273166Sse#define NCR_825_ID (0x00031000ul) 132810936Sse#define NCR_860_ID (0x00061000ul) 132910936Sse#define NCR_875_ID (0x000f1000ul) 133026568Sse#define NCR_875_ID2 (0x008f1000ul) 133126568Sse#define NCR_885_ID (0x000d1000ul) 133226568Sse#define NCR_895_ID (0x000c1000ul) 133326568Sse#define NCR_896_ID (0x000b1000ul) 133456446Sgroudier#define NCR_895A_ID (0x00121000ul) 133556446Sgroudier#define NCR_1510D_ID (0x000a1000ul) 13363166Sse 13372432Sse 13382814Ssestatic char *ncr_name (ncb_p np) 13392814Sse{ 13402814Sse static char name[10]; 134141514Sarchie snprintf(name, sizeof(name), "ncr%d", np->unit); 13423533Sse return (name); 13432814Sse} 13447228Sse 13452432Sse/*========================================================== 13462432Sse** 13472432Sse** 13482432Sse** Scripts for NCR-Processor. 13492432Sse** 13502432Sse** Use ncr_script_bind for binding to physical addresses. 13512432Sse** 13522432Sse** 13532432Sse**========================================================== 13542432Sse** 13552435Sse** NADDR generates a reference to a field of the controller data. 13562432Sse** PADDR generates a reference to another part of the script. 13572435Sse** RADDR generates a reference to a script processor register. 13582435Sse** FADDR generates a reference to a script processor register 13592435Sse** with offset. 13602432Sse** 13612432Sse**---------------------------------------------------------- 13622432Sse*/ 13632432Sse 13642432Sse#define RELOC_SOFTC 0x40000000 13652432Sse#define RELOC_LABEL 0x50000000 13662432Sse#define RELOC_REGISTER 0x60000000 136727744Sse#define RELOC_KVAR 0x70000000 136827744Sse#define RELOC_LABELH 0x80000000 13692432Sse#define RELOC_MASK 0xf0000000 13702432Sse 13712432Sse#define NADDR(label) (RELOC_SOFTC | offsetof(struct ncb, label)) 13722432Sse#define PADDR(label) (RELOC_LABEL | offsetof(struct script, label)) 137327744Sse#define PADDRH(label) (RELOC_LABELH | offsetof(struct scripth, label)) 13742432Sse#define RADDR(label) (RELOC_REGISTER | REG(label)) 13752435Sse#define FADDR(label,ofs)(RELOC_REGISTER | ((REG(label))+(ofs))) 137627744Sse#define KVAR(which) (RELOC_KVAR | (which)) 13772432Sse 137834961Sphk#define KVAR_SECOND (0) 137934961Sphk#define KVAR_TICKS (1) 138027744Sse#define KVAR_NCR_CACHE (2) 138127744Sse 138227744Sse#define SCRIPT_KVAR_FIRST (0) 138327744Sse#define SCRIPT_KVAR_LAST (3) 138427744Sse 138527744Sse/* 138627744Sse * Kernel variables referenced in the scripts. 138727744Sse * THESE MUST ALL BE ALIGNED TO A 4-BYTE BOUNDARY. 138827744Sse */ 1389246037Sjhbstatic volatile void *script_kvars[] = 139034961Sphk { &time_second, &ticks, &ncr_cache }; 139127744Sse 13922432Ssestatic struct script script0 = { 13932432Sse/*--------------------------< START >-----------------------*/ { 13942432Sse /* 13952432Sse ** Claim to be still alive ... 13962432Sse */ 13972432Sse SCR_COPY (sizeof (((struct ncb *)0)->heartbeat)), 139834961Sphk KVAR (KVAR_SECOND), 13992432Sse NADDR (heartbeat), 14002432Sse /* 14012432Sse ** Make data structure address invalid. 14022432Sse ** clear SIGP. 14032432Sse */ 14042432Sse SCR_LOAD_REG (dsa, 0xff), 14052432Sse 0, 14062432Sse SCR_FROM_REG (ctest2), 14072432Sse 0, 14082432Sse}/*-------------------------< START0 >----------------------*/,{ 14092432Sse /* 14106705Sse ** Hook for interrupted GetConditionCode. 14112432Sse ** Will be patched to ... IFTRUE by 14126705Sse ** the interrupt handler. 14132432Sse */ 14142432Sse SCR_INT ^ IFFALSE (0), 14152814Sse SIR_SENSE_RESTART, 14167228Sse 14172432Sse}/*-------------------------< START1 >----------------------*/,{ 14182432Sse /* 14192432Sse ** Hook for stalled start queue. 14206705Sse ** Will be patched to IFTRUE by the interrupt handler. 14212432Sse */ 14222432Sse SCR_INT ^ IFFALSE (0), 14232814Sse SIR_STALL_RESTART, 14242432Sse /* 14252432Sse ** Then jump to a certain point in tryloop. 14262432Sse ** Due to the lack of indirect addressing the code 14272432Sse ** is self modifying here. 14282432Sse */ 14292432Sse SCR_JUMP, 14302432Sse}/*-------------------------< STARTPOS >--------------------*/,{ 143127744Sse PADDRH(tryloop), 14327228Sse 14332432Sse}/*-------------------------< TRYSEL >----------------------*/,{ 14342432Sse /* 14352432Sse ** Now: 14362432Sse ** DSA: Address of a Data Structure 14372432Sse ** or Address of the IDLE-Label. 14382432Sse ** 14392432Sse ** TEMP: Address of a script, which tries to 14402432Sse ** start the NEXT entry. 14412432Sse ** 14422432Sse ** Save the TEMP register into the SCRATCHA register. 14432432Sse ** Then copy the DSA to TEMP and RETURN. 14442432Sse ** This is kind of an indirect jump. 14452432Sse ** (The script processor has NO stack, so the 14462432Sse ** CALL is actually a jump and link, and the 14472432Sse ** RETURN is an indirect jump.) 14482432Sse ** 14492432Sse ** If the slot was empty, DSA contains the address 14502432Sse ** of the IDLE part of this script. The processor 14512432Sse ** jumps to IDLE and waits for a reselect. 14522432Sse ** It will wake up and try the same slot again 14532432Sse ** after the SIGP bit becomes set by the host. 14542432Sse ** 14552432Sse ** If the slot was not empty, DSA contains 145639247Sgibbs ** the address of the phys-part of a nccb. 14572432Sse ** The processor jumps to this address. 14582432Sse ** phys starts with head, 14592432Sse ** head starts with launch, 14602432Sse ** so actually the processor jumps to 14612432Sse ** the lauch part. 146210567Sse ** If the entry is scheduled for execution, 14632432Sse ** then launch contains a jump to SELECT. 14642432Sse ** If it's not scheduled, it contains a jump to IDLE. 14652432Sse */ 14662432Sse SCR_COPY (4), 14672432Sse RADDR (temp), 14682432Sse RADDR (scratcha), 14692432Sse SCR_COPY (4), 14702432Sse RADDR (dsa), 14712432Sse RADDR (temp), 14722432Sse SCR_RETURN, 14732432Sse 0 14747228Sse 14752432Sse}/*-------------------------< SKIP >------------------------*/,{ 14762432Sse /* 14772432Sse ** This entry has been canceled. 14782432Sse ** Next time use the next slot. 14792432Sse */ 14802432Sse SCR_COPY (4), 14812432Sse RADDR (scratcha), 14822432Sse PADDR (startpos), 14832432Sse /* 14842432Sse ** patch the launch field. 14852432Sse ** should look like an idle process. 14862432Sse */ 148727684Sse SCR_COPY_F (4), 14882432Sse RADDR (dsa), 14892432Sse PADDR (skip2), 14902432Sse SCR_COPY (8), 14912432Sse PADDR (idle), 14922432Sse}/*-------------------------< SKIP2 >-----------------------*/,{ 14932432Sse 0, 14942432Sse SCR_JUMP, 14952432Sse PADDR(start), 14962432Sse}/*-------------------------< IDLE >------------------------*/,{ 14972432Sse /* 14982432Sse ** Nothing to do? 14992432Sse ** Wait for reselect. 15002432Sse */ 15012432Sse SCR_JUMP, 15022432Sse PADDR(reselect), 15037228Sse 15042432Sse}/*-------------------------< SELECT >----------------------*/,{ 15052432Sse /* 15062432Sse ** DSA contains the address of a scheduled 15072432Sse ** data structure. 15082432Sse ** 15092432Sse ** SCRATCHA contains the address of the script, 15102432Sse ** which starts the next entry. 15112432Sse ** 15122432Sse ** Set Initiator mode. 15132432Sse ** 151410567Sse ** (Target mode is left as an exercise for the reader) 15152432Sse */ 15162432Sse 15172432Sse SCR_CLR (SCR_TRG), 15182432Sse 0, 15192814Sse SCR_LOAD_REG (HS_REG, 0xff), 15202432Sse 0, 15212432Sse 15222432Sse /* 15232432Sse ** And try to select this target. 15242432Sse */ 15252432Sse SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select), 15262432Sse PADDR (reselect), 15272432Sse 15282432Sse /* 15292432Sse ** Now there are 4 possibilities: 15302432Sse ** 1531160964Syar ** (1) The ncr loses arbitration. 15322432Sse ** This is ok, because it will try again, 15332432Sse ** when the bus becomes idle. 15342432Sse ** (But beware of the timeout function!) 15352432Sse ** 15362432Sse ** (2) The ncr is reselected. 15372432Sse ** Then the script processor takes the jump 15382432Sse ** to the RESELECT label. 15392432Sse ** 15402432Sse ** (3) The ncr completes the selection. 15412432Sse ** Then it will execute the next statement. 15422432Sse ** 15432432Sse ** (4) There is a selection timeout. 15446705Sse ** Then the ncr should interrupt the host and stop. 15452432Sse ** Unfortunately, it seems to continue execution 15462432Sse ** of the script. But it will fail with an 15476705Sse ** IID-interrupt on the next WHEN. 15482432Sse */ 15492432Sse 15502432Sse SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)), 15512432Sse 0, 15527228Sse 15532432Sse /* 15542432Sse ** Send the IDENTIFY and SIMPLE_TAG messages 155539247Sgibbs ** (and the MSG_EXT_SDTR message) 15562432Sse */ 15572432Sse SCR_MOVE_TBL ^ SCR_MSG_OUT, 15582432Sse offsetof (struct dsb, smsg), 155913364Sse#ifdef undef /* XXX better fail than try to deal with this ... */ 15602432Sse SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_OUT)), 15612432Sse -16, 156213364Sse#endif 15632432Sse SCR_CLR (SCR_ATN), 15642432Sse 0, 15652432Sse SCR_COPY (1), 15662432Sse RADDR (sfbr), 15672432Sse NADDR (lastmsg), 15682432Sse /* 15692432Sse ** Selection complete. 15702432Sse ** Next time use the next slot. 15712432Sse */ 15722432Sse SCR_COPY (4), 15732432Sse RADDR (scratcha), 15742432Sse PADDR (startpos), 15752432Sse}/*-------------------------< PREPARE >----------------------*/,{ 15762432Sse /* 15772432Sse ** The ncr doesn't have an indirect load 15782432Sse ** or store command. So we have to 15792432Sse ** copy part of the control block to a 15802432Sse ** fixed place, where we can access it. 15812432Sse ** 15822432Sse ** We patch the address part of a 15832432Sse ** COPY command with the DSA-register. 15842432Sse */ 158527684Sse SCR_COPY_F (4), 15862432Sse RADDR (dsa), 15872432Sse PADDR (loadpos), 15882432Sse /* 15892432Sse ** then we do the actual copy. 15902432Sse */ 15912432Sse SCR_COPY (sizeof (struct head)), 15922432Sse /* 15932432Sse ** continued after the next label ... 15942432Sse */ 15957228Sse 15962432Sse}/*-------------------------< LOADPOS >---------------------*/,{ 15972432Sse 0, 15982432Sse NADDR (header), 15992432Sse /* 160039247Sgibbs ** Mark this nccb as not scheduled. 16012432Sse */ 16022432Sse SCR_COPY (8), 16032432Sse PADDR (idle), 16042432Sse NADDR (header.launch), 16052432Sse /* 16062432Sse ** Set a time stamp for this selection 16072432Sse */ 160839386Sgibbs SCR_COPY (sizeof (ticks)), 160934961Sphk KVAR (KVAR_TICKS), 16102432Sse NADDR (header.stamp.select), 16112432Sse /* 16122432Sse ** load the savep (saved pointer) into 16132432Sse ** the TEMP register (actual pointer) 16142432Sse */ 16152432Sse SCR_COPY (4), 16162432Sse NADDR (header.savep), 16172432Sse RADDR (temp), 16182432Sse /* 16192432Sse ** Initialize the status registers 16202432Sse */ 16212432Sse SCR_COPY (4), 16222432Sse NADDR (header.status), 16232432Sse RADDR (scr0), 16247228Sse 16252432Sse}/*-------------------------< PREPARE2 >---------------------*/,{ 16262432Sse /* 16272432Sse ** Load the synchronous mode register 16282432Sse */ 16292814Sse SCR_COPY (1), 16302814Sse NADDR (sync_st), 16312814Sse RADDR (sxfer), 16322432Sse /* 16332814Sse ** Load the wide mode and timing register 16342814Sse */ 16352814Sse SCR_COPY (1), 16362814Sse NADDR (wide_st), 16372814Sse RADDR (scntl3), 16382814Sse /* 16392432Sse ** Initialize the msgout buffer with a NOOP message. 16402432Sse */ 164139247Sgibbs SCR_LOAD_REG (scratcha, MSG_NOOP), 16422432Sse 0, 16432432Sse SCR_COPY (1), 16442432Sse RADDR (scratcha), 16452432Sse NADDR (msgout), 16462432Sse SCR_COPY (1), 16472432Sse RADDR (scratcha), 16482432Sse NADDR (msgin), 16492432Sse /* 16502814Sse ** Message in phase ? 16512432Sse */ 16522814Sse SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 16532432Sse PADDR (dispatch), 16542432Sse /* 16552814Sse ** Extended or reject message ? 16562432Sse */ 16572814Sse SCR_FROM_REG (sbdl), 16582814Sse 0, 165939247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_EXTENDED)), 16602814Sse PADDR (msg_in), 166139247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_MESSAGE_REJECT)), 166227744Sse PADDRH (msg_reject), 16632814Sse /* 16642814Sse ** normal processing 16652814Sse */ 16662432Sse SCR_JUMP, 16672432Sse PADDR (dispatch), 16682432Sse}/*-------------------------< SETMSG >----------------------*/,{ 16692432Sse SCR_COPY (1), 16702432Sse RADDR (scratcha), 16712432Sse NADDR (msgout), 16722432Sse SCR_SET (SCR_ATN), 16732432Sse 0, 16742432Sse}/*-------------------------< CLRACK >----------------------*/,{ 16752432Sse /* 16762432Sse ** Terminate possible pending message phase. 16772432Sse */ 16782814Sse SCR_CLR (SCR_ACK), 16792432Sse 0, 16807228Sse 16812432Sse}/*-----------------------< DISPATCH >----------------------*/,{ 16822814Sse SCR_FROM_REG (HS_REG), 16832814Sse 0, 16842814Sse SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), 16852814Sse SIR_NEGO_FAILED, 16866179Sse /* 16876179Sse ** remove bogus output signals 16886179Sse */ 16896179Sse SCR_REG_REG (socl, SCR_AND, CACK|CATN), 16906179Sse 0, 16912432Sse SCR_RETURN ^ IFTRUE (WHEN (SCR_DATA_OUT)), 16922432Sse 0, 16932432Sse SCR_RETURN ^ IFTRUE (IF (SCR_DATA_IN)), 16942432Sse 0, 16952432Sse SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)), 16962432Sse PADDR (msg_out), 16972432Sse SCR_JUMP ^ IFTRUE (IF (SCR_MSG_IN)), 16982432Sse PADDR (msg_in), 16992432Sse SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)), 17002432Sse PADDR (command), 17012432Sse SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)), 17022432Sse PADDR (status), 17032432Sse /* 17042432Sse ** Discard one illegal phase byte, if required. 17052432Sse */ 17062814Sse SCR_LOAD_REG (scratcha, XE_BAD_PHASE), 17072814Sse 0, 17082814Sse SCR_COPY (1), 17092814Sse RADDR (scratcha), 17102814Sse NADDR (xerr_st), 17112432Sse SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_OUT)), 17122432Sse 8, 17132432Sse SCR_MOVE_ABS (1) ^ SCR_ILG_OUT, 17142432Sse NADDR (scratch), 17152432Sse SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_IN)), 17162432Sse 8, 17172432Sse SCR_MOVE_ABS (1) ^ SCR_ILG_IN, 17182432Sse NADDR (scratch), 17192432Sse SCR_JUMP, 17202432Sse PADDR (dispatch), 17217228Sse 17222432Sse}/*-------------------------< NO_DATA >--------------------*/,{ 17232432Sse /* 17242432Sse ** The target wants to tranfer too much data 17252432Sse ** or in the wrong direction. 17262814Sse ** Remember that in extended error. 17272432Sse */ 17282814Sse SCR_LOAD_REG (scratcha, XE_EXTRA_DATA), 17292432Sse 0, 17302432Sse SCR_COPY (1), 17312432Sse RADDR (scratcha), 17322814Sse NADDR (xerr_st), 17332432Sse /* 17342432Sse ** Discard one data byte, if required. 17352432Sse */ 17362432Sse SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)), 17372432Sse 8, 17382432Sse SCR_MOVE_ABS (1) ^ SCR_DATA_OUT, 17392432Sse NADDR (scratch), 17402432Sse SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)), 17412432Sse 8, 17422432Sse SCR_MOVE_ABS (1) ^ SCR_DATA_IN, 17432432Sse NADDR (scratch), 17442432Sse /* 17452432Sse ** .. and repeat as required. 17462432Sse */ 17472432Sse SCR_CALL, 17482432Sse PADDR (dispatch), 17492432Sse SCR_JUMP, 17502432Sse PADDR (no_data), 17512432Sse}/*-------------------------< CHECKATN >--------------------*/,{ 17522432Sse /* 17532432Sse ** If AAP (bit 1 of scntl0 register) is set 17542432Sse ** and a parity error is detected, 17552432Sse ** the script processor asserts ATN. 17562432Sse ** 17572432Sse ** The target should switch to a MSG_OUT phase 17582432Sse ** to get the message. 17592432Sse */ 17602432Sse SCR_FROM_REG (socl), 17612432Sse 0, 17622432Sse SCR_JUMP ^ IFFALSE (MASK (CATN, CATN)), 17632432Sse PADDR (dispatch), 17642432Sse /* 17652432Sse ** count it 17662432Sse */ 17672814Sse SCR_REG_REG (PS_REG, SCR_ADD, 1), 17682432Sse 0, 17692432Sse /* 177039247Sgibbs ** Prepare a MSG_INITIATOR_DET_ERR message 17712432Sse ** (initiator detected error). 17722432Sse ** The target should retry the transfer. 17732432Sse */ 177439247Sgibbs SCR_LOAD_REG (scratcha, MSG_INITIATOR_DET_ERR), 17752432Sse 0, 17762432Sse SCR_JUMP, 17772432Sse PADDR (setmsg), 17787228Sse 17792432Sse}/*-------------------------< COMMAND >--------------------*/,{ 17802432Sse /* 17812432Sse ** If this is not a GETCC transfer ... 17822432Sse */ 17832814Sse SCR_FROM_REG (SS_REG), 17842432Sse 0, 178539247Sgibbs/*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (SCSI_STATUS_CHECK_COND)), 17862432Sse 28, 17872432Sse /* 17882432Sse ** ... set a timestamp ... 17892432Sse */ 179039386Sgibbs SCR_COPY (sizeof (ticks)), 179134961Sphk KVAR (KVAR_TICKS), 17922432Sse NADDR (header.stamp.command), 17932432Sse /* 17942432Sse ** ... and send the command 17952432Sse */ 17962432Sse SCR_MOVE_TBL ^ SCR_COMMAND, 17972432Sse offsetof (struct dsb, cmd), 17982432Sse SCR_JUMP, 17992432Sse PADDR (dispatch), 18002432Sse /* 18012432Sse ** Send the GETCC command 18022432Sse */ 18037250Sse/*>>>*/ SCR_MOVE_TBL ^ SCR_COMMAND, 18047250Sse offsetof (struct dsb, scmd), 18052432Sse SCR_JUMP, 18062432Sse PADDR (dispatch), 18077228Sse 18082432Sse}/*-------------------------< STATUS >--------------------*/,{ 18092432Sse /* 18102432Sse ** set the timestamp. 18112432Sse */ 181239386Sgibbs SCR_COPY (sizeof (ticks)), 181334961Sphk KVAR (KVAR_TICKS), 18142432Sse NADDR (header.stamp.status), 18152432Sse /* 18162432Sse ** If this is a GETCC transfer, 18172432Sse */ 18182814Sse SCR_FROM_REG (SS_REG), 18192432Sse 0, 182039247Sgibbs/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (SCSI_STATUS_CHECK_COND)), 18212814Sse 40, 18222432Sse /* 18232432Sse ** get the status 18242432Sse */ 18252432Sse SCR_MOVE_ABS (1) ^ SCR_STATUS, 18262432Sse NADDR (scratch), 18272432Sse /* 18282814Sse ** Save status to scsi_status. 18292432Sse ** Mark as complete. 18302432Sse ** And wait for disconnect. 18312432Sse */ 18322814Sse SCR_TO_REG (SS_REG), 18332432Sse 0, 183439247Sgibbs SCR_REG_REG (SS_REG, SCR_OR, SCSI_STATUS_SENSE), 18352432Sse 0, 18362814Sse SCR_LOAD_REG (HS_REG, HS_COMPLETE), 18372814Sse 0, 18382432Sse SCR_JUMP, 18392432Sse PADDR (checkatn), 18402432Sse /* 18412432Sse ** If it was no GETCC transfer, 18422432Sse ** save the status to scsi_status. 18432432Sse */ 18442432Sse/*>>>*/ SCR_MOVE_ABS (1) ^ SCR_STATUS, 18452432Sse NADDR (scratch), 18462814Sse SCR_TO_REG (SS_REG), 18472432Sse 0, 18482432Sse /* 18492432Sse ** if it was no check condition ... 18502432Sse */ 185139247Sgibbs SCR_JUMP ^ IFTRUE (DATA (SCSI_STATUS_CHECK_COND)), 18522432Sse PADDR (checkatn), 18532432Sse /* 18542432Sse ** ... mark as complete. 18552432Sse */ 18562814Sse SCR_LOAD_REG (HS_REG, HS_COMPLETE), 18572432Sse 0, 18582432Sse SCR_JUMP, 18592432Sse PADDR (checkatn), 18607228Sse 18612432Sse}/*-------------------------< MSG_IN >--------------------*/,{ 18622432Sse /* 18632432Sse ** Get the first byte of the message 18642432Sse ** and save it to SCRATCHA. 18652432Sse ** 18662432Sse ** The script processor doesn't negate the 18672432Sse ** ACK signal after this transfer. 18682432Sse */ 18692432Sse SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 18702432Sse NADDR (msgin[0]), 18712432Sse /* 18722432Sse ** Check for message parity error. 18732432Sse */ 18742432Sse SCR_TO_REG (scratcha), 18752432Sse 0, 18762432Sse SCR_FROM_REG (socl), 18772432Sse 0, 18782432Sse SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), 187927744Sse PADDRH (msg_parity), 18802432Sse SCR_FROM_REG (scratcha), 18812432Sse 0, 18822432Sse /* 18832432Sse ** Parity was ok, handle this message. 18842432Sse */ 188539247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_CMDCOMPLETE)), 18862432Sse PADDR (complete), 188739247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_SAVEDATAPOINTER)), 18882432Sse PADDR (save_dp), 188939247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_RESTOREPOINTERS)), 18902432Sse PADDR (restore_dp), 189139247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_DISCONNECT)), 18922432Sse PADDR (disconnect), 189339247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_EXTENDED)), 189427744Sse PADDRH (msg_extended), 189539247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_NOOP)), 18962814Sse PADDR (clrack), 189739247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_MESSAGE_REJECT)), 189827744Sse PADDRH (msg_reject), 189939247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_IGN_WIDE_RESIDUE)), 190027744Sse PADDRH (msg_ign_residue), 19012432Sse /* 19022432Sse ** Rest of the messages left as 19032432Sse ** an exercise ... 19042432Sse ** 19052432Sse ** Unimplemented messages: 19062432Sse ** fall through to MSG_BAD. 19072432Sse */ 19082432Sse}/*-------------------------< MSG_BAD >------------------*/,{ 19092432Sse /* 19102432Sse ** unimplemented message - reject it. 19112432Sse */ 19122432Sse SCR_INT, 19132814Sse SIR_REJECT_SENT, 191439247Sgibbs SCR_LOAD_REG (scratcha, MSG_MESSAGE_REJECT), 19152432Sse 0, 19162432Sse SCR_JUMP, 19172432Sse PADDR (setmsg), 19187228Sse 19192432Sse}/*-------------------------< COMPLETE >-----------------*/,{ 19202432Sse /* 19212432Sse ** Complete message. 19222432Sse ** 19232814Sse ** If it's not the get condition code, 19242814Sse ** copy TEMP register to LASTP in header. 19252814Sse */ 19262814Sse SCR_FROM_REG (SS_REG), 19272814Sse 0, 192839247Sgibbs/*<<<*/ SCR_JUMPR ^ IFTRUE (MASK (SCSI_STATUS_SENSE, SCSI_STATUS_SENSE)), 19292814Sse 12, 19302814Sse SCR_COPY (4), 19312814Sse RADDR (temp), 19322814Sse NADDR (header.lastp), 19332814Sse/*>>>*/ /* 19342432Sse ** When we terminate the cycle by clearing ACK, 19352432Sse ** the target may disconnect immediately. 19362432Sse ** 19372432Sse ** We don't want to be told of an 19382432Sse ** "unexpected disconnect", 19392432Sse ** so we disable this feature. 19402432Sse */ 19412432Sse SCR_REG_REG (scntl2, SCR_AND, 0x7f), 19422432Sse 0, 19432432Sse /* 19442432Sse ** Terminate cycle ... 19452432Sse */ 19466215Sse SCR_CLR (SCR_ACK|SCR_ATN), 19472432Sse 0, 19482432Sse /* 19492432Sse ** ... and wait for the disconnect. 19502432Sse */ 19512432Sse SCR_WAIT_DISC, 19522432Sse 0, 19532432Sse}/*-------------------------< CLEANUP >-------------------*/,{ 19542432Sse /* 195539247Sgibbs ** dsa: Pointer to nccb 195639247Sgibbs ** or xxxxxxFF (no nccb) 19572432Sse ** 19582814Sse ** HS_REG: Host-Status (<>0!) 19592432Sse */ 19602432Sse SCR_FROM_REG (dsa), 19612432Sse 0, 19622432Sse SCR_JUMP ^ IFTRUE (DATA (0xff)), 19632432Sse PADDR (signal), 19642432Sse /* 19652432Sse ** dsa is valid. 19662432Sse ** save the status registers 19672432Sse */ 19682432Sse SCR_COPY (4), 19692432Sse RADDR (scr0), 19702432Sse NADDR (header.status), 19712432Sse /* 197239247Sgibbs ** and copy back the header to the nccb. 19732432Sse */ 197427684Sse SCR_COPY_F (4), 19752432Sse RADDR (dsa), 19762814Sse PADDR (cleanup0), 19772432Sse SCR_COPY (sizeof (struct head)), 19782432Sse NADDR (header), 19792814Sse}/*-------------------------< CLEANUP0 >--------------------*/,{ 19802432Sse 0, 19817228Sse 19822432Sse /* 19832432Sse ** If command resulted in "check condition" 19842432Sse ** status and is not yet completed, 19852432Sse ** try to get the condition code. 19862432Sse */ 19872814Sse SCR_FROM_REG (HS_REG), 19882432Sse 0, 19892814Sse/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (0, HS_DONEMASK)), 19902432Sse 16, 19912814Sse SCR_FROM_REG (SS_REG), 19922432Sse 0, 199339247Sgibbs SCR_JUMP ^ IFTRUE (DATA (SCSI_STATUS_CHECK_COND)), 199427744Sse PADDRH(getcc2), 19952432Sse}/*-------------------------< SIGNAL >----------------------*/,{ 19962432Sse /* 19972432Sse ** if status = queue full, 19982432Sse ** reinsert in startqueue and stall queue. 19992432Sse */ 200039247Sgibbs/*>>>*/ SCR_FROM_REG (SS_REG), 20012432Sse 0, 200239247Sgibbs SCR_INT ^ IFTRUE (DATA (SCSI_STATUS_QUEUE_FULL)), 20032814Sse SIR_STALL_QUEUE, 200439247Sgibbs /* 200539247Sgibbs ** And make the DSA register invalid. 200639247Sgibbs */ 200739247Sgibbs SCR_LOAD_REG (dsa, 0xff), /* invalid */ 200839247Sgibbs 0, 20092432Sse /* 20102432Sse ** if job completed ... 20112432Sse */ 20122814Sse SCR_FROM_REG (HS_REG), 20132432Sse 0, 20142432Sse /* 20152432Sse ** ... signal completion to the host 20162432Sse */ 20172814Sse SCR_INT_FLY ^ IFFALSE (MASK (0, HS_DONEMASK)), 20182432Sse 0, 20192432Sse /* 20202432Sse ** Auf zu neuen Schandtaten! 20212432Sse */ 20222432Sse SCR_JUMP, 20232432Sse PADDR(start), 20247228Sse 20252432Sse}/*-------------------------< SAVE_DP >------------------*/,{ 20262432Sse /* 20272432Sse ** SAVE_DP message: 20282432Sse ** Copy TEMP register to SAVEP in header. 20292432Sse */ 20302432Sse SCR_COPY (4), 20312432Sse RADDR (temp), 20322432Sse NADDR (header.savep), 20332432Sse SCR_JUMP, 20342432Sse PADDR (clrack), 20352432Sse}/*-------------------------< RESTORE_DP >---------------*/,{ 20362432Sse /* 20372432Sse ** RESTORE_DP message: 20382432Sse ** Copy SAVEP in header to TEMP register. 20392432Sse */ 20402432Sse SCR_COPY (4), 20412432Sse NADDR (header.savep), 20422432Sse RADDR (temp), 20432432Sse SCR_JUMP, 20442432Sse PADDR (clrack), 20457228Sse 20462432Sse}/*-------------------------< DISCONNECT >---------------*/,{ 20472432Sse /* 20482814Sse ** If QUIRK_AUTOSAVE is set, 2049108470Sschweikh ** do a "save pointer" operation. 20502814Sse */ 20512814Sse SCR_FROM_REG (QU_REG), 20522814Sse 0, 20532814Sse/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)), 20542814Sse 12, 20552814Sse /* 20562814Sse ** like SAVE_DP message: 20572814Sse ** Copy TEMP register to SAVEP in header. 20582814Sse */ 20592814Sse SCR_COPY (4), 20602814Sse RADDR (temp), 20612814Sse NADDR (header.savep), 20622814Sse/*>>>*/ /* 20632814Sse ** Check if temp==savep or temp==goalp: 20642814Sse ** if not, log a missing save pointer message. 206510567Sse ** In fact, it's a comparison mod 256. 20662814Sse ** 20672814Sse ** Hmmm, I hadn't thought that I would be urged to 20682814Sse ** write this kind of ugly self modifying code. 20692814Sse ** 20702814Sse ** It's unbelievable, but the ncr53c8xx isn't able 20712814Sse ** to subtract one register from another. 20722814Sse */ 20732814Sse SCR_FROM_REG (temp), 20742814Sse 0, 20752814Sse /* 20762814Sse ** You are not expected to understand this .. 207710567Sse ** 207810567Sse ** CAUTION: only little endian architectures supported! XXX 20792814Sse */ 208027684Sse SCR_COPY_F (1), 20812814Sse NADDR (header.savep), 20822814Sse PADDR (disconnect0), 20832814Sse}/*-------------------------< DISCONNECT0 >--------------*/,{ 20842814Sse/*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (1)), 20852814Sse 20, 20862814Sse /* 20872814Sse ** neither this 20882814Sse */ 208927684Sse SCR_COPY_F (1), 20902814Sse NADDR (header.goalp), 20912814Sse PADDR (disconnect1), 20922814Sse}/*-------------------------< DISCONNECT1 >--------------*/,{ 20932814Sse SCR_INT ^ IFFALSE (DATA (1)), 20942814Sse SIR_MISSING_SAVE, 20952814Sse/*>>>*/ 20967228Sse 20972814Sse /* 20982814Sse ** DISCONNECTing ... 20992814Sse ** 21006132Sdg ** disable the "unexpected disconnect" feature, 21016132Sdg ** and remove the ACK signal. 21022432Sse */ 21032432Sse SCR_REG_REG (scntl2, SCR_AND, 0x7f), 21042432Sse 0, 21056215Sse SCR_CLR (SCR_ACK|SCR_ATN), 21062432Sse 0, 21072432Sse /* 21082432Sse ** Wait for the disconnect. 21092432Sse */ 21102432Sse SCR_WAIT_DISC, 21112432Sse 0, 21122432Sse /* 21132432Sse ** Profiling: 21142432Sse ** Set a time stamp, 21152432Sse ** and count the disconnects. 21162432Sse */ 211739386Sgibbs SCR_COPY (sizeof (ticks)), 211834961Sphk KVAR (KVAR_TICKS), 21192432Sse NADDR (header.stamp.disconnect), 21202432Sse SCR_COPY (4), 21212432Sse NADDR (disc_phys), 21222432Sse RADDR (temp), 21232432Sse SCR_REG_REG (temp, SCR_ADD, 0x01), 21242432Sse 0, 21252432Sse SCR_COPY (4), 21262432Sse RADDR (temp), 21272432Sse NADDR (disc_phys), 21282432Sse /* 21292432Sse ** Status is: DISCONNECTED. 21302432Sse */ 21312814Sse SCR_LOAD_REG (HS_REG, HS_DISCONNECT), 21322432Sse 0, 21332432Sse SCR_JUMP, 21342432Sse PADDR (cleanup), 21357228Sse 21362432Sse}/*-------------------------< MSG_OUT >-------------------*/,{ 21372432Sse /* 21382432Sse ** The target requests a message. 21392432Sse */ 21402432Sse SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, 21412432Sse NADDR (msgout), 21422432Sse SCR_COPY (1), 21432432Sse RADDR (sfbr), 21442432Sse NADDR (lastmsg), 21452432Sse /* 21462432Sse ** If it was no ABORT message ... 21472432Sse */ 214839247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_ABORT)), 214927744Sse PADDRH (msg_out_abort), 21502432Sse /* 21512432Sse ** ... wait for the next phase 21522432Sse ** if it's a message out, send it again, ... 21532432Sse */ 21542432Sse SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)), 21552432Sse PADDR (msg_out), 21562432Sse}/*-------------------------< MSG_OUT_DONE >--------------*/,{ 21572432Sse /* 21582432Sse ** ... else clear the message ... 21592432Sse */ 216039247Sgibbs SCR_LOAD_REG (scratcha, MSG_NOOP), 21612432Sse 0, 21622432Sse SCR_COPY (4), 21632432Sse RADDR (scratcha), 21642432Sse NADDR (msgout), 21652432Sse /* 21662432Sse ** ... and process the next phase 21672432Sse */ 21682432Sse SCR_JUMP, 21692432Sse PADDR (dispatch), 21707228Sse 21712432Sse}/*------------------------< BADGETCC >---------------------*/,{ 21722432Sse /* 21732432Sse ** If SIGP was set, clear it and try again. 21742432Sse */ 21752432Sse SCR_FROM_REG (ctest2), 21762432Sse 0, 21772432Sse SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), 217827744Sse PADDRH (getcc2), 21792432Sse SCR_INT, 21802814Sse SIR_SENSE_FAILED, 21812432Sse}/*-------------------------< RESELECT >--------------------*/,{ 21822432Sse /* 218327684Sse ** This NOP will be patched with LED OFF 218427684Sse ** SCR_REG_REG (gpreg, SCR_OR, 0x01) 218527684Sse */ 218627684Sse SCR_NO_OP, 218727684Sse 0, 218827684Sse 218927684Sse /* 21902432Sse ** make the DSA invalid. 21912432Sse */ 21922432Sse SCR_LOAD_REG (dsa, 0xff), 21932432Sse 0, 21942432Sse SCR_CLR (SCR_TRG), 21952432Sse 0, 21962432Sse /* 21972432Sse ** Sleep waiting for a reselection. 21982432Sse ** If SIGP is set, special treatment. 21992432Sse ** 22002432Sse ** Zu allem bereit .. 22012432Sse */ 22022432Sse SCR_WAIT_RESEL, 22032432Sse PADDR(reselect2), 220427684Sse}/*-------------------------< RESELECT1 >--------------------*/,{ 22052432Sse /* 220627684Sse ** This NOP will be patched with LED ON 220727684Sse ** SCR_REG_REG (gpreg, SCR_AND, 0xfe) 220827684Sse */ 220927684Sse SCR_NO_OP, 221027684Sse 0, 221127684Sse /* 22122432Sse ** ... zu nichts zu gebrauchen ? 22132432Sse ** 22142432Sse ** load the target id into the SFBR 22152432Sse ** and jump to the control block. 22162432Sse ** 22172432Sse ** Look at the declarations of 22182432Sse ** - struct ncb 22192432Sse ** - struct tcb 22202432Sse ** - struct lcb 222139247Sgibbs ** - struct nccb 22222432Sse ** to understand what's going on. 22232432Sse */ 222418875Sse SCR_REG_SFBR (ssid, SCR_AND, 0x8F), 22252432Sse 0, 222646843Sse SCR_TO_REG (sdid), 22272432Sse 0, 22282432Sse SCR_JUMP, 22292432Sse NADDR (jump_tcb), 22302432Sse}/*-------------------------< RESELECT2 >-------------------*/,{ 22312432Sse /* 223227684Sse ** This NOP will be patched with LED ON 223327684Sse ** SCR_REG_REG (gpreg, SCR_AND, 0xfe) 223427684Sse */ 223527684Sse SCR_NO_OP, 223627684Sse 0, 223727684Sse /* 22382432Sse ** If it's not connected :( 22396705Sse ** -> interrupted by SIGP bit. 22402432Sse ** Jump to start. 22412432Sse */ 22422432Sse SCR_FROM_REG (ctest2), 22432432Sse 0, 22442432Sse SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), 22452432Sse PADDR (start), 22462432Sse SCR_JUMP, 22472432Sse PADDR (reselect), 22487228Sse 22492432Sse}/*-------------------------< RESEL_TMP >-------------------*/,{ 22502432Sse /* 22512432Sse ** The return address in TEMP 22522432Sse ** is in fact the data structure address, 22532432Sse ** so copy it to the DSA register. 22542432Sse */ 22552432Sse SCR_COPY (4), 22562432Sse RADDR (temp), 22572432Sse RADDR (dsa), 22582432Sse SCR_JUMP, 22592432Sse PADDR (prepare), 22602432Sse 22612432Sse}/*-------------------------< RESEL_LUN >-------------------*/,{ 22622432Sse /* 22632432Sse ** come back to this point 22642432Sse ** to get an IDENTIFY message 22652432Sse ** Wait for a msg_in phase. 22662432Sse */ 22672432Sse/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), 22682432Sse 48, 22692432Sse /* 22702432Sse ** message phase 22712432Sse ** It's not a sony, it's a trick: 22722432Sse ** read the data without acknowledging it. 22732432Sse */ 22742432Sse SCR_FROM_REG (sbdl), 22752432Sse 0, 227639247Sgibbs/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (MSG_IDENTIFYFLAG, 0x98)), 22772432Sse 32, 22782432Sse /* 22792432Sse ** It WAS an Identify message. 22802432Sse ** get it and ack it! 22812432Sse */ 22822432Sse SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 22832432Sse NADDR (msgin), 22842432Sse SCR_CLR (SCR_ACK), 22852432Sse 0, 22862432Sse /* 22877228Sse ** Mask out the lun. 22882432Sse */ 22892432Sse SCR_REG_REG (sfbr, SCR_AND, 0x07), 22902432Sse 0, 22912432Sse SCR_RETURN, 22922432Sse 0, 22932432Sse /* 22942432Sse ** No message phase or no IDENTIFY message: 22952432Sse ** return 0. 22962432Sse */ 22972432Sse/*>>>*/ SCR_LOAD_SFBR (0), 22982432Sse 0, 22992432Sse SCR_RETURN, 23002432Sse 0, 23017228Sse 23022432Sse}/*-------------------------< RESEL_TAG >-------------------*/,{ 23032432Sse /* 23042432Sse ** come back to this point 23052432Sse ** to get a SIMPLE_TAG message 23062432Sse ** Wait for a MSG_IN phase. 23072432Sse */ 23082432Sse/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), 23092432Sse 64, 23102432Sse /* 23112432Sse ** message phase 23122432Sse ** It's a trick - read the data 23132432Sse ** without acknowledging it. 23142432Sse */ 23152432Sse SCR_FROM_REG (sbdl), 23162432Sse 0, 231739247Sgibbs/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (MSG_SIMPLE_Q_TAG)), 23182432Sse 48, 23192432Sse /* 23202432Sse ** It WAS a SIMPLE_TAG message. 23212432Sse ** get it and ack it! 23222432Sse */ 23232432Sse SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 23242432Sse NADDR (msgin), 23252432Sse SCR_CLR (SCR_ACK), 23262432Sse 0, 23272432Sse /* 23282432Sse ** Wait for the second byte (the tag) 23292432Sse */ 23302432Sse/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), 23312432Sse 24, 23322432Sse /* 23332432Sse ** Get it and ack it! 23342432Sse */ 23352432Sse SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 23362432Sse NADDR (msgin), 23372432Sse SCR_CLR (SCR_ACK|SCR_CARRY), 23382432Sse 0, 23392432Sse SCR_RETURN, 23402432Sse 0, 23412432Sse /* 23422432Sse ** No message phase or no SIMPLE_TAG message 23432432Sse ** or no second byte: return 0. 23442432Sse */ 23452432Sse/*>>>*/ SCR_LOAD_SFBR (0), 23462432Sse 0, 23472432Sse SCR_SET (SCR_CARRY), 23482432Sse 0, 23492432Sse SCR_RETURN, 23502432Sse 0, 23517228Sse 23522432Sse}/*-------------------------< DATA_IN >--------------------*/,{ 23532432Sse/* 23542432Sse** Because the size depends on the 23552432Sse** #define MAX_SCATTER parameter, 23562432Sse** it is filled in at runtime. 23572432Sse** 23582432Sse** SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), 23592432Sse** PADDR (no_data), 236039386Sgibbs** SCR_COPY (sizeof (ticks)), 236134961Sphk** KVAR (KVAR_TICKS), 23622432Sse** NADDR (header.stamp.data), 23632432Sse** SCR_MOVE_TBL ^ SCR_DATA_IN, 23642432Sse** offsetof (struct dsb, data[ 0]), 23652432Sse** 23662432Sse** ##===========< i=1; i<MAX_SCATTER >========= 23672432Sse** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)), 23682432Sse** || PADDR (checkatn), 23692432Sse** || SCR_MOVE_TBL ^ SCR_DATA_IN, 23702432Sse** || offsetof (struct dsb, data[ i]), 23712432Sse** ##========================================== 23722432Sse** 23732432Sse** SCR_CALL, 23742432Sse** PADDR (checkatn), 23752432Sse** SCR_JUMP, 23762432Sse** PADDR (no_data), 23772432Sse*/ 23782432Sse0 23792432Sse}/*-------------------------< DATA_OUT >-------------------*/,{ 23802432Sse/* 23812432Sse** Because the size depends on the 23822432Sse** #define MAX_SCATTER parameter, 23832432Sse** it is filled in at runtime. 23842432Sse** 238527744Sse** SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_OUT)), 23862432Sse** PADDR (no_data), 238739386Sgibbs** SCR_COPY (sizeof (ticks)), 238834961Sphk** KVAR (KVAR_TICKS), 23892432Sse** NADDR (header.stamp.data), 23902432Sse** SCR_MOVE_TBL ^ SCR_DATA_OUT, 23912432Sse** offsetof (struct dsb, data[ 0]), 23922432Sse** 23932432Sse** ##===========< i=1; i<MAX_SCATTER >========= 23942432Sse** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)), 23952432Sse** || PADDR (dispatch), 23962432Sse** || SCR_MOVE_TBL ^ SCR_DATA_OUT, 23972432Sse** || offsetof (struct dsb, data[ i]), 23982432Sse** ##========================================== 23992432Sse** 24002432Sse** SCR_CALL, 24012432Sse** PADDR (dispatch), 24022432Sse** SCR_JUMP, 24032432Sse** PADDR (no_data), 24042432Sse** 24052432Sse**--------------------------------------------------------- 24062432Sse*/ 240736735Sdfr(u_long)0 24087228Sse 240927744Sse}/*--------------------------------------------------------*/ 241027744Sse}; 241127744Sse 241227744Sse 241327744Ssestatic struct scripth scripth0 = { 241427744Sse/*-------------------------< TRYLOOP >---------------------*/{ 241527744Sse/* 241627744Sse** Load an entry of the start queue into dsa 241727744Sse** and try to start it by jumping to TRYSEL. 241827744Sse** 241927744Sse** Because the size depends on the 242027744Sse** #define MAX_START parameter, it is filled 242127744Sse** in at runtime. 242227744Sse** 242327744Sse**----------------------------------------------------------- 242427744Sse** 242527744Sse** ##===========< I=0; i<MAX_START >=========== 242627744Sse** || SCR_COPY (4), 242727744Sse** || NADDR (squeue[i]), 242827744Sse** || RADDR (dsa), 242927744Sse** || SCR_CALL, 243027744Sse** || PADDR (trysel), 243127744Sse** ##========================================== 243227744Sse** 243327744Sse** SCR_JUMP, 243427744Sse** PADDRH(tryloop), 243527744Sse** 243627744Sse**----------------------------------------------------------- 243727744Sse*/ 243827744Sse0 243927744Sse}/*-------------------------< MSG_PARITY >---------------*/,{ 244027744Sse /* 244127744Sse ** count it 244227744Sse */ 244327744Sse SCR_REG_REG (PS_REG, SCR_ADD, 0x01), 244427744Sse 0, 244527744Sse /* 244627744Sse ** send a "message parity error" message. 244727744Sse */ 244839247Sgibbs SCR_LOAD_REG (scratcha, MSG_PARITY_ERROR), 244927744Sse 0, 245027744Sse SCR_JUMP, 245127744Sse PADDR (setmsg), 245239247Sgibbs}/*-------------------------< MSG_MESSAGE_REJECT >---------------*/,{ 245327744Sse /* 245427744Sse ** If a negotiation was in progress, 245527744Sse ** negotiation failed. 245627744Sse */ 245727744Sse SCR_FROM_REG (HS_REG), 245827744Sse 0, 245927744Sse SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), 246027744Sse SIR_NEGO_FAILED, 246127744Sse /* 246227744Sse ** else make host log this message 246327744Sse */ 246427744Sse SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)), 246527744Sse SIR_REJECT_RECEIVED, 246627744Sse SCR_JUMP, 246727744Sse PADDR (clrack), 246827744Sse 246927744Sse}/*-------------------------< MSG_IGN_RESIDUE >----------*/,{ 247027744Sse /* 247127744Sse ** Terminate cycle 247227744Sse */ 247327744Sse SCR_CLR (SCR_ACK), 247427744Sse 0, 247527744Sse SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 247627744Sse PADDR (dispatch), 247727744Sse /* 247827744Sse ** get residue size. 247927744Sse */ 248027744Sse SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 248127744Sse NADDR (msgin[1]), 248227744Sse /* 248327744Sse ** Check for message parity error. 248427744Sse */ 248527744Sse SCR_TO_REG (scratcha), 248627744Sse 0, 248727744Sse SCR_FROM_REG (socl), 248827744Sse 0, 248927744Sse SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), 249027744Sse PADDRH (msg_parity), 249127744Sse SCR_FROM_REG (scratcha), 249227744Sse 0, 249327744Sse /* 249427744Sse ** Size is 0 .. ignore message. 249527744Sse */ 249627744Sse SCR_JUMP ^ IFTRUE (DATA (0)), 249727744Sse PADDR (clrack), 249827744Sse /* 249927744Sse ** Size is not 1 .. have to interrupt. 250027744Sse */ 250127744Sse/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (1)), 250227744Sse 40, 250327744Sse /* 250427744Sse ** Check for residue byte in swide register 250527744Sse */ 250627744Sse SCR_FROM_REG (scntl2), 250727744Sse 0, 250827744Sse/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)), 250927744Sse 16, 251027744Sse /* 251127744Sse ** There IS data in the swide register. 251227744Sse ** Discard it. 251327744Sse */ 251427744Sse SCR_REG_REG (scntl2, SCR_OR, WSR), 251527744Sse 0, 251627744Sse SCR_JUMP, 251727744Sse PADDR (clrack), 251827744Sse /* 251927744Sse ** Load again the size to the sfbr register. 252027744Sse */ 252127744Sse/*>>>*/ SCR_FROM_REG (scratcha), 252227744Sse 0, 252327744Sse/*>>>*/ SCR_INT, 252427744Sse SIR_IGN_RESIDUE, 252527744Sse SCR_JUMP, 252627744Sse PADDR (clrack), 252727744Sse 252827744Sse}/*-------------------------< MSG_EXTENDED >-------------*/,{ 252927744Sse /* 253027744Sse ** Terminate cycle 253127744Sse */ 253227744Sse SCR_CLR (SCR_ACK), 253327744Sse 0, 253427744Sse SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 253527744Sse PADDR (dispatch), 253627744Sse /* 253727744Sse ** get length. 253827744Sse */ 253927744Sse SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 254027744Sse NADDR (msgin[1]), 254127744Sse /* 254227744Sse ** Check for message parity error. 254327744Sse */ 254427744Sse SCR_TO_REG (scratcha), 254527744Sse 0, 254627744Sse SCR_FROM_REG (socl), 254727744Sse 0, 254827744Sse SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), 254927744Sse PADDRH (msg_parity), 255027744Sse SCR_FROM_REG (scratcha), 255127744Sse 0, 255227744Sse /* 255327744Sse */ 255427744Sse SCR_JUMP ^ IFTRUE (DATA (3)), 255527744Sse PADDRH (msg_ext_3), 255627744Sse SCR_JUMP ^ IFFALSE (DATA (2)), 255727744Sse PADDR (msg_bad), 255827744Sse}/*-------------------------< MSG_EXT_2 >----------------*/,{ 255927744Sse SCR_CLR (SCR_ACK), 256027744Sse 0, 256127744Sse SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 256227744Sse PADDR (dispatch), 256327744Sse /* 256427744Sse ** get extended message code. 256527744Sse */ 256627744Sse SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 256727744Sse NADDR (msgin[2]), 256827744Sse /* 256927744Sse ** Check for message parity error. 257027744Sse */ 257127744Sse SCR_TO_REG (scratcha), 257227744Sse 0, 257327744Sse SCR_FROM_REG (socl), 257427744Sse 0, 257527744Sse SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), 257627744Sse PADDRH (msg_parity), 257727744Sse SCR_FROM_REG (scratcha), 257827744Sse 0, 257939247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_EXT_WDTR)), 258027744Sse PADDRH (msg_wdtr), 258127744Sse /* 258227744Sse ** unknown extended message 258327744Sse */ 258427744Sse SCR_JUMP, 258527744Sse PADDR (msg_bad) 258627744Sse}/*-------------------------< MSG_WDTR >-----------------*/,{ 258727744Sse SCR_CLR (SCR_ACK), 258827744Sse 0, 258927744Sse SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 259027744Sse PADDR (dispatch), 259127744Sse /* 259227744Sse ** get data bus width 259327744Sse */ 259427744Sse SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 259527744Sse NADDR (msgin[3]), 259627744Sse SCR_FROM_REG (socl), 259727744Sse 0, 259827744Sse SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), 259927744Sse PADDRH (msg_parity), 260027744Sse /* 260127744Sse ** let the host do the real work. 260227744Sse */ 260327744Sse SCR_INT, 260427744Sse SIR_NEGO_WIDE, 260527744Sse /* 260627744Sse ** let the target fetch our answer. 260727744Sse */ 260827744Sse SCR_SET (SCR_ATN), 260927744Sse 0, 261027744Sse SCR_CLR (SCR_ACK), 261127744Sse 0, 261227744Sse 261327744Sse SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), 261427744Sse SIR_NEGO_PROTO, 261527744Sse /* 261639247Sgibbs ** Send the MSG_EXT_WDTR 261727744Sse */ 261827744Sse SCR_MOVE_ABS (4) ^ SCR_MSG_OUT, 261927744Sse NADDR (msgout), 262027744Sse SCR_CLR (SCR_ATN), 262127744Sse 0, 262227744Sse SCR_COPY (1), 262327744Sse RADDR (sfbr), 262427744Sse NADDR (lastmsg), 262527744Sse SCR_JUMP, 262627744Sse PADDR (msg_out_done), 262727744Sse 262827744Sse}/*-------------------------< MSG_EXT_3 >----------------*/,{ 262927744Sse SCR_CLR (SCR_ACK), 263027744Sse 0, 263127744Sse SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 263227744Sse PADDR (dispatch), 263327744Sse /* 263427744Sse ** get extended message code. 263527744Sse */ 263627744Sse SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 263727744Sse NADDR (msgin[2]), 263827744Sse /* 263927744Sse ** Check for message parity error. 264027744Sse */ 264127744Sse SCR_TO_REG (scratcha), 264227744Sse 0, 264327744Sse SCR_FROM_REG (socl), 264427744Sse 0, 264527744Sse SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), 264627744Sse PADDRH (msg_parity), 264727744Sse SCR_FROM_REG (scratcha), 264827744Sse 0, 264939247Sgibbs SCR_JUMP ^ IFTRUE (DATA (MSG_EXT_SDTR)), 265027744Sse PADDRH (msg_sdtr), 265127744Sse /* 265227744Sse ** unknown extended message 265327744Sse */ 265427744Sse SCR_JUMP, 265527744Sse PADDR (msg_bad) 265627744Sse 265727744Sse}/*-------------------------< MSG_SDTR >-----------------*/,{ 265827744Sse SCR_CLR (SCR_ACK), 265927744Sse 0, 266027744Sse SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 266127744Sse PADDR (dispatch), 266227744Sse /* 266327744Sse ** get period and offset 266427744Sse */ 266527744Sse SCR_MOVE_ABS (2) ^ SCR_MSG_IN, 266627744Sse NADDR (msgin[3]), 266727744Sse SCR_FROM_REG (socl), 266827744Sse 0, 266927744Sse SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), 267027744Sse PADDRH (msg_parity), 267127744Sse /* 267227744Sse ** let the host do the real work. 267327744Sse */ 267427744Sse SCR_INT, 267527744Sse SIR_NEGO_SYNC, 267627744Sse /* 267727744Sse ** let the target fetch our answer. 267827744Sse */ 267927744Sse SCR_SET (SCR_ATN), 268027744Sse 0, 268127744Sse SCR_CLR (SCR_ACK), 268227744Sse 0, 268327744Sse 268427744Sse SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), 268527744Sse SIR_NEGO_PROTO, 268627744Sse /* 268739247Sgibbs ** Send the MSG_EXT_SDTR 268827744Sse */ 268927744Sse SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, 269027744Sse NADDR (msgout), 269127744Sse SCR_CLR (SCR_ATN), 269227744Sse 0, 269327744Sse SCR_COPY (1), 269427744Sse RADDR (sfbr), 269527744Sse NADDR (lastmsg), 269627744Sse SCR_JUMP, 269727744Sse PADDR (msg_out_done), 269827744Sse 269927744Sse}/*-------------------------< MSG_OUT_ABORT >-------------*/,{ 270027744Sse /* 270127744Sse ** After ABORT message, 270227744Sse ** 270327744Sse ** expect an immediate disconnect, ... 270427744Sse */ 270527744Sse SCR_REG_REG (scntl2, SCR_AND, 0x7f), 270627744Sse 0, 270727744Sse SCR_CLR (SCR_ACK|SCR_ATN), 270827744Sse 0, 270927744Sse SCR_WAIT_DISC, 271027744Sse 0, 271127744Sse /* 271227744Sse ** ... and set the status to "ABORTED" 271327744Sse */ 271427744Sse SCR_LOAD_REG (HS_REG, HS_ABORTED), 271527744Sse 0, 271627744Sse SCR_JUMP, 271727744Sse PADDR (cleanup), 271827744Sse 271927744Sse}/*-------------------------< GETCC >-----------------------*/,{ 272027744Sse /* 272127744Sse ** The ncr doesn't have an indirect load 272227744Sse ** or store command. So we have to 272327744Sse ** copy part of the control block to a 272427744Sse ** fixed place, where we can modify it. 272527744Sse ** 272627744Sse ** We patch the address part of a COPY command 272727744Sse ** with the address of the dsa register ... 272827744Sse */ 272927744Sse SCR_COPY_F (4), 273027744Sse RADDR (dsa), 273127744Sse PADDRH (getcc1), 273227744Sse /* 273327744Sse ** ... then we do the actual copy. 273427744Sse */ 273527744Sse SCR_COPY (sizeof (struct head)), 273627744Sse}/*-------------------------< GETCC1 >----------------------*/,{ 273727744Sse 0, 273827744Sse NADDR (header), 273927744Sse /* 274027744Sse ** Initialize the status registers 274127744Sse */ 274227744Sse SCR_COPY (4), 274327744Sse NADDR (header.status), 274427744Sse RADDR (scr0), 274527744Sse}/*-------------------------< GETCC2 >----------------------*/,{ 274627744Sse /* 274727744Sse ** Get the condition code from a target. 274827744Sse ** 274927744Sse ** DSA points to a data structure. 275027744Sse ** Set TEMP to the script location 275127744Sse ** that receives the condition code. 275227744Sse ** 275327744Sse ** Because there is no script command 275427744Sse ** to load a longword into a register, 275527744Sse ** we use a CALL command. 275627744Sse */ 275727744Sse/*<<<*/ SCR_CALLR, 275827744Sse 24, 275927744Sse /* 276027744Sse ** Get the condition code. 276127744Sse */ 276227744Sse SCR_MOVE_TBL ^ SCR_DATA_IN, 276327744Sse offsetof (struct dsb, sense), 276427744Sse /* 276527744Sse ** No data phase may follow! 276627744Sse */ 276727744Sse SCR_CALL, 276827744Sse PADDR (checkatn), 276927744Sse SCR_JUMP, 277027744Sse PADDR (no_data), 277127744Sse/*>>>*/ 277227744Sse 277327744Sse /* 277427744Sse ** The CALL jumps to this point. 277527744Sse ** Prepare for a RESTORE_POINTER message. 277627744Sse ** Save the TEMP register into the saved pointer. 277727744Sse */ 277827744Sse SCR_COPY (4), 277927744Sse RADDR (temp), 278027744Sse NADDR (header.savep), 278127744Sse /* 278227744Sse ** Load scratcha, because in case of a selection timeout, 278327744Sse ** the host will expect a new value for startpos in 278427744Sse ** the scratcha register. 278527744Sse */ 278627744Sse SCR_COPY (4), 278727744Sse PADDR (startpos), 278827744Sse RADDR (scratcha), 278927744Sse#ifdef NCR_GETCC_WITHMSG 279027744Sse /* 279127744Sse ** If QUIRK_NOMSG is set, select without ATN. 279227744Sse ** and don't send a message. 279327744Sse */ 279427744Sse SCR_FROM_REG (QU_REG), 279527744Sse 0, 279627744Sse SCR_JUMP ^ IFTRUE (MASK (QUIRK_NOMSG, QUIRK_NOMSG)), 279727744Sse PADDRH(getcc3), 279827744Sse /* 279927744Sse ** Then try to connect to the target. 280027744Sse ** If we are reselected, special treatment 280127744Sse ** of the current job is required before 280227744Sse ** accepting the reselection. 280327744Sse */ 280427744Sse SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select), 280527744Sse PADDR(badgetcc), 280627744Sse /* 280727744Sse ** Send the IDENTIFY message. 280827744Sse ** In case of short transfer, remove ATN. 280927744Sse */ 281027744Sse SCR_MOVE_TBL ^ SCR_MSG_OUT, 281127744Sse offsetof (struct dsb, smsg2), 281227744Sse SCR_CLR (SCR_ATN), 281327744Sse 0, 281427744Sse /* 281527744Sse ** save the first byte of the message. 281627744Sse */ 281727744Sse SCR_COPY (1), 281827744Sse RADDR (sfbr), 281927744Sse NADDR (lastmsg), 282027744Sse SCR_JUMP, 282127744Sse PADDR (prepare2), 282227744Sse 282327744Sse#endif 282427744Sse}/*-------------------------< GETCC3 >----------------------*/,{ 282527744Sse /* 282627744Sse ** Try to connect to the target. 282727744Sse ** If we are reselected, special treatment 282827744Sse ** of the current job is required before 282927744Sse ** accepting the reselection. 283027744Sse ** 283127744Sse ** Silly target won't accept a message. 283227744Sse ** Select without ATN. 283327744Sse */ 283427744Sse SCR_SEL_TBL ^ offsetof (struct dsb, select), 283527744Sse PADDR(badgetcc), 283627744Sse /* 283727744Sse ** Force error if selection timeout 283827744Sse */ 283927744Sse SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)), 284027744Sse 0, 284127744Sse /* 284227744Sse ** don't negotiate. 284327744Sse */ 284427744Sse SCR_JUMP, 284527744Sse PADDR (prepare2), 28462432Sse}/*-------------------------< ABORTTAG >-------------------*/,{ 28472432Sse /* 28482432Sse ** Abort a bad reselection. 28492432Sse ** Set the message to ABORT vs. ABORT_TAG 28502432Sse */ 285139247Sgibbs SCR_LOAD_REG (scratcha, MSG_ABORT_TAG), 28522432Sse 0, 28532432Sse SCR_JUMPR ^ IFFALSE (CARRYSET), 28542432Sse 8, 28552432Sse}/*-------------------------< ABORT >----------------------*/,{ 285639247Sgibbs SCR_LOAD_REG (scratcha, MSG_ABORT), 28572432Sse 0, 28582432Sse SCR_COPY (1), 28592432Sse RADDR (scratcha), 28602432Sse NADDR (msgout), 28612432Sse SCR_SET (SCR_ATN), 28622432Sse 0, 28632432Sse SCR_CLR (SCR_ACK), 28642432Sse 0, 28652432Sse /* 28662432Sse ** and send it. 28672432Sse ** we expect an immediate disconnect 28682432Sse */ 28692432Sse SCR_REG_REG (scntl2, SCR_AND, 0x7f), 28702432Sse 0, 28712432Sse SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, 28722432Sse NADDR (msgout), 28732432Sse SCR_COPY (1), 28742432Sse RADDR (sfbr), 28752432Sse NADDR (lastmsg), 28766215Sse SCR_CLR (SCR_ACK|SCR_ATN), 28776132Sdg 0, 28782432Sse SCR_WAIT_DISC, 28792432Sse 0, 28802432Sse SCR_JUMP, 28812432Sse PADDR (start), 28823166Sse}/*-------------------------< SNOOPTEST >-------------------*/,{ 28833166Sse /* 28843166Sse ** Read the variable. 28853166Sse */ 28863166Sse SCR_COPY (4), 288727744Sse KVAR (KVAR_NCR_CACHE), 28883166Sse RADDR (scratcha), 28893166Sse /* 28903166Sse ** Write the variable. 28913166Sse */ 28923166Sse SCR_COPY (4), 28933166Sse RADDR (temp), 289427744Sse KVAR (KVAR_NCR_CACHE), 28953166Sse /* 28963166Sse ** Read back the variable. 28973166Sse */ 28983166Sse SCR_COPY (4), 289927744Sse KVAR (KVAR_NCR_CACHE), 29003166Sse RADDR (temp), 29016526Sse}/*-------------------------< SNOOPEND >-------------------*/,{ 29023166Sse /* 29033166Sse ** And stop. 29043166Sse */ 29053166Sse SCR_INT, 29063166Sse 99, 29072432Sse}/*--------------------------------------------------------*/ 29082432Sse}; 29097228Sse 291027744Sse 29112432Sse/*========================================================== 29122432Sse** 29132432Sse** 29142432Sse** Fill in #define dependent parts of the script 29152432Sse** 29162432Sse** 29172432Sse**========================================================== 29182432Sse*/ 29192432Sse 2920105219Sphkstatic void ncr_script_fill (struct script * scr, struct scripth * scrh) 29212432Sse{ 29222432Sse int i; 29232432Sse ncrcmd *p; 29242432Sse 292527744Sse p = scrh->tryloop; 29262432Sse for (i=0; i<MAX_START; i++) { 29272432Sse *p++ =SCR_COPY (4); 29282432Sse *p++ =NADDR (squeue[i]); 29292432Sse *p++ =RADDR (dsa); 29302432Sse *p++ =SCR_CALL; 29312432Sse *p++ =PADDR (trysel); 29322432Sse }; 29332432Sse *p++ =SCR_JUMP; 293427744Sse *p++ =PADDRH(tryloop); 29352432Sse 293639554Sgibbs assert ((char *)p == (char *)&scrh->tryloop + sizeof (scrh->tryloop)); 29372432Sse 29382432Sse p = scr->data_in; 29392432Sse 29402432Sse *p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)); 29412432Sse *p++ =PADDR (no_data); 294239386Sgibbs *p++ =SCR_COPY (sizeof (ticks)); 294334961Sphk *p++ =(ncrcmd) KVAR (KVAR_TICKS); 29442432Sse *p++ =NADDR (header.stamp.data); 29452432Sse *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; 29462432Sse *p++ =offsetof (struct dsb, data[ 0]); 29472432Sse 29482432Sse for (i=1; i<MAX_SCATTER; i++) { 29492432Sse *p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)); 29502432Sse *p++ =PADDR (checkatn); 29512432Sse *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; 29522432Sse *p++ =offsetof (struct dsb, data[i]); 29532432Sse }; 29542432Sse 29552432Sse *p++ =SCR_CALL; 29562432Sse *p++ =PADDR (checkatn); 29572432Sse *p++ =SCR_JUMP; 29582432Sse *p++ =PADDR (no_data); 29592432Sse 296039554Sgibbs assert ((char *)p == (char *)&scr->data_in + sizeof (scr->data_in)); 29617228Sse 29622432Sse p = scr->data_out; 29632432Sse 29642432Sse *p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_OUT)); 29652432Sse *p++ =PADDR (no_data); 296639386Sgibbs *p++ =SCR_COPY (sizeof (ticks)); 296734961Sphk *p++ =(ncrcmd) KVAR (KVAR_TICKS); 29682432Sse *p++ =NADDR (header.stamp.data); 29692432Sse *p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT; 29702432Sse *p++ =offsetof (struct dsb, data[ 0]); 29712432Sse 29722432Sse for (i=1; i<MAX_SCATTER; i++) { 29732432Sse *p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)); 29742432Sse *p++ =PADDR (dispatch); 29752432Sse *p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT; 29762432Sse *p++ =offsetof (struct dsb, data[i]); 29772432Sse }; 29782432Sse 29792432Sse *p++ =SCR_CALL; 29802432Sse *p++ =PADDR (dispatch); 29812432Sse *p++ =SCR_JUMP; 29822432Sse *p++ =PADDR (no_data); 29832432Sse 298439554Sgibbs assert ((char *)p == (char *)&scr->data_out + sizeof (scr->data_out)); 29852432Sse} 29867228Sse 29872432Sse/*========================================================== 29882432Sse** 29892432Sse** 29902432Sse** Copy and rebind a script. 29912432Sse** 29922432Sse** 29932432Sse**========================================================== 29942432Sse*/ 29952432Sse 299628636Ssestatic void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len) 29972432Sse{ 299827744Sse ncrcmd opcode, new, old, tmp1, tmp2; 299927744Sse ncrcmd *start, *end; 300039532Sken int relocs, offset; 30012432Sse 30022432Sse start = src; 300327744Sse end = src + len/4; 300439532Sken offset = 0; 30058876Srgrimes 30062432Sse while (src < end) { 30072432Sse 300839532Sken opcode = *src++; 300939532Sken WRITESCRIPT_OFF(dst, offset, opcode); 301039532Sken offset += 4; 30112432Sse 30122432Sse /* 30132432Sse ** If we forget to change the length 30142432Sse ** in struct script, a field will be 30152432Sse ** padded with 0. This is an illegal 30162432Sse ** command. 30172432Sse */ 30182432Sse 30192814Sse if (opcode == 0) { 30202432Sse printf ("%s: ERROR0 IN SCRIPT at %d.\n", 302127744Sse ncr_name(np), (int) (src-start-1)); 30222814Sse DELAY (1000000); 30232814Sse }; 30242432Sse 30253552Sse if (DEBUG_FLAGS & DEBUG_SCRIPT) 302627744Sse printf ("%p: <%x>\n", 302727744Sse (src-1), (unsigned)opcode); 30282432Sse 30292432Sse /* 30302432Sse ** We don't have to decode ALL commands 30312432Sse */ 30322432Sse switch (opcode >> 28) { 30337228Sse 30342432Sse case 0xc: 30352432Sse /* 30362432Sse ** COPY has TWO arguments. 30372432Sse */ 30382432Sse relocs = 2; 303927744Sse tmp1 = src[0]; 304027744Sse if ((tmp1 & RELOC_MASK) == RELOC_KVAR) 304127744Sse tmp1 = 0; 304227744Sse tmp2 = src[1]; 304327744Sse if ((tmp2 & RELOC_MASK) == RELOC_KVAR) 304427744Sse tmp2 = 0; 304527744Sse if ((tmp1 ^ tmp2) & 3) { 30462814Sse printf ("%s: ERROR1 IN SCRIPT at %d.\n", 304727744Sse ncr_name(np), (int) (src-start-1)); 30482814Sse DELAY (1000000); 304927744Sse } 305027684Sse /* 305127744Sse ** If PREFETCH feature not enabled, remove 305227744Sse ** the NO FLUSH bit if present. 305327684Sse */ 305427744Sse if ((opcode & SCR_NO_FLUSH) && !(np->features&FE_PFEN)) 305539532Sken WRITESCRIPT_OFF(dst, offset - 4, 305639532Sken (opcode & ~SCR_NO_FLUSH)); 30572432Sse break; 30582432Sse 30592432Sse case 0x0: 30602432Sse /* 30612432Sse ** MOVE (absolute address) 30622432Sse */ 30632432Sse relocs = 1; 30642432Sse break; 30652432Sse 30662432Sse case 0x8: 30672432Sse /* 30682432Sse ** JUMP / CALL 30692432Sse ** dont't relocate if relative :-) 30702432Sse */ 30712432Sse if (opcode & 0x00800000) 30722432Sse relocs = 0; 30732432Sse else 30742432Sse relocs = 1; 30752432Sse break; 30762432Sse 30772432Sse case 0x4: 30782432Sse case 0x5: 30792432Sse case 0x6: 30802432Sse case 0x7: 30812432Sse relocs = 1; 30822432Sse break; 30832432Sse 30842432Sse default: 30852432Sse relocs = 0; 30862432Sse break; 30872432Sse }; 30887228Sse 30892432Sse if (relocs) { 30902432Sse while (relocs--) { 309110605Sse old = *src++; 30922432Sse 30932432Sse switch (old & RELOC_MASK) { 30942432Sse case RELOC_REGISTER: 309560974Sdfr new = (old & ~RELOC_MASK) + rman_get_start(np->reg_res); 30962432Sse break; 30972432Sse case RELOC_LABEL: 309810677Sse new = (old & ~RELOC_MASK) + np->p_script; 30992432Sse break; 310027744Sse case RELOC_LABELH: 310127744Sse new = (old & ~RELOC_MASK) + np->p_scripth; 310227744Sse break; 31032432Sse case RELOC_SOFTC: 31042432Sse new = (old & ~RELOC_MASK) + vtophys(np); 31052432Sse break; 310627744Sse case RELOC_KVAR: 310727744Sse if (((old & ~RELOC_MASK) < 310827744Sse SCRIPT_KVAR_FIRST) || 310927744Sse ((old & ~RELOC_MASK) > 311027744Sse SCRIPT_KVAR_LAST)) 311127744Sse panic("ncr KVAR out of range"); 311227744Sse new = vtophys(script_kvars[old & 311327744Sse ~RELOC_MASK]); 311427744Sse break; 31152432Sse case 0: 31162432Sse /* Don't relocate a 0 address. */ 31172432Sse if (old == 0) { 31182432Sse new = old; 31192432Sse break; 31202432Sse } 3121102412Scharnier /* FALLTHROUGH */ 31222432Sse default: 312339532Sken panic("ncr_script_copy_and_bind: weird relocation %x @ %d\n", old, (int)(src - start)); 31242432Sse break; 31252432Sse } 31262432Sse 312739532Sken WRITESCRIPT_OFF(dst, offset, new); 312839532Sken offset += 4; 31292432Sse } 313039532Sken } else { 313139532Sken WRITESCRIPT_OFF(dst, offset, *src++); 313239532Sken offset += 4; 313339532Sken } 31342432Sse 31352432Sse }; 31362432Sse} 31377228Sse 31382432Sse/*========================================================== 31392432Sse** 31402432Sse** 31412432Sse** Auto configuration. 31422432Sse** 31432432Sse** 31442432Sse**========================================================== 31452432Sse*/ 31462432Sse 314743309Sdillon#if 0 31482432Sse/*---------------------------------------------------------- 31492432Sse** 31502432Sse** Reduce the transfer length to the max value 31512432Sse** we can transfer safely. 31522432Sse** 31532432Sse** Reading a block greater then MAX_SIZE from the 31542432Sse** raw (character) device exercises a memory leak 31552432Sse** in the vm subsystem. This is common to ALL devices. 31562432Sse** We have submitted a description of this bug to 31572432Sse** <FreeBSD-bugs@freefall.cdrom.com>. 31582432Sse** It should be fixed in the current release. 31592432Sse** 31602432Sse**---------------------------------------------------------- 31612432Sse*/ 31622432Sse 31632432Ssevoid ncr_min_phys (struct buf *bp) 31642432Sse{ 31659364Sse if ((unsigned long)bp->b_bcount > MAX_SIZE) bp->b_bcount = MAX_SIZE; 31662432Sse} 31672432Sse 316843309Sdillon#endif 316943309Sdillon 317043309Sdillon#if 0 31712432Sse/*---------------------------------------------------------- 31722432Sse** 31732432Sse** Maximal number of outstanding requests per target. 31742432Sse** 31752432Sse**---------------------------------------------------------- 31762432Sse*/ 31772432Sse 317814453Sgibbsu_int32_t ncr_info (int unit) 31792432Sse{ 31802432Sse return (1); /* may be changed later */ 31812432Sse} 31827228Sse 318343309Sdillon#endif 318443309Sdillon 31852432Sse/*---------------------------------------------------------- 31862432Sse** 318727684Sse** NCR chip devices table and chip look up function. 318827684Sse** Features bit are defined in ncrreg.h. Is it the 318927684Sse** right place? 319027684Sse** 319127684Sse**---------------------------------------------------------- 319227684Sse*/ 319327684Ssetypedef struct { 319427684Sse unsigned long device_id; 319528636Sse unsigned short minrevid; 319628636Sse char *name; 319727684Sse unsigned char maxburst; 319827684Sse unsigned char maxoffs; 319927684Sse unsigned char clock_divn; 320027684Sse unsigned int features; 320127684Sse} ncr_chip; 320227684Sse 320327684Ssestatic ncr_chip ncr_chip_table[] = { 320428636Sse {NCR_810_ID, 0x00, "ncr 53c810 fast10 scsi", 4, 8, 4, 320527684Sse FE_ERL} 320627684Sse , 320728636Sse {NCR_810_ID, 0x10, "ncr 53c810a fast10 scsi", 4, 8, 4, 320828636Sse FE_ERL|FE_LDSTR|FE_PFEN|FE_BOF} 320927684Sse , 321028636Sse {NCR_815_ID, 0x00, "ncr 53c815 fast10 scsi", 4, 8, 4, 321127684Sse FE_ERL|FE_BOF} 321227684Sse , 321328636Sse {NCR_820_ID, 0x00, "ncr 53c820 fast10 wide scsi", 4, 8, 4, 321427684Sse FE_WIDE|FE_ERL} 321527684Sse , 321628636Sse {NCR_825_ID, 0x00, "ncr 53c825 fast10 wide scsi", 4, 8, 4, 321727684Sse FE_WIDE|FE_ERL|FE_BOF} 321827684Sse , 321928636Sse {NCR_825_ID, 0x10, "ncr 53c825a fast10 wide scsi", 7, 8, 4, 322028636Sse FE_WIDE|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} 322127684Sse , 322228636Sse {NCR_860_ID, 0x00, "ncr 53c860 fast20 scsi", 4, 8, 5, 322328636Sse FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_LDSTR|FE_PFEN} 322427684Sse , 322528636Sse {NCR_875_ID, 0x00, "ncr 53c875 fast20 wide scsi", 7, 16, 5, 322628636Sse FE_WIDE|FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} 322727684Sse , 322828636Sse {NCR_875_ID, 0x02, "ncr 53c875 fast20 wide scsi", 7, 16, 5, 322928636Sse FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} 323027684Sse , 323128636Sse {NCR_875_ID2, 0x00, "ncr 53c875j fast20 wide scsi", 7, 16, 5, 323228636Sse FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} 323327684Sse , 323428636Sse {NCR_885_ID, 0x00, "ncr 53c885 fast20 wide scsi", 7, 16, 5, 323528636Sse FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} 323627684Sse , 323728636Sse {NCR_895_ID, 0x00, "ncr 53c895 fast40 wide scsi", 7, 31, 7, 323828636Sse FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} 323928636Sse , 324028636Sse {NCR_896_ID, 0x00, "ncr 53c896 fast40 wide scsi", 7, 31, 7, 324128636Sse FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} 324256446Sgroudier , 324356446Sgroudier {NCR_895A_ID, 0x00, "ncr 53c895a fast40 wide scsi", 7, 31, 7, 324456446Sgroudier FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} 324556446Sgroudier , 324656446Sgroudier {NCR_1510D_ID, 0x00, "ncr 53c1510d fast40 wide scsi", 7, 31, 7, 324756446Sgroudier FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} 324827684Sse}; 324927684Sse 325027684Ssestatic int ncr_chip_lookup(u_long device_id, u_char revision_id) 325127684Sse{ 325227684Sse int i, found; 325328636Sse 325427684Sse found = -1; 325527684Sse for (i = 0; i < sizeof(ncr_chip_table)/sizeof(ncr_chip_table[0]); i++) { 325627684Sse if (device_id == ncr_chip_table[i].device_id && 325728636Sse ncr_chip_table[i].minrevid <= revision_id) { 325828636Sse if (found < 0 || 325928636Sse ncr_chip_table[found].minrevid 326028636Sse < ncr_chip_table[i].minrevid) { 326128636Sse found = i; 326228636Sse } 326327684Sse } 326427684Sse } 326527684Sse return found; 326627684Sse} 326727684Sse 326827684Sse/*---------------------------------------------------------- 326927684Sse** 32702432Sse** Probe the hostadapter. 32712432Sse** 32722432Sse**---------------------------------------------------------- 32732432Sse*/ 32742432Sse 32752432Sse 32762432Sse 327760974Sdfrstatic int ncr_probe (device_t dev) 32782432Sse{ 327927684Sse int i; 32803533Sse 328160974Sdfr i = ncr_chip_lookup(pci_get_devid(dev), pci_get_revid(dev)); 328260974Sdfr if (i >= 0) { 328360974Sdfr device_set_desc(dev, ncr_chip_table[i].name); 3284142398Simp return (BUS_PROBE_DEFAULT); 328560974Sdfr } 32863533Sse 328760974Sdfr return (ENXIO); 32882432Sse} 32892432Sse 32903533Sse 32917228Sse 32922432Sse/*========================================================== 32932432Sse** 329427684Sse** NCR chip clock divisor table. 329527684Sse** Divisors are multiplied by 10,000,000 in order to make 329627684Sse** calculations more simple. 32972432Sse** 329827684Sse**========================================================== 329927684Sse*/ 330027684Sse 330127684Sse#define _5M 5000000 330227684Ssestatic u_long div_10M[] = 330327684Sse {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M}; 330427684Sse 330527684Sse/*=============================================================== 330627684Sse** 330727684Sse** NCR chips allow burst lengths of 2, 4, 8, 16, 32, 64, 128 330827684Sse** transfers. 32,64,128 are only supported by 875 and 895 chips. 330927684Sse** We use log base 2 (burst length) as internal code, with 331027684Sse** value 0 meaning "burst disabled". 331127684Sse** 331227684Sse**=============================================================== 331327684Sse*/ 331427684Sse 331527684Sse/* 331627684Sse * Burst length from burst code. 331727684Sse */ 331827684Sse#define burst_length(bc) (!(bc))? 0 : 1 << (bc) 331927684Sse 332027684Sse/* 332127684Sse * Burst code from io register bits. 332227684Sse */ 332327684Sse#define burst_code(dmode, ctest4, ctest5) \ 332427684Sse (ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1 332527684Sse 332627684Sse/* 332727684Sse * Set initial io register bits from burst code. 332827684Sse */ 332939247Sgibbsstatic void 333039247Sgibbsncr_init_burst(ncb_p np, u_char bc) 333127684Sse{ 333227684Sse np->rv_ctest4 &= ~0x80; 333327684Sse np->rv_dmode &= ~(0x3 << 6); 333427684Sse np->rv_ctest5 &= ~0x4; 333527684Sse 333627684Sse if (!bc) { 333727684Sse np->rv_ctest4 |= 0x80; 333827684Sse } 333927684Sse else { 334027684Sse --bc; 334127684Sse np->rv_dmode |= ((bc & 0x3) << 6); 334227684Sse np->rv_ctest5 |= (bc & 0x4); 334327684Sse } 334427684Sse} 334527684Sse 334627684Sse/*========================================================== 334727684Sse** 334827684Sse** 33492432Sse** Auto configuration: attach and init a host adapter. 33502432Sse** 33512432Sse** 33522432Sse**========================================================== 33532432Sse*/ 33542432Sse 33552432Sse 335660974Sdfrstatic int 335760974Sdfrncr_attach (device_t dev) 33582432Sse{ 335960974Sdfr ncb_p np = (struct ncb*) device_get_softc(dev); 336039247Sgibbs u_char rev = 0; 336139247Sgibbs u_long period; 336260974Sdfr int i, rid; 336339247Sgibbs u_int8_t usrsync; 336439247Sgibbs u_int8_t usrwide; 336539247Sgibbs struct cam_devq *devq; 33662432Sse 33672432Sse /* 336827684Sse ** allocate and initialize structures. 33692432Sse */ 33702432Sse 337160974Sdfr np->unit = device_get_unit(dev); 33722432Sse 33732432Sse /* 33742432Sse ** Try to map the controller chip to 33752432Sse ** virtual and physical memory. 33762432Sse */ 33772432Sse 337860974Sdfr np->reg_rid = 0x14; 3379127135Snjl np->reg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 3380127135Snjl &np->reg_rid, RF_ACTIVE); 338160974Sdfr if (!np->reg_res) { 338260974Sdfr device_printf(dev, "could not map memory\n"); 338360974Sdfr return ENXIO; 338460974Sdfr } 33852432Sse 338618886Sse /* 338718886Sse ** Make the controller's registers available. 338818886Sse ** Now the INB INW INL OUTB OUTW OUTL macros 338918886Sse ** can be used safely. 339018886Sse */ 339118886Sse 339260974Sdfr np->bst = rman_get_bustag(np->reg_res); 339360974Sdfr np->bsh = rman_get_bushandle(np->reg_res); 339418886Sse 339560974Sdfr 33966401Sse#ifdef NCR_IOMAPPED 33976401Sse /* 33986401Sse ** Try to map the controller chip into iospace. 33996401Sse */ 34006401Sse 34016401Sse if (!pci_map_port (config_id, 0x10, &np->port)) 34026401Sse return; 34036401Sse#endif 34046401Sse 34057228Sse 34062432Sse /* 340720435Sse ** Save some controller register default values 34082814Sse */ 34092814Sse 341027684Sse np->rv_scntl3 = INB(nc_scntl3) & 0x77; 341127684Sse np->rv_dmode = INB(nc_dmode) & 0xce; 341227684Sse np->rv_dcntl = INB(nc_dcntl) & 0xa9; 341327684Sse np->rv_ctest3 = INB(nc_ctest3) & 0x01; 341427684Sse np->rv_ctest4 = INB(nc_ctest4) & 0x88; 341527684Sse np->rv_ctest5 = INB(nc_ctest5) & 0x24; 341627684Sse np->rv_gpcntl = INB(nc_gpcntl); 341727684Sse np->rv_stest2 = INB(nc_stest2) & 0x20; 341818875Sse 341927744Sse if (bootverbose >= 2) { 342027684Sse printf ("\tBIOS values: SCNTL3:%02x DMODE:%02x DCNTL:%02x\n", 342127684Sse np->rv_scntl3, np->rv_dmode, np->rv_dcntl); 342227684Sse printf ("\t CTEST3:%02x CTEST4:%02x CTEST5:%02x\n", 342327684Sse np->rv_ctest3, np->rv_ctest4, np->rv_ctest5); 342427684Sse } 342527684Sse 342627684Sse np->rv_dcntl |= NOCOM; 342727684Sse 342818875Sse /* 342920435Sse ** Do chip dependent initialization. 343020435Sse */ 343120435Sse 343260974Sdfr rev = pci_get_revid(dev); 343320435Sse 343420435Sse /* 343527684Sse ** Get chip features from chips table. 343627684Sse */ 343760974Sdfr i = ncr_chip_lookup(pci_get_devid(dev), rev); 343827684Sse 343927684Sse if (i >= 0) { 344027684Sse np->maxburst = ncr_chip_table[i].maxburst; 344127684Sse np->maxoffs = ncr_chip_table[i].maxoffs; 344227684Sse np->clock_divn = ncr_chip_table[i].clock_divn; 344327684Sse np->features = ncr_chip_table[i].features; 344427684Sse } else { /* Should'nt happen if probe() is ok */ 344527684Sse np->maxburst = 4; 344627684Sse np->maxoffs = 8; 344727684Sse np->clock_divn = 4; 344827684Sse np->features = FE_ERL; 344927684Sse } 345027684Sse 345127684Sse np->maxwide = np->features & FE_WIDE ? 1 : 0; 345227684Sse np->clock_khz = np->features & FE_CLK80 ? 80000 : 40000; 345327684Sse if (np->features & FE_QUAD) np->multiplier = 4; 345427684Sse else if (np->features & FE_DBLR) np->multiplier = 2; 345527684Sse else np->multiplier = 1; 345627684Sse 345727684Sse /* 345818875Sse ** Get the frequency of the chip's clock. 345918875Sse ** Find the right value for scntl3. 346018875Sse */ 346127684Sse if (np->features & (FE_ULTRA|FE_ULTRA2)) 346227684Sse ncr_getclock(np, np->multiplier); 346318875Sse 346420435Sse#ifdef NCR_TEKRAM_EEPROM 346527684Sse if (bootverbose) { 346627684Sse printf ("%s: Tekram EEPROM read %s\n", 346727684Sse ncr_name(np), 346827684Sse read_tekram_eeprom (np, NULL) ? 346927684Sse "succeeded" : "failed"); 347027684Sse } 347127684Sse#endif /* NCR_TEKRAM_EEPROM */ 347227684Sse 347327684Sse /* 347427684Sse * If scntl3 != 0, we assume BIOS is present. 347527684Sse */ 347627684Sse if (np->rv_scntl3) 347727684Sse np->features |= FE_BIOS; 347827684Sse 347927684Sse /* 348027684Sse * Divisor to be used for async (timer pre-scaler). 348127684Sse */ 348227684Sse i = np->clock_divn - 1; 348327684Sse while (i >= 0) { 348427684Sse --i; 348527684Sse if (10ul * SCSI_NCR_MIN_ASYNC * np->clock_khz > div_10M[i]) { 348627684Sse ++i; 348727684Sse break; 348820435Sse } 34893166Sse } 349027684Sse np->rv_scntl3 = i+1; 34912814Sse 34922814Sse /* 349327684Sse * Minimum synchronous period factor supported by the chip. 349427684Sse * Btw, 'period' is in tenths of nanoseconds. 349527684Sse */ 349627684Sse 349727684Sse period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz; 349827684Sse if (period <= 250) np->minsync = 10; 349927684Sse else if (period <= 303) np->minsync = 11; 350027684Sse else if (period <= 500) np->minsync = 12; 350127684Sse else np->minsync = (period + 40 - 1) / 40; 350227684Sse 350327684Sse /* 350427684Sse * Check against chip SCSI standard support (SCSI-2,ULTRA,ULTRA2). 350527684Sse */ 350627684Sse 350727684Sse if (np->minsync < 25 && !(np->features & (FE_ULTRA|FE_ULTRA2))) 350827684Sse np->minsync = 25; 350927684Sse else if (np->minsync < 12 && !(np->features & FE_ULTRA2)) 351027684Sse np->minsync = 12; 351127684Sse 351227684Sse /* 351327684Sse * Maximum synchronous period factor supported by the chip. 351427684Sse */ 351527684Sse 351627684Sse period = (11 * div_10M[np->clock_divn - 1]) / (4 * np->clock_khz); 351727684Sse np->maxsync = period > 2540 ? 254 : period / 10; 351827684Sse 351927684Sse /* 352027684Sse * Now, some features available with Symbios compatible boards. 352127684Sse * LED support through GPIO0 and DIFF support. 352227684Sse */ 352327684Sse 352427684Sse#ifdef SCSI_NCR_SYMBIOS_COMPAT 352527684Sse if (!(np->rv_gpcntl & 0x01)) 352627684Sse np->features |= FE_LED0; 352727684Sse#if 0 /* Not safe enough without NVRAM support or user settable option */ 352827684Sse if (!(INB(nc_gpreg) & 0x08)) 352927684Sse np->features |= FE_DIFF; 353027684Sse#endif 353127684Sse#endif /* SCSI_NCR_SYMBIOS_COMPAT */ 353227684Sse 353327684Sse /* 353427684Sse * Prepare initial IO registers settings. 353527684Sse * Trust BIOS only if we believe we have one and if we want to. 353627684Sse */ 353727684Sse#ifdef SCSI_NCR_TRUST_BIOS 353827684Sse if (!(np->features & FE_BIOS)) { 353927684Sse#else 354027684Sse if (1) { 354127684Sse#endif 354227684Sse np->rv_dmode = 0; 354327684Sse np->rv_dcntl = NOCOM; 354427684Sse np->rv_ctest3 = 0; 354527684Sse np->rv_ctest4 = MPEE; 354627684Sse np->rv_ctest5 = 0; 354727684Sse np->rv_stest2 = 0; 354827684Sse 354927684Sse if (np->features & FE_ERL) 355027684Sse np->rv_dmode |= ERL; /* Enable Read Line */ 355127684Sse if (np->features & FE_BOF) 355227684Sse np->rv_dmode |= BOF; /* Burst Opcode Fetch */ 355327684Sse if (np->features & FE_ERMP) 355427684Sse np->rv_dmode |= ERMP; /* Enable Read Multiple */ 355527684Sse if (np->features & FE_CLSE) 355627684Sse np->rv_dcntl |= CLSE; /* Cache Line Size Enable */ 355727684Sse if (np->features & FE_WRIE) 355827684Sse np->rv_ctest3 |= WRIE; /* Write and Invalidate */ 355927684Sse if (np->features & FE_PFEN) 356027684Sse np->rv_dcntl |= PFEN; /* Prefetch Enable */ 356127684Sse if (np->features & FE_DFS) 356227684Sse np->rv_ctest5 |= DFS; /* Dma Fifo Size */ 356327684Sse if (np->features & FE_DIFF) 356427684Sse np->rv_stest2 |= 0x20; /* Differential mode */ 356527684Sse ncr_init_burst(np, np->maxburst); /* Max dwords burst length */ 356627684Sse } else { 356727684Sse np->maxburst = 356827684Sse burst_code(np->rv_dmode, np->rv_ctest4, np->rv_ctest5); 356927684Sse } 357027684Sse 357127684Sse /* 357228636Sse ** Get on-chip SRAM address, if supported 357327744Sse */ 357460974Sdfr if ((np->features & FE_RAM) && sizeof(struct script) <= 4096) { 357560974Sdfr np->sram_rid = 0x18; 3576127135Snjl np->sram_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 3577127135Snjl &np->sram_rid, 3578127135Snjl RF_ACTIVE); 357960974Sdfr } 358027744Sse 358128636Sse /* 358228636Sse ** Allocate structure for script relocation. 358328636Sse */ 358460974Sdfr if (np->sram_res != NULL) { 358539682Sdfr np->script = NULL; 358660974Sdfr np->p_script = rman_get_start(np->sram_res); 358760974Sdfr np->bst2 = rman_get_bustag(np->sram_res); 358860974Sdfr np->bsh2 = rman_get_bushandle(np->sram_res); 358928636Sse } else if (sizeof (struct script) > PAGE_SIZE) { 3590124460Salc np->script = (struct script*) contigmalloc 3591124460Salc (round_page(sizeof (struct script)), M_DEVBUF, M_WAITOK, 3592124460Salc 0, 0xffffffff, PAGE_SIZE, 0); 359328636Sse } else { 359428636Sse np->script = (struct script *) 3595111119Simp malloc (sizeof (struct script), M_DEVBUF, M_WAITOK); 359628636Sse } 359728636Sse 359828636Sse if (sizeof (struct scripth) > PAGE_SIZE) { 3599124460Salc np->scripth = (struct scripth*) contigmalloc 3600124460Salc (round_page(sizeof (struct scripth)), M_DEVBUF, M_WAITOK, 3601124460Salc 0, 0xffffffff, PAGE_SIZE, 0); 360228636Sse } else 360328636Sse { 360428636Sse np->scripth = (struct scripth *) 3605111119Simp malloc (sizeof (struct scripth), M_DEVBUF, M_WAITOK); 360628636Sse } 360728636Sse 360827744Sse#ifdef SCSI_NCR_PCI_CONFIG_FIXUP 360927744Sse /* 361027744Sse ** If cache line size is enabled, check PCI config space and 361127744Sse ** try to fix it up if necessary. 361227744Sse */ 361327744Sse#ifdef PCIR_CACHELNSZ /* To be sure that new PCI stuff is present */ 361428636Sse { 361560974Sdfr u_char cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1); 361660974Sdfr u_short command = pci_read_config(dev, PCIR_COMMAND, 2); 361727744Sse 361827744Sse if (!cachelnsz) { 361927744Sse cachelnsz = 8; 362027744Sse printf("%s: setting PCI cache line size register to %d.\n", 362127744Sse ncr_name(np), (int)cachelnsz); 362260974Sdfr pci_write_config(dev, PCIR_CACHELNSZ, cachelnsz, 1); 362327744Sse } 362427744Sse 3625254263Sscottl if (!(command & PCIM_CMD_MWRICEN)) { 3626254263Sscottl command |= PCIM_CMD_MWRICEN; 362727744Sse printf("%s: setting PCI command write and invalidate.\n", 362827744Sse ncr_name(np)); 362960974Sdfr pci_write_config(dev, PCIR_COMMAND, command, 2); 363027744Sse } 363128636Sse } 363227744Sse#endif /* PCIR_CACHELNSZ */ 363327744Sse 363427744Sse#endif /* SCSI_NCR_PCI_CONFIG_FIXUP */ 363527744Sse 363639247Sgibbs /* Initialize per-target user settings */ 363739247Sgibbs usrsync = 0; 363839247Sgibbs if (SCSI_NCR_DFLT_SYNC) { 363939247Sgibbs usrsync = SCSI_NCR_DFLT_SYNC; 364039247Sgibbs if (usrsync > np->maxsync) 364139247Sgibbs usrsync = np->maxsync; 364239247Sgibbs if (usrsync < np->minsync) 364339247Sgibbs usrsync = np->minsync; 364439247Sgibbs }; 364539247Sgibbs 364639247Sgibbs usrwide = (SCSI_NCR_MAX_WIDE); 364739247Sgibbs if (usrwide > np->maxwide) usrwide=np->maxwide; 364839247Sgibbs 364939247Sgibbs for (i=0;i<MAX_TARGET;i++) { 365039247Sgibbs tcb_p tp = &np->target[i]; 365139247Sgibbs 365239247Sgibbs tp->tinfo.user.period = usrsync; 365339247Sgibbs tp->tinfo.user.offset = usrsync != 0 ? np->maxoffs : 0; 365439247Sgibbs tp->tinfo.user.width = usrwide; 365539247Sgibbs tp->tinfo.disc_tag = NCR_CUR_DISCENB 365639247Sgibbs | NCR_CUR_TAGENB 365739247Sgibbs | NCR_USR_DISCENB 365839247Sgibbs | NCR_USR_TAGENB; 365939247Sgibbs } 366039247Sgibbs 366127744Sse /* 366227684Sse ** Bells and whistles ;-) 366327684Sse */ 366428636Sse if (bootverbose) 366528636Sse printf("%s: minsync=%d, maxsync=%d, maxoffs=%d, %d dwords burst, %s dma fifo\n", 366627684Sse ncr_name(np), np->minsync, np->maxsync, np->maxoffs, 366727684Sse burst_length(np->maxburst), 366827684Sse (np->rv_ctest5 & DFS) ? "large" : "normal"); 366927684Sse 367027684Sse /* 367127744Sse ** Print some complementary information that can be helpfull. 36722432Sse */ 367327744Sse if (bootverbose) 367427744Sse printf("%s: %s, %s IRQ driver%s\n", 367527744Sse ncr_name(np), 367627744Sse np->rv_stest2 & 0x20 ? "differential" : "single-ended", 367727744Sse np->rv_dcntl & IRQM ? "totem pole" : "open drain", 367860974Sdfr np->sram_res ? ", using on-chip SRAM" : ""); 367927744Sse 368027744Sse /* 368127744Sse ** Patch scripts to physical addresses 368227744Sse */ 368327744Sse ncr_script_fill (&script0, &scripth0); 36842432Sse 368539532Sken if (np->script) 368639532Sken np->p_script = vtophys(np->script); 368727744Sse np->p_scripth = vtophys(np->scripth); 368827744Sse 368927744Sse ncr_script_copy_and_bind (np, (ncrcmd *) &script0, 369028636Sse (ncrcmd *) np->script, sizeof(struct script)); 369127744Sse 369227744Sse ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, 369328636Sse (ncrcmd *) np->scripth, sizeof(struct scripth)); 369427744Sse 36952432Sse /* 369627684Sse ** Patch the script for LED support. 369727684Sse */ 369827684Sse 369927684Sse if (np->features & FE_LED0) { 370039532Sken WRITESCRIPT(reselect[0], SCR_REG_REG(gpreg, SCR_OR, 0x01)); 370139532Sken WRITESCRIPT(reselect1[0], SCR_REG_REG(gpreg, SCR_AND, 0xfe)); 370239532Sken WRITESCRIPT(reselect2[0], SCR_REG_REG(gpreg, SCR_AND, 0xfe)); 370327684Sse } 370427684Sse 370527684Sse /* 37062432Sse ** init data structure 37072432Sse */ 37082432Sse 370910677Sse np->jump_tcb.l_cmd = SCR_JUMP; 371027744Sse np->jump_tcb.l_paddr = NCB_SCRIPTH_PHYS (np, abort); 37112432Sse 37122432Sse /* 37132432Sse ** Get SCSI addr of host adapter (set by bios?). 37142432Sse */ 37152432Sse 37162432Sse np->myaddr = INB(nc_scid) & 0x07; 37172432Sse if (!np->myaddr) np->myaddr = SCSI_NCR_MYADDR; 37182432Sse 37196132Sdg#ifdef NCR_DUMP_REG 37202432Sse /* 37216132Sdg ** Log the initial register contents 37226132Sdg */ 37236132Sdg { 37246132Sdg int reg; 37256132Sdg for (reg=0; reg<256; reg+=4) { 37266132Sdg if (reg%16==0) printf ("reg[%2x]", reg); 37276132Sdg printf (" %08x", (int)pci_conf_read (config_id, reg)); 37286132Sdg if (reg%16==12) printf ("\n"); 37296132Sdg } 37306132Sdg } 373120435Sse#endif /* NCR_DUMP_REG */ 37326132Sdg 37336132Sdg /* 373420435Sse ** Reset chip. 37356132Sdg */ 37366132Sdg 37376132Sdg OUTB (nc_istat, SRST); 373810605Sse DELAY (1000); 37396132Sdg OUTB (nc_istat, 0 ); 37406132Sdg 37416132Sdg 37426132Sdg /* 37433166Sse ** Now check the cache handling of the pci chipset. 37443166Sse */ 37453166Sse 37463166Sse if (ncr_snooptest (np)) { 37473166Sse printf ("CACHE INCORRECTLY CONFIGURED.\n"); 374860974Sdfr return EINVAL; 37493166Sse }; 37503166Sse 37513166Sse /* 37526705Sse ** Install the interrupt handler. 37533533Sse */ 37543533Sse 375560974Sdfr rid = 0; 3756127135Snjl np->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 3757127135Snjl RF_SHAREABLE | RF_ACTIVE); 375860974Sdfr if (np->irq_res == NULL) { 375960974Sdfr device_printf(dev, 376060974Sdfr "interruptless mode: reduced performance.\n"); 376160974Sdfr } else { 376273280Smarkm bus_setup_intr(dev, np->irq_res, INTR_TYPE_CAM | INTR_ENTROPY, 3763166920Simp NULL, ncr_intr, np, &np->irq_handle); 376460974Sdfr } 37653533Sse 37663533Sse /* 376739386Sgibbs ** Create the device queue. We only allow MAX_START-1 concurrent 376839386Sgibbs ** transactions so we can be sure to have one element free in our 376939386Sgibbs ** start queue to reset to the idle loop. 37702432Sse */ 377139386Sgibbs devq = cam_simq_alloc(MAX_START - 1); 377239247Sgibbs if (devq == NULL) 377360974Sdfr return ENOMEM; 37742432Sse 37752432Sse /* 377639247Sgibbs ** Now tell the generic SCSI layer 377739247Sgibbs ** about our bus. 37782432Sse */ 377939247Sgibbs np->sim = cam_sim_alloc(ncr_action, ncr_poll, "ncr", np, np->unit, 3780168752Sscottl &Giant, 1, MAX_TAGS, devq); 378139247Sgibbs if (np->sim == NULL) { 378239247Sgibbs cam_simq_free(devq); 378360974Sdfr return ENOMEM; 378439247Sgibbs } 37852432Sse 378639247Sgibbs 3787170872Sscottl if (xpt_bus_register(np->sim, dev, 0) != CAM_SUCCESS) { 378847374Sken cam_sim_free(np->sim, /*free_devq*/ TRUE); 378960974Sdfr return ENOMEM; 379010605Sse } 379139247Sgibbs 379239247Sgibbs if (xpt_create_path(&np->path, /*periph*/NULL, 379339247Sgibbs cam_sim_path(np->sim), CAM_TARGET_WILDCARD, 379439247Sgibbs CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 379539247Sgibbs xpt_bus_deregister(cam_sim_path(np->sim)); 379647374Sken cam_sim_free(np->sim, /*free_devq*/TRUE); 379760974Sdfr return ENOMEM; 379839247Sgibbs } 37992432Sse 38002432Sse /* 38012432Sse ** start the timeout daemon 38022432Sse */ 38032432Sse ncr_timeout (np); 38042432Sse np->lasttime=0; 38052432Sse 380660974Sdfr return 0; 38072432Sse} 38087228Sse 38092432Sse/*========================================================== 38102432Sse** 38112432Sse** 38126705Sse** Process pending device interrupts. 38132432Sse** 38142432Sse** 38152432Sse**========================================================== 38162432Sse*/ 38172432Sse 381813597Ssestatic void 381912879Sbdencr_intr(vnp) 382012879Sbde void *vnp; 38212432Sse{ 382212879Sbde ncb_p np = vnp; 382339247Sgibbs int oldspl = splcam(); 38242432Sse 38253552Sse if (DEBUG_FLAGS & DEBUG_TINY) printf ("["); 38262432Sse 38273533Sse if (INB(nc_istat) & (INTF|SIP|DIP)) { 38283533Sse /* 38293533Sse ** Repeat until no outstanding ints 38303533Sse */ 38313533Sse do { 38323533Sse ncr_exception (np); 38333533Sse } while (INB(nc_istat) & (INTF|SIP|DIP)); 38343533Sse 38353533Sse np->ticks = 100; 38362432Sse }; 38372432Sse 38383552Sse if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n"); 38392432Sse 38406460Sse splx (oldspl); 38412432Sse} 38427228Sse 38432432Sse/*========================================================== 38442432Sse** 38452432Sse** 38462432Sse** Start execution of a SCSI command. 38472432Sse** This is called from the generic SCSI driver. 38482432Sse** 38492432Sse** 38502432Sse**========================================================== 38512432Sse*/ 38522432Sse 385339247Sgibbsstatic void 385439247Sgibbsncr_action (struct cam_sim *sim, union ccb *ccb) 38552432Sse{ 385639247Sgibbs ncb_p np; 38572432Sse 385839247Sgibbs np = (ncb_p) cam_sim_softc(sim); 38592432Sse 386039247Sgibbs switch (ccb->ccb_h.func_code) { 386139247Sgibbs /* Common cases first */ 386239247Sgibbs case XPT_SCSI_IO: /* Execute the requested I/O operation */ 386339247Sgibbs { 386439247Sgibbs nccb_p cp; 386539247Sgibbs lcb_p lp; 386639247Sgibbs tcb_p tp; 386739247Sgibbs int oldspl; 386839247Sgibbs struct ccb_scsiio *csio; 386939247Sgibbs u_int8_t *msgptr; 387039247Sgibbs u_int msglen; 387139247Sgibbs u_int msglen2; 387239247Sgibbs int segments; 387339247Sgibbs u_int8_t nego; 387439247Sgibbs u_int8_t idmsg; 3875118073Srobert int qidx; 387639247Sgibbs 387739247Sgibbs tp = &np->target[ccb->ccb_h.target_id]; 387839247Sgibbs csio = &ccb->csio; 38792432Sse 388039247Sgibbs oldspl = splcam(); 38812432Sse 388239247Sgibbs /* 388339247Sgibbs * Last time we need to check if this CCB needs to 388439247Sgibbs * be aborted. 388539247Sgibbs */ 388639247Sgibbs if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 388739247Sgibbs xpt_done(ccb); 388839247Sgibbs splx(oldspl); 388939247Sgibbs return; 389039247Sgibbs } 389139247Sgibbs ccb->ccb_h.status |= CAM_SIM_QUEUED; 38927228Sse 389339247Sgibbs /*--------------------------------------------------- 389439247Sgibbs ** 389539247Sgibbs ** Assign an nccb / bind ccb 389639247Sgibbs ** 389739247Sgibbs **---------------------------------------------------- 389839247Sgibbs */ 389939247Sgibbs cp = ncr_get_nccb (np, ccb->ccb_h.target_id, 390039247Sgibbs ccb->ccb_h.target_lun); 390139247Sgibbs if (cp == NULL) { 390239247Sgibbs /* XXX JGibbs - Freeze SIMQ */ 390339247Sgibbs ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 390439247Sgibbs xpt_done(ccb); 390539247Sgibbs return; 390639247Sgibbs }; 390739247Sgibbs 390839247Sgibbs cp->ccb = ccb; 390939247Sgibbs 391039247Sgibbs /*--------------------------------------------------- 391139247Sgibbs ** 391239247Sgibbs ** timestamp 391339247Sgibbs ** 391439247Sgibbs **---------------------------------------------------- 391539247Sgibbs */ 391639247Sgibbs /* 391739247Sgibbs ** XXX JGibbs - Isn't this expensive 391839247Sgibbs ** enough to be conditionalized?? 391939247Sgibbs */ 39202432Sse 392139247Sgibbs bzero (&cp->phys.header.stamp, sizeof (struct tstamp)); 392239247Sgibbs cp->phys.header.stamp.start = ticks; 39232432Sse 392439247Sgibbs nego = 0; 392539247Sgibbs if (tp->nego_cp == NULL) { 392639247Sgibbs 392739247Sgibbs if (tp->tinfo.current.width 392839247Sgibbs != tp->tinfo.goal.width) { 392939247Sgibbs tp->nego_cp = cp; 393039247Sgibbs nego = NS_WIDE; 393146581Sken } else if ((tp->tinfo.current.period 393246581Sken != tp->tinfo.goal.period) 393346581Sken || (tp->tinfo.current.offset 393446581Sken != tp->tinfo.goal.offset)) { 393539247Sgibbs tp->nego_cp = cp; 393639247Sgibbs nego = NS_SYNC; 393739247Sgibbs }; 393839247Sgibbs }; 39392814Sse 394039247Sgibbs /*--------------------------------------------------- 394139247Sgibbs ** 394239247Sgibbs ** choose a new tag ... 394339247Sgibbs ** 394439247Sgibbs **---------------------------------------------------- 394539247Sgibbs */ 394639247Sgibbs lp = tp->lp[ccb->ccb_h.target_lun]; 394739247Sgibbs 394839247Sgibbs if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0 394940418Sgibbs && (ccb->csio.tag_action != CAM_TAG_ACTION_NONE) 395039247Sgibbs && (nego == 0)) { 395139247Sgibbs /* 395239247Sgibbs ** assign a tag to this nccb 395339247Sgibbs */ 395439247Sgibbs while (!cp->tag) { 395539247Sgibbs nccb_p cp2 = lp->next_nccb; 395639247Sgibbs lp->lasttag = lp->lasttag % 255 + 1; 395739247Sgibbs while (cp2 && cp2->tag != lp->lasttag) 395839247Sgibbs cp2 = cp2->next_nccb; 395939247Sgibbs if (cp2) continue; 396039247Sgibbs cp->tag=lp->lasttag; 396139247Sgibbs if (DEBUG_FLAGS & DEBUG_TAGS) { 396239247Sgibbs PRINT_ADDR(ccb); 396339247Sgibbs printf ("using tag #%d.\n", cp->tag); 396439247Sgibbs }; 396539247Sgibbs }; 396639247Sgibbs } else { 396739247Sgibbs cp->tag=0; 39682814Sse }; 39692814Sse 397039247Sgibbs /*---------------------------------------------------- 397139247Sgibbs ** 397239247Sgibbs ** Build the identify / tag / sdtr message 397339247Sgibbs ** 397439247Sgibbs **---------------------------------------------------- 397539247Sgibbs */ 397639247Sgibbs idmsg = MSG_IDENTIFYFLAG | ccb->ccb_h.target_lun; 397739247Sgibbs if (tp->tinfo.disc_tag & NCR_CUR_DISCENB) 397839247Sgibbs idmsg |= MSG_IDENTIFY_DISCFLAG; 397918875Sse 398039247Sgibbs msgptr = cp->scsi_smsg; 398139247Sgibbs msglen = 0; 398239247Sgibbs msgptr[msglen++] = idmsg; 39832814Sse 398439247Sgibbs if (cp->tag) { 398539247Sgibbs msgptr[msglen++] = ccb->csio.tag_action; 398639247Sgibbs msgptr[msglen++] = cp->tag; 398739247Sgibbs } 39882432Sse 398939247Sgibbs switch (nego) { 399039247Sgibbs case NS_SYNC: 399139247Sgibbs msgptr[msglen++] = MSG_EXTENDED; 399239247Sgibbs msgptr[msglen++] = MSG_EXT_SDTR_LEN; 399339247Sgibbs msgptr[msglen++] = MSG_EXT_SDTR; 399439247Sgibbs msgptr[msglen++] = tp->tinfo.goal.period; 3995201758Smbr msgptr[msglen++] = tp->tinfo.goal.offset; 399639247Sgibbs if (DEBUG_FLAGS & DEBUG_NEGO) { 399739247Sgibbs PRINT_ADDR(ccb); 399839247Sgibbs printf ("sync msgout: "); 399939247Sgibbs ncr_show_msg (&cp->scsi_smsg [msglen-5]); 400039247Sgibbs printf (".\n"); 400139247Sgibbs }; 400239247Sgibbs break; 400339247Sgibbs case NS_WIDE: 400439247Sgibbs msgptr[msglen++] = MSG_EXTENDED; 400539247Sgibbs msgptr[msglen++] = MSG_EXT_WDTR_LEN; 400639247Sgibbs msgptr[msglen++] = MSG_EXT_WDTR; 400739247Sgibbs msgptr[msglen++] = tp->tinfo.goal.width; 400839247Sgibbs if (DEBUG_FLAGS & DEBUG_NEGO) { 400939247Sgibbs PRINT_ADDR(ccb); 401039247Sgibbs printf ("wide msgout: "); 401139247Sgibbs ncr_show_msg (&cp->scsi_smsg [msglen-4]); 401239247Sgibbs printf (".\n"); 401339247Sgibbs }; 401439247Sgibbs break; 401539247Sgibbs }; 40162432Sse 401739247Sgibbs /*---------------------------------------------------- 401839247Sgibbs ** 401939247Sgibbs ** Build the identify message for getcc. 402039247Sgibbs ** 402139247Sgibbs **---------------------------------------------------- 402239247Sgibbs */ 40232432Sse 402439247Sgibbs cp->scsi_smsg2 [0] = idmsg; 402539247Sgibbs msglen2 = 1; 40262432Sse 402739247Sgibbs /*---------------------------------------------------- 402839247Sgibbs ** 402939247Sgibbs ** Build the data descriptors 403039247Sgibbs ** 403139247Sgibbs **---------------------------------------------------- 403239247Sgibbs */ 40332432Sse 403439247Sgibbs /* XXX JGibbs - Handle other types of I/O */ 403539247Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 403639247Sgibbs segments = ncr_scatter(&cp->phys, 403739247Sgibbs (vm_offset_t)csio->data_ptr, 403839247Sgibbs (vm_size_t)csio->dxfer_len); 40396302Sse 404039247Sgibbs if (segments < 0) { 404139247Sgibbs ccb->ccb_h.status = CAM_REQ_TOO_BIG; 404239247Sgibbs ncr_free_nccb(np, cp); 404339247Sgibbs splx(oldspl); 404439247Sgibbs xpt_done(ccb); 404539247Sgibbs return; 404639247Sgibbs } 404739247Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 404839247Sgibbs cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_in); 404939247Sgibbs cp->phys.header.goalp = cp->phys.header.savep +20 +segments*16; 405039247Sgibbs } else { /* CAM_DIR_OUT */ 405139247Sgibbs cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_out); 405239247Sgibbs cp->phys.header.goalp = cp->phys.header.savep +20 +segments*16; 405339247Sgibbs } 405439247Sgibbs } else { 405539247Sgibbs cp->phys.header.savep = NCB_SCRIPT_PHYS (np, no_data); 405639247Sgibbs cp->phys.header.goalp = cp->phys.header.savep; 405739247Sgibbs } 40582432Sse 405939247Sgibbs cp->phys.header.lastp = cp->phys.header.savep; 40602432Sse 40617228Sse 406239247Sgibbs /*---------------------------------------------------- 406339247Sgibbs ** 406439247Sgibbs ** fill in nccb 406539247Sgibbs ** 406639247Sgibbs **---------------------------------------------------- 406739247Sgibbs ** 406839247Sgibbs ** 406939247Sgibbs ** physical -> virtual backlink 407039247Sgibbs ** Generic SCSI command 407139247Sgibbs */ 407239247Sgibbs cp->phys.header.cp = cp; 407326568Sse /* 407439247Sgibbs ** Startqueue 407526568Sse */ 407639247Sgibbs cp->phys.header.launch.l_paddr = NCB_SCRIPT_PHYS (np, select); 407739247Sgibbs cp->phys.header.launch.l_cmd = SCR_JUMP; 40782432Sse /* 407939247Sgibbs ** select 408014556Sse */ 408139247Sgibbs cp->phys.select.sel_id = ccb->ccb_h.target_id; 408239247Sgibbs cp->phys.select.sel_scntl3 = tp->tinfo.wval; 408339247Sgibbs cp->phys.select.sel_sxfer = tp->tinfo.sval; 408439247Sgibbs /* 408539247Sgibbs ** message 408639247Sgibbs */ 408739247Sgibbs cp->phys.smsg.addr = CCB_PHYS (cp, scsi_smsg); 408839247Sgibbs cp->phys.smsg.size = msglen; 408939247Sgibbs 409039247Sgibbs cp->phys.smsg2.addr = CCB_PHYS (cp, scsi_smsg2); 409139247Sgibbs cp->phys.smsg2.size = msglen2; 409239247Sgibbs /* 409339247Sgibbs ** command 409439247Sgibbs */ 409539247Sgibbs /* XXX JGibbs - Support other command types */ 409639247Sgibbs cp->phys.cmd.addr = vtophys (csio->cdb_io.cdb_bytes); 409739247Sgibbs cp->phys.cmd.size = csio->cdb_len; 409839247Sgibbs /* 409939247Sgibbs ** sense command 410039247Sgibbs */ 410139247Sgibbs cp->phys.scmd.addr = CCB_PHYS (cp, sensecmd); 410239247Sgibbs cp->phys.scmd.size = 6; 410339247Sgibbs /* 410439247Sgibbs ** patch requested size into sense command 410539247Sgibbs */ 410639247Sgibbs cp->sensecmd[0] = 0x03; 410739247Sgibbs cp->sensecmd[1] = ccb->ccb_h.target_lun << 5; 410839247Sgibbs cp->sensecmd[4] = sizeof(struct scsi_sense_data); 410939247Sgibbs cp->sensecmd[4] = csio->sense_len; 411039247Sgibbs /* 411139247Sgibbs ** sense data 411239247Sgibbs */ 411339247Sgibbs cp->phys.sense.addr = vtophys (&csio->sense_data); 411439247Sgibbs cp->phys.sense.size = csio->sense_len; 411539247Sgibbs /* 411639247Sgibbs ** status 411739247Sgibbs */ 411839467Sgibbs cp->actualquirks = QUIRK_NOMSG; 411939247Sgibbs cp->host_status = nego ? HS_NEGOTIATE : HS_BUSY; 412039247Sgibbs cp->s_status = SCSI_STATUS_ILLEGAL; 412139247Sgibbs cp->parity_status = 0; 412239247Sgibbs 412339247Sgibbs cp->xerr_status = XE_OK; 412439247Sgibbs cp->sync_status = tp->tinfo.sval; 412539247Sgibbs cp->nego_status = nego; 412639247Sgibbs cp->wide_status = tp->tinfo.wval; 412714556Sse 412839247Sgibbs /*---------------------------------------------------- 412939247Sgibbs ** 413039247Sgibbs ** Critical region: start this job. 413139247Sgibbs ** 413239247Sgibbs **---------------------------------------------------- 413339247Sgibbs */ 413414556Sse 413514556Sse /* 413639247Sgibbs ** reselect pattern and activate this job. 41372432Sse */ 41388876Srgrimes 413939247Sgibbs cp->jump_nccb.l_cmd = (SCR_JUMP ^ IFFALSE (DATA (cp->tag))); 414039247Sgibbs cp->tlimit = time_second 414139247Sgibbs + ccb->ccb_h.timeout / 1000 + 2; 414239247Sgibbs cp->magic = CCB_MAGIC; 414327684Sse 414427684Sse /* 414539247Sgibbs ** insert into start queue. 414627684Sse */ 414727684Sse 414839247Sgibbs qidx = np->squeueput + 1; 4149118073Srobert if (qidx >= MAX_START) 4150118073Srobert qidx = 0; 415139247Sgibbs np->squeue [qidx ] = NCB_SCRIPT_PHYS (np, idle); 415239247Sgibbs np->squeue [np->squeueput] = CCB_PHYS (cp, phys); 415339247Sgibbs np->squeueput = qidx; 41547228Sse 415539247Sgibbs if(DEBUG_FLAGS & DEBUG_QUEUE) 415639247Sgibbs printf("%s: queuepos=%d tryoffset=%d.\n", 415739247Sgibbs ncr_name (np), np->squeueput, 415839532Sken (unsigned)(READSCRIPT(startpos[0]) - 415939247Sgibbs (NCB_SCRIPTH_PHYS (np, tryloop)))); 41602432Sse 41612432Sse /* 416239247Sgibbs ** Script processor may be waiting for reselect. 416339247Sgibbs ** Wake it up. 41642432Sse */ 416539247Sgibbs OUTB (nc_istat, SIGP); 41667228Sse 41672432Sse /* 416839247Sgibbs ** and reenable interrupts 41692432Sse */ 417039247Sgibbs splx (oldspl); 417139247Sgibbs break; 41722432Sse } 417339247Sgibbs case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 417439247Sgibbs case XPT_EN_LUN: /* Enable LUN as a target */ 417539247Sgibbs case XPT_TARGET_IO: /* Execute target I/O request */ 417639247Sgibbs case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 417739247Sgibbs case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 417839247Sgibbs case XPT_ABORT: /* Abort the specified CCB */ 417939247Sgibbs /* XXX Implement */ 418039247Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 418139247Sgibbs xpt_done(ccb); 41822814Sse break; 418339247Sgibbs case XPT_SET_TRAN_SETTINGS: 418439247Sgibbs { 4185163816Smjacob struct ccb_trans_settings *cts = &ccb->cts; 418639247Sgibbs tcb_p tp; 418739247Sgibbs u_int update_type; 418839247Sgibbs int s; 4189163816Smjacob struct ccb_trans_settings_scsi *scsi = 4190163816Smjacob &cts->proto_specific.scsi; 4191163816Smjacob struct ccb_trans_settings_spi *spi = 4192163816Smjacob &cts->xport_specific.spi; 41937228Sse 419439247Sgibbs update_type = 0; 4195163816Smjacob if (cts->type == CTS_TYPE_CURRENT_SETTINGS) 4196163816Smjacob update_type |= NCR_TRANS_GOAL; 4197163816Smjacob if (cts->type == CTS_TYPE_USER_SETTINGS) 4198163816Smjacob update_type |= NCR_TRANS_USER; 4199163816Smjacob 4200163816Smjacob s = splcam(); 4201163816Smjacob tp = &np->target[ccb->ccb_h.target_id]; 4202163816Smjacob /* Tag and disc enables */ 4203163816Smjacob if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { 4204163816Smjacob if (update_type & NCR_TRANS_GOAL) { 4205163816Smjacob if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) 4206163816Smjacob tp->tinfo.disc_tag |= NCR_CUR_DISCENB; 4207163816Smjacob else 4208163816Smjacob tp->tinfo.disc_tag &= ~NCR_CUR_DISCENB; 4209163816Smjacob } 4210163816Smjacob 4211163816Smjacob if (update_type & NCR_TRANS_USER) { 4212163816Smjacob if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) 4213163816Smjacob tp->tinfo.disc_tag |= NCR_USR_DISCENB; 4214163816Smjacob else 4215163816Smjacob tp->tinfo.disc_tag &= ~NCR_USR_DISCENB; 4216163816Smjacob } 4217163816Smjacob 4218163816Smjacob } 4219163816Smjacob 4220163816Smjacob if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 4221163816Smjacob if (update_type & NCR_TRANS_GOAL) { 4222163816Smjacob if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) 4223163816Smjacob tp->tinfo.disc_tag |= NCR_CUR_TAGENB; 4224163816Smjacob else 4225163816Smjacob tp->tinfo.disc_tag &= ~NCR_CUR_TAGENB; 4226163816Smjacob } 4227163816Smjacob 4228163816Smjacob if (update_type & NCR_TRANS_USER) { 4229163816Smjacob if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) 4230163816Smjacob tp->tinfo.disc_tag |= NCR_USR_TAGENB; 4231163816Smjacob else 4232163816Smjacob tp->tinfo.disc_tag &= ~NCR_USR_TAGENB; 4233163816Smjacob } 4234163816Smjacob } 4235163816Smjacob 4236163816Smjacob /* Filter bus width and sync negotiation settings */ 4237163816Smjacob if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { 4238163816Smjacob if (spi->bus_width > np->maxwide) 4239163816Smjacob spi->bus_width = np->maxwide; 4240163816Smjacob } 4241163816Smjacob 4242163816Smjacob if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) 4243163816Smjacob || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) { 4244163816Smjacob if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) { 4245163816Smjacob if (spi->sync_period != 0 4246163816Smjacob && (spi->sync_period < np->minsync)) 4247163816Smjacob spi->sync_period = np->minsync; 4248163816Smjacob } 4249163816Smjacob if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) { 4250163816Smjacob if (spi->sync_offset == 0) 4251163816Smjacob spi->sync_period = 0; 4252163816Smjacob if (spi->sync_offset > np->maxoffs) 4253163816Smjacob spi->sync_offset = np->maxoffs; 4254163816Smjacob } 4255163816Smjacob } 4256163816Smjacob if ((update_type & NCR_TRANS_USER) != 0) { 4257163816Smjacob if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) 4258163816Smjacob tp->tinfo.user.period = spi->sync_period; 4259163816Smjacob if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) 4260163816Smjacob tp->tinfo.user.offset = spi->sync_offset; 4261163816Smjacob if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) 4262163816Smjacob tp->tinfo.user.width = spi->bus_width; 4263163816Smjacob } 4264163816Smjacob if ((update_type & NCR_TRANS_GOAL) != 0) { 4265163816Smjacob if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) 4266163816Smjacob tp->tinfo.goal.period = spi->sync_period; 4267163816Smjacob 4268163816Smjacob if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) 4269163816Smjacob tp->tinfo.goal.offset = spi->sync_offset; 4270163816Smjacob 4271163816Smjacob if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) 4272163816Smjacob tp->tinfo.goal.width = spi->bus_width; 4273163816Smjacob } 4274163816Smjacob splx(s); 427539247Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 427639247Sgibbs xpt_done(ccb); 427739247Sgibbs break; 427839247Sgibbs } 427939247Sgibbs case XPT_GET_TRAN_SETTINGS: 428039247Sgibbs /* Get default/user set transfer settings for the target */ 428139247Sgibbs { 4282163816Smjacob struct ccb_trans_settings *cts = &ccb->cts; 428339247Sgibbs struct ncr_transinfo *tinfo; 4284163816Smjacob tcb_p tp = &np->target[ccb->ccb_h.target_id]; 428539247Sgibbs int s; 4286163816Smjacob struct ccb_trans_settings_scsi *scsi = 4287163816Smjacob &cts->proto_specific.scsi; 4288163816Smjacob struct ccb_trans_settings_spi *spi = 4289163816Smjacob &cts->xport_specific.spi; 42902814Sse 4291163816Smjacob cts->protocol = PROTO_SCSI; 4292163816Smjacob cts->protocol_version = SCSI_REV_2; 4293163816Smjacob cts->transport = XPORT_SPI; 4294163816Smjacob cts->transport_version = 2; 4295163816Smjacob 429639247Sgibbs s = splcam(); 4297163816Smjacob if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { 4298163816Smjacob tinfo = &tp->tinfo.current; 4299163816Smjacob if (tp->tinfo.disc_tag & NCR_CUR_DISCENB) 4300163816Smjacob spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 4301163816Smjacob else 4302163816Smjacob spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 4303163816Smjacob 4304163816Smjacob if (tp->tinfo.disc_tag & NCR_CUR_TAGENB) 4305163816Smjacob scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 4306163816Smjacob else 4307163816Smjacob scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 4308163816Smjacob } else { 4309163816Smjacob tinfo = &tp->tinfo.user; 4310163816Smjacob if (tp->tinfo.disc_tag & NCR_USR_DISCENB) 4311163816Smjacob spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 4312163816Smjacob else 4313163816Smjacob spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 4314163816Smjacob 4315163816Smjacob if (tp->tinfo.disc_tag & NCR_USR_TAGENB) 4316163816Smjacob scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 4317163816Smjacob else 4318163816Smjacob scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 4319163816Smjacob } 4320163816Smjacob 4321163816Smjacob spi->sync_period = tinfo->period; 4322163816Smjacob spi->sync_offset = tinfo->offset; 4323163816Smjacob spi->bus_width = tinfo->width; 4324163816Smjacob 4325163816Smjacob splx(s); 4326163816Smjacob spi->valid = CTS_SPI_VALID_SYNC_RATE 4327163816Smjacob | CTS_SPI_VALID_SYNC_OFFSET 4328163816Smjacob | CTS_SPI_VALID_BUS_WIDTH 4329163816Smjacob | CTS_SPI_VALID_DISC; 4330163816Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 43317228Sse 433239247Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 433339247Sgibbs xpt_done(ccb); 433439247Sgibbs break; 433539247Sgibbs } 433639247Sgibbs case XPT_CALC_GEOMETRY: 433739247Sgibbs { 433839247Sgibbs /* XXX JGibbs - I'm sure the NCR uses a different strategy, 433939247Sgibbs * but it should be able to deal with Adaptec 434039247Sgibbs * geometry too. 434139247Sgibbs */ 4342116351Snjl cam_calc_geometry(&ccb->ccg, /*extended*/1); 434339247Sgibbs xpt_done(ccb); 434439247Sgibbs break; 434539247Sgibbs } 434639247Sgibbs case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 434739247Sgibbs { 434839247Sgibbs OUTB (nc_scntl1, CRST); 434939247Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 435039247Sgibbs DELAY(10000); /* Wait until our interrupt handler sees it */ 435139247Sgibbs xpt_done(ccb); 435239247Sgibbs break; 435339247Sgibbs } 435439247Sgibbs case XPT_TERM_IO: /* Terminate the I/O process */ 435539247Sgibbs /* XXX Implement */ 435639247Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 435739247Sgibbs xpt_done(ccb); 435839247Sgibbs break; 435939247Sgibbs case XPT_PATH_INQ: /* Path routing inquiry */ 436039247Sgibbs { 436139247Sgibbs struct ccb_pathinq *cpi = &ccb->cpi; 436239247Sgibbs 436339247Sgibbs cpi->version_num = 1; /* XXX??? */ 436439247Sgibbs cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE; 436539247Sgibbs if ((np->features & FE_WIDE) != 0) 436639247Sgibbs cpi->hba_inquiry |= PI_WIDE_16; 436739247Sgibbs cpi->target_sprt = 0; 436839247Sgibbs cpi->hba_misc = 0; 436939247Sgibbs cpi->hba_eng_cnt = 0; 437039247Sgibbs cpi->max_target = (np->features & FE_WIDE) ? 15 : 7; 437139247Sgibbs cpi->max_lun = MAX_LUN - 1; 437239247Sgibbs cpi->initiator_id = np->myaddr; 437339247Sgibbs cpi->bus_id = cam_sim_bus(sim); 437446581Sken cpi->base_transfer_speed = 3300; 437539247Sgibbs strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 437639247Sgibbs strncpy(cpi->hba_vid, "Symbios", HBA_IDLEN); 437739247Sgibbs strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 437839247Sgibbs cpi->unit_number = cam_sim_unit(sim); 4379163816Smjacob cpi->transport = XPORT_SPI; 4380163816Smjacob cpi->transport_version = 2; 4381163816Smjacob cpi->protocol = PROTO_SCSI; 4382163816Smjacob cpi->protocol_version = SCSI_REV_2; 438339247Sgibbs cpi->ccb_h.status = CAM_REQ_CMP; 438439247Sgibbs xpt_done(ccb); 438539247Sgibbs break; 438639247Sgibbs } 438739247Sgibbs default: 438839247Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 438939247Sgibbs xpt_done(ccb); 439039247Sgibbs break; 439139247Sgibbs } 43922432Sse} 43937228Sse 43942432Sse/*========================================================== 43952432Sse** 43962432Sse** 43972432Sse** Complete execution of a SCSI command. 43982432Sse** Signal completion to the generic SCSI driver. 43992432Sse** 44002432Sse** 44012432Sse**========================================================== 44022432Sse*/ 44032432Sse 4404105219Sphkstatic void 440539247Sgibbsncr_complete (ncb_p np, nccb_p cp) 44062432Sse{ 440739247Sgibbs union ccb *ccb; 44082432Sse tcb_p tp; 44092432Sse 44102432Sse /* 44112432Sse ** Sanity check 44122432Sse */ 44132432Sse 441439247Sgibbs if (!cp || (cp->magic!=CCB_MAGIC) || !cp->ccb) return; 44152432Sse cp->magic = 1; 44162432Sse cp->tlimit= 0; 44172432Sse 44182432Sse /* 44192432Sse ** No Reselect anymore. 44202432Sse */ 442139247Sgibbs cp->jump_nccb.l_cmd = (SCR_JUMP); 44222432Sse 44232432Sse /* 44242432Sse ** No starting. 44252432Sse */ 442610677Sse cp->phys.header.launch.l_paddr= NCB_SCRIPT_PHYS (np, idle); 44272432Sse 44282432Sse /* 44292432Sse ** timestamp 44302432Sse */ 44312432Sse ncb_profile (np, cp); 44327228Sse 44333552Sse if (DEBUG_FLAGS & DEBUG_TINY) 443439532Sken printf ("CCB=%x STAT=%x/%x\n", (int)(intptr_t)cp & 0xfff, 443539247Sgibbs cp->host_status,cp->s_status); 44362432Sse 443739247Sgibbs ccb = cp->ccb; 443839247Sgibbs cp->ccb = NULL; 443939247Sgibbs tp = &np->target[ccb->ccb_h.target_id]; 44402432Sse 44412432Sse /* 444239247Sgibbs ** We do not queue more than 1 nccb per target 444339247Sgibbs ** with negotiation at any time. If this nccb was 444427684Sse ** used for negotiation, clear this info in the tcb. 444527684Sse */ 444627684Sse 444727684Sse if (cp == tp->nego_cp) 444839247Sgibbs tp->nego_cp = NULL; 444927684Sse 445027684Sse /* 44512432Sse ** Check for parity errors. 44522432Sse */ 445339247Sgibbs /* XXX JGibbs - What about reporting them??? */ 44542432Sse 44552814Sse if (cp->parity_status) { 445639247Sgibbs PRINT_ADDR(ccb); 44572814Sse printf ("%d parity error(s), fallback.\n", cp->parity_status); 44582432Sse /* 44592432Sse ** fallback to asynch transfer. 44602432Sse */ 446139247Sgibbs tp->tinfo.goal.period = 0; 446239247Sgibbs tp->tinfo.goal.offset = 0; 44632432Sse }; 44642814Sse 44652814Sse /* 44662814Sse ** Check for extended errors. 44672814Sse */ 44682814Sse 44697250Sse if (cp->xerr_status != XE_OK) { 447039247Sgibbs PRINT_ADDR(ccb); 44712814Sse switch (cp->xerr_status) { 44722814Sse case XE_EXTRA_DATA: 44732814Sse printf ("extraneous data discarded.\n"); 44742814Sse break; 44752814Sse case XE_BAD_PHASE: 44762814Sse printf ("illegal scsi phase (4/5).\n"); 44772814Sse break; 44782814Sse default: 44792814Sse printf ("extended error %d.\n", cp->xerr_status); 44802814Sse break; 44812814Sse }; 44822814Sse if (cp->host_status==HS_COMPLETE) 44832814Sse cp->host_status = HS_FAIL; 44842814Sse }; 44857228Sse 44862432Sse /* 44872432Sse ** Check the status. 44882432Sse */ 448939247Sgibbs if (cp->host_status == HS_COMPLETE) { 44902432Sse 449139247Sgibbs if (cp->s_status == SCSI_STATUS_OK) { 44922814Sse 44932814Sse /* 449439247Sgibbs ** All went well. 44952435Sse */ 449639247Sgibbs /* XXX JGibbs - Properly calculate residual */ 44972432Sse 449839247Sgibbs tp->bytes += ccb->csio.dxfer_len; 449939247Sgibbs tp->transfers ++; 45007228Sse 450139247Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 450239247Sgibbs } else if ((cp->s_status & SCSI_STATUS_SENSE) != 0) { 45032432Sse 450439247Sgibbs /* 450539247Sgibbs * XXX Could be TERMIO too. Should record 450639247Sgibbs * original status. 450739247Sgibbs */ 450839247Sgibbs ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 450939247Sgibbs cp->s_status &= ~SCSI_STATUS_SENSE; 451039247Sgibbs if (cp->s_status == SCSI_STATUS_OK) { 451139247Sgibbs ccb->ccb_h.status = 451239247Sgibbs CAM_AUTOSNS_VALID|CAM_SCSI_STATUS_ERROR; 451339247Sgibbs } else { 451439247Sgibbs ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; 451539247Sgibbs } 451639247Sgibbs } else { 451739247Sgibbs ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 451839247Sgibbs ccb->csio.scsi_status = cp->s_status; 451939247Sgibbs } 452039247Sgibbs 452139247Sgibbs 452214938Sgibbs } else if (cp->host_status == HS_SEL_TIMEOUT) { 45232432Sse 45242432Sse /* 452514938Sgibbs ** Device failed selection 452614938Sgibbs */ 452739247Sgibbs ccb->ccb_h.status = CAM_SEL_TIMEOUT; 452829292Sse 452939247Sgibbs } else if (cp->host_status == HS_TIMEOUT) { 453014938Sgibbs 453114938Sgibbs /* 45322432Sse ** No response 45332432Sse */ 453439247Sgibbs ccb->ccb_h.status = CAM_CMD_TIMEOUT; 453539247Sgibbs } else if (cp->host_status == HS_STALL) { 453639247Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 45372432Sse } else { 45382432Sse 45392432Sse /* 45402432Sse ** Other protocol messes 45412432Sse */ 454239247Sgibbs PRINT_ADDR(ccb); 454339532Sken printf ("COMMAND FAILED (%x %x) @%p.\n", 454439532Sken cp->host_status, cp->s_status, cp); 45452432Sse 454639247Sgibbs ccb->ccb_h.status = CAM_CMD_TIMEOUT; 45472432Sse } 45487228Sse 454939247Sgibbs if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 455039247Sgibbs xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); 455139247Sgibbs ccb->ccb_h.status |= CAM_DEV_QFRZN; 455239247Sgibbs } 45532432Sse 45542432Sse /* 455539247Sgibbs ** Free this nccb 45562435Sse */ 455739247Sgibbs ncr_free_nccb (np, cp); 45582435Sse 45592435Sse /* 45602432Sse ** signal completion to generic driver. 45612432Sse */ 456239247Sgibbs xpt_done (ccb); 45632432Sse} 45647228Sse 45652432Sse/*========================================================== 45662432Sse** 45672432Sse** 45682432Sse** Signal all (or one) control block done. 45692432Sse** 45702432Sse** 45712432Sse**========================================================== 45722432Sse*/ 45732432Sse 4574105219Sphkstatic void 457539247Sgibbsncr_wakeup (ncb_p np, u_long code) 45762432Sse{ 45772432Sse /* 457839247Sgibbs ** Starting at the default nccb and following 45792432Sse ** the links, complete all jobs with a 45802432Sse ** host_status greater than "disconnect". 45812432Sse ** 45822432Sse ** If the "code" parameter is not zero, 45832432Sse ** complete all jobs that are not IDLE. 45842432Sse */ 45852432Sse 458639247Sgibbs nccb_p cp = np->link_nccb; 45872432Sse while (cp) { 45882432Sse switch (cp->host_status) { 45892432Sse 45902432Sse case HS_IDLE: 45912432Sse break; 45922432Sse 45932432Sse case HS_DISCONNECT: 45943552Sse if(DEBUG_FLAGS & DEBUG_TINY) printf ("D"); 4595102412Scharnier /* FALLTHROUGH */ 45962432Sse 45972432Sse case HS_BUSY: 45982432Sse case HS_NEGOTIATE: 45992432Sse if (!code) break; 46002432Sse cp->host_status = code; 46012432Sse 4602102412Scharnier /* FALLTHROUGH */ 46032432Sse 46042432Sse default: 46052432Sse ncr_complete (np, cp); 46062432Sse break; 46072432Sse }; 460839247Sgibbs cp = cp -> link_nccb; 46092432Sse }; 46102432Sse} 46117228Sse 461239247Sgibbsstatic void 461339247Sgibbsncr_freeze_devq (ncb_p np, struct cam_path *path) 461439247Sgibbs{ 461539386Sgibbs nccb_p cp; 461639438Sgibbs int i; 461739386Sgibbs int count; 461839438Sgibbs int firstskip; 461939247Sgibbs /* 462039247Sgibbs ** Starting at the first nccb and following 462139247Sgibbs ** the links, complete all jobs that match 462239247Sgibbs ** the passed in path and are in the start queue. 462339247Sgibbs */ 462439247Sgibbs 462539386Sgibbs cp = np->link_nccb; 462639386Sgibbs count = 0; 462739438Sgibbs firstskip = 0; 462839247Sgibbs while (cp) { 462939247Sgibbs switch (cp->host_status) { 463039247Sgibbs 463139247Sgibbs case HS_BUSY: 463239247Sgibbs case HS_NEGOTIATE: 463339247Sgibbs if ((cp->phys.header.launch.l_paddr 463439247Sgibbs == NCB_SCRIPT_PHYS (np, select)) 463539247Sgibbs && (xpt_path_comp(path, cp->ccb->ccb_h.path) >= 0)) { 463639247Sgibbs 463739386Sgibbs /* Mark for removal from the start queue */ 463839438Sgibbs for (i = 1; i < MAX_START; i++) { 463939438Sgibbs int idx; 464039438Sgibbs 464139438Sgibbs idx = np->squeueput - i; 464239438Sgibbs 464339438Sgibbs if (idx < 0) 464439438Sgibbs idx = MAX_START + idx; 464539438Sgibbs if (np->squeue[idx] 464639438Sgibbs == CCB_PHYS(cp, phys)) { 464739438Sgibbs np->squeue[idx] = 464839366Sgibbs NCB_SCRIPT_PHYS (np, skip); 464939438Sgibbs if (i > firstskip) 465039438Sgibbs firstskip = i; 465139438Sgibbs break; 465239438Sgibbs } 465339366Sgibbs } 465439247Sgibbs cp->host_status=HS_STALL; 465539247Sgibbs ncr_complete (np, cp); 465639386Sgibbs count++; 465739247Sgibbs } 465839366Sgibbs break; 465939247Sgibbs default: 466039247Sgibbs break; 466139247Sgibbs } 466239247Sgibbs cp = cp->link_nccb; 466339366Sgibbs } 466439386Sgibbs 466539386Sgibbs if (count > 0) { 466639386Sgibbs int j; 466739386Sgibbs int bidx; 466839386Sgibbs 466939386Sgibbs /* Compress the start queue */ 467039386Sgibbs j = 0; 467139386Sgibbs bidx = np->squeueput; 467239438Sgibbs i = np->squeueput - firstskip; 467339438Sgibbs if (i < 0) 467439438Sgibbs i = MAX_START + i; 467539438Sgibbs for (;;) { 467639386Sgibbs 467739386Sgibbs bidx = i - j; 467839386Sgibbs if (bidx < 0) 467939386Sgibbs bidx = MAX_START + bidx; 468039386Sgibbs 468139438Sgibbs if (np->squeue[i] == NCB_SCRIPT_PHYS (np, skip)) { 468239386Sgibbs j++; 468339438Sgibbs } else if (j != 0) { 468439386Sgibbs np->squeue[bidx] = np->squeue[i]; 468539386Sgibbs if (np->squeue[bidx] 468639386Sgibbs == NCB_SCRIPT_PHYS(np, idle)) 468739386Sgibbs break; 468839386Sgibbs } 468939438Sgibbs i = (i + 1) % MAX_START; 469039386Sgibbs } 469139386Sgibbs np->squeueput = bidx; 469239386Sgibbs } 469339247Sgibbs} 469439247Sgibbs 46952432Sse/*========================================================== 46962432Sse** 46972432Sse** 46982432Sse** Start NCR chip. 46992432Sse** 47002432Sse** 47012432Sse**========================================================== 47022432Sse*/ 47032432Sse 4704105219Sphkstatic void 470546581Skenncr_init(ncb_p np, char * msg, u_long code) 47062432Sse{ 47072432Sse int i; 47082432Sse 47092432Sse /* 47102432Sse ** Reset chip. 47112432Sse */ 47122432Sse 471310605Sse OUTB (nc_istat, SRST); 471410605Sse DELAY (1000); 471528958Sse OUTB (nc_istat, 0); 47162432Sse 47172432Sse /* 47182432Sse ** Message. 47192432Sse */ 47202432Sse 47212432Sse if (msg) printf ("%s: restart (%s).\n", ncr_name (np), msg); 47222432Sse 47232432Sse /* 47242432Sse ** Clear Start Queue 47252432Sse */ 47262432Sse 47272432Sse for (i=0;i<MAX_START;i++) 472810677Sse np -> squeue [i] = NCB_SCRIPT_PHYS (np, idle); 47292432Sse 47302432Sse /* 47312432Sse ** Start at first entry. 47322432Sse */ 47332432Sse 47342432Sse np->squeueput = 0; 473539532Sken WRITESCRIPT(startpos[0], NCB_SCRIPTH_PHYS (np, tryloop)); 473639532Sken WRITESCRIPT(start0 [0], SCR_INT ^ IFFALSE (0)); 47372432Sse 47382432Sse /* 47392432Sse ** Wakeup all pending jobs. 47402432Sse */ 47412432Sse 47422432Sse ncr_wakeup (np, code); 47437228Sse 47442432Sse /* 47452432Sse ** Init chip. 47462432Sse */ 47472432Sse 474820435Sse OUTB (nc_istat, 0x00 ); /* Remove Reset, abort ... */ 47492432Sse OUTB (nc_scntl0, 0xca ); /* full arb., ena parity, par->ATN */ 47502432Sse OUTB (nc_scntl1, 0x00 ); /* odd parity, and remove CRST!! */ 475127684Sse ncr_selectclock(np, np->rv_scntl3); /* Select SCSI clock */ 47526856Sse OUTB (nc_scid , RRE|np->myaddr);/* host adapter SCSI address */ 475310605Sse OUTW (nc_respid, 1ul<<np->myaddr);/* id to respond to */ 475410605Sse OUTB (nc_istat , SIGP ); /* Signal Process */ 475520435Sse OUTB (nc_dmode , np->rv_dmode); /* XXX modify burstlen ??? */ 475620435Sse OUTB (nc_dcntl , np->rv_dcntl); 475720435Sse OUTB (nc_ctest3, np->rv_ctest3); 475820435Sse OUTB (nc_ctest5, np->rv_ctest5); 475927684Sse OUTB (nc_ctest4, np->rv_ctest4);/* enable master parity checking */ 476027684Sse OUTB (nc_stest2, np->rv_stest2|EXT); /* Extended Sreq/Sack filtering */ 476110605Sse OUTB (nc_stest3, TE ); /* TolerANT enable */ 476213447Sse OUTB (nc_stime0, 0x0b ); /* HTH = disabled, STO = 0.1 sec. */ 47632432Sse 476427744Sse if (bootverbose >= 2) { 476527684Sse printf ("\tACTUAL values:SCNTL3:%02x DMODE:%02x DCNTL:%02x\n", 476627684Sse np->rv_scntl3, np->rv_dmode, np->rv_dcntl); 476727684Sse printf ("\t CTEST3:%02x CTEST4:%02x CTEST5:%02x\n", 476827684Sse np->rv_ctest3, np->rv_ctest4, np->rv_ctest5); 476920435Sse } 477020435Sse 47712432Sse /* 477227684Sse ** Enable GPIO0 pin for writing if LED support. 477327684Sse */ 477427684Sse 477527684Sse if (np->features & FE_LED0) { 477627684Sse OUTOFFB (nc_gpcntl, 0x01); 477727684Sse } 477827684Sse 477927684Sse /* 47802814Sse ** Fill in target structure. 47812814Sse */ 47822432Sse for (i=0;i<MAX_TARGET;i++) { 47832432Sse tcb_p tp = &np->target[i]; 47842814Sse 478539247Sgibbs tp->tinfo.sval = 0; 478639247Sgibbs tp->tinfo.wval = np->rv_scntl3; 47872814Sse 478839247Sgibbs tp->tinfo.current.period = 0; 478939247Sgibbs tp->tinfo.current.offset = 0; 479039247Sgibbs tp->tinfo.current.width = MSG_EXT_WDTR_BUS_8_BIT; 47912432Sse } 47922432Sse 47932432Sse /* 47942432Sse ** enable ints 47952432Sse */ 47962432Sse 47972432Sse OUTW (nc_sien , STO|HTH|MA|SGE|UDC|RST); 47982432Sse OUTB (nc_dien , MDPE|BF|ABRT|SSI|SIR|IID); 47992432Sse 48002432Sse /* 48012432Sse ** Start script processor. 48022432Sse */ 48032432Sse 480410677Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start)); 48057228Sse 48062814Sse /* 480739247Sgibbs * Notify the XPT of the event 480839247Sgibbs */ 480939247Sgibbs if (code == HS_RESET) 481039247Sgibbs xpt_async(AC_BUS_RESET, np->path, NULL); 481139247Sgibbs} 48122814Sse 481339247Sgibbsstatic void 481439247Sgibbsncr_poll(struct cam_sim *sim) 481539247Sgibbs{ 481639247Sgibbs ncr_intr(cam_sim_softc(sim)); 481739247Sgibbs} 48182814Sse 48192814Sse 48202814Sse/*========================================================== 48212814Sse** 482227684Sse** Get clock factor and sync divisor for a given 482327684Sse** synchronous factor period. 482427684Sse** Returns the clock factor (in sxfer) and scntl3 482527684Sse** synchronous divisor field. 482627684Sse** 482727684Sse**========================================================== 482827684Sse*/ 482927684Sse 483027684Ssestatic void ncr_getsync(ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p) 483127684Sse{ 483227684Sse u_long clk = np->clock_khz; /* SCSI clock frequency in kHz */ 483327684Sse int div = np->clock_divn; /* Number of divisors supported */ 483427684Sse u_long fak; /* Sync factor in sxfer */ 483527684Sse u_long per; /* Period in tenths of ns */ 483627684Sse u_long kpc; /* (per * clk) */ 483727684Sse 483827684Sse /* 483927684Sse ** Compute the synchronous period in tenths of nano-seconds 484027684Sse */ 484127684Sse if (sfac <= 10) per = 250; 484227684Sse else if (sfac == 11) per = 303; 484327684Sse else if (sfac == 12) per = 500; 484427684Sse else per = 40 * sfac; 484527684Sse 484627684Sse /* 484727684Sse ** Look for the greatest clock divisor that allows an 484827684Sse ** input speed faster than the period. 484927684Sse */ 485027684Sse kpc = per * clk; 485127684Sse while (--div >= 0) 485227684Sse if (kpc >= (div_10M[div] * 4)) break; 485327684Sse 485427684Sse /* 485527684Sse ** Calculate the lowest clock factor that allows an output 485627684Sse ** speed not faster than the period. 485727684Sse */ 485827684Sse fak = (kpc - 1) / div_10M[div] + 1; 485927684Sse 4860249585Sgabor#if 0 /* You can #if 1 if you think this optimization is useful */ 486127684Sse 486227684Sse per = (fak * div_10M[div]) / clk; 486327684Sse 486427684Sse /* 486527684Sse ** Why not to try the immediate lower divisor and to choose 486627684Sse ** the one that allows the fastest output speed ? 486727684Sse ** We dont want input speed too much greater than output speed. 486827684Sse */ 486927684Sse if (div >= 1 && fak < 6) { 487027684Sse u_long fak2, per2; 487127684Sse fak2 = (kpc - 1) / div_10M[div-1] + 1; 487227684Sse per2 = (fak2 * div_10M[div-1]) / clk; 487327684Sse if (per2 < per && fak2 <= 6) { 487427684Sse fak = fak2; 487527684Sse per = per2; 487627684Sse --div; 487727684Sse } 487827684Sse } 487927684Sse#endif 488027684Sse 488127684Sse if (fak < 4) fak = 4; /* Should never happen, too bad ... */ 488227684Sse 488327684Sse /* 488427684Sse ** Compute and return sync parameters for the ncr 488527684Sse */ 488627684Sse *fakp = fak - 4; 488727684Sse *scntl3p = ((div+1) << 4) + (sfac < 25 ? 0x80 : 0); 488827684Sse} 488927684Sse 489027684Sse/*========================================================== 489127684Sse** 489235256Sdes** Switch sync mode for current job and its target 48932432Sse** 48942432Sse**========================================================== 48952432Sse*/ 48962432Sse 489739247Sgibbsstatic void 489839247Sgibbsncr_setsync(ncb_p np, nccb_p cp, u_char scntl3, u_char sxfer, u_char period) 48992432Sse{ 490039247Sgibbs union ccb *ccb; 490139247Sgibbs struct ccb_trans_settings neg; 490239247Sgibbs tcb_p tp; 490339247Sgibbs int div; 490446843Sse u_int target = INB (nc_sdid) & 0x0f; 490539247Sgibbs u_int period_10ns; 49062432Sse 49072432Sse assert (cp); 49082432Sse if (!cp) return; 49092432Sse 491039247Sgibbs ccb = cp->ccb; 491139247Sgibbs assert (ccb); 491239247Sgibbs if (!ccb) return; 491339247Sgibbs assert (target == ccb->ccb_h.target_id); 49142432Sse 49152432Sse tp = &np->target[target]; 49162814Sse 491727684Sse if (!scntl3 || !(sxfer & 0x1f)) 491827684Sse scntl3 = np->rv_scntl3; 491939247Sgibbs scntl3 = (scntl3 & 0xf0) | (tp->tinfo.wval & EWS) 492039247Sgibbs | (np->rv_scntl3 & 0x07); 492127684Sse 492227684Sse /* 492327684Sse ** Deduce the value of controller sync period from scntl3. 492427684Sse ** period is in tenths of nano-seconds. 492527684Sse */ 492627684Sse 492727684Sse div = ((scntl3 >> 4) & 0x7); 492827684Sse if ((sxfer & 0x1f) && div) 492939247Sgibbs period_10ns = 493039247Sgibbs (((sxfer>>5)+4)*div_10M[div-1])/np->clock_khz; 493127684Sse else 493239247Sgibbs period_10ns = 0; 493327684Sse 493439247Sgibbs tp->tinfo.goal.period = period; 493539247Sgibbs tp->tinfo.goal.offset = sxfer & 0x1f; 493639247Sgibbs tp->tinfo.current.period = period; 493739247Sgibbs tp->tinfo.current.offset = sxfer & 0x1f; 493839247Sgibbs 493927684Sse /* 494027684Sse ** Stop there if sync parameters are unchanged 494127684Sse */ 494239247Sgibbs if (tp->tinfo.sval == sxfer && tp->tinfo.wval == scntl3) return; 494339247Sgibbs tp->tinfo.sval = sxfer; 494439247Sgibbs tp->tinfo.wval = scntl3; 494527684Sse 494620435Sse if (sxfer & 0x1f) { 49472432Sse /* 49482432Sse ** Disable extended Sreq/Sack filtering 49492432Sse */ 495039247Sgibbs if (period_10ns <= 2000) OUTOFFB (nc_stest2, EXT); 495139247Sgibbs } 49522432Sse 49532432Sse /* 495439247Sgibbs ** Tell the SCSI layer about the 495539247Sgibbs ** new transfer parameters. 495639247Sgibbs */ 4957163816Smjacob memset(&neg, 0, sizeof (neg)); 4958163816Smjacob neg.protocol = PROTO_SCSI; 4959163816Smjacob neg.protocol_version = SCSI_REV_2; 4960163816Smjacob neg.transport = XPORT_SPI; 4961163816Smjacob neg.transport_version = 2; 4962163816Smjacob neg.xport_specific.spi.sync_period = period; 4963163816Smjacob neg.xport_specific.spi.sync_offset = sxfer & 0x1f; 4964163816Smjacob neg.xport_specific.spi.valid = CTS_SPI_VALID_SYNC_RATE 4965163816Smjacob | CTS_SPI_VALID_SYNC_OFFSET; 496639247Sgibbs xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path, 496739247Sgibbs /*priority*/1); 496839247Sgibbs xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg); 496939247Sgibbs 497039247Sgibbs /* 49712432Sse ** set actual value and sync_status 49722432Sse */ 49732432Sse OUTB (nc_sxfer, sxfer); 49742814Sse np->sync_st = sxfer; 497527684Sse OUTB (nc_scntl3, scntl3); 497627684Sse np->wide_st = scntl3; 49772432Sse 49782432Sse /* 497939247Sgibbs ** patch ALL nccbs of this target. 49802432Sse */ 498139247Sgibbs for (cp = np->link_nccb; cp; cp = cp->link_nccb) { 498239247Sgibbs if (!cp->ccb) continue; 498339247Sgibbs if (cp->ccb->ccb_h.target_id != target) continue; 49842432Sse cp->sync_status = sxfer; 498527684Sse cp->wide_status = scntl3; 49862432Sse }; 49872432Sse} 49887228Sse 49892432Sse/*========================================================== 49902432Sse** 499135256Sdes** Switch wide mode for current job and its target 499227684Sse** SCSI specs say: a SCSI device that accepts a WDTR 499327684Sse** message shall reset the synchronous agreement to 499427684Sse** asynchronous mode. 49952814Sse** 49962814Sse**========================================================== 49972814Sse*/ 49982814Sse 499939247Sgibbsstatic void ncr_setwide (ncb_p np, nccb_p cp, u_char wide, u_char ack) 50002814Sse{ 500139247Sgibbs union ccb *ccb; 500239247Sgibbs struct ccb_trans_settings neg; 500346843Sse u_int target = INB (nc_sdid) & 0x0f; 500439247Sgibbs tcb_p tp; 500527684Sse u_char scntl3; 500627684Sse u_char sxfer; 50072814Sse 50082814Sse assert (cp); 50092814Sse if (!cp) return; 50102814Sse 501139247Sgibbs ccb = cp->ccb; 501239247Sgibbs assert (ccb); 501339247Sgibbs if (!ccb) return; 501439247Sgibbs assert (target == ccb->ccb_h.target_id); 50152814Sse 50162814Sse tp = &np->target[target]; 501739247Sgibbs tp->tinfo.current.width = wide; 501839247Sgibbs tp->tinfo.goal.width = wide; 501939247Sgibbs tp->tinfo.current.period = 0; 502039247Sgibbs tp->tinfo.current.offset = 0; 502127684Sse 502239247Sgibbs scntl3 = (tp->tinfo.wval & (~EWS)) | (wide ? EWS : 0); 502327684Sse 502439247Sgibbs sxfer = ack ? 0 : tp->tinfo.sval; 502539247Sgibbs 502627684Sse /* 502727684Sse ** Stop there if sync/wide parameters are unchanged 502827684Sse */ 502939247Sgibbs if (tp->tinfo.sval == sxfer && tp->tinfo.wval == scntl3) return; 503039247Sgibbs tp->tinfo.sval = sxfer; 503139247Sgibbs tp->tinfo.wval = scntl3; 50322814Sse 503339247Sgibbs /* Tell the SCSI layer about the new transfer params */ 5034163816Smjacob memset(&neg, 0, sizeof (neg)); 5035163816Smjacob neg.protocol = PROTO_SCSI; 5036163816Smjacob neg.protocol_version = SCSI_REV_2; 5037163816Smjacob neg.transport = XPORT_SPI; 5038163816Smjacob neg.transport_version = 2; 5039163816Smjacob neg.xport_specific.spi.bus_width = (scntl3 & EWS) ? 5040163816Smjacob MSG_EXT_WDTR_BUS_16_BIT : MSG_EXT_WDTR_BUS_8_BIT; 5041163816Smjacob neg.xport_specific.spi.sync_period = 0; 5042163816Smjacob neg.xport_specific.spi.sync_offset = 0; 5043163816Smjacob neg.xport_specific.spi.valid = CTS_SPI_VALID_SYNC_RATE 5044163816Smjacob | CTS_SPI_VALID_SYNC_OFFSET 5045163816Smjacob | CTS_SPI_VALID_BUS_WIDTH; 5046163816Smjacob xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path, /*priority*/1); 504739247Sgibbs xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg); 50482814Sse 50492814Sse /* 50502814Sse ** set actual value and sync_status 50512814Sse */ 505227684Sse OUTB (nc_sxfer, sxfer); 505327684Sse np->sync_st = sxfer; 50542814Sse OUTB (nc_scntl3, scntl3); 50552814Sse np->wide_st = scntl3; 50562814Sse 50572814Sse /* 505839247Sgibbs ** patch ALL nccbs of this target. 50592814Sse */ 506039247Sgibbs for (cp = np->link_nccb; cp; cp = cp->link_nccb) { 506139247Sgibbs if (!cp->ccb) continue; 506239247Sgibbs if (cp->ccb->ccb_h.target_id != target) continue; 506327684Sse cp->sync_status = sxfer; 50642814Sse cp->wide_status = scntl3; 50652814Sse }; 50662814Sse} 50677228Sse 50682814Sse/*========================================================== 50692814Sse** 50702432Sse** 50712432Sse** ncr timeout handler. 50722432Sse** 50732432Sse** 50742432Sse**========================================================== 50752432Sse** 50762432Sse** Misused to keep the driver running when 50776705Sse** interrupts are not configured correctly. 50782432Sse** 50792432Sse**---------------------------------------------------------- 50802432Sse*/ 50812432Sse 508239247Sgibbsstatic void 508339247Sgibbsncr_timeout (void *arg) 50842432Sse{ 508525048Sbde ncb_p np = arg; 508639554Sgibbs time_t thistime = time_second; 508739554Sgibbs ticks_t step = np->ticks; 50882432Sse u_long count = 0; 50892432Sse long signed t; 509039247Sgibbs nccb_p cp; 50912432Sse 50922432Sse if (np->lasttime != thistime) { 50936132Sdg /* 50946705Sse ** block ncr interrupts 50956132Sdg */ 509639247Sgibbs int oldspl = splcam(); 50972432Sse np->lasttime = thistime; 50982432Sse 50992432Sse /*---------------------------------------------------- 51002432Sse ** 51012432Sse ** handle ncr chip timeouts 51022432Sse ** 51032432Sse ** Assumption: 51042432Sse ** We have a chance to arbitrate for the 51052432Sse ** SCSI bus at least every 10 seconds. 51062432Sse ** 51072432Sse **---------------------------------------------------- 51082432Sse */ 51092432Sse 51102432Sse t = thistime - np->heartbeat; 51112432Sse 51122432Sse if (t<2) np->latetime=0; else np->latetime++; 51132432Sse 51142432Sse if (np->latetime>2) { 51152432Sse /* 51162432Sse ** If there are no requests, the script 51172432Sse ** processor will sleep on SEL_WAIT_RESEL. 51182432Sse ** But we have to check whether it died. 511920435Sse ** Let's try to wake it up. 51202432Sse */ 51212432Sse OUTB (nc_istat, SIGP); 51222432Sse }; 51232432Sse 51242432Sse /*---------------------------------------------------- 51252432Sse ** 512639247Sgibbs ** handle nccb timeouts 51272432Sse ** 51282432Sse **---------------------------------------------------- 51292432Sse */ 51302432Sse 513139247Sgibbs for (cp=np->link_nccb; cp; cp=cp->link_nccb) { 51322432Sse /* 513339247Sgibbs ** look for timed out nccbs. 51342432Sse */ 51352432Sse if (!cp->host_status) continue; 51362432Sse count++; 51372432Sse if (cp->tlimit > thistime) continue; 51382432Sse 51392432Sse /* 51402432Sse ** Disable reselect. 51412432Sse ** Remove it from startqueue. 51422432Sse */ 514339247Sgibbs cp->jump_nccb.l_cmd = (SCR_JUMP); 51442432Sse if (cp->phys.header.launch.l_paddr == 514510677Sse NCB_SCRIPT_PHYS (np, select)) { 514639532Sken printf ("%s: timeout nccb=%p (skip)\n", 514739532Sken ncr_name (np), cp); 51482432Sse cp->phys.header.launch.l_paddr 514910677Sse = NCB_SCRIPT_PHYS (np, skip); 51502432Sse }; 51512432Sse 51522432Sse switch (cp->host_status) { 51532432Sse 51542432Sse case HS_BUSY: 51552432Sse case HS_NEGOTIATE: 5156102412Scharnier /* FALLTHROUGH */ 51572432Sse case HS_DISCONNECT: 51582432Sse cp->host_status=HS_TIMEOUT; 51592432Sse }; 51602432Sse cp->tag = 0; 51612432Sse 51622432Sse /* 516339247Sgibbs ** wakeup this nccb. 51642432Sse */ 51656132Sdg ncr_complete (np, cp); 51662432Sse }; 51676132Sdg splx (oldspl); 51682432Sse } 51697228Sse 517039247Sgibbs np->timeout_ch = 517139247Sgibbs timeout (ncr_timeout, (caddr_t) np, step ? step : 1); 51722432Sse 51736302Sse if (INB(nc_istat) & (INTF|SIP|DIP)) { 51742432Sse 51752432Sse /* 51766705Sse ** Process pending interrupts. 51772432Sse */ 51782432Sse 517939247Sgibbs int oldspl = splcam(); 51803552Sse if (DEBUG_FLAGS & DEBUG_TINY) printf ("{"); 51812432Sse ncr_exception (np); 51823552Sse if (DEBUG_FLAGS & DEBUG_TINY) printf ("}"); 51832432Sse splx (oldspl); 51842432Sse }; 51852432Sse} 51867228Sse 51872432Sse/*========================================================== 51882432Sse** 518927744Sse** log message for real hard errors 51902432Sse** 519127744Sse** "ncr0 targ 0?: ERROR (ds:si) (so-si-sd) (sxfer/scntl3) @ name (dsp:dbc)." 519227744Sse** " reg: r0 r1 r2 r3 r4 r5 r6 ..... rf." 519327744Sse** 519427744Sse** exception register: 519527744Sse** ds: dstat 519627744Sse** si: sist 519727744Sse** 519827744Sse** SCSI bus lines: 519927744Sse** so: control lines as driver by NCR. 520027744Sse** si: control lines as seen by NCR. 520127744Sse** sd: scsi data lines as seen by NCR. 520227744Sse** 520327744Sse** wide/fastmode: 520427744Sse** sxfer: (see the manual) 520527744Sse** scntl3: (see the manual) 520627744Sse** 520727744Sse** current script command: 520880203Skris** dsp: script address (relative to start of script). 520927744Sse** dbc: first word of script command. 521027744Sse** 521127744Sse** First 16 register of the chip: 521227744Sse** r0..rf 521327744Sse** 521427744Sse**========================================================== 521527744Sse*/ 521627744Sse 521727744Ssestatic void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat) 521827744Sse{ 521928960Sse u_int32_t dsp; 522027744Sse int script_ofs; 522127744Sse int script_size; 522227744Sse char *script_name; 522327744Sse u_char *script_base; 522427744Sse int i; 522527744Sse 522627744Sse dsp = INL (nc_dsp); 522727744Sse 522828636Sse if (np->p_script < dsp && 522928636Sse dsp <= np->p_script + sizeof(struct script)) { 523027744Sse script_ofs = dsp - np->p_script; 523127744Sse script_size = sizeof(struct script); 523227744Sse script_base = (u_char *) np->script; 523327744Sse script_name = "script"; 523427744Sse } 523528636Sse else if (np->p_scripth < dsp && 523628636Sse dsp <= np->p_scripth + sizeof(struct scripth)) { 523727744Sse script_ofs = dsp - np->p_scripth; 523827744Sse script_size = sizeof(struct scripth); 523927744Sse script_base = (u_char *) np->scripth; 524027744Sse script_name = "scripth"; 524128636Sse } else { 524228636Sse script_ofs = dsp; 524328636Sse script_size = 0; 524428636Sse script_base = 0; 524528636Sse script_name = "mem"; 524627744Sse } 524727744Sse 524828636Sse printf ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n", 524946843Sse ncr_name (np), (unsigned)INB (nc_sdid)&0x0f, dstat, sist, 525027744Sse (unsigned)INB (nc_socl), (unsigned)INB (nc_sbcl), (unsigned)INB (nc_sbdl), 525127744Sse (unsigned)INB (nc_sxfer),(unsigned)INB (nc_scntl3), script_name, script_ofs, 525227744Sse (unsigned)INL (nc_dbc)); 525327744Sse 525427744Sse if (((script_ofs & 3) == 0) && 525527744Sse (unsigned)script_ofs < script_size) { 525627744Sse printf ("%s: script cmd = %08x\n", ncr_name(np), 525739532Sken (int)READSCRIPT_OFF(script_base, script_ofs)); 525827744Sse } 525927744Sse 526027744Sse printf ("%s: regdump:", ncr_name(np)); 526127744Sse for (i=0; i<16;i++) 526227744Sse printf (" %02x", (unsigned)INB_OFF(i)); 526327744Sse printf (".\n"); 526427744Sse} 526527744Sse 526627744Sse/*========================================================== 526727744Sse** 526827744Sse** 52692432Sse** ncr chip exception handler. 52702432Sse** 52712432Sse** 52722432Sse**========================================================== 52732432Sse*/ 52742432Sse 5275105219Sphkstatic void ncr_exception (ncb_p np) 52762432Sse{ 527710072Sse u_char istat, dstat; 527810072Sse u_short sist; 52792432Sse 52802432Sse /* 52816705Sse ** interrupt on the fly ? 52822432Sse */ 52832432Sse while ((istat = INB (nc_istat)) & INTF) { 528418875Sse if (DEBUG_FLAGS & DEBUG_TINY) printf ("F "); 528513448Sse OUTB (nc_istat, INTF); 52862432Sse np->profile.num_fly++; 52872432Sse ncr_wakeup (np, 0); 52882432Sse }; 528918875Sse if (!(istat & (SIP|DIP))) { 529018875Sse return; 529118875Sse } 52922432Sse 52932432Sse /* 52942432Sse ** Steinbach's Guideline for Systems Programming: 52952432Sse ** Never test for an error condition you don't know how to handle. 52962432Sse */ 52972432Sse 529820435Sse sist = (istat & SIP) ? INW (nc_sist) : 0; 529919548Sse dstat = (istat & DIP) ? INB (nc_dstat) : 0; 53002432Sse np->profile.num_int++; 53012432Sse 53023552Sse if (DEBUG_FLAGS & DEBUG_TINY) 53032432Sse printf ("<%d|%x:%x|%x:%x>", 53042432Sse INB(nc_scr0), 53052432Sse dstat,sist, 53063533Sse (unsigned)INL(nc_dsp), 53073533Sse (unsigned)INL(nc_dbc)); 53082432Sse if ((dstat==DFE) && (sist==PAR)) return; 53097228Sse 53102432Sse/*========================================================== 53112432Sse** 53122432Sse** First the normal cases. 53132432Sse** 53142432Sse**========================================================== 53152432Sse*/ 53162432Sse /*------------------------------------------- 53172432Sse ** SCSI reset 53182432Sse **------------------------------------------- 53192432Sse */ 53202432Sse 53212432Sse if (sist & RST) { 532210605Sse ncr_init (np, bootverbose ? "scsi reset" : NULL, HS_RESET); 53232432Sse return; 53242432Sse }; 53252432Sse 53262432Sse /*------------------------------------------- 53272432Sse ** selection timeout 53282432Sse ** 53292432Sse ** IID excluded from dstat mask! 53302432Sse ** (chip bug) 53312432Sse **------------------------------------------- 53322432Sse */ 53332432Sse 53342432Sse if ((sist & STO) && 53352432Sse !(sist & (GEN|HTH|MA|SGE|UDC|RST|PAR)) && 53362432Sse !(dstat & (MDPE|BF|ABRT|SIR))) { 53372432Sse ncr_int_sto (np); 53382432Sse return; 53392432Sse }; 53402432Sse 53412432Sse /*------------------------------------------- 53422432Sse ** Phase mismatch. 53432432Sse **------------------------------------------- 53442432Sse */ 53452432Sse 53462432Sse if ((sist & MA) && 53472432Sse !(sist & (STO|GEN|HTH|SGE|UDC|RST|PAR)) && 53482432Sse !(dstat & (MDPE|BF|ABRT|SIR|IID))) { 534927512Sse ncr_int_ma (np, dstat); 53502432Sse return; 53512432Sse }; 53527228Sse 53532814Sse /*---------------------------------------- 53542814Sse ** move command with length 0 53552814Sse **---------------------------------------- 53562814Sse */ 53572432Sse 53582814Sse if ((dstat & IID) && 53592814Sse !(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) && 53602814Sse !(dstat & (MDPE|BF|ABRT|SIR)) && 53612814Sse ((INL(nc_dbc) & 0xf8000000) == SCR_MOVE_TBL)) { 53622814Sse /* 53632814Sse ** Target wants more data than available. 53642814Sse ** The "no_data" script will do it. 53652814Sse */ 536610677Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, no_data)); 53672814Sse return; 53682814Sse }; 53692814Sse 53702432Sse /*------------------------------------------- 53716705Sse ** Programmed interrupt 53722432Sse **------------------------------------------- 53732432Sse */ 53742432Sse 53752432Sse if ((dstat & SIR) && 53762432Sse !(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) && 53772432Sse !(dstat & (MDPE|BF|ABRT|IID)) && 53782814Sse (INB(nc_dsps) <= SIR_MAX)) { 53792432Sse ncr_int_sir (np); 53802432Sse return; 53812432Sse }; 53822814Sse 53832432Sse /*======================================== 538427744Sse ** log message for real hard errors 538527744Sse **======================================== 538627744Sse */ 538727744Sse 538827744Sse ncr_log_hard_error(np, sist, dstat); 538927744Sse 539027744Sse /*======================================== 53912432Sse ** do the register dump 53922432Sse **======================================== 53932432Sse */ 53942432Sse 539539554Sgibbs if (time_second - np->regtime > 10) { 53962432Sse int i; 539739554Sgibbs np->regtime = time_second; 53982432Sse for (i=0; i<sizeof(np->regdump); i++) 539943309Sdillon ((volatile char*)&np->regdump)[i] = INB_OFF(i); 54002432Sse np->regdump.nc_dstat = dstat; 54012432Sse np->regdump.nc_sist = sist; 54022432Sse }; 54037228Sse 54042432Sse 54052432Sse /*---------------------------------------- 54062432Sse ** clean up the dma fifo 54072432Sse **---------------------------------------- 54082432Sse */ 54092432Sse 54102814Sse if ( (INB(nc_sstat0) & (ILF|ORF|OLF) ) || 54117228Sse (INB(nc_sstat1) & (FF3210) ) || 54122814Sse (INB(nc_sstat2) & (ILF1|ORF1|OLF1)) || /* wide .. */ 54132814Sse !(dstat & DFE)) { 54142432Sse printf ("%s: have to clear fifos.\n", ncr_name (np)); 54152432Sse OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */ 541620435Sse OUTB (nc_ctest3, np->rv_ctest3 | CLF); 541720435Sse /* clear dma fifo */ 54182432Sse } 54192432Sse 54202432Sse /*---------------------------------------- 542110605Sse ** handshake timeout 542210605Sse **---------------------------------------- 542310605Sse */ 542410605Sse 542510605Sse if (sist & HTH) { 542610605Sse printf ("%s: handshake timeout\n", ncr_name(np)); 542710605Sse OUTB (nc_scntl1, CRST); 542810605Sse DELAY (1000); 542910605Sse OUTB (nc_scntl1, 0x00); 543010605Sse OUTB (nc_scr0, HS_FAIL); 543110677Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, cleanup)); 543210605Sse return; 543310605Sse } 543410605Sse 543510605Sse /*---------------------------------------- 54362432Sse ** unexpected disconnect 54372432Sse **---------------------------------------- 54382432Sse */ 54392432Sse 54402432Sse if ((sist & UDC) && 54412432Sse !(sist & (STO|GEN|HTH|MA|SGE|RST|PAR)) && 54422432Sse !(dstat & (MDPE|BF|ABRT|SIR|IID))) { 54432432Sse OUTB (nc_scr0, HS_UNEXPECTED); 544410677Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, cleanup)); 54452432Sse return; 54462432Sse }; 54472814Sse 54482432Sse /*---------------------------------------- 54492432Sse ** cannot disconnect 54502432Sse **---------------------------------------- 54512432Sse */ 54522432Sse 54532432Sse if ((dstat & IID) && 54542432Sse !(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) && 54552432Sse !(dstat & (MDPE|BF|ABRT|SIR)) && 54562814Sse ((INL(nc_dbc) & 0xf8000000) == SCR_WAIT_DISC)) { 54572432Sse /* 54586132Sdg ** Unexpected data cycle while waiting for disconnect. 54592432Sse */ 54606132Sdg if (INB(nc_sstat2) & LDSC) { 54616132Sdg /* 54626132Sdg ** It's an early reconnect. 54636132Sdg ** Let's continue ... 54646132Sdg */ 546520435Sse OUTB (nc_dcntl, np->rv_dcntl | STD); 54666132Sdg /* 54676132Sdg ** info message 54686132Sdg */ 54697228Sse printf ("%s: INFO: LDSC while IID.\n", 54706132Sdg ncr_name (np)); 54716132Sdg return; 54726132Sdg }; 547310605Sse printf ("%s: target %d doesn't release the bus.\n", 547446843Sse ncr_name (np), INB (nc_sdid)&0x0f); 54752432Sse /* 54766132Sdg ** return without restarting the NCR. 54776132Sdg ** timeout will do the real work. 54782432Sse */ 54792432Sse return; 54802432Sse }; 54812432Sse 54822432Sse /*---------------------------------------- 54832432Sse ** single step 54842432Sse **---------------------------------------- 54852432Sse */ 54862432Sse 54872432Sse if ((dstat & SSI) && 54882432Sse !(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) && 54892432Sse !(dstat & (MDPE|BF|ABRT|SIR|IID))) { 549020435Sse OUTB (nc_dcntl, np->rv_dcntl | STD); 54912432Sse return; 54922432Sse }; 54937228Sse 54942432Sse/* 54952432Sse** @RECOVER@ HTH, SGE, ABRT. 54962432Sse** 54976705Sse** We should try to recover from these interrupts. 549810567Sse** They may occur if there are problems with synch transfers, or 549910567Sse** if targets are switched on or off while the driver is running. 55002432Sse*/ 55012432Sse 55022432Sse if (sist & SGE) { 550320435Sse /* clear scsi offsets */ 550420435Sse OUTB (nc_ctest3, np->rv_ctest3 | CLF); 55052432Sse } 55062432Sse 55072432Sse /* 55082432Sse ** Freeze controller to be able to read the messages. 55092432Sse */ 55102432Sse 55113552Sse if (DEBUG_FLAGS & DEBUG_FREEZE) { 55122432Sse int i; 55132432Sse unsigned char val; 55142432Sse for (i=0; i<0x60; i++) { 55152432Sse switch (i%16) { 55162432Sse 55172432Sse case 0: 55182432Sse printf ("%s: reg[%d0]: ", 55192432Sse ncr_name(np),i/16); 55202432Sse break; 55212432Sse case 4: 55222432Sse case 8: 55232432Sse case 12: 55242432Sse printf (" "); 55252432Sse break; 55262432Sse }; 552760974Sdfr val = bus_space_read_1(np->bst, np->bsh, i); 55282432Sse printf (" %x%x", val/16, val%16); 55292432Sse if (i%16==15) printf (".\n"); 55302432Sse }; 55312432Sse 553229681Sgibbs untimeout (ncr_timeout, (caddr_t) np, np->timeout_ch); 55332432Sse 55342432Sse printf ("%s: halted!\n", ncr_name(np)); 55352432Sse /* 55362432Sse ** don't restart controller ... 55372432Sse */ 55382432Sse OUTB (nc_istat, SRST); 55392432Sse return; 55402432Sse }; 55412432Sse 55426705Sse#ifdef NCR_FREEZE 55432432Sse /* 55446705Sse ** Freeze system to be able to read the messages. 55456705Sse */ 55466705Sse printf ("ncr: fatal error: system halted - press reset to reboot ..."); 55476705Sse for (;;); 55486705Sse#endif 55496705Sse 55506705Sse /* 55512432Sse ** sorry, have to kill ALL jobs ... 55522432Sse */ 55532432Sse 55542432Sse ncr_init (np, "fatal error", HS_FAIL); 55552432Sse} 55567228Sse 55572432Sse/*========================================================== 55582432Sse** 55592432Sse** ncr chip exception handler for selection timeout 55602432Sse** 55612432Sse**========================================================== 55622432Sse** 55632432Sse** There seems to be a bug in the 53c810. 55646705Sse** Although a STO-Interrupt is pending, 55652432Sse** it continues executing script commands. 55666705Sse** But it will fail and interrupt (IID) on 55672432Sse** the next instruction where it's looking 55682432Sse** for a valid phase. 55692432Sse** 55702432Sse**---------------------------------------------------------- 55712432Sse*/ 55722432Sse 5573105219Sphkstatic void ncr_int_sto (ncb_p np) 55742432Sse{ 55752432Sse u_long dsa, scratcha, diff; 557639247Sgibbs nccb_p cp; 55773552Sse if (DEBUG_FLAGS & DEBUG_TINY) printf ("T"); 55782432Sse 55792432Sse /* 558039247Sgibbs ** look for nccb and set the status. 55812432Sse */ 55822432Sse 55832432Sse dsa = INL (nc_dsa); 558439247Sgibbs cp = np->link_nccb; 558510677Sse while (cp && (CCB_PHYS (cp, phys) != dsa)) 558639247Sgibbs cp = cp->link_nccb; 55872432Sse 55882432Sse if (cp) { 55892432Sse cp-> host_status = HS_SEL_TIMEOUT; 55902432Sse ncr_complete (np, cp); 55912432Sse }; 55922432Sse 55932432Sse /* 55942432Sse ** repair start queue 55952432Sse */ 55962432Sse 55972432Sse scratcha = INL (nc_scratcha); 559827744Sse diff = scratcha - NCB_SCRIPTH_PHYS (np, tryloop); 55992432Sse 56009364Sse/* assert ((diff <= MAX_START * 20) && !(diff % 20));*/ 56012432Sse 56022432Sse if ((diff <= MAX_START * 20) && !(diff % 20)) { 560339532Sken WRITESCRIPT(startpos[0], scratcha); 560410677Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start)); 56052432Sse return; 56062432Sse }; 56072432Sse ncr_init (np, "selection timeout", HS_FAIL); 56082432Sse} 56097228Sse 56102432Sse/*========================================================== 56112432Sse** 56122432Sse** 56132432Sse** ncr chip exception handler for phase errors. 56142432Sse** 56152432Sse** 56162432Sse**========================================================== 56172432Sse** 56182432Sse** We have to construct a new transfer descriptor, 56192432Sse** to transfer the rest of the current block. 56202432Sse** 56212432Sse**---------------------------------------------------------- 56222432Sse*/ 56232432Sse 562427512Ssestatic void ncr_int_ma (ncb_p np, u_char dstat) 56252432Sse{ 562628960Sse u_int32_t dbc; 562728960Sse u_int32_t rest; 562828960Sse u_int32_t dsa; 562928960Sse u_int32_t dsp; 563028960Sse u_int32_t nxtdsp; 563139532Sken volatile void *vdsp_base; 563239532Sken size_t vdsp_off; 563328960Sse u_int32_t oadr, olen; 563428960Sse u_int32_t *tblp, *newcmd; 563527684Sse u_char cmd, sbcl, ss0, ss2, ctest5; 563627684Sse u_short delta; 563739247Sgibbs nccb_p cp; 56382432Sse 56392432Sse dsp = INL (nc_dsp); 56402432Sse dsa = INL (nc_dsa); 56412432Sse dbc = INL (nc_dbc); 56422432Sse ss0 = INB (nc_sstat0); 56432814Sse ss2 = INB (nc_sstat2); 56442432Sse sbcl= INB (nc_sbcl); 56452432Sse 56462432Sse cmd = dbc >> 24; 56472432Sse rest= dbc & 0xffffff; 56482432Sse 564927684Sse ctest5 = (np->rv_ctest5 & DFS) ? INB (nc_ctest5) : 0; 565027684Sse if (ctest5 & DFS) 565127684Sse delta=(((ctest5<<8) | (INB (nc_dfifo) & 0xff)) - rest) & 0x3ff; 565227684Sse else 565327684Sse delta=(INB (nc_dfifo) - rest) & 0x7f; 565427684Sse 565527684Sse 56562432Sse /* 56572432Sse ** The data in the dma fifo has not been transfered to 56582432Sse ** the target -> add the amount to the rest 56592432Sse ** and clear the data. 56602814Sse ** Check the sstat2 register in case of wide transfer. 56612432Sse */ 56622432Sse 566327512Sse if (!(dstat & DFE)) rest += delta; 56642432Sse if (ss0 & OLF) rest++; 56652432Sse if (ss0 & ORF) rest++; 56662814Sse if (INB(nc_scntl3) & EWS) { 56672814Sse if (ss2 & OLF1) rest++; 56682814Sse if (ss2 & ORF1) rest++; 56692814Sse }; 567020435Sse OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */ 567120435Sse OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */ 56727228Sse 56732432Sse /* 56749364Sse ** locate matching cp 56752432Sse */ 567639247Sgibbs cp = np->link_nccb; 567710677Sse while (cp && (CCB_PHYS (cp, phys) != dsa)) 567839247Sgibbs cp = cp->link_nccb; 56792432Sse 56809364Sse if (!cp) { 568139554Sgibbs printf ("%s: SCSI phase error fixup: CCB already dequeued (%p)\n", 568239554Sgibbs ncr_name (np), (void *) np->header.cp); 56839364Sse return; 56849364Sse } 56859364Sse if (cp != np->header.cp) { 568639310Sgibbs printf ("%s: SCSI phase error fixup: CCB address mismatch " 568739390Sgibbs "(%p != %p) np->nccb = %p\n", 568839390Sgibbs ncr_name (np), (void *)cp, (void *)np->header.cp, 568939390Sgibbs (void *)np->link_nccb); 569013809Sse/* return;*/ 56919364Sse } 56922432Sse 56932432Sse /* 56946705Sse ** find the interrupted script command, 56959364Sse ** and the address at which to continue. 56962432Sse */ 56972432Sse 56982432Sse if (dsp == vtophys (&cp->patch[2])) { 569939532Sken vdsp_base = cp; 570039532Sken vdsp_off = offsetof(struct nccb, patch[0]); 570139532Sken nxtdsp = READSCRIPT_OFF(vdsp_base, vdsp_off + 3*4); 57022432Sse } else if (dsp == vtophys (&cp->patch[6])) { 570339532Sken vdsp_base = cp; 570439532Sken vdsp_off = offsetof(struct nccb, patch[4]); 570539532Sken nxtdsp = READSCRIPT_OFF(vdsp_base, vdsp_off + 3*4); 570627744Sse } else if (dsp > np->p_script && 570727744Sse dsp <= np->p_script + sizeof(struct script)) { 570839532Sken vdsp_base = np->script; 570939532Sken vdsp_off = dsp - np->p_script - 8; 571027744Sse nxtdsp = dsp; 57112432Sse } else { 571239532Sken vdsp_base = np->scripth; 571339532Sken vdsp_off = dsp - np->p_scripth - 8; 57142432Sse nxtdsp = dsp; 57152432Sse }; 57162432Sse 57172432Sse /* 57182432Sse ** log the information 57192432Sse */ 57203552Sse if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE)) { 572110605Sse printf ("P%x%x ",cmd&7, sbcl&7); 57223533Sse printf ("RL=%d D=%d SS0=%x ", 57233533Sse (unsigned) rest, (unsigned) delta, ss0); 57242432Sse }; 57253552Sse if (DEBUG_FLAGS & DEBUG_PHASE) { 572639532Sken printf ("\nCP=%p CP2=%p DSP=%x NXT=%x VDSP=%p CMD=%x ", 572739532Sken cp, np->header.cp, 572839532Sken dsp, 572960974Sdfr nxtdsp, (volatile char*)vdsp_base+vdsp_off, cmd); 57302432Sse }; 57312432Sse 57322432Sse /* 57332432Sse ** get old startaddress and old length. 57342432Sse */ 57352432Sse 573639532Sken oadr = READSCRIPT_OFF(vdsp_base, vdsp_off + 1*4); 57372432Sse 57382432Sse if (cmd & 0x10) { /* Table indirect */ 573928960Sse tblp = (u_int32_t *) ((char*) &cp->phys + oadr); 57402432Sse olen = tblp[0]; 57412432Sse oadr = tblp[1]; 57422432Sse } else { 574328960Sse tblp = (u_int32_t *) 0; 574439532Sken olen = READSCRIPT_OFF(vdsp_base, vdsp_off) & 0xffffff; 57452432Sse }; 57467228Sse 57473552Sse if (DEBUG_FLAGS & DEBUG_PHASE) { 574839757Sbde printf ("OCMD=%x\nTBLP=%p OLEN=%lx OADR=%lx\n", 574939532Sken (unsigned) (READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24), 575039757Sbde (void *) tblp, 575139757Sbde (u_long) olen, 575239757Sbde (u_long) oadr); 57532432Sse }; 57542432Sse 57552432Sse /* 57562432Sse ** if old phase not dataphase, leave here. 57572432Sse */ 57582432Sse 575939532Sken if (cmd != (READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24)) { 576039247Sgibbs PRINT_ADDR(cp->ccb); 576110567Sse printf ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n", 576239532Sken (unsigned)cmd, 576339532Sken (unsigned)READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24); 576410567Sse 576510567Sse return; 576610567Sse } 57672432Sse if (cmd & 0x06) { 576839247Sgibbs PRINT_ADDR(cp->ccb); 576910605Sse printf ("phase change %x-%x %d@%08x resid=%d.\n", 57703533Sse cmd&7, sbcl&7, (unsigned)olen, 57713533Sse (unsigned)oadr, (unsigned)rest); 57722432Sse 577320435Sse OUTB (nc_dcntl, np->rv_dcntl | STD); 57742432Sse return; 57752432Sse }; 57762432Sse 57772432Sse /* 57782432Sse ** choose the correct patch area. 57792432Sse ** if savep points to one, choose the other. 57802432Sse */ 57812432Sse 57822432Sse newcmd = cp->patch; 57832432Sse if (cp->phys.header.savep == vtophys (newcmd)) newcmd+=4; 57842432Sse 57852432Sse /* 57862432Sse ** fillin the commands 57872432Sse */ 57882432Sse 57892432Sse newcmd[0] = ((cmd & 0x0f) << 24) | rest; 57902432Sse newcmd[1] = oadr + olen - rest; 57912432Sse newcmd[2] = SCR_JUMP; 57922432Sse newcmd[3] = nxtdsp; 57932432Sse 57943552Sse if (DEBUG_FLAGS & DEBUG_PHASE) { 579539247Sgibbs PRINT_ADDR(cp->ccb); 57962432Sse printf ("newcmd[%d] %x %x %x %x.\n", 579739532Sken (int)(newcmd - cp->patch), 57983533Sse (unsigned)newcmd[0], 57993533Sse (unsigned)newcmd[1], 58003533Sse (unsigned)newcmd[2], 58013533Sse (unsigned)newcmd[3]); 58022432Sse } 58032432Sse /* 58042432Sse ** fake the return address (to the patch). 58052432Sse ** and restart script processor at dispatcher. 58062432Sse */ 58072432Sse np->profile.num_break++; 58082432Sse OUTL (nc_temp, vtophys (newcmd)); 580927512Sse if ((cmd & 7) == 0) 581027512Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch)); 581127512Sse else 581227512Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, checkatn)); 58132432Sse} 58147228Sse 58152432Sse/*========================================================== 58162432Sse** 58172432Sse** 58186705Sse** ncr chip exception handler for programmed interrupts. 58192432Sse** 58202432Sse** 58212432Sse**========================================================== 58222432Sse*/ 58232432Sse 58242814Ssestatic int ncr_show_msg (u_char * msg) 58252432Sse{ 58262432Sse u_char i; 58272432Sse printf ("%x",*msg); 582839247Sgibbs if (*msg==MSG_EXTENDED) { 58292432Sse for (i=1;i<8;i++) { 58302432Sse if (i-1>msg[1]) break; 58312432Sse printf ("-%x",msg[i]); 58322432Sse }; 58332814Sse return (i+1); 58342432Sse } else if ((*msg & 0xf0) == 0x20) { 58352432Sse printf ("-%x",msg[1]); 58362814Sse return (2); 58372814Sse }; 58382814Sse return (1); 58392432Sse} 58402432Sse 5841105219Sphkstatic void ncr_int_sir (ncb_p np) 58422432Sse{ 584327762Sse u_char scntl3; 58442814Sse u_char chg, ofs, per, fak, wide; 58452432Sse u_char num = INB (nc_dsps); 584639247Sgibbs nccb_p cp=0; 58472432Sse u_long dsa; 584846843Sse u_int target = INB (nc_sdid) & 0x0f; 58492814Sse tcb_p tp = &np->target[target]; 58502814Sse int i; 58513552Sse if (DEBUG_FLAGS & DEBUG_TINY) printf ("I#%d", num); 58522432Sse 58532432Sse switch (num) { 58542814Sse case SIR_SENSE_RESTART: 58552814Sse case SIR_STALL_RESTART: 58562814Sse break; 58572814Sse 58582814Sse default: 58592432Sse /* 586039247Sgibbs ** lookup the nccb 58612432Sse */ 58622432Sse dsa = INL (nc_dsa); 586339247Sgibbs cp = np->link_nccb; 586410677Sse while (cp && (CCB_PHYS (cp, phys) != dsa)) 586539247Sgibbs cp = cp->link_nccb; 58662432Sse 58672432Sse assert (cp); 58682432Sse if (!cp) 58692432Sse goto out; 587010639Sse assert (cp == np->header.cp); 587110639Sse if (cp != np->header.cp) 587210639Sse goto out; 58732432Sse } 58742432Sse 58752432Sse switch (num) { 58767228Sse 58772432Sse/*-------------------------------------------------------------------- 58782432Sse** 58796705Sse** Processing of interrupted getcc selects 58802432Sse** 58812432Sse**-------------------------------------------------------------------- 58822432Sse*/ 58832432Sse 58842814Sse case SIR_SENSE_RESTART: 58852814Sse /*------------------------------------------ 58862432Sse ** Script processor is idle. 58876705Sse ** Look for interrupted "check cond" 58882435Sse **------------------------------------------ 58892432Sse */ 58902432Sse 58913552Sse if (DEBUG_FLAGS & DEBUG_RESTART) 58922435Sse printf ("%s: int#%d",ncr_name (np),num); 589339247Sgibbs cp = (nccb_p) 0; 58942432Sse for (i=0; i<MAX_TARGET; i++) { 58953552Sse if (DEBUG_FLAGS & DEBUG_RESTART) printf (" t%d", i); 58962432Sse tp = &np->target[i]; 58973552Sse if (DEBUG_FLAGS & DEBUG_RESTART) printf ("+"); 58982432Sse cp = tp->hold_cp; 58992432Sse if (!cp) continue; 59003552Sse if (DEBUG_FLAGS & DEBUG_RESTART) printf ("+"); 59012432Sse if ((cp->host_status==HS_BUSY) && 590239247Sgibbs (cp->s_status==SCSI_STATUS_CHECK_COND)) 59032432Sse break; 59043552Sse if (DEBUG_FLAGS & DEBUG_RESTART) printf ("- (remove)"); 590539247Sgibbs tp->hold_cp = cp = (nccb_p) 0; 59062432Sse }; 59072432Sse 59082432Sse if (cp) { 59093552Sse if (DEBUG_FLAGS & DEBUG_RESTART) 59102435Sse printf ("+ restart job ..\n"); 591110677Sse OUTL (nc_dsa, CCB_PHYS (cp, phys)); 591227744Sse OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, getcc)); 59132432Sse return; 59142432Sse }; 59157228Sse 59162432Sse /* 59172432Sse ** no job, resume normal processing 59182432Sse */ 59193552Sse if (DEBUG_FLAGS & DEBUG_RESTART) printf (" -- remove trap\n"); 592039532Sken WRITESCRIPT(start0[0], SCR_INT ^ IFFALSE (0)); 59212432Sse break; 59222435Sse 59232814Sse case SIR_SENSE_FAILED: 59242814Sse /*------------------------------------------- 59256632Sse ** While trying to select for 59262432Sse ** getting the condition code, 59272432Sse ** a target reselected us. 59282435Sse **------------------------------------------- 59292432Sse */ 593010072Sse if (DEBUG_FLAGS & DEBUG_RESTART) { 593139247Sgibbs PRINT_ADDR(cp->ccb); 59322435Sse printf ("in getcc reselect by t%d.\n", 593310605Sse INB(nc_ssid) & 0x0f); 593410072Sse } 59352432Sse 59362432Sse /* 59372432Sse ** Mark this job 59382432Sse */ 59392432Sse cp->host_status = HS_BUSY; 594039247Sgibbs cp->s_status = SCSI_STATUS_CHECK_COND; 594139247Sgibbs np->target[cp->ccb->ccb_h.target_id].hold_cp = cp; 59422432Sse 59432432Sse /* 59442432Sse ** And patch code to restart it. 59452432Sse */ 594639532Sken WRITESCRIPT(start0[0], SCR_INT); 59472432Sse break; 59487228Sse 59492814Sse/*----------------------------------------------------------------------------- 59502432Sse** 59512814Sse** Was Sie schon immer ueber transfermode negotiation wissen wollten ... 59522432Sse** 59532814Sse** We try to negotiate sync and wide transfer only after 59549364Sse** a successfull inquire command. We look at byte 7 of the 59552814Sse** inquire data to determine the capabilities if the target. 59562814Sse** 59572814Sse** When we try to negotiate, we append the negotiation message 59589364Sse** to the identify and (maybe) simple tag message. 59592814Sse** The host status field is set to HS_NEGOTIATE to mark this 59602814Sse** situation. 59612814Sse** 59622814Sse** If the target doesn't answer this message immidiately 59636705Sse** (as required by the standard), the SIR_NEGO_FAIL interrupt 59642814Sse** will be raised eventually. 59652814Sse** The handler removes the HS_NEGOTIATE status, and sets the 59662814Sse** negotiated value to the default (async / nowide). 59672814Sse** 59682814Sse** If we receive a matching answer immediately, we check it 59692814Sse** for validity, and set the values. 59702814Sse** 59712814Sse** If we receive a Reject message immediately, we assume the 59729364Sse** negotiation has failed, and fall back to standard values. 59732814Sse** 59742814Sse** If we receive a negotiation message while not in HS_NEGOTIATE 59752814Sse** state, it's a target initiated negotiation. We prepare a 59769364Sse** (hopefully) valid answer, set our parameters, and send back 59779364Sse** this answer to the target. 59782814Sse** 59792814Sse** If the target doesn't fetch the answer (no message out phase), 59809364Sse** we assume the negotiation has failed, and fall back to default 59819364Sse** settings. 59822814Sse** 598339247Sgibbs** When we set the values, we adjust them in all nccbs belonging 59849364Sse** to this target, in the controller's register, and in the "phys" 59859364Sse** field of the controller's struct ncb. 59862814Sse** 598710072Sse** Possible cases: hs sir msg_in value send goto 59882432Sse** We try try to negotiate: 59892814Sse** -> target doesnt't msgin NEG FAIL noop defa. - dispatch 59902814Sse** -> target rejected our msg NEG FAIL reject defa. - dispatch 59912814Sse** -> target answered (ok) NEG SYNC sdtr set - clrack 59922814Sse** -> target answered (!ok) NEG SYNC sdtr defa. REJ--->msg_bad 59932814Sse** -> target answered (ok) NEG WIDE wdtr set - clrack 59942814Sse** -> target answered (!ok) NEG WIDE wdtr defa. REJ--->msg_bad 599510072Sse** -> any other msgin NEG FAIL noop defa. - dispatch 59962432Sse** 59972432Sse** Target tries to negotiate: 599810072Sse** -> incoming message --- SYNC sdtr set SDTR - 599910072Sse** -> incoming message --- WIDE wdtr set WDTR - 60002814Sse** We sent our answer: 60012814Sse** -> target doesn't msgout --- PROTO ? defa. - dispatch 60022432Sse** 60032814Sse**----------------------------------------------------------------------------- 60042432Sse*/ 60057228Sse 60062814Sse case SIR_NEGO_FAILED: 60072814Sse /*------------------------------------------------------- 60082814Sse ** 60092814Sse ** Negotiation failed. 60102814Sse ** Target doesn't send an answer message, 60112814Sse ** or target rejected our message. 60122814Sse ** 60132814Sse ** Remove negotiation request. 60142814Sse ** 60152814Sse **------------------------------------------------------- 60162814Sse */ 60172814Sse OUTB (HS_PRT, HS_BUSY); 60182814Sse 6019102412Scharnier /* FALLTHROUGH */ 60202814Sse 60212814Sse case SIR_NEGO_PROTO: 60222814Sse /*------------------------------------------------------- 60232814Sse ** 60242814Sse ** Negotiation failed. 60252814Sse ** Target doesn't fetch the answer message. 60262814Sse ** 60272814Sse **------------------------------------------------------- 60282814Sse */ 60293552Sse 60303552Sse if (DEBUG_FLAGS & DEBUG_NEGO) { 603139247Sgibbs PRINT_ADDR(cp->ccb); 60322814Sse printf ("negotiation failed sir=%x status=%x.\n", 60332814Sse num, cp->nego_status); 60342814Sse }; 60353552Sse 60362432Sse /* 60372814Sse ** any error in negotiation: 60382814Sse ** fall back to default mode. 60392432Sse */ 60402814Sse switch (cp->nego_status) { 60412432Sse 60422814Sse case NS_SYNC: 604339247Sgibbs ncr_setsync (np, cp, 0, 0xe0, 0); 60442814Sse break; 60452814Sse 60462814Sse case NS_WIDE: 604727684Sse ncr_setwide (np, cp, 0, 0); 60482814Sse break; 60492814Sse 60502814Sse }; 605139247Sgibbs np->msgin [0] = MSG_NOOP; 605239247Sgibbs np->msgout[0] = MSG_NOOP; 60532814Sse cp->nego_status = 0; 605410677Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch)); 60552814Sse break; 60567228Sse 60572814Sse case SIR_NEGO_SYNC: 60582814Sse /* 60592814Sse ** Synchronous request message received. 60602814Sse */ 60613552Sse 60623552Sse if (DEBUG_FLAGS & DEBUG_NEGO) { 606339247Sgibbs PRINT_ADDR(cp->ccb); 60642432Sse printf ("sync msgin: "); 60652814Sse (void) ncr_show_msg (np->msgin); 60662432Sse printf (".\n"); 60672432Sse }; 60682432Sse 60692432Sse /* 60702814Sse ** get requested values. 60712432Sse */ 60722432Sse 60732814Sse chg = 0; 60742432Sse per = np->msgin[3]; 60752432Sse ofs = np->msgin[4]; 60762814Sse if (ofs==0) per=255; 60772814Sse 60782432Sse /* 60792814Sse ** check values against driver limits. 60802432Sse */ 608127684Sse if (per < np->minsync) 608227684Sse {chg = 1; per = np->minsync;} 608339247Sgibbs if (per < tp->tinfo.user.period) 608439247Sgibbs {chg = 1; per = tp->tinfo.user.period;} 608539247Sgibbs if (ofs > tp->tinfo.user.offset) 608639247Sgibbs {chg = 1; ofs = tp->tinfo.user.offset;} 60872814Sse 60882814Sse /* 60892814Sse ** Check against controller limits. 60902814Sse */ 609127684Sse 609227684Sse fak = 7; 609327684Sse scntl3 = 0; 609417449Sse if (ofs != 0) { 609527684Sse ncr_getsync(np, per, &fak, &scntl3); 609627684Sse if (fak > 7) { 609717449Sse chg = 1; 609817449Sse ofs = 0; 609917449Sse } 610017449Sse } 610117449Sse if (ofs == 0) { 610227684Sse fak = 7; 610327684Sse per = 0; 610427684Sse scntl3 = 0; 610517449Sse } 61062432Sse 61073552Sse if (DEBUG_FLAGS & DEBUG_NEGO) { 610839247Sgibbs PRINT_ADDR(cp->ccb); 610927684Sse printf ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n", 611027684Sse per, scntl3, ofs, fak, chg); 61112432Sse } 61127228Sse 61132814Sse if (INB (HS_PRT) == HS_NEGOTIATE) { 61142814Sse OUTB (HS_PRT, HS_BUSY); 61152814Sse switch (cp->nego_status) { 61162432Sse 61172814Sse case NS_SYNC: 61182814Sse /* 61192814Sse ** This was an answer message 61202814Sse */ 61212814Sse if (chg) { 61222814Sse /* 61232814Sse ** Answer wasn't acceptable. 61242814Sse */ 612539247Sgibbs ncr_setsync (np, cp, 0, 0xe0, 0); 612610677Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad)); 61272814Sse } else { 61282814Sse /* 61292814Sse ** Answer is ok. 61302814Sse */ 613139247Sgibbs ncr_setsync (np,cp,scntl3,(fak<<5)|ofs, per); 613210677Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack)); 61332814Sse }; 61342814Sse return; 61352432Sse 61362814Sse case NS_WIDE: 613727684Sse ncr_setwide (np, cp, 0, 0); 61382814Sse break; 61392814Sse }; 61402814Sse }; 61412432Sse 61422432Sse /* 61432814Sse ** It was a request. Set value and 61442814Sse ** prepare an answer message 61452432Sse */ 61462814Sse 614739247Sgibbs ncr_setsync (np, cp, scntl3, (fak<<5)|ofs, per); 61482432Sse 614939247Sgibbs np->msgout[0] = MSG_EXTENDED; 61502432Sse np->msgout[1] = 3; 615139247Sgibbs np->msgout[2] = MSG_EXT_SDTR; 61522432Sse np->msgout[3] = per; 61532432Sse np->msgout[4] = ofs; 61542432Sse 61552814Sse cp->nego_status = NS_SYNC; 61562814Sse 61573552Sse if (DEBUG_FLAGS & DEBUG_NEGO) { 615839247Sgibbs PRINT_ADDR(cp->ccb); 61592432Sse printf ("sync msgout: "); 616013809Sse (void) ncr_show_msg (np->msgout); 61612432Sse printf (".\n"); 61622432Sse } 61639364Sse 61649364Sse if (!ofs) { 616510677Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad)); 61669364Sse return; 61679364Sse } 616839247Sgibbs np->msgin [0] = MSG_NOOP; 61699364Sse 61702432Sse break; 61717228Sse 61722814Sse case SIR_NEGO_WIDE: 61732814Sse /* 61742814Sse ** Wide request message received. 61752814Sse */ 61763552Sse if (DEBUG_FLAGS & DEBUG_NEGO) { 617739247Sgibbs PRINT_ADDR(cp->ccb); 61782814Sse printf ("wide msgin: "); 61792814Sse (void) ncr_show_msg (np->msgin); 61802814Sse printf (".\n"); 61812814Sse }; 61822432Sse 61832814Sse /* 61842814Sse ** get requested values. 61852814Sse */ 61862432Sse 61872814Sse chg = 0; 61882814Sse wide = np->msgin[3]; 61892814Sse 61902814Sse /* 61912814Sse ** check values against driver limits. 61922814Sse */ 61932814Sse 619439247Sgibbs if (wide > tp->tinfo.user.width) 619539247Sgibbs {chg = 1; wide = tp->tinfo.user.width;} 61962814Sse 61973552Sse if (DEBUG_FLAGS & DEBUG_NEGO) { 619839247Sgibbs PRINT_ADDR(cp->ccb); 61992814Sse printf ("wide: wide=%d chg=%d.\n", wide, chg); 62002814Sse } 62017228Sse 62022814Sse if (INB (HS_PRT) == HS_NEGOTIATE) { 62032814Sse OUTB (HS_PRT, HS_BUSY); 62042814Sse switch (cp->nego_status) { 62052814Sse 62062814Sse case NS_WIDE: 62072814Sse /* 62082814Sse ** This was an answer message 62092814Sse */ 62102814Sse if (chg) { 62112814Sse /* 62122814Sse ** Answer wasn't acceptable. 62132814Sse */ 621427684Sse ncr_setwide (np, cp, 0, 1); 621510677Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad)); 62162814Sse } else { 62172814Sse /* 62182814Sse ** Answer is ok. 62192814Sse */ 622027684Sse ncr_setwide (np, cp, wide, 1); 622110677Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack)); 62222814Sse }; 62232814Sse return; 62242814Sse 62252814Sse case NS_SYNC: 622639247Sgibbs ncr_setsync (np, cp, 0, 0xe0, 0); 62272814Sse break; 62282814Sse }; 62292814Sse }; 62302814Sse 62312814Sse /* 62322814Sse ** It was a request, set value and 62332814Sse ** prepare an answer message 62342814Sse */ 62352814Sse 623627684Sse ncr_setwide (np, cp, wide, 1); 62372814Sse 623839247Sgibbs np->msgout[0] = MSG_EXTENDED; 62392814Sse np->msgout[1] = 2; 624039247Sgibbs np->msgout[2] = MSG_EXT_WDTR; 62412814Sse np->msgout[3] = wide; 62422814Sse 624339247Sgibbs np->msgin [0] = MSG_NOOP; 62442814Sse 62452814Sse cp->nego_status = NS_WIDE; 62462814Sse 62473552Sse if (DEBUG_FLAGS & DEBUG_NEGO) { 624839247Sgibbs PRINT_ADDR(cp->ccb); 62492814Sse printf ("wide msgout: "); 625013809Sse (void) ncr_show_msg (np->msgout); 62512814Sse printf (".\n"); 62522814Sse } 62532814Sse break; 62547228Sse 62552432Sse/*-------------------------------------------------------------------- 62562432Sse** 62572432Sse** Processing of special messages 62582432Sse** 62592432Sse**-------------------------------------------------------------------- 62602432Sse*/ 62612432Sse 62622814Sse case SIR_REJECT_RECEIVED: 62632814Sse /*----------------------------------------------- 62642814Sse ** 626539247Sgibbs ** We received a MSG_MESSAGE_REJECT message. 62662814Sse ** 62672814Sse **----------------------------------------------- 62682432Sse */ 62692814Sse 627039247Sgibbs PRINT_ADDR(cp->ccb); 627139247Sgibbs printf ("MSG_MESSAGE_REJECT received (%x:%x).\n", 62723533Sse (unsigned)np->lastmsg, np->msgout[0]); 62732432Sse break; 62742432Sse 62752814Sse case SIR_REJECT_SENT: 62762814Sse /*----------------------------------------------- 62772814Sse ** 62782432Sse ** We received an unknown message 62792814Sse ** 62802814Sse **----------------------------------------------- 62812432Sse */ 62822814Sse 628339247Sgibbs PRINT_ADDR(cp->ccb); 628439247Sgibbs printf ("MSG_MESSAGE_REJECT sent for "); 62852814Sse (void) ncr_show_msg (np->msgin); 62862432Sse printf (".\n"); 62872432Sse break; 62887228Sse 62892432Sse/*-------------------------------------------------------------------- 62902432Sse** 62912814Sse** Processing of special messages 62922814Sse** 62932814Sse**-------------------------------------------------------------------- 62942814Sse*/ 62952814Sse 62962814Sse case SIR_IGN_RESIDUE: 62972814Sse /*----------------------------------------------- 62982814Sse ** 62992814Sse ** We received an IGNORE RESIDUE message, 63002814Sse ** which couldn't be handled by the script. 63012814Sse ** 63022814Sse **----------------------------------------------- 63032814Sse */ 63042814Sse 630539247Sgibbs PRINT_ADDR(cp->ccb); 630639247Sgibbs printf ("MSG_IGN_WIDE_RESIDUE received, but not yet implemented.\n"); 63072814Sse break; 63082814Sse 63092814Sse case SIR_MISSING_SAVE: 63102814Sse /*----------------------------------------------- 63112814Sse ** 63122814Sse ** We received an DISCONNECT message, 63132814Sse ** but the datapointer wasn't saved before. 63142814Sse ** 63152814Sse **----------------------------------------------- 63162814Sse */ 63172814Sse 631839247Sgibbs PRINT_ADDR(cp->ccb); 631939247Sgibbs printf ("MSG_DISCONNECT received, but datapointer not saved:\n" 63203533Sse "\tdata=%x save=%x goal=%x.\n", 63213533Sse (unsigned) INL (nc_temp), 63223533Sse (unsigned) np->header.savep, 63233533Sse (unsigned) np->header.goalp); 63242814Sse break; 63257228Sse 63262814Sse/*-------------------------------------------------------------------- 63272814Sse** 632839247Sgibbs** Processing of a "SCSI_STATUS_QUEUE_FULL" status. 63292432Sse** 633039247Sgibbs** XXX JGibbs - We should do the same thing for BUSY status. 633139247Sgibbs** 63322814Sse** The current command has been rejected, 63332814Sse** because there are too many in the command queue. 63342432Sse** We have started too many commands for that target. 63352432Sse** 63362432Sse**-------------------------------------------------------------------- 63372432Sse*/ 63382814Sse case SIR_STALL_QUEUE: 633939386Sgibbs cp->xerr_status = XE_OK; 634039386Sgibbs cp->host_status = HS_COMPLETE; 634139247Sgibbs cp->s_status = SCSI_STATUS_QUEUE_FULL; 634239247Sgibbs ncr_freeze_devq(np, cp->ccb->ccb_h.path); 634339247Sgibbs ncr_complete(np, cp); 63442432Sse 6345102412Scharnier /* FALLTHROUGH */ 63462432Sse 63472814Sse case SIR_STALL_RESTART: 63482814Sse /*----------------------------------------------- 63492814Sse ** 63502814Sse ** Enable selecting again, 63512814Sse ** if NO disconnected jobs. 63522814Sse ** 63532814Sse **----------------------------------------------- 63543043Srgrimes */ 63552814Sse /* 63562432Sse ** Look for a disconnected job. 63572432Sse */ 635839247Sgibbs cp = np->link_nccb; 63592432Sse while (cp && cp->host_status != HS_DISCONNECT) 636039247Sgibbs cp = cp->link_nccb; 63612432Sse 63622432Sse /* 63632432Sse ** if there is one, ... 63642432Sse */ 63652432Sse if (cp) { 63662432Sse /* 63672432Sse ** wait for reselection 63682432Sse */ 636910677Sse OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, reselect)); 63702432Sse return; 63712432Sse }; 63722432Sse 63732432Sse /* 63746705Sse ** else remove the interrupt. 63752432Sse */ 63762432Sse 63772432Sse printf ("%s: queue empty.\n", ncr_name (np)); 637839532Sken WRITESCRIPT(start1[0], SCR_INT ^ IFFALSE (0)); 63792432Sse break; 63802432Sse }; 63812432Sse 63822432Sseout: 638320435Sse OUTB (nc_dcntl, np->rv_dcntl | STD); 63842432Sse} 63857228Sse 63862432Sse/*========================================================== 63872432Sse** 63882432Sse** 63892432Sse** Aquire a control block 63902432Sse** 63912432Sse** 63922432Sse**========================================================== 63932432Sse*/ 63942432Sse 639539247Sgibbsstatic nccb_p ncr_get_nccb 639639247Sgibbs (ncb_p np, u_long target, u_long lun) 63972432Sse{ 63982432Sse lcb_p lp; 639939247Sgibbs nccb_p cp = NULL; 64002432Sse 64012432Sse /* 64022432Sse ** Lun structure available ? 64032432Sse */ 64042432Sse 64052432Sse lp = np->target[target].lp[lun]; 640610567Sse if (lp) { 640739247Sgibbs cp = lp->next_nccb; 64082432Sse 640910567Sse /* 641010567Sse ** Look for free CCB 641110567Sse */ 64122432Sse 641320435Sse while (cp && cp->magic) { 641439247Sgibbs cp = cp->next_nccb; 641520435Sse } 641610567Sse } 64172432Sse 64182432Sse /* 641939247Sgibbs ** if nothing available, create one. 64202432Sse */ 64212432Sse 642239247Sgibbs if (cp == NULL) 642339247Sgibbs cp = ncr_alloc_nccb(np, target, lun); 64242432Sse 642539247Sgibbs if (cp != NULL) { 642639247Sgibbs if (cp->magic) { 642739247Sgibbs printf("%s: Bogus free cp found\n", ncr_name(np)); 642839247Sgibbs return (NULL); 642939247Sgibbs } 643039247Sgibbs cp->magic = 1; 643120435Sse } 64322432Sse return (cp); 64332432Sse} 64347228Sse 64352432Sse/*========================================================== 64362432Sse** 64372432Sse** 64382432Sse** Release one control block 64392432Sse** 64402432Sse** 64412432Sse**========================================================== 64422432Sse*/ 64432432Sse 6444105219Sphkstatic void ncr_free_nccb (ncb_p np, nccb_p cp) 64452432Sse{ 64462432Sse /* 64472432Sse ** sanity 64482432Sse */ 64492432Sse 645010567Sse assert (cp != NULL); 64512432Sse 64522432Sse cp -> host_status = HS_IDLE; 64532432Sse cp -> magic = 0; 64542432Sse} 64557228Sse 64562432Sse/*========================================================== 64572432Sse** 64582432Sse** 64592432Sse** Allocation of resources for Targets/Luns/Tags. 64602432Sse** 64612432Sse** 64622432Sse**========================================================== 64632432Sse*/ 64642432Sse 646539247Sgibbsstatic nccb_p 646639247Sgibbsncr_alloc_nccb (ncb_p np, u_long target, u_long lun) 64672432Sse{ 64682432Sse tcb_p tp; 64692432Sse lcb_p lp; 647039247Sgibbs nccb_p cp; 64712432Sse 647210567Sse assert (np != NULL); 64732432Sse 647439247Sgibbs if (target>=MAX_TARGET) return(NULL); 647539247Sgibbs if (lun >=MAX_LUN ) return(NULL); 64762432Sse 64772432Sse tp=&np->target[target]; 64782432Sse 64792432Sse if (!tp->jump_tcb.l_cmd) { 64802432Sse 64812432Sse /* 64822432Sse ** initialize it. 64832432Sse */ 64842432Sse tp->jump_tcb.l_cmd = (SCR_JUMP^IFFALSE (DATA (0x80 + target))); 64852432Sse tp->jump_tcb.l_paddr = np->jump_tcb.l_paddr; 64862432Sse 648727684Sse tp->getscr[0] = 648827684Sse (np->features & FE_PFEN)? SCR_COPY(1) : SCR_COPY_F(1); 648939247Sgibbs tp->getscr[1] = vtophys (&tp->tinfo.sval); 649060974Sdfr tp->getscr[2] = rman_get_start(np->reg_res) + offsetof (struct ncr_reg, nc_sxfer); 649127684Sse tp->getscr[3] = 649227684Sse (np->features & FE_PFEN)? SCR_COPY(1) : SCR_COPY_F(1); 649339247Sgibbs tp->getscr[4] = vtophys (&tp->tinfo.wval); 649460974Sdfr tp->getscr[5] = rman_get_start(np->reg_res) + offsetof (struct ncr_reg, nc_scntl3); 64952432Sse 649639247Sgibbs assert (((offsetof(struct ncr_reg, nc_sxfer) ^ 649739247Sgibbs (offsetof(struct tcb ,tinfo) 649839247Sgibbs + offsetof(struct ncr_target_tinfo, sval))) & 3) == 0); 649939247Sgibbs assert (((offsetof(struct ncr_reg, nc_scntl3) ^ 650039247Sgibbs (offsetof(struct tcb, tinfo) 650139247Sgibbs + offsetof(struct ncr_target_tinfo, wval))) &3) == 0); 65022432Sse 65032432Sse tp->call_lun.l_cmd = (SCR_CALL); 650410677Sse tp->call_lun.l_paddr = NCB_SCRIPT_PHYS (np, resel_lun); 65052432Sse 65062432Sse tp->jump_lcb.l_cmd = (SCR_JUMP); 650727744Sse tp->jump_lcb.l_paddr = NCB_SCRIPTH_PHYS (np, abort); 65082432Sse np->jump_tcb.l_paddr = vtophys (&tp->jump_tcb); 65092432Sse } 65107228Sse 65112432Sse /* 65122432Sse ** Logic unit control block 65132432Sse */ 65142432Sse lp = tp->lp[lun]; 65152432Sse if (!lp) { 65162432Sse /* 65172432Sse ** Allocate a lcb 65182432Sse */ 651969781Sdwmalone lp = (lcb_p) malloc (sizeof (struct lcb), M_DEVBUF, 652069781Sdwmalone M_NOWAIT | M_ZERO); 652139247Sgibbs if (!lp) return(NULL); 65222432Sse 65232432Sse /* 65242432Sse ** Initialize it 65252432Sse */ 65262432Sse lp->jump_lcb.l_cmd = (SCR_JUMP ^ IFFALSE (DATA (lun))); 65272432Sse lp->jump_lcb.l_paddr = tp->jump_lcb.l_paddr; 65282432Sse 65292432Sse lp->call_tag.l_cmd = (SCR_CALL); 653010677Sse lp->call_tag.l_paddr = NCB_SCRIPT_PHYS (np, resel_tag); 65312432Sse 653239247Sgibbs lp->jump_nccb.l_cmd = (SCR_JUMP); 653339247Sgibbs lp->jump_nccb.l_paddr = NCB_SCRIPTH_PHYS (np, aborttag); 65342432Sse 65352432Sse lp->actlink = 1; 65369364Sse 65372432Sse /* 65389364Sse ** Chain into LUN list 65392432Sse */ 65402432Sse tp->jump_lcb.l_paddr = vtophys (&lp->jump_lcb); 65412432Sse tp->lp[lun] = lp; 65422432Sse 65432432Sse } 65442432Sse 65452432Sse /* 654639247Sgibbs ** Allocate a nccb 65472432Sse */ 654869781Sdwmalone cp = (nccb_p) malloc (sizeof (struct nccb), M_DEVBUF, M_NOWAIT|M_ZERO); 65492432Sse 65502432Sse if (!cp) 655139247Sgibbs return (NULL); 65522432Sse 655339247Sgibbs if (DEBUG_FLAGS & DEBUG_ALLOC) { 655439532Sken printf ("new nccb @%p.\n", cp); 65552432Sse } 65562432Sse 65572432Sse /* 655810639Sse ** Fill in physical addresses 655910639Sse */ 656010639Sse 656139247Sgibbs cp->p_nccb = vtophys (cp); 656210639Sse 656310639Sse /* 65649364Sse ** Chain into reselect list 65652432Sse */ 656639247Sgibbs cp->jump_nccb.l_cmd = SCR_JUMP; 656739247Sgibbs cp->jump_nccb.l_paddr = lp->jump_nccb.l_paddr; 656839247Sgibbs lp->jump_nccb.l_paddr = CCB_PHYS (cp, jump_nccb); 65692432Sse cp->call_tmp.l_cmd = SCR_CALL; 657010677Sse cp->call_tmp.l_paddr = NCB_SCRIPT_PHYS (np, resel_tmp); 65712432Sse 65722432Sse /* 65739364Sse ** Chain into wakeup list 65742432Sse */ 657539247Sgibbs cp->link_nccb = np->link_nccb; 657639247Sgibbs np->link_nccb = cp; 65772432Sse 65782432Sse /* 65799364Sse ** Chain into CCB list 65802432Sse */ 658139247Sgibbs cp->next_nccb = lp->next_nccb; 658239247Sgibbs lp->next_nccb = cp; 65837228Sse 658439247Sgibbs return (cp); 65852432Sse} 65867228Sse 65872432Sse/*========================================================== 65882432Sse** 65892432Sse** 65902432Sse** Build Scatter Gather Block 65912432Sse** 65922432Sse** 65932432Sse**========================================================== 65942432Sse** 65952432Sse** The transfer area may be scattered among 65962432Sse** several non adjacent physical pages. 65972432Sse** 65982432Sse** We may use MAX_SCATTER blocks. 65992432Sse** 66002432Sse**---------------------------------------------------------- 66012432Sse*/ 66022432Sse 66032814Ssestatic int ncr_scatter 66042432Sse (struct dsb* phys, vm_offset_t vaddr, vm_size_t datalen) 66052432Sse{ 66062432Sse u_long paddr, pnext; 66072432Sse 66082432Sse u_short segment = 0; 66092432Sse u_long segsize, segaddr; 66102432Sse u_long size, csize = 0; 66112432Sse u_long chunk = MAX_SIZE; 66122432Sse int free; 66132432Sse 66142432Sse bzero (&phys->data, sizeof (phys->data)); 66152432Sse if (!datalen) return (0); 66162432Sse 66172432Sse paddr = vtophys (vaddr); 66182432Sse 66192432Sse /* 66202432Sse ** insert extra break points at a distance of chunk. 662110567Sse ** We try to reduce the number of interrupts caused 662210567Sse ** by unexpected phase changes due to disconnects. 66232432Sse ** A typical harddisk may disconnect before ANY block. 662410567Sse ** If we wanted to avoid unexpected phase changes at all 662510567Sse ** we had to use a break point every 512 bytes. 66262432Sse ** Of course the number of scatter/gather blocks is 66272432Sse ** limited. 66282432Sse */ 66292432Sse 66302432Sse free = MAX_SCATTER - 1; 66312432Sse 663215583Sphk if (vaddr & PAGE_MASK) free -= datalen / PAGE_SIZE; 66332432Sse 66342432Sse if (free>1) 66352432Sse while ((chunk * free >= 2 * datalen) && (chunk>=1024)) 66362432Sse chunk /= 2; 66372432Sse 66383552Sse if(DEBUG_FLAGS & DEBUG_SCATTER) 663939532Sken printf("ncr?:\tscattering virtual=%p size=%d chunk=%d.\n", 664039532Sken (void *) vaddr, (unsigned) datalen, (unsigned) chunk); 66417228Sse 66422432Sse /* 66432432Sse ** Build data descriptors. 66442432Sse */ 66452432Sse while (datalen && (segment < MAX_SCATTER)) { 66462432Sse 66472432Sse /* 66482432Sse ** this segment is empty 66492432Sse */ 66502432Sse segsize = 0; 66512432Sse segaddr = paddr; 66522432Sse pnext = paddr; 66532432Sse 66542432Sse if (!csize) csize = chunk; 66552432Sse 66562432Sse while ((datalen) && (paddr == pnext) && (csize)) { 66572432Sse 66582432Sse /* 66592432Sse ** continue this segment 66602432Sse */ 666115583Sphk pnext = (paddr & (~PAGE_MASK)) + PAGE_SIZE; 66622432Sse 66632432Sse /* 66642432Sse ** Compute max size 66652432Sse */ 66662432Sse 66677228Sse size = pnext - paddr; /* page size */ 66682432Sse if (size > datalen) size = datalen; /* data size */ 66692432Sse if (size > csize ) size = csize ; /* chunksize */ 66702432Sse 66712432Sse segsize += size; 66722432Sse vaddr += size; 66732432Sse csize -= size; 66742432Sse datalen -= size; 66752432Sse paddr = vtophys (vaddr); 66762432Sse }; 66772432Sse 66783552Sse if(DEBUG_FLAGS & DEBUG_SCATTER) 66792432Sse printf ("\tseg #%d addr=%x size=%d (rest=%d).\n", 66803533Sse segment, 66813533Sse (unsigned) segaddr, 66823533Sse (unsigned) segsize, 66833533Sse (unsigned) datalen); 66842432Sse 66852432Sse phys->data[segment].addr = segaddr; 66862432Sse phys->data[segment].size = segsize; 66872432Sse segment++; 66882432Sse } 66892432Sse 66902814Sse if (datalen) { 66912432Sse printf("ncr?: scatter/gather failed (residue=%d).\n", 66923533Sse (unsigned) datalen); 66932814Sse return (-1); 66942814Sse }; 66952432Sse 66962814Sse return (segment); 66972432Sse} 66987228Sse 66992432Sse/*========================================================== 67002432Sse** 67012432Sse** 67023166Sse** Test the pci bus snoop logic :-( 67033166Sse** 67046705Sse** Has to be called with interrupts disabled. 67053166Sse** 67063166Sse** 67073166Sse**========================================================== 67083166Sse*/ 67093166Sse 67106401Sse#ifndef NCR_IOMAPPED 67116398Ssestatic int ncr_regtest (struct ncb* np) 67126398Sse{ 671339532Sken register volatile u_int32_t data; 67146398Sse /* 67156398Sse ** ncr registers may NOT be cached. 67166398Sse ** write 0xffffffff to a read only register area, 67176398Sse ** and try to read it back. 67186398Sse */ 67196398Sse data = 0xffffffff; 672039532Sken OUTL_OFF(offsetof(struct ncr_reg, nc_dstat), data); 672139532Sken data = INL_OFF(offsetof(struct ncr_reg, nc_dstat)); 67226398Sse#if 1 67236398Sse if (data == 0xffffffff) { 67246398Sse#else 67256398Sse if ((data & 0xe2f0fffd) != 0x02000080) { 67266398Sse#endif 67276398Sse printf ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n", 67286398Sse (unsigned) data); 67296398Sse return (0x10); 67306398Sse }; 67316398Sse return (0); 67326401Sse} 67336398Sse#endif 67346398Sse 67353166Ssestatic int ncr_snooptest (struct ncb* np) 67363166Sse{ 673728960Sse u_int32_t ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc; 673828960Sse int i, err=0; 67396398Sse#ifndef NCR_IOMAPPED 67406398Sse err |= ncr_regtest (np); 67416398Sse if (err) return (err); 67426398Sse#endif 67433166Sse /* 67443166Sse ** init 67453166Sse */ 674627744Sse pc = NCB_SCRIPTH_PHYS (np, snooptest); 67473166Sse host_wr = 1; 67483166Sse ncr_wr = 2; 67493166Sse /* 67503166Sse ** Set memory and register. 67513166Sse */ 67523166Sse ncr_cache = host_wr; 67533166Sse OUTL (nc_temp, ncr_wr); 67543166Sse /* 67553166Sse ** Start script (exchange values) 67563166Sse */ 67573166Sse OUTL (nc_dsp, pc); 67583166Sse /* 67596526Sse ** Wait 'til done (with timeout) 67603166Sse */ 67616526Sse for (i=0; i<NCR_SNOOP_TIMEOUT; i++) 67626526Sse if (INB(nc_istat) & (INTF|SIP|DIP)) 67636526Sse break; 67643166Sse /* 67656526Sse ** Save termination position. 67666526Sse */ 67676526Sse pc = INL (nc_dsp); 67686526Sse /* 67693166Sse ** Read memory and register. 67703166Sse */ 67713166Sse host_rd = ncr_cache; 67723166Sse ncr_rd = INL (nc_scratcha); 67733166Sse ncr_bk = INL (nc_temp); 67743166Sse /* 67753166Sse ** Reset ncr chip 67763166Sse */ 67773166Sse OUTB (nc_istat, SRST); 677810605Sse DELAY (1000); 67793166Sse OUTB (nc_istat, 0 ); 67803166Sse /* 67816526Sse ** check for timeout 67826526Sse */ 67836526Sse if (i>=NCR_SNOOP_TIMEOUT) { 67846526Sse printf ("CACHE TEST FAILED: timeout.\n"); 67856526Sse return (0x20); 67866526Sse }; 67876526Sse /* 67886526Sse ** Check termination position. 67896526Sse */ 679027744Sse if (pc != NCB_SCRIPTH_PHYS (np, snoopend)+8) { 67916526Sse printf ("CACHE TEST FAILED: script execution failed.\n"); 679228960Sse printf ("start=%08lx, pc=%08lx, end=%08lx\n", 679328960Sse (u_long) NCB_SCRIPTH_PHYS (np, snooptest), (u_long) pc, 679428960Sse (u_long) NCB_SCRIPTH_PHYS (np, snoopend) +8); 67956526Sse return (0x40); 67966526Sse }; 67976526Sse /* 67983166Sse ** Show results. 67993166Sse */ 68003166Sse if (host_wr != ncr_rd) { 68013166Sse printf ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n", 68023533Sse (int) host_wr, (int) ncr_rd); 68033166Sse err |= 1; 68043166Sse }; 68053166Sse if (host_rd != ncr_wr) { 68063166Sse printf ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n", 68073533Sse (int) ncr_wr, (int) host_rd); 68083166Sse err |= 2; 68093166Sse }; 68103166Sse if (ncr_bk != ncr_wr) { 68113166Sse printf ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n", 68123533Sse (int) ncr_wr, (int) ncr_bk); 68133166Sse err |= 4; 68143166Sse }; 68153166Sse return (err); 68163166Sse} 68177228Sse 68183166Sse/*========================================================== 68193166Sse** 68203166Sse** 68212432Sse** Profiling the drivers and targets performance. 68222432Sse** 68232432Sse** 68242432Sse**========================================================== 68252432Sse*/ 68262432Sse 68272432Sse/* 68282432Sse** Compute the difference in milliseconds. 68292432Sse**/ 68302432Sse 683134961Sphkstatic int ncr_delta (int *from, int *to) 68322432Sse{ 683334961Sphk if (!from) return (-1); 683434961Sphk if (!to) return (-2); 683534961Sphk return ((to - from) * 1000 / hz); 68362432Sse} 68377228Sse 68382432Sse#define PROFILE cp->phys.header.stamp 683939247Sgibbsstatic void ncb_profile (ncb_p np, nccb_p cp) 68402432Sse{ 68412432Sse int co, da, st, en, di, se, post,work,disc; 68422432Sse u_long diff; 68432432Sse 684434961Sphk PROFILE.end = ticks; 68452432Sse 68462432Sse st = ncr_delta (&PROFILE.start,&PROFILE.status); 68472432Sse if (st<0) return; /* status not reached */ 68482432Sse 68492432Sse da = ncr_delta (&PROFILE.start,&PROFILE.data); 68502432Sse if (da<0) return; /* No data transfer phase */ 68512432Sse 68522432Sse co = ncr_delta (&PROFILE.start,&PROFILE.command); 68532432Sse if (co<0) return; /* command not executed */ 68542432Sse 68552432Sse en = ncr_delta (&PROFILE.start,&PROFILE.end), 68562432Sse di = ncr_delta (&PROFILE.start,&PROFILE.disconnect), 68572432Sse se = ncr_delta (&PROFILE.start,&PROFILE.select); 68582432Sse post = en - st; 68592432Sse 68602432Sse /* 68612432Sse ** @PROFILE@ Disconnect time invalid if multiple disconnects 68622432Sse */ 68632432Sse 68642432Sse if (di>=0) disc = se-di; else disc = 0; 68652432Sse 68662432Sse work = (st - co) - disc; 68672432Sse 68682432Sse diff = (np->disc_phys - np->disc_ref) & 0xff; 68692432Sse np->disc_ref += diff; 68702432Sse 68712432Sse np->profile.num_trans += 1; 687239247Sgibbs if (cp->ccb) 687339247Sgibbs np->profile.num_bytes += cp->ccb->csio.dxfer_len; 68742432Sse np->profile.num_disc += diff; 68752432Sse np->profile.ms_setup += co; 68762432Sse np->profile.ms_data += work; 68772432Sse np->profile.ms_disc += disc; 68782432Sse np->profile.ms_post += post; 68792432Sse} 68802432Sse#undef PROFILE 68817228Sse 68822432Sse/*========================================================== 68832432Sse** 68842432Sse** Determine the ncr's clock frequency. 688527684Sse** This is essential for the negotiation 68862432Sse** of the synchronous transfer rate. 68872432Sse** 68882432Sse**========================================================== 68892432Sse** 68902432Sse** Note: we have to return the correct value. 68912432Sse** THERE IS NO SAVE DEFAULT VALUE. 68922432Sse** 689327684Sse** Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock. 689427684Sse** 53C860 and 53C875 rev. 1 support fast20 transfers but 689527684Sse** do not have a clock doubler and so are provided with a 689627684Sse** 80 MHz clock. All other fast20 boards incorporate a doubler 689727684Sse** and so should be delivered with a 40 MHz clock. 689827684Sse** The future fast40 chips (895/895) use a 40 Mhz base clock 689927684Sse** and provide a clock quadrupler (160 Mhz). The code below 690027684Sse** tries to deal as cleverly as possible with all this stuff. 69012432Sse** 69022432Sse**---------------------------------------------------------- 69032432Sse*/ 69042432Sse 690527684Sse/* 690627684Sse * Select NCR SCSI clock frequency 690727684Sse */ 690827684Ssestatic void ncr_selectclock(ncb_p np, u_char scntl3) 690927684Sse{ 691027684Sse if (np->multiplier < 2) { 691127684Sse OUTB(nc_scntl3, scntl3); 691227684Sse return; 691327684Sse } 69142432Sse 691527684Sse if (bootverbose >= 2) 691627684Sse printf ("%s: enabling clock multiplier\n", ncr_name(np)); 691727684Sse 691827684Sse OUTB(nc_stest1, DBLEN); /* Enable clock multiplier */ 691927684Sse if (np->multiplier > 2) { /* Poll bit 5 of stest4 for quadrupler */ 692027684Sse int i = 20; 692127684Sse while (!(INB(nc_stest4) & LCKFRQ) && --i > 0) 692227684Sse DELAY(20); 692327684Sse if (!i) 692427684Sse printf("%s: the chip cannot lock the frequency\n", ncr_name(np)); 692527684Sse } else /* Wait 20 micro-seconds for doubler */ 692627684Sse DELAY(20); 692727684Sse OUTB(nc_stest3, HSC); /* Halt the scsi clock */ 692827684Sse OUTB(nc_scntl3, scntl3); 692927684Sse OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */ 693027684Sse OUTB(nc_stest3, 0x00); /* Restart scsi clock */ 693127684Sse} 693227684Sse 693318875Sse/* 693418875Sse * calculate NCR SCSI clock frequency (in KHz) 693518875Sse */ 693618875Ssestatic unsigned 693718875Ssencrgetfreq (ncb_p np, int gen) 69382432Sse{ 693918875Sse int ms = 0; 69402432Sse /* 694118875Sse * Measure GEN timer delay in order 694218875Sse * to calculate SCSI clock frequency 694318875Sse * 694418875Sse * This code will never execute too 694518875Sse * many loop iterations (if DELAY is 694618875Sse * reasonably correct). It could get 694718875Sse * too low a delay (too high a freq.) 694818875Sse * if the CPU is slow executing the 694918875Sse * loop for some reason (an NMI, for 695018875Sse * example). For this reason we will 695118875Sse * if multiple measurements are to be 695218875Sse * performed trust the higher delay 695318875Sse * (lower frequency returned). 695418875Sse */ 695518875Sse OUTB (nc_stest1, 0); /* make sure clock doubler is OFF */ 695618875Sse OUTW (nc_sien , 0); /* mask all scsi interrupts */ 695718875Sse (void) INW (nc_sist); /* clear pending scsi interrupt */ 695818875Sse OUTB (nc_dien , 0); /* mask all dma interrupts */ 695918875Sse (void) INW (nc_sist); /* another one, just to be sure :) */ 696018875Sse OUTB (nc_scntl3, 4); /* set pre-scaler to divide by 3 */ 696118875Sse OUTB (nc_stime1, 0); /* disable general purpose timer */ 696218875Sse OUTB (nc_stime1, gen); /* set to nominal delay of (1<<gen) * 125us */ 696318875Sse while (!(INW(nc_sist) & GEN) && ms++ < 1000) 696418875Sse DELAY(1000); /* count ms */ 696518875Sse OUTB (nc_stime1, 0); /* disable general purpose timer */ 696618875Sse OUTB (nc_scntl3, 0); 696718875Sse /* 696818875Sse * Set prescaler to divide by whatever "0" means. 696918875Sse * "0" ought to choose divide by 2, but appears 697018875Sse * to set divide by 3.5 mode in my 53c810 ... 697118875Sse */ 697218875Sse OUTB (nc_scntl3, 0); 69732432Sse 697427744Sse if (bootverbose >= 2) 697539310Sgibbs printf ("\tDelay (GEN=%d): %u msec\n", gen, ms); 697617836Sse /* 697718875Sse * adjust for prescaler, and convert into KHz 697817836Sse */ 697918875Sse return ms ? ((1 << gen) * 4440) / ms : 0; 698018875Sse} 698117836Sse 698227684Ssestatic void ncr_getclock (ncb_p np, u_char multiplier) 698318875Sse{ 698418875Sse unsigned char scntl3; 698518875Sse unsigned char stest1; 698618875Sse scntl3 = INB(nc_scntl3); 698718875Sse stest1 = INB(nc_stest1); 698818875Sse 698927684Sse np->multiplier = 1; 699046581Sken 699146581Sken if (multiplier > 1) { 699227684Sse np->multiplier = multiplier; 699327684Sse np->clock_khz = 40000 * multiplier; 699418875Sse } else { 699518875Sse if ((scntl3 & 7) == 0) { 699618875Sse unsigned f1, f2; 699718875Sse /* throw away first result */ 699818875Sse (void) ncrgetfreq (np, 11); 699918875Sse f1 = ncrgetfreq (np, 11); 700018875Sse f2 = ncrgetfreq (np, 11); 700118875Sse 700227744Sse if (bootverbose >= 2) 700339310Sgibbs printf ("\tNCR clock is %uKHz, %uKHz\n", f1, f2); 700418875Sse if (f1 > f2) f1 = f2; /* trust lower result */ 700518875Sse if (f1 > 45000) { 700618875Sse scntl3 = 5; /* >45Mhz: assume 80MHz */ 700718875Sse } else { 700818875Sse scntl3 = 3; /* <45Mhz: assume 40MHz */ 700918875Sse } 701018875Sse } 701127684Sse else if ((scntl3 & 7) == 5) 701227684Sse np->clock_khz = 80000; /* Probably a 875 rev. 1 ? */ 701317850Sse } 70142432Sse} 70152432Sse 70162432Sse/*=========================================================================*/ 701720435Sse 701820435Sse#ifdef NCR_TEKRAM_EEPROM 701920435Sse 702020435Ssestruct tekram_eeprom_dev { 702120435Sse u_char devmode; 702220435Sse#define TKR_PARCHK 0x01 702320435Sse#define TKR_TRYSYNC 0x02 702420435Sse#define TKR_ENDISC 0x04 702520435Sse#define TKR_STARTUNIT 0x08 702620435Sse#define TKR_USETAGS 0x10 702720435Sse#define TKR_TRYWIDE 0x20 702820435Sse u_char syncparam; /* max. sync transfer rate (table ?) */ 702920435Sse u_char filler1; 703020435Sse u_char filler2; 703120435Sse}; 703220435Sse 703320435Sse 703420435Ssestruct tekram_eeprom { 703520435Sse struct tekram_eeprom_dev 703620435Sse dev[16]; 703720435Sse u_char adaptid; 703820435Sse u_char adaptmode; 703920435Sse#define TKR_ADPT_GT2DRV 0x01 704020435Sse#define TKR_ADPT_GT1GB 0x02 704120435Sse#define TKR_ADPT_RSTBUS 0x04 704220435Sse#define TKR_ADPT_ACTNEG 0x08 704320435Sse#define TKR_ADPT_NOSEEK 0x10 704420435Sse#define TKR_ADPT_MORLUN 0x20 704542155Shoek u_char delay; /* unit ? ( table ??? ) */ 704620435Sse u_char tags; /* use 4 times as many ... */ 704720435Sse u_char filler[60]; 704820435Sse}; 704920435Sse 705020435Ssestatic void 705120435Ssetekram_write_bit (ncb_p np, int bit) 705220435Sse{ 705320435Sse u_char val = 0x10 + ((bit & 1) << 1); 705420435Sse 705520435Sse DELAY(10); 705620435Sse OUTB (nc_gpreg, val); 705720435Sse DELAY(10); 705820435Sse OUTB (nc_gpreg, val | 0x04); 705920435Sse DELAY(10); 706020435Sse OUTB (nc_gpreg, val); 706120435Sse DELAY(10); 706220435Sse} 706320435Sse 706420435Ssestatic int 706520435Ssetekram_read_bit (ncb_p np) 706620435Sse{ 706720435Sse OUTB (nc_gpreg, 0x10); 706820435Sse DELAY(10); 706920435Sse OUTB (nc_gpreg, 0x14); 707020435Sse DELAY(10); 707120435Sse return INB (nc_gpreg) & 1; 707220435Sse} 707320435Sse 707420435Ssestatic u_short 707520435Sseread_tekram_eeprom_reg (ncb_p np, int reg) 707620435Sse{ 707720435Sse int bit; 707820435Sse u_short result = 0; 707920435Sse int cmd = 0x80 | reg; 708020435Sse 708120435Sse OUTB (nc_gpreg, 0x10); 708220435Sse 708320435Sse tekram_write_bit (np, 1); 708420435Sse for (bit = 7; bit >= 0; bit--) 708520435Sse { 708620435Sse tekram_write_bit (np, cmd >> bit); 708720435Sse } 708820435Sse 708920435Sse for (bit = 0; bit < 16; bit++) 709020435Sse { 709120435Sse result <<= 1; 709220435Sse result |= tekram_read_bit (np); 709320435Sse } 709420435Sse 709520435Sse OUTB (nc_gpreg, 0x00); 709620435Sse return result; 709720435Sse} 709820435Sse 709920435Ssestatic int 710020435Sseread_tekram_eeprom(ncb_p np, struct tekram_eeprom *buffer) 710120435Sse{ 710220435Sse u_short *p = (u_short *) buffer; 710320435Sse u_short sum = 0; 710420435Sse int i; 710520435Sse 710620435Sse if (INB (nc_gpcntl) != 0x09) 710720435Sse { 710820435Sse return 0; 710920435Sse } 711020435Sse for (i = 0; i < 64; i++) 711120435Sse { 711220435Sse u_short val; 711320435Sseif((i&0x0f) == 0) printf ("%02x:", i*2); 711420435Sse val = read_tekram_eeprom_reg (np, i); 711520435Sse if (p) 711620435Sse *p++ = val; 711720435Sse sum += val; 711820435Sseif((i&0x01) == 0x00) printf (" "); 711920435Sse printf ("%02x%02x", val & 0xff, (val >> 8) & 0xff); 712020435Sseif((i&0x0f) == 0x0f) printf ("\n"); 712120435Sse } 712220435Sseprintf ("Sum = %04x\n", sum); 712320435Sse return sum == 0x1234; 712420435Sse} 712520435Sse#endif /* NCR_TEKRAM_EEPROM */ 712620435Sse 712760974Sdfrstatic device_method_t ncr_methods[] = { 712860974Sdfr /* Device interface */ 712960974Sdfr DEVMETHOD(device_probe, ncr_probe), 713060974Sdfr DEVMETHOD(device_attach, ncr_attach), 713160974Sdfr 713260974Sdfr { 0, 0 } 713360974Sdfr}; 713460974Sdfr 713560974Sdfrstatic driver_t ncr_driver = { 713660974Sdfr "ncr", 713760974Sdfr ncr_methods, 713860974Sdfr sizeof(struct ncb), 713960974Sdfr}; 714060974Sdfr 714160974Sdfrstatic devclass_t ncr_devclass; 714260974Sdfr 7143113506SmdoddDRIVER_MODULE(ncr, pci, ncr_driver, ncr_devclass, 0, 0); 7144135043SseMODULE_DEPEND(ncr, cam, 1, 1, 1); 7145113506SmdoddMODULE_DEPEND(ncr, pci, 1, 1, 1); 714660974Sdfr 714720435Sse/*=========================================================================*/ 714855206Speter#endif /* _KERNEL */ 7149