;************************************************************************** ;** ** ;** I N T E L P R O P R I E T A R Y ** ;** ** ;** COPYRIGHT (c) 1996, 1997 BY INTEL CORPORATION. ALL RIGHTS ** ;** RESERVED. NO PART OF THIS PROGRAM OR PUBLICATION MAY ** ;** BE REPRODUCED, TRANSMITTED, TRANSCRIBED, STORED IN A ** ;** RETRIEVAL SYSTEM, OR TRANSLATED INTO ANY LANGUAGE OR COMPUTER ** ;** LANGUAGE IN ANY FORM OR BY ANY MEANS, ELECTRONIC, MECHANICAL, ** ;** MAGNETIC, OPTICAL, CHEMICAL, MANUAL, OR OTHERWISE, WITHOUT ** ;** THE PRIOR WRITTEN PERMISSION OF : ** ;** ** ;** INTEL CORPORATION ** ;** ** ;** 2200 MISSON COLLEGE BLVD ** ;** ** ;** SANTA CLARA, CALIFORNIA 95052-8119 ** ;** ** ;************************************************************************** ; (C) Copyright Intel Corp., 1997 ; ; File: hub_ep0.asm ; ; Universal Serial Bus 930 Test firmware ; HUB ROM CODE Version ; ; ;*** NOTE to Programmer !!! ; Please change the Revision number in the device descriptor and in Serial # ; String Descriptor (String_3) at end of code. ; ; Revision History ; --------------------------------------------- ; 1.51 7-23-98 Paul Luse ; cleanup ; changed includes to absolute ; fixed Keil org statements to CSEG at ; 1.5 07-23-97 Chip Linthicum ; Changed VID from 8086 to 042B for INTEL for hub ; 1.4 07-14-97 Chip Linthicum ; Removed serial number - set to 0 for compliance ; with new MS Memphis Beta 1 stack ; 1.3 05-29-97 Chip Linthicum ; Changed HUB_FIRM.ASM to fix problem when the ; embedded function is disabled and host continued ; to see status changes on port 4. ; 1.2 05-12-97 Chip / Ken ; Changed ONE_OH.INC hub_desc to 29h ; 1.1 03-27-97 Charles H Linthicum Jr. ; Added HELSINKI switch for HELSINKI ROM code - ; enabling the fourth downstream port ; This code supports both Helsinki and Halifax ; and EVAL boards and FUB board. ; 1.0 03-19-97 Charles H Linthicum Jr. ; Moved all configuration switches to SWITCH.INC ; Added checking P1 bit 1 to determine if ; Embedded Function will be enabled or disabled ; Mode 1 FUB jumper: P1 Bit 1.1 = 1 = attached or enabled ; Mode 1 FUB jumper: P1 Bit 1.1 = 0 = not attached ; Fixed strings for embedded function. ; Changed code to work with Intel Compatibility turned on. ; Added interface string descriptor as index 5 ; Added display of SWITCH setup to display in the ; Configuration string descriptor ; Changed use of INTERNAL_PORT switch to be used by ; eval board setups to enable/disable the embedded ; function. ; 0.9 03-07-97 Charles H Linthicum Jr. ; Fixed Get Status to return correct status of ; part power - whether bus or self ; Added string for index 0 - English Lang. ID ; Added string for serial number = firmware rev ; Added configuration string to say "embedded fn disabled" ; Removed carriage returns from strings ; 0.8 03-05-97 Charles H Linthicum Jr. ; Added checking P1 bit 0 to determine if ; FUB HUB will be bus or self powered ; Bit 1.0 = 1 = Self Powered ; Bit 1.0 = 0 = Bus Powered ; fixed string descriptors ; Config 1 is self powered ; Config 2 is bus powered ; 0.7 02-13-97 Charles H Linthicum Jr. ; Added OHCI fix around setting TXCLR ; 0.6 12-03-96 Charles H Linthicum Jr. ; Added capability to enable LC toggle during heartbeat, by ; changing LC_TOGGLE assembler directive. ; 0.5 08-20-96 Kenneth Schultz ; Cleaned up stuff for hub and test out better. ; ; 0.4 08-01-96 Kenneth Schultz ; Cleaned up and documented better. Also added hooks for ; control write command Data Stages, & Hub. ; 0.3 07-15-96 Kenneth Schultz ; Converted to using A Register only for furture products. ; 0.2 06-29-96 Kenneth Schultz ; 0.1 05-27-96 Abdul Rahman Ismail ; ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ ;These two equate statements allow the user to switch between the PLC ;and Keil assemblers. Place a 1 on the assembler that is to be used to ;assemble this file. PLC EQU 1 KEIL EQU 0 ;======================================================================= ;= Includes ;======================================================================= IF PLC include "8X930HX.INC" include "SWITCH.INC" ENDIF IF KEIL $INCLUDE (Reg930.inc) $INCLUDE (SWITCH.INC) ENDIF IF DOUG == USE ; Use DOUG routines INCLUDE "c:\include\flags.inc" SV equ ENABLED ARCH equ 251 PROC equ i8X930HX INCLUDE "c:\include\sv.inc" ; DON'T use DOUG ENDIF ;======================================================================= ;= Equates ;======================================================================= FIFO_SIZE equ 008h GET_COMMAND equ 080h EP1_TX_FIFO_SIZE equ 20h ; 32 bytes EP2_TX_FIFO_SIZE equ 08h ; 8 bytes SETUP_PHASE equ 000h DATA_PHASE equ 001h STATUS_PHASE equ 002h EP0_MAX_PACKET_SIZE equ 08h NULL_DATA_PACKET equ 000h ;======================================================================= ;= External Routines / Code ;======================================================================= IF PLC extern GetClassDeviceCommand:CODE extern GetClassOtherCommand:CODE extern SetClassDeviceCommand:CODE extern SetClassOtherCommand:CODE extern InitilizeHubVariables:CODE extern InitilizeEmbeddedFunction:CODE extern FifoWatchDog:CODE ENDIF IF KEIL extern CODE (GetClassDeviceCommand) extern CODE (GetClassOtherCommand) extern CODE (SetClassDeviceCommand) extern CODE (SetClassOtherCommand) extern CODE (InitilizeHubVariables) extern CODE (InitilizeEmbeddedFunction) extern CODE (FifoWatchDog) ENDIF public LoadBuffer public gbFControlBufferLocation public EmbeddedFunctionInReset public RightCylon, LeftCylon IF PLC xdef bRequest xdef wValue xdef wIndex extern FUNCTION_ISR:CODE extern SV_SOF_ROUTINE extern EmbeddedFunctionSofRoutine:CODE extern FUNCTION_SUSPEND_ROUTINE:CODE, FUNCTION_RESUME_ROUTINE:CODE extern STACK_DATA:PDATA ENDIF IF KEIL public bRequest public wValue public wIndex extern CODE (FUNCTION_ISR) extern CODE (SV_SOF_ROUTINE) extern CODE (EmbeddedFunctionSofRoutine) extern CODE (FUNCTION_SUSPEND_ROUTINE), CODE (FUNCTION_RESUME_ROUTINE) extern EDATA (STACK_DATA) ENDIF IF PLC extern VendorGetDeviceCommandExec:CODE ENDIF IF KEIL extern CODE (VendorGetDeviceCommandExec) ENDIF public FwValue, RWUTimer public EMBD_FN_FLG ;------------------------------------------------------ ;---------- Device Configuration Bytes -------------- ;------------------------------------------------------ IF DOUG == USE DEFINE CCB_SEGMENT, SPACE=CODE, ORG=0FFfff8H ELSE IF PLC DEFINE CCB_SEGMENT, SPACE=CODE, ORG=0FF7ff8H ENDIF IF KEIL CCB_SEGMENT SEGMENT CODE AT 07ff8H ENDIF ENDIF IF RISM == DISABLED IF FUB_BOARD == DISABLED RSEG CCB_SEGMENT db 0D2h ;Original Binary Mode- NON PAGED MODE ;db 0D3h ;Original Source Mode- NON PAGED MODE - chl testing ... ;db 0D1h ;Original Source Mode- PAGED MODE - chl testing ... db 0F7h ELSE ;FOR FUB BOARD USE THE FOLLOWING CCBS. rseg CCB_SEGMENT db 0D2h ;Original Binary Mode - Paged Mode db 0F7h ENDIF ELSE ; If RISM is enabled then there is no need for CCBs ENDIF ;---------------------------------------------------- ;- Reset Segment is ORGed at 00, but the linker will ;- Place the reset of the signigiant figures ;---------------------------------------------------- ;----------------------------------------------------- ;---------- Interrupt Vectors -------------------- ;----------------------------------------------------- IF PLC public END_VECTORS,RESET_VECTOR ENDIF IF RISM == ENABLED IF PLC DEFINE VECTOR_SEG, SPACE=CODE, ORG=004000h ENDIF IF KEIL VECTOR_SEG SEGMENT CODE AT 004000H ENDIF ELSE IF PLC DEFINE VECTOR_SEG, SPACE=CODE, ORG=0FF0000h ENDIF IF KEIL VECTOR_SEG SEGMENT CODE AT 0FF0000H ENDIF ENDIF IF PLC SEGMENT VECTOR_SEG RESET_VECTOR: LJMP main INT0_VECTOR: LJMP $ ds 5 TIM0_VECTOR: LJMP $ ds 5 INT1_VECTOR: LJMP $ ds 5 TIM1_VECTOR: LJMP $ ds 5 SER_VECTOR: LJMP $ ds 5 TIM2_VECTOR: LJMP $ ds 5 PCA_VECTOR: LJMP $ ds 13 SOF_VECTOR: LJMP SOF_ISR ds 5 USB_FUNC_VECTOR: LJMP FUNCTION_ISR ds 5 SUS_RSM_VECTOR: LJMP SUSPEND_RESUME_ISR ds 25h TRAP_VECTOR: LJMP $ ENDIF IF KEIL ;USB interrupts and the jump to the service routines RSEG VECTOR_SEG CSEG AT 0 LJMP MAIN CSEG AT 043H LJMP SOF_ISR CSEG AT 04BH LJMP FUNCTION_ISR CSEG AT 053H LJMP SUSPEND_RESUME_ISR ENDIF END_VECTORS: IF RISM == ENABLED IF PLC DEFINE HUB_EP0_CODE_SEGMENT, SPACE=CODE, ORG = 004080H ENDIF IF KEIL HUB_EP0_CODE_SEGMENT SEGMENT CODE AT 004080H ENDIF ELSE IF PLC DEFINE HUB_EP0_CODE_SEGMENT, SPACE=CODE, ORG= 0FF0080H ENDIF IF KEIL HUB_EP0_CODE_SEGMENT SEGMENT CODE AT 0FF0080H ENDIF ENDIF IF PLC SEGMENT HUB_EP0_CODE_SEGMENT ENDIF IF KEIL RSEG HUB_EP0_CODE_SEGMENT ENDIF ;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ;M---------------------------------------------------------------------M ;M MAIN M ;M---------------------------------------------------------------------M ;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM main: mov SP, #LOW (STACK_DATA) mov SPH, #HIGH(STACK_DATA) ; Set the stack to start @ 00:0500h mov DPXL, #0ffh ; Set DPXL to point at the FLASH device ; to access constants inc FTLOCK_FLG IF DOUG == USE lcall lc_init ; set LC bit according to DOUG setting mov DPTR, #Header lcall puts mov WR16, #0FFFFh mov WR18, #HEX_DSP_32 mov A, #0FFh mov @DR16 ,R11 mov WR18, #HEX_DSP_54 mov @DR16 ,R11 mov EP0_ERROR_CNT, #0 mov FTLOCK_FLG, #0 ENDIF lCall INIT_VARIABLES ; Initialize the RAM space as required lCall INIT_USB Lcall InitilizeHubVariables ;---------------------------------------- ;--- Enable Function Interrupts ;---------------------------------------- ;---------------------------------------- ;--- Enable HUB Interrupts ;---------------------------------------- mov EPINDEX, #80h ; Select Hub EP1 mov EPCON, #03fh ; CNTL, ENable all mov HIE, #03h ; Enable the USB Function HUB EP0 setb IEN1.0 ; Enable HUB/SOF ISR mov EPINDEX, #00h ; Resume is set here mov RWUTimer, #00h ; CLear RWU Timer mov EmbeddedFunctionInReset, #00h ; Used to track when we are sending a reset to the Embdeeded function. setb IEN1.2 ; ENable Suspend/Resume ISR setb EA ; Enable Interrupts. SETB LC ; (kls) SET LC will reduce current draw ; by dropping the clk frequency by 75% ; Default mode.. ljmp ActiveLoop ;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ;A---------------------------------------------------------------------A ;A ACTIVE LOOP A ;A---------------------------------------------------------------------A ;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ;COMMENT *------------------------------------------------------------ ;Function name : ActiveLoop ;Brief Description : This routine simply sets and clears HEARTBEAT_LED P1.3 at a periodic rate ; : It purpose is to let the user know the part is alive. ; : If a FUB board is being used this routine will also poll the ; : embedded function switch on the switch port to "enable" the ; : embedded function. ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE ActiveLoop: IF DOUG == USE mov A, P1 mov WR16, #0FFFFh mov WR18, #HEX_DSP_10 mov @DR16 ,R11 mov WR18, #HEX_DSP_76 ENDIF IF FUB_BOARD == ENABLED MOV A, SWITCH_PORT jnb EMBD_FN_SWITCH, NO_EMBD_FN mov R11, EMBD_FN_FLG jnz NO_EMBD_FN push HPINDEX mov HPINDEX, #EMBEDDED_PORT_NUMBER ; EMBEDDED fn on port #4 setb PCSC pop HPINDEX mov A, #02h mov EMBD_FN_FLG, R11 ELSE ; If not a FUB board - use the INTERNAL_PORT switch to enable/disable the ; embedded function. IF INTERNAL_PORT == ENABLED mov R11, EMBD_FN_FLG ; check value of flag cjne A, #02h, SHOW_EMB_FN sjmp ALREADY_SHOWED_EMB_FN SHOW_EMB_FN: push HPINDEX mov HPINDEX, #EMBEDDED_PORT_NUMBER ; EMBEDDED fn on port #4 setb PCSC pop HPINDEX mov A, #02h mov EMBD_FN_FLG, R11 ENDIF ENDIF ALREADY_SHOWED_EMB_FN: NO_EMBD_FN: ;------------------------------------------------------------------ ;-- Heart Beat ;------------------------------------------------------------------ HeartBeat: IF LC_TOGGLE == ENABLED ; if HC/LC ENABLED toggle LC bit cpl LC ENDIF ; ************* Heartbeat visual LED **************** mov WR0, Heart1 inc WR0, #1 mov Heart1, WR0 cmp WR0, #7FFFh jl ClearBit setb HEARTBEAT_LED sjmp ActiveLoop ClearBit: clr HEARTBEAT_LED sjmp ActiveLoop ;---------------------------------------------------------------- ;SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS ;SS SUSPEND/RESUME ISR ;SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS ;---------------------------------------------------------------- ;COMMENT *------------------------------------------------------------ ;Function name : SUSPEND_RESUME_ISR ;BrieS Description : Service the SUSPEND_RESUME Interrupt ; : ;Regs preserved : Reg. A, B & EPINDEX are saved ;--------------------------------------------------------------------* ;SCOPE SUSPEND_RESUME_ISR: push PSW push PSW1 lcall FUNCTION_SUSPEND_ROUTINE push ACC push DR0 JNB GSUS,REALSUSPEND RETI REALSUSPEND: mov R11, RWUTimer ; If timmer is zero, do a normal suspend. orl R11, RWUTimer+1 JZ DoSuspend ; Otherwise wait a delay and then resume. DoRWU: push WR2 mov WR2, RWUTimer mov WR0, #0 WaitLoop: dec DR0, #1h jne WaitLoop setb RWU D1: jb RWU, D1 ; Wait until RWU is done. pop WR2 sjmp RESUME_CODE DoSuspend: setb PD nop nop RESUME_CODE: lcall FUNCTION_RESUME_ROUTINE ; Let function know that a resume signal was detected. clr GRSM ; CLear Resume Flag clr GSUS ; CLear Suspend Flag pop DR0 pop ACC pop PSW1 pop PSW reti ;---------------------------------------------------------------- ;SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS ;SS SOF ISR ;SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS ;---------------------------------------------------------------- ;COMMENT *------------------------------------------------------------ ;Function name : SOF_ISR ;Brief Description : Service the SOF_ISR Interrupt ; : This routine simply displays the upper three bytes of the ; : SOF in the lower three bits of the LEDs on P1. ; : It does not affect the other LEDS. Very usefull ; : in determining when the function is receiveing SOFs ;Regs preserved : Reg. A is saved ;--------------------------------------------------------------------* ;SCOPE SOF_ISR: push PSW push PSW1 push R11 jnb ASOF, ExitSofIsr ; If this ASOF bit not set, the ISR could be a HUB. Go Check. lcall EmbeddedFunctionSofRoutine ExitSofIsr: ; The HX shares this ISR with the hub. ; Check to see if there is a HUB pending ISR ; By checking this last, we give the SOF interrupt ; higher priority. jb HRXD0, HUB_ISR ; jb HTXD0, HUB_ISR ExitSofAndHubISR: pop R11 pop PSW1 pop PSW reti ;---------------------------------------------------------------- ;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH ;HH HUB ISR ;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH ;---------------------------------------------------------------- ;COMMENT *------------------------------------------------------------ ;Function name : HUB_ISR ;Brief Description : Service the HUB_ISR Interrupt ; : This routine scans the interrupt pending bits in order ; : and branches to any routines that have pending interrupts. ; : After finishing the routine jumps back to the top of ; : the scanning loop to preserve interrupt priority. ; : ; : NOTE: The order of precidence is set by the order in which the ; : user places the checks. ; : ;Regs preserved : Reg. A, B & EPINDEX are saved ;--------------------------------------------------------------------* ;SCOPE HUB_ISR: push ACC push B push EPINDEX ProcessHubEndpoints: H_EP0: mov A, HIFLG ; First check to see if this is EP0 Command anl A, #03h ; As they require extra overhead. Mask off all but EP0 Interrupts jz ExitHub ;---------------------------------------------------------------- ;-- Process the EP0 COmmand in the correct order ;---------------------------------------------------------------- ; If this an EP0 command then we need to process TX & RX ; ISRs in the correct order if, for whatever reason they occurred ; back to back. This happens in OHCI systems. mov A, gbSetupSeqTX cjne A, #SETUP_PHASE, CheckDataStatusStage sjmp DoRxFirst ; If the status stage is Setup then check the RX First. CheckDataStatusStage: ; Now check to see what stage the TX is in. ; If it is in the data stage then check it first. ; If it's in the status stage then check the RX first. cjne A, #DATA_PHASE, DoRxFirst ; If current stage a data stage->a control read ; and we should process TX before RX ISR ;---------------------------------------------------------------- ;-- Process the TX FIFO first ;---------------------------------------------------------------- DoTxFirst: H_EP0_TXA: jnb HTXD0, H_EP0_RXA mov EPINDEX,#80h lCall ProcessInToken ; 82930 has sent a packet to HC ljmp ProcessHubEndpoints ; Look at all Interrupt flags again H_EP0_RXA: jnb HRXD0, ExitHub mov EPINDEX,#80h lCall ProcessOutToken ; 82930 has received a packet from HC ljmp ProcessHubEndpoints ; Look at all Interrupt flags again ;-------------------------------------------------------------------------------- DoRxFirst: ;---------------------------------------------------------------- ;-- Process the RX FIFO first ;---------------------------------------------------------------- H_EP0_RXB: jnb HRXD0, H_EP0_TXB mov EPINDEX,#80h lCall ProcessOutToken ; 82930 has received a packet from HC ljmp ProcessHubEndpoints ; Look at all Interrupt flags again H_EP0_TXB: jnb HTXD0, ExitHub mov EPINDEX,#80h lCall ProcessInToken ; 82930 has sent a packet to HC ljmp ProcessHubEndpoints ; Look at all Interrupt flags again ;-------------------------------------------------------------------------------- ;------------------------------------------------------------------------------ ;---------------------------------------------------------------- ;-- Process the Other EPs next ;---------------------------------------------------------------- NonEp0ISR: ExitHub: pop EPINDEX pop B pop ACC sjmp ExitSofAndHubISR ; pop PSW1 ; pop PSW ; ; reti ;COMMENT *------------------------------------------------------------ ;Function name : ProcessOutToken ;Brief Description : Services all OUTs on EP0. ; : This routine checks to see if this is an OUT token oor ; : SETUP token. If a SETUP token then the Control COmmand ; : State machine is initilized to SETUP STAGE ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE ProcessOutToken: mov A, EPINDEX jb ACC.7, HubCommand HubCommand: anl HIFLG, #EP0_RX_CLR ; Clear the interrupt bit. ProcCommand: mov A, RXSTAT jnb ACC.6, CheckOutStatusPhase ; Is this a setup packet?? ; Now Check for Data still in FIFO. ; If this is true then the function ; did not see the ACK form the host. mov A, TXFLG anl A, #0C0h jZ NoEP0Error setb TXCLR mov TXCNTL, #00h ; OHCI fix for device Errata setb TXCLR ; OHCI fix for device Errata inc EP0_ERROR_CNT NoEP0Error: anl EPCON, #03Fh ; If a stall was set on EP0, this will clear it ; as stated in the new updates of the spec. lCall SetupReceived anl RXSTAT, #0BFh sjmp ReturnProcessOutToken CheckOutStatusPhase: mov A, gbSetupSeqRX cjne A, #STATUS_PHASE, CheckDataPhase ; Is this the status phase of a "GET" ; command? setb RXFFRC ; Update receive FIFO state setb TXCLR ; Flush the Transmit FIFOS in case ; a null packet is still left. mov TXCNTL, #00h ; OHCI fix for device Errata setb TXCLR ; OHCI fix for device Errata mov A, #SETUP_PHASE ; Update the state machine-Expect ; a setup packet mov gbSetupSeqRX, A mov gbSetupSeqTX, A ljmp ReturnProcessOutToken ;--------------------------------------------------------------- ; - Control Write Data Stage ;--------------------------------------------------------------- ; If this is a control write command with a datastage then this ; routine will belcalled on all data stages of the control write. ; When all the data has been collected(Bytes received=wLength) ; the actual routine is called. The size of data is limited to this ; buffer length. ; THE CALLING CODE MUST THEN CALL SetUpControlWriteStatusStage to allow ; the status stage to continue. The user must NOT do this themselves. ; Later in the life of this code, other features will be added here. CheckDataPhase: cjne A, #DATA_PHASE, ReturnProcessOutToken ; Are we processing a Control Write, ; i.e. Set Descr... ; Added to handle control writes with data stages. ; When a control Write with a data stage is detected ; the data is placed in the buffer 'CntlWriteDataBuffer' ; When all the data ; has been collected(Bytes received=wLength) the actual routine is ; called. The size of data is limited to this buffer length. ;--------------------------------------------------------- ;------------------- NOTE -------------------------------- ;--------------------------------------------------------- ; For this routine to work all the data must be stored below ; 100h as I am using byte addressing. Also, since 80-FF is used ; as SFRs and I don't want to for the user to use indirect ; addressing, the data must ne stored between 20h-7Fh. ; Also, these routines will only work for data sets of less than ; 256. But the above limitations put this the max much ower than ; this. MaxBuffer = (7F-20h-Other varaibles in this region) push R0 mov A, #CntlWriteDataBuffer ; Get location of buffer add A, CntlWriteDataPntr ; Add the offset mov R0, A ; R0 now contains the location to start storing the ; data. ; Update the data stored in memory mov A, RXCNTL ; Get number of bytes to move add A, CntlWriteDataPntr ; Add number received mov CntlWriteDataPntr, A ; update memory variable mov A, RXCNTL JZ RdDone ; If no data in the buffer, then exit. ReadData: mov @R0, RXDAT ; Get the data and store it. inc R0 djnz ACC, ReadData pop R0 RdDone: setb RXFFRC ; Update receive FIFO state ; Now check to see if this was the last ; read by checking if (Bytes received=wLength) mov A, CntlWriteDataPntr cjne A, wLength+1, NeedMoreData ; If this is not equal to the expected, then jmp around. ; When all the data has been received, the ; other routines in this program will ; be called to process it. ProcessControlWriteData: push DPX ; Processing the jump table will ; corrupt DPX. Save it here lcall DoJumpTable ; At this point all data has been ; stored and all we need to do now is to ; process it. pop DPX ; Restore DPX ljmp ReturnProcessOutToken NeedMoreData: CheckCommand2: ReturnProcessOutToken: Ret ;COMMENT *------------------------------------------------------------ ;Function name : SetupReceived ;Brief Description : Service all Setup Tokens recd. on EP0 ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE SetupReceived: mov A, RXCNTL ; Get the no. of bytes clr CY subb A, #8 ; 8 is length of all setup packets. JNZ ReturnSetup ; If less than 8 bytes recd. ; Return ; Since buffer will reside within the ; the first 255 bytes, I can use ; register indirect addressing ; Move FIFO to command buffer. ; Notice byte swapping of word fields ; For Word Fields make USB Little Endian words->'251 Big Endian words clr EDOVW mov COMMAND_BUFFER, RXDAT ; bmRequestType mov COMMAND_BUFFER+1, RXDAT ; bRequest mov COMMAND_BUFFER+3, RXDAT ; wValue LSB mov COMMAND_BUFFER+2, RXDAT ; wValue MSB mov COMMAND_BUFFER+5, RXDAT ; wIndex LSB mov COMMAND_BUFFER+4, RXDAT ; wIndex MSB mov COMMAND_BUFFER+7, RXDAT ; wLength LSB mov COMMAND_BUFFER+6, RXDAT ; wLength MSB setb RXFFRC ; Update receive FIFO state clr RXSETUP push DPX ; Processing the jump table will ; corrupt DPX. Save it here lCall ProcessSetup pop DPX ; Restore DPX ReturnSetup: Ret ;COMMENT *------------------------------------------------------------ ;Function name : ProcessSetup ;Brief Description : Process a Setup token recd. on EP0. Thile some of the ; : code may look sifficult to understand the end result is not. ; : The following simply prepares a byte of data for use in a jump table. ; : The code compresses the 8 byte bmRequestValue into 4 1/2 ; : bits by removing bits 2,3 & 4. These bits are never used ; : and it allows the jump table to be signfigantly smaller. ; : By using this jump table, the code size reduces by several ; : hundred bytes over the entire code! ; : THIS FIRMWARE IS ASSUMES BITS 2,3 & 4 are zero!!!! ; : By compressing the byte down, we limit the size ; : of the jump table. ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE ProcessSetup: ; The First step is setting up the Stage tracing variable by examing the ; bmRequest value. This will tell us if this is a control Write ; or control read command. For right now we will assume that this ; is a no data command and will therefore pre-initilize the data ; byte counters used to send data back, to zero. mov gbFControlBufferBytesLeft, #00h mov gbFControlBufferBytesLeft + 1, #00h mov A, bmRequestType jb ACC.7, SetupGetCommand SetupSetCommand: mov gbSetupSeqRX, #DATA_PHASE ; Advance State Machine to next state mov gbSetupSeqTX, #STATUS_PHASE ; Now check to see if this is a control write with a data stage. mov A, wLength orl A, wLength+1 jz DoJumpTable ; If this is a no data command then process it ret ; If we are expecting data then don't ; process the command yet. Exit and wait ; for the rest of the data to come in. SetupGetCommand: mov gbSetupSeqRX, #STATUS_PHASE ; Advance State Machine to next state mov gbSetupSeqTX, #DATA_PHASE DoJumpTable: ; This table will jump to the correct subroutine ; to handle the type of command contained in bmRequestType ; The new jmp table will be compressed by shifting and rotating ; out bits, 2,3 & 4. ; Place bmRequestType in the following order and then do the jump table ; on it. ; xx65107x ; if bits 65 == 11, Reserved = Error ; Unless you have time, don't spend a lot of time tracing the algorythm ; It's fancy and it works. If you don't understand it go ask someone for a quarter. mov A, bmRequestType ; Get the value. anl A, #0E3h ; Clear out bits 2,3,4 since ; we don't need these ; Reg A now looks like 765xxx10 RL A ; Put bits 1,0,& 7 in new placement RL A ; Leave LSB cleared so jump is the number of words. ; xxxx1076 CheckBit6: ; 6 is currently in bit 0 position, jnb ACC.0, CheckBit5 ; Convert it to bit 5 position setb ACC.5 ; xx6x107x CheckBit5: ; Bit 5 is currently at 7 position jnb ACC.7, CheckValidType ; Convert it to bit 4 position setb ACC.4 ; xx65107x CheckValidType: ; jnb ACC.5, GoodCommand ; If this bit (6) is clear we know ; it's a valid value jb ACC.4, ReservedCommand ; Bit (6) was set, if bit 5 is set it's ; a reserved command. ljmp GoodCommand ReservedCommand: orl EPCON, #0C0h ; Stall EP0. ret ; THis code will branch to the correct jump statement ; in the bmRequestJumpTable below. GoodCommand: anl A, #3Eh mov B, A rr A anl A, #1fH clr CY ADD A, B mov DPTR, #bmRequestJumpTable IF PLC mov DPXL, #LOW HIGH16(GoodCommand) ; Get Page of Jump Table. ENDIF IF KEIL mov DPXL, #BYTE2(GoodCommand) ENDIF ; Low byte of the upper 16 bits of the 32 bit address of the ; jump table. ; Is this code in RAM or ROM jmp @A+DPTR ; Used because I use RISM sometimes ; which places code in RAM ;--------------------------------------- ;-- bmRequest Jump Table --------------- ;-- The order of these are based on the ;-- compresion algorythm used above. ;-- Each of these instructions occupy two bytes of ;-- ROM. Do not change AJMP to LJMP as the algorytm depends on the ;-- 2 byte length of AJMP. LJMP is 3 bytes long ;-- ------------------------------------ bmRequestJumpTable: LJMP StandardSetDeviceCommand LJMP StandardGetDeviceCommand LJMP StandardSetInterfaceCommand LJMP StandardGetInterfaceCommand LJMP StandardSetEndpointCommand LJMP StandardGetEndpointCommand LJMP StandardSetOtherCommand LJMP StandardGetOtherCommand LJMP ClassSetDeviceCommand LJMP ClassGetDeviceCommand LJMP ClassSetInterfaceCommand LJMP ClassGetInterfaceCommand LJMP ClassSetEndpointCommand LJMP ClassGetEndpointCommand LJMP ClassSetOtherCommand LJMP ClassGetOtherCommand LJMP VendorSetDeviceCommand LJMP VendorGetDeviceCommand LJMP VendorSetInterfaceCommand LJMP VendorGetInterfaceCommand LJMP VendorSetEndpointCommand LJMP VendorGetEndpointCommand LJMP VendorSetOtherCommand LJMP VendorGetOtherCommand ;----------------------------------------------------------------- ;SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSs ;S ;S STANDARD TYPE COMMANDS FIRST ;S ;SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSs ;----------------------------------------------------------------- ;COMMENT *------------------------------------------------------------ ;Function name : GetStandardDeviceCommand: ;Brief Description : Process a Get Standard Device Command Setup Token ; : This can only be a Get (Device or Configuration) Descriptor, ; : or Get Device Status, Get Configuration. ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE StandardGetDeviceCommand: mov A, bRequest cjne A, #GET_DESCRIPTOR, Jump2_CheckGetConfiguration sjmp GET_DESCRIPTOR_TYPE Jump2_CheckGetConfiguration: ljmp CheckGetConfiguration GET_DESCRIPTOR_TYPE: mov A, bDescriptorType cjne A, #DEVICE_DESCR, CheckConfigDescriptor ; ****************************************************************** ; ********************** GET DESCRIPTOR, DEVICE ******************* ; ****************************************************************** IF PLC mov gbFControlBufferLocation, #LOW HIGH16(BEGIN_DEVICE_DESCRIPTOR) mov gbFControlBufferLocation+1, #HIGH LOW16(BEGIN_DEVICE_DESCRIPTOR) mov gbFControlBufferLocation+2, #LOW LOW16(BEGIN_DEVICE_DESCRIPTOR) ENDIF IF KEIL mov gbFControlBufferLocation, #BYTE2(BEGIN_DEVICE_DESCRIPTOR) mov gbFControlBufferLocation+1, #BYTE1(BEGIN_DEVICE_DESCRIPTOR) mov gbFControlBufferLocation+2, #BYTE0(BEGIN_DEVICE_DESCRIPTOR) ENDIF mov A, #12h mov B, #00h ljmp LoadBuffer CheckConfigDescriptor: cjne A, #CONFIG_DESCR, CheckStringDescriptor ; ****************************************************************** ; ********************** GET DESCRIPTOR, CONFIGURATION ************ ; ****************************************************************** IF FUB_BOARD == DISABLED ; if not a FUB board just assume SELF powered ljmp GiveSelfPoweredDescr ELSE ;FUB BOARD - check Mode 0 Jumper to determine if bus or self powered ; Self Powered vs Bus Powered : Bit 1.0 = 1 = self Powered, 0 = bus powered jnb PWR_SEL_SWITCH, GiveBusPoweredDescr ENDIF GiveSelfPoweredDescr: IF PLC mov gbFControlBufferLocation, #LOW HIGH16(BEGIN_CONFIG1_DESCRIPTOR) mov gbFControlBufferLocation+1, #HIGH LOW16(BEGIN_CONFIG1_DESCRIPTOR) mov gbFControlBufferLocation+2, #LOW LOW16(BEGIN_CONFIG1_DESCRIPTOR) ENDIF IF KEIL mov gbFControlBufferLocation, #BYTE2(BEGIN_CONFIG1_DESCRIPTOR) mov gbFControlBufferLocation+1, #BYTE1(BEGIN_CONFIG1_DESCRIPTOR) mov gbFControlBufferLocation+2, #BYTE0(BEGIN_CONFIG1_DESCRIPTOR) ENDIF sjmp DoConfigLoad GiveBusPoweredDescr: IF PLC mov gbFControlBufferLocation, #LOW HIGH16(BEGIN_CONFIG2_DESCRIPTOR) mov gbFControlBufferLocation+1, #HIGH LOW16(BEGIN_CONFIG2_DESCRIPTOR) mov gbFControlBufferLocation+2, #LOW LOW16(BEGIN_CONFIG2_DESCRIPTOR) ENDIF IF KEIL mov gbFControlBufferLocation, #BYTE2(BEGIN_CONFIG2_DESCRIPTOR) mov gbFControlBufferLocation+1, #BYTE1(BEGIN_CONFIG2_DESCRIPTOR) mov gbFControlBufferLocation+2, #BYTE0(BEGIN_CONFIG2_DESCRIPTOR) ENDIF DoConfigLoad: ; Note since config descriptors are same length - this routine works for ; both config1 and config2 mov A, #LOW (END_CONFIG1_DESCRIPTOR - BEGIN_CONFIG1_DESCRIPTOR) mov B, #HIGH (END_CONFIG1_DESCRIPTOR - BEGIN_CONFIG1_DESCRIPTOR) ljmp LoadBuffer CheckStringDescriptor: cmp R11, #STRING_DESCR ; R11 == Accum A je Check4Index0 ljmp CheckForOtherDescr ; not string descriptor check for other ; ****************************************************************** ; ********************** GET DESCRIPTOR, STRING ******************* ; ****************************************************************** Check4Index0: ; if string index = 0 ... regardless of language ID, return the language ID's ; supported by this device mov A, bDescriptorIndex CheckString0: cjne A, #0, CheckStringLangId ; *********** Return list of Languages Supported *********** IF PLC mov gbFControlBufferLocation, #LOW HIGH16(STRING_0) mov gbFControlBufferLocation+1, #HIGH LOW16(STRING_0) mov gbFControlBufferLocation+2, #LOW LOW16(STRING_0) ENDIF IF KEIL mov gbFControlBufferLocation, #BYTE2(STRING_0) mov gbFControlBufferLocation+1, #BYTE1(STRING_0) mov gbFControlBufferLocation+2, #BYTE0(STRING_0) ENDIF mov A, #LOW (STRING_1-STRING_0) mov B, #HIGH(STRING_1-STRING_0) ljmp LoadBuffer CheckStringLangId: ; First check to make sure wIndex = language ID = 0 or 0x0409 -> English. If not stall. mov B, wIndex ; move high byte - Sub language ID to B mov A, wIndex+1 ; move low byte - Primary language ID to A cmp R11, #09h ; R11 == A ... low byte jne Go_Bad_Lang_ID cmp R10, #04h ; R10 == B ... high byte je Get_Str Go_Bad_Lang_ID: ljmp ReturnBADSTDGetDeviceCommand ; NEW CODE-Return English ID Codes Get_Str: mov A, bDescriptorIndex CheckString1: cjne A, #1, CheckString2 ; *********** Return MANUFACTURER String ************* IF PLC mov gbFControlBufferLocation, #LOW HIGH16(STRING_1) mov gbFControlBufferLocation+1, #HIGH LOW16(STRING_1) mov gbFControlBufferLocation+2, #LOW LOW16(STRING_1) ENDIF IF KEIL mov gbFControlBufferLocation, #BYTE2(STRING_1) mov gbFControlBufferLocation+1, #BYTE1(STRING_1) mov gbFControlBufferLocation+2, #BYTE0(STRING_1) ENDIF mov A, #LOW (STRING_2-STRING_1) mov B, #HIGH(STRING_2-STRING_1) ljmp LoadBuffer CheckString2: cjne A, #2, CheckString3 ; *********** Return PRODUCT String ************* IF PLC mov gbFControlBufferLocation, #LOW HIGH16(STRING_2) mov gbFControlBufferLocation+1, #HIGH LOW16(STRING_2) mov gbFControlBufferLocation+2, #LOW LOW16(STRING_2) ENDIF IF KEIL mov gbFControlBufferLocation, #BYTE2(STRING_2) mov gbFControlBufferLocation+1, #BYTE1(STRING_2) mov gbFControlBufferLocation+2, #BYTE0(STRING_2) ENDIF mov A, #LOW (STRING_3-STRING_2) mov B, #HIGH(STRING_3-STRING_2) ljmp LoadBuffer CheckString3: cjne A, #3, CheckString4 ; *********** Return SERIAL Number String ************* IF PLC mov gbFControlBufferLocation, #LOW HIGH16(STRING_3) mov gbFControlBufferLocation+1, #HIGH LOW16(STRING_3) mov gbFControlBufferLocation+2, #LOW LOW16(STRING_3) ENDIF IF KEIL mov gbFControlBufferLocation, #BYTE2(STRING_3) mov gbFControlBufferLocation+1, #BYTE1(STRING_3) mov gbFControlBufferLocation+2, #BYTE0(STRING_3) ENDIF mov A, #LOW (STRING_4-STRING_3) mov B, #HIGH(STRING_4-STRING_3) ljmp LoadBuffer CheckString4: cjne A, #4, CheckString5 ; *********** Return CONFIGURATION String *********** IF PLC mov gbFControlBufferLocation, #LOW HIGH16(STRING_4) mov gbFControlBufferLocation+1, #HIGH LOW16(STRING_4) mov gbFControlBufferLocation+2, #LOW LOW16(STRING_4) ENDIF IF KEIL mov gbFControlBufferLocation, #BYTE2(STRING_4) mov gbFControlBufferLocation+1, #BYTE1(STRING_4) mov gbFControlBufferLocation+2, #BYTE0(STRING_4) ENDIF mov A, #LOW (STRING_5-STRING_4) mov B, #HIGH(STRING_5-STRING_4) ljmp LoadBuffer CheckString5: cjne A, #5, ReturnBADSTDGetDeviceCommand ; *********** Return INTERFACE String *********** IF PLC mov gbFControlBufferLocation, #LOW HIGH16(STRING_5) mov gbFControlBufferLocation+1, #HIGH LOW16(STRING_5) mov gbFControlBufferLocation+2, #LOW LOW16(STRING_5) ENDIF IF KEIL mov gbFControlBufferLocation, #BYTE2(STRING_5) mov gbFControlBufferLocation+1, #BYTE1(STRING_5) mov gbFControlBufferLocation+2, #BYTE0(STRING_5) ENDIF mov A, #LOW (STRING_6-STRING_5) mov B, #HIGH(STRING_6-STRING_5) ljmp LoadBuffer CheckForOtherDescr: sjmp ReturnBADSTDGetDeviceCommand LoadBuffer: ; Compare to see which is shorter. ; The amount asked for or the amount ; availible. push ACC push B clr CY ; A=Actual-wLength=AskedFor subb A, wLength+1 mov A, B subb A, wLength jc AskedFor_IsLarger LengthsMatch: wLengthIsSmaller: ; If Asked for is smaller, replace ; actual with asked for. pop B pop ACC mov B, wLength mov A, wLength+1 sjmp LoadIt AskedFor_IsLarger: pop B pop ACC LoadIt: ; From now on, wLength = bytes remaining. mov gbFControlBufferBytesLeft, B mov gbFControlBufferBytesLeft+1, A lcall LoadControlTXFifo ljmp ReturnSTDGetDeviceCommand CheckGetConfiguration: cjne A, #GET_CONFIGURATION, CheckGetStatus ;------------------------------------------------ ;- GET CONFIGURATION ;------------------------------------------------ mov R11, CurrentConfiguration mov TXDAT, A mov TXCNTL,#01h ljmp ReturnSTDGetDeviceCommand CheckGetStatus: cjne A, #GET_STATUS, ReturnSTDGetDeviceCommand ;------------------------------------------------ ;- GET DEVICE STATUS ;------------------------------------------------ mov A, #00h jnb HRWUPE, CheckBusSelfPwr setb ACC.1 ; set RWU enabled bit CheckBusSelfPwr: IF FUB_BOARD == DISABLED setb ACC.0 ; set self powered bit ELSE ; check P1.0 Mode 0 jumper for Bus or Self Powered board jnb PWR_SEL_SWITCH, DoneGetDeviceStatus ; don't set self powered bit setb ACC.0 ; set self powered bit ENDIF DoneGetDeviceStatus: mov TXDAT, A mov TXDAT, #00h mov TXCNTL,#02h ljmp ReturnSTDGetDeviceCommand ReturnBADSTDGetDeviceCommand: orl EPCON, #0C0h ; Stall EP0 ReturnSTDGetDeviceCommand: ret ;COMMENT *------------------------------------------------------------ ;Function name : StandardGetEndpointCommand: ;Brief Description : Process a Standard Set Endpoint Command Setup Token ; : This can only be a Set,Clear Feature - Endpoint Stall ; : ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE StandardGetEndpointCommand: mov A, bRequest cjne A, #GET_STATUS, ReturnBadSTDGetEPCommand ;------------------------------------------------ ;- GET ENDPOINT STATUS ;------------------------------------------------ mov A, wIndex + 1 anl A, #0Fh ; Mask off all but the endpoint value orl EPINDEX,A ; Point the Index register at the mov A, wIndex + 1 ; Start by clearing out R0 jb ACC.7, GetInStallStatus GetOutStallStatus: mov A, EPCON jnb ACC.6, NotStalled mov A, #01 ; Return Stalled ljmp DoneWithCommand GetInStallStatus: mov A, wIndex +1 anl A, #0Fh cjne A, #00, GetEp1InStall mov A, EPCON jnb ACC.7, NotStalled mov A, #01 sjmp DoneWithCommand GetEp1InStall: mov A, HSTAT ; GET EP1 Stall Information anl A, #020h ; Mask off all but stall bit. jz NotStalled mov A, #01h sjmp DoneWithCommand NotStalled: mov A, #00h DoneWithCommand: anl EPINDEX,#80h ; Point the index back to EP0 mov TXDAT, A mov TXDAT, #00h mov TXCNTL, #02 ret ReturnBadSTDGetEPCommand: orl EPCON, #0C0h ; Stall EP0 ReturnSTDGetEPCommand: Ret ;COMMENT *------------------------------------------------------------ ;Function name : SetUpSinglePacketControlReadStatusStage ;Brief Description : Sets the status in the IN buffer and initilizes all the ; : registers needed to do a single packet control read. ; : This needs to be done so the IN token is processed correctly. ; : ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE SetUpSinglePacketControlReadStatusStage: mov wLength, #00 mov wLength+1, #00 mov gbSetupSeqRX, #STATUS_PHASE ; Advance State Machine to next state mov gbSetupSeqTX, #DATA_PHASE setb TXOE ; Enable data transmit Ret ;COMMENT *------------------------------------------------------------ ;Function name : StandardSetEndpointCommand: ;Brief Description : Process a Standard Set Endpoint Command Setup Token ; : This can only be a Set,Clear Feature - Endpoint Stall ; : ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE StandardSetEndpointCommand: push EPINDEX mov A, wIndex+1 ; Get the endpoint of the stall to clear anl A, #0Fh ; Find out if this is an EP0 CLear Stall Command. orl EPINDEX,A ; Setup the EPINDEX to point at correct index. ; Check to make sure this is an Endpoint Stall. ; If it is not then it's a wrong command plus you ; save a few bytes doing it in this order. mov A, wValue+1 cjne A, #ENDPOINT_STALL, ReturnBadSTDSetEPCommand mov A, bRequest cjne A, #CLEAR_FEATURE, CheckSetEndpointFeature ClearEndpointFeature: ;------------------------------------------------ ;- CLEAR ENDPOINT STALL ;------------------------------------------------ ClearEndpointStall: mov A, wIndex+1 ; Get the endpoint of the stall to clear anl A, #0Fh ; Find out if this is an EP0 CLear Stall Command. JNZ ClearNonEP0Stall anl EPCON, #03Fh ; For EP0 Clear both TX & RX stall bits ljmp ReturnSTDSetEPCommand ClearNonEP0Stall: ; Must be EP1 Clear Stall command. mov A, wIndex+1 ; Get the endpoint of the stall to clear JB ACC.7, ClearInStall ; For Non EP0, examing the direction bit as well. ClearOutStall: anl HSTAT, #5Ah ; Clear the stall on Hub EP1 ljmp ReturnSTDSetEPCommand ClearInStall: anl HSTAT, #5Ah ; Clear the stall on Hub EP1 ljmp ReturnSTDSetEPCommand CheckSetEndpointFeature: cjne A, #SET_FEATURE, ReturnBadSTDSetEPCommand SetEndpointFeature: ;------------------------------------------------ ;- SET ENDPOINT STALL ;------------------------------------------------ SetEndpointStall: mov A, wIndex+1 ; Get the endpoint to stall JB ACC.7, SetInStall SetOutStall: orl HSTAT, #20h ljmp ReturnSTDSetEPCommand SetInStall: orl HSTAT, #20h ljmp ReturnSTDSetEPCommand ReturnBadSTDSetEPCommand: push EPINDEX mov EPINDEX, #01 mov TXDAT, #14h mov TXCNTL, #01h pop EPINDEX orl EPCON, #0C0h ;Stall EP0 ReturnSTDSetEPCommand: pop EPINDEX ljmp SetUpControlWriteStatusStage ;COMMENT *------------------------------------------------------------ ;Function name : StandardSetDeviceCommand: ;Brief Description : Process a Standard Set Device Command Setup Token ; : The only valid commands are Set Address, ; : Set Configuration. Other commands which have this ; : field but are un-defined are ; : ClearDeviceFeature, SetDescriptor, SetDeviceFeature. ; : ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE StandardSetDeviceCommand: mov A, bRequest cjne A, #SET_CONFIGURATION, CheckSetDeviceAddress SetDeviceConfiguration: ;------------------------------------------------ ;- SET DEVICE CONFIGURATION ;------------------------------------------------ mov A, wValue+1 CheckConfig0: cjne A, #0, CheckConfig1 mov CurrentConfiguration, R11 ; Set up the variables mov EPINDEX, #80h clr HSTAT.4 ; Disbale EP1 ;(kls) clr HRWUPE ljmp ReturnSTDSetDevice CheckConfig1: cjne A, #1, ReturnBadSetDeviceCommand mov CurrentConfiguration, R11 ; Set up the variables mov EPINDEX, #80h ; Select Hub EP1 setb HSTAT.4 ; Enable EP1 ljmp ReturnSTDSetDevice CheckConfig2: cjne A, #2, ReturnBadSetDeviceCommand sjmp ReturnSTDSetDevice ;------- TBD ------- ; Call SetConfiguration sjmp ReturnSTDSetDevice CheckSetDeviceAddress: cjne A, #SET_ADDRESS, CheckSetDeviceRWU ;------------------------------------------------ ;- SET DEVICE ADDRESS ;------------------------------------------------ ; Set Address should just return. The command will be executed following ; the status stage sjmp ReturnSTDSetDevice CheckSetDeviceRWU: cjne A, #SET_FEATURE, CheckClearDeviceRWU mov A, wValue+1 cjne A, #DEVICE_REMOTE_WAKEUP, ReturnBadSetDeviceCommand setb HRWUPE ; Enable the hub to respnd to RWU. sjmp ReturnSTDSetDevice CheckClearDeviceRWU: cjne A, #CLEAR_FEATURE, ReturnBadSetDeviceCommand mov A, wValue+1 cjne A, #DEVICE_REMOTE_WAKEUP, ReturnBadSetDeviceCommand clr HRWUPE ; Disable the hub to respnd to RWU. sjmp ReturnSTDSetDevice ReturnSTDSetDevice: ljmp SetUpControlWriteStatusStage StandardSetInterfaceCommand: mov A, bRequest cjne A, #SET_INTERFACE, ReturnBadSetDeviceCommand mov A, wValue+1 orl A, wIndex+1 jnz ReturnBadSetDeviceCommand mov CurrentConfig1Interface, R11 sjmp ReturnSTDSetDevice StandardGetInterfaceCommand: mov A, bRequest cjne A, #GET_INTERFACE, ReturnBadSetDeviceCommand mov A, wValue+1 jnz ReturnBadSetDeviceCommand mov R11, CurrentConfig1Interface mov TXDAT, A mov TXCNTL, #01 ret StandardSetOtherCommand: StandardGetOtherCommand: ;------------------------------------------ ; - Unknown Standard Command -- STALL ENDPOINT ;------------------------------------------ ReturnBadSetDeviceCommand: orl EPCON, #0C0h ; Stall Endpoint ret ;----------------------------------------------------------------- ;SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSs ;S ;S END OF STANDARD TYPE COMMANDS ;S ;SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSs ;----------------------------------------------------------------- ;----------------------------------------------------------------- ;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ;C ;C START OF CLASS COMMANDS ;C ;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ;----------------------------------------------------------------- ClassGetDeviceCommand: lcall GetClassDeviceCommand ret ClassGetOtherCommand: lcall GetClassOtherCommand ret ClassSetDeviceCommand: lcall SetClassDeviceCommand lcall SetUpControlWriteStatusStage ; We know this will was a single packet only ret ; command so go ahead and prepare/arm the status stage ClassSetEndpointCommand: ClassSetOtherCommand: lcall SetClassOtherCommand lcall SetUpControlWriteStatusStage ; We know this will was a single packet only ; command so go ahead and prepare/arm the status stage ret ClassSetInterfaceCommand: ClassGetInterfaceCommand: ClassGetEndpointCommand: ;------------------------------------------ ; - Unknown Class Command -- STALL ENDPOINT ;------------------------------------------ orl EPCON, #0C0h ;Stall Endpoint ret ;----------------------------------------------------------------- ;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ;C ;C END OF CLASS COMMANDS ;C ;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ;----------------------------------------------------------------- ;----------------------------------------------------------------- ;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV ;V ;V START OF VENDOR COMMANDS ;V ;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV ;----------------------------------------------------------------- VendorSetDeviceCommand: VendorGetDeviceCommand: lcall VendorGetDeviceCommandExec ret VendorSetInterfaceCommand: VendorGetInterfaceCommand: VendorSetEndpointCommand: VendorGetEndpointCommand: VendorSetOtherCommand: VendorGetOtherCommand: ;------------------------------------------ ; - UnknownVendorCommand -- STALL ENDPOINT ;------------------------------------------ orl EPCON, #0C0h ;Stall Endpoint ret ;----------------------------------------------------------------- ;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV ;V ;V END OF VENDOR COMMANDS ;V ;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV ;----------------------------------------------------------------- ;----------------------------------------------------------------- ;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU ;U ;U UTILILITY ROUTINES ;U ;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU ;----------------------------------------------------------------- ;COMMENT *------------------------------------------------------------ ;Function name : ProcessInToken ;Brief Description : Services all INs on EP0. ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE ProcessInToken: ;(HUB) jb EPINDEX.7, ProcessHubInToken ; Is this a HUB or NON Hub Call? anl FIFLG, #EP0_TX_CLR ; clear the interrupt bit ljmp CheckInStatusPhase ProcessHubInToken: anl HIFLG, #EP0_TX_CLR ; clear the interrupt bit CheckInStatusPhase: mov A, gbSetupSeqTX ; read state variable cjne A, #STATUS_PHASE,SendDataBack ; Should this be the end to ; a setup sequence StatusPhaseDone: lCall CompleteSetCommand mov gbSetupSeqTX, #SETUP_PHASE ; Set state var. to expect setup. mov gbSetupSeqRX, #SETUP_PHASE sjmp ReturnProcessIn SendDataBack: cjne A, #DATA_PHASE, ReturnProcessIn lcall LoadControlTXFifo ReturnProcessIn: Ret ;COMMENT *------------------------------------------------------------ ;Function name : CompleteSetCommand ;Brief Description : Called after the status phase of a set command has ; : completed. This is called everytime there is a ; : xmit status stage. ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE CompleteSetCommand: mov A, bRequest ; If this was not a Std. Set ; command then return. cjne A, #SET_ADDRESS, CheckNextCommand ;------------------------------------------------ ;- SET ADDRESS ;------------------------------------------------ DoSetAddress: jnb EPINDEX.7, SetFunctionAddress ; Use EPINDEX to tell if this SetHubAddress: ; was a hub command or function command. mov HADDR, wValue+1 ; Set to new address sjmp ReturnCompleteSet SetFunctionAddress: mov FADDR, wValue+1 ; Set to new address sjmp ReturnCompleteSet CheckNextCommand: ReturnCompleteSet: ret ;COMMENT *------------------------------------------------------------ ;Function name : SetUpControlWriteStatusStage ;Brief Description : Sets the status in the IN buffer. ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE SetUpControlWriteStatusStage: mov TXCNTL, #00 ; Setup Null Packet ; setb TXOE0 ; Enable data transmit Ret ;COMMENT *------------------------------------------------------------ ;Function name : LoadControlTXFifo ;Brief Description : Copy data from the location pointed to by ; : the three byte value gbFControlBufferLocation. ; : The number of bytes left to transmit are stored in ; : gbFControlBufferBytesLeft. If zero bytes are left then ; : a Null packet is loaded even if the null/short packet is ; : not needed. ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE LoadControlTXFifo: push R0 ; Need to save this register push DPX mov DPXL, gbFControlBufferLocation ; Get location of data to send. mov DPH, gbFControlBufferLocation+1 mov DPL, gbFControlBufferLocation+2 mov A, gbFControlBufferBytesLeft ; First check to sei if any data is availble orl A, gbFControlBufferBytesLeft+1 ; to send. jnz CntlDataAvail mov R0, #0 ; if there is data do normal flow ljmp ControlArmTx ; if none, do null packet CntlDataAvail: mov R0, #0 ; Number of bytes in FIFO- Awlays <=16 mov A, DPXL JZ DataInRAM ;----------------------------------------------- ; Data is in ROM, use instrcutions to pull from ROM. ;----------------------------------------------- DataInROM: mov A, #00h movc A, @A+DPTR ; Get Data to transmit mov TXDAT, A inc DPTR inc R0 ; Increment the number of bytes in FIFO djnz gbFControlBufferBytesLeft+1, ROMCheckMaxPacket ; If not zero, the continue. ROMCheckUpper1: mov A, gbFControlBufferBytesLeft ; If upper byte of wLength is also zero, buffer is empty. jz ControlTxUpd ; Are we done with the buffer dec A ; If it's not zero dec. the upper byte as well. mov gbFControlBufferBytesLeft, A ; And store it. ROMCheckMaxPacket: cjne R0, #EP0_MAX_PACKET_SIZE, DataInROM ; Loop until FIFO is Full ljmp ControlTxUpd ; Done with this FIFO. ;----------------------------------------------- ; Data is in RAM, use instrcutions to pull from RAM. ;----------------------------------------------- DataInRAM: movx A, @DPTR ; Get Data to transmit mov TXDAT, A inc DPTR inc R0 ; Increment the number of bytes in FIFO djnz gbFControlBufferBytesLeft+1, RAMCheckMaxPacket ; If not zero, the continue. RAMCheckUpper1: mov A, gbFControlBufferBytesLeft ; If upper byte of gbFControlBufferBytesLeft is also zero, buffer is empty. jz ControlTxUpd ; Are we done with the buffer dec A ; If it's not zero dec. the upper byte as well. mov gbFControlBufferBytesLeft, A ; And store it. RAMCheckMaxPacket: cjne R0, #EP0_MAX_PACKET_SIZE, DataInRAM ; Loop until FIFO is Full ControlTxUpd: mov gbFControlBufferLocation+1, DPH ; Update read pointers. mov gbFControlBufferLocation+2, DPL ControlArmTx: mov TXCNTL, R0 ; Write count into TXCNT register setb TXOE ; Enable data transmit ReturnLoadCntl: pop DPX pop R0 Ret ;COMMENT *------------------------------------------------------------ ;Function name : GetOUTData ;Brief Description : takes data from the FIFO, Puts it in memory and ; : then updates writes it to the fifo. ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE ;GetOUTData: ; mov WR26, #LOW16(OUT_BUFFERS) ; mov R7, RXCNTL ; Read count of bytes rec'd ; mov @WR26, R7 ; Store the count in the OUT_BUFFERS space. ; add WR26, #01h ; Increment mem pointer ; orl R7, R7 ; Set flags ; je Return ;WriteToOUTBuffer: ; mov R8, RXDAT ; mov @WR26, R8 ; inc WR26, #01h ; djnz R7, WriteToOUTBuffer ;Return: ; Ret ;COMMENT *------------------------------------------------------------ ;Function name : INIT_USB ;Brief Description : Initialize USB SFRs ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE INIT_USB: ; EP0 Comes up as it should except that ; all flow control is turned off except for ; OE bits. This will turn them on so we can ; accept all data. ; All other endpoints should not be configured ; until a Set Configuration command is given. mov EPINDEX, #80 mov EPCON, #3Fh ReturnInitUSB: Ret ;COMMENT *------------------------------------------------------------ ;Function name : INIT_VARIABLES ;Brief Description : Initializes global variables ;Regs preserved : No reg. is saved ;--------------------------------------------------------------------* ;SCOPE INIT_VARIABLES: ;Init SETUP VARIABLES mov R0, #00h mov Heart1, R0 mov Heart1+1, R0 mov gbSetupSeqRX, R0 ; SetupSeq is set to mov gbSetupSeqTX, R0 ; STATUS_PHASE mov gbFControlBufferLocation, R0 mov gbFControlBufferLocation+1, R0 mov gbFControlBufferLocation+2, R0 mov gbFControlBufferBytesLeft, R0 mov CurrentConfiguration, R0 mov CurrentConfig1Interface, R0 mov WR0, #0 ; Zero Out Counter mov WR2, WR0 mov SWITCH_PORT, #0FFH mov EMBD_FN_FLG, R0 ; init to 00h ReturnInit: Ret ;======================================================================== ;====================== RightCylon ====================================== ;======================================================================== ;This routine does a cylon pattern to the right. The time between steps is ; contained in WR2. Only the flag register is modified during this routine. RightCylon: push WR2 push ACC mov A, #80h CylonRightLoop: dec WR2, #1 cmp R2, #00h jne CylonRightLoop srl R11 mov LED_PORT, A pop WR2 push WR2 jnb ACC.0, CylonRightLoop pop ACC pop WR2 ret ;======================================================================== ;====================== LeftCylon ====================================== ;======================================================================== ;This routine does a cylon pattern to the left. The time between steps is ; contained in WR2. Only the flag register is modified during this routine. LeftCylon: push WR2 push ACC mov A, #01h CylonLeftLoop: dec WR2, #1 cmp R2, #0h jne CylonLeftLoop sll R11 mov LED_PORT, A pop WR2 push WR2 jnb ACC.7, CylonLeftLoop pop ACC pop WR2 ret ;======================================================================== ;====================== Delay ====================================== ;======================================================================== ; This routine delays by the delay specified in DR0. ; If Fixed delay is called, the FixedDelay: mov WR2, #0 mov WR0, #20h VaraibleDelay: delay1: dec DR0, #01 jne delay1 ret ;************************************************************************ ;************* DEVICE DESCRIPTOR **************************************** ;************************************************************************ ; NOTE!!!!! '251 is a Big Endian machine. Words and DWords are stored with the ; LSB in the numerically higher address. ;------------------------------------------------ ;-------- HUB DESCRIPTOR ------------------------ ;------------------------------------------------ ; ; NOTE!!!!! '251 is a Big Endian machine. Words and DWords are stored with the ; LSB in the numerically higher address. ; IF PLC DEFINE DESCRIPTORS_CODE_SEG, SPACE=CODE SEGMENT DESCRIPTORS_CODE_SEG ENDIF IF KEIL DESCRIPTORS_CODE_SEG SEGMENT CODE RSEG DESCRIPTORS_CODE_SEG ENDIF Header: db "HUB FIRMWARE ",10,13,00 BEGIN_DEVICE_DESCRIPTOR: gDevice_bLength: db 12h; DEVICE_DESCRIPTOR_LENGTH gDevice_bDescriptorType: db DEVICE_DESCR gDevice_bcdUSB: dw 0001h ; Version 1.00 compliant gDevice_bDeviceClass: db 09h ; 9 gDevice_bDeviceSubClass: db 00h gDevice_bDeviceProtocol: db 00h gDevice_wMaxPacketSize0: db 08h ;8 byte max for EP0 gDevice_widVendor: dw 2B04h ;Intel Vendor ID (042B) IF HELSINKI == ENABLED gDevice_widProduct: dw 0593h ;product ID 9305h 930 hub with 5 downstream ports ;downstream ports ELSE gDevice_widProduct: dw 0493h ;product ID 9304h 930 hub with 4 downstream ports ;downstream ports ENDIF ;********************************************************************** ; Change the device number to match the firmware version number: gDevice_bcdDevice: dw 5001h ;device version 1.50 ;********************************************************************** gDevice_iManufacturer: db 01h ; Manufacturer String gDevice_iProduct: db 02h ; Product String gDevice_iSerialNumber: db 00h ; No Serial Number String - Rev 1.4 change gDevice_bNumConfigurations: db 1 END_DEVICE_DESCRIPTOR: ; SELF POWERED Descriptors ;/*--------------- Initialize Config 1 descriptor ----------------*/ BEGIN_CONFIG1_DESCRIPTOR: gConfig1_bLength: db 09h gConfig1_bDescriptorType: db CONFIG_DESCR gConfig1_bTotalLength: db END_CONFIG1_DESCRIPTOR - BEGIN_CONFIG1_DESCRIPTOR gConfig1_bCorrection: db 0 gConfig1_bNumInterfaces: db 1 ; NUM_OF_INTERFACES; gConfig1_bConfigurationValue: db 1 gConfig1_iConfiguration: db 04h gConfig1_bmAttributes: db 060h ; Self Powered, RWU Enabled gConfig1_MaxPower: db 001 ;2 ma ; /*------------- Initialize Interface 1 descriptor ---------------*/ BEGIN_INTERFACE1_DESCRIPTOR: gInterface1_bLength: db END_INTERFACE1_DESCRIPTOR - BEGIN_INTERFACE1_DESCRIPTOR gInterface1_bDescriptorType: db INTERFACE_DESCR gInterface1_bInterfaceNumber: db 0 gInterface1_bAlternateSetting: db 0 gInterface1_bNumEndpoints: db 01h gInterface1_bInterfaceClass: db 09h gInterface1_bInterfaceSubClass: db 00h gInterface1_bInterfaceProtocol: db 00h gInterface1_iInterface: db 05H END_INTERFACE1_DESCRIPTOR: ; /*------------- Initialize Endpoint 1 descriptor 1---------------*/ BEGIN_ENDPOINT1_DESCRIPTOR: gEP1_bLength1: db END_ENDPOINT1_DESCRIPTOR - BEGIN_ENDPOINT1_DESCRIPTOR gEP1_bDescriptorType1: db ENDPOINT_DESCR gEP1_bEndpointAddress1: db 81h ;EP address 1, in gEP1_bmAtrributes1: db 03h ;Interrupt gEP1_wMaxPacketSize1: dw 0100h ;Max Packet 8 bytes gEP1_bInterval1: db 20h ; 32 milliseconds END_ENDPOINT1_DESCRIPTOR: END_CONFIG1_DESCRIPTOR: ; BUS POWERED Descriptors ;/*--------------- Initialize Config 2 descriptor ----------------*/ BEGIN_CONFIG2_DESCRIPTOR: gConfig2_bLength: db 09h gConfig2_bDescriptorType: db CONFIG_DESCR gConfig2_bTotalLength: db END_CONFIG2_DESCRIPTOR - BEGIN_CONFIG2_DESCRIPTOR gConfig2_bCorrection: db 0 gConfig2_bNumInterfaces: db 1 ; NUM_OF_INTERFACES; gConfig2_bConfigurationValue: db 1 gConfig2_iConfiguration: db 04h gConfig2_bmAttributes: db 0A0h ; Bus Powered, RWU Capable gConfig2_MaxPower: db 045 ;90ma ; /*------------- Initialize Interface 2 descriptor ---------------*/ BEGIN_INTERFACE2_DESCRIPTOR: gInterface2_bLength: db END_INTERFACE2_DESCRIPTOR - BEGIN_INTERFACE2_DESCRIPTOR gInterface2_bDescriptorType: db INTERFACE_DESCR gInterface2_bInterfaceNumber: db 0 gInterface2_bAlternateSetting: db 0 gInterface2_bNumEndpoints: db 01h gInterface2_bInterfaceClass: db 09h gInterface2_bInterfaceSubClass: db 00h gInterface2_bInterfaceProtocol: db 00h gInterface2_iInterface: db 05H END_INTERFACE2_DESCRIPTOR: ; /*------------- Initialize Endpoint 1 descriptor 2---------------*/ BEGIN_ENDPOINT2_DESCRIPTOR: gEP1_bLength2: db END_ENDPOINT2_DESCRIPTOR - BEGIN_ENDPOINT2_DESCRIPTOR gEP1_bDescriptorType2: db ENDPOINT_DESCR gEP1_bEndpointAddress2: db 81h ;EP address 1, in gEP1_bmAtrributes2: db 03h ;Interrupt gEP1_wMaxPacketSize2: dw 0100h ;Max Packet 8 bytes gEP1_bInterval2: db 20h ; 32 milliseconds END_ENDPOINT2_DESCRIPTOR: END_CONFIG2_DESCRIPTOR: IF PLC DEFINE HUB_STRINGS_CODE_SEG, SPACE=CODE SEGMENT HUB_STRINGS_CODE_SEG ENDIF IF KEIL HUB_STRINGS_CODE_SEG SEGMENT CODE RSEG HUB_STRINGS_CODE_SEG ENDIF STRING_LOC_TABLE: ;*********** LANGUAGE ID's supported text *************** STRING_0: db LOW(STRING_1-STRING_0) db STRING_DESCR db 09h,04h ; 2 Byte lang id for English: ie. 0409h ;*********** MANUFACTURER String Descriptor text *************** STRING_1: db LOW(STRING_2-STRING_1) db STRING_DESCR db 'I',00,'n',00,'t',00,'e',00,'l',00,' ',00,' ',00,'1',00,'9',00,'9',00,'7',00,' ',00 db 'C',00,'E',00,'G',00,' ',00,'-',00,' ',00,'C',00,'L',00,'E',00,' ',00,'-',00,' ',00,'U',00,'S',00,'B',00,0Dh,00,0Ah,00 db 'W',00,'r',00,'i',00,'t',00,'t',00,'e',00,'n',00,' ',00,'b',00,'y',00,' ',00 db 'K',00,'e',00,'n',00,' ',00,'S',00,'c',00,'h',00,'u',00,'l',00,'t',00,'z',00,' ',00,'&',00,' ',00 db 'C',00,'h',00,'i',00,'p',00,' ',00 db 'L',00,'i',00,'n',00,'t',00,'h',00,'i',00,'c',00,'u',00,'m',00 ;*********** PRODUCT String Descriptor text *************** STRING_2: db LOW(STRING_3-STRING_2) db STRING_DESCR db '8',00,'X',00,'9',00,'3',00,'0',00,'H',00,'X',00,' ',00 db 'S',00,'t',00,'a',00,'n',00,'d',00,' ',00,'A',00,'l',00,'o',00,'n',00,'e',00,' ',00 db 'H',00,'u',00,'b',00 IF HELSINKI == ENABLED db ',',00,' ',00,'5',00,' ',00,'D',00,'S',00,' ',00,'P',00,'o',00,'r',00,'t',00,'s',00 ELSE db ',',00,' ',00,'4',00,' ',00,'D',00,'S',00,' ',00,'P',00,'o',00,'r',00,'t',00,'s',00 ENDIF db ' ',00,'(',00,'1',00,' ',00,'I',00,'n',00,'t',00,'e',00,'r',00,'n',00,'a',00,'l',00,')',00 ;*********** SERIAL # String Descriptor text *************** STRING_3: db LOW(STRING_4-STRING_3) db STRING_DESCR db 'F',00,'i',00,'r',00,'m',00,'w',00,'a',00,'r',00,'e',00,' ',00,':',00,' ',00 ;****** CHANGE FIRMWARE REV HERE WITH EACH RELEASE ***** db 'R',00,'e',00,'v',00,'.',00,' ',00,'1',00,'.',00,'5',00,'0',00 ;*********** CONFIGURATION String Descriptor text ************** STRING_4: db LOW(STRING_5-STRING_4) db STRING_DESCR IF FUB_BOARD == ENABLED ; fub board setup message db 'F',00,'U',00,'B',00,' ',00,'B',00,'o',00,'a',00,'r',00,'d',00,' ',00,'S',00,'e',00,'t',00,'u',00,'p',00,',',00,' ',00 ELSE ; eval board setup message db 'E',00,'V',00,'A',00,'L',00,' ',00,'B',00,'o',00,'a',00,'r',00,'d',00,' ',00,'S',00,'e',00,'t',00,'u',00,'p',00,',',00,' ',00 ENDIF db 'E',00,'m',00,'b',00,'e',00,'d',00,'d',00,'e',00,'d',00,' ',00 db 'F',00,'u',00,'n',00,'c',00,'t',00,'i',00,'o',00,'n',00,' ',00 IF FUB_BOARD == ENABLED db 'E',00,'n',00,'a',00,'b',00,'l',00,'e',00,'d',00,' ',00 db 'b',00,'y',00,' ',00,'J',00,'P',00,'6',00 ELSE IF INTERNAL_PORT == ENABLED db 'E',00,'n',00,'a',00,'b',00,'l',00,'e',00,'d',00,' ',00 ELSE db 'D',00,'i',00,'s',00,'a',00,'b',00,'l',00,'e',00,'d',00,' ',00 ENDIF ENDIF ;*********** INTERFACE String Descriptor text *************** STRING_5: db LOW(STRING_6-STRING_5) db STRING_DESCR db '<',00,' ',00,'I',00,'n',00,'t',00,'e',00,'r',00,'f',00,'a',00,'c',00,'e',00,' ',00 db 'S',00,'t',00,'r',00,'i',00,'n',00,'g',00,' ',00,'>',00 STRING_6: ;############################################################# ;####### RAM MEMORY MAP ###################################### ;############################################################# ;---------------------------------------------------------------------------- ;- Control varaibles need to be placed between 20h & 7fh for the addressing mode ;- If RISM is running, RISM needs 20h-3fH so be careful running RISM. ;---------------------------------------------------------------------------- IF PLC DEFINE HUB_DATA_SEG, SPACE=DATA SEGMENT HUB_DATA_SEG ENDIF IF KEIL HUB_DATA_SEG SEGMENT DATA RSEG HUB_DATA_SEG ENDIF ;; ;; Buffer and associated variables for Control Endpoint management gbSetupSeqTX: ds 1 gbSetupSeqRX: ds 1 SuspendResumeFlag: ds 1 ; If 0, then we are not suspended, and no suspend event is pending ; If 1, then we are not suspended, but a suspend event is pending ; If 2, then we are suspended, and no resume event is pending ; If 3, then we are suspended, but a resume event is pending COMMAND_BUFFER: StandardDeviceRequest: bmRequestType: ds 1 bRequest: ds 1 wValue: FwValue: wFeatureSelector: bDescriptorType: ds 1 bDescriptorIndex: ds 1 wTargetSelector: wIndex: ds 2 wLength: ds 2 ; -------------------------------------------------------- ; CntlWriteDataBuffer is Not Needed for a Hub as there ; are no control writes with a data stage for a hub ; -------------------------------------------------------- CntlWriteDataBuffer: ;ds 0 ; Added to handle control writes with data stages. ; When a control Write with a data stage is detected ; the data is placed in this buffer. When all the data ; has been collected(Bytes received=wLength) the actual routine is ; called. The size of data is limited to this buffer length. CntlWriteDataPntr: ; ds 1 ; Used to point into the CntlWriteDataBuffer. gbFControlBufferLocation: ds 3 gbFControlBufferBytesLeft: ds 2 Heart1: ds 2 EP0_ERROR_CNT: ds 1 FTLOCK_FLG: ds 1 RWUTimer: ds 1 EmbeddedFunctionInReset: ds 1 IF PLC DEFINE HUB_PDATA_SEG, SPACE=PDATA SEGMENT HUB_PDATA_SEG ENDIF IF KEIL HUB_PDATA_SEG SEGMENT EDATA RSEG HUB_PDATA_SEG ENDIF CurrentConfiguration: ds 1 CurrentConfig1Interface: ds 1 EMBD_FN_FLG: ds 1 END