;COMMENT /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;************************************************************************** ;** ** ;** 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 931 AX/HX ROM CODE software ; ; ;*** 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 ; --------------------------------------------- ; 3.06 11-12-97 Charles H Linthicum Jr. ; Changed emb_func for loopback hole fixes. ; from this rev on - should be running HC too - this is ; set in switch.inc. ; 3.05 10-20-97 Charles H Linthicum Jr. ; Added CHUB assembler directive to turn off ; heartbeat LED until device gets the "set config 1" ; and its enumerated. ; 3.04 10-02-97 Charles H Linthicum Jr. ; Added OVRI_DETECT assembler directive to enabled ; or disable setting of OVRI_EN ; 3.03 08-19-97 Charles H Linthicum Jr. ; Added ability to trip remote wakeup using INT0 if ; in configuration 1 and not keyboard setup ; changes made in SV_CODE as well ; Made changes to HUB_FIRM to handle clearing OVRI ; SC - CheckClearPortOVRISC ; 3.02 07-30-97 Charles H Linthicum Jr. ; adding Keyboard stuff on Configuration KEYBOARD_CONFIG ; moved heartbeat LED to LED0 ; 3.01 07-30-97 Charles H Linthicum Jr. ; fixed CheckGetStatus for bus/self switches ; 3.00 07-24-97 Charles H Linthicum Jr. ; added status stage to HUB_FIRM.ASM ; made changes for integrated AX/HX code ; added switch to determine if it's AX or HX ; added DEVICE_TYPE flag for AX or HX ; "00h" ---> "931 AX" ; "01h" ---> "931 HX" ; basically for AX code the setup is slightly ; different, SOF handling is different, most FN ; calls are shared with HUB's embedded function ; routines ; removed all HONG_KONG conditional stuff ! ; changed Intel VID to 042B instead of 8086 ; Started with version 2.03 of 931 HX firmware ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ INCLUDE "SWITCH.INC" IF DOUG == USE ; Use DOUG routines INCLUDE "flags.inc" SV equ ENABLED ARCH equ 51 PROC equ i8X930HX INCLUDE "svp_regs.inc" INCLUDE "sv.inc" ELSE ; DON'T use DOUG include 8X931HX.INC ENDIF 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 ;======================================================================= public LoadBuffer public gbFControlBufferLocation public EMBD_FN_FLG public STACK_DATA public DEVICE_TYPE public Heart_Beat xdef bRequest xdef wValue xdef wIndex extern GetClassDeviceCommand:CODE extern GetClassOtherCommand:CODE extern SetClassDeviceCommand:CODE extern SetClassOtherCommand:CODE extern InitilizeHubVariables:CODE extern InitializeEmbeddedFunction:CODE extern FifoWatchDog:CODE extern FUNCTION_ISR:CODE, INT0_ISR:CODE extern SV_SOF_ROUTINE extern EmbeddedFunctionSofRoutine:CODE, fCurrentConfiguration:DATA extern FUNCTION_SUSPEND_RESUME_ROUTINE:CODE extern Ep1RAM_TO_TX_PUSH:CODE, Ep2RAM_TO_TX_PUSH:CODE extern VendorGetDeviceCommandExec:CODE, VendorSetDeviceCommandExec:CODE extern FLASH_LEDS: CODE extern init_serial, putc_ser, putret_ser, puts_ser, putc_hex_ser extern FN_RWU_FLG extern Ep1WritePointer, Ep1ReadPointer, Ep1BytesInBuffer, Ep1LoopBackBuffer extern Ep2WritePointer, Ep2ReadPointer, Ep2BytesInBuffer, Ep2LoopBackBuffer extern TIMER0_ISR:CODE, TIMER1_ISR:CODE,KSI_ISR:CODE,KeyboardResetRoutine:CODE ;HONG_KONG ; Self Powered vs Bus Powered : Bit 3.2 = 1 = self Powered, 0 = bus powered ; Embedded function attached : Bit 3.3 = 1 = Attached, 0 =Un attaced. ;------------------------------------------------------ ;----- CCBs --------------------------------------- ;------------------------------------------------------ ; Recall that HONG_KONG is '51 core so it has no CCB's ;*** NOTE *** Because INTR=1 it is NOT necessary to have ISR's push ; and pop PSW1. ;---------------------------------------------------- ;- Reset Segment is ORGed at 00, but the linker will ;- Place the reset of the signigiant figures ;---------------------------------------------------- public END_VECTORS,RESET_VECTOR IF RISM == ENABLED DEFINE VECTOR_SEG, SPACE=CODE, ORG = 4000H ELSE DEFINE VECTOR_SEG, SPACE=CODE, ORG= 0000H ENDIF SEGMENT VECTOR_SEG RESET_VECTOR: ljmp main INT0_VECTOR: ljmp INT0_ISR ; trip remote wakeup 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 5 KBD_VECTOR: ljmp KSI_ISR ds 5 SOF_VECTOR: ljmp SOF_ISR ds 5 USB_FUNC_VECTOR: ljmp FUNCTION_ISR ds 5 SUS_RSM_VECTOR: ljmp SUSPEND_RESUME_ISR ds 10h END_VECTORS: DEFINE HUB_EP0_CODE_SEGMENT, SPACE=CODE, ORG= 00080H SEGMENT HUB_EP0_CODE_SEGMENT ;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ;M---------------------------------------------------------------------M ;M MAIN M ;M---------------------------------------------------------------------M ;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM main: IF SIMULATION_MODE1 == ENABLED ; short length USB frames - simulation mode only mov P1, #11h mov HFRTMRL, #88h mov HFRTMRH, #2Ch ENDIF mov SP , #STACK_DATA IF SIO_DEBUG == ENABLED anl PCON, #LC_CLR_MASK ; go to high clock mode lcall init_serial mov DPTR, #STARTUP_MSG lcall puts_ser ENDIF lcall AX_OR_HX? ; Find out if I'm a 931 AX or 931 HX IF CHUB == DISABLED mov KBCON, #20h ; set KSEN to allow usage of keyboard LEDs - leds ON ELSE mov KBCON, #2Fh ; set KSEN to allow usage of keyboard LEDs - leds OFF ENDIF mov P1, #0FFh ; P1 needs to be high(Just pullups) to allow external ; pull downs to be used mov P1, #00h ; initially clear LEDs on Port 1 orl P3, #00001100b ; pull up P3.3 and P3.2 initially so they can be ; pulled down by jumper if necessary mov A, DEVICE_TYPE ; Based on the device type do different setup jnz SETUP_FOR_HX_DEVICE lcall InitializeEmbeddedFunction ; Initialize USB stuff for a FUNCTION ljmp ActiveLoop SETUP_FOR_HX_DEVICE: lcall INIT_HUB_VARIABLES ; Initialize the RAM space as required lcall INIT_HUB_USB ; Initialize USB stuff for a HUB ljmp ActiveLoop ;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ;M END OF MAIN PROGRAM CODE M ;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ;A---------------------------------------------------------------------A ;A ACTIVE LOOP A ;A---------------------------------------------------------------------A ;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA COMMENT *------------------------------------------------------------ Function name : ActiveLoop Brief Description : This routine simply sets and clears P1.3 at a periodic rate : It purpose is to let the user know the part is alive. Regs preserved : No reg. is saved --------------------------------------------------------------------* SCOPE ActiveLoop: ;------------------------------------------------------------------ ;-- Heart Beat ;------------------------------------------------------------------ HeartBeat: mov A, Heart_Beat+1 ; Get LSB inc A mov Heart_Beat+1, A JNZ UpdateHeartBeat mov A, Heart_Beat ; Get MSB inc A mov Heart_Beat, A UpdateHeartBeat: mov A, Heart_Beat jnb ACC.7, ClearBit mov A, Heart_Beat anl A, #0Fh cjne A, #01h, ActiveLoop setb HEARTBEAT_LED mov A, #0FFh more_delay1: djnz ACC, more_delay1 sjmp ActiveLoop ClearBit: ; added with Rev 3.05 IF CHUB == ENABLED push 06h ; check to see if current configuration=1 ? mov R6, CurrentConfiguration cjne R6, #1, DONT_LIGHT_LED0 pop 06h clr HEARTBEAT_LED ; turn ON LED0 sjmp ActiveLoop DONT_LIGHT_LED0: pop 06h setb HEARTBEAT_LED sjmp ActiveLoop ELSE clr HEARTBEAT_LED ; turn ON LED0 sjmp ActiveLoop ENDIF ;---------------------------------------------------------------- ;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 lcall FUNCTION_SUSPEND_RESUME_ROUTINE 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 ACC mov A, SOFH jnb ACC.ASOF_BIT, ExitSofIsr ; If this ASOF bit not set, the ISR could be a HUB. Go Check. lcall EmbeddedFunctionSofRoutine mov A, DEVICE_TYPE jz ExitSofAndHubISR ; if we are AX then quit out here ; otherwise if we are HX then check for HUB pending ISR 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 ACC 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 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 sjmp ExitSofAndHubISR 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 orl TXCON, #TXCLR_SET_MASK 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? orl RXCON, #RXFFRC_SET_MASK ; Update receive FIFO state orl TXCON, #TXCLR_SET_MASK ; Flush the Transmit FIFOS in case ; a null packet is still left. 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 0 ; R0 is at address 0 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 0 ; R0 is at address 0 RdDone: orl RXCON, #RXFFRC_SET_MASK ; 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 DPH push DPL lcall DoJumpTable ; At this point all data has been ; stored and all we need to do now is to ; process it. pop DPL pop DPH 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 anl RXSTAT, #EDOVW_CLR_MASK 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 orl RXCON, #RXFFRC_SET_MASK anl RXSTAT, #RXSETUP_CLR_MASK push DPH push DPL lCall ProcessSetup pop DPL pop DPH 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 algorithm ; 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 jmp @A+DPTR ;--------------------------------------- ;-- 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, xCheckGetConfiguration sjmp GetTheDescriptor xCheckGetConfiguration: ljmp CheckGetConfiguration GetTheDescriptor: mov A, bDescriptorType cjne A, #DEVICE_DESCR, CheckConfigDescriptor ; ****************************************************************** ; ********************** GET DESCRIPTOR, DEVICE ******************* ; ****************************************************************** mov gbFControlBufferLocation+0, #HIGH(BEGIN_DEVICE_DESCRIPTOR) mov gbFControlBufferLocation+1, #LOW(BEGIN_DEVICE_DESCRIPTOR) mov A, #12h mov B, #00h ljmp LoadBuffer CheckConfigDescriptor: cjne A, #CONFIG_DESCR, CheckStringDescriptor ;HONG_KONG ; Self Powered vs Bus Powered : Bit 3.2 = 1 = self Powered, 0 = bus powered ; Embedded function attached : Bit 3.3 = 1 = Attached, 0 =Un attaced. ; ****************************************************************** ; ********************** GET DESCRIPTOR, CONFIGURATION ************ ; ****************************************************************** MOV A, SWITCH_PORT jnb ACC.POWER_BIT, GiveBusPoweredDescr GiveSelfPoweredDescr: mov gbFControlBufferLocation+0, #HIGH(BEGIN_CONFIG1_DESCRIPTOR) mov gbFControlBufferLocation+1, #LOW(BEGIN_CONFIG1_DESCRIPTOR) sjmp DoConfigLoad GiveBusPoweredDescr: mov gbFControlBufferLocation+0, #HIGH(BEGIN_CONFIG2_DESCRIPTOR) mov gbFControlBufferLocation+1, #LOW(BEGIN_CONFIG2_DESCRIPTOR) DoConfigLoad: mov A, #LOW (END_CONFIG1_DESCRIPTOR - BEGIN_CONFIG1_DESCRIPTOR) mov B, #HIGH (END_CONFIG1_DESCRIPTOR - BEGIN_CONFIG1_DESCRIPTOR) ljmp LoadBuffer CheckStringDescriptor: cjne A, #STRING_DESCR, llll1 sjmp Check4Index0 llll1: 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 *********** mov gbFControlBufferLocation+0, #HIGH(STRING_0) mov gbFControlBufferLocation+1, #LOW(STRING_0) 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 A, wIndex+1 ; move low byte - Primary language ID to A cjne A, #09h ,Go_Bad_Lang_ID ; R11 == A ... low byte mov A, wIndex ; move high byte - Sub language ID to B cjne A, #04h ,Go_Bad_Lang_ID ; R11 == A ... low byte sjmp Get_Str Go_Bad_Lang_ID: ljmp ReturnBADSTDGetDeviceCommand ; Return English ID Codes Get_Str: mov A, bDescriptorIndex CheckString1: cjne A, #1, CheckString2 ; *********** Return MANUFACTURER String ************* mov gbFControlBufferLocation+0, #HIGH(STRING_1) mov gbFControlBufferLocation+1, #LOW(STRING_1) mov A, #LOW (STRING_2-STRING_1) mov B, #HIGH(STRING_2-STRING_1) ljmp LoadBuffer CheckString2: cjne A, #2, CheckString3 ; *********** Return PRODUCT String ************* mov gbFControlBufferLocation+0, #HIGH(STRING_2) mov gbFControlBufferLocation+1, #LOW(STRING_2) 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 ************* mov gbFControlBufferLocation+0, #HIGH(STRING_3) mov gbFControlBufferLocation+1, #LOW(STRING_3) mov A, #LOW (STRING_4-STRING_3) mov B, #HIGH(STRING_4-STRING_3) ljmp LoadBuffer CheckString4: cjne A, #4, CheckString5 ; *********** Return CONFIGURATION String *********** mov gbFControlBufferLocation+0, #HIGH(STRING_4) mov gbFControlBufferLocation+1, #LOW(STRING_4) mov A, #LOW (STRING_5-STRING_4) mov B, #HIGH(STRING_5-STRING_4) ljmp LoadBuffer CheckString5: cjne A, #5, ReturnBADSTDGetDeviceCommand ; *********** Return INTERFACE String *********** mov gbFControlBufferLocation+0, #HIGH(STRING_5) mov gbFControlBufferLocation+1, #LOW(STRING_5) 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 A, CurrentConfiguration mov TXDAT, A mov TXCNTL,#01h ljmp ReturnSTDGetDeviceCommand CheckGetStatus: cjne A, #GET_STATUS, ReturnSTDGetDeviceCommand ;------------------------------------------------ ;- GET DEVICE STATUS ;------------------------------------------------ push 00h mov A, HSTAT jnb ACC.HRWUPE_BIT, NotRWUEnabled mov R0, #02h ; RWU Enabled sjmp CheckBusorSelfPowered NotRWUEnabled: mov R0, #00h ; RWU Not Enabled CheckBusorSelfPowered: MOV A, SWITCH_PORT jnb ACC.POWER_BIT, ClearSelfPoweredStatusBit SetSelfPoweredStatusBit: mov A, R0 ; get previous saved status setb ACC.0 ; set the self powered bit sjmp DoneGetDeviceStatus ClearSelfPoweredStatusBit: mov A, R0 ; get previous saved status DoneGetDeviceStatus: pop 00h 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 SetUpSinglePacketReadStatusStage: mov wLength, #00 mov wLength+1, #00 mov gbSetupSeqRX, #STATUS_PHASE ; Advance State Machine to next state mov gbSetupSeqTX, #DATA_PHASE 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, A ; Set up the variables mov EPINDEX, #80h anl HSTAT, #EP1STL_CLR_MASK ; Disbale EP1 ljmp ReturnSTDSetDevice CheckConfig1: cjne A, #1, CheckConfig2 mov CurrentConfiguration, A ; Set up the variables mov EPINDEX, #80h ; Select Hub EP1 orl HSTAT, #EP1EN_SET_MASK IF OVRI_DETECT == ENABLED orl HSTAT, #80h ; enables OVRI_EN detection ENDIF ljmp ReturnSTDSetDevice CheckConfig2: cjne A, #2, ReturnBadSetDeviceCommand mov HPINDEX, #EMBEDDED_PORT_NUMBER mov HPCON, #ENABLE_PORT_CMD ; DO the reset. IF OVRI_DETECT == ENABLED orl HSTAT, #80h ; enables OVRI_EN detection ENDIF mov HADDR, #02h ; Set the hub's address to 02h lcall InitializeEmbeddedFunction sjmp ReturnSTDSetDevice ;------- TBD ------- ; Call Setonfiguration 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 orl HSTAT, #HRWUPE_SET_MASK ; ENable RWU sjmp ReturnSTDSetDevice CheckClearDeviceRWU: cjne A, #CLEAR_FEATURE, ReturnBadSetDeviceCommand mov A, wValue+1 cjne A, #DEVICE_REMOTE_WAKEUP, ReturnBadSetDeviceCommand anl HSTAT, #HRWUPE_CLR_MASK ; 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, A sjmp ReturnSTDSetDevice StandardGetInterfaceCommand: mov A, bRequest cjne A, #GET_INTERFACE, ReturnBadSetDeviceCommand mov A, wValue+1 jnz ReturnBadSetDeviceCommand mov A, 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: lcall VendorSetDeviceCommandExec lcall SetUpControlWriteStatusStage ; We know this will was a single packet only ret 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: 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: SetHubAddress: ; was a hub command or function command. mov HADDR, wValue+1 ; Set to new address 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 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 0 ; R0 is at address 0 ; Need to save this register push DPH push DPL mov DPH, gbFControlBufferLocation+0 mov DPL, gbFControlBufferLocation+1 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 ;----------------------------------------------- ; 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. ControlTxUpd: mov gbFControlBufferLocation, DPH ; Update read pointers. mov gbFControlBufferLocation+1, DPL ControlArmTx: mov TXCNTL, R0 ; Write count into TXCNT register ReturnLoadCntl: pop DPL pop DPH pop 0 ; R0 is at address 0 ret COMMENT *------------------------------------------------------------ Function name : AX_OR_HX? Brief Description : This subroutine determines whether we are HX or AX and sets the DEVICE_TYPE accordingly where 0 is for AX and 1 is for HX Regs preserved : --------------------------------------------------------------------* SCOPE AX_OR_HX?: push ACC push DPH push DPL mov A, HADDR jnz GOT_AX_DEVICE ; HADDR = 00 for HX, and FF for AX after reset ! GOT_HX_DEVICE: mov DEVICE_TYPE, #01h IF SIO_DEBUG == ENABLED mov DPTR, #HX_DEVICE_MSG lcall puts_ser lcall putret_ser ENDIF sjmp DONE_AXHX_CHK GOT_AX_DEVICE: mov DEVICE_TYPE, #00h IF SIO_DEBUG == ENABLED mov DPTR, #AX_DEVICE_MSG lcall puts_ser lcall putret_ser ENDIF DONE_AXHX_CHK: pop DPL pop DPH pop ACC ret COMMENT *------------------------------------------------------------ Function name : INIT_HUB_USB Brief Description : Initialize USB SFRs Regs preserved : No reg. is saved --------------------------------------------------------------------* SCOPE INIT_HUB_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. orl SOFH, #SOFDIS_SET_MASK mov EPINDEX, #80 mov EPCON, #3Fh ;---------------------------------------- ;--- Enable HUB Interrupts ;---------------------------------------- mov EPINDEX, #80h ; Select Hub EP1 mov EPCON, #03fh ; CNTL, ENable all mov HIE, #03h ; Enable the USB FunctionHUB EP0 orl USB_IEN1, #01h ;setb IEN1.0 ; Enable HUB/SOF ISR mov EPINDEX, #00h ;---------------------------------------- ;--- Enable Function Interrupts ;---------------------------------------- ; Resume is set here orl USB_IEN1, #04h ; ENable Suspend/Resume ISR mov A, DEVICE_TYPE ; Based on the device type do different setup jnz SKIP_INT0_SETUP ; If I'm an HX then skip driving RWU ; External interrupt 0 setup IF AX DEVICE orl TCON, #00h ; setup ext int 0 for level triggered (active low) orl IPH0, #01h ; set external interrup 0 priority bit high orl IPL0, #01h ; set external interrup 0 priority bit high orl IEN0, #01h ; enable external interrupt 0 SKIP_INT0_SETUP: setb EA ; Enable Interrupts. ReturnInitUSB: Ret COMMENT *------------------------------------------------------------ Function name : INIT_HUB_VARIABLES Brief Description : Initializes global variables Regs preserved : No reg. is saved --------------------------------------------------------------------* SCOPE INIT_HUB_VARIABLES: ;Init SETUP VARIABLES mov R0, #00h mov Heart_Beat, R0 mov Heart_Beat+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 fCurrentConfiguration, #00h mov EMBD_FN_FLG, #00h ReturnInit: Ret ; ;************************************************************************ ;************* DEVICE DESCRIPTOR **************************************** ;************************************************************************ 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) gDevice_widProduct: dw 1693h ;product ID 9315h 931 hub with 5 downstream ports gDevice_bcdDevice: dw 0603h ;device version 03.06 gDevice_iManufacturer: db 01h ;These three fields are supposed gDevice_iProduct: db 2h ;to contain the index of strings ;*************************************************************************** ; NOTE ABOUT SERIAL NUMBER: ; Unless you are going to give a unique serial number for EACH rom burned ; with this code, DO NOT return an index to a serial number string here, but ; return 0 - this is vital to the correct operation of multiple, similar ; devices connected to a system running Memphis ;*************************************************************************** gDevice_iSerialNumber: db 0 gDevice_bNumConfigurations: db 1 END_DEVICE_DESCRIPTOR: ; ------------------------------------------ ; --- SELF POWERED CONFIG 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 4 gConfig1_bmAttributes: db 060h ; Self Powered, RWU ENABLED gConfig1_MaxPower: db 025 ;50ma ; /*------------- Initialize global Interface 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 ---------------*/ 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 CONFIG 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 global Interface 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 ---------------*/ BEGIN_ENDPOINT2_DESCRIPTOR: gEP2_bLength1: db END_ENDPOINT2_DESCRIPTOR - BEGIN_ENDPOINT2_DESCRIPTOR gEP2_bDescriptorType1: db ENDPOINT_DESCR gEP2_bEndpointAddress1: db 81h ;EP address 1, in gEP2_bmAtrributes1: db 03h ;Interrupt gEP2_wMaxPacketSize1: dw 0100h ;Max Packet 8 bytes gEP2_bInterval1: db 20h ; 32 milliseconds END_ENDPOINT2_DESCRIPTOR: END_CONFIG2_DESCRIPTOR: DEFINE HUB_STRINGS_CODE_SEG, SPACE=CODE SEGMENT HUB_STRINGS_CODE_SEG 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 'S',00,'y',00,'s',00,'.',00,' ',00,'V',00,'a',00,'l',00,'.',00,' ',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,'1',00,'H',00,'X',00,' ',00 db 'H',00,'u',00,'b',00,' ',00,'W',00,'i',00,'t',00,'h',00,' ',00 db '5',00,' ',00,'D',00,'S',00,' ',00,'P',00,'o',00,'r',00,'t',00,'s',00,',',00,' ',00 db '1',00,' ',00,'I',00,'n',00,'t',00,'e',00,'r',00,'n',00,'a',00,'l',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,'3',00,'.',00,'0',00,'6',00 ;*********** CONFIGURATION String Descriptor text ************** STRING_4: db LOW(STRING_5-STRING_4) db STRING_DESCR 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 db 'S',00,'u',00,'p',00,'p',00,'o',00,'r',00,'t',00,'s',00,' ',00 db '4',00,'0',00,' ',00,'b',00,'y',00,'t',00,'e',00,' ',00 db 'b',00,'u',00,'f',00,'f',00,'e',00,'r',00,' ',00 db 'L',00,'o',00,'o',00,'p',00,'b',00,'a',00,'c',00,'k',00,'!',00 ;*********** 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: IF SIO_DEBUG == ENABLED STARTUP_MSG: db " 931 AX/HX code started ! ...",CR,LF,NUL GOT_THERE_MSG: db " I got there, Chipper-do !",CR,LF,NUL AX_DEVICE_MSG: db " I'm an Intel 931 AX Device !",CR,LF,NUL HX_DEVICE_MSG: db " I'm an Intel 931 HX Device !",CR,LF,NUL ENDIF ;############################################################# ;####### 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. ;---------------------------------------------------------------------------- ; Force this data segment in the lower part of internal RAM DEFINE HUB_EP0_DATA_SEG, SPACE=DATA, ORG=021h SEGMENT HUB_EP0_DATA_SEG ;; Buffer and associated variables for Control Endpoint management gbSetupSeqTX: ds 1 gbSetupSeqRX: ds 1 COMMAND_BUFFER: bmRequestType: ds 1 bRequest: ds 1 wValue: bDescriptorType: ds 1 bDescriptorIndex: ds 1 wIndex: ds 2 wLength: ds 2 CntlWriteDataBuffer: ds 1 ;8 ; 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 Heart_Beat: ds 2 ; Counter for heart beat delay/calculation CurrentConfiguration: ds 1 ; saves current device configuration CurrentConfig1Interface: ds 1 EMBD_FN_FLG: ds 1 ; used with switch port to determine when embdn fn is enabled DEVICE_TYPE: ds 1 ; 0 = AX, 1 = HX device type flag variable DEFINE STACK_DATA_SEG, SPACE=DATA, ORG=0DFh SEGMENT STACK_DATA_SEG ; Put the stack up in the top of internal RAM STACK_DATA: ds 20h ; 32 byte stack area END