⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isp_linux.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
	    f = (Scsi_Cmnd *) b->host_scribble;	    if (f == Cmnd) {		b->host_scribble = f->host_scribble;		if (isp->isp_osinfo.wqtail == Cmnd)		     isp->isp_osinfo.wqtail = b;		break;	    }	    b = f;	}    }    if (f) {	f->host_scribble = NULL;	isp->isp_osinfo.wqcnt -= 1;    }    return (f);}static INLINE voidisplinux_runwaitq(struct ispsoftc *isp){    Scsi_Cmnd *f;    while ((f = isp_remove_from_waitq(isp->isp_osinfo.wqnext)) != NULL) {	int result = isp_start(f);	/*	 * Restart the timer for this command if it is queued or completing.	 */	if (result == CMD_QUEUED || result == CMD_COMPLETE) {	    int ntime = f->timeout_per_command;	    if (isp_xtime)		ntime *= isp_xtime;	    scsi_add_timer(f, ntime, f->done);	}	if (result == CMD_QUEUED) {	    if (isp->isp_osinfo.hiwater < isp->isp_nactive)		isp->isp_osinfo.hiwater = isp->isp_nactive;	    continue;	}	/*	 * If we cannot start a command on a fibre channel card, it means	 * that loop state isn't ready for us to do so. Activate the FC	 * thread to rediscover loop and fabric residency- but not if	 * we consider the loop to be dead. If the loop is considered dead,	 * we wait until a PDB Changed after a Loop UP activates the FC	 * thread.	 */	if (result == CMD_RQLATER && IS_FC(isp) && isp->isp_deadloop == 0) {	    SEND_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, 0);	}	/*	 * Put the command back on the wait queue. Don't change any	 * timer parameters for it because they were established	 * when we originally put the command on the waitq in the first	 * place.	 */	if (result == CMD_EAGAIN || result == CMD_RQLATER) {	    isplinux_insert_head_waitq(isp, f);	    break;	}	if (result == CMD_COMPLETE) {	    isp_done(f);	} else {	    panic("isplinux_runwaitq: result %d", result);	}    }}static INLINE voidisplinux_flushwaitq(struct ispsoftc *isp){    Scsi_Cmnd *Cmnd, *Ncmnd;       if ((Cmnd = isp->isp_osinfo.wqnext) == NULL) {	return;    }    isp->isp_osinfo.wqnext = isp->isp_osinfo.wqtail = NULL;    isp->isp_osinfo.wqcnt = 0;    ISP_UNLK_SOFTC(isp);    do {        Ncmnd = (Scsi_Cmnd *) Cmnd->host_scribble;        Cmnd->host_scribble = NULL;	XS_INITERR(Cmnd);	XS_SETERR(Cmnd, DID_NO_CONNECT);	/*	 * Add back a timer else scsi_done drops this on the floor.	 */	scsi_add_timer(Cmnd, Cmnd->timeout_per_command, Cmnd->done);	ISP_LOCK_SCSI_DONE(isp);	(*Cmnd->scsi_done)(Cmnd);	ISP_UNLK_SCSI_DONE(isp);    } while ((Cmnd = Ncmnd) != NULL);    ISP_LOCK_SOFTC(isp);}static INLINE Scsi_Cmnd *isplinux_remove_from_doneq(Scsi_Cmnd *Cmnd){    Scsi_Cmnd *f;    struct ispsoftc *isp;    if (Cmnd == NULL)	return (NULL);    isp = (struct ispsoftc *) Cmnd->host->hostdata;    if (isp->isp_osinfo.dqnext == NULL)	return (NULL);    if ((f = isp->isp_osinfo.dqnext) == Cmnd) {	isp->isp_osinfo.dqnext = (Scsi_Cmnd *) Cmnd->host_scribble;    } else {	Scsi_Cmnd *b = f;	while (f) {	    f = (Scsi_Cmnd *) b->host_scribble;	    if (f == Cmnd) {		b->host_scribble = f->host_scribble;		if (isp->isp_osinfo.dqtail == Cmnd)		     isp->isp_osinfo.dqtail = b;		break;	    }	    b = f;	}    }    if (f) {	f->host_scribble = NULL;    }    return (f);}intisplinux_queuecommand(Scsi_Cmnd *Cmnd, void (*donecmd)(Scsi_Cmnd *)){    struct Scsi_Host *host = Cmnd->host;    struct ispsoftc *isp = (struct ispsoftc *) (host->hostdata);    int result;    Cmnd->scsi_done = donecmd;    Cmnd->sense_buffer[0] = 0;    if (isp_xtime) {	Cmnd->timeout *= isp_xtime;    }    ISP_DRIVER_ENTRY_LOCK(isp);    ISP_LOCK_SOFTC(isp);    /*     * First off, see whether we need to (re)init the HBA.     * If we need to and fail to, pretend that this was a selection timeout.     */    if (isp->isp_state != ISP_RUNSTATE) {	if (isp->isp_role != ISP_ROLE_NONE) {	    isplinux_reinit(isp);	}	if (isp->isp_state != ISP_RUNSTATE) {	    ISP_UNLK_SOFTC(isp);	    ISP_DRIVER_EXIT_LOCK(isp);	    XS_INITERR(Cmnd);	    XS_SETERR(Cmnd, DID_NO_CONNECT);	    donecmd(Cmnd);	    return (0);	}    }   /*    * Next see if we have any stored up commands to run. If so, run them.    * If we get back from this with commands still ready to run, put the    * current command at the tail of waiting commands to be run later.    */    isplinux_runwaitq(isp);    if (isp->isp_osinfo.wqnext) {	isplinux_append_to_waitq(isp, Cmnd);	ISP_UNLK_SOFTC(isp);	ISP_DRIVER_EXIT_LOCK(isp);	return (0);    }   /*    * Finally, try and run this command.    */    result = isp_start(Cmnd);    if (result == CMD_QUEUED) {	if (isp->isp_osinfo.hiwater < isp->isp_nactive)	    isp->isp_osinfo.hiwater = isp->isp_nactive;	result = 0;	if (isp_xtime) {		scsi_delete_timer(Cmnd);		scsi_add_timer(Cmnd, isp_xtime * Cmnd->timeout_per_command,		    Cmnd->done);	}    } else if (result == CMD_EAGAIN) {	/*	 * We ran out of request queue space (or could not	 * get DMA resources). Tell the upper layer to try	 * later.	 */	result = 1;    } else if (result == CMD_RQLATER) {	/*	 * Temporarily hold off on this one.	 * Typically this means for fibre channel	 * that the loop is down or we're processing	 * some other change (e.g., fabric membership	 * change)	 */	isplinux_append_to_waitq(isp, Cmnd);	if (IS_FC(isp) && isp->isp_deadloop == 0) {	    SEND_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, 0);	}	result = 0;    } else if (result == CMD_COMPLETE) {	result = -1;    } else {	panic("unknown return code %d from isp_start", result);    }    ISP_UNLK_SOFTC(isp);    ISP_DRIVER_EXIT_LOCK(isp);    if (result == -1) {	Cmnd->result &= ~0xff;	Cmnd->result |= Cmnd->SCp.Status;        Cmnd->host_scribble = NULL;	(*Cmnd->scsi_done)(Cmnd);	result = 0;    }    return (result);}static INLINE void isplinux_scsi_probe_done(Scsi_Cmnd *);static INLINE voidisplinux_scsi_probe_done(Scsi_Cmnd *Cmnd){    struct ispsoftc *isp = (struct ispsoftc *) Cmnd->host->hostdata;    /*     * If we haven't seen this target yet, check the command result. If     * it was an inquiry and it succeeded okay, then we can update our     * notions about this target's capabilities.     *     * If the command did *not* succeed, we also update our notions about     * this target's capabilities (pessimistically) - it's probably not there.     * All of this so we can know when we're done so we stop wasting cycles     * seeing whether we can enable sync mode or not.     */    if (isp->isp_psco[Cmnd->channel][Cmnd->target] == 0) {	int i, b;	caddr_t iqd;	sdparam *sdp = (sdparam *) isp->isp_param;	sdp += Cmnd->channel;	if (Cmnd->cmnd[0] == 0x12 && host_byte(Cmnd->result) == DID_OK) {	    if (Cmnd->use_sg == 0) {		iqd = (caddr_t) Cmnd->buffer;	    } else {		iqd = ((struct scatterlist *) Cmnd->request_buffer)->address;	    }	    sdp->isp_devparam[Cmnd->target].goal_flags &=		~(DPARM_TQING|DPARM_SYNC|DPARM_WIDE);	    if (iqd[7] & 0x2) {		sdp->isp_devparam[Cmnd->target].goal_flags |= DPARM_TQING;	    }	    if (iqd[7] & 0x10) {		sdp->isp_devparam[Cmnd->target].goal_flags |= DPARM_SYNC;	    }	    if (iqd[7] & 0x20) {		sdp->isp_devparam[Cmnd->target].goal_flags |= DPARM_WIDE;	    }	    sdp->isp_devparam[Cmnd->target].dev_update = 1;	    isp->isp_psco[Cmnd->channel][Cmnd->target] = 1;	} else if (host_byte(Cmnd->result) != DID_OK) {	    isp->isp_psco[Cmnd->channel][Cmnd->target] = 1;	}	isp->isp_dutydone = 1;	for (b = 0; b < (IS_DUALBUS(isp)?2 : 1) && isp->isp_dutydone; b++) {	    for (i = 0; i < MAX_TARGETS; i++) {		if (i != sdp->isp_initiator_id) {		    if (isp->isp_psco[b][i] == 0) {			isp->isp_dutydone = 0;			break;		    }		}	    }	}	/*	 * Have we scanned all busses and all targets? You only get	 * one chance (per reset) to see what devices on this bus have	 * to offer.	 */	if (isp->isp_dutydone) {	    for (b = 0; b < (IS_DUALBUS(isp)?2 : 1) && isp->isp_dutydone; b++) {		for (i = 0; i < MAX_TARGETS; i++) {		    isp->isp_psco[b][i] = 0;		}		isp->isp_update |= (1 << b);	    }	}	        }}voidisp_done(Scsi_Cmnd *Cmnd){    struct ispsoftc *isp = (struct ispsoftc *) (Cmnd->host->hostdata);    if (IS_SCSI(isp) && isp->isp_dutydone == 0)  {	isplinux_scsi_probe_done(Cmnd);    }    Cmnd->result &= ~0xff;    Cmnd->result |= Cmnd->SCp.Status;    if (Cmnd->SCp.Status != GOOD) {	isp_prt(isp, ISP_LOGDEBUG0, "%d.%d.%d: cmd finishes with status 0x%x",	    XS_CHANNEL(Cmnd), XS_TGT(Cmnd), XS_LUN(Cmnd), Cmnd->SCp.Status);    }    /*     * If we had a way handling residuals, this is where we'd do it     */    /*     * Queue command on completion queue.     */    if (isp->isp_osinfo.dqnext == NULL) {	isp->isp_osinfo.dqnext = Cmnd;    } else {	isp->isp_osinfo.dqtail->host_scribble = (unsigned char *) Cmnd;    }    isp->isp_osinfo.dqtail = Cmnd;    Cmnd->host_scribble = NULL;}/* * Error handling routines */intisplinux_abort(Scsi_Cmnd *Cmnd){    struct ispsoftc *isp;    u_int16_t handle;    if (Cmnd == NULL || Cmnd->host == NULL) {	return (FAILED);    }    isp = (struct ispsoftc *) Cmnd->host->hostdata;    if (Cmnd->serial_number != Cmnd->serial_number_at_timeout) {	isp_prt(isp, ISP_LOGWARN, "isplinux_abort: serial number mismatch");	return (FAILED);    }    ISP_DRIVER_ENTRY_LOCK(isp);    ISP_LOCKU_SOFTC(isp);    handle = isp_find_handle(isp, Cmnd);    if (handle == 0) {	int wqfnd = 0;	Scsi_Cmnd *NewCmnd = isp_remove_from_waitq(Cmnd);	if (NewCmnd == NULL) {		NewCmnd = isplinux_remove_from_doneq(Cmnd);		wqfnd++;	}	ISP_UNLKU_SOFTC(isp);	isp_prt(isp, ISP_LOGINFO,	    "isplinux_abort: found %d:%p for non-running cmd for %d.%d.%d",	    wqfnd, NewCmnd, XS_CHANNEL(Cmnd), XS_TGT(Cmnd), XS_LUN(Cmnd));	if (NewCmnd == NULL) {	    ISP_DRIVER_EXIT_LOCK(isp);	    return (FAILED);	}    } else {	if (isp_control(isp, ISPCTL_ABORT_CMD, Cmnd)) {	    ISP_UNLKU_SOFTC(isp);	    ISP_DRIVER_EXIT_LOCK(isp);	    return (FAILED);	}	if (isp->isp_nactive > 0)	    isp->isp_nactive--;	isp_destroy_handle(isp, handle);	ISP_UNLKU_SOFTC(isp);	ISP_DRIVER_EXIT_LOCK(isp);	isp_prt(isp, ISP_LOGINFO,	    "isplinux_abort: aborted running cmd (handle 0x%x) for %d.%d.%d",	    handle, XS_CHANNEL(Cmnd), XS_TGT(Cmnd), XS_LUN(Cmnd));    }    Cmnd->result = DID_ABORT << 16;    (*Cmnd->scsi_done)(Cmnd);    return (SUCCESS);}/* * XXX: What does the midlayer expect for commands in process? * XXX: Are we supposed to clean up dead commands ourselves? */intisplinux_bdr(Scsi_Cmnd *Cmnd){    struct ispsoftc *isp;    int arg;    if (Cmnd == NULL || Cmnd->host == NULL) {	return (FAILED);    }    isp = (struct ispsoftc *) Cmnd->host->hostdata;    arg = Cmnd->channel << 16 | Cmnd->target;    ISP_DRIVER_ENTRY_LOCK(isp);    ISP_LOCKU_SOFTC(isp);    arg = isp_control(isp, ISPCTL_RESET_DEV, &arg);    ISP_UNLKU_SOFTC(isp);    ISP_DRIVER_EXIT_LOCK(isp);    isp_prt(isp, ISP_LOGINFO, "Bus Device Reset %succesfully sent to %d.%d.%d",	arg == 0? "s" : "uns", Cmnd->channel, Cmnd->target, Cmnd->lun);    return ((arg == 0)? SUCCESS : FAILED);}/* * XXX: What does the midlayer expect for commands in process? */intisplinux_sreset(Scsi_Cmnd *Cmnd){    struct ispsoftc *isp;    int arg;    if (Cmnd == NULL || Cmnd->host == NULL)	return (FAILED);    isp = (struct ispsoftc *) Cmnd->host->hostdata;    arg = Cmnd->channel;    ISP_DRIVER_ENTRY_LOCK(isp);    ISP_LOCKU_SOFTC(isp);    arg = isp_control(isp, ISPCTL_RESET_BUS, &arg);    ISP_UNLKU_SOFTC(isp);    ISP_DRIVER_EXIT_LOCK(isp);    isp_prt(isp, ISP_LOGINFO, "SCSI Bus Reset on Channel %d %succesful",	Cmnd->channel, arg == 0? "s" : "uns");    return ((arg == 0)? SUCCESS : FAILED);}/* * We call completion on any commands owned here- * except the one we were called with. */intisplinux_hreset(Scsi_Cmnd *Cmnd){    Scsi_Cmnd *tmp, *dq, *wq, *xqf, *xql;    struct ispsoftc *isp;    u_int16_t handle;    if (Cmnd == NULL || Cmnd->host == NULL)	return (FAILED);    isp = (struct ispsoftc *) Cmnd->host->hostdata;    isp_prt(isp, ISP_LOGINFO, "Resetting Host Adapter");    ISP_DRIVER_ENTRY_LOCK(isp);    ISP_LOCKU_SOFTC(isp);    /*     * Save pending, running, and completed commands.     */    xql = xqf = NULL;    for (handle = 1; handle <= isp->isp_maxcmds; handle++) {	tmp = isp_find_xs(isp, handle);	if (tmp == NULL) {	    continue;        }	isp_destroy_handle(isp, handle);	tmp->host_scribble = NULL;	if (xqf) {	    xql->host_scribble = (unsigned char *) tmp;	} else {	    xqf = xql = tmp;	}        xql = tmp;    }    dq = isp->isp_osinfo.dqnext;    isp->isp_osinfo.dqnext = NULL;    wq = isp->isp_osinfo.wqnext;    isp->isp_osinfo.wqnext = NULL;    isp->isp_nactive = 0;    isplinux_reinit(isp);    ISP_UNLKU_SOFTC(isp);    ISP_DRIVER_EXIT_LOCK(isp);    /*     * Call completion on the detritus, skipping the one we were called with.     */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -