/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*
* isp1161 USB HCD for Linux Version 0.9.5 (10/28/2001)
*
* requires (includes) hc_simple.[hc] simple generic HCD frontend
*
* Roman Weissgaerber weissg@vienna.at (C) 2001
*
* Thanks to Benjamin Herrenschmidt for debugging and the removing of
* some bugs.
*
*-------------------------------------------------------------------------*
* 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
*
*-------------------------------------------------------------------------*/
/*History*/
/* V 0.9.5 10/28/2001 correct toggle on error */
/* inw, outw macros; ISOC support */
/* V 0.9 remove some bugs, ISOC still missing */
/* V 0.8.1 9/5/2001 mv memcpy of in packet to hc */
/* V 0.8 initial release */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/list.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/usb.h>
#undef HC_URB_TIMEOUT
#undef HC_SWITCH_INT
#undef HC_ENABLE_ISOC
#include "hc_isp1161A1.h"
#include "hc_isp1161A1_simple.h"
static int hc_verbose = 1;
static int hc_error_verbose = 0;
static int urb_debug = 0;
#include "hc_isp1161A1_simple.c"
#include "hc_isp1161A1_rh.c"
#define EPI400_USB_HC_GPIO 5
static int irq = IRQ_GPIO(EPI400_USB_HC_GPIO);
static int hcport = 0xf4000000; /* DATA Port */
static int hcport2 = 0xf4000002; /* COMMAND Port */
MODULE_PARM(hc_verbose,"i");
MODULE_PARM_DESC(hc_verbose,"verbose startup messages, default is 1 (yes)");
MODULE_PARM(hc_error_verbose,"i");
MODULE_PARM_DESC(hc_error_verbose,"verbose error/warning messages, default is 0 (no)");
MODULE_PARM(urb_debug,"i");
MODULE_PARM_DESC(urb_debug,"debug urb messages, default is 0 (no)");
MODULE_PARM(irq,"i");
MODULE_PARM_DESC(irq,"IRQ 3, 10 (default)");
MODULE_PARM(hcport,"i");
MODULE_PARM_DESC(hcport,"ISP116x PORT 0x290");
MODULE_PARM(hcport2,"i");
MODULE_PARM_DESC(hcport2,"ISP116x PORT2 0x292");
static inline void ISP116x_OUTW (int val, int addr)
{
outw (val, addr);
udelay(1);
}
static inline int ISP116x_INW (int addr)
{
int val;
val = inw (addr) & 0xffff;
udelay(1);
return val;
}
static inline int READ_REG32 (hci_t * hci, int regindex)
{
hcipriv_t * hp = &hci->hp;
int val16, val;
ISP116x_OUTW (regindex, hp->hcport2);
val16 = ISP116x_INW (hp->hcport);
val = val16;
val16 = ISP116x_INW (hp->hcport);
val |= val16 << 16;
return val;
}
static inline int READ_REG16 (hci_t * hci, int regindex)
{
hcipriv_t * hp = &hci->hp;
int val = 0;
ISP116x_OUTW (regindex, hp->hcport2);
val = ISP116x_INW (hp->hcport);
return val;
}
static inline void READ_REGn16 (hci_t * hci, int regindex, int length, __u8 * buffer)
{
hcipriv_t * hp = &hci->hp;
int i;
int val = 0;
ISP116x_OUTW (regindex, hp->hcport2);
for (i = 0; i < length - 1; i += 2) {
val = ISP116x_INW (hp->hcport);
buffer [i] = val;
buffer [i+1] = val >> 8;
}
if (length & 1) {
val = ISP116x_INW (hp->hcport);
buffer [length - 1] = val;
}
#ifdef DEBUG1
printk (" READ_REGn16: %d :", length);
for (i = 0; i < length; i++)
printk (" %2x", buffer [i]);
printk("\n");
#endif
}
static inline void WRITE_REG32 (hci_t * hci, unsigned int value, int regindex)
{
hcipriv_t * hp = &hci->hp;
ISP116x_OUTW (regindex | 0x80, hp->hcport2);
ISP116x_OUTW (value, hp->hcport);
ISP116x_OUTW (value >> 16, hp->hcport);
}
static inline void WRITE_REG16 (hci_t * hci, unsigned int value, int regindex)
{
hcipriv_t * hp = &hci->hp;
ISP116x_OUTW (regindex | 0x80, hp->hcport2);
ISP116x_OUTW (value, hp->hcport);
}
static inline void WRITE_REG0 (hci_t * hci, int regindex)
{
hcipriv_t * hp = &hci->hp;
ISP116x_OUTW (regindex | 0x80, hp->hcport2);
}
static inline void WRITE_REGn16 (hci_t * hci, int regindex, int length, __u8 * buffer)
{
hcipriv_t * hp = &hci->hp;
int i;
ISP116x_OUTW (regindex | 0x80, hp->hcport2);
for (i = 0; i < length - 1; i += 2) {
ISP116x_OUTW (buffer [i] + (buffer [i+1] << 8), hp->hcport);
}
if (length & 1) {
ISP116x_OUTW (buffer [length - 1], hp->hcport);
}
#ifdef DEBUG1
printk (" WRITE_REGn16: %d :", length);
for (i = 0; i < length; i++)
printk (" %2x", buffer [i]);
printk("\n");
#endif
}
/*-------------------------------------------------------------------------*/
/* tl functions */
static inline void hc_mark_last_trans (hci_t * hci)
{
hcipriv_t * hp = &hci->hp;
__u8 * ptd = hp->tl;
if (hp->tlp > 0)
*(ptd + hp->tl_last) |= (1 << 3);
}
static inline void hc_flush_data_cache (hci_t * hci, void * data, int len)
{}
static inline int hc_add_trans (hci_t * hci, int len, void * data,
int toggle, int maxps, int slow, int endpoint, int address, int pid, int format)
{
hcipriv_t * hp = &hci->hp;
int last = 0;
__u8 * ptd = hp->tl;
int parts = 2;
/* just send 4 packets of each kind at a frame,
* other URBs also want some bandwitdh, and a NACK is cheaper
* with less packets */
switch (hci->active_urbs) {
case 1: parts = 8; break;
case 2: parts = 6; break;
case 3: parts = 4; break;
case 4: parts = 3; break;
case 5: parts = 2; break;
default: parts = 2;
}
if (len > maxps * parts)
len = maxps * parts;
if (hp->units_left < ((len + 8 + 3) & ~0x3))
return -1;
else
hp->units_left -= (len + 8 + 3) & ~0x3;
ptd += hp->tlp;
hp->tl_last = hp->tlp + 3;
ptd [0] = 0;
ptd [1] = (toggle << 2) | (1 << 3) | (0xf << 4);
ptd [2] = maxps;
ptd [3] = ((maxps >> 8) & 0x3) | (slow << 2) | (last << 3) | (endpoint << 4);
ptd [4] = len;
ptd [5] = ((len >> 8) & 0x3) | (pid << 2);
ptd [6] = address | (format << 7);
ptd [7] = 0;
if (pid != PID_IN && len)
memcpy (ptd + 8, data, len);
hp->tlp += ((len + 8 + 3) & ~0x3);
return len;
}
static inline int hc_parse_trans (hci_t * hci, int * actbytes, void * data,
int * cc, int * toggle, int length)
{
hcipriv_t * hp = &hci->hp;
int last = 0;
int totbytes;
int pid;
__u8 *ptd = hp->tl + hp->tlp;
*cc = (ptd [1] >> 4) & 0xf;
last = (ptd [3] >> 3) & 0x1;
*actbytes = ((ptd [1] & 0x3) << 8) | ptd [0];
totbytes = ((ptd [5] & 0x3) << 8) | ptd [4];
pid = (ptd [5] >> 2) & 0x3;
if (*actbytes > length)
*actbytes = length;
if (pid == PID_IN && *actbytes)
memcpy (data, ptd + 8, *actbytes);
*toggle = (ptd [1] >> 2 & 1);
if (*cc > 0 && *cc < 0xE && *cc != 9)
*toggle = !*toggle;
hp->tlp += ((totbytes + 8 + 3) & ~0x3);
return !last;
}
/*-------------------------------------------------------------------------*/
static void hc_start_int (hci_t * hci)
{
#ifdef HC_SWITCH_INT
int mask = SOFITLInt | ATLInt | OPR_Reg;
WRITE_REG16 (hci, mask, HcuPInterrupt);
WRITE_REG16 (hci, mask, HcuPInterruptEnable);
#endif
}
static void hc_stop_int (hci_t * hci)
{
#ifdef HC_SWITCH_INT
WRITE_REG16 (hci, 0, HcuPInterruptEnable);
#endif
}
/* an interrupt happens */
static void hc_interrupt (int irq, void * __hci, struct pt_regs * r)
{
hci_t * hci = __hci;
hcipriv_t * hp = &hci->hp;
int ints_uP, ints = 0, bstat = 0;
int iso_buffer_index = 0;
hc_isp1161A1.rar_PXA255 USB_arm usb_isp1161_isp1161a_usb IsP
版权申诉
194 浏览量
2022-09-23
23:13:38
上传
评论
收藏 6KB RAR 举报
APei
- 粉丝: 64
- 资源: 1万+
最新资源
- multisim1仿真运放及三极管电路应用经典电路multisim10仿真实例源文件合集(21个).zip
- 基于Android的Fragment+ViewPager实现滑屛切换界面应用设计与实现1(源码)
- tensorflow-2.9.3-cp38-cp38-win-amd64.whl
- tensorflow-gpu-2.9.3-cp38-cp38-win-amd64.whl
- 1716994562763661.750000.jpg
- tensorflow-gpu-2.9.2-cp38-cp38-win-amd64.whl
- FSA-火烈鸟搜索优化算法
- 幸运女生眷顾.html
- 送修改教程.zip
- java-选择排序.rar
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈