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

📄 gscdd.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 2 页
字号:
static intgsc_ioctl(dev_t dev, int cmd, void *arg, ulong dflag){    switch (cmd) {    case GSC_CMD:	return (gsccmd(dev, arg, dflag));    case GSC_SETDBG:    {	int i;	cmd = copyin(arg, (caddr_t) &i, sizeof (int));	if (cmd != 0) {	    return (cmd);	}	cmd = scudebug;	scudebug = i;	return (copyout((caddr_t) &cmd, arg, sizeof (int)));    }    default:	return (ENOTTY);    }}/****************************************************************************/static intgsccmd(dev_t dev, scmd_t *argcmd, ulong dflag){    gsc_softc_t *sp;    scmd_t local, *l;    char sbyte, albits;    struct sc_buf *usc;    struct buf *Ubp;    int r, r2, ival, upin, unit, rqvalid, once;    unit = minor(dev);    Trace2(1, "%d: cmd for unit %d", __LINE__, minor(dev));    if (unit < 0 || unit >= MAX_UNITS) {	setuerror(ENXIO);	return (ENXIO);    }    sp = &softinfo[unit];    if (sp->iscfg == 0 || sp->fp == NULL) {	Trace2(0, "gsccmd: bad unit %d (cfg=%d)", unit, sp->iscfg);	r = ENODEV;	setuerror(r);	return (r);    }    simple_lock(&sp->dd_lock);    l = &local;    if (dflag & DKERNEL) {	l = argcmd;    } else {	r = copyin((caddr_t) argcmd, (caddr_t) l, sizeof (scmd_t));	if (r != 0) {	    Trace2(0, "%d: copyin=%d", __LINE__, r);	    setuerror(r);	    MJ_RTN (r);	}    }    Trace6(1, "%d: cdblen%d datalen%d snslen%d rw=%d tv=%d", __LINE__,	   l->cdblen, l->datalen, l->senselen, l->rw, l->timeval);    sbyte = 0;    rqvalid = upin = r = r2 = 0;    usc = &sp->cmdbuf;    Ubp = &usc->bufstruct;    memset(usc, 0, sizeof (struct sc_buf));    /*     * Check some parameters...     */    if (l->cdblen > sizeof (struct sc_cmd)) {	r = EINVAL;	goto out;    }    /*     * Setup sc_buf structure     */    Ubp->b_iodone = gscdd_intr;    Ubp->b_dev = sp->dev;    Ubp->b_flags = B_BUSY | B_MPSAFE;    Ubp->b_resid = Ubp->b_bcount = l->datalen;    Ubp->b_xmemd.aspace_id = XMEM_INVAL;    Ubp->b_event = EVENT_NULL;    if (l->datalen) {	Ubp->b_un.b_addr = l->data_buf;	if (l->rw) {	    Ubp->b_flags |= B_READ;	}	if (dflag & DKERNEL) {	    r = pinu(l->data_buf, l->datalen, UIO_SYSSPACE);	} else {	    r = pinu(l->data_buf, l->datalen, UIO_USERSPACE);	}	if (r) {	    Trace2(0, "%d: pinu buf %d", __LINE__, r);	    goto out;	}	upin++;	if (dflag & DKERNEL) {	    r = xmattach(l->data_buf, l->datalen, &Ubp->b_xmemd, SYS_ADSPACE);	} else {	    r = xmattach(l->data_buf, l->datalen, &Ubp->b_xmemd, USER_ADSPACE);	}	if (r != XMEM_SUCC) {	    Trace2(0, "%d: xmattach %d", __LINE__, r);	    r = EFAULT;	    goto out;	}	upin++;	r = xmemdma(&Ubp->b_xmemd, l->data_buf, XMEM_UNHIDE);	if (r == XMEM_FAIL) {	    Trace2(0, "%d: xmemdma %d", __LINE__, r);	    r = EFAULT;	    goto out;	}	r = 0;    }    usc->scsi_command.scsi_id = sp->tgt;    usc->scsi_command.scsi_length = l->cdblen;    if (dflag & DKERNEL) {	bcopy(l->cdb, (caddr_t)&usc->scsi_command.scsi_cmd, l->cdblen);    } else {	r = copyin(l->cdb, (caddr_t) & usc->scsi_command.scsi_cmd, l->cdblen);	if (r != 0) {	    goto out;	}    }    /* Setting lun in SCSI CDB as well as sc_buf structure */    usc->lun = sp->lun;    usc->scsi_command.scsi_cmd.lun &= 0x1F;    usc->scsi_command.scsi_cmd.lun |= (sp->lun << 5) & 0xE0;    albits = usc->scsi_command.scsi_cmd.lun;    usc->timeout_value = l->timeval;    if (sp->needresume) {	usc->flags |= SC_RESUME;	sp->needresume = 0;    }    if (scudebug > 1) {	char *c = (char *) &usc->scsi_command.scsi_cmd;	char cdbuf[64];	(void) sprintf(cdbuf,		       "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x "		       "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",		       c[0], c[1], c[2], c[3], c[4], c[5],		       c[6], c[7], c[8], c[9], c[10], c[11]);	Trace2(0, "%d: cdb=%s", __LINE__, cdbuf);    }    once = 0;again:    Ubp->b_flags &= ~B_DONE;    r = devstrat(Ubp);    if (r == 0) {	ival = disable_lock(INTCLASS1, &sp->buf_lock);	while ((Ubp->b_flags & B_DONE) == 0) {	    e_sleep_thread(&Ubp->b_event, &sp->buf_lock, LOCK_HANDLER);	}	unlock_enable(ival, &sp->buf_lock);    } else {	/*	 * If ENXIO,  We never actually got started.	 */	if (r == ENXIO && once == 0) {	    once++;	    usc->flags |= SC_RESUME|SC_DELAY_CMD;	    goto again;	}	sp->needresume = 1;	Trace2(1, "%d: devstrat=%d", __LINE__, r);	goto out;    }    Trace4(1, "%d: b_flags %x b_error %d b_resid %d", __LINE__,	   Ubp->b_flags, Ubp->b_error, Ubp->b_resid);    Trace5(1, "%d: sv %x st %x gc %x as %x", __LINE__,	   usc->status_validity, usc->scsi_status,	   usc->general_card_status, usc->adap_q_status);    if (Ubp->b_flags & B_ERROR) {	r = Ubp->b_error;	sp->needresume = 1;    }    if (usc->status_validity & SC_SCSI_ERROR) {	sbyte = (usc->scsi_status & SCSI_STATUS_MASK);	sp->needresume = 1;	if (sbyte == SC_CHECK_CONDITION && l->senselen) {	    struct sc_buf *usl;	    struct buf *Sbp;	    r = make_rqs(sp, albits, l->sense_buf, l->senselen,		     (dflag & DKERNEL) != 0);	    if (r) {		Trace2(0, "%d: make_rqs=%d", __LINE__, r);		goto out;	    }	    usl = &sp->rqsbuf;	    Sbp = &usl->bufstruct;	    r = devstrat(Sbp);	    if (r == 0) {		ival = disable_lock(INTCLASS1, &sp->buf_lock);		while ((Sbp->b_flags & B_DONE) == 0) {		    e_sleep_thread(&Sbp->b_event, &sp->buf_lock, LOCK_HANDLER);		}		unlock_enable(ival, &sp->buf_lock);	    } else {		Trace2(0, "%d:ds=%d for rqs", __LINE__, r);		goto out;	    }	    xmdetach(&Sbp->b_xmemd);	    if (dflag & DKERNEL) {		(void) unpinu(l->sense_buf, l->senselen, UIO_SYSSPACE);	    } else {		(void) unpinu(l->sense_buf, l->senselen, UIO_USERSPACE);	    }	    Trace4(1, "%d SENSE: b_flags %x b_error %d b_resid %d",		   __LINE__, Sbp->b_flags, Sbp->b_error,		   Sbp->b_resid);	    Trace5(1, "%d: sv %x st %x gc %x as %x", __LINE__,		   usl->status_validity, usl->scsi_status,		   usl->general_card_status, usl->adap_q_status);	    if (usl->scsi_status || usl->general_card_status) {		r = EIO;	    } else {		rqvalid = 1;	    }	}    }    if (usc->status_validity & SC_ADAPTER_ERROR) {	sp->needresume = 1;	Trace2(0, "%d: adapter error 0x%x", __LINE__,	       usc->general_card_status);	Ubp->b_flags |= B_ERROR;	switch (usc->general_card_status) {	case SC_NO_DEVICE_RESPONSE:	case SC_HOST_IO_BUS_ERR:	case SC_SCSI_BUS_FAULT:	case SC_CMD_TIMEOUT:	case SC_ADAPTER_HDW_FAILURE:	case SC_ADAPTER_SFW_FAILURE:	case SC_FUSE_OR_TERMINAL_PWR:	case SC_SCSI_BUS_RESET:	default:	    r = EIO;	    break;	}    }    /*     * Log errors through errsave function     */    if (usc->status_validity & (SC_SCSI_ERROR|SC_ADAPTER_ERROR)) {	struct sc_error_log_df log;	memset(&log, 0, sizeof (log));	/*	 * All errors are 'temporary unknown driver error'	 */	log.error_id = ERRID_SCSI_ERR6;	(void) sprintf(log.resource_name, "gsc%d", unit);	memcpy(&log.scsi_command, &usc->scsi_command, sizeof (struct scsi));	log.status_validity = usc->status_validity;	log.scsi_status = usc->scsi_status;	log.general_card_status	= usc->general_card_status;	if (rqvalid) {	    int amt;	    if (l->senselen > 128)		amt = 128;	    else		amt = l->senselen;	    (void) copyin(l->sense_buf, log.req_sense_data, amt);	}	errsave(&log, sizeof (struct sc_error_log_df));    }    if (dflag & DKERNEL) {	*l->statusp = sbyte;    } else {	r2 = copyout(&sbyte, l->statusp, 1);	if (r2 != 0) {	    if (r == 0)		r = r2;	    goto out;	}    }out:    if (l->datalen) {	if (upin > 1) {	    xmdetach(&Ubp->b_xmemd);	    upin--;	}	if (upin > 0) {	    if (dflag & DKERNEL) {		(void) unpinu(l->data_buf, l->datalen, UIO_SYSSPACE);	    } else {		(void) unpinu(l->data_buf, l->datalen, UIO_USERSPACE);	    }	    upin--;	}    }    Trace2(1, "%d: returning %d", __LINE__, r);    if (r)	setuerror(r);    MJ_RTN (r);}static intmake_rqs(gsc_softc_t * sp, char albits, char *uaddr, int ulen, int isk){    struct sc_buf *usl;    struct buf *Sbp;    int err, upin;    if (ulen > 255)	ulen = 255;    upin = err = 0;    usl = &sp->rqsbuf;    Sbp = &usl->bufstruct;    memset(usl, 0, sizeof (struct sc_buf));    Sbp->b_un.b_addr = uaddr;    Sbp->b_resid = Sbp->b_bcount = ulen;    Sbp->b_iodone = gscdd_intr;    Sbp->b_dev = sp->dev;    Sbp->b_flags = B_BUSY | B_READ | B_MPSAFE;    Sbp->b_event = EVENT_NULL;    Sbp->b_xmemd.aspace_id = XMEM_INVAL;    if (isk)	err = pinu(uaddr, ulen, UIO_SYSSPACE);    else	err = pinu(uaddr, ulen, UIO_USERSPACE);    if (err)	goto out;    upin++;    if (isk)	err = xmattach(uaddr, ulen, &Sbp->b_xmemd, SYS_ADSPACE);    else	err = xmattach(uaddr, ulen, &Sbp->b_xmemd, USER_ADSPACE);    if (err != XMEM_SUCC) {	err = EFAULT;	goto out;    }    upin++;    err = xmemdma(&Sbp->b_xmemd, Sbp->b_un.b_addr, XMEM_UNHIDE);    if (err == XMEM_FAIL) {	err = EFAULT;	(void) xmdetach(&Sbp->b_xmemd);	goto out;    }    err = 0;    usl->lun = sp->lun; /* Setting lun in sc_buf structure */    usl->scsi_command.scsi_id = sp->tgt;    usl->scsi_command.scsi_length = 6;    usl->scsi_command.scsi_cmd.scsi_op_code = 0x3;    usl->scsi_command.scsi_cmd.lun = albits & 0xE0; /*ONLY copy the lun bits*/    usl->scsi_command.scsi_cmd.scsi_bytes[2] = ulen;    usl->timeout_value = 2;    usl->flags = SC_RESUME;    sp->needresume = 0; out:    if (err) {	if (upin > 1) {	    xmdetach(&Sbp->b_xmemd);	    upin--;	}	if (upin > 0) {	    if (isk)		(void) unpinu(uaddr, ulen, UIO_SYSSPACE);	    else		(void) unpinu(uaddr, ulen, UIO_USERSPACE);	    upin--;	}    }    return (err);}voidgscdd_intr(struct buf * bp){    int lv;    gsc_softc_t *sp = &softinfo[((gsc_buf_t *)bp)->index];    lv = disable_lock(INTIODONE, &sp->buf_lock);    bp->b_flags |= B_DONE;    unlock_enable(lv, &sp->buf_lock);    e_wakeup(&bp->b_event);}/* * mode: c * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * End: */

⌨️ 快捷键说明

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