📄 usb20hw.c
字号:
/*
* Start of Zoran Standard Header
* Copyright (c) 2003 - 2004 Zoran Corporation.
*
*
* All rights reserved. Proprietary and confidential.
*
* DESCRIPTION for usb20hw.c
* USB 2.0 hardware-specific function calls.
*
* NEW HISTORY COMMENT (description must be followed by a blank line)
* <Enter change description here>
* ===== HISTORY of changes in //depot/misc/projects/tps/usb/usb20hw.c
*
* 15/Jun/04 #17 lee Remove no longer needed debug code.
* 10/Jun/04 #16 imgeng ifdef DEBUG_USB_RESET_CAUSE
* 10/Jun/04 #15 imgeng ifdef DEBUG_USB_RESET_CAUSE
* 4/Jun/04 #14 lee Increase hardware loop counts from 10 to 100 to fix USB1.1 problems.
* 1/Jun/04 #13 lee Fix allocation of endpoint queue headers.
* 3/May/04 #12 lee Protect USB_ISR_io_request() from reentrancy issue.
* 19/Jan/04 #11 lee Change for USB Speed print out.
* 19/Jan/04 #10 lee Put in "real" HW work-around for scanner/flash card conflict.
* 8/Jan/04 #9 lee "USB suspend" code broke the loader build; now
* RESET_PWR_CYCLE always set to 0 for BOOTCODE.
* 8/Jan/04 #8 lee Hardware workaround for scanner/flash card conflict is now in
* USB_ISR_io_request(). Also added code to do a "USB suspend" during
* reset if task-level reset occurs after USB connection is configured.
* 19/Dec/03 #7 lee Forgot to run stdhdr last time.
* 19/Dec/03 #6 lee Now immediately move to high-level ISR so scanner can interrupt.
* 14/Oct/03 #5 lee Remove local definition of ASSERT.
* 29/Sep/03 #4 lee Fixes to STALL code.
* 18/Sep/03 #3 lee Fixed USB_ISR_set_endpoint_status() to STALL properly.
* 27/Aug/03 #2 emiller Get rid of unnecessary nucleus.h, add util.h
* 21/Aug/03 #1 lee Created
*
* End of Zoran Standard Header
*/
/*****************************************************************************/
/*
* If we do a task reset due to an unrecoverable error now we also go into
* suspend state to get Windows to give us a fresh start. This can be disabled
* by adding "-DRESET_PWR_CYCLE=0" to the compile flags.
*/
#ifndef RESET_PWR_CYCLE
#define RESET_PWR_CYCLE 1
#endif
#ifndef HW_LOOP_CNT
#define HW_LOOP_CNT 100
#endif
#ifdef BOOTCODE
/* This version is used by flash-ROM boot code */
#undef RESET_PWR_CYCLE
#define RESET_PWR_CYCLE 0
typedef unsigned char uchar; /* unsigned character */
typedef unsigned char Uint8; /* 8-bit signed integer */
typedef unsigned short Uint16; /* 16-bit unsigned integer*/
typedef unsigned long Uint32; /* 32-bit unsigned integer*/
typedef long Sint32; /* 32-bit unsigned integer*/
typedef int Boolean;
#include "usbpriv.h"
#include "oti4100.h"
#define USB_INTS_OFF {*(unsigned long *)EXMSK1A &= ~2;}
#define USB_INTS_ON {*(unsigned long *)EXMSK1A |= 2;}
#define ARM_INTS_OFF
#define ARM_INTS_ON
#ifdef BZERO
#undef BZERO
#endif
static void BZERO(void *ptr, int n)
{
Uint8 *p = (Uint8 *)ptr;
while (n-- >= 0)
*p++ = 0;
}
#else /* not BOOTCODE */
#include "univ.gh"
#include "targmach.gh"
#include "arch.h"
#include "pile.h"
#include "util.h"
#include "oti4100.h"
#include "dbg.h"
#include "ts.h"
#include "nucleus.h"
#include "usbpriv.h"
/* prototype for interrupts off/on functions */
void armIntsOff(void);
void armIntsOn(void);
/* For protection over longer periods, only disable the USB interrupt. */
#define USB_INTS_OFF {armIntsOff();*(unsigned long *)EXMSK1A &= ~2;armIntsOn();}
#define USB_INTS_ON {armIntsOff();*(unsigned long *)EXMSK1A |= 2;armIntsOn();}
/* Just turn off ARM chip interrupts for brief protection. */
#define ARM_INTS_OFF armIntsOff();
#define ARM_INTS_ON armIntsOn();
#endif /* not BOOTCODE */
/* USB-disconnect flag (used to flash lights when reconnecting to JetDirect) */
Boolean USB_disconnect;
/* USB state structure */
USB_DEV_STATE_STRUCT usb_state;
/* Local copy of USB control packet setup array */
SETUP_STRUCT usb_setup;
/* Flag indicating that USB_task needs wake-up call for H/W reset */
volatile int USB_ForceReset;
#if RESET_PWR_CYCLE
static volatile Boolean USB_Hard_Reset;
#endif
/* Array of USB endpoint service routines */
extern void(*USBserviceEP[32])(Uint8, Boolean, Uint32);
/* Pointer to USB hardware registers */
static VUSB20_OPREG_STRUCT *usb_opreg;
/* Lock into Test Mode once requested by "set function" command from host */
static Boolean TestModeLock;
/* Test packet for sending during test mode */
static const Uint8 test_packet[53] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xEE, 0xEE, 0xEE,
0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xBF, 0xDF,
0xEF, 0xF7, 0xFB, 0xFD, 0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7,
0xFB, 0xFD, 0x7E
/* CRC16 - generated by the hardware */
/* EOP - generated by the hardware */
};
static void USB_chip_and_data_base_initialize(void);
static void USB_ISR_process_tr_complete(void);
static void USB_ISR_process_reset(void);
/*
* Task-level loop count: limit for loops on USB register values.
* If hardware fails to respond it is assumed to be hung and reset.
*/
#define HW_LOOP_LIMIT 10000
/*
* Allocate memory for the endpoint queue heads (with additional 2K
* bytes so that we can align first queue head to a 2K boundary),
* and for Device Transfer Descriptors (32-bytes aligned).
*/
static Uint8 ep_queue_head_mem[2*USB_MAX_ENDPOINTS*sizeof(dQH_STRUCT) + 2052];
static Uint32 dtd_base_ptr_mem[((DTD_POOL_CNT * sizeof(dDT_STRUCT)) + 36)/4];
/**************************************************************************
*
* Function Name : USB_init
* Returned Value : USB_OK or error code
* Comments :
* Initializes the USB device specific data structures and calls
* the low-level device controller chip initialization routine.
*
**************************************************************************/
void USB_init(void)
{
USB_ForceReset = NO_RESET;
TestModeLock = FALSE;
#if RESET_PWR_CYCLE
USB_Hard_Reset = FALSE;
#endif
/* Zero out the internal USB state structure. */
BZERO(&usb_state, sizeof(USB_DEV_STATE_STRUCT));
usb_opreg = (VUSB20_OPREG_STRUCT *)USB20USBCMD;
usb_state.USB_STATE = USB_STATE_POWER_ON;
usb_state.USB_DEVICE_STATE = USB_SELF_POWERED;
usb_state.USB_SUSPEND = 0;
usb_state.SPEED = 0;
usb_state.USB_CURR_CONFIG = 0;
/*
* Align the endpoint queue head to 2K boundary. Additionally, the
* dDT structure size must be exactly 32 bytes (or a multiple of 32,
* a hardware requirement).
*/
usb_state.EP_QUEUE_HEAD_PTR =
(dQH_STRUCT *)(Uint32)USB_MEM2048_ALIGN((dQH_STRUCT *)ep_queue_head_mem);
USB_ASSERT(sizeof(dDT_STRUCT) == 32);
/* Align the dTD base to 32 byte boundary. */
usb_state.DTD_ALIGNED_BASE_PTR =
(dDT_STRUCT *)USB_MEM32_ALIGN((dDT_STRUCT *)dtd_base_ptr_mem);
/* Initialize the VUSB_HS controller and USB data base. */
USB_chip_and_data_base_initialize();
usb_state.USB_STATE = USB_STATE_DEFAULT;
}
/**************************************************************************
*
* Function Name : USB_lisr
* Returned Value : None
* Comments :
* Services all the VUSB_HS interrupt sources.
*
**************************************************************************/
#ifdef BOOTCODE
/*
* BOOTCODE version doesn't include nucleus so no HISR possible
*/
void USB_lisr(int interruptBit)
{
Uint32 status;
Uint8 new_speed;
for (;;) {
status = usb_opreg->USB_STS;
if (!(status & usb_opreg->USB_INTR))
break;
/* Clear all the interrupts that occured. */
usb_opreg->USB_STS = status;
/*
* Only process interrupt bits if we have not already invoked
* the reset task, otherwise let it proceed without interference.
*/
if (!USB_ForceReset && usb_state.USB_STATE != USB_STATE_POWER_ON) {
/* Process reset. */
if (status & VUSB_STS_RESET) {
/* Deconfigure interface before reset. */
USB_deconfigure_current_interface();
/*
* Only reset in Interrupt Service Routine if deconfigure
* went OK.
*/
if (!USB_ForceReset)
USB_ISR_process_reset();
}
/* Process change of speed (if not also reset). */
else if (status & VUSB_STS_PORT_CHANGE) {
if (usb_opreg->PORTSCX[0] & VUSB_PORTSCX_PORT_HIGH_SPEED)
new_speed = USB_DEV_HIGH_SPEED;
else
new_speed = USB_DEV_FULL_SPEED;
if (usb_state.SPEED != new_speed) {
usb_state.SPEED = new_speed;
usb_state.USB_STATE = USB_STATE_DEFAULT;
USB_speed_change();
}
}
/* Error count not currently used for anything. */
if (status & VUSB_STS_ERR)
usb_state.ERRORS++;
/* I/O transfer complete. */
if (status & VUSB_STS_INT)
USB_ISR_process_tr_complete();
/* Monitor change of suspend/resume. */
if (usb_state.USB_SUSPEND != (status & VUSB_STS_SUSPEND)) {
usb_state.USB_SUSPEND = status & VUSB_STS_SUSPEND;
/*
* Call to "suspend/resume" routine can go here.
*/
}
/* Start of USB frame: not currently enabled in VUSB_INTERRUPT_BITS */
if (status & VUSB_STS_SOF) {
/*
* Call to "Start of Frame" routine can go here; frame
* number is in "usb_opreg->USB_FRINDEX".
*/
}
}
}
/*
* Wake up USB reset/1248.4 task if appropriate.
*/
if (USB_ForceReset)
USB_WakeUpUSB_Task();
/* Clear bit in exception register. */
*(Uint32 *)EXCLRA = (1 << USB_INTERRUPT_BIT);
}
#else
NU_HISR usbHISR;
void USB_lisr(int interruptBit)
{
/* Mask off USB interrupts because we're moving to HISR */
*(unsigned long *)EXMSK1A &= ~2;
NU_Activate_HISR(&usbHISR);
/* Clear bit in exception register. */
*(Uint32 *)EXCLRA = (1 << USB_INTERRUPT_BIT);
}
/* High Interrupt Service Routine: Just wakes up USB task. */
void USB_hisr(void)
{
Uint32 status;
Uint8 new_speed;
/* Once test mode is entered, hang here until power cycle. */
while (TestModeLock)
{
}
for (;;) {
status = usb_opreg->USB_STS;
if (!(status & usb_opreg->USB_INTR))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -