⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ueagle-atm.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
					"with error %d\n", ret);			goto err;		}		pfw += len + 3;	}	if (size != 0)		goto err_fw_corrupted;	/*	 * Tell the modem we finish : de-assert reset	 */	value = 0;	ret = uea_send_modem_cmd(usb, F8051_USBCS, 1, &value);	if (ret < 0)		uea_err(usb, "modem de-assert failed with error %d\n", ret);	else		uea_info(usb, "firmware uploaded\n");	uea_leaves(usb);	return;err_fw_corrupted:	uea_err(usb, "firmware is corrupted\n");err:	uea_leaves(usb);}/** * uea_load_firmware - Load usb firmware for pre-firmware devices. */static int uea_load_firmware(struct usb_device *usb, unsigned int ver){	int ret;	char *fw_name = FW_DIR "eagle.fw";	uea_enters(usb);	uea_info(usb, "pre-firmware device, uploading firmware\n");	switch (ver) {	case ADI930:		fw_name = FW_DIR "adi930.fw";		break;	case EAGLE_I:		fw_name = FW_DIR "eagleI.fw";		break;	case EAGLE_II:		fw_name = FW_DIR "eagleII.fw";		break;	case EAGLE_III:		fw_name = FW_DIR "eagleIII.fw";		break;	}	ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware);	if (ret)		uea_err(usb, "firmware %s is not available\n", fw_name);	else		uea_info(usb, "loading firmware %s\n", fw_name);	uea_leaves(usb);	return ret;}/* modem management : dsp firmware, send/read CMV, monitoring statistic *//* * Make sure that the DSP code provided is safe to use. */static int check_dsp(u8 *dsp, unsigned int len){	u8 pagecount, blockcount;	u16 blocksize;	u32 pageoffset;	unsigned int i, j, p, pp;	pagecount = FW_GET_BYTE(dsp);	p = 1;	/* enough space for page offsets? */	if (p + 4 * pagecount > len)		return 1;	for (i = 0; i < pagecount; i++) {		pageoffset = FW_GET_LONG(dsp + p);		p += 4;		if (pageoffset == 0)			continue;		/* enough space for blockcount? */		if (pageoffset >= len)			return 1;		pp = pageoffset;		blockcount = FW_GET_BYTE(dsp + pp);		pp += 1;		for (j = 0; j < blockcount; j++) {			/* enough space for block header? */			if (pp + 4 > len)				return 1;			pp += 2;	/* skip blockaddr */			blocksize = FW_GET_WORD(dsp + pp);			pp += 2;			/* enough space for block data? */			if (pp + blocksize > len)				return 1;			pp += blocksize;		}	}	return 0;}/* * send data to the idma pipe * */static int uea_idma_write(struct uea_softc *sc, void *data, u32 size){	int ret = -ENOMEM;	u8 *xfer_buff;	int bytes_read;	xfer_buff = kmalloc(size, GFP_KERNEL);	if (!xfer_buff) {		uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");		return ret;	}	memcpy(xfer_buff, data, size);	ret = usb_bulk_msg(sc->usb_dev,			 usb_sndbulkpipe(sc->usb_dev, UEA_IDMA_PIPE),			 xfer_buff, size, &bytes_read, BULK_TIMEOUT);	kfree(xfer_buff);	if (ret < 0)		return ret;	if (size != bytes_read) {		uea_err(INS_TO_USBDEV(sc), "size != bytes_read %d %d\n", size,		       bytes_read);		return -EIO;	}	return 0;}static int request_dsp(struct uea_softc *sc){	int ret;	char *dsp_name;	if (UEA_CHIP_VERSION(sc) == ADI930) {		if (IS_ISDN(sc))			dsp_name = FW_DIR "DSP9i.bin";		else			dsp_name = FW_DIR "DSP9p.bin";	} else {		if (IS_ISDN(sc))			dsp_name = FW_DIR "DSPei.bin";		else			dsp_name = FW_DIR "DSPep.bin";	}	ret = request_firmware(&sc->dsp_firm, dsp_name, &sc->usb_dev->dev);	if (ret < 0) {		uea_err(INS_TO_USBDEV(sc),		       "requesting firmware %s failed with error %d\n",		       dsp_name, ret);		return ret;	}	if (check_dsp(sc->dsp_firm->data, sc->dsp_firm->size)) {		uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n",		       dsp_name);		release_firmware(sc->dsp_firm);		sc->dsp_firm = NULL;		return -EILSEQ;	}	return 0;}/* * The uea_load_page() function must be called within a process context */static void uea_load_page(void *xsc){	struct uea_softc *sc = xsc;	u16 pageno = sc->pageno;	u16 ovl = sc->ovl;	struct block_info bi;	u8 *p;	u8 pagecount, blockcount;	u16 blockaddr, blocksize;	u32 pageoffset;	int i;	/* reload firmware when reboot start and it's loaded already */	if (ovl == 0 && pageno == 0 && sc->dsp_firm) {		release_firmware(sc->dsp_firm);		sc->dsp_firm = NULL;	}	if (sc->dsp_firm == NULL && request_dsp(sc) < 0)		return;	p = sc->dsp_firm->data;	pagecount = FW_GET_BYTE(p);	p += 1;	if (pageno >= pagecount)		goto bad1;	p += 4 * pageno;	pageoffset = FW_GET_LONG(p);	if (pageoffset == 0)		goto bad1;	p = sc->dsp_firm->data + pageoffset;	blockcount = FW_GET_BYTE(p);	p += 1;	uea_dbg(INS_TO_USBDEV(sc),	       "sending %u blocks for DSP page %u\n", blockcount, pageno);	bi.wHdr = cpu_to_le16(UEA_BIHDR);	bi.wOvl = cpu_to_le16(ovl);	bi.wOvlOffset = cpu_to_le16(ovl | 0x8000);	for (i = 0; i < blockcount; i++) {		blockaddr = FW_GET_WORD(p);		p += 2;		blocksize = FW_GET_WORD(p);		p += 2;		bi.wSize = cpu_to_le16(blocksize);		bi.wAddress = cpu_to_le16(blockaddr);		bi.wLast = cpu_to_le16((i == blockcount - 1) ? 1 : 0);		/* send block info through the IDMA pipe */		if (uea_idma_write(sc, &bi, BLOCK_INFO_SIZE))			goto bad2;		/* send block data through the IDMA pipe */		if (uea_idma_write(sc, p, blocksize))			goto bad2;		p += blocksize;	}	return;bad2:	uea_err(INS_TO_USBDEV(sc), "sending DSP block %u failed\n", i);	return;bad1:	uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno);}static inline void wake_up_cmv_ack(struct uea_softc *sc){	BUG_ON(sc->cmv_ack);	sc->cmv_ack = 1;	wake_up(&sc->cmv_ack_wait);}static inline int wait_cmv_ack(struct uea_softc *sc){	int ret = wait_event_timeout(sc->cmv_ack_wait,						   sc->cmv_ack, ACK_TIMEOUT);	sc->cmv_ack = 0;	uea_dbg(INS_TO_USBDEV(sc), "wait_event_timeout : %d ms\n",			jiffies_to_msecs(ret));	if (ret < 0)		return ret;	return (ret == 0) ? -ETIMEDOUT : 0;}#define UCDC_SEND_ENCAPSULATED_COMMAND 0x00static int uea_request(struct uea_softc *sc,		u16 value, u16 index, u16 size, void *data){	u8 *xfer_buff;	int ret = -ENOMEM;	xfer_buff = kmalloc(size, GFP_KERNEL);	if (!xfer_buff) {		uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");		return ret;	}	memcpy(xfer_buff, data, size);	ret = usb_control_msg(sc->usb_dev, usb_sndctrlpipe(sc->usb_dev, 0),			      UCDC_SEND_ENCAPSULATED_COMMAND,			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,			      value, index, xfer_buff, size, CTRL_TIMEOUT);	kfree(xfer_buff);	if (ret < 0) {		uea_err(INS_TO_USBDEV(sc), "usb_control_msg error %d\n", ret);		return ret;	}	if (ret != size) {		uea_err(INS_TO_USBDEV(sc),		       "usb_control_msg send only %d bytes (instead of %d)\n",		       ret, size);		return -EIO;	}	return 0;}static int uea_cmv(struct uea_softc *sc,		u8 function, u32 address, u16 offset, u32 data){	struct cmv cmv;	int ret;	uea_enters(INS_TO_USBDEV(sc));	uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, "			"offset : 0x%04x, data : 0x%08x\n",			FUNCTION_TYPE(function), FUNCTION_SUBTYPE(function),			GETSA1(address), GETSA2(address), GETSA3(address),			GETSA4(address), offset, data);	/* we send a request, but we expect a reply */	sc->cmv_function = function | 0x2;	sc->cmv_idx++;	sc->cmv_address = address;	sc->cmv_offset = offset;	cmv.wPreamble = cpu_to_le16(PREAMBLE);	cmv.bDirection = HOSTTOMODEM;	cmv.bFunction = function;	cmv.wIndex = cpu_to_le16(sc->cmv_idx);	put_unaligned(cpu_to_le32(address), &cmv.dwSymbolicAddress);	cmv.wOffsetAddress = cpu_to_le16(offset);	put_unaligned(cpu_to_le32(data >> 16 | data << 16), &cmv.dwData);	ret = uea_request(sc, UEA_SET_BLOCK, UEA_MPTX_START, CMV_SIZE, &cmv);	if (ret < 0)		return ret;	ret = wait_cmv_ack(sc);	uea_leaves(INS_TO_USBDEV(sc));	return ret;}static inline int uea_read_cmv(struct uea_softc *sc,		u32 address, u16 offset, u32 *data){	int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTREAD),			  address, offset, 0);	if (ret < 0)		uea_err(INS_TO_USBDEV(sc),			"reading cmv failed with error %d\n", ret);	else	 	*data = sc->data;	return ret;}static inline int uea_write_cmv(struct uea_softc *sc,		u32 address, u16 offset, u32 data){	int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTWRITE),			  address, offset, data);	if (ret < 0)		uea_err(INS_TO_USBDEV(sc),			"writing cmv failed with error %d\n", ret);	return ret;}/* * Monitor the modem and update the stat * return 0 if everything is ok * return < 0 if an error occurs (-EAGAIN reboot needed) */static int uea_stat(struct uea_softc *sc){	u32 data;	int ret;	uea_enters(INS_TO_USBDEV(sc));	data = sc->stats.phy.state;	ret = uea_read_cmv(sc, SA_STAT, 0, &sc->stats.phy.state);	if (ret < 0)		return ret;	switch (GET_STATUS(sc->stats.phy.state)) {	case 0:		/* not yet synchronized */		uea_dbg(INS_TO_USBDEV(sc),		       "modem not yet synchronized\n");		return 0;	case 1:		/* initialization */		uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n");		return 0;	case 2:		/* operational */		uea_vdbg(INS_TO_USBDEV(sc), "modem operational\n");		break;	case 3:		/* fail ... */		uea_info(INS_TO_USBDEV(sc), "modem synchronization failed\n");		return -EAGAIN;	case 4 ... 6:	/* test state */		uea_warn(INS_TO_USBDEV(sc),				"modem in test mode - not supported\n");		return -EAGAIN;	case 7:		/* fast-retain ... */		uea_info(INS_TO_USBDEV(sc), "modem in fast-retain mode\n");		return 0;	default:		uea_err(INS_TO_USBDEV(sc), "modem invalid SW mode %d\n",			GET_STATUS(sc->stats.phy.state));		return -EAGAIN;	}	if (GET_STATUS(data) != 2) {		uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_OFF, 0, NULL);		uea_info(INS_TO_USBDEV(sc), "modem operational\n");		/* release the dsp firmware as it is not needed until		 * the next failure		 */		if (sc->dsp_firm) {			release_firmware(sc->dsp_firm);			sc->dsp_firm = NULL;		}		ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid);		if (ret < 0)			return ret;		uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n",				sc->stats.phy.firmid);	}	/* always update it as atm layer could not be init when we switch to	 * operational state	 */	UPDATE_ATM_STAT(signal, ATM_PHY_SIG_FOUND);	/* wake up processes waiting for synchronization */	wake_up(&sc->sync_q);	ret = uea_read_cmv(sc, SA_DIAG, 2, &sc->stats.phy.flags);	if (ret < 0)		return ret;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -