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