/* 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;
}
Beispiel #2
0
/* 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;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
0
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;
}