📄 scsi_asc.c
字号:
sc->sc_active = 0; /* init the active flag */ sc->port_start = asc_scsistart; /* init the port_start switch */ sc->port_reset = asc_reset; /* init the port_reset switch */ sc->sc_scsiaddr = (caddr_t) vbaddr; /* Save the cntr address */ sc->sc_rambuff = ASC_BUF_ADDR; /* init the RAM buffer pointer*/#ifdef SZDEBUG if (asc_firstcall) printf("%s\n", asc_version);#endif SZDEBUG /* Attach the dma subsystem. The cpu value is passed to indicate what type of system the PDMA code needs to setup for. This call needs to be made before any target data xfers take place. */ PRINTD( 0xFF, 0x8000, ("asc_probe: calling PDMA attach cpu %d\n", cpu )); if( tc_addr_to_name(sc->sc_slotvaddr, modname) == -1) cprintf("tc_addr_to_name failed "); if( !strcmp(modname, "PMAZ-AA ") ) { opt_type = DS_5000; } else if( !strcmp(modname, "PMAZ-AB ") ) { opt_type = DS_5000_100; } else opt_type = cpu; if( pdma_attach( sc, opt_type ) != PDMA_SUCCESS ) { cprintf("asc_probe: pdma_attach( %x, %x ) failed\n", sc, opt_type ); alive = 0; } else { asc_reset(sc); /* reset the ASC chip */ ascaddr = ASC_REG_ADDR; /* set the register pointer */ } } /* end if (alive) */ /* * Use the inquiry command to determine number * and type of targets on this controller. * If this controller does not exist alive will * be zero and the for loop won't do anything. */ for (targid = 0; targid < NDPS; targid++) { if (alive == 0) break; sc->scsi_bus_idle = 1; sc->sc_active = (1 << targid); /* signal active */ sc->sc_selstat[targid] = SZ_IDLE; sc->sc_ascsentsync[targid] = 0; sc->sc_ascreqack[targid] = 0; sc->sc_attached[targid] = 0; sc->sc_ascsyncper[targid] = 0; sc->sc_no_disconnects[targid] = 0; sc->sc_rzspecial[targid] = 0; sc->sc_rmv_media &= ~(1 << targid); if (targid == sc->sc_sysid) continue; /* skip initiator */ retries = 5; status = 1; i = sz_wait_for_devices; while (retries) { /* Clear where the inquiry data will be going. This is like putting the cart before the horse, the offsets have not been setup yet. However, scsistart() calls recvdata() and recvdata() uses the values in ascdboff[] in transfering the data. This causes all transfers to occur in the first ram buffer "page". And valid inquiry data from the previou target is still there. This can cause some interesting device types. *//*RPS --- This stuff is non HBA specific. The sc_rambuff entry in the softc structure isn't used by the 3min so this may cause a problem. */ if ( !sc->ioasicp ) bzero((char *)(sc->sc_rambuff + sc->sc_ascdboff[targid]), DBOFF_LEN); sc->sc_szflags[targid] = SZ_NORMAL; sc->sc_curcmd[targid] = SZ_INQ; sc->sc_ascsentsync[targid] = 1; sz_bldpkt(sc, targid, SZ_INQ, 0, 0); stat = asc_scsistart(sc, targid, 0); if (sc->sc_szflags[targid] & SZ_BUSYTARG) { sc->sc_szflags[targid] &= ~SZ_BUSYTARG; DELAY(1000000); /* delay 1 second */ if (++i >= sz_max_wait_for_devices) break; continue; } if (stat == SZ_SUCCESS) { status = 0; break; } /* end if stat == SUCCESS */ else if (stat == SZ_RET_ABORT) { PRINTD(targid, SCSID_ERRORS, ("asc_probe: stat == RET_ABORT\n")); status = 1; break; } /* end else stat == RET_ABORT */ DELAY(1000); /* JAG different # ? */ retries--; continue; } /* end while */ if (status != 0) continue; /* * Initialize data structures for this target and * save all pertinent inquiry data (device type, etc.). */ idp = (struct sz_inq_dt *)&sc->sz_dat[targid]; /* Save removable media bit for each target */ if (idp->rmb) sc->sc_rmv_media |= (1 << targid); PRINTD(targid, SCSID_CMD_EXP, ("\n",asc_print_inq_info(idp))); /* * Zero device name and revsion level * ASCII strings, so we know whether or * not they were loaded by the INQUIRY. */ for (i = 0; i < SZ_DNSIZE; i++) sc->sc_devnam[targid][i] = (char)0; for (i = 0; i < SZ_REV_LEN; i++) sc->sc_revlvl[targid][i] = (char)0; /* * Save the device name and revision level. * DEC combines vendor & product ID strings. */ p = &sc->sc_devnam[targid][0]; for (i=0; i<SZ_VID_LEN; i++) *p++ = idp->vndrid[i]; for (i=0; i<SZ_PID_LEN; i++) *p++ = idp->prodid[i]; p = &sc->sc_revlvl[targid][0]; for (i=0; i<SZ_REV_LEN; i++) *p++ = idp->revlvl[i]; PRINTD(targid, SCSID_FLOW, ("asc_probe: targid %d perfdt=0x%x\n", targid, idp->perfdt)); switch(idp->perfdt) { default: /* Unknown device type */ printf("asc_probe: scsi %d targetID %d: %s (%d).\n", um->um_ctlr, targid, "unknown peripheral device type", idp->perfdt); /* NO 128 KB data buffer slot will be assigned! */ sc->sc_alive[targid] = 0; sc->sc_devtyp[targid] = SZ_UNKNOWN; sc->sc_xstate[targid] = SZ_NEXT; sc->sc_xevent[targid] = SZ_BEGIN; bcopy(DEV_UNKNOWN, sc->sc_device[targid], strlen(DEV_UNKNOWN)); break; case 0: /* Direct-access device (disk) */ case 1: /* Sequential-access device (tape) */ case 5: /* Read-only direct-access device (CDROM) */ /* * Allocate PTEs for data buffer double mapping. * We are in BIG trouble if this fails! We print * an error message, but the system will most * likely stall, spin, crash, burn! Account for * max transfer size (64k) plus 2 guard pages. */ i = get_sys_ptes(btoc(ASC_MAX_XFER) + 2, &sc->sc_szbufmap[targid]); if (i == 0) { printf("asc_probe: scsi %d targetID %d: %s\n", um->um_ctlr, targid, "cannot get %d PTEs for bufmap", (btoc(ASC_MAX_XFER) + 2) ); break; } else sc->sc_SZ_bufmap[targid] = (char *)i; sc->sc_alive[targid] = 1; sc->sc_szflags[targid] = SZ_NORMAL; /* house keeping */ sc->sc_xstate[targid] = SZ_NEXT; sc->sc_xevent[targid] = SZ_BEGIN; /* * Find this device in the scsi_devtab in scsi_data.c. * The answer could come back as unknown or missing. */ usdp = (struct scsi_devtab *)0; sdp_match = 0; for (sdp=scsi_devtab; sdp->namelen; sdp++) { if ((idp->perfdt == 0) && ((sdp->devtype&SZ_DISK) == 0)) continue; if ((idp->perfdt == 1) && ((sdp->devtype&SZ_TAPE) == 0)) continue; if ((idp->perfdt == 5) && ((sdp->devtype&SZ_CDROM) == 0)) continue; /* Save address of unknown device entry, if it exists. */ if ((sdp->name) && (strcmp("UNKNOWN", sdp->name) == 0)) usdp = (struct scsi_devtab *)sdp; /* HACK: DEC tapes don't use vendor/product ID fields. */ if ((sdp->devtype & SZ_TAPE) && (idp->perfdt == 1) && (sc->sc_devnam[targid][0] == 0) && (idp->devtq == sdp->tapetype)) { sdp_match++; break; } if (sdp->name) { if (strncmp(sc->sc_devnam[targid], sdp->name, sdp->namelen) == 0) { sdp_match++; break; } /* end if strncmp(devnam, sdp->name) */ } /* end if (sdp->name) */ } /* end for */ /* * If the device name did not match call it RZxx or TZxx. * Use the UNKNOWN entry from scsi_devtab (if it exists), * otherwise use our internal UNKNOWN entry. */ if (!sdp_match) { if (usdp) sdp = usdp; else if (idp->perfdt == 0) sdp = &szp_rz_udt; else if (idp->perfdt == 1) sdp = &szp_tz_udt; else sdp = &szp_cz_udt; } /* end if !match */ /* * Update counters and set the pointer to the completion * handler. */ if (sdp->devtype & SZ_DISK){ szp_nrz++; sc->device_comp[targid] = rzcomplete; } if (sdp->devtype & SZ_TAPE){ szp_ntz++; sc->device_comp[targid] = tzcomplete; } if (sdp->devtype & SZ_CDROM){ szp_ncz++; sc->device_comp[targid] = rzcomplete; } if ((sdp->devtype == RX23) || (sdp->devtype == RX33) || (sdp->devtype == RX26)) { szp_nrx++; sc->sc_mc_cnt[targid] = 1; sc->device_comp[targid] = rzcomplete; } /* TODO: assumes length < 8 bytes */ bcopy(sdp->sysname, sc->sc_device[targid], strlen(sdp->sysname)); sc->sc_devtab[targid] = sdp; sc->sc_devtyp[targid] = sdp->devtype; sc->sc_dstp[targid] = sdp->disksize; /* * Act on the flags in device's scsi_devtab entry. */ if (sdp->flags & SCSI_TRYSYNC) sc->sc_ascsentsync[targid] = 0; else sc->sc_ascsentsync[targid] = 1; if (sdp->flags & SCSI_REQSNS) { sc->sc_curcmd[targid] = SZ_RQSNS; sz_bldpkt(sc, targid, SZ_RQSNS, 0, 1); asc_scsistart(sc, targid, 0); } if (sdp->flags & SCSI_STARTUNIT) { /* * Send two start unit commands because a pending unit * attention may cause the first one to fail. We don't * for the drive to spin up here (happens in rzopen). */ sc->sc_curcmd[targid] = SZ_P_SSUNIT; sz_bldpkt(sc, targid, SZ_P_SSUNIT, 0, 1); asc_scsistart(sc, targid, 0); asc_scsistart(sc, targid, 0); } if (sdp->flags & SCSI_TESTUNITREADY) { sc->sc_curcmd[targid] = SZ_TUR; sz_bldpkt(sc, targid, SZ_TUR, 0, 1); asc_scsistart(sc, targid, 0); } if (sdp->flags & SCSI_READCAPACITY) { sc->sc_curcmd[targid] = SZ_RDCAP; sz_bldpkt(sc, targid, SZ_RDCAP, 0, 1); asc_scsistart(sc, targid, 0); } if (sdp->probedelay > 0) { DELAY(sdp->probedelay); } if (sdp->flags & SCSI_NODIAG) sz_unit_rcvdiag[(cntlr * NDPS) + targid] = 1; break; } /* end of switch */ /* * Just to be sure the bus is free after inquiry. * RRD40 may hold bus for a while. */ DELAY(asc_wait_after_inquiry); } /* end of for loop */ if (alive) { stat = ascaddr->asc_intr; /* read clears INTP */ wbflush(); } /* end if alive */ DELAY(10000); sc->sc_active = 0; /* clear active */ dboff = 0x0; /* * Setup ram buffer slots for each target to * be used for non READ/WRITE DMA Transfers on the ASC. */ for (i = 0; i < NDPS; i++) { sc->sc_ascdboff[i] = dboff; dboff += DBOFF_LEN; } /* end for */ dboff = TARGBUF_START; /* determine rz slot size, must be > 16kb */ cz_slotsize = tz_slotsize = rz_slotsize = TARGBUF_LEN; for (targid = 0; targid < NDPS; targid++) { if (targid == sc->sc_sysid) continue; if (sc->sc_alive[targid] == 0) continue; sc->sc_dboff[targid][0] = dboff; sc->sc_dboff[targid][1] = dboff + ASC_DMA_XLEN; sc->sc_segcnt[targid] = ASC_MAX_XFER; dboff += rz_slotsize; PRINTD(targid, SCSID_CMD_EXP, ("asc_probe: cntlr=%d targid=%d devtype=0x%x ", cntlr, targid, sc->sc_devtyp[targid])); PRINTD(targid, SCSID_CMD_EXP, ("req/ack=%d slotsize=%d\n", sc->sc_ascreqack[targid], sc->sc_segcnt[targid])); } /* end for targ=0, etc. */ asc_firstcall = 0; splx(s); return(alive);} /* end asc_probe *//****************************************************************** * * Name: asc_scsistart * * Abstract: Start a SCSI operation on the 53c94 controller. * * o Get register address from softc * o Load cdb into FIFO. * o Issue Select With ATN command. * o If not polled mode, return SZ_IP to upper state machine. * o If polled mode, spin wait for interrupt, then * call ascintr() to process. * * Inputs: * * sc - a pointer to the controller data structure * targid - the target id * bp - the buf pointer for this operation * * * Outputs: None. * * Return values: SZ_IP - command in progress * SZ_SUCCESS - command completed successfully * SZ_RET_ERR - command completed with an error * SZ_RET_ABORT - the cmd was aborted due to an error * ******************************************************************/asc_scsistart(sc, targid, bp)register struct sz_softc *sc;int targid;register struct buf *bp;{ int cntlr = sc->sc_ascnum; ASC_REG *ascaddr = ASC_REG_ADDR; /* setup the register pointer */ int retval; int timer; int phase; u_char stat; int s; int save_flags;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -