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$"); 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#if 0 477105059Scognet /* XXX Need a timeout handler */ 478105059Scognet ccb->ccb_h.timeout_ch = timeout(trmtimeout, (caddr_t)srb, (ccb->ccb_h.timeout * hz) / 1000); 479105059Scognet#endif 480105059Scognet trm_SendSRB(pACB, pSRB); 481105059Scognet splx(flags); 482105059Scognet return; 483105059Scognet} 484105059Scognet 485105059Scognetstatic void 486105059Scognettrm_SendSRB(PACB pACB, PSRB pSRB) 487105059Scognet{ 488105059Scognet PDCB pDCB; 489105059Scognet 490105059Scognet pDCB = pSRB->pSRBDCB; 491111158Scognet if (!(pDCB->MaxActiveCommandCnt > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) 492105059Scognet || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV))) { 493111158Scognet TRM_DPRINTF("pDCB->MaxCommand=%d \n",pDCB->MaxActiveCommandCnt); 494105059Scognet TRM_DPRINTF("pDCB->GoingSRBCnt=%d \n",pDCB->GoingSRBCnt); 495105059Scognet TRM_DPRINTF("pACB->pActiveDCB=%8x \n",(u_int)pACB->pActiveDCB); 496105059Scognet TRM_DPRINTF("pACB->ACBFlag=%x \n",pACB->ACBFlag); 497105059Scognet trm_SRBwaiting(pDCB, pSRB); 498105059Scognet goto SND_EXIT; 499105059Scognet } 500105059Scognet 501105059Scognet if (pDCB->pWaitingSRB) { 502105059Scognet trm_SRBwaiting(pDCB, pSRB); 503105059Scognet pSRB = pDCB->pWaitingSRB; 504105059Scognet pDCB->pWaitingSRB = pSRB->pNextSRB; 505105059Scognet pSRB->pNextSRB = NULL; 506105059Scognet } 507105059Scognet 508105059Scognet if (!trm_StartSCSI(pACB, pDCB, pSRB)) { 509105059Scognet /* 510105059Scognet * If trm_StartSCSI return 0 : 511105059Scognet * current interrupt status is interrupt enable 512105059Scognet * It's said that SCSI processor is unoccupied 513105059Scognet */ 514105059Scognet pDCB->GoingSRBCnt++; /* stack waiting SRB*/ 515105059Scognet if (pDCB->pGoingSRB) { 516105059Scognet pDCB->pGoingLastSRB->pNextSRB = pSRB; 517105059Scognet pDCB->pGoingLastSRB = pSRB; 518105059Scognet } else { 519105059Scognet pDCB->pGoingSRB = pSRB; 520105059Scognet pDCB->pGoingLastSRB = pSRB; 521105059Scognet } 522105059Scognet } else { 523105059Scognet /* 524105059Scognet * If trm_StartSCSI return 1 : 525105059Scognet * current interrupt status is interrupt disreenable 526105059Scognet * It's said that SCSI processor has more one SRB need to do 527105059Scognet */ 528105059Scognet trm_RewaitSRB0(pDCB, pSRB); 529105059Scognet } 530105059ScognetSND_EXIT: 531105059Scognet return; 532105059Scognet} 533105059Scognet 534105059Scognet 535105059Scognetstatic void 536105059Scognettrm_action(struct cam_sim *psim, union ccb *pccb) 537105059Scognet{ 538105059Scognet PACB pACB; 539111158Scognet int actionflags; 540105059Scognet u_int target_id,target_lun; 541105059Scognet 542105059Scognet CAM_DEBUG(pccb->ccb_h.path, CAM_DEBUG_TRACE, ("trm_action\n")); 543105059Scognet 544111158Scognet actionflags = splcam(); 545105059Scognet pACB = (PACB) cam_sim_softc(psim); 546105059Scognet target_id = pccb->ccb_h.target_id; 547105059Scognet target_lun = pccb->ccb_h.target_lun; 548105059Scognet 549105059Scognet switch (pccb->ccb_h.func_code) { 550105059Scognet case XPT_NOOP: 551105059Scognet TRM_DPRINTF(" XPT_NOOP \n"); 552105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 553105059Scognet xpt_done(pccb); 554105059Scognet break; 555105059Scognet /* 556105059Scognet * Execute the requested I/O operation 557105059Scognet */ 558105059Scognet case XPT_SCSI_IO: { 559105059Scognet PDCB pDCB = NULL; 560105059Scognet PSRB pSRB; 561105059Scognet struct ccb_scsiio *pcsio; 562246713Skib int error; 563105059Scognet 564105059Scognet pcsio = &pccb->csio; 565105059Scognet TRM_DPRINTF(" XPT_SCSI_IO \n"); 566105059Scognet TRM_DPRINTF("trm: target_id= %d target_lun= %d \n" 567105059Scognet ,target_id, target_lun); 568105059Scognet TRM_DPRINTF( 569105059Scognet "pACB->scan_devices[target_id][target_lun]= %d \n" 570105059Scognet ,pACB->scan_devices[target_id][target_lun]); 571116813Scognet if ((pccb->ccb_h.status & CAM_STATUS_MASK) != 572116813Scognet CAM_REQ_INPROG) { 573111158Scognet xpt_done(pccb); 574111158Scognet splx(actionflags); 575111158Scognet return; 576111158Scognet } 577111158Scognet pDCB = &pACB->DCBarray[target_id][target_lun]; 578116813Scognet if (!(pDCB->DCBstatus & DS_IN_QUEUE)) { 579111158Scognet pACB->scan_devices[target_id][target_lun] = 1; 580111158Scognet trm_initDCB(pACB, pDCB, pACB->AdapterUnit, 581111158Scognet target_id, target_lun); 582111158Scognet } 583105059Scognet /* 584105059Scognet * Assign an SRB and connect it with this ccb. 585105059Scognet */ 586105059Scognet pSRB = trm_GetSRB(pACB); 587105059Scognet if (!pSRB) { 588105059Scognet /* Freeze SIMQ */ 589105059Scognet pccb->ccb_h.status = CAM_RESRC_UNAVAIL; 590105059Scognet xpt_done(pccb); 591111158Scognet splx(actionflags); 592105059Scognet return; 593105059Scognet } 594105059Scognet pSRB->pSRBDCB = pDCB; 595105059Scognet pccb->ccb_h.ccb_trmsrb_ptr = pSRB; 596105059Scognet pccb->ccb_h.ccb_trmacb_ptr = pACB; 597105059Scognet pSRB->pccb = pccb; 598105059Scognet pSRB->ScsiCmdLen = pcsio->cdb_len; 599105059Scognet /* 600105059Scognet * move layer of CAM command block to layer of SCSI 601105059Scognet * Request Block for SCSI processor command doing 602105059Scognet */ 603116813Scognet if ((pccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { 604116813Scognet if ((pccb->ccb_h.flags & CAM_CDB_PHYS) == 0) { 605111158Scognet bcopy(pcsio->cdb_io.cdb_ptr,pSRB->CmdBlock 606111158Scognet ,pcsio->cdb_len); 607111158Scognet } else { 608111158Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 609111158Scognet pSRB->pNextSRB = pACB->pFreeSRB; 610111158Scognet pACB->pFreeSRB= pSRB; 611111158Scognet xpt_done(pccb); 612111158Scognet splx(actionflags); 613111158Scognet return; 614111158Scognet } 615111158Scognet } else 616111158Scognet bcopy(pcsio->cdb_io.cdb_bytes, 617111158Scognet pSRB->CmdBlock, pcsio->cdb_len); 618246713Skib error = bus_dmamap_load_ccb(pACB->buffer_dmat, 619105059Scognet pSRB->dmamap, 620246713Skib pccb, 621105059Scognet trm_ExecuteSRB, 622105059Scognet pSRB, 623105059Scognet 0); 624246713Skib if (error == EINPROGRESS) { 625246713Skib xpt_freeze_simq(pACB->psim, 1); 626246713Skib pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 627246713Skib } 628105059Scognet break; 629246713Skib } 630105059Scognet case XPT_GDEV_TYPE: 631105059Scognet TRM_DPRINTF(" XPT_GDEV_TYPE \n"); 632105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 633105059Scognet xpt_done(pccb); 634105059Scognet break; 635105059Scognet case XPT_GDEVLIST: 636105059Scognet TRM_DPRINTF(" XPT_GDEVLIST \n"); 637105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 638105059Scognet xpt_done(pccb); 639105059Scognet break; 640105059Scognet /* 641105059Scognet * Path routing inquiry 642105059Scognet * Path Inquiry CCB 643105059Scognet */ 644105059Scognet case XPT_PATH_INQ: { 645105059Scognet struct ccb_pathinq *cpi = &pccb->cpi; 646105059Scognet 647105059Scognet TRM_DPRINTF(" XPT_PATH_INQ \n"); 648105059Scognet cpi->version_num = 1; 649105059Scognet cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; 650105059Scognet cpi->target_sprt = 0; 651105059Scognet cpi->hba_misc = 0; 652105059Scognet cpi->hba_eng_cnt = 0; 653105059Scognet cpi->max_target = 15 ; 654105059Scognet cpi->max_lun = pACB->max_lun; /* 7 or 0 */ 655105059Scognet cpi->initiator_id = pACB->AdaptSCSIID; 656105059Scognet cpi->bus_id = cam_sim_bus(psim); 657111158Scognet cpi->base_transfer_speed = 3300; 658105059Scognet strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 659105059Scognet strncpy(cpi->hba_vid, "Tekram_TRM", HBA_IDLEN); 660105059Scognet strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 661105059Scognet cpi->unit_number = cam_sim_unit(psim); 662163816Smjacob cpi->transport = XPORT_SPI; 663163816Smjacob cpi->transport_version = 2; 664163816Smjacob cpi->protocol = PROTO_SCSI; 665163816Smjacob cpi->protocol_version = SCSI_REV_2; 666105059Scognet cpi->ccb_h.status = CAM_REQ_CMP; 667105059Scognet xpt_done(pccb); 668105059Scognet } 669105059Scognet break; 670105059Scognet /* 671105059Scognet * Release a frozen SIM queue 672105059Scognet * Release SIM Queue 673105059Scognet */ 674105059Scognet case XPT_REL_SIMQ: 675105059Scognet TRM_DPRINTF(" XPT_REL_SIMQ \n"); 676105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 677105059Scognet xpt_done(pccb); 678105059Scognet break; 679105059Scognet /* 680105059Scognet * Set Asynchronous Callback Parameters 681105059Scognet * Set Asynchronous Callback CCB 682105059Scognet */ 683105059Scognet case XPT_SASYNC_CB: 684105059Scognet TRM_DPRINTF(" XPT_SASYNC_CB \n"); 685105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 686105059Scognet xpt_done(pccb); 687105059Scognet break; 688105059Scognet /* 689105059Scognet * Set device type information 690105059Scognet * Set Device Type CCB 691105059Scognet */ 692105059Scognet case XPT_SDEV_TYPE: 693105059Scognet TRM_DPRINTF(" XPT_SDEV_TYPE \n"); 694105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 695105059Scognet xpt_done(pccb); 696105059Scognet break; 697105059Scognet /* 698105059Scognet * Get EDT entries matching the given pattern 699105059Scognet */ 700105059Scognet case XPT_DEV_MATCH: 701105059Scognet TRM_DPRINTF(" XPT_DEV_MATCH \n"); 702105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 703105059Scognet xpt_done(pccb); 704105059Scognet break; 705105059Scognet /* 706105059Scognet * Turn on debugging for a bus, target or lun 707105059Scognet */ 708105059Scognet case XPT_DEBUG: 709105059Scognet TRM_DPRINTF(" XPT_DEBUG \n"); 710105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 711105059Scognet xpt_done(pccb); 712105059Scognet break; 713105059Scognet /* 714105059Scognet * XPT_ABORT = 0x10, Abort the specified CCB 715105059Scognet * Abort XPT request CCB 716105059Scognet */ 717105059Scognet case XPT_ABORT: 718105059Scognet TRM_DPRINTF(" XPT_ABORT \n"); 719105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 720105059Scognet xpt_done(pccb); 721105059Scognet break; 722105059Scognet /* 723105059Scognet * Reset the specified SCSI bus 724105059Scognet * Reset SCSI Bus CCB 725105059Scognet */ 726105059Scognet case XPT_RESET_BUS: { 727105059Scognet int i; 728105059Scognet 729105059Scognet TRM_DPRINTF(" XPT_RESET_BUS \n"); 730105059Scognet trm_reset(pACB); 731105059Scognet pACB->ACBFlag=0; 732105059Scognet for (i=0; i<500; i++) 733105059Scognet DELAY(1000); 734105059Scognet pccb->ccb_h.status = CAM_REQ_CMP; 735105059Scognet xpt_done(pccb); 736105059Scognet } 737105059Scognet break; 738105059Scognet /* 739105059Scognet * Bus Device Reset the specified SCSI device 740105059Scognet * Reset SCSI Device CCB 741105059Scognet */ 742105059Scognet case XPT_RESET_DEV: 743105059Scognet /* 744105059Scognet * Don't (yet?) support vendor 745105059Scognet * specific commands. 746105059Scognet */ 747105059Scognet TRM_DPRINTF(" XPT_RESET_DEV \n"); 748105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 749105059Scognet xpt_done(pccb); 750105059Scognet break; 751105059Scognet /* 752105059Scognet * Terminate the I/O process 753105059Scognet * Terminate I/O Process Request CCB 754105059Scognet */ 755105059Scognet case XPT_TERM_IO: 756105059Scognet TRM_DPRINTF(" XPT_TERM_IO \n"); 757105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 758105059Scognet xpt_done(pccb); 759105059Scognet break; 760105059Scognet /* 761105059Scognet * Get/Set transfer rate/width/disconnection/tag queueing 762105059Scognet * settings 763105059Scognet * (GET) default/user transfer settings for the target 764105059Scognet */ 765105059Scognet case XPT_GET_TRAN_SETTINGS: { 766163816Smjacob struct ccb_trans_settings *cts = &pccb->cts; 767105059Scognet int intflag; 768105059Scognet struct trm_transinfo *tinfo; 769105059Scognet PDCB pDCB; 770163816Smjacob struct ccb_trans_settings_scsi *scsi = 771163816Smjacob &cts->proto_specific.scsi; 772163816Smjacob struct ccb_trans_settings_spi *spi = 773163816Smjacob &cts->xport_specific.spi; 774163816Smjacob 775163816Smjacob cts->protocol = PROTO_SCSI; 776163816Smjacob cts->protocol_version = SCSI_REV_2; 777163816Smjacob cts->transport = XPORT_SPI; 778163816Smjacob cts->transport_version = 2; 779163816Smjacob 780105059Scognet TRM_DPRINTF(" XPT_GET_TRAN_SETTINGS \n"); 781111158Scognet pDCB = &pACB->DCBarray[target_id][target_lun]; 782105059Scognet intflag = splcam(); 783105059Scognet /* 784105059Scognet * disable interrupt 785105059Scognet */ 786163816Smjacob if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { 787163816Smjacob /* current transfer settings */ 788163816Smjacob if (pDCB->tinfo.disc_tag & TRM_CUR_DISCENB) 789163816Smjacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 790163816Smjacob else 791163816Smjacob spi->flags = 0;/* no tag & disconnect */ 792163816Smjacob if (pDCB->tinfo.disc_tag & TRM_CUR_TAGENB) 793163816Smjacob scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 794163816Smjacob tinfo = &pDCB->tinfo.current; 795163816Smjacob TRM_DPRINTF("CURRENT: cts->flags= %2x \n", 796163816Smjacob cts->flags); 797163816Smjacob } else { 798163816Smjacob /* default(user) transfer settings */ 799163816Smjacob if (pDCB->tinfo.disc_tag & TRM_USR_DISCENB) 800163816Smjacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 801163816Smjacob else 802163816Smjacob spi->flags = 0; 803163816Smjacob if (pDCB->tinfo.disc_tag & TRM_USR_TAGENB) 804163816Smjacob scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 805163816Smjacob tinfo = &pDCB->tinfo.user; 806163816Smjacob TRM_DPRINTF("USER: cts->flags= %2x \n", 807163816Smjacob cts->flags); 808163816Smjacob } 809163816Smjacob spi->sync_period = tinfo->period; 810163816Smjacob spi->sync_offset = tinfo->offset; 811163816Smjacob spi->bus_width = tinfo->width; 812163816Smjacob TRM_DPRINTF("pDCB->SyncPeriod: %d \n", 813163816Smjacob pDCB->SyncPeriod); 814163816Smjacob TRM_DPRINTF("period: %d \n", tinfo->period); 815163816Smjacob TRM_DPRINTF("offset: %d \n", tinfo->offset); 816163816Smjacob TRM_DPRINTF("width: %d \n", tinfo->width); 817163816Smjacob 818163816Smjacob splx(intflag); 819163816Smjacob spi->valid = CTS_SPI_VALID_SYNC_RATE | 820163816Smjacob CTS_SPI_VALID_SYNC_OFFSET | 821163816Smjacob CTS_SPI_VALID_BUS_WIDTH | 822163816Smjacob CTS_SPI_VALID_DISC; 823163816Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 824105059Scognet pccb->ccb_h.status = CAM_REQ_CMP; 825105059Scognet xpt_done(pccb); 826105059Scognet } 827105059Scognet break; 828105059Scognet /* 829105059Scognet * Get/Set transfer rate/width/disconnection/tag queueing 830105059Scognet * settings 831105059Scognet * (Set) transfer rate/width negotiation settings 832105059Scognet */ 833105059Scognet case XPT_SET_TRAN_SETTINGS: { 834163816Smjacob struct ccb_trans_settings *cts = &pccb->cts; 835105059Scognet u_int update_type; 836105059Scognet int intflag; 837105059Scognet PDCB pDCB; 838163816Smjacob struct ccb_trans_settings_scsi *scsi = 839163816Smjacob &cts->proto_specific.scsi; 840163816Smjacob struct ccb_trans_settings_spi *spi = 841163816Smjacob &cts->xport_specific.spi; 842105059Scognet 843105059Scognet TRM_DPRINTF(" XPT_SET_TRAN_SETTINGS \n"); 844105059Scognet update_type = 0; 845163816Smjacob if (cts->type == CTS_TYPE_CURRENT_SETTINGS) 846163816Smjacob update_type |= TRM_TRANS_GOAL; 847163816Smjacob if (cts->type == CTS_TYPE_USER_SETTINGS) 848163816Smjacob update_type |= TRM_TRANS_USER; 849163816Smjacob intflag = splcam(); 850163816Smjacob pDCB = &pACB->DCBarray[target_id][target_lun]; 851163816Smjacob 852163816Smjacob if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { 853163816Smjacob /*ccb disc enables */ 854163816Smjacob if (update_type & TRM_TRANS_GOAL) { 855163816Smjacob if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) 856163816Smjacob != 0) 857163816Smjacob pDCB->tinfo.disc_tag 858163816Smjacob |= TRM_CUR_DISCENB; 859163816Smjacob else 860163816Smjacob pDCB->tinfo.disc_tag &= 861163816Smjacob ~TRM_CUR_DISCENB; 862163816Smjacob } 863163816Smjacob if (update_type & TRM_TRANS_USER) { 864163816Smjacob if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) 865163816Smjacob != 0) 866163816Smjacob pDCB->tinfo.disc_tag 867163816Smjacob |= TRM_USR_DISCENB; 868163816Smjacob else 869163816Smjacob pDCB->tinfo.disc_tag &= 870163816Smjacob ~TRM_USR_DISCENB; 871163816Smjacob } 872163816Smjacob } 873163816Smjacob if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 874163816Smjacob /* if ccb tag q active */ 875163816Smjacob if (update_type & TRM_TRANS_GOAL) { 876163816Smjacob if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) 877163816Smjacob != 0) 878163816Smjacob pDCB->tinfo.disc_tag |= 879163816Smjacob TRM_CUR_TAGENB; 880163816Smjacob else 881163816Smjacob pDCB->tinfo.disc_tag &= 882163816Smjacob ~TRM_CUR_TAGENB; 883163816Smjacob } 884163816Smjacob if (update_type & TRM_TRANS_USER) { 885163816Smjacob if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) 886163816Smjacob != 0) 887163816Smjacob pDCB->tinfo.disc_tag |= 888163816Smjacob TRM_USR_TAGENB; 889163816Smjacob else 890163816Smjacob pDCB->tinfo.disc_tag &= 891163816Smjacob ~TRM_USR_TAGENB; 892163816Smjacob } 893163816Smjacob } 894163816Smjacob /* Minimum sync period factor */ 895163816Smjacob 896163816Smjacob if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) { 897163816Smjacob /* if ccb sync active */ 898163816Smjacob /* TRM-S1040 MinSyncPeriod = 4 clocks/byte */ 899163816Smjacob if ((spi->sync_period != 0) && 900163816Smjacob (spi->sync_period < 125)) 901163816Smjacob spi->sync_period = 125; 902163816Smjacob /* 1/(125*4) minsync 2 MByte/sec */ 903163816Smjacob if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) 904163816Smjacob != 0) { 905163816Smjacob if (spi->sync_offset == 0) 906163816Smjacob spi->sync_period = 0; 907163816Smjacob /* TRM-S1040 MaxSyncOffset = 15 bytes*/ 908163816Smjacob if (spi->sync_offset > 15) 909163816Smjacob spi->sync_offset = 15; 910163816Smjacob } 911163816Smjacob } 912163816Smjacob if ((update_type & TRM_TRANS_USER) != 0) { 913163816Smjacob pDCB->tinfo.user.period = spi->sync_period; 914163816Smjacob pDCB->tinfo.user.offset = spi->sync_offset; 915163816Smjacob pDCB->tinfo.user.width = spi->bus_width; 916163816Smjacob } 917163816Smjacob if ((update_type & TRM_TRANS_GOAL) != 0) { 918163816Smjacob pDCB->tinfo.goal.period = spi->sync_period; 919163816Smjacob pDCB->tinfo.goal.offset = spi->sync_offset; 920163816Smjacob pDCB->tinfo.goal.width = spi->bus_width; 921163816Smjacob } 922163816Smjacob splx(intflag); 923105059Scognet pccb->ccb_h.status = CAM_REQ_CMP; 924105059Scognet xpt_done(pccb); 925105059Scognet break; 926105059Scognet } 927105059Scognet /* 928105059Scognet * Calculate the geometry parameters for a device give 929105059Scognet * the sector size and volume size. 930105059Scognet */ 931116351Snjl case XPT_CALC_GEOMETRY: 932105059Scognet TRM_DPRINTF(" XPT_CALC_GEOMETRY \n"); 933116351Snjl cam_calc_geometry(&pccb->ccg, /*extended*/1); 934105059Scognet xpt_done(pccb); 935105059Scognet break; 936105059Scognet case XPT_ENG_INQ: 937105059Scognet TRM_DPRINTF(" XPT_ENG_INQ \n"); 938105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 939105059Scognet xpt_done(pccb); 940105059Scognet break; 941105059Scognet /* 942105059Scognet * HBA execute engine request 943105059Scognet * This structure must match SCSIIO size 944105059Scognet */ 945105059Scognet case XPT_ENG_EXEC: 946105059Scognet TRM_DPRINTF(" XPT_ENG_EXEC \n"); 947105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 948105059Scognet xpt_done(pccb); 949105059Scognet break; 950105059Scognet /* 951105059Scognet * XPT_EN_LUN = 0x30, Enable LUN as a target 952105059Scognet * Target mode structures. 953105059Scognet */ 954105059Scognet case XPT_EN_LUN: 955105059Scognet /* 956105059Scognet * Don't (yet?) support vendor 957105059Scognet * specific commands. 958105059Scognet */ 959105059Scognet TRM_DPRINTF(" XPT_EN_LUN \n"); 960105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 961105059Scognet xpt_done(pccb); 962105059Scognet break; 963105059Scognet /* 964105059Scognet * Execute target I/O request 965105059Scognet */ 966105059Scognet case XPT_TARGET_IO: 967105059Scognet /* 968105059Scognet * Don't (yet?) support vendor 969105059Scognet * specific commands. 970105059Scognet */ 971105059Scognet TRM_DPRINTF(" XPT_TARGET_IO \n"); 972105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 973105059Scognet xpt_done(pccb); 974105059Scognet break; 975105059Scognet /* 976105059Scognet * Accept Host Target Mode CDB 977105059Scognet */ 978105059Scognet case XPT_ACCEPT_TARGET_IO: 979105059Scognet /* 980105059Scognet * Don't (yet?) support vendor 981105059Scognet * specific commands. 982105059Scognet */ 983105059Scognet TRM_DPRINTF(" XPT_ACCEPT_TARGET_IO \n"); 984105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 985105059Scognet xpt_done(pccb); 986105059Scognet break; 987105059Scognet /* 988105059Scognet * Continue Host Target I/O Connection 989105059Scognet */ 990105059Scognet case XPT_CONT_TARGET_IO: 991105059Scognet /* 992105059Scognet * Don't (yet?) support vendor 993105059Scognet * specific commands. 994105059Scognet */ 995105059Scognet TRM_DPRINTF(" XPT_CONT_TARGET_IO \n"); 996105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 997105059Scognet xpt_done(pccb); 998105059Scognet break; 999105059Scognet /* 1000105059Scognet * Notify Host Target driver of event 1001105059Scognet */ 1002105059Scognet case XPT_IMMED_NOTIFY: 1003105059Scognet TRM_DPRINTF(" XPT_IMMED_NOTIFY \n"); 1004105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 1005105059Scognet xpt_done(pccb); 1006105059Scognet break; 1007105059Scognet /* 1008105059Scognet * Acknowledgement of event 1009105059Scognet */ 1010105059Scognet case XPT_NOTIFY_ACK: 1011105059Scognet TRM_DPRINTF(" XPT_NOTIFY_ACK \n"); 1012105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 1013105059Scognet xpt_done(pccb); 1014105059Scognet break; 1015105059Scognet /* 1016105059Scognet * XPT_VUNIQUE = 0x80 1017105059Scognet */ 1018105059Scognet case XPT_VUNIQUE: 1019105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 1020105059Scognet xpt_done(pccb); 1021105059Scognet break; 1022105059Scognet default: 1023105059Scognet pccb->ccb_h.status = CAM_REQ_INVALID; 1024105059Scognet xpt_done(pccb); 1025105059Scognet break; 1026105059Scognet } 1027111158Scognet splx(actionflags); 1028105059Scognet} 1029105059Scognet 1030105059Scognetstatic void 1031105059Scognettrm_poll(struct cam_sim *psim) 1032105059Scognet{ 1033128090Scognet trm_Interrupt(cam_sim_softc(psim)); 1034105059Scognet} 1035105059Scognet 1036105059Scognetstatic void 1037105059Scognettrm_ResetDevParam(PACB pACB) 1038105059Scognet{ 1039105059Scognet PDCB pDCB, pdcb; 1040105059Scognet PNVRAMTYPE pEEpromBuf; 1041105059Scognet u_int8_t PeriodIndex; 1042105059Scognet 1043105059Scognet pDCB = pACB->pLinkDCB; 1044105059Scognet if (pDCB == NULL) 1045105059Scognet return; 1046105059Scognet pdcb = pDCB; 1047105059Scognet do { 1048105059Scognet pDCB->SyncMode &= ~(SYNC_NEGO_DONE+ WIDE_NEGO_DONE); 1049105059Scognet pDCB->SyncPeriod = 0; 1050105059Scognet pDCB->SyncOffset = 0; 1051105059Scognet pEEpromBuf = &trm_eepromBuf[pACB->AdapterUnit]; 1052105059Scognet pDCB->DevMode = 1053105059Scognet pEEpromBuf->NvramTarget[pDCB->TargetID].NvmTarCfg0; 1054105059Scognet pDCB->AdpMode = pEEpromBuf->NvramChannelCfg; 1055105059Scognet PeriodIndex = 1056105059Scognet pEEpromBuf->NvramTarget[pDCB->TargetID].NvmTarPeriod & 0x07; 1057111158Scognet if (pACB->AdaptType == 1) /* is U2? */ 1058111158Scognet pDCB->MaxNegoPeriod = dc395u2x_clock_period[PeriodIndex]; 1059111158Scognet else 1060111158Scognet pDCB->MaxNegoPeriod = dc395x_clock_period[PeriodIndex]; 1061105059Scognet if ((pDCB->DevMode & NTC_DO_WIDE_NEGO) && 1062105059Scognet (pACB->Config & HCC_WIDE_CARD)) 1063105059Scognet pDCB->SyncMode |= WIDE_NEGO_ENABLE; 1064105059Scognet pDCB = pDCB->pNextDCB; 1065105059Scognet } 1066105059Scognet while (pdcb != pDCB); 1067105059Scognet} 1068105059Scognet 1069105059Scognetstatic void 1070105059Scognettrm_RecoverSRB(PACB pACB) 1071105059Scognet{ 1072105059Scognet PDCB pDCB, pdcb; 1073105059Scognet PSRB psrb, psrb2; 1074105059Scognet u_int16_t cnt, i; 1075105059Scognet 1076105059Scognet pDCB = pACB->pLinkDCB; 1077105059Scognet if (pDCB == NULL) 1078105059Scognet return; 1079105059Scognet pdcb = pDCB; 1080105059Scognet do { 1081105059Scognet cnt = pdcb->GoingSRBCnt; 1082105059Scognet psrb = pdcb->pGoingSRB; 1083105059Scognet for (i = 0; i < cnt; i++) { 1084105059Scognet psrb2 = psrb; 1085105059Scognet psrb = psrb->pNextSRB; 1086105059Scognet if (pdcb->pWaitingSRB) { 1087105059Scognet psrb2->pNextSRB = pdcb->pWaitingSRB; 1088105059Scognet pdcb->pWaitingSRB = psrb2; 1089105059Scognet } else { 1090105059Scognet pdcb->pWaitingSRB = psrb2; 1091111158Scognet pdcb->pWaitingLastSRB = psrb2; 1092105059Scognet psrb2->pNextSRB = NULL; 1093105059Scognet } 1094105059Scognet } 1095105059Scognet pdcb->GoingSRBCnt = 0; 1096105059Scognet pdcb->pGoingSRB = NULL; 1097105059Scognet pdcb = pdcb->pNextDCB; 1098105059Scognet } 1099105059Scognet while (pdcb != pDCB); 1100105059Scognet} 1101105059Scognet 1102105059Scognetstatic void 1103105059Scognettrm_reset(PACB pACB) 1104105059Scognet{ 1105105059Scognet int intflag; 1106105059Scognet u_int16_t i; 1107105059Scognet 1108105059Scognet TRM_DPRINTF("trm: RESET"); 1109105059Scognet intflag = splcam(); 1110105059Scognet trm_reg_write8(0x00, TRMREG_DMA_INTEN); 1111105059Scognet trm_reg_write8(0x00, TRMREG_SCSI_INTEN); 1112105059Scognet 1113105059Scognet trm_ResetSCSIBus(pACB); 1114105059Scognet for (i = 0; i < 500; i++) 1115105059Scognet DELAY(1000); 1116105059Scognet trm_reg_write8(0x7F, TRMREG_SCSI_INTEN); 1117105059Scognet /* Enable DMA interrupt */ 1118105059Scognet trm_reg_write8(EN_SCSIINTR, TRMREG_DMA_INTEN); 1119105059Scognet /* Clear DMA FIFO */ 1120105059Scognet trm_reg_write8(CLRXFIFO, TRMREG_DMA_CONTROL); 1121105059Scognet /* Clear SCSI FIFO */ 1122105059Scognet trm_reg_write16(DO_CLRFIFO,TRMREG_SCSI_CONTROL); 1123105059Scognet trm_ResetDevParam(pACB); 1124105059Scognet trm_DoingSRB_Done(pACB); 1125105059Scognet pACB->pActiveDCB = NULL; 1126105059Scognet pACB->ACBFlag = 0;/* RESET_DETECT, RESET_DONE ,RESET_DEV */ 1127105059Scognet trm_DoWaitingSRB(pACB); 1128105059Scognet /* Tell the XPT layer that a bus reset occured */ 1129105059Scognet if (pACB->ppath != NULL) 1130105059Scognet xpt_async(AC_BUS_RESET, pACB->ppath, NULL); 1131105059Scognet splx(intflag); 1132105059Scognet return; 1133105059Scognet} 1134105059Scognet 1135105059Scognetstatic u_int16_t 1136105059Scognettrm_StartSCSI(PACB pACB, PDCB pDCB, PSRB pSRB) 1137105059Scognet{ 1138105059Scognet u_int16_t return_code; 1139111158Scognet u_int8_t scsicommand, i,command,identify_message; 1140105059Scognet u_int8_t * ptr; 1141105059Scognet union ccb *pccb; 1142105059Scognet struct ccb_scsiio *pcsio; 1143105059Scognet 1144105059Scognet pccb = pSRB->pccb; 1145105059Scognet pcsio = &pccb->csio; 1146105059Scognet 1147105059Scognet trm_reg_write8(pACB->AdaptSCSIID, TRMREG_SCSI_HOSTID); 1148105059Scognet trm_reg_write8(pDCB->TargetID, TRMREG_SCSI_TARGETID); 1149105059Scognet trm_reg_write8(pDCB->SyncPeriod, TRMREG_SCSI_SYNC); 1150105059Scognet trm_reg_write8(pDCB->SyncOffset, TRMREG_SCSI_OFFSET); 1151105059Scognet pSRB->ScsiPhase = PH_BUS_FREE;/* initial phase */ 1152105059Scognet /* Flush FIFO */ 1153105059Scognet trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL); 1154105059Scognet 1155105059Scognet identify_message = pDCB->IdentifyMsg; 1156105059Scognet 1157105059Scognet if ((pSRB->CmdBlock[0] == INQUIRY) || 1158105059Scognet (pSRB->CmdBlock[0] == REQUEST_SENSE) || 1159105059Scognet (pSRB->SRBFlag & AUTO_REQSENSE)) { 1160105059Scognet if (((pDCB->SyncMode & WIDE_NEGO_ENABLE) && 1161111158Scognet !(pDCB->SyncMode & WIDE_NEGO_DONE)) 1162105059Scognet || ((pDCB->SyncMode & SYNC_NEGO_ENABLE) && 1163105059Scognet !(pDCB->SyncMode & SYNC_NEGO_DONE))) { 1164105059Scognet if (!(pDCB->IdentifyMsg & 7) || 1165105059Scognet (pSRB->CmdBlock[0] != INQUIRY)) { 1166105059Scognet scsicommand = SCMD_SEL_ATNSTOP; 1167105059Scognet pSRB->SRBState = SRB_MSGOUT; 1168105059Scognet goto polling; 1169105059Scognet } 1170105059Scognet } 1171105059Scognet /* 1172105059Scognet * Send identify message 1173105059Scognet */ 1174105059Scognet trm_reg_write8((identify_message & 0xBF) ,TRMREG_SCSI_FIFO); 1175105059Scognet scsicommand = SCMD_SEL_ATN; 1176105059Scognet pSRB->SRBState = SRB_START_; 1177105059Scognet } else { 1178105059Scognet /* not inquiry,request sense,auto request sense */ 1179105059Scognet /* 1180105059Scognet * Send identify message 1181105059Scognet */ 1182105059Scognet trm_reg_write8(identify_message,TRMREG_SCSI_FIFO); 1183105059Scognet scsicommand = SCMD_SEL_ATN; 1184105059Scognet pSRB->SRBState = SRB_START_; 1185105059Scognet if (pDCB->SyncMode & EN_TAG_QUEUING) { 1186105059Scognet /* Send Tag message */ 1187111158Scognet trm_reg_write8(MSG_SIMPLE_QTAG, TRMREG_SCSI_FIFO); 1188111158Scognet trm_reg_write8(pSRB->TagNumber, TRMREG_SCSI_FIFO); 1189105059Scognet scsicommand = SCMD_SEL_ATN3; 1190105059Scognet } 1191105059Scognet } 1192105059Scognetpolling: 1193105059Scognet /* 1194105059Scognet * Send CDB ..command block ......... 1195105059Scognet */ 1196105059Scognet if (pSRB->SRBFlag & AUTO_REQSENSE) { 1197105059Scognet trm_reg_write8(REQUEST_SENSE, TRMREG_SCSI_FIFO); 1198105059Scognet trm_reg_write8((pDCB->IdentifyMsg << 5), TRMREG_SCSI_FIFO); 1199105059Scognet trm_reg_write8(0, TRMREG_SCSI_FIFO); 1200105059Scognet trm_reg_write8(0, TRMREG_SCSI_FIFO); 1201105059Scognet trm_reg_write8(pcsio->sense_len, TRMREG_SCSI_FIFO); 1202105059Scognet trm_reg_write8(0, TRMREG_SCSI_FIFO); 1203105059Scognet } else { 1204105059Scognet ptr = (u_int8_t *) pSRB->CmdBlock; 1205105059Scognet for (i = 0; i < pSRB->ScsiCmdLen ; i++) { 1206105059Scognet command = *ptr++; 1207105059Scognet trm_reg_write8(command,TRMREG_SCSI_FIFO); 1208105059Scognet } 1209105059Scognet } 1210105059Scognet if (trm_reg_read16(TRMREG_SCSI_STATUS) & SCSIINTERRUPT) { 1211105059Scognet /* 1212105059Scognet * If trm_StartSCSI return 1 : 1213105059Scognet * current interrupt status is interrupt disreenable 1214105059Scognet * It's said that SCSI processor has more one SRB need to do, 1215105059Scognet * SCSI processor has been occupied by one SRB. 1216105059Scognet */ 1217105059Scognet pSRB->SRBState = SRB_READY; 1218105059Scognet return_code = 1; 1219105059Scognet } else { 1220105059Scognet /* 1221105059Scognet * If trm_StartSCSI return 0 : 1222105059Scognet * current interrupt status is interrupt enable 1223105059Scognet * It's said that SCSI processor is unoccupied 1224105059Scognet */ 1225105059Scognet pSRB->ScsiPhase = SCSI_NOP1; /* SCSI bus free Phase */ 1226105059Scognet pACB->pActiveDCB = pDCB; 1227105059Scognet pDCB->pActiveSRB = pSRB; 1228105059Scognet return_code = 0; 1229105059Scognet trm_reg_write16(DO_DATALATCH | DO_HWRESELECT, 1230105059Scognet TRMREG_SCSI_CONTROL);/* it's important for atn stop*/ 1231105059Scognet /* 1232105059Scognet * SCSI cammand 1233105059Scognet */ 1234105059Scognet trm_reg_write8(scsicommand,TRMREG_SCSI_COMMAND); 1235105059Scognet } 1236105059Scognet return (return_code); 1237105059Scognet} 1238105059Scognet 1239105059Scognetstatic void 1240105059Scognettrm_Interrupt(vpACB) 1241105059Scognetvoid *vpACB; 1242105059Scognet{ 1243105059Scognet PACB pACB; 1244105059Scognet PDCB pDCB; 1245105059Scognet PSRB pSRB; 1246105059Scognet u_int16_t phase; 1247111158Scognet void (*stateV)(PACB, PSRB, u_int16_t *); 1248111158Scognet u_int16_t scsi_status=0; 1249111158Scognet u_int8_t scsi_intstatus; 1250105059Scognet 1251105059Scognet pACB = vpACB; 1252105059Scognet 1253105059Scognet scsi_status = trm_reg_read16(TRMREG_SCSI_STATUS); 1254105059Scognet if (!(scsi_status & SCSIINTERRUPT)) { 1255105059Scognet TRM_DPRINTF("trm_Interrupt: TRMREG_SCSI_STATUS scsi_status = NULL ,return......"); 1256105059Scognet return; 1257105059Scognet } 1258105059Scognet TRM_DPRINTF("scsi_status=%2x,",scsi_status); 1259105059Scognet 1260105059Scognet scsi_intstatus = trm_reg_read8(TRMREG_SCSI_INTSTATUS); 1261105059Scognet 1262105059Scognet TRM_DPRINTF("scsi_intstatus=%2x,",scsi_intstatus); 1263105059Scognet 1264105059Scognet if (scsi_intstatus & (INT_SELTIMEOUT | INT_DISCONNECT)) { 1265105059Scognet trm_Disconnect(pACB); 1266105059Scognet return; 1267105059Scognet } 1268105059Scognet 1269105059Scognet if (scsi_intstatus & INT_RESELECTED) { 1270105059Scognet trm_Reselect(pACB); 1271105059Scognet return; 1272105059Scognet } 1273105059Scognet if (scsi_intstatus & INT_SCSIRESET) { 1274105059Scognet trm_ScsiRstDetect(pACB); 1275105059Scognet return; 1276105059Scognet } 1277105059Scognet 1278105059Scognet if (scsi_intstatus & (INT_BUSSERVICE | INT_CMDDONE)) { 1279105059Scognet pDCB = pACB->pActiveDCB; 1280126053Scognet KASSERT(pDCB != NULL, ("no active DCB")); 1281105059Scognet pSRB = pDCB->pActiveSRB; 1282126053Scognet if (pDCB->DCBFlag & ABORT_DEV_) 1283105059Scognet trm_EnableMsgOutAbort1(pACB, pSRB); 1284105059Scognet phase = (u_int16_t) pSRB->ScsiPhase; /* phase: */ 1285105059Scognet stateV = (void *) trm_SCSI_phase0[phase]; 1286105059Scognet stateV(pACB, pSRB, &scsi_status); 1287105059Scognet pSRB->ScsiPhase = scsi_status & PHASEMASK; 1288105059Scognet /* phase:0,1,2,3,4,5,6,7 */ 1289105059Scognet phase = (u_int16_t) scsi_status & PHASEMASK; 1290105059Scognet stateV = (void *) trm_SCSI_phase1[phase]; 1291105059Scognet stateV(pACB, pSRB, &scsi_status); 1292105059Scognet } 1293105059Scognet} 1294105059Scognet 1295105059Scognetstatic void 1296111158Scognettrm_MsgOutPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1297105059Scognet{ 1298105059Scognet 1299105059Scognet if (pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT)) 1300105059Scognet *pscsi_status = PH_BUS_FREE; 1301105059Scognet /*.. initial phase*/ 1302105059Scognet} 1303105059Scognet 1304105059Scognetstatic void 1305111158Scognettrm_MsgOutPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1306105059Scognet{ 1307105059Scognet u_int8_t bval; 1308105059Scognet u_int16_t i, cnt; 1309105059Scognet u_int8_t * ptr; 1310105059Scognet PDCB pDCB; 1311105059Scognet 1312105059Scognet trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL); 1313105059Scognet pDCB = pACB->pActiveDCB; 1314105059Scognet if (!(pSRB->SRBState & SRB_MSGOUT)) { 1315105059Scognet cnt = pSRB->MsgCnt; 1316105059Scognet if (cnt) { 1317105059Scognet ptr = (u_int8_t *) pSRB->MsgOutBuf; 1318105059Scognet for (i = 0; i < cnt; i++) { 1319105059Scognet trm_reg_write8(*ptr, TRMREG_SCSI_FIFO); 1320105059Scognet ptr++; 1321105059Scognet } 1322105059Scognet pSRB->MsgCnt = 0; 1323105059Scognet if ((pDCB->DCBFlag & ABORT_DEV_) && 1324105059Scognet (pSRB->MsgOutBuf[0] == MSG_ABORT)) { 1325105059Scognet pSRB->SRBState = SRB_ABORT_SENT; 1326105059Scognet } 1327105059Scognet } else { 1328105059Scognet bval = MSG_ABORT; 1329105059Scognet if ((pSRB->CmdBlock[0] == INQUIRY) || 1330105059Scognet (pSRB->CmdBlock[0] == REQUEST_SENSE) || 1331105059Scognet (pSRB->SRBFlag & AUTO_REQSENSE)) { 1332105059Scognet if (pDCB->SyncMode & SYNC_NEGO_ENABLE) { 1333105059Scognet goto mop1; 1334105059Scognet } 1335105059Scognet } 1336105059Scognet trm_reg_write8(bval, TRMREG_SCSI_FIFO); 1337105059Scognet } 1338105059Scognet } else { 1339105059Scognetmop1: /* message out phase */ 1340105059Scognet if (!(pSRB->SRBState & SRB_DO_WIDE_NEGO) 1341105059Scognet && (pDCB->SyncMode & WIDE_NEGO_ENABLE)) { 1342105059Scognet /* 1343105059Scognet * WIDE DATA TRANSFER REQUEST code (03h) 1344105059Scognet */ 1345105059Scognet pDCB->SyncMode &= ~(SYNC_NEGO_DONE | EN_ATN_STOP); 1346105059Scognet trm_reg_write8((pDCB->IdentifyMsg & 0xBF), 1347105059Scognet TRMREG_SCSI_FIFO); 1348105059Scognet trm_reg_write8(MSG_EXTENDED,TRMREG_SCSI_FIFO); 1349105059Scognet /* (01h) */ 1350105059Scognet trm_reg_write8(2,TRMREG_SCSI_FIFO); 1351105059Scognet /* Message length (02h) */ 1352105059Scognet trm_reg_write8(3,TRMREG_SCSI_FIFO); 1353105059Scognet /* wide data xfer (03h) */ 1354105059Scognet trm_reg_write8(1,TRMREG_SCSI_FIFO); 1355105059Scognet /* width:0(8bit),1(16bit),2(32bit) */ 1356105059Scognet pSRB->SRBState |= SRB_DO_WIDE_NEGO; 1357105059Scognet } else if (!(pSRB->SRBState & SRB_DO_SYNC_NEGO) 1358105059Scognet && (pDCB->SyncMode & SYNC_NEGO_ENABLE)) { 1359105059Scognet /* 1360105059Scognet * SYNCHRONOUS DATA TRANSFER REQUEST code (01h) 1361105059Scognet */ 1362105059Scognet if (!(pDCB->SyncMode & WIDE_NEGO_DONE)) 1363105059Scognet trm_reg_write8((pDCB->IdentifyMsg & 0xBF), 1364105059Scognet TRMREG_SCSI_FIFO); 1365105059Scognet trm_reg_write8(MSG_EXTENDED,TRMREG_SCSI_FIFO); 1366105059Scognet /* (01h) */ 1367105059Scognet trm_reg_write8(3,TRMREG_SCSI_FIFO); 1368105059Scognet /* Message length (03h) */ 1369105059Scognet trm_reg_write8(1,TRMREG_SCSI_FIFO); 1370105059Scognet /* SYNCHRONOUS DATA TRANSFER REQUEST code (01h) */ 1371105059Scognet trm_reg_write8(pDCB->MaxNegoPeriod,TRMREG_SCSI_FIFO); 1372105059Scognet /* Transfer peeriod factor */ 1373111158Scognet trm_reg_write8((pACB->AdaptType == 1) ? 31 : 15, 1374111158Scognet TRMREG_SCSI_FIFO); 1375105059Scognet /* REQ/ACK offset */ 1376105059Scognet pSRB->SRBState |= SRB_DO_SYNC_NEGO; 1377105059Scognet } 1378105059Scognet } 1379105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1380105059Scognet /* it's important for atn stop */ 1381105059Scognet /* 1382105059Scognet * SCSI cammand 1383105059Scognet */ 1384105059Scognet trm_reg_write8(SCMD_FIFO_OUT, TRMREG_SCSI_COMMAND); 1385105059Scognet} 1386105059Scognet 1387105059Scognetstatic void 1388111158Scognettrm_CommandPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1389105059Scognet{ 1390105059Scognet 1391105059Scognet} 1392105059Scognet 1393105059Scognetstatic void 1394111158Scognettrm_CommandPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1395105059Scognet{ 1396105059Scognet PDCB pDCB; 1397105059Scognet u_int8_t * ptr; 1398105059Scognet u_int16_t i, cnt; 1399105059Scognet union ccb *pccb; 1400105059Scognet struct ccb_scsiio *pcsio; 1401105059Scognet 1402105059Scognet pccb = pSRB->pccb; 1403105059Scognet pcsio = &pccb->csio; 1404105059Scognet 1405105059Scognet trm_reg_write16(DO_CLRATN | DO_CLRFIFO , TRMREG_SCSI_CONTROL); 1406105059Scognet if (!(pSRB->SRBFlag & AUTO_REQSENSE)) { 1407105059Scognet cnt = (u_int16_t) pSRB->ScsiCmdLen; 1408105059Scognet ptr = (u_int8_t *) pSRB->CmdBlock; 1409105059Scognet for (i = 0; i < cnt; i++) { 1410105059Scognet trm_reg_write8(*ptr, TRMREG_SCSI_FIFO); 1411105059Scognet ptr++; 1412105059Scognet } 1413105059Scognet } else { 1414105059Scognet trm_reg_write8(REQUEST_SENSE, TRMREG_SCSI_FIFO); 1415105059Scognet pDCB = pACB->pActiveDCB; 1416105059Scognet /* target id */ 1417105059Scognet trm_reg_write8((pDCB->IdentifyMsg << 5), TRMREG_SCSI_FIFO); 1418105059Scognet trm_reg_write8(0, TRMREG_SCSI_FIFO); 1419105059Scognet trm_reg_write8(0, TRMREG_SCSI_FIFO); 1420105059Scognet /* sizeof(struct scsi_sense_data) */ 1421105059Scognet trm_reg_write8(pcsio->sense_len, TRMREG_SCSI_FIFO); 1422105059Scognet trm_reg_write8(0, TRMREG_SCSI_FIFO); 1423105059Scognet } 1424105059Scognet pSRB->SRBState = SRB_COMMAND; 1425105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1426105059Scognet /* it's important for atn stop*/ 1427105059Scognet /* 1428105059Scognet * SCSI cammand 1429105059Scognet */ 1430105059Scognet trm_reg_write8(SCMD_FIFO_OUT, TRMREG_SCSI_COMMAND); 1431105059Scognet} 1432105059Scognet 1433105059Scognetstatic void 1434111158Scognettrm_DataOutPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1435105059Scognet{ 1436105059Scognet PDCB pDCB; 1437105059Scognet u_int8_t TempDMAstatus,SGIndexTemp; 1438105059Scognet u_int16_t scsi_status; 1439105059Scognet PSEG pseg; 1440105059Scognet u_long TempSRBXferredLength,dLeftCounter=0; 1441105059Scognet 1442105059Scognet pDCB = pSRB->pSRBDCB; 1443105059Scognet scsi_status = *pscsi_status; 1444105059Scognet 1445105059Scognet if (!(pSRB->SRBState & SRB_XFERPAD)) { 1446105059Scognet if (scsi_status & PARITYERROR) 1447105059Scognet pSRB->SRBStatus |= PARITY_ERROR; 1448105059Scognet if (!(scsi_status & SCSIXFERDONE)) { 1449105059Scognet /* 1450105059Scognet * when data transfer from DMA FIFO to SCSI FIFO 1451105059Scognet * if there was some data left in SCSI FIFO 1452105059Scognet */ 1453105059Scognet dLeftCounter = (u_long) 1454111158Scognet (trm_reg_read8(TRMREG_SCSI_FIFOCNT) & 0x3F); 1455105059Scognet if (pDCB->SyncPeriod & WIDE_SYNC) { 1456105059Scognet /* 1457105059Scognet * if WIDE scsi SCSI FIFOCNT unit is word 1458105059Scognet * so need to * 2 1459105059Scognet */ 1460105059Scognet dLeftCounter <<= 1; 1461105059Scognet } 1462105059Scognet } 1463105059Scognet /* 1464105059Scognet * caculate all the residue data that not yet tranfered 1465105059Scognet * SCSI transfer counter + left in SCSI FIFO data 1466105059Scognet * 1467105059Scognet * .....TRM_SCSI_COUNTER (24bits) 1468105059Scognet * The counter always decrement by one for every SCSI byte 1469105059Scognet *transfer. 1470105059Scognet * .....TRM_SCSI_FIFOCNT (5bits) 1471105059Scognet * The counter is SCSI FIFO offset counter 1472105059Scognet */ 1473105059Scognet dLeftCounter += trm_reg_read32(TRMREG_SCSI_COUNTER); 1474105059Scognet if (dLeftCounter == 1) { 1475105059Scognet dLeftCounter = 0; 1476105059Scognet trm_reg_write16(DO_CLRFIFO,TRMREG_SCSI_CONTROL); 1477105059Scognet } 1478105059Scognet if ((dLeftCounter == 0) || 1479105059Scognet (scsi_status & SCSIXFERCNT_2_ZERO)) { 1480105059Scognet TempDMAstatus = trm_reg_read8(TRMREG_DMA_STATUS); 1481105059Scognet while (!(TempDMAstatus & DMAXFERCOMP)) { 1482105059Scognet TempDMAstatus = 1483105059Scognet trm_reg_read8(TRMREG_DMA_STATUS); 1484105059Scognet } 1485105059Scognet pSRB->SRBTotalXferLength = 0; 1486105059Scognet } else { 1487105059Scognet /* Update SG list */ 1488105059Scognet /* 1489105059Scognet * if transfer not yet complete 1490105059Scognet * there were some data residue in SCSI FIFO or 1491105059Scognet * SCSI transfer counter not empty 1492105059Scognet */ 1493105059Scognet if (pSRB->SRBTotalXferLength != dLeftCounter) { 1494105059Scognet /* 1495105059Scognet * data that had transferred length 1496105059Scognet */ 1497105059Scognet TempSRBXferredLength = 1498105059Scognet pSRB->SRBTotalXferLength - dLeftCounter; 1499105059Scognet /* 1500105059Scognet * next time to be transferred length 1501105059Scognet */ 1502105059Scognet pSRB->SRBTotalXferLength = dLeftCounter; 1503105059Scognet /* 1504105059Scognet * parsing from last time disconnect SRBSGIndex 1505105059Scognet */ 1506105059Scognet pseg = 1507111158Scognet pSRB->pSRBSGL + pSRB->SRBSGIndex; 1508105059Scognet for (SGIndexTemp = pSRB->SRBSGIndex; 1509105059Scognet SGIndexTemp < pSRB->SRBSGCount; 1510105059Scognet SGIndexTemp++) { 1511105059Scognet /* 1512105059Scognet * find last time which SG transfer be 1513105059Scognet * disconnect 1514105059Scognet */ 1515105059Scognet if (TempSRBXferredLength >= 1516105059Scognet pseg->length) 1517105059Scognet TempSRBXferredLength -= 1518105059Scognet pseg->length; 1519105059Scognet else { 1520105059Scognet /* 1521105059Scognet * update last time disconnected SG 1522105059Scognet * list 1523105059Scognet */ 1524105059Scognet pseg->length -= 1525105059Scognet TempSRBXferredLength; 1526105059Scognet /* residue data length */ 1527105059Scognet pseg->address += 1528105059Scognet TempSRBXferredLength; 1529105059Scognet /* residue data pointer */ 1530105059Scognet pSRB->SRBSGIndex = SGIndexTemp; 1531105059Scognet break; 1532105059Scognet } 1533105059Scognet pseg++; 1534105059Scognet } 1535105059Scognet } 1536105059Scognet } 1537105059Scognet } 1538105059Scognet trm_reg_write8(STOPDMAXFER ,TRMREG_DMA_CONTROL); 1539105059Scognet} 1540105059Scognet 1541105059Scognet 1542105059Scognetstatic void 1543111158Scognettrm_DataOutPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1544105059Scognet{ 1545105059Scognet u_int16_t ioDir; 1546105059Scognet /* 1547105059Scognet * do prepare befor transfer when data out phase 1548105059Scognet */ 1549105059Scognet 1550105059Scognet ioDir = XFERDATAOUT; 1551105059Scognet trm_DataIO_transfer(pACB, pSRB, ioDir); 1552105059Scognet} 1553105059Scognet 1554105059Scognetstatic void 1555111158Scognettrm_DataInPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1556105059Scognet{ 1557111158Scognet u_int8_t TempDMAstatus, SGIndexTemp; 1558105059Scognet u_int16_t scsi_status; 1559105059Scognet PSEG pseg; 1560105059Scognet u_long TempSRBXferredLength,dLeftCounter = 0; 1561105059Scognet 1562105059Scognet scsi_status = *pscsi_status; 1563105059Scognet if (!(pSRB->SRBState & SRB_XFERPAD)) { 1564105059Scognet if (scsi_status & PARITYERROR) 1565105059Scognet pSRB->SRBStatus |= PARITY_ERROR; 1566105059Scognet dLeftCounter += trm_reg_read32(TRMREG_SCSI_COUNTER); 1567105059Scognet if ((dLeftCounter == 0) || (scsi_status & SCSIXFERCNT_2_ZERO)) { 1568111158Scognet TempDMAstatus = trm_reg_read8(TRMREG_DMA_STATUS); 1569111158Scognet while (!(TempDMAstatus & DMAXFERCOMP)) 1570111158Scognet TempDMAstatus = trm_reg_read8(TRMREG_DMA_STATUS); 1571105059Scognet pSRB->SRBTotalXferLength = 0; 1572105059Scognet } else { 1573105059Scognet /* 1574105059Scognet * parsing the case: 1575105059Scognet * when a transfer not yet complete 1576105059Scognet * but be disconnected by uper layer 1577105059Scognet * if transfer not yet complete 1578105059Scognet * there were some data residue in SCSI FIFO or 1579105059Scognet * SCSI transfer counter not empty 1580105059Scognet */ 1581105059Scognet if (pSRB->SRBTotalXferLength != dLeftCounter) { 1582105059Scognet /* 1583105059Scognet * data that had transferred length 1584105059Scognet */ 1585105059Scognet TempSRBXferredLength = 1586105059Scognet pSRB->SRBTotalXferLength - dLeftCounter; 1587105059Scognet /* 1588105059Scognet * next time to be transferred length 1589105059Scognet */ 1590105059Scognet pSRB->SRBTotalXferLength = dLeftCounter; 1591105059Scognet /* 1592105059Scognet * parsing from last time disconnect SRBSGIndex 1593105059Scognet */ 1594111158Scognet pseg = pSRB->pSRBSGL + pSRB->SRBSGIndex; 1595105059Scognet for (SGIndexTemp = pSRB->SRBSGIndex; 1596105059Scognet SGIndexTemp < pSRB->SRBSGCount; 1597105059Scognet SGIndexTemp++) { 1598105059Scognet /* 1599105059Scognet * find last time which SG transfer be disconnect 1600105059Scognet */ 1601105059Scognet if (TempSRBXferredLength >= pseg->length) 1602105059Scognet TempSRBXferredLength -= pseg->length; 1603105059Scognet else { 1604105059Scognet /* 1605105059Scognet * update last time disconnected SG list 1606105059Scognet */ 1607105059Scognet pseg->length -= TempSRBXferredLength; 1608105059Scognet /* residue data length */ 1609105059Scognet pseg->address += TempSRBXferredLength; 1610105059Scognet /* residue data pointer */ 1611105059Scognet pSRB->SRBSGIndex = SGIndexTemp; 1612105059Scognet break; 1613105059Scognet } 1614105059Scognet pseg++; 1615105059Scognet } 1616105059Scognet } 1617105059Scognet } 1618105059Scognet } 1619105059Scognet} 1620105059Scognet 1621105059Scognetstatic void 1622111158Scognettrm_DataInPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1623105059Scognet{ 1624105059Scognet u_int16_t ioDir; 1625105059Scognet /* 1626105059Scognet * do prepare befor transfer when data in phase 1627105059Scognet */ 1628105059Scognet 1629105059Scognet ioDir = XFERDATAIN; 1630105059Scognet trm_DataIO_transfer(pACB, pSRB, ioDir); 1631105059Scognet} 1632105059Scognet 1633105059Scognetstatic void 1634105059Scognettrm_DataIO_transfer(PACB pACB, PSRB pSRB, u_int16_t ioDir) 1635105059Scognet{ 1636105059Scognet u_int8_t bval; 1637105059Scognet PDCB pDCB; 1638105059Scognet 1639105059Scognet pDCB = pSRB->pSRBDCB; 1640105059Scognet if (pSRB->SRBSGIndex < pSRB->SRBSGCount) { 1641105059Scognet if (pSRB->SRBTotalXferLength != 0) { 1642105059Scognet /* 1643105059Scognet * load what physical address of Scatter/Gather list 1644105059Scognet table want to be transfer 1645105059Scognet */ 1646111158Scognet TRM_DPRINTF(" SG->address=%8x \n",pSRB->pSRBSGL->address); 1647111158Scognet TRM_DPRINTF(" SG->length=%8x \n",pSRB->pSRBSGL->length); 1648111158Scognet TRM_DPRINTF(" pDCB->SyncPeriod=%x \n",pDCB->SyncPeriod); 1649111158Scognet TRM_DPRINTF(" pSRB->pSRBSGL=%8x \n",(unsigned int)pSRB->pSRBSGL); 1650111158Scognet TRM_DPRINTF(" pSRB->SRBSGPhyAddr=%8x \n",pSRB->SRBSGPhyAddr); 1651111158Scognet TRM_DPRINTF(" pSRB->SRBSGIndex=%d \n",pSRB->SRBSGIndex); 1652111158Scognet TRM_DPRINTF(" pSRB->SRBSGCount=%d \n",pSRB->SRBSGCount); 1653111158Scognet TRM_DPRINTF(" pSRB->SRBTotalXferLength=%d \n",pSRB->SRBTotalXferLength); 1654111158Scognet 1655105059Scognet pSRB->SRBState = SRB_DATA_XFER; 1656105059Scognet trm_reg_write32(0, TRMREG_DMA_XHIGHADDR); 1657105059Scognet trm_reg_write32( 1658105059Scognet (pSRB->SRBSGPhyAddr + 1659105059Scognet ((u_long)pSRB->SRBSGIndex << 3)), 1660105059Scognet TRMREG_DMA_XLOWADDR); 1661105059Scognet /* 1662105059Scognet * load how many bytes in the Scatter/Gather 1663105059Scognet * list table 1664105059Scognet */ 1665105059Scognet trm_reg_write32( 1666105059Scognet ((u_long)(pSRB->SRBSGCount - pSRB->SRBSGIndex) << 3), 1667105059Scognet TRMREG_DMA_XCNT); 1668105059Scognet /* 1669105059Scognet * load total transfer length (24bits) max value 1670105059Scognet * 16Mbyte 1671105059Scognet */ 1672105059Scognet trm_reg_write32(pSRB->SRBTotalXferLength, 1673105059Scognet TRMREG_SCSI_COUNTER); 1674105059Scognet /* Start DMA transfer */ 1675105059Scognet trm_reg_write16(ioDir, TRMREG_DMA_COMMAND); 1676105059Scognet /* Start SCSI transfer */ 1677105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1678105059Scognet /* it's important for atn stop */ 1679105059Scognet /* 1680105059Scognet * SCSI cammand 1681105059Scognet */ 1682105059Scognet bval = (ioDir == XFERDATAOUT) ? 1683105059Scognet SCMD_DMA_OUT : SCMD_DMA_IN; 1684105059Scognet trm_reg_write8(bval, TRMREG_SCSI_COMMAND); 1685105059Scognet } else { 1686105059Scognet /* xfer pad */ 1687105059Scognet if (pSRB->SRBSGCount) { 1688105059Scognet pSRB->AdaptStatus = H_OVER_UNDER_RUN; 1689105059Scognet pSRB->SRBStatus |= OVER_RUN; 1690105059Scognet } 1691105059Scognet if (pDCB->SyncPeriod & WIDE_SYNC) 1692105059Scognet trm_reg_write32(2,TRMREG_SCSI_COUNTER); 1693105059Scognet else 1694105059Scognet trm_reg_write32(1,TRMREG_SCSI_COUNTER); 1695105059Scognet if (ioDir == XFERDATAOUT) 1696105059Scognet trm_reg_write16(0, TRMREG_SCSI_FIFO); 1697105059Scognet else 1698105059Scognet trm_reg_read16(TRMREG_SCSI_FIFO); 1699105059Scognet pSRB->SRBState |= SRB_XFERPAD; 1700105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1701105059Scognet /* it's important for atn stop */ 1702105059Scognet /* 1703105059Scognet * SCSI cammand 1704105059Scognet */ 1705105059Scognet bval = (ioDir == XFERDATAOUT) ? 1706105059Scognet SCMD_FIFO_OUT : SCMD_FIFO_IN; 1707105059Scognet trm_reg_write8(bval, TRMREG_SCSI_COMMAND); 1708105059Scognet } 1709105059Scognet } 1710105059Scognet} 1711105059Scognet 1712105059Scognetstatic void 1713111158Scognettrm_StatusPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1714105059Scognet{ 1715105059Scognet 1716105059Scognet pSRB->TargetStatus = trm_reg_read8(TRMREG_SCSI_FIFO); 1717105059Scognet pSRB->SRBState = SRB_COMPLETED; 1718105059Scognet *pscsi_status = PH_BUS_FREE; 1719105059Scognet /*.. initial phase*/ 1720105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1721105059Scognet /* it's important for atn stop */ 1722105059Scognet /* 1723105059Scognet * SCSI cammand 1724105059Scognet */ 1725105059Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1726105059Scognet} 1727105059Scognet 1728105059Scognet 1729105059Scognet 1730105059Scognetstatic void 1731111158Scognettrm_StatusPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1732105059Scognet{ 1733105059Scognet 1734105059Scognet if (trm_reg_read16(TRMREG_DMA_COMMAND) & 0x0001) { 1735105059Scognet if (!(trm_reg_read8(TRMREG_SCSI_FIFOCNT) & 0x40)) 1736105059Scognet trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL); 1737105059Scognet if (!(trm_reg_read16(TRMREG_DMA_FIFOCNT) & 0x8000)) 1738105059Scognet trm_reg_write8(CLRXFIFO, TRMREG_DMA_CONTROL); 1739105059Scognet } else { 1740105059Scognet if (!(trm_reg_read16(TRMREG_DMA_FIFOCNT) & 0x8000)) 1741105059Scognet trm_reg_write8(CLRXFIFO, TRMREG_DMA_CONTROL); 1742105059Scognet if (!(trm_reg_read8(TRMREG_SCSI_FIFOCNT) & 0x40)) 1743105059Scognet trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL); 1744105059Scognet } 1745105059Scognet pSRB->SRBState = SRB_STATUS; 1746105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1747105059Scognet /* it's important for atn stop */ 1748105059Scognet /* 1749105059Scognet * SCSI cammand 1750105059Scognet */ 1751105059Scognet trm_reg_write8(SCMD_COMP, TRMREG_SCSI_COMMAND); 1752105059Scognet} 1753105059Scognet 1754105059Scognet/* 1755105059Scognet *scsiiom 1756105059Scognet * trm_MsgInPhase0: one of trm_SCSI_phase0[] vectors 1757105059Scognet * stateV = (void *) trm_SCSI_phase0[phase] 1758105059Scognet * if phase =7 1759105059Scognet * extended message codes: 1760105059Scognet * 1761105059Scognet * code description 1762105059Scognet * 1763105059Scognet * 02h Reserved 1764105059Scognet * 00h MODIFY DATA POINTER 1765105059Scognet * 01h SYNCHRONOUS DATA TRANSFER REQUEST 1766105059Scognet * 03h WIDE DATA TRANSFER REQUEST 1767105059Scognet * 04h - 7Fh Reserved 1768105059Scognet * 80h - FFh Vendor specific 1769105059Scognet * 1770105059Scognet */ 1771105059Scognet 1772105059Scognetstatic void 1773111158Scognettrm_MsgInPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 1774105059Scognet{ 1775105059Scognet u_int8_t message_in_code,bIndex,message_in_tag_id; 1776105059Scognet PDCB pDCB; 1777105059Scognet PSRB pSRBTemp; 1778105059Scognet 1779105059Scognet pDCB = pACB->pActiveDCB; 1780105059Scognet 1781105059Scognet message_in_code = trm_reg_read8(TRMREG_SCSI_FIFO); 1782105059Scognet if (!(pSRB->SRBState & SRB_EXTEND_MSGIN)) { 1783105059Scognet if (message_in_code == MSG_DISCONNECT) { 1784105059Scognet pSRB->SRBState = SRB_DISCONNECT; 1785111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1786111158Scognet /* it's important for atn stop */ 1787111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1788111158Scognet /* 1789111158Scognet * SCSI command 1790111158Scognet */ 1791111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1792111158Scognet return; 1793105059Scognet } else if (message_in_code == MSG_SAVE_PTR) { 1794111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1795111158Scognet /* it's important for atn stop */ 1796111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1797111158Scognet /* 1798111158Scognet * SCSI command 1799111158Scognet */ 1800111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1801111158Scognet return; 1802105059Scognet } else if ((message_in_code == MSG_EXTENDED) || 1803105059Scognet ((message_in_code >= MSG_SIMPLE_QTAG) && 1804105059Scognet (message_in_code <= MSG_ORDER_QTAG))) { 1805105059Scognet pSRB->SRBState |= SRB_EXTEND_MSGIN; 1806105059Scognet pSRB->MsgInBuf[0] = message_in_code; 1807105059Scognet /* extended message (01h) */ 1808105059Scognet pSRB->MsgCnt = 1; 1809105059Scognet pSRB->pMsgPtr = &pSRB->MsgInBuf[1]; 1810105059Scognet /* extended message length (n) */ 1811111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1812111158Scognet /* it's important for atn stop */ 1813111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1814111158Scognet /* 1815111158Scognet * SCSI command 1816111158Scognet */ 1817111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1818111158Scognet return; 1819105059Scognet } else if (message_in_code == MSG_REJECT_) { 1820105059Scognet /* Reject message */ 1821105059Scognet if (pDCB->SyncMode & WIDE_NEGO_ENABLE) { 1822105059Scognet /* do wide nego reject */ 1823105059Scognet pDCB = pSRB->pSRBDCB; 1824105059Scognet pDCB->SyncMode |= WIDE_NEGO_DONE; 1825105059Scognet pDCB->SyncMode &= ~(SYNC_NEGO_DONE | 1826105059Scognet EN_ATN_STOP | WIDE_NEGO_ENABLE); 1827105059Scognet pSRB->SRBState &= ~(SRB_DO_WIDE_NEGO+SRB_MSGIN); 1828105059Scognet if ((pDCB->SyncMode & SYNC_NEGO_ENABLE) 1829105059Scognet && !(pDCB->SyncMode & SYNC_NEGO_DONE)) { 1830105059Scognet /* Set ATN, in case ATN was clear */ 1831105059Scognet pSRB->SRBState |= SRB_MSGOUT; 1832105059Scognet trm_reg_write16( 1833105059Scognet DO_SETATN, 1834105059Scognet TRMREG_SCSI_CONTROL); 1835105059Scognet } else { 1836105059Scognet /* Clear ATN */ 1837105059Scognet trm_reg_write16( 1838105059Scognet DO_CLRATN, 1839105059Scognet TRMREG_SCSI_CONTROL); 1840105059Scognet } 1841105059Scognet } else if (pDCB->SyncMode & SYNC_NEGO_ENABLE) { 1842105059Scognet /* do sync nego reject */ 1843105059Scognet trm_reg_write16(DO_CLRATN,TRMREG_SCSI_CONTROL); 1844105059Scognet if (pSRB->SRBState & SRB_DO_SYNC_NEGO) { 1845105059Scognet pDCB = pSRB->pSRBDCB; 1846105059Scognet pDCB->SyncMode &= 1847105059Scognet ~(SYNC_NEGO_ENABLE+SYNC_NEGO_DONE); 1848105059Scognet pDCB->SyncPeriod = 0; 1849105059Scognet pDCB->SyncOffset = 0; 1850111158Scognet /* 1851111158Scognet * 1852111158Scognet * program SCSI control register 1853111158Scognet * 1854111158Scognet */ 1855111158Scognet trm_reg_write8(pDCB->SyncPeriod, 1856111158Scognet TRMREG_SCSI_SYNC); 1857111158Scognet trm_reg_write8(pDCB->SyncOffset, 1858111158Scognet TRMREG_SCSI_OFFSET); 1859111158Scognet trm_SetXferRate(pACB,pSRB,pDCB); 1860105059Scognet } 1861105059Scognet } 1862111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1863111158Scognet /* it's important for atn stop */ 1864111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1865111158Scognet /* 1866111158Scognet * SCSI command 1867111158Scognet */ 1868111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1869111158Scognet return; 1870105059Scognet } else if (message_in_code == MSG_IGNOREWIDE) { 1871105059Scognet trm_reg_write32(1, TRMREG_SCSI_COUNTER); 1872105059Scognet trm_reg_read8(TRMREG_SCSI_FIFO); 1873111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1874111158Scognet /* it's important for atn stop */ 1875111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1876111158Scognet /* 1877111158Scognet * SCSI command 1878111158Scognet */ 1879111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1880111158Scognet return; 1881105059Scognet } else { 1882105059Scognet /* Restore data pointer message */ 1883105059Scognet /* Save data pointer message */ 1884105059Scognet /* Completion message */ 1885105059Scognet /* NOP message */ 1886111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1887111158Scognet /* it's important for atn stop */ 1888111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1889111158Scognet /* 1890111158Scognet * SCSI command 1891111158Scognet */ 1892111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1893111158Scognet return; 1894105059Scognet } 1895105059Scognet } else { 1896105059Scognet /* 1897105059Scognet * Parsing incomming extented messages 1898105059Scognet */ 1899105059Scognet *pSRB->pMsgPtr = message_in_code; 1900105059Scognet pSRB->MsgCnt++; 1901105059Scognet pSRB->pMsgPtr++; 1902105059Scognet TRM_DPRINTF("pSRB->MsgInBuf[0]=%2x \n ",pSRB->MsgInBuf[0]); 1903105059Scognet TRM_DPRINTF("pSRB->MsgInBuf[1]=%2x \n ",pSRB->MsgInBuf[1]); 1904105059Scognet TRM_DPRINTF("pSRB->MsgInBuf[2]=%2x \n ",pSRB->MsgInBuf[2]); 1905105059Scognet TRM_DPRINTF("pSRB->MsgInBuf[3]=%2x \n ",pSRB->MsgInBuf[3]); 1906105059Scognet TRM_DPRINTF("pSRB->MsgInBuf[4]=%2x \n ",pSRB->MsgInBuf[4]); 1907105059Scognet if ((pSRB->MsgInBuf[0] >= MSG_SIMPLE_QTAG) 1908105059Scognet && (pSRB->MsgInBuf[0] <= MSG_ORDER_QTAG)) { 1909105059Scognet /* 1910105059Scognet * is QUEUE tag message : 1911105059Scognet * 1912105059Scognet * byte 0: 1913105059Scognet * HEAD QUEUE TAG (20h) 1914105059Scognet * ORDERED QUEUE TAG (21h) 1915105059Scognet * SIMPLE QUEUE TAG (22h) 1916105059Scognet * byte 1: 1917105059Scognet * Queue tag (00h - FFh) 1918105059Scognet */ 1919105059Scognet if (pSRB->MsgCnt == 2) { 1920105059Scognet pSRB->SRBState = 0; 1921105059Scognet message_in_tag_id = pSRB->MsgInBuf[1]; 1922105059Scognet pSRB = pDCB->pGoingSRB; 1923105059Scognet pSRBTemp = pDCB->pGoingLastSRB; 1924105059Scognet if (pSRB) { 1925105059Scognet for (;;) { 1926105059Scognet if (pSRB->TagNumber != 1927105059Scognet message_in_tag_id) { 1928105059Scognet if (pSRB == pSRBTemp) { 1929105059Scognet goto mingx0; 1930105059Scognet } 1931105059Scognet pSRB = pSRB->pNextSRB; 1932105059Scognet } else 1933105059Scognet break; 1934105059Scognet } 1935105059Scognet if (pDCB->DCBFlag & ABORT_DEV_) { 1936105059Scognet pSRB->SRBState = SRB_ABORT_SENT; 1937105059Scognet trm_EnableMsgOutAbort1( 1938105059Scognet pACB, pSRB); 1939105059Scognet } 1940111158Scognet if (!(pSRB->SRBState & SRB_DISCONNECT)) { 1941111158Scognet TRM_DPRINTF("SRB not yet disconnect........ \n "); 1942105059Scognet goto mingx0; 1943111158Scognet } 1944105059Scognet pDCB->pActiveSRB = pSRB; 1945105059Scognet pSRB->SRBState = SRB_DATA_XFER; 1946105059Scognet } else { 1947105059Scognetmingx0: 1948111158Scognet pSRB = &pACB->TmpSRB; 1949105059Scognet pSRB->SRBState = SRB_UNEXPECT_RESEL; 1950105059Scognet pDCB->pActiveSRB = pSRB; 1951105059Scognet pSRB->MsgOutBuf[0] = MSG_ABORT_TAG; 1952105059Scognet trm_EnableMsgOutAbort2( 1953105059Scognet pACB, 1954105059Scognet pSRB); 1955105059Scognet } 1956105059Scognet } 1957111158Scognet *pscsi_status = PH_BUS_FREE; 1958111158Scognet /* .. initial phase */ 1959111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1960111158Scognet /* it's important for atn stop */ 1961111158Scognet /* 1962111158Scognet * SCSI command 1963111158Scognet */ 1964111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1965111158Scognet return; 1966105059Scognet } else if ((pSRB->MsgInBuf[0] == MSG_EXTENDED) && 1967105059Scognet (pSRB->MsgInBuf[2] == 3) && (pSRB->MsgCnt == 4)) { 1968105059Scognet /* 1969105059Scognet * is Wide data xfer Extended message : 1970105059Scognet * ====================================== 1971105059Scognet * WIDE DATA TRANSFER REQUEST 1972105059Scognet * ====================================== 1973105059Scognet * byte 0 : Extended message (01h) 1974105059Scognet * byte 1 : Extended message length (02h) 1975105059Scognet * byte 2 : WIDE DATA TRANSFER code (03h) 1976105059Scognet * byte 3 : Transfer width exponent 1977105059Scognet */ 1978105059Scognet pDCB = pSRB->pSRBDCB; 1979105059Scognet pSRB->SRBState &= ~(SRB_EXTEND_MSGIN+SRB_DO_WIDE_NEGO); 1980105059Scognet if ((pSRB->MsgInBuf[1] != 2)) { 1981105059Scognet /* Length is wrong, reject it */ 1982105059Scognet pDCB->SyncMode &= 1983105059Scognet ~(WIDE_NEGO_ENABLE+WIDE_NEGO_DONE); 1984105059Scognet pSRB->MsgCnt = 1; 1985105059Scognet pSRB->MsgInBuf[0] = MSG_REJECT_; 1986105059Scognet trm_reg_write16(DO_SETATN, TRMREG_SCSI_CONTROL); 1987111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 1988111158Scognet /* it's important for atn stop */ 1989111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 1990111158Scognet /* 1991111158Scognet * SCSI command 1992111158Scognet */ 1993111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 1994111158Scognet return; 1995105059Scognet } 1996105059Scognet if (pDCB->SyncMode & WIDE_NEGO_ENABLE) { 1997105059Scognet /* Do wide negoniation */ 1998105059Scognet if (pSRB->MsgInBuf[3] > 2) { 1999105059Scognet /* > 32 bit */ 2000105059Scognet /* reject_msg: */ 2001105059Scognet pDCB->SyncMode &= 2002105059Scognet ~(WIDE_NEGO_ENABLE+WIDE_NEGO_DONE); 2003105059Scognet pSRB->MsgCnt = 1; 2004105059Scognet pSRB->MsgInBuf[0] = MSG_REJECT_; 2005105059Scognet trm_reg_write16(DO_SETATN, 2006105059Scognet TRMREG_SCSI_CONTROL); 2007111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 2008111158Scognet /* it's important for atn stop */ 2009111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2010111158Scognet /* 2011111158Scognet * SCSI command 2012111158Scognet */ 2013111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 2014111158Scognet return; 2015105059Scognet } 2016105059Scognet if (pSRB->MsgInBuf[3] == 2) { 2017105059Scognet pSRB->MsgInBuf[3] = 1; 2018105059Scognet /* do 16 bits */ 2019105059Scognet } else { 2020105059Scognet if (!(pDCB->SyncMode 2021105059Scognet & WIDE_NEGO_DONE)) { 2022105059Scognet pSRB->SRBState &= 2023105059Scognet ~(SRB_DO_WIDE_NEGO+SRB_MSGIN); 2024105059Scognet pDCB->SyncMode |= 2025105059Scognet WIDE_NEGO_DONE; 2026105059Scognet pDCB->SyncMode &= 2027105059Scognet ~(SYNC_NEGO_DONE | 2028105059Scognet EN_ATN_STOP | 2029105059Scognet WIDE_NEGO_ENABLE); 2030105059Scognet if (pSRB->MsgInBuf[3] != 0) { 2031105059Scognet /* is Wide data xfer */ 2032105059Scognet pDCB->SyncPeriod |= 2033105059Scognet WIDE_SYNC; 2034105059Scognet pDCB->tinfo.current.width 2035105059Scognet = MSG_EXT_WDTR_BUS_16_BIT; 2036105059Scognet pDCB->tinfo.goal.width 2037105059Scognet = MSG_EXT_WDTR_BUS_16_BIT; 2038105059Scognet } 2039105059Scognet } 2040105059Scognet } 2041105059Scognet } else 2042105059Scognet pSRB->MsgInBuf[3] = 0; 2043105059Scognet pSRB->SRBState |= SRB_MSGOUT; 2044105059Scognet trm_reg_write16(DO_SETATN,TRMREG_SCSI_CONTROL); 2045111158Scognet *pscsi_status = PH_BUS_FREE; /* .. initial phase */ 2046111158Scognet /* it's important for atn stop */ 2047111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2048111158Scognet /* 2049111158Scognet * SCSI command 2050111158Scognet */ 2051111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 2052111158Scognet return; 2053105059Scognet } else if ((pSRB->MsgInBuf[0] == MSG_EXTENDED) && 2054105059Scognet (pSRB->MsgInBuf[2] == 1) && (pSRB->MsgCnt == 5)) { 2055105059Scognet /* 2056105059Scognet * is 8bit transfer Extended message : 2057105059Scognet * ================================= 2058105059Scognet * SYNCHRONOUS DATA TRANSFER REQUEST 2059105059Scognet * ================================= 2060105059Scognet * byte 0 : Extended message (01h) 2061105059Scognet * byte 1 : Extended message length (03) 2062105059Scognet * byte 2 : SYNCHRONOUS DATA TRANSFER code (01h) 2063105059Scognet * byte 3 : Transfer period factor 2064105059Scognet * byte 4 : REQ/ACK offset 2065105059Scognet */ 2066105059Scognet pSRB->SRBState &= ~(SRB_EXTEND_MSGIN+SRB_DO_SYNC_NEGO); 2067105059Scognet if ((pSRB->MsgInBuf[1] != 3) || 2068105059Scognet (pSRB->MsgInBuf[2] != 1)) { 2069105059Scognet /* reject_msg: */ 2070105059Scognet pSRB->MsgCnt = 1; 2071105059Scognet pSRB->MsgInBuf[0] = MSG_REJECT_; 2072105059Scognet trm_reg_write16(DO_SETATN, TRMREG_SCSI_CONTROL); 2073111158Scognet *pscsi_status = PH_BUS_FREE; 2074111158Scognet /* .. initial phase */ 2075111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2076111158Scognet /* it's important for atn stop */ 2077111158Scognet /* 2078111158Scognet * SCSI cammand 2079111158Scognet */ 2080111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 2081111158Scognet return; 2082105059Scognet } else if (!(pSRB->MsgInBuf[3]) || !(pSRB->MsgInBuf[4])) { 2083105059Scognet /* set async */ 2084105059Scognet pDCB = pSRB->pSRBDCB; 2085105059Scognet /* disable sync & sync nego */ 2086105059Scognet pDCB->SyncMode &= 2087105059Scognet ~(SYNC_NEGO_ENABLE+SYNC_NEGO_DONE); 2088105059Scognet pDCB->SyncPeriod = 0; 2089105059Scognet pDCB->SyncOffset = 0; 2090105059Scognet pDCB->tinfo.goal.period = 0; 2091105059Scognet pDCB->tinfo.goal.offset = 0; 2092105059Scognet pDCB->tinfo.current.period = 0; 2093105059Scognet pDCB->tinfo.current.offset = 0; 2094105059Scognet pDCB->tinfo.current.width = 2095105059Scognet MSG_EXT_WDTR_BUS_8_BIT; 2096111158Scognet /* 2097111158Scognet * 2098111158Scognet * program SCSI control register 2099111158Scognet * 2100111158Scognet */ 2101111158Scognet trm_reg_write8(pDCB->SyncPeriod,TRMREG_SCSI_SYNC); 2102111158Scognet trm_reg_write8(pDCB->SyncOffset,TRMREG_SCSI_OFFSET); 2103111158Scognet trm_SetXferRate(pACB,pSRB,pDCB); 2104111158Scognet *pscsi_status = PH_BUS_FREE; 2105111158Scognet /* .. initial phase */ 2106111158Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2107111158Scognet /* it's important for atn stop */ 2108111158Scognet /* 2109111158Scognet * SCSI cammand 2110111158Scognet */ 2111111158Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 2112111158Scognet return; 2113105059Scognet } else { 2114105059Scognet /* set sync */ 2115105059Scognet pDCB = pSRB->pSRBDCB; 2116105059Scognet pDCB->SyncMode |= 2117105059Scognet SYNC_NEGO_ENABLE+SYNC_NEGO_DONE; 2118105059Scognet pDCB->MaxNegoPeriod = pSRB->MsgInBuf[3]; 2119105059Scognet /* Transfer period factor */ 2120105059Scognet pDCB->SyncOffset = pSRB->MsgInBuf[4]; 2121105059Scognet /* REQ/ACK offset */ 2122116813Scognet if (pACB->AdaptType == 1) { 2123111158Scognet for(bIndex = 0; bIndex < 7; bIndex++) { 2124116813Scognet if (pSRB->MsgInBuf[3] <= 2125111158Scognet dc395u2x_clock_period[bIndex]) { 2126111158Scognet pDCB->tinfo.goal.period = 2127111158Scognet dc395u2x_tinfo_period[bIndex]; 2128111158Scognet pDCB->tinfo.current.period = 2129111158Scognet dc395u2x_tinfo_period[bIndex]; 2130111158Scognet pDCB->tinfo.goal.offset = 2131111158Scognet pDCB->SyncOffset; 2132111158Scognet pDCB->tinfo.current.offset = 2133111158Scognet pDCB->SyncOffset; 2134111158Scognet pDCB->SyncPeriod |= (bIndex|LVDS_SYNC); 2135111158Scognet break; 2136111158Scognet } 2137111158Scognet } 2138111158Scognet } else { 2139111158Scognet for(bIndex = 0; bIndex < 7; bIndex++) { 2140116813Scognet if (pSRB->MsgInBuf[3] <= 2141111158Scognet dc395x_clock_period[bIndex]) { 2142111158Scognet pDCB->tinfo.goal.period = 2143111158Scognet dc395x_tinfo_period[bIndex]; 2144111158Scognet pDCB->tinfo.current.period = 2145111158Scognet dc395x_tinfo_period[bIndex]; 2146111158Scognet pDCB->tinfo.goal.offset = 2147111158Scognet pDCB->SyncOffset; 2148111158Scognet pDCB->tinfo.current.offset = 2149111158Scognet pDCB->SyncOffset; 2150111158Scognet pDCB->SyncPeriod |= 2151111158Scognet (bIndex|ALT_SYNC); 2152111158Scognet break; 2153111158Scognet } 2154111158Scognet } 2155105059Scognet } 2156105059Scognet /* 2157105059Scognet * 2158105059Scognet * program SCSI control register 2159105059Scognet * 2160105059Scognet */ 2161105059Scognet trm_reg_write8(pDCB->SyncPeriod, 2162105059Scognet TRMREG_SCSI_SYNC); 2163105059Scognet trm_reg_write8(pDCB->SyncOffset, 2164105059Scognet TRMREG_SCSI_OFFSET); 2165105059Scognet trm_SetXferRate(pACB,pSRB,pDCB); 2166111158Scognet *pscsi_status=PH_BUS_FREE;/*.. initial phase*/ 2167111158Scognet trm_reg_write16(DO_DATALATCH,TRMREG_SCSI_CONTROL);/* it's important for atn stop*/ 2168111158Scognet /* 2169111158Scognet ** SCSI command 2170111158Scognet */ 2171111158Scognet trm_reg_write8(SCMD_MSGACCEPT,TRMREG_SCSI_COMMAND); 2172111158Scognet return; 2173105059Scognet } 2174105059Scognet } 2175105059Scognet *pscsi_status = PH_BUS_FREE; 2176105059Scognet /* .. initial phase */ 2177105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2178105059Scognet /* it's important for atn stop */ 2179105059Scognet /* 2180105059Scognet * SCSI cammand 2181105059Scognet */ 2182105059Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 2183111158Scognet } 2184105059Scognet} 2185105059Scognet 2186105059Scognetstatic void 2187111158Scognettrm_MsgInPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 2188105059Scognet{ 2189105059Scognet 2190105059Scognet trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL); 2191105059Scognet trm_reg_write32(1,TRMREG_SCSI_COUNTER); 2192105059Scognet if (!(pSRB->SRBState & SRB_MSGIN)) { 2193105059Scognet pSRB->SRBState &= SRB_DISCONNECT; 2194105059Scognet pSRB->SRBState |= SRB_MSGIN; 2195105059Scognet } 2196105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2197105059Scognet /* it's important for atn stop*/ 2198105059Scognet /* 2199105059Scognet * SCSI cammand 2200105059Scognet */ 2201105059Scognet trm_reg_write8(SCMD_FIFO_IN, TRMREG_SCSI_COMMAND); 2202105059Scognet} 2203105059Scognet 2204105059Scognetstatic void 2205111158Scognettrm_Nop0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 2206105059Scognet{ 2207105059Scognet 2208105059Scognet} 2209105059Scognet 2210105059Scognetstatic void 2211111158Scognettrm_Nop1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status) 2212105059Scognet{ 2213105059Scognet 2214105059Scognet} 2215105059Scognet 2216105059Scognetstatic void 2217105059Scognettrm_SetXferRate(PACB pACB,PSRB pSRB, PDCB pDCB) 2218105059Scognet{ 2219111158Scognet union ccb *pccb; 2220111158Scognet struct ccb_trans_settings neg; 2221105059Scognet u_int16_t cnt, i; 2222105059Scognet u_int8_t bval; 2223105059Scognet PDCB pDCBTemp; 2224105059Scognet 2225105059Scognet /* 2226105059Scognet * set all lun device's period , offset 2227105059Scognet */ 2228111158Scognet TRM_DPRINTF("trm_SetXferRate\n"); 2229111158Scognet pccb = pSRB->pccb; 2230163816Smjacob memset(&neg, 0, sizeof (neg)); 2231163816Smjacob neg.xport_specific.spi.sync_period = pDCB->tinfo.goal.period; 2232163816Smjacob neg.xport_specific.spi.sync_offset = pDCB->tinfo.goal.offset; 2233163816Smjacob neg.xport_specific.spi.valid = 2234163816Smjacob CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET; 2235111158Scognet xpt_setup_ccb(&neg.ccb_h, pccb->ccb_h.path, /* priority */1); 2236111158Scognet xpt_async(AC_TRANSFER_NEG, pccb->ccb_h.path, &neg); 2237105059Scognet if (!(pDCB->IdentifyMsg & 0x07)) { 2238111158Scognet pDCBTemp = pACB->pLinkDCB; 2239111158Scognet cnt = pACB->DeviceCnt; 2240111158Scognet bval = pDCB->TargetID; 2241111158Scognet for (i = 0; i < cnt; i++) { 2242111158Scognet if (pDCBTemp->TargetID == bval) { 2243111158Scognet pDCBTemp->SyncPeriod = pDCB->SyncPeriod; 2244111158Scognet pDCBTemp->SyncOffset = pDCB->SyncOffset; 2245111158Scognet pDCBTemp->SyncMode = pDCB->SyncMode; 2246105059Scognet } 2247111158Scognet pDCBTemp = pDCBTemp->pNextDCB; 2248105059Scognet } 2249105059Scognet } 2250105059Scognet return; 2251105059Scognet} 2252105059Scognet 2253105059Scognet/* 2254105059Scognet * scsiiom 2255105059Scognet * trm_Interrupt 2256105059Scognet * 2257105059Scognet * 2258105059Scognet * ---SCSI bus phase 2259105059Scognet * 2260105059Scognet * PH_DATA_OUT 0x00 Data out phase 2261105059Scognet * PH_DATA_IN 0x01 Data in phase 2262105059Scognet * PH_COMMAND 0x02 Command phase 2263105059Scognet * PH_STATUS 0x03 Status phase 2264105059Scognet * PH_BUS_FREE 0x04 Invalid phase used as bus free 2265105059Scognet * PH_BUS_FREE 0x05 Invalid phase used as bus free 2266105059Scognet * PH_MSG_OUT 0x06 Message out phase 2267105059Scognet * PH_MSG_IN 0x07 Message in phase 2268105059Scognet * 2269105059Scognet */ 2270105059Scognetstatic void 2271105059Scognettrm_Disconnect(PACB pACB) 2272105059Scognet{ 2273105059Scognet PDCB pDCB; 2274105059Scognet PSRB pSRB, psrb; 2275105059Scognet u_int16_t i,j, cnt; 2276105059Scognet u_int target_id,target_lun; 2277105059Scognet 2278105059Scognet TRM_DPRINTF("trm_Disconnect...............\n "); 2279105059Scognet 2280105059Scognet pDCB = pACB->pActiveDCB; 2281105059Scognet if (!pDCB) { 2282105059Scognet TRM_DPRINTF(" Exception Disconnect DCB=NULL..............\n "); 2283105059Scognet j = 400; 2284105059Scognet while (--j) 2285105059Scognet DELAY(1); 2286105059Scognet /* 1 msec */ 2287105059Scognet trm_reg_write16((DO_CLRFIFO | DO_HWRESELECT), 2288105059Scognet TRMREG_SCSI_CONTROL); 2289105059Scognet return; 2290105059Scognet } 2291105059Scognet pSRB = pDCB->pActiveSRB; 2292105059Scognet /* bug pSRB=0 */ 2293105059Scognet target_id = pSRB->pccb->ccb_h.target_id; 2294105059Scognet target_lun = pSRB->pccb->ccb_h.target_lun; 2295105059Scognet TRM_DPRINTF(":pDCB->pActiveSRB= %8x \n ",(u_int) pDCB->pActiveSRB); 2296105059Scognet pACB->pActiveDCB = 0; 2297105059Scognet pSRB->ScsiPhase = PH_BUS_FREE; 2298105059Scognet /* SCSI bus free Phase */ 2299105059Scognet trm_reg_write16((DO_CLRFIFO | DO_HWRESELECT), TRMREG_SCSI_CONTROL); 2300105059Scognet if (pSRB->SRBState & SRB_UNEXPECT_RESEL) { 2301105059Scognet pSRB->SRBState = 0; 2302105059Scognet trm_DoWaitingSRB(pACB); 2303105059Scognet } else if (pSRB->SRBState & SRB_ABORT_SENT) { 2304105059Scognet pDCB->DCBFlag = 0; 2305105059Scognet cnt = pDCB->GoingSRBCnt; 2306105059Scognet pDCB->GoingSRBCnt = 0; 2307105059Scognet pSRB = pDCB->pGoingSRB; 2308105059Scognet for (i = 0; i < cnt; i++) { 2309105059Scognet psrb = pSRB->pNextSRB; 2310105059Scognet pSRB->pNextSRB = pACB->pFreeSRB; 2311105059Scognet pACB->pFreeSRB = pSRB; 2312105059Scognet pSRB = psrb; 2313105059Scognet } 2314105059Scognet pDCB->pGoingSRB = 0; 2315105059Scognet trm_DoWaitingSRB(pACB); 2316105059Scognet } else { 2317105059Scognet if ((pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) || 2318105059Scognet !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED))) { 2319105059Scognet /* Selection time out */ 2320111158Scognet if (!(pACB->scan_devices[target_id][target_lun]) && 2321111158Scognet pSRB->CmdBlock[0] != 0x00 && /* TEST UNIT READY */ 2322111158Scognet pSRB->CmdBlock[0] != INQUIRY) { 2323105059Scognet pSRB->SRBState = SRB_READY; 2324105059Scognet trm_RewaitSRB(pDCB, pSRB); 2325105059Scognet } else { 2326105059Scognet pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT; 2327105059Scognet goto disc1; 2328105059Scognet } 2329105059Scognet } else if (pSRB->SRBState & SRB_DISCONNECT) { 2330105059Scognet /* 2331105059Scognet * SRB_DISCONNECT 2332105059Scognet */ 2333105059Scognet trm_DoWaitingSRB(pACB); 2334105059Scognet } else if (pSRB->SRBState & SRB_COMPLETED) { 2335105059Scognetdisc1: 2336105059Scognet /* 2337105059Scognet * SRB_COMPLETED 2338105059Scognet */ 2339105059Scognet pDCB->pActiveSRB = 0; 2340105059Scognet pSRB->SRBState = SRB_FREE; 2341105059Scognet trm_SRBdone(pACB, pDCB, pSRB); 2342105059Scognet } 2343105059Scognet } 2344105059Scognet return; 2345105059Scognet} 2346105059Scognet 2347105059Scognetstatic void 2348105059Scognettrm_Reselect(PACB pACB) 2349105059Scognet{ 2350105059Scognet PDCB pDCB; 2351105059Scognet PSRB pSRB; 2352105059Scognet u_int16_t RselTarLunId; 2353105059Scognet 2354105059Scognet TRM_DPRINTF("trm_Reselect................. \n"); 2355105059Scognet pDCB = pACB->pActiveDCB; 2356105059Scognet if (pDCB) { 2357105059Scognet /* Arbitration lost but Reselection win */ 2358105059Scognet pSRB = pDCB->pActiveSRB; 2359105059Scognet pSRB->SRBState = SRB_READY; 2360105059Scognet trm_RewaitSRB(pDCB, pSRB); 2361105059Scognet } 2362105059Scognet /* Read Reselected Target Id and LUN */ 2363105059Scognet RselTarLunId = trm_reg_read16(TRMREG_SCSI_TARGETID) & 0x1FFF; 2364105059Scognet pDCB = pACB->pLinkDCB; 2365105059Scognet while (RselTarLunId != *((u_int16_t *) &pDCB->TargetID)) { 2366105059Scognet /* get pDCB of the reselect id */ 2367105059Scognet pDCB = pDCB->pNextDCB; 2368105059Scognet } 2369105059Scognet 2370105059Scognet pACB->pActiveDCB = pDCB; 2371105059Scognet if (pDCB->SyncMode & EN_TAG_QUEUING) { 2372111158Scognet pSRB = &pACB->TmpSRB; 2373105059Scognet pDCB->pActiveSRB = pSRB; 2374105059Scognet } else { 2375105059Scognet pSRB = pDCB->pActiveSRB; 2376105059Scognet if (!pSRB || !(pSRB->SRBState & SRB_DISCONNECT)) { 2377105059Scognet /* 2378105059Scognet * abort command 2379105059Scognet */ 2380111158Scognet pSRB = &pACB->TmpSRB; 2381105059Scognet pSRB->SRBState = SRB_UNEXPECT_RESEL; 2382105059Scognet pDCB->pActiveSRB = pSRB; 2383105059Scognet trm_EnableMsgOutAbort1(pACB, pSRB); 2384105059Scognet } else { 2385105059Scognet if (pDCB->DCBFlag & ABORT_DEV_) { 2386105059Scognet pSRB->SRBState = SRB_ABORT_SENT; 2387105059Scognet trm_EnableMsgOutAbort1(pACB, pSRB); 2388105059Scognet } else 2389105059Scognet pSRB->SRBState = SRB_DATA_XFER; 2390105059Scognet } 2391105059Scognet } 2392105059Scognet pSRB->ScsiPhase = PH_BUS_FREE; 2393105059Scognet /* SCSI bus free Phase */ 2394105059Scognet /* 2395105059Scognet * Program HA ID, target ID, period and offset 2396105059Scognet */ 2397105059Scognet trm_reg_write8((u_int8_t) RselTarLunId,TRMREG_SCSI_TARGETID); 2398105059Scognet /* target ID */ 2399105059Scognet trm_reg_write8(pACB->AdaptSCSIID,TRMREG_SCSI_HOSTID); 2400105059Scognet /* host ID */ 2401105059Scognet trm_reg_write8(pDCB->SyncPeriod,TRMREG_SCSI_SYNC); 2402105059Scognet /* period */ 2403105059Scognet trm_reg_write8(pDCB->SyncOffset,TRMREG_SCSI_OFFSET); 2404105059Scognet /* offset */ 2405105059Scognet trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL); 2406105059Scognet /* it's important for atn stop*/ 2407105059Scognet /* 2408105059Scognet * SCSI cammand 2409105059Scognet */ 2410105059Scognet trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND); 2411105059Scognet /* to rls the /ACK signal */ 2412105059Scognet} 2413105059Scognet 2414105059Scognetstatic void 2415105059Scognettrm_SRBdone(PACB pACB, PDCB pDCB, PSRB pSRB) 2416105059Scognet{ 2417105059Scognet PSRB psrb; 2418105059Scognet u_int8_t bval, bval1,status; 2419105059Scognet union ccb *pccb; 2420105059Scognet struct ccb_scsiio *pcsio; 2421105059Scognet PSCSI_INQDATA ptr; 2422105059Scognet int intflag; 2423105059Scognet u_int target_id,target_lun; 2424105059Scognet PDCB pTempDCB; 2425105059Scognet 2426105059Scognet pccb = pSRB->pccb; 2427105059Scognet if (pccb == NULL) 2428105059Scognet return; 2429105059Scognet pcsio = &pccb->csio; 2430105059Scognet target_id = pSRB->pccb->ccb_h.target_id; 2431105059Scognet target_lun = pSRB->pccb->ccb_h.target_lun; 2432105059Scognet if ((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 2433115343Sscottl bus_dmasync_op_t op; 2434105059Scognet if ((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 2435105059Scognet op = BUS_DMASYNC_POSTREAD; 2436105059Scognet else 2437105059Scognet op = BUS_DMASYNC_POSTWRITE; 2438105059Scognet bus_dmamap_sync(pACB->buffer_dmat, pSRB->dmamap, op); 2439105059Scognet bus_dmamap_unload(pACB->buffer_dmat, pSRB->dmamap); 2440105059Scognet } 2441105059Scognet /* 2442105059Scognet * 2443105059Scognet * target status 2444105059Scognet * 2445105059Scognet */ 2446105059Scognet status = pSRB->TargetStatus; 2447105059Scognet pcsio->scsi_status=SCSI_STAT_GOOD; 2448105059Scognet pccb->ccb_h.status = CAM_REQ_CMP; 2449105059Scognet if (pSRB->SRBFlag & AUTO_REQSENSE) { 2450105059Scognet /* 2451105059Scognet * status of auto request sense 2452105059Scognet */ 2453105059Scognet pSRB->SRBFlag &= ~AUTO_REQSENSE; 2454105059Scognet pSRB->AdaptStatus = 0; 2455105059Scognet pSRB->TargetStatus = SCSI_STATUS_CHECK_COND; 2456105059Scognet 2457105059Scognet if (status == SCSI_STATUS_CHECK_COND) { 2458105059Scognet pccb->ccb_h.status = CAM_SEL_TIMEOUT; 2459105059Scognet goto ckc_e; 2460105059Scognet } 2461105059Scognet *((u_long *) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0]; 2462105059Scognet *((u_long *) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1]; 2463105059Scognet pSRB->SRBTotalXferLength = pSRB->Segment1[1]; 2464111158Scognet pSRB->pSRBSGL->address = pSRB->SgSenseTemp.address; 2465111158Scognet pSRB->pSRBSGL->length = pSRB->SgSenseTemp.length; 2466105059Scognet pcsio->scsi_status = SCSI_STATUS_CHECK_COND; 2467111158Scognet bcopy(trm_get_sense_buf(pACB, pSRB), &pcsio->sense_data, 2468111158Scognet pcsio->sense_len); 2469111158Scognet pcsio->ccb_h.status = CAM_SCSI_STATUS_ERROR 2470111158Scognet | CAM_AUTOSNS_VALID; 2471105059Scognet goto ckc_e; 2472105059Scognet } 2473105059Scognet /* 2474105059Scognet * target status 2475105059Scognet */ 2476105059Scognet if (status) { 2477105059Scognet if (status == SCSI_STATUS_CHECK_COND) { 2478105059Scognet if ((pcsio->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) { 2479105059Scognet TRM_DPRINTF("trm_RequestSense..................\n"); 2480105059Scognet trm_RequestSense(pACB, pDCB, pSRB); 2481105059Scognet return; 2482105059Scognet } 2483105059Scognet pcsio->scsi_status = SCSI_STATUS_CHECK_COND; 2484111158Scognet pccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 2485105059Scognet goto ckc_e; 2486105059Scognet } else if (status == SCSI_STAT_QUEUEFULL) { 2487105059Scognet bval = (u_int8_t) pDCB->GoingSRBCnt; 2488105059Scognet bval--; 2489111158Scognet pDCB->MaxActiveCommandCnt = bval; 2490105059Scognet trm_RewaitSRB(pDCB, pSRB); 2491105059Scognet pSRB->AdaptStatus = 0; 2492105059Scognet pSRB->TargetStatus = 0; 2493111158Scognet return; 2494105059Scognet } else if (status == SCSI_STAT_SEL_TIMEOUT) { 2495105059Scognet pSRB->AdaptStatus = H_SEL_TIMEOUT; 2496105059Scognet pSRB->TargetStatus = 0; 2497105059Scognet pcsio->scsi_status = SCSI_STAT_SEL_TIMEOUT; 2498105059Scognet pccb->ccb_h.status = CAM_SEL_TIMEOUT; 2499105059Scognet } else if (status == SCSI_STAT_BUSY) { 2500105059Scognet TRM_DPRINTF("trm: target busy at %s %d\n", 2501105059Scognet __FILE__, __LINE__); 2502105059Scognet pcsio->scsi_status = SCSI_STAT_BUSY; 2503105059Scognet pccb->ccb_h.status = CAM_SCSI_BUSY; 2504111158Scognet return; 2505105059Scognet /* The device busy, try again later? */ 2506105059Scognet } else if (status == SCSI_STAT_RESCONFLICT) { 2507105059Scognet TRM_DPRINTF("trm: target reserved at %s %d\n", 2508105059Scognet __FILE__, __LINE__); 2509105059Scognet pcsio->scsi_status = SCSI_STAT_RESCONFLICT; 2510105059Scognet pccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; /*XXX*/ 2511111158Scognet return; 2512105059Scognet } else { 2513105059Scognet pSRB->AdaptStatus = 0; 2514105059Scognet if (pSRB->RetryCnt) { 2515105059Scognet pSRB->RetryCnt--; 2516105059Scognet pSRB->TargetStatus = 0; 2517105059Scognet pSRB->SRBSGIndex = 0; 2518105059Scognet if (trm_StartSCSI(pACB, pDCB, pSRB)) { 2519105059Scognet /* 2520105059Scognet * If trm_StartSCSI return 1 : 2521105059Scognet * current interrupt status is interrupt 2522105059Scognet * disreenable 2523105059Scognet * It's said that SCSI processor has more 2524105059Scognet * one SRB need to do 2525105059Scognet */ 2526105059Scognet trm_RewaitSRB(pDCB, pSRB); 2527105059Scognet } 2528105059Scognet return; 2529105059Scognet } else { 2530105059Scognet TRM_DPRINTF("trm: driver stuffup at %s %d\n", 2531105059Scognet __FILE__, __LINE__); 2532105059Scognet pccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 2533105059Scognet } 2534105059Scognet } 2535105059Scognet } else { 2536105059Scognet /* 2537105059Scognet * process initiator status.......................... 2538105059Scognet * Adapter (initiator) status 2539105059Scognet */ 2540105059Scognet status = pSRB->AdaptStatus; 2541105059Scognet if (status & H_OVER_UNDER_RUN) { 2542105059Scognet pSRB->TargetStatus = 0; 2543105059Scognet pccb->ccb_h.status = CAM_DATA_RUN_ERR; 2544105059Scognet /* Illegal length (over/under run) */ 2545105059Scognet } else if (pSRB->SRBStatus & PARITY_ERROR) { 2546105059Scognet TRM_DPRINTF("trm: driver stuffup %s %d\n", 2547105059Scognet __FILE__, __LINE__); 2548105059Scognet pDCB->tinfo.goal.period = 0; 2549105059Scognet pDCB->tinfo.goal.offset = 0; 2550105059Scognet /* Driver failed to perform operation */ 2551105059Scognet pccb->ccb_h.status = CAM_UNCOR_PARITY; 2552105059Scognet } else { 2553105059Scognet /* no error */ 2554105059Scognet pSRB->AdaptStatus = 0; 2555105059Scognet pSRB->TargetStatus = 0; 2556105059Scognet pccb->ccb_h.status = CAM_REQ_CMP; 2557105059Scognet /* there is no error, (sense is invalid) */ 2558105059Scognet } 2559105059Scognet } 2560105059Scognetckc_e: 2561105059Scognet if (pACB->scan_devices[target_id][target_lun]) { 2562105059Scognet /* 2563105059Scognet * if SCSI command in "scan devices" duty 2564105059Scognet */ 2565105059Scognet if (pSRB->CmdBlock[0] == TEST_UNIT_READY) 2566105059Scognet pACB->scan_devices[target_id][target_lun] = 0; 2567105059Scognet /* SCSI command phase :test unit ready */ 2568105059Scognet else if (pSRB->CmdBlock[0] == INQUIRY) { 2569105059Scognet /* 2570105059Scognet * SCSI command phase :inquiry scsi device data 2571105059Scognet * (type,capacity,manufacture.... 2572105059Scognet */ 2573105059Scognet if (pccb->ccb_h.status == CAM_SEL_TIMEOUT) 2574105059Scognet goto NO_DEV; 2575105059Scognet ptr = (PSCSI_INQDATA) pcsio->data_ptr; 2576105059Scognet /* page fault */ 2577105059Scognet TRM_DPRINTF("trm_SRBdone..PSCSI_INQDATA:%2x \n", 2578105059Scognet ptr->DevType); 2579105059Scognet bval1 = ptr->DevType & SCSI_DEVTYPE; 2580105059Scognet if (bval1 == SCSI_NODEV) { 2581105059ScognetNO_DEV: 2582105059Scognet TRM_DPRINTF("trm_SRBdone NO Device:target_id= %d ,target_lun= %d \n", 2583105059Scognet target_id, 2584105059Scognet target_lun); 2585105059Scognet intflag = splcam(); 2586105059Scognet pACB->scan_devices[target_id][target_lun] = 0; 2587105059Scognet /* no device set scan device flag =0*/ 2588105059Scognet /* pDCB Q link */ 2589105059Scognet /* move the head of DCB to tempDCB*/ 2590105059Scognet pTempDCB=pACB->pLinkDCB; 2591105059Scognet /* search current DCB for pass link */ 2592105059Scognet while (pTempDCB->pNextDCB != pDCB) { 2593105059Scognet pTempDCB = pTempDCB->pNextDCB; 2594105059Scognet } 2595105059Scognet /* 2596105059Scognet * when the current DCB found than connect 2597105059Scognet * current DCB tail 2598105059Scognet */ 2599105059Scognet /* to the DCB tail that before current DCB */ 2600105059Scognet pTempDCB->pNextDCB = pDCB->pNextDCB; 2601105059Scognet /* 2602105059Scognet * if there was only one DCB ,connect his tail 2603105059Scognet * to his head 2604105059Scognet */ 2605105059Scognet if (pACB->pLinkDCB == pDCB) 2606105059Scognet pACB->pLinkDCB = pTempDCB->pNextDCB; 2607105059Scognet if (pACB->pDCBRunRobin == pDCB) 2608105059Scognet pACB->pDCBRunRobin = pTempDCB->pNextDCB; 2609111158Scognet pDCB->DCBstatus &= ~DS_IN_QUEUE; 2610105059Scognet pACB->DeviceCnt--; 2611105059Scognet if (pACB->DeviceCnt == 0) { 2612105059Scognet pACB->pLinkDCB = NULL; 2613105059Scognet pACB->pDCBRunRobin = NULL; 2614105059Scognet } 2615105059Scognet splx(intflag); 2616105059Scognet } else { 2617105059Scognet#ifdef trm_DEBUG1 2618105059Scognet int j; 2619105059Scognet for (j = 0; j < 28; j++) { 2620105059Scognet TRM_DPRINTF("ptr=%2x ", 2621105059Scognet ((u_int8_t *)ptr)[j]); 2622105059Scognet } 2623105059Scognet#endif 2624105059Scognet pDCB->DevType = bval1; 2625105059Scognet if (bval1 == SCSI_DASD || 2626105059Scognet bval1 == SCSI_OPTICAL) { 2627105059Scognet if ((((ptr->Vers & 0x07) >= 2) || 2628105059Scognet ((ptr->RDF & 0x0F) == 2)) && 2629105059Scognet (ptr->Flags & SCSI_INQ_CMDQUEUE) && 2630105059Scognet (pDCB->DevMode & TAG_QUEUING_) && 2631105059Scognet (pDCB->DevMode & EN_DISCONNECT_)) { 2632105059Scognet if (pDCB->DevMode & 2633105059Scognet TAG_QUEUING_) { 2634111158Scognet pDCB-> 2635111158Scognet MaxActiveCommandCnt = 2636105059Scognet pACB->TagMaxNum; 2637105059Scognet pDCB->SyncMode |= 2638105059Scognet EN_TAG_QUEUING; 2639105059Scognet pDCB->tinfo.disc_tag |= 2640105059Scognet TRM_CUR_TAGENB; 2641105059Scognet } else { 2642105059Scognet pDCB->SyncMode |= 2643105059Scognet EN_ATN_STOP; 2644105059Scognet pDCB->tinfo.disc_tag &= 2645105059Scognet ~TRM_CUR_TAGENB; 2646105059Scognet } 2647105059Scognet } 2648105059Scognet } 2649105059Scognet } 2650105059Scognet /* pSRB->CmdBlock[0] == INQUIRY */ 2651105059Scognet } 2652105059Scognet /* pACB->scan_devices[target_id][target_lun] */ 2653105059Scognet } 2654105059Scognet intflag = splcam(); 2655105059Scognet /* ReleaseSRB(pDCB, pSRB); */ 2656105059Scognet if (pSRB == pDCB->pGoingSRB) 2657105059Scognet pDCB->pGoingSRB = pSRB->pNextSRB; 2658105059Scognet else { 2659105059Scognet psrb = pDCB->pGoingSRB; 2660105059Scognet while (psrb->pNextSRB != pSRB) { 2661105059Scognet psrb = psrb->pNextSRB; 2662105059Scognet } 2663105059Scognet psrb->pNextSRB = pSRB->pNextSRB; 2664105059Scognet if (pSRB == pDCB->pGoingLastSRB) { 2665105059Scognet pDCB->pGoingLastSRB = psrb; 2666105059Scognet } 2667105059Scognet } 2668105059Scognet pSRB->pNextSRB = pACB->pFreeSRB; 2669105059Scognet pACB->pFreeSRB = pSRB; 2670105059Scognet pDCB->GoingSRBCnt--; 2671105059Scognet trm_DoWaitingSRB(pACB); 2672105059Scognet 2673105059Scognet splx(intflag); 2674105059Scognet /* Notify cmd done */ 2675105059Scognet xpt_done (pccb); 2676105059Scognet} 2677105059Scognet 2678105059Scognetstatic void 2679105059Scognettrm_DoingSRB_Done(PACB pACB) 2680105059Scognet{ 2681105059Scognet PDCB pDCB, pdcb; 2682105059Scognet PSRB psrb, psrb2; 2683105059Scognet u_int16_t cnt, i; 2684105059Scognet union ccb *pccb; 2685105059Scognet 2686105059Scognet pDCB = pACB->pLinkDCB; 2687105059Scognet if (pDCB == NULL) 2688105059Scognet return; 2689105059Scognet pdcb = pDCB; 2690105059Scognet do { 2691105059Scognet cnt = pdcb->GoingSRBCnt; 2692105059Scognet psrb = pdcb->pGoingSRB; 2693105059Scognet for (i = 0; i < cnt; i++) { 2694105059Scognet psrb2 = psrb->pNextSRB; 2695105059Scognet pccb = psrb->pccb; 2696105059Scognet pccb->ccb_h.status = CAM_SEL_TIMEOUT; 2697105059Scognet /* ReleaseSRB(pDCB, pSRB); */ 2698105059Scognet psrb->pNextSRB = pACB->pFreeSRB; 2699105059Scognet pACB->pFreeSRB = psrb; 2700105059Scognet xpt_done(pccb); 2701105059Scognet psrb = psrb2; 2702105059Scognet } 2703201758Smbr pdcb->GoingSRBCnt = 0; 2704105059Scognet pdcb->pGoingSRB = NULL; 2705105059Scognet pdcb = pdcb->pNextDCB; 2706105059Scognet } 2707105059Scognet while (pdcb != pDCB); 2708105059Scognet} 2709105059Scognet 2710105059Scognetstatic void 2711105059Scognettrm_ResetSCSIBus(PACB pACB) 2712105059Scognet{ 2713105059Scognet int intflag; 2714105059Scognet 2715105059Scognet intflag = splcam(); 2716105059Scognet pACB->ACBFlag |= RESET_DEV; 2717105059Scognet 2718105059Scognet trm_reg_write16(DO_RSTSCSI,TRMREG_SCSI_CONTROL); 2719105059Scognet while (!(trm_reg_read16(TRMREG_SCSI_INTSTATUS) & INT_SCSIRESET)); 2720105059Scognet splx(intflag); 2721105059Scognet return; 2722105059Scognet} 2723105059Scognet 2724105059Scognetstatic void 2725105059Scognettrm_ScsiRstDetect(PACB pACB) 2726105059Scognet{ 2727105059Scognet int intflag; 2728105059Scognet u_long wlval; 2729105059Scognet 2730105059Scognet TRM_DPRINTF("trm_ScsiRstDetect \n"); 2731105059Scognet wlval = 1000; 2732105059Scognet while (--wlval) 2733105059Scognet DELAY(1000); 2734105059Scognet intflag = splcam(); 2735105059Scognet trm_reg_write8(STOPDMAXFER,TRMREG_DMA_CONTROL); 2736105059Scognet 2737105059Scognet trm_reg_write16(DO_CLRFIFO,TRMREG_SCSI_CONTROL); 2738105059Scognet 2739105059Scognet if (pACB->ACBFlag & RESET_DEV) 2740105059Scognet pACB->ACBFlag |= RESET_DONE; 2741105059Scognet else { 2742105059Scognet pACB->ACBFlag |= RESET_DETECT; 2743105059Scognet trm_ResetDevParam(pACB); 2744105059Scognet /* trm_DoingSRB_Done(pACB); ???? */ 2745105059Scognet trm_RecoverSRB(pACB); 2746105059Scognet pACB->pActiveDCB = NULL; 2747105059Scognet pACB->ACBFlag = 0; 2748105059Scognet trm_DoWaitingSRB(pACB); 2749105059Scognet } 2750105059Scognet splx(intflag); 2751105059Scognet return; 2752105059Scognet} 2753105059Scognet 2754105059Scognetstatic void 2755105059Scognettrm_RequestSense(PACB pACB, PDCB pDCB, PSRB pSRB) 2756105059Scognet{ 2757105059Scognet union ccb *pccb; 2758105059Scognet struct ccb_scsiio *pcsio; 2759105059Scognet 2760105059Scognet pccb = pSRB->pccb; 2761105059Scognet pcsio = &pccb->csio; 2762105059Scognet 2763105059Scognet pSRB->SRBFlag |= AUTO_REQSENSE; 2764105059Scognet pSRB->Segment0[0] = *((u_long *) &(pSRB->CmdBlock[0])); 2765105059Scognet pSRB->Segment0[1] = *((u_long *) &(pSRB->CmdBlock[4])); 2766105059Scognet pSRB->Segment1[0] = (u_long) ((pSRB->ScsiCmdLen << 8) + 2767105059Scognet pSRB->SRBSGCount); 2768105059Scognet pSRB->Segment1[1] = pSRB->SRBTotalXferLength; /* ?????????? */ 2769105059Scognet 2770105059Scognet /* $$$$$$ Status of initiator/target $$$$$$$$ */ 2771105059Scognet pSRB->AdaptStatus = 0; 2772105059Scognet pSRB->TargetStatus = 0; 2773105059Scognet /* $$$$$$ Status of initiator/target $$$$$$$$ */ 2774105059Scognet 2775105059Scognet pSRB->SRBTotalXferLength = sizeof(pcsio->sense_data); 2776111158Scognet pSRB->SgSenseTemp.address = pSRB->pSRBSGL->address; 2777111158Scognet pSRB->SgSenseTemp.length = pSRB->pSRBSGL->length; 2778111158Scognet pSRB->pSRBSGL->address = trm_get_sense_bufaddr(pACB, pSRB); 2779111158Scognet pSRB->pSRBSGL->length = (u_long) sizeof(struct scsi_sense_data); 2780105059Scognet pSRB->SRBSGCount = 1; 2781105059Scognet pSRB->SRBSGIndex = 0; 2782105059Scognet 2783105059Scognet *((u_long *) &(pSRB->CmdBlock[0])) = 0x00000003; 2784105059Scognet pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5; 2785105059Scognet *((u_int16_t *) &(pSRB->CmdBlock[4])) = pcsio->sense_len; 2786105059Scognet pSRB->ScsiCmdLen = 6; 2787105059Scognet 2788105059Scognet if (trm_StartSCSI(pACB, pDCB, pSRB)) 2789105059Scognet /* 2790105059Scognet * If trm_StartSCSI return 1 : 2791105059Scognet * current interrupt status is interrupt disreenable 2792105059Scognet * It's said that SCSI processor has more one SRB need to do 2793105059Scognet */ 2794105059Scognet trm_RewaitSRB(pDCB, pSRB); 2795105059Scognet} 2796105059Scognet 2797105059Scognetstatic void 2798105059Scognettrm_EnableMsgOutAbort2(PACB pACB, PSRB pSRB) 2799105059Scognet{ 2800105059Scognet 2801105059Scognet pSRB->MsgCnt = 1; 2802105059Scognet trm_reg_write16(DO_SETATN, TRMREG_SCSI_CONTROL); 2803105059Scognet} 2804105059Scognet 2805105059Scognetstatic void 2806105059Scognettrm_EnableMsgOutAbort1(PACB pACB, PSRB pSRB) 2807105059Scognet{ 2808105059Scognet 2809105059Scognet pSRB->MsgOutBuf[0] = MSG_ABORT; 2810105059Scognet trm_EnableMsgOutAbort2(pACB, pSRB); 2811105059Scognet} 2812105059Scognet 2813105059Scognetstatic void 2814105059Scognettrm_initDCB(PACB pACB, PDCB pDCB, u_int16_t unit,u_int32_t i,u_int32_t j) 2815105059Scognet{ 2816105059Scognet PNVRAMTYPE pEEpromBuf; 2817105059Scognet u_int8_t bval,PeriodIndex; 2818105059Scognet u_int target_id,target_lun; 2819105059Scognet PDCB pTempDCB; 2820105059Scognet int intflag; 2821105059Scognet 2822105059Scognet target_id = i; 2823105059Scognet target_lun = j; 2824105059Scognet 2825111158Scognet /* 2826111158Scognet * Using the lun 0 device to init other DCB first, if the device 2827111158Scognet * has been initialized. 2828111158Scognet * I don't want init sync arguments one by one, it is the same. 2829111158Scognet */ 2830111158Scognet if (target_lun != 0 && 2831111158Scognet (pACB->DCBarray[target_id][0].DCBstatus & DS_IN_QUEUE)) 2832111158Scognet bcopy(&pACB->DCBarray[target_id][0], pDCB, 2833111158Scognet sizeof(TRM_DCB)); 2834105059Scognet intflag = splcam(); 2835105059Scognet if (pACB->pLinkDCB == 0) { 2836105059Scognet pACB->pLinkDCB = pDCB; 2837105059Scognet /* 2838105059Scognet * RunRobin impersonate the role 2839105059Scognet * that let each device had good proportion 2840105059Scognet * about SCSI command proceeding 2841105059Scognet */ 2842105059Scognet pACB->pDCBRunRobin = pDCB; 2843105059Scognet pDCB->pNextDCB = pDCB; 2844105059Scognet } else { 2845105059Scognet pTempDCB=pACB->pLinkDCB; 2846105059Scognet /* search the last nod of DCB link */ 2847105059Scognet while (pTempDCB->pNextDCB != pACB->pLinkDCB) 2848105059Scognet pTempDCB = pTempDCB->pNextDCB; 2849105059Scognet /* connect current DCB with last DCB tail */ 2850105059Scognet pTempDCB->pNextDCB = pDCB; 2851105059Scognet /* connect current DCB tail to this DCB Q head */ 2852105059Scognet pDCB->pNextDCB=pACB->pLinkDCB; 2853105059Scognet } 2854105059Scognet splx(intflag); 2855105059Scognet 2856105059Scognet pACB->DeviceCnt++; 2857105059Scognet pDCB->TargetID = target_id; 2858105059Scognet pDCB->TargetLUN = target_lun; 2859105059Scognet pDCB->pWaitingSRB = NULL; 2860105059Scognet pDCB->pGoingSRB = NULL; 2861105059Scognet pDCB->GoingSRBCnt = 0; 2862105059Scognet pDCB->pActiveSRB = NULL; 2863111158Scognet pDCB->MaxActiveCommandCnt = 1; 2864105059Scognet pDCB->DCBFlag = 0; 2865111158Scognet pDCB->DCBstatus |= DS_IN_QUEUE; 2866105059Scognet /* $$$$$$$ */ 2867105059Scognet pEEpromBuf = &trm_eepromBuf[unit]; 2868105059Scognet pDCB->DevMode = pEEpromBuf->NvramTarget[target_id].NvmTarCfg0; 2869105059Scognet pDCB->AdpMode = pEEpromBuf->NvramChannelCfg; 2870105059Scognet /* $$$$$$$ */ 2871105059Scognet /* 2872105059Scognet * disconnect enable ? 2873105059Scognet */ 2874105059Scognet if (pDCB->DevMode & NTC_DO_DISCONNECT) { 2875105059Scognet bval = 0xC0; 2876105059Scognet pDCB->tinfo.disc_tag |= TRM_USR_DISCENB ; 2877105059Scognet } else { 2878105059Scognet bval = 0x80; 2879105059Scognet pDCB->tinfo.disc_tag &= ~(TRM_USR_DISCENB); 2880105059Scognet } 2881105059Scognet bval |= target_lun; 2882105059Scognet pDCB->IdentifyMsg = bval; 2883111158Scognet if (target_lun != 0 && 2884111158Scognet (pACB->DCBarray[target_id][0].DCBstatus & DS_IN_QUEUE)) 2885111158Scognet return; 2886105059Scognet /* $$$$$$$ */ 2887105059Scognet /* 2888105059Scognet * tag Qing enable ? 2889105059Scognet */ 2890105059Scognet if (pDCB->DevMode & TAG_QUEUING_) { 2891105059Scognet pDCB->tinfo.disc_tag |= TRM_USR_TAGENB ; 2892105059Scognet } else 2893105059Scognet pDCB->tinfo.disc_tag &= ~(TRM_USR_TAGENB); 2894105059Scognet /* $$$$$$$ */ 2895105059Scognet /* 2896105059Scognet * wide nego ,sync nego enable ? 2897105059Scognet */ 2898105059Scognet pDCB->SyncPeriod = 0; 2899105059Scognet pDCB->SyncOffset = 0; 2900105059Scognet PeriodIndex = pEEpromBuf->NvramTarget[target_id].NvmTarPeriod & 0x07; 2901116813Scognet if (pACB->AdaptType==1) {/* is U2? */ 2902111158Scognet pDCB->MaxNegoPeriod=dc395u2x_clock_period[ PeriodIndex ]; 2903111158Scognet pDCB->tinfo.user.period=pDCB->MaxNegoPeriod; 2904111158Scognet pDCB->tinfo.user.offset=(pDCB->SyncMode & SYNC_NEGO_ENABLE) ? 31 : 0; 2905111158Scognet } else { 2906111158Scognet pDCB->MaxNegoPeriod=dc395x_clock_period[ PeriodIndex ]; 2907111158Scognet pDCB->tinfo.user.period=pDCB->MaxNegoPeriod; 2908111158Scognet pDCB->tinfo.user.offset=(pDCB->SyncMode & SYNC_NEGO_ENABLE) ? 15 : 0; 2909111158Scognet } 2910105059Scognet pDCB->SyncMode = 0; 2911105059Scognet if ((pDCB->DevMode & NTC_DO_WIDE_NEGO) && 2912105059Scognet (pACB->Config & HCC_WIDE_CARD)) 2913105059Scognet pDCB->SyncMode |= WIDE_NEGO_ENABLE; 2914105059Scognet /* enable wide nego */ 2915105059Scognet if (pDCB->DevMode & NTC_DO_SYNC_NEGO) 2916105059Scognet pDCB->SyncMode |= SYNC_NEGO_ENABLE; 2917105059Scognet /* enable sync nego */ 2918105059Scognet /* $$$$$$$ */ 2919105059Scognet /* 2920105059Scognet * Fill in tinfo structure. 2921105059Scognet */ 2922105059Scognet pDCB->tinfo.user.width = (pDCB->SyncMode & WIDE_NEGO_ENABLE) ? 2923105059Scognet MSG_EXT_WDTR_BUS_16_BIT : MSG_EXT_WDTR_BUS_8_BIT; 2924105059Scognet 2925105059Scognet pDCB->tinfo.current.period = 0; 2926105059Scognet pDCB->tinfo.current.offset = 0; 2927105059Scognet pDCB->tinfo.current.width = MSG_EXT_WDTR_BUS_8_BIT; 2928105059Scognet} 2929105059Scognet 2930111158Scognetstatic void 2931111158Scognettrm_srbmapSG(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2932105059Scognet{ 2933111158Scognet PSRB pSRB; 2934111158Scognet 2935111158Scognet pSRB=(PSRB) arg; 2936111158Scognet pSRB->SRBSGPhyAddr=segs->ds_addr; 2937111158Scognet return; 2938105059Scognet} 2939105059Scognet 2940126725Scognetstatic void 2941126725Scognettrm_destroySRB(PACB pACB) 2942126725Scognet{ 2943126725Scognet PSRB pSRB; 2944126725Scognet 2945126725Scognet pSRB = pACB->pFreeSRB; 2946126725Scognet while (pSRB) { 2947126725Scognet if (pSRB->sg_dmamap) { 2948126725Scognet bus_dmamap_unload(pACB->sg_dmat, pSRB->sg_dmamap); 2949126725Scognet bus_dmamem_free(pACB->sg_dmat, pSRB->pSRBSGL, 2950126725Scognet pSRB->sg_dmamap); 2951126725Scognet bus_dmamap_destroy(pACB->sg_dmat, pSRB->sg_dmamap); 2952126725Scognet } 2953126725Scognet if (pSRB->dmamap) 2954126725Scognet bus_dmamap_destroy(pACB->buffer_dmat, pSRB->dmamap); 2955126725Scognet pSRB = pSRB->pNextSRB; 2956126725Scognet } 2957126725Scognet} 2958126725Scognet 2959111158Scognetstatic int 2960111158Scognettrm_initSRB(PACB pACB) 2961105059Scognet{ 2962116813Scognet u_int16_t i; 2963116813Scognet PSRB pSRB; 2964118693Sscottl int error; 2965105059Scognet 2966116813Scognet for (i = 0; i < TRM_MAX_SRB_CNT; i++) { 2967116813Scognet pSRB = (PSRB)&pACB->pFreeSRB[i]; 2968111158Scognet 2969126725Scognet if (bus_dmamem_alloc(pACB->sg_dmat, (void **)&pSRB->pSRBSGL, 2970116813Scognet BUS_DMA_NOWAIT, &pSRB->sg_dmamap) !=0 ) { 2971116813Scognet return ENXIO; 2972111158Scognet } 2973126725Scognet bus_dmamap_load(pACB->sg_dmat, pSRB->sg_dmamap, pSRB->pSRBSGL, 2974116813Scognet TRM_MAX_SG_LISTENTRY * sizeof(SGentry), 2975116813Scognet trm_srbmapSG, pSRB, /*flags*/0); 2976116813Scognet if (i != TRM_MAX_SRB_CNT - 1) { 2977116813Scognet /* 2978116813Scognet * link all SRB 2979116813Scognet */ 2980116813Scognet pSRB->pNextSRB = &pACB->pFreeSRB[i+1]; 2981116813Scognet } else { 2982116813Scognet /* 2983116813Scognet * load NULL to NextSRB of the last SRB 2984116813Scognet */ 2985116813Scognet pSRB->pNextSRB = NULL; 2986116813Scognet } 2987116813Scognet pSRB->TagNumber = i; 2988118693Sscottl 2989118693Sscottl /* 2990118693Sscottl * Create the dmamap. This is no longer optional! 2991118693Sscottl */ 2992118693Sscottl if ((error = bus_dmamap_create(pACB->buffer_dmat, 0, 2993118693Sscottl &pSRB->dmamap)) != 0) 2994118693Sscottl return (error); 2995118693Sscottl 2996105059Scognet } 2997116813Scognet return (0); 2998105059Scognet} 2999105059Scognet 3000105059Scognet 3001111158Scognet 3002111158Scognet 3003105059Scognetstatic void 3004111158Scognettrm_initACB(PACB pACB, u_int8_t adaptType, u_int16_t unit) 3005105059Scognet{ 3006105059Scognet PNVRAMTYPE pEEpromBuf; 3007105059Scognet 3008105059Scognet pEEpromBuf = &trm_eepromBuf[unit]; 3009105059Scognet pACB->max_id = 15; 3010105059Scognet 3011105059Scognet if (pEEpromBuf->NvramChannelCfg & NAC_SCANLUN) 3012105059Scognet pACB->max_lun = 7; 3013105059Scognet else 3014105059Scognet pACB->max_lun = 0; 3015105059Scognet 3016105059Scognet TRM_DPRINTF("trm: pACB->max_id= %d pACB->max_lun= %d \n", 3017105059Scognet pACB->max_id, pACB->max_lun); 3018105059Scognet pACB->pLinkDCB = NULL; 3019105059Scognet pACB->pDCBRunRobin = NULL; 3020105059Scognet pACB->pActiveDCB = NULL; 3021111158Scognet pACB->AdapterUnit = (u_int8_t)unit; 3022105059Scognet pACB->AdaptSCSIID = pEEpromBuf->NvramScsiId; 3023105059Scognet pACB->AdaptSCSILUN = 0; 3024105059Scognet pACB->DeviceCnt = 0; 3025111158Scognet pACB->AdaptType = adaptType; 3026111158Scognet pACB->TagMaxNum = 2 << pEEpromBuf->NvramMaxTag; 3027105059Scognet pACB->ACBFlag = 0; 3028111158Scognet return; 3029105059Scognet} 3030105059Scognet 3031105059Scognetstatic void 3032111158ScognetNVRAM_trm_write_all(PNVRAMTYPE pEEpromBuf,PACB pACB) 3033105059Scognet{ 3034105059Scognet u_int8_t *bpEeprom = (u_int8_t *) pEEpromBuf; 3035105059Scognet u_int8_t bAddr; 3036105059Scognet 3037105059Scognet /* Enable SEEPROM */ 3038105059Scognet trm_reg_write8((trm_reg_read8(TRMREG_GEN_CONTROL) | EN_EEPROM), 3039105059Scognet TRMREG_GEN_CONTROL); 3040105059Scognet /* 3041105059Scognet * Write enable 3042105059Scognet */ 3043111158Scognet NVRAM_trm_write_cmd(pACB, 0x04, 0xFF); 3044105059Scognet trm_reg_write8(0, TRMREG_GEN_NVRAM); 3045111158Scognet NVRAM_trm_wait_30us(pACB); 3046105059Scognet for (bAddr = 0; bAddr < 128; bAddr++, bpEeprom++) { 3047111158Scognet NVRAM_trm_set_data(pACB, bAddr, *bpEeprom); 3048105059Scognet } 3049105059Scognet /* 3050105059Scognet * Write disable 3051105059Scognet */ 3052111158Scognet NVRAM_trm_write_cmd(pACB, 0x04, 0x00); 3053105059Scognet trm_reg_write8(0 , TRMREG_GEN_NVRAM); 3054111158Scognet NVRAM_trm_wait_30us(pACB); 3055105059Scognet /* Disable SEEPROM */ 3056105059Scognet trm_reg_write8((trm_reg_read8(TRMREG_GEN_CONTROL) & ~EN_EEPROM), 3057105059Scognet TRMREG_GEN_CONTROL); 3058105059Scognet return; 3059105059Scognet} 3060105059Scognet 3061105059Scognetstatic void 3062111158ScognetNVRAM_trm_set_data(PACB pACB, u_int8_t bAddr, u_int8_t bData) 3063105059Scognet{ 3064105059Scognet int i; 3065105059Scognet u_int8_t bSendData; 3066105059Scognet /* 3067105059Scognet * Send write command & address 3068105059Scognet */ 3069105059Scognet 3070111158Scognet NVRAM_trm_write_cmd(pACB, 0x05, bAddr); 3071105059Scognet /* 3072105059Scognet * Write data 3073105059Scognet */ 3074105059Scognet for (i = 0; i < 8; i++, bData <<= 1) { 3075105059Scognet bSendData = NVR_SELECT; 3076105059Scognet if (bData & 0x80) 3077105059Scognet /* Start from bit 7 */ 3078105059Scognet bSendData |= NVR_BITOUT; 3079105059Scognet trm_reg_write8(bSendData , TRMREG_GEN_NVRAM); 3080111158Scognet NVRAM_trm_wait_30us(pACB); 3081105059Scognet trm_reg_write8((bSendData | NVR_CLOCK), TRMREG_GEN_NVRAM); 3082111158Scognet NVRAM_trm_wait_30us(pACB); 3083105059Scognet } 3084105059Scognet trm_reg_write8(NVR_SELECT , TRMREG_GEN_NVRAM); 3085111158Scognet NVRAM_trm_wait_30us(pACB); 3086105059Scognet /* 3087105059Scognet * Disable chip select 3088105059Scognet */ 3089105059Scognet trm_reg_write8(0 , TRMREG_GEN_NVRAM); 3090111158Scognet NVRAM_trm_wait_30us(pACB); 3091105059Scognet trm_reg_write8(NVR_SELECT ,TRMREG_GEN_NVRAM); 3092111158Scognet NVRAM_trm_wait_30us(pACB); 3093105059Scognet /* 3094105059Scognet * Wait for write ready 3095105059Scognet */ 3096105059Scognet while (1) { 3097105059Scognet trm_reg_write8((NVR_SELECT | NVR_CLOCK), TRMREG_GEN_NVRAM); 3098111158Scognet NVRAM_trm_wait_30us(pACB); 3099105059Scognet trm_reg_write8(NVR_SELECT, TRMREG_GEN_NVRAM); 3100111158Scognet NVRAM_trm_wait_30us(pACB); 3101105059Scognet if (trm_reg_read8(TRMREG_GEN_NVRAM) & NVR_BITIN) { 3102105059Scognet break; 3103105059Scognet } 3104105059Scognet } 3105105059Scognet /* 3106105059Scognet * Disable chip select 3107105059Scognet */ 3108105059Scognet trm_reg_write8(0, TRMREG_GEN_NVRAM); 3109105059Scognet return; 3110105059Scognet} 3111105059Scognet 3112105059Scognetstatic void 3113111158ScognetNVRAM_trm_read_all(PNVRAMTYPE pEEpromBuf, PACB pACB) 3114105059Scognet{ 3115105059Scognet u_int8_t *bpEeprom = (u_int8_t*) pEEpromBuf; 3116105059Scognet u_int8_t bAddr; 3117105059Scognet 3118105059Scognet /* 3119105059Scognet * Enable SEEPROM 3120105059Scognet */ 3121105059Scognet trm_reg_write8((trm_reg_read8(TRMREG_GEN_CONTROL) | EN_EEPROM), 3122105059Scognet TRMREG_GEN_CONTROL); 3123105059Scognet for (bAddr = 0; bAddr < 128; bAddr++, bpEeprom++) 3124111158Scognet *bpEeprom = NVRAM_trm_get_data(pACB, bAddr); 3125105059Scognet /* 3126105059Scognet * Disable SEEPROM 3127105059Scognet */ 3128105059Scognet trm_reg_write8((trm_reg_read8(TRMREG_GEN_CONTROL) & ~EN_EEPROM), 3129105059Scognet TRMREG_GEN_CONTROL); 3130105059Scognet return; 3131105059Scognet} 3132105059Scognet 3133105059Scognetstatic u_int8_t 3134111158ScognetNVRAM_trm_get_data(PACB pACB, u_int8_t bAddr) 3135105059Scognet{ 3136105059Scognet int i; 3137105059Scognet u_int8_t bReadData, bData = 0; 3138105059Scognet /* 3139105059Scognet * Send read command & address 3140105059Scognet */ 3141105059Scognet 3142111158Scognet NVRAM_trm_write_cmd(pACB, 0x06, bAddr); 3143105059Scognet 3144105059Scognet for (i = 0; i < 8; i++) { 3145105059Scognet /* 3146105059Scognet * Read data 3147105059Scognet */ 3148105059Scognet trm_reg_write8((NVR_SELECT | NVR_CLOCK) , TRMREG_GEN_NVRAM); 3149111158Scognet NVRAM_trm_wait_30us(pACB); 3150105059Scognet trm_reg_write8(NVR_SELECT , TRMREG_GEN_NVRAM); 3151105059Scognet /* 3152105059Scognet * Get data bit while falling edge 3153105059Scognet */ 3154105059Scognet bReadData = trm_reg_read8(TRMREG_GEN_NVRAM); 3155105059Scognet bData <<= 1; 3156105059Scognet if (bReadData & NVR_BITIN) { 3157105059Scognet bData |= 1; 3158105059Scognet } 3159111158Scognet NVRAM_trm_wait_30us(pACB); 3160105059Scognet } 3161105059Scognet /* 3162105059Scognet * Disable chip select 3163105059Scognet */ 3164105059Scognet trm_reg_write8(0, TRMREG_GEN_NVRAM); 3165105059Scognet return (bData); 3166105059Scognet} 3167105059Scognet 3168105059Scognetstatic void 3169111158ScognetNVRAM_trm_wait_30us(PACB pACB) 3170105059Scognet{ 3171105059Scognet 3172105059Scognet /* ScsiPortStallExecution(30); wait 30 us */ 3173105059Scognet trm_reg_write8(5, TRMREG_GEN_TIMER); 3174105059Scognet while (!(trm_reg_read8(TRMREG_GEN_STATUS) & GTIMEOUT)); 3175105059Scognet return; 3176105059Scognet} 3177105059Scognet 3178105059Scognetstatic void 3179111158ScognetNVRAM_trm_write_cmd(PACB pACB, u_int8_t bCmd, u_int8_t bAddr) 3180105059Scognet{ 3181105059Scognet int i; 3182105059Scognet u_int8_t bSendData; 3183105059Scognet 3184105059Scognet for (i = 0; i < 3; i++, bCmd <<= 1) { 3185105059Scognet /* 3186105059Scognet * Program SB+OP code 3187105059Scognet */ 3188105059Scognet bSendData = NVR_SELECT; 3189105059Scognet if (bCmd & 0x04) 3190105059Scognet bSendData |= NVR_BITOUT; 3191105059Scognet /* start from bit 2 */ 3192105059Scognet trm_reg_write8(bSendData, TRMREG_GEN_NVRAM); 3193111158Scognet NVRAM_trm_wait_30us(pACB); 3194105059Scognet trm_reg_write8((bSendData | NVR_CLOCK), TRMREG_GEN_NVRAM); 3195111158Scognet NVRAM_trm_wait_30us(pACB); 3196105059Scognet } 3197105059Scognet for (i = 0; i < 7; i++, bAddr <<= 1) { 3198105059Scognet /* 3199105059Scognet * Program address 3200105059Scognet */ 3201105059Scognet bSendData = NVR_SELECT; 3202105059Scognet if (bAddr & 0x40) 3203105059Scognet /* Start from bit 6 */ 3204105059Scognet bSendData |= NVR_BITOUT; 3205105059Scognet trm_reg_write8(bSendData , TRMREG_GEN_NVRAM); 3206111158Scognet NVRAM_trm_wait_30us(pACB); 3207105059Scognet trm_reg_write8((bSendData | NVR_CLOCK), TRMREG_GEN_NVRAM); 3208111158Scognet NVRAM_trm_wait_30us(pACB); 3209105059Scognet } 3210105059Scognet trm_reg_write8(NVR_SELECT, TRMREG_GEN_NVRAM); 3211111158Scognet NVRAM_trm_wait_30us(pACB); 3212105059Scognet} 3213105059Scognet 3214105059Scognetstatic void 3215105059Scognettrm_check_eeprom(PNVRAMTYPE pEEpromBuf, PACB pACB) 3216105059Scognet{ 3217105059Scognet u_int16_t *wpEeprom = (u_int16_t *) pEEpromBuf; 3218105059Scognet u_int16_t wAddr, wCheckSum; 3219105059Scognet u_long dAddr, *dpEeprom; 3220105059Scognet 3221111158Scognet NVRAM_trm_read_all(pEEpromBuf,pACB); 3222105059Scognet wCheckSum = 0; 3223105059Scognet for (wAddr = 0, wpEeprom = (u_int16_t *) pEEpromBuf; 3224105059Scognet wAddr < 64; wAddr++, wpEeprom++) { 3225105059Scognet wCheckSum += *wpEeprom; 3226105059Scognet } 3227105059Scognet if (wCheckSum != 0x1234) { 3228105059Scognet /* 3229105059Scognet * Checksum error, load default 3230105059Scognet */ 3231105059Scognet pEEpromBuf->NvramSubVendorID[0] = (u_int8_t) PCI_Vendor_ID_TEKRAM; 3232105059Scognet pEEpromBuf->NvramSubVendorID[1] = 3233105059Scognet (u_int8_t) (PCI_Vendor_ID_TEKRAM >> 8); 3234105059Scognet pEEpromBuf->NvramSubSysID[0] = (u_int8_t) PCI_Device_ID_TRM_S1040; 3235105059Scognet pEEpromBuf->NvramSubSysID[1] = 3236105059Scognet (u_int8_t) (PCI_Device_ID_TRM_S1040 >> 8); 3237105059Scognet pEEpromBuf->NvramSubClass = 0x00; 3238105059Scognet pEEpromBuf->NvramVendorID[0] = (u_int8_t) PCI_Vendor_ID_TEKRAM; 3239105059Scognet pEEpromBuf->NvramVendorID[1] = 3240105059Scognet (u_int8_t) (PCI_Vendor_ID_TEKRAM >> 8); 3241105059Scognet pEEpromBuf->NvramDeviceID[0] = (u_int8_t) PCI_Device_ID_TRM_S1040; 3242105059Scognet pEEpromBuf->NvramDeviceID[1] = 3243105059Scognet (u_int8_t) (PCI_Device_ID_TRM_S1040 >> 8); 3244105059Scognet pEEpromBuf->NvramReserved = 0x00; 3245105059Scognet 3246105059Scognet for (dAddr = 0, dpEeprom = (u_long *) pEEpromBuf->NvramTarget; 3247105059Scognet dAddr < 16; dAddr++, dpEeprom++) { 3248105059Scognet *dpEeprom = 0x00000077; 3249105059Scognet /* NvmTarCfg3,NvmTarCfg2,NvmTarPeriod,NvmTarCfg0 */ 3250105059Scognet } 3251105059Scognet 3252105059Scognet *dpEeprom++ = 0x04000F07; 3253105059Scognet /* NvramMaxTag,NvramDelayTime,NvramChannelCfg,NvramScsiId */ 3254105059Scognet *dpEeprom++ = 0x00000015; 3255105059Scognet /* NvramReserved1,NvramBootLun,NvramBootTarget,NvramReserved0 */ 3256105059Scognet for (dAddr = 0; dAddr < 12; dAddr++, dpEeprom++) 3257105059Scognet *dpEeprom = 0x00; 3258105059Scognet pEEpromBuf->NvramCheckSum = 0x00; 3259105059Scognet for (wAddr = 0, wCheckSum = 0, wpEeprom = (u_int16_t *) pEEpromBuf; 3260105059Scognet wAddr < 63; wAddr++, wpEeprom++) 3261105059Scognet wCheckSum += *wpEeprom; 3262105059Scognet *wpEeprom = 0x1234 - wCheckSum; 3263111158Scognet NVRAM_trm_write_all(pEEpromBuf,pACB); 3264105059Scognet } 3265105059Scognet return; 3266105059Scognet} 3267105059Scognetstatic int 3268111158Scognettrm_initAdapter(PACB pACB, u_int16_t unit) 3269105059Scognet{ 3270105059Scognet PNVRAMTYPE pEEpromBuf; 3271105059Scognet u_int16_t wval; 3272105059Scognet u_int8_t bval; 3273105059Scognet 3274105059Scognet pEEpromBuf = &trm_eepromBuf[unit]; 3275105059Scognet 3276105059Scognet /* 250ms selection timeout */ 3277105059Scognet trm_reg_write8(SEL_TIMEOUT, TRMREG_SCSI_TIMEOUT); 3278105059Scognet /* Mask all the interrupt */ 3279105059Scognet trm_reg_write8(0x00, TRMREG_DMA_INTEN); 3280105059Scognet trm_reg_write8(0x00, TRMREG_SCSI_INTEN); 3281105059Scognet /* Reset SCSI module */ 3282105059Scognet trm_reg_write16(DO_RSTMODULE, TRMREG_SCSI_CONTROL); 3283105059Scognet /* program configuration 0 */ 3284105059Scognet pACB->Config = HCC_AUTOTERM | HCC_PARITY; 3285105059Scognet if (trm_reg_read8(TRMREG_GEN_STATUS) & WIDESCSI) 3286105059Scognet pACB->Config |= HCC_WIDE_CARD; 3287105059Scognet if (pEEpromBuf->NvramChannelCfg & NAC_POWERON_SCSI_RESET) 3288105059Scognet pACB->Config |= HCC_SCSI_RESET; 3289105059Scognet if (pACB->Config & HCC_PARITY) 3290105059Scognet bval = PHASELATCH | INITIATOR | BLOCKRST | PARITYCHECK; 3291105059Scognet else 3292105059Scognet bval = PHASELATCH | INITIATOR | BLOCKRST ; 3293105059Scognet trm_reg_write8(bval,TRMREG_SCSI_CONFIG0); 3294105059Scognet /* program configuration 1 */ 3295105059Scognet trm_reg_write8(0x13, TRMREG_SCSI_CONFIG1); 3296105059Scognet /* program Host ID */ 3297105059Scognet bval = pEEpromBuf->NvramScsiId; 3298105059Scognet trm_reg_write8(bval, TRMREG_SCSI_HOSTID); 3299105059Scognet /* set ansynchronous transfer */ 3300105059Scognet trm_reg_write8(0x00, TRMREG_SCSI_OFFSET); 3301105059Scognet /* Trun LED control off*/ 3302105059Scognet wval = trm_reg_read16(TRMREG_GEN_CONTROL) & 0x7F; 3303105059Scognet trm_reg_write16(wval, TRMREG_GEN_CONTROL); 3304105059Scognet /* DMA config */ 3305105059Scognet wval = trm_reg_read16(TRMREG_DMA_CONFIG) | DMA_ENHANCE; 3306105059Scognet trm_reg_write16(wval, TRMREG_DMA_CONFIG); 3307105059Scognet /* Clear pending interrupt status */ 3308105059Scognet trm_reg_read8(TRMREG_SCSI_INTSTATUS); 3309105059Scognet /* Enable SCSI interrupt */ 3310105059Scognet trm_reg_write8(0x7F, TRMREG_SCSI_INTEN); 3311105059Scognet trm_reg_write8(EN_SCSIINTR, TRMREG_DMA_INTEN); 3312105059Scognet return (0); 3313105059Scognet} 3314105059Scognet 3315111158Scognetstatic void 3316111158Scognettrm_mapSRB(void *arg, bus_dma_segment_t *segs, int nseg, int error) 3317111158Scognet{ 3318111158Scognet PACB pACB; 3319111158Scognet 3320111158Scognet pACB = (PACB)arg; 3321111158Scognet pACB->srb_physbase = segs->ds_addr; 3322111158Scognet} 3323111158Scognet 3324111158Scognetstatic void 3325111158Scognettrm_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 3326111158Scognet{ 3327111158Scognet bus_addr_t *baddr; 3328111158Scognet 3329111158Scognet baddr = (bus_addr_t *)arg; 3330111158Scognet *baddr = segs->ds_addr; 3331111158Scognet} 3332111158Scognet 3333105059Scognetstatic PACB 3334111158Scognettrm_init(u_int16_t unit, device_t dev) 3335105059Scognet{ 3336105059Scognet PACB pACB; 3337119690Sjhb int rid = PCIR_BAR(0), i = 0, j = 0; 3338111158Scognet u_int16_t adaptType = 0; 3339105059Scognet 3340111158Scognet pACB = (PACB) device_get_softc(dev); 3341105059Scognet if (!pACB) { 3342105059Scognet printf("trm%d: cannot allocate ACB !\n", unit); 3343105059Scognet return (NULL); 3344105059Scognet } 3345127135Snjl pACB->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 3346127135Snjl &rid, RF_ACTIVE); 3347107928Scognet if (pACB->iores == NULL) { 3348105059Scognet printf("trm_init: bus_alloc_resource failed!\n"); 3349105059Scognet return (NULL); 3350105059Scognet } 3351111158Scognet switch (pci_get_devid(dev)) { 3352111158Scognet case PCI_DEVICEID_TRMS1040: 3353111158Scognet adaptType = 0; 3354111158Scognet break; 3355111158Scognet case PCI_DEVICEID_TRMS2080: 3356111158Scognet adaptType = 1; 3357111158Scognet break; 3358111158Scognet default: 3359111158Scognet printf("trm_init %d: unknown adapter type!\n", unit); 3360111158Scognet goto bad; 3361111158Scognet } 3362111158Scognet pACB->dev = dev; 3363107928Scognet pACB->tag = rman_get_bustag(pACB->iores); 3364107928Scognet pACB->bsh = rman_get_bushandle(pACB->iores); 3365117126Sscottl if (bus_dma_tag_create( 3366232874Sscottl /*parent_dmat*/ bus_get_dma_tag(dev), 3367232874Sscottl /*alignment*/ 1, 3368232874Sscottl /*boundary*/ 0, 3369232874Sscottl /*lowaddr*/ BUS_SPACE_MAXADDR, 3370232874Sscottl /*highaddr*/ BUS_SPACE_MAXADDR, 3371232874Sscottl /*filter*/ NULL, 3372232874Sscottl /*filterarg*/ NULL, 3373232874Sscottl /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 3374232874Sscottl /*nsegments*/ BUS_SPACE_UNRESTRICTED, 3375232874Sscottl /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3376232874Sscottl /*flags*/ 0, 3377232874Sscottl /*lockfunc*/ NULL, 3378232874Sscottl /*lockarg*/ NULL, 3379232874Sscottl /* dmat */ &pACB->parent_dmat) != 0) 3380232874Sscottl goto bad; 3381232874Sscottl if (bus_dma_tag_create( 3382117126Sscottl /*parent_dmat*/ pACB->parent_dmat, 3383117126Sscottl /*alignment*/ 1, 3384117126Sscottl /*boundary*/ 0, 3385117126Sscottl /*lowaddr*/ BUS_SPACE_MAXADDR, 3386117126Sscottl /*highaddr*/ BUS_SPACE_MAXADDR, 3387117126Sscottl /*filter*/ NULL, 3388117126Sscottl /*filterarg*/ NULL, 3389117126Sscottl /*maxsize*/ MAXBSIZE, 3390117126Sscottl /*nsegments*/ TRM_NSEG, 3391117126Sscottl /*maxsegsz*/ TRM_MAXTRANSFER_SIZE, 3392117126Sscottl /*flags*/ BUS_DMA_ALLOCNOW, 3393117126Sscottl /*lockfunc*/ busdma_lock_mutex, 3394117126Sscottl /*lockarg*/ &Giant, 3395117126Sscottl /* dmat */ &pACB->buffer_dmat) != 0) 3396107928Scognet goto bad; 3397111158Scognet /* DMA tag for our ccb structures */ 3398116813Scognet if (bus_dma_tag_create( 3399111158Scognet /*parent_dmat*/pACB->parent_dmat, 3400111158Scognet /*alignment*/ 1, 3401111158Scognet /*boundary*/ 0, 3402111158Scognet /*lowaddr*/ BUS_SPACE_MAXADDR, 3403111158Scognet /*highaddr*/ BUS_SPACE_MAXADDR, 3404111158Scognet /*filter*/ NULL, 3405111158Scognet /*filterarg*/ NULL, 3406111158Scognet /*maxsize*/ TRM_MAX_SRB_CNT * sizeof(TRM_SRB), 3407111158Scognet /*nsegments*/ 1, 3408111158Scognet /*maxsegsz*/ TRM_MAXTRANSFER_SIZE, 3409117126Sscottl /*flags*/ 0, 3410117126Sscottl /*lockfunc*/ busdma_lock_mutex, 3411117126Sscottl /*lockarg*/ &Giant, 3412111158Scognet /*dmat*/ &pACB->srb_dmat) != 0) { 3413111158Scognet printf("trm_init %d: bus_dma_tag_create SRB failure\n", unit); 3414111158Scognet goto bad; 3415111158Scognet } 3416111158Scognet if (bus_dmamem_alloc(pACB->srb_dmat, (void **)&pACB->pFreeSRB, 3417111158Scognet BUS_DMA_NOWAIT, &pACB->srb_dmamap) != 0) { 3418111158Scognet printf("trm_init %d: bus_dmamem_alloc SRB failure\n", unit); 3419111158Scognet goto bad; 3420111158Scognet } 3421111158Scognet bus_dmamap_load(pACB->srb_dmat, pACB->srb_dmamap, pACB->pFreeSRB, 3422111158Scognet TRM_MAX_SRB_CNT * sizeof(TRM_SRB), trm_mapSRB, pACB, 3423111158Scognet /* flags */0); 3424111158Scognet /* Create, allocate, and map DMA buffers for autosense data */ 3425232874Sscottl if (bus_dma_tag_create( 3426232874Sscottl /*parent_dmat*/pACB->parent_dmat, 3427232874Sscottl /*alignment*/1, 3428111158Scognet /*boundary*/0, 3429111158Scognet /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 3430111158Scognet /*highaddr*/BUS_SPACE_MAXADDR, 3431111158Scognet /*filter*/NULL, /*filterarg*/NULL, 3432111158Scognet sizeof(struct scsi_sense_data) * TRM_MAX_SRB_CNT, 3433111158Scognet /*nsegments*/1, 3434111158Scognet /*maxsegsz*/TRM_MAXTRANSFER_SIZE, 3435117126Sscottl /*flags*/0, /*lockfunc*/busdma_lock_mutex, 3436117126Sscottl /*lockarg*/&Giant, &pACB->sense_dmat) != 0) { 3437111158Scognet if (bootverbose) 3438111158Scognet device_printf(dev, "cannot create sense buffer dmat\n"); 3439111158Scognet goto bad; 3440111158Scognet } 3441111158Scognet 3442111158Scognet if (bus_dmamem_alloc(pACB->sense_dmat, (void **)&pACB->sense_buffers, 3443111158Scognet BUS_DMA_NOWAIT, &pACB->sense_dmamap) != 0) 3444111158Scognet goto bad; 3445111158Scognet 3446111158Scognet bus_dmamap_load(pACB->sense_dmat, pACB->sense_dmamap, 3447111158Scognet pACB->sense_buffers, 3448111158Scognet sizeof(struct scsi_sense_data) * TRM_MAX_SRB_CNT, 3449111158Scognet trm_dmamap_cb, &pACB->sense_busaddr, /*flags*/0); 3450111158Scognet 3451105059Scognet trm_check_eeprom(&trm_eepromBuf[unit],pACB); 3452111158Scognet trm_initACB(pACB, adaptType, unit); 3453111158Scognet for (i = 0; i < (pACB->max_id + 1); i++) { 3454111158Scognet if (pACB->AdaptSCSIID == i) 3455111158Scognet continue; 3456111158Scognet for(j = 0; j < (pACB->max_lun + 1); j++) { 3457111158Scognet pACB->scan_devices[i][j] = 1; 3458111158Scognet /* we assume we need to scan all devices */ 3459111158Scognet trm_initDCB(pACB, &pACB->DCBarray[i][j], unit, i, j); 3460111158Scognet } 3461111158Scognet } 3462111158Scognet bzero(pACB->pFreeSRB, TRM_MAX_SRB_CNT * sizeof(TRM_SRB)); 3463126725Scognet if (bus_dma_tag_create( 3464232874Sscottl /*parent_dmat*/pACB->parent_dmat, 3465126725Scognet /*alignment*/ 1, 3466126725Scognet /*boundary*/ 0, 3467126725Scognet /*lowaddr*/ BUS_SPACE_MAXADDR, 3468126725Scognet /*highaddr*/ BUS_SPACE_MAXADDR, 3469126725Scognet /*filter*/ NULL, 3470126725Scognet /*filterarg*/ NULL, 3471126725Scognet /*maxsize*/ TRM_MAX_SG_LISTENTRY * sizeof(SGentry), 3472126725Scognet /*nsegments*/ 1, 3473126725Scognet /*maxsegsz*/ TRM_MAXTRANSFER_SIZE, 3474126725Scognet /*flags*/ 0, 3475126725Scognet /*lockfunc*/ busdma_lock_mutex, 3476126725Scognet /*lockarg*/ &Giant, 3477126725Scognet /*dmat*/ &pACB->sg_dmat) != 0) 3478126725Scognet goto bad; 3479126725Scognet 3480111158Scognet if (trm_initSRB(pACB)) { 3481111158Scognet printf("trm_initSRB: error\n"); 3482111158Scognet goto bad; 3483111158Scognet } 3484111158Scognet if (trm_initAdapter(pACB, unit)) { 3485105059Scognet printf("trm_initAdapter: initial ERROR\n"); 3486107928Scognet goto bad; 3487105059Scognet } 3488105059Scognet return (pACB); 3489107928Scognetbad: 3490107928Scognet if (pACB->iores) 3491119690Sjhb bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), 3492107928Scognet pACB->iores); 3493111158Scognet if (pACB->sense_dmamap) { 3494111158Scognet bus_dmamap_unload(pACB->sense_dmat, pACB->sense_dmamap); 3495111158Scognet bus_dmamem_free(pACB->sense_dmat, pACB->sense_buffers, 3496111158Scognet pACB->sense_dmamap); 3497111158Scognet bus_dmamap_destroy(pACB->sense_dmat, pACB->sense_dmamap); 3498111158Scognet } 3499111158Scognet if (pACB->sense_dmat) 3500111158Scognet bus_dma_tag_destroy(pACB->sense_dmat); 3501126725Scognet if (pACB->sg_dmat) { 3502126725Scognet trm_destroySRB(pACB); 3503126725Scognet bus_dma_tag_destroy(pACB->sg_dmat); 3504126725Scognet } 3505111158Scognet if (pACB->srb_dmamap) { 3506111158Scognet bus_dmamap_unload(pACB->srb_dmat, pACB->srb_dmamap); 3507111158Scognet bus_dmamem_free(pACB->srb_dmat, pACB->pFreeSRB, 3508111158Scognet pACB->srb_dmamap); 3509111158Scognet bus_dmamap_destroy(pACB->srb_dmat, pACB->srb_dmamap); 3510111158Scognet } 3511111158Scognet if (pACB->srb_dmat) 3512111158Scognet bus_dma_tag_destroy(pACB->srb_dmat); 3513107928Scognet if (pACB->buffer_dmat) 3514107928Scognet bus_dma_tag_destroy(pACB->buffer_dmat); 3515232874Sscottl if (pACB->parent_dmat) 3516232874Sscottl bus_dma_tag_destroy(pACB->parent_dmat); 3517107928Scognet return (NULL); 3518105059Scognet} 3519105059Scognet 3520105059Scognetstatic int 3521111158Scognettrm_attach(device_t dev) 3522105059Scognet{ 3523105059Scognet struct cam_devq *device_Q; 3524105059Scognet u_long device_id; 3525105059Scognet PACB pACB = 0; 3526105059Scognet int rid = 0; 3527111158Scognet int unit = device_get_unit(dev); 3528105059Scognet 3529111158Scognet device_id = pci_get_devid(dev); 3530105059Scognet /* 3531105059Scognet * These cards do not allow memory mapped accesses 3532105059Scognet */ 3533111158Scognet if ((pACB = trm_init((u_int16_t) unit, 3534111158Scognet dev)) == NULL) { 3535111158Scognet printf("trm%d: trm_init error!\n",unit); 3536105059Scognet return (ENXIO); 3537111158Scognet } 3538105059Scognet /* After setting up the adapter, map our interrupt */ 3539105059Scognet /* 3540105059Scognet * Now let the CAM generic SCSI layer find the SCSI devices on the bus 3541105059Scognet * start queue to reset to the idle loop. 3542105059Scognet * Create device queue of SIM(s) 3543105059Scognet * (MAX_START_JOB - 1) : max_sim_transactions 3544105059Scognet */ 3545127135Snjl pACB->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 3546127135Snjl RF_SHAREABLE | RF_ACTIVE); 3547107928Scognet if (pACB->irq == NULL || 3548111158Scognet bus_setup_intr(dev, pACB->irq, 3549166901Spiso INTR_TYPE_CAM, NULL, trm_Interrupt, pACB, &pACB->ih)) { 3550105059Scognet printf("trm%d: register Interrupt handler error!\n", unit); 3551107928Scognet goto bad; 3552105059Scognet } 3553111158Scognet device_Q = cam_simq_alloc(TRM_MAX_START_JOB); 3554105059Scognet if (device_Q == NULL){ 3555105059Scognet printf("trm%d: device_Q == NULL !\n",unit); 3556107928Scognet goto bad; 3557105059Scognet } 3558105059Scognet /* 3559105059Scognet * Now tell the generic SCSI layer 3560105059Scognet * about our bus. 3561105059Scognet * If this is the xpt layer creating a sim, then it's OK 3562105059Scognet * to wait for an allocation. 3563105059Scognet * XXX Should we pass in a flag to indicate that wait is OK? 3564105059Scognet * 3565105059Scognet * SIM allocation 3566105059Scognet * 3567105059Scognet * SCSI Interface Modules 3568105059Scognet * The sim driver creates a sim for each controller. The sim device 3569105059Scognet * queue is separately created in order to allow resource sharing betwee 3570105059Scognet * sims. For instance, a driver may create one sim for each channel of 3571105059Scognet * a multi-channel controller and use the same queue for each channel. 3572105059Scognet * In this way, the queue resources are shared across all the channels 3573105059Scognet * of the multi-channel controller. 3574105059Scognet * trm_action : sim_action_func 3575105059Scognet * trm_poll : sim_poll_func 3576111119Simp * "trm" : sim_name ,if sim_name = "xpt" ..M_DEVBUF,M_WAITOK 3577105059Scognet * pACB : *softc if sim_name <> "xpt" ..M_DEVBUF,M_NOWAIT 3578105059Scognet * pACB->unit : unit 3579105059Scognet * 1 : max_dev_transactions 3580105059Scognet * MAX_TAGS : max_tagged_dev_transactions 3581105059Scognet * 3582105059Scognet * *******Construct our first channel SIM entry 3583105059Scognet */ 3584105059Scognet pACB->psim = cam_sim_alloc(trm_action, 3585105059Scognet trm_poll, 3586105059Scognet "trm", 3587105059Scognet pACB, 3588105059Scognet unit, 3589168752Sscottl &Giant, 3590105059Scognet 1, 3591111158Scognet TRM_MAX_TAGS_CMD_QUEUE, 3592105059Scognet device_Q); 3593105059Scognet if (pACB->psim == NULL) { 3594105059Scognet printf("trm%d: SIM allocate fault !\n",unit); 3595105059Scognet cam_simq_free(device_Q); /* SIM allocate fault*/ 3596107928Scognet goto bad; 3597105059Scognet } 3598170872Sscottl if (xpt_bus_register(pACB->psim, dev, 0) != CAM_SUCCESS) { 3599105059Scognet printf("trm%d: xpt_bus_register fault !\n",unit); 3600107928Scognet goto bad; 3601105059Scognet } 3602105059Scognet if (xpt_create_path(&pACB->ppath, 3603105059Scognet NULL, 3604105059Scognet cam_sim_path(pACB->psim), 3605105059Scognet CAM_TARGET_WILDCARD, 3606105059Scognet CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 3607105059Scognet printf("trm%d: xpt_create_path fault !\n",unit); 3608105059Scognet xpt_bus_deregister(cam_sim_path(pACB->psim)); 3609107928Scognet goto bad; 3610105059Scognet } 3611105059Scognet return (0); 3612107928Scognetbad: 3613107928Scognet if (pACB->iores) 3614119690Sjhb bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), 3615107928Scognet pACB->iores); 3616126725Scognet if (pACB->sg_dmat) { 3617126725Scognet trm_destroySRB(pACB); 3618126725Scognet bus_dma_tag_destroy(pACB->sg_dmat); 3619126725Scognet } 3620126725Scognet 3621111158Scognet if (pACB->srb_dmamap) { 3622111158Scognet bus_dmamap_unload(pACB->srb_dmat, pACB->srb_dmamap); 3623111158Scognet bus_dmamem_free(pACB->srb_dmat, pACB->pFreeSRB, 3624111158Scognet pACB->srb_dmamap); 3625111158Scognet bus_dmamap_destroy(pACB->srb_dmat, pACB->srb_dmamap); 3626111158Scognet } 3627111158Scognet if (pACB->srb_dmat) 3628111158Scognet bus_dma_tag_destroy(pACB->srb_dmat); 3629111158Scognet if (pACB->sense_dmamap) { 3630111158Scognet bus_dmamap_unload(pACB->sense_dmat, pACB->sense_dmamap); 3631111158Scognet bus_dmamem_free(pACB->sense_dmat, pACB->sense_buffers, 3632111158Scognet pACB->sense_dmamap); 3633111158Scognet bus_dmamap_destroy(pACB->sense_dmat, pACB->sense_dmamap); 3634111158Scognet } 3635111158Scognet if (pACB->sense_dmat) 3636111158Scognet bus_dma_tag_destroy(pACB->sense_dmat); 3637107928Scognet if (pACB->buffer_dmat) 3638107928Scognet bus_dma_tag_destroy(pACB->buffer_dmat); 3639107928Scognet if (pACB->ih) 3640111158Scognet bus_teardown_intr(dev, pACB->irq, pACB->ih); 3641107928Scognet if (pACB->irq) 3642111158Scognet bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irq); 3643107928Scognet if (pACB->psim) 3644107928Scognet cam_sim_free(pACB->psim, TRUE); 3645107928Scognet 3646107928Scognet return (ENXIO); 3647107928Scognet 3648105059Scognet} 3649105059Scognet 3650105059Scognet/* 3651105059Scognet* pci_device 3652105059Scognet* trm_probe (device_t tag, pcidi_t type) 3653105059Scognet* 3654105059Scognet*/ 3655105059Scognetstatic int 3656111158Scognettrm_probe(device_t dev) 3657105059Scognet{ 3658111158Scognet switch (pci_get_devid(dev)) { 3659111158Scognet case PCI_DEVICEID_TRMS1040: 3660111158Scognet device_set_desc(dev, 3661105059Scognet "Tekram DC395U/UW/F DC315/U Fast20 Wide SCSI Adapter"); 3662142880Simp return (BUS_PROBE_DEFAULT); 3663111158Scognet case PCI_DEVICEID_TRMS2080: 3664111158Scognet device_set_desc(dev, 3665111158Scognet "Tekram DC395U2D/U2W Fast40 Wide SCSI Adapter"); 3666142880Simp return (BUS_PROBE_DEFAULT); 3667111158Scognet default: 3668105059Scognet return (ENXIO); 3669111158Scognet } 3670105059Scognet} 3671105059Scognet 3672105059Scognetstatic int 3673107928Scognettrm_detach(device_t dev) 3674105059Scognet{ 3675107928Scognet PACB pACB = device_get_softc(dev); 3676107928Scognet 3677119690Sjhb bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), pACB->iores); 3678126725Scognet trm_destroySRB(pACB); 3679126725Scognet bus_dma_tag_destroy(pACB->sg_dmat); 3680111158Scognet bus_dmamap_unload(pACB->srb_dmat, pACB->srb_dmamap); 3681111158Scognet bus_dmamem_free(pACB->srb_dmat, pACB->pFreeSRB, 3682111158Scognet pACB->srb_dmamap); 3683111158Scognet bus_dmamap_destroy(pACB->srb_dmat, pACB->srb_dmamap); 3684111158Scognet bus_dma_tag_destroy(pACB->srb_dmat); 3685111158Scognet bus_dmamap_unload(pACB->sense_dmat, pACB->sense_dmamap); 3686111158Scognet bus_dmamem_free(pACB->sense_dmat, pACB->sense_buffers, 3687111158Scognet pACB->sense_dmamap); 3688111158Scognet bus_dmamap_destroy(pACB->sense_dmat, pACB->sense_dmamap); 3689111158Scognet bus_dma_tag_destroy(pACB->sense_dmat); 3690111158Scognet bus_dma_tag_destroy(pACB->buffer_dmat); 3691107928Scognet bus_teardown_intr(dev, pACB->irq, pACB->ih); 3692107928Scognet bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irq); 3693105059Scognet xpt_async(AC_LOST_DEVICE, pACB->ppath, NULL); 3694105059Scognet xpt_free_path(pACB->ppath); 3695105059Scognet xpt_bus_deregister(cam_sim_path(pACB->psim)); 3696105059Scognet cam_sim_free(pACB->psim, TRUE); 3697105059Scognet return (0); 3698105059Scognet} 3699105059Scognetstatic device_method_t trm_methods[] = { 3700105059Scognet /* Device interface */ 3701105059Scognet DEVMETHOD(device_probe, trm_probe), 3702105059Scognet DEVMETHOD(device_attach, trm_attach), 3703105059Scognet DEVMETHOD(device_detach, trm_detach), 3704105059Scognet { 0, 0 } 3705105059Scognet}; 3706105059Scognet 3707105059Scognetstatic driver_t trm_driver = { 3708105059Scognet "trm", trm_methods, sizeof(struct _ACB) 3709105059Scognet}; 3710105059Scognet 3711105059Scognetstatic devclass_t trm_devclass; 3712105059ScognetDRIVER_MODULE(trm, pci, trm_driver, trm_devclass, 0, 0); 3713165102SmjacobMODULE_DEPEND(trm, pci, 1, 1, 1); 3714124318ScognetMODULE_DEPEND(trm, cam, 1, 1, 1); 3715