Esempio n. 1
0
/*****************************************************************************
 *            hermes_cor_reset                                               *
 *                                                                           *
 * This is the first step in initializing the card's firmware and hardware:  *
 * write HERMES_PCI_COR_MASK to the Configuration Option Register            *
 *****************************************************************************/
int hermes_cor_reset (hermes_t *hw) {
	int k;
	u16_t reg;

	/* Assert the reset until the card notice */
	hermes_write_reg (hw, HERMES_PCI_COR, HERMES_PCI_COR_MASK);

	milli_delay (HERMES_PCI_COR_ONT);

	/* Give time for the card to recover from this hard effort */
	hermes_write_reg (hw, HERMES_PCI_COR, 0x0000);

	milli_delay (HERMES_PCI_COR_OFFT);

	/* The card is ready when it's no longer busy */
	k = HERMES_PCI_COR_BUSYT;
	reg = hermes_read_reg (hw, HERMES_CMD);
	while (k && (reg & HERMES_CMD_BUSY)) {
		k--;
		milli_delay (1);
		reg = hermes_read_reg (hw, HERMES_CMD);
	}

	/* Did we timeout ? */
	if (reg & HERMES_CMD_BUSY) {
		printf ("Busy timeout after resetting the COR\n");
		return -1;
	}

	return (0);
}
Esempio n. 2
0
/* Set up a BAP to read a particular chunk of data from card's internal buffer.
 *
 * Returns: < 0 on internal failure (errno), 0 on success, >0 on error
 * from firmware
 *
 * Callable from any context */
static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
{
	int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
	int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
	int k;
	u16 reg;

	/* Paranoia.. */
	if ( (offset > HERMES_BAP_OFFSET_MAX) || (offset % 2) )
		return -EINVAL;

	k = HERMES_BAP_BUSY_TIMEOUT;
	reg = hermes_read_reg(hw, oreg);
	while ((reg & HERMES_OFFSET_BUSY) && k) {
		k--;
		udelay(1);
		reg = hermes_read_reg(hw, oreg);
	}

#ifdef HERMES_DEBUG_BUFFER
	hw->profile[HERMES_BAP_BUSY_TIMEOUT - k]++;

	if (k < HERMES_BAP_BUSY_TIMEOUT) {
		struct hermes_debug_entry *e = 
			&hw->dbuf[(hw->dbufp++) % HERMES_DEBUG_BUFSIZE];
		e->bap = bap;
		e->id = id;
		e->offset = offset;
		e->cycles = HERMES_BAP_BUSY_TIMEOUT - k;
	}
#endif

	if (reg & HERMES_OFFSET_BUSY)
		return -ETIMEDOUT;

	/* Now we actually set up the transfer */
	hermes_write_reg(hw, sreg, id);
	hermes_write_reg(hw, oreg, offset);

	/* Wait for the BAP to be ready */
	k = HERMES_BAP_BUSY_TIMEOUT;
	reg = hermes_read_reg(hw, oreg);
	while ( (reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) {
		k--;
		udelay(1);
		reg = hermes_read_reg(hw, oreg);
	}

	if (reg & HERMES_OFFSET_BUSY) {
		return -ETIMEDOUT;
	}

	if (reg & HERMES_OFFSET_ERR) {
		return -EIO;
	}


	return 0;
}
Esempio n. 3
0
/* Set up a BAP to read a particular chunk of data from card's internal buffer.
 *
 * Returns: < 0 on internal failure (errno), 0 on success, >0 on error
 * from firmware
 *
 * Callable from any context */
static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
{
	int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
	int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
	int k;
	u16 reg;

	/* Paranoia.. */
	if ( (offset > HERMES_BAP_OFFSET_MAX) || (offset % 2) )
		return -EINVAL;

	k = HERMES_BAP_BUSY_TIMEOUT;
	reg = hermes_read_reg(hw, oreg);
	while ((reg & HERMES_OFFSET_BUSY) && k) {
		k--;
		udelay(1);
		reg = hermes_read_reg(hw, oreg);
	}

	if (reg & HERMES_OFFSET_BUSY)
		return -ETIMEDOUT;

	/* Now we actually set up the transfer */
	hermes_write_reg(hw, sreg, id);
	hermes_write_reg(hw, oreg, offset);

	/* Wait for the BAP to be ready */
	k = HERMES_BAP_BUSY_TIMEOUT;
	reg = hermes_read_reg(hw, oreg);
	while ( (reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) {
		k--;
		udelay(1);
		reg = hermes_read_reg(hw, oreg);
	}

	if (reg != offset) {
		printk(KERN_ERR "hermes @ %p: BAP%d offset %s: "
		       "reg=0x%x id=0x%x offset=0x%x\n", hw->iobase, bap,
		       (reg & HERMES_OFFSET_BUSY) ? "timeout" : "error",
		       reg, id, offset);

		if (reg & HERMES_OFFSET_BUSY) {
			return -ETIMEDOUT;
		}

		return -EIO;		/* error or wrong offset */
	}

	return 0;
}
static int hermes_bap_seek(struct hermes *hw, int bap, u16 id, u16 offset)
{
	int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
	int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
	int k;
	u16 reg;

	
	if ((offset > HERMES_BAP_OFFSET_MAX) || (offset % 2))
		return -EINVAL;

	k = HERMES_BAP_BUSY_TIMEOUT;
	reg = hermes_read_reg(hw, oreg);
	while ((reg & HERMES_OFFSET_BUSY) && k) {
		k--;
		udelay(1);
		reg = hermes_read_reg(hw, oreg);
	}

	if (reg & HERMES_OFFSET_BUSY)
		return -ETIMEDOUT;

	
	hermes_write_reg(hw, sreg, id);
	hermes_write_reg(hw, oreg, offset);

	
	k = HERMES_BAP_BUSY_TIMEOUT;
	reg = hermes_read_reg(hw, oreg);
	while ((reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) {
		k--;
		udelay(1);
		reg = hermes_read_reg(hw, oreg);
	}

	if (reg != offset) {
		printk(KERN_ERR "hermes @ %p: BAP%d offset %s: "
		       "reg=0x%x id=0x%x offset=0x%x\n", hw->iobase, bap,
		       (reg & HERMES_OFFSET_BUSY) ? "timeout" : "error",
		       reg, id, offset);

		if (reg & HERMES_OFFSET_BUSY)
			return -ETIMEDOUT;

		return -EIO;		
	}

	return 0;
}
Esempio n. 5
0
/* Set up a BAP to read a particular chunk of data from card's internal buffer.
 *
 * Returns: < 0 on internal failure (errno), 0 on success, >0 on error
 * from firmware
 *
 * Callable from any context */
int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
{
	int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
	int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
	int k;
	u16 reg;

	/* Paranoia.. */
	if ( (offset > HERMES_BAP_OFFSET_MAX) || (offset % 2) )
		return -EINVAL;

	k = BAP_BUSY_TIMEOUT;
	reg = hermes_read_reg(hw, oreg);
	while ((reg & HERMES_OFFSET_BUSY) && k) {
		k--;
		udelay(1);
		reg = hermes_read_reg(hw, oreg);
	}

	if (reg & HERMES_OFFSET_BUSY)
		return -ETIMEDOUT;

	/* Now we actually set up the transfer */
	hermes_write_reg(hw, sreg, id);
	hermes_write_reg(hw, oreg, offset);

	/* Wait for the BAP to be ready */
	k = BAP_BUSY_TIMEOUT;
	reg = hermes_read_reg(hw, oreg);
	while ( (reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) {
		k--;
		udelay(1);
		reg = hermes_read_reg(hw, oreg);
	}

	if (reg & HERMES_OFFSET_BUSY) {
		DEBUG(1,"hermes_bap_seek: timeout\n");
		return -ETIMEDOUT;
	}

	if (reg & HERMES_OFFSET_ERR) {
		DEBUG(1,"hermes_bap_seek: BAP error\n");
		return -EIO;
	}


	return 0;
}
Esempio n. 6
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;
}
Esempio n. 7
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, int bufsize,
		    u16 *length, void *buf)
{
	int err = 0;
	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
	u16 rlength, rtype;
	hermes_response_t resp;

	if (bufsize % 2)
		return -EINVAL;

	err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, &resp);
	if (err)
		goto out;

	err = hermes_bap_seek(hw, bap, rid, 0);
	if (err)
		goto out;

	rlength = hermes_read_reg(hw, dreg);
	rtype = hermes_read_reg(hw, dreg);

	if (length)
		*length = rlength;

	if (rtype != rid)
		printk(KERN_WARNING "hermes_read_ltv(): rid  (0x%04x) does "
		       "not match type (0x%04x)\n", rid, rtype);
	if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize)
		printk(KERN_WARNING "hermes @ 0x%x: Truncating LTV record from %d to %d bytes. "
		       "(rid=0x%04x, len=0x%04x)\n", hw->iobase,
		       HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength);
	
	/* FIXME: we should read the min of the requested length and
           the actual record length */
	hermes_read_words(hw, dreg, buf, bufsize / 2);

 out:
	return err;
}
Esempio n. 8
0
/*****************************************************************************
 *            hermes_issue_cmd                                               *
 *                                                                           *
 * Issue a command to the chip. Waiting for it to complete is the caller's   *
 * problem. The only thing we have to do first is to see whether we can      *
 * actually write something in the CMD register: is it unbusy?               *
 * Returns -EBUSY if the command register is busy, 0 on success.             *
 *****************************************************************************/
static int hermes_issue_cmd (hermes_t * hw, u16_t cmd, u16_t param0) {
	int k = HERMES_CMD_BUSY_TIMEOUT;
	u16_t reg;

	/* First wait for the command register to unbusy */
	reg = hermes_read_reg (hw, HERMES_CMD);
	while ((reg & HERMES_CMD_BUSY) && k) {
		k--;
		micro_delay (1);
		reg = hermes_read_reg (hw, HERMES_CMD);
	}
	/* it takes too long. Bailing out */
	if (reg & HERMES_CMD_BUSY) {
		printf("Hermes: HERMES_CMD_BUSY timeout\n");
		return -EBUSY;
	}

	/* write the values to the right registers */
	hermes_write_reg (hw, HERMES_PARAM2, 0);
	hermes_write_reg (hw, HERMES_PARAM1, 0);
	hermes_write_reg (hw, HERMES_PARAM0, param0);
	hermes_write_reg (hw, HERMES_CMD, cmd);
	return 0;
}
Esempio n. 9
0
/*****************************************************************************
 *            hermes_init                                                    *
 *                                                                           *
 * Initialize the card                                                       *
 *****************************************************************************/
int hermes_init (hermes_t * hw)
{
	u32_t status, reg, resp0;
	int err = 0;
	int k;

	/* We don't want to be interrupted while resetting the chipset. By 
	 * setting the control mask for hardware interrupt generation to 0,
	 * we won't be disturbed*/
	hw->inten = 0x0;
	hermes_write_reg (hw, HERMES_INTEN, 0);

	/* Acknowledge any pending events waiting for acknowledgement. We 
	 * assume there won't be any important to take care off */
	hermes_write_reg (hw, HERMES_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 = HERMES_CMD_BUSY_TIMEOUT;
	reg = hermes_read_reg (hw, HERMES_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 */
			printf("Hermes: Card removed?\n");
			return -ENODEV;
		}

		k--;
		micro_delay (1);
		reg = hermes_read_reg (hw, HERMES_CMD);
	}

	/* No need to explicitly handle the timeout - if we've timed
	 * out hermes_issue_cmd() will probably return -EBUSY below.
	 * But i check to be sure :-) */
	if (reg & HERMES_CMD_BUSY) {
		printf("Hermes: Timeout waiting for the CMD_BUSY to unset\n");
		return -EBUSY;
	}

	/* According to the documentation, EVSTAT may contain
	 * obsolete event occurrence information.  We have to acknowledge
	 * it by writing EVACK. */
	reg = hermes_read_reg (hw, HERMES_EVSTAT);
	hermes_write_reg (hw, HERMES_EVACK, reg);

	err = hermes_issue_cmd (hw, HERMES_CMD_INIT, 0);
	if (err){
		printf("Hermes: errornr: 0x%x issueing HERMES_CMD_INIT\n",
			 err);
		return err;
	}

	/* here we start waiting for the above command,CMD_INIT, to complete.
	 * Completion is noticeable when the HERMES_EV_CMD bit in the 
	 * HERMES_EVSTAT register is set to 1 */
	reg = hermes_read_reg (hw, HERMES_EVSTAT);
	k = HERMES_CMD_INIT_TIMEOUT;
	while ((!(reg & HERMES_EV_CMD)) && k) {
		k--;
		micro_delay (10);
		reg = hermes_read_reg (hw, HERMES_EVSTAT);
	}


	/* the software support register 0 (there are 3) is filled with a 
	 * magic number. With this one can test the availability of the card */
	hermes_write_reg (hw, HERMES_SWSUPPORT0, HERMES_MAGIC);

	if (!hermes_present (hw)) {
		printf("Hermes: Card not present?: got mag. nr.0x%x\n",
			 hermes_read_reg (hw, HERMES_SWSUPPORT0));
	}

	if (!(reg & HERMES_EV_CMD)) {
		printf("hermes @ %x: Timeout waiting for card to reset\n",
			hw->iobase);
		return -ETIMEDOUT;
	}

	status = hermes_read_reg (hw, HERMES_STATUS);
	resp0 = hermes_read_reg (hw, HERMES_RESP0);

	/* after having issued the command above, the completion set a bit in 
	 * the EVSTAT register. This has to be acknowledged, as follows */
	hermes_write_reg (hw, HERMES_EVACK, HERMES_EV_CMD);

	/* Was the status, the result of the issued command, ok? */
	/* The expression below should be zero. Non-zero means an error */
	if (status & HERMES_STATUS_RESULT) {
		printf("Hermes:Result of INIT_CMD wrong.error value: 0x%x\n",
			(status & HERMES_STATUS_RESULT) >> 8);
		err = -EIO;
	}
Esempio n. 10
0
/*****************************************************************************
 *            hermes_present                                                 *
 *                                                                           *
 * Check whether we have access to the card. Does the SWSUPPORT0 contain the *
 * value we put in it earlier?                                               *
 *****************************************************************************/
PRIVATE int hermes_present (hermes_t * hw) {
	int i = hermes_read_reg (hw, HERMES_SWSUPPORT0) == HERMES_MAGIC;
	if (!i)
		printf("Hermes: Error, card not present?\n");
	return i;
}