/* 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;
}
static int hermes_doicmd_wait(struct hermes *hw, u16 cmd,
			      u16 parm0, u16 parm1, u16 parm2,
			      struct hermes_response *resp)
{
	int err = 0;
	int k;
	u16 status, reg;

	err = hermes_issue_cmd(hw, cmd, parm0, parm1, parm2);
	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 @ %p: "
		       "Timeout waiting for card to reset (reg=0x%04x)!\n",
		       hw->iobase, reg);
		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 #3
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;
}
static int hermes_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
			     struct hermes_response *resp)
{
	int err;
	int k;
	u16 reg;
	u16 status;

	err = hermes_issue_cmd(hw, cmd, parm0, 0, 0);
	if (err) {
		if (!hermes_present(hw)) {
			if (net_ratelimit())
				printk(KERN_WARNING "hermes @ %p: "
				       "Card removed while issuing command "
				       "0x%04x.\n", hw->iobase, cmd);
			err = -ENODEV;
		} else
			if (net_ratelimit())
				printk(KERN_ERR "hermes @ %p: "
				       "Error %d issuing command 0x%04x.\n",
				       hw->iobase, err, cmd);
		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 @ %p: Card removed "
		       "while waiting for command 0x%04x completion.\n",
		       hw->iobase, cmd);
		err = -ENODEV;
		goto out;
	}

	if (!(reg & HERMES_EV_CMD)) {
		printk(KERN_ERR "hermes @ %p: Timeout waiting for "
		       "command 0x%04x completion.\n", hw->iobase, cmd);
		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 #5
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;
	}