Пример #1
0
static void
siop_scsicmd_end(struct siop_adapter *adp, struct scsi_xfer *xs)
{

	switch(xs->status) {
	case SCSI_OK:
		xs->error = XS_NOERROR;
		break;
	case SCSI_BUSY:
	case SCSI_CHECK:
	case SCSI_QUEUE_FULL:
		xs->error = XS_BUSY;
		break;
	case SCSI_SIOP_NOCHECK:
		/*
		 * don't check status, xs->error is already valid
		 */
		break;
	case SCSI_SIOP_NOSTATUS:
		/*
		 * the status byte was not updated, cmd was
		 * aborted
		 */
		xs->error = XS_SELTIMEOUT;
		break;
	default:
		printf("invalid status code %d\n", xs->status);
		xs->error = XS_DRIVER_STUFFUP;
	}
	_inv((u_long)xs->cmd, xs->cmdlen);
	if (xs->datalen != 0)
		_inv((u_long)xs->data, xs->datalen);
	xs->xs_status = XS_STS_DONE;
}
/*
 *	Sets the transformation matrix and its inverse (T and iT, respectively).
 */
void CoordsLib::_setT(){
	float subT1[3][3], subT2[3][3], aux[3][3];

	subT1[0][0] = _lmn1[0]; subT1[0][1] = _lmn2[0]; subT1[0][2] = _lmn3[0];
	subT1[1][0] = _lmn1[1]; subT1[1][1] = _lmn2[1]; subT1[1][2] = _lmn3[1];
	subT1[2][0] = _lmn1[2]; subT1[2][1] = _lmn2[2]; subT1[2][2] = _lmn3[2];

	subT2[0][0] = _LMN1[0]; subT2[0][1] = _LMN2[0]; subT2[0][2] = _LMN3[0];
	subT2[1][0] = _LMN1[1]; subT2[1][1] = _LMN2[1]; subT2[1][2] = _LMN3[1];
	subT2[2][0] = _LMN1[2]; subT2[2][1] = _LMN2[2]; subT2[2][2] = _LMN3[2];

	_inv(subT2, aux);
	_m_prod(subT1, aux, _T);
	_inv(_T, _iT);
}
Пример #3
0
void scp256_inv(unsigned char *x) {

    fe a;

    _frombytes(a, x);
    _inv(a, a);
    _tobytes(x, a);

    cleanup(a);
}
Пример #4
0
static int
siop_scsi_request(struct siop_adapter *adp, struct scsi_xfer *xs)
{
	void *xfer = adp->xfer;
	int timo, error;

	if (adp->sel_t != xs->target) {
		const int free_lo = __arraycount(siop_script);
		int i;
		void *scriptaddr = (void *)local_to_PCI((u_long)adp->script);

		if (adp->sel_t != -1)
			adp->script[Ent_resel_targ0 / 4 + adp->sel_t * 2] =
			    htoc32(0x800c00ff);

		for (i = 0; i < __arraycount(lun_switch); i++)
			adp->script[free_lo + i] = htoc32(lun_switch[i]);
		adp->script[free_lo + E_abs_lunsw_return_Used[0]] =
		    htoc32(scriptaddr + Ent_lunsw_return);

		siop_add_reselsw(adp, xs->target, free_lo);

		adp->sel_t = xs->target;
	}

restart:

	siop_setuptables(adp, xfer, xs);

	/* load the DMA maps */
	if (xs->datalen != 0)
		_inv((u_long)xs->data, xs->datalen);
	_wbinv((u_long)xs->cmd, xs->cmdlen);

	_wbinv((u_long)xfer, sizeof(struct siop_xfer));
	siop_start(adp, xs);

	adp->xs = xs;
	timo = 0;
	while (!(xs->xs_status & XS_STS_DONE)) {
		delay(1000);
		siop_intr(adp);

		if (timo++ > 3000) {		/* XXXX: 3sec */
			printf("%s: timeout\n", __func__);
			return ETIMEDOUT;
		}
	}

	if (xs->error != XS_NOERROR) {
		if (xs->error == XS_BUSY || xs->status == SCSI_CHECK)
			scsi_request_sense(adp, xs);

		switch (xs->error) {
		case XS_SENSE:
		case XS_SHORTSENSE:
			error = scsi_interpret_sense(adp, xs);
			break;
		case XS_RESOURCE_SHORTAGE:
			printf("adapter resource shortage\n");

			/* FALLTHROUGH */
		case XS_BUSY:
			error = EBUSY;
			break;
		case XS_REQUEUE:
			printf("XXXX: requeue...\n");
			error = ERESTART;
			break;
		case XS_SELTIMEOUT:
		case XS_TIMEOUT:
			error = EIO;
			break;
		case XS_RESET:
			error = EIO;
			break;
		case XS_DRIVER_STUFFUP:
			printf("generic HBA error\n");
			error = EIO;
			break;
		default:
			printf("invalid return code from adapter: %d\n",
			    xs->error);
			error = EIO;
			break;
		}
		if (error == ERESTART) {
			xs->error = XS_NOERROR;
			xs->status = SCSI_OK;
			xs->xs_status &= ~XS_STS_DONE;
			goto restart;
		}
		return error;
	}
	return 0;
}
Пример #5
0
static int
siop_intr(struct siop_adapter *adp)
{
	struct siop_xfer *siop_xfer = NULL;
	struct scsi_xfer *xs = NULL;
	u_long scriptaddr = local_to_PCI((u_long)adp->script);
	int offset, target, lun, tag, restart = 0, need_reset = 0;
	uint32_t dsa, irqcode;
	uint16_t sist;
	uint8_t dstat, sstat1, istat;

	istat = readb(adp->addr + SIOP_ISTAT);
	if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)
		return 0;
	if (istat & ISTAT_INTF) {
		printf("INTRF\n");
		writeb(adp->addr + SIOP_ISTAT, ISTAT_INTF);
	}
	if ((istat & (ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
	    (ISTAT_DIP | ISTAT_ABRT))
		/* clear abort */
		writeb(adp->addr + SIOP_ISTAT, 0);
	/* use DSA to find the current siop_cmd */
	dsa = readl(adp->addr + SIOP_DSA);
	if (dsa >= local_to_PCI((u_long)adp->xfer) &&
	    dsa < local_to_PCI((u_long)adp->xfer) + SIOP_TABLE_SIZE) {
		dsa -= local_to_PCI((u_long)adp->xfer);
		siop_xfer = adp->xfer;
		_inv((u_long)siop_xfer, sizeof(*siop_xfer));

		xs = adp->xs;
	}

	if (istat & ISTAT_DIP)
		dstat = readb(adp->addr + SIOP_DSTAT);
	if (istat & ISTAT_SIP) {
		if (istat & ISTAT_DIP)
			delay(10);
		/*
		 * Can't read sist0 & sist1 independently, or we have to
		 * insert delay
		 */
		sist = readw(adp->addr + SIOP_SIST0);
		sstat1 = readb(adp->addr + SIOP_SSTAT1);

		if ((sist & SIST0_MA) && need_reset == 0) {
			if (siop_xfer) {
				int scratcha0;

				dstat = readb(adp->addr + SIOP_DSTAT);
				/*
				 * first restore DSA, in case we were in a S/G
				 * operation.
				 */
				writel(adp->addr + SIOP_DSA,
				    local_to_PCI((u_long)siop_xfer));
				scratcha0 = readb(adp->addr + SIOP_SCRATCHA);
				switch (sstat1 & SSTAT1_PHASE_MASK) {
				case SSTAT1_PHASE_STATUS:
				/*
				 * previous phase may be aborted for any reason
				 * ( for example, the target has less data to
				 * transfer than requested). Compute resid and
				 * just go to status, the command should
				 * terminate.
				 */
					if (scratcha0 & A_flag_data)
						siop_ma(adp, xs);
					else if ((dstat & DSTAT_DFE) == 0)
						siop_clearfifo(adp);
					CALL_SCRIPT(Ent_status);
					return 1;
				case SSTAT1_PHASE_MSGIN:
				/*
				 * target may be ready to disconnect
				 * Compute resid which would be used later
				 * if a save data pointer is needed.
				 */
					if (scratcha0 & A_flag_data)
						siop_ma(adp, xs);
					else if ((dstat & DSTAT_DFE) == 0)
						siop_clearfifo(adp);
					writeb(adp->addr + SIOP_SCRATCHA,
					    scratcha0 & ~A_flag_data);
					CALL_SCRIPT(Ent_msgin);
					return 1;
				}
				printf("unexpected phase mismatch %d\n",
				    sstat1 & SSTAT1_PHASE_MASK);
			} else
				printf("phase mismatch without command\n");
			need_reset = 1;
		}
		if (sist & (SIST1_STO << 8)) {
			/* selection time out, assume there's no device here */
			if (siop_xfer) {
				xs->error = XS_SELTIMEOUT;
				goto end;
			} else
				printf("selection timeout without command\n");
		}

		/* Else it's an unhandled exception (for now). */
		printf("unhandled scsi interrupt,"
		    " sist=0x%x sstat1=0x%x DSA=0x%x DSP=0x%lx\n",
		    sist, sstat1, dsa, 
		    readl(adp->addr + SIOP_DSP) - scriptaddr);
		if (siop_xfer) {
			xs->error = XS_SELTIMEOUT;
			goto end;
		}
		need_reset = 1;
	}
	if (need_reset) {
reset:
		printf("XXXXX: fatal error, need reset the bus...\n");
		return 1;
	}

//scintr:
	if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
		irqcode = readl(adp->addr + SIOP_DSPS);
		/*
		 * no command, or an inactive command is only valid for a
		 * reselect interrupt
		 */
		if ((irqcode & 0x80) == 0) {
			if (siop_xfer == NULL) {
				printf(
				    "script interrupt 0x%x with invalid DSA\n",
				    irqcode);
				goto reset;
			}
		}
		switch(irqcode) {
		case A_int_err:
			printf("error, DSP=0x%lx\n",
			    readl(adp->addr + SIOP_DSP) - scriptaddr);
			if (xs) {
				xs->error = XS_SELTIMEOUT;
				goto end;
			} else {
				goto reset;
			}
		case A_int_reseltarg:
			printf("reselect with invalid target\n");
			goto reset;
		case A_int_resellun:
			target = readb(adp->addr + SIOP_SCRATCHA) & 0xf;
			lun = readb(adp->addr + SIOP_SCRATCHA + 1);
			tag = readb(adp->addr + SIOP_SCRATCHA + 2);
			if (target != adp->xs->target ||
			    lun != adp->xs->lun ||
			    tag != 0) {
				printf("unknwon resellun:"
				    " target %d lun %d tag %d\n",
				    target, lun, tag);
				goto reset;
			}
			siop_xfer = adp->xfer;
			dsa = local_to_PCI((u_long)siop_xfer);
			writel(adp->addr + SIOP_DSP,
			    dsa + sizeof(struct siop_common_xfer) +
			    Ent_ldsa_reload_dsa);
			_wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
			return 1;
		case A_int_reseltag:
			printf("reselect with invalid tag\n");
			goto reset;
		case A_int_disc:
			offset = readb(adp->addr + SIOP_SCRATCHA + 1);
			siop_sdp(adp, siop_xfer, xs, offset);
#if 0
			/* we start again with no offset */
			siop_cmd->saved_offset = SIOP_NOOFFSET;
#endif
			_wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
			CALL_SCRIPT(Ent_script_sched);
			return 1;
		case A_int_resfail:
			printf("reselect failed\n");
			return  1;
		case A_int_done:
			if (xs == NULL) {
				printf("done without command, DSA=0x%lx\n",
				    local_to_PCI((u_long)adp->xfer));
				return 1;
			}
			/* update resid.  */
			offset = readb(adp->addr + SIOP_SCRATCHA + 1);
#if 0
			/*
			 * if we got a disconnect between the last data phase
			 * and the status phase, offset will be 0. In this
			 * case, siop_cmd->saved_offset will have the proper
			 * value if it got updated by the controller
			 */
			if (offset == 0 &&
			    siop_cmd->saved_offset != SIOP_NOOFFSET)
				offset = siop_cmd->saved_offset;
#endif
			siop_update_resid(adp, siop_xfer, xs, offset);
			goto end;
		default:
			printf("unknown irqcode %x\n", irqcode);
			if (xs) {
				xs->error = XS_SELTIMEOUT;
				goto end;
			}
			goto reset;
		}
		return 1;
	}
	/* We just should't get there */
	panic("siop_intr: I shouldn't be there !");

	return 1;

end:
	/*
	 * restart the script now if command completed properly
	 * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the
	 * queue
	 */
	xs->status = ctoh32(siop_xfer->siop_tables.status);
	if (xs->status == SCSI_OK)
		writel(adp->addr + SIOP_DSP, scriptaddr + Ent_script_sched);
	else
		restart = 1;
	siop_scsicmd_end(adp, xs);
	if (restart)
		writel(adp->addr + SIOP_DSP, scriptaddr + Ent_script_sched);

	return 1;
}