1105059Scognet/* 2111158Scognet * O.S : FreeBSD CAM 3105059Scognet * FILE NAME : trm.c 4105059Scognet * BY : C.L. Huang (ching@tekram.com.tw) 5111158Scognet * Erich Chen (erich@tekram.com.tw) 6111158Scognet * Description: Device Driver for Tekram SCSI adapters 7111158Scognet * DC395U/UW/F ,DC315/U(TRM-S1040) 8111158Scognet * DC395U2D/U2W(TRM-S2080) 9111158Scognet * PCI SCSI Bus Master Host Adapter 10111158Scognet * (SCSI chip set used Tekram ASIC TRM-S1040,TRM-S2080) 11105059Scognet */ 12105059Scognet 13119418Sobrien#include <sys/cdefs.h> 14119418Sobrien__FBSDID("$FreeBSD: stable/10/sys/dev/trm/trm.c 315813 2017-03-23 06:41:13Z mav $"); 15119418Sobrien 16105059Scognet/* 17105059Scognet * HISTORY: 18105059Scognet * 19105059Scognet * REV# DATE NAME DESCRIPTION 20105059Scognet * 1.05 05/01/1999 ERICH CHEN First released for 3.x.x (CAM) 21105059Scognet * 1.06 07/29/1999 ERICH CHEN Modify for NEW PCI 22105059Scognet * 1.07 12/12/1999 ERICH CHEN Modify for 3.3.x ,DCB no free 23105059Scognet * 1.08 06/12/2000 ERICH CHEN Modify for 4.x.x 24111158Scognet * 1.09 11/03/2000 ERICH CHEN Modify for 4.1.R ,new sim 25111158Scognet * 1.10 10/10/2001 Oscar Feng Fixed CAM rescan hang up bug. 26111158Scognet * 1.11 10/13/2001 Oscar Feng Fixed wrong Async speed display bug. 27105059Scognet */ 28105059Scognet 29139749Simp/*- 30139749Simp * (C)Copyright 1995-2001 Tekram Technology Co.,Ltd. 31105059Scognet * 32105059Scognet * Redistribution and use in source and binary forms, with or without 33105059Scognet * modification, are permitted provided that the following conditions 34105059Scognet * are met: 35105059Scognet * 1. Redistributions of source code must retain the above copyright 36105059Scognet * notice, this list of conditions and the following disclaimer. 37105059Scognet * 2. Redistributions in binary form must reproduce the above copyright 38105059Scognet * notice, this list of conditions and the following disclaimer in the 39105059Scognet * documentation and/or other materials provided with the distribution. 40105059Scognet * 3. The name of the author may not be used to endorse or promote products 41105059Scognet * derived from this software without specific prior written permission. 42105059Scognet * 43105059Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 44105059Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 45105059Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 46105059Scognet * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 47105059Scognet * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 48105059Scognet * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49105059Scognet * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50105059Scognet * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51105059Scognet * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 52105059Scognet * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53105059Scognet * 54105059Scognet */ 55105059Scognet 56105059Scognet/* 57105059Scognet * Imported into FreeBSD source repository, and updated to compile under 58105059Scognet * FreeBSD-3.0-DEVELOPMENT, by Stefan Esser <se@FreeBSD.Org>, 1996-12-17 59105059Scognet */ 60105059Scognet 61105059Scognet/* 62105059Scognet * Updated to compile under FreeBSD 5.0-CURRENT by Olivier Houchard 63105059Scognet * <doginou@ci0.org>, 2002-03-04 64105059Scognet */ 65105059Scognet 66105059Scognet#include <sys/param.h> 67105059Scognet 68105059Scognet#include <sys/systm.h> 69105059Scognet#include <sys/malloc.h> 70105059Scognet#include <sys/queue.h> 71105059Scognet#if __FreeBSD_version >= 500000 72105059Scognet#include <sys/bio.h> 73105059Scognet#endif 74105059Scognet#include <sys/buf.h> 75105059Scognet#include <sys/bus.h> 76105059Scognet#include <sys/kernel.h> 77129879Sphk#include <sys/module.h> 78105059Scognet 79105059Scognet#include <vm/vm.h> 80105059Scognet#include <vm/pmap.h> 81105059Scognet 82119287Simp#include <dev/pci/pcivar.h> 83119287Simp#include <dev/pci/pcireg.h> 84105059Scognet#include <machine/resource.h> 85105059Scognet#include <machine/bus.h> 86105059Scognet#include <sys/rman.h> 87105059Scognet 88105059Scognet#include <cam/cam.h> 89105059Scognet#include <cam/cam_ccb.h> 90105059Scognet#include <cam/cam_sim.h> 91105059Scognet#include <cam/cam_xpt_sim.h> 92105059Scognet#include <cam/cam_debug.h> 93105059Scognet 94105059Scognet#include <cam/scsi/scsi_all.h> 95111158Scognet#include <cam/scsi/scsi_message.h> 96105059Scognet 97105059Scognet#include <dev/trm/trm.h> 98105059Scognet 99105059Scognet#define trm_reg_read8(reg) bus_space_read_1(pACB->tag, pACB->bsh, reg) 100105059Scognet#define trm_reg_read16(reg) bus_space_read_2(pACB->tag, pACB->bsh, reg) 101105059Scognet#define trm_reg_read32(reg) bus_space_read_4(pACB->tag, pACB->bsh, reg) 102105059Scognet#define trm_reg_write8(value,reg) bus_space_write_1(pACB->tag, pACB->bsh,\ 103105059Scognet reg, value) 104105059Scognet#define trm_reg_write16(value,reg) bus_space_write_2(pACB->tag, pACB->bsh,\ 105105059Scognet reg, value) 106105059Scognet#define trm_reg_write32(value,reg) bus_space_write_4(pACB->tag, pACB->bsh,\ 107105059Scognet reg, value) 108105059Scognet 109105059Scognet#define PCI_Vendor_ID_TEKRAM 0x1DE1 110105059Scognet#define PCI_Device_ID_TRM_S1040 0x0391 111105059Scognet#define PCI_DEVICEID_TRMS1040 0x03911DE1 112111158Scognet#define PCI_DEVICEID_TRMS2080 0x03921DE1 113105059Scognet 114105059Scognet#ifdef trm_DEBUG1 115105059Scognet#define TRM_DPRINTF(fmt, arg...) printf("trm: " fmt, ##arg) 116105059Scognet#else 117105059Scognet#define TRM_DPRINTF(fmt, arg...) {} 118105059Scognet#endif /* TRM_DEBUG */ 119105059Scognet 120105059Scognetstatic void trm_check_eeprom(PNVRAMTYPE pEEpromBuf,PACB pACB); 121111158Scognetstatic void NVRAM_trm_read_all(PNVRAMTYPE pEEpromBuf,PACB pACB); 122111158Scognetstatic u_int8_t NVRAM_trm_get_data(PACB pACB, u_int8_t bAddr); 123111158Scognetstatic void NVRAM_trm_write_all(PNVRAMTYPE pEEpromBuf,PACB pACB); 124111158Scognetstatic void NVRAM_trm_set_data(PACB pACB, u_int8_t bAddr, u_int8_t bData); 125111158Scognetstatic void NVRAM_trm_write_cmd(PACB pACB, u_int8_t bCmd, u_int8_t bAddr); 126111158Scognetstatic void NVRAM_trm_wait_30us(PACB pACB); 127105059Scognet 128105059Scognetstatic void trm_Interrupt(void *vpACB); 129105059Scognetstatic void trm_DataOutPhase0(PACB pACB, PSRB pSRB, 130111158Scognet u_int16_t * pscsi_status); 131105059Scognetstatic void trm_DataInPhase0(PACB pACB, PSRB pSRB, 132111158Scognet u_int16_t * pscsi_status); 133105059Scognetstatic void trm_CommandPhase0(PACB pACB, PSRB pSRB, 134111158Scognet u_int16_t * pscsi_status); 135105059Scognetstatic void trm_StatusPhase0(PACB pACB, PSRB pSRB, 136111158Scognet u_int16_t * pscsi_status); 137105059Scognetstatic void trm_MsgOutPhase0(PACB pACB, PSRB pSRB, 138111158Scognet u_int16_t * pscsi_status); 139105059Scognetstatic void trm_MsgInPhase0(PACB pACB, PSRB pSRB, 140111158Scognet u_int16_t * pscsi_status); 141105059Scognetstatic void trm_DataOutPhase1(PACB pACB, PSRB pSRB, 142111158Scognet u_int16_t * pscsi_status); 143105059Scognetstatic void trm_DataInPhase1(PACB pACB, PSRB pSRB, 144111158Scognet u_int16_t * pscsi_status); 145105059Scognetstatic void trm_CommandPhase1(PACB pACB, PSRB pSRB, 146111158Scognet u_int16_t * pscsi_status); 147105059Scognetstatic void trm_StatusPhase1(PACB pACB, PSRB pSRB, 148111158Scognet u_int16_t * pscsi_status); 149105059Scognetstatic void trm_MsgOutPhase1(PACB pACB, PSRB pSRB, 150111158Scognet u_int16_t * pscsi_status); 151105059Scognetstatic void trm_MsgInPhase1(PACB pACB, PSRB pSRB, 152111158Scognet u_int16_t * pscsi_status); 153111158Scognetstatic void trm_Nop0(PACB pACB, PSRB pSRB, u_int16_t * pscsi_status); 154111158Scognetstatic void trm_Nop1(PACB pACB, PSRB pSRB, u_int16_t * pscsi_status); 155105059Scognetstatic void trm_SetXferRate(PACB pACB, PSRB pSRB,PDCB pDCB); 156105059Scognetstatic void trm_DataIO_transfer(PACB pACB, PSRB pSRB, u_int16_t ioDir); 157105059Scognetstatic void trm_Disconnect(PACB pACB); 158105059Scognetstatic void trm_Reselect(PACB pACB); 159105059Scognetstatic void trm_SRBdone(PACB pACB, PDCB pDCB, PSRB pSRB); 160105059Scognetstatic void trm_DoingSRB_Done(PACB pACB); 161105059Scognetstatic void trm_ScsiRstDetect(PACB pACB); 162105059Scognetstatic void trm_ResetSCSIBus(PACB pACB); 163105059Scognetstatic void trm_RequestSense(PACB pACB, PDCB pDCB, PSRB pSRB); 164105059Scognetstatic void trm_EnableMsgOutAbort2(PACB pACB, PSRB pSRB); 165105059Scognetstatic void trm_EnableMsgOutAbort1(PACB pACB, PSRB pSRB); 166105059Scognetstatic void trm_SendSRB(PACB pACB, PSRB pSRB); 167105059Scognetstatic int trm_probe(device_t tag); 168105059Scognetstatic int trm_attach(device_t tag); 169105059Scognetstatic void trm_reset(PACB pACB); 170105059Scognet 171105059Scognetstatic u_int16_t trm_StartSCSI(PACB pACB, PDCB pDCB, PSRB pSRB); 172105059Scognet 173111158Scognetstatic int trm_initAdapter(PACB pACB, u_int16_t unit); 174105059Scognetstatic void trm_initDCB(PACB pACB, PDCB pDCB, u_int16_t unit, 175105059Scognet u_int32_t i, u_int32_t j); 176111158Scognetstatic int trm_initSRB(PACB pACB); 177111158Scognetstatic void trm_initACB(PACB pACB, u_int8_t adaptType, u_int16_t unit); 178105059Scognet/* CAM SIM entry points */ 179105059Scognet#define ccb_trmsrb_ptr spriv_ptr0 180105059Scognet#define ccb_trmacb_ptr spriv_ptr1 181105059Scognetstatic void trm_action(struct cam_sim *psim, union ccb *pccb); 182105059Scognetstatic void trm_poll(struct cam_sim *psim); 183105059Scognet 184105059Scognet 185105059Scognetstatic void * trm_SCSI_phase0[] = { 186105059Scognet trm_DataOutPhase0, /* phase:0 */ 187105059Scognet trm_DataInPhase0, /* phase:1 */ 188105059Scognet trm_CommandPhase0, /* phase:2 */ 189105059Scognet trm_StatusPhase0, /* phase:3 */ 190105059Scognet trm_Nop0, /* phase:4 */ 191105059Scognet trm_Nop1, /* phase:5 */ 192105059Scognet trm_MsgOutPhase0, /* phase:6 */ 193105059Scognet trm_MsgInPhase0, /* phase:7 */ 194105059Scognet}; 195105059Scognet 196105059Scognet/* 197105059Scognet * 198105059Scognet * stateV = (void *) trm_SCSI_phase1[phase] 199105059Scognet * 200105059Scognet */ 201105059Scognetstatic void * trm_SCSI_phase1[] = { 202105059Scognet trm_DataOutPhase1, /* phase:0 */ 203105059Scognet trm_DataInPhase1, /* phase:1 */ 204105059Scognet trm_CommandPhase1, /* phase:2 */ 205105059Scognet trm_StatusPhase1, /* phase:3 */ 206105059Scognet trm_Nop0, /* phase:4 */ 207105059Scognet trm_Nop1, /* phase:5 */ 208105059Scognet trm_MsgOutPhase1, /* phase:6 */ 209105059Scognet trm_MsgInPhase1, /* phase:7 */ 210105059Scognet}; 211105059Scognet 212105059Scognet 213111158ScognetNVRAMTYPE trm_eepromBuf[TRM_MAX_ADAPTER_NUM]; 214105059Scognet/* 215105059Scognet *Fast20: 000 50ns, 20.0 Mbytes/s 216105059Scognet * 001 75ns, 13.3 Mbytes/s 217105059Scognet * 010 100ns, 10.0 Mbytes/s 218105059Scognet * 011 125ns, 8.0 Mbytes/s 219105059Scognet * 100 150ns, 6.6 Mbytes/s 220105059Scognet * 101 175ns, 5.7 Mbytes/s 221105059Scognet * 110 200ns, 5.0 Mbytes/s 222105059Scognet * 111 250ns, 4.0 Mbytes/s 223105059Scognet * 224105059Scognet *Fast40: 000 25ns, 40.0 Mbytes/s 225105059Scognet * 001 50ns, 20.0 Mbytes/s 226105059Scognet * 010 75ns, 13.3 Mbytes/s 227105059Scognet * 011 100ns, 10.0 Mbytes/s 228105059Scognet * 100 125ns, 8.0 Mbytes/s 229105059Scognet * 101 150ns, 6.6 Mbytes/s 230105059Scognet * 110 175ns, 5.7 Mbytes/s 231105059Scognet * 111 200ns, 5.0 Mbytes/s 232105059Scognet */ 233105059Scognet /* real period: */ 234111158Scognetu_int8_t dc395x_clock_period[] = { 235105059Scognet 12,/* 48 ns 20 MB/sec */ 236105059Scognet 18,/* 72 ns 13.3 MB/sec */ 237105059Scognet 25,/* 100 ns 10.0 MB/sec */ 238105059Scognet 31,/* 124 ns 8.0 MB/sec */ 239105059Scognet 37,/* 148 ns 6.6 MB/sec */ 240105059Scognet 43,/* 172 ns 5.7 MB/sec */ 241105059Scognet 50,/* 200 ns 5.0 MB/sec */ 242105059Scognet 62 /* 248 ns 4.0 MB/sec */ 243105059Scognet}; 244105059Scognet 245111158Scognetu_int8_t dc395u2x_clock_period[]={ 246111158Scognet 10,/* 25 ns 40.0 MB/sec */ 247111158Scognet 12,/* 48 ns 20.0 MB/sec */ 248111158Scognet 18,/* 72 ns 13.3 MB/sec */ 249111158Scognet 25,/* 100 ns 10.0 MB/sec */ 250111158Scognet 31,/* 124 ns 8.0 MB/sec */ 251111158Scognet 37,/* 148 ns 6.6 MB/sec */ 252111158Scognet 43,/* 172 ns 5.7 MB/sec */ 253111158Scognet 50,/* 200 ns 5.0 MB/sec */ 254105059Scognet}; 255105059Scognet 256111158Scognet#define dc395x_tinfo_period dc395x_clock_period 257111158Scognet#define dc395u2x_tinfo_period dc395u2x_clock_period 258111158Scognet 259105059Scognetstatic PSRB 260105059Scognettrm_GetSRB(PACB pACB) 261105059Scognet{ 262105059Scognet int intflag; 263105059Scognet PSRB pSRB; 264105059Scognet 265105059Scognet intflag = splcam(); 266105059Scognet pSRB = pACB->pFreeSRB; 267105059Scognet if (pSRB) { 268105059Scognet pACB->pFreeSRB = pSRB->pNextSRB; 269105059Scognet pSRB->pNextSRB = NULL; 270105059Scognet } 271105059Scognet splx(intflag); 272105059Scognet return (pSRB); 273105059Scognet} 274105059Scognet 275105059Scognetstatic void 276105059Scognettrm_RewaitSRB0(PDCB pDCB, PSRB pSRB) 277105059Scognet{ 278105059Scognet PSRB psrb1; 279105059Scognet int intflag; 280105059Scognet 281105059Scognet intflag = splcam(); 282105059Scognet if ((psrb1 = pDCB->pWaitingSRB)) { 283105059Scognet pSRB->pNextSRB = psrb1; 284105059Scognet pDCB->pWaitingSRB = pSRB; 285105059Scognet } else { 286105059Scognet pSRB->pNextSRB = NULL; 287105059Scognet pDCB->pWaitingSRB = pSRB; 288111158Scognet pDCB->pWaitingLastSRB = pSRB; 289105059Scognet } 290105059Scognet splx(intflag); 291105059Scognet} 292105059Scognet 293105059Scognetstatic void 294105059Scognettrm_RewaitSRB(PDCB pDCB, PSRB pSRB) 295105059Scognet{ 296105059Scognet PSRB psrb1; 297105059Scognet int intflag; 298105059Scognet 299105059Scognet intflag = splcam(); 300105059Scognet pDCB->GoingSRBCnt--; 301105059Scognet psrb1 = pDCB->pGoingSRB; 302105059Scognet if (pSRB == psrb1) 303111158Scognet /* 304111158Scognet * if this SRB is GoingSRB 305111158Scognet * remove this SRB from GoingSRB Q 306111158Scognet */ 307105059Scognet pDCB->pGoingSRB = psrb1->pNextSRB; 308105059Scognet else { 309111158Scognet /* 310111158Scognet * if this SRB is not current GoingSRB 311111158Scognet * remove this SRB from GoingSRB Q 312111158Scognet */ 313105059Scognet while (pSRB != psrb1->pNextSRB) 314105059Scognet psrb1 = psrb1->pNextSRB; 315105059Scognet psrb1->pNextSRB = pSRB->pNextSRB; 316105059Scognet if (pSRB == pDCB->pGoingLastSRB) 317105059Scognet pDCB->pGoingLastSRB = psrb1; 318105059Scognet } 319105059Scognet if ((psrb1 = pDCB->pWaitingSRB)) { 320111158Scognet /* 321111158Scognet * if WaitingSRB Q is not NULL 322111158Scognet * Q back this SRB into WaitingSRB 323111158Scognet */ 324111158Scognet 325105059Scognet pSRB->pNextSRB = psrb1; 326105059Scognet pDCB->pWaitingSRB = pSRB; 327105059Scognet } else { 328105059Scognet pSRB->pNextSRB = NULL; 329105059Scognet pDCB->pWaitingSRB = pSRB; 330111158Scognet pDCB->pWaitingLastSRB = pSRB; 331105059Scognet } 332105059Scognet splx(intflag); 333105059Scognet} 334105059Scognet 335105059Scognetstatic void 336105059Scognettrm_DoWaitingSRB(PACB pACB) 337105059Scognet{ 338105059Scognet int intflag; 339105059Scognet PDCB ptr, ptr1; 340105059Scognet PSRB pSRB; 341105059Scognet 342105059Scognet intflag = splcam(); 343105059Scognet if (!(pACB->pActiveDCB) && 344105059Scognet !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV))) { 345105059Scognet ptr = pACB->pDCBRunRobin; 346105059Scognet if (!ptr) { 347105059Scognet ptr = pACB->pLinkDCB; 348105059Scognet pACB->pDCBRunRobin = ptr; 349105059Scognet } 350105059Scognet ptr1 = ptr; 351105059Scognet for (;ptr1 ;) { 352105059Scognet pACB->pDCBRunRobin = ptr1->pNextDCB; 353111158Scognet if (!(ptr1->MaxActiveCommandCnt > ptr1->GoingSRBCnt) 354105059Scognet || !(pSRB = ptr1->pWaitingSRB)) { 355105059Scognet if (pACB->pDCBRunRobin == ptr) 356105059Scognet break; 357105059Scognet ptr1 = ptr1->pNextDCB; 358105059Scognet } else { 359105059Scognet if (!trm_StartSCSI(pACB, ptr1, pSRB)) { 360105059Scognet /* 361105059Scognet * If trm_StartSCSI return 0 : 362105059Scognet * current interrupt status is interrupt enable 363105059Scognet * It's said that SCSI processor is unoccupied 364105059Scognet */ 365105059Scognet ptr1->GoingSRBCnt++; 366111158Scognet if (ptr1->pWaitingLastSRB == pSRB) { 367105059Scognet ptr1->pWaitingSRB = NULL; 368111158Scognet ptr1->pWaitingLastSRB = NULL; 369105059Scognet } else 370105059Scognet ptr1->pWaitingSRB = pSRB->pNextSRB; 371105059Scognet pSRB->pNextSRB = NULL; 372105059Scognet if (ptr1->pGoingSRB) 373105059Scognet ptr1->pGoingLastSRB->pNextSRB = pSRB; 374105059Scognet else 375105059Scognet ptr1->pGoingSRB = pSRB; 376105059Scognet ptr1->pGoingLastSRB = pSRB; 377105059Scognet } 378105059Scognet break; 379105059Scognet } 380105059Scognet } 381105059Scognet } 382105059Scognet splx(intflag); 383105059Scognet return; 384105059Scognet} 385105059Scognet 386105059Scognetstatic void 387105059Scognettrm_SRBwaiting(PDCB pDCB, PSRB pSRB) 388105059Scognet{ 389105059Scognet 390105059Scognet if (pDCB->pWaitingSRB) { 391111158Scognet pDCB->pWaitingLastSRB->pNextSRB = pSRB; 392111158Scognet pDCB->pWaitingLastSRB = pSRB; 393105059Scognet pSRB->pNextSRB = NULL; 394105059Scognet } else { 395105059Scognet pDCB->pWaitingSRB = pSRB; 396111158Scognet pDCB->pWaitingLastSRB = pSRB; 397105059Scognet } 398105059Scognet} 399105059Scognet 400111158Scognetstatic u_int32_t 401111158Scognettrm_get_sense_bufaddr(PACB pACB, PSRB pSRB) 402111158Scognet{ 403111158Scognet int offset; 404111158Scognet 405111158Scognet offset = pSRB->TagNumber; 406111158Scognet return (pACB->sense_busaddr + 407111158Scognet (offset * sizeof(struct scsi_sense_data))); 408111158Scognet} 409111158Scognet 410111158Scognetstatic struct scsi_sense_data * 411111158Scognettrm_get_sense_buf(PACB pACB, PSRB pSRB) 412111158Scognet{ 413111158Scognet int offset; 414111158Scognet 415111158Scognet offset = pSRB->TagNumber; 416111158Scognet return (&pACB->sense_buffers[offset]); 417111158Scognet} 418105059Scognetstatic void 419111158Scognettrm_ExecuteSRB(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 420105059Scognet{ 421105059Scognet int flags; 422105059Scognet PACB pACB; 423105059Scognet PSRB pSRB; 424105059Scognet union ccb *ccb; 425105059Scognet u_long totalxferlen=0; 426105059Scognet 427111158Scognet flags = splcam(); 428105059Scognet pSRB = (PSRB)arg; 429105059Scognet ccb = pSRB->pccb; 430105059Scognet pACB = (PACB)ccb->ccb_h.ccb_trmacb_ptr; 431105059Scognet TRM_DPRINTF("trm_ExecuteSRB..........\n"); 432105059Scognet if (nseg != 0) { 433105059Scognet PSEG psg; 434105059Scognet bus_dma_segment_t *end_seg; 435113350Smux int op; 436105059Scognet 437105059Scognet /* Copy the segments into our SG list */ 438105059Scognet end_seg = dm_segs + nseg; 439111158Scognet psg = pSRB->pSRBSGL; 440105059Scognet while (dm_segs < end_seg) { 441111158Scognet psg->address = dm_segs->ds_addr; 442105059Scognet psg->length = (u_long)dm_segs->ds_len; 443105059Scognet totalxferlen += dm_segs->ds_len; 444105059Scognet psg++; 445105059Scognet dm_segs++; 446105059Scognet } 447105059Scognet if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 448105059Scognet op = BUS_DMASYNC_PREREAD; 449105059Scognet } else { 450105059Scognet op = BUS_DMASYNC_PREWRITE; 451105059Scognet } 452105059Scognet bus_dmamap_sync(pACB->buffer_dmat, pSRB->dmamap, op); 453105059Scognet } 454105059Scognet pSRB->RetryCnt = 0; 455111158Scognet pSRB->SRBTotalXferLength = totalxferlen; 456105059Scognet pSRB->SRBSGCount = nseg; 457105059Scognet pSRB->SRBSGIndex = 0; 458105059Scognet pSRB->AdaptStatus = 0; 459105059Scognet pSRB->TargetStatus = 0; 460105059Scognet pSRB->MsgCnt = 0; 461105059Scognet pSRB->SRBStatus = 0; 462105059Scognet pSRB->SRBFlag = 0; 463105059Scognet pSRB->SRBState = 0; 464105059Scognet pSRB->ScsiPhase = PH_BUS_FREE; /* SCSI bus free Phase */ 465105059Scognet 466105059Scognet if (ccb->ccb_h.status != CAM_REQ_INPROG) { 467105059Scognet if (nseg != 0) 468105059Scognet bus_dmamap_unload(pACB->buffer_dmat, pSRB->dmamap); 469105059Scognet pSRB->pNextSRB = pACB->pFreeSRB; 470105059Scognet pACB->pFreeSRB = pSRB; 471105059Scognet xpt_done(ccb); 472105059Scognet splx(flags); 473105059Scognet return; 474105059Scognet } 475105059Scognet ccb->ccb_h.status |= CAM_SIM_QUEUED; 476105059Scognet trm_SendSRB(pACB, pSRB); 477105059Scognet splx(flags); 478105059Scognet return; 479105059Scognet} 480105059Scognet 481105059Scognetstatic void 482105059Scognettrm_SendSRB(PACB pACB, PSRB pSRB) 483105059Scognet{ 484105059Scognet PDCB pDCB; 485105059Scognet 486105059Scognet pDCB = pSRB->pSRBDCB; 487111158Scognet if (!(pDCB->MaxActiveCommandCnt > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) 488105059Scognet || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV))) { 489111158Scognet TRM_DPRINTF("pDCB->MaxCommand=%d \n",pDCB->MaxActiveCommandCnt); 490105059Scognet TRM_DPRINTF("pDCB->GoingSRBCnt=%d \n",pDCB->GoingSRBCnt); 491105059Scognet TRM_DPRINTF("pACB->pActiveDCB=%8x \n",(u_int)pACB->pActiveDCB); 492105059Scognet TRM_DPRINTF("pACB->ACBFlag=%x \n",pACB->ACBFlag); 493105059Scognet trm_SRBwaiting(pDCB, pSRB); 494105059Scognet goto SND_EXIT; 495105059Scognet } 496105059Scognet 497105059Scognet if (pDCB->pWaitingSRB) { 498105059Scognet trm_SRBwaiting(pDCB, pSRB); 499105059Scognet pSRB = pDCB->pWaitingSRB; 500105059Scognet pDCB->pWaitingSRB = pSRB->pNextSRB; 501105059Scognet pSRB->pNextSRB = NULL; 502105059Scognet } 503105059Scognet 504105059Scognet if (!trm_StartSCSI(pACB, pDCB, pSRB)) { 505105059Scognet /* 506105059Scognet * If trm_StartSCSI return 0 : 507105059Scognet * current interrupt status is interrupt enable 508105059Scognet * It's said that SCSI processor is unoccupied 509105059Scognet */ 510105059Scognet pDCB->GoingSRBCnt++; /* stack waiting SRB*/ 511105059Scognet if (pDCB->pGoingSRB) { 512105059Scognet pDCB->pGoingLastSRB->pNextSRB = pSRB; 513105059Scognet pDCB->pGoingLastSRB = pSRB; 514105059Scognet } else { 515105059Scognet pDCB->pGoingSRB = pSRB; 516105059Scognet pDCB->pGoingLastSRB = pSRB; 517105059Scognet } 518105059Scognet } else { 519105059Scognet /* 520105059Scognet * If trm_StartSCSI return 1 : 521105059Scognet * current interrupt status is interrupt disreenable 522105059Scognet * It's said that SCSI processor has more one SRB need to do 523105059Scognet */ 524105059Scognet trm_RewaitSRB0(pDCB, pSRB); 525105059Scognet } 526105059ScognetSND_EXIT: 527105059Scognet return; 528105059Scognet} 529105059Scognet 530105059Scognet 531105059Scognetstatic void 532105059Scognettrm_action(struct cam_sim *psim, union ccb *pccb) 533105059Scognet{ 534105059Scognet PACB pACB; 535111158Scognet int actionflags; 536105059Scognet u_int target_id,target_lun; 537105059Scognet 538105059Scognet CAM_DEBUG(pccb->ccb_h.path, CAM_DEBUG_TRACE, ("trm_action\n")); 539105059Scognet 540111158Scognet actionflags = splcam(); 541105059Scognet pACB = (PACB) cam_sim_softc(psim); 542105059Scognet target_id = pccb->ccb_h.target_id; 543105059Scognet target_lun = pccb->ccb_h.target_lun; 544105059Scognet 545105059Scognet switch (pccb->ccb_h.func_code) { 546105059Scognet case XPT_NOOP: 547105059Scognet TRM_DPRINTF(" XPT_NOOP \n"); 548105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 549105059Scognet xpt_done(pccb); 550105059Scognet break; 551105059Scognet /* 552105059Scognet * Execute the requested I/O operation 553105059Scognet */ 554105059Scognet case XPT_SCSI_IO: { 555105059Scognet PDCB pDCB = NULL; 556105059Scognet PSRB pSRB; 557105059Scognet struct ccb_scsiio *pcsio; 558246713Skib int error; 559105059Scognet 560105059Scognet pcsio = &pccb->csio; 561105059Scognet TRM_DPRINTF(" XPT_SCSI_IO \n"); 562105059Scognet TRM_DPRINTF("trm: target_id= %d target_lun= %d \n" 563105059Scognet ,target_id, target_lun); 564105059Scognet TRM_DPRINTF( 565105059Scognet "pACB->scan_devices[target_id][target_lun]= %d \n" 566105059Scognet ,pACB->scan_devices[target_id][target_lun]); 567116813Scognet if ((pccb->ccb_h.status & CAM_STATUS_MASK) != 568116813Scognet CAM_REQ_INPROG) { 569111158Scognet xpt_done(pccb); 570111158Scognet splx(actionflags); 571111158Scognet return; 572111158Scognet } 573111158Scognet pDCB = &pACB->DCBarray[target_id][target_lun]; 574116813Scognet if (!(pDCB->DCBstatus & DS_IN_QUEUE)) { 575111158Scognet pACB->scan_devices[target_id][target_lun] = 1; 576111158Scognet trm_initDCB(pACB, pDCB, pACB->AdapterUnit, 577111158Scognet target_id, target_lun); 578111158Scognet } 579105059Scognet /* 580105059Scognet * Assign an SRB and connect it with this ccb. 581105059Scognet */ 582105059Scognet pSRB = trm_GetSRB(pACB); 583105059Scognet if (!pSRB) { 584105059Scognet /* Freeze SIMQ */ 585105059Scognet pccb->ccb_h.status = CAM_RESRC_UNAVAIL; 586105059Scognet xpt_done(pccb); 587111158Scognet splx(actionflags); 588105059Scognet return; 589105059Scognet } 590105059Scognet pSRB->pSRBDCB = pDCB; 591105059Scognet pccb->ccb_h.ccb_trmsrb_ptr = pSRB; 592105059Scognet pccb->ccb_h.ccb_trmacb_ptr = pACB; 593105059Scognet pSRB->pccb = pccb; 594105059Scognet pSRB->ScsiCmdLen = pcsio->cdb_len; 595105059Scognet /* 596105059Scognet * move layer of CAM command block to layer of SCSI 597105059Scognet * Request Block for SCSI processor command doing 598105059Scognet */ 599116813Scognet if ((pccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { 600116813Scognet if ((pccb->ccb_h.flags & CAM_CDB_PHYS) == 0) { 601111158Scognet bcopy(pcsio->cdb_io.cdb_ptr,pSRB->CmdBlock 602111158Scognet ,pcsio->cdb_len); 603111158Scognet } else { 604111158Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 605111158Scognet pSRB->pNextSRB = pACB->pFreeSRB; 606111158Scognet pACB->pFreeSRB= pSRB; 607111158Scognet xpt_done(pccb); 608111158Scognet splx(actionflags); 609111158Scognet return; 610111158Scognet } 611111158Scognet } else 612111158Scognet bcopy(pcsio->cdb_io.cdb_bytes, 613111158Scognet pSRB->CmdBlock, pcsio->cdb_len); 614246713Skib error = bus_dmamap_load_ccb(pACB->buffer_dmat, 615105059Scognet pSRB->dmamap, 616246713Skib pccb, 617105059Scognet trm_ExecuteSRB, 618105059Scognet pSRB, 619105059Scognet 0); 620246713Skib if (error == EINPROGRESS) { 621246713Skib xpt_freeze_simq(pACB->psim, 1); 622246713Skib pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 623246713Skib } 624105059Scognet break; 625246713Skib } 626105059Scognet case XPT_GDEV_TYPE: 627105059Scognet TRM_DPRINTF(" XPT_GDEV_TYPE \n"); 628105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 629105059Scognet xpt_done(pccb); 630105059Scognet break; 631105059Scognet case XPT_GDEVLIST: 632105059Scognet TRM_DPRINTF(" XPT_GDEVLIST \n"); 633105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 634105059Scognet xpt_done(pccb); 635105059Scognet break; 636105059Scognet /* 637105059Scognet * Path routing inquiry 638105059Scognet * Path Inquiry CCB 639105059Scognet */ 640105059Scognet case XPT_PATH_INQ: { 641105059Scognet struct ccb_pathinq *cpi = &pccb->cpi; 642105059Scognet 643105059Scognet TRM_DPRINTF(" XPT_PATH_INQ \n"); 644105059Scognet cpi->version_num = 1; 645105059Scognet cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; 646105059Scognet cpi->target_sprt = 0; 647105059Scognet cpi->hba_misc = 0; 648105059Scognet cpi->hba_eng_cnt = 0; 649105059Scognet cpi->max_target = 15 ; 650105059Scognet cpi->max_lun = pACB->max_lun; /* 7 or 0 */ 651105059Scognet cpi->initiator_id = pACB->AdaptSCSIID; 652105059Scognet cpi->bus_id = cam_sim_bus(psim); 653111158Scognet cpi->base_transfer_speed = 3300; 654315813Smav strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 655315813Smav strlcpy(cpi->hba_vid, "Tekram_TRM", HBA_IDLEN); 656315813Smav strlcpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 657105059Scognet cpi->unit_number = cam_sim_unit(psim); 658163816Smjacob cpi->transport = XPORT_SPI; 659163816Smjacob cpi->transport_version = 2; 660163816Smjacob cpi->protocol = PROTO_SCSI; 661163816Smjacob cpi->protocol_version = SCSI_REV_2; 662105059Scognet cpi->ccb_h.status = CAM_REQ_CMP; 663105059Scognet xpt_done(pccb); 664105059Scognet } 665105059Scognet break; 666105059Scognet /* 667105059Scognet * Release a frozen SIM queue 668105059Scognet * Release SIM Queue 669105059Scognet */ 670105059Scognet case XPT_REL_SIMQ: 671105059Scognet TRM_DPRINTF(" XPT_REL_SIMQ \n"); 672105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 673105059Scognet xpt_done(pccb); 674105059Scognet break; 675105059Scognet /* 676105059Scognet * Set Asynchronous Callback Parameters 677105059Scognet * Set Asynchronous Callback CCB 678105059Scognet */ 679105059Scognet case XPT_SASYNC_CB: 680105059Scognet TRM_DPRINTF(" XPT_SASYNC_CB \n"); 681105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 682105059Scognet xpt_done(pccb); 683105059Scognet break; 684105059Scognet /* 685105059Scognet * Set device type information 686105059Scognet * Set Device Type CCB 687105059Scognet */ 688105059Scognet case XPT_SDEV_TYPE: 689105059Scognet TRM_DPRINTF(" XPT_SDEV_TYPE \n"); 690105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 691105059Scognet xpt_done(pccb); 692105059Scognet break; 693105059Scognet /* 694105059Scognet * Get EDT entries matching the given pattern 695105059Scognet */ 696105059Scognet case XPT_DEV_MATCH: 697105059Scognet TRM_DPRINTF(" XPT_DEV_MATCH \n"); 698105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 699105059Scognet xpt_done(pccb); 700105059Scognet break; 701105059Scognet /* 702105059Scognet * Turn on debugging for a bus, target or lun 703105059Scognet */ 704105059Scognet case XPT_DEBUG: 705105059Scognet TRM_DPRINTF(" XPT_DEBUG \n"); 706105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 707105059Scognet xpt_done(pccb); 708105059Scognet break; 709105059Scognet /* 710105059Scognet * XPT_ABORT = 0x10, Abort the specified CCB 711105059Scognet * Abort XPT request CCB 712105059Scognet */ 713105059Scognet case XPT_ABORT: 714105059Scognet TRM_DPRINTF(" XPT_ABORT \n"); 715105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 716105059Scognet xpt_done(pccb); 717105059Scognet break; 718105059Scognet /* 719105059Scognet * Reset the specified SCSI bus 720105059Scognet * Reset SCSI Bus CCB 721105059Scognet */ 722105059Scognet case XPT_RESET_BUS: { 723105059Scognet int i; 724105059Scognet 725105059Scognet TRM_DPRINTF(" XPT_RESET_BUS \n"); 726105059Scognet trm_reset(pACB); 727105059Scognet pACB->ACBFlag=0; 728105059Scognet for (i=0; i<500; i++) 729105059Scognet DELAY(1000); 730105059Scognet pccb->ccb_h.status = CAM_REQ_CMP; 731105059Scognet xpt_done(pccb); 732105059Scognet } 733105059Scognet break; 734105059Scognet /* 735105059Scognet * Bus Device Reset the specified SCSI device 736105059Scognet * Reset SCSI Device CCB 737105059Scognet */ 738105059Scognet case XPT_RESET_DEV: 739105059Scognet /* 740105059Scognet * Don't (yet?) support vendor 741105059Scognet * specific commands. 742105059Scognet */ 743105059Scognet TRM_DPRINTF(" XPT_RESET_DEV \n"); 744105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 745105059Scognet xpt_done(pccb); 746105059Scognet break; 747105059Scognet /* 748105059Scognet * Terminate the I/O process 749105059Scognet * Terminate I/O Process Request CCB 750105059Scognet */ 751105059Scognet case XPT_TERM_IO: 752105059Scognet TRM_DPRINTF(" XPT_TERM_IO \n"); 753105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 754105059Scognet xpt_done(pccb); 755105059Scognet break; 756105059Scognet /* 757105059Scognet * Get/Set transfer rate/width/disconnection/tag queueing 758105059Scognet * settings 759105059Scognet * (GET) default/user transfer settings for the target 760105059Scognet */ 761105059Scognet case XPT_GET_TRAN_SETTINGS: { 762163816Smjacob struct ccb_trans_settings *cts = &pccb->cts; 763105059Scognet int intflag; 764105059Scognet struct trm_transinfo *tinfo; 765105059Scognet PDCB pDCB; 766163816Smjacob struct ccb_trans_settings_scsi *scsi = 767163816Smjacob &cts->proto_specific.scsi; 768163816Smjacob struct ccb_trans_settings_spi *spi = 769163816Smjacob &cts->xport_specific.spi; 770163816Smjacob 771163816Smjacob cts->protocol = PROTO_SCSI; 772163816Smjacob cts->protocol_version = SCSI_REV_2; 773163816Smjacob cts->transport = XPORT_SPI; 774163816Smjacob cts->transport_version = 2; 775163816Smjacob 776105059Scognet TRM_DPRINTF(" XPT_GET_TRAN_SETTINGS \n"); 777111158Scognet pDCB = &pACB->DCBarray[target_id][target_lun]; 778105059Scognet intflag = splcam(); 779105059Scognet /* 780105059Scognet * disable interrupt 781105059Scognet */ 782163816Smjacob if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { 783163816Smjacob /* current transfer settings */ 784163816Smjacob if (pDCB->tinfo.disc_tag & TRM_CUR_DISCENB) 785163816Smjacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 786163816Smjacob else 787163816Smjacob spi->flags = 0;/* no tag & disconnect */ 788163816Smjacob if (pDCB->tinfo.disc_tag & TRM_CUR_TAGENB) 789163816Smjacob scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 790163816Smjacob tinfo = &pDCB->tinfo.current; 791163816Smjacob TRM_DPRINTF("CURRENT: cts->flags= %2x \n", 792163816Smjacob cts->flags); 793163816Smjacob } else { 794163816Smjacob /* default(user) transfer settings */ 795163816Smjacob if (pDCB->tinfo.disc_tag & TRM_USR_DISCENB) 796163816Smjacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 797163816Smjacob else 798163816Smjacob spi->flags = 0; 799163816Smjacob if (pDCB->tinfo.disc_tag & TRM_USR_TAGENB) 800163816Smjacob scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 801163816Smjacob tinfo = &pDCB->tinfo.user; 802163816Smjacob TRM_DPRINTF("USER: cts->flags= %2x \n", 803163816Smjacob cts->flags); 804163816Smjacob } 805163816Smjacob spi->sync_period = tinfo->period; 806163816Smjacob spi->sync_offset = tinfo->offset; 807163816Smjacob spi->bus_width = tinfo->width; 808163816Smjacob TRM_DPRINTF("pDCB->SyncPeriod: %d \n", 809163816Smjacob pDCB->SyncPeriod); 810163816Smjacob TRM_DPRINTF("period: %d \n", tinfo->period); 811163816Smjacob TRM_DPRINTF("offset: %d \n", tinfo->offset); 812163816Smjacob TRM_DPRINTF("width: %d \n", tinfo->width); 813163816Smjacob 814163816Smjacob splx(intflag); 815163816Smjacob spi->valid = CTS_SPI_VALID_SYNC_RATE | 816163816Smjacob CTS_SPI_VALID_SYNC_OFFSET | 817163816Smjacob CTS_SPI_VALID_BUS_WIDTH | 818163816Smjacob CTS_SPI_VALID_DISC; 819163816Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 820105059Scognet pccb->ccb_h.status = CAM_REQ_CMP; 821105059Scognet xpt_done(pccb); 822105059Scognet } 823105059Scognet break; 824105059Scognet /* 825105059Scognet * Get/Set transfer rate/width/disconnection/tag queueing 826105059Scognet * settings 827105059Scognet * (Set) transfer rate/width negotiation settings 828105059Scognet */ 829105059Scognet case XPT_SET_TRAN_SETTINGS: { 830163816Smjacob struct ccb_trans_settings *cts = &pccb->cts; 831105059Scognet u_int update_type; 832105059Scognet int intflag; 833105059Scognet PDCB pDCB; 834163816Smjacob struct ccb_trans_settings_scsi *scsi = 835163816Smjacob &cts->proto_specific.scsi; 836163816Smjacob struct ccb_trans_settings_spi *spi = 837163816Smjacob &cts->xport_specific.spi; 838105059Scognet 839105059Scognet TRM_DPRINTF(" XPT_SET_TRAN_SETTINGS \n"); 840105059Scognet update_type = 0; 841163816Smjacob if (cts->type == CTS_TYPE_CURRENT_SETTINGS) 842163816Smjacob update_type |= TRM_TRANS_GOAL; 843163816Smjacob if (cts->type == CTS_TYPE_USER_SETTINGS) 844163816Smjacob update_type |= TRM_TRANS_USER; 845163816Smjacob intflag = splcam(); 846163816Smjacob pDCB = &pACB->DCBarray[target_id][target_lun]; 847163816Smjacob 848163816Smjacob if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { 849163816Smjacob /*ccb disc enables */ 850163816Smjacob if (update_type & TRM_TRANS_GOAL) { 851163816Smjacob if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) 852163816Smjacob != 0) 853163816Smjacob pDCB->tinfo.disc_tag 854163816Smjacob |= TRM_CUR_DISCENB; 855163816Smjacob else 856163816Smjacob pDCB->tinfo.disc_tag &= 857163816Smjacob ~TRM_CUR_DISCENB; 858163816Smjacob } 859163816Smjacob if (update_type & TRM_TRANS_USER) { 860163816Smjacob if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) 861163816Smjacob != 0) 862163816Smjacob pDCB->tinfo.disc_tag 863163816Smjacob |= TRM_USR_DISCENB; 864163816Smjacob else 865163816Smjacob pDCB->tinfo.disc_tag &= 866163816Smjacob ~TRM_USR_DISCENB; 867163816Smjacob } 868163816Smjacob } 869163816Smjacob if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 870163816Smjacob /* if ccb tag q active */ 871163816Smjacob if (update_type & TRM_TRANS_GOAL) { 872163816Smjacob if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) 873163816Smjacob != 0) 874163816Smjacob pDCB->tinfo.disc_tag |= 875163816Smjacob TRM_CUR_TAGENB; 876163816Smjacob else 877163816Smjacob pDCB->tinfo.disc_tag &= 878163816Smjacob ~TRM_CUR_TAGENB; 879163816Smjacob } 880163816Smjacob if (update_type & TRM_TRANS_USER) { 881163816Smjacob if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) 882163816Smjacob != 0) 883163816Smjacob pDCB->tinfo.disc_tag |= 884163816Smjacob TRM_USR_TAGENB; 885163816Smjacob else 886163816Smjacob pDCB->tinfo.disc_tag &= 887163816Smjacob ~TRM_USR_TAGENB; 888163816Smjacob } 889163816Smjacob } 890163816Smjacob /* Minimum sync period factor */ 891163816Smjacob 892163816Smjacob if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) { 893163816Smjacob /* if ccb sync active */ 894163816Smjacob /* TRM-S1040 MinSyncPeriod = 4 clocks/byte */ 895163816Smjacob if ((spi->sync_period != 0) && 896163816Smjacob (spi->sync_period < 125)) 897163816Smjacob spi->sync_period = 125; 898163816Smjacob /* 1/(125*4) minsync 2 MByte/sec */ 899163816Smjacob if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) 900163816Smjacob != 0) { 901163816Smjacob if (spi->sync_offset == 0) 902163816Smjacob spi->sync_period = 0; 903163816Smjacob /* TRM-S1040 MaxSyncOffset = 15 bytes*/ 904163816Smjacob if (spi->sync_offset > 15) 905163816Smjacob spi->sync_offset = 15; 906163816Smjacob } 907163816Smjacob } 908163816Smjacob if ((update_type & TRM_TRANS_USER) != 0) { 909163816Smjacob pDCB->tinfo.user.period = spi->sync_period; 910163816Smjacob pDCB->tinfo.user.offset = spi->sync_offset; 911163816Smjacob pDCB->tinfo.user.width = spi->bus_width; 912163816Smjacob } 913163816Smjacob if ((update_type & TRM_TRANS_GOAL) != 0) { 914163816Smjacob pDCB->tinfo.goal.period = spi->sync_period; 915163816Smjacob pDCB->tinfo.goal.offset = spi->sync_offset; 916163816Smjacob pDCB->tinfo.goal.width = spi->bus_width; 917163816Smjacob } 918163816Smjacob splx(intflag); 919105059Scognet pccb->ccb_h.status = CAM_REQ_CMP; 920105059Scognet xpt_done(pccb); 921105059Scognet break; 922105059Scognet } 923105059Scognet /* 924105059Scognet * Calculate the geometry parameters for a device give 925105059Scognet * the sector size and volume size. 926105059Scognet */ 927116351Snjl case XPT_CALC_GEOMETRY: 928105059Scognet TRM_DPRINTF(" XPT_CALC_GEOMETRY \n"); 929116351Snjl cam_calc_geometry(&pccb->ccg, /*extended*/1); 930105059Scognet xpt_done(pccb); 931105059Scognet break; 932105059Scognet case XPT_ENG_INQ: 933105059Scognet TRM_DPRINTF(" XPT_ENG_INQ \n"); 934105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 935105059Scognet xpt_done(pccb); 936105059Scognet break; 937105059Scognet /* 938105059Scognet * HBA execute engine request 939105059Scognet * This structure must match SCSIIO size 940105059Scognet */ 941105059Scognet case XPT_ENG_EXEC: 942105059Scognet TRM_DPRINTF(" XPT_ENG_EXEC \n"); 943105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 944105059Scognet xpt_done(pccb); 945105059Scognet break; 946105059Scognet /* 947105059Scognet * XPT_EN_LUN = 0x30, Enable LUN as a target 948105059Scognet * Target mode structures. 949105059Scognet */ 950105059Scognet case XPT_EN_LUN: 951105059Scognet /* 952105059Scognet * Don't (yet?) support vendor 953105059Scognet * specific commands. 954105059Scognet */ 955105059Scognet TRM_DPRINTF(" XPT_EN_LUN \n"); 956105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 957105059Scognet xpt_done(pccb); 958105059Scognet break; 959105059Scognet /* 960105059Scognet * Execute target I/O request 961105059Scognet */ 962105059Scognet case XPT_TARGET_IO: 963105059Scognet /* 964105059Scognet * Don't (yet?) support vendor 965105059Scognet * specific commands. 966105059Scognet */ 967105059Scognet TRM_DPRINTF(" XPT_TARGET_IO \n"); 968105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 969105059Scognet xpt_done(pccb); 970105059Scognet break; 971105059Scognet /* 972105059Scognet * Accept Host Target Mode CDB 973105059Scognet */ 974105059Scognet case XPT_ACCEPT_TARGET_IO: 975105059Scognet /* 976105059Scognet * Don't (yet?) support vendor 977105059Scognet * specific commands. 978105059Scognet */ 979105059Scognet TRM_DPRINTF(" XPT_ACCEPT_TARGET_IO \n"); 980105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 981105059Scognet xpt_done(pccb); 982105059Scognet break; 983105059Scognet /* 984105059Scognet * Continue Host Target I/O Connection 985105059Scognet */ 986105059Scognet case XPT_CONT_TARGET_IO: 987105059Scognet /* 988105059Scognet * Don't (yet?) support vendor 989105059Scognet * specific commands. 990105059Scognet */ 991105059Scognet TRM_DPRINTF(" XPT_CONT_TARGET_IO \n"); 992105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 993105059Scognet xpt_done(pccb); 994105059Scognet break; 995105059Scognet /* 996105059Scognet * Notify Host Target driver of event 997105059Scognet */ 998105059Scognet case XPT_IMMED_NOTIFY: 999105059Scognet TRM_DPRINTF(" XPT_IMMED_NOTIFY \n"); 1000105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 1001105059Scognet xpt_done(pccb); 1002105059Scognet break; 1003105059Scognet /* 1004105059Scognet * Acknowledgement of event 1005105059Scognet */ 1006105059Scognet case XPT_NOTIFY_ACK: 1007105059Scognet TRM_DPRINTF(" XPT_NOTIFY_ACK \n"); 1008105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 1009105059Scognet xpt_done(pccb); 1010105059Scognet break; 1011105059Scognet /* 1012105059Scognet * XPT_VUNIQUE = 0x80 1013105059Scognet */ 1014105059Scognet case XPT_VUNIQUE: 1015105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 1016105059Scognet xpt_done(pccb); 1017105059Scognet break; 1018105059Scognet default: 1019105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 1020105059Scognet xpt_done(pccb); 1021105059Scognet break; 1022105059Scognet } 1023111158Scognet splx(actionflags); 1024105059Scognet} 1025105059Scognet 1026105059Scognetstatic void 1027105059Scognettrm_poll(struct cam_sim *psim) 1028105059Scognet{ 1029128090Scognet trm_Interrupt(cam_sim_softc(psim)); 1030105059Scognet} 1031105059Scognet 1032105059Scognetstatic void 1033105059Scognettrm_ResetDevParam(PACB pACB) 1034105059Scognet{ 1035105059Scognet PDCB pDCB, pdcb; 1036105059Scognet PNVRAMTYPE pEEpromBuf; 1037105059Scognet u_int8_t PeriodIndex; 1038105059Scognet 1039105059Scognet pDCB = pACB->pLinkDCB; 1040105059Scognet if (pDCB == NULL) 1041105059Scognet return; 1042105059Scognet pdcb = pDCB; 1043105059Scognet do { 1044105059Scognet pDCB->SyncMode &= ~(SYNC_NEGO_DONE+ WIDE_NEGO_DONE); 1045105059Scognet pDCB->SyncPeriod = 0; 1046105059Scognet pDCB->SyncOffset = 0; 1047105059Scognet pEEpromBuf = &trm_eepromBuf[pACB->AdapterUnit]; 1048105059Scognet pDCB->DevMode = 1049105059Scognet pEEpromBuf->NvramTarget[pDCB->TargetID].NvmTarCfg0; 1050105059Scognet pDCB->AdpMode = pEEpromBuf->NvramChannelCfg; 1051105059Scognet PeriodIndex = 1052105059Scognet pEEpromBuf->NvramTarget[pDCB->TargetID].NvmTarPeriod & 0x07; 1053111158Scognet if (pACB->AdaptType == 1) /* is U2? */ 1054111158Scognet pDCB->MaxNegoPeriod = dc395u2x_clock_period[PeriodIndex]; 1055111158Scognet else 1056111158Scognet pDCB->MaxNegoPeriod = dc395x_clock_period[PeriodIndex]; 1057105059Scognet if ((pDCB->DevMode & NTC_DO_WIDE_NEGO) && 1058105059Scognet (pACB->Config & HCC_WIDE_CARD)) 1059105059Scognet pDCB->SyncMode |= WIDE_NEGO_ENABLE; 1060105059Scognet pDCB = pDCB->pNextDCB; 1061105059Scognet } 1062105059Scognet while (pdcb != pDCB); 1063105059Scognet} 1064105059Scognet 1065105059Scognetstatic void 1066105059Scognettrm_RecoverSRB(PACB pACB) 1067105059Scognet{ 1068105059Scognet PDCB pDCB, pdcb; 1069105059Scognet PSRB psrb, psrb2; 1070105059Scognet u_int16_t cnt, i; 1071105059Scognet 1072105059Scognet pDCB = pACB->pLinkDCB; 1073105059Scognet if (pDCB == NULL) 1074105059Scognet return; 1075105059Scognet pdcb = pDCB; 1076105059Scognet do { 1077105059Scognet cnt = pdcb->GoingSRBCnt; 1078105059Scognet psrb = pdcb->pGoingSRB; 1079105059Scognet for (i = 0; i < cnt; i++) { 1080105059Scognet psrb2 = psrb; 1081105059Scognet psrb = psrb->pNextSRB; 1082105059Scognet if (pdcb->pWaitingSRB) { 1083105059Scognet psrb2->pNextSRB = pdcb->pWaitingSRB; 1084105059Scognet pdcb->pWaitingSRB = psrb2; 1085105059Scognet } else { 1086105059Scognet pdcb->pWaitingSRB = psrb2; 1087111158Scognet pdcb->pWaitingLastSRB = psrb2; 1088105059Scognet psrb2->pNextSRB = NULL; 1089105059Scognet } 1090105059Scognet } 1091105059Scognet pdcb->GoingSRBCnt = 0; 1092105059Scognet pdcb->pGoingSRB = NULL; 1093105059Scognet pdcb = pdcb->pNextDCB; 1094105059Scognet } 1095105059Scognet while (pdcb != pDCB); 1096105059Scognet} 1097105059Scognet 1098105059Scognetstatic void 1099105059Scognettrm_reset(PACB pACB) 1100105059Scognet{ 1101105059Scognet int intflag; 1102105059Scognet u_int16_t i; 1103105059Scognet 1104105059Scognet TRM_DPRINTF("trm: RESET"); 1105105059Scognet intflag = splcam(); 1106105059Scognet trm_reg_write8(0x00, TRMREG_DMA_INTEN); 1107105059Scognet trm_reg_write8(0x00, TRMREG_SCSI_INTEN); 1108105059Scognet 1109105059Scognet trm_ResetSCSIBus(pACB); 1110105059Scognet for (i = 0; i < 500; i++) 1111105059Scognet DELAY(1000); 1112105059Scognet trm_reg_write8(0x7F, TRMREG_SCSI_INTEN); 1113105059Scognet /* Enable DMA interrupt */ 1114105059Scognet trm_reg_write8(EN_SCSIINTR, TRMREG_DMA_INTEN); 1115105059Scognet /* Clear DMA FIFO */ 1116105059Scognet trm_reg_write8(CLRXFIFO, TRMREG_DMA_CONTROL); 1117105059Scognet /* Clear SCSI FIFO */ 1118105059Scognet trm_reg_write16(DO_CLRFIFO,TRMREG_SCSI_CONTROL); 1119105059Scognet trm_ResetDevParam(pACB); 1120105059Scognet trm_DoingSRB_Done(pACB); 1121105059Scognet pACB->pActiveDCB = NULL; 1122105059Scognet pACB->ACBFlag = 0;/* RESET_DETECT, RESET_DONE ,RESET_DEV */ 1123105059Scognet trm_DoWaitingSRB(pACB); 1124105059Scognet /* Tell the XPT layer that a bus reset occured */ 1125105059Scognet if (pACB->ppath != NULL) 1126105059Scognet xpt_async(AC_BUS_RESET, pACB->ppath, NULL); 1127105059Scognet splx(intflag); 1128105059Scognet return; 1129105059Scognet} 1130105059Scognet 1131105059Scognetstatic u_int16_t 1132105059Scognettrm_StartSCSI(PACB pACB, PDCB pDCB, PSRB pSRB) 1133105059Scognet{ 1134105059Scognet u_int16_t return_code; 1135111158Scognet u_int8_t scsicommand, i,command,identify_message; 1136105059Scognet u_int8_t * ptr; 1137105059Scognet union ccb *pccb; 1138105059Scognet struct ccb_scsiio *pcsio; 1139105059Scognet 1140105059Scognet pccb = pSRB->pccb; 1141105059Scognet pcsio = &pccb->csio; 1142105059Scognet 1143105059Scognet trm_reg_write8(pACB->AdaptSCSIID, TRMREG_SCSI_HOSTID); 1144105059Scognet trm_reg_write8(pDCB->TargetID, TRMREG_SCSI_TARGETID); 1145105059Scognet trm_reg_write8(pDCB->SyncPeriod, TRMREG_SCSI_SYNC); 1146105059Scognet trm_reg_write8(pDCB->SyncOffset, TRMREG_SCSI_OFFSET); 1147105059Scognet pSRB->ScsiPhase = PH_BUS_FREE;/* initial phase */ 1148105059Scognet /* Flush FIFO */ 1149105059Scognet trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL); 1150105059Scognet 1151105059Scognet identify_message = pDCB->IdentifyMsg; 1152105059Scognet 1153105059Scognet if ((pSRB->CmdBlock[0] == INQUIRY) || 1154105059Scognet (pSRB->CmdBlock[0] == REQUEST_SENSE) || 1155105059Scognet (pSRB->SRBFlag & AUTO_REQSENSE)) { 1156105059Scognet if (((pDCB->SyncMode & WIDE_NEGO_ENABLE) && 1157111158Scognet !(pDCB->SyncMode & WIDE_NEGO_DONE)) 1158105059Scognet || ((pDCB->SyncMode & SYNC_NEGO_ENABLE) && 1159105059Scognet !(pDCB->SyncMode & SYNC_NEGO_DONE))) { 1160105059Scognet if (!(pDCB->IdentifyMsg & 7) || 1161105059Scognet (pSRB->CmdBlock[0] != INQUIRY)) { 1162105059Scognet scsicommand = SCMD_SEL_ATNSTOP; 1163105059Scognet pSRB->SRBState = SRB_MSGOUT; 1164105059Scognet goto polling; 1165105059Scognet } 1166105059Scognet } 1167105059Scognet /* 1168105059Scognet * Send identify message 1169105059Scognet */ 1170105059Scognet trm_reg_write8((identify_message & 0xBF) ,TRMREG_SCSI_FIFO); 1171105059Scognet scsicommand = SCMD_SEL_ATN; 1172105059Scognet pSRB->SRBState = SRB_START_; 1173105059Scognet } else { 1174105059Scognet /* not inquiry,request sense,auto request sense */ 1175105059Scognet /* 1176105059Scognet * Send identify message 1177105059Scognet */ 1178105059Scognet trm_reg_write8(identify_message,TRMREG_SCSI_FIFO); 1179105059Scognet scsicommand = SCMD_SEL_ATN; 1180105059Scognet pSRB->SRBState = SRB_START_; 1181105059Scognet if (pDCB->SyncMode & EN_TAG_QUEUING) { 1182105059Scognet /* Send Tag message */ 1183111158Scognet trm_reg_write8(MSG_SIMPLE_QTAG, TRMREG_SCSI_FIFO); 1184111158Scognet trm_reg_write8(pSRB->TagNumber, TRMREG_SCSI_FIFO); 1185105059Scognet scsicommand = SCMD_SEL_ATN3; 1186105059Scognet } 1187105059Scognet } 1188105059Scognetpolling: 1189105059Scognet /* 1190105059Scognet * Send CDB ..command block ......... 1191105059Scognet */ 1192105059Scognet if (pSRB->SRBFlag & AUTO_REQSENSE) { 1193105059Scognet trm_reg_write8(REQUEST_SENSE, TRMREG_SCSI_FIFO); 1194105059Scognet trm_reg_write8((pDCB->IdentifyMsg << 5), TRMREG_SCSI_FIFO); 1195105059Scognet trm_reg_write8(0, TRMREG_SCSI_FIFO); 1196105059Scognet trm_reg_write8(0, TRMREG_SCSI_FIFO); 1197105059Scognet trm_reg_write8(pcsio->sense_len, TRMREG_SCSI_FIFO); 1198105059Scognet trm_reg_write8(0, TRMREG_SCSI_FIFO); 1199105059Scognet } else { 1200105059Scognet ptr = (u_int8_t *) pSRB->CmdBlock; 1201105059Scognet for (i = 0; i < pSRB->ScsiCmdLen ; i++) { 1202105059Scognet command = *ptr++; 1203105059Scognet trm_reg_write8(command,TRMREG_SCSI_FIFO); 1204105059Scognet } 1205105059Scognet } 1206105059Scognet if (trm_reg_read16(TRMREG_SCSI_STATUS) & SCSIINTERRUPT) { 1207105059Scognet /* 1208105059Scognet * If trm_StartSCSI return 1 : 1209105059Scognet * current interrupt status is interrupt disreenable 1210105059Scognet * It's said that SCSI processor has more one SRB need to do, 1211105059Scognet * SCSI processor has been occupied by one SRB. 1212105059Scognet */ 1213105059Scognet pSRB->SRBState = SRB_READY; 1214105059Scognet return_code = 1; 1215105059Scognet } else { 1216105059Scognet /* 1217105059Scognet * If trm_StartSCSI return 0 : 1218105059Scognet * current interrupt status is interrupt enable 1219105059Scognet * It's said that SCSI processor is unoccupied 1220105059Scognet */ 1221105059Scognet pSRB->ScsiPhase = SCSI_NOP1; /* SCSI bus free Phase */ 1222105059Scognet pACB->pActiveDCB = pDCB; 1223105059Scognet pDCB->pActiveSRB = pSRB; 1224105059Scognet return_code = 0; 1225105059Scognet trm_reg_write16(DO_DATALATCH | DO_HWRESELECT, 1226105059Scognet TRMREG_SCSI_CONTROL);/* it's important for atn stop*/ 1227105059Scognet /* 1228105059Scognet * SCSI cammand 1229105059Scognet */ 1230105059Scognet trm_reg_write8(scsicommand,TRMREG_SCSI_COMMAND); 1231105059Scognet } 1232105059Scognet return (return_code); 1233105059Scognet} 1234105059Scognet 1235105059Scognetstatic void 1236105059Scognettrm_Interrupt(vpACB) 1237105059Scognetvoid *vpACB; 1238105059Scognet{ 1239105059Scognet PACB pACB; 1240105059Scognet PDCB pDCB; 1241105059Scognet PSRB pSRB; 1242105059Scognet u_int16_t phase; 1243111158Scognet void (*stateV)(PACB, PSRB, u_int16_t *); 1244111158Scognet u_int16_t scsi_status=0; 1245111158Scognet u_int8_t scsi_intstatus; 1246105059Scognet 1247105059Scognet pACB = vpACB; 1248105059Scognet 1249105059Scognet scsi_status = trm_reg_read16(TRMREG_SCSI_STATUS); 1250105059Scognet if (!(scsi_status & SCSIINTERRUPT)) { 1251105059Scognet TRM_DPRINTF("trm_Interrupt: TRMREG_SCSI_STATUS scsi_status = NULL ,return......"); 1252105059Scognet return; 1253105059Scognet } 1254105059Scognet TRM_DPRINTF("scsi_status=%2x,",scsi_status); 1255105059Scognet 1256105059Scognet scsi_intstatus = trm_reg_read8(TRMREG_SCSI_INTSTATUS); 1257105059Scognet 1258105059Scognet TRM_DPRINTF("scsi_intstatus=%2x,",scsi_intstatus); 1259105059Scognet 1260105059Scognet if (scsi_intstatus & (INT_SELTIMEOUT | INT_DISCONNECT)) { 1261105059Scognet trm_Disconnect(pACB); 1262105059Scognet return; 1263105059Scognet } 1264105059Scognet 1265105059Scognet if (scsi_intstatus & INT_RESELECTED) { 1266105059Scognet trm_Reselect(pACB); 1267105059Scognet return; 1268105059Scognet } 1269105059Scognet if (scsi_intstatus & INT_SCSIRESET) { 1270105059Scognet trm_ScsiRstDetect(pACB); 1271105059Scognet return; 1272105059Scognet } 1273105059Scognet 1274105059Scognet if (scsi_intstatus & (INT_BUSSERVICE | INT_CMDDONE)) { 1275105059Scognet pDCB = pACB->pActiveDCB; 1276126053Scognet KASSERT(pDCB != NULL, ("no active DCB")); 1277105059Scognet pSRB = pDCB->pActiveSRB; 1278126053Scognet if (pDCB->DCBFlag & ABORT_DEV_) 1279105059Scognet trm_EnableMsgOutAbort1(pACB, pSRB); 1280105059Scognet phase = (u_int16_t) pSRB->ScsiPhase; /* phase: */ 1281105059Scognet stateV = (void *) trm_SCSI_phase0[phase]; 1282105059Scognet stateV(pACB, pSRB, &scsi_status); 1283105059Scognet pSRB->ScsiPhase = scsi_status & PHASEMASK; 1284105059Scognet /* phase:0,1,2,3,4,5,6,7 */ 1285105059Scognet phase = (u_int16_t) scsi_status & PHASEMASK; 1286105059Scognet stateV = (void *) trm_SCSI_phase1[phase]; 1287105059Scognet stateV(pACB, pSRB, &scsi_status); 1288105059Scognet } 1289105059Scognet} 1290105059Scognet 1291105059Scognetstatic void 1292111158Scognettrm_MsgOutPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1293105059Scognet{ 1294105059Scognet 1295105059Scognet if (pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT)) 1296105059Scognet *pscsi_status = PH_BUS_FREE; 1297105059Scognet /*.. initial phase*/ 1298105059Scognet} 1299105059Scognet 1300105059Scognetstatic void 1301111158Scognettrm_MsgOutPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1302105059Scognet{ 1303105059Scognet u_int8_t bval; 1304105059Scognet u_int16_t i, cnt; 1305105059Scognet u_int8_t * ptr; 1306105059Scognet PDCB pDCB; 1307105059Scognet 1308105059Scognet trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL); 1309105059Scognet pDCB = pACB->pActiveDCB; 1310105059Scognet if (!(pSRB->SRBState & SRB_MSGOUT)) { 1311105059Scognet cnt = pSRB->MsgCnt; 1312105059Scognet if (cnt) { 1313105059Scognet ptr = (u_int8_t *) pSRB->MsgOutBuf; 1314105059Scognet for (i = 0; i < cnt; i++) { 1315105059Scognet trm_reg_write8(*ptr, TRMREG_SCSI_FIFO); 1316105059Scognet ptr++; 1317105059Scognet } 1318105059Scognet pSRB->MsgCnt = 0; 1319105059Scognet if ((pDCB->DCBFlag & ABORT_DEV_) && 1320105059Scognet (pSRB->MsgOutBuf[0] == MSG_ABORT)) { 1321105059Scognet pSRB->SRBState = SRB_ABORT_SENT; 1322105059Scognet } 1323105059Scognet } else { 1324105059Scognet bval = MSG_ABORT; 1325105059Scognet if ((pSRB->CmdBlock[0] == INQUIRY) || 1326105059Scognet (pSRB->CmdBlock[0] == REQUEST_SENSE) || 1327105059Scognet (pSRB->SRBFlag & AUTO_REQSENSE)) { 1328105059Scognet if (pDCB->SyncMode & SYNC_NEGO_ENABLE) { 1329105059Scognet goto mop1; 1330105059Scognet } 1331105059Scognet } 1332105059Scognet trm_reg_write8(bval, TRMREG_SCSI_FIFO); 1333105059Scognet } 1334105059Scognet } else { 1335105059Scognetmop1: /* message out phase */ 1336105059Scognet if (!(pSRB->SRBState & SRB_DO_WIDE_NEGO) 1337105059Scognet && (pDCB->SyncMode & WIDE_NEGO_ENABLE)) { 1338105059Scognet /* 1339105059Scognet * WIDE DATA TRANSFER REQUEST code (03h) 1340105059Scognet */ 1341105059Scognet pDCB->SyncMode &= ~(SYNC_NEGO_DONE | EN_ATN_STOP); 1342105059Scognet trm_reg_write8((pDCB->IdentifyMsg & 0xBF), 1343105059Scognet TRMREG_SCSI_FIFO); 1344105059Scognet trm_reg_write8(MSG_EXTENDED,TRMREG_SCSI_FIFO); 1345105059Scognet /* (01h) */ 1346105059Scognet trm_reg_write8(2,TRMREG_SCSI_FIFO); 1347105059Scognet /* Message length (02h) */ 1348105059Scognet trm_reg_write8(3,TRMREG_SCSI_FIFO); 1349105059Scognet /* wide data xfer (03h) */ 1350105059Scognet trm_reg_write8(1,TRMREG_SCSI_FIFO); 1351105059Scognet /* width:0(8bit),1(16bit),2(32bit) */ 1352105059Scognet pSRB->SRBState |= SRB_DO_WIDE_NEGO; 1353105059Scognet } else if (!(pSRB->SRBState & SRB_DO_SYNC_NEGO) 1354105059Scognet && (pDCB->SyncMode & SYNC_NEGO_ENABLE)) { 1355105059Scognet /* 1356105059Scognet * SYNCHRONOUS DATA TRANSFER REQUEST code (01h) 1357105059Scognet */ 1358105059Scognet if (!(pDCB->SyncMode & WIDE_NEGO_DONE)) 1359105059Scognet trm_reg_write8((pDCB->IdentifyMsg & 0xBF), 1360105059Scognet TRMREG_SCSI_FIFO); 1361105059Scognet trm_reg_write8(MSG_EXTENDED,TRMREG_SCSI_FIFO); 1362105059Scognet /* (01h) */ 1363105059Scognet trm_reg_write8(3,TRMREG_SCSI_FIFO); 1364105059Scognet /* Message length (03h) */ 1365105059Scognet trm_reg_write8(1,TRMREG_SCSI_FIFO); 1366105059Scognet /* SYNCHRONOUS DATA TRANSFER REQUEST code (01h) */ 1367105059Scognet trm_reg_write8(pDCB->MaxNegoPeriod,TRMREG_SCSI_FIFO); 1368105059Scognet /* Transfer peeriod factor */ 1369111158Scognet trm_reg_write8((pACB->AdaptType == 1) ? 31 : 15, 1370111158Scognet TRMREG_SCSI_FIFO); 1371105059Scognet /* REQ/ACK offset */ 1372105059Scognet pSRB->SRBState |= SRB_DO_SYNC_NEGO; 1373105059Scognet } 1374105059Scognet } 1375105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1376105059Scognet /* it's important for atn stop */ 1377105059Scognet /* 1378105059Scognet * SCSI cammand 1379105059Scognet */ 1380105059Scognet trm_reg_write8(SCMD_FIFO_OUT, TRMREG_SCSI_COMMAND); 1381105059Scognet} 1382105059Scognet 1383105059Scognetstatic void 1384111158Scognettrm_CommandPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1385105059Scognet{ 1386105059Scognet 1387105059Scognet} 1388105059Scognet 1389105059Scognetstatic void 1390111158Scognettrm_CommandPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1391105059Scognet{ 1392105059Scognet PDCB pDCB; 1393105059Scognet u_int8_t * ptr; 1394105059Scognet u_int16_t i, cnt; 1395105059Scognet union ccb *pccb; 1396105059Scognet struct ccb_scsiio *pcsio; 1397105059Scognet 1398105059Scognet pccb = pSRB->pccb; 1399105059Scognet pcsio = &pccb->csio; 1400105059Scognet 1401105059Scognet trm_reg_write16(DO_CLRATN | DO_CLRFIFO , TRMREG_SCSI_CONTROL); 1402105059Scognet if (!(pSRB->SRBFlag & AUTO_REQSENSE)) { 1403105059Scognet cnt = (u_int16_t) pSRB->ScsiCmdLen; 1404105059Scognet ptr = (u_int8_t *) pSRB->CmdBlock; 1405105059Scognet for (i = 0; i < cnt; i++) { 1406105059Scognet trm_reg_write8(*ptr, TRMREG_SCSI_FIFO); 1407105059Scognet ptr++; 1408105059Scognet } 1409105059Scognet } else { 1410105059Scognet trm_reg_write8(REQUEST_SENSE, TRMREG_SCSI_FIFO); 1411105059Scognet pDCB = pACB->pActiveDCB; 1412105059Scognet /* target id */ 1413105059Scognet trm_reg_write8((pDCB->IdentifyMsg << 5), TRMREG_SCSI_FIFO); 1414105059Scognet trm_reg_write8(0, TRMREG_SCSI_FIFO); 1415105059Scognet trm_reg_write8(0, TRMREG_SCSI_FIFO); 1416105059Scognet /* sizeof(struct scsi_sense_data) */ 1417105059Scognet trm_reg_write8(pcsio->sense_len, TRMREG_SCSI_FIFO); 1418105059Scognet trm_reg_write8(0, TRMREG_SCSI_FIFO); 1419105059Scognet } 1420105059Scognet pSRB->SRBState = SRB_COMMAND; 1421105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1422105059Scognet /* it's important for atn stop*/ 1423105059Scognet /* 1424105059Scognet * SCSI cammand 1425105059Scognet */ 1426105059Scognet trm_reg_write8(SCMD_FIFO_OUT, TRMREG_SCSI_COMMAND); 1427105059Scognet} 1428105059Scognet 1429105059Scognetstatic void 1430111158Scognettrm_DataOutPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1431105059Scognet{ 1432105059Scognet PDCB pDCB; 1433105059Scognet u_int8_t TempDMAstatus,SGIndexTemp; 1434105059Scognet u_int16_t scsi_status; 1435105059Scognet PSEG pseg; 1436105059Scognet u_long TempSRBXferredLength,dLeftCounter=0; 1437105059Scognet 1438105059Scognet pDCB = pSRB->pSRBDCB; 1439105059Scognet scsi_status = *pscsi_status; 1440105059Scognet 1441105059Scognet if (!(pSRB->SRBState & SRB_XFERPAD)) { 1442105059Scognet if (scsi_status & PARITYERROR) 1443105059Scognet pSRB->SRBStatus |= PARITY_ERROR; 1444105059Scognet if (!(scsi_status & SCSIXFERDONE)) { 1445105059Scognet /* 1446105059Scognet * when data transfer from DMA FIFO to SCSI FIFO 1447105059Scognet * if there was some data left in SCSI FIFO 1448105059Scognet */ 1449105059Scognet dLeftCounter = (u_long) 1450111158Scognet (trm_reg_read8(TRMREG_SCSI_FIFOCNT) & 0x3F); 1451105059Scognet if (pDCB->SyncPeriod & WIDE_SYNC) { 1452105059Scognet /* 1453105059Scognet * if WIDE scsi SCSI FIFOCNT unit is word 1454105059Scognet * so need to * 2 1455105059Scognet */ 1456105059Scognet dLeftCounter <<= 1; 1457105059Scognet } 1458105059Scognet } 1459105059Scognet /* 1460105059Scognet * caculate all the residue data that not yet tranfered 1461105059Scognet * SCSI transfer counter + left in SCSI FIFO data 1462105059Scognet * 1463105059Scognet * .....TRM_SCSI_COUNTER (24bits) 1464105059Scognet * The counter always decrement by one for every SCSI byte 1465105059Scognet *transfer. 1466105059Scognet * .....TRM_SCSI_FIFOCNT (5bits) 1467105059Scognet * The counter is SCSI FIFO offset counter 1468105059Scognet */ 1469105059Scognet dLeftCounter += trm_reg_read32(TRMREG_SCSI_COUNTER); 1470105059Scognet if (dLeftCounter == 1) { 1471105059Scognet dLeftCounter = 0; 1472105059Scognet trm_reg_write16(DO_CLRFIFO,TRMREG_SCSI_CONTROL); 1473105059Scognet } 1474105059Scognet if ((dLeftCounter == 0) || 1475105059Scognet (scsi_status & SCSIXFERCNT_2_ZERO)) { 1476105059Scognet TempDMAstatus = trm_reg_read8(TRMREG_DMA_STATUS); 1477105059Scognet while (!(TempDMAstatus & DMAXFERCOMP)) { 1478105059Scognet TempDMAstatus = 1479105059Scognet trm_reg_read8(TRMREG_DMA_STATUS); 1480105059Scognet } 1481105059Scognet pSRB->SRBTotalXferLength = 0; 1482105059Scognet } else { 1483105059Scognet /* Update SG list */ 1484105059Scognet /* 1485105059Scognet * if transfer not yet complete 1486105059Scognet * there were some data residue in SCSI FIFO or 1487105059Scognet * SCSI transfer counter not empty 1488105059Scognet */ 1489105059Scognet if (pSRB->SRBTotalXferLength != dLeftCounter) { 1490105059Scognet /* 1491105059Scognet * data that had transferred length 1492105059Scognet */ 1493105059Scognet TempSRBXferredLength = 1494105059Scognet pSRB->SRBTotalXferLength - dLeftCounter; 1495105059Scognet /* 1496105059Scognet * next time to be transferred length 1497105059Scognet */ 1498105059Scognet pSRB->SRBTotalXferLength = dLeftCounter; 1499105059Scognet /* 1500105059Scognet * parsing from last time disconnect SRBSGIndex 1501105059Scognet */ 1502105059Scognet pseg = 1503111158Scognet pSRB->pSRBSGL + pSRB->SRBSGIndex; 1504105059Scognet for (SGIndexTemp = pSRB->SRBSGIndex; 1505105059Scognet SGIndexTemp < pSRB->SRBSGCount; 1506105059Scognet SGIndexTemp++) { 1507105059Scognet /* 1508105059Scognet * find last time which SG transfer be 1509105059Scognet * disconnect 1510105059Scognet */ 1511105059Scognet if (TempSRBXferredLength >= 1512105059Scognet pseg->length) 1513105059Scognet TempSRBXferredLength -= 1514105059Scognet pseg->length; 1515105059Scognet else { 1516105059Scognet /* 1517105059Scognet * update last time disconnected SG 1518105059Scognet * list 1519105059Scognet */ 1520105059Scognet pseg->length -= 1521105059Scognet TempSRBXferredLength; 1522105059Scognet /* residue data length */ 1523105059Scognet pseg->address += 1524105059Scognet TempSRBXferredLength; 1525105059Scognet /* residue data pointer */ 1526105059Scognet pSRB->SRBSGIndex = SGIndexTemp; 1527105059Scognet break; 1528105059Scognet } 1529105059Scognet pseg++; 1530105059Scognet } 1531105059Scognet } 1532105059Scognet } 1533105059Scognet } 1534105059Scognet trm_reg_write8(STOPDMAXFER ,TRMREG_DMA_CONTROL); 1535105059Scognet} 1536105059Scognet 1537105059Scognet 1538105059Scognetstatic void 1539111158Scognettrm_DataOutPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1540105059Scognet{ 1541105059Scognet u_int16_t ioDir; 1542105059Scognet /* 1543105059Scognet * do prepare befor transfer when data out phase 1544105059Scognet */ 1545105059Scognet 1546105059Scognet ioDir = XFERDATAOUT; 1547105059Scognet trm_DataIO_transfer(pACB, pSRB, ioDir); 1548105059Scognet} 1549105059Scognet 1550105059Scognetstatic void 1551111158Scognettrm_DataInPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1552105059Scognet{ 1553111158Scognet u_int8_t TempDMAstatus, SGIndexTemp; 1554105059Scognet u_int16_t scsi_status; 1555105059Scognet PSEG pseg; 1556105059Scognet u_long TempSRBXferredLength,dLeftCounter = 0; 1557105059Scognet 1558105059Scognet scsi_status = *pscsi_status; 1559105059Scognet if (!(pSRB->SRBState & SRB_XFERPAD)) { 1560105059Scognet if (scsi_status & PARITYERROR) 1561105059Scognet pSRB->SRBStatus |= PARITY_ERROR; 1562105059Scognet dLeftCounter += trm_reg_read32(TRMREG_SCSI_COUNTER); 1563105059Scognet if ((dLeftCounter == 0) || (scsi_status & SCSIXFERCNT_2_ZERO)) { 1564111158Scognet TempDMAstatus = trm_reg_read8(TRMREG_DMA_STATUS); 1565111158Scognet while (!(TempDMAstatus & DMAXFERCOMP)) 1566111158Scognet TempDMAstatus = trm_reg_read8(TRMREG_DMA_STATUS); 1567105059Scognet pSRB->SRBTotalXferLength = 0; 1568105059Scognet } else { 1569105059Scognet /* 1570105059Scognet * parsing the case: 1571105059Scognet * when a transfer not yet complete 1572105059Scognet * but be disconnected by uper layer 1573105059Scognet * if transfer not yet complete 1574105059Scognet * there were some data residue in SCSI FIFO or 1575105059Scognet * SCSI transfer counter not empty 1576105059Scognet */ 1577105059Scognet if (pSRB->SRBTotalXferLength != dLeftCounter) { 1578105059Scognet /* 1579105059Scognet * data that had transferred length 1580105059Scognet */ 1581105059Scognet TempSRBXferredLength = 1582105059Scognet pSRB->SRBTotalXferLength - dLeftCounter; 1583105059Scognet /* 1584105059Scognet * next time to be transferred length 1585105059Scognet */ 1586105059Scognet pSRB->SRBTotalXferLength = dLeftCounter; 1587105059Scognet /* 1588105059Scognet * parsing from last time disconnect SRBSGIndex 1589105059Scognet */ 1590111158Scognet pseg = pSRB->pSRBSGL + pSRB->SRBSGIndex; 1591105059Scognet for (SGIndexTemp = pSRB->SRBSGIndex; 1592105059Scognet SGIndexTemp < pSRB->SRBSGCount; 1593105059Scognet SGIndexTemp++) { 1594105059Scognet /* 1595105059Scognet * find last time which SG transfer be disconnect 1596105059Scognet */ 1597105059Scognet if (TempSRBXferredLength >= pseg->length) 1598105059Scognet TempSRBXferredLength -= pseg->length; 1599105059Scognet else { 1600105059Scognet /* 1601105059Scognet * update last time disconnected SG list 1602105059Scognet */ 1603105059Scognet pseg->length -= TempSRBXferredLength; 1604105059Scognet /* residue data length */ 1605105059Scognet pseg->address += TempSRBXferredLength; 1606105059Scognet /* residue data pointer */ 1607105059Scognet pSRB->SRBSGIndex = SGIndexTemp; 1608105059Scognet break; 1609105059Scognet } 1610105059Scognet pseg++; 1611105059Scognet } 1612105059Scognet } 1613105059Scognet } 1614105059Scognet } 1615105059Scognet} 1616105059Scognet 1617105059Scognetstatic void 1618111158Scognettrm_DataInPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1619105059Scognet{ 1620105059Scognet u_int16_t ioDir; 1621105059Scognet /* 1622105059Scognet * do prepare befor transfer when data in phase 1623105059Scognet */ 1624105059Scognet 1625105059Scognet ioDir = XFERDATAIN; 1626105059Scognet trm_DataIO_transfer(pACB, pSRB, ioDir); 1627105059Scognet} 1628105059Scognet 1629105059Scognetstatic void 1630105059Scognettrm_DataIO_transfer(PACB pACB, PSRB pSRB, u_int16_t ioDir) 1631105059Scognet{ 1632105059Scognet u_int8_t bval; 1633105059Scognet PDCB pDCB; 1634105059Scognet 1635105059Scognet pDCB = pSRB->pSRBDCB; 1636105059Scognet if (pSRB->SRBSGIndex < pSRB->SRBSGCount) { 1637105059Scognet if (pSRB->SRBTotalXferLength != 0) { 1638105059Scognet /* 1639105059Scognet * load what physical address of Scatter/Gather list 1640105059Scognet table want to be transfer 1641105059Scognet */ 1642111158Scognet TRM_DPRINTF(" SG->address=%8x \n",pSRB->pSRBSGL->address); 1643111158Scognet TRM_DPRINTF(" SG->length=%8x \n",pSRB->pSRBSGL->length); 1644111158Scognet TRM_DPRINTF(" pDCB->SyncPeriod=%x \n",pDCB->SyncPeriod); 1645111158Scognet TRM_DPRINTF(" pSRB->pSRBSGL=%8x \n",(unsigned int)pSRB->pSRBSGL); 1646111158Scognet TRM_DPRINTF(" pSRB->SRBSGPhyAddr=%8x \n",pSRB->SRBSGPhyAddr); 1647111158Scognet TRM_DPRINTF(" pSRB->SRBSGIndex=%d \n",pSRB->SRBSGIndex); 1648111158Scognet TRM_DPRINTF(" pSRB->SRBSGCount=%d \n",pSRB->SRBSGCount); 1649111158Scognet TRM_DPRINTF(" pSRB->SRBTotalXferLength=%d \n",pSRB->SRBTotalXferLength); 1650111158Scognet 1651105059Scognet pSRB->SRBState = SRB_DATA_XFER; 1652105059Scognet trm_reg_write32(0, TRMREG_DMA_XHIGHADDR); 1653105059Scognet trm_reg_write32( 1654105059Scognet (pSRB->SRBSGPhyAddr + 1655105059Scognet ((u_long)pSRB->SRBSGIndex << 3)), 1656105059Scognet TRMREG_DMA_XLOWADDR); 1657105059Scognet /* 1658105059Scognet * load how many bytes in the Scatter/Gather 1659105059Scognet * list table 1660105059Scognet */ 1661105059Scognet trm_reg_write32( 1662105059Scognet ((u_long)(pSRB->SRBSGCount - pSRB->SRBSGIndex) << 3), 1663105059Scognet TRMREG_DMA_XCNT); 1664105059Scognet /* 1665105059Scognet * load total transfer length (24bits) max value 1666105059Scognet * 16Mbyte 1667105059Scognet */ 1668105059Scognet trm_reg_write32(pSRB->SRBTotalXferLength, 1669105059Scognet TRMREG_SCSI_COUNTER); 1670105059Scognet /* Start DMA transfer */ 1671105059Scognet trm_reg_write16(ioDir, TRMREG_DMA_COMMAND); 1672105059Scognet /* Start SCSI transfer */ 1673105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1674105059Scognet /* it's important for atn stop */ 1675105059Scognet /* 1676105059Scognet * SCSI cammand 1677105059Scognet */ 1678105059Scognet bval = (ioDir == XFERDATAOUT) ? 1679105059Scognet SCMD_DMA_OUT : SCMD_DMA_IN; 1680105059Scognet trm_reg_write8(bval, TRMREG_SCSI_COMMAND); 1681105059Scognet } else { 1682105059Scognet /* xfer pad */ 1683105059Scognet if (pSRB->SRBSGCount) { 1684105059Scognet pSRB->AdaptStatus = H_OVER_UNDER_RUN; 1685105059Scognet pSRB->SRBStatus |= OVER_RUN; 1686105059Scognet } 1687105059Scognet if (pDCB->SyncPeriod & WIDE_SYNC) 1688105059Scognet trm_reg_write32(2,TRMREG_SCSI_COUNTER); 1689105059Scognet else 1690105059Scognet trm_reg_write32(1,TRMREG_SCSI_COUNTER); 1691105059Scognet if (ioDir == XFERDATAOUT) 1692105059Scognet trm_reg_write16(0, TRMREG_SCSI_FIFO); 1693105059Scognet else 1694105059Scognet trm_reg_read16(TRMREG_SCSI_FIFO); 1695105059Scognet pSRB->SRBState |= SRB_XFERPAD; 1696105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1697105059Scognet /* it's important for atn stop */ 1698105059Scognet /* 1699105059Scognet * SCSI cammand 1700105059Scognet */ 1701105059Scognet bval = (ioDir == XFERDATAOUT) ? 1702105059Scognet SCMD_FIFO_OUT : SCMD_FIFO_IN; 1703105059Scognet trm_reg_write8(bval, TRMREG_SCSI_COMMAND); 1704105059Scognet } 1705105059Scognet } 1706105059Scognet} 1707105059Scognet 1708105059Scognetstatic void 1709111158Scognettrm_StatusPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1710105059Scognet{ 1711105059Scognet 1712105059Scognet pSRB->TargetStatus = trm_reg_read8(TRMREG_SCSI_FIFO); 1713105059Scognet pSRB->SRBState = SRB_COMPLETED; 1714105059Scognet *pscsi_status = PH_BUS_FREE; 1715105059Scognet /*.. initial phase*/ 1716105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1717105059Scognet /* it's important for atn stop */ 1718105059Scognet /* 1719105059Scognet * SCSI cammand 1720105059Scognet */ 1721105059Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1722105059Scognet} 1723105059Scognet 1724105059Scognet 1725105059Scognet 1726105059Scognetstatic void 1727111158Scognettrm_StatusPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1728105059Scognet{ 1729105059Scognet 1730105059Scognet if (trm_reg_read16(TRMREG_DMA_COMMAND) & 0x0001) { 1731105059Scognet if (!(trm_reg_read8(TRMREG_SCSI_FIFOCNT) & 0x40)) 1732105059Scognet trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL); 1733105059Scognet if (!(trm_reg_read16(TRMREG_DMA_FIFOCNT) & 0x8000)) 1734105059Scognet trm_reg_write8(CLRXFIFO, TRMREG_DMA_CONTROL); 1735105059Scognet } else { 1736105059Scognet if (!(trm_reg_read16(TRMREG_DMA_FIFOCNT) & 0x8000)) 1737105059Scognet trm_reg_write8(CLRXFIFO, TRMREG_DMA_CONTROL); 1738105059Scognet if (!(trm_reg_read8(TRMREG_SCSI_FIFOCNT) & 0x40)) 1739105059Scognet trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL); 1740105059Scognet } 1741105059Scognet pSRB->SRBState = SRB_STATUS; 1742105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1743105059Scognet /* it's important for atn stop */ 1744105059Scognet /* 1745105059Scognet * SCSI cammand 1746105059Scognet */ 1747105059Scognet trm_reg_write8(SCMD_COMP, TRMREG_SCSI_COMMAND); 1748105059Scognet} 1749105059Scognet 1750105059Scognet/* 1751105059Scognet *scsiiom 1752105059Scognet * trm_MsgInPhase0: one of trm_SCSI_phase0[] vectors 1753105059Scognet * stateV = (void *) trm_SCSI_phase0[phase] 1754105059Scognet * if phase =7 1755105059Scognet * extended message codes: 1756105059Scognet * 1757105059Scognet * code description 1758105059Scognet * 1759105059Scognet * 02h Reserved 1760105059Scognet * 00h MODIFY DATA POINTER 1761105059Scognet * 01h SYNCHRONOUS DATA TRANSFER REQUEST 1762105059Scognet * 03h WIDE DATA TRANSFER REQUEST 1763105059Scognet * 04h - 7Fh Reserved 1764105059Scognet * 80h - FFh Vendor specific 1765105059Scognet * 1766105059Scognet */ 1767105059Scognet 1768105059Scognetstatic void 1769111158Scognettrm_MsgInPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1770105059Scognet{ 1771105059Scognet u_int8_t message_in_code,bIndex,message_in_tag_id; 1772105059Scognet PDCB pDCB; 1773105059Scognet PSRB pSRBTemp; 1774105059Scognet 1775105059Scognet pDCB = pACB->pActiveDCB; 1776105059Scognet 1777105059Scognet message_in_code = trm_reg_read8(TRMREG_SCSI_FIFO); 1778105059Scognet if (!(pSRB->SRBState & SRB_EXTEND_MSGIN)) { 1779105059Scognet if (message_in_code == MSG_DISCONNECT) { 1780105059Scognet pSRB->SRBState = SRB_DISCONNECT; 1781111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1782111158Scognet /* it's important for atn stop */ 1783111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1784111158Scognet /* 1785111158Scognet * SCSI command 1786111158Scognet */ 1787111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1788111158Scognet return; 1789105059Scognet } else if (message_in_code == MSG_SAVE_PTR) { 1790111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1791111158Scognet /* it's important for atn stop */ 1792111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1793111158Scognet /* 1794111158Scognet * SCSI command 1795111158Scognet */ 1796111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1797111158Scognet return; 1798105059Scognet } else if ((message_in_code == MSG_EXTENDED) || 1799105059Scognet ((message_in_code >= MSG_SIMPLE_QTAG) && 1800105059Scognet (message_in_code <= MSG_ORDER_QTAG))) { 1801105059Scognet pSRB->SRBState |= SRB_EXTEND_MSGIN; 1802105059Scognet pSRB->MsgInBuf[0] = message_in_code; 1803105059Scognet /* extended message (01h) */ 1804105059Scognet pSRB->MsgCnt = 1; 1805105059Scognet pSRB->pMsgPtr = &pSRB->MsgInBuf[1]; 1806105059Scognet /* extended message length (n) */ 1807111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1808111158Scognet /* it's important for atn stop */ 1809111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1810111158Scognet /* 1811111158Scognet * SCSI command 1812111158Scognet */ 1813111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1814111158Scognet return; 1815105059Scognet } else if (message_in_code == MSG_REJECT_) { 1816105059Scognet /* Reject message */ 1817105059Scognet if (pDCB->SyncMode & WIDE_NEGO_ENABLE) { 1818105059Scognet /* do wide nego reject */ 1819105059Scognet pDCB = pSRB->pSRBDCB; 1820105059Scognet pDCB->SyncMode |= WIDE_NEGO_DONE; 1821105059Scognet pDCB->SyncMode &= ~(SYNC_NEGO_DONE | 1822105059Scognet EN_ATN_STOP | WIDE_NEGO_ENABLE); 1823105059Scognet pSRB->SRBState &= ~(SRB_DO_WIDE_NEGO+SRB_MSGIN); 1824105059Scognet if ((pDCB->SyncMode & SYNC_NEGO_ENABLE) 1825105059Scognet && !(pDCB->SyncMode & SYNC_NEGO_DONE)) { 1826105059Scognet /* Set ATN, in case ATN was clear */ 1827105059Scognet pSRB->SRBState |= SRB_MSGOUT; 1828105059Scognet trm_reg_write16( 1829105059Scognet DO_SETATN, 1830105059Scognet TRMREG_SCSI_CONTROL); 1831105059Scognet } else { 1832105059Scognet /* Clear ATN */ 1833105059Scognet trm_reg_write16( 1834105059Scognet DO_CLRATN, 1835105059Scognet TRMREG_SCSI_CONTROL); 1836105059Scognet } 1837105059Scognet } else if (pDCB->SyncMode & SYNC_NEGO_ENABLE) { 1838105059Scognet /* do sync nego reject */ 1839105059Scognet trm_reg_write16(DO_CLRATN,TRMREG_SCSI_CONTROL); 1840105059Scognet if (pSRB->SRBState & SRB_DO_SYNC_NEGO) { 1841105059Scognet pDCB = pSRB->pSRBDCB; 1842105059Scognet pDCB->SyncMode &= 1843105059Scognet ~(SYNC_NEGO_ENABLE+SYNC_NEGO_DONE); 1844105059Scognet pDCB->SyncPeriod = 0; 1845105059Scognet pDCB->SyncOffset = 0; 1846111158Scognet /* 1847111158Scognet * 1848111158Scognet * program SCSI control register 1849111158Scognet * 1850111158Scognet */ 1851111158Scognet trm_reg_write8(pDCB->SyncPeriod, 1852111158Scognet TRMREG_SCSI_SYNC); 1853111158Scognet trm_reg_write8(pDCB->SyncOffset, 1854111158Scognet TRMREG_SCSI_OFFSET); 1855111158Scognet trm_SetXferRate(pACB,pSRB,pDCB); 1856105059Scognet } 1857105059Scognet } 1858111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1859111158Scognet /* it's important for atn stop */ 1860111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1861111158Scognet /* 1862111158Scognet * SCSI command 1863111158Scognet */ 1864111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1865111158Scognet return; 1866105059Scognet } else if (message_in_code == MSG_IGNOREWIDE) { 1867105059Scognet trm_reg_write32(1, TRMREG_SCSI_COUNTER); 1868105059Scognet trm_reg_read8(TRMREG_SCSI_FIFO); 1869111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1870111158Scognet /* it's important for atn stop */ 1871111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1872111158Scognet /* 1873111158Scognet * SCSI command 1874111158Scognet */ 1875111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1876111158Scognet return; 1877105059Scognet } else { 1878105059Scognet /* Restore data pointer message */ 1879105059Scognet /* Save data pointer message */ 1880105059Scognet /* Completion message */ 1881105059Scognet /* NOP message */ 1882111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1883111158Scognet /* it's important for atn stop */ 1884111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1885111158Scognet /* 1886111158Scognet * SCSI command 1887111158Scognet */ 1888111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1889111158Scognet return; 1890105059Scognet } 1891105059Scognet } else { 1892105059Scognet /* 1893105059Scognet * Parsing incomming extented messages 1894105059Scognet */ 1895105059Scognet *pSRB->pMsgPtr = message_in_code; 1896105059Scognet pSRB->MsgCnt++; 1897105059Scognet pSRB->pMsgPtr++; 1898105059Scognet TRM_DPRINTF("pSRB->MsgInBuf[0]=%2x \n ",pSRB->MsgInBuf[0]); 1899105059Scognet TRM_DPRINTF("pSRB->MsgInBuf[1]=%2x \n ",pSRB->MsgInBuf[1]); 1900105059Scognet TRM_DPRINTF("pSRB->MsgInBuf[2]=%2x \n ",pSRB->MsgInBuf[2]); 1901105059Scognet TRM_DPRINTF("pSRB->MsgInBuf[3]=%2x \n ",pSRB->MsgInBuf[3]); 1902105059Scognet TRM_DPRINTF("pSRB->MsgInBuf[4]=%2x \n ",pSRB->MsgInBuf[4]); 1903105059Scognet if ((pSRB->MsgInBuf[0] >= MSG_SIMPLE_QTAG) 1904105059Scognet && (pSRB->MsgInBuf[0] <= MSG_ORDER_QTAG)) { 1905105059Scognet /* 1906105059Scognet * is QUEUE tag message : 1907105059Scognet * 1908105059Scognet * byte 0: 1909105059Scognet * HEAD QUEUE TAG (20h) 1910105059Scognet * ORDERED QUEUE TAG (21h) 1911105059Scognet * SIMPLE QUEUE TAG (22h) 1912105059Scognet * byte 1: 1913105059Scognet * Queue tag (00h - FFh) 1914105059Scognet */ 1915105059Scognet if (pSRB->MsgCnt == 2) { 1916105059Scognet pSRB->SRBState = 0; 1917105059Scognet message_in_tag_id = pSRB->MsgInBuf[1]; 1918105059Scognet pSRB = pDCB->pGoingSRB; 1919105059Scognet pSRBTemp = pDCB->pGoingLastSRB; 1920105059Scognet if (pSRB) { 1921105059Scognet for (;;) { 1922105059Scognet if (pSRB->TagNumber != 1923105059Scognet message_in_tag_id) { 1924105059Scognet if (pSRB == pSRBTemp) { 1925105059Scognet goto mingx0; 1926105059Scognet } 1927105059Scognet pSRB = pSRB->pNextSRB; 1928105059Scognet } else 1929105059Scognet break; 1930105059Scognet } 1931105059Scognet if (pDCB->DCBFlag & ABORT_DEV_) { 1932105059Scognet pSRB->SRBState = SRB_ABORT_SENT; 1933105059Scognet trm_EnableMsgOutAbort1( 1934105059Scognet pACB, pSRB); 1935105059Scognet } 1936111158Scognet if (!(pSRB->SRBState & SRB_DISCONNECT)) { 1937111158Scognet TRM_DPRINTF("SRB not yet disconnect........ \n "); 1938105059Scognet goto mingx0; 1939111158Scognet } 1940105059Scognet pDCB->pActiveSRB = pSRB; 1941105059Scognet pSRB->SRBState = SRB_DATA_XFER; 1942105059Scognet } else { 1943105059Scognetmingx0: 1944111158Scognet pSRB = &pACB->TmpSRB; 1945105059Scognet pSRB->SRBState = SRB_UNEXPECT_RESEL; 1946105059Scognet pDCB->pActiveSRB = pSRB; 1947105059Scognet pSRB->MsgOutBuf[0] = MSG_ABORT_TAG; 1948105059Scognet trm_EnableMsgOutAbort2( 1949105059Scognet pACB, 1950105059Scognet pSRB); 1951105059Scognet } 1952105059Scognet } 1953111158Scognet *pscsi_status = PH_BUS_FREE; 1954111158Scognet /* .. initial phase */ 1955111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1956111158Scognet /* it's important for atn stop */ 1957111158Scognet /* 1958111158Scognet * SCSI command 1959111158Scognet */ 1960111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1961111158Scognet return; 1962105059Scognet } else if ((pSRB->MsgInBuf[0] == MSG_EXTENDED) && 1963105059Scognet (pSRB->MsgInBuf[2] == 3) && (pSRB->MsgCnt == 4)) { 1964105059Scognet /* 1965105059Scognet * is Wide data xfer Extended message : 1966105059Scognet * ====================================== 1967105059Scognet * WIDE DATA TRANSFER REQUEST 1968105059Scognet * ====================================== 1969105059Scognet * byte 0 : Extended message (01h) 1970105059Scognet * byte 1 : Extended message length (02h) 1971105059Scognet * byte 2 : WIDE DATA TRANSFER code (03h) 1972105059Scognet * byte 3 : Transfer width exponent 1973105059Scognet */ 1974105059Scognet pDCB = pSRB->pSRBDCB; 1975105059Scognet pSRB->SRBState &= ~(SRB_EXTEND_MSGIN+SRB_DO_WIDE_NEGO); 1976105059Scognet if ((pSRB->MsgInBuf[1] != 2)) { 1977105059Scognet /* Length is wrong, reject it */ 1978105059Scognet pDCB->SyncMode &= 1979105059Scognet ~(WIDE_NEGO_ENABLE+WIDE_NEGO_DONE); 1980105059Scognet pSRB->MsgCnt = 1; 1981105059Scognet pSRB->MsgInBuf[0] = MSG_REJECT_; 1982105059Scognet trm_reg_write16(DO_SETATN, TRMREG_SCSI_CONTROL); 1983111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1984111158Scognet /* it's important for atn stop */ 1985111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1986111158Scognet /* 1987111158Scognet * SCSI command 1988111158Scognet */ 1989111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1990111158Scognet return; 1991105059Scognet } 1992105059Scognet if (pDCB->SyncMode & WIDE_NEGO_ENABLE) { 1993105059Scognet /* Do wide negoniation */ 1994105059Scognet if (pSRB->MsgInBuf[3] > 2) { 1995105059Scognet /* > 32 bit */ 1996105059Scognet /* reject_msg: */ 1997105059Scognet pDCB->SyncMode &= 1998105059Scognet ~(WIDE_NEGO_ENABLE+WIDE_NEGO_DONE); 1999105059Scognet pSRB->MsgCnt = 1; 2000105059Scognet pSRB->MsgInBuf[0] = MSG_REJECT_; 2001105059Scognet trm_reg_write16(DO_SETATN, 2002105059Scognet TRMREG_SCSI_CONTROL); 2003111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 2004111158Scognet /* it's important for atn stop */ 2005111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2006111158Scognet /* 2007111158Scognet * SCSI command 2008111158Scognet */ 2009111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 2010111158Scognet return; 2011105059Scognet } 2012105059Scognet if (pSRB->MsgInBuf[3] == 2) { 2013105059Scognet pSRB->MsgInBuf[3] = 1; 2014105059Scognet /* do 16 bits */ 2015105059Scognet } else { 2016105059Scognet if (!(pDCB->SyncMode 2017105059Scognet & WIDE_NEGO_DONE)) { 2018105059Scognet pSRB->SRBState &= 2019105059Scognet ~(SRB_DO_WIDE_NEGO+SRB_MSGIN); 2020105059Scognet pDCB->SyncMode |= 2021105059Scognet WIDE_NEGO_DONE; 2022105059Scognet pDCB->SyncMode &= 2023105059Scognet ~(SYNC_NEGO_DONE | 2024105059Scognet EN_ATN_STOP | 2025105059Scognet WIDE_NEGO_ENABLE); 2026105059Scognet if (pSRB->MsgInBuf[3] != 0) { 2027105059Scognet /* is Wide data xfer */ 2028105059Scognet pDCB->SyncPeriod |= 2029105059Scognet WIDE_SYNC; 2030105059Scognet pDCB->tinfo.current.width 2031105059Scognet = MSG_EXT_WDTR_BUS_16_BIT; 2032105059Scognet pDCB->tinfo.goal.width 2033105059Scognet = MSG_EXT_WDTR_BUS_16_BIT; 2034105059Scognet } 2035105059Scognet } 2036105059Scognet } 2037105059Scognet } else 2038105059Scognet pSRB->MsgInBuf[3] = 0; 2039105059Scognet pSRB->SRBState |= SRB_MSGOUT; 2040105059Scognet trm_reg_write16(DO_SETATN,TRMREG_SCSI_CONTROL); 2041111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 2042111158Scognet /* it's important for atn stop */ 2043111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2044111158Scognet /* 2045111158Scognet * SCSI command 2046111158Scognet */ 2047111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 2048111158Scognet return; 2049105059Scognet } else if ((pSRB->MsgInBuf[0] == MSG_EXTENDED) && 2050105059Scognet (pSRB->MsgInBuf[2] == 1) && (pSRB->MsgCnt == 5)) { 2051105059Scognet /* 2052105059Scognet * is 8bit transfer Extended message : 2053105059Scognet * ================================= 2054105059Scognet * SYNCHRONOUS DATA TRANSFER REQUEST 2055105059Scognet * ================================= 2056105059Scognet * byte 0 : Extended message (01h) 2057105059Scognet * byte 1 : Extended message length (03) 2058105059Scognet * byte 2 : SYNCHRONOUS DATA TRANSFER code (01h) 2059105059Scognet * byte 3 : Transfer period factor 2060105059Scognet * byte 4 : REQ/ACK offset 2061105059Scognet */ 2062105059Scognet pSRB->SRBState &= ~(SRB_EXTEND_MSGIN+SRB_DO_SYNC_NEGO); 2063105059Scognet if ((pSRB->MsgInBuf[1] != 3) || 2064105059Scognet (pSRB->MsgInBuf[2] != 1)) { 2065105059Scognet /* reject_msg: */ 2066105059Scognet pSRB->MsgCnt = 1; 2067105059Scognet pSRB->MsgInBuf[0] = MSG_REJECT_; 2068105059Scognet trm_reg_write16(DO_SETATN, TRMREG_SCSI_CONTROL); 2069111158Scognet *pscsi_status = PH_BUS_FREE; 2070111158Scognet /* .. initial phase */ 2071111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2072111158Scognet /* it's important for atn stop */ 2073111158Scognet /* 2074111158Scognet * SCSI cammand 2075111158Scognet */ 2076111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 2077111158Scognet return; 2078105059Scognet } else if (!(pSRB->MsgInBuf[3]) || !(pSRB->MsgInBuf[4])) { 2079105059Scognet /* set async */ 2080105059Scognet pDCB = pSRB->pSRBDCB; 2081105059Scognet /* disable sync & sync nego */ 2082105059Scognet pDCB->SyncMode &= 2083105059Scognet ~(SYNC_NEGO_ENABLE+SYNC_NEGO_DONE); 2084105059Scognet pDCB->SyncPeriod = 0; 2085105059Scognet pDCB->SyncOffset = 0; 2086105059Scognet pDCB->tinfo.goal.period = 0; 2087105059Scognet pDCB->tinfo.goal.offset = 0; 2088105059Scognet pDCB->tinfo.current.period = 0; 2089105059Scognet pDCB->tinfo.current.offset = 0; 2090105059Scognet pDCB->tinfo.current.width = 2091105059Scognet MSG_EXT_WDTR_BUS_8_BIT; 2092111158Scognet /* 2093111158Scognet * 2094111158Scognet * program SCSI control register 2095111158Scognet * 2096111158Scognet */ 2097111158Scognet trm_reg_write8(pDCB->SyncPeriod,TRMREG_SCSI_SYNC); 2098111158Scognet trm_reg_write8(pDCB->SyncOffset,TRMREG_SCSI_OFFSET); 2099111158Scognet trm_SetXferRate(pACB,pSRB,pDCB); 2100111158Scognet *pscsi_status = PH_BUS_FREE; 2101111158Scognet /* .. initial phase */ 2102111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2103111158Scognet /* it's important for atn stop */ 2104111158Scognet /* 2105111158Scognet * SCSI cammand 2106111158Scognet */ 2107111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 2108111158Scognet return; 2109105059Scognet } else { 2110105059Scognet /* set sync */ 2111105059Scognet pDCB = pSRB->pSRBDCB; 2112105059Scognet pDCB->SyncMode |= 2113105059Scognet SYNC_NEGO_ENABLE+SYNC_NEGO_DONE; 2114105059Scognet pDCB->MaxNegoPeriod = pSRB->MsgInBuf[3]; 2115105059Scognet /* Transfer period factor */ 2116105059Scognet pDCB->SyncOffset = pSRB->MsgInBuf[4]; 2117105059Scognet /* REQ/ACK offset */ 2118116813Scognet if (pACB->AdaptType == 1) { 2119111158Scognet for(bIndex = 0; bIndex < 7; bIndex++) { 2120116813Scognet if (pSRB->MsgInBuf[3] <= 2121111158Scognet dc395u2x_clock_period[bIndex]) { 2122111158Scognet pDCB->tinfo.goal.period = 2123111158Scognet dc395u2x_tinfo_period[bIndex]; 2124111158Scognet pDCB->tinfo.current.period = 2125111158Scognet dc395u2x_tinfo_period[bIndex]; 2126111158Scognet pDCB->tinfo.goal.offset = 2127111158Scognet pDCB->SyncOffset; 2128111158Scognet pDCB->tinfo.current.offset = 2129111158Scognet pDCB->SyncOffset; 2130111158Scognet pDCB->SyncPeriod |= (bIndex|LVDS_SYNC); 2131111158Scognet break; 2132111158Scognet } 2133111158Scognet } 2134111158Scognet } else { 2135111158Scognet for(bIndex = 0; bIndex < 7; bIndex++) { 2136116813Scognet if (pSRB->MsgInBuf[3] <= 2137111158Scognet dc395x_clock_period[bIndex]) { 2138111158Scognet pDCB->tinfo.goal.period = 2139111158Scognet dc395x_tinfo_period[bIndex]; 2140111158Scognet pDCB->tinfo.current.period = 2141111158Scognet dc395x_tinfo_period[bIndex]; 2142111158Scognet pDCB->tinfo.goal.offset = 2143111158Scognet pDCB->SyncOffset; 2144111158Scognet pDCB->tinfo.current.offset = 2145111158Scognet pDCB->SyncOffset; 2146111158Scognet pDCB->SyncPeriod |= 2147111158Scognet (bIndex|ALT_SYNC); 2148111158Scognet break; 2149111158Scognet } 2150111158Scognet } 2151105059Scognet } 2152105059Scognet /* 2153105059Scognet * 2154105059Scognet * program SCSI control register 2155105059Scognet * 2156105059Scognet */ 2157105059Scognet trm_reg_write8(pDCB->SyncPeriod, 2158105059Scognet TRMREG_SCSI_SYNC); 2159105059Scognet trm_reg_write8(pDCB->SyncOffset, 2160105059Scognet TRMREG_SCSI_OFFSET); 2161105059Scognet trm_SetXferRate(pACB,pSRB,pDCB); 2162111158Scognet *pscsi_status=PH_BUS_FREE;/*.. initial phase*/ 2163111158Scognet trm_reg_write16(DO_DATALATCH,TRMREG_SCSI_CONTROL);/* it's important for atn stop*/ 2164111158Scognet /* 2165111158Scognet ** SCSI command 2166111158Scognet */ 2167111158Scognet trm_reg_write8(SCMD_MSGACCEPT,TRMREG_SCSI_COMMAND); 2168111158Scognet return; 2169105059Scognet } 2170105059Scognet } 2171105059Scognet *pscsi_status = PH_BUS_FREE; 2172105059Scognet /* .. initial phase */ 2173105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2174105059Scognet /* it's important for atn stop */ 2175105059Scognet /* 2176105059Scognet * SCSI cammand 2177105059Scognet */ 2178105059Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 2179111158Scognet } 2180105059Scognet} 2181105059Scognet 2182105059Scognetstatic void 2183111158Scognettrm_MsgInPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 2184105059Scognet{ 2185105059Scognet 2186105059Scognet trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL); 2187105059Scognet trm_reg_write32(1,TRMREG_SCSI_COUNTER); 2188105059Scognet if (!(pSRB->SRBState & SRB_MSGIN)) { 2189105059Scognet pSRB->SRBState &= SRB_DISCONNECT; 2190105059Scognet pSRB->SRBState |= SRB_MSGIN; 2191105059Scognet } 2192105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2193105059Scognet /* it's important for atn stop*/ 2194105059Scognet /* 2195105059Scognet * SCSI cammand 2196105059Scognet */ 2197105059Scognet trm_reg_write8(SCMD_FIFO_IN, TRMREG_SCSI_COMMAND); 2198105059Scognet} 2199105059Scognet 2200105059Scognetstatic void 2201111158Scognettrm_Nop0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 2202105059Scognet{ 2203105059Scognet 2204105059Scognet} 2205105059Scognet 2206105059Scognetstatic void 2207111158Scognettrm_Nop1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 2208105059Scognet{ 2209105059Scognet 2210105059Scognet} 2211105059Scognet 2212105059Scognetstatic void 2213105059Scognettrm_SetXferRate(PACB pACB,PSRB pSRB, PDCB pDCB) 2214105059Scognet{ 2215111158Scognet union ccb *pccb; 2216111158Scognet struct ccb_trans_settings neg; 2217105059Scognet u_int16_t cnt, i; 2218105059Scognet u_int8_t bval; 2219105059Scognet PDCB pDCBTemp; 2220105059Scognet 2221105059Scognet /* 2222105059Scognet * set all lun device's period , offset 2223105059Scognet */ 2224111158Scognet TRM_DPRINTF("trm_SetXferRate\n"); 2225111158Scognet pccb = pSRB->pccb; 2226163816Smjacob memset(&neg, 0, sizeof (neg)); 2227163816Smjacob neg.xport_specific.spi.sync_period = pDCB->tinfo.goal.period; 2228163816Smjacob neg.xport_specific.spi.sync_offset = pDCB->tinfo.goal.offset; 2229163816Smjacob neg.xport_specific.spi.valid = 2230163816Smjacob CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET; 2231111158Scognet xpt_setup_ccb(&neg.ccb_h, pccb->ccb_h.path, /* priority */1); 2232111158Scognet xpt_async(AC_TRANSFER_NEG, pccb->ccb_h.path, &neg); 2233105059Scognet if (!(pDCB->IdentifyMsg & 0x07)) { 2234111158Scognet pDCBTemp = pACB->pLinkDCB; 2235111158Scognet cnt = pACB->DeviceCnt; 2236111158Scognet bval = pDCB->TargetID; 2237111158Scognet for (i = 0; i < cnt; i++) { 2238111158Scognet if (pDCBTemp->TargetID == bval) { 2239111158Scognet pDCBTemp->SyncPeriod = pDCB->SyncPeriod; 2240111158Scognet pDCBTemp->SyncOffset = pDCB->SyncOffset; 2241111158Scognet pDCBTemp->SyncMode = pDCB->SyncMode; 2242105059Scognet } 2243111158Scognet pDCBTemp = pDCBTemp->pNextDCB; 2244105059Scognet } 2245105059Scognet } 2246105059Scognet return; 2247105059Scognet} 2248105059Scognet 2249105059Scognet/* 2250105059Scognet * scsiiom 2251105059Scognet * trm_Interrupt 2252105059Scognet * 2253105059Scognet * 2254105059Scognet * ---SCSI bus phase 2255105059Scognet * 2256105059Scognet * PH_DATA_OUT 0x00 Data out phase 2257105059Scognet * PH_DATA_IN 0x01 Data in phase 2258105059Scognet * PH_COMMAND 0x02 Command phase 2259105059Scognet * PH_STATUS 0x03 Status phase 2260105059Scognet * PH_BUS_FREE 0x04 Invalid phase used as bus free 2261105059Scognet * PH_BUS_FREE 0x05 Invalid phase used as bus free 2262105059Scognet * PH_MSG_OUT 0x06 Message out phase 2263105059Scognet * PH_MSG_IN 0x07 Message in phase 2264105059Scognet * 2265105059Scognet */ 2266105059Scognetstatic void 2267105059Scognettrm_Disconnect(PACB pACB) 2268105059Scognet{ 2269105059Scognet PDCB pDCB; 2270105059Scognet PSRB pSRB, psrb; 2271105059Scognet u_int16_t i,j, cnt; 2272105059Scognet u_int target_id,target_lun; 2273105059Scognet 2274105059Scognet TRM_DPRINTF("trm_Disconnect...............\n "); 2275105059Scognet 2276105059Scognet pDCB = pACB->pActiveDCB; 2277105059Scognet if (!pDCB) { 2278105059Scognet TRM_DPRINTF(" Exception Disconnect DCB=NULL..............\n "); 2279105059Scognet j = 400; 2280105059Scognet while (--j) 2281105059Scognet DELAY(1); 2282105059Scognet /* 1 msec */ 2283105059Scognet trm_reg_write16((DO_CLRFIFO | DO_HWRESELECT), 2284105059Scognet TRMREG_SCSI_CONTROL); 2285105059Scognet return; 2286105059Scognet } 2287105059Scognet pSRB = pDCB->pActiveSRB; 2288105059Scognet /* bug pSRB=0 */ 2289105059Scognet target_id = pSRB->pccb->ccb_h.target_id; 2290105059Scognet target_lun = pSRB->pccb->ccb_h.target_lun; 2291105059Scognet TRM_DPRINTF(":pDCB->pActiveSRB= %8x \n ",(u_int) pDCB->pActiveSRB); 2292105059Scognet pACB->pActiveDCB = 0; 2293105059Scognet pSRB->ScsiPhase = PH_BUS_FREE; 2294105059Scognet /* SCSI bus free Phase */ 2295105059Scognet trm_reg_write16((DO_CLRFIFO | DO_HWRESELECT), TRMREG_SCSI_CONTROL); 2296105059Scognet if (pSRB->SRBState & SRB_UNEXPECT_RESEL) { 2297105059Scognet pSRB->SRBState = 0; 2298105059Scognet trm_DoWaitingSRB(pACB); 2299105059Scognet } else if (pSRB->SRBState & SRB_ABORT_SENT) { 2300105059Scognet pDCB->DCBFlag = 0; 2301105059Scognet cnt = pDCB->GoingSRBCnt; 2302105059Scognet pDCB->GoingSRBCnt = 0; 2303105059Scognet pSRB = pDCB->pGoingSRB; 2304105059Scognet for (i = 0; i < cnt; i++) { 2305105059Scognet psrb = pSRB->pNextSRB; 2306105059Scognet pSRB->pNextSRB = pACB->pFreeSRB; 2307105059Scognet pACB->pFreeSRB = pSRB; 2308105059Scognet pSRB = psrb; 2309105059Scognet } 2310105059Scognet pDCB->pGoingSRB = 0; 2311105059Scognet trm_DoWaitingSRB(pACB); 2312105059Scognet } else { 2313105059Scognet if ((pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) || 2314105059Scognet !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED))) { 2315105059Scognet /* Selection time out */ 2316111158Scognet if (!(pACB->scan_devices[target_id][target_lun]) && 2317111158Scognet pSRB->CmdBlock[0] != 0x00 && /* TEST UNIT READY */ 2318111158Scognet pSRB->CmdBlock[0] != INQUIRY) { 2319105059Scognet pSRB->SRBState = SRB_READY; 2320105059Scognet trm_RewaitSRB(pDCB, pSRB); 2321105059Scognet } else { 2322105059Scognet pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT; 2323105059Scognet goto disc1; 2324105059Scognet } 2325105059Scognet } else if (pSRB->SRBState & SRB_DISCONNECT) { 2326105059Scognet /* 2327105059Scognet * SRB_DISCONNECT 2328105059Scognet */ 2329105059Scognet trm_DoWaitingSRB(pACB); 2330105059Scognet } else if (pSRB->SRBState & SRB_COMPLETED) { 2331105059Scognetdisc1: 2332105059Scognet /* 2333105059Scognet * SRB_COMPLETED 2334105059Scognet */ 2335105059Scognet pDCB->pActiveSRB = 0; 2336105059Scognet pSRB->SRBState = SRB_FREE; 2337105059Scognet trm_SRBdone(pACB, pDCB, pSRB); 2338105059Scognet } 2339105059Scognet } 2340105059Scognet return; 2341105059Scognet} 2342105059Scognet 2343105059Scognetstatic void 2344105059Scognettrm_Reselect(PACB pACB) 2345105059Scognet{ 2346105059Scognet PDCB pDCB; 2347105059Scognet PSRB pSRB; 2348105059Scognet u_int16_t RselTarLunId; 2349105059Scognet 2350105059Scognet TRM_DPRINTF("trm_Reselect................. \n"); 2351105059Scognet pDCB = pACB->pActiveDCB; 2352105059Scognet if (pDCB) { 2353105059Scognet /* Arbitration lost but Reselection win */ 2354105059Scognet pSRB = pDCB->pActiveSRB; 2355105059Scognet pSRB->SRBState = SRB_READY; 2356105059Scognet trm_RewaitSRB(pDCB, pSRB); 2357105059Scognet } 2358105059Scognet /* Read Reselected Target Id and LUN */ 2359105059Scognet RselTarLunId = trm_reg_read16(TRMREG_SCSI_TARGETID) & 0x1FFF; 2360105059Scognet pDCB = pACB->pLinkDCB; 2361105059Scognet while (RselTarLunId != *((u_int16_t *) &pDCB->TargetID)) { 2362105059Scognet /* get pDCB of the reselect id */ 2363105059Scognet pDCB = pDCB->pNextDCB; 2364105059Scognet } 2365105059Scognet 2366105059Scognet pACB->pActiveDCB = pDCB; 2367105059Scognet if (pDCB->SyncMode & EN_TAG_QUEUING) { 2368111158Scognet pSRB = &pACB->TmpSRB; 2369105059Scognet pDCB->pActiveSRB = pSRB; 2370105059Scognet } else { 2371105059Scognet pSRB = pDCB->pActiveSRB; 2372105059Scognet if (!pSRB || !(pSRB->SRBState & SRB_DISCONNECT)) { 2373105059Scognet /* 2374105059Scognet * abort command 2375105059Scognet */ 2376111158Scognet pSRB = &pACB->TmpSRB; 2377105059Scognet pSRB->SRBState = SRB_UNEXPECT_RESEL; 2378105059Scognet pDCB->pActiveSRB = pSRB; 2379105059Scognet trm_EnableMsgOutAbort1(pACB, pSRB); 2380105059Scognet } else { 2381105059Scognet if (pDCB->DCBFlag & ABORT_DEV_) { 2382105059Scognet pSRB->SRBState = SRB_ABORT_SENT; 2383105059Scognet trm_EnableMsgOutAbort1(pACB, pSRB); 2384105059Scognet } else 2385105059Scognet pSRB->SRBState = SRB_DATA_XFER; 2386105059Scognet } 2387105059Scognet } 2388105059Scognet pSRB->ScsiPhase = PH_BUS_FREE; 2389105059Scognet /* SCSI bus free Phase */ 2390105059Scognet /* 2391105059Scognet * Program HA ID, target ID, period and offset 2392105059Scognet */ 2393105059Scognet trm_reg_write8((u_int8_t) RselTarLunId,TRMREG_SCSI_TARGETID); 2394105059Scognet /* target ID */ 2395105059Scognet trm_reg_write8(pACB->AdaptSCSIID,TRMREG_SCSI_HOSTID); 2396105059Scognet /* host ID */ 2397105059Scognet trm_reg_write8(pDCB->SyncPeriod,TRMREG_SCSI_SYNC); 2398105059Scognet /* period */ 2399105059Scognet trm_reg_write8(pDCB->SyncOffset,TRMREG_SCSI_OFFSET); 2400105059Scognet /* offset */ 2401105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2402105059Scognet /* it's important for atn stop*/ 2403105059Scognet /* 2404105059Scognet * SCSI cammand 2405105059Scognet */ 2406105059Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 2407105059Scognet /* to rls the /ACK signal */ 2408105059Scognet} 2409105059Scognet 2410105059Scognetstatic void 2411105059Scognettrm_SRBdone(PACB pACB, PDCB pDCB, PSRB pSRB) 2412105059Scognet{ 2413105059Scognet PSRB psrb; 2414105059Scognet u_int8_t bval, bval1,status; 2415105059Scognet union ccb *pccb; 2416105059Scognet struct ccb_scsiio *pcsio; 2417105059Scognet PSCSI_INQDATA ptr; 2418105059Scognet int intflag; 2419105059Scognet u_int target_id,target_lun; 2420105059Scognet PDCB pTempDCB; 2421105059Scognet 2422105059Scognet pccb = pSRB->pccb; 2423105059Scognet if (pccb == NULL) 2424105059Scognet return; 2425105059Scognet pcsio = &pccb->csio; 2426105059Scognet target_id = pSRB->pccb->ccb_h.target_id; 2427105059Scognet target_lun = pSRB->pccb->ccb_h.target_lun; 2428105059Scognet if ((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 2429115343Sscottl bus_dmasync_op_t op; 2430105059Scognet if ((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 2431105059Scognet op = BUS_DMASYNC_POSTREAD; 2432105059Scognet else 2433105059Scognet op = BUS_DMASYNC_POSTWRITE; 2434105059Scognet bus_dmamap_sync(pACB->buffer_dmat, pSRB->dmamap, op); 2435105059Scognet bus_dmamap_unload(pACB->buffer_dmat, pSRB->dmamap); 2436105059Scognet } 2437105059Scognet /* 2438105059Scognet * 2439105059Scognet * target status 2440105059Scognet * 2441105059Scognet */ 2442105059Scognet status = pSRB->TargetStatus; 2443105059Scognet pcsio->scsi_status=SCSI_STAT_GOOD; 2444105059Scognet pccb->ccb_h.status = CAM_REQ_CMP; 2445105059Scognet if (pSRB->SRBFlag & AUTO_REQSENSE) { 2446105059Scognet /* 2447105059Scognet * status of auto request sense 2448105059Scognet */ 2449105059Scognet pSRB->SRBFlag &= ~AUTO_REQSENSE; 2450105059Scognet pSRB->AdaptStatus = 0; 2451105059Scognet pSRB->TargetStatus = SCSI_STATUS_CHECK_COND; 2452105059Scognet 2453105059Scognet if (status == SCSI_STATUS_CHECK_COND) { 2454105059Scognet pccb->ccb_h.status = CAM_SEL_TIMEOUT; 2455105059Scognet goto ckc_e; 2456105059Scognet } 2457105059Scognet *((u_long *) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0]; 2458105059Scognet *((u_long *) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1]; 2459105059Scognet pSRB->SRBTotalXferLength = pSRB->Segment1[1]; 2460111158Scognet pSRB->pSRBSGL->address = pSRB->SgSenseTemp.address; 2461111158Scognet pSRB->pSRBSGL->length = pSRB->SgSenseTemp.length; 2462105059Scognet pcsio->scsi_status = SCSI_STATUS_CHECK_COND; 2463111158Scognet bcopy(trm_get_sense_buf(pACB, pSRB), &pcsio->sense_data, 2464111158Scognet pcsio->sense_len); 2465111158Scognet pcsio->ccb_h.status = CAM_SCSI_STATUS_ERROR 2466111158Scognet | CAM_AUTOSNS_VALID; 2467105059Scognet goto ckc_e; 2468105059Scognet } 2469105059Scognet /* 2470105059Scognet * target status 2471105059Scognet */ 2472105059Scognet if (status) { 2473105059Scognet if (status == SCSI_STATUS_CHECK_COND) { 2474105059Scognet if ((pcsio->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) { 2475105059Scognet TRM_DPRINTF("trm_RequestSense..................\n"); 2476105059Scognet trm_RequestSense(pACB, pDCB, pSRB); 2477105059Scognet return; 2478105059Scognet } 2479105059Scognet pcsio->scsi_status = SCSI_STATUS_CHECK_COND; 2480111158Scognet pccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 2481105059Scognet goto ckc_e; 2482105059Scognet } else if (status == SCSI_STAT_QUEUEFULL) { 2483105059Scognet bval = (u_int8_t) pDCB->GoingSRBCnt; 2484105059Scognet bval--; 2485111158Scognet pDCB->MaxActiveCommandCnt = bval; 2486105059Scognet trm_RewaitSRB(pDCB, pSRB); 2487105059Scognet pSRB->AdaptStatus = 0; 2488105059Scognet pSRB->TargetStatus = 0; 2489111158Scognet return; 2490105059Scognet } else if (status == SCSI_STAT_SEL_TIMEOUT) { 2491105059Scognet pSRB->AdaptStatus = H_SEL_TIMEOUT; 2492105059Scognet pSRB->TargetStatus = 0; 2493105059Scognet pcsio->scsi_status = SCSI_STAT_SEL_TIMEOUT; 2494105059Scognet pccb->ccb_h.status = CAM_SEL_TIMEOUT; 2495105059Scognet } else if (status == SCSI_STAT_BUSY) { 2496105059Scognet TRM_DPRINTF("trm: target busy at %s %d\n", 2497105059Scognet __FILE__, __LINE__); 2498105059Scognet pcsio->scsi_status = SCSI_STAT_BUSY; 2499105059Scognet pccb->ccb_h.status = CAM_SCSI_BUSY; 2500111158Scognet return; 2501105059Scognet /* The device busy, try again later? */ 2502105059Scognet } else if (status == SCSI_STAT_RESCONFLICT) { 2503105059Scognet TRM_DPRINTF("trm: target reserved at %s %d\n", 2504105059Scognet __FILE__, __LINE__); 2505105059Scognet pcsio->scsi_status = SCSI_STAT_RESCONFLICT; 2506105059Scognet pccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; /*XXX*/ 2507111158Scognet return; 2508105059Scognet } else { 2509105059Scognet pSRB->AdaptStatus = 0; 2510105059Scognet if (pSRB->RetryCnt) { 2511105059Scognet pSRB->RetryCnt--; 2512105059Scognet pSRB->TargetStatus = 0; 2513105059Scognet pSRB->SRBSGIndex = 0; 2514105059Scognet if (trm_StartSCSI(pACB, pDCB, pSRB)) { 2515105059Scognet /* 2516105059Scognet * If trm_StartSCSI return 1 : 2517105059Scognet * current interrupt status is interrupt 2518105059Scognet * disreenable 2519105059Scognet * It's said that SCSI processor has more 2520105059Scognet * one SRB need to do 2521105059Scognet */ 2522105059Scognet trm_RewaitSRB(pDCB, pSRB); 2523105059Scognet } 2524105059Scognet return; 2525105059Scognet } else { 2526105059Scognet TRM_DPRINTF("trm: driver stuffup at %s %d\n", 2527105059Scognet __FILE__, __LINE__); 2528105059Scognet pccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 2529105059Scognet } 2530105059Scognet } 2531105059Scognet } else { 2532105059Scognet /* 2533105059Scognet * process initiator status.......................... 2534105059Scognet * Adapter (initiator) status 2535105059Scognet */ 2536105059Scognet status = pSRB->AdaptStatus; 2537105059Scognet if (status & H_OVER_UNDER_RUN) { 2538105059Scognet pSRB->TargetStatus = 0; 2539105059Scognet pccb->ccb_h.status = CAM_DATA_RUN_ERR; 2540105059Scognet /* Illegal length (over/under run) */ 2541105059Scognet } else if (pSRB->SRBStatus & PARITY_ERROR) { 2542105059Scognet TRM_DPRINTF("trm: driver stuffup %s %d\n", 2543105059Scognet __FILE__, __LINE__); 2544105059Scognet pDCB->tinfo.goal.period = 0; 2545105059Scognet pDCB->tinfo.goal.offset = 0; 2546105059Scognet /* Driver failed to perform operation */ 2547105059Scognet pccb->ccb_h.status = CAM_UNCOR_PARITY; 2548105059Scognet } else { 2549105059Scognet /* no error */ 2550105059Scognet pSRB->AdaptStatus = 0; 2551105059Scognet pSRB->TargetStatus = 0; 2552105059Scognet pccb->ccb_h.status = CAM_REQ_CMP; 2553105059Scognet /* there is no error, (sense is invalid) */ 2554105059Scognet } 2555105059Scognet } 2556105059Scognetckc_e: 2557105059Scognet if (pACB->scan_devices[target_id][target_lun]) { 2558105059Scognet /* 2559105059Scognet * if SCSI command in "scan devices" duty 2560105059Scognet */ 2561105059Scognet if (pSRB->CmdBlock[0] == TEST_UNIT_READY) 2562105059Scognet pACB->scan_devices[target_id][target_lun] = 0; 2563105059Scognet /* SCSI command phase :test unit ready */ 2564105059Scognet else if (pSRB->CmdBlock[0] == INQUIRY) { 2565105059Scognet /* 2566105059Scognet * SCSI command phase :inquiry scsi device data 2567105059Scognet * (type,capacity,manufacture.... 2568105059Scognet */ 2569105059Scognet if (pccb->ccb_h.status == CAM_SEL_TIMEOUT) 2570105059Scognet goto NO_DEV; 2571105059Scognet ptr = (PSCSI_INQDATA) pcsio->data_ptr; 2572105059Scognet /* page fault */ 2573105059Scognet TRM_DPRINTF("trm_SRBdone..PSCSI_INQDATA:%2x \n", 2574105059Scognet ptr->DevType); 2575105059Scognet bval1 = ptr->DevType & SCSI_DEVTYPE; 2576105059Scognet if (bval1 == SCSI_NODEV) { 2577105059ScognetNO_DEV: 2578105059Scognet TRM_DPRINTF("trm_SRBdone NO Device:target_id= %d ,target_lun= %d \n", 2579105059Scognet target_id, 2580105059Scognet target_lun); 2581105059Scognet intflag = splcam(); 2582105059Scognet pACB->scan_devices[target_id][target_lun] = 0; 2583105059Scognet /* no device set scan device flag =0*/ 2584105059Scognet /* pDCB Q link */ 2585105059Scognet /* move the head of DCB to tempDCB*/ 2586105059Scognet pTempDCB=pACB->pLinkDCB; 2587105059Scognet /* search current DCB for pass link */ 2588105059Scognet while (pTempDCB->pNextDCB != pDCB) { 2589105059Scognet pTempDCB = pTempDCB->pNextDCB; 2590105059Scognet } 2591105059Scognet /* 2592105059Scognet * when the current DCB found than connect 2593105059Scognet * current DCB tail 2594105059Scognet */ 2595105059Scognet /* to the DCB tail that before current DCB */ 2596105059Scognet pTempDCB->pNextDCB = pDCB->pNextDCB; 2597105059Scognet /* 2598105059Scognet * if there was only one DCB ,connect his tail 2599105059Scognet * to his head 2600105059Scognet */ 2601105059Scognet if (pACB->pLinkDCB == pDCB) 2602105059Scognet pACB->pLinkDCB = pTempDCB->pNextDCB; 2603105059Scognet if (pACB->pDCBRunRobin == pDCB) 2604105059Scognet pACB->pDCBRunRobin = pTempDCB->pNextDCB; 2605111158Scognet pDCB->DCBstatus &= ~DS_IN_QUEUE; 2606105059Scognet pACB->DeviceCnt--; 2607105059Scognet if (pACB->DeviceCnt == 0) { 2608105059Scognet pACB->pLinkDCB = NULL; 2609105059Scognet pACB->pDCBRunRobin = NULL; 2610105059Scognet } 2611105059Scognet splx(intflag); 2612105059Scognet } else { 2613105059Scognet#ifdef trm_DEBUG1 2614105059Scognet int j; 2615105059Scognet for (j = 0; j < 28; j++) { 2616105059Scognet TRM_DPRINTF("ptr=%2x ", 2617105059Scognet ((u_int8_t *)ptr)[j]); 2618105059Scognet } 2619105059Scognet#endif 2620105059Scognet pDCB->DevType = bval1; 2621105059Scognet if (bval1 == SCSI_DASD || 2622105059Scognet bval1 == SCSI_OPTICAL) { 2623105059Scognet if ((((ptr->Vers & 0x07) >= 2) || 2624105059Scognet ((ptr->RDF & 0x0F) == 2)) && 2625105059Scognet (ptr->Flags & SCSI_INQ_CMDQUEUE) && 2626105059Scognet (pDCB->DevMode & TAG_QUEUING_) && 2627105059Scognet (pDCB->DevMode & EN_DISCONNECT_)) { 2628105059Scognet if (pDCB->DevMode & 2629105059Scognet TAG_QUEUING_) { 2630111158Scognet pDCB-> 2631111158Scognet MaxActiveCommandCnt = 2632105059Scognet pACB->TagMaxNum; 2633105059Scognet pDCB->SyncMode |= 2634105059Scognet EN_TAG_QUEUING; 2635105059Scognet pDCB->tinfo.disc_tag |= 2636105059Scognet TRM_CUR_TAGENB; 2637105059Scognet } else { 2638105059Scognet pDCB->SyncMode |= 2639105059Scognet EN_ATN_STOP; 2640105059Scognet pDCB->tinfo.disc_tag &= 2641105059Scognet ~TRM_CUR_TAGENB; 2642105059Scognet } 2643105059Scognet } 2644105059Scognet } 2645105059Scognet } 2646105059Scognet /* pSRB->CmdBlock[0] == INQUIRY */ 2647105059Scognet } 2648105059Scognet /* pACB->scan_devices[target_id][target_lun] */ 2649105059Scognet } 2650105059Scognet intflag = splcam(); 2651105059Scognet /* ReleaseSRB(pDCB, pSRB); */ 2652105059Scognet if (pSRB == pDCB->pGoingSRB) 2653105059Scognet pDCB->pGoingSRB = pSRB->pNextSRB; 2654105059Scognet else { 2655105059Scognet psrb = pDCB->pGoingSRB; 2656105059Scognet while (psrb->pNextSRB != pSRB) { 2657105059Scognet psrb = psrb->pNextSRB; 2658105059Scognet } 2659105059Scognet psrb->pNextSRB = pSRB->pNextSRB; 2660105059Scognet if (pSRB == pDCB->pGoingLastSRB) { 2661105059Scognet pDCB->pGoingLastSRB = psrb; 2662105059Scognet } 2663105059Scognet } 2664105059Scognet pSRB->pNextSRB = pACB->pFreeSRB; 2665105059Scognet pACB->pFreeSRB = pSRB; 2666105059Scognet pDCB->GoingSRBCnt--; 2667105059Scognet trm_DoWaitingSRB(pACB); 2668105059Scognet 2669105059Scognet splx(intflag); 2670105059Scognet /* Notify cmd done */ 2671105059Scognet xpt_done (pccb); 2672105059Scognet} 2673105059Scognet 2674105059Scognetstatic void 2675105059Scognettrm_DoingSRB_Done(PACB pACB) 2676105059Scognet{ 2677105059Scognet PDCB pDCB, pdcb; 2678105059Scognet PSRB psrb, psrb2; 2679105059Scognet u_int16_t cnt, i; 2680105059Scognet union ccb *pccb; 2681105059Scognet 2682105059Scognet pDCB = pACB->pLinkDCB; 2683105059Scognet if (pDCB == NULL) 2684105059Scognet return; 2685105059Scognet pdcb = pDCB; 2686105059Scognet do { 2687105059Scognet cnt = pdcb->GoingSRBCnt; 2688105059Scognet psrb = pdcb->pGoingSRB; 2689105059Scognet for (i = 0; i < cnt; i++) { 2690105059Scognet psrb2 = psrb->pNextSRB; 2691105059Scognet pccb = psrb->pccb; 2692105059Scognet pccb->ccb_h.status = CAM_SEL_TIMEOUT; 2693105059Scognet /* ReleaseSRB(pDCB, pSRB); */ 2694105059Scognet psrb->pNextSRB = pACB->pFreeSRB; 2695105059Scognet pACB->pFreeSRB = psrb; 2696105059Scognet xpt_done(pccb); 2697105059Scognet psrb = psrb2; 2698105059Scognet } 2699201758Smbr pdcb->GoingSRBCnt = 0; 2700105059Scognet pdcb->pGoingSRB = NULL; 2701105059Scognet pdcb = pdcb->pNextDCB; 2702105059Scognet } 2703105059Scognet while (pdcb != pDCB); 2704105059Scognet} 2705105059Scognet 2706105059Scognetstatic void 2707105059Scognettrm_ResetSCSIBus(PACB pACB) 2708105059Scognet{ 2709105059Scognet int intflag; 2710105059Scognet 2711105059Scognet intflag = splcam(); 2712105059Scognet pACB->ACBFlag |= RESET_DEV; 2713105059Scognet 2714105059Scognet trm_reg_write16(DO_RSTSCSI,TRMREG_SCSI_CONTROL); 2715105059Scognet while (!(trm_reg_read16(TRMREG_SCSI_INTSTATUS) & INT_SCSIRESET)); 2716105059Scognet splx(intflag); 2717105059Scognet return; 2718105059Scognet} 2719105059Scognet 2720105059Scognetstatic void 2721105059Scognettrm_ScsiRstDetect(PACB pACB) 2722105059Scognet{ 2723105059Scognet int intflag; 2724105059Scognet u_long wlval; 2725105059Scognet 2726105059Scognet TRM_DPRINTF("trm_ScsiRstDetect \n"); 2727105059Scognet wlval = 1000; 2728105059Scognet while (--wlval) 2729105059Scognet DELAY(1000); 2730105059Scognet intflag = splcam(); 2731105059Scognet trm_reg_write8(STOPDMAXFER,TRMREG_DMA_CONTROL); 2732105059Scognet 2733105059Scognet trm_reg_write16(DO_CLRFIFO,TRMREG_SCSI_CONTROL); 2734105059Scognet 2735105059Scognet if (pACB->ACBFlag & RESET_DEV) 2736105059Scognet pACB->ACBFlag |= RESET_DONE; 2737105059Scognet else { 2738105059Scognet pACB->ACBFlag |= RESET_DETECT; 2739105059Scognet trm_ResetDevParam(pACB); 2740105059Scognet /* trm_DoingSRB_Done(pACB); ???? */ 2741105059Scognet trm_RecoverSRB(pACB); 2742105059Scognet pACB->pActiveDCB = NULL; 2743105059Scognet pACB->ACBFlag = 0; 2744105059Scognet trm_DoWaitingSRB(pACB); 2745105059Scognet } 2746105059Scognet splx(intflag); 2747105059Scognet return; 2748105059Scognet} 2749105059Scognet 2750105059Scognetstatic void 2751105059Scognettrm_RequestSense(PACB pACB, PDCB pDCB, PSRB pSRB) 2752105059Scognet{ 2753105059Scognet union ccb *pccb; 2754105059Scognet struct ccb_scsiio *pcsio; 2755105059Scognet 2756105059Scognet pccb = pSRB->pccb; 2757105059Scognet pcsio = &pccb->csio; 2758105059Scognet 2759105059Scognet pSRB->SRBFlag |= AUTO_REQSENSE; 2760105059Scognet pSRB->Segment0[0] = *((u_long *) &(pSRB->CmdBlock[0])); 2761105059Scognet pSRB->Segment0[1] = *((u_long *) &(pSRB->CmdBlock[4])); 2762105059Scognet pSRB->Segment1[0] = (u_long) ((pSRB->ScsiCmdLen << 8) + 2763105059Scognet pSRB->SRBSGCount); 2764105059Scognet pSRB->Segment1[1] = pSRB->SRBTotalXferLength; /* ?????????? */ 2765105059Scognet 2766105059Scognet /* $$$$$$ Status of initiator/target $$$$$$$$ */ 2767105059Scognet pSRB->AdaptStatus = 0; 2768105059Scognet pSRB->TargetStatus = 0; 2769105059Scognet /* $$$$$$ Status of initiator/target $$$$$$$$ */ 2770105059Scognet 2771105059Scognet pSRB->SRBTotalXferLength = sizeof(pcsio->sense_data); 2772111158Scognet pSRB->SgSenseTemp.address = pSRB->pSRBSGL->address; 2773111158Scognet pSRB->SgSenseTemp.length = pSRB->pSRBSGL->length; 2774111158Scognet pSRB->pSRBSGL->address = trm_get_sense_bufaddr(pACB, pSRB); 2775111158Scognet pSRB->pSRBSGL->length = (u_long) sizeof(struct scsi_sense_data); 2776105059Scognet pSRB->SRBSGCount = 1; 2777105059Scognet pSRB->SRBSGIndex = 0; 2778105059Scognet 2779105059Scognet *((u_long *) &(pSRB->CmdBlock[0])) = 0x00000003; 2780105059Scognet pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5; 2781105059Scognet *((u_int16_t *) &(pSRB->CmdBlock[4])) = pcsio->sense_len; 2782105059Scognet pSRB->ScsiCmdLen = 6; 2783105059Scognet 2784105059Scognet if (trm_StartSCSI(pACB, pDCB, pSRB)) 2785105059Scognet /* 2786105059Scognet * If trm_StartSCSI return 1 : 2787105059Scognet * current interrupt status is interrupt disreenable 2788105059Scognet * It's said that SCSI processor has more one SRB need to do 2789105059Scognet */ 2790105059Scognet trm_RewaitSRB(pDCB, pSRB); 2791105059Scognet} 2792105059Scognet 2793105059Scognetstatic void 2794105059Scognettrm_EnableMsgOutAbort2(PACB pACB, PSRB pSRB) 2795105059Scognet{ 2796105059Scognet 2797105059Scognet pSRB->MsgCnt = 1; 2798105059Scognet trm_reg_write16(DO_SETATN, TRMREG_SCSI_CONTROL); 2799105059Scognet} 2800105059Scognet 2801105059Scognetstatic void 2802105059Scognettrm_EnableMsgOutAbort1(PACB pACB, PSRB pSRB) 2803105059Scognet{ 2804105059Scognet 2805105059Scognet pSRB->MsgOutBuf[0] = MSG_ABORT; 2806105059Scognet trm_EnableMsgOutAbort2(pACB, pSRB); 2807105059Scognet} 2808105059Scognet 2809105059Scognetstatic void 2810105059Scognettrm_initDCB(PACB pACB, PDCB pDCB, u_int16_t unit,u_int32_t i,u_int32_t j) 2811105059Scognet{ 2812105059Scognet PNVRAMTYPE pEEpromBuf; 2813105059Scognet u_int8_t bval,PeriodIndex; 2814105059Scognet u_int target_id,target_lun; 2815105059Scognet PDCB pTempDCB; 2816105059Scognet int intflag; 2817105059Scognet 2818105059Scognet target_id = i; 2819105059Scognet target_lun = j; 2820105059Scognet 2821111158Scognet /* 2822111158Scognet * Using the lun 0 device to init other DCB first, if the device 2823111158Scognet * has been initialized. 2824111158Scognet * I don't want init sync arguments one by one, it is the same. 2825111158Scognet */ 2826111158Scognet if (target_lun != 0 && 2827111158Scognet (pACB->DCBarray[target_id][0].DCBstatus & DS_IN_QUEUE)) 2828111158Scognet bcopy(&pACB->DCBarray[target_id][0], pDCB, 2829111158Scognet sizeof(TRM_DCB)); 2830105059Scognet intflag = splcam(); 2831105059Scognet if (pACB->pLinkDCB == 0) { 2832105059Scognet pACB->pLinkDCB = pDCB; 2833105059Scognet /* 2834105059Scognet * RunRobin impersonate the role 2835105059Scognet * that let each device had good proportion 2836105059Scognet * about SCSI command proceeding 2837105059Scognet */ 2838105059Scognet pACB->pDCBRunRobin = pDCB; 2839105059Scognet pDCB->pNextDCB = pDCB; 2840105059Scognet } else { 2841105059Scognet pTempDCB=pACB->pLinkDCB; 2842105059Scognet /* search the last nod of DCB link */ 2843105059Scognet while (pTempDCB->pNextDCB != pACB->pLinkDCB) 2844105059Scognet pTempDCB = pTempDCB->pNextDCB; 2845105059Scognet /* connect current DCB with last DCB tail */ 2846105059Scognet pTempDCB->pNextDCB = pDCB; 2847105059Scognet /* connect current DCB tail to this DCB Q head */ 2848105059Scognet pDCB->pNextDCB=pACB->pLinkDCB; 2849105059Scognet } 2850105059Scognet splx(intflag); 2851105059Scognet 2852105059Scognet pACB->DeviceCnt++; 2853105059Scognet pDCB->TargetID = target_id; 2854105059Scognet pDCB->TargetLUN = target_lun; 2855105059Scognet pDCB->pWaitingSRB = NULL; 2856105059Scognet pDCB->pGoingSRB = NULL; 2857105059Scognet pDCB->GoingSRBCnt = 0; 2858105059Scognet pDCB->pActiveSRB = NULL; 2859111158Scognet pDCB->MaxActiveCommandCnt = 1; 2860105059Scognet pDCB->DCBFlag = 0; 2861111158Scognet pDCB->DCBstatus |= DS_IN_QUEUE; 2862105059Scognet /* $$$$$$$ */ 2863105059Scognet pEEpromBuf = &trm_eepromBuf[unit]; 2864105059Scognet pDCB->DevMode = pEEpromBuf->NvramTarget[target_id].NvmTarCfg0; 2865105059Scognet pDCB->AdpMode = pEEpromBuf->NvramChannelCfg; 2866105059Scognet /* $$$$$$$ */ 2867105059Scognet /* 2868105059Scognet * disconnect enable ? 2869105059Scognet */ 2870105059Scognet if (pDCB->DevMode & NTC_DO_DISCONNECT) { 2871105059Scognet bval = 0xC0; 2872105059Scognet pDCB->tinfo.disc_tag |= TRM_USR_DISCENB ; 2873105059Scognet } else { 2874105059Scognet bval = 0x80; 2875105059Scognet pDCB->tinfo.disc_tag &= ~(TRM_USR_DISCENB); 2876105059Scognet } 2877105059Scognet bval |= target_lun; 2878105059Scognet pDCB->IdentifyMsg = bval; 2879111158Scognet if (target_lun != 0 && 2880111158Scognet (pACB->DCBarray[target_id][0].DCBstatus & DS_IN_QUEUE)) 2881111158Scognet return; 2882105059Scognet /* $$$$$$$ */ 2883105059Scognet /* 2884105059Scognet * tag Qing enable ? 2885105059Scognet */ 2886105059Scognet if (pDCB->DevMode & TAG_QUEUING_) { 2887105059Scognet pDCB->tinfo.disc_tag |= TRM_USR_TAGENB ; 2888105059Scognet } else 2889105059Scognet pDCB->tinfo.disc_tag &= ~(TRM_USR_TAGENB); 2890105059Scognet /* $$$$$$$ */ 2891105059Scognet /* 2892105059Scognet * wide nego ,sync nego enable ? 2893105059Scognet */ 2894105059Scognet pDCB->SyncPeriod = 0; 2895105059Scognet pDCB->SyncOffset = 0; 2896105059Scognet PeriodIndex = pEEpromBuf->NvramTarget[target_id].NvmTarPeriod & 0x07; 2897116813Scognet if (pACB->AdaptType==1) {/* is U2? */ 2898111158Scognet pDCB->MaxNegoPeriod=dc395u2x_clock_period[ PeriodIndex ]; 2899111158Scognet pDCB->tinfo.user.period=pDCB->MaxNegoPeriod; 2900111158Scognet pDCB->tinfo.user.offset=(pDCB->SyncMode & SYNC_NEGO_ENABLE) ? 31 : 0; 2901111158Scognet } else { 2902111158Scognet pDCB->MaxNegoPeriod=dc395x_clock_period[ PeriodIndex ]; 2903111158Scognet pDCB->tinfo.user.period=pDCB->MaxNegoPeriod; 2904111158Scognet pDCB->tinfo.user.offset=(pDCB->SyncMode & SYNC_NEGO_ENABLE) ? 15 : 0; 2905111158Scognet } 2906105059Scognet pDCB->SyncMode = 0; 2907105059Scognet if ((pDCB->DevMode & NTC_DO_WIDE_NEGO) && 2908105059Scognet (pACB->Config & HCC_WIDE_CARD)) 2909105059Scognet pDCB->SyncMode |= WIDE_NEGO_ENABLE; 2910105059Scognet /* enable wide nego */ 2911105059Scognet if (pDCB->DevMode & NTC_DO_SYNC_NEGO) 2912105059Scognet pDCB->SyncMode |= SYNC_NEGO_ENABLE; 2913105059Scognet /* enable sync nego */ 2914105059Scognet /* $$$$$$$ */ 2915105059Scognet /* 2916105059Scognet * Fill in tinfo structure. 2917105059Scognet */ 2918105059Scognet pDCB->tinfo.user.width = (pDCB->SyncMode & WIDE_NEGO_ENABLE) ? 2919105059Scognet MSG_EXT_WDTR_BUS_16_BIT : MSG_EXT_WDTR_BUS_8_BIT; 2920105059Scognet 2921105059Scognet pDCB->tinfo.current.period = 0; 2922105059Scognet pDCB->tinfo.current.offset = 0; 2923105059Scognet pDCB->tinfo.current.width = MSG_EXT_WDTR_BUS_8_BIT; 2924105059Scognet} 2925105059Scognet 2926111158Scognetstatic void 2927111158Scognettrm_srbmapSG(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2928105059Scognet{ 2929111158Scognet PSRB pSRB; 2930111158Scognet 2931111158Scognet pSRB=(PSRB) arg; 2932111158Scognet pSRB->SRBSGPhyAddr=segs->ds_addr; 2933111158Scognet return; 2934105059Scognet} 2935105059Scognet 2936126725Scognetstatic void 2937126725Scognettrm_destroySRB(PACB pACB) 2938126725Scognet{ 2939126725Scognet PSRB pSRB; 2940126725Scognet 2941126725Scognet pSRB = pACB->pFreeSRB; 2942126725Scognet while (pSRB) { 2943126725Scognet if (pSRB->sg_dmamap) { 2944126725Scognet bus_dmamap_unload(pACB->sg_dmat, pSRB->sg_dmamap); 2945126725Scognet bus_dmamem_free(pACB->sg_dmat, pSRB->pSRBSGL, 2946126725Scognet pSRB->sg_dmamap); 2947126725Scognet bus_dmamap_destroy(pACB->sg_dmat, pSRB->sg_dmamap); 2948126725Scognet } 2949126725Scognet if (pSRB->dmamap) 2950126725Scognet bus_dmamap_destroy(pACB->buffer_dmat, pSRB->dmamap); 2951126725Scognet pSRB = pSRB->pNextSRB; 2952126725Scognet } 2953126725Scognet} 2954126725Scognet 2955111158Scognetstatic int 2956111158Scognettrm_initSRB(PACB pACB) 2957105059Scognet{ 2958116813Scognet u_int16_t i; 2959116813Scognet PSRB pSRB; 2960118693Sscottl int error; 2961105059Scognet 2962116813Scognet for (i = 0; i < TRM_MAX_SRB_CNT; i++) { 2963116813Scognet pSRB = (PSRB)&pACB->pFreeSRB[i]; 2964111158Scognet 2965126725Scognet if (bus_dmamem_alloc(pACB->sg_dmat, (void **)&pSRB->pSRBSGL, 2966116813Scognet BUS_DMA_NOWAIT, &pSRB->sg_dmamap) !=0 ) { 2967116813Scognet return ENXIO; 2968111158Scognet } 2969126725Scognet bus_dmamap_load(pACB->sg_dmat, pSRB->sg_dmamap, pSRB->pSRBSGL, 2970116813Scognet TRM_MAX_SG_LISTENTRY * sizeof(SGentry), 2971116813Scognet trm_srbmapSG, pSRB, /*flags*/0); 2972116813Scognet if (i != TRM_MAX_SRB_CNT - 1) { 2973116813Scognet /* 2974116813Scognet * link all SRB 2975116813Scognet */ 2976116813Scognet pSRB->pNextSRB = &pACB->pFreeSRB[i+1]; 2977116813Scognet } else { 2978116813Scognet /* 2979116813Scognet * load NULL to NextSRB of the last SRB 2980116813Scognet */ 2981116813Scognet pSRB->pNextSRB = NULL; 2982116813Scognet } 2983116813Scognet pSRB->TagNumber = i; 2984118693Sscottl 2985118693Sscottl /* 2986118693Sscottl * Create the dmamap. This is no longer optional! 2987118693Sscottl */ 2988118693Sscottl if ((error = bus_dmamap_create(pACB->buffer_dmat, 0, 2989118693Sscottl &pSRB->dmamap)) != 0) 2990118693Sscottl return (error); 2991118693Sscottl 2992105059Scognet } 2993116813Scognet return (0); 2994105059Scognet} 2995105059Scognet 2996105059Scognet 2997111158Scognet 2998111158Scognet 2999105059Scognetstatic void 3000111158Scognettrm_initACB(PACB pACB, u_int8_t adaptType, u_int16_t unit) 3001105059Scognet{ 3002105059Scognet PNVRAMTYPE pEEpromBuf; 3003105059Scognet 3004105059Scognet pEEpromBuf = &trm_eepromBuf[unit]; 3005105059Scognet pACB->max_id = 15; 3006105059Scognet 3007105059Scognet if (pEEpromBuf->NvramChannelCfg & NAC_SCANLUN) 3008105059Scognet pACB->max_lun = 7; 3009105059Scognet else 3010105059Scognet pACB->max_lun = 0; 3011105059Scognet 3012105059Scognet TRM_DPRINTF("trm: pACB->max_id= %d pACB->max_lun= %d \n", 3013105059Scognet pACB->max_id, pACB->max_lun); 3014105059Scognet pACB->pLinkDCB = NULL; 3015105059Scognet pACB->pDCBRunRobin = NULL; 3016105059Scognet pACB->pActiveDCB = NULL; 3017111158Scognet pACB->AdapterUnit = (u_int8_t)unit; 3018105059Scognet pACB->AdaptSCSIID = pEEpromBuf->NvramScsiId; 3019105059Scognet pACB->AdaptSCSILUN = 0; 3020105059Scognet pACB->DeviceCnt = 0; 3021111158Scognet pACB->AdaptType = adaptType; 3022111158Scognet pACB->TagMaxNum = 2 << pEEpromBuf->NvramMaxTag; 3023105059Scognet pACB->ACBFlag = 0; 3024111158Scognet return; 3025105059Scognet} 3026105059Scognet 3027105059Scognetstatic void 3028111158ScognetNVRAM_trm_write_all(PNVRAMTYPE pEEpromBuf,PACB pACB) 3029105059Scognet{ 3030105059Scognet u_int8_t *bpEeprom = (u_int8_t *) pEEpromBuf; 3031105059Scognet u_int8_t bAddr; 3032105059Scognet 3033105059Scognet /* Enable SEEPROM */ 3034105059Scognet trm_reg_write8((trm_reg_read8(TRMREG_GEN_CONTROL) | EN_EEPROM), 3035105059Scognet TRMREG_GEN_CONTROL); 3036105059Scognet /* 3037105059Scognet * Write enable 3038105059Scognet */ 3039111158Scognet NVRAM_trm_write_cmd(pACB, 0x04, 0xFF); 3040105059Scognet trm_reg_write8(0, TRMREG_GEN_NVRAM); 3041111158Scognet NVRAM_trm_wait_30us(pACB); 3042105059Scognet for (bAddr = 0; bAddr < 128; bAddr++, bpEeprom++) { 3043111158Scognet NVRAM_trm_set_data(pACB, bAddr, *bpEeprom); 3044105059Scognet } 3045105059Scognet /* 3046105059Scognet * Write disable 3047105059Scognet */ 3048111158Scognet NVRAM_trm_write_cmd(pACB, 0x04, 0x00); 3049105059Scognet trm_reg_write8(0 , TRMREG_GEN_NVRAM); 3050111158Scognet NVRAM_trm_wait_30us(pACB); 3051105059Scognet /* Disable SEEPROM */ 3052105059Scognet trm_reg_write8((trm_reg_read8(TRMREG_GEN_CONTROL) & ~EN_EEPROM), 3053105059Scognet TRMREG_GEN_CONTROL); 3054105059Scognet return; 3055105059Scognet} 3056105059Scognet 3057105059Scognetstatic void 3058111158ScognetNVRAM_trm_set_data(PACB pACB, u_int8_t bAddr, u_int8_t bData) 3059105059Scognet{ 3060105059Scognet int i; 3061105059Scognet u_int8_t bSendData; 3062105059Scognet /* 3063105059Scognet * Send write command & address 3064105059Scognet */ 3065105059Scognet 3066111158Scognet NVRAM_trm_write_cmd(pACB, 0x05, bAddr); 3067105059Scognet /* 3068105059Scognet * Write data 3069105059Scognet */ 3070105059Scognet for (i = 0; i < 8; i++, bData <<= 1) { 3071105059Scognet bSendData = NVR_SELECT; 3072105059Scognet if (bData & 0x80) 3073105059Scognet /* Start from bit 7 */ 3074105059Scognet bSendData |= NVR_BITOUT; 3075105059Scognet trm_reg_write8(bSendData , TRMREG_GEN_NVRAM); 3076111158Scognet NVRAM_trm_wait_30us(pACB); 3077105059Scognet trm_reg_write8((bSendData | NVR_CLOCK), TRMREG_GEN_NVRAM); 3078111158Scognet NVRAM_trm_wait_30us(pACB); 3079105059Scognet } 3080105059Scognet trm_reg_write8(NVR_SELECT , TRMREG_GEN_NVRAM); 3081111158Scognet NVRAM_trm_wait_30us(pACB); 3082105059Scognet /* 3083105059Scognet * Disable chip select 3084105059Scognet */ 3085105059Scognet trm_reg_write8(0 , TRMREG_GEN_NVRAM); 3086111158Scognet NVRAM_trm_wait_30us(pACB); 3087105059Scognet trm_reg_write8(NVR_SELECT ,TRMREG_GEN_NVRAM); 3088111158Scognet NVRAM_trm_wait_30us(pACB); 3089105059Scognet /* 3090105059Scognet * Wait for write ready 3091105059Scognet */ 3092105059Scognet while (1) { 3093105059Scognet trm_reg_write8((NVR_SELECT | NVR_CLOCK), TRMREG_GEN_NVRAM); 3094111158Scognet NVRAM_trm_wait_30us(pACB); 3095105059Scognet trm_reg_write8(NVR_SELECT, TRMREG_GEN_NVRAM); 3096111158Scognet NVRAM_trm_wait_30us(pACB); 3097105059Scognet if (trm_reg_read8(TRMREG_GEN_NVRAM) & NVR_BITIN) { 3098105059Scognet break; 3099105059Scognet } 3100105059Scognet } 3101105059Scognet /* 3102105059Scognet * Disable chip select 3103105059Scognet */ 3104105059Scognet trm_reg_write8(0, TRMREG_GEN_NVRAM); 3105105059Scognet return; 3106105059Scognet} 3107105059Scognet 3108105059Scognetstatic void 3109111158ScognetNVRAM_trm_read_all(PNVRAMTYPE pEEpromBuf, PACB pACB) 3110105059Scognet{ 3111105059Scognet u_int8_t *bpEeprom = (u_int8_t*) pEEpromBuf; 3112105059Scognet u_int8_t bAddr; 3113105059Scognet 3114105059Scognet /* 3115105059Scognet * Enable SEEPROM 3116105059Scognet */ 3117105059Scognet trm_reg_write8((trm_reg_read8(TRMREG_GEN_CONTROL) | EN_EEPROM), 3118105059Scognet TRMREG_GEN_CONTROL); 3119105059Scognet for (bAddr = 0; bAddr < 128; bAddr++, bpEeprom++) 3120111158Scognet *bpEeprom = NVRAM_trm_get_data(pACB, bAddr); 3121105059Scognet /* 3122105059Scognet * Disable SEEPROM 3123105059Scognet */ 3124105059Scognet trm_reg_write8((trm_reg_read8(TRMREG_GEN_CONTROL) & ~EN_EEPROM), 3125105059Scognet TRMREG_GEN_CONTROL); 3126105059Scognet return; 3127105059Scognet} 3128105059Scognet 3129105059Scognetstatic u_int8_t 3130111158ScognetNVRAM_trm_get_data(PACB pACB, u_int8_t bAddr) 3131105059Scognet{ 3132105059Scognet int i; 3133105059Scognet u_int8_t bReadData, bData = 0; 3134105059Scognet /* 3135105059Scognet * Send read command & address 3136105059Scognet */ 3137105059Scognet 3138111158Scognet NVRAM_trm_write_cmd(pACB, 0x06, bAddr); 3139105059Scognet 3140105059Scognet for (i = 0; i < 8; i++) { 3141105059Scognet /* 3142105059Scognet * Read data 3143105059Scognet */ 3144105059Scognet trm_reg_write8((NVR_SELECT | NVR_CLOCK) , TRMREG_GEN_NVRAM); 3145111158Scognet NVRAM_trm_wait_30us(pACB); 3146105059Scognet trm_reg_write8(NVR_SELECT , TRMREG_GEN_NVRAM); 3147105059Scognet /* 3148105059Scognet * Get data bit while falling edge 3149105059Scognet */ 3150105059Scognet bReadData = trm_reg_read8(TRMREG_GEN_NVRAM); 3151105059Scognet bData <<= 1; 3152105059Scognet if (bReadData & NVR_BITIN) { 3153105059Scognet bData |= 1; 3154105059Scognet } 3155111158Scognet NVRAM_trm_wait_30us(pACB); 3156105059Scognet } 3157105059Scognet /* 3158105059Scognet * Disable chip select 3159105059Scognet */ 3160105059Scognet trm_reg_write8(0, TRMREG_GEN_NVRAM); 3161105059Scognet return (bData); 3162105059Scognet} 3163105059Scognet 3164105059Scognetstatic void 3165111158ScognetNVRAM_trm_wait_30us(PACB pACB) 3166105059Scognet{ 3167105059Scognet 3168105059Scognet /* ScsiPortStallExecution(30); wait 30 us */ 3169105059Scognet trm_reg_write8(5, TRMREG_GEN_TIMER); 3170105059Scognet while (!(trm_reg_read8(TRMREG_GEN_STATUS) & GTIMEOUT)); 3171105059Scognet return; 3172105059Scognet} 3173105059Scognet 3174105059Scognetstatic void 3175111158ScognetNVRAM_trm_write_cmd(PACB pACB, u_int8_t bCmd, u_int8_t bAddr) 3176105059Scognet{ 3177105059Scognet int i; 3178105059Scognet u_int8_t bSendData; 3179105059Scognet 3180105059Scognet for (i = 0; i < 3; i++, bCmd <<= 1) { 3181105059Scognet /* 3182105059Scognet * Program SB+OP code 3183105059Scognet */ 3184105059Scognet bSendData = NVR_SELECT; 3185105059Scognet if (bCmd & 0x04) 3186105059Scognet bSendData |= NVR_BITOUT; 3187105059Scognet /* start from bit 2 */ 3188105059Scognet trm_reg_write8(bSendData, TRMREG_GEN_NVRAM); 3189111158Scognet NVRAM_trm_wait_30us(pACB); 3190105059Scognet trm_reg_write8((bSendData | NVR_CLOCK), TRMREG_GEN_NVRAM); 3191111158Scognet NVRAM_trm_wait_30us(pACB); 3192105059Scognet } 3193105059Scognet for (i = 0; i < 7; i++, bAddr <<= 1) { 3194105059Scognet /* 3195105059Scognet * Program address 3196105059Scognet */ 3197105059Scognet bSendData = NVR_SELECT; 3198105059Scognet if (bAddr & 0x40) 3199105059Scognet /* Start from bit 6 */ 3200105059Scognet bSendData |= NVR_BITOUT; 3201105059Scognet trm_reg_write8(bSendData , TRMREG_GEN_NVRAM); 3202111158Scognet NVRAM_trm_wait_30us(pACB); 3203105059Scognet trm_reg_write8((bSendData | NVR_CLOCK), TRMREG_GEN_NVRAM); 3204111158Scognet NVRAM_trm_wait_30us(pACB); 3205105059Scognet } 3206105059Scognet trm_reg_write8(NVR_SELECT, TRMREG_GEN_NVRAM); 3207111158Scognet NVRAM_trm_wait_30us(pACB); 3208105059Scognet} 3209105059Scognet 3210105059Scognetstatic void 3211105059Scognettrm_check_eeprom(PNVRAMTYPE pEEpromBuf, PACB pACB) 3212105059Scognet{ 3213105059Scognet u_int16_t *wpEeprom = (u_int16_t *) pEEpromBuf; 3214105059Scognet u_int16_t wAddr, wCheckSum; 3215105059Scognet u_long dAddr, *dpEeprom; 3216105059Scognet 3217111158Scognet NVRAM_trm_read_all(pEEpromBuf,pACB); 3218105059Scognet wCheckSum = 0; 3219105059Scognet for (wAddr = 0, wpEeprom = (u_int16_t *) pEEpromBuf; 3220105059Scognet wAddr < 64; wAddr++, wpEeprom++) { 3221105059Scognet wCheckSum += *wpEeprom; 3222105059Scognet } 3223105059Scognet if (wCheckSum != 0x1234) { 3224105059Scognet /* 3225105059Scognet * Checksum error, load default 3226105059Scognet */ 3227105059Scognet pEEpromBuf->NvramSubVendorID[0] = (u_int8_t) PCI_Vendor_ID_TEKRAM; 3228105059Scognet pEEpromBuf->NvramSubVendorID[1] = 3229105059Scognet (u_int8_t) (PCI_Vendor_ID_TEKRAM >> 8); 3230105059Scognet pEEpromBuf->NvramSubSysID[0] = (u_int8_t) PCI_Device_ID_TRM_S1040; 3231105059Scognet pEEpromBuf->NvramSubSysID[1] = 3232105059Scognet (u_int8_t) (PCI_Device_ID_TRM_S1040 >> 8); 3233105059Scognet pEEpromBuf->NvramSubClass = 0x00; 3234105059Scognet pEEpromBuf->NvramVendorID[0] = (u_int8_t) PCI_Vendor_ID_TEKRAM; 3235105059Scognet pEEpromBuf->NvramVendorID[1] = 3236105059Scognet (u_int8_t) (PCI_Vendor_ID_TEKRAM >> 8); 3237105059Scognet pEEpromBuf->NvramDeviceID[0] = (u_int8_t) PCI_Device_ID_TRM_S1040; 3238105059Scognet pEEpromBuf->NvramDeviceID[1] = 3239105059Scognet (u_int8_t) (PCI_Device_ID_TRM_S1040 >> 8); 3240105059Scognet pEEpromBuf->NvramReserved = 0x00; 3241105059Scognet 3242105059Scognet for (dAddr = 0, dpEeprom = (u_long *) pEEpromBuf->NvramTarget; 3243105059Scognet dAddr < 16; dAddr++, dpEeprom++) { 3244105059Scognet *dpEeprom = 0x00000077; 3245105059Scognet /* NvmTarCfg3,NvmTarCfg2,NvmTarPeriod,NvmTarCfg0 */ 3246105059Scognet } 3247105059Scognet 3248105059Scognet *dpEeprom++ = 0x04000F07; 3249105059Scognet /* NvramMaxTag,NvramDelayTime,NvramChannelCfg,NvramScsiId */ 3250105059Scognet *dpEeprom++ = 0x00000015; 3251105059Scognet /* NvramReserved1,NvramBootLun,NvramBootTarget,NvramReserved0 */ 3252105059Scognet for (dAddr = 0; dAddr < 12; dAddr++, dpEeprom++) 3253105059Scognet *dpEeprom = 0x00; 3254105059Scognet pEEpromBuf->NvramCheckSum = 0x00; 3255105059Scognet for (wAddr = 0, wCheckSum = 0, wpEeprom = (u_int16_t *) pEEpromBuf; 3256105059Scognet wAddr < 63; wAddr++, wpEeprom++) 3257105059Scognet wCheckSum += *wpEeprom; 3258105059Scognet *wpEeprom = 0x1234 - wCheckSum; 3259111158Scognet NVRAM_trm_write_all(pEEpromBuf,pACB); 3260105059Scognet } 3261105059Scognet return; 3262105059Scognet} 3263105059Scognetstatic int 3264111158Scognettrm_initAdapter(PACB pACB, u_int16_t unit) 3265105059Scognet{ 3266105059Scognet PNVRAMTYPE pEEpromBuf; 3267105059Scognet u_int16_t wval; 3268105059Scognet u_int8_t bval; 3269105059Scognet 3270105059Scognet pEEpromBuf = &trm_eepromBuf[unit]; 3271105059Scognet 3272105059Scognet /* 250ms selection timeout */ 3273105059Scognet trm_reg_write8(SEL_TIMEOUT, TRMREG_SCSI_TIMEOUT); 3274105059Scognet /* Mask all the interrupt */ 3275105059Scognet trm_reg_write8(0x00, TRMREG_DMA_INTEN); 3276105059Scognet trm_reg_write8(0x00, TRMREG_SCSI_INTEN); 3277105059Scognet /* Reset SCSI module */ 3278105059Scognet trm_reg_write16(DO_RSTMODULE, TRMREG_SCSI_CONTROL); 3279105059Scognet /* program configuration 0 */ 3280105059Scognet pACB->Config = HCC_AUTOTERM | HCC_PARITY; 3281105059Scognet if (trm_reg_read8(TRMREG_GEN_STATUS) & WIDESCSI) 3282105059Scognet pACB->Config |= HCC_WIDE_CARD; 3283105059Scognet if (pEEpromBuf->NvramChannelCfg & NAC_POWERON_SCSI_RESET) 3284105059Scognet pACB->Config |= HCC_SCSI_RESET; 3285105059Scognet if (pACB->Config & HCC_PARITY) 3286105059Scognet bval = PHASELATCH | INITIATOR | BLOCKRST | PARITYCHECK; 3287105059Scognet else 3288105059Scognet bval = PHASELATCH | INITIATOR | BLOCKRST ; 3289105059Scognet trm_reg_write8(bval,TRMREG_SCSI_CONFIG0); 3290105059Scognet /* program configuration 1 */ 3291105059Scognet trm_reg_write8(0x13, TRMREG_SCSI_CONFIG1); 3292105059Scognet /* program Host ID */ 3293105059Scognet bval = pEEpromBuf->NvramScsiId; 3294105059Scognet trm_reg_write8(bval, TRMREG_SCSI_HOSTID); 3295105059Scognet /* set ansynchronous transfer */ 3296105059Scognet trm_reg_write8(0x00, TRMREG_SCSI_OFFSET); 3297105059Scognet /* Trun LED control off*/ 3298105059Scognet wval = trm_reg_read16(TRMREG_GEN_CONTROL) & 0x7F; 3299105059Scognet trm_reg_write16(wval, TRMREG_GEN_CONTROL); 3300105059Scognet /* DMA config */ 3301105059Scognet wval = trm_reg_read16(TRMREG_DMA_CONFIG) | DMA_ENHANCE; 3302105059Scognet trm_reg_write16(wval, TRMREG_DMA_CONFIG); 3303105059Scognet /* Clear pending interrupt status */ 3304105059Scognet trm_reg_read8(TRMREG_SCSI_INTSTATUS); 3305105059Scognet /* Enable SCSI interrupt */ 3306105059Scognet trm_reg_write8(0x7F, TRMREG_SCSI_INTEN); 3307105059Scognet trm_reg_write8(EN_SCSIINTR, TRMREG_DMA_INTEN); 3308105059Scognet return (0); 3309105059Scognet} 3310105059Scognet 3311111158Scognetstatic void 3312111158Scognettrm_mapSRB(void *arg, bus_dma_segment_t *segs, int nseg, int error) 3313111158Scognet{ 3314111158Scognet PACB pACB; 3315111158Scognet 3316111158Scognet pACB = (PACB)arg; 3317111158Scognet pACB->srb_physbase = segs->ds_addr; 3318111158Scognet} 3319111158Scognet 3320111158Scognetstatic void 3321111158Scognettrm_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 3322111158Scognet{ 3323111158Scognet bus_addr_t *baddr; 3324111158Scognet 3325111158Scognet baddr = (bus_addr_t *)arg; 3326111158Scognet *baddr = segs->ds_addr; 3327111158Scognet} 3328111158Scognet 3329105059Scognetstatic PACB 3330111158Scognettrm_init(u_int16_t unit, device_t dev) 3331105059Scognet{ 3332105059Scognet PACB pACB; 3333119690Sjhb int rid = PCIR_BAR(0), i = 0, j = 0; 3334111158Scognet u_int16_t adaptType = 0; 3335105059Scognet 3336111158Scognet pACB = (PACB) device_get_softc(dev); 3337105059Scognet if (!pACB) { 3338105059Scognet printf("trm%d: cannot allocate ACB !\n", unit); 3339105059Scognet return (NULL); 3340105059Scognet } 3341127135Snjl pACB->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 3342127135Snjl &rid, RF_ACTIVE); 3343107928Scognet if (pACB->iores == NULL) { 3344105059Scognet printf("trm_init: bus_alloc_resource failed!\n"); 3345105059Scognet return (NULL); 3346105059Scognet } 3347111158Scognet switch (pci_get_devid(dev)) { 3348111158Scognet case PCI_DEVICEID_TRMS1040: 3349111158Scognet adaptType = 0; 3350111158Scognet break; 3351111158Scognet case PCI_DEVICEID_TRMS2080: 3352111158Scognet adaptType = 1; 3353111158Scognet break; 3354111158Scognet default: 3355111158Scognet printf("trm_init %d: unknown adapter type!\n", unit); 3356111158Scognet goto bad; 3357111158Scognet } 3358111158Scognet pACB->dev = dev; 3359107928Scognet pACB->tag = rman_get_bustag(pACB->iores); 3360107928Scognet pACB->bsh = rman_get_bushandle(pACB->iores); 3361117126Sscottl if (bus_dma_tag_create( 3362232874Sscottl /*parent_dmat*/ bus_get_dma_tag(dev), 3363232874Sscottl /*alignment*/ 1, 3364232874Sscottl /*boundary*/ 0, 3365232874Sscottl /*lowaddr*/ BUS_SPACE_MAXADDR, 3366232874Sscottl /*highaddr*/ BUS_SPACE_MAXADDR, 3367232874Sscottl /*filter*/ NULL, 3368232874Sscottl /*filterarg*/ NULL, 3369232874Sscottl /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 3370232874Sscottl /*nsegments*/ BUS_SPACE_UNRESTRICTED, 3371232874Sscottl /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3372232874Sscottl /*flags*/ 0, 3373232874Sscottl /*lockfunc*/ NULL, 3374232874Sscottl /*lockarg*/ NULL, 3375232874Sscottl /* dmat */ &pACB->parent_dmat) != 0) 3376232874Sscottl goto bad; 3377232874Sscottl if (bus_dma_tag_create( 3378117126Sscottl /*parent_dmat*/ pACB->parent_dmat, 3379117126Sscottl /*alignment*/ 1, 3380117126Sscottl /*boundary*/ 0, 3381117126Sscottl /*lowaddr*/ BUS_SPACE_MAXADDR, 3382117126Sscottl /*highaddr*/ BUS_SPACE_MAXADDR, 3383117126Sscottl /*filter*/ NULL, 3384117126Sscottl /*filterarg*/ NULL, 3385281826Smav /*maxsize*/ TRM_MAXPHYS, 3386117126Sscottl /*nsegments*/ TRM_NSEG, 3387117126Sscottl /*maxsegsz*/ TRM_MAXTRANSFER_SIZE, 3388117126Sscottl /*flags*/ BUS_DMA_ALLOCNOW, 3389117126Sscottl /*lockfunc*/ busdma_lock_mutex, 3390117126Sscottl /*lockarg*/ &Giant, 3391117126Sscottl /* dmat */ &pACB->buffer_dmat) != 0) 3392107928Scognet goto bad; 3393111158Scognet /* DMA tag for our ccb structures */ 3394116813Scognet if (bus_dma_tag_create( 3395111158Scognet /*parent_dmat*/pACB->parent_dmat, 3396111158Scognet /*alignment*/ 1, 3397111158Scognet /*boundary*/ 0, 3398111158Scognet /*lowaddr*/ BUS_SPACE_MAXADDR, 3399111158Scognet /*highaddr*/ BUS_SPACE_MAXADDR, 3400111158Scognet /*filter*/ NULL, 3401111158Scognet /*filterarg*/ NULL, 3402111158Scognet /*maxsize*/ TRM_MAX_SRB_CNT * sizeof(TRM_SRB), 3403111158Scognet /*nsegments*/ 1, 3404111158Scognet /*maxsegsz*/ TRM_MAXTRANSFER_SIZE, 3405117126Sscottl /*flags*/ 0, 3406117126Sscottl /*lockfunc*/ busdma_lock_mutex, 3407117126Sscottl /*lockarg*/ &Giant, 3408111158Scognet /*dmat*/ &pACB->srb_dmat) != 0) { 3409111158Scognet printf("trm_init %d: bus_dma_tag_create SRB failure\n", unit); 3410111158Scognet goto bad; 3411111158Scognet } 3412111158Scognet if (bus_dmamem_alloc(pACB->srb_dmat, (void **)&pACB->pFreeSRB, 3413111158Scognet BUS_DMA_NOWAIT, &pACB->srb_dmamap) != 0) { 3414111158Scognet printf("trm_init %d: bus_dmamem_alloc SRB failure\n", unit); 3415111158Scognet goto bad; 3416111158Scognet } 3417111158Scognet bus_dmamap_load(pACB->srb_dmat, pACB->srb_dmamap, pACB->pFreeSRB, 3418111158Scognet TRM_MAX_SRB_CNT * sizeof(TRM_SRB), trm_mapSRB, pACB, 3419111158Scognet /* flags */0); 3420111158Scognet /* Create, allocate, and map DMA buffers for autosense data */ 3421232874Sscottl if (bus_dma_tag_create( 3422232874Sscottl /*parent_dmat*/pACB->parent_dmat, 3423232874Sscottl /*alignment*/1, 3424111158Scognet /*boundary*/0, 3425111158Scognet /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 3426111158Scognet /*highaddr*/BUS_SPACE_MAXADDR, 3427111158Scognet /*filter*/NULL, /*filterarg*/NULL, 3428111158Scognet sizeof(struct scsi_sense_data) * TRM_MAX_SRB_CNT, 3429111158Scognet /*nsegments*/1, 3430111158Scognet /*maxsegsz*/TRM_MAXTRANSFER_SIZE, 3431117126Sscottl /*flags*/0, /*lockfunc*/busdma_lock_mutex, 3432117126Sscottl /*lockarg*/&Giant, &pACB->sense_dmat) != 0) { 3433111158Scognet if (bootverbose) 3434111158Scognet device_printf(dev, "cannot create sense buffer dmat\n"); 3435111158Scognet goto bad; 3436111158Scognet } 3437111158Scognet 3438111158Scognet if (bus_dmamem_alloc(pACB->sense_dmat, (void **)&pACB->sense_buffers, 3439111158Scognet BUS_DMA_NOWAIT, &pACB->sense_dmamap) != 0) 3440111158Scognet goto bad; 3441111158Scognet 3442111158Scognet bus_dmamap_load(pACB->sense_dmat, pACB->sense_dmamap, 3443111158Scognet pACB->sense_buffers, 3444111158Scognet sizeof(struct scsi_sense_data) * TRM_MAX_SRB_CNT, 3445111158Scognet trm_dmamap_cb, &pACB->sense_busaddr, /*flags*/0); 3446111158Scognet 3447105059Scognet trm_check_eeprom(&trm_eepromBuf[unit],pACB); 3448111158Scognet trm_initACB(pACB, adaptType, unit); 3449111158Scognet for (i = 0; i < (pACB->max_id + 1); i++) { 3450111158Scognet if (pACB->AdaptSCSIID == i) 3451111158Scognet continue; 3452111158Scognet for(j = 0; j < (pACB->max_lun + 1); j++) { 3453111158Scognet pACB->scan_devices[i][j] = 1; 3454111158Scognet /* we assume we need to scan all devices */ 3455111158Scognet trm_initDCB(pACB, &pACB->DCBarray[i][j], unit, i, j); 3456111158Scognet } 3457111158Scognet } 3458111158Scognet bzero(pACB->pFreeSRB, TRM_MAX_SRB_CNT * sizeof(TRM_SRB)); 3459126725Scognet if (bus_dma_tag_create( 3460232874Sscottl /*parent_dmat*/pACB->parent_dmat, 3461126725Scognet /*alignment*/ 1, 3462126725Scognet /*boundary*/ 0, 3463126725Scognet /*lowaddr*/ BUS_SPACE_MAXADDR, 3464126725Scognet /*highaddr*/ BUS_SPACE_MAXADDR, 3465126725Scognet /*filter*/ NULL, 3466126725Scognet /*filterarg*/ NULL, 3467126725Scognet /*maxsize*/ TRM_MAX_SG_LISTENTRY * sizeof(SGentry), 3468126725Scognet /*nsegments*/ 1, 3469126725Scognet /*maxsegsz*/ TRM_MAXTRANSFER_SIZE, 3470126725Scognet /*flags*/ 0, 3471126725Scognet /*lockfunc*/ busdma_lock_mutex, 3472126725Scognet /*lockarg*/ &Giant, 3473126725Scognet /*dmat*/ &pACB->sg_dmat) != 0) 3474126725Scognet goto bad; 3475126725Scognet 3476111158Scognet if (trm_initSRB(pACB)) { 3477111158Scognet printf("trm_initSRB: error\n"); 3478111158Scognet goto bad; 3479111158Scognet } 3480111158Scognet if (trm_initAdapter(pACB, unit)) { 3481105059Scognet printf("trm_initAdapter: initial ERROR\n"); 3482107928Scognet goto bad; 3483105059Scognet } 3484105059Scognet return (pACB); 3485107928Scognetbad: 3486107928Scognet if (pACB->iores) 3487119690Sjhb bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), 3488107928Scognet pACB->iores); 3489111158Scognet if (pACB->sense_dmamap) { 3490111158Scognet bus_dmamap_unload(pACB->sense_dmat, pACB->sense_dmamap); 3491111158Scognet bus_dmamem_free(pACB->sense_dmat, pACB->sense_buffers, 3492111158Scognet pACB->sense_dmamap); 3493111158Scognet bus_dmamap_destroy(pACB->sense_dmat, pACB->sense_dmamap); 3494111158Scognet } 3495111158Scognet if (pACB->sense_dmat) 3496111158Scognet bus_dma_tag_destroy(pACB->sense_dmat); 3497126725Scognet if (pACB->sg_dmat) { 3498126725Scognet trm_destroySRB(pACB); 3499126725Scognet bus_dma_tag_destroy(pACB->sg_dmat); 3500126725Scognet } 3501111158Scognet if (pACB->srb_dmamap) { 3502111158Scognet bus_dmamap_unload(pACB->srb_dmat, pACB->srb_dmamap); 3503111158Scognet bus_dmamem_free(pACB->srb_dmat, pACB->pFreeSRB, 3504111158Scognet pACB->srb_dmamap); 3505111158Scognet bus_dmamap_destroy(pACB->srb_dmat, pACB->srb_dmamap); 3506111158Scognet } 3507111158Scognet if (pACB->srb_dmat) 3508111158Scognet bus_dma_tag_destroy(pACB->srb_dmat); 3509107928Scognet if (pACB->buffer_dmat) 3510107928Scognet bus_dma_tag_destroy(pACB->buffer_dmat); 3511232874Sscottl if (pACB->parent_dmat) 3512232874Sscottl bus_dma_tag_destroy(pACB->parent_dmat); 3513107928Scognet return (NULL); 3514105059Scognet} 3515105059Scognet 3516105059Scognetstatic int 3517111158Scognettrm_attach(device_t dev) 3518105059Scognet{ 3519105059Scognet struct cam_devq *device_Q; 3520105059Scognet u_long device_id; 3521105059Scognet PACB pACB = 0; 3522105059Scognet int rid = 0; 3523111158Scognet int unit = device_get_unit(dev); 3524105059Scognet 3525111158Scognet device_id = pci_get_devid(dev); 3526105059Scognet /* 3527105059Scognet * These cards do not allow memory mapped accesses 3528105059Scognet */ 3529111158Scognet if ((pACB = trm_init((u_int16_t) unit, 3530111158Scognet dev)) == NULL) { 3531111158Scognet printf("trm%d: trm_init error!\n",unit); 3532105059Scognet return (ENXIO); 3533111158Scognet } 3534105059Scognet /* After setting up the adapter, map our interrupt */ 3535105059Scognet /* 3536105059Scognet * Now let the CAM generic SCSI layer find the SCSI devices on the bus 3537105059Scognet * start queue to reset to the idle loop. 3538105059Scognet * Create device queue of SIM(s) 3539105059Scognet * (MAX_START_JOB - 1) : max_sim_transactions 3540105059Scognet */ 3541127135Snjl pACB->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 3542127135Snjl RF_SHAREABLE | RF_ACTIVE); 3543107928Scognet if (pACB->irq == NULL || 3544111158Scognet bus_setup_intr(dev, pACB->irq, 3545166901Spiso INTR_TYPE_CAM, NULL, trm_Interrupt, pACB, &pACB->ih)) { 3546105059Scognet printf("trm%d: register Interrupt handler error!\n", unit); 3547107928Scognet goto bad; 3548105059Scognet } 3549111158Scognet device_Q = cam_simq_alloc(TRM_MAX_START_JOB); 3550105059Scognet if (device_Q == NULL){ 3551105059Scognet printf("trm%d: device_Q == NULL !\n",unit); 3552107928Scognet goto bad; 3553105059Scognet } 3554105059Scognet /* 3555105059Scognet * Now tell the generic SCSI layer 3556105059Scognet * about our bus. 3557105059Scognet * If this is the xpt layer creating a sim, then it's OK 3558105059Scognet * to wait for an allocation. 3559105059Scognet * XXX Should we pass in a flag to indicate that wait is OK? 3560105059Scognet * 3561105059Scognet * SIM allocation 3562105059Scognet * 3563105059Scognet * SCSI Interface Modules 3564105059Scognet * The sim driver creates a sim for each controller. The sim device 3565105059Scognet * queue is separately created in order to allow resource sharing betwee 3566105059Scognet * sims. For instance, a driver may create one sim for each channel of 3567105059Scognet * a multi-channel controller and use the same queue for each channel. 3568105059Scognet * In this way, the queue resources are shared across all the channels 3569105059Scognet * of the multi-channel controller. 3570105059Scognet * trm_action : sim_action_func 3571105059Scognet * trm_poll : sim_poll_func 3572111119Simp * "trm" : sim_name ,if sim_name = "xpt" ..M_DEVBUF,M_WAITOK 3573105059Scognet * pACB : *softc if sim_name <> "xpt" ..M_DEVBUF,M_NOWAIT 3574105059Scognet * pACB->unit : unit 3575105059Scognet * 1 : max_dev_transactions 3576105059Scognet * MAX_TAGS : max_tagged_dev_transactions 3577105059Scognet * 3578105059Scognet * *******Construct our first channel SIM entry 3579105059Scognet */ 3580105059Scognet pACB->psim = cam_sim_alloc(trm_action, 3581105059Scognet trm_poll, 3582105059Scognet "trm", 3583105059Scognet pACB, 3584105059Scognet unit, 3585168752Sscottl &Giant, 3586105059Scognet 1, 3587111158Scognet TRM_MAX_TAGS_CMD_QUEUE, 3588105059Scognet device_Q); 3589105059Scognet if (pACB->psim == NULL) { 3590105059Scognet printf("trm%d: SIM allocate fault !\n",unit); 3591105059Scognet cam_simq_free(device_Q); /* SIM allocate fault*/ 3592107928Scognet goto bad; 3593105059Scognet } 3594170872Sscottl if (xpt_bus_register(pACB->psim, dev, 0) != CAM_SUCCESS) { 3595105059Scognet printf("trm%d: xpt_bus_register fault !\n",unit); 3596107928Scognet goto bad; 3597105059Scognet } 3598105059Scognet if (xpt_create_path(&pACB->ppath, 3599105059Scognet NULL, 3600105059Scognet cam_sim_path(pACB->psim), 3601105059Scognet CAM_TARGET_WILDCARD, 3602105059Scognet CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 3603105059Scognet printf("trm%d: xpt_create_path fault !\n",unit); 3604105059Scognet xpt_bus_deregister(cam_sim_path(pACB->psim)); 3605107928Scognet goto bad; 3606105059Scognet } 3607105059Scognet return (0); 3608107928Scognetbad: 3609107928Scognet if (pACB->iores) 3610119690Sjhb bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), 3611107928Scognet pACB->iores); 3612126725Scognet if (pACB->sg_dmat) { 3613126725Scognet trm_destroySRB(pACB); 3614126725Scognet bus_dma_tag_destroy(pACB->sg_dmat); 3615126725Scognet } 3616126725Scognet 3617111158Scognet if (pACB->srb_dmamap) { 3618111158Scognet bus_dmamap_unload(pACB->srb_dmat, pACB->srb_dmamap); 3619111158Scognet bus_dmamem_free(pACB->srb_dmat, pACB->pFreeSRB, 3620111158Scognet pACB->srb_dmamap); 3621111158Scognet bus_dmamap_destroy(pACB->srb_dmat, pACB->srb_dmamap); 3622111158Scognet } 3623111158Scognet if (pACB->srb_dmat) 3624111158Scognet bus_dma_tag_destroy(pACB->srb_dmat); 3625111158Scognet if (pACB->sense_dmamap) { 3626111158Scognet bus_dmamap_unload(pACB->sense_dmat, pACB->sense_dmamap); 3627111158Scognet bus_dmamem_free(pACB->sense_dmat, pACB->sense_buffers, 3628111158Scognet pACB->sense_dmamap); 3629111158Scognet bus_dmamap_destroy(pACB->sense_dmat, pACB->sense_dmamap); 3630111158Scognet } 3631111158Scognet if (pACB->sense_dmat) 3632111158Scognet bus_dma_tag_destroy(pACB->sense_dmat); 3633107928Scognet if (pACB->buffer_dmat) 3634107928Scognet bus_dma_tag_destroy(pACB->buffer_dmat); 3635107928Scognet if (pACB->ih) 3636111158Scognet bus_teardown_intr(dev, pACB->irq, pACB->ih); 3637107928Scognet if (pACB->irq) 3638111158Scognet bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irq); 3639107928Scognet if (pACB->psim) 3640107928Scognet cam_sim_free(pACB->psim, TRUE); 3641107928Scognet 3642107928Scognet return (ENXIO); 3643107928Scognet 3644105059Scognet} 3645105059Scognet 3646105059Scognet/* 3647105059Scognet* pci_device 3648105059Scognet* trm_probe (device_t tag, pcidi_t type) 3649105059Scognet* 3650105059Scognet*/ 3651105059Scognetstatic int 3652111158Scognettrm_probe(device_t dev) 3653105059Scognet{ 3654111158Scognet switch (pci_get_devid(dev)) { 3655111158Scognet case PCI_DEVICEID_TRMS1040: 3656111158Scognet device_set_desc(dev, 3657105059Scognet "Tekram DC395U/UW/F DC315/U Fast20 Wide SCSI Adapter"); 3658142880Simp return (BUS_PROBE_DEFAULT); 3659111158Scognet case PCI_DEVICEID_TRMS2080: 3660111158Scognet device_set_desc(dev, 3661111158Scognet "Tekram DC395U2D/U2W Fast40 Wide SCSI Adapter"); 3662142880Simp return (BUS_PROBE_DEFAULT); 3663111158Scognet default: 3664105059Scognet return (ENXIO); 3665111158Scognet } 3666105059Scognet} 3667105059Scognet 3668105059Scognetstatic int 3669107928Scognettrm_detach(device_t dev) 3670105059Scognet{ 3671107928Scognet PACB pACB = device_get_softc(dev); 3672107928Scognet 3673119690Sjhb bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), pACB->iores); 3674126725Scognet trm_destroySRB(pACB); 3675126725Scognet bus_dma_tag_destroy(pACB->sg_dmat); 3676111158Scognet bus_dmamap_unload(pACB->srb_dmat, pACB->srb_dmamap); 3677111158Scognet bus_dmamem_free(pACB->srb_dmat, pACB->pFreeSRB, 3678111158Scognet pACB->srb_dmamap); 3679111158Scognet bus_dmamap_destroy(pACB->srb_dmat, pACB->srb_dmamap); 3680111158Scognet bus_dma_tag_destroy(pACB->srb_dmat); 3681111158Scognet bus_dmamap_unload(pACB->sense_dmat, pACB->sense_dmamap); 3682111158Scognet bus_dmamem_free(pACB->sense_dmat, pACB->sense_buffers, 3683111158Scognet pACB->sense_dmamap); 3684111158Scognet bus_dmamap_destroy(pACB->sense_dmat, pACB->sense_dmamap); 3685111158Scognet bus_dma_tag_destroy(pACB->sense_dmat); 3686111158Scognet bus_dma_tag_destroy(pACB->buffer_dmat); 3687107928Scognet bus_teardown_intr(dev, pACB->irq, pACB->ih); 3688107928Scognet bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irq); 3689105059Scognet xpt_async(AC_LOST_DEVICE, pACB->ppath, NULL); 3690105059Scognet xpt_free_path(pACB->ppath); 3691105059Scognet xpt_bus_deregister(cam_sim_path(pACB->psim)); 3692105059Scognet cam_sim_free(pACB->psim, TRUE); 3693105059Scognet return (0); 3694105059Scognet} 3695105059Scognetstatic device_method_t trm_methods[] = { 3696105059Scognet /* Device interface */ 3697105059Scognet DEVMETHOD(device_probe, trm_probe), 3698105059Scognet DEVMETHOD(device_attach, trm_attach), 3699105059Scognet DEVMETHOD(device_detach, trm_detach), 3700105059Scognet { 0, 0 } 3701105059Scognet}; 3702105059Scognet 3703105059Scognetstatic driver_t trm_driver = { 3704105059Scognet "trm", trm_methods, sizeof(struct _ACB) 3705105059Scognet}; 3706105059Scognet 3707105059Scognetstatic devclass_t trm_devclass; 3708105059ScognetDRIVER_MODULE(trm, pci, trm_driver, trm_devclass, 0, 0); 3709165102SmjacobMODULE_DEPEND(trm, pci, 1, 1, 1); 3710124318ScognetMODULE_DEPEND(trm, cam, 1, 1, 1); 3711