/* Issue a command to the chip, and (busy!) wait for it to * complete. * * Returns: < 0 on internal error, 0 on success, > 0 on error returned by the firmware * * Callable from any context, but locking is your problem. */ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, hermes_response_t *resp) { int err; int k; u16 reg; u16 status; err = hermes_issue_cmd(hw, cmd, parm0); if (err) { if (! hermes_present(hw)) { printk(KERN_WARNING "hermes @ %s0x%lx: " "Card removed while issuing command.\n", IO_TYPE(hw), hw->iobase); err = -ENODEV; } else printk(KERN_ERR "hermes @ %s0x%lx: Error %d issuing command.\n", IO_TYPE(hw), hw->iobase, err); goto out; } reg = hermes_read_regn(hw, EVSTAT); k = CMD_COMPL_TIMEOUT; while ( (! (reg & HERMES_EV_CMD)) && k) { k--; udelay(10); reg = hermes_read_regn(hw, EVSTAT); } if (! hermes_present(hw)) { printk(KERN_WARNING "hermes @ %s0x%lx: " "Card removed while waiting for command completion.\n", IO_TYPE(hw), hw->iobase); err = -ENODEV; goto out; } if (! (reg & HERMES_EV_CMD)) { printk(KERN_ERR "hermes @ %s0x%lx: " "Timeout waiting for command completion.\n", IO_TYPE(hw), hw->iobase); err = -ETIMEDOUT; goto out; } status = hermes_read_regn(hw, STATUS); if (resp) { resp->status = status; resp->resp0 = hermes_read_regn(hw, RESP0); resp->resp1 = hermes_read_regn(hw, RESP1); resp->resp2 = hermes_read_regn(hw, RESP2); } hermes_write_regn(hw, EVACK, HERMES_EV_CMD); if (status & HERMES_STATUS_RESULT) err = -EIO; out: return err; }
/* Read a Length-Type-Value record from the card. * * If length is NULL, we ignore the length read from the card, and * read the entire buffer regardless. This is useful because some of * the configuration records appear to have incorrect lengths in * practice. * * Callable from user or bh context. */ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, u16 *length, void *buf) { int err = 0; int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; u16 rlength, rtype; unsigned nwords; if ( (bufsize < 0) || (bufsize % 2) ) return -EINVAL; err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, NULL); if (err) return err; err = hermes_bap_seek(hw, bap, rid, 0); if (err) return err; rlength = hermes_read_reg(hw, dreg); if (! rlength) return -ENOENT; rtype = hermes_read_reg(hw, dreg); if (length) *length = rlength; if (rtype != rid) printk(KERN_WARNING "hermes @ %s0x%lx: " "hermes_read_ltv(): rid (0x%04x) does not match type (0x%04x)\n", IO_TYPE(hw), hw->iobase, rid, rtype); if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize) printk(KERN_WARNING "hermes @ %s0x%lx: " "Truncating LTV record from %d to %d bytes. " "(rid=0x%04x, len=0x%04x)\n", IO_TYPE(hw), hw->iobase, HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength); nwords = min((unsigned)rlength - 1, bufsize / 2); hermes_read_words(hw, dreg, buf, nwords); return 0; }
int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) { int err = 0; int k; u16 reg; if ( (size < HERMES_ALLOC_LEN_MIN) || (size > HERMES_ALLOC_LEN_MAX) ) return -EINVAL; err = hermes_docmd_wait(hw, HERMES_CMD_ALLOC, size, NULL); if (err) { return err; } reg = hermes_read_regn(hw, EVSTAT); k = ALLOC_COMPL_TIMEOUT; while ( (! (reg & HERMES_EV_ALLOC)) && k) { k--; udelay(10); reg = hermes_read_regn(hw, EVSTAT); } if (! hermes_present(hw)) { printk(KERN_WARNING "hermes @ %s0x%lx: " "Card removed waiting for frame allocation.\n", IO_TYPE(hw), hw->iobase); return -ENODEV; } if (! (reg & HERMES_EV_ALLOC)) { printk(KERN_ERR "hermes @ %s0x%lx: " "Timeout waiting for frame allocation\n", IO_TYPE(hw), hw->iobase); return -ETIMEDOUT; } *fid = hermes_read_regn(hw, ALLOCFID); hermes_write_regn(hw, EVACK, HERMES_EV_ALLOC); return 0; }
int hermes_init(hermes_t *hw) { u16 status, reg; int err = 0; int k; /* We don't want to be interrupted while resetting the chipset */ hw->inten = 0x0; hermes_write_regn(hw, INTEN, 0); hermes_write_regn(hw, EVACK, 0xffff); /* Normally it's a "can't happen" for the command register to be busy when we go to issue a command because we are serializing all commands. However we want to have some chance of resetting the card even if it gets into a stupid state, so we actually wait to see if the command register will unbusy itself here. */ k = CMD_BUSY_TIMEOUT; reg = hermes_read_regn(hw, CMD); while (k && (reg & HERMES_CMD_BUSY)) { if (reg == 0xffff) /* Special case - the card has probably been removed, so don't wait for the timeout */ return -ENODEV; k--; udelay(1); reg = hermes_read_regn(hw, CMD); } /* No need to explicitly handle the timeout - if we've timed out hermes_issue_cmd() will probably return -EBUSY below */ /* According to the documentation, EVSTAT may contain obsolete event occurrence information. We have to acknowledge it by writing EVACK. */ reg = hermes_read_regn(hw, EVSTAT); hermes_write_regn(hw, EVACK, reg); /* We don't use hermes_docmd_wait here, because the reset wipes the magic constant in SWSUPPORT0 away, and it gets confused */ err = hermes_issue_cmd(hw, HERMES_CMD_INIT, 0); if (err) return err; reg = hermes_read_regn(hw, EVSTAT); k = CMD_INIT_TIMEOUT; while ( (! (reg & HERMES_EV_CMD)) && k) { k--; udelay(10); reg = hermes_read_regn(hw, EVSTAT); } hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC); if (! hermes_present(hw)) { DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n", hw->iobase); err = -ENODEV; goto out; } if (! (reg & HERMES_EV_CMD)) { printk(KERN_ERR "hermes @ %s0x%lx: " "Timeout waiting for card to reset (reg=0x%04x)!\n", IO_TYPE(hw), hw->iobase, reg); err = -ETIMEDOUT; goto out; } status = hermes_read_regn(hw, STATUS); hermes_write_regn(hw, EVACK, HERMES_EV_CMD); if (status & HERMES_STATUS_RESULT) err = -EIO; out: return err; }
void _fcontext(FIOSPTR css) { register short is_int; /* 1 if internal file I/O */ register int utindex; char *file, *fstruct, *idir, *oprn, *sepr; register unum_t unum; /* Fortran unit number */ long stmt; /* I/O statement type */ unit *cup; /* Pointer to unit table entry */ /* Just return if no Fortran statement info is available */ if (css == NULL) return; /* Retrieve global data */ cup = css->f_cu; unum = css->f_curun; stmt = css->f_iostmt; is_int = css->f_intflg; file = (!OPEN_UPTR(cup) || cup->alfnm == NULL) ? NULL : cup->alfnm; if (stmt & TF_READ) idir = " READ from"; else if (stmt & TF_WRITE) idir = " WRITE to"; else idir = ""; /* Determine the type of error */ switch (stmt) { case T_RSF: /* Sequential formatted READ */ case T_WSF: /* Sequential formatted WRITE */ oprn = " sequential formatted"; break; case T_RSU: /* Sequential unformatted READ */ case T_WSU: /* Sequential unformatted WRITE */ oprn = " sequential unformatted"; break; case T_RDF: /* Direct formatted READ */ case T_WDF: /* Direct formatted WRITE */ oprn = " direct access formatted"; break; case T_RDU: /* Direct unformatted READ */ case T_WDU: /* Direct unformatted WRITE */ oprn = " direct access unformatted"; break; case T_RLIST: /* List-directed READ */ case T_WLIST: /* List-directed WRITE */ oprn = " list-directed"; break; case T_RNL: /* Namelist READ */ case T_WNL: /* Namelist WRITE */ oprn = " namelist"; break; case T_BUFOUT: /* BUFFER OUT */ oprn = " BUFFER OUT on"; idir = ""; break; case T_BUFIN: /* BUFFER IN */ oprn = " BUFFER IN from"; idir = ""; break; case T_OPEN: /* OPEN */ oprn = "n OPEN of"; idir = ""; break; case T_REWIND: /* REWIND */ oprn = " REWIND on"; idir = ""; break; case T_BACKSPACE:/* BACKSPACE */ oprn = " BACKSPACE on"; idir = ""; break; case T_ENDFILE: /* ENDFILE */ oprn = "n ENDFILE on"; idir = ""; break; case T_CLOSE: /* CLOSE */ oprn = " CLOSE of"; idir = ""; break; case T_INQF: /* INQUIRE */ oprn = "n INQUIRE by file on"; unum = -1; idir = ""; break; case T_INQU: /* INQUIRE */ oprn = "n INQUIRE by unit on"; idir = ""; break; case T_GETPOS: /* GETPOS */ oprn = " GETPOS on"; idir = ""; break; case T_SETPOS: /* SETPOS */ oprn = " SETPOS on"; idir = ""; break; case T_LENGTH: /* LENGTH */ oprn = " LENGTH function on"; idir = ""; break; case T_UNIT: /* UNIT */ oprn = " UNIT function on"; idir = ""; break; case T_TAPE: /* TAPE */ oprn = " tape operation on"; idir = ""; break; default: oprn = "n I/O operation on"; break; } /* switch */ (void) fprintf(errfile, "\nEncountered during a%s%s", oprn, idir); if (is_int) (void) fprintf(errfile, " an internal file (character variable)\n"); else { if (unum != -1) { (void) fprintf(errfile, " unit %lld\n", unum); (void) fprintf(errfile, "Fortran unit %lld is ", unum); if (!OPEN_UPTR(cup)) { if (GOOD_UNUM(unum)) (void) fprintf(errfile, "not connected\n"); else (void) fprintf(errfile, "not a valid unit number\n"); } else { (void) fprintf(errfile, "connected to "); utindex = IO_TYPE(cup); fstruct = FIO_STRUCT(_deduce_fstruct( cup->ufs, (struct fdinfo*)cup->ufp.fdc, cup->ufmt)); if (fstruct == NULL) fstruct = ""; (void) fprintf(errfile, "a %s %s file", FIO_METHOD(utindex), fstruct); if (file == NULL && cup->ufs != FS_FDC) { if (cup->ufp.std == stdin) file = "standard input"; else if (cup->ufp.std == stdout) file = "standard output"; else if (cup->ufp.std == stderr) file = "standard error"; else file = "unnamed"; (void) fprintf(errfile, "\n (%s).\n", file); } else { /* Format to under 80 chars. per line */ if ((int)strlen(file) > 8) sepr = ":\n "; else sepr = ": "; (void) fprintf(errfile, "%s\"%s\"\n", sepr, file); } /* * If the connection is formatted and there's * a format, print the format and point to * the current position therein. */ if ((stmt & TF_FMT) && css->u.fmt.u.fe.fmtbuf != NULL) { int i, offset; offset = css->u.fmt.u.fe.fmtcol - 2 + fprintf(errfile, " Current format: "); if (css->u.fmt.u.fe.fmtnum > 0) /* If format label, print it */ offset = offset + fprintf(errfile, "%5d FORMAT", css->u.fmt.u.fe.fmtnum); (void) fprintf(errfile, "%.*s\n", css->u.fmt.u.fe.fmtlen, css->u.fmt.u.fe.fmtbuf); for (i = 0; i <= offset; i++) (void) fprintf(errfile, " "); (void) fprintf(errfile, "^\n"); } } } else /* Unknown state */ if (file == NULL) (void) fprintf(errfile, " an indeterminate file\n"); else (void) fprintf(errfile, " file \"%s\"\n", file); } /* * Print name of the routine which called _ferr() which called us. */ #ifdef _UNICOS { int len, lineno; char name[MAX_ENT_LEN]; len = _who_called_me(&lineno, name, MAX_ENT_LEN, 2); if (len > 0) { /* If no error */ name[len] = '\0'; (void) fprintf(errfile, "Error initiated at line %d in routine '%s'.\n", lineno, name); } } #endif #ifdef _CRAY2 /* * Print traceback * * On CX/CEA systems, the traceback is printed by the abort() call. */ (void) _tracebk(25, errfile); #endif return; }