sc2440_usb_hw.c
资源名称:SMDK2440.rar [点击查看]
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:46k
源码类别:
Windows CE
开发平台:
Windows_Unix
- /**
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- PARTICULAR PURPOSE.
- Copyright (c) 2001. Samsung Electronics, co. ltd All rights reserved.
- Module Name:
- Abstract:
- S3C2440 USB function(ACTIVE SYNC) device driver (Chip Layer)
- rev:
- 2003.3.18 : EP3 is replaced by EP4 for DMA operation because DMA2(EP3) is used by audio. (purnnamu)
- 2003.3.17 : Every USBD interrupt is followed by the dummy interrupt
- because USBD sub-pending interrupt is cleared after clearing INTPND register.
- So,USBD sub-pending bit is cleared before clearing INTPND register. (purnnamu)
- 2002.5.7 : Add to s3c2410_code (Seung-han, Lim)
- 2002.1.22 : First release/no error recovery (kwangyoon LEE, kwangyoon@samsung.com)
- Notes:
- */
- #include <windows.h>
- #include <types.h>
- #include <ceddk.h>
- #include <memory.h>
- #include <serhw.h>
- #include <nkintr.h>
- #include "S2440.h"
- #include <SC2440_usb_hw.h>
- #include <SC2440_usb_ser.h>
- #undef ZONE_INIT
- #include <serdbg.h>
- #include <drv_glob.h> //:-)
- #include <2440usb.h> //:-)
- #define USBDMSG DEBUGMSG //RETAILMSG
- PDRIVER_GLOBALS v_pDriverGlobals=NULL; //:-)
- volatile USBD_GLOBALS *usbdShMem=NULL; //:-)
- volatile DMAreg *v_pDMAregs=NULL; //:-)
- volatile INTreg *v_pINTregs=NULL; //:-)
- ULONG realPhysicalAddr_UsbdRxBuf=0;
- ULONG totalRxCnt=0; //debug
- /*
- #if (USBD_GLOBALS_BUF_SIZE!=0x4000)
- STOP_COMPILE GEN_ERROR
- //drv_glob.h should be changed correctly
- #endif
- */
- // This driver defines a simple BULK FIFO device. It supports only one
- // interface with one alternate setting, as shown below.
- //
- // Endpoint Setting 0
- //------------------------
- // EP0 Control
- // EP1 In Bulk
- // EP3 Out Bulk
- // Steal the useless IR zone from MDD and use it as EP0 & USB specific stuff
- #define ZONE_USB ZONE_IR
- // Define the configuration descriptor length
- #define CFGLEN 32
- #define iCONF 18
- #define TLEN (CFGLEN + 18)
- // Define the configuration descriptor itself
- const BYTE uStd[TLEN]= {
- 0x12, // 0 desc size
- DEVICE, // 1 desc type (DEVICE)
- 0x00, // 2 USB release
- 0x01, // 3 => 1.00
- 0xff, // 4 class
- 0xff, // 5 subclass
- 0xff, // 6 protocol
- EP0_MAXP_SIZE, // 7 max pack size
- 0x47, // 8 vendor ID LSB (Samsung Semi)
- 0x05, // 9 vendor ID MSB ( 0x1419 )
- 0x20, // 10 product ID LSB
- 0x27, // 11 product ID MSB
- 0x00, // 12 device release LSB
- 0x00, // 13 device release MSB
- 0x00, // 14 manufacturer string desc index
- 0x00, // 15 product string desc index
- 0x00, // 16 serial num string desc index
- 0x01, // 17 num of possible configurations
- // Configuration Descriptor
- 0x09, // desc size
- CONFIGURATION, // desc type (CONFIGURATION)
- CFGLEN%256, // total length of data returned LSB
- CFGLEN/256, // total length of data returned MSB
- 0x01, // num of interfaces
- 0x01, // value to select config (1 for now)
- 0x00, // index of string desc ( 0 for now)
- 0x80, // bus powered
- 25, // max power, 50mA for now
- // Interface Decriptor
- 0x09, // desc size
- INTERFACE, // desc type (INTERFACE)
- 0x00, // interface index.
- 0x00, // value for alternate setting
- 0x02, // bNumEndpoints (number endpoints used, excluding EP0)
- 0xff,
- 0xff,
- 0xff,
- 0x00, // string index,
- // Endpoint descriptor (EP 1 Bulk IN)
- 0x07, // desc size
- ENDPOINT, // desc type (ENDPOINT)
- 0x81, // endpoint address: endpoint 1, IN
- 0x02, // endpoint attributes: Bulk
- EP1_IN_MAXP_SIZE, // max packet size LSB
- 0x00, // max packet size MSB
- 0x00, // polling interval (4ms/bit=time,500ms)
- #if 0
- // Endpoint descriptor (EP 2 Interrupt IN)
- 0x07, // desc size
- ENDPOINT, // desc type (ENDPOINT)
- 0x82, // endpoint address: endpoint 2, IN
- 0x03, // endpoint attributes: Interrupt
- EP2_IN_MAXP_SIZE, // max packet size LSB
- 0x00, // max packet size MSB
- 0xFA, // polling interval (4ms/bit=time,100ms)
- #endif
- // Endpoint descriptor (EP 4 Bulk OUT)
- 0x07, // desc size
- ENDPOINT, // desc type (ENDPOINT)
- 0x04, // endpoint address: endpoint 4, OUT
- 0x02, // endpoint attributes: Bulk
- EP4_OUT_MAXP_SIZE, // max packet size LSB
- 0x00, // max packet size MSB
- 0x00 // polling interval (4ms/bit=time,500ms)
- #if 0
- // Endpoint descriptor (EP 4 Interrupt OUT)
- 0x07, // desc size
- ENDPOINT, // desc type (ENDPOINT)
- 0x04, // endpoint address: endpoint 4, OUT
- 0x03, // endpoint attributes: Interrupt
- EP4_OUT_MAXP_SIZE, // max packet size LSB
- 0x00, // max packet size MSB
- 0x00 // polling interval (4ms/bit=time,500ms) // $$$$
- #endif
- };
- // Register writes need to be verified. This macro loops the write until
- // the effects are visible and records the number of retries.
- #define UDC_REG_WRITE(_struct,_ptr,_field,_val) IOW_REG_FIELD(_struct,_ptr,_field,_val)
- #define UDC_REG_BITSET(_struct,_ptr,_field,_val) { _struct xx;
- *(unsigned int *)&xx = 0;
- xx._field = _val;
- IOW_REG_SET(_struct,_ptr,*(unsigned int*)&xx); }
- #define UDC_REG_WRITEX(_setptr,_setval) (_setptr) = _setval;
- // Variables for EP0 resend control. Keep track of last packet sent.
- static char *sendPacket;
- static int sendPacketLength;
- static int sendTotalLength;
- static char *savSendPacket;
- static int savSendPacketLength;
- // EP1/EP3 packet size. For polling this can not be greater than 16
- static unsigned int maxPacketSize = EP1Len;
- // Read the command from the endpoint 0 FIFO
- void HW_USBClocks(PSER_INFO pHWHead);
- static
- int getCommand(PSER_INFO pHWHead, void *argP)
- {
- unsigned char *bufP = (unsigned char*)argP;
- int length = pHWHead->pUSBCtrlAddr->OFCR1.out_cnt_low | pHWHead->pUSBCtrlAddr->OFCR2.out_cnt_high<<8;
- int i;
- memset(bufP, 0x55, 8);
- // All setup commands are 8 bytes in length
- if (length != 8)
- {
- DEBUGMSG(1, (TEXT("UDC bad command length %dn"), length));
- return 1;
- }
- DEBUGMSG(1, (TEXT("[GETCOMMAND : ")));
- for (i=0; i < length; i++)
- {
- bufP[i] = (BYTE)pHWHead->pUSBCtrlAddr->EP0F.fifo_data;
- DEBUGMSG(1, (TEXT("%2x "), bufP[i]));
- }
- DEBUGMSG(1, (TEXT("]rn")));
- return 0;
- }
- /*************************************************************************
- Command response with data packets
- *************************************************************************/
- static
- void sendData(PSER_INFO pHWHead, void *argP, int length, int totalLen)
- {
- unsigned char *bufP = (unsigned char*)argP;
- struct EP0ICSR1Bits EP0ICSR1;
- int i;
- // Endpoint0 mode
- pHWHead->pUSBCtrlAddr->INDEX.index = 0x0;
- DEBUGMSG(1, (TEXT("[UDC WILL SEND] %d bytesrn"), length));
- // Send the data back. The FIFO should be turned around for
- // us already. Just blast away ...
- for (i=0; (i < length) && (i < EP0Len); i++)
- {
- IOW_REG_FIELD(struct EP0FBits,
- &pHWHead->pUSBCtrlAddr->EP0F, fifo_data, bufP[i]);
- }
- // Form the register update. Always set IN_PKT_RDY.
- EP0ICSR1 = pHWHead->pUSBCtrlAddr->EP0ICSR1;
- EP0ICSR1.ipr_ = 1;
- // We can complete on a packet which is full. We need to wait till
- // next time and generate a zero length packet, so only complete
- // if we're at the end and it is not the max packet size.
- if ((i == length) && (i != EP0Len))
- {
- savSendPacket = sendPacket;
- savSendPacketLength = sendPacketLength;
- sendPacket = NULL;
- sendPacketLength = length - i;
- sendTotalLength = totalLen - i;
- EP0ICSR1.de_ff = 1;
- }
- // Need to send another packet.
- else {
- sendPacket = (char*)&bufP[i];
- sendPacketLength = length - i;
- sendTotalLength = totalLen - i;
- savSendPacket = sendPacket;
- savSendPacketLength = sendPacketLength;
- DEBUGMSG(1, (TEXT("UDC WILL SEND %d more bytes laterrn"),
- sendPacketLength));
- }
- /* Update the register
- */
- UDC_REG_WRITEX(*(volatile unsigned *)&pHWHead->pUSBCtrlAddr->EP0ICSR1,
- *(unsigned *)&EP0ICSR1);
- }
- /*************************************************************************
- Send command done
- *************************************************************************/
- static
- void sendCommandDone(PSER_INFO pHWHead)
- {
- BYTE index;
- // Endpoint0 mode
- index = pHWHead->pUSBCtrlAddr->INDEX.index;
- pHWHead->pUSBCtrlAddr->INDEX.index = 0x0;
- // Set SERVICE_OUT_PKY_RDY bit
- pHWHead->pUSBCtrlAddr->EP0ICSR1.sopr_cdt = 0x1;
- pHWHead->pUSBCtrlAddr->INDEX.index = index;
- }
- /*************************************************************************
- Command response with no data packets
- *************************************************************************/
- static
- void sendDone(PSER_INFO pHWHead, int err)
- {
- struct EP0ICSR1Bits EP0ICSR1;
- BYTE index;
- EP0ICSR1 = pHWHead->pUSBCtrlAddr->EP0ICSR1;
- EP0ICSR1.sopr_cdt = 1;
- EP0ICSR1.de_ff = 1;
- EP0ICSR1.sts_ur = (BYTE)err;
- // Endpoint 0 mode
- index = pHWHead->pUSBCtrlAddr->INDEX.index;
- pHWHead->pUSBCtrlAddr->INDEX.index = 0x0;
- if (err) {
- DEBUGMSG(ZONE_ERROR, (TEXT("SENT_STALL CLEARrn")));
- }
- UDC_REG_WRITEX( *(volatile DWORD *)&pHWHead->pUSBCtrlAddr->EP0ICSR1,
- *(DWORD *)&EP0ICSR1 );
- pHWHead->pUSBCtrlAddr->INDEX.index = index;
- }
- /*************************************************************************
- Set the device address
- *************************************************************************/
- static
- void setAddress(PSER_INFO pHWHead, int addr)
- {
- DEBUGMSG(ZONE_USB, (TEXT("[SET ADDRESS to %x]rn"), addr));
- pHWHead->pUSBCtrlAddr->udcFAR.func_addr = (BYTE)addr;
- pHWHead->pUSBCtrlAddr->udcFAR.addr_up = 1;
- }
- /*************************************************************************
- SC2440_USB_Init
- Initialize the UDC.
- *************************************************************************/
- extern
- void SC2440_USB_Init(PSER_INFO pHWHead)
- {
- BYTE index;
- int i;
- EnterCriticalSection(&pHWHead->HwRegCritSec);
- USBDMSG(1, (TEXT("++SC2440_USB_Initrn")));
- //RETAILMSG(1, (TEXT("++SC2440_USB_Initrn")));
- //DebugBreak();;;
- pHWHead->dConfIdx = 0;
- pHWHead->dSetting = 0;
- pHWHead->dInterface = 0;
- pHWHead->dAddress = 0;
- pHWHead->ModemStatus = 0; // All lines low till we get connected.
- pHWHead->wSOFStableCnt = 0;
- _re_enable:
- switch (pHWHead->State) {
- case IDLE:
- //RETAILMSG(1, (TEXT("IDLErn")));
- //
- // Enable the USB Clocks
- //
- HW_USBClocks(pHWHead);
- break;
- case OFF:
- //RETAILMSG(1, (TEXT("OFFrn")));
- //
- // Disable the USB Clocks
- //
- HW_USBClocks(pHWHead);
- DEBUGMSG(ZONE_INIT, (TEXT("rUPLLCON: 0x%Xrn"), pHWHead->pCLKPWR->rUPLLCON));
- goto _done;
- break;
- case SUSPEND:
- // should never get here
- //RETAILMSG(1, (TEXT("SUSPENDrn")));
- ASSERT(0);
- goto _done;
- break;
- case RESUME:
- // Suspend disconnects us from the USB.
- // When we Resume we re-enumerate on the USB.
- //RETAILMSG(1, (TEXT("RESUME => ")));
- default:
- pHWHead->State = IDLE;
- goto _re_enable;
- break;
- }
- //
- // Initialize the USBD Controller
- //
- index = pHWHead->pUSBCtrlAddr->INDEX.index;
- // suspend mode disable
- pHWHead->pUSBCtrlAddr->PMR.sus_en = 0x0;
- ASSERT(pHWHead->pUSBCtrlAddr->PMR.sus_en == 0x0);
- // setup endpoint 0
- pHWHead->pUSBCtrlAddr->INDEX.index = 0;
- ASSERT(pHWHead->pUSBCtrlAddr->INDEX.index == 0);
- pHWHead->pUSBCtrlAddr->MAXP.maxp = 0x1; // 8 BYTE
- ASSERT(pHWHead->pUSBCtrlAddr->MAXP.maxp == 0x1);
- pHWHead->pUSBCtrlAddr->EP0ICSR1.sopr_cdt = 1; // OUT_PKT_RDY
- //ASSERT(pHWHead->pUSBCtrlAddr->EP0ICSR1.sopr_cdt == 1); // W only
- pHWHead->pUSBCtrlAddr->EP0ICSR1.sse_ = 1; // SETUP_END
- //ASSERT(pHWHead->pUSBCtrlAddr->EP0ICSR1.sse_ == 1); // W only
- // setup endpoint 1
- pHWHead->pUSBCtrlAddr->INDEX.index = 1;
- ASSERT(pHWHead->pUSBCtrlAddr->INDEX.index == 1);
- pHWHead->pUSBCtrlAddr->MAXP.maxp = 0x8; // 64 BYTE
- ASSERT(pHWHead->pUSBCtrlAddr->MAXP.maxp == 0x8);
- pHWHead->pUSBCtrlAddr->ICSR2.mode_in = 1; // IN
- ASSERT(pHWHead->pUSBCtrlAddr->ICSR2.mode_in == 1);
- pHWHead->pUSBCtrlAddr->ICSR2.iso = 0; // BULK
- ASSERT(pHWHead->pUSBCtrlAddr->ICSR2.iso == 0);
- // setup endpoint 4
- pHWHead->pUSBCtrlAddr->INDEX.index = 4;
- ASSERT(pHWHead->pUSBCtrlAddr->INDEX.index == 4);
- pHWHead->pUSBCtrlAddr->MAXP.maxp = 0x8; // 64 BYTE
- ASSERT(pHWHead->pUSBCtrlAddr->MAXP.maxp == 0x8);
- pHWHead->pUSBCtrlAddr->ICSR2.mode_in = 0; // OUT
- ASSERT(pHWHead->pUSBCtrlAddr->ICSR2.mode_in == 0);
- pHWHead->pUSBCtrlAddr->OCSR2.iso = 0; // BULK
- ASSERT(pHWHead->pUSBCtrlAddr->OCSR2.iso == 0);
- // clear all EP interrupts
- pHWHead->pUSBCtrlAddr->EIR.ep0_int = 0x1;
- ASSERT(pHWHead->pUSBCtrlAddr->EIR.ep0_int == 0);
- pHWHead->pUSBCtrlAddr->EIR.ep1_int = 0x1;
- ASSERT(pHWHead->pUSBCtrlAddr->EIR.ep1_int == 0);
- pHWHead->pUSBCtrlAddr->EIR.ep2_int = 0x1;
- ASSERT(pHWHead->pUSBCtrlAddr->EIR.ep2_int == 0);
- pHWHead->pUSBCtrlAddr->EIR.ep3_int = 0x1;
- ASSERT(pHWHead->pUSBCtrlAddr->EIR.ep3_int == 0);
- pHWHead->pUSBCtrlAddr->EIR.ep4_int = 0x1;
- ASSERT(pHWHead->pUSBCtrlAddr->EIR.ep4_int == 0);
- // clear reset int
- pHWHead->pUSBCtrlAddr->UIR.reset_int = 0x1;
- ASSERT(pHWHead->pUSBCtrlAddr->UIR.reset_int == 0x0);
- // EP0, 1, & 4 Enabled, EP2, 3 Disabled
- pHWHead->pUSBCtrlAddr->EIER.ep2_int_en = 0x0;
- ASSERT(pHWHead->pUSBCtrlAddr->EIER.ep2_int_en == 0x0);
- pHWHead->pUSBCtrlAddr->EIER.ep3_int_en = 0x0;
- ASSERT(pHWHead->pUSBCtrlAddr->EIER.ep3_int_en == 0x0);
- pHWHead->pUSBCtrlAddr->EIER.ep0_int_en = 0x1;
- ASSERT(pHWHead->pUSBCtrlAddr->EIER.ep0_int_en == 0x1);
- pHWHead->pUSBCtrlAddr->EIER.ep1_int_en = 0x1;
- ASSERT(pHWHead->pUSBCtrlAddr->EIER.ep1_int_en == 0x1);
- pHWHead->pUSBCtrlAddr->EIER.ep4_int_en = 0x1;
- ASSERT(pHWHead->pUSBCtrlAddr->EIER.ep4_int_en == 0x1);
- // enable reset int
- pHWHead->pUSBCtrlAddr->UIER.reset_int_en = 0x1;
- ASSERT(pHWHead->pUSBCtrlAddr->UIER.reset_int_en == 0x1);
- if(v_pDMAregs==NULL)
- {
- //RETAILMSG(1, (TEXT("ERROR: SC2440_usb_hw: v_pDMAregs=NULLrn")));
- while(1);
- }
- pHWHead->pUSBCtrlAddr->INDEX.index = 0x4;
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DC=0x0;
- //may not be needed, not to operate DMA during initialization.
- UsbdInitDma3(0,0);
- usbdShMem->usbdRxRdPt=0;
- usbdShMem->usbdRxWrPt=0;
- usbdShMem->usbdRxCnt=0;
- usbdShMem->usbdEir=0;
- usbdShMem->usbdUir=0;
- usbdShMem->usbdDma3Int=0;
- //rEP4_DMA_FIFO=0x40; //not needed for OUT operation.
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DTL=USBD_GLOBALS_BUF_SIZE&0xff;
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DTM=(USBD_GLOBALS_BUF_SIZE>>8)&0xff;
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DTH=(USBD_GLOBALS_BUF_SIZE>>16)&0x0f;
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->OCSR2=
- *(BYTE *)&pHWHead->pUSBCtrlAddr->OCSR2 | (BYTE)EPO_AUTO_CLR /*| EPO_OUT_DMA_INT_MASK*/;
- //AUTO_CLR(OUT_PKT_READY is cleared automatically), interrupt_masking.
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DU=0x01; //DMA transfer unit=1byte
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DC=UDMA_OUT_DMA_RUN|UDMA_DMA_MODE_EN;
- //deamnd disable,out_dma_run=run,in_dma_run=stop,DMA mode enable
- //wait until DMA_CON is effective.
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DC;
- for(i=0;i<10;i++);
- v_pINTregs->rINTMSK&=~(BIT_DMA3); //enable DMA3 interrupt
- pHWHead->pUSBCtrlAddr->INDEX.index = 0x0; //del me
- _done:
- LeaveCriticalSection(&pHWHead->HwRegCritSec);
- USBDMSG(1, (TEXT("--SC2440_USB_Initrn")));
- //RETAILMSG(1, (TEXT("--SC2440_USB_Initrn")));
- }
- /*************************************************************************
- Process Endpoint 0 interrupt. We are called here on every EIR interrupt.
- We need to check the EP0 status and send the next packet, if any. We need
- to handle errors as follows:
- SE - This is set if we received a new command before we finished the last
- one. This happens when the host does not wish to read all reply data
- (it may only be interested in the first 8 bytes of a device descriptor
- to get the max packet size, for example). We will simply discard the
- next data to send and continue with the normal command handling. We
- need to clear SE by asserting SSE before we continue.
- SST - This is set when the UDC actually issues a stall. We just clear it
- and continue.
- Normal setup is as follows:
- OPR - This indicates a receive command packet is ready to be read. Commands
- are always 8 bytes in length and follow the form defined in chapter 9.
- If OPR is not set and IPR is not set and SE is not set we must be here
- because IPR transitioned from 1 -> 0. This means the last packet has been
- sent (ACK'd). Send the next packet, if any.
- We are emulating a serial line here. The state of the modem control lines
- are sent in a command packet. Extract these and set the modem status bits
- as for a normal serial line. This allows the upper levels to treat this
- link just like a serial line with modem control (no flow control is
- explicitly required and hence is not supported.
- **************************************************************************/
- void SC2440_USB_DoEndpoint0(PSER_INFO pHWHead, PDWORD pModemStatus)
- {
- BYTE dbuf[8];
- WORD len, totLen;
- PUCHAR p;
- unsigned int cnt=0;
- struct EP0ICSR1Bits EP0ICSR1=pHWHead->pUSBCtrlAddr->EP0ICSR1;
- // Endpoint 0 mode
- UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x0);
- DEBUGMSG(1, (TEXT("++SC2440_USB_DoEndpoint0rn")));
- //RETAILMSG(1, (TEXT("++SC2440_USB_DoEndpoint0rn")));
- /* If there is data to send and the transmitter is open go send
- * the next packet. But, do not continue to send if the host has
- * aborted the transfer or sent a new one. We'll clean up below.
- */
- if ((EP0ICSR1.se_sds == 0) && (EP0ICSR1.ipr_ == 0) &&
- (EP0ICSR1.opr_ipr == 0) && (sendPacket))
- {
- DEBUGMSG( 1, (TEXT("Send remaining data !!!rn")));
- sendData(pHWHead, sendPacket, sendPacketLength, sendTotalLength);
- }
- // If setup end, the host has aborted the last transfer. Kill any
- //remaining packets and continue;
- if (EP0ICSR1.se_sds) {
- sendPacketLength = 0;
- sendPacket = NULL;
- UDC_REG_BITSET(struct EP0ICSR1Bits, &pHWHead->pUSBCtrlAddr->EP0ICSR1, sse_, 1);
- }
- // If stall ack, not sure what needs to be done here.
- if (EP0ICSR1.sts_ur)
- {
- DEBUGMSG( 1, (TEXT("Stall ACK setrn")));
- UDC_REG_BITSET(struct EP0ICSR1Bits, &pHWHead->pUSBCtrlAddr->EP0ICSR1, sts_ur, 0); // 0 -> clear
- }
- // If new command received ...
- DEBUGMSG(1, (TEXT("OUT_PKT_RDY = 0x%xrn"), EP0ICSR1.opr_ipr));
- // if (EP0ICSR1.opr_ipr)
- if (EP0ICSR1.opr_ipr)
- {
- // New command with existing data. Not sure how this can happen but if
- // it does just clear the old data and continue.
- if (sendPacket)
- sendPacket = NULL;
- cnt = pHWHead->pUSBCtrlAddr->OFCR1.out_cnt_low | pHWHead->pUSBCtrlAddr->OFCR2.out_cnt_high << 8;
- DEBUGMSG(1,(TEXT("UDC received setup, EP0ICSR1 %x, len %dn"),
- EP0ICSR1, cnt));
- // Read the command from the input FIFO
- if (getCommand(pHWHead, (void*)&pHWHead->dReq) != 0)
- {
- sendDone(pHWHead,1);
- }
- DEBUGMSG(1,
- (TEXT("bmRequest: %02x bRequest: %02x wValue: %04x wIndex: %04x wLength: %04xn"),
- pHWHead->dReq.bmRequest,
- pHWHead->dReq.bRequest,
- pHWHead->dReq.wValue,
- pHWHead->dReq.wIndex,
- pHWHead->dReq.wLength));
- // Decode and execute the command. We support two sets of commands, vendor
- // specific (modem control) and chapter 9 standard commands.
- if (pHWHead->dReq.bmRequest & 0x60) // vendor or class command
- {
- DEBUGMSG(1, (TEXT("Vendor/Class Command !!n")));
- if (SET_CONTROL_LINE_STATE == pHWHead->dReq.bRequest)
- {
- // Host is notifying us of control line state.
- // wValue contains bitmask
- // 0 - DTR
- // 1 - RTS
- DEBUGMSG(1, (TEXT("SET_CONTROL_LINE_STATE %4.4Xrn"),
- pHWHead->dReq.wValue));
- if (pHWHead->dReq.wValue & 0x01)
- *pModemStatus |= (MS_DSR_ON|MS_RLSD_ON); // DTR active, set DSR/RLSD
- else
- *pModemStatus &= ~(MS_DSR_ON|MS_RLSD_ON); // DTR clear, clr DSR/RLSD
- if (pHWHead->dReq.wValue & 0x02)
- *pModemStatus |= MS_CTS_ON; // RTS active, set CTS
- else
- *pModemStatus &= ~MS_CTS_ON; // RTS clear, clear CTS
- }
- else {
- // Unknown vendor/class request
- DEBUGMSG(1,(TEXT("Unknown vendor/class request %2.2Xrn"),
- pHWHead->dReq.bRequest));
- }
- // Command is complete
- sendDone(pHWHead,0);
- return;
- }
- // standard chapter 9 commands
- switch (pHWHead->dReq.bRequest) {
- case GET_STATUS:
- RETAILMSG(1, (TEXT("GET_STATUSrn")));
- dbuf[0] = 0;
- dbuf[1] = 0;
- // If this is a request to the endpoint return the stalled status.
- if (pHWHead->dReq.bmRequest == 0x82) {
- dbuf[0] = 0;
- switch (pHWHead->dReq.wIndex & 15) {
- // Control endpoint can't stall (we wouldn't get this message).
- case 0:
- break;
- // OUT endpoint. Return send_stall.
- case 1:
- UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x4);
- if (pHWHead->pUSBCtrlAddr->OCSR1.send_stall)
- dbuf[0] = 1;
- break;
- // IN endpoint. Return send_stall.
- case 2:
- //case 3:
- case 4:
- UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x1);
- if (pHWHead->pUSBCtrlAddr->EP0ICSR1.se_sds)
- dbuf[0] = 1;
- break;
- }
- UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0);
- }
- // Clear the OPR bit and start the data phase
- sendCommandDone(pHWHead);
- // Send the reply data.
- sendData(pHWHead, dbuf, 2, 2);
- //RETAILMSG(1, (TEXT("GS[0x%X]rn"), pHWHead->dReq.wIndex & 0xFF));
- break;
- case CLEAR_FEATURE:
- DEBUGMSG(1, (TEXT("CLEAR_FEATURErn")));
- if (pHWHead->dReq.bmRequest == 0x02) { // Halt
- switch (pHWHead->dReq.wIndex & 15) {
- // Control endpoint. Not suggested.
- case 0:
- break;
- // OUT endpoint. Set and clear sendstall to reset DATA0/DATA1.
- case 1:
- UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x4);
- UDC_REG_BITSET(struct OCSR1Bits,
- &pHWHead->pUSBCtrlAddr->OCSR1,send_stall,1); // STALL!!!
- UDC_REG_BITSET(struct OCSR1Bits,
- &pHWHead->pUSBCtrlAddr->OCSR1,send_stall,0);
- UDC_REG_BITSET(struct OCSR1Bits,
- &pHWHead->pUSBCtrlAddr->OCSR1,sent_stall,0); // CLEAR STALL
- break;
- // IN endpoint. Set and clear sendstall to reset DATA0/DATA1.
- case 2:
- //case 3:
- case 4:
- UDC_REG_WRITE(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x1);
- UDC_REG_BITSET(struct EP0ICSR1Bits,
- &pHWHead->pUSBCtrlAddr->EP0ICSR1,se_sds,1); // STALL!!!
- UDC_REG_BITSET(struct EP0ICSR1Bits,
- &pHWHead->pUSBCtrlAddr->EP0ICSR1,se_sds,0);
- UDC_REG_BITSET(struct EP0ICSR1Bits,
- &pHWHead->pUSBCtrlAddr->EP0ICSR1,sds_sts,0); // CLEAR STALL
- break;
- }
- UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0);
- }
- // Command is complete
- sendDone(pHWHead,0);
- //RETAILMSG(1, (TEXT("CF[0x%X]rn"), pHWHead->dReq.wIndex & 0xFF));
- break;
- case SET_FEATURE:
- DEBUGMSG(1, (TEXT("SET_FEATURE %drn"), pHWHead->dReq.bmRequest));
- if (pHWHead->dReq.bmRequest == 0x02) {
- switch (pHWHead->dReq.wIndex & 15) {
- // Control endpoint. Not suggested.
- case 0:
- break;
- /* OUT endpoint. Set sendstall to force stall condition
- */
- case 1:
- UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x4);
- UDC_REG_BITSET(struct OCSR1Bits,
- &pHWHead->pUSBCtrlAddr->OCSR1, send_stall, 1); // STALL
- break;
- /* IN endpoint. Set sendstall to force stall condition
- */
- case 2:
- //case 3:
- case 4:
- UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x1);
- UDC_REG_BITSET(struct EP0ICSR1Bits,
- &pHWHead->pUSBCtrlAddr->EP0ICSR1, se_sds, 1); // STALL
- break;
- }
- UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0);
- }
- // Command is complete
- sendDone(pHWHead,0);
- //RETAILMSG(1, (TEXT("SF[0x%X]rn"), pHWHead->dReq.wIndex & 0xFF));
- break;
- case SET_ADDRESS:
- RETAILMSG(1, (TEXT("SET_ADDRESS - 0x%Xrn"), pHWHead->dReq.wValue));
- pHWHead->dAddress = (BYTE)pHWHead->dReq.wValue;
- // Note, this write needs to be started here but it will not read back
- // until the command completes. There is no retry mechanism.
- setAddress(pHWHead, pHWHead->dAddress);
- // Command is complete
- sendDone(pHWHead,0);
- break;
- case GET_DESCRIPTOR:
- switch ((BYTE)(pHWHead->dReq.wValue>>8)) {
- case DEVICE: // 0x01
- RETAILMSG(1, (TEXT("GET_DESCRIPTOR:DEVICE 0x%X, 0x%Xrn"),
- uStd[0], pHWHead->dReq.wLength));
- //sendCommandDone(pHWHead);
- p = (PUCHAR)uStd;
- len = (BYTE)min(uStd[0],pHWHead->dReq.wLength);
- totLen = uStd[0];
- break;
- case CONFIGURATION: // 0x02
- RETAILMSG(1,(TEXT("GET_DESCRIPTOR:CONFIGURATIONrn")));
- //sendCommandDone(pHWHead);
- p = (PUCHAR)&uStd[iCONF];
- len = (BYTE)min(CFGLEN,pHWHead->dReq.wLength);
- totLen = CFGLEN;
- break;
- case STRING: // 0x03
- DEBUGMSG(1,(TEXT("GET_DESCRIPTOR:STRINGrn")));
- //sendCommandDone(pHWHead);
- p = NULL;
- len = 0;
- totLen = 0;
- break;
- default:
- DEBUGMSG(1,(TEXT("GET_DESCRIPTOR:Unknown %drn"),
- (pHWHead->dReq.wValue>>8) ));
- sendCommandDone(pHWHead);
- p = NULL;
- len = 0;
- totLen = 0;
- break;
- }
- // Clear the OPR bit and start the data phase
- sendCommandDone(pHWHead);
- // Send the reply data.
- sendData(pHWHead, p, len, totLen);
- DEBUGMSG(1,(TEXT("GET_DESCRIPTOR:EP0ICSR1 status value = 0x%xrn"), pHWHead->pUSBCtrlAddr->EP0ICSR1));
- break;
- case GET_CONFIG:
- RETAILMSG(1, (TEXT("GET_CONFIGrn")));
- // Clear the OPR bit and start the data phase
- sendCommandDone(pHWHead);
- // Send the reply data.
- sendData(pHWHead, &pHWHead->dConfIdx, 1, 1);
- break;
- case GET_INTERFACE:
- DEBUGMSG(1,(TEXT("GET_INTERFACErn")));
- // Clear the OPR bit and start the data phase
- sendCommandDone(pHWHead);
- // Send the reply data.
- sendData(pHWHead, &pHWHead->dInterface, 1, 1);
- break;
- case SET_CONFIG:
- RETAILMSG(1,(TEXT("SET_CONFIG %drn"),
- pHWHead->dReq.wValue));
- pHWHead->dConfIdx = (BYTE)pHWHead->dReq.wValue;
- // Command done
- sendDone(pHWHead,0);
- break;
- case SET_DESCRIPTOR:
- RETAILMSG(1, (TEXT("SET_DESCRIPTORrn")));
- // Command done
- sendDone(pHWHead,0);
- break;
- case SET_INTERFACE:
- DEBUGMSG(1,(TEXT("SET_INTERFACE : %d,%drn"),
- pHWHead->dReq.wIndex,
- pHWHead->dReq.wValue));
- pHWHead->dInterface = (BYTE)pHWHead->dReq.wIndex;
- pHWHead->dSetting = (BYTE)pHWHead->dReq.wValue;
- // Command done
- sendDone(pHWHead,0);
- break;
- default:
- DEBUGMSG(1,(TEXT("Unhandled Command : %drn"),
- pHWHead->dReq.bRequest));
- // Command done
- sendDone(pHWHead,0);
- break;
- }
- }
- DEBUGMSG(1, (TEXT("--SC2440_USB_DoEndpoint0rn")));
- }
- /*************************************************************************
- SC2440_USB_GetInterruptType
- Determine the source of an interrupt and return flags to control
- which function gets called to handle it. EP0 is handled as modem
- interrupt, EP1 as TX, EP3 as RX and reset is handle as line
- interrupt.
- *************************************************************************/
- INTERRUPT_TYPE SC2440_USB_GetInterruptType( PSER_INFO pHWHead) //:-)
- {
- INTERRUPT_TYPE interruptFlags = 0;
- //BYTE saveIndex;
- pHWHead->wPrevSOF = pHWHead->wSOF;
- pHWHead->wSOF = (pHWHead->pUSBCtrlAddr->FNR2.fr_n2 << 8) | pHWHead->pUSBCtrlAddr->FNR1.fr_n1;
- DEBUGMSG(1, (TEXT("SOF: %u, wPrevSOF: %urn"), pHWHead->wSOF, pHWHead->wPrevSOF));
- //RETAILMSG(1, (TEXT("SOF: %u, wPrevSOF: %urn"), pHWHead->wSOF, pHWHead->wPrevSOF));
- //important notes
- // 1. INDEX register should be preserved here. //:-)
- // 2. 'else if' should not be used here. //:-)
- if (usbdShMem->usbdEir& USBDEIR_EP1) // EP1(IN), ready to TX more data.
- {
- interruptFlags |= INTR_TX;
- }
- if (usbdShMem->usbdEir& USBDEIR_EP4) // EP4(OUT), RX data ready
- {
- interruptFlags |= INTR_RX;
- }
- if (usbdShMem->usbdDma3Int) // DMA3 done interrupt
- {
- interruptFlags |= INTR_RX;
- USBDMSG(1, (TEXT("<D3Int>rn")));
- }
- if (usbdShMem->usbdUir& USBDUIR_RESET)// USB reset, so re-initialize our driver.
- {
- USBDMSG(1, (TEXT("RESET INTrn")));
- interruptFlags |= INTR_LINE; // We use INTR_LINE to handle USB Reset
- usbdShMem->usbdUir&=~USBDUIR_RESET;
- }
- if (usbdShMem->usbdEir&USBDEIR_EP0) // EP0, Control endpoint
- {
- interruptFlags |= INTR_MODEM; // Use INTR_MODEM for EP0 interrupts
- // call SerModemIntr function by shim 020503
- usbdShMem->usbdEir&=~USBDEIR_EP0;
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->INDEX=0x0;
- //temp_kiw, should be repaired officially.
- USBDMSG(1, (TEXT("<EP0 Int>rn")));
- }
- return (interruptFlags);
- }
- /*************************************************************************
- SC2440_USB_LineIntHandler
- This handler is called for reset interrupts
- *************************************************************************/
- void SC2440_USB_LineIntHandler(PSER_INFO pHWHead)
- {
- DEBUGMSG(1, (TEXT("++SC2440_USB_LineIntHandlerrn")));
- SC2440_USB_Init(pHWHead);
- UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0);
- DEBUGMSG(1, (TEXT("--SC2440_USB_LineIntHandlerrn")));
- }
- /*************************************************************************
- SC2440_USB_RxIntHandler
- Read characters up to the max packet length from the IN FIFO. Return the
- number of characters read in the supplied argument. The function returns
- a boolean indicating whether event characters are present.
- *************************************************************************/
- BOOL SC2440_USB_RxIntHandler(PSER_INFO pHWHead,
- PUCHAR pRxBuffer,
- ULONG *pBuffLen)
- {
- BOOL fRXFlag = FALSE;
- UCHAR cEvtChar = pHWHead->dcb.EvtChar;
- int buflen = *pBuffLen;
- UCHAR cRxChar;
- ULONG usbdRxRdPt=0;
- ULONG usbdRxWrPt=0;
- ULONG usbdRxCnt;
- BYTE* usbdRxBuf;
- ULONG cnt,saveCnt;
- int swRdCnt=0;
- BYTE saveIndex;
- DEBUGMSG(1, (TEXT("++SC2440_USB_RxIntHandlerrn")));
- usbdRxRdPt=usbdShMem->usbdRxRdPt;
- usbdRxBuf=(BYTE*)usbdShMem->usbdRxBuf;
- *pBuffLen = 0;
- // Endpoint 4 mode
- saveIndex=*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->INDEX;
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->INDEX=0x4;
- if (usbdShMem->usbdDma3Int)
- {
- //usbdRxWrPt=v_pDMAregs->rDCDST3 - realPhysicalAddr_UsbdRxBuf;
- USBDMSG(1,(TEXT("[RxPt:%d]"),usbdRxRdPt));
- if(usbdRxRdPt==0)
- {
- usbdShMem->usbdDma3Int=0;
- USBDMSG(1,(TEXT("[D:%d"),pHWHead->pUSBCtrlAddr->OFCR1.out_cnt_low));
- // cnt=swRdCnt=pHWHead->pUSBCtrlAddr->OFCR1.out_cnt_low | pHWHead->pUSBCtrlAddr->OFCR1.out_cnt_high;
- swRdCnt=pHWHead->pUSBCtrlAddr->OFCR1.out_cnt_low | pHWHead->pUSBCtrlAddr->OFCR2.out_cnt_high;
- for(cnt=0; cnt < swRdCnt; cnt++)
- {
- usbdRxBuf[cnt]=(UCHAR)pHWHead->pUSBCtrlAddr->EP4F.fifo_data;
- }
- if((pHWHead->pUSBCtrlAddr->OFCR1.out_cnt_low | pHWHead->pUSBCtrlAddr->OFCR2.out_cnt_high)==0 &&
- pHWHead->pUSBCtrlAddr->OCSR1.out_pkt_rdy==1)
- {
- USBDMSG(1, (TEXT(",OPR CLR,")));
- UDC_REG_BITSET(struct OCSR1Bits,&pHWHead->pUSBCtrlAddr->OCSR1, out_pkt_rdy, 0);
- }
- UsbdInitDma3(0,swRdCnt);
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DTL=(USBD_GLOBALS_BUF_SIZE-swRdCnt)&0xff;
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DTM=((USBD_GLOBALS_BUF_SIZE-swRdCnt)>>8)&0xff;
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DTH=((USBD_GLOBALS_BUF_SIZE-swRdCnt)>>16)&0x0f;
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DC=UDMA_OUT_DMA_RUN|UDMA_DMA_MODE_EN;
- }
- }
- usbdRxWrPt=v_pDMAregs->rDCDST3 - realPhysicalAddr_UsbdRxBuf;
- if(usbdRxWrPt==USBD_GLOBALS_BUF_SIZE)
- {
- usbdRxWrPt=swRdCnt;
- //usbdRxWrPt=0;
- }
- if(usbdRxRdPt<=usbdRxWrPt)
- usbdRxCnt=usbdRxWrPt-usbdRxRdPt;
- else
- usbdRxCnt=USBD_GLOBALS_BUF_SIZE-usbdRxRdPt+usbdRxWrPt;
- if( buflen > usbdRxCnt)
- saveCnt=cnt=usbdRxCnt;
- else
- saveCnt=cnt=buflen;
- if (usbdRxCnt == 0) // No data to read
- {
- USBDMSG(1, (TEXT("[R0]")));
- }
- else
- {
- USBDMSG(1, (TEXT("<%d>"),cnt));
- while(cnt--)
- {
- *pRxBuffer++ = cRxChar = (UCHAR)usbdRxBuf[usbdRxRdPt++];
- if(usbdRxRdPt==USBD_GLOBALS_BUF_SIZE)
- usbdRxRdPt=0;
- if( cRxChar == cEvtChar )
- fRXFlag = TRUE;
- }
- (*pBuffLen)=saveCnt;
- usbdRxCnt-=saveCnt;
- usbdShMem->usbdRxRdPt=usbdRxRdPt;
- usbdShMem->usbdEir&=~USBDEIR_EP4;
- }
- //not be needed. Only for test
- if(pHWHead->pUSBCtrlAddr->OFCR1.out_cnt_low==0 )
- if(pHWHead->pUSBCtrlAddr->OCSR1.out_pkt_rdy==1)
- {
- USBDMSG(1, (TEXT("__OPR__(NEVER EXECUTED)")));
- UDC_REG_BITSET(struct OCSR1Bits,&pHWHead->pUSBCtrlAddr->OCSR1, out_pkt_rdy, 0);
- }
- // If we didn't read the whole buffer we need to come back. Leave with
- // the interrupt still enabled so the MDD will recall.
- if (usbdRxCnt>0)
- {
- USBDMSG(1, (TEXT("[%d->MDD]"),usbdRxCnt));
- usbdShMem->usbdEir|=USBDEIR_EP4;
- // MDD will recall RxIntHandler by chekcing SC2440_USB_GetInterruptType().
- // So, usbdShMem->usbdEir:USBDEIR_EP3 must not be cleared //:-)
- //Sleep(100);
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->INDEX=saveIndex;
- return fRXFlag;
- }
- usbdShMem->usbdEir&=~USBDEIR_EP4;
- DEBUGMSG(1, (TEXT("--SC2440_USB_RxIntHandlerrn")));
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->INDEX=saveIndex;
- return fRXFlag;
- }
- /*************************************************************************
- SC2440_USB_TxIntHandler
- Send the next packet to the USB. The first packet gets sent by directly
- calling this function (via dispatch table) from the MDD. After the first
- call the interrupt mechanism will keep things going.
- We return the actual number of bytes we've queued to the UDC. Note that
- until the next interrupt we wont know if it has been transmitted. We'll
- deal with the failure by saving the original packet and retransmitting if
- we get an error. In that case we'll return 0 as the number of bytes sent
- since no new bytes have been consumed from the caller's buffer.
- When the packet is accepted we return the number of bytes and grab the
- next packet (or portion thereof).
- *************************************************************************/
- //:-)
- void SC2440_USB_TxIntHandler( PSER_INFO pHWHead,
- PUCHAR pTxBuffer,
- ULONG *pBuffLen )
- {
- unsigned int i;
- UCHAR ucLen;
- BYTE saveIndex;
- //DEBUGMSG(1, (TEXT("++SC2440_USB_TxIntHandlerrn")));
- //USBDMSG(1, (TEXT("<T:%d>"),*pBuffLen));
- usbdShMem->usbdEir&=~USBDEIR_EP1;
- // Endpoint 1 mode
- saveIndex=*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->INDEX;
- UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x1);
- //pHWHead->pUSBCtrlAddr->INDEX.index=0x1; //:-)
- pHWHead->CommErrors &= ~CE_TXFULL;
- // If nothing to send, just return after clearing interrupt.
- if (! *pBuffLen )
- {
- //DEBUGMSG (1, (TEXT("[TX:nothing to send]")));
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->INDEX=saveIndex;
- return;
- }
- // Don't try to send more than EP1 can handle.
- if( *pBuffLen > EP1Len )
- ucLen = EP1Len;
- else {
- // If we end exactly on a packet boundary, the host doesn't
- // realize there is no more data. So if we exactly fill the final
- // packet, truncate it so we can send a short packet next frame
- // indicating end of the transmission
- if( *pBuffLen == EP1Len )
- {
- //USBDMSG (1, (TEXT("Tx breaking packetrn")));
- ucLen = EP1Len - 2;
- } else {
- ucLen = (UCHAR)*pBuffLen;
- }
- }
- if (!pHWHead->pUSBCtrlAddr->EP0ICSR1.opr_ipr)
- {
- // Write to the FIFO directly to send the bytes.
- for (i=0; i < ucLen; i++)
- {
- IOW_REG_FIELD(struct EP1FBits,
- &pHWHead->pUSBCtrlAddr->EP1F, fifo_data, *pTxBuffer++);
- }
- // Return number of bytes transmitted via pBuffLen.
- *pBuffLen = ucLen;
- UDC_REG_WRITE(struct EP0ICSR1Bits, &pHWHead->pUSBCtrlAddr->EP0ICSR1, opr_ipr, 1);
- } else {
- // Transmit already in progress. Just return and wait for current
- // transmission to complete before sending more.
- //USBDMSG(0, (TEXT("Write Pend !!!rn")));
- *pBuffLen = 0;
- }
- //DEBUGMSG(0, (TEXT("--SC2440_USB_TxIntHandlerrn")));
- *(volatile BYTE *)&pHWHead->pUSBCtrlAddr->INDEX=saveIndex;
- }
- BOOL
- HW_PowerOff(
- PSER_INFO pHWHead
- )
- {
- pHWHead->State = OFF;
- // cache the interrupt regs
- pHWHead->cIntStat_uir = *(BYTE *)&pHWHead->pUSBCtrlAddr->UIR;
- pHWHead->cIntStat_eir = *(BYTE *)&pHWHead->pUSBCtrlAddr->EIR;
- // disable the USB Clocks
- EnterCriticalSection(&pHWHead->HwRegCritSec);
- //DEBUGMSG(1, (TEXT("USB:HW_PowerOff()rn")));
- //RETAILMSG(1, (TEXT("USB:HW_PowerOff()rn")));
- HW_USBClocks(pHWHead);
- LeaveCriticalSection(&pHWHead->HwRegCritSec);
- return TRUE;
- }
- BOOL
- HW_PowerOn(
- PSER_INFO pHWHead
- )
- {
- pHWHead->State = RESUME;
- // enable the USB Clocks
- EnterCriticalSection(&pHWHead->HwRegCritSec);
- //DEBUGMSG(1, (TEXT("USB:HW_PowerOn()rn")));
- //RETAILMSG(1, (TEXT("USB:HW_PowerOn()rn")));
- HW_USBClocks(pHWHead);
- LeaveCriticalSection(&pHWHead->HwRegCritSec);
- SetInterruptEvent(pHWHead->pHWObj->dwIntID);
- return TRUE;
- }
- VOID
- HW_USBClocks(PSER_INFO pHWHead)
- {
- if ((pHWHead->State == IDLE) || (pHWHead->State == RESUME))
- {
- DEBUGMSG(1, (TEXT("HW_USBClocks::IDLErn")));
- //
- // Enable the USB Clocks
- //
- pHWHead->pCLKPWR->rCLKCON |= (1<<7);
- DEBUGMSG(ZONE_INIT, (TEXT("rCLKCON: 0x%Xrn"), pHWHead->pCLKPWR->rCLKCON));
- // Fin=12MHz, Fout=48MHz
- //pHWHead->pCLKPWR->rUPLLCON = 0x48032; // ((0x48 << 12) + (0x3 << 4) + 0x2)
- //DEBUGMSG(ZONE_INIT, (TEXT("rUPLLCON: 0x%Xrn"), pHWHead->pCLKPWR->rUPLLCON));
- //
- // MISCCR: USBD Pads, Normal mode
- //
- pHWHead->pIrqCtrlAddr->rMISCCR &= ~((3 << 12) | (1 << 3));
- // TO DO :
- // Enable USB_PULLUP on GPIO PIN (tied to USB D+) & set high
- //
- //pHWHead->pIrqCtrlAddr->rGPBCON &= ~(3 << 18); // clear GPE15
- //pHWHead->pIrqCtrlAddr->rGPBCON |= (1 << 18); // config as output
- //pHWHead->pIrqCtrlAddr->rGPBUP &= ~(1 << 9); // pullup disabled
- //pHWHead->pIrqCtrlAddr->rGPBDAT |= (1 << 9); // set high
- pHWHead->pIrqCtrlAddr->rGPGCON &= ~(3 << 24); // clear GPE15
- pHWHead->pIrqCtrlAddr->rGPGCON |= (1 << 24); // config as output
- pHWHead->pIrqCtrlAddr->rGPGUP &= ~(1 << 12); // pullup disabled
- pHWHead->pIrqCtrlAddr->rGPGDAT |= (1 << 12); // set high
- DEBUGMSG(ZONE_INIT, (TEXT("rGPDCON: 0x%Xrn"), pHWHead->pIrqCtrlAddr->rGPDCON));
- DEBUGMSG(ZONE_INIT, (TEXT("rGPDUP: 0x%Xrn"), pHWHead->pIrqCtrlAddr->rGPDUP));
- DEBUGMSG(ZONE_INIT, (TEXT("rGPDDAT: 0x%Xrn"), pHWHead->pIrqCtrlAddr->rGPDDAT));
- }
- else if (pHWHead->State == OFF)
- {
- DEBUGMSG(1, (TEXT("HW_USBClocks::OFFrn")));
- //
- // Disable the USB Clocks
- //
- pHWHead->pCLKPWR->rCLKCON &= ~(1<<7);
- DEBUGMSG(ZONE_INIT, (TEXT("rCLKCON: 0x%Xrn"), pHWHead->pCLKPWR->rCLKCON));
- // Fin=12MHz, Fout=48MHz
- //pHWHead->pCLKPWR->rUPLLCON = 0;
- // MISCCR: USBD Pads, Suspend mode
- pHWHead->pIrqCtrlAddr->rMISCCR |= (3 << 12);
- // TO DO :
- // Disable USB_PULLUP to remove us from the bus
- //pHWHead->pIrqCtrlAddr->rGPBCON &= ~(3 << 18); // clear GPE15
- //pHWHead->pIrqCtrlAddr->rGPBCON |= (1 << 18); // config as output
- //pHWHead->pIrqCtrlAddr->rGPBUP |= (1 << 9); // pullup disabled
- //pHWHead->pIrqCtrlAddr->rGPBDAT &= ~(1 << 9); // set low
- pHWHead->pIrqCtrlAddr->rGPGCON &= ~(3 << 24); // clear GPE15
- pHWHead->pIrqCtrlAddr->rGPGCON |= (1 << 24); // config as output
- pHWHead->pIrqCtrlAddr->rGPGUP |= (1 << 12); // pullup disabled
- pHWHead->pIrqCtrlAddr->rGPGDAT &= ~(1 << 12); // set low
- DEBUGMSG(ZONE_INIT, (TEXT("rUPLLCON: 0x%Xrn"), pHWHead->pCLKPWR->rUPLLCON));
- }
- }
- // :-)
- /***************************************
- Added routines for USBD Rx:DMA Tx:ISR
- ***************************************/
- BOOL InitUsbdDriverGlobals(void)
- {
- BOOL Ret;
- int i;
- if ( v_pDriverGlobals == NULL )
- {
- v_pDriverGlobals =(PDRIVER_GLOBALS)VirtualAlloc( 0,
- DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,
- MEM_RESERVE,
- PAGE_NOACCESS);
- if ( v_pDriverGlobals == NULL )
- {
- USBDMSG( 1, (TEXT( "InitUsbdDriverGlobals : VirtualAlloc failed!rn")) );
- return ( FALSE );
- }
- Ret = VirtualCopy( (LPVOID)v_pDriverGlobals,
- (LPVOID)DRIVER_GLOBALS_PHYSICAL_MEMORY_START,
- DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,
- PAGE_READWRITE | PAGE_NOCACHE
- );
- if ( Ret == FALSE )
- {
- DEBUGMSG( ZONE_ERROR, (TEXT( "InitUsbdDriverGlobals: VirtualCopy failed!rn")) );
- if ( v_pDriverGlobals )
- {
- VirtualFree( v_pDriverGlobals,
- DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE ,
- MEM_RELEASE
- );
- v_pDriverGlobals = NULL;
- }
- return ( FALSE );
- }
- }
- usbdShMem=&(v_pDriverGlobals->usbd);
- for(i=0;i<USBD_GLOBALS_BUF_SIZE;i++)
- {
- usbdShMem->usbdRxBuf[i]=0x0;
- //usbdShMem->usbdTxBuf[i]=0x0;
- }
- usbdShMem->usbdRxRdPt=0;
- usbdShMem->usbdRxWrPt=0;
- usbdShMem->usbdRxCnt=0;
- //usbdShMem->usbdTxRdPt=0;
- //usbdShMem->usbdTxWrPt=0;
- //usbdShMem->usbdTxCnt=0;
- usbdShMem->usbdEir=0;
- usbdShMem->usbdUir=0;
- usbdShMem->usbdDma3Int=0;
- //usbdShMem->usbdMddRxCnt=0;
- USBDMSG( 1, (TEXT( "USBD:DRIVER_GLOBALS is initializedrn")) );
- return( TRUE );
- }
- BOOL UsbdAllocateVm(void)
- {
- if(v_pDMAregs == NULL)
- {
- v_pDMAregs = (volatile DMAreg *)
- VirtualAlloc(0,sizeof(DMAreg),MEM_RESERVE, PAGE_NOACCESS);
- if(v_pDMAregs == NULL)
- {
- ERRORMSG(1,(TEXT("For DMAreg: VirtualAlloc failed!rn")));
- return (FALSE);
- }
- else
- {
- if(!VirtualCopy((PVOID)v_pDMAregs,(PVOID)(DMA_BASE),sizeof(DMAreg),
- PAGE_READWRITE | PAGE_NOCACHE ))
- {
- ERRORMSG(1,(TEXT("For pIOPregs: VirtualCopy failed!rn")));
- UsbdDeallocateVm();
- return (FALSE);
- }
- }
- }
- if(v_pINTregs == NULL)
- {
- v_pINTregs = (volatile INTreg *)
- VirtualAlloc(0,sizeof(INTreg),MEM_RESERVE, PAGE_NOACCESS);
- if(v_pINTregs == NULL)
- {
- ERRORMSG(1,(TEXT("For INTreg: VirtualAlloc failed!rn")));
- return (FALSE);
- }
- else
- {
- if(!VirtualCopy((PVOID)v_pINTregs,(PVOID)(INT_BASE),sizeof(INTreg),
- PAGE_READWRITE | PAGE_NOCACHE ))
- {
- ERRORMSG(1,(TEXT("For INTreg: VirtualCopy failed!rn")));
- return (FALSE);
- }
- }
- }
- return TRUE;
- }
- void UsbdDeallocateVm(void)
- {
- if(v_pDMAregs)
- {
- VirtualFree((void*)v_pDMAregs, sizeof(DMAreg), MEM_RELEASE);
- v_pDMAregs=NULL;
- }
- if(v_pINTregs)
- {
- VirtualFree((void*)v_pINTregs, sizeof(INTreg), MEM_RELEASE);
- v_pINTregs=NULL;
- }
- }
- void UsbdInitDma3(int bufIndex,int bufOffset)
- {
- //ULONG usbdRxRdPt,usbdRxWrPt;
- //If DMA3 is turned on, DMA3 should be turned off.
- if((v_pDMAregs->rDMASKTRIG3&(1<<1))!=0)
- {
- v_pDMAregs->rDMASKTRIG3=(1<<2); //DMA3 stop
- while(v_pDMAregs->rDMASKTRIG3&(1<<1)); //wait until DMA3 stop
- usbdShMem->usbdRxRdPt=0;
- USBDMSG( 1, (TEXT("[DMA3 is stopped]rn")));
- }
- v_pDMAregs->rDISRCC3 = (1<<1)|(1<<0); //src=APB, srcAddr=fixed
- v_pDMAregs->rDISRC3 = REAL_PHYSICAL_ADDR_EP4_FIFO; //srcAddr=EP4_FIFO
- v_pDMAregs->rDIDSTC3 = (0<<1)|(0<<0); //dst=AHB(memory),increase,
- #if (DRIVER_GLOBALS_PHYSICAL_MEMORY_START<0xA0000000 || DMA_BUFFER_BASE<0xA0000000)
- GENERATE_ERROR
- //The above two address should be non-cacheable area.
- #endif
- realPhysicalAddr_UsbdRxBuf =
- (ULONG)&((DRIVER_GLOBALS *)DRIVER_GLOBALS_PHYSICAL_MEMORY_START)->usbd.usbdRxBuf
- - DMA_BUFFER_BASE + DMA_PHYSICAL_BASE;
- //USBDMSG( 1, (TEXT( "[USBD:RPA_URxBuf=%x]"),realPhysicalAddr_UsbdRxBuf) );
- //Real physical address of usbdShMem->usbdRxBuf
- if(bufIndex==0)
- {
- v_pDMAregs->rDIDST3=realPhysicalAddr_UsbdRxBuf+0+bufOffset;
- }
- else
- {
- v_pDMAregs->rDIDST3=realPhysicalAddr_UsbdRxBuf+(USBD_GLOBALS_BUF_SIZE/2)+bufOffset;
- }
- v_pDMAregs->rDCON3=(USBD_GLOBALS_BUF_SIZE-bufOffset)|(1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(4<<24)|(1<<23)|(1<<22)|(0<<20);
- //handshake,requestor=APB,CURR_TC int enable,unit transfer,
- //single service,src=USBD,H/W request,no_autoreload,byte,CURR_TC
- v_pDMAregs->rDMASKTRIG3=(1<<1); //DMA 3 on
- USBDMSG( 1, (TEXT( "[USBD:rDIDST3=%x,rDCDST3=%x]rn"),v_pDMAregs->rDIDST3,v_pDMAregs->rDCDST3) );
- }