From e8b3efcc2d355cc9c4acd7ec1d997ca53aa34e26 Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Sat, 13 Dec 2008 03:32:16 +0000 Subject: [PATCH] 1) common headers 2) usb code git-svn-id: svn://kolibrios.org@954 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/system/drivers/agp/agp.c | 2 - programs/system/drivers/agp/agp.h | 24 + programs/system/drivers/agp/makefile | 11 +- programs/system/drivers/ati2d/accel_2d.h | 5 +- programs/system/drivers/ati2d/ati2d.c | 2 +- programs/system/drivers/ati2d/ati2d.h | 2 +- programs/system/drivers/ati2d/blend.inc | 284 +++++++++- programs/system/drivers/ati2d/init_3d.inc | 11 +- programs/system/drivers/ati2d/makefile | 15 +- programs/system/drivers/ati2d/vs_prog.inc | 3 - programs/system/drivers/include/link.h | 60 +++ programs/system/drivers/include/syscall.h | 299 +++++++++++ programs/system/drivers/include/types.h | 24 + programs/system/drivers/usb/ch9.h | 577 +++++++++++++++++++++ programs/system/drivers/usb/detect.inc | 63 +++ programs/system/drivers/usb/hcd.inc | 604 ++++++++++++++++++++++ programs/system/drivers/usb/hid.h | 523 +++++++++++++++++++ programs/system/drivers/usb/hid.inc | 154 ++++++ programs/system/drivers/usb/makefile | 42 ++ programs/system/drivers/usb/pci.h | 95 ++++ programs/system/drivers/usb/pci.inc | 98 ++++ programs/system/drivers/usb/usb.asm | 27 + programs/system/drivers/usb/usb.c | 231 +++++++++ programs/system/drivers/usb/usb.h | 247 +++++++++ programs/system/drivers/usb/usb.lk1 | 22 + 25 files changed, 3377 insertions(+), 48 deletions(-) create mode 100644 programs/system/drivers/include/link.h create mode 100644 programs/system/drivers/include/syscall.h create mode 100644 programs/system/drivers/include/types.h create mode 100644 programs/system/drivers/usb/ch9.h create mode 100644 programs/system/drivers/usb/detect.inc create mode 100644 programs/system/drivers/usb/hcd.inc create mode 100644 programs/system/drivers/usb/hid.h create mode 100644 programs/system/drivers/usb/hid.inc create mode 100644 programs/system/drivers/usb/makefile create mode 100644 programs/system/drivers/usb/pci.h create mode 100644 programs/system/drivers/usb/pci.inc create mode 100644 programs/system/drivers/usb/usb.asm create mode 100644 programs/system/drivers/usb/usb.c create mode 100644 programs/system/drivers/usb/usb.h create mode 100644 programs/system/drivers/usb/usb.lk1 diff --git a/programs/system/drivers/agp/agp.c b/programs/system/drivers/agp/agp.c index 189f6e65a8..a43abfa1ca 100644 --- a/programs/system/drivers/agp/agp.c +++ b/programs/system/drivers/agp/agp.c @@ -500,8 +500,6 @@ void agp_device_command(u32_t bridge_agpstat, int agp_v3) } - - void agp_generic_enable(u32_t requested_mode) { u32_t bridge_agpstat, temp; diff --git a/programs/system/drivers/agp/agp.h b/programs/system/drivers/agp/agp.h index 5b8e577d0a..2880553a12 100644 --- a/programs/system/drivers/agp/agp.h +++ b/programs/system/drivers/agp/agp.h @@ -115,4 +115,28 @@ typedef struct // void (*agp_destroy_page)(void *); }agp_t; +/* + * min()/max() macros that also do + * strict type-checking.. See the + * "unnecessary" pointer comparison. + */ +#define min(x,y) ({ \ + typeof(x) _x = (x); \ + typeof(y) _y = (y); \ + (void) (&_x == &_y); \ + _x < _y ? _x : _y; }) + +#define max(x,y) ({ \ + typeof(x) _x = (x); \ + typeof(y) _y = (y); \ + (void) (&_x == &_y); \ + _x > _y ? _x : _y; }) + + +#define min_t(type,x,y) \ + ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) +#define max_t(type,x,y) \ + ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) + + diff --git a/programs/system/drivers/agp/makefile b/programs/system/drivers/agp/makefile index 6bc3f65ff3..51b23250a8 100644 --- a/programs/system/drivers/agp/makefile +++ b/programs/system/drivers/agp/makefile @@ -4,9 +4,12 @@ FASM = e:/fasm/fasm.exe CFLAGS = -c -O2 -fomit-frame-pointer -fno-builtin-printf LDRHD = -shared -T ld.x -s --file-alignment 32 -HFILES:= agp.h \ - syscall.h \ - pci.h \ +INCLUDES = -I ../include + +HFILES:= ../include/types.h \ + ../include/syscall.h \ + agp.h \ + pci.h \ SRC_DEP:= pci.inc \ detect.inc \ @@ -24,7 +27,7 @@ $(AGP): agp.obj $(SRC_DEP) $(HFILES) Makefile kpack.exe agp.dll agp.drv agp.obj : agp.c $(SRC_DEP) $(HFILES) Makefile - $(CC) $(CFLAGS) -o agp.obj agp.c + $(CC) $(INCLUDES) $(CFLAGS) -o agp.obj agp.c diff --git a/programs/system/drivers/ati2d/accel_2d.h b/programs/system/drivers/ati2d/accel_2d.h index 615da15f94..7e22621baa 100644 --- a/programs/system/drivers/ati2d/accel_2d.h +++ b/programs/system/drivers/ati2d/accel_2d.h @@ -129,7 +129,10 @@ typedef struct int w; int h; - color_t key; + union { + color_t key; + color_t alpha; + }; }io_blit_t; diff --git a/programs/system/drivers/ati2d/ati2d.c b/programs/system/drivers/ati2d/ati2d.c index 83ed1a5467..001748cadb 100644 --- a/programs/system/drivers/ati2d/ati2d.c +++ b/programs/system/drivers/ati2d/ati2d.c @@ -146,7 +146,7 @@ int __stdcall srv_2d(ioctl_t *io) break; case PX_BLIT_ALPHA: - if(io->inp_size==8) + if(io->inp_size==9) return RadeonComposite((io_blit_t*)inp); break; diff --git a/programs/system/drivers/ati2d/ati2d.h b/programs/system/drivers/ati2d/ati2d.h index 2400e17921..a2f22c403b 100644 --- a/programs/system/drivers/ati2d/ati2d.h +++ b/programs/system/drivers/ati2d/ati2d.h @@ -91,7 +91,7 @@ typedef enum (info->ChipFamily == CHIP_FAMILY_RS600) || \ (info->ChipFamily == CHIP_FAMILY_RS740) || \ (info->ChipFamily == CHIP_FAMILY_RS400) || \ - (info->ChipFamily == CHIP_FAMILY_RS480)) + (info->ChipFamily == CHIP_FAMILY_RS480)) diff --git a/programs/system/drivers/ati2d/blend.inc b/programs/system/drivers/ati2d/blend.inc index 33f569de2e..24b993ca1c 100644 --- a/programs/system/drivers/ati2d/blend.inc +++ b/programs/system/drivers/ati2d/blend.inc @@ -34,6 +34,63 @@ static struct blendinfo RadeonBlendOp[] = { {0, 0, RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ONE}, }; +static Bool R200PrepareComposite(local_pixmap_t *dstpix, int dstX, int dstY, + local_pixmap_t *srcpix, int srcX, int srcY, + int w, int h, int alpha) +{ + u32_t tex_size = 0, txformat, blend_cntl; + int dst_pitch; + + if ((w > 2048) || (h > 2048)) + return FALSE; + + txformat = RADEON_TXFORMAT_ARGB8888 | + RADEON_TXFORMAT_ALPHA_IN_MAP | + RADEON_TXFORMAT_NON_POWER2; + + blend_cntl = RADEON_SRC_BLEND_GL_SRC_ALPHA | + RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA; + + tex_size = ((h - 1) << 16) | (w - 1); + { + u32_t *ring; + u32_t ifl = safe_cli(); + + BEGIN_ACCEL(168); + OUT_ACCEL_REG(R200_PP_TXFORMAT_0, txformat); + OUT_ACCEL_REG(R200_PP_TXFORMAT_X_0, 0); + OUT_ACCEL_REG(R200_PP_TXSIZE_0, tex_size); + OUT_ACCEL_REG(R200_PP_TXPITCH_0, srcpix->pitch - 32); + OUT_ACCEL_REG(R200_PP_TXOFFSET_0, (u32_t)srcpix->local); + OUT_ACCEL_REG(R200_PP_TXFILTER_0, R200_MAG_FILTER_NEAREST | + R200_MIN_FILTER_NEAREST | + R200_CLAMP_S_WRAP | + R200_CLAMP_T_WRAP); + + OUT_ACCEL_REG(RADEON_RB3D_CNTL, RADEON_COLOR_FORMAT_ARGB8888 | + RADEON_ALPHA_BLEND_ENABLE); + OUT_ACCEL_REG(RADEON_PP_CNTL, RADEON_TEX_0_ENABLE | + RADEON_TEX_BLEND_0_ENABLE); + OUT_ACCEL_REG(R200_PP_TFACTOR_0, alpha << 24); + OUT_ACCEL_REG(R200_PP_TXCBLEND_0, R200_TXC_ARG_A_TFACTOR_COLOR | + R200_TXC_ARG_B_R0_ALPHA); + OUT_ACCEL_REG(R200_PP_TXCBLEND2_0,R200_TXC_OUTPUT_REG_R0); + OUT_ACCEL_REG(R200_PP_TXABLEND_0, R200_TXA_ARG_A_TFACTOR_ALPHA | + R200_TXA_ARG_B_R0_ALPHA); + OUT_ACCEL_REG(R200_PP_TXABLEND2_0, R200_TXA_OUTPUT_REG_R0); + OUT_ACCEL_REG(R200_SE_VTX_FMT_0, 0); + OUT_ACCEL_REG(R200_SE_VTX_FMT_1, (2 << R200_VTX_TEX0_COMP_CNT_SHIFT)); + OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blend_cntl); + + OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, dstpix->pitch >> 2); + OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, (u32_t)dstpix->local); + + COMMIT_RING(); + safe_sti(ifl); + }; + + return TRUE; +} static Bool R300TextureSetup(RHDPtr info,local_pixmap_t *srcpix, int w, int h, int unit) { @@ -67,7 +124,7 @@ static Bool R300TextureSetup(RHDPtr info,local_pixmap_t *srcpix, int w, int h, i //txformat1 = R300TexFormats[i].card_fmt; - txformat1 = R300_TX_FORMAT_A8R8G8B8;// R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8); + txformat1 = R300_TX_FORMAT_A8R8G8B8; txformat0 = ((((w - 1) & 0x7ff) << R300_TXWIDTH_SHIFT) | (((h - 1) & 0x7ff) << R300_TXHEIGHT_SHIFT)); @@ -253,12 +310,14 @@ Bool R300PrepareComposite(local_pixmap_t *dstpix, int dstX, int dstY, * - Xv * Here we select the offset of the vertex program we want to use */ + if (info->has_tcl) { OUT_ACCEL_REG(R300_VAP_PVS_CODE_CNTL_0, - ((3 << R300_PVS_FIRST_INST_SHIFT) | - (4 << R300_PVS_XYZW_VALID_INST_SHIFT) | - (4 << R300_PVS_LAST_INST_SHIFT))); + ((3 << R300_PVS_FIRST_INST_SHIFT) | + (4 << R300_PVS_XYZW_VALID_INST_SHIFT) | + (4 << R300_PVS_LAST_INST_SHIFT))); OUT_ACCEL_REG(R300_VAP_PVS_CODE_CNTL_1, - (4 << R300_PVS_LAST_VTX_SRC_INST_SHIFT)); + (4 << R300_PVS_LAST_VTX_SRC_INST_SHIFT)); + } /* Position and one or two sets of 2 texture coordinates */ OUT_ACCEL_REG(R300_VAP_OUT_VTX_FMT_0, R300_VTX_POS_PRESENT); //VTX_COLOR_0_PRESENT @@ -274,6 +333,111 @@ Bool R300PrepareComposite(local_pixmap_t *dstpix, int dstX, int dstY, /* setup pixel shader */ if (IS_R300_3D) { + u32_t output_fmt; + int src_color, src_alpha; + int mask_color, mask_alpha; + + src_color = R300_ALU_RGB_SRC0_RGB; + + src_alpha = R300_ALU_ALPHA_SRC0_A; + + mask_color = R300_ALU_RGB_1_0; + mask_alpha = R300_ALU_ALPHA_1_0; + + /* shader output swizzling */ + output_fmt = (R300_OUT_FMT_C4_8 | + R300_OUT_FMT_C0_SEL_BLUE | + R300_OUT_FMT_C1_SEL_GREEN | + R300_OUT_FMT_C2_SEL_RED | + R300_OUT_FMT_C3_SEL_ALPHA); + + + /* setup the rasterizer, load FS */ + BEGIN_ACCEL(10); + /* 2 components: 2 for tex0 */ + OUT_ACCEL_REG(R300_RS_COUNT, + ((2 << R300_RS_COUNT_IT_COUNT_SHIFT) | + R300_RS_COUNT_HIRES_EN)); + + OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6)); + + OUT_ACCEL_REG(R300_US_CODE_OFFSET, (R300_ALU_CODE_OFFSET(0) | + R300_ALU_CODE_SIZE(0) | + R300_TEX_CODE_OFFSET(0) | + R300_TEX_CODE_SIZE(0))); + + OUT_ACCEL_REG(R300_US_CODE_ADDR_3, + (R300_ALU_START(0) | + R300_ALU_SIZE(0) | + R300_TEX_START(0) | + R300_TEX_SIZE(0) | + R300_RGBA_OUT)); + + OUT_ACCEL_REG(R300_US_PIXSIZE, 1); /* highest temp used */ + /* shader output swizzling */ + OUT_ACCEL_REG(R300_US_OUT_FMT_0, output_fmt); + + /* tex inst for src texture is pre-loaded in RADEONInit3DEngine() */ + /* tex inst for mask texture is pre-loaded in RADEONInit3DEngine() */ + + /* RGB inst + * temp addresses for texture inputs + * ALU_RGB_ADDR0 is src tex (temp 0) + * ALU_RGB_ADDR1 is mask tex (temp 1) + * R300_ALU_RGB_OMASK - output components to write + * R300_ALU_RGB_TARGET_A - render target + */ + OUT_ACCEL_REG(R300_US_ALU_RGB_ADDR(0), + (R300_ALU_RGB_ADDR0(0) | + R300_ALU_RGB_ADDR1(1) | + R300_ALU_RGB_ADDR2(0) | + R300_ALU_RGB_ADDRD(0) | + R300_ALU_RGB_OMASK((R300_ALU_RGB_MASK_R | + R300_ALU_RGB_MASK_G | + R300_ALU_RGB_MASK_B)) | + R300_ALU_RGB_TARGET_A)); + /* RGB inst + * ALU operation + */ + OUT_ACCEL_REG(R300_US_ALU_RGB_INST(0), + (R300_ALU_RGB_SEL_A(src_color) | + R300_ALU_RGB_MOD_A(R300_ALU_RGB_MOD_NOP) | + R300_ALU_RGB_SEL_B(mask_color) | + R300_ALU_RGB_MOD_B(R300_ALU_RGB_MOD_NOP) | + R300_ALU_RGB_SEL_C(R300_ALU_RGB_0_0) | + R300_ALU_RGB_MOD_C(R300_ALU_RGB_MOD_NOP) | + R300_ALU_RGB_OP(R300_ALU_RGB_OP_MAD) | + R300_ALU_RGB_OMOD(R300_ALU_RGB_OMOD_NONE) | + R300_ALU_RGB_CLAMP)); + /* Alpha inst + * temp addresses for texture inputs + * ALU_ALPHA_ADDR0 is src tex (0) + * ALU_ALPHA_ADDR1 is mask tex (1) + * R300_ALU_ALPHA_OMASK - output components to write + * R300_ALU_ALPHA_TARGET_A - render target + */ + OUT_ACCEL_REG(R300_US_ALU_ALPHA_ADDR(0), + (R300_ALU_ALPHA_ADDR0(0) | + R300_ALU_ALPHA_ADDR1(1) | + R300_ALU_ALPHA_ADDR2(0) | + R300_ALU_ALPHA_ADDRD(0) | + R300_ALU_ALPHA_OMASK(R300_ALU_ALPHA_MASK_A) | + R300_ALU_ALPHA_TARGET_A | + R300_ALU_ALPHA_OMASK_W(R300_ALU_ALPHA_MASK_NONE))); + /* Alpha inst + * ALU operation + */ + OUT_ACCEL_REG(R300_US_ALU_ALPHA_INST(0), + (R300_ALU_ALPHA_SEL_A(src_alpha) | + R300_ALU_ALPHA_MOD_A(R300_ALU_ALPHA_MOD_NOP) | + R300_ALU_ALPHA_SEL_B(mask_alpha) | + R300_ALU_ALPHA_MOD_B(R300_ALU_ALPHA_MOD_NOP) | + R300_ALU_ALPHA_SEL_C(R300_ALU_ALPHA_0_0) | + R300_ALU_ALPHA_MOD_C(R300_ALU_ALPHA_MOD_NOP) | + R300_ALU_ALPHA_OP(R300_ALU_ALPHA_OP_MAD) | + R300_ALU_ALPHA_OMOD(R300_ALU_ALPHA_OMOD_NONE) | + R300_ALU_ALPHA_CLAMP)); + FINISH_ACCEL(); } else { @@ -287,8 +451,8 @@ Bool R300PrepareComposite(local_pixmap_t *dstpix, int dstX, int dstY, // R500_ALU_RGB_B_SWIZ_A_0); // else src_color = (R500_ALU_RGB_R_SWIZ_A_R | - R500_ALU_RGB_G_SWIZ_A_G | - R500_ALU_RGB_B_SWIZ_A_B); + R500_ALU_RGB_G_SWIZ_A_G | + R500_ALU_RGB_B_SWIZ_A_B); // if (PICT_FORMAT_A(PICT_a8r8g8b8) == 0) // src_alpha = R500_ALPHA_SWIZ_A_1; @@ -445,16 +609,16 @@ static __inline__ u32_t F_TO_DW(float val) #define OUT_RING_F(x) OUT_RING(F_TO_DW(x)) #define VTX_OUT(_dstX, _dstY, _srcX, _srcY) \ -do { \ - OUT_RING_F(_dstX); \ - OUT_RING_F(_dstY); \ - OUT_RING_F(_srcX); \ - OUT_RING_F(_srcY); \ +do { \ + OUT_RING_F(_dstX); \ + OUT_RING_F(_dstY); \ + OUT_RING_F(_srcX); \ + OUT_RING_F(_srcY); \ } while (0) -static int RadeonCompositeTile(int srcX, int srcY, +static int R300CompositeTile(int srcX, int srcY, int dstX, int dstY, int w, int h) { @@ -532,7 +696,7 @@ static int RadeonCompositeTile(int srcX, int srcY, /* flushing is pipelined, free/finish is not */ OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D); - OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN); + // OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN); COMMIT_RING(); @@ -540,6 +704,59 @@ static int RadeonCompositeTile(int srcX, int srcY, // LEAVE_DRAW(0); } + + +static int R200CompositeTile(int srcX, int srcY, + int dstX, int dstY, + int w, int h) +{ + xPointFixed srcTopLeft, srcTopRight, srcBottomLeft, srcBottomRight; + xPointFixed maskTopLeft, maskTopRight, maskBottomLeft, maskBottomRight; + + srcTopLeft.x = IntToxFixed(srcX); + srcTopLeft.y = IntToxFixed(srcY); + srcTopRight.x = IntToxFixed(srcX + w); + srcTopRight.y = IntToxFixed(srcY); + srcBottomLeft.x = IntToxFixed(srcX); + srcBottomLeft.y = IntToxFixed(srcY + h); + srcBottomRight.x = IntToxFixed(srcX + w); + srcBottomRight.y = IntToxFixed(srcY + h); + + { + u32_t *ring; + u32_t ifl = safe_cli(); + + BEGIN_RING(4 + 4 * VTX_COUNT); + + OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2, 4 * VTX_COUNT)); + OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN | + RADEON_CP_VC_CNTL_PRIM_WALK_RING | + (4 << RADEON_CP_VC_CNTL_NUM_SHIFT)); + + + VTX_OUT((float)dstX, (float)dstY, + xFixedToFloat(srcTopLeft.x) / w, // info->texW[0], + xFixedToFloat(srcTopLeft.y) / h); // info->texH[0]); + + VTX_OUT((float)dstX, (float)(dstY + h), + xFixedToFloat(srcBottomLeft.x) / w, // info->texW[0], + xFixedToFloat(srcBottomLeft.y) / h); // info->texH[0]); + + VTX_OUT((float)(dstX + w), (float)(dstY + h), + xFixedToFloat(srcBottomRight.x) / w, // info->texW[0], + xFixedToFloat(srcBottomRight.y) / h); // info->texH[0]); + + VTX_OUT((float)(dstX + w), (float)dstY, + xFixedToFloat(srcTopRight.x) / w, // info->texW[0], + xFixedToFloat(srcTopRight.y) / h); // info->texH[0]); + + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN); + + COMMIT_RING(); + safe_sti(ifl); + }; +}; + #undef VTX_OUT #undef VTX_OUT_MASK @@ -576,24 +793,45 @@ int RadeonComposite( io_blit_t *blit) ); OUT_RING(srcpixmap->pitch_offset); - OUT_RING(blit->key); + OUT_RING(blit->alpha<<24); OUT_RING( 0 ); OUT_RING((srcpixmap->width<<16)|srcpixmap->height); COMMIT_RING(); + RHDPtr info = &rhd; + + if( IS_R300_3D || IS_R500_3D ) + { + R300PrepareComposite(dstpixmap, blit->dst_x, blit->dst_y, + srcpixmap, blit->src_x, blit->src_y, + blit->w, blit->h, 3); + +// if (!need_src_tile_x && !need_src_tile_y) { + R300CompositeTile( blit->src_x, blit->src_y, + blit->dst_x, blit->dst_y, + blit->w, blit->h); + } + else if ((info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280) || + (info->ChipFamily == CHIP_FAMILY_RS300) || + (info->ChipFamily == CHIP_FAMILY_R200)) + { + R200PrepareComposite(dstpixmap, blit->dst_x, blit->dst_y, + srcpixmap, blit->src_x, blit->src_y, + blit->w, blit->h, blit->alpha); + R200CompositeTile( blit->src_x, blit->src_y, + blit->dst_x, blit->dst_y, + blit->w, blit->h); + }; + + safe_sti(ifl); }; - R300PrepareComposite(dstpixmap, blit->dst_x, blit->dst_y, - srcpixmap, blit->src_x, blit->src_y, - blit->w, blit->h, 3); -// if (!need_src_tile_x && !need_src_tile_y) { - RadeonCompositeTile( blit->src_x, blit->src_y, - blit->dst_x, blit->dst_y, - blit->w, blit->h); - return 0; + + return 0; // } /* Tiling logic borrowed from exaFillRegionTiled */ diff --git a/programs/system/drivers/ati2d/init_3d.inc b/programs/system/drivers/ati2d/init_3d.inc index e43c37cefd..095c5b7d2e 100644 --- a/programs/system/drivers/ati2d/init_3d.inc +++ b/programs/system/drivers/ati2d/init_3d.inc @@ -11,8 +11,6 @@ int Init3DEngine(RHDPtr info) ifl = safe_cli(); - - if (IS_R300_3D || IS_R500_3D) { BEGIN_ACCEL(3); @@ -617,11 +615,10 @@ int Init3DEngine(RHDPtr info) OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, 0); else OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, RADEON_TCL_BYPASS); - OUT_ACCEL_REG(RADEON_SE_COORD_FMT, - RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | - RADEON_VTX_ST0_NONPARAMETRIC | - RADEON_VTX_ST1_NONPARAMETRIC | - RADEON_TEX1_W_ROUTING_USE_W0); + OUT_ACCEL_REG(RADEON_SE_COORD_FMT, RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | + RADEON_VTX_ST0_NONPARAMETRIC | + RADEON_VTX_ST1_NONPARAMETRIC | + RADEON_TEX1_W_ROUTING_USE_W0); FINISH_ACCEL(); BEGIN_ACCEL(5); diff --git a/programs/system/drivers/ati2d/makefile b/programs/system/drivers/ati2d/makefile index 142ef52f7d..85623ffe8a 100644 --- a/programs/system/drivers/ati2d/makefile +++ b/programs/system/drivers/ati2d/makefile @@ -4,11 +4,14 @@ FASM = e:/fasm/fasm.exe CFLAGS = -c -O2 -fomit-frame-pointer -fno-builtin-printf LDRHD = -shared -T ld.x -s --file-alignment 32 -HFILES:= ati2d.h \ - syscall.h \ - pci.h \ - accel_2d.h \ - r5xx_regs.h \ +INCLUDES = -I ../include + +HFILES:= ../include/types.h \ + ../include/syscall.h \ + ati2d.h \ + pci.h \ + accel_2d.h \ + r5xx_regs.h \ radeon_microcode.h SRC_DEP:= init.c \ @@ -40,7 +43,7 @@ $(ATI2D): $(ATI_OBJ) $(SRC_DEP) $(HFILES) Makefile kpack.exe ati2d.dll ati2d.drv ati2d.obj : ati2d.c $(SRC_DEP) $(HFILES) Makefile - $(CC) $(CFLAGS) -o ati2d.obj ati2d.c + $(CC) $(INCLUDES) $(CFLAGS) -o ati2d.obj ati2d.c curhelp.obj : curhelp.asm $(FASM) curhelp.asm diff --git a/programs/system/drivers/ati2d/vs_prog.inc b/programs/system/drivers/ati2d/vs_prog.inc index 65c0b86116..1544d98ed9 100644 --- a/programs/system/drivers/ati2d/vs_prog.inc +++ b/programs/system/drivers/ati2d/vs_prog.inc @@ -201,9 +201,6 @@ typedef struct u32_t sign :1; }src_t; -int parse_vs(); -int parse_mov(); -int parse_dcl(); int parse_vs(const u32_t *stream); diff --git a/programs/system/drivers/include/link.h b/programs/system/drivers/include/link.h new file mode 100644 index 0000000000..adf9c1de63 --- /dev/null +++ b/programs/system/drivers/include/link.h @@ -0,0 +1,60 @@ + +typedef struct link +{ + struct link *prev; + struct link *next; +}link_t; + +#define LIST_INITIALIZE(name) \ + link_t name = { .prev = &name, .next = &name } + +#define list_get_instance(link, type, member) \ + ((type *)(((u8_t *)(link)) - ((u8_t *)&(((type *)NULL)->member)))) + +static inline void link_initialize(link_t *link) +{ + link->prev = NULL; + link->next = NULL; +} + +static inline void list_initialize(link_t *head) +{ + head->prev = head; + head->next = head; +} + +static inline void list_append(link_t *link, link_t *head) +{ + link->prev = head->prev; + link->next = head; + head->prev->next = link; + head->prev = link; +} + +static inline void list_remove(link_t *link) +{ + link->next->prev = link->prev; + link->prev->next = link->next; + link_initialize(link); +} + +static inline Bool list_empty(link_t *head) +{ + return head->next == head ? TRUE : FALSE; +} + +static inline void list_prepend(link_t *link, link_t *head) +{ + link->next = head->next; + link->prev = head; + head->next->prev = link; + head->next = link; +} + +static inline list_insert(link_t *new, link_t *old) +{ + new->prev = old->prev; + new->next = old; + new->prev->next = new; + old->prev = new; +} diff --git a/programs/system/drivers/include/syscall.h b/programs/system/drivers/include/syscall.h new file mode 100644 index 0000000000..6981e45506 --- /dev/null +++ b/programs/system/drivers/include/syscall.h @@ -0,0 +1,299 @@ + +#define OS_BASE 0x80000000 + +typedef struct +{ + u32_t handle; + u32_t io_code; + void *input; + int inp_size; + void *output; + int out_size; +}ioctl_t; + +typedef int (__stdcall *srv_proc_t)(ioctl_t *); + +#define ERR_OK 0 +#define ERR_PARAM -1 + + +u32_t __stdcall drvEntry(int)__asm__("_drvEntry"); + +/////////////////////////////////////////////////////////////////////////////// + +#define STDCALL __attribute__ ((stdcall)) __attribute__ ((dllimport)) +#define IMPORT __attribute__ ((dllimport)) + +/////////////////////////////////////////////////////////////////////////////// + +#define SysMsgBoardStr __SysMsgBoardStr +#define PciApi __PciApi +//#define RegService __RegService +#define CreateObject __CreateObject +#define DestroyObject __DestroyObject + +/////////////////////////////////////////////////////////////////////////////// + +#define PG_SW 0x003 +#define PG_NOCACHE 0x018 + +void* STDCALL AllocKernelSpace(size_t size)__asm__("AllocKernelSpace"); +void* STDCALL KernelAlloc(size_t size)__asm__("KernelAlloc"); +void* STDCALL KernelFree(void *mem)__asm__("KernelFree"); +void* STDCALL UserAlloc(size_t size)__asm__("UserAlloc"); +int STDCALL UserFree(void *mem)__asm__("UserFree"); + +addr_t STDCALL AllocPages(count_t count)__asm__("AllocPages"); + +void* STDCALL CreateRingBuffer(size_t size, u32_t map)__asm__("CreateRingBuffer"); + +u32_t STDCALL RegService(char *name, srv_proc_t proc)__asm__("RegService"); + +//void *CreateObject(u32 pid, size_t size); +//void *DestroyObject(void *obj); + +addr_t STDCALL MapIoMem(void* base,size_t size,u32_t flags)__asm__("MapIoMem"); + +/////////////////////////////////////////////////////////////////////////////// + +void STDCALL SetMouseData(int btn, int x, int y, + int z, int h)__asm__("SetMouseData"); + +static u32_t PciApi(int cmd); + +u8_t STDCALL PciRead8 (u32_t bus, u32_t devfn, u32_t reg)__asm__("PciRead8"); +u16_t STDCALL PciRead16(u32_t bus, u32_t devfn, u32_t reg)__asm__("PciRead16"); +u32_t STDCALL PciRead32(u32_t bus, u32_t devfn, u32_t reg)__asm__("PciRead32"); + +u32_t STDCALL PciWrite8 (u32_t bus, u32_t devfn, u32_t reg,u8_t val) __asm__("PciWrite8"); +u32_t STDCALL PciWrite16(u32_t bus, u32_t devfn, u32_t reg,u16_t val)__asm__("PciWrite16"); +u32_t STDCALL PciWrite32(u32_t bus, u32_t devfn, u32_t reg,u32_t val)__asm__("PciWrite32"); + +#define pciReadByte(tag, reg) \ + PciRead8(PCI_BUS_FROM_TAG(tag),PCI_DFN_FROM_TAG(tag),(reg)) + +#define pciReadWord(tag, reg) \ + PciRead16(PCI_BUS_FROM_TAG(tag),PCI_DFN_FROM_TAG(tag),(reg)) + +#define pciReadLong(tag, reg) \ + PciRead32(PCI_BUS_FROM_TAG(tag),PCI_DFN_FROM_TAG(tag),(reg)) + +#define pciWriteByte(tag, reg, val) \ + PciWrite8(PCI_BUS_FROM_TAG(tag),PCI_DFN_FROM_TAG(tag),(reg),(val)) + +#define pciWriteWord(tag, reg, val) \ + PciWrite16(PCI_BUS_FROM_TAG(tag),PCI_DFN_FROM_TAG(tag),(reg),(val)) + +#define pciWriteLong(tag, reg, val) \ + PciWrite32(PCI_BUS_FROM_TAG(tag),PCI_DFN_FROM_TAG(tag),(reg),(val)) + + +/////////////////////////////////////////////////////////////////////////////// + +int dbg_open(char *path); +int dbgprintf(const char* format, ...); + +/////////////////////////////////////////////////////////////////////////////// + +extern inline int GetScreenSize() +{ + int retval; + + asm("int $0x40" + :"=a"(retval) + :"a"(61), "b"(1)); + return retval; +} + +extern inline int GetScreenBpp() +{ + int retval; + + asm("int $0x40" + :"=a"(retval) + :"a"(61), "b"(2)); + return retval; +} + +extern inline int GetScreenPitch() +{ + int retval; + + asm("int $0x40" + :"=a"(retval) + :"a"(61), "b"(3)); + return retval; +} + +extern inline u32_t GetPgAddr(void *mem) +{ + u32_t retval; + + __asm__ __volatile__ ( + "call *__imp__GetPgAddr \n\t" + :"=eax" (retval) + :"a" (mem) ); + return retval; +}; + +extern inline void CommitPages(void *mem, u32_t page, u32_t size) +{ + size = (size+4095) & ~4095; + __asm__ __volatile__ ( + "call *__imp__CommitPages" + ::"a" (page), "b"(mem),"c"(size>>12) + :"edx" ); + __asm__ __volatile__ ("":::"eax","ebx","ecx"); +}; + +extern inline void UnmapPages(void *mem, size_t size) +{ + size = (size+4095) & ~4095; + __asm__ __volatile__ ( + "call *__imp__UnmapPages" + ::"a" (mem), "c"(size>>12) + :"edx"); + __asm__ __volatile__ ("":::"eax","ecx"); +}; + +extern inline void usleep(u32_t delay) +{ + if( !delay ) + delay++; + delay*=1000; + + while(delay--) + __asm__ __volatile__ ( + "xorl %%eax, %%eax \n\t" + "cpuid \n\t" + :::"eax","ebx","ecx","edx"); +}; + +extern inline u32_t __PciApi(int cmd) +{ + u32_t retval; + + __asm__ __volatile__ ( + "call *__imp__PciApi" + :"=a" (retval) + :"a" (cmd) + :"memory"); + return retval; +}; + +extern inline void* __CreateObject(u32_t pid, size_t size) +{ + void *retval; + + __asm__ __volatile__ ( + "call *__imp__CreateObject \n\t" + :"=a" (retval) + :"a" (size),"b"(pid) + :"esi","edi", "memory"); + return retval; +} + +extern inline void *__DestroyObject(void *obj) +{ + __asm__ __volatile__ ( + "call *__imp__DestroyObject" + : + :"a" (obj) + :"ebx","edx","esi","edi", "memory"); +} + + +/* +u32 __RegService(char *name, srv_proc_t proc) +{ + u32 retval; + + asm __volatile__ + ( + "pushl %%eax \n\t" + "pushl %%ebx \n\t" + "call *__imp__RegService \n\t" + :"=eax" (retval) + :"a" (proc), "b" (name) + :"memory" + ); + return retval; +}; +*/ + +extern inline u32_t safe_cli(void) +{ + u32_t ifl; + __asm__ __volatile__ ( + "pushf\n\t" + "popl %0\n\t" + "cli\n" + : "=r" (ifl)); + return ifl; +} + +extern inline void safe_sti(u32_t ifl) +{ + __asm__ __volatile__ ( + "pushl %0\n\t" + "popf\n" + : : "r" (ifl) + ); +} + +extern inline void __clear (void * dst, unsigned len) +{ + u32_t tmp; + __asm__ __volatile__ ( +// "xorl %%eax, %%eax \n\t" + "cld \n\t" + "rep stosb \n" + :"=c"(tmp),"=D"(tmp) + :"a"(0),"c"(len),"D"(dst)); + __asm__ __volatile__ ("":::"ecx","edi"); +}; + +extern inline void out8(const u16_t port, const u8_t val) +{ + __asm__ __volatile__ + ("outb %1, %0\n" : : "dN"(port), "a"(val)); +} + +extern inline void out16(const u16_t port, const u16_t val) +{ + __asm__ __volatile__ + ("outw %1, %0\n" : : "dN"(port), "a"(val)); +} + +extern inline void out32(const u16_t port, const u32_t val) +{ + __asm__ __volatile__ + ("outl %1, %0\n" : : "dN"(port), "a"(val)); +} + +extern inline u16_t in16(const u16_t port) +{ + u16_t tmp; + __asm__ __volatile__ + ("inw %1, %0\n" : "=a"(tmp) : "dN"(port)); + return tmp; +}; + +extern inline u32_t in32(const u16_t port) +{ + u32_t tmp; + __asm__ __volatile__ + ("inl %1, %0\n" : "=a"(tmp) : "dN"(port)); + return tmp; +}; + +extern inline void delay(int time) +{ + __asm__ __volatile__ ( + "call *__imp__Delay" + ::"b" (time)); + __asm__ __volatile__ ( + "":::"ebx"); + +} + diff --git a/programs/system/drivers/include/types.h b/programs/system/drivers/include/types.h new file mode 100644 index 0000000000..351b9553e4 --- /dev/null +++ b/programs/system/drivers/include/types.h @@ -0,0 +1,24 @@ + +#define NULL (void*)0 + + +typedef unsigned char u8_t; +typedef unsigned short int u16_t; +typedef unsigned int u32_t; +typedef unsigned long long u64_t; + +typedef signed char i8_t; +typedef signed short int i16_t; + +typedef unsigned int addr_t; + +typedef unsigned int size_t; +typedef unsigned int count_t; +typedef unsigned int eflags_t; + +typedef unsigned int Bool; + +#define TRUE (Bool)1 +#define FALSE (Bool)0 + + diff --git a/programs/system/drivers/usb/ch9.h b/programs/system/drivers/usb/ch9.h new file mode 100644 index 0000000000..1122a6c2c1 --- /dev/null +++ b/programs/system/drivers/usb/ch9.h @@ -0,0 +1,577 @@ +/* + * This file holds USB constants and structures that are needed for + * USB device APIs. These are used by the USB device model, which is + * defined in chapter 9 of the USB 2.0 specification and in the + * Wireless USB 1.0 (spread around). Linux has several APIs in C that + * need these: + * + * - the master/host side Linux-USB kernel driver API; + * - the "usbfs" user space API; and + * - the Linux "gadget" slave/device/peripheral side driver API. + * + * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems + * act either as a USB master/host or as a USB slave/device. That means + * the master and slave side APIs benefit from working well together. + * + * There's also "Wireless USB", using low power short range radios for + * peripheral interconnection but otherwise building on the USB framework. + * + * Note all descriptors are declared '__attribute__((packed))' so that: + * + * [a] they never get padded, either internally (USB spec writers + * probably handled that) or externally; + * + * [b] so that accessing bigger-than-a-bytes fields will never + * generate bus errors on any platform, even when the location of + * its descriptor inside a bundle isn't "naturally aligned", and + * + * [c] for consistency, removing all doubt even when it appears to + * someone that the two other points are non-issues for that + * particular descriptor type. + */ + +#ifndef __LINUX_USB_CH9_H +#define __LINUX_USB_CH9_H + +#include /* __u8 etc */ + +/*-------------------------------------------------------------------------*/ + +/* CONTROL REQUEST SUPPORT */ + +/* + * USB directions + * + * This bit flag is used in endpoint descriptors' bEndpointAddress field. + * It's also one of three fields in control requests bRequestType. + */ +#define USB_DIR_OUT 0 /* to device */ +#define USB_DIR_IN 0x80 /* to host */ + +/* + * USB types, the second of three bRequestType fields + */ +#define USB_TYPE_MASK (0x03 << 5) +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) + +/* + * USB recipients, the third of three bRequestType fields + */ +#define USB_RECIP_MASK 0x1f +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 +/* From Wireless USB 1.0 */ +#define USB_RECIP_PORT 0x04 +#define USB_RECIP_RPIPE 0x05 + +/* + * Standard requests, for the bRequest field of a SETUP packet. + * + * These are qualified by the bRequestType field, so that for example + * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved + * by a GET_STATUS request. + */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + +#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */ +#define USB_REQ_GET_ENCRYPTION 0x0E +#define USB_REQ_RPIPE_ABORT 0x0E +#define USB_REQ_SET_HANDSHAKE 0x0F +#define USB_REQ_RPIPE_RESET 0x0F +#define USB_REQ_GET_HANDSHAKE 0x10 +#define USB_REQ_SET_CONNECTION 0x11 +#define USB_REQ_SET_SECURITY_DATA 0x12 +#define USB_REQ_GET_SECURITY_DATA 0x13 +#define USB_REQ_SET_WUSB_DATA 0x14 +#define USB_REQ_LOOPBACK_DATA_WRITE 0x15 +#define USB_REQ_LOOPBACK_DATA_READ 0x16 +#define USB_REQ_SET_INTERFACE_DS 0x17 + +/* + * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and + * are read as a bit array returned by USB_REQ_GET_STATUS. (So there + * are at most sixteen features of each type.) + */ +#define USB_DEVICE_SELF_POWERED 0 /* (read only) */ +#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ +#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ +#define USB_DEVICE_BATTERY 2 /* (wireless) */ +#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ +#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/ +#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ +#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ +#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ + +#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ + + +/** + * struct usb_ctrlrequest - SETUP data for a USB device control request + * @bRequestType: matches the USB bmRequestType field + * @bRequest: matches the USB bRequest field + * @wValue: matches the USB wValue field (le16 byte order) + * @wIndex: matches the USB wIndex field (le16 byte order) + * @wLength: matches the USB wLength field (le16 byte order) + * + * This structure is used to send control requests to a USB device. It matches + * the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the + * USB spec for a fuller description of the different fields, and what they are + * used for. + * + * Note that the driver for any interface can issue control requests. + * For most devices, interfaces don't coordinate with each other, so + * such requests may be made at any time. + */ +struct usb_ctrlrequest { + __u8 bRequestType; + __u8 bRequest; + __le16 wValue; + __le16 wIndex; + __le16 wLength; +} __attribute__ ((packed)); + +/*-------------------------------------------------------------------------*/ + +/* + * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or + * (rarely) accepted by SET_DESCRIPTOR. + * + * Note that all multi-byte values here are encoded in little endian + * byte order "on the wire". But when exposed through Linux-USB APIs, + * they've been converted to cpu byte order. + */ + +/* + * Descriptor types ... USB 2.0 spec table 9.5 + */ +#define USB_DT_DEVICE 0x01 +#define USB_DT_CONFIG 0x02 +#define USB_DT_STRING 0x03 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 +#define USB_DT_DEVICE_QUALIFIER 0x06 +#define USB_DT_OTHER_SPEED_CONFIG 0x07 +#define USB_DT_INTERFACE_POWER 0x08 +/* these are from a minor usb 2.0 revision (ECN) */ +#define USB_DT_OTG 0x09 +#define USB_DT_DEBUG 0x0a +#define USB_DT_INTERFACE_ASSOCIATION 0x0b +/* these are from the Wireless USB spec */ +#define USB_DT_SECURITY 0x0c +#define USB_DT_KEY 0x0d +#define USB_DT_ENCRYPTION_TYPE 0x0e +#define USB_DT_BOS 0x0f +#define USB_DT_DEVICE_CAPABILITY 0x10 +#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11 +#define USB_DT_WIRE_ADAPTER 0x21 +#define USB_DT_RPIPE 0x22 + +/* conventional codes for class-specific descriptors */ +#define USB_DT_CS_DEVICE 0x21 +#define USB_DT_CS_CONFIG 0x22 +#define USB_DT_CS_STRING 0x23 +#define USB_DT_CS_INTERFACE 0x24 +#define USB_DT_CS_ENDPOINT 0x25 + +/* All standard descriptors have these 2 fields at the beginning */ +struct usb_descriptor_header { + __u8 bLength; + __u8 bDescriptorType; +} __attribute__ ((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE: Device descriptor */ +struct usb_device_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __le16 bcdUSB; + __u8 bDeviceClass; + __u8 bDeviceSubClass; + __u8 bDeviceProtocol; + __u8 bMaxPacketSize0; + __le16 idVendor; + __le16 idProduct; + __le16 bcdDevice; + __u8 iManufacturer; + __u8 iProduct; + __u8 iSerialNumber; + __u8 bNumConfigurations; +} __attribute__ ((packed)); + +#define USB_DT_DEVICE_SIZE 18 + + +/* + * Device and/or Interface Class codes + * as found in bDeviceClass or bInterfaceClass + * and defined by www.usb.org documents + */ +#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_COMM 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_PHYSICAL 5 +#define USB_CLASS_STILL_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_CDC_DATA 0x0a +#define USB_CLASS_CSCID 0x0b /* chip+ smart card */ +#define USB_CLASS_CONTENT_SEC 0x0d /* content security */ +#define USB_CLASS_VIDEO 0x0e +#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 +#define USB_CLASS_MISC 0xef +#define USB_CLASS_APP_SPEC 0xfe +#define USB_CLASS_VENDOR_SPEC 0xff + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_CONFIG: Configuration descriptor information. + * + * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the + * descriptor type is different. Highspeed-capable devices can look + * different depending on what speed they're currently running. Only + * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG + * descriptors. + */ +struct usb_config_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __le16 wTotalLength; + __u8 bNumInterfaces; + __u8 bConfigurationValue; + __u8 iConfiguration; + __u8 bmAttributes; + __u8 bMaxPower; +} __attribute__ ((packed)); + +#define USB_DT_CONFIG_SIZE 9 + +/* from config descriptor bmAttributes */ +#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ +#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ +#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ +#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_STRING: String descriptor */ +struct usb_string_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __le16 wData[1]; /* UTF-16LE encoded */ +} __attribute__ ((packed)); + +/* note that "string" zero is special, it holds language codes that + * the device supports, not Unicode characters. + */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_INTERFACE: Interface descriptor */ +struct usb_interface_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bInterfaceNumber; + __u8 bAlternateSetting; + __u8 bNumEndpoints; + __u8 bInterfaceClass; + __u8 bInterfaceSubClass; + __u8 bInterfaceProtocol; + __u8 iInterface; +} __attribute__ ((packed)); + +#define USB_DT_INTERFACE_SIZE 9 + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_ENDPOINT: Endpoint descriptor */ +struct usb_endpoint_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bEndpointAddress; + __u8 bmAttributes; + __le16 wMaxPacketSize; + __u8 bInterval; + + /* NOTE: these two are _only_ in audio endpoints. */ + /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */ + __u8 bRefresh; + __u8 bSynchAddress; +} __attribute__ ((packed)); + +#define USB_DT_ENDPOINT_SIZE 7 +#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ + + +/* + * Endpoints + */ +#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ +#define USB_ENDPOINT_DIR_MASK 0x80 + +#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ +#define USB_ENDPOINT_XFER_CONTROL 0 +#define USB_ENDPOINT_XFER_ISOC 1 +#define USB_ENDPOINT_XFER_BULK 2 +#define USB_ENDPOINT_XFER_INT 3 +#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ +struct usb_qualifier_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __le16 bcdUSB; + __u8 bDeviceClass; + __u8 bDeviceSubClass; + __u8 bDeviceProtocol; + __u8 bMaxPacketSize0; + __u8 bNumConfigurations; + __u8 bRESERVED; +} __attribute__ ((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_OTG (from OTG 1.0a supplement) */ +struct usb_otg_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bmAttributes; /* support for HNP, SRP, etc */ +} __attribute__ ((packed)); + +/* from usb_otg_descriptor.bmAttributes */ +#define USB_OTG_SRP (1 << 0) +#define USB_OTG_HNP (1 << 1) /* swap host/device roles */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */ +struct usb_debug_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + /* bulk endpoints with 8 byte maxpacket */ + __u8 bDebugInEndpoint; + __u8 bDebugOutEndpoint; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */ +struct usb_interface_assoc_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bFirstInterface; + __u8 bInterfaceCount; + __u8 bFunctionClass; + __u8 bFunctionSubClass; + __u8 bFunctionProtocol; + __u8 iFunction; +} __attribute__ ((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_SECURITY: group of wireless security descriptors, including + * encryption types available for setting up a CC/association. + */ +struct usb_security_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __le16 wTotalLength; + __u8 bNumEncryptionTypes; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_KEY: used with {GET,SET}_SECURITY_DATA; only public keys + * may be retrieved. + */ +struct usb_key_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 tTKID[3]; + __u8 bReserved; + __u8 bKeyData[0]; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_ENCRYPTION_TYPE: bundled in DT_SECURITY groups */ +struct usb_encryption_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bEncryptionType; +#define USB_ENC_TYPE_UNSECURE 0 +#define USB_ENC_TYPE_WIRED 1 /* non-wireless mode */ +#define USB_ENC_TYPE_CCM_1 2 /* aes128/cbc session */ +#define USB_ENC_TYPE_RSA_1 3 /* rsa3072/sha1 auth */ + __u8 bEncryptionValue; /* use in SET_ENCRYPTION */ + __u8 bAuthKeyIndex; +} __attribute__((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_BOS: group of wireless capabilities */ +struct usb_bos_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __le16 wTotalLength; + __u8 bNumDeviceCaps; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE_CAPABILITY: grouped with BOS */ +struct usb_dev_cap_header { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; +} __attribute__((packed)); + +#define USB_CAP_TYPE_WIRELESS_USB 1 + +struct usb_wireless_cap_descriptor { /* Ultra Wide Band */ + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; + + __u8 bmAttributes; +#define USB_WIRELESS_P2P_DRD (1 << 1) +#define USB_WIRELESS_BEACON_MASK (3 << 2) +#define USB_WIRELESS_BEACON_SELF (1 << 2) +#define USB_WIRELESS_BEACON_DIRECTED (2 << 2) +#define USB_WIRELESS_BEACON_NONE (3 << 2) + __le16 wPHYRates; /* bit rates, Mbps */ +#define USB_WIRELESS_PHY_53 (1 << 0) /* always set */ +#define USB_WIRELESS_PHY_80 (1 << 1) +#define USB_WIRELESS_PHY_107 (1 << 2) /* always set */ +#define USB_WIRELESS_PHY_160 (1 << 3) +#define USB_WIRELESS_PHY_200 (1 << 4) /* always set */ +#define USB_WIRELESS_PHY_320 (1 << 5) +#define USB_WIRELESS_PHY_400 (1 << 6) +#define USB_WIRELESS_PHY_480 (1 << 7) + __u8 bmTFITXPowerInfo; /* TFI power levels */ + __u8 bmFFITXPowerInfo; /* FFI power levels */ + __le16 bmBandGroup; + __u8 bReserved; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with + * each endpoint descriptor for a wireless device + */ +struct usb_wireless_ep_comp_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bMaxBurst; + __u8 bMaxSequence; + __le16 wMaxStreamDelay; + __le16 wOverTheAirPacketSize; + __u8 bOverTheAirInterval; + __u8 bmCompAttributes; +#define USB_ENDPOINT_SWITCH_MASK 0x03 /* in bmCompAttributes */ +#define USB_ENDPOINT_SWITCH_NO 0 +#define USB_ENDPOINT_SWITCH_SWITCH 1 +#define USB_ENDPOINT_SWITCH_SCALE 2 +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless + * host and a device for connection set up, mutual authentication, and + * exchanging short lived session keys. The handshake depends on a CC. + */ +struct usb_handshake { + __u8 bMessageNumber; + __u8 bStatus; + __u8 tTKID[3]; + __u8 bReserved; + __u8 CDID[16]; + __u8 nonce[16]; + __u8 MIC[8]; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC). + * A CC may also be set up using non-wireless secure channels (including + * wired USB!), and some devices may support CCs with multiple hosts. + */ +struct usb_connection_context { + __u8 CHID[16]; /* persistent host id */ + __u8 CDID[16]; /* device id (unique w/in host context) */ + __u8 CK[16]; /* connection key */ +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB 2.0 defines three speeds, here's how Linux identifies them */ + +enum usb_device_speed { + USB_SPEED_UNKNOWN = 0, /* enumerating */ + USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ + USB_SPEED_HIGH, /* usb 2.0 */ + USB_SPEED_VARIABLE, /* wireless (usb 2.5) */ +}; + +enum usb_device_state { + /* NOTATTACHED isn't in the USB spec, and this state acts + * the same as ATTACHED ... but it's clearer this way. + */ + USB_STATE_NOTATTACHED = 0, + + /* chapter 9 and authentication (wireless) device states */ + USB_STATE_ATTACHED, + USB_STATE_POWERED, /* wired */ + USB_STATE_UNAUTHENTICATED, /* auth */ + USB_STATE_RECONNECTING, /* auth */ + USB_STATE_DEFAULT, /* limited function */ + USB_STATE_ADDRESS, + USB_STATE_CONFIGURED, /* most functions */ + + USB_STATE_SUSPENDED + + /* NOTE: there are actually four different SUSPENDED + * states, returning to POWERED, DEFAULT, ADDRESS, or + * CONFIGURED respectively when SOF tokens flow again. + */ +}; + +#endif /* __LINUX_USB_CH9_H */ diff --git a/programs/system/drivers/usb/detect.inc b/programs/system/drivers/usb/detect.inc new file mode 100644 index 0000000000..fcdb6c3cd0 --- /dev/null +++ b/programs/system/drivers/usb/detect.inc @@ -0,0 +1,63 @@ + + +Bool FindPciDevice() +{ + Bool retval = FALSE; + u32_t bus, last_bus; + PCITAG tag; + + if( (last_bus = PciApi(1))==-1) + return retval; + + for(bus=0;bus<=last_bus;bus++) + { + u32_t devfn; + + for(devfn=0;devfn<256;devfn++) + { + hc_t *hc; + + u32_t id; + u16_t pcicmd; + u16_t devclass; + int i; + + devclass = PciRead16(bus,devfn, 0x0A); + + if( devclass != 0x0C03) + continue; + + pcicmd = PciRead16(bus,devfn, PCI_COMMAND); + if (! pcicmd & PCI_COMMAND_IO) + continue; + + hc = (hc_t*)malloc(sizeof(hc_t)); + memset(hc, 0, sizeof(hc_t)); + link_initialize(&hc->link); + + hc->pciId = PciRead32(bus,devfn, 0); + hc->PciTag = pciTag(bus,(devfn>>3)&0x1F,devfn&0x7); + + for (i = 0; i < 6; i++) + { + u32_t base; + Bool validSize; + + base = PciRead32(bus,devfn, PCI_MAP_REG_START + (i << 2)); + if(base) + { + if (base & PCI_MAP_IO) { + hc->ioBase[i] = (addr_t)PCIGETIO(base); + hc->memType[i] = base & PCI_MAP_IO_ATTR_MASK; + } else { + hc->memBase[i] = (u32_t)PCIGETMEMORY(base); + hc->memType[i] = base & PCI_MAP_MEMORY_ATTR_MASK; + } + } + }; + list_prepend(&hc->link, &hc_list); + retval = TRUE; + }; + }; + return retval; +}; diff --git a/programs/system/drivers/usb/hcd.inc b/programs/system/drivers/usb/hcd.inc new file mode 100644 index 0000000000..1ab8248f18 --- /dev/null +++ b/programs/system/drivers/usb/hcd.inc @@ -0,0 +1,604 @@ + +#define UHCI_USBLEGSUP 0x00c0 /* legacy support */ +#define UHCI_USBCMD 0 /* command register */ +#define UHCI_USBINTR 4 /* interrupt register */ +#define UHCI_USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ +#define UHCI_USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ +#define UHCI_USBCMD_RUN 0x0001 /* RUN/STOP bit */ +#define UHCI_USBCMD_HCRESET 0x0002 /* Host Controller reset */ +#define UHCI_USBCMD_EGSM 0x0008 /* Global Suspend Mode */ +#define UHCI_USBCMD_CONFIGURE 0x0040 /* Config Flag */ +#define UHCI_USBINTR_RESUME 0x0002 /* Resume interrupt enable */ + + +#define USBCMD 0 +#define USBCMD_RS 0x0001 /* Run/Stop */ +#define USBCMD_HCRESET 0x0002 /* Host reset */ +#define USBCMD_GRESET 0x0004 /* Global reset */ +#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ +#define USBCMD_FGR 0x0010 /* Force Global Resume */ +#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ +#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ +#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ + +#define USBSTS 2 +#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ +#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ +#define USBSTS_RD 0x0004 /* Resume Detect */ +#define USBSTS_HSE 0x0008 /* Host System Error: PCI problems */ +#define USBSTS_HCPE 0x0010 /* Host Controller Process Error: + * the schedule is buggy */ +#define USBSTS_HCH 0x0020 /* HC Halted */ + + +#define USBFRNUM 6 +#define USBFLBASEADD 8 +#define USBSOF 12 +#define USBSOF_DEFAULT 64 /* Frame length is exactly 1 ms */ + +#define USBPORTSC1 16 +#define USBPORTSC2 18 + +#define UHCI_RH_MAXCHILD 7 + + +/* + * Make sure the controller is completely inactive, unable to + * generate interrupts or do DMA. + */ +void uhci_reset_hc(hc_t *hc) +{ + /* Turn off PIRQ enable and SMI enable. (This also turns off the + * BIOS's USB Legacy Support.) Turn off all the R/WC bits too. + */ + pciWriteWord(hc->PciTag, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC); + + /* Reset the HC - this will force us to get a + * new notification of any already connected + * ports due to the virtual disconnect that it + * implies. + */ + out16(hc->iobase + UHCI_USBCMD, UHCI_USBCMD_HCRESET); + __asm__ __volatile__ ("":::"memory"); + + delay(20/10); + + if (in16(hc->iobase + UHCI_USBCMD) & UHCI_USBCMD_HCRESET) + dbgprintf("HCRESET not completed yet!\n"); + + /* Just to be safe, disable interrupt requests and + * make sure the controller is stopped. + */ + out16(hc->iobase + UHCI_USBINTR, 0); + out16(hc->iobase + UHCI_USBCMD, 0); +}; + +int uhci_check_and_reset_hc(hc_t *hc) +{ + u16_t legsup; + unsigned int cmd, intr; + + /* + * When restarting a suspended controller, we expect all the + * settings to be the same as we left them: + * + * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP; + * Controller is stopped and configured with EGSM set; + * No interrupts enabled except possibly Resume Detect. + * + * If any of these conditions are violated we do a complete reset. + */ + legsup = pciReadWord(hc->PciTag, UHCI_USBLEGSUP); + if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) { + dbgprintf("%s: legsup = 0x%04x\n",__FUNCTION__, legsup); + goto reset_needed; + } + + cmd = in16(hc->iobase + UHCI_USBCMD); + if ( (cmd & UHCI_USBCMD_RUN) || + !(cmd & UHCI_USBCMD_CONFIGURE) || + !(cmd & UHCI_USBCMD_EGSM)) + { + dbgprintf("%s: cmd = 0x%04x\n", __FUNCTION__, cmd); + goto reset_needed; + } + + intr = in16(hc->iobase + UHCI_USBINTR); + if (intr & (~UHCI_USBINTR_RESUME)) + { + dbgprintf("%s: intr = 0x%04x\n", __FUNCTION__, intr); + goto reset_needed; + } + return 0; + +reset_needed: + dbgprintf("Performing full reset\n"); + uhci_reset_hc(hc); + return 1; +} + + +Bool init_hc(hc_t *hc) +{ + int port; + u32_t ifl; + u16_t dev_status; + int i; + + dbgprintf("\n\ninit uhci %x\n\n", hc->pciId); + + for(i=0;i<6;i++) + { + if(hc->ioBase[i]){ + hc->iobase = hc->ioBase[i]; + // dbgprintf("Io base_%d 0x%x\n", i,hc->ioBase[i]); + break; + }; + }; + + /* The UHCI spec says devices must have 2 ports, and goes on to say + * they may have more but gives no way to determine how many there + * are. However according to the UHCI spec, Bit 7 of the port + * status and control register is always set to 1. So we try to + * use this to our advantage. Another common failure mode when + * a nonexistent register is addressed is to return all ones, so + * we test for that also. + */ + for (port = 0; port < 2; port++) + { + u32_t status; + + status = in16(hc->iobase + USBPORTSC1 + (port * 2)); + dbgprintf("port%d status %x\n", port, status); + if (!(status & 0x0080) || status == 0xffff) + break; + } + dbgprintf("detected %d ports\n\n", port); + + hc->numports = port; + + /* Kick BIOS off this hardware and reset if the controller + * isn't already safely quiescent. + */ + uhci_check_and_reset_hc(hc); + + hc->frame_base = (u32_t*)KernelAlloc(4096); + hc->frame_dma = GetPgAddr(hc->frame_base); + hc->frame_number = 0; + + qh_t *qh = alloc_qh(); + + qh->qlink = 1; + qh->qelem = 1; + + hc->qh1 = qh; + + // dbgprintf("alloc qh %x dma %x\n", qh, qh->dma); + + for(i=0; i<1024; i++) + hc->frame_base[i] = qh->dma | 2; + + + /* Set the frame length to the default: 1 ms exactly */ + out8(hc->iobase + USBSOF, USBSOF_DEFAULT); + + /* Store the frame list base address */ + out32(hc->iobase + USBFLBASEADD, hc->frame_dma); + + /* Set the current frame number */ + out16(hc->iobase + USBFRNUM, 0); + + out16(hc->iobase + USBSTS, 0x3F); + out16(hc->iobase + USBCMD, USBCMD_RS | USBCMD_CF | + USBCMD_MAXP); + + for (port = 0; port < hc->numports; ++port) + out16(hc->iobase + USBPORTSC1 + (port * 2), 0x200); + delay(100/10); + + for (port = 0; port < 2; ++port) + { + time_t timeout; + + u32_t status = in16(hc->iobase + USBPORTSC1 + (port * 2)); + dbgprintf("port%d status %x\n", port, status); + + out16(hc->iobase + USBPORTSC1 + (port * 2), 0); + + timeout = 100/10; + while(timeout--) + { + delay(10/10); + status = in16(hc->iobase + USBPORTSC1 + (port * 2)); + if(status & 1) + { + udev_t *dev = malloc(sizeof(udev_t)); + + out16(hc->iobase + USBPORTSC1 + (port * 2), 0x0E); + + delay(20/10); + + dbgprintf("enable port\n"); + status = in16(hc->iobase + USBPORTSC1 + (port * 2)); + dbgprintf("port%d status %x\n", port, status); + + link_initialize(&dev->link); + dev->id = 0; + dev->host = hc; + dev->addr = 0; + dev->port = port; + dev->ep0_size = 8; + dev->status = status; + + dbgprintf("port%d connected", port); + if(status & 4) + dbgprintf(" enabled"); + else + dbgprintf(" disabled"); + if(status & 0x100){ + dev->speed = 0x4000000; + dbgprintf(" low speed\n"); + } else { + dev->speed = 0; + dbgprintf(" full speed\n"); + }; + + if(set_address(dev)) { + list_prepend(&dev->link, &newdev_list); + hc->port_map |= 1<iobase + USBPORTSC1 + (port * 2), 0); + } + break; + }; + }; + }; + return TRUE; +}; + +u16_t __attribute__((aligned(16))) + req_descr[4] = {0x0680,0x0100,0x0000,8}; + +/* +IN(69) OUT(E1) SETUP(2D) +SETUP(0) IN(1) +SETUP(0) OUT(1) OUT(0) OUT(1)...IN(1) +SETUP(0) IN(1) IN(0) IN(1)...OUT(0) +*/ + + +Bool set_address(udev_t *dev) +{ + static udev_id = 0; + static udev_addr = 0; + static u16_t __attribute__((aligned(16))) + req_addr[4] = {0x0500,0x0001,0x0000,0x0000}; + + static u16_t __attribute__((aligned(16))) + req_descr[4] = {0x0680,0x0100,0x0000,8}; + + static u32_t data[2] __attribute__((aligned(16))); + + qh_t *qh; + td_t *td0, *td1, *td2; + u32_t dev_status; + count_t timeout; + int address; + + address = ++udev_addr; + + req_addr[1] = address; + + if( !ctrl_request(dev, &req_addr, DOUT, NULL, 0)) + return FALSE; + + dev->addr = address; + dev->id = (++udev_id << 8) | address; + + dbgprintf("set address %d\n", address); + + data[0] = 0; + data[1] = 0; + + if( !ctrl_request(dev, &req_descr, DIN, data, 8)) + return FALSE; + + dev_descr_t *descr = (dev_descr_t*)&data; + dev->ep0_size = descr->bMaxPacketSize0; + + return TRUE; +} + +request_t *create_request(udev_t *dev, endp_t *enp, u32_t dir, + void *data, size_t req_size) +{ + td_t *td, *td_prev; + addr_t data_dma; + + request_t *rq = (request_t*)malloc(sizeof(request_t)); + + link_initialize(&rq->link); + + rq->td_head = 0; + rq->td_tail = 0; + + rq->data = (addr_t)data; + rq->size = req_size; + rq->dev = dev; + + if(data) + data_dma = DMA(data); + + td_prev = NULL; + + while(req_size >= enp->size) + { + td = alloc_td(); + td->link = 1; + + if(rq->td_head == NULL) + rq->td_head = td; + + if( td_prev ) + td_prev->link = td->dma | 4; + td->status = 0x00800000 | dev->speed; + td->token = TOKEN(enp->size,enp->toggle,enp->address, + dev->addr,dir); + td->buffer = data_dma; + td->bk = td_prev; + + td_prev = td; + + data_dma+= enp->size; + req_size-= enp->size; + enp->toggle ^= DATA1; + } + if(req_size) + { + td = alloc_td(); + td->link = 1; + + if(rq->td_head == NULL) + rq->td_head = td; + + if( td_prev ) + td_prev->link = td->dma | 4; + + td->status = 0x00800000 | dev->speed; + td->token = TOKEN( req_size, enp->toggle, enp->address, + dev->addr, dir); + td->buffer = data_dma; + td->bk = td_prev; + + enp->toggle ^= DATA1; + } + rq->td_tail = td; +/* + dbgprintf("create request %x\n" + "head %x\n" + "tail %x\n" + "data %x\n" + "size %x\n", + rq, rq->td_head, rq->td_tail, + rq->data, rq->size); +*/ + return rq; +} + +Bool ctrl_request(udev_t *dev, void *req, u32_t pid, + void *data, size_t req_size) +{ + size_t packet_size = dev->ep0_size; + size_t size = req_size; + u32_t toggle = DATA1; + + td_t *td0, *td, *td_prev; + qh_t *qh; + addr_t data_dma = 0; + Bool retval; + + td0 = alloc_td(); + + td0->status = 0x00800000 | dev->speed; + td0->token = TOKEN( 8, DATA0, 0, dev->addr, 0x2D); + td0->buffer = DMA(req); + td0->bk = NULL; + + if(data) + data_dma = DMA(data); + + td_prev = td0; + + while(size >= packet_size) + { + td = alloc_td(); + td_prev->link = td->dma | 4; + td->status = 0x00800000 | dev->speed; + td->token = TOKEN(packet_size, toggle, 0,dev->addr, pid); + td->buffer = data_dma; + td->bk = td_prev; + + td_prev = td; + + data_dma+= packet_size; + size-= packet_size; + toggle ^= DATA1; + } + if(size) + { + td = alloc_td(); + td_prev->link = td->dma | 4; + td->status = 0x00800000 | dev->speed; + td->token = ((size-1)<<21)|toggle|(dev->addr<<8)|pid; + td->buffer = data_dma; + td->bk = td_prev; + + td_prev = td; + + data_dma+= packet_size; + size-= packet_size; + toggle ^= DATA1; + } + + td = alloc_td(); + td_prev->link = td->dma | 4; + + pid = (pid == DIN) ? DOUT : DIN; + + td->link = 1; + td->status = 0x00800000 | dev->speed; + td->token = (0x7FF<<21)|DATA1|(dev->addr<<8)|pid; + td->buffer = 0; + td->bk = td_prev; + + qh = dev->host->qh1; + + qh->qelem = td0->dma; + __asm__ __volatile__ ("":::"memory"); + + count_t timeout = 25; + while(timeout--){ + delay(10/10); + if( !(td->status & TD_CTRL_ACTIVE)) + break; + } + + if( (td0->status & TD_ANY_ERROR) || + (td_prev->status & TD_ANY_ERROR) || + (td->status & TD_ANY_ERROR)) + { + u32_t dev_status = in16(dev->host->iobase + USBSTS); + + dbgprintf("\nframe %x, cmd %x status %x\n", + in16(dev->host->iobase + USBFRNUM), + in16(dev->host->iobase + USBCMD), + dev_status); + dbgprintf("td0 status %x\n",td0->status); + dbgprintf("td_prev status %x\n",td_prev->status); + dbgprintf("td status %x\n",td->status); + dbgprintf("qh %x \n", qh->qelem); + + retval = FALSE; + } else retval = TRUE; + + do + { + td_prev = td->bk; + free_td(td); + td = td_prev; + }while( td != NULL); + + return retval; +}; + + +Bool init_device(udev_t *dev) +{ + static u16_t __attribute__((aligned(16))) + req_descr[4] = {0x0680,0x0100,0x0000,18}; + + static u16_t __attribute__((aligned(16))) + req_conf[4] = {0x0680,0x0200,0x0000,9}; + + static dev_descr_t __attribute__((aligned(16))) descr; + + interface_descr_t *interface; + + u32_t data[8]; + + u8_t *dptr; + conf_descr_t *conf; + + dbgprintf("\ninit device %x, host %x, port %d\n\n", + dev->id, dev->host->pciId, dev->port); + + if( !ctrl_request(dev, req_descr, DIN, &descr, 18)) + return; + + dev->dev_descr = descr; + + dbgprintf("device descriptor:\n\n" + "bLength %d\n" + "bDescriptorType %d\n" + "bcdUSB %x\n" + "bDeviceClass %x\n" + "bDeviceSubClass %x\n" + "bDeviceProtocol %x\n" + "bMaxPacketSize0 %d\n" + "idVendor %x\n" + "idProduct %x\n" + "bcdDevice %x\n" + "iManufacturer %x\n" + "iProduct %x\n" + "iSerialNumber %x\n" + "bNumConfigurations %d\n\n", + descr.bLength, descr.bDescriptorType, + descr.bcdUSB, descr.bDeviceClass, + descr.bDeviceSubClass, descr.bDeviceProtocol, + descr.bMaxPacketSize0, descr.idVendor, + descr.idProduct, descr.bcdDevice, + descr.iManufacturer, descr.iProduct, + descr.iSerialNumber, descr.bNumConfigurations); + + req_conf[3] = 8; + if( !ctrl_request(dev, req_conf, DIN, &data, 8)) + return; + + conf = (conf_descr_t*)&data; + + size_t conf_size = conf->wTotalLength; + + req_conf[3] = conf_size; + conf = malloc(conf_size); + + if( !ctrl_request(dev, req_conf, DIN, conf, conf_size)) + return; + + dptr = (u8_t*)conf; + dptr+= conf->bLength; + + dbgprintf("configuration descriptor\n\n" + "bLength %d\n" + "bDescriptorType %d\n" + "wTotalLength %d\n" + "bNumInterfaces %d\n" + "bConfigurationValue %x\n" + "iConfiguration %d\n" + "bmAttributes %x\n" + "bMaxPower %dmA\n\n", + conf->bLength, + conf->bDescriptorType, + conf->wTotalLength, + conf->bNumInterfaces, + conf->bConfigurationValue, + conf->iConfiguration, + conf->bmAttributes, + conf->bMaxPower*2); + + interface = (interface_descr_t*)dptr; + + switch(interface->bInterfaceClass) + { + case USB_CLASS_AUDIO: + dbgprintf( "audio device\n"); + break; + case USB_CLASS_HID: + dev->conf = conf; + list_remove(&dev->link); + return init_hid(dev); + + case USB_CLASS_PRINTER: + dbgprintf("printer\n"); + break; + case USB_CLASS_MASS_STORAGE: + dbgprintf("mass storage device\n"); + break; + case USB_CLASS_HUB: + dbgprintf("hub device\n"); + break; + default: + dbgprintf("unknown device\n"); + }; +}; diff --git a/programs/system/drivers/usb/hid.h b/programs/system/drivers/usb/hid.h new file mode 100644 index 0000000000..8c97d4d3fd --- /dev/null +++ b/programs/system/drivers/usb/hid.h @@ -0,0 +1,523 @@ +#ifndef __HID_H +#define __HID_H + +/* + * $Id: hid.h,v 1.24 2001/12/27 10:37:41 vojtech Exp $ + * + * Copyright (c) 1999 Andreas Gal + * Copyright (c) 2000-2001 Vojtech Pavlik + * Copyright (c) 2006-2007 Jiri Kosina + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic + */ + +#include +#include +#include +#include +#include +#include + +/* + * USB HID (Human Interface Device) interface class code + */ + +#define USB_INTERFACE_CLASS_HID 3 + +/* + * USB HID interface subclass and protocol codes + */ + +#define USB_INTERFACE_SUBCLASS_BOOT 1 +#define USB_INTERFACE_PROTOCOL_KEYBOARD 1 +#define USB_INTERFACE_PROTOCOL_MOUSE 2 + +/* + * HID class requests + */ + +#define HID_REQ_GET_REPORT 0x01 +#define HID_REQ_GET_IDLE 0x02 +#define HID_REQ_GET_PROTOCOL 0x03 +#define HID_REQ_SET_REPORT 0x09 +#define HID_REQ_SET_IDLE 0x0A +#define HID_REQ_SET_PROTOCOL 0x0B + +/* + * HID class descriptor types + */ + +#define HID_DT_HID (USB_TYPE_CLASS | 0x01) +#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02) +#define HID_DT_PHYSICAL (USB_TYPE_CLASS | 0x03) + +/* + * We parse each description item into this structure. Short items data + * values are expanded to 32-bit signed int, long items contain a pointer + * into the data area. + */ + +struct hid_item { + unsigned format; + __u8 size; + __u8 type; + __u8 tag; + union { + __u8 u8; + __s8 s8; + __u16 u16; + __s16 s16; + __u32 u32; + __s32 s32; + __u8 *longdata; + } data; +}; + +/* + * HID report item format + */ + +#define HID_ITEM_FORMAT_SHORT 0 +#define HID_ITEM_FORMAT_LONG 1 + +/* + * Special tag indicating long items + */ + +#define HID_ITEM_TAG_LONG 15 + +/* + * HID report descriptor item type (prefix bit 2,3) + */ + +#define HID_ITEM_TYPE_MAIN 0 +#define HID_ITEM_TYPE_GLOBAL 1 +#define HID_ITEM_TYPE_LOCAL 2 +#define HID_ITEM_TYPE_RESERVED 3 + +/* + * HID report descriptor main item tags + */ + +#define HID_MAIN_ITEM_TAG_INPUT 8 +#define HID_MAIN_ITEM_TAG_OUTPUT 9 +#define HID_MAIN_ITEM_TAG_FEATURE 11 +#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 10 +#define HID_MAIN_ITEM_TAG_END_COLLECTION 12 + +/* + * HID report descriptor main item contents + */ + +#define HID_MAIN_ITEM_CONSTANT 0x001 +#define HID_MAIN_ITEM_VARIABLE 0x002 +#define HID_MAIN_ITEM_RELATIVE 0x004 +#define HID_MAIN_ITEM_WRAP 0x008 +#define HID_MAIN_ITEM_NONLINEAR 0x010 +#define HID_MAIN_ITEM_NO_PREFERRED 0x020 +#define HID_MAIN_ITEM_NULL_STATE 0x040 +#define HID_MAIN_ITEM_VOLATILE 0x080 +#define HID_MAIN_ITEM_BUFFERED_BYTE 0x100 + +/* + * HID report descriptor collection item types + */ + +#define HID_COLLECTION_PHYSICAL 0 +#define HID_COLLECTION_APPLICATION 1 +#define HID_COLLECTION_LOGICAL 2 + +/* + * HID report descriptor global item tags + */ + +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0 +#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1 +#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2 +#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3 +#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4 +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5 +#define HID_GLOBAL_ITEM_TAG_UNIT 6 +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7 +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 8 +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9 +#define HID_GLOBAL_ITEM_TAG_PUSH 10 +#define HID_GLOBAL_ITEM_TAG_POP 11 + +/* + * HID report descriptor local item tags + */ + +#define HID_LOCAL_ITEM_TAG_USAGE 0 +#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1 +#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5 +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 7 +#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8 +#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9 +#define HID_LOCAL_ITEM_TAG_DELIMITER 10 + +/* + * HID usage tables + */ + +#define HID_USAGE_PAGE 0xffff0000 + +#define HID_UP_UNDEFINED 0x00000000 +#define HID_UP_GENDESK 0x00010000 +#define HID_UP_SIMULATION 0x00020000 +#define HID_UP_KEYBOARD 0x00070000 +#define HID_UP_LED 0x00080000 +#define HID_UP_BUTTON 0x00090000 +#define HID_UP_ORDINAL 0x000a0000 +#define HID_UP_CONSUMER 0x000c0000 +#define HID_UP_DIGITIZER 0x000d0000 +#define HID_UP_PID 0x000f0000 +#define HID_UP_HPVENDOR 0xff7f0000 +#define HID_UP_MSVENDOR 0xff000000 +#define HID_UP_CUSTOM 0x00ff0000 +#define HID_UP_LOGIVENDOR 0xffbc0000 + +#define HID_USAGE 0x0000ffff + +#define HID_GD_POINTER 0x00010001 +#define HID_GD_MOUSE 0x00010002 +#define HID_GD_JOYSTICK 0x00010004 +#define HID_GD_GAMEPAD 0x00010005 +#define HID_GD_KEYBOARD 0x00010006 +#define HID_GD_KEYPAD 0x00010007 +#define HID_GD_MULTIAXIS 0x00010008 +#define HID_GD_X 0x00010030 +#define HID_GD_Y 0x00010031 +#define HID_GD_Z 0x00010032 +#define HID_GD_RX 0x00010033 +#define HID_GD_RY 0x00010034 +#define HID_GD_RZ 0x00010035 +#define HID_GD_SLIDER 0x00010036 +#define HID_GD_DIAL 0x00010037 +#define HID_GD_WHEEL 0x00010038 +#define HID_GD_HATSWITCH 0x00010039 +#define HID_GD_BUFFER 0x0001003a +#define HID_GD_BYTECOUNT 0x0001003b +#define HID_GD_MOTION 0x0001003c +#define HID_GD_START 0x0001003d +#define HID_GD_SELECT 0x0001003e +#define HID_GD_VX 0x00010040 +#define HID_GD_VY 0x00010041 +#define HID_GD_VZ 0x00010042 +#define HID_GD_VBRX 0x00010043 +#define HID_GD_VBRY 0x00010044 +#define HID_GD_VBRZ 0x00010045 +#define HID_GD_VNO 0x00010046 +#define HID_GD_FEATURE 0x00010047 +#define HID_GD_UP 0x00010090 +#define HID_GD_DOWN 0x00010091 +#define HID_GD_RIGHT 0x00010092 +#define HID_GD_LEFT 0x00010093 + +/* + * HID report types --- Ouch! HID spec says 1 2 3! + */ + +#define HID_INPUT_REPORT 0 +#define HID_OUTPUT_REPORT 1 +#define HID_FEATURE_REPORT 2 + +/* + * HID device quirks. + */ + +#define HID_QUIRK_INVERT 0x00000001 +#define HID_QUIRK_NOTOUCH 0x00000002 +#define HID_QUIRK_IGNORE 0x00000004 +#define HID_QUIRK_NOGET 0x00000008 +#define HID_QUIRK_HIDDEV 0x00000010 +#define HID_QUIRK_BADPAD 0x00000020 +#define HID_QUIRK_MULTI_INPUT 0x00000040 +#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 +#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 +#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 +#define HID_QUIRK_MIGHTYMOUSE 0x00000400 +#define HID_QUIRK_CYMOTION 0x00000800 +#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 +#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 +#define HID_QUIRK_INVERT_HWHEEL 0x00004000 +#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000 +#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000 +#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000 +#define HID_QUIRK_IGNORE_MOUSE 0x00040000 +#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000 +#define HID_QUIRK_LOGITECH_S510_DESCRIPTOR 0x00100000 +#define HID_QUIRK_DUPLICATE_USAGES 0x00200000 + +/* + * This is the global environment of the parser. This information is + * persistent for main-items. The global environment can be saved and + * restored with PUSH/POP statements. + */ + +struct hid_global { + unsigned usage_page; + __s32 logical_minimum; + __s32 logical_maximum; + __s32 physical_minimum; + __s32 physical_maximum; + __s32 unit_exponent; + unsigned unit; + unsigned report_id; + unsigned report_size; + unsigned report_count; +}; + +/* + * This is the local environment. It is persistent up the next main-item. + */ + +#define HID_MAX_DESCRIPTOR_SIZE 4096 +#define HID_MAX_USAGES 8192 +#define HID_DEFAULT_NUM_COLLECTIONS 16 + +struct hid_local { + unsigned usage[HID_MAX_USAGES]; /* usage array */ + unsigned collection_index[HID_MAX_USAGES]; /* collection index array */ + unsigned usage_index; + unsigned usage_minimum; + unsigned delimiter_depth; + unsigned delimiter_branch; +}; + +/* + * This is the collection stack. We climb up the stack to determine + * application and function of each field. + */ + +struct hid_collection { + unsigned type; + unsigned usage; + unsigned level; +}; + +struct hid_usage { + unsigned hid; /* hid usage code */ + unsigned collection_index; /* index into collection array */ + /* hidinput data */ + __u16 code; /* input driver code */ + __u8 type; /* input driver type */ + __s8 hat_min; /* hat switch fun */ + __s8 hat_max; /* ditto */ + __s8 hat_dir; /* ditto */ +}; + +struct hid_input; + +struct hid_field { + unsigned physical; /* physical usage for this field */ + unsigned logical; /* logical usage for this field */ + unsigned application; /* application usage for this field */ + struct hid_usage *usage; /* usage table for this function */ + unsigned maxusage; /* maximum usage index */ + unsigned flags; /* main-item flags (i.e. volatile,array,constant) */ + unsigned report_offset; /* bit offset in the report */ + unsigned report_size; /* size of this field in the report */ + unsigned report_count; /* number of this field in the report */ + unsigned report_type; /* (input,output,feature) */ + __s32 *value; /* last known value(s) */ + __s32 logical_minimum; + __s32 logical_maximum; + __s32 physical_minimum; + __s32 physical_maximum; + __s32 unit_exponent; + unsigned unit; + struct hid_report *report; /* associated report */ + unsigned index; /* index into report->field[] */ + /* hidinput data */ + struct hid_input *hidinput; /* associated input structure */ + __u16 dpad; /* dpad input code */ +}; + +#define HID_MAX_FIELDS 64 + +struct hid_report { + struct list_head list; + unsigned id; /* id of this report */ + unsigned type; /* report type */ + struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */ + unsigned maxfield; /* maximum valid field index */ + unsigned size; /* size of the report (bits) */ + struct hid_device *device; /* associated device */ +}; + +struct hid_report_enum { + unsigned numbered; + struct list_head report_list; + struct hid_report *report_id_hash[256]; +}; + +#define HID_REPORT_TYPES 3 + +#define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */ +#define HID_MAX_BUFFER_SIZE 4096 /* 4kb */ +#define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */ +#define HID_OUTPUT_FIFO_SIZE 64 + +struct hid_control_fifo { + unsigned char dir; + struct hid_report *report; +}; + +#define HID_CLAIMED_INPUT 1 +#define HID_CLAIMED_HIDDEV 2 + +#define HID_CTRL_RUNNING 1 +#define HID_OUT_RUNNING 2 +#define HID_IN_RUNNING 3 +#define HID_RESET_PENDING 4 +#define HID_SUSPENDED 5 +#define HID_CLEAR_HALT 6 + +struct hid_input { + struct list_head list; + struct hid_report *report; + struct input_dev *input; +}; + +struct hid_device { /* device report descriptor */ + __u8 *rdesc; + unsigned rsize; + struct hid_collection *collection; /* List of HID collections */ + unsigned collection_size; /* Number of allocated hid_collections */ + unsigned maxcollection; /* Number of parsed collections */ + unsigned maxapplication; /* Number of applications */ + unsigned short bus; /* BUS ID */ + unsigned short vendor; /* Vendor ID */ + unsigned short product; /* Product ID */ + unsigned version; /* HID version */ + unsigned country; /* HID country */ + struct hid_report_enum report_enum[HID_REPORT_TYPES]; + + struct device *dev; /* device */ + + unsigned claimed; /* Claimed by hidinput, hiddev? */ + unsigned quirks; /* Various quirks the device can pull on us */ + + struct list_head inputs; /* The list of inputs */ + void *hiddev; /* The hiddev structure */ + int minor; /* Hiddev minor number */ + + wait_queue_head_t wait; /* For sleeping */ + + int open; /* is the device open by anyone? */ + char name[128]; /* Device name */ + char phys[64]; /* Device physical location */ + char uniq[64]; /* Device unique identifier (serial #) */ + + void *driver_data; + + /* device-specific function pointers */ + int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int); + int (*hid_open) (struct hid_device *); + void (*hid_close) (struct hid_device *); + + /* hiddev event handler */ + void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field, + struct hid_usage *, __s32); + void (*hiddev_report_event) (struct hid_device *, struct hid_report *); +#ifdef CONFIG_USB_HIDINPUT_POWERBOOK + unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; + unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; +#endif +}; + +#define HID_GLOBAL_STACK_SIZE 4 +#define HID_COLLECTION_STACK_SIZE 4 + +struct hid_parser { + struct hid_global global; + struct hid_global global_stack[HID_GLOBAL_STACK_SIZE]; + unsigned global_stack_ptr; + struct hid_local local; + unsigned collection_stack[HID_COLLECTION_STACK_SIZE]; + unsigned collection_stack_ptr; + struct hid_device *device; +}; + +struct hid_class_descriptor { + __u8 bDescriptorType; + __u16 wDescriptorLength; +} __attribute__ ((packed)); + +struct hid_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u16 bcdHID; + __u8 bCountryCode; + __u8 bNumDescriptors; + + struct hid_class_descriptor desc[1]; +} __attribute__ ((packed)); + +/* Applications from HID Usage Tables 4/8/99 Version 1.1 */ +/* We ignore a few input applications that are not widely used */ +#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001)) + +/* HID core API */ +extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); +extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report); +extern int hidinput_connect(struct hid_device *); +extern void hidinput_disconnect(struct hid_device *); + +int hid_set_field(struct hid_field *, unsigned, __s32); +int hid_input_report(struct hid_device *, int type, u8 *, int, int); +int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); +void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt); +void hid_output_report(struct hid_report *report, __u8 *data); +void hid_free_device(struct hid_device *device); +struct hid_device *hid_parse_report(__u8 *start, unsigned size); + +#ifdef CONFIG_HID_FF +int hid_ff_init(struct hid_device *hid); + +int hid_lgff_init(struct hid_device *hid); +int hid_plff_init(struct hid_device *hid); +int hid_tmff_init(struct hid_device *hid); +int hid_zpff_init(struct hid_device *hid); +#ifdef CONFIG_HID_PID +int hid_pidff_init(struct hid_device *hid); +#else +static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; } +#endif + +#else +static inline int hid_ff_init(struct hid_device *hid) { return -1; } +#endif +#ifdef DEBUG +#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \ + __FILE__ , ## arg) +#else +#define dbg(format, arg...) do {} while (0) +#endif + +#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \ + __FILE__ , ## arg) +#endif + diff --git a/programs/system/drivers/usb/hid.inc b/programs/system/drivers/usb/hid.inc new file mode 100644 index 0000000000..598f9227b4 --- /dev/null +++ b/programs/system/drivers/usb/hid.inc @@ -0,0 +1,154 @@ + +struct hid_class_descriptor { + u8_t bDescriptorType; + u16_t wDescriptorLength; +} __attribute__ ((packed)); + +struct hid_descriptor { + u8_t bLength; + u8_t bDescriptorType; + u16_t bcdHID; + u8_t bCountryCode; + u8_t bNumDescriptors; + + struct hid_class_descriptor desc[1]; +} __attribute__ ((packed)); + +void create_hid_mouse(udev_t *dev, endpoint_descr_t *en_d); + +Bool init_hid(udev_t *dev) +{ + interface_descr_t *interface; + struct hid_descriptor *hds; + struct hid_class_descriptor *hidclass; + u8_t *dptr = (u8_t*)dev->conf; + + int i=0, j=0; + + dbgprintf( "init hid device\n"); + + dptr+= dev->conf->bLength; + + // for(i = 0; i < dev->conf->bNumInterfaces; i++) + // { + interface = (interface_descr_t*)dptr; + dptr+= interface->bLength; + + dbgprintf("interface %d\n\n" + "bLength %d\n" + "bDescriptorType %d\n" + "bInterfaceNumber %d\n" + "bAlternateSetting %d\n" + "bNumEndpoints %d\n" + "bInterfaceClass %d\n" + "bInterfaceSubClass %d\n" + "bInterfaceProtocol %d\n" + "iInterface %d\n\n", + i+1, + interface->bLength, + interface->bDescriptorType, + interface->bInterfaceNumber, + interface->bAlternateSetting, + interface->bNumEndpoints, + interface->bInterfaceClass, + interface->bInterfaceSubClass, + interface->bInterfaceProtocol, + interface->iInterface); + + hds = (struct hid_descriptor*) dptr; + + dbgprintf("hid descriptor\n\n" + "bLength %d\n" + "bDescriptorType %d\n" + "bcdHID %x\n" + "bCountryCode %d\n" + "bNumDescriptors %d\n", + hds->bLength, + hds->bDescriptorType, + hds->bcdHID, + hds->bCountryCode, + hds->bNumDescriptors); + + for(j=0; j < hds->bNumDescriptors; j++) + { + dbgprintf("bDescriptorType %d\n" + "wDescriptorLength %d\n", + hds->desc[j].bDescriptorType, + hds->desc[j].wDescriptorLength); + }; + dptr+= hds->bLength; + + endpoint_descr_t *ep; + ep = (endpoint_descr_t*)dptr; + + dbgprintf("\nendpoint\n\n" + "bLength %d\n" + "bDescriptorType %d\n" + "bEndpointAddress %d\n" + "bmAttributes %d\n" + "wMaxPacketSize %d\n" + "bInterval %d\n", + ep->bLength, ep->bDescriptorType, + ep->bEndpointAddress, ep->bmAttributes, + ep->wMaxPacketSize, ep->bInterval); + dptr+= ep->bLength; + + if( interface->bInterfaceProtocol == 2) + create_hid_mouse(dev, ep); + // } + return TRUE; +}; + + +Bool mouse_handler(udev_t *dev, struct tag_request *rq) +{ + td_t *td; + + td = rq->td_head; + + if( (td->status &0x7FF)==rq->size-1) + { + struct boot_packet *pkt; + pkt = (struct boot_packet *)rq->data; + SetMouseData(pkt->buttons, pkt->x, -pkt->y, -pkt->z, 0); + }; + td->status = 0x00800000 | dev->speed; + td->token ^= DATA1; + + return TRUE; +}; + +void create_hid_mouse(udev_t *dev, endpoint_descr_t *en_d) +{ + request_t *rq; + endp_t enp; + + addr_t address; + addr_t size; + u32_t toggle; + + void *packet; + + td_t *td; + qh_t *qh; + + static u16_t __attribute__((aligned(16))) + req_set_conf[4] = {0x0900,0x0001,0x0000,0x0000}; + + if( !ctrl_request(dev, req_set_conf, DOUT, 0, 0)) + return; + + enp.address = en_d->bEndpointAddress; + enp.size = en_d->wMaxPacketSize; + enp.toggle = DATA0; + + packet = malloc(enp.size); + memset(packet, 0, enp.size); + + rq = create_request(dev, &enp, DIN, packet, enp.size); + rq->handler = &mouse_handler; + + list_prepend(&rq->link, &rq_list); + + dbgprintf("create_hid_mouse\n"); +} diff --git a/programs/system/drivers/usb/makefile b/programs/system/drivers/usb/makefile new file mode 100644 index 0000000000..60128bb6c7 --- /dev/null +++ b/programs/system/drivers/usb/makefile @@ -0,0 +1,42 @@ + +CC = gcc +FASM = e:/fasm/fasm.exe +CFLAGS = -c -O2 -fomit-frame-pointer -fno-builtin-printf +LDRHD = -shared -T ld.x -s --file-alignment 32 + +INCLUDES = -I ../include + +HFILES:= ../include/types.h \ + ../include/syscall.h \ + ../include/link.h \ + pci.h \ + usb.h + +SRC_DEP:= pci.inc \ + detect.inc \ + hcd.inc \ + hid.inc + +USB_SRC:= usb.c + +USB_OBJ:= usb.obj + + +USB = usb.dll + +all: $(USB) + +$(USB): $(USB_OBJ) $(SRC_DEP) $(HFILES) Makefile + wlink name usb.dll SYS nt_dll lib libdrv op offset=0 op nod op maxe=25 op el op STUB=stub.exe op START=_drvEntry @usb.lk1 + kpack.exe usb.dll usb.drv + +usb.obj : usb.c $(SRC_DEP) $(HFILES) Makefile + $(CC) $(INCLUDES) $(CFLAGS) -o usb.obj usb.c + +%.obj : %.c $(HFILES) + $(CC) $(CFLAGS) -o $@ $< + +%.obj: %.asm + as -o $@ $< + + diff --git a/programs/system/drivers/usb/pci.h b/programs/system/drivers/usb/pci.h new file mode 100644 index 0000000000..4ec48ac41c --- /dev/null +++ b/programs/system/drivers/usb/pci.h @@ -0,0 +1,95 @@ + + +#pragma pack(push, 1) +typedef struct +{ + u16_t device; + u16_t ChipSet; +}PciChipset_t; +#pragma pack(pop) + + +#define PCI_VENDOR_ID 0x00 /* 16 bits */ +#define PCI_DEVICE_ID 0x02 /* 16 bits */ +#define PCI_COMMAND 0x04 /* 16 bits */ +#define PCI_COMMAND_IO 0x01 /* Enable response in I/O space */ +#define PCI_COMMAND_MEMORY 0x02 /* Enable response in Memory space */ +#define PCI_COMMAND_MASTER 0x04 /* Enable bus mastering */ +#define PCI_COMMAND_SPECIAL 0x08 /* Enable response to special cycles */ +#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ +#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ +#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ +#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ +#define PCI_COMMAND_SERR 0x100 /* Enable SERR */ +#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ +#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */ + + + +#define PCI_MAP_REG_START 0x10 +#define PCI_MAP_REG_END 0x28 +#define PCI_MAP_ROM_REG 0x30 + +#define PCI_MAP_MEMORY 0x00000000 +#define PCI_MAP_IO 0x00000001 + +#define PCI_MAP_MEMORY_TYPE 0x00000007 +#define PCI_MAP_IO_TYPE 0x00000003 + +#define PCI_MAP_MEMORY_TYPE_32BIT 0x00000000 +#define PCI_MAP_MEMORY_TYPE_32BIT_1M 0x00000002 +#define PCI_MAP_MEMORY_TYPE_64BIT 0x00000004 +#define PCI_MAP_MEMORY_TYPE_MASK 0x00000006 +#define PCI_MAP_MEMORY_CACHABLE 0x00000008 +#define PCI_MAP_MEMORY_ATTR_MASK 0x0000000e +#define PCI_MAP_MEMORY_ADDRESS_MASK 0xfffffff0 + +#define PCI_MAP_IO_ATTR_MASK 0x00000003 + +#define PCI_MAP_IS_IO(b) ((b) & PCI_MAP_IO) +#define PCI_MAP_IS_MEM(b) (!PCI_MAP_IS_IO(b)) + +#define PCI_MAP_IS64BITMEM(b) \ + (((b) & PCI_MAP_MEMORY_TYPE_MASK) == PCI_MAP_MEMORY_TYPE_64BIT) + +#define PCIGETMEMORY(b) ((b) & PCI_MAP_MEMORY_ADDRESS_MASK) +#define PCIGETMEMORY64HIGH(b) (*((CARD32*)&b + 1)) +#define PCIGETMEMORY64(b) \ + (PCIGETMEMORY(b) | ((CARD64)PCIGETMEMORY64HIGH(b) << 32)) + +#define PCI_MAP_IO_ADDRESS_MASK 0xfffffffc + +#define PCIGETIO(b) ((b) & PCI_MAP_IO_ADDRESS_MASK) + +#define PCI_MAP_ROM_DECODE_ENABLE 0x00000001 +#define PCI_MAP_ROM_ADDRESS_MASK 0xfffff800 + +#define PCIGETROM(b) ((b) & PCI_MAP_ROM_ADDRESS_MASK) + + +#ifndef PCI_DOM_MASK +# define PCI_DOM_MASK 0x0ffu +#endif +#define PCI_DOMBUS_MASK (((PCI_DOM_MASK) << 8) | 0x0ffu) + +#define PCI_MAKE_TAG(b,d,f) ((((b) & (PCI_DOMBUS_MASK)) << 16) | \ + (((d) & 0x00001fu) << 11) | \ + (((f) & 0x000007u) << 8)) + +#define PCI_BUS_FROM_TAG(tag) (((tag) >> 16) & (PCI_DOMBUS_MASK)) +#define PCI_DEV_FROM_TAG(tag) (((tag) & 0x0000f800u) >> 11) +#define PCI_FUNC_FROM_TAG(tag) (((tag) & 0x00000700u) >> 8) +#define PCI_DFN_FROM_TAG(tag) (((tag) & 0x0000ff00u) >> 8) + + +typedef unsigned int PCITAG; + +extern inline PCITAG +pciTag(int busnum, int devnum, int funcnum) +{ + return(PCI_MAKE_TAG(busnum,devnum,funcnum)); +} + +u32_t pciGetBaseSize(int bus, int devfn, int index, Bool destructive, Bool *min); + +Bool FindPciDevice(); diff --git a/programs/system/drivers/usb/pci.inc b/programs/system/drivers/usb/pci.inc new file mode 100644 index 0000000000..2db682ad91 --- /dev/null +++ b/programs/system/drivers/usb/pci.inc @@ -0,0 +1,98 @@ + + +u32_t pciGetBaseSize(int bus, int devfn, int index, + Bool destructive, Bool *min) +{ + int offset; + u32_t addr1; + u32_t addr2; + u32_t mask1; + u32_t mask2; + int bits = 0; + + /* + * silently ignore bogus index values. Valid values are 0-6. 0-5 are + * the 6 base address registers, and 6 is the ROM base address register. + */ + if (index < 0 || index > 6) + return 0; + + if (min) + *min = destructive; + + /* Get the PCI offset */ + if (index == 6) + offset = PCI_MAP_ROM_REG; + else + offset = PCI_MAP_REG_START + (index << 2); + + addr1 = PciRead32(bus, devfn, offset); + /* + * Check if this is the second part of a 64 bit address. + * XXX need to check how endianness affects 64 bit addresses. + */ + if (index > 0 && index < 6) { + addr2 = PciRead32(bus, devfn, offset - 4); + if (PCI_MAP_IS_MEM(addr2) && PCI_MAP_IS64BITMEM(addr2)) + return 0; + } + + if (destructive) { + PciWrite32(bus, devfn, offset, 0xffffffff); + mask1 = PciRead32(bus, devfn, offset); + PciWrite32(bus, devfn, offset, addr1); + } else { + mask1 = addr1; + } + + /* Check if this is the first part of a 64 bit address. */ + if (index < 5 && PCI_MAP_IS_MEM(mask1) && PCI_MAP_IS64BITMEM(mask1)) + { + if (PCIGETMEMORY(mask1) == 0) + { + addr2 = PciRead32(bus, devfn, offset + 4); + if (destructive) + { + PciWrite32(bus, devfn, offset + 4, 0xffffffff); + mask2 = PciRead32(bus, devfn, offset + 4); + PciWrite32(bus, devfn, offset + 4, addr2); + } + else + { + mask2 = addr2; + } + if (mask2 == 0) + return 0; + bits = 32; + while ((mask2 & 1) == 0) + { + bits++; + mask2 >>= 1; + } + if (bits > 32) + return bits; + } + } + if (index < 6) + if (PCI_MAP_IS_MEM(mask1)) + mask1 = PCIGETMEMORY(mask1); + else + mask1 = PCIGETIO(mask1); + else + mask1 = PCIGETROM(mask1); + if (mask1 == 0) + return 0; + bits = 0; + while ((mask1 & 1) == 0) { + bits++; + mask1 >>= 1; + } + /* I/O maps can be no larger than 8 bits */ + + if ((index < 6) && PCI_MAP_IS_IO(addr1) && bits > 8) + bits = 8; + /* ROM maps can be no larger than 24 bits */ + if (index == 6 && bits > 24) + bits = 24; + return bits; +} diff --git a/programs/system/drivers/usb/usb.asm b/programs/system/drivers/usb/usb.asm new file mode 100644 index 0000000000..65eab9a4e3 --- /dev/null +++ b/programs/system/drivers/usb/usb.asm @@ -0,0 +1,27 @@ + +use32 + +db 'MENUET01' +dd 1 +dd start +dd i_end +dd mem +dd mem +dd 0 +dd 0 + +start: + mov eax, 68 + mov ebx, 21 + mov ecx, sz_usb + int 0x40 + + mov eax, -1 + int 0x40 + +sz_usb db '/rd/1/drivers/usb.drv',0 + +align 4 +i_end: +rb 128 +mem: diff --git a/programs/system/drivers/usb/usb.c b/programs/system/drivers/usb/usb.c new file mode 100644 index 0000000000..8169237963 --- /dev/null +++ b/programs/system/drivers/usb/usb.c @@ -0,0 +1,231 @@ + + +#include "types.h" +#include "link.h" + +#include +#include +#include + +#include "pci.h" + +#include "syscall.h" +#include "usb.h" + + +int __stdcall srv_usb(ioctl_t *io); + +Bool init_hc(hc_t *hc); + +static slab_t qh_slab; +static slab_t td_slab; + +static link_t hc_list; +static link_t newdev_list; +static link_t rq_list; + +u32_t __stdcall drvEntry(int action) +{ + u32_t retval; + hc_t *hc; + udev_t *dev; + + int i; + + if(action != 1) + return 0; + + if(!dbg_open("/rd/1/drivers/usb.log")) + { + printf("Can't open /rd/1/drivers/usb.log\nExit\n"); + return 0; + } + + list_initialize(&hc_list); + list_initialize(&newdev_list); + list_initialize(&rq_list); + + if( !FindPciDevice() ) { + dbgprintf("no uhci devices found\n"); + return 0; + }; + + qh_slab.available = 256; + qh_slab.start = KernelAlloc(4096); + qh_slab.nextavail = (addr_t)qh_slab.start; + qh_slab.dma = GetPgAddr(qh_slab.start); + + qh_t *p; + addr_t dma; + + for (i = 0, p = (qh_t*)qh_slab.start, dma = qh_slab.dma; + i < 256; i++, p++, dma+= sizeof(qh_t)) + { + p->qlink = (addr_t)(p+1); + p->qelem = 1; + p->dma = dma; + p->r1 = 0; + }; + + td_slab.available = 128; + td_slab.start = KernelAlloc(4096); + td_slab.nextavail = (addr_t)td_slab.start; + td_slab.dma = GetPgAddr(td_slab.start); + + td_t *td; + for (i = 0, td = (td_t*)td_slab.start, dma = td_slab.dma; + i < 128; i++, td++, dma+= sizeof(td_t)) + { + td->link = (addr_t)(td+1); + td->status = 0; + td->token = 0; + td->buffer = 0; + td->dma = dma; + }; + + + hc = (hc_t*)hc_list.next; + + while( &hc->link != &hc_list) + { + init_hc(hc); + hc = (hc_t*)hc->link.next; + } + + dbgprintf("\n"); + + dev = (udev_t*)newdev_list.next; + while( &dev->link != &newdev_list) + { + udev_t *tmp = dev; + dev = (udev_t*)dev->link.next; + + if(tmp->id != 0) + init_device(tmp); + } + + while(1) + { + udev_t *dev; + request_t *rq; + + rq = (request_t*)rq_list.next; + while( &rq->link != &rq_list) + { + qh_t *qh; + td_t *td; + + td = rq->td_head; + dev = rq->dev; + qh = dev->host->qh1; + + qh->qelem = td->dma; + + __asm__ __volatile__ ("":::"memory"); + rq = (request_t*)rq->link.next; + }; + + delay(10/10); + + rq = (request_t*)rq_list.next; + while( &rq->link != &rq_list) + { + request_t *tmp; + td_t *td; + + tmp = rq; + rq = (request_t*)rq->link.next; + + td = tmp->td_head; + + if( td->status & TD_CTRL_ACTIVE) + continue; + + tmp->handler(tmp->dev, tmp); + }; + }; + + retval = RegService("USB", srv_usb); + dbgprintf("reg service USB as: %x\n", retval); + + return retval; +}; + + +#define API_VERSION 0x01000100 + +#define SRV_GETVERSION 0 + + +int __stdcall srv_usb(ioctl_t *io) +{ + u32_t *inp; + u32_t *outp; + + inp = io->input; + outp = io->output; + + switch(io->io_code) + { + case SRV_GETVERSION: + if(io->out_size==4) + { + *outp = API_VERSION; + return 0; + } + break; + + + default: + return ERR_PARAM; + }; + return ERR_PARAM; +} + + +static qh_t* alloc_qh() +{ + if( qh_slab.available ) + { + qh_t *qh; + + qh_slab.available--; + qh = (qh_t*)qh_slab.nextavail; + qh_slab.nextavail = qh->qlink; + return qh; + } + return NULL; +}; + +static void free_qh(qh_t *qh) +{ + qh->qlink = qh_slab.nextavail; + qh_slab.nextavail = (addr_t)qh; + qh_slab.available++; +}; + +static td_t* alloc_td() +{ + if( td_slab.available ) + { + td_t *td; + + td_slab.available--; + td = (td_t*)td_slab.nextavail; + td_slab.nextavail = td->link; + return td; + } + return NULL; +}; + +static void free_td(td_t *td) +{ + td->link = td_slab.nextavail; + td_slab.nextavail = (addr_t)td; + td_slab.available++; +}; + +#include "pci.inc" +#include "detect.inc" +#include "hcd.inc" +#include "hid.inc" diff --git a/programs/system/drivers/usb/usb.h b/programs/system/drivers/usb/usb.h new file mode 100644 index 0000000000..2e53961157 --- /dev/null +++ b/programs/system/drivers/usb/usb.h @@ -0,0 +1,247 @@ + + +typedef struct { + int available; /**< Count of available items in this slab. */ + void *start; /**< Start address of first item. */ + addr_t nextavail; /**< The index of next available item. */ + addr_t dma; +} slab_t; + + +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_COMM 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_PHYSICAL 5 +#define USB_CLASS_STILL_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_CDC_DATA 0x0a +#define USB_CLASS_CSCID 0x0b /* chip+ smart card */ +#define USB_CLASS_CONTENT_SEC 0x0d /* content security */ +#define USB_CLASS_VIDEO 0x0e +#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 +#define USB_CLASS_MISC 0xef +#define USB_CLASS_APP_SPEC 0xfe +#define USB_CLASS_VENDOR_SPEC 0xff + + +typedef struct +{ + addr_t qlink; + addr_t qelem; + + addr_t dma; + u32_t r1; + +}qh_t __attribute__((aligned(16))); + +typedef struct +{ + link_t link; + + addr_t iobase; + + u32_t *frame_base; + count_t frame_number; + addr_t frame_dma; + + qh_t *qh1; + + u32_t *data; + addr_t data_dma; + + u32_t port_map; + + int numports; + + u32_t pciId; + PCITAG PciTag; + addr_t ioBase[6]; + addr_t memBase[6]; + size_t memSize[6]; + u32_t memType[6]; +}hc_t; + +typedef struct tag_td +{ + /* Hardware fields */ + addr_t link; + u32_t status; + u32_t token; + addr_t buffer; + + /* Software fields */ + addr_t dma; + + struct tag_td *bk; + + // struct list_head list; + + // int frame; /* for iso: what frame? */ + // struct list_head fl_list; + + u32_t reserved[2]; +} td_t __attribute__((aligned(16))); + +#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ +#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ +#define TD_CTRL_C_ERR_SHIFT 27 +#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ +#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ +#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ +#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ +#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ +#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ +#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ +#define TD_CTRL_NAK (1 << 19) /* NAK Received */ +#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ +#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ + +#define TD_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ + TD_CTRL_BABBLE | TD_CTRL_CRCTIMEO | \ + TD_CTRL_BITSTUFF) + +typedef struct __attribute__ ((packed)) +{ + u8_t bLength; + u8_t bDescriptorType; + u16_t bcdUSB; + + u8_t bDeviceClass; + u8_t bDeviceSubClass; + u8_t bDeviceProtocol; + u8_t bMaxPacketSize0; + + u16_t idVendor; + u16_t idProduct; + u16_t bcdDevice; + + u8_t iManufacturer; + u8_t iProduct; + u8_t iSerialNumber; + u8_t bNumConfigurations; +}dev_descr_t; + +typedef struct __attribute__ ((packed)) +{ + u8_t bLength; + u8_t bDescriptorType; + u16_t wTotalLength; + u8_t bNumInterfaces; + u8_t bConfigurationValue; + u8_t iConfiguration; + u8_t bmAttributes; + u8_t bMaxPower; +}conf_descr_t; + +typedef struct __attribute__ ((packed)) +{ + u8_t bLength; + u8_t bDescriptorType; + u8_t bInterfaceNumber; + u8_t bAlternateSetting; + u8_t bNumEndpoints; + u8_t bInterfaceClass; + u8_t bInterfaceSubClass; + u8_t bInterfaceProtocol; + u8_t iInterface; +}interface_descr_t ; + +typedef struct __attribute__ ((packed)) +{ + u8_t bLength; + u8_t bDescriptorType; + + u8_t bEndpointAddress; + u8_t bmAttributes; + u16_t wMaxPacketSize; + u8_t bInterval; + + /* NOTE: these two are _only_ in audio endpoints. */ + /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */ + u8_t bRefresh; + u8_t bSynchAddress; +}endpoint_descr_t; + +typedef struct +{ + addr_t address; + addr_t size; + u32_t toggle; + +}endp_t; + +typedef struct __attribute__ ((packed)) +{ + u8_t bRequestType; + u8_t bRequest; + u16_t wValue; + u16_t wIndex; + u16_t wLength; +}ctrl_request_t; + + +typedef struct +{ + link_t link; + u32_t id; + + hc_t *host; + + u32_t speed; + addr_t addr; + + addr_t ep0_size; + + endp_t enp; + + u32_t status; + int port; + + dev_descr_t dev_descr; + conf_descr_t *conf; +}udev_t; + +typedef struct tag_request +{ + link_t link; + td_t *td_head; + td_t *td_tail; + addr_t data; + size_t size; + udev_t *dev; + u32_t type; + Bool (*handler)(udev_t *dev, struct tag_request *rq); +}request_t; + + +#define DMA(val) GetPgAddr(val)|(((addr_t)(val))&0xFFF) + +#define TOKEN( size, toggle, ep, addr, pid) \ + ( (((size)-1)<<21)|(toggle)|(((ep)&0xF)<<15)|((addr)<<8)|(pid)) + +Bool ctrl_request(udev_t *dev, void *req, u32_t dir, + void *data, size_t req_size); + + +Bool set_address(udev_t *dev); + +Bool init_device(udev_t *dev); + +Bool init_hid(udev_t *dev); + +struct boot_packet +{ + u8_t buttons; + i8_t x; + i8_t y; + i8_t z; +}__attribute__ ((packed)); + +#define DOUT 0xE1 +#define DIN 0x69 + +#define DATA0 (0<<19) +#define DATA1 (1<<19) + diff --git a/programs/system/drivers/usb/usb.lk1 b/programs/system/drivers/usb/usb.lk1 new file mode 100644 index 0000000000..054e70e857 --- /dev/null +++ b/programs/system/drivers/usb/usb.lk1 @@ -0,0 +1,22 @@ +IMP + _KernelAlloc core.KernelAlloc, + _KernelFree core.KernelFree, + _UserAlloc core.UserAlloc, + _UserFree core.UserFree, + _MapIoMem core.MapIoMem, + _GetPgAddr core.GetPgAddr, + _PciApi core.PciApi, + _PciRead8 core.PciRead8, + _PciRead16 core.PciRead16, + _PciRead32 core.PciRead32, + _PciWrite16 core.PciWrite16, + _PciWrite32 core.PciWrite32, + _RegService core.RegService, + _SysMsgBoardStr core.SysMsgBoardStr, + _Delay core.Delay, + _SetMouseData core.SetMouseData + + +FIL usb.obj, + vsprintf.obj, + icompute.obj