[Prism54-devel] prism54 USB devel
Feyd
feyd@seznam.cz
Sat, 3 Apr 2004 11:00:23 +0200
This is a multi-part message in MIME format.
--Multipart=_Sat__3_Apr_2004_11_00_23_+0200_qXiU4ylBeKckvszz
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
On Wed, 31 Mar 2004 15:19:14 -0700 (MST)
Teunis Peters <teunis@ru2shy.net> wrote:
> Well, seeing as there's no such driver yet, I've started working on it.
> I've got the easy stuff done (a module that loads and detects add/remove
> of USB device) but now am working on device communications so any/all
> suggestions would be helpful :)
>
> hardware:
> Linksys WUSB56G
We are workinkg on that with Johannes. You couldnt see that, as the list
was dead for some time :)
Feyd
--Multipart=_Sat__3_Apr_2004_11_00_23_+0200_qXiU4ylBeKckvszz
Content-Type: application/octet-stream;
name="Makefile.k26"
Content-Disposition: attachment;
filename="Makefile.k26"
Content-Transfer-Encoding: base64
IyAkSWQ6IE1ha2VmaWxlLmsyNix2IDEuOCAyMDA0LzAzLzE4IDA1OjI1OjI0IG1jZ3JvZiBFeHAg
JAoKcHJpc201NC1vYmpzIDo9IGlzbHBjaV9ldGgubyBpc2xwY2lfbWd0Lm8gXAogICAgICAgICAg
ICAgICAgaXNsXzM4eHgubyBpc2xfaW9jdGwubyBpc2xwY2lfZGV2Lm8gXAoJCWlzbHBjaV9ob3Rw
bHVnLm8gb2lkX21ndC5vCgpwcmlzbTU0dS1vYmpzIDo9IHVzYl9pbml0Lm8gdXNiX25ldGRldi5v
IHVzYl90cmFuc3BvcnQubwoKb2JqLSQoQ09ORklHX1BSSVNNNTQpICs9IHByaXNtNTR1Lm8KCkVY
VFJBX0NGTEFHUyA9IC1JJChQV0QpIC1Xbm8tdW51c2VkIy1EQ09ORklHX1BSSVNNNTRfV0RTCgo=
--Multipart=_Sat__3_Apr_2004_11_00_23_+0200_qXiU4ylBeKckvszz
Content-Type: text/x-chdr;
name="prism54_usb.h"
Content-Disposition: attachment;
filename="prism54_usb.h"
Content-Transfer-Encoding: 7bit
/*
* Prism54 USB driver
T: Bus=01 Lev=01 Prnt=01 Port=03 Cnt=01 Dev#= 2 Spd=480 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=5041 ProdID=2234 Rev= 2.02
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA
I: If#= 0 Alt= 0 #EPs=11 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=8d(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=0d(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=8e(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=0e(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=8f(I) Atr=03(Int.) MxPS= 4 Ivl=125us
*/
//#undef CONFIG_USB_DEBUG
//#define CONFIG_USB_DEBUG y
#ifdef CONFIG_USB_DEBUG
#define p54u_dbg(format, arg...) if(debug > 1) printk(format "\n" ,##arg)
#else
#define p54u_dbg(format, arg...)
#endif
#define p54u_info(format, arg...) if(debug) printk(KERN_INFO __FILE__ ": " format "\n" , ##arg)
#define p54u_warn(format, arg...) printk(KERN_WARN __FILE__ ": " format "\n" , ##arg)
#define p54u_err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" ,##arg)
//#define p54u_time(arg...) 0LL
#define p54u_time(arg...) (get_jiffies_64(##arg) - p54u->time)
#define P54U_TX_TIMEOUT (2*HZ)
#define P54U_REG_WSIZE (sizeof(struct p54u_reg))
#define P54U_REG_RSIZE (P54U_REG_WSIZE - (sizeof(u32)))
#define P54U_PORT_BRG 0x0010
#define P54U_PORT_BRG_CFG 0x0000
#define P54U_PORT_DEV 0x0800
#define P54U_PORT_DEV_CFG 0x0880
#define P54U_PORT_U16 0x0003
#define P54U_PORT_U32 0x000f
#define P54U_PORT_BRG_U32 (P54U_PORT_BRG | P54U_PORT_U32)
#define P54U_PORT_BRG_CFG_U32 (P54U_PORT_BRG_CFG | P54U_PORT_U32)
#define P54U_PORT_BRG_CFG_U16 (P54U_PORT_BRG_CFG | P54U_PORT_U16)
#define P54U_PORT_DEV_U32 (P54U_PORT_DEV | P54U_PORT_U32)
#define P54U_PORT_DEV_CFG_U32 (P54U_PORT_DEV_CFG | P54U_PORT_U32)
#define P54U_PORT_DEV_CFG_U16 (P54U_PORT_DEV_CFG | P54U_PORT_U16)
#define P54U_BRG_BASE 0x10000000
#define P54U_BRG_BASE_2 0x20000000
#define P54U_BRG_POWER_UP 0x01
#define P54U_BRG_POWER_DOWN 0x02
#define P54U_BRG_CTRL_REG 0x50
#define P54U_BRG_REV_REG 0x88
#define P54U_DEV_BASE 0x40000000
#define P54U_TRDY_TIMEOUT 0x40
#define P54U_RETRY_TIMEOUTG 0x41
#define P54U_IMAGE_FILE "isl3890"
//#define P54U_MAX_FRAME_SIZE 16384
#define P54U_MAX_FRAME_SIZE 2048
//#define P54U_QUEUE_LEN 16
#define P54U_QUEUE_LEN 2
#define P54U_FW_BLOCK 512
#define P54U_INIT_BLOCK 0x03fc
#define p54u_brg_writel(dev, addr, val) p54u_reg_rw(dev, 1, P54U_PIPE_BRG, P54U_PORT_BRG_U32, addr, val)
#define p54u_pcicfg_brg_writel(dev, addr, val) p54u_reg_rw(dev, 1, P54U_PIPE_BRG, P54U_PORT_BRG_CFG_U32, addr, val)
#define p54u_pcicfg_brg_writew(dev, addr, val) p54u_reg_rw(dev, 1, P54U_PIPE_BRG, P54U_PORT_BRG_CFG_U16, addr, (val & 0xffff))
#define p54u_dev_writel(dev, reg, val) p54u_reg_rw(dev, 1, P54U_PIPE_DEV, P54U_PORT_DEV_U32, (P54U_DEV_BASE | reg), val)
#define p54u_pcicfg_dev_writel(dev, addr, val) p54u_reg_rw(dev, 1, P54U_PIPE_DEV, P54U_PORT_DEV_CFG_U32, addr, val)
#define p54u_pcicfg_dev_writew(dev, addr, val) p54u_reg_rw(dev, 1, P54U_PIPE_DEV, P54U_PORT_DEV_CFG_U16, addr, (val & 0xffff))
#define p54u_brg_readl(dev, addr) p54u_reg_rw(dev, 0, P54U_PIPE_BRG, P54U_PORT_BRG_U32, addr, 0)
#define p54u_pcicfg_brg_readl(dev, addr) p54u_reg_rw(dev, 0, P54U_PIPE_BRG, P54U_PORT_BRG_CFG_U32, addr, 0)
#define p54u_pcicfg_brg_readw(dev, addr) (p54u_reg_rw(dev, 0, P54U_PIPE_BRG, P54U_PORT_BRG_CFG_U16, addr, 0) & 0xffff)
#define p54u_dev_readl(dev, reg) p54u_reg_rw(dev, 0, P54U_PIPE_DEV, P54U_PORT_DEV_U32, (P54U_DEV_BASE | reg), 0)
#define p54u_pcicfg_dev_readl(dev, addr) p54u_reg_rw(dev, 0, P54U_PIPE_DEV, P54U_PORT_DEV_CFG_U32, addr, 0)
#define p54u_pcicfg_dev_readw(dev, addr) (p54u_reg_rw(dev, 0, P54U_PIPE_DEV, P54U_PORT_DEV_CFG_U16, addr, 0) & 0xffff)
enum p54u_pipe_addr {
P54U_PIPE_DATA = 0x01,
P54U_PIPE_MGMT = 0x02,
P54U_PIPE_3 = 0x03,
P54U_PIPE_4 = 0x04,
P54U_PIPE_BRG = 0x0d,
P54U_PIPE_DEV = 0x0e,
P54U_PIPE_INT = 0x0f,
};
enum p54u_pipe_index {
P54U_TX_DATA,
P54U_TX_MGMT,
P54U_TX_BRG,
P54U_TX_DEV,
P54U_RX_DATA,
P54U_RX_MGMT,
P54U_RX_3,
P54U_RX_4,
P54U_RX_BRG,
P54U_RX_DEV,
P54U_RX_INT,
P54U_PIPES,
};
struct p54u_reg {
u16 port;
u32 addr;
u32 val;
} __attribute__ ((packed));
struct p54u_mgmt_tx {
u32 magic1;
u32 magic2;
u32 magic3;
u16 pos;
u16 len;
} __attribute__ ((packed));
struct p54u_mgmt_rx {
u16 len;
u16 pos;
u32 magic1;
u32 magic2;
u32 magic3;
struct p54u_mgmt_tx id;
} __attribute__ ((packed));
struct p54u_pipe_desc {
u8 addr; /* the address of the endpoint */
u8 type; /* the transfer type of the endpoint */
size_t p_size; /* the size of the packet */
void (*callback)(struct urb *urb, struct pt_regs *regs);
};
struct p54u_pipe {
struct urb **urb; /* the urb used to send data */
void **buf; /* the buffer */
size_t *size; /* the size of the buffer */
int len; /* the length of the ringbufer */
int head;
int tail;
atomic_t busy; /* true if urb is busy */
wait_queue_head_t wqh;
struct completion comp; /* wait for the operation to finish */
int done;
u8 addr; /* the address of the endpoint */
u8 type; /* the transfer type of the endpoint */
size_t pkt_size; /* the size of the packet */
};
/* Structure to hold all of our device specific stuff */
struct p54u {
struct usb_device *usbdev; /* save off the usb device pointer */
struct usb_interface *interface; /* save off the usb device pointer */
struct net_device *netdev;
int running;
int err;
struct workqueue_struct *queue;
struct work *boot;
struct completion *comp;
struct p54u_pipe data_tx;
struct p54u_pipe data_rx;
struct p54u_pipe mgmt_tx;
struct p54u_pipe mgmt_rx;
struct p54u_pipe int_rx;
struct semaphore disconnect_sem; /* prevent races between open() and disconnect() */
const struct firmware *fw_entry;
u64 time;
};
extern int load_fw;
extern int debug;
extern const char dummy_mac[ETH_ALEN];
int p54u_setup_net(struct net_device *netdev);
int p54u_boot(struct net_device *netdev);
int p54u_shutdown(struct net_device *netdev);
void p54u_mdelay(int ms);
u32 p54u_reg_rw(struct net_device *netdev, int write, int ep, int port, u32 addr, u32 val);
u32 p54u_readi(struct net_device *netdev);
void p54u_int_rx_cb(struct urb *urb, struct pt_regs *p);
void p54u_data_rx_cb(struct urb *urb, struct pt_regs *p);
void p54u_mgmt_rx_cb(struct urb *urb, struct pt_regs *p);
u32 p54u_wait_int(struct net_device *netdev);
int p54u_bulk_msg(struct net_device *netdev, unsigned int ep, void *data, int len);
--Multipart=_Sat__3_Apr_2004_11_00_23_+0200_qXiU4ylBeKckvszz
Content-Type: text/x-csrc;
name="usb_init.c"
Content-Disposition: attachment;
filename="usb_init.c"
Content-Transfer-Encoding: 7bit
/*
* Prism54 USB driver
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/usb.h>
#include <linux/pci.h>
#include <linux/firmware.h>
#include <asm/uaccess.h>
#include "prism54_usb.h"
#include "isl_38xx.h"
#ifdef CONFIG_USB_DEBUG
int debug = 2;
#else
int debug;
#endif
int load_fw;
static const char driver_name[] = "prism54_usb";
static const struct usb_device_id p54u_table[] = {
{USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */
{}
};
static const struct p54u_pipe_desc p54u_pipes[] = {
{ P54U_PIPE_DATA, USB_ENDPOINT_XFER_BULK },
{ P54U_PIPE_MGMT, USB_ENDPOINT_XFER_BULK },
{ P54U_PIPE_BRG, USB_ENDPOINT_XFER_BULK },
{ P54U_PIPE_DEV, USB_ENDPOINT_XFER_BULK },
{ P54U_PIPE_DATA | USB_DIR_IN, USB_ENDPOINT_XFER_BULK },
{ P54U_PIPE_MGMT | USB_DIR_IN, USB_ENDPOINT_XFER_BULK },
{ P54U_PIPE_3 | USB_DIR_IN, USB_ENDPOINT_XFER_BULK },
{ P54U_PIPE_4 | USB_DIR_IN, USB_ENDPOINT_XFER_BULK },
{ P54U_PIPE_BRG | USB_DIR_IN, USB_ENDPOINT_XFER_BULK },
{ P54U_PIPE_DEV | USB_DIR_IN, USB_ENDPOINT_XFER_BULK },
{ P54U_PIPE_INT | USB_DIR_IN, USB_ENDPOINT_XFER_INT },
};
static const char p54u_mgmt_0c[16] = {
0x6c, 0x06, 0x02, 0x00, 0x0c, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const char p54u_mgmt_30[16] = {
0x6c, 0x06, 0x02, 0x00, 0x30, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
MODULE_DESCRIPTION("Prism54 USB Driver");
MODULE_AUTHOR("Feyd <feyd@seznam.cz>");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(usb, p54u_table);
MODULE_PARM(debug, "i");
MODULE_PARM(load_fw, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
MODULE_PARM_DESC(load_fw, "Load firmware on probe (1) or open (0)");
static int p54u_reset_usb(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
int err;
// return 0;
p54u_info("%s: Reset USB device.\n", netdev->name);
err = usb_reset_device(usbdev);
if(err) {
p54u_err("%s: Reset USB device failed.\n", netdev->name);
return err;
}
// p54u_mdelay(200);
p54u_info("%s: Reset USB device done.\n", netdev->name);
return 0;
}
static void p54u_free_pipe(struct net_device *netdev, struct p54u_pipe *pipe)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
int i;
p54u_info("Freeing pipe.\n");
if(!pipe->buf) {
p54u_info("pipe->buf == NULL\n");
goto do_free_urb;
}
if(!pipe->urb) {
p54u_info("pipe->urb == NULL\n");
goto do_free_size;
}
if(!pipe->size) {
p54u_info("pipe->size == NULL\n");
goto do_clear;
}
for(i = 0; i < pipe->len; i++) {
if(pipe->urb[i]) {
/* FIXME: unlink the busy one */
if(pipe->buf[i]) {
usb_buffer_free(usbdev, pipe->size[i], pipe->buf[i], pipe->urb[i]->transfer_dma);
} else {
p54u_info("pipe->buf[%i] == NULL\n", i);
}
usb_free_urb(pipe->urb[i]);
} else {
p54u_info("pipe->urb[%i] == NULL\n", i);
}
}
kfree(pipe->buf);
do_free_urb:
if(pipe->urb) {
kfree(pipe->urb);
} else {
p54u_info("pipe->urb == NULL\n");
}
do_free_size:
if(pipe->size) {
kfree(pipe->size);
} else {
p54u_info("pipe->size == NULL\n");
}
do_clear:
p54u_info("Clear the memory.\n");
memset(pipe, 0, sizeof(*pipe));
p54u_info("Freeing pipe done.\n");
return;
}
static void p54u_free_buffers(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
p54u_free_pipe(netdev, &p54u->data_tx);
p54u_free_pipe(netdev, &p54u->data_rx);
p54u_free_pipe(netdev, &p54u->mgmt_tx);
p54u_free_pipe(netdev, &p54u->mgmt_rx);
p54u_free_pipe(netdev, &p54u->int_rx);
return;
}
static int p54u_alloc_pipe(struct net_device *netdev, struct usb_endpoint_descriptor *desc, struct p54u_pipe *pipe, usb_complete_t callback)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
int err, i, p, e;
if(!pipe)
return 0;
p54u_info("%s: Allocate pipe %02x.\n", netdev->name, desc->bEndpointAddress);
pipe->pkt_size = desc->wMaxPacketSize;
pipe->type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
pipe->addr = desc->bEndpointAddress;
pipe->len = P54U_QUEUE_LEN;
pipe->size = kmalloc(sizeof(*pipe->size) * pipe->len, GFP_KERNEL);
if(!pipe->size) {
p54u_info("Failed to allocate pipe->size\n");
goto do_enomem;
} else {
p54u_info("pipe->size == %p\n", pipe->size);
}
memset(pipe->size, 0, sizeof(*pipe->size) * pipe->len);
pipe->urb = kmalloc(sizeof(*pipe->urb) * pipe->len, GFP_KERNEL);
if(!pipe->urb) {
p54u_info("Failed to allocate pipe->urb\n");
goto do_enomem;
} else {
p54u_info("pipe->urb == %p\n", pipe->urb);
}
memset(pipe->urb, 0, sizeof(*pipe->urb) * pipe->len);
pipe->buf = kmalloc(sizeof(*pipe->buf) * pipe->len, GFP_KERNEL);
if(!pipe->buf) {
p54u_info("Failed to allocate pipe->buf\n");
goto do_enomem;
} else {
p54u_info("pipe->buf == %p\n", pipe->buf);
}
memset(pipe->buf, 0, sizeof(*pipe->buf) * pipe->len);
p54u_info("%s: Allocate buffers.\n", netdev->name);
for(i = 0; i < pipe->len; i++) {
pipe->size[i] = P54U_MAX_FRAME_SIZE;
if(pipe->type == USB_ENDPOINT_XFER_INT) {
pipe->size[i] = 4;
}
p54u_info("pipe->size [%i] = %i\n", i, pipe->size[i]);
pipe->urb[i] = usb_alloc_urb(0, GFP_KERNEL);
if(!pipe->urb[i]) {
p54u_info("Failed to allocate pipe->urb[%i]\n", i);
goto do_enomem;
} else {
p54u_info("pipe->urb[%i] == %p\n", i, pipe->urb[i]);
}
pipe->urb[i]->transfer_flags = (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
pipe->buf[i] = usb_buffer_alloc(usbdev, pipe->size[i], GFP_KERNEL, &pipe->urb[i]->transfer_dma);
if(!pipe->buf[i]) {
p54u_info("Failed to allocate pipe->buf[%i]\n", i);
goto do_enomem;
} else {
p54u_info("pipe->buf[%i] == %p\n", i, pipe->buf[i]);
}
e = pipe->addr & USB_ENDPOINT_NUMBER_MASK;
p54u_info("pipe->addr = %i\n", e);
// e = pipe->addr;
switch(pipe->type) {
case USB_ENDPOINT_XFER_BULK:
p = pipe->addr & USB_DIR_IN ? usb_rcvbulkpipe(usbdev, e) : usb_sndbulkpipe(usbdev, e);
usb_fill_bulk_urb(pipe->urb[i], usbdev, p, pipe->buf[i], pipe->size[i], callback, netdev);
case USB_ENDPOINT_XFER_INT:
p = usb_rcvintpipe(usbdev, e);
usb_fill_int_urb(pipe->urb[i], usbdev, p, pipe->buf[i], pipe->size[i], callback, netdev, 10);
// usb_fill_int_urb(pipe->urb[i], usbdev, p, pipe->buf[i], pipe->size[i], callback, netdev, HZ / 4);
// p = pipe->addr & USB_DIR_IN ? usb_rcvbulkpipe(usbdev, e) : usb_sndbulkpipe(usbdev, e);
// usb_fill_bulk_urb(pipe->urb[i], usbdev, p, pipe->buf[i], pipe->size[i], callback, netdev);
}
init_completion(&pipe->comp);
}
p54u_info("%s: Allocate pipe done.\n", netdev->name);
return 0;
do_enomem:
p54u_info("%s: Not enough memory.\n", netdev->name);
err = -ENOMEM;
do_err:
p54u_info("%s: Allocate pipe failed.\n", netdev->name);
return err;
}
static int p54u_alloc_buffers(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
struct usb_interface *interface = p54u->interface;
struct usb_host_interface *iface_desc = &interface->altsetting[0];
struct usb_endpoint_descriptor *desc;
struct p54u_pipe *pipe;
int err = 0, i;
p54u_info("%s: Setup USB structures.\n", netdev->name);
for(i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
desc = &iface_desc->endpoint[i].desc;
switch(desc->bEndpointAddress) {
case P54U_PIPE_DATA:
err = p54u_alloc_pipe(netdev, desc, &p54u->data_tx, NULL);
break;
case P54U_PIPE_MGMT:
err = p54u_alloc_pipe(netdev, desc, &p54u->mgmt_tx, NULL);
break;
case P54U_PIPE_DATA | USB_DIR_IN:
err = p54u_alloc_pipe(netdev, desc, &p54u->data_rx, p54u_data_rx_cb);
break;
case P54U_PIPE_MGMT | USB_DIR_IN:
err = p54u_alloc_pipe(netdev, desc, &p54u->mgmt_rx, p54u_mgmt_rx_cb);
break;
case P54U_PIPE_INT | USB_DIR_IN:
err = p54u_alloc_pipe(netdev, desc , &p54u->int_rx, p54u_int_rx_cb);
break;
default:
break;
}
if(err)
goto do_err;
}
p54u_info("%s: Setup USB structures successful.\n", netdev->name);
return 0;
do_err:
p54u_info("%s: Setup USB structures failed: %i\n", netdev->name, err);
p54u_free_buffers(netdev);
return err;
}
static int p54u_reset_dev(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
u32 reg, revision;
int err;
p54u_info("%s: Reset device.\n", netdev->name);
/* Bridge */
/* Reset the usb<->pci bridge */
p54u_dbg("%s: Reset bridge\n", netdev->name);
reg = p54u_brg_readl(netdev, P54U_BRG_CTRL_REG);
//reg = 0x3e;
p54u_brg_writel(netdev, P54U_BRG_CTRL_REG, (reg | P54U_BRG_POWER_DOWN) & ~P54U_BRG_POWER_UP);
if(p54u->err)
goto do_err;
p54u_mdelay(100);
p54u_brg_writel(netdev, P54U_BRG_CTRL_REG, (reg | P54U_BRG_POWER_UP) & ~P54U_BRG_POWER_DOWN);
if(p54u->err)
goto do_err;
p54u_dbg("%s: Reset bridge done\n", netdev->name);
p54u_mdelay(100);
/* Magic */
p54u_dbg("%s: Magic 1\n", netdev->name);
p54u_brg_writel(netdev, 0, 0x0224);
if(p54u->err)
goto do_err;
p54u_dbg("%s: Magic 1 done\n", netdev->name);
p54u_mdelay(20);
/* Enable mmio and busmaster on the bridge */
p54u_dbg("%s: Setup bridge pci resources\n", netdev->name);
p54u_pcicfg_brg_writew(netdev, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER));
/* Set base address 0 */
p54u_pcicfg_brg_writel(netdev, PCI_BASE_ADDRESS_0, P54U_BRG_BASE);
/* Set PCI_STATUS_REC_MASTER_ABORT) (why?) */
reg = p54u_pcicfg_brg_readw(netdev, PCI_STATUS);
p54u_pcicfg_brg_writew(netdev, PCI_STATUS, (reg | PCI_STATUS_REC_MASTER_ABORT));
/* Read revision? */
revision = p54u_brg_readl(netdev, P54U_BRG_REV_REG);
p54u_dbg("%s: Setup bridge pci resources done\n", netdev->name);
/* Magic */
p54u_dbg("%s: Magic 2\n", netdev->name);
p54u_brg_writel(netdev, 0x0324, 0x04);
p54u_brg_writel(netdev, 0x0364, 0x04);
p54u_dbg("%s: Magic 2 done\n", netdev->name);
/* Set base address 2 */
p54u_dbg("%s: Setup bridge base addr 2\n", netdev->name);
p54u_pcicfg_brg_writel(netdev, PCI_BASE_ADDRESS_2, P54U_BRG_BASE_2);
p54u_dbg("%s: Setup bridge base addr 2 done\n", netdev->name);
/* Device */
/* Enable mmio and busmaster on the device */
p54u_dbg("%s: Setup device pci resources\n", netdev->name);
p54u_pcicfg_dev_writew(netdev, PCI_COMMAND | 0x10000, (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER));
/* Set TRDY_TIMEOUT and RETRY_TIMEOUT to 0 */
p54u_pcicfg_dev_writew(netdev, P54U_TRDY_TIMEOUT | 0x10000, 0);
/* Set base address 0 */
p54u_pcicfg_dev_writel(netdev, PCI_BASE_ADDRESS_0 | 0x10000, P54U_DEV_BASE);
p54u_dbg("%s: Setup device pci resources done\n", netdev->name);
/* Magic */
p54u_dbg("%s: Magic 3\n", netdev->name);
p54u_brg_writel(netdev, 0x24, 0);
p54u_brg_writel(netdev, 0x2c, 0x01000000);
p54u_dbg("%s: Magic 3 done\n", netdev->name);
/* Assert wakeup */
p54u_dbg("%s: Assert device\n", netdev->name);
p54u_dev_writel(netdev, ISL38XX_DEV_INT_REG, ISL38XX_DEV_INT_WAKEUP);
if(p54u->err)
goto do_err;
p54u_mdelay(20);
/* Assert something unknown */
p54u_dev_writel(netdev, ISL38XX_DEV_INT_REG, 0x20);
if(p54u->err)
goto do_err;
p54u_dbg("%s: Assert device done\n", netdev->name);
p54u_mdelay(20);
/* Reset the device */
p54u_dbg("%s: Reset device\n", netdev->name);
reg = p54u_dev_readl(netdev, ISL38XX_CTRL_STAT_REG);
reg &= ~(ISL38XX_CTRL_STAT_RESET | ISL38XX_CTRL_STAT_RAMBOOT | ISL38XX_CTRL_STAT_CLKRUN);
p54u_dev_writel(netdev, ISL38XX_CTRL_STAT_REG, reg);
p54u_dev_writel(netdev, ISL38XX_CTRL_STAT_REG, reg | ISL38XX_CTRL_STAT_RESET);
p54u_dev_writel(netdev, ISL38XX_CTRL_STAT_REG, reg);
if(p54u->err)
goto do_err;
p54u_dbg("%s: Reset device done\n", netdev->name);
p54u_mdelay(100);
p54u_dbg("%s: Disable irq\n", netdev->name);
p54u_dev_writel(netdev, ISL38XX_INT_EN_REG, 0);
p54u_dbg("%s: Disable irq done\n", netdev->name);
/* Ack the irqs */
p54u_dbg("%s: Ack irq\n", netdev->name);
reg = p54u_dev_readl(netdev, ISL38XX_INT_IDENT_REG);
p54u_dev_writel(netdev, ISL38XX_INT_ACK_REG, reg);
if(p54u->err)
goto do_err;
p54u_dbg("%s: Ack done\n", netdev->name);
p54u_info("%s: Reset device done.\n", netdev->name);
return 0;
do_err:
p54u_err("%s: Reset error: %i\n", netdev->name, p54u->err);
err = p54u->err;
p54u->err = 0;
return err;
}
static int p54u_load_firmware(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
unsigned int pipe;
u32 reg;
void *data;
size_t len;
int err, i, j, k, l;
u64 t, t1, t2;
char *rcv;
p54u_info("%s: Load firmware.\n", netdev->name);
/* Firmware */
/* Magic */
p54u_dbg("%s: Magic 4\n", netdev->name);
p54u_brg_writel(netdev, 0x032c, P54U_FW_BLOCK);
p54u_brg_writel(netdev, 0x034c, P54U_FW_BLOCK);
p54u_brg_writel(netdev, 0x036c, P54U_FW_BLOCK);
p54u_brg_writel(netdev, 0x038c, P54U_FW_BLOCK);
p54u_brg_writel(netdev, 0x032c, P54U_FW_BLOCK);
p54u_dbg("%s: Magic 4 done\n", netdev->name);
pipe = usb_sndbulkpipe(usbdev, P54U_PIPE_DATA);
data = p54u->fw_entry->data;
i = p54u->fw_entry->size;
j = 0;
while(i > 0) {
len = i > P54U_FW_BLOCK ? P54U_FW_BLOCK : i;
t1 = p54u_time();
p54u->err = usb_bulk_msg(usbdev, pipe, data, len, &len, HZ);
t2 = p54u_time();
t = t2 - t1;
for(k = 0; k < len; k+= 16) {
if(k == 0) {
printk(KERN_CRIT "[OUT >%-6lld<%-6lld+%-6lld]\t%02x -> 00000000:", t1, t2, t, P54U_PIPE_DATA);
//printk(KERN_CRIT "%02x -> %08x:", P54U_PIPE_DATA, k);
} else {
printk(KERN_CRIT "\t\t\t\t -> %08x:", k);
}
for (l = 0; (l < 16) && (k + l < len); ++l) {
printk(" %02x", ((unsigned char *)data)[k + l]);
}
printk("\n");
}
if(p54u->err) {
p54u_dbg("%s: Error writing firmware block: writen %i of %i.\n", netdev->name, j, p54u->fw_entry->size);
goto do_release;
}
data += P54U_FW_BLOCK;
i -= P54U_FW_BLOCK;
/* Magic */
p54u_dev_writel(netdev, ISL38XX_DIR_MEM_BASE_REG, 0xc0000f00);
p54u_dev_writel(netdev, 0x1020, 0);
p54u_dev_writel(netdev, 0x1020, 1);
p54u_dev_writel(netdev, 0x1024, len);
p54u_dev_writel(netdev, 0x1028, j | 0x00020000);
p54u_dev_writel(netdev, 0x0060, 0x20000000);
p54u_dev_writel(netdev, 0x0064, i > 0 ? 0x80 : 0x2e);
p54u_dev_writel(netdev, 0x0068, 4);
reg = p54u_dev_readl(netdev, 0x102c);
if(i > 0)
p54u_brg_writel(netdev, 0x032c, P54U_FW_BLOCK);
if(p54u->err) {
p54u_dbg("%s: Error updating registers: writen %i of %i.\n", netdev->name, j, p54u->fw_entry->size);
goto do_release;
}
j += P54U_FW_BLOCK;
}
p54u_info("%s: Load firmware done.\n", netdev->name);
return 0;
do_release:
do_err:
p54u_err("%s: Load error: %i\n", netdev->name, p54u->err);
err = p54u->err;
p54u->err = 0;
return err;
}
int p54u_setup_dev(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
struct p54u_mgmt_tx *tx1, *tx2;
u32 reg;
int i, j, k;
reg = p54u_dev_readl(netdev, ISL38XX_CTRL_STAT_REG);
p54u_dev_writel(netdev, ISL38XX_CTRL_STAT_REG, reg | ISL38XX_CTRL_STAT_RAMBOOT);
p54u_dev_writel(netdev, ISL38XX_CTRL_STAT_REG, reg | ISL38XX_CTRL_STAT_RAMBOOT | ISL38XX_CTRL_STAT_RESET);
p54u_dev_writel(netdev, ISL38XX_CTRL_STAT_REG, reg | ISL38XX_CTRL_STAT_RAMBOOT);
if(p54u->err) {
p54u_dbg("%s: Error latching reset: %i\n", netdev->name, p54u->err);
}
p54u->err = usb_submit_urb(p54u->int_rx.urb[0], GFP_KERNEL);
if(p54u->err) {
p54u_dbg("%s: Error submit int 0: %i\n", netdev->name, p54u->err);
} else {
p54u_dbg("%s: Submit int 0 ok.\n", netdev->name);
}
p54u->err = usb_submit_urb(p54u->data_rx.urb[0], GFP_KERNEL);
if(p54u->err) {
p54u_dbg("%s: Error submit data: %i\n", netdev->name, p54u->err);
} else {
p54u_dbg("%s: Submit data ok.\n", netdev->name);
}
p54u->err = usb_submit_urb(p54u->mgmt_rx.urb[0], GFP_KERNEL);
if(p54u->err) {
p54u_dbg("%s: Error submit mgmt: %i\n", netdev->name, p54u->err);
} else {
p54u_dbg("%s: Submit mgmt ok.\n", netdev->name);
}
p54u_dev_writel(netdev, ISL38XX_INT_EN_REG, 0xffffffff);
p54u_brg_writel(netdev, 0x2c, 0x01000000);
p54u_brg_writel(netdev, 0x24, 0x81000000);
p54u_dev_writel(netdev, ISL38XX_DEV_INT_REG, ISL38XX_DEV_INT_RESET);
while(p54u_wait_int(netdev)) {
p54u_dev_writel(netdev, ISL38XX_INT_EN_REG, 0xffffffff);
p54u_brg_writel(netdev, 0x2c, 0x01000000);
}
// p54u_dev_writel(netdev, ISL38XX_INT_EN_REG, 0x00004004);
p54u_dev_writel(netdev, ISL38XX_INT_EN_REG, 0xffffffff);
p54u_brg_writel(netdev, 0x2c, 0x01000000);
/* Send the initial data to 0x02 pipe */
memset(p54u->mgmt_tx.buf[0], 0, p54u->mgmt_tx.size[0]);
memset(p54u->mgmt_tx.buf[1], 0, p54u->mgmt_tx.size[1]);
tx1 = p54u->mgmt_tx.buf[0];
tx2 = p54u->mgmt_tx.buf[1];
tx1->magic1 = 0x0002066c;
tx1->magic2 = 0x0002040c;
tx1->magic3 = 0;
tx1->pos = 0;
tx1->len = 0;
tx2->magic1 = 0x04008000;
tx2->magic2 = 0x813376b0;
tx2->magic3 = 0x0000000c;
tx2->pos = 0;
tx2->len = P54U_INIT_BLOCK;
for(i = 0; i < 1; i++) {
p54u_bulk_msg(netdev, P54U_PIPE_MGMT, tx1, 16);
p54u_dev_writel(netdev, ISL38XX_DEV_INT_REG, 0x80);
p54u_bulk_msg(netdev, P54U_PIPE_MGMT, tx2, P54U_INIT_BLOCK + 16);
// p54u_bulk_msg(netdev, P54U_PIPE_MGMT, tx2, 512);
tx2->pos += P54U_INIT_BLOCK;
p54u_mdelay(200);
}
return p54u->err;
}
int p54u_boot(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
int err;
p54u_info("%s: Boot the device.\n", netdev->name);
p54u_dbg("%s: Request firmware.\n", netdev->name);
err = request_firmware(&p54u->fw_entry, P54U_IMAGE_FILE, netdev->class_dev.dev);
if(err) {
p54u_err("%s: Request firmware failed: %i\n", netdev->name, err);
return err;
}
p54u_dbg("%s: Request firmware done: len = %i.\n", netdev->name, p54u->fw_entry->size);
p54u->time = get_jiffies_64();
err = p54u_reset_usb(netdev);
if(!err)
err = p54u_alloc_buffers(netdev);
if(!err)
err = p54u_reset_dev(netdev);
if(!err)
err = p54u_load_firmware(netdev);
if(!err)
err = p54u_setup_dev(netdev);
release_firmware(p54u->fw_entry);
memcpy(netdev->dev_addr, dummy_mac, ETH_ALEN);
p54u->running = 1;
if(err) {
p54u_err("%s: Boot the device failed: %i\n", netdev->name, err);
return err;
}
p54u_info("%s: Boot the device done.\n", netdev->name);
return 0;
}
int p54u_shutdown(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
u32 reg;
p54u_dbg("%s: Shutting down the device.\n", netdev->name);
p54u_free_buffers(netdev);
// reg = p54u_brg_readl(netdev, P54U_BRG_CTRL_REG);
// p54u_brg_writel(netdev, P54U_BRG_CTRL_REG, (reg | P54U_BRG_POWER_DOWN) & ~P54U_BRG_POWER_UP);
// p54u_brg_writel(netdev, P54U_BRG_CTRL_REG, 0x3e);
p54u->running = 0;
p54u_dbg("%s: Shutdown complete.\n", netdev->name);
return 0;
}
static int p54u_validate_device(struct usb_interface *interface, const struct usb_device_id *id)
{
/* See if the device offered us matches what we can accept */
return 0;
}
static int p54u_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_device *usbdev = interface_to_usbdev(interface);
struct net_device *netdev;
struct p54u *p54u;
p54u_dbg("Prism54 USB Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x", usbdev->devnum, (int) usbdev->descriptor.idVendor, (int) usbdev->descriptor.idProduct, (int) usbdev->descriptor.bcdDevice);
p54u_dbg("Device at %p", usbdev);
p54u_dbg("Descriptor length: %x type: %x", (int) usbdev->descriptor.bLength, (int) usbdev->descriptor.bDescriptorType);
if(p54u_validate_device(interface, id))
return -ENODEV;
netdev = alloc_etherdev(sizeof(*p54u));
if (!netdev) {
p54u_err("Failed to allocate netdevice.");
return -ENOMEM;
}
SET_MODULE_OWNER(netdev);
SET_NETDEV_DEV(netdev, &interface->dev);
usb_set_intfdata(interface, netdev);
p54u = netdev_priv(netdev);
p54u->interface = interface;
p54u->usbdev = usbdev;
p54u->netdev = netdev;
init_MUTEX (&p54u->disconnect_sem);
memcpy(netdev->dev_addr, dummy_mac, ETH_ALEN);
if(load_fw)
/* Dont error if it fails, give it chance on open. */
p54u_boot(netdev);
if(p54u_setup_net(netdev)) {
p54u_err("Failed to setup netdevice.");
goto do_cleanup;
}
if(register_netdev(netdev)) {
p54u_err("Failed to register netdevice.");
goto do_cleanup;
}
p54u_info("Prism54 USB device now attached to %s", netdev->name);
return 0;
do_cleanup:
p54u_free_buffers(netdev);
usb_set_intfdata(interface, NULL);
free_netdev(netdev);
return -EIO;
}
static void p54u_disconnect(struct usb_interface *interface)
{
struct net_device *netdev = usb_get_intfdata(interface);
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
p54u_info("Prism54 USB device %s disconnecing\n", netdev->name);
p54u_dbg("sem down\n");
down(&p54u->disconnect_sem);
p54u_dbg("sem down done\n");
p54u->running = 0;
p54u_dbg("Running = 0.\n");
usb_set_intfdata(interface, NULL);
p54u_dbg("Cleared interface data.\n");
unregister_netdev(netdev);
p54u_dbg("Unregistered netdevice.\n");
p54u_free_buffers(netdev);
p54u_dbg("Freed buffers.\n");
free_netdev(netdev);
p54u_dbg("Freed netdevice.\n");
p54u_info("Disconnect complete.\n");
p54u_dbg("sem up\n");
up(&p54u->disconnect_sem);
p54u_dbg("sem up done\n");
}
static struct usb_driver p54u_driver = {
.owner = THIS_MODULE,
.name = driver_name,
.probe = p54u_probe,
.disconnect = p54u_disconnect,
.id_table = p54u_table,
};
static int __init p54u_init(void)
{
int result;
/* register this driver with the USB subsystem */
result = usb_register(&p54u_driver);
if (result) {
p54u_err("usb_register failed. Error number %d", result);
return result;
}
return 0;
}
static void __exit p54u_exit(void)
{
/* deregister this driver with the USB subsystem */
usb_deregister(&p54u_driver);
}
module_init(p54u_init);
module_exit(p54u_exit);
--Multipart=_Sat__3_Apr_2004_11_00_23_+0200_qXiU4ylBeKckvszz
Content-Type: text/x-csrc;
name="usb_netdev.c"
Content-Disposition: attachment;
filename="usb_netdev.c"
Content-Transfer-Encoding: 7bit
/*
* Prism54 USB driver
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
#include "prism54_usb.h"
#include "isl_38xx.h"
const char dummy_mac[ETH_ALEN] = {0x00, 0x3d, 0xb4, 0x00, 0x00, 0x00};
static int p54u_open(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
p54u_info("sem down\n");
down (&p54u->disconnect_sem);
p54u_info("sem down done\n");
if(!p54u->running && p54u_boot(netdev)) {
p54u_err("Failed to boot device.\n");
goto do_err;
}
netif_start_queue(netdev);
p54u_info("sem up\n");
up(&p54u->disconnect_sem);
p54u_info("sem up done\n");
return 0;
do_err:
p54u_err("Failed to open device.\n");
p54u_info("sem up\n");
up(&p54u->disconnect_sem);
p54u_info("sem up done\n");
return -EIO;
}
static int p54u_close(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
netif_stop_queue(netdev);
if(!load_fw && p54u->running && p54u_shutdown(netdev))
return -EIO;
return 0;
}
static void p54u_tx_timeout(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
return;
}
static int p54u_transmit(struct sk_buff *skb, struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
return 0;
}
int p54u_setup_net(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
/* initialize the function pointers */
netdev->open = &p54u_open;
netdev->stop = &p54u_close;
// netdev->get_stats = &p54u_statistics;
// netdev->get_wireless_stats = &p54u_wireless_stats;
// netdev->do_ioctl = &p54u_ioctl;
// netdev->wireless_handlers = (struct iw_handler_def *) &p54u_handler_def;
netdev->hard_start_xmit = &p54u_transmit;
netdev->addr_len = ETH_ALEN;
// netdev->set_mac_address = &prism54_set_mac_address;
netdev->watchdog_timeo = P54U_TX_TIMEOUT;
netdev->tx_timeout = &p54u_tx_timeout;
return 0;
}
--Multipart=_Sat__3_Apr_2004_11_00_23_+0200_qXiU4ylBeKckvszz
Content-Type: text/x-csrc;
name="usb_transport.c"
Content-Disposition: attachment;
filename="usb_transport.c"
Content-Transfer-Encoding: 7bit
/*
* Prism54 USB driver
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/usb.h>
#include <linux/pci.h>
#include <linux/firmware.h>
#include <asm/uaccess.h>
#include "prism54_usb.h"
#include "isl_38xx.h"
void p54u_mdelay(int ms)
{
int t = (ms * HZ + 500) / 1000;
if(!t && ms)
t = 1;
set_current_state(TASK_UNINTERRUPTIBLE);
while(t) {
//printk("t: %i\n", t);
t = schedule_timeout(t);
}
return;
}
void p54u_data_debug(struct net_device *netdev, unsigned int ep, void *_data, int len)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
unsigned char *data = _data;
int k, l, in;
in = ep & USB_DIR_IN;
if(debug > 1) {
for(k = 0; k < len; k+= 16) {
if(k == 0) {
printk(KERN_CRIT "[%s >%-6lld<%-6lld+%-6lld]\t%02x %s 00000000:", in?"IN ":"OUT", 0LL, 0LL, 0LL, ep, in?"<-":"->");
} else {
printk(KERN_CRIT "\t\t\t\t -> %08x:", k);
}
for (l = 0; (l < 16) && (k + l < len); ++l) {
printk(" %02x", ((unsigned char *)data)[k + l]);
}
printk("\n");
}
}
}
int p54u_bulk_msg(struct net_device *netdev, unsigned int ep, void *_data, int len)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
unsigned char *data = _data;
size_t alen;
int pipe, err, k, l;
p54u_data_debug(netdev, ep, data, len);
pipe = usb_sndbulkpipe(usbdev, ep);
err = usb_bulk_msg(usbdev, pipe, data, len, &alen, 2 * HZ);
if(err)
p54u_info("bulk submit failed: %i\n", err);
/* for(;;) {
err = usb_bulk_msg(usbdev, pipe, data, len, alen, HZ);
switch(err) {
case -EPIPE:
default:
return err;
}
} while(err);
*/
return err;
}
u32 p54u_reg_rw(struct net_device *netdev, int write, int ep, int port, u32 addr, u32 val)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
struct p54u_reg *reg;
unsigned char data[sizeof(*reg)];
unsigned int pipe;
size_t len;
int err, i, epd;
u64 t, t1, t2;
if(debug > 2) {
if(write) {
printk(KERN_DEBUG __FILE__ " Write %02x %04x %08x %08x", ep, port, addr, val);
} else {
printk(KERN_DEBUG __FILE__ " Read %02x %04x %08x ", ep, port, addr);
}
}
reg = (struct p54u_reg *)data;
reg->port = cpu_to_le16(port);
reg->addr = cpu_to_le32(addr);
reg->val = ((port & P54U_PORT_U32) == P54U_PORT_U32) ? cpu_to_le32(val) : cpu_to_le16(val);
len = write ? P54U_REG_WSIZE : P54U_REG_RSIZE;
pipe = usb_sndbulkpipe(usbdev, ep & USB_ENDPOINT_NUMBER_MASK);
t1 = p54u_time();
err = usb_bulk_msg(usbdev, pipe, data, len, &len, HZ);
t2 = p54u_time();
t = t2 - t1;
if(debug > 1) {
printk(KERN_CRIT "[OUT >%-6lld<%-6lld+%-6lld]\t%02x -> 00000000:", t1, t2, t, ep);
for (i = 0; i < len; ++i) {
printk(" %02x", data[i]);
}
}
if(err)
p54u->err = err;
if(debug > 1) {
if(err) {
printk(" failed: %i", err);
}
printk("\n");
} else if(err) {
p54u_err("%s %02x %04x %08x %08x: failed: %i", write ? "Write": "Read", ep, port, addr, val, err);
return 0;
}
if(write)
return 0;
pipe = usb_rcvbulkpipe(usbdev, ep & USB_ENDPOINT_NUMBER_MASK);
len = sizeof(data);
t1 = p54u_time();
err = usb_bulk_msg(usbdev, pipe, data, len, &len, HZ);
t2 = p54u_time();
t = t2 - t1;
if(err)
p54u->err = err;
if(debug > 1) {
printk(KERN_CRIT "[IN >%-6lld<%-6lld+%-6lld]\t%02x <- 00000000:", t1, t2, t, ep | USB_DIR_IN);
if(err) {
printk("failed: %i\n", err);
return 0;
}
for (i = 0; i < len; ++i) {
printk(" %02x", data[i]);
}
printk("\n");
} else {
if(err) {
p54u_err("Register read %02x %04x %08x %08x: failed: %i", ep, port, addr, val, err);
return 0;
}
}
return ((port & P54U_PORT_U32) == P54U_PORT_U32) ? le32_to_cpu(*(u32*)data) : le16_to_cpu(*(u32*)data);
}
u32 p54u_wait_int(struct net_device *netdev)
{
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
u32 reg;
int err;
wait_for_completion(&p54u->int_rx.comp);
p54u_dev_writel(netdev, ISL38XX_INT_EN_REG, 0);
reg = p54u_dev_readl(netdev, ISL38XX_INT_IDENT_REG);
p54u_dev_writel(netdev, ISL38XX_INT_ACK_REG, reg);
printk("readi: %08x\n", reg);
err = usb_submit_urb(p54u->int_rx.urb[0], GFP_KERNEL);
if(err)
p54u_info("int resubmit failed %i\n", err);
return reg;
}
void p54u_int_rx_cb(struct urb *urb, struct pt_regs *p)
{
struct net_device *netdev = urb->context;
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
int err;
u32 reg;
u64 t;
t = p54u_time();
p54u_info("Int %08x\t%d\t\%lld\n", *(int *)urb->transfer_buffer, urb->status, t);
complete(&p54u->int_rx.comp);
// INIT_COMPLETION(p54u->int_rx.comp);
return;
}
void p54u_data_rx_cb(struct urb *urb, struct pt_regs *p)
{
struct net_device *netdev = urb->context;
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
int err;
p54u_info("Data %08x\t%d\n", *(int *)urb->transfer_buffer, urb->status);
err = usb_submit_urb(urb, GFP_ATOMIC);
if(err)
p54u_info("data resubmit failed %i\n", err);
return;
}
void p54u_mgmt_rx_cb(struct urb *urb, struct pt_regs *p)
{
struct net_device *netdev = urb->context;
struct p54u *p54u = netdev_priv(netdev);
struct usb_device *usbdev = p54u->usbdev;
unsigned char *data;
size_t len;
int err, k, l;
u64 t;
p54u_dbg("Mgmt %d\n", urb->status);
t = p54u_time();
len = urb->actual_length;
data = urb->transfer_buffer;
if(debug > 1) {
for(k = 0; k < len; k+= 16) {
if(k == 0) {
printk(KERN_CRIT "[IN >%-6lld<%-6lld+%-6lld]\t%02x <- 00000000:", 0LL, t, 0LL, 0x82);
} else {
printk(KERN_CRIT "\t\t\t\t -> %08x:", k);
}
for (l = 0; (l < 16) && (k + l < len); ++l) {
printk(" %02x", ((unsigned char *)data)[k + l]);
}
printk("\n");
}
}
err = usb_submit_urb(urb, GFP_ATOMIC);
if(err)
p54u_info("mgmt resubmit failed %i\n", err);
return;
}
--Multipart=_Sat__3_Apr_2004_11_00_23_+0200_qXiU4ylBeKckvszz--