📄 sl811.c
字号:
#include "defs.h"
#include "44b0x.h"
#include "usb.h"
#include "sl811.h"
#include <avt.h>
#include <stdarg.h>
// U盘设备地址
#define USB_ADDR 1
// 主机控制器中断允许位
#define INTS (SL_INTEN_DONE_A | SL_INTEN_Insert/* | SL_INTEN_SOF*/)
// USB请求返回值类型
#define ISR_CONTINUE 0 // 还有后续步骤
#define ISR_REPEAT 1 // 重复该步骤
#define ISR_ERROR 2 // 错误
#define ISR_DONE 3 // 结束本请求
#define ISR_SUSPEND 4 // 挂起
// 中断的开、关
#define PSW int psw;
#define DISABLE psw = interrupts_disable()
#define ENABLE interrupts_enable(psw)
//////////////////////////////////////////////////////////
void SL811Handler(void);
void udelay(UINT us);
void mdelay(UINT ms);
void sm_init(UINT);
//////////////////////////////////////////////////////////
static HC SL811; // USB主控制器
static MASS_STOR MassStor; // U盘结构
DRIVE UsbDsk; // U盘驱动器
UINT smSL811; // 信号量
// 调试输出
void
DbgOut(const char *fmt, ...) {
va_list ap;
PSW
static char buf[1024];
psw = interrupts_disable();
va_start(ap, fmt);
myvsprintf(buf, fmt, ap);
va_end(ap);
interrupts_enable(psw);
bsp_puts(buf);
}
// 诊断失败
// f: 文件
// l: 行
// expr: 表达式
//
void
__assert(const char *f, int l, const char *expr) {
interrupts_disable();
DbgOut("%s:%u `%s`", f, l, expr);
while(1);
}
///////////////////////////////////////////////////////////
// 读主控制器寄存器
//
// hc: 主控制器
// reg:寄存器
//
static UCHAR
hc_read(HC *hc, UCHAR reg) {
outb(hc->AddrPort, reg);
return inb(hc->DataPort);
}
// 写主控制器寄存器
//
// hc: 主控制器
// reg:寄存器
// val:值
//
static void
hc_write(HC *hc, UCHAR reg, UCHAR val) {
outb(hc->AddrPort, reg);
outb(hc->DataPort, val);
}
// 写连续的多个主控制器寄存器
//
// hc: 主控制器
// addr:起始寄存器
// buf: 值数组起始地址
// count: 寄存器数
//
static void
hc_write_buf(HC *hc, UCHAR addr, const UCHAR *buf, UINT count) {
ASSERT(count <= 64);
outb(hc->AddrPort, addr);
do {
outb(hc->DataPort, *buf++);
} while (--count);
}
// 读连续的多个主控制器寄存器
// hc: 主控制器
// addr:起始寄存器
// buf: 值数组起始地址
// count: 寄存器数
//
static void
hc_read_buf(HC *hc, UCHAR addr, UCHAR *buf, UINT count) {
ASSERT(count <= 64);
outb(hc->AddrPort, addr);
do {
*buf++ = inb(hc->DataPort);
} while (--count);
}
///////////////////////////////////////////////////////////////////
// SETUP阶段
//
// hc: 主控制器
// urb: USB请求
//
static int
SA_Setup(HC *hc, URB *urb) {
UCHAR ctl;
PSW
/* Build the value to stick into the ctl register
*/
ctl = SL_HCR_Out | SL_HCR_Arm | SL_HCR_Enable;
/* preamble?
*/
if (urb->Flags & URB_FLAG_LOW_SPEED)
ctl |= SL_HCR_Preamble;
DISABLE;
/* Set buffer pointer to start of usable RAM
*/
hc_write(hc, SL_HBA_A, SL_MEM);
/* If we got something to say
*/
hc_write_buf(hc, SL_MEM, urb->SetupData, 8);
/* BUGBUG check for time
*/
/* Length
*/
hc_write(hc,SL_HBL_A,8);
/* Set PID, endpoint address, device address
*/
hc_write(hc, SL_HPID_A,
SL_MAKE_HPID(SL_HPID_SETUP, 0/*urb->Ep->Endpoint*/));
hc_write(hc, SL_HDA_A, urb->DeviceAddress);
/* Go
*/
hc_write(hc, SL_ISTATUS, 0xFF);
hc_write(hc, SL_HCR_A, ctl);
urb->Ep->Toggle = SL_HCR_DToggle;
ENABLE;
return ISR_CONTINUE;
}
// 根据主控制器状态寄存器,决定本阶段结果
//
// hc: 主控制器
// urb: USB请求
//
static int
SA_CheckErrors(HC *hc, URB *urb) {
UCHAR Status;
Status = hc_read(hc, SL_STATUS_A);
// BUGBUG, some device response (ACK|Overflow) --YKH
if(Status & SL_STATUS_ACK)
return ISR_CONTINUE;
/* Everything ok?
*/
if (0 == (Status & (SL_STATUS_NAK |
SL_STATUS_Error |
SL_STATUS_Timeout |
SL_STATUS_STALL |
SL_STATUS_Overflow)))
{
return ISR_CONTINUE;
}
/* Just a glitch?
*/
if (Status & SL_STATUS_NAK)
{
return ISR_SUSPEND;
}
/* Something serious, bail out
* Swap STALL and Timeout to make STALL same as others
*/
#define MiStatus(s) ((UINT)((s & ~0x84) | ((s&0x80)>>5) | ((s&4)<<5)))
urb->FinalStatus = MiStatus(Status);
return ISR_ERROR;
}
// USB输入命令阶段
//
// hc: 主控制器
// urb: USB请求
//
static int
SA_In(HC *hc, URB *urb) {
PSW
UINT l = urb->ExpectedDataLength - urb->ActualDataLength;
UCHAR ctl;
DISABLE;
/* Build the value to stick into the ctl register
*/
ctl = urb->Ep->Toggle;
ctl |= SL_HCR_Arm | SL_HCR_Enable;
/* isochronous?
*/
if (urb->Flags & URB_FLAG_ISOCHRONOUS)
ctl |= SL_HCR_ISO;
/* preamble?
*/
if (urb->Flags & URB_FLAG_LOW_SPEED)
ctl |= SL_HCR_Preamble;
/* Set buffer pointer to start of usable RAM
*/
hc_write(hc, SL_HBA_A, SL_MEM);
/* Length
*/
if (l > urb->Ep->Payload)
l = urb->Ep->Payload;
hc_write(hc, SL_HBL_A, (UCHAR)l);
/* Set PID for IN phase, endpoint address
*/
hc_write(hc, SL_HPID_A,
SL_MAKE_HPID(SL_HPID_IN, urb->Ep->Endpoint));
hc_write(hc, SL_HDA_A, urb->DeviceAddress);
/* Go
*/
hc_write(hc, SL_ISTATUS, 0xFF);
hc_write(hc, SL_HCR_A, ctl);
urb->Ep->Toggle ^= SL_HCR_DToggle;
ENABLE;
return ISR_CONTINUE;
}
// USB输出命令阶段
//
// hc: 主控制器
// urb: USB请求
//
static int
SA_Out(HC *hc, URB *urb) {
PSW
UINT l = urb->ExpectedDataLength - urb->ActualDataLength;
UCHAR ctl;
DISABLE;
if (l > urb->Ep->Payload)
l = urb->Ep->Payload;
/* Build the value to stick into the ctl register
*/
ctl = urb->Ep->Toggle;
ctl |= SL_HCR_Arm | SL_HCR_Enable | SL_HCR_Out;
/* isochronous?
*/
if (urb->Flags & URB_FLAG_ISOCHRONOUS)
ctl |= SL_HCR_ISO;
/* preamble?
*/
if (urb->Flags & URB_FLAG_LOW_SPEED)
ctl |= SL_HCR_Preamble;
/* We got something to say
*/
if (l)
{
/* Set buffer pointer to start of usable RAM
*/
hc_write(hc, SL_HBA_A, SL_MEM);
hc_write_buf(hc, SL_MEM, urb->Data + urb->ActualDataLength, l);
}
/* Length
*/
hc_write(hc, SL_HBL_A, (UCHAR)l);
/* Set PID for OUT phase, endpoint address
*/
hc_write(hc, SL_HPID_A,
SL_MAKE_HPID(SL_HPID_OUT, urb->Ep->Endpoint));
hc_write(hc, SL_HDA_A, urb->DeviceAddress);
/* Go
*/
hc_write(hc, SL_ISTATUS, 0xFF);
hc_write(hc, SL_HCR_A, ctl);
urb->Ep->Toggle ^= SL_HCR_DToggle;
ENABLE;
return ISR_CONTINUE;
}
// USB输出阶段(延时)
//
// hc: 主控制器
// urb: USB请求
//
static int
SA_Out2(HC *hc, URB *urb) {
/* No idea why this should be necessary.
* Minimum value seems to be around 86-90us.
*/
udelay(100);
return SA_Out(hc, urb);
}
// USB输入数据阶段
//
// hc: 主控制器
// urb: USB请求
//
static int
SA_InBytes(HC *hc, URB *urb) {
UINT Length;
UINT Bytes2Go = 0;
if(!(hc_read(hc, SL_STATUS_A) & SL_STATUS_ACK)) {
return SA_CheckErrors(hc, urb);
}
Length = hc_read(hc, SL_HBL_A) - hc_read(hc, SL_TC_A);
/* BUGBUG Shakey h/w ...
*/
Length &= 0xff;
if (Length)
{
hc_read_buf(hc, SL_MEM, urb->Data + urb->ActualDataLength, Length);
urb->ActualDataLength += (USHORT)Length;
Bytes2Go = urb->ExpectedDataLength - urb->ActualDataLength;
/* But not if we did not get a full packet */
if (Length < urb->Ep->Payload)
Bytes2Go = 0;
}
/* Ask for more iff...
*/
if (Bytes2Go &&
Length)
{
return ISR_REPEAT;
}
/* Only go to status for SETUPs
*/
if (!(urb->Flags & URB_FLAG_CONTROL))
return ISR_DONE;
return ISR_CONTINUE;
}
// USB输出数据阶段
//
// hc: 主控制器
// urb: USB请求
//
static int
SA_OutBytes(HC *hc, URB *urb) {
UINT Length;
UINT Bytes2Go;
int r;
r = SA_CheckErrors(hc, urb);
if (r != ISR_CONTINUE)
return r;
Length = hc_read(hc, SL_HBL_A) - hc_read(hc, SL_TC_A);
urb->ActualDataLength += (USHORT)Length;
Bytes2Go = urb->ExpectedDataLength - urb->ActualDataLength;
if (Bytes2Go)
{
return ISR_REPEAT;
}
/* Only go to status for SETUPs
*/
if (!(urb->Flags & URB_FLAG_CONTROL))
return ISR_DONE;
return ISR_CONTINUE;
}
// USB输入状态阶段
//
// hc: 主控制器
// urb: USB请求
//
static int
SA_StatusIn(HC *hc, URB *urb) {
UCHAR ctl;
/* Build the value to stick into the ctl register
*/
ctl = SL_HCR_Arm | SL_HCR_Enable | SL_HCR_DToggle;
/* preamble?
*/
if (urb->Flags & URB_FLAG_LOW_SPEED)
ctl |= SL_HCR_Preamble;
/* Length
*/
hc_write(hc, SL_HBL_A, 0);
/* Set PID for IN phase, endpoint address
*/
hc_write(hc, SL_HPID_A,
SL_MAKE_HPID(SL_HPID_IN, urb->Ep->Endpoint));
hc_write(hc, SL_HDA_A, urb->DeviceAddress);
/* Go
*/
hc_write(hc, SL_ISTATUS, 0xFF);
hc_write(hc, SL_HCR_A, ctl);
return ISR_CONTINUE;
}
// USB输出状态(ACK)阶段
//
// hc: 主控制器
// urb: USB请求
//
static int
SA_StatusOut(HC *hc, URB *urb) {
UCHAR ctl;
/* Build the value to stick into the ctl register
*/
ctl = SL_HCR_Arm | SL_HCR_Enable | SL_HCR_Out | SL_HCR_DToggle;
/* preamble?
*/
if (urb->Flags & URB_FLAG_LOW_SPEED)
ctl |= SL_HCR_Preamble;
/* Length
*/
hc_write(hc, SL_HBL_A, 0);
/* Set PID for IN phase, endpoint address
*/
hc_write(hc, SL_HPID_A,
SL_MAKE_HPID(SL_HPID_OUT, urb->Ep->Endpoint));
hc_write(hc, SL_HDA_A, urb->DeviceAddress);
/* Go
*/
hc_write(hc, SL_ISTATUS, 0xFF);
hc_write(hc, SL_HCR_A, ctl);
return ISR_CONTINUE;
}
// USB结束阶段
//
// hc: 主控制器
// urb: USB请求
//
static int
SA_ControlDone(HC *hc, URB *urb) {
int r;
r = SA_CheckErrors(hc, urb);
if (r != ISR_CONTINUE)
return r;
return ISR_DONE;
}
//
// USB请求脚本
//
static SCRIPT AllScripts[] = {
#define NoDataControlScript 0 // 无数据控制写
{ SA_Setup, SA_CheckErrors},
{ SA_StatusIn, SA_ControlDone},
#define ControlReadScript 2 // 控制读
{ SA_Setup, SA_CheckErrors},
{ SA_In, SA_InBytes},
{ SA_StatusOut, SA_ControlDone},
#define ControlWriteScript 5 // 控制写
{ SA_Setup, SA_CheckErrors},
{ SA_Out2, SA_OutBytes},
{ SA_StatusIn, SA_ControlDone},
#define ReadScript 8 // 读
{ SA_In, SA_InBytes},
#define WriteScript 9 // 写
{ SA_Out, SA_OutBytes}
};
/////////////////////////////////////////////////////
// SL811HS中断处理程序
//
void
SL811Isr(void) {
PSW
URB *urb;
HC *hc = &SL811;
int r;
UCHAR st;
UCHAR DoScript;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -