예제 #1
0
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;
}
예제 #2
0
파일: dusb_cmd.c 프로젝트: TC01/tilibs
// 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;
}
예제 #3
0
파일: cmd68k.c 프로젝트: TC01/tilibs
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);
}
예제 #4
0
파일: cmd68k.c 프로젝트: TC01/tilibs
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);
}
예제 #5
0
파일: cmd68k.c 프로젝트: TC01/tilibs
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);
}
예제 #6
0
파일: gpif.c 프로젝트: Bobzikwick/fx2lib
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));
}
예제 #7
0
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;
}
예제 #8
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;
}
예제 #9
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;
}
예제 #10
0
파일: cmd68k.c 프로젝트: TC01/tilibs
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);
}
예제 #11
0
/* 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);
}
예제 #12
0
파일: dusb_rpkt.c 프로젝트: TC01/tilibs
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;
}
예제 #13
0
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;
}
예제 #14
0
파일: dusb_cmd.c 프로젝트: TC01/tilibs
// 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;
}
예제 #15
0
파일: cmd89.c 프로젝트: tobiasBora/emacs_ti
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;
}
예제 #16
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;
}
예제 #17
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;
}
예제 #18
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;
}
예제 #19
0
파일: cmd89.c 프로젝트: tobiasBora/emacs_ti
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;
}
예제 #20
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;
}
예제 #21
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;
}
예제 #22
0
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;
        }
    }
예제 #23
0
/**
 * 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(&reg->hccr);

	/* Pause RISC. */
	WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC); 
	if (IS_QLA2300(ha)) {
		for (cnt = 30000;
		    (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
			rval == QLA_SUCCESS; cnt--) {
			if (cnt)
				udelay(100);
			else
				rval = QLA_FUNCTION_TIMEOUT;
		}
	} else {
		RD_REG_WORD(&reg->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(&reg->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(&reg->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(&reg->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(&reg->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(&reg->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(&reg->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(&reg->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(&reg->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(&reg->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(&reg->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(&reg->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(&reg->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(&reg->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(&reg->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(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
		for (cnt = 0; cnt < 30000; cnt++) {
			if ((RD_REG_WORD(&reg->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(&reg->hccr, HCCR_SET_HOST_INT);

		for (timer = 6000000; timer; timer--) {
			/* Check for pending interrupts. */
 			stat = RD_REG_DWORD(&reg->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(&reg->semaphore, 0);
					WRT_REG_WORD(&reg->hccr,
					    HCCR_CLR_RISC_INT);
					RD_REG_WORD(&reg->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(&reg->hccr,
					    HCCR_CLR_RISC_INT);
					RD_REG_WORD(&reg->hccr);
					break;
				}

				/* clear this intr; it wasn't a mailbox intr */
				WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
				RD_REG_WORD(&reg->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(&reg->hccr, HCCR_SET_HOST_INT);

		for (timer = 6000000; timer; timer--) {
			/* Check for pending interrupts. */
 			stat = RD_REG_DWORD(&reg->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(&reg->semaphore, 0);
					WRT_REG_WORD(&reg->hccr,
					    HCCR_CLR_RISC_INT);
					RD_REG_WORD(&reg->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(&reg->hccr,
					    HCCR_CLR_RISC_INT);
					RD_REG_WORD(&reg->hccr);
					break;
				}

				/* clear this intr; it wasn't a mailbox intr */
				WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
				RD_REG_WORD(&reg->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(&reg->hccr, HCCR_SET_HOST_INT);

		for (timer = 6000000; timer; timer--) {
			/* Check for pending interrupts. */
 			stat = RD_REG_DWORD(&reg->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(&reg->semaphore, 0);
					WRT_REG_WORD(&reg->hccr,
					    HCCR_CLR_RISC_INT);
					RD_REG_WORD(&reg->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(&reg->hccr,
					    HCCR_CLR_RISC_INT);
					RD_REG_WORD(&reg->hccr);
					break;
				}

				/* clear this intr; it wasn't a mailbox intr */
				WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
				RD_REG_WORD(&reg->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);
}
예제 #24
0
파일: qla_isr.c 프로젝트: wxlong/Test
/**
 * 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(&reg->istatus) & ISR_RISC_INT) == 0)
				break;

			if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
				WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
				RD_REG_WORD(&reg->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(&reg->semaphore, 0);
				/* Workaround for ISP2100 chip. */
				if (IS_QLA2100(ha))
					RD_REG_WORD(&reg->semaphore);
			} else {
				qla2x00_process_response_queue(ha);
	
				WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
				RD_REG_WORD(&reg->hccr);
			}
		} else /* IS_QLA23XX(ha) */ {
			stat = RD_REG_DWORD(&reg->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(&reg->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(&reg->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(&reg->hccr,
					    HCCR_RESET_RISC);
					RD_REG_WORD(&reg->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(&reg->hccr, HCCR_CLR_RISC_INT);
			RD_REG_WORD(&reg->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);
}
예제 #25
0
파일: qla_isr.c 프로젝트: wxlong/Test
/**
 * 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;
	}
}
예제 #26
0
/**
 * 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(&reg->host_status);
		if (stat & HSRX_RISC_PAUSED) {
			hccr = RD_REG_DWORD(&reg->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(&reg->mailbox1);
			mb[2] = RD_REG_WORD(&reg->mailbox2);
			mb[3] = RD_REG_WORD(&reg->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(&reg->hccr, HCCRX_CLR_RISC_INT);
		RD_REG_DWORD_RELAXED(&reg->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;
}
예제 #27
0
/**
 * 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(&reg->u.isp2300.host_status);
		if (stat & HSR_RISC_PAUSED) {
			hccr = RD_REG_WORD(&reg->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(&reg->hccr, HCCR_RESET_RISC);
			RD_REG_WORD(&reg->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(&reg->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(&reg->hccr, HCCR_CLR_RISC_INT);
		RD_REG_WORD_RELAXED(&reg->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);
}
예제 #28
0
파일: dusb_vpkt.c 프로젝트: TC01/tilibs
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;
}
예제 #29
0
파일: ports.c 프로젝트: debrouxl/tiemu
void io3_put_long(uint32_t addr, uint32_t arg) 
{
    io3_put_word(addr,   MSW(arg));
    io3_put_word(addr+2, LSW(arg));
}
예제 #30
0
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;
}