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); }
void scp256_inv(unsigned char *x) { fe a; _frombytes(a, x); _inv(a, a); _tobytes(x, a); cleanup(a); }
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; }
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; }