linux-bk/drivers/net/atari_pamsnet.c
<<
>>
Prefs
   1/* atari_pamsnet.c     PAMsNet device driver for linux68k.
   2 *
   3 * Version:     @(#)PAMsNet.c   0.2ß    03/31/96
   4 *
   5 * Author:  Torsten Lang <Torsten.Lang@ap.physik.uni-giessen.de>
   6 *                       <Torsten.Lang@jung.de>
   7 *
   8 * This driver is based on my driver PAMSDMA.c for MiNT-Net and
   9 * on the driver bionet.c written by
  10 *          Hartmut Laue <laue@ifk-mp.uni-kiel.de>
  11 * and      Torsten Narjes <narjes@ifk-mp.uni-kiel.de>
  12 *
  13 * Little adaptions for integration into pl7 by Roman Hodek
  14 *
  15        What is it ?
  16        ------------
  17        This driver controls the PAMsNet LAN-Adapter which connects
  18        an ATARI ST/TT via the ACSI-port to an Ethernet-based network.
  19
  20        This version can be compiled as a loadable module (See the
  21        compile command at the bottom of this file).
  22        At load time, you can optionally set the debugging level and the
  23        fastest response time on the command line of 'insmod'.
  24
  25        'pamsnet_debug'
  26                controls the amount of diagnostic messages:
  27          0  : no messages
  28          >0 : see code for meaning of printed messages
  29
  30        'pamsnet_min_poll_time' (always >=1)
  31                gives the time (in jiffies) between polls. Low values
  32                increase the system load (beware!)
  33
  34        When loaded, a net device with the name 'eth?' becomes available,
  35        which can be controlled with the usual 'ifconfig' command.
  36
  37        It is possible to compile this driver into the kernel like other
  38        (net) drivers. For this purpose, some source files (e.g. config-files
  39        makefiles, Space.c) must be changed accordingly. (You may refer to
  40        other drivers how to do it.) In this case, the device will be detected
  41        at boot time and (probably) appear as 'eth0'.
  42
  43        Theory of Operation
  44        -------------------
  45        Because the ATARI DMA port is usually shared between several
  46        devices (eg. harddisk, floppy) we cannot block the ACSI bus
  47        while waiting for interrupts. Therefore we use a polling mechanism
  48        to fetch packets from the adapter. For the same reason, we send
  49        packets without checking that the previous packet has been sent to
  50        the LAN. We rely on the higher levels of the networking code to detect
  51        missing packets and resend them.
  52
  53        Before we access the ATARI DMA controller, we check if another
  54        process is using the DMA. If not, we lock the DMA, perform one or
  55        more packet transfers and unlock the DMA before returning.
  56        We do not use 'stdma_lock' unconditionally because it is unclear
  57        if the networking code can be set to sleep, which will happen if
  58        another (possibly slow) device is using the DMA controller.
  59
  60        The polling is done via timer interrupts which periodically
  61        'simulate' an interrupt from the Ethernet adapter. The time (in jiffies)
  62        between polls varies depending on an estimate of the net activity.
  63        The allowed range is given by the variable 'bionet_min_poll_time'
  64        for the lower (fastest) limit and the constant 'MAX_POLL_TIME'
  65        for the higher (slowest) limit.
  66
  67        Whenever a packet arrives, we switch to fastest response by setting
  68        the polling time to its lowest limit. If the following poll fails,
  69        because no packets have arrived, we increase the time for the next
  70        poll. When the net activity is low, the polling time effectively
  71        stays at its maximum value, resulting in the lowest load for the
  72        machine.
  73 */
  74
  75#define MAX_POLL_TIME   10
  76
  77static char *version =
  78        "pamsnet.c:v0.2beta 30-mar-96 (c) Torsten Lang.\n";
  79
  80#include <linux/module.h>
  81
  82#include <linux/kernel.h>
  83#include <linux/jiffies.h>
  84#include <linux/types.h>
  85#include <linux/fcntl.h>
  86#include <linux/interrupt.h>
  87#include <linux/ioport.h>
  88#include <linux/in.h>
  89#include <linux/slab.h>
  90#include <linux/string.h>
  91#include <asm/system.h>
  92#include <asm/pgtable.h>
  93#include <asm/bitops.h>
  94#include <asm/io.h>
  95#include <asm/dma.h>
  96#include <linux/errno.h>
  97#include <asm/atarihw.h>
  98#include <asm/atariints.h>
  99#include <asm/atari_stdma.h>
 100#include <asm/atari_acsi.h>
 101
 102#include <linux/delay.h>
 103#include <linux/timer.h>
 104#include <linux/init.h>
 105
 106#include <linux/netdevice.h>
 107#include <linux/etherdevice.h>
 108#include <linux/skbuff.h>
 109
 110#undef READ
 111#undef WRITE
 112
 113extern struct net_device *init_etherdev(struct net_device *dev, int sizeof_private);
 114
 115/* use 0 for production, 1 for verification, >2 for debug
 116 */
 117#ifndef NET_DEBUG
 118#define NET_DEBUG 0
 119#endif
 120/*
 121 * Global variable 'pamsnet_debug'. Can be set at load time by 'insmod'
 122 */
 123unsigned int pamsnet_debug = NET_DEBUG;
 124MODULE_PARM(pamsnet_debug, "i");
 125MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)");
 126MODULE_LICENSE("GPL");
 127
 128static unsigned int pamsnet_min_poll_time = 2;
 129
 130
 131/* Information that need to be kept for each board.
 132 */
 133struct net_local {
 134        struct net_device_stats stats;
 135        long open_time;                 /* for debugging */
 136        int  poll_time;                 /* polling time varies with net load */
 137};
 138
 139static struct nic_pkt_s {               /* packet format */
 140        unsigned char   buffer[2048];
 141} *nic_packet = 0;
 142unsigned char *phys_nic_packet;
 143
 144typedef unsigned char HADDR[6]; /* 6-byte hardware address of lance */
 145
 146/* Index to functions, as function prototypes.
 147 */
 148static void     start (int target);
 149static int      stop (int target);
 150static int      testpkt (int target);
 151static int      sendpkt (int target, unsigned char *buffer, int length);
 152static int      receivepkt (int target, unsigned char *buffer);
 153static int      inquiry (int target, unsigned char *buffer);
 154static HADDR    *read_hw_addr(int target, unsigned char *buffer);
 155static void     setup_dma (void *address, unsigned rw_flag, int num_blocks);
 156static int      send_first (int target, unsigned char byte);
 157static int      send_1_5 (int lun, unsigned char *command, int dma);
 158static int      get_status (void);
 159static int      calc_received (void *start_address);
 160
 161extern int pamsnet_probe(struct net_device *dev);
 162
 163static int pamsnet_open(struct net_device *dev);
 164static int pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev);
 165static void pamsnet_poll_rx(struct net_device *);
 166static int pamsnet_close(struct net_device *dev);
 167static struct net_device_stats *net_get_stats(struct net_device *dev);
 168static void pamsnet_tick(unsigned long);
 169
 170static irqreturn_t pamsnet_intr(int irq, void *data, struct pt_regs *fp);
 171
 172static struct timer_list pamsnet_timer = TIMER_INITIALIZER(pamsnet_tick, 0, 0);
 173
 174#define STRAM_ADDR(a)   (((a) & 0xff000000) == 0)
 175
 176typedef struct
 177{
 178        unsigned char reserved1[0x38];
 179        HADDR  hwaddr;
 180        unsigned char reserved2[0x1c2];
 181} DMAHWADDR;
 182
 183/*
 184 * Definitions of commands understood by the PAMs DMA adaptor.
 185 *
 186 * In general the DMA adaptor uses LUN 0, 5, 6 and 7 on one ID changeable
 187 * by the PAM's Net software.
 188 *
 189 * LUN 0 works as a harddisk. You can boot the PAM's Net driver there.
 190 * LUN 5 works as a harddisk and lets you access the RAM and some I/O HW
 191 *       area. In sector 0, bytes 0x38-0x3d you find the ethernet HW address
 192 *       of the adaptor.
 193 * LUN 6 works as a harddisk and lets you access the firmware ROM.
 194 * LUN 7 lets you send and receive packets.
 195 *
 196 * Some commands like the INQUIRY command work identical on all used LUNs.
 197 *
 198 * UNKNOWN1 seems to read some data.
 199 *          Command length is 6 bytes.
 200 * UNKNOWN2 seems to read some data (command byte 1 must be !=0). The
 201 *          following bytes seem to be something like an allocation length.
 202 *          Command length is 6 bytes.
 203 * READPKT  reads a packet received by the DMA adaptor.
 204 *          Command length is 6 bytes.
 205 * WRITEPKT sends a packet transferred by the following DMA phase. The length
 206 *          of the packet is transferred in command bytes 3 and 4.
 207 *          The adaptor automatically replaces the src hw address in an ethernet
 208 *          packet by its own hw address.
 209 *          Command length is 6 bytes.
 210 * INQUIRY  has the same function as the INQUIRY command supported by harddisks
 211 *          and other SCSI devices. It lets you detect which device you found
 212 *          at a given address.
 213 *          Command length is 6 bytes.
 214 * START    initializes the DMA adaptor. After this command it is able to send
 215 *          and receive packets. There is no status byte returned!
 216 *          Command length is 1 byte.
 217 * NUMPKTS  gives back the number of received packets waiting in the queue in
 218 *          the status byte.
 219 *          Command length is 1 byte.
 220 * UNKNOWN3
 221 * UNKNOWN4 Function of these three commands is unknown.
 222 * UNKNOWN5 The command length of these three commands is 1 byte.
 223 * DESELECT immediately deselects the DMA adaptor. May important with interrupt
 224 *          driven operation.
 225 *          Command length is 1 byte.
 226 * STOP     resets the DMA adaptor. After this command packets can no longer
 227 *          be received or transferred.
 228 *          Command length is 6 byte.
 229 */
 230
 231enum {UNKNOWN1=3, READPKT=8, UNKNOWN2, WRITEPKT=10, INQUIRY=18, START,
 232      NUMPKTS=22, UNKNOWN3, UNKNOWN4, UNKNOWN5, DESELECT, STOP};
 233
 234#define READSECTOR  READPKT
 235#define WRITESECTOR WRITEPKT
 236
 237u_char *inquire8="MV      PAM's NET/GK";
 238
 239#define DMALOW   dma_wd.dma_lo
 240#define DMAMID   dma_wd.dma_md
 241#define DMAHIGH  dma_wd.dma_hi
 242#define DACCESS  dma_wd.fdc_acces_seccount
 243
 244#define MFP_GPIP mfp.par_dt_reg
 245
 246/* Some useful functions */
 247
 248#define INT      (!(MFP_GPIP & 0x20))
 249#define DELAY ({MFP_GPIP; MFP_GPIP; MFP_GPIP;})
 250#define WRITEMODE(value)                                        \
 251        ({      u_short dummy = value;                          \
 252                __asm__ volatile("movew %0, 0xFFFF8606" : : "d"(dummy));        \
 253                DELAY;                                          \
 254        })
 255#define WRITEBOTH(value1, value2)                               \
 256        ({      u_long dummy = (u_long)(value1)<<16 | (u_short)(value2);        \
 257                __asm__ volatile("movel %0, 0xFFFF8604" : : "d"(dummy));        \
 258                DELAY;                                          \
 259        })
 260
 261/* Definitions for DMODE */
 262
 263#define READ        0x000
 264#define WRITE       0x100
 265
 266#define DMA_FDC     0x080
 267#define DMA_ACSI    0x000
 268
 269#define DMA_DISABLE 0x040
 270
 271#define SEC_COUNT   0x010
 272#define DMA_WINDOW  0x000
 273
 274#define REG_ACSI    0x008
 275#define REG_FDC     0x000
 276
 277#define A1          0x002
 278
 279/* Timeout constants */
 280
 281#define TIMEOUTCMD HZ/2   /* ca. 500ms */
 282#define TIMEOUTDMA HZ     /* ca. 1s */
 283#define COMMAND_DELAY 500 /* ca. 0.5ms */
 284
 285unsigned rw;
 286int lance_target = -1;
 287int if_up = 0;
 288
 289/* The following routines access the ethernet board connected to the
 290 * ACSI port via the st_dma chip.
 291 */
 292
 293/* The following lowlevel routines work on physical addresses only and assume
 294 * that eventually needed buffers are
 295 * - completely located in ST RAM
 296 * - are contigous in the physical address space
 297 */
 298
 299/* Setup the DMA counter */
 300
 301static void
 302setup_dma (address, rw_flag, num_blocks)
 303        void *address;
 304        unsigned rw_flag;
 305        int num_blocks;
 306{
 307        WRITEMODE((unsigned) rw_flag          | DMA_FDC | SEC_COUNT | REG_ACSI |
 308                  A1);
 309        WRITEMODE((unsigned)(rw_flag ^ WRITE) | DMA_FDC | SEC_COUNT | REG_ACSI |
 310                  A1);
 311        WRITEMODE((unsigned) rw_flag          | DMA_FDC | SEC_COUNT | REG_ACSI |
 312                  A1);
 313        DMALOW  = (unsigned char)((unsigned long)address & 0xFF);
 314        DMAMID  = (unsigned char)(((unsigned long)address >>  8) & 0xFF);
 315        DMAHIGH = (unsigned char)(((unsigned long)address >> 16) & 0xFF);
 316        WRITEBOTH((unsigned)num_blocks & 0xFF,
 317                  rw_flag | DMA_FDC | DMA_WINDOW | REG_ACSI | A1);
 318        rw = rw_flag;
 319}
 320
 321/* Send the first byte of an command block */
 322
 323static int
 324send_first (target, byte)
 325        int target;
 326        unsigned char byte;
 327{
 328        rw = READ;
 329        acsi_delay_end(COMMAND_DELAY);
 330        /*
 331         * wake up ACSI
 332         */
 333        WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI);
 334        /*
 335         * write command byte
 336         */
 337        WRITEBOTH((target << 5) | (byte & 0x1F), DMA_FDC |
 338                  DMA_WINDOW | REG_ACSI | A1);
 339        return (!acsi_wait_for_IRQ(TIMEOUTCMD));
 340}
 341
 342/* Send the rest of an command block */
 343
 344static int
 345send_1_5 (lun, command, dma)
 346        int lun;
 347        unsigned char *command;
 348        int dma;
 349{
 350        int i, j;
 351
 352        for (i=0; i<5; i++) {
 353                WRITEBOTH((!i ? (((lun & 0x7) << 5) | (command[i] & 0x1F))
 354                              : command[i]),
 355                          rw | REG_ACSI | DMA_WINDOW |
 356                           ((i < 4) ? DMA_FDC
 357                                    : (dma ? DMA_ACSI
 358                                           : DMA_FDC)) | A1);
 359                if (i < 4 && (j = !acsi_wait_for_IRQ(TIMEOUTCMD)))
 360                        return (j);
 361        }
 362        return (0);
 363}
 364
 365/* Read a status byte */
 366
 367static int
 368get_status (void)
 369{
 370        WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI | A1);
 371        acsi_delay_start();
 372        return ((int)(DACCESS & 0xFF));
 373}
 374
 375/* Calculate the number of received bytes */
 376
 377static int
 378calc_received (start_address)
 379        void *start_address;
 380{
 381        return (int)(
 382                (((unsigned long)DMAHIGH << 16) | ((unsigned)DMAMID << 8) | DMALOW)
 383              - (unsigned long)start_address);
 384}
 385
 386/* The following midlevel routines still work on physical addresses ... */
 387
 388/* start() starts the PAM's DMA adaptor */
 389
 390static void
 391start (target)
 392        int target;
 393{
 394        send_first(target, START);
 395}
 396
 397/* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */
 398
 399static int
 400stop (target)
 401        int target;
 402{
 403        int ret = -1;
 404        unsigned char cmd_buffer[5];
 405
 406        if (send_first(target, STOP))
 407                goto bad;
 408        cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] =
 409        cmd_buffer[3] = cmd_buffer[4] = 0;
 410        if (send_1_5(7, cmd_buffer, 0) ||
 411            !acsi_wait_for_IRQ(TIMEOUTDMA) ||
 412            get_status())
 413                goto bad;
 414        ret = 0;
 415bad:
 416        return (ret);
 417}
 418
 419/* testpkt() returns the number of received packets waiting in the queue */
 420
 421static int
 422testpkt(target)
 423        int target;
 424{
 425        int ret = -1;
 426
 427        if (send_first(target, NUMPKTS))
 428                goto bad;
 429        ret = get_status();
 430bad:
 431        return (ret);
 432}
 433
 434/* inquiry() returns 0 when PAM's DMA found, -1 when timeout, -2 otherwise */
 435/* Please note: The buffer is for internal use only but must be defined!   */
 436
 437static int
 438inquiry (target, buffer)
 439        int target;
 440        unsigned char *buffer;
 441{
 442        int ret = -1;
 443        unsigned char *vbuffer = phys_to_virt((unsigned long)buffer);
 444        unsigned char cmd_buffer[5];
 445
 446        if (send_first(target, INQUIRY))
 447                goto bad;
 448        setup_dma(buffer, READ, 1);
 449        vbuffer[8] = vbuffer[27] = 0; /* Avoid confusion with previous read data */
 450        cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0;
 451        cmd_buffer[3] = 48;
 452        if (send_1_5(5, cmd_buffer, 1) ||
 453            !acsi_wait_for_IRQ(TIMEOUTDMA) ||
 454            get_status() ||
 455            (calc_received(buffer) < 32))
 456                goto bad;
 457        dma_cache_maintenance((unsigned long)(buffer+8), 20, 0);
 458        if (memcmp(inquire8, vbuffer+8, 20))
 459                goto bad;
 460        ret = 0;
 461bad:
 462        if (!!NET_DEBUG) {
 463                vbuffer[8+20]=0;
 464                printk("inquiry of target %d: %s\n", target, vbuffer+8);
 465        }
 466        return (ret);
 467}
 468
 469/*
 470 * read_hw_addr() reads the sector containing the hwaddr and returns
 471 * a pointer to it (virtual address!) or 0 in case of an error
 472 */
 473
 474static HADDR
 475*read_hw_addr(target, buffer)
 476        int target;
 477        unsigned char *buffer;
 478{
 479        HADDR *ret = 0;
 480        unsigned char cmd_buffer[5];
 481
 482        if (send_first(target, READSECTOR))
 483                goto bad;
 484        setup_dma(buffer, READ, 1);
 485        cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0;
 486        cmd_buffer[3] = 1;
 487        if (send_1_5(5, cmd_buffer, 1) ||
 488            !acsi_wait_for_IRQ(TIMEOUTDMA) ||
 489            get_status())
 490                goto bad;
 491        ret = phys_to_virt(&(((DMAHWADDR *)buffer)->hwaddr));
 492        dma_cache_maintenance((unsigned long)buffer, 512, 0);
 493bad:
 494        return (ret);
 495}
 496
 497static irqreturn_t
 498pamsnet_intr(irq, data, fp)
 499        int irq;
 500        void *data;
 501        struct pt_regs *fp;
 502{
 503        return IRQ_HANDLED;
 504}
 505
 506/* receivepkt() loads a packet to a given buffer and returns its length */
 507
 508static int
 509receivepkt (target, buffer)
 510        int target;
 511        unsigned char *buffer;
 512{
 513        int ret = -1;
 514        unsigned char cmd_buffer[5];
 515
 516        if (send_first(target, READPKT))
 517                goto bad;
 518        setup_dma(buffer, READ, 3);
 519        cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0;
 520        cmd_buffer[3] = 3;
 521        if (send_1_5(7, cmd_buffer, 1) ||
 522            !acsi_wait_for_IRQ(TIMEOUTDMA) ||
 523            get_status())
 524                goto bad;
 525        ret = calc_received(buffer);
 526bad:
 527        return (ret);
 528}
 529
 530/* sendpkt() sends a packet and returns a value of zero when the packet was sent
 531             successfully */
 532
 533static int
 534sendpkt (target, buffer, length)
 535        int target;
 536        unsigned char *buffer;
 537        int length;
 538{
 539        int ret = -1;
 540        unsigned char cmd_buffer[5];
 541
 542        if (send_first(target, WRITEPKT))
 543                goto bad;
 544        setup_dma(buffer, WRITE, 3);
 545        cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[4] = 0;
 546        cmd_buffer[2] = length >> 8;
 547        cmd_buffer[3] = length & 0xFF;
 548        if (send_1_5(7, cmd_buffer, 1) ||
 549            !acsi_wait_for_IRQ(TIMEOUTDMA) ||
 550            get_status())
 551                goto bad;
 552        ret = 0;
 553bad:
 554        return (ret);
 555}
 556
 557/* The following higher level routines work on virtual addresses and convert them to
 558 * physical addresses when passed to the lowlevel routines. It's up to the higher level
 559 * routines to copy data from Alternate RAM to ST RAM if neccesary!
 560 */
 561
 562/* Check for a network adaptor of this type, and return '0' if one exists.
 563 */
 564
 565int __init 
 566pamsnet_probe (dev)
 567        struct net_device *dev;
 568{
 569        int i;
 570        HADDR *hwaddr;
 571
 572        unsigned char station_addr[6];
 573        static unsigned version_printed;
 574        /* avoid "Probing for..." printed 4 times - the driver is supporting only one adapter now! */
 575        static int no_more_found;
 576
 577        if (no_more_found)
 578                return -ENODEV;
 579
 580        SET_MODULE_OWNER(dev);
 581
 582        no_more_found = 1;
 583
 584        printk("Probing for PAM's Net/GK Adapter...\n");
 585
 586        /* Allocate the DMA buffer here since we need it for probing! */
 587
 588        nic_packet = (struct nic_pkt_s *)acsi_buffer;
 589        phys_nic_packet = (unsigned char *)phys_acsi_buffer;
 590        if (pamsnet_debug > 0) {
 591                printk("nic_packet at 0x%p, phys at 0x%p\n",
 592                           nic_packet, phys_nic_packet );
 593        }
 594
 595        stdma_lock(pamsnet_intr, NULL);
 596        DISABLE_IRQ();
 597
 598        for (i=0; i<8; i++) {
 599                /* Do two inquiries to cover cases with strange equipment on previous ID */
 600                /* blocking the ACSI bus (like the SLMC804 laser printer controller...   */
 601                inquiry(i, phys_nic_packet);
 602                if (!inquiry(i, phys_nic_packet)) {
 603                        lance_target = i;
 604                        break;
 605                }
 606        }
 607
 608        if (!!NET_DEBUG)
 609                printk("ID: %d\n",i);
 610
 611        if (lance_target >= 0) {
 612                if (!(hwaddr = read_hw_addr(lance_target, phys_nic_packet)))
 613                        lance_target = -1;
 614                else
 615                        memcpy (station_addr, hwaddr, ETH_ALEN);
 616        }
 617
 618        ENABLE_IRQ();
 619        stdma_release();
 620
 621        if (lance_target < 0)
 622                printk("No PAM's Net/GK found.\n");
 623
 624        if ((dev == NULL) || (lance_target < 0))
 625                return -ENODEV;
 626        if (pamsnet_debug > 0 && version_printed++ == 0)
 627                printk(version);
 628
 629        printk("%s: %s found on target %01d, eth-addr: %02x:%02x:%02x:%02x:%02x:%02x.\n",
 630                dev->name, "PAM's Net/GK", lance_target,
 631                station_addr[0], station_addr[1], station_addr[2],
 632                station_addr[3], station_addr[4], station_addr[5]);
 633
 634        /* Initialize the device structure. */
 635        if (dev->priv == NULL)
 636                dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
 637        if (!dev->priv)
 638                return -ENOMEM;
 639        memset(dev->priv, 0, sizeof(struct net_local));
 640
 641        dev->open               = pamsnet_open;
 642        dev->stop               = pamsnet_close;
 643        dev->hard_start_xmit    = pamsnet_send_packet;
 644        dev->get_stats          = net_get_stats;
 645
 646        /* Fill in the fields of the device structure with ethernet-generic
 647         * values. This should be in a common file instead of per-driver.
 648         */
 649
 650        for (i = 0; i < ETH_ALEN; i++) {
 651#if 0
 652                dev->broadcast[i] = 0xff;
 653#endif
 654                dev->dev_addr[i]  = station_addr[i];
 655        }
 656        ether_setup(dev);
 657
 658        return(0);
 659}
 660
 661/* Open/initialize the board.  This is called (in the current kernel)
 662   sometime after booting when the 'ifconfig' program is run.
 663
 664   This routine should set everything up anew at each open, even
 665   registers that "should" only need to be set once at boot, so that
 666   there is non-reboot way to recover if something goes wrong.
 667 */
 668static int
 669pamsnet_open(struct net_device *dev) {
 670        struct net_local *lp = (struct net_local *)dev->priv;
 671
 672        if (pamsnet_debug > 0)
 673                printk("pamsnet_open\n");
 674        stdma_lock(pamsnet_intr, NULL);
 675        DISABLE_IRQ();
 676
 677        /* Reset the hardware here.
 678         */
 679        if (!if_up)
 680                start(lance_target);
 681        if_up = 1;
 682        lp->open_time = 0;      /*jiffies*/
 683        lp->poll_time = MAX_POLL_TIME;
 684
 685        dev->tbusy = 0;
 686        dev->interrupt = 0;
 687        dev->start = 1;
 688
 689        ENABLE_IRQ();
 690        stdma_release();
 691        pamsnet_timer.data = (long)dev;
 692        pamsnet_timer.expires = jiffies + lp->poll_time;
 693        add_timer(&pamsnet_timer);
 694        return 0;
 695}
 696
 697static int
 698pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) {
 699        struct net_local *lp = (struct net_local *)dev->priv;
 700        unsigned long flags;
 701
 702        /* Block a timer-based transmit from overlapping.  This could better be
 703         * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
 704         */
 705        local_irq_save(flags);
 706
 707        if (stdma_islocked()) {
 708                local_irq_restore(flags);
 709                lp->stats.tx_errors++;
 710        }
 711        else {
 712                int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 713                unsigned long buf = virt_to_phys(skb->data);
 714                int stat;
 715
 716                stdma_lock(pamsnet_intr, NULL);
 717                DISABLE_IRQ();
 718
 719                local_irq_restore(flags);
 720                if( !STRAM_ADDR(buf+length-1) ) {
 721                        memcpy(nic_packet->buffer, skb->data, length);
 722                        buf = (unsigned long)phys_nic_packet;
 723                }
 724
 725                dma_cache_maintenance(buf, length, 1);
 726
 727                stat = sendpkt(lance_target, (unsigned char *)buf, length);
 728                ENABLE_IRQ();
 729                stdma_release();
 730
 731                dev->trans_start = jiffies;
 732                dev->tbusy       = 0;
 733                lp->stats.tx_packets++;
 734                lp->stats.tx_bytes+=length;
 735        }
 736        dev_kfree_skb(skb);
 737
 738        return 0;
 739}
 740
 741/* We have a good packet(s), get it/them out of the buffers.
 742 */
 743static void
 744pamsnet_poll_rx(struct net_device *dev) {
 745        struct net_local *lp = (struct net_local *)dev->priv;
 746        int boguscount;
 747        int pkt_len;
 748        struct sk_buff *skb;
 749        unsigned long flags;
 750
 751        local_irq_save(flags);
 752        /* ++roman: Take care at locking the ST-DMA... This must be done with ints
 753         * off, since otherwise an int could slip in between the question and the
 754         * locking itself, and then we'd go to sleep... And locking itself is
 755         * necessary to keep the floppy_change timer from working with ST-DMA
 756         * registers. */
 757        if (stdma_islocked()) {
 758                local_irq_restore(flags);
 759                return;
 760        }
 761        stdma_lock(pamsnet_intr, NULL);
 762        DISABLE_IRQ();
 763        local_irq_restore(flags);
 764
 765        boguscount = testpkt(lance_target);
 766        if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
 767
 768        while(boguscount--) {
 769                pkt_len = receivepkt(lance_target, phys_nic_packet);
 770
 771                if( pkt_len < 60 ) break;
 772
 773                /* Good packet... */
 774
 775                dma_cache_maintenance((unsigned long)phys_nic_packet, pkt_len, 0);
 776
 777                lp->poll_time = pamsnet_min_poll_time;    /* fast poll */
 778                if( pkt_len >= 60 && pkt_len <= 2048 ) {
 779                        if (pkt_len > 1514)
 780                                pkt_len = 1514;
 781
 782                        /* Malloc up new buffer.
 783                         */
 784                        skb = alloc_skb(pkt_len, GFP_ATOMIC);
 785                        if (skb == NULL) {
 786                                printk("%s: Memory squeeze, dropping packet.\n",
 787                                        dev->name);
 788                                lp->stats.rx_dropped++;
 789                                break;
 790                        }
 791                        skb->len = pkt_len;
 792                        skb->dev = dev;
 793
 794                        /* 'skb->data' points to the start of sk_buff data area.
 795                         */
 796                        memcpy(skb->data, nic_packet->buffer, pkt_len);
 797                        netif_rx(skb);
 798                        dev->last_rx = jiffies;
 799                        lp->stats.rx_packets++;
 800                        lp->stats.rx_bytes+=pkt_len;
 801                }
 802        }
 803
 804        /* If any worth-while packets have been received, dev_rint()
 805           has done a mark_bh(INET_BH) for us and will work on them
 806           when we get to the bottom-half routine.
 807         */
 808
 809        ENABLE_IRQ();
 810        stdma_release();
 811        return;
 812}
 813
 814/* pamsnet_tick: called by pamsnet_timer. Reads packets from the adapter,
 815 * passes them to the higher layers and restarts the timer.
 816 */
 817static void
 818pamsnet_tick(unsigned long data) {
 819        struct net_device        *dev = (struct net_device *)data;
 820        struct net_local *lp = (struct net_local *)dev->priv;
 821
 822        if( pamsnet_debug > 0 && (lp->open_time++ & 7) == 8 )
 823                printk("pamsnet_tick: %ld\n", lp->open_time);
 824
 825        pamsnet_poll_rx(dev);
 826
 827        pamsnet_timer.expires = jiffies + lp->poll_time;
 828        add_timer(&pamsnet_timer);
 829}
 830
 831/* The inverse routine to pamsnet_open().
 832 */
 833static int
 834pamsnet_close(struct net_device *dev) {
 835        struct net_local *lp = (struct net_local *)dev->priv;
 836
 837        if (pamsnet_debug > 0)
 838                printk("pamsnet_close, open_time=%ld\n", lp->open_time);
 839        del_timer(&pamsnet_timer);
 840        stdma_lock(pamsnet_intr, NULL);
 841        DISABLE_IRQ();
 842
 843        if (if_up)
 844                stop(lance_target);
 845        if_up = 0;
 846
 847        lp->open_time = 0;
 848
 849        dev->tbusy = 1;
 850        dev->start = 0;
 851
 852        ENABLE_IRQ();
 853        stdma_release();
 854        return 0;
 855}
 856
 857/* Get the current statistics.
 858   This may be called with the card open or closed.
 859 */
 860static struct net_device_stats *net_get_stats(struct net_device *dev) 
 861{
 862        struct net_local *lp = (struct net_local *)dev->priv;
 863        return &lp->stats;
 864}
 865
 866
 867#ifdef MODULE
 868
 869static struct net_device pam_dev;
 870
 871int
 872init_module(void) {
 873        int err;
 874
 875        pam_dev.init = pamsnet_probe;
 876        if ((err = register_netdev(&pam_dev))) {
 877                if (err == -EEXIST)  {
 878                        printk("PAM's Net/GK: devices already present. Module not loaded.\n");
 879                }
 880                return err;
 881        }
 882        return 0;
 883}
 884
 885void
 886cleanup_module(void) {
 887        unregister_netdev(&pam_dev);
 888}
 889
 890#endif /* MODULE */
 891
 892/* Local variables:
 893 *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include
 894        -b m68k-linuxaout -Wall -Wstrict-prototypes -O2
 895        -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c atari_pamsnet.c"
 896 *  version-control: t
 897 *  kept-new-versions: 5
 898 *  tab-width: 8
 899 * End:
 900 */
 901
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.