static int ql_mb_dump_ram(struct ql_adapter *qdev, u64 req_dma, u32 addr, u32 size) { int status = 0; struct mbox_params mbc; struct mbox_params *mbcp = &mbc; memset(mbcp, 0, sizeof(struct mbox_params)); mbcp->in_count = 9; mbcp->out_count = 1; mbcp->mbox_in[0] = MB_CMD_DUMP_RISC_RAM; mbcp->mbox_in[1] = LSW(addr); mbcp->mbox_in[2] = MSW(req_dma); mbcp->mbox_in[3] = LSW(req_dma); mbcp->mbox_in[4] = MSW(size); mbcp->mbox_in[5] = LSW(size); mbcp->mbox_in[6] = MSW(MSD(req_dma)); mbcp->mbox_in[7] = LSW(MSD(req_dma)); mbcp->mbox_in[8] = MSW(addr); status = ql_mailbox_command(qdev, mbcp); if (status) return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { netif_err(qdev, drv, qdev->ndev, "Failed to dump risc RAM.\n"); status = -EIO; } return status; }
// 0x0009: request directory listing TIEXPORT3 int TICALL dusb_cmd_s_dirlist_request(CalcHandle *handle, unsigned int naids, const uint16_t *aids) { DUSBVirtualPacket* pkt; unsigned int i; unsigned int j = 0; int retval = 0; VALIDATE_HANDLE(handle); VALIDATE_ATTRS(naids, aids); pkt = dusb_vtl_pkt_new_ex(handle, 4 + 2 * naids + 7, DUSB_VPKT_DIR_REQ, dusb_vtl_pkt_alloc_data(4 + 2 * naids + 7)); pkt->data[j++] = MSB(MSW(naids)); pkt->data[j++] = LSB(MSW(naids)); pkt->data[j++] = MSB(LSW(naids)); pkt->data[j++] = LSB(LSW(naids)); for (i = 0; i < naids; i++) { pkt->data[j++] = MSB(aids[i]); pkt->data[j++] = LSB(aids[i]); } pkt->data[j++] = 0x00; pkt->data[j++] = 0x01; pkt->data[j++] = 0x00; pkt->data[j++] = 0x01; pkt->data[j++] = 0x00; pkt->data[j++] = 0x01; pkt->data[j++] = 0x01; retval = dusb_send_data(handle, pkt); dusb_vtl_pkt_del(handle, pkt); ticalcs_info(" naids=%i", naids); return retval; }
TIEXPORT3 int TICALL ti68k_send_VAR(CalcHandle* handle, uint32_t varsize, uint8_t vartype, const char *varname, uint8_t target) { uint8_t buffer[32]; char trans[127]; uint8_t extra = (target == DBUS_MID_PC_TI92) ? 0 : ((vartype == TI89_BKUP) ? 0 : 1); uint16_t len; VALIDATE_HANDLE(handle); VALIDATE_NONNULL(varname); len = (uint16_t)strlen(varname); if (len > 17) { ticalcs_critical("Oversized variable name has length %i, clamping to 17", len); len = 17; } ticonv_varname_to_utf8_sn(handle->model, varname, trans, sizeof(trans), vartype); buffer[0] = LSB(LSW(varsize)); buffer[1] = MSB(LSW(varsize)); buffer[2] = LSB(MSW(varsize)); buffer[3] = MSB(MSW(varsize)); buffer[4] = vartype; buffer[5] = len; memcpy(buffer + 6, varname, len); buffer[6 + len] = 0x03; ticalcs_info(" PC->TI: VAR (size=0x%08X=%i, id=%02X, name=%s)", varsize, varsize, vartype, trans); return dbus_send(handle, target, DBUS_CMD_VAR, 6 + len + extra, buffer); }
TIEXPORT3 int TICALL ti92_send_RTS(CalcHandle* handle, uint32_t varsize, uint8_t vartype, const char *varname) { uint8_t buffer[32]; uint16_t len; VALIDATE_HANDLE(handle); VALIDATE_NONNULL(varname); len = (uint16_t)strlen(varname); if (len > 17) { ticalcs_critical("Oversized variable name has length %i, clamping to 17", len); len = 17; } buffer[0] = LSB(LSW(varsize)); buffer[1] = MSB(LSW(varsize)); buffer[2] = LSB(MSW(varsize)); buffer[3] = MSB(MSW(varsize)); buffer[4] = vartype; buffer[5] = len; memcpy(buffer + 6, varname, len); ticalcs_info(" PC->TI: RTS (size=0x%08X=%i, id=%02X, name=%s)", varsize, varsize, vartype, varname); return dbus_send(handle, DBUS_MID_PC_TI92, DBUS_CMD_RTS, 6 + len, buffer); }
TIEXPORT3 int TICALL ti89_send_RTS(CalcHandle* handle, uint32_t varsize, uint8_t vartype, const char *varname) { uint8_t buffer[32]; uint16_t len; VALIDATE_HANDLE(handle); VALIDATE_NONNULL(varname); len = (uint16_t)strlen(varname); if (len > 17) { ticalcs_critical("Oversized variable name has length %i, clamping to 17", len); len = 17; } buffer[0] = LSB(LSW(varsize)); buffer[1] = MSB(LSW(varsize)); buffer[2] = LSB(MSW(varsize)); buffer[3] = MSB(MSW(varsize)); buffer[4] = vartype; buffer[5] = len; memcpy(buffer + 6, varname, len); buffer[6 + len] = 0x00; len += 6 + 1; // used by AMS <= 2.09 ? //if ((vartype == TI89_AMS) || (vartype == TI89_APPL)) len--; ticalcs_info(" PC->TI: RTS (size=0x%08X=%i, id=%02X, name=%s)", varsize, varsize, vartype, varname); return dbus_send(handle, ti68k_handle_to_dbus_mid(handle), DBUS_CMD_RTS, len, buffer); }
void gpif_set_tc32(DWORD tc) { GPIFTCB3 = MSB(MSW(tc)); SYNCDELAY; GPIFTCB2 = LSB(MSW(tc)); SYNCDELAY; GPIFTCB1 = MSB(LSW(tc)); SYNCDELAY; GPIFTCB0 = LSB(LSW(tc)); }
static int qlcnic_sriov_set_pvid_mode(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd) { adapter->rx_pvid = MSW(cmd->rsp.arg[1]) & 0xffff; adapter->flags &= ~QLCNIC_TAGGING_ENABLED; return 0; }
int cmd_s_os_install(CalcHandle *h, uint32_t size) { VirtualPacket* pkt; ticalcs_info(" installing OS:"); pkt = nsp_vtl_pkt_new_ex(4, NSP_SRC_ADDR, nsp_src_port, NSP_DEV_ADDR, PORT_OS_INSTALL); pkt->cmd = CMD_OS_INSTALL; pkt->data[0] = MSB(MSW(size)); pkt->data[1] = LSB(MSW(size)); pkt->data[2] = MSB(LSW(size)); pkt->data[3] = LSB(LSW(size)); TRYF(nsp_send_data(h, pkt)); nsp_vtl_pkt_del(pkt); return 0; }
int ti92_send_RTS_h(CalcHandle* handle, uint32_t varsize, uint8_t vartype, const char *varname) { uint8_t buffer[32] = { 0 }; buffer[0] = LSB(LSW(varsize)); buffer[1] = MSB(LSW(varsize)); buffer[2] = LSB(MSW(varsize)); buffer[3] = MSB(MSW(varsize)); buffer[4] = vartype; buffer[5] = strlen(varname); memcpy(buffer + 6, varname, strlen(varname)); ticalcs_info(" PC->TI: RTS (size=0x%08X=%i, id=%02X, name=%s)", varsize, varsize, vartype, varname); TRYF(dbus_send(handle, PC_TI92, CMD_RTS, 6 + strlen(varname), buffer)); return 0; }
TIEXPORT3 int TICALL ti89_send_RTS2(CalcHandle* handle, uint32_t varsize, uint8_t vartype, uint8_t hw_id) { uint8_t buffer[9]; VALIDATE_HANDLE(handle); buffer[0] = LSB(LSW(varsize)); buffer[1] = MSB(LSW(varsize)); buffer[2] = LSB(MSW(varsize)); buffer[3] = MSB(MSW(varsize)); buffer[4] = vartype; buffer[5] = 0x00; buffer[6] = 0x08; buffer[7] = 0x00; buffer[8] = hw_id; // 0x08 -> V200, 0x09 -> Titanium (Hardware ID) ticalcs_info(" PC->TI: RTS (size=0x%08X=%i, id=%02X, hw_id=%02x)", varsize, varsize, vartype, hw_id); return dbus_send(handle, ti68k_handle_to_dbus_mid(handle), DBUS_CMD_RTS, 9, buffer); }
/* FLASH (special var header: size, id, flag, offset, page) */ TIEXPORT3 int TICALL ti73_send_VAR2(CalcHandle* handle, uint32_t length, uint8_t type, uint8_t flag, uint16_t offset, uint16_t page) { uint8_t buffer[11]; buffer[0] = LSB(LSW(length)); buffer[1] = MSB(LSW(length)); buffer[2] = type; buffer[3] = LSB(MSW(length)); buffer[4] = MSB(MSW(length)); buffer[5] = flag; buffer[6] = LSB(offset); buffer[7] = MSB(offset); buffer[8] = LSB(page); buffer[9] = MSB(page); ticalcs_info(" PC->TI: VAR (size=0x%04X, id=%02X, flag=%02X, offset=%04X, page=%02X)", length, type, flag, offset, page); return dbus_send(handle, PC_TI7383, CMD_VAR, 10, buffer); }
TIEXPORT3 int TICALL dusb_send(CalcHandle* handle, DUSBRawPacket* pkt) { uint8_t buf[sizeof(pkt->data) + 5]; uint32_t size; int ret; VALIDATE_HANDLE(handle); VALIDATE_NONNULL(pkt); memset(buf, 0, sizeof(buf)); size = pkt->size; if (size > sizeof(pkt->data)) { size = sizeof(pkt->data); } buf[0] = MSB(MSW(size)); buf[1] = LSB(MSW(size)); buf[2] = MSB(LSW(size)); buf[3] = LSB(LSW(size)); buf[4] = pkt->type; memcpy(buf + 5, pkt->data, size); //printf("dusb_send: pkt->size=%d\n", pkt->size); ticables_progress_reset(handle->cable); ret = ticables_cable_send(handle->cable, buf, size + 5); if (!ret) { if (size >= 128) { ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); } if (handle->updat->cancel) { ret = ERR_ABORT; } } return ret; }
int ti92_send_VAR_h(CalcHandle* handle, uint32_t varsize, uint8_t vartype, const char *varname) { uint8_t buffer[32]; char trans[17]; ticonv_varname_to_utf8_s(handle->model, varname, trans, vartype); buffer[0] = LSB(LSW(varsize)); buffer[1] = MSB(LSW(varsize)); buffer[2] = LSB(MSW(varsize)); buffer[3] = MSB(MSW(varsize)); buffer[4] = vartype; buffer[5] = strlen(varname); memcpy(buffer + 6, varname, strlen(varname)); ticalcs_info(" PC->TI: VAR (size=0x%08X=%i, id=%02X, name=%s)", varsize, varsize, vartype, trans); TRYF(dbus_send(handle, PC_TI92, CMD_VAR, 6 + strlen(varname), buffer)); return 0; }
// 0x0002: begin OS transfer TIEXPORT3 int TICALL dusb_cmd_s_os_begin(CalcHandle *handle, uint32_t size) { DUSBVirtualPacket* pkt; int retval = 0; VALIDATE_HANDLE(handle); pkt = dusb_vtl_pkt_new_ex(handle, 11, DUSB_VPKT_OS_BEGIN, dusb_vtl_pkt_alloc_data(11)); pkt->data[7] = MSB(MSW(size)); pkt->data[8] = LSB(MSW(size)); pkt->data[9] = MSB(LSW(size)); pkt->data[10]= LSB(LSW(size)); retval = dusb_send_data(handle, pkt); dusb_vtl_pkt_del(handle, pkt); ticalcs_info(" size = %08x (%i)", size, size); return retval; }
int ti89_send_RTS2_h(CalcHandle* handle, uint32_t varsize, uint8_t vartype, uint8_t hw_id) { uint8_t buffer[32] = { 0 }; uint16_t len; buffer[0] = LSB(LSW(varsize)); buffer[1] = MSB(LSW(varsize)); buffer[2] = LSB(MSW(varsize)); buffer[3] = MSB(MSW(varsize)); buffer[4] = vartype; buffer[5] = 0x00; buffer[6] = 0x08; buffer[7] = 0x00; buffer[8] = hw_id; // 0x08 -> V200, 0x09 -> Titanium (Hardware ID) len = 9; ticalcs_info(" PC->TI: RTS (size=0x%08X=%i, id=%02X, hw_id=%02x)", varsize, varsize, vartype, hw_id); TRYF(dbus_send(handle, PC_TI9X, CMD_RTS, len, buffer)); return 0; }
int dusb_send(CalcHandle* handle, RawPacket* pkt) { uint8_t buf[1023 + 5]= { 0 }; uint32_t size = pkt->size + 5; buf[0] = MSB(MSW(pkt->size)); buf[1] = LSB(MSW(pkt->size)); buf[2] = MSB(LSW(pkt->size)); buf[3] = LSB(LSW(pkt->size)); buf[4] = pkt->type; memcpy(buf+5, pkt->data, pkt->size); //printf("dusb_send: pkt->size=%d\n", pkt->size); ticables_progress_reset(handle->cable); TRYF(ticables_cable_send(handle->cable, buf, size)); if(size >= 128) ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); if (handle->updat->cancel) return ERR_ABORT; return 0; }
// Call it before ti68k_state_save to update registers with current clock // so that clock is correcly saved int rtc3_state_save(void) { TTIME rtc3_cur; TTIME d, a; if(tihw.hw_type < HW3) return 0; // get time and computes time elapsed since reload (cur - beg + load) rtc3_get_time(&rtc3_cur); rtc3_diff_time(&rtc3_cur, &tihw.rtc3_beg, &d); rtc3_add_time(&d, &tihw.rtc3_load, &a); // 1/16th of seconds tihw.io3[0x45] = (a.ms+a.ms) / 125; // seconds since January 1st, 1997 00:00:00 tihw.io3[0x46] = MSB(MSW(a.s)); tihw.io3[0x47] = LSB(MSW(a.s)); tihw.io3[0x48] = MSB(LSW(a.s)); tihw.io3[0x49] = LSB(LSW(a.s)); //printf("%i.%i\n", tihw.io3[0x49], tihw.io3[0x45]); /* rtc3_diff_time(&rtc3_cur, &tihw.rtc3_beg, &r); printf("%i.%i - %i.%i = %i.%i\n", rtc3_cur.s, rtc3_cur.ms, tihw.rtc3_beg.s, tihw.rtc3_beg.ms, r.s, r.ms); */ /* rtc3_add_time(&rtc3_cur, &tihw.rtc3_beg, &r); printf("%i.%i - %i.%i = %i.%i\n", rtc3_cur.s, rtc3_cur.ms, tihw.rtc3_beg.s, tihw.rtc3_beg.ms, r.s, r.ms); */ return 0; }
int cmd_s_put_file(CalcHandle *h, const char *name, uint32_t size) { VirtualPacket* pkt; int o; size_t len = strlen(name) < 8 ? 8 : strlen(name); ticalcs_info(" sending variable:"); pkt = nsp_vtl_pkt_new_ex(6 + len, NSP_SRC_ADDR, nsp_src_port, NSP_DEV_ADDR, PORT_FILE_MGMT); pkt->cmd = CMD_FM_PUT_FILE; pkt->data[0] = 0x01; o = put_str(pkt->data + 1, name); o++; pkt->data[o+0] = MSB(MSW(size)); pkt->data[o+1] = LSB(MSW(size)); pkt->data[o+2] = MSB(LSW(size)); pkt->data[o+3] = LSB(LSW(size)); TRYF(nsp_send_data(h, pkt)); nsp_vtl_pkt_del(pkt); return 0; }
int ti89_send_RTS_h(CalcHandle* handle, uint32_t varsize, uint8_t vartype, const char *varname) { uint8_t buffer[32] = { 0 }; uint16_t len; buffer[0] = LSB(LSW(varsize)); buffer[1] = MSB(LSW(varsize)); buffer[2] = LSB(MSW(varsize)); buffer[3] = MSB(MSW(varsize)); buffer[4] = vartype; buffer[5] = strlen(varname); memcpy(buffer + 6, varname, strlen(varname)); buffer[6 + strlen(varname)] = 0x00; len = 6 + strlen(varname) + 1; // used by AMS <= 2.09 ? //if ((vartype == TI89_AMS) || (vartype == TI89_APPL)) len--; ticalcs_info(" PC->TI: RTS (size=0x%08X=%i, id=%02X, name=%s)", varsize, varsize, vartype, varname); TRYF(dbus_send(handle, PC_TI9X, CMD_RTS, len, buffer)); return 0; }
TIEXPORT3 int TICALL dusb_send(CalcHandle* handle, DUSBRawPacket* pkt) { uint8_t buf[1023 + 5]= { 0 }; uint32_t size; if (handle == NULL) { ticalcs_critical("%s: handle is NULL", __FUNCTION__); return ERR_INVALID_HANDLE; } if (pkt == NULL) { ticalcs_critical("%s: pkt is NULL", __FUNCTION__); return ERR_INVALID_PACKET; } size = pkt->size + 5; buf[0] = MSB(MSW(pkt->size)); buf[1] = LSB(MSW(pkt->size)); buf[2] = MSB(LSW(pkt->size)); buf[3] = LSB(LSW(pkt->size)); buf[4] = pkt->type; memcpy(buf+5, pkt->data, pkt->size); //printf("dusb_send: pkt->size=%d\n", pkt->size); ticables_progress_reset(handle->cable); TRYF(ticables_cable_send(handle->cable, buf, size)); if(size >= 128) ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); if (handle->updat->cancel) return ERR_ABORT; return 0; }
/* Get eSwitch Capabilities */ int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *adapter, u8 port, struct qlcnic_eswitch *eswitch) { int err = -EIO; u32 arg1, arg2; if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) return err; err = qlcnic_issue_cmd(adapter, adapter->ahw.pci_func, adapter->fw_hal_version, port, 0, 0, QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY); if (err == QLCNIC_RCODE_SUCCESS) { arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); eswitch->port = arg1 & 0xf; eswitch->active_vports = LSB(arg2); eswitch->max_ucast_filters = MSB(arg2); eswitch->max_active_vlans = LSB(MSW(arg2)); if (arg1 & BIT_6) eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING; if (arg1 & BIT_7) eswitch->flags |= QLCNIC_SWITCH_PROMISC_MODE; if (arg1 & BIT_8) eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING; } else { dev_err(&adapter->pdev->dev, "Failed to get eswitch capabilities%d\n", err); } return err; }
VOID SetConsoleDmost(VOID) { long ystart; long xstart; long i; long adj=0; // dont setup the startumost/dmost arrays if border is 0 if (gs.BorderNum == BORDER_NONE || gs.BorderNum == BORDER_MINI_BAR) return; // // Set the whole thing to the size of the bar // ystart = f_ydim - Y_TO_FIXED(BAR_HEIGHT); #undef STATUS_BAR #define STATUS_BAR 2434 if (ydim == 480 && gs.BorderNum == 2) adj = 1; #ifdef SW_3DFX if (ydim == 384 && gs.BorderNum == 2) adj = 1; #endif //for (i = FIXED(0, 0); i < f_320; i += x_pix_size) for (i = 0; i < xdim; i++) // define picture // boundaries { startdmost[i] = MSW(ystart) + adj; } }
/** * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. * @ha: HA context * @hardware_locked: Called with the hardware_lock */ void qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) { int rval; uint32_t cnt, timer; uint32_t risc_address; uint16_t mb0, mb2; uint32_t stat; device_reg_t __iomem *reg = ha->iobase; uint16_t __iomem *dmp_reg; unsigned long flags; struct qla2300_fw_dump *fw; uint32_t dump_size, data_ram_cnt; risc_address = data_ram_cnt = 0; mb0 = mb2 = 0; flags = 0; if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); if (ha->fw_dump != NULL) { qla_printk(KERN_WARNING, ha, "Firmware has been previously dumped (%p) -- ignoring " "request...\n", ha->fw_dump); goto qla2300_fw_dump_failed; } /* Allocate (large) dump buffer. */ dump_size = sizeof(struct qla2300_fw_dump); dump_size += (ha->fw_memory_size - 0x11000) * sizeof(uint16_t); ha->fw_dump_order = get_order(dump_size); ha->fw_dump = (struct qla2300_fw_dump *) __get_free_pages(GFP_ATOMIC, ha->fw_dump_order); if (ha->fw_dump == NULL) { qla_printk(KERN_WARNING, ha, "Unable to allocated memory for firmware dump (%d/%d).\n", ha->fw_dump_order, dump_size); goto qla2300_fw_dump_failed; } fw = ha->fw_dump; rval = QLA_SUCCESS; fw->hccr = RD_REG_WORD(®->hccr); /* Pause RISC. */ WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC); if (IS_QLA2300(ha)) { for (cnt = 30000; (RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) == 0 && rval == QLA_SUCCESS; cnt--) { if (cnt) udelay(100); else rval = QLA_FUNCTION_TIMEOUT; } } else { RD_REG_WORD(®->hccr); /* PCI Posting. */ udelay(10); } if (rval == QLA_SUCCESS) { dmp_reg = (uint16_t __iomem *)(reg + 0); for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) fw->pbiu_reg[cnt] = RD_REG_WORD(dmp_reg++); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10); for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++) fw->risc_host_reg[cnt] = RD_REG_WORD(dmp_reg++); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x40); for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) fw->mailbox_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x40); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->resp_dma_reg) / 2; cnt++) fw->resp_dma_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x50); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++) fw->dma_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x00); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0); for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++) fw->risc_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2000); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++) fw->risc_gp0_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2200); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++) fw->risc_gp1_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2400); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++) fw->risc_gp2_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2600); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++) fw->risc_gp3_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2800); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++) fw->risc_gp4_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2A00); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++) fw->risc_gp5_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2C00); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++) fw->risc_gp6_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2E00); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++) fw->risc_gp7_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x10); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++) fw->frame_buf_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x20); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++) fw->fpm_b0_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x30); dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++) fw->fpm_b1_reg[cnt] = RD_REG_WORD(dmp_reg++); /* Reset RISC. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); for (cnt = 0; cnt < 30000; cnt++) { if ((RD_REG_WORD(®->ctrl_status) & CSR_ISP_SOFT_RESET) == 0) break; udelay(10); } } if (!IS_QLA2300(ha)) { for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 && rval == QLA_SUCCESS; cnt--) { if (cnt) udelay(100); else rval = QLA_FUNCTION_TIMEOUT; } } if (rval == QLA_SUCCESS) { /* Get RISC SRAM. */ risc_address = 0x800; WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_WORD); clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); } for (cnt = 0; cnt < sizeof(fw->risc_ram) / 2 && rval == QLA_SUCCESS; cnt++, risc_address++) { WRT_MAILBOX_REG(ha, reg, 1, (uint16_t)risc_address); WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT); for (timer = 6000000; timer; timer--) { /* Check for pending interrupts. */ stat = RD_REG_DWORD(®->u.isp2300.host_status); if (stat & HSR_RISC_INT) { stat &= 0xff; if (stat == 0x1 || stat == 0x2) { set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); mb0 = RD_MAILBOX_REG(ha, reg, 0); mb2 = RD_MAILBOX_REG(ha, reg, 2); /* Release mailbox registers. */ WRT_REG_WORD(®->semaphore, 0); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); break; } else if (stat == 0x10 || stat == 0x11) { set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); mb0 = RD_MAILBOX_REG(ha, reg, 0); mb2 = RD_MAILBOX_REG(ha, reg, 2); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); break; } /* clear this intr; it wasn't a mailbox intr */ WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); } udelay(5); } if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { rval = mb0 & MBS_MASK; fw->risc_ram[cnt] = mb2; } else { rval = QLA_FUNCTION_FAILED; } } if (rval == QLA_SUCCESS) { /* Get stack SRAM. */ risc_address = 0x10000; WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_EXTENDED); clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); } for (cnt = 0; cnt < sizeof(fw->stack_ram) / 2 && rval == QLA_SUCCESS; cnt++, risc_address++) { WRT_MAILBOX_REG(ha, reg, 1, LSW(risc_address)); WRT_MAILBOX_REG(ha, reg, 8, MSW(risc_address)); WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT); for (timer = 6000000; timer; timer--) { /* Check for pending interrupts. */ stat = RD_REG_DWORD(®->u.isp2300.host_status); if (stat & HSR_RISC_INT) { stat &= 0xff; if (stat == 0x1 || stat == 0x2) { set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); mb0 = RD_MAILBOX_REG(ha, reg, 0); mb2 = RD_MAILBOX_REG(ha, reg, 2); /* Release mailbox registers. */ WRT_REG_WORD(®->semaphore, 0); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); break; } else if (stat == 0x10 || stat == 0x11) { set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); mb0 = RD_MAILBOX_REG(ha, reg, 0); mb2 = RD_MAILBOX_REG(ha, reg, 2); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); break; } /* clear this intr; it wasn't a mailbox intr */ WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); } udelay(5); } if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { rval = mb0 & MBS_MASK; fw->stack_ram[cnt] = mb2; } else { rval = QLA_FUNCTION_FAILED; } } if (rval == QLA_SUCCESS) { /* Get data SRAM. */ risc_address = 0x11000; data_ram_cnt = ha->fw_memory_size - risc_address + 1; WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_EXTENDED); clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); } for (cnt = 0; cnt < data_ram_cnt && rval == QLA_SUCCESS; cnt++, risc_address++) { WRT_MAILBOX_REG(ha, reg, 1, LSW(risc_address)); WRT_MAILBOX_REG(ha, reg, 8, MSW(risc_address)); WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT); for (timer = 6000000; timer; timer--) { /* Check for pending interrupts. */ stat = RD_REG_DWORD(®->u.isp2300.host_status); if (stat & HSR_RISC_INT) { stat &= 0xff; if (stat == 0x1 || stat == 0x2) { set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); mb0 = RD_MAILBOX_REG(ha, reg, 0); mb2 = RD_MAILBOX_REG(ha, reg, 2); /* Release mailbox registers. */ WRT_REG_WORD(®->semaphore, 0); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); break; } else if (stat == 0x10 || stat == 0x11) { set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); mb0 = RD_MAILBOX_REG(ha, reg, 0); mb2 = RD_MAILBOX_REG(ha, reg, 2); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); break; } /* clear this intr; it wasn't a mailbox intr */ WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); } udelay(5); } if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { rval = mb0 & MBS_MASK; fw->data_ram[cnt] = mb2; } else { rval = QLA_FUNCTION_FAILED; } } if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Failed to dump firmware (%x)!!!\n", rval); free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order); ha->fw_dump = NULL; } else { qla_printk(KERN_INFO, ha, "Firmware dump saved to temp buffer (%ld/%p).\n", ha->host_no, ha->fw_dump); } qla2300_fw_dump_failed: if (!hardware_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); }
/** * qla2x00_intr_handler() - Process interrupts for the ISP. * @irq: * @dev_id: SCSI driver HA context * @regs: * * Called by system whenever the host adapter generates an interrupt. * * Returns handled flag. */ irqreturn_t qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) { scsi_qla_host_t *ha; device_reg_t *reg; uint32_t mbx; int status = 0; unsigned long flags = 0; unsigned long mbx_flags = 0; unsigned long intr_iter; uint32_t stat; uint16_t hccr; /* Don't loop forever, interrupt are OFF */ intr_iter = 50; ha = (scsi_qla_host_t *) dev_id; if (!ha) { printk(KERN_INFO "%s(): NULL host pointer\n", __func__); return (IRQ_NONE); } reg = ha->iobase; spin_lock_irqsave(&ha->hardware_lock, flags); for (;;) { /* Relax CPU! */ if (!(intr_iter--)) break; if (IS_QLA2100(ha) || IS_QLA2200(ha)) { if ((RD_REG_WORD(®->istatus) & ISR_RISC_INT) == 0) break; if (RD_REG_WORD(®->semaphore) & BIT_0) { WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); /* Get mailbox data. */ mbx = RD_MAILBOX_REG(ha, reg, 0); if (mbx > 0x3fff && mbx < 0x8000) { qla2x00_mbx_completion(ha, (uint16_t)mbx); status |= MBX_INTERRUPT; } else if (mbx > 0x7fff && mbx < 0xc000) { qla2x00_async_event(ha, mbx); } else { /*EMPTY*/ DEBUG2(printk("scsi(%ld): Unrecognized " "interrupt type (%d)\n", ha->host_no, mbx)); } /* Release mailbox registers. */ WRT_REG_WORD(®->semaphore, 0); /* Workaround for ISP2100 chip. */ if (IS_QLA2100(ha)) RD_REG_WORD(®->semaphore); } else { qla2x00_process_response_queue(ha); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); } } else /* IS_QLA23XX(ha) */ { stat = RD_REG_DWORD(®->u.isp2300.host_status); if ((stat & HSR_RISC_INT) == 0) break; mbx = MSW(stat); switch (stat & 0xff) { case 0x13: qla2x00_process_response_queue(ha); break; case 0x1: case 0x2: case 0x10: case 0x11: qla2x00_mbx_completion(ha, (uint16_t)mbx); status |= MBX_INTERRUPT; /* Release mailbox registers. */ WRT_REG_WORD(®->semaphore, 0); break; case 0x12: qla2x00_async_event(ha, mbx); break; case 0x15: mbx = mbx << 16 | MBA_CMPLT_1_16BIT; qla2x00_async_event(ha, mbx); break; case 0x16: mbx = mbx << 16 | MBA_SCSI_COMPLETION; qla2x00_async_event(ha, mbx); break; default: hccr = RD_REG_WORD(®->hccr); if (hccr & HCCR_RISC_PAUSE) { qla_printk(KERN_INFO, ha, "RISC paused, dumping HCCR=%x\n", hccr); /* * Issue a "HARD" reset in order for * the RISC interrupt bit to be * cleared. Schedule a big hammmer to * get out of the RISC PAUSED state. */ WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); RD_REG_WORD(®->hccr); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; } else { DEBUG2(printk("scsi(%ld): Unrecognized " "interrupt type (%d)\n", ha->host_no, stat & 0xff)); } break; } WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); } } spin_unlock_irqrestore(&ha->hardware_lock, flags); qla2x00_next(ha); ha->last_irq_cpu = smp_processor_id(); ha->total_isr_cnt++; if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { /* There was a mailbox completion */ DEBUG3(printk("%s(%ld): Going to get mbx reg lock.\n", __func__, ha->host_no)); spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); if (ha->mcp == NULL) { DEBUG3(printk("%s(%ld): Error mbx pointer.\n", __func__, ha->host_no)); } else { DEBUG3(printk("%s(%ld): Going to set mbx intr flags. " "cmd=%x.\n", __func__, ha->host_no, ha->mcp->mb[0])); } set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); DEBUG3(printk("%s(%ld): Going to wake up mbx function for " "completion.\n", __func__, ha->host_no)); up(&ha->mbx_intr_sem); DEBUG3(printk("%s(%ld): Going to release mbx reg lock.\n", __func__, ha->host_no)); spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); } if (!list_empty(&ha->done_queue)) qla2x00_done(ha); /* Wakeup the DPC routine */ if ((!ha->flags.mbox_busy && (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))) && ha->dpc_wait && !ha->dpc_active) { up(ha->dpc_wait); } return (IRQ_HANDLED); }
/** * qla2x00_async_event() - Process aynchronous events. * @ha: SCSI driver HA context * @mb0: Mailbox0 register */ static void qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) { static char *link_speeds[5] = { "1", "2", "4", "?", "10" }; char *link_speed; uint16_t mb[4]; uint16_t handle_cnt; uint16_t cnt; uint32_t handles[5]; device_reg_t *reg = ha->iobase; uint32_t rscn_entry, host_pid; uint8_t rscn_queue_index; /* Setup to process RIO completion. */ handle_cnt = 0; mb[0] = LSW(mbx); switch (mb[0]) { case MBA_SCSI_COMPLETION: if (IS_QLA2100(ha) || IS_QLA2200(ha)) handles[0] = le32_to_cpu( ((uint32_t)(RD_MAILBOX_REG(ha, reg, 2) << 16)) | RD_MAILBOX_REG(ha, reg, 1)); else handles[0] = le32_to_cpu( ((uint32_t)(RD_MAILBOX_REG(ha, reg, 2) << 16)) | MSW(mbx)); handle_cnt = 1; break; case MBA_CMPLT_1_16BIT: if (IS_QLA2100(ha) || IS_QLA2200(ha)) handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1); else handles[0] = MSW(mbx); handle_cnt = 1; mb[0] = MBA_SCSI_COMPLETION; break; case MBA_CMPLT_2_16BIT: handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1); handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2); handle_cnt = 2; mb[0] = MBA_SCSI_COMPLETION; break; case MBA_CMPLT_3_16BIT: handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1); handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2); handles[2] = (uint32_t)RD_MAILBOX_REG(ha, reg, 3); handle_cnt = 3; mb[0] = MBA_SCSI_COMPLETION; break; case MBA_CMPLT_4_16BIT: handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1); handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2); handles[2] = (uint32_t)RD_MAILBOX_REG(ha, reg, 3); handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6); handle_cnt = 4; mb[0] = MBA_SCSI_COMPLETION; break; case MBA_CMPLT_5_16BIT: handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1); handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2); handles[2] = (uint32_t)RD_MAILBOX_REG(ha, reg, 3); handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6); handles[4] = (uint32_t)RD_MAILBOX_REG(ha, reg, 7); handle_cnt = 5; mb[0] = MBA_SCSI_COMPLETION; break; case MBA_CMPLT_2_32BIT: handles[0] = le32_to_cpu( ((uint32_t)(RD_MAILBOX_REG(ha, reg, 2) << 16)) | RD_MAILBOX_REG(ha, reg, 1)); handles[1] = le32_to_cpu( ((uint32_t)(RD_MAILBOX_REG(ha, reg, 7) << 16)) | RD_MAILBOX_REG(ha, reg, 6)); handle_cnt = 2; mb[0] = MBA_SCSI_COMPLETION; break; default: break; } mb[0] = LSW(mbx); switch (mb[0]) { case MBA_SCSI_COMPLETION: /* Fast Post */ if (!ha->flags.online) break; for (cnt = 0; cnt < handle_cnt; cnt++) qla2x00_process_completed_request(ha, handles[cnt]); break; case MBA_RESET: /* Reset */ DEBUG2(printk("scsi(%ld): Asynchronous RESET.\n", ha->host_no)); set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); break; case MBA_SYSTEM_ERR: /* System Error */ mb[1] = RD_MAILBOX_REG(ha, reg, 1); mb[2] = RD_MAILBOX_REG(ha, reg, 2); mb[3] = RD_MAILBOX_REG(ha, reg, 3); qla_printk(KERN_INFO, ha, "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n", mb[1], mb[2], mb[3]); if (IS_QLA2100(ha) || IS_QLA2200(ha)) qla2100_fw_dump(ha, 1); else qla2300_fw_dump(ha, 1); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */ DEBUG2(printk("scsi(%ld): ISP Request Transfer Error.\n", ha->host_no)); qla_printk(KERN_WARNING, ha, "ISP Request Transfer Error.\n"); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */ DEBUG2(printk("scsi(%ld): ISP Response Transfer Error.\n", ha->host_no)); qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n"); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ DEBUG2(printk("scsi(%ld): Asynchronous WAKEUP_THRES.\n", ha->host_no)); break; case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ mb[1] = RD_MAILBOX_REG(ha, reg, 1); DEBUG2(printk("scsi(%ld): LIP occured (%x).\n", ha->host_no, mb[1])); qla_printk(KERN_INFO, ha, "LIP occured (%x).\n", mb[1]); if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); qla2x00_mark_all_devices_lost(ha); } set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); ha->flags.management_server_logged_in = 0; /* Update AEN queue. */ qla2x00_enqueue_aen(ha, MBA_LIP_OCCURRED, NULL); ha->total_lip_cnt++; break; case MBA_LOOP_UP: /* Loop Up Event */ mb[1] = RD_MAILBOX_REG(ha, reg, 1); ha->link_data_rate = 0; if (IS_QLA2100(ha) || IS_QLA2200(ha)) { link_speed = link_speeds[0]; } else { link_speed = link_speeds[3]; if (mb[1] < 5) link_speed = link_speeds[mb[1]]; ha->link_data_rate = mb[1]; } DEBUG2(printk("scsi(%ld): Asynchronous LOOP UP (%s Gbps).\n", ha->host_no, link_speed)); qla_printk(KERN_INFO, ha, "LOOP UP detected (%s Gbps).\n", link_speed); ha->flags.management_server_logged_in = 0; /* Update AEN queue. */ qla2x00_enqueue_aen(ha, MBA_LOOP_UP, NULL); break; case MBA_LOOP_DOWN: /* Loop Down Event */ DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN.\n", ha->host_no)); qla_printk(KERN_INFO, ha, "LOOP DOWN detected.\n"); if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); ha->device_flags |= DFLG_NO_CABLE; qla2x00_mark_all_devices_lost(ha); } ha->flags.management_server_logged_in = 0; ha->link_data_rate = 0; /* Update AEN queue. */ qla2x00_enqueue_aen(ha, MBA_LOOP_DOWN, NULL); break; case MBA_LIP_RESET: /* LIP reset occurred */ mb[1] = RD_MAILBOX_REG(ha, reg, 1); DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n", ha->host_no, mb[1])); qla_printk(KERN_INFO, ha, "LIP reset occured (%x).\n", mb[1]); if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); qla2x00_mark_all_devices_lost(ha); } set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); ha->operating_mode = LOOP; ha->flags.management_server_logged_in = 0; /* Update AEN queue. */ qla2x00_enqueue_aen(ha, MBA_LIP_RESET, NULL); ha->total_lip_cnt++; break; case MBA_POINT_TO_POINT: /* Point-to-Point */ if (IS_QLA2100(ha)) break; DEBUG2(printk("scsi(%ld): Asynchronous P2P MODE received.\n", ha->host_no)); /* * Until there's a transition from loop down to loop up, treat * this as loop down only. */ if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); if (!atomic_read(&ha->loop_down_timer)) atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); qla2x00_mark_all_devices_lost(ha); } if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) { set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); } set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); break; case MBA_CHG_IN_CONNECTION: /* Change in connection mode */ if (IS_QLA2100(ha)) break; mb[1] = RD_MAILBOX_REG(ha, reg, 1); DEBUG2(printk("scsi(%ld): Asynchronous Change In Connection " "received.\n", ha->host_no)); qla_printk(KERN_INFO, ha, "Configuration change detected: value=%x.\n", mb[1]); if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); if (!atomic_read(&ha->loop_down_timer)) atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); qla2x00_mark_all_devices_lost(ha); } set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); break; case MBA_PORT_UPDATE: /* Port database update */ mb[1] = RD_MAILBOX_REG(ha, reg, 1); mb[2] = RD_MAILBOX_REG(ha, reg, 2); /* * If a single remote port just logged into (or logged out of) * us, create a new entry in our rscn fcports list and handle * the event like an RSCN. */ if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && !IS_QLA6322(ha) && ha->flags.init_done && mb[1] != 0xffff && ((ha->operating_mode == P2P && mb[1] != 0) || (ha->operating_mode != P2P && mb[1] != SNS_FIRST_LOOP_ID)) && (mb[2] == 6 || mb[2] == 7)) { int rval; fc_port_t *rscn_fcport; /* Create new fcport for login. */ rscn_fcport = qla2x00_alloc_rscn_fcport(ha, GFP_ATOMIC); if (rscn_fcport) { DEBUG14(printk("scsi(%ld): Port Update -- " "creating RSCN fcport %p for login.\n", ha->host_no, rscn_fcport)); rscn_fcport->loop_id = mb[1]; rscn_fcport->d_id.b24 = INVALID_PORT_ID; atomic_set(&rscn_fcport->state, FCS_DEVICE_LOST); list_add_tail(&rscn_fcport->list, &ha->rscn_fcports); rval = qla2x00_handle_port_rscn(ha, 0, rscn_fcport, 1); if (rval == QLA_SUCCESS) break; } else { DEBUG14(printk("scsi(%ld): Port Update -- " "-- unable to allocate RSCN fcport " "login.\n", ha->host_no)); } } /* * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET * event etc. earlier indicating loop is down) then process * it. Otherwise ignore it and Wait for RSCN to come in. */ if (atomic_read(&ha->loop_state) != LOOP_DOWN) { DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE " "ignored.\n", ha->host_no)); break; } DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n", ha->host_no)); DEBUG(printk(KERN_INFO "scsi(%ld): Port database changed %04x %04x.\n", ha->host_no, mb[1], mb[2])); /* * Mark all devices as missing so we will login again. */ atomic_set(&ha->loop_state, LOOP_UP); atomic_set(&ha->loop_down_timer, 0); qla2x00_mark_all_devices_lost(ha); ha->flags.rscn_queue_overflow = 1; set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); /* Update AEN queue. */ qla2x00_enqueue_aen(ha, MBA_PORT_UPDATE, NULL); break; case MBA_RSCN_UPDATE: /* State Change Registration */ mb[1] = RD_MAILBOX_REG(ha, reg, 1); mb[2] = RD_MAILBOX_REG(ha, reg, 2); DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", ha->host_no)); DEBUG(printk(KERN_INFO "scsi(%ld): RSCN database changed -- %04x %04x.\n", ha->host_no, mb[1], mb[2])); rscn_entry = (mb[1] << 16) | mb[2]; host_pid = (ha->d_id.b.domain << 16) | (ha->d_id.b.area << 8) | ha->d_id.b.al_pa; if (rscn_entry == host_pid) { DEBUG(printk(KERN_INFO "scsi(%ld): Ignoring RSCN update to local host " "port ID (%06x)\n", ha->host_no, host_pid)); break; } rscn_queue_index = ha->rscn_in_ptr + 1; if (rscn_queue_index == MAX_RSCN_COUNT) rscn_queue_index = 0; if (rscn_queue_index != ha->rscn_out_ptr) { ha->rscn_queue[ha->rscn_in_ptr] = rscn_entry; ha->rscn_in_ptr = rscn_queue_index; } else { ha->flags.rscn_queue_overflow = 1; } atomic_set(&ha->loop_state, LOOP_UPDATE); atomic_set(&ha->loop_down_timer, 0); ha->flags.management_server_logged_in = 0; set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); set_bit(RSCN_UPDATE, &ha->dpc_flags); /* Update AEN queue. */ qla2x00_enqueue_aen(ha, MBA_RSCN_UPDATE, &mb[0]); break; /* case MBA_RIO_RESPONSE: */ case MBA_ZIO_RESPONSE: DEBUG2(printk("scsi(%ld): [R|Z]IO update completion.\n", ha->host_no)); DEBUG(printk(KERN_INFO "scsi(%ld): [R|Z]IO update completion.\n", ha->host_no)); qla2x00_process_response_queue(ha); break; } }
/** * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. * @irq: * @dev_id: SCSI driver HA context * @regs: * * Called by system whenever the host adapter generates an interrupt. * * Returns handled flag. */ irqreturn_t qla24xx_intr_handler(int irq, void *dev_id, struct pt_regs *regs) { scsi_qla_host_t *ha; struct device_reg_24xx __iomem *reg; int status; unsigned long flags; unsigned long iter; uint32_t stat; uint32_t hccr; uint16_t mb[4]; ha = (scsi_qla_host_t *) dev_id; if (!ha) { printk(KERN_INFO "%s(): NULL host pointer\n", __func__); return IRQ_NONE; } reg = &ha->iobase->isp24; status = 0; spin_lock_irqsave(&ha->hardware_lock, flags); for (iter = 50; iter--; ) { stat = RD_REG_DWORD(®->host_status); if (stat & HSRX_RISC_PAUSED) { hccr = RD_REG_DWORD(®->hccr); qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " "Dumping firmware!\n", hccr); qla24xx_fw_dump(ha, 1); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; } else if ((stat & HSRX_RISC_INT) == 0) break; switch (stat & 0xff) { case 0x1: case 0x2: case 0x10: case 0x11: qla24xx_mbx_completion(ha, MSW(stat)); status |= MBX_INTERRUPT; break; case 0x12: mb[0] = MSW(stat); mb[1] = RD_REG_WORD(®->mailbox1); mb[2] = RD_REG_WORD(®->mailbox2); mb[3] = RD_REG_WORD(®->mailbox3); qla2x00_async_event(ha, mb); break; case 0x13: qla24xx_process_response_queue(ha); break; default: DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " "(%d).\n", ha->host_no, stat & 0xff)); break; } WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); RD_REG_DWORD_RELAXED(®->hccr); } spin_unlock_irqrestore(&ha->hardware_lock, flags); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { spin_lock_irqsave(&ha->mbx_reg_lock, flags); set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); up(&ha->mbx_intr_sem); spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); } return IRQ_HANDLED; }
/** * qla2300_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. * @irq: * @dev_id: SCSI driver HA context * @regs: * * Called by system whenever the host adapter generates an interrupt. * * Returns handled flag. */ irqreturn_t qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs) { scsi_qla_host_t *ha; struct device_reg_2xxx __iomem *reg; int status; unsigned long flags; unsigned long iter; uint32_t stat; uint16_t hccr; uint16_t mb[4]; ha = (scsi_qla_host_t *) dev_id; if (!ha) { printk(KERN_INFO "%s(): NULL host pointer\n", __func__); return (IRQ_NONE); } reg = &ha->iobase->isp; status = 0; spin_lock_irqsave(&ha->hardware_lock, flags); for (iter = 50; iter--; ) { stat = RD_REG_DWORD(®->u.isp2300.host_status); if (stat & HSR_RISC_PAUSED) { hccr = RD_REG_WORD(®->hccr); if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8)) qla_printk(KERN_INFO, ha, "Parity error -- HCCR=%x.\n", hccr); else qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x.\n", hccr); /* * Issue a "HARD" reset in order for the RISC * interrupt bit to be cleared. Schedule a big * hammmer to get out of the RISC PAUSED state. */ WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); RD_REG_WORD(®->hccr); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; } else if ((stat & HSR_RISC_INT) == 0) break; switch (stat & 0xff) { case 0x1: case 0x2: case 0x10: case 0x11: qla2x00_mbx_completion(ha, MSW(stat)); status |= MBX_INTERRUPT; /* Release mailbox registers. */ WRT_REG_WORD(®->semaphore, 0); break; case 0x12: mb[0] = MSW(stat); mb[1] = RD_MAILBOX_REG(ha, reg, 1); mb[2] = RD_MAILBOX_REG(ha, reg, 2); mb[3] = RD_MAILBOX_REG(ha, reg, 3); qla2x00_async_event(ha, mb); break; case 0x13: qla2x00_process_response_queue(ha); break; case 0x15: mb[0] = MBA_CMPLT_1_16BIT; mb[1] = MSW(stat); qla2x00_async_event(ha, mb); break; case 0x16: mb[0] = MBA_SCSI_COMPLETION; mb[1] = MSW(stat); mb[2] = RD_MAILBOX_REG(ha, reg, 2); qla2x00_async_event(ha, mb); break; default: DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " "(%d).\n", ha->host_no, stat & 0xff)); break; } WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD_RELAXED(®->hccr); } spin_unlock_irqrestore(&ha->hardware_lock, flags); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { spin_lock_irqsave(&ha->mbx_reg_lock, flags); set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); up(&ha->mbx_intr_sem); spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); } return (IRQ_HANDLED); }
TIEXPORT3 int TICALL dusb_send_data(CalcHandle *handle, DUSBVirtualPacket *vtl) { DUSBRawPacket raw; int i, r, q; long offset; int ret; VALIDATE_HANDLE(handle); VALIDATE_NONNULL(vtl); if (vtl->size && !vtl->data) { return ERR_INVALID_PARAMETER; } memset(&raw, 0, sizeof(raw)); do { if (vtl->size <= handle->priv.dusb_rpkt_maxlen - DUSB_DH_SIZE) { // we have a single packet which is the last one, too raw.size = vtl->size + DUSB_DH_SIZE; raw.type = DUSB_RPKT_VIRT_DATA_LAST; raw.data[0] = MSB(MSW(vtl->size)); raw.data[1] = LSB(MSW(vtl->size)); raw.data[2] = MSB(LSW(vtl->size)); raw.data[3] = LSB(LSW(vtl->size)); raw.data[4] = MSB(vtl->type); raw.data[5] = LSB(vtl->type); if (vtl->data) { memcpy(&raw.data[DUSB_DH_SIZE], vtl->data, vtl->size); } ret = dusb_send(handle, &raw); if (ret) { break; } #if (VPKT_DBG == 2) ticalcs_info(" PC->TI: Virtual Packet Data Final\n\t\t(size = %08x, type = %s)", vtl->size, dusb_vpkt_type2name(vtl->type)); #elif (VPKT_DBG == 1) ticalcs_info(" PC->TI: %s", dusb_vpkt_type2name(vtl->type)); #endif workaround_send(handle, &raw, vtl); ret = dusb_recv_acknowledge(handle); if (ret) { break; } } else { // we have more than one packet: first packet has data header raw.size = handle->priv.dusb_rpkt_maxlen; raw.type = DUSB_RPKT_VIRT_DATA; raw.data[0] = MSB(MSW(vtl->size)); raw.data[1] = LSB(MSW(vtl->size)); raw.data[2] = MSB(LSW(vtl->size)); raw.data[3] = LSB(LSW(vtl->size)); raw.data[4] = MSB(vtl->type); raw.data[5] = LSB(vtl->type); memcpy(&raw.data[DUSB_DH_SIZE], vtl->data, handle->priv.dusb_rpkt_maxlen - DUSB_DH_SIZE); offset = handle->priv.dusb_rpkt_maxlen - DUSB_DH_SIZE; ret = dusb_send(handle, &raw); if (ret) { break; } #if (VPKT_DBG == 2) ticalcs_info(" PC->TI: Virtual Packet Data with Continuation\n\t\t(size = %08x, type = %s)", vtl->size, dusb_vpkt_type2name(vtl->type)); #elif (VPKT_DBG == 1) ticalcs_info(" PC->TI: %s", dusb_vpkt_type2name(vtl->type)); #endif ret = dusb_recv_acknowledge(handle); if (ret) { break; } // other packets doesn't have data header but last one has a different type q = (vtl->size - offset) / handle->priv.dusb_rpkt_maxlen; r = (vtl->size - offset) % handle->priv.dusb_rpkt_maxlen; // send full chunks (no header) for (i = 1; i <= q; i++) { raw.size = handle->priv.dusb_rpkt_maxlen; raw.type = DUSB_RPKT_VIRT_DATA; memcpy(raw.data, vtl->data + offset, handle->priv.dusb_rpkt_maxlen); offset += handle->priv.dusb_rpkt_maxlen; ret = dusb_send(handle, &raw); if (ret) { goto end; } #if (VPKT_DBG == 2) ticalcs_info(" PC->TI: Virtual Packet Data with Continuation"); #endif ret = dusb_recv_acknowledge(handle); if (ret) { goto end; } handle->updat->max1 = vtl->size; handle->updat->cnt1 += handle->priv.dusb_rpkt_maxlen; handle->updat->pbar(); } // send last chunk (type) raw.size = r; raw.type = DUSB_RPKT_VIRT_DATA_LAST; memcpy(raw.data, vtl->data + offset, r); offset += r; ret = dusb_send(handle, &raw); if (ret) { break; } #if (VPKT_DBG == 2) ticalcs_info(" PC->TI: Virtual Packet Data Final"); #endif // XXX is that workaround necessary on 83PCE/84+CE/84+CE-T ? if (handle->model != CALC_TI84P_USB && handle->model != CALC_TI84PC_USB && handle->model != CALC_TI82A_USB && handle->model != CALC_TI84PT_USB) { workaround_send(handle, &raw, vtl); } ret = dusb_recv_acknowledge(handle); if (ret) { break; } } } while(0); end: return ret; }
void io3_put_long(uint32_t addr, uint32_t arg) { io3_put_word(addr, MSW(arg)); io3_put_word(addr+2, LSW(arg)); }
TIEXPORT3 int TICALL dusb_send_data(CalcHandle *h, DUSBVirtualPacket *vtl) { DUSBRawPacket raw; int i, r, q; long offset; if (h == NULL) { ticalcs_critical("%s: h is NULL", __FUNCTION__); return ERR_INVALID_HANDLE; } if (vtl == NULL) { ticalcs_critical("%s: vtl is NULL", __FUNCTION__); return ERR_INVALID_PACKET; } memset(&raw, 0, sizeof(raw)); if(vtl->size <= DATA_SIZE - DUSB_DH_SIZE) { // we have a single packet which is the last one, too raw.size = vtl->size + DUSB_DH_SIZE; raw.type = DUSB_RPKT_VIRT_DATA_LAST; raw.data[0] = MSB(MSW(vtl->size)); raw.data[1] = LSB(MSW(vtl->size)); raw.data[2] = MSB(LSW(vtl->size)); raw.data[3] = LSB(LSW(vtl->size)); raw.data[4] = MSB(vtl->type); raw.data[5] = LSB(vtl->type); memcpy(&raw.data[DUSB_DH_SIZE], vtl->data, vtl->size); TRYF(dusb_send(h, &raw)); #if (VPKT_DBG == 2) ticalcs_info(" PC->TI: Virtual Packet Data Final\n\t\t(size = %08x, type = %s)", vtl->size, dusb_vpkt_type2name(vtl->type)); #elif (VPKT_DBG == 1) ticalcs_info(" PC->TI: %s", dusb_vpkt_type2name(vtl->type)); #endif workaround_send(h, &raw, vtl); TRYF(dusb_recv_acknowledge(h)); } else { // we have more than one packet: first packet has data header raw.size = DATA_SIZE; raw.type = DUSB_RPKT_VIRT_DATA; raw.data[0] = MSB(MSW(vtl->size)); raw.data[1] = LSB(MSW(vtl->size)); raw.data[2] = MSB(LSW(vtl->size)); raw.data[3] = LSB(LSW(vtl->size)); raw.data[4] = MSB(vtl->type); raw.data[5] = LSB(vtl->type); memcpy(&raw.data[DUSB_DH_SIZE], vtl->data, DATA_SIZE - DUSB_DH_SIZE); offset = DATA_SIZE - DUSB_DH_SIZE; TRYF(dusb_send(h, &raw)); #if (VPKT_DBG == 2) ticalcs_info(" PC->TI: Virtual Packet Data with Continuation\n\t\t(size = %08x, type = %s)", vtl->size, dusb_vpkt_type2name(vtl->type)); #elif (VPKT_DBG == 1) ticalcs_info(" PC->TI: %s", dusb_vpkt_type2name(vtl->type)); #endif //workaround_send(h, &raw, vtl); TRYF(dusb_recv_acknowledge(h)); // other packets doesn't have data header but last one has a different type q = (vtl->size - offset) / DATA_SIZE; r = (vtl->size - offset) % DATA_SIZE; // send full chunks (no header) for(i = 1; i <= q; i++) { raw.size = DATA_SIZE; raw.type = DUSB_RPKT_VIRT_DATA; memcpy(raw.data, vtl->data + offset, DATA_SIZE); offset += DATA_SIZE; TRYF(dusb_send(h, &raw)); #if (VPKT_DBG == 2) ticalcs_info(" PC->TI: Virtual Packet Data with Continuation"); #endif TRYF(dusb_recv_acknowledge(h)); h->updat->max1 = vtl->size; h->updat->cnt1 += DATA_SIZE; h->updat->pbar(); } // send last chunk (type) //if(r) { raw.size = r; raw.type = DUSB_RPKT_VIRT_DATA_LAST; memcpy(raw.data, vtl->data + offset, r); offset += r; TRYF(dusb_send(h, &raw)); #if (VPKT_DBG == 2) ticalcs_info(" PC->TI: Virtual Packet Data Final"); #endif if (h->model != CALC_TI84P_USB) { workaround_send(h, &raw, vtl); } TRYF(dusb_recv_acknowledge(h)); } } return 0; }