|
@@ -1517,125 +1517,133 @@ exit_failure:
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
-int ft1000_poll(void* dev_id)
|
|
|
+int ft1000_poll(void *dev_id)
|
|
|
{
|
|
|
- struct ft1000_usb *dev = (struct ft1000_usb *)dev_id;
|
|
|
+ struct ft1000_usb *dev = (struct ft1000_usb *)dev_id;
|
|
|
struct ft1000_info *info = netdev_priv(dev->net);
|
|
|
+ u16 tempword;
|
|
|
+ int status;
|
|
|
+ u16 size;
|
|
|
+ int i;
|
|
|
+ u16 data;
|
|
|
+ u16 modulo;
|
|
|
+ u16 portid;
|
|
|
|
|
|
- u16 tempword;
|
|
|
- int status;
|
|
|
- u16 size;
|
|
|
- int i;
|
|
|
- u16 data;
|
|
|
- u16 modulo;
|
|
|
- u16 portid;
|
|
|
-
|
|
|
- if (ft1000_chkcard(dev) == FALSE) {
|
|
|
- DEBUG("ft1000_poll::ft1000_chkcard: failed\n");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- status = ft1000_read_register (dev, &tempword, FT1000_REG_DOORBELL);
|
|
|
-
|
|
|
- if ( !status )
|
|
|
- {
|
|
|
-
|
|
|
- if (tempword & FT1000_DB_DPRAM_RX) {
|
|
|
-
|
|
|
- status = ft1000_read_dpram16(dev, 0x200, (u8 *)&data, 0);
|
|
|
- size = ntohs(data) + 16 + 2;
|
|
|
- if (size % 4) {
|
|
|
- modulo = 4 - (size % 4);
|
|
|
- size = size + modulo;
|
|
|
- }
|
|
|
- status = ft1000_read_dpram16(dev, 0x201, (u8 *)&portid, 1);
|
|
|
- portid &= 0xff;
|
|
|
-
|
|
|
- if (size < MAX_CMD_SQSIZE) {
|
|
|
- switch (portid)
|
|
|
- {
|
|
|
- case DRIVERID:
|
|
|
- DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX : portid DRIVERID\n");
|
|
|
-
|
|
|
- status = ft1000_proc_drvmsg (dev, size);
|
|
|
- if (status != 0 )
|
|
|
- return status;
|
|
|
- break;
|
|
|
- case DSPBCMSGID:
|
|
|
- status = dsp_broadcast_msg_id(dev);
|
|
|
- break;
|
|
|
- default:
|
|
|
- status = handle_misc_portid(dev);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- DEBUG("FT1000:dpc:Invalid total length for SlowQ = %d\n", size);
|
|
|
- }
|
|
|
- status = ft1000_write_register (dev, FT1000_DB_DPRAM_RX, FT1000_REG_DOORBELL);
|
|
|
- }
|
|
|
- else if (tempword & FT1000_DSP_ASIC_RESET) {
|
|
|
-
|
|
|
- // Let's reset the ASIC from the Host side as well
|
|
|
- status = ft1000_write_register (dev, ASIC_RESET_BIT, FT1000_REG_RESET);
|
|
|
- status = ft1000_read_register (dev, &tempword, FT1000_REG_RESET);
|
|
|
- i = 0;
|
|
|
- while (tempword & ASIC_RESET_BIT) {
|
|
|
- status = ft1000_read_register (dev, &tempword, FT1000_REG_RESET);
|
|
|
- msleep(10);
|
|
|
- i++;
|
|
|
- if (i==100)
|
|
|
- break;
|
|
|
- }
|
|
|
- if (i==100) {
|
|
|
- DEBUG("Unable to reset ASIC\n");
|
|
|
- return 0;
|
|
|
- }
|
|
|
- msleep(10);
|
|
|
- // Program WMARK register
|
|
|
- status = ft1000_write_register (dev, 0x600, FT1000_REG_MAG_WATERMARK);
|
|
|
- // clear ASIC reset doorbell
|
|
|
- status = ft1000_write_register (dev, FT1000_DSP_ASIC_RESET, FT1000_REG_DOORBELL);
|
|
|
- msleep(10);
|
|
|
- }
|
|
|
- else if (tempword & FT1000_ASIC_RESET_REQ) {
|
|
|
- DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_ASIC_RESET_REQ\n");
|
|
|
-
|
|
|
- // clear ASIC reset request from DSP
|
|
|
- status = ft1000_write_register (dev, FT1000_ASIC_RESET_REQ, FT1000_REG_DOORBELL);
|
|
|
- status = ft1000_write_register (dev, HOST_INTF_BE, FT1000_REG_SUP_CTRL);
|
|
|
- // copy dsp session record from Adapter block
|
|
|
- status = ft1000_write_dpram32 (dev, 0, (u8 *)&info->DSPSess.Rec[0], 1024);
|
|
|
- // Program WMARK register
|
|
|
- status = ft1000_write_register (dev, 0x600, FT1000_REG_MAG_WATERMARK);
|
|
|
- // ring doorbell to tell DSP that ASIC is out of reset
|
|
|
- status = ft1000_write_register (dev, FT1000_ASIC_RESET_DSP, FT1000_REG_DOORBELL);
|
|
|
- }
|
|
|
- else if (tempword & FT1000_DB_COND_RESET) {
|
|
|
- DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_COND_RESET\n");
|
|
|
-
|
|
|
- if (!dev->fAppMsgPend) {
|
|
|
- // Reset ASIC and DSP
|
|
|
-
|
|
|
- status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER0, (u8 *)&(info->DSP_TIME[0]), FT1000_MAG_DSP_TIMER0_INDX);
|
|
|
- status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER1, (u8 *)&(info->DSP_TIME[1]), FT1000_MAG_DSP_TIMER1_INDX);
|
|
|
- status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER2, (u8 *)&(info->DSP_TIME[2]), FT1000_MAG_DSP_TIMER2_INDX);
|
|
|
- status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER3, (u8 *)&(info->DSP_TIME[3]), FT1000_MAG_DSP_TIMER3_INDX);
|
|
|
- info->CardReady = 0;
|
|
|
- info->DrvErrNum = DSP_CONDRESET_INFO;
|
|
|
- DEBUG("ft1000_hw:DSP conditional reset requested\n");
|
|
|
- info->ft1000_reset(dev->net);
|
|
|
- }
|
|
|
- else {
|
|
|
- dev->fProvComplete = false;
|
|
|
- dev->fCondResetPend = true;
|
|
|
- }
|
|
|
-
|
|
|
- ft1000_write_register(dev, FT1000_DB_COND_RESET, FT1000_REG_DOORBELL);
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-
|
|
|
+ if (ft1000_chkcard(dev) == FALSE) {
|
|
|
+ DEBUG("ft1000_poll::ft1000_chkcard: failed\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL);
|
|
|
+ if (!status) {
|
|
|
+ if (tempword & FT1000_DB_DPRAM_RX) {
|
|
|
+ status = ft1000_read_dpram16(dev,
|
|
|
+ 0x200, (u8 *)&data, 0);
|
|
|
+ size = ntohs(data) + 16 + 2;
|
|
|
+ if (size % 4) {
|
|
|
+ modulo = 4 - (size % 4);
|
|
|
+ size = size + modulo;
|
|
|
+ }
|
|
|
+ status = ft1000_read_dpram16(dev, 0x201,
|
|
|
+ (u8 *)&portid, 1);
|
|
|
+ portid &= 0xff;
|
|
|
+ if (size < MAX_CMD_SQSIZE) {
|
|
|
+ switch (portid) {
|
|
|
+ case DRIVERID:
|
|
|
+ DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX : portid DRIVERID\n");
|
|
|
+ status = ft1000_proc_drvmsg(dev, size);
|
|
|
+ if (status != 0)
|
|
|
+ return status;
|
|
|
+ break;
|
|
|
+ case DSPBCMSGID:
|
|
|
+ status = dsp_broadcast_msg_id(dev);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ status = handle_misc_portid(dev);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else
|
|
|
+ DEBUG("FT1000:dpc:Invalid total length for SlowQ = %d\n", size);
|
|
|
+ status = ft1000_write_register(dev,
|
|
|
+ FT1000_DB_DPRAM_RX,
|
|
|
+ FT1000_REG_DOORBELL);
|
|
|
+ } else if (tempword & FT1000_DSP_ASIC_RESET) {
|
|
|
+ /* Let's reset the ASIC from the Host side as well */
|
|
|
+ status = ft1000_write_register(dev, ASIC_RESET_BIT,
|
|
|
+ FT1000_REG_RESET);
|
|
|
+ status = ft1000_read_register(dev, &tempword,
|
|
|
+ FT1000_REG_RESET);
|
|
|
+ i = 0;
|
|
|
+ while (tempword & ASIC_RESET_BIT) {
|
|
|
+ status = ft1000_read_register(dev, &tempword,
|
|
|
+ FT1000_REG_RESET);
|
|
|
+ usleep_range(9000, 11000);
|
|
|
+ i++;
|
|
|
+ if (i == 100)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (i == 100) {
|
|
|
+ DEBUG("Unable to reset ASIC\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ usleep_range(9000, 11000);
|
|
|
+ /* Program WMARK register */
|
|
|
+ status = ft1000_write_register(dev, 0x600,
|
|
|
+ FT1000_REG_MAG_WATERMARK);
|
|
|
+ /* clear ASIC reset doorbell */
|
|
|
+ status = ft1000_write_register(dev,
|
|
|
+ FT1000_DSP_ASIC_RESET,
|
|
|
+ FT1000_REG_DOORBELL);
|
|
|
+ usleep_range(9000, 11000);
|
|
|
+ } else if (tempword & FT1000_ASIC_RESET_REQ) {
|
|
|
+ DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_ASIC_RESET_REQ\n");
|
|
|
+ /* clear ASIC reset request from DSP */
|
|
|
+ status = ft1000_write_register(dev,
|
|
|
+ FT1000_ASIC_RESET_REQ,
|
|
|
+ FT1000_REG_DOORBELL);
|
|
|
+ status = ft1000_write_register(dev, HOST_INTF_BE,
|
|
|
+ FT1000_REG_SUP_CTRL);
|
|
|
+ /* copy dsp session record from Adapter block */
|
|
|
+ status = ft1000_write_dpram32(dev, 0,
|
|
|
+ (u8 *)&info->DSPSess.Rec[0], 1024);
|
|
|
+ status = ft1000_write_register(dev, 0x600,
|
|
|
+ FT1000_REG_MAG_WATERMARK);
|
|
|
+ /* ring doorbell to tell DSP that
|
|
|
+ * ASIC is out of reset
|
|
|
+ * */
|
|
|
+ status = ft1000_write_register(dev,
|
|
|
+ FT1000_ASIC_RESET_DSP,
|
|
|
+ FT1000_REG_DOORBELL);
|
|
|
+ } else if (tempword & FT1000_DB_COND_RESET) {
|
|
|
+ DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_COND_RESET\n");
|
|
|
+ if (!dev->fAppMsgPend) {
|
|
|
+ /* Reset ASIC and DSP */
|
|
|
+ status = ft1000_read_dpram16(dev,
|
|
|
+ FT1000_MAG_DSP_TIMER0,
|
|
|
+ (u8 *)&(info->DSP_TIME[0]),
|
|
|
+ FT1000_MAG_DSP_TIMER0_INDX);
|
|
|
+ status = ft1000_read_dpram16(dev,
|
|
|
+ FT1000_MAG_DSP_TIMER1,
|
|
|
+ (u8 *)&(info->DSP_TIME[1]),
|
|
|
+ FT1000_MAG_DSP_TIMER1_INDX);
|
|
|
+ status = ft1000_read_dpram16(dev,
|
|
|
+ FT1000_MAG_DSP_TIMER2,
|
|
|
+ (u8 *)&(info->DSP_TIME[2]),
|
|
|
+ FT1000_MAG_DSP_TIMER2_INDX);
|
|
|
+ status = ft1000_read_dpram16(dev,
|
|
|
+ FT1000_MAG_DSP_TIMER3,
|
|
|
+ (u8 *)&(info->DSP_TIME[3]),
|
|
|
+ FT1000_MAG_DSP_TIMER3_INDX);
|
|
|
+ info->CardReady = 0;
|
|
|
+ info->DrvErrNum = DSP_CONDRESET_INFO;
|
|
|
+ DEBUG("ft1000_hw:DSP conditional reset requested\n");
|
|
|
+ info->ft1000_reset(dev->net);
|
|
|
+ } else {
|
|
|
+ dev->fProvComplete = false;
|
|
|
+ dev->fCondResetPend = true;
|
|
|
+ }
|
|
|
+ ft1000_write_register(dev, FT1000_DB_COND_RESET,
|
|
|
+ FT1000_REG_DOORBELL);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
}
|