Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 77b2555b52a894a2e39a42e43d993df875c46a6a 407 lines 10 kB view raw
1/* 2 * GeneSys GL620USB-A based links 3 * Copyright (C) 2001 by Jiun-Jie Huang <huangjj@genesyslogic.com.tw> 4 * Copyright (C) 2001 by Stanislav Brabec <utx@penguin.cz> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21// #define DEBUG // error path messages, extra info 22// #define VERBOSE // more; success messages 23 24#include <linux/config.h> 25#ifdef CONFIG_USB_DEBUG 26# define DEBUG 27#endif 28#include <linux/module.h> 29#include <linux/sched.h> 30#include <linux/init.h> 31#include <linux/netdevice.h> 32#include <linux/etherdevice.h> 33#include <linux/ethtool.h> 34#include <linux/workqueue.h> 35#include <linux/mii.h> 36#include <linux/usb.h> 37 38#include "usbnet.h" 39 40 41/* 42 * GeneSys GL620USB-A (www.genesyslogic.com.tw) 43 * 44 * ... should partially interop with the Win32 driver for this hardware. 45 * The GeneSys docs imply there's some NDIS issue motivating this framing. 46 * 47 * Some info from GeneSys: 48 * - GL620USB-A is full duplex; GL620USB is only half duplex for bulk. 49 * (Some cables, like the BAFO-100c, use the half duplex version.) 50 * - For the full duplex model, the low bit of the version code says 51 * which side is which ("left/right"). 52 * - For the half duplex type, a control/interrupt handshake settles 53 * the transfer direction. (That's disabled here, partially coded.) 54 * A control URB would block until other side writes an interrupt. 55 * 56 * Original code from Jiun-Jie Huang <huangjj@genesyslogic.com.tw> 57 * and merged into "usbnet" by Stanislav Brabec <utx@penguin.cz>. 58 */ 59 60// control msg write command 61#define GENELINK_CONNECT_WRITE 0xF0 62// interrupt pipe index 63#define GENELINK_INTERRUPT_PIPE 0x03 64// interrupt read buffer size 65#define INTERRUPT_BUFSIZE 0x08 66// interrupt pipe interval value 67#define GENELINK_INTERRUPT_INTERVAL 0x10 68// max transmit packet number per transmit 69#define GL_MAX_TRANSMIT_PACKETS 32 70// max packet length 71#define GL_MAX_PACKET_LEN 1514 72// max receive buffer size 73#define GL_RCV_BUF_SIZE \ 74 (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4) 75 76struct gl_packet { 77 u32 packet_length; 78 char packet_data [1]; 79}; 80 81struct gl_header { 82 u32 packet_count; 83 struct gl_packet packets; 84}; 85 86#ifdef GENELINK_ACK 87 88// FIXME: this code is incomplete, not debugged; it doesn't 89// handle interrupts correctly; it should use the generic 90// status IRQ code (which didn't exist back in 2001). 91 92struct gl_priv { 93 struct urb *irq_urb; 94 char irq_buf [INTERRUPT_BUFSIZE]; 95}; 96 97static inline int gl_control_write(struct usbnet *dev, u8 request, u16 value) 98{ 99 int retval; 100 101 retval = usb_control_msg(dev->udev, 102 usb_sndctrlpipe(dev->udev, 0), 103 request, 104 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 105 value, 106 0, // index 107 0, // data buffer 108 0, // size 109 USB_CTRL_SET_TIMEOUT); 110 return retval; 111} 112 113static void gl_interrupt_complete(struct urb *urb, struct pt_regs *regs) 114{ 115 int status = urb->status; 116 117 switch (status) { 118 case 0: 119 /* success */ 120 break; 121 case -ECONNRESET: 122 case -ENOENT: 123 case -ESHUTDOWN: 124 /* this urb is terminated, clean up */ 125 dbg("%s - urb shutting down with status: %d", 126 __FUNCTION__, status); 127 return; 128 default: 129 dbg("%s - nonzero urb status received: %d", 130 __FUNCTION__, urb->status); 131 } 132 133 status = usb_submit_urb(urb, GFP_ATOMIC); 134 if (status) 135 err("%s - usb_submit_urb failed with result %d", 136 __FUNCTION__, status); 137} 138 139static int gl_interrupt_read(struct usbnet *dev) 140{ 141 struct gl_priv *priv = dev->priv_data; 142 int retval; 143 144 // issue usb interrupt read 145 if (priv && priv->irq_urb) { 146 // submit urb 147 if ((retval = usb_submit_urb(priv->irq_urb, GFP_KERNEL)) != 0) 148 dbg("gl_interrupt_read: submit fail - %X...", retval); 149 else 150 dbg("gl_interrupt_read: submit success..."); 151 } 152 153 return 0; 154} 155 156// check whether another side is connected 157static int genelink_check_connect(struct usbnet *dev) 158{ 159 int retval; 160 161 dbg("genelink_check_connect..."); 162 163 // detect whether another side is connected 164 if ((retval = gl_control_write(dev, GENELINK_CONNECT_WRITE, 0)) != 0) { 165 dbg("%s: genelink_check_connect write fail - %X", 166 dev->net->name, retval); 167 return retval; 168 } 169 170 // usb interrupt read to ack another side 171 if ((retval = gl_interrupt_read(dev)) != 0) { 172 dbg("%s: genelink_check_connect read fail - %X", 173 dev->net->name, retval); 174 return retval; 175 } 176 177 dbg("%s: genelink_check_connect read success", dev->net->name); 178 return 0; 179} 180 181// allocate and initialize the private data for genelink 182static int genelink_init(struct usbnet *dev) 183{ 184 struct gl_priv *priv; 185 186 // allocate the private data structure 187 if ((priv = kmalloc(sizeof *priv, GFP_KERNEL)) == 0) { 188 dbg("%s: cannot allocate private data per device", 189 dev->net->name); 190 return -ENOMEM; 191 } 192 193 // allocate irq urb 194 if ((priv->irq_urb = usb_alloc_urb(0, GFP_KERNEL)) == 0) { 195 dbg("%s: cannot allocate private irq urb per device", 196 dev->net->name); 197 kfree(priv); 198 return -ENOMEM; 199 } 200 201 // fill irq urb 202 usb_fill_int_urb(priv->irq_urb, dev->udev, 203 usb_rcvintpipe(dev->udev, GENELINK_INTERRUPT_PIPE), 204 priv->irq_buf, INTERRUPT_BUFSIZE, 205 gl_interrupt_complete, 0, 206 GENELINK_INTERRUPT_INTERVAL); 207 208 // set private data pointer 209 dev->priv_data = priv; 210 211 return 0; 212} 213 214// release the private data 215static int genelink_free(struct usbnet *dev) 216{ 217 struct gl_priv *priv = dev->priv_data; 218 219 if (!priv) 220 return 0; 221 222// FIXME: can't cancel here; it's synchronous, and 223// should have happened earlier in any case (interrupt 224// handling needs to be generic) 225 226 // cancel irq urb first 227 usb_kill_urb(priv->irq_urb); 228 229 // free irq urb 230 usb_free_urb(priv->irq_urb); 231 232 // free the private data structure 233 kfree(priv); 234 235 return 0; 236} 237 238#endif 239 240static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb) 241{ 242 struct gl_header *header; 243 struct gl_packet *packet; 244 struct sk_buff *gl_skb; 245 u32 size; 246 247 header = (struct gl_header *) skb->data; 248 249 // get the packet count of the received skb 250 le32_to_cpus(&header->packet_count); 251 if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS) 252 || (header->packet_count < 0)) { 253 dbg("genelink: invalid received packet count %d", 254 header->packet_count); 255 return 0; 256 } 257 258 // set the current packet pointer to the first packet 259 packet = &header->packets; 260 261 // decrement the length for the packet count size 4 bytes 262 skb_pull(skb, 4); 263 264 while (header->packet_count > 1) { 265 // get the packet length 266 size = le32_to_cpu(packet->packet_length); 267 268 // this may be a broken packet 269 if (size > GL_MAX_PACKET_LEN) { 270 dbg("genelink: invalid rx length %d", size); 271 return 0; 272 } 273 274 // allocate the skb for the individual packet 275 gl_skb = alloc_skb(size, GFP_ATOMIC); 276 if (gl_skb) { 277 278 // copy the packet data to the new skb 279 memcpy(skb_put(gl_skb, size), 280 packet->packet_data, size); 281 usbnet_skb_return(dev, gl_skb); 282 } 283 284 // advance to the next packet 285 packet = (struct gl_packet *) 286 &packet->packet_data [size]; 287 header->packet_count--; 288 289 // shift the data pointer to the next gl_packet 290 skb_pull(skb, size + 4); 291 } 292 293 // skip the packet length field 4 bytes 294 skb_pull(skb, 4); 295 296 if (skb->len > GL_MAX_PACKET_LEN) { 297 dbg("genelink: invalid rx length %d", skb->len); 298 return 0; 299 } 300 return 1; 301} 302 303static struct sk_buff * 304genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags) 305{ 306 int padlen; 307 int length = skb->len; 308 int headroom = skb_headroom(skb); 309 int tailroom = skb_tailroom(skb); 310 u32 *packet_count; 311 u32 *packet_len; 312 313 // FIXME: magic numbers, bleech 314 padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1; 315 316 if ((!skb_cloned(skb)) 317 && ((headroom + tailroom) >= (padlen + (4 + 4*1)))) { 318 if ((headroom < (4 + 4*1)) || (tailroom < padlen)) { 319 skb->data = memmove(skb->head + (4 + 4*1), 320 skb->data, skb->len); 321 skb->tail = skb->data + skb->len; 322 } 323 } else { 324 struct sk_buff *skb2; 325 skb2 = skb_copy_expand(skb, (4 + 4*1) , padlen, flags); 326 dev_kfree_skb_any(skb); 327 skb = skb2; 328 if (!skb) 329 return NULL; 330 } 331 332 // attach the packet count to the header 333 packet_count = (u32 *) skb_push(skb, (4 + 4*1)); 334 packet_len = packet_count + 1; 335 336 *packet_count = cpu_to_le32(1); 337 *packet_len = cpu_to_le32(length); 338 339 // add padding byte 340 if ((skb->len % dev->maxpacket) == 0) 341 skb_put(skb, 1); 342 343 return skb; 344} 345 346static int genelink_bind(struct usbnet *dev, struct usb_interface *intf) 347{ 348 dev->hard_mtu = GL_RCV_BUF_SIZE; 349 dev->net->hard_header_len += 4; 350 dev->in = usb_rcvbulkpipe(dev->udev, dev->driver_info->in); 351 dev->out = usb_sndbulkpipe(dev->udev, dev->driver_info->out); 352 return 0; 353} 354 355static const struct driver_info genelink_info = { 356 .description = "Genesys GeneLink", 357 .flags = FLAG_FRAMING_GL | FLAG_NO_SETINT, 358 .bind = genelink_bind, 359 .rx_fixup = genelink_rx_fixup, 360 .tx_fixup = genelink_tx_fixup, 361 362 .in = 1, .out = 2, 363 364#ifdef GENELINK_ACK 365 .check_connect =genelink_check_connect, 366#endif 367}; 368 369static const struct usb_device_id products [] = { 370 371{ 372 USB_DEVICE(0x05e3, 0x0502), // GL620USB-A 373 .driver_info = (unsigned long) &genelink_info, 374}, 375 /* NOT: USB_DEVICE(0x05e3, 0x0501), // GL620USB 376 * that's half duplex, not currently supported 377 */ 378 { }, // END 379}; 380MODULE_DEVICE_TABLE(usb, products); 381 382static struct usb_driver gl620a_driver = { 383 .owner = THIS_MODULE, 384 .name = "gl620a", 385 .id_table = products, 386 .probe = usbnet_probe, 387 .disconnect = usbnet_disconnect, 388 .suspend = usbnet_suspend, 389 .resume = usbnet_resume, 390}; 391 392static int __init usbnet_init(void) 393{ 394 return usb_register(&gl620a_driver); 395} 396module_init(usbnet_init); 397 398static void __exit usbnet_exit(void) 399{ 400 usb_deregister(&gl620a_driver); 401} 402module_exit(usbnet_exit); 403 404MODULE_AUTHOR("Jiun-Jie Huang"); 405MODULE_DESCRIPTION("GL620-USB-A Host-to-Host Link cables"); 406MODULE_LICENSE("GPL"); 407