/* 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; }
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; }
/***************************************************************************** * 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; }