at v2.6.14 674 lines 18 kB view raw
1/* bionet.c BioNet-100 device driver for linux68k. 2 * 3 * Version: @(#)bionet.c 1.0 02/06/96 4 * 5 * Author: Hartmut Laue <laue@ifk-mp.uni-kiel.de> 6 * and Torsten Narjes <narjes@ifk-mp.uni-kiel.de> 7 * 8 * Little adaptions for integration into pl7 by Roman Hodek 9 * 10 * Some changes in bionet_poll_rx by Karl-Heinz Lohner 11 * 12 What is it ? 13 ------------ 14 This driver controls the BIONET-100 LAN-Adapter which connects 15 an ATARI ST/TT via the ACSI-port to an Ethernet-based network. 16 17 This version can be compiled as a loadable module (See the 18 compile command at the bottom of this file). 19 At load time, you can optionally set the debugging level and the 20 fastest response time on the command line of 'insmod'. 21 22 'bionet_debug' 23 controls the amount of diagnostic messages: 24 0 : no messages 25 >0 : see code for meaning of printed messages 26 27 'bionet_min_poll_time' (always >=1) 28 gives the time (in jiffies) between polls. Low values 29 increase the system load (beware!) 30 31 When loaded, a net device with the name 'bio0' becomes available, 32 which can be controlled with the usual 'ifconfig' command. 33 34 It is possible to compile this driver into the kernel like other 35 (net) drivers. For this purpose, some source files (e.g. config-files 36 makefiles, Space.c) must be changed accordingly. (You may refer to 37 other drivers how to do it.) In this case, the device will be detected 38 at boot time and (probably) appear as 'eth0'. 39 40 This code is based on several sources: 41 - The driver code for a parallel port ethernet adapter by 42 Donald Becker (see file 'atp.c' from the PC linux distribution) 43 - The ACSI code by Roman Hodek for the ATARI-ACSI harddisk support 44 and DMA handling. 45 - Very limited information about moving packets in and out of the 46 BIONET-adapter from the TCP package for TOS by BioData GmbH. 47 48 Theory of Operation 49 ------------------- 50 Because the ATARI DMA port is usually shared between several 51 devices (eg. harddisk, floppy) we cannot block the ACSI bus 52 while waiting for interrupts. Therefore we use a polling mechanism 53 to fetch packets from the adapter. For the same reason, we send 54 packets without checking that the previous packet has been sent to 55 the LAN. We rely on the higher levels of the networking code to detect 56 missing packets and resend them. 57 58 Before we access the ATARI DMA controller, we check if another 59 process is using the DMA. If not, we lock the DMA, perform one or 60 more packet transfers and unlock the DMA before returning. 61 We do not use 'stdma_lock' unconditionally because it is unclear 62 if the networking code can be set to sleep, which will happen if 63 another (possibly slow) device is using the DMA controller. 64 65 The polling is done via timer interrupts which periodically 66 'simulate' an interrupt from the Ethernet adapter. The time (in jiffies) 67 between polls varies depending on an estimate of the net activity. 68 The allowed range is given by the variable 'bionet_min_poll_time' 69 for the lower (fastest) limit and the constant 'MAX_POLL_TIME' 70 for the higher (slowest) limit. 71 72 Whenever a packet arrives, we switch to fastest response by setting 73 the polling time to its lowest limit. If the following poll fails, 74 because no packets have arrived, we increase the time for the next 75 poll. When the net activity is low, the polling time effectively 76 stays at its maximum value, resulting in the lowest load for the 77 machine. 78 */ 79 80#define MAX_POLL_TIME 10 81 82static char version[] = 83 "bionet.c:v1.0 06-feb-96 (c) Hartmut Laue.\n"; 84 85#include <linux/module.h> 86 87#include <linux/errno.h> 88#include <linux/kernel.h> 89#include <linux/jiffies.h> 90#include <linux/types.h> 91#include <linux/fcntl.h> 92#include <linux/interrupt.h> 93#include <linux/ioport.h> 94#include <linux/in.h> 95#include <linux/slab.h> 96#include <linux/string.h> 97#include <linux/delay.h> 98#include <linux/timer.h> 99#include <linux/init.h> 100#include <linux/bitops.h> 101 102#include <linux/netdevice.h> 103#include <linux/etherdevice.h> 104#include <linux/skbuff.h> 105 106#include <asm/setup.h> 107#include <asm/pgtable.h> 108#include <asm/system.h> 109#include <asm/io.h> 110#include <asm/dma.h> 111#include <asm/atarihw.h> 112#include <asm/atariints.h> 113#include <asm/atari_acsi.h> 114#include <asm/atari_stdma.h> 115 116 117/* use 0 for production, 1 for verification, >2 for debug 118 */ 119#ifndef NET_DEBUG 120#define NET_DEBUG 0 121#endif 122/* 123 * Global variable 'bionet_debug'. Can be set at load time by 'insmod' 124 */ 125unsigned int bionet_debug = NET_DEBUG; 126MODULE_PARM(bionet_debug, "i"); 127MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)"); 128MODULE_LICENSE("GPL"); 129 130static unsigned int bionet_min_poll_time = 2; 131 132 133/* Information that need to be kept for each board. 134 */ 135struct net_local { 136 struct net_device_stats stats; 137 long open_time; /* for debugging */ 138 int poll_time; /* polling time varies with net load */ 139}; 140 141static struct nic_pkt_s { /* packet format */ 142 unsigned char status; 143 unsigned char dummy; 144 unsigned char l_lo, l_hi; 145 unsigned char buffer[3000]; 146} *nic_packet; 147unsigned char *phys_nic_packet; 148 149/* Index to functions, as function prototypes. 150 */ 151static int bionet_open(struct net_device *dev); 152static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev); 153static void bionet_poll_rx(struct net_device *); 154static int bionet_close(struct net_device *dev); 155static struct net_device_stats *net_get_stats(struct net_device *dev); 156static void bionet_tick(unsigned long); 157 158static DEFINE_TIMER(bionet_timer, bionet_tick, 0, 0); 159 160#define STRAM_ADDR(a) (((a) & 0xff000000) == 0) 161 162/* The following routines access the ethernet board connected to the 163 * ACSI port via the st_dma chip. 164 */ 165#define NODE_ADR 0x60 166 167#define C_READ 8 168#define C_WRITE 0x0a 169#define C_GETEA 0x0f 170#define C_SETCR 0x0e 171 172static int 173sendcmd(unsigned int a0, unsigned int mod, unsigned int cmd) { 174 unsigned int c; 175 176 dma_wd.dma_mode_status = (mod | ((a0) ? 2 : 0) | 0x88); 177 dma_wd.fdc_acces_seccount = cmd; 178 dma_wd.dma_mode_status = (mod | 0x8a); 179 180 if( !acsi_wait_for_IRQ(HZ/2) ) /* wait for cmd ack */ 181 return -1; /* timeout */ 182 183 c = dma_wd.fdc_acces_seccount; 184 return (c & 0xff); 185} 186 187 188static void 189set_status(int cr) { 190 sendcmd(0,0x100,NODE_ADR | C_SETCR); /* CMD: SET CR */ 191 sendcmd(1,0x100,cr); 192 193 dma_wd.dma_mode_status = 0x80; 194} 195 196static int 197get_status(unsigned char *adr) { 198 int i,c; 199 200 DISABLE_IRQ(); 201 c = sendcmd(0,0x00,NODE_ADR | C_GETEA); /* CMD: GET ETH ADR*/ 202 if( c < 0 ) goto gsend; 203 204 /* now read status bytes */ 205 206 for (i=0; i<6; i++) { 207 dma_wd.fdc_acces_seccount = 0; /* request next byte */ 208 209 if( !acsi_wait_for_IRQ(HZ/2) ) { /* wait for cmd ack */ 210 c = -1; 211 goto gsend; /* timeout */ 212 } 213 c = dma_wd.fdc_acces_seccount; 214 *adr++ = (unsigned char)c; 215 } 216 c = 1; 217gsend: 218 dma_wd.dma_mode_status = 0x80; 219 return c; 220} 221 222static irqreturn_t 223bionet_intr(int irq, void *data, struct pt_regs *fp) { 224 return IRQ_HANDLED; 225} 226 227 228static int 229get_frame(unsigned long paddr, int odd) { 230 int c; 231 unsigned long flags; 232 233 DISABLE_IRQ(); 234 local_irq_save(flags); 235 236 dma_wd.dma_mode_status = 0x9a; 237 dma_wd.dma_mode_status = 0x19a; 238 dma_wd.dma_mode_status = 0x9a; 239 dma_wd.fdc_acces_seccount = 0x04; /* sector count (was 5) */ 240 dma_wd.dma_lo = (unsigned char)paddr; 241 paddr >>= 8; 242 dma_wd.dma_md = (unsigned char)paddr; 243 paddr >>= 8; 244 dma_wd.dma_hi = (unsigned char)paddr; 245 local_irq_restore(flags); 246 247 c = sendcmd(0,0x00,NODE_ADR | C_READ); /* CMD: READ */ 248 if( c < 128 ) goto rend; 249 250 /* now read block */ 251 252 c = sendcmd(1,0x00,odd); /* odd flag for address shift */ 253 dma_wd.dma_mode_status = 0x0a; 254 255 if( !acsi_wait_for_IRQ(100) ) { /* wait for DMA to complete */ 256 c = -1; 257 goto rend; 258 } 259 dma_wd.dma_mode_status = 0x8a; 260 dma_wd.dma_mode_status = 0x18a; 261 dma_wd.dma_mode_status = 0x8a; 262 c = dma_wd.fdc_acces_seccount; 263 264 dma_wd.dma_mode_status = 0x88; 265 c = dma_wd.fdc_acces_seccount; 266 c = 1; 267 268rend: 269 dma_wd.dma_mode_status = 0x80; 270 udelay(40); 271 acsi_wait_for_noIRQ(20); 272 return c; 273} 274 275 276static int 277hardware_send_packet(unsigned long paddr, int cnt) { 278 unsigned int c; 279 unsigned long flags; 280 281 DISABLE_IRQ(); 282 local_irq_save(flags); 283 284 dma_wd.dma_mode_status = 0x19a; 285 dma_wd.dma_mode_status = 0x9a; 286 dma_wd.dma_mode_status = 0x19a; 287 dma_wd.dma_lo = (unsigned char)paddr; 288 paddr >>= 8; 289 dma_wd.dma_md = (unsigned char)paddr; 290 paddr >>= 8; 291 dma_wd.dma_hi = (unsigned char)paddr; 292 293 dma_wd.fdc_acces_seccount = 0x4; /* sector count */ 294 local_irq_restore(flags); 295 296 c = sendcmd(0,0x100,NODE_ADR | C_WRITE); /* CMD: WRITE */ 297 c = sendcmd(1,0x100,cnt&0xff); 298 c = sendcmd(1,0x100,cnt>>8); 299 300 /* now write block */ 301 302 dma_wd.dma_mode_status = 0x10a; /* DMA enable */ 303 if( !acsi_wait_for_IRQ(100) ) /* wait for DMA to complete */ 304 goto end; 305 306 dma_wd.dma_mode_status = 0x19a; /* DMA disable ! */ 307 c = dma_wd.fdc_acces_seccount; 308 309end: 310 c = sendcmd(1,0x100,0); 311 c = sendcmd(1,0x100,0); 312 313 dma_wd.dma_mode_status = 0x180; 314 udelay(40); 315 acsi_wait_for_noIRQ(20); 316 return( c & 0x02); 317} 318 319 320/* Check for a network adaptor of this type, and return '0' if one exists. 321 */ 322struct net_device * __init bionet_probe(int unit) 323{ 324 struct net_device *dev; 325 unsigned char station_addr[6]; 326 static unsigned version_printed; 327 static int no_more_found; /* avoid "Probing for..." printed 4 times */ 328 int i; 329 int err; 330 331 if (!MACH_IS_ATARI || no_more_found) 332 return ERR_PTR(-ENODEV); 333 334 dev = alloc_etherdev(sizeof(struct net_local)); 335 if (!dev) 336 return ERR_PTR(-ENOMEM); 337 if (unit >= 0) { 338 sprintf(dev->name, "eth%d", unit); 339 netdev_boot_setup_check(dev); 340 } 341 SET_MODULE_OWNER(dev); 342 343 printk("Probing for BioNet 100 Adapter...\n"); 344 345 stdma_lock(bionet_intr, NULL); 346 i = get_status(station_addr); /* Read the station address PROM. */ 347 ENABLE_IRQ(); 348 stdma_release(); 349 350 /* Check the first three octets of the S.A. for the manufactor's code. 351 */ 352 353 if( i < 0 354 || station_addr[0] != 'B' 355 || station_addr[1] != 'I' 356 || station_addr[2] != 'O' ) { 357 no_more_found = 1; 358 printk( "No BioNet 100 found.\n" ); 359 free_netdev(dev); 360 return ERR_PTR(-ENODEV); 361 } 362 363 if (bionet_debug > 0 && version_printed++ == 0) 364 printk(version); 365 366 printk("%s: %s found, eth-addr: %02x-%02x-%02x:%02x-%02x-%02x.\n", 367 dev->name, "BioNet 100", 368 station_addr[0], station_addr[1], station_addr[2], 369 station_addr[3], station_addr[4], station_addr[5]); 370 371 /* Initialize the device structure. */ 372 373 nic_packet = (struct nic_pkt_s *)acsi_buffer; 374 phys_nic_packet = (unsigned char *)phys_acsi_buffer; 375 if (bionet_debug > 0) { 376 printk("nic_packet at 0x%p, phys at 0x%p\n", 377 nic_packet, phys_nic_packet ); 378 } 379 380 dev->open = bionet_open; 381 dev->stop = bionet_close; 382 dev->hard_start_xmit = bionet_send_packet; 383 dev->get_stats = net_get_stats; 384 385 /* Fill in the fields of the device structure with ethernet-generic 386 * values. This should be in a common file instead of per-driver. 387 */ 388 389 for (i = 0; i < ETH_ALEN; i++) { 390#if 0 391 dev->broadcast[i] = 0xff; 392#endif 393 dev->dev_addr[i] = station_addr[i]; 394 } 395 err = register_netdev(dev); 396 if (!err) 397 return dev; 398 free_netdev(dev); 399 return ERR_PTR(err); 400} 401 402/* Open/initialize the board. This is called (in the current kernel) 403 sometime after booting when the 'ifconfig' program is run. 404 405 This routine should set everything up anew at each open, even 406 registers that "should" only need to be set once at boot, so that 407 there is non-reboot way to recover if something goes wrong. 408 */ 409static int 410bionet_open(struct net_device *dev) { 411 struct net_local *lp = netdev_priv(dev); 412 413 if (bionet_debug > 0) 414 printk("bionet_open\n"); 415 stdma_lock(bionet_intr, NULL); 416 417 /* Reset the hardware here. 418 */ 419 set_status(4); 420 lp->open_time = 0; /*jiffies*/ 421 lp->poll_time = MAX_POLL_TIME; 422 423 dev->tbusy = 0; 424 dev->interrupt = 0; 425 dev->start = 1; 426 427 stdma_release(); 428 bionet_timer.data = (long)dev; 429 bionet_timer.expires = jiffies + lp->poll_time; 430 add_timer(&bionet_timer); 431 return 0; 432} 433 434static int 435bionet_send_packet(struct sk_buff *skb, struct net_device *dev) { 436 struct net_local *lp = netdev_priv(dev); 437 unsigned long flags; 438 439 /* Block a timer-based transmit from overlapping. This could better be 440 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. 441 */ 442 local_irq_save(flags); 443 444 if (stdma_islocked()) { 445 local_irq_restore(flags); 446 lp->stats.tx_errors++; 447 } 448 else { 449 int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; 450 unsigned long buf = virt_to_phys(skb->data); 451 int stat; 452 453 stdma_lock(bionet_intr, NULL); 454 local_irq_restore(flags); 455 if( !STRAM_ADDR(buf+length-1) ) { 456 memcpy(nic_packet->buffer, skb->data, length); 457 buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer; 458 } 459 460 if (bionet_debug >1) { 461 u_char *data = nic_packet->buffer, *p; 462 int i; 463 464 printk( "%s: TX pkt type 0x%4x from ", dev->name, 465 ((u_short *)data)[6]); 466 467 for( p = &data[6], i = 0; i < 6; i++ ) 468 printk("%02x%s", *p++,i != 5 ? ":" : "" ); 469 printk(" to "); 470 471 for( p = data, i = 0; i < 6; i++ ) 472 printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); 473 474 printk( "%s: ", dev->name ); 475 printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" 476 " %02x%02x%02x%02x len %d\n", 477 data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], 478 data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], 479 data[28], data[29], data[30], data[31], data[32], data[33], 480 length ); 481 } 482 dma_cache_maintenance(buf, length, 1); 483 484 stat = hardware_send_packet(buf, length); 485 ENABLE_IRQ(); 486 stdma_release(); 487 488 dev->trans_start = jiffies; 489 dev->tbusy = 0; 490 lp->stats.tx_packets++; 491 lp->stats.tx_bytes+=length; 492 } 493 dev_kfree_skb(skb); 494 495 return 0; 496} 497 498/* We have a good packet(s), get it/them out of the buffers. 499 */ 500static void 501bionet_poll_rx(struct net_device *dev) { 502 struct net_local *lp = netdev_priv(dev); 503 int boguscount = 10; 504 int pkt_len, status; 505 unsigned long flags; 506 507 local_irq_save(flags); 508 /* ++roman: Take care at locking the ST-DMA... This must be done with ints 509 * off, since otherwise an int could slip in between the question and the 510 * locking itself, and then we'd go to sleep... And locking itself is 511 * necessary to keep the floppy_change timer from working with ST-DMA 512 * registers. */ 513 if (stdma_islocked()) { 514 local_irq_restore(flags); 515 return; 516 } 517 stdma_lock(bionet_intr, NULL); 518 DISABLE_IRQ(); 519 local_irq_restore(flags); 520 521 if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++; 522 523 while(boguscount--) { 524 status = get_frame((unsigned long)phys_nic_packet, 0); 525 526 if( status == 0 ) break; 527 528 /* Good packet... */ 529 530 dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0); 531 532 pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo; 533 534 lp->poll_time = bionet_min_poll_time; /* fast poll */ 535 if( pkt_len >= 60 && pkt_len <= 1520 ) { 536 /* ^^^^ war 1514 KHL */ 537 /* Malloc up new buffer. 538 */ 539 struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 ); 540 if (skb == NULL) { 541 printk("%s: Memory squeeze, dropping packet.\n", 542 dev->name); 543 lp->stats.rx_dropped++; 544 break; 545 } 546 547 skb->dev = dev; 548 skb_reserve( skb, 2 ); /* 16 Byte align */ 549 skb_put( skb, pkt_len ); /* make room */ 550 551 /* 'skb->data' points to the start of sk_buff data area. 552 */ 553 memcpy(skb->data, nic_packet->buffer, pkt_len); 554 skb->protocol = eth_type_trans( skb, dev ); 555 netif_rx(skb); 556 dev->last_rx = jiffies; 557 lp->stats.rx_packets++; 558 lp->stats.rx_bytes+=pkt_len; 559 560 /* If any worth-while packets have been received, dev_rint() 561 has done a mark_bh(INET_BH) for us and will work on them 562 when we get to the bottom-half routine. 563 */ 564 565 if (bionet_debug >1) { 566 u_char *data = nic_packet->buffer, *p; 567 int i; 568 569 printk( "%s: RX pkt type 0x%4x from ", dev->name, 570 ((u_short *)data)[6]); 571 572 573 for( p = &data[6], i = 0; i < 6; i++ ) 574 printk("%02x%s", *p++,i != 5 ? ":" : "" ); 575 printk(" to "); 576 for( p = data, i = 0; i < 6; i++ ) 577 printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); 578 579 printk( "%s: ", dev->name ); 580 printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" 581 " %02x%02x%02x%02x len %d\n", 582 data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], 583 data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], 584 data[28], data[29], data[30], data[31], data[32], data[33], 585 pkt_len ); 586 } 587 } 588 else { 589 printk(" Packet has wrong length: %04d bytes\n", pkt_len); 590 lp->stats.rx_errors++; 591 } 592 } 593 stdma_release(); 594 ENABLE_IRQ(); 595 return; 596} 597 598/* bionet_tick: called by bionet_timer. Reads packets from the adapter, 599 * passes them to the higher layers and restarts the timer. 600 */ 601static void 602bionet_tick(unsigned long data) { 603 struct net_device *dev = (struct net_device *)data; 604 struct net_local *lp = netdev_priv(dev); 605 606 if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 ) 607 printk("bionet_tick: %ld\n", lp->open_time); 608 609 if( !stdma_islocked() ) bionet_poll_rx(dev); 610 611 bionet_timer.expires = jiffies + lp->poll_time; 612 add_timer(&bionet_timer); 613} 614 615/* The inverse routine to bionet_open(). 616 */ 617static int 618bionet_close(struct net_device *dev) { 619 struct net_local *lp = netdev_priv(dev); 620 621 if (bionet_debug > 0) 622 printk("bionet_close, open_time=%ld\n", lp->open_time); 623 del_timer(&bionet_timer); 624 stdma_lock(bionet_intr, NULL); 625 626 set_status(0); 627 lp->open_time = 0; 628 629 dev->tbusy = 1; 630 dev->start = 0; 631 632 stdma_release(); 633 return 0; 634} 635 636/* Get the current statistics. 637 This may be called with the card open or closed. 638 */ 639static struct net_device_stats *net_get_stats(struct net_device *dev) 640{ 641 struct net_local *lp = netdev_priv(dev); 642 return &lp->stats; 643} 644 645 646#ifdef MODULE 647 648static struct net_device *bio_dev; 649 650int init_module(void) 651{ 652 bio_dev = bionet_probe(-1); 653 if (IS_ERR(bio_dev)) 654 return PTR_ERR(bio_dev); 655 return 0; 656} 657 658void cleanup_module(void) 659{ 660 unregister_netdev(bio_dev); 661 free_netdev(bio_dev); 662} 663 664#endif /* MODULE */ 665 666/* Local variables: 667 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include 668 -b m68k-linuxaout -Wall -Wstrict-prototypes -O2 669 -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c bionet.c" 670 * version-control: t 671 * kept-new-versions: 5 672 * tab-width: 8 673 * End: 674 */