OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [net/] [pt.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
#undef PT_DEBUG 1
2
/*
3
 * pt.c: Linux device driver for the Gracilis PackeTwin.
4
 * Copyright (c) 1995 Craig Small VK2XLZ (vk2xlz@vk2xlz.ampr.org.)
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 version 2, as
8
 * published by the Free Software Foundation.
9
 *
10
 * This program is distributed in the hope that it will be useful, but
11
 * WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
 * General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software Foundation,
17
 * Inc., 675 Mass Ave, Cambridge MA 02139, USA.
18
 *
19
 * This driver is largely based upon the PI driver by David Perry.
20
 *
21
 * Revision History
22
 * 23/02/95 cs  Started again on driver, last one scrapped
23
 * 27/02/95 cs  Program works, we have chan A only.  Tx stays on
24
 * 28/02/95 cs  Fix Tx problem (& TxUIE instead of | )
25
 *              Fix Chan B Tx timer problem, used TMR2 instead of TMR1
26
 * 03/03/95 cs  Painfully found out (after 3 days) SERIAL_CFG is write only
27
 *              created image of it and DMA_CFG
28
 * 21/06/95 cs  Upgraded to suit PI driver 0.8 ALPHA
29
 * 22/08/95     cs      Changed it all around to make it like pi driver
30
 * 23/08/95 cs  It now works, got caught again by TMR2 and we must have
31
 *                              auto-enables for daughter boards.
32
 * 07/10/95 cs  Fixed for 1.3.30 (hopefully)
33
 * 26/11/95 cs  Fixed for 1.3.43, ala 29/10 for pi2.c by ac
34
 * 21/12/95 cs  Got rid of those nasty warnings when compiling, for 1.3.48
35
 * 08/08/96 jsn Convert to use as a module. Removed send_kiss, empty_scc and
36
 *              pt_loopback functions - they were unused.
37
 */
38
 
39
/*
40
 * default configuration of the PackeTwin,
41
 * ie What Craig uses his PT for.
42
 */
43
#define PT_DMA 3
44
 
45
#define DEF_A_SPEED     4800            /* 4800 baud */
46
#define DEF_A_TXDELAY   350             /* 350 mS */
47
#define DEF_A_PERSIST   64              /* 25% persistence */
48
#define DEF_A_SLOTIME   10              /* 10 mS */
49
#define DEF_A_SQUELDELAY 30             /* 30 mS */
50
#define DEF_A_CLOCKMODE 0                /* Normal clock mode */
51
#define DEF_A_NRZI              1               /* NRZI mode */
52
 
53
#define DEF_B_SPEED     0                /* 0 means external clock */
54
#define DEF_B_TXDELAY   250             /* 250 mS */
55
#define DEF_B_PERSIST   64              /* 25% */
56
#define DEF_B_SLOTIME   10              /* 10 mS */
57
#define DEF_B_SQUELDELAY 30             /* 30 mS */
58
#define DEF_B_CLOCKMODE 0               /* Normal clock mode ?!? */
59
#define DEF_B_NRZI              1               /* NRZI mode */
60
 
61
 
62
#define PARAM_TXDELAY   1
63
#define PARAM_PERSIST   2
64
#define PARAM_SLOTTIME  3
65
#define PARAM_FULLDUP   5
66
#define PARAM_HARDWARE  6
67
#define PARAM_RETURN    255
68
 
69
#include <linux/config.h>
70
#include <linux/kernel.h>
71
#include <linux/module.h>
72
#include <linux/sched.h>
73
#include <linux/types.h>
74
#include <linux/fcntl.h>
75
#include <linux/interrupt.h>
76
#include <linux/ptrace.h>
77
#include <linux/ioport.h>
78
#include <linux/in.h>
79
#include <linux/malloc.h>
80
#include <linux/string.h>
81
#include <linux/errno.h>
82
#include <asm/system.h>
83
#include <asm/bitops.h>
84
#include <asm/io.h>
85
#include <asm/dma.h>
86
#include <asm/segment.h>
87
#include <linux/inet.h>
88
#include <linux/netdevice.h>
89
#include <linux/etherdevice.h>
90
#include <linux/skbuff.h>
91
#include <linux/timer.h>
92
#include <linux/if_arp.h>
93
#include <linux/pt.h>
94
#include "z8530.h"
95
#include <net/ax25.h>
96
 
97
struct mbuf {
98
    struct mbuf *next;
99
    int cnt;
100
    char data[0];
101
};
102
 
103
/*
104
 * The actual PT devices we will use
105
 */
106
static int pt0_preprobe(struct device *dev) {return 0;} /* Dummy probe function */
107
static struct device pt0a = { "pt0a", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pt0_preprobe };
108
static struct device pt0b = { "pt0b", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pt0_preprobe };
109
 
110
/* Ok, they shouldn't be here, but both channels share them */
111
/* The Images of the Serial and DMA config registers */
112
static unsigned char pt_sercfg = 0;
113
static unsigned char pt_dmacfg = 0;
114
 
115
/* The number of IO ports used by the card */
116
#define PT_TOTAL_SIZE   16
117
 
118
/* Index to functions, as function prototypes. */
119
 
120
static int pt_probe(struct device *dev);
121
static int pt_open(struct device *dev);
122
static int pt_send_packet(struct sk_buff *skb, struct device *dev);
123
static void pt_interrupt(int irq, void *dev_id, struct pt_regs *regs);
124
static int pt_close(struct device *dev);
125
static int pt_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
126
static struct enet_statistics *pt_get_stats(struct device *dev);
127
static void pt_rts(struct pt_local *lp, int x);
128
static void pt_rxisr(struct device *dev);
129
static void pt_txisr(struct pt_local *lp);
130
static void pt_exisr(struct pt_local *lp);
131
static void pt_tmrisr(struct pt_local *lp);
132
static char *get_dma_buffer(unsigned long *mem_ptr);
133
static int valid_dma_page(unsigned long addr, unsigned long dev_buffsize);
134
static int hw_probe(int ioaddr);
135
static void tdelay(struct pt_local *lp, int time);
136
static void chipset_init(struct device *dev);
137
 
138
static char ax25_bcast[7] =
139
{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
140
static char ax25_test[7] =
141
{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
142
 
143
 
144
 
145
static int ext2_secrm_seed = 152;
146
 
147
static inline unsigned char random(void)
148
{
149
    return (unsigned char) (ext2_secrm_seed = ext2_secrm_seed * 60691 + 1);
150
}
151
 
152
static inline void wrtscc(int cbase, int ctl, int sccreg, unsigned char val)
153
{
154
    outb_p(sccreg, ctl);        /* Select register */
155
    outb_p(val, ctl);           /* Output value */
156
}
157
 
158
static inline unsigned char rdscc(int cbase, int ctl, int sccreg)
159
{
160
    unsigned char retval;
161
 
162
    outb_p(sccreg, ctl);        /* Select register */
163
    retval = inb_p(ctl);
164
    return retval;
165
}
166
 
167
static void switchbuffers(struct pt_local *lp)
168
{
169
    if (lp->rcvbuf == lp->rxdmabuf1)
170
        lp->rcvbuf = lp->rxdmabuf2;
171
    else
172
        lp->rcvbuf = lp->rxdmabuf1;
173
}
174
 
175
static void hardware_send_packet(struct pt_local *lp, struct sk_buff *skb)
176
{
177
    char kickflag;
178
    unsigned long flags;
179
    char *ptr;
180
    struct device *dev;
181
 
182
        /* First, let's see if this packet is actually a KISS packet */
183
        ptr = skb->data;
184
        if (ptr[0] != 0 && skb->len >= 2)
185
        {
186
#ifdef PT_DEBUG
187
                printk(KERN_DEBUG "PT: Rx KISS... Control = %d, value = %d.\n", ptr[0], (skb->len > 1? ptr[1] : -1));
188
#endif
189
                /* Kludge to get device */
190
                if ((struct pt_local*)(&pt0b.priv) == lp)
191
                        dev = &pt0b;
192
                else
193
                        dev = &pt0a;
194
                switch(ptr[0])
195
                {
196
 
197
                        case PARAM_TXDELAY:
198
                                /*TxDelay is in 10mS increments */
199
                                lp->txdelay = ptr[1] * 10;
200
                                break;
201
                        case PARAM_PERSIST:
202
                                lp->persist = ptr[1];
203
                                break;
204
                        case PARAM_SLOTTIME:
205
                                lp->slotime = ptr[1];
206
                                break;
207
                        case PARAM_FULLDUP:
208
                                /* Yeah right, you wish!  Fullduplex is a little while to
209
                                 * go folks, but this is how you fire it up
210
                                 */
211
                                break;
212
                        /* Perhaps we should have txtail here?? */
213
                } /*switch */
214
                return;
215
        }
216
 
217
    lp->stats.tx_packets++;
218
 
219
    save_flags(flags);
220
    cli();
221
    kickflag = (skb_peek(&lp->sndq) == NULL) && (lp->sndbuf == NULL);
222
    restore_flags(flags);
223
 
224
#ifdef PT_DEBUG
225
        printk(KERN_DEBUG "PT: hardware_send_packet(): kickflag = %d (%d).\n", kickflag, lp->base & CHANA);
226
#endif  
227
    skb_queue_tail(&lp->sndq, skb);
228
    if (kickflag) {
229
        /* Simulate interrupt to transmit */
230
            if (lp->dmachan)
231
            {
232
                pt_txisr(lp);
233
            } else {
234
                save_flags(flags);
235
                        cli();
236
                if (lp->tstate == IDLE)
237
                        pt_txisr(lp);
238
                restore_flags(flags);
239
            }
240
    }
241
} /* hardware_send_packet() */
242
 
243
static void setup_rx_dma(struct pt_local *lp)
244
{
245
    unsigned long flags;
246
    int cmd;
247
    unsigned long dma_abs;
248
    unsigned char dmachan;
249
 
250
    save_flags(flags);
251
    cli();
252
 
253
    dma_abs = (unsigned long) (lp->rcvbuf->data);
254
    dmachan = lp->dmachan;
255
    cmd = lp->base + CTL;
256
 
257
    if(!valid_dma_page(dma_abs, DMA_BUFF_SIZE + sizeof(struct mbuf)))
258
        panic("PI: RX buffer violates DMA boundary!");
259
 
260
    /* Get ready for RX DMA */
261
    wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | WT_RDY_RT | INT_ERR_Rx | EXT_INT_ENAB);
262
 
263
    disable_dma(dmachan);
264
    clear_dma_ff(dmachan);
265
 
266
    /* Set DMA mode register to single transfers, incrementing address,
267
     *  auto init, writes
268
     */
269
    set_dma_mode(dmachan, DMA_MODE_READ | 0x10);
270
    set_dma_addr(dmachan, dma_abs);
271
    set_dma_count(dmachan, lp->bufsiz);
272
    enable_dma(dmachan);
273
 
274
    /* If a packet is already coming in, this line is supposed to
275
           avoid receiving a partial packet.
276
     */
277
    wrtscc(lp->cardbase, cmd, R0, RES_Rx_CRC);
278
 
279
    /* Enable RX dma */
280
    wrtscc(lp->cardbase, cmd, R1,
281
      WT_RDY_ENAB | WT_FN_RDYFN | WT_RDY_RT | INT_ERR_Rx | EXT_INT_ENAB);
282
 
283
    restore_flags(flags);
284
}
285
 
286
static void setup_tx_dma(struct pt_local *lp, int length)
287
{
288
    unsigned long dma_abs;
289
    unsigned long flags;
290
    unsigned long dmachan;
291
 
292
    save_flags(flags);
293
    cli();
294
 
295
    dmachan = lp->dmachan;
296
    dma_abs = (unsigned long) (lp->txdmabuf);
297
 
298
    if(!valid_dma_page(dma_abs, DMA_BUFF_SIZE + sizeof(struct mbuf)))
299
        panic("PT: TX buffer violates DMA boundary!");
300
 
301
    disable_dma(dmachan);
302
    /* Set DMA mode register to single transfers, incrementing address,
303
     *  no auto init, reads
304
     */
305
    set_dma_mode(dmachan, DMA_MODE_WRITE);
306
    clear_dma_ff(dmachan);
307
    set_dma_addr(dmachan, dma_abs);
308
    /* output byte count */
309
    set_dma_count(dmachan, length);
310
 
311
    restore_flags(flags);
312
}
313
 
314
static void free_p(struct sk_buff *skb)
315
{
316
    dev_kfree_skb(skb, FREE_WRITE);
317
}
318
 
319
/* Fill in the MAC-level header */
320
static int pt_header (struct sk_buff *skb, struct device *dev, unsigned short type,
321
                void *daddr, void *saddr, unsigned len)
322
{
323
        return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
324
}
325
 
326
 
327
/* Rebuild the MAC-level header */
328
static int pt_rebuild_header(void *buff, struct device *dev, unsigned long raddr,
329
                                struct sk_buff *skb)
330
{
331
        return ax25_rebuild_header(buff, dev, raddr, skb);
332
}
333
 
334
 
335
 
336
 
337
 
338
/*
339
 * This sets up all the registers in the SCC for the given channel
340
 * based upon tsync_hwint()
341
 */
342
static void scc_init(struct device *dev)
343
{
344
    unsigned long flags;
345
    struct pt_local *lp = (struct pt_local*) dev->priv;
346
    register int cmd = lp->base + CTL;
347
    int tc, br;
348
 
349
#ifdef PT_DEBUG
350
        printk(KERN_DEBUG "PT: scc_init(): (%d).\n", lp->base & CHANA);
351
#endif  
352
    save_flags(flags);
353
    cli();
354
 
355
    /* We may put something here to enable_escc */
356
 
357
    if (cmd & CHANA)
358
    {
359
        wrtscc(lp->cardbase, cmd, R9, CHRA);            /* Reset channel A */
360
        wrtscc(lp->cardbase, cmd, R2, 0xff);            /* Initialise interrupt vector */
361
    } else {
362
        wrtscc(lp->cardbase, cmd, R9, CHRB);            /* Reset channel B */
363
    }
364
 
365
    /* Deselect all Rx and Tx interrupts */
366
    wrtscc(lp->cardbase, cmd, R1, 0);
367
 
368
    /* Turn off external interrupts (like CTS/CD) */
369
    wrtscc(lp->cardbase, cmd, R15, 0);
370
 
371
    /* X1 clock, SDLC mode */
372
    wrtscc(lp->cardbase, cmd, R4, SDLC | X1CLK);
373
 
374
        /* Preset CRC and set mode */
375
        if (lp->nrzi)
376
        {
377
        /* Preset Tx CRC, put into NRZI mode */
378
       wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
379
    } else {
380
        /* Preset Tx CRC, put into NRZ mode */
381
       wrtscc(lp->cardbase, cmd, R10, CRCPS);
382
    }
383
 
384
    /* Tx/Rx parameters */
385
    if (lp->speed)              /* Use internal clocking */
386
    {
387
       /* Tx Clk from BRG. Rx Clk form DPLL, TRxC pin outputs DPLL */
388
       wrtscc(lp->cardbase, cmd, R11, TCBR | RCDPLL | TRxCDP | TRxCOI);
389
 
390
    } else {                    /* Use external clocking */
391
           /* Tx Clk from TRxCL. Rx Clk from RTxCL, TRxC pin if input */
392
           wrtscc(lp->cardbase, cmd, R11, TCTRxCP | RCRTxCP | TRxCBR);
393
           wrtscc(lp->cardbase,cmd, R14, 0);     /* wiz1 */
394
    }
395
 
396
    /* Null out SDLC start address */
397
    wrtscc(lp->cardbase, cmd, R6, 0);
398
 
399
    /* SDLC flag */
400
    wrtscc(lp->cardbase, cmd, R7, FLAG);
401
 
402
    /* Setup Tx but don't enable it */
403
    wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR);
404
 
405
    /* Setup Rx */
406
    wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8);
407
 
408
    /* Setup the BRG, turn it off first */
409
    wrtscc(lp->cardbase, cmd, R14, BRSRC);
410
 
411
    /* set the 32x time constant for the BRG in Rx mode */
412
        if (lp->speed)
413
        {
414
                br = lp->speed;
415
                tc = ((lp->xtal / 32) / (br * 2)) - 2;
416
            wrtscc(lp->cardbase, cmd, R12, tc & 0xff);          /* lower byte */
417
                wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);       /* upper byte */
418
        }
419
 
420
        /* Turn transmitter off, to setup stuff */
421
        pt_rts(lp, OFF);
422
 
423
        /* External clocking */
424
        if (lp->speed)
425
        {
426
                /* DPLL frm BRG, BRG src PCLK */
427
                wrtscc(lp->cardbase, cmd, R14, BRSRC | SSBR);
428
                wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH); /* SEARCH mode, keep BRG src */
429
            wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL);    /* Enable the BRG */
430
 
431
            /* Turn off external clock port */
432
        if (lp->base & CHANA)
433
            outb_p( (pt_sercfg &= ~PT_EXTCLKA), (lp->cardbase + SERIAL_CFG) );
434
        else
435
            outb_p( (pt_sercfg &= ~PT_EXTCLKB), (lp->cardbase + SERIAL_CFG) );
436
    } else {
437
                /* DPLL frm rtxc,BRG src PCLK */
438
/*              wrtscc(lp->cardbase, cmd, R14, BRSRC | SSRTxC);*/
439
        /* Turn on external clock port */
440
        if (lp->base & CHANA)
441
            outb_p( (pt_sercfg |= PT_EXTCLKA), (lp->cardbase + SERIAL_CFG) );
442
        else
443
            outb_p( (pt_sercfg |= PT_EXTCLKB), (lp->cardbase + SERIAL_CFG) );
444
    }
445
 
446
    if (!lp->dmachan)
447
                wrtscc(lp->cardbase, cmd, R1, (INT_ALL_Rx | EXT_INT_ENAB));
448
 
449
    wrtscc(lp->cardbase, cmd, R15, BRKIE);      /* ABORT int */
450
 
451
        /* Turn on the DTR to tell modem we're alive */
452
        if (lp->base & CHANA)
453
            outb_p( (pt_sercfg |= PT_DTRA_ON), (lp->cardbase + SERIAL_CFG) );
454
        else
455
        outb_p( (pt_sercfg |= PT_DTRB_ON), (lp->cardbase + SERIAL_CFG) );
456
 
457
    /* Now, turn on the receiver and hunt for a flag */
458
    wrtscc(lp->cardbase, cmd, R3, RxENABLE | RxCRC_ENAB | AUTO_ENAB | Rx8 );
459
 
460
        restore_flags(flags);
461
 
462
} /* scc_init() */
463
 
464
/* Resets the given channel and whole SCC if both channels off */
465
static void chipset_init(struct device *dev)
466
{
467
 
468
        struct pt_local *lp = (struct pt_local*) dev->priv;
469
#ifdef PT_DEBUG
470
        printk(KERN_DEBUG "PT: chipset_init(): pt0a tstate = %d.\n", ((struct pt_local*)pt0a.priv)->tstate);
471
        printk(KERN_DEBUG "PT: chipset_init(): pt0b tstate = %d.\n", ((struct pt_local*)pt0b.priv)->tstate);
472
#endif
473
        /* Reset SCC if both channels are to be canned */
474
        if ( ((lp->base & CHANA) && !(pt_sercfg & PT_DTRB_ON)) ||
475
                        (!(lp->base & CHANA) && !(pt_sercfg & PT_DTRA_ON)) )
476
        {
477
                wrtscc(lp->cardbase, lp->base + CTL, R9, FHWRES);
478
                /* Reset int and dma registers */
479
                outb_p((pt_sercfg = 0), lp->cardbase + SERIAL_CFG);
480
                outb_p((pt_dmacfg = 0), lp->cardbase + DMA_CFG);
481
#ifdef PT_DEBUG
482
                printk(KERN_DEBUG "PT: chipset_init() Resetting SCC, called by ch (%d).\n", lp->base & CHANA);
483
#endif                          
484
        }
485
        /* Reset individual channel */
486
        if (lp->base & CHANA) {
487
                wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | DLC | NV | CHRA);
488
                outb_p( (pt_sercfg &= ~PT_DTRA_ON), lp->cardbase + SERIAL_CFG);
489
        } else {
490
                wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | DLC | NV | CHRB);
491
                        outb_p( (pt_sercfg &= ~PT_DTRB_ON), lp->cardbase + SERIAL_CFG);
492
        }
493
} /* chipset_init() */
494
 
495
 
496
 
497
int pt_init(void)
498
{
499
    int *port;
500
    int ioaddr = 0;
501
    int card_type = 0;
502
    int ports[] =
503
    { 0x230, 0x240, 0x250, 0x260, 0x270, 0x280, 0x290, 0x2a0,
504
      0x2b0, 0x300, 0x330, 0x3f0,  0};
505
 
506
    printk(KERN_INFO "PT: 0.41 ALPHA 07 October 1995 Craig Small (vk2xlz@vk2xlz.ampr.org)\n");
507
 
508
    for (port = &ports[0]; *port && !card_type; port++) {
509
        ioaddr = *port;
510
 
511
        if (check_region(ioaddr, PT_TOTAL_SIZE) == 0) {
512
            printk(KERN_INFO "PT: Probing for card at address %#3x\n", ioaddr);
513
            card_type = hw_probe(ioaddr);
514
        }
515
    }
516
    if (card_type) {
517
        printk(KERN_INFO "PT: Found a PT at address %#3x\n",ioaddr);
518
    } else {
519
        printk(KERN_ERR "PT: ERROR: No card found.\n");
520
        return -EIO;
521
    }
522
 
523
    /*
524
     * Link a couple of device structures into the chain
525
     *
526
     * For the A port
527
     * Allocate space for 4 buffers even though we only need 3,
528
     * because one of them may cross a DMA page boundary and
529
     * be rejected by get_dma_buffer().
530
     */
531
    register_netdev(&pt0a);
532
 
533
    pt0a.priv= kmalloc(sizeof(struct pt_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);
534
 
535
    pt0a.dma = 0;        /* wizzer - no dma yet */
536
    pt0a.base_addr = ioaddr + CHANA;
537
    pt0a.irq = 0;
538
 
539
    /* And B port */
540
    register_netdev(&pt0b);
541
 
542
    pt0b.priv= kmalloc(sizeof(struct pt_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);
543
 
544
    pt0b.base_addr = ioaddr + CHANB;
545
    pt0b.irq = 0;
546
 
547
    /* Now initialise them */
548
    pt_probe(&pt0a);
549
    pt_probe(&pt0b);
550
 
551
    pt0b.irq = pt0a.irq;        /* IRQ is shared */
552
 
553
    return 0;
554
} /* pt_init() */
555
 
556
/*
557
 * Probe for PT card.  Also initialises the timers
558
 */
559
static int hw_probe(int ioaddr)
560
{
561
    int time = 1000;            /* Number of milliseconds to test */
562
    int a = 1;
563
    int b = 1;
564
    unsigned long start_time, end_time;
565
 
566
    inb_p(ioaddr + TMR1CLR);
567
    inb_p(ioaddr + TMR2CLR);
568
 
569
    /* Timer counter channel 0, 1mS period */
570
    outb_p(SC0 | LSB_MSB | MODE3, ioaddr + TMRCMD);
571
    outb_p(0x00, ioaddr + TMR0);
572
    outb_p(0x18, ioaddr + TMR0);
573
 
574
    /* Setup timer control word for timer 1 */
575
    outb_p(SC1 | LSB_MSB | MODE0, ioaddr + TMRCMD);
576
    outb_p((time << 1) & 0xff, ioaddr + TMR1);
577
    outb_p((time >> 7) & 0xff, ioaddr + TMR1);
578
 
579
    /* wait until counter reg is loaded */
580
    do {
581
        /* Latch count for reading */
582
        outb_p(SC1, ioaddr + TMRCMD);
583
        a = inb_p(ioaddr + TMR1);
584
        b = inb_p(ioaddr + TMR1);
585
    } while (b == 0);
586
    start_time = jiffies;
587
    while(b != 0)
588
    {
589
        /* Latch count for reading */
590
        outb_p(SC1, ioaddr + TMRCMD);
591
        a = inb_p(ioaddr + TMR1);
592
        b = inb_p(ioaddr + TMR1);
593
        end_time = jiffies;
594
        /* Don't wait forever - there may be no card here */
595
        if ((end_time - start_time) > 200)
596
        {
597
                inb_p(ioaddr + TMR1CLR);
598
            return 0;
599
        }
600
    }
601
 
602
    /* Now fix the timers up for general operation */
603
 
604
    /* Clear the timers */
605
    inb_p(ioaddr + TMR1CLR);
606
    inb_p(ioaddr + TMR2CLR);
607
 
608
    outb_p(SC1 | LSB_MSB | MODE0, ioaddr + TMRCMD);
609
    inb_p(ioaddr + TMR1CLR);
610
 
611
    outb_p(SC2 | LSB_MSB | MODE0, ioaddr + TMRCMD);
612
    /* Should this be tmr1 or tmr2? wiz3*/
613
    inb_p(ioaddr + TMR1CLR);
614
 
615
    return 1;
616
} /* hw_probe() */
617
 
618
 
619
static void pt_rts(struct pt_local *lp, int x)
620
{
621
        int tc;
622
        long br;
623
        int cmd = lp->base + CTL;
624
#ifdef PT_DEBUG
625
        printk(KERN_DEBUG "PT: pt_rts(): Transmitter status will be %d (%d).\n", x, lp->base & CHANA);
626
#endif                  
627
        if (x == ON) {
628
            /* Ex ints off to avoid int */
629
            wrtscc(lp->cardbase, cmd, R15, 0);
630
            wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8);     /* Rx off */
631
            lp->rstate = IDLE;
632
 
633
            if(lp->dmachan)
634
            {
635
                /* Setup for Tx DMA */
636
                wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);
637
            } else {
638
                /* No interrupts */
639
                wrtscc(lp->cardbase, cmd, R1, 0);
640
            }
641
 
642
            if (!lp->clockmode)
643
            {
644
                if (lp->speed)
645
                {
646
                    br = lp->speed;
647
                    tc = (lp->xtal / (br * 2)) - 2;
648
                    wrtscc(lp->cardbase, cmd, R12, tc & 0xff);
649
                    wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);
650
                }
651
            }
652
            /* Turn on Tx by raising RTS */
653
            wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8 | DTR);
654
            /* Transmitter on now */
655
        } else {                /* turning off Tx */
656
            lp->tstate = IDLE;
657
 
658
            /* Turn off Tx by dropping RTS */
659
            wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR);
660
            if (!lp->clockmode)
661
            {
662
                if (lp->speed)          /* internally clocked */
663
                {
664
                    /* Reprogram BRG from 32x clock for Rx DPLL */
665
                    /* BRG off, keep PClk source */
666
                    wrtscc(lp->cardbase, cmd, R14, BRSRC);
667
                    br = lp->speed;
668
                    tc = ((lp->xtal / 32) / (br * 2)) - 2;
669
                    wrtscc(lp->cardbase, cmd, R12, tc & 0xff);
670
                    wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);
671
 
672
                    /* SEARCH mode, BRG source */
673
                    wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH);
674
                    /* Enable the BRG */
675
                    wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL);
676
                }
677
            }
678
            /* Flush Rx fifo */
679
            /* Turn Rx off */
680
            wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8);
681
 
682
            /* Reset error latch */
683
            wrtscc(lp->cardbase, cmd, R0, ERR_RES);
684
 
685
            /* get status byte from R1 */
686
            (void) rdscc(lp->cardbase, cmd, R1);
687
 
688
            /* Read and dump data in queue */
689
            (void) rdscc(lp->cardbase, cmd, R8);
690
            (void) rdscc(lp->cardbase, cmd, R8);
691
            (void) rdscc(lp->cardbase, cmd, R8);
692
 
693
            /* Now, turn on Rx and hunt for a flag */
694
              wrtscc(lp->cardbase, cmd, R3, RxENABLE | AUTO_ENAB | Rx8 );
695
 
696
            lp->rstate = ACTIVE;
697
 
698
            if (lp->dmachan)
699
            {
700
                setup_rx_dma(lp);
701
            } else {
702
                /* Reset buffer pointers */
703
                lp->rcp = lp->rcvbuf->data;
704
                lp->rcvbuf->cnt = 0;
705
                /* Allow aborts to interrupt us */
706
                wrtscc(lp->cardbase, cmd, R1, INT_ALL_Rx | EXT_INT_ENAB);
707
 
708
        }
709
        wrtscc(lp->cardbase, cmd, R15, BRKIE );
710
    }
711
} /* pt_rts() */
712
 
713
 
714
static int valid_dma_page(unsigned long addr, unsigned long dev_bufsize)
715
{
716
    if (((addr & 0xffff) + dev_bufsize) <= 0x10000)
717
        return 1;
718
    else
719
        return 0;
720
}
721
 
722
static int pt_set_mac_address(struct device *dev, void *addr)
723
{
724
        struct sockaddr *sa = (struct sockaddr *)addr;
725
        memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);              /* addr is an AX.25 shifted ASCII */
726
        return 0;                /* mac address */
727
}
728
 
729
 
730
/* Allocate a buffer which does not cross a DMA page boundary */
731
static char * get_dma_buffer(unsigned long *mem_ptr)
732
{
733
    char *ret;
734
 
735
    ret = (char *) *mem_ptr;
736
 
737
    if (!valid_dma_page(*mem_ptr, DMA_BUFF_SIZE + sizeof(struct mbuf))) {
738
        *mem_ptr += (DMA_BUFF_SIZE + sizeof(struct mbuf));
739
        ret = (char *) *mem_ptr;
740
    }
741
    *mem_ptr += (DMA_BUFF_SIZE + sizeof(struct mbuf));
742
    return (ret);
743
} /* get_dma_buffer() */
744
 
745
 
746
/*
747
 * Sets up all the structures for the PT device
748
 */
749
static int pt_probe(struct device *dev)
750
{
751
    short ioaddr;
752
    struct pt_local *lp;
753
    int i;
754
    unsigned long flags;
755
    unsigned long mem_ptr;
756
 
757
    ioaddr = dev->base_addr;
758
 
759
    /*
760
     * Initialise the device structure.
761
     * Must be done before chipset_init()
762
     * Make sure data structures used by  the PT are aligned
763
     */
764
    dev->priv = (void *) (((int) dev->priv + 7) & ~7);
765
    lp = (struct pt_local*) dev->priv;
766
 
767
    memset(dev->priv, 0, sizeof(struct pt_local));
768
 
769
    /* Allocate some buffers which do not cross DMA boundaries */
770
    mem_ptr = (unsigned long) dev->priv + sizeof(struct pt_local);
771
    lp->txdmabuf = get_dma_buffer(&mem_ptr);
772
    lp->rxdmabuf1 = (struct mbuf *) get_dma_buffer(&mem_ptr);
773
    lp->rxdmabuf2 = (struct mbuf *) get_dma_buffer(&mem_ptr);
774
 
775
    /* Initialise the Rx buffer */
776
    lp->rcvbuf = lp->rxdmabuf1;
777
    lp->rcp = lp->rcvbuf->data;
778
    lp->rcvbuf->cnt = 0;
779
 
780
    /* Initialise the transmit queue head structure */
781
    skb_queue_head_init(&lp->sndq);
782
 
783
    lp->base = dev->base_addr;
784
    lp->cardbase = dev->base_addr & 0x3f0;
785
 
786
    /* These need to be initialised before scc_init() is called.
787
     */
788
    lp->xtal = XTAL;
789
 
790
    if (dev->base_addr & CHANA) {
791
        lp->speed = DEF_A_SPEED;
792
        lp->txdelay = DEF_A_TXDELAY;
793
        lp->persist = DEF_A_PERSIST;
794
        lp->slotime = DEF_A_SLOTIME;
795
        lp->squeldelay = DEF_A_SQUELDELAY;
796
        lp->clockmode = DEF_A_CLOCKMODE;
797
        lp->nrzi = DEF_A_NRZI;
798
    } else {
799
        lp->speed = DEF_B_SPEED;
800
        lp->txdelay = DEF_B_TXDELAY;
801
        lp->persist = DEF_B_PERSIST;
802
        lp->slotime = DEF_B_SLOTIME;
803
        lp->squeldelay = DEF_B_SQUELDELAY;
804
        lp->clockmode = DEF_B_CLOCKMODE;
805
        lp->nrzi = DEF_B_NRZI;
806
    }
807
    lp->bufsiz = DMA_BUFF_SIZE;
808
    lp->tstate = IDLE;
809
 
810
    chipset_init(dev);
811
 
812
    if (dev->base_addr & CHANA) {
813
        /* Note that a single IRQ services 2 devices (A and B channels)
814
        */
815
 
816
        /*
817
         * We disable the dma for a while, we have to get ints working
818
         * properly first!!
819
         */
820
        lp->dmachan = 0;
821
 
822
        if (dev->irq < 2) {
823
            autoirq_setup(0);
824
 
825
            /* Turn on PT interrupts */
826
            save_flags(flags);
827
            cli();
828
            outb_p( pt_sercfg |= PT_EI, lp->cardbase + INT_CFG);
829
            restore_flags(flags);
830
 
831
            /* Set a timer interrupt */
832
            tdelay(lp, 1);
833
            dev->irq = autoirq_report(20);
834
 
835
            /* Turn off PT interrupts */
836
            save_flags(flags);
837
            cli();
838
            outb_p( (pt_sercfg  &= ~ PT_EI), lp->cardbase + INT_CFG);
839
            restore_flags(flags);
840
 
841
            if (!dev->irq) {
842
                printk(KERN_ERR "PT: ERROR: Failed to detect IRQ line, assuming IRQ7.\n");
843
            }
844
        }
845
 
846
        printk(KERN_INFO "PT: Autodetected IRQ %d, assuming DMA %d\n", dev->irq, dev->dma);
847
 
848
        /* This board has jumpered interrupts. Snarf the interrupt vector
849
         * now.  There is no point in waiting since no other device can use
850
         * the interrupt, and this marks the 'irqaction' as busy.
851
         */
852
        {
853
            int irqval = request_irq(dev->irq, &pt_interrupt,0, "pt", NULL);
854
            if (irqval) {
855
                printk(KERN_ERR "PT: ERROR: Unable to get IRQ %d (irqval = %d).\n",
856
                    dev->irq, irqval);
857
                return EAGAIN;
858
            }
859
        }
860
 
861
        /* Grab the region */
862
        request_region(ioaddr & 0x3f0, PT_TOTAL_SIZE, "pt" );
863
    } /* A port */
864
    dev->open = pt_open;
865
    dev->stop = pt_close;
866
    dev->do_ioctl = pt_ioctl;
867
    dev->hard_start_xmit = pt_send_packet;
868
    dev->get_stats = pt_get_stats;
869
 
870
    /* Fill in the fields of the device structure */
871
    for (i=0; i < DEV_NUMBUFFS; i++)
872
        skb_queue_head_init(&dev->buffs[i]);
873
 
874
    dev->hard_header = pt_header;
875
    dev->rebuild_header = pt_rebuild_header;
876
    dev->set_mac_address = pt_set_mac_address;
877
 
878
    dev->type = ARPHRD_AX25;            /* AF_AX25 device */
879
    dev->hard_header_len = 73;      /* We do digipeaters now */
880
    dev->mtu = 1500;                /* eth_mtu is default */
881
    dev->addr_len = 7;               /* sizeof an ax.25 address */
882
    memcpy(dev->broadcast, ax25_bcast, 7);
883
    memcpy(dev->dev_addr, ax25_test, 7);
884
 
885
    /* New style flags */
886
    dev->flags = 0;
887
    dev->family = AF_INET;
888
 
889
#ifdef CONFIG_INET
890
    dev->pa_addr    = in_aton("192.168.0.1");
891
    dev->pa_brdaddr = in_aton("192.168.0.255");
892
    dev->pa_mask    = in_aton("255.255.255.0");
893
    dev->pa_alen    = 4;
894
#endif
895
 
896
    return 0;
897
} /* pt_probe() */
898
 
899
 
900
/* Open/initialise the board.  This is called (in the current kernel)
901
 * sometime after booting when the 'ifconfig' program is run.
902
 *
903
 * This routine should set everything up anew at each open, even
904
 * registers that 'should' only be set once at boot, so that there is
905
 * a non-reboot way to recover if something goes wrong.
906
 * derived from last half of tsync_attach()
907
 */
908
static int pt_open(struct device *dev)
909
{
910
    unsigned long flags;
911
    struct pt_local *lp = dev->priv;
912
    static int first_time = 1;
913
 
914
    if (dev->base_addr & CHANA)
915
    {
916
        if (first_time)
917
        {
918
            if (request_dma(dev->dma, "pt"))
919
            {
920
                free_irq(dev->irq, NULL);
921
                return -EAGAIN;
922
            }
923
        }
924
        irq2dev_map[dev->irq] = dev;
925
 
926
         /* Reset hardware */
927
         chipset_init(dev);
928
     }
929
     lp->tstate = IDLE;
930
 
931
     if (dev->base_addr & CHANA)
932
     {
933
         scc_init(dev);
934
         scc_init(dev->next);
935
     }
936
     /* Save a copy of register RR0 for comparing with later on */
937
     /* We always put 0 in zero count */
938
     lp->saved_RR0 = rdscc(lp->cardbase, lp->base + CTL, R0) & ~ZCOUNT;
939
 
940
    /* master interrupt enable */
941
    save_flags(flags);
942
    cli();
943
    wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | NV);
944
    outb_p( pt_sercfg |= PT_EI, lp->cardbase + INT_CFG);
945
    restore_flags(flags);
946
 
947
    lp->open_time = jiffies;
948
 
949
    dev->tbusy = 0;
950
    dev->interrupt = 0;
951
    dev->start = 1;
952
    first_time = 0;
953
 
954
    MOD_INC_USE_COUNT;
955
 
956
    return 0;
957
} /* pt_open() */
958
 
959
static int pt_send_packet(struct sk_buff *skb, struct device *dev)
960
{
961
        struct pt_local *lp = (struct pt_local *) dev->priv;
962
 
963
#ifdef PT_DEBUG
964
        printk(KERN_DEBUG "PT: pt_send_packet(): (%d)\n", lp->base & CHANA);
965
#endif                  
966
        /* If some higher layer thinks we've missed an tx-done interrupt
967
           we are passed NULL. Caution: dev_tint() handles the cli()/sti()
968
           itself.*/
969
        if (skb == NULL) {
970
                dev_tint(dev);
971
                return 0;
972
        }
973
        hardware_send_packet(lp, skb);
974
        dev->trans_start = jiffies;
975
 
976
        return 0;
977
}
978
 
979
 
980
 
981
/* The inverse routine to pt_open() */
982
static int pt_close(struct device *dev)
983
{
984
        unsigned long flags;
985
        struct pt_local *lp = dev->priv;
986
        struct sk_buff *ptr = NULL;
987
        int cmd;
988
 
989
        cmd = lp->base + CTL;
990
 
991
        save_flags(flags);
992
        cli();
993
 
994
        /* Reset SCC or channel */
995
        chipset_init(dev);
996
        disable_dma(lp->dmachan);
997
 
998
        lp->open_time = 0;
999
        dev->tbusy = 1;
1000
        dev->start = 0;
1001
 
1002
        /* Free any buffers left in the hardware transmit queue */
1003
        while ((ptr = skb_dequeue(&lp->sndq)) != NULL)
1004
                free_p(ptr);
1005
 
1006
        restore_flags(flags);
1007
 
1008
#ifdef PT_DEBUG
1009
        printk(KERN_DEBUG "PT: pt_close(): Closing down channel (%d).\n", lp->base & CHANA);
1010
#endif  
1011
 
1012
        MOD_DEC_USE_COUNT;
1013
 
1014
        return 0;
1015
} /* pt_close() */
1016
 
1017
 
1018
static int pt_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
1019
{
1020
    unsigned long flags;
1021
    struct pt_req rq;
1022
    struct pt_local *lp = (struct pt_local *) dev->priv;
1023
 
1024
    int ret = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct pt_req));
1025
    if (ret)
1026
        return ret;
1027
 
1028
    if (cmd != SIOCDEVPRIVATE)
1029
        return -EINVAL;
1030
 
1031
    memcpy_fromfs(&rq, ifr->ifr_data, sizeof(struct pt_req));
1032
 
1033
    switch (rq.cmd) {
1034
    case SIOCSPIPARAM:
1035
 
1036
        if (!suser())
1037
            return -EPERM;
1038
        save_flags(flags);
1039
        cli();
1040
        lp->txdelay = rq.txdelay;
1041
        lp->persist = rq.persist;
1042
        lp->slotime = rq.slotime;
1043
        lp->squeldelay = rq.squeldelay;
1044
        lp->clockmode = rq.clockmode;
1045
        lp->speed = rq.speed;
1046
        pt_open(&pt0a);
1047
        restore_flags(flags);
1048
        ret = 0;
1049
        break;
1050
 
1051
    case SIOCSPIDMA:
1052
 
1053
        if (!suser())
1054
            return -EPERM;
1055
        ret = 0;
1056
        if (dev->base_addr & CHANA) {   /* if A channel */
1057
           if (rq.dmachan < 1 || rq.dmachan > 3)
1058
                return -EINVAL;
1059
           save_flags(flags);
1060
           cli();
1061
           pt_close(dev);
1062
           free_dma(lp->dmachan);
1063
           dev->dma = lp->dmachan = rq.dmachan;
1064
           if (request_dma(lp->dmachan,"pt"))
1065
                ret = -EAGAIN;
1066
           pt_open(dev);
1067
           restore_flags(flags);
1068
        }
1069
        break;
1070
 
1071
    case SIOCSPIIRQ:
1072
        ret = -EINVAL;      /* add this later */
1073
        break;
1074
 
1075
    case SIOCGPIPARAM:
1076
    case SIOCGPIDMA:
1077
    case SIOCGPIIRQ:
1078
 
1079
        rq.speed = lp->speed;
1080
        rq.txdelay = lp->txdelay;
1081
        rq.persist = lp->persist;
1082
        rq.slotime = lp->slotime;
1083
        rq.squeldelay = lp->squeldelay;
1084
        rq.clockmode = lp->clockmode;
1085
        rq.dmachan = lp->dmachan;
1086
        rq.irq = dev->irq;
1087
        memcpy_tofs(ifr->ifr_data, &rq, sizeof(struct pt_req));
1088
        ret = 0;
1089
        break;
1090
 
1091
    default:
1092
        ret = -EINVAL;
1093
    }
1094
    return ret;
1095
}
1096
 
1097
/* Get the current statistics.  This may be called with the card open or
1098
   closed. */
1099
static struct netstats *
1100
 pt_get_stats(struct device *dev)
1101
{
1102
    struct pt_local *lp = (struct pt_local *) dev->priv;
1103
 
1104
    return &lp->stats;
1105
}
1106
 
1107
 
1108
/*
1109
 * Local variables:
1110
 *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c"
1111
 *  version-control: t
1112
 *  kept-new-versions: 5
1113
 *  tab-width: 4
1114
 * End:
1115
 */
1116
 
1117
 
1118
static void tdelay(struct pt_local *lp, int time)
1119
{
1120
        /* For some reason, we turn off the Tx interrupts here! */
1121
        if (!lp->dmachan)
1122
                wrtscc(lp->cardbase, lp->base + CTL, R1, INT_ALL_Rx | EXT_INT_ENAB);
1123
 
1124
    if (lp->base & CHANA) {
1125
        outb_p(time & 0xff, lp->cardbase + TMR1);
1126
        outb_p((time >> 8)&0xff, lp->cardbase + TMR1);
1127
    } else {
1128
        outb_p(time & 0xff, lp->cardbase + TMR2);
1129
        outb_p((time >> 8)&0xff, lp->cardbase + TMR2);
1130
    }
1131
} /* tdelay */
1132
 
1133
 
1134
static void pt_txisr(struct pt_local *lp)
1135
{
1136
        unsigned long flags;
1137
        int cmd;
1138
        unsigned char c;
1139
 
1140
        save_flags(flags);
1141
        cli();
1142
        cmd = lp->base + CTL;
1143
 
1144
#ifdef PT_DEBUG
1145
        printk(KERN_DEBUG "PT: pt_txisr(): tstate = %d (%d).\n", lp->tstate, lp->base & CHANA);
1146
#endif  
1147
 
1148
        switch (lp->tstate)
1149
        {
1150
        case CRCOUT:
1151
            lp->tstate = FLAGOUT;
1152
            tdelay(lp, lp->squeldelay);
1153
            restore_flags(flags);
1154
            return;
1155
 
1156
        case IDLE:
1157
            /* Transmitter idle. Find a frame for transmission */
1158
            if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL)
1159
            {
1160
                /* Nothing to send - return to receive mode
1161
                 * Tx off now - flag should have gone
1162
                 */
1163
                pt_rts(lp, OFF);
1164
 
1165
                restore_flags(flags);
1166
                return;
1167
            }
1168
            if (!lp->dmachan)
1169
            {
1170
                    lp->txptr = lp->sndbuf->data;
1171
                    lp->txptr++;                /* Ignore KISS control byte */
1172
                    lp->txcnt = (int) lp->sndbuf->len - 1;
1173
                }
1174
            /* If a buffer to send, drop though here */
1175
 
1176
        case DEFER:
1177
            /* Check DCD - debounce it */
1178
            /* See Intel Microcommunications Handbook p2-308 */
1179
            wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
1180
            wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
1181
            if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0)
1182
            {
1183
                lp->tstate = DEFER;
1184
                tdelay(lp, 100);
1185
                /* DEFER until DCD transition or timeout */
1186
                wrtscc(lp->cardbase, cmd, R15, DCDIE);
1187
                restore_flags(flags);
1188
                return;
1189
            }
1190
            if (random() > lp->persist)
1191
            {
1192
                lp->tstate = DEFER;
1193
                tdelay(lp, lp->slotime);
1194
                restore_flags(flags);
1195
                return;
1196
            }
1197
            pt_rts(lp, ON);             /* Tx on */
1198
            if (lp->dmachan)
1199
                wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);
1200
            lp->tstate = ST_TXDELAY;
1201
            tdelay(lp, lp->txdelay);
1202
            restore_flags(flags);
1203
            return;
1204
 
1205
        case ACTIVE:
1206
            /* Here we are actively sending a frame */
1207
            if (lp->txcnt--)
1208
            {
1209
                /* XLZ - checkout Gracilis PT code to see if the while
1210
                 * loop is better or not.
1211
                 */
1212
                c = *lp->txptr++;
1213
                /* next char is gone */
1214
                wrtscc(lp->cardbase, cmd, R8, c);
1215
                /* stuffing a char satisfies interrupt condition */
1216
            } else {
1217
                /* No more to send */
1218
                free_p(lp->sndbuf);
1219
                lp->sndbuf = NULL;
1220
                if ((rdscc(lp->cardbase, cmd, R0) & TxEOM))
1221
                {
1222
                    /* Did we underrun */
1223
                    lp->stats.tx_errors++;
1224
                    lp->stats.tx_fifo_errors++;
1225
                    wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);
1226
                    lp->tstate = FLAGOUT;
1227
                    tdelay(lp, lp->squeldelay);
1228
                    restore_flags(flags);
1229
                    return;
1230
                }
1231
                lp->tstate = UNDERRUN;
1232
                /* Send flags on underrun */
1233
               if (lp->nrzi)
1234
               {
1235
                   wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
1236
               } else {
1237
                   wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZ);
1238
               }
1239
               /* Reset Tx interrupt pending */
1240
               wrtscc(lp->cardbase, cmd, R0, RES_Tx_P);
1241
           }
1242
           restore_flags(flags);
1243
           return;
1244
        default:
1245
                printk(KERN_ERR "PT: pt_txisr(): Invalid tstate (%d) for chan %s.\n", lp->tstate, (cmd & CHANA? "A": "B") );
1246
                pt_rts(lp, OFF);
1247
                lp->tstate = IDLE;
1248
                break;
1249
    }                           /*switch */
1250
    restore_flags(flags);
1251
}
1252
 
1253
static void pt_rxisr(struct device *dev)
1254
{
1255
    struct pt_local *lp = (struct pt_local*) dev->priv;
1256
    int cmd = lp->base + CTL;
1257
    int bytecount;
1258
    unsigned long flags;
1259
    char rse;
1260
    struct sk_buff *skb;
1261
    int sksize, pkt_len;
1262
    struct mbuf *cur_buf = NULL;
1263
    unsigned char *cfix;
1264
 
1265
    save_flags(flags);
1266
    cli();
1267
 
1268
    /* Get status byte from R1 */
1269
    rse = rdscc(lp->cardbase, cmd, R1);
1270
 
1271
#ifdef PT_DEBUG
1272
    printk(KERN_DEBUG "PT: pt_rxisr(): R1 = %#3x. (%d)\n", rse, lp->base & CHANA);
1273
#endif        
1274
 
1275
        if (lp->dmachan && (rse & Rx_OVR))
1276
                lp->rstate = RXERROR;
1277
 
1278
    if (rdscc(lp->cardbase, cmd, R0) & Rx_CH_AV && !lp->dmachan)
1279
    {
1280
        /* There is a char to be stored
1281
         * Read special condition bits before reading the data char
1282
         */
1283
        if (rse & Rx_OVR)
1284
        {
1285
             /* Rx overrun - toss buffer */
1286
             /* wind back the pointers */
1287
             lp->rcp = lp->rcvbuf->data;
1288
             lp->rcvbuf->cnt = 0;
1289
             lp->rstate = RXERROR;
1290
             lp->stats.rx_errors++;
1291
             lp->stats.rx_fifo_errors++;
1292
         } else if (lp->rcvbuf->cnt >= lp->bufsiz)
1293
             {
1294
                 /* Too large packet
1295
                  * wind back Rx buffer pointers
1296
                  */
1297
                 lp->rcp = lp->rcvbuf->data;
1298
                 lp->rcvbuf->cnt = 0;
1299
                 lp->rstate = TOOBIG;
1300
             }
1301
         /* ok, we can store the Rx char if no errors */
1302
         if (lp->rstate == ACTIVE)
1303
         {
1304
             *lp->rcp++ = rdscc(lp->cardbase, cmd, R8);
1305
             lp->rcvbuf->cnt++;
1306
         } else {
1307
             /* we got an error, dump the FIFO */
1308
             (void) rdscc(lp->cardbase, cmd, R8);
1309
             (void) rdscc(lp->cardbase, cmd, R8);
1310
             (void) rdscc(lp->cardbase, cmd, R8);
1311
 
1312
             /* Reset error latch */
1313
             wrtscc(lp->cardbase, cmd, R0, ERR_RES);
1314
             lp->rstate = ACTIVE;
1315
 
1316
             /* Resync the SCC */
1317
             wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
1318
 
1319
         }
1320
     }
1321
 
1322
     if (rse & END_FR)
1323
     {
1324
#ifdef PT_DEBUG
1325
        printk(KERN_DEBUG "PT: pt_rxisr() Got end of a %u byte frame.\n", lp->rcvbuf->cnt);
1326
#endif       
1327
                if (lp->dmachan)
1328
                {
1329
                        clear_dma_ff(lp->dmachan);
1330
                        bytecount = lp->bufsiz - get_dma_residue(lp->dmachan);
1331
                } else {
1332
                        bytecount = lp->rcvbuf->cnt;
1333
                }
1334
 
1335
         /* END OF FRAME - Make sure Rx was active */
1336
         if (lp->rcvbuf->cnt > 0 || lp->dmachan)
1337
         {
1338
             if ((rse & CRC_ERR) || (lp->rstate > ACTIVE) || (bytecount < 10))
1339
             {
1340
                 if ((bytecount >= 10) && (rse & CRC_ERR))
1341
                 {
1342
                     lp->stats.rx_crc_errors++;
1343
                 }
1344
                 if (lp->dmachan)
1345
                 {
1346
                        if (lp->rstate == RXERROR)
1347
                        {
1348
                                lp->stats.rx_errors++;
1349
                                lp->stats.rx_over_errors++;
1350
                        }
1351
                        lp->rstate = ACTIVE;
1352
                        setup_rx_dma(lp);
1353
                 } else {
1354
                         /* wind back Rx buffer pointers */
1355
                     lp->rcp = lp->rcvbuf->data;
1356
                         lp->rcvbuf->cnt = 0;
1357
 
1358
                                        /* Re-sync the SCC */
1359
                                        wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
1360
 
1361
                     }
1362
#ifdef PT_DEBUG
1363
        printk(KERN_DEBUG "PT: pt_rxisr() %s error.\n", (rse & CRC_ERR)? "CRC" : "state");
1364
#endif                 
1365
             } else {
1366
                 /* We have a valid frame */
1367
                 if (lp->dmachan)
1368
                 {
1369
                        pkt_len = lp->rcvbuf->cnt = bytecount - 2 +1;
1370
                                        /* Get buffer for next frame */
1371
                        cur_buf = lp->rcvbuf;
1372
                        switchbuffers(lp);
1373
                        setup_rx_dma(lp);
1374
                 } else {
1375
                         pkt_len = lp->rcvbuf->cnt -= 2;  /* Toss 2 CRC bytes */
1376
                     pkt_len += 1;      /* make room for KISS control byte */
1377
                        }
1378
 
1379
                 /* Malloc up new buffer */
1380
                 sksize = pkt_len;
1381
                 skb = dev_alloc_skb(sksize);
1382
                 if (skb == NULL)
1383
                 {
1384
                     printk(KERN_ERR "PT: %s: Memory squeeze, dropping packet.\n", dev->name);
1385
                     lp->stats.rx_dropped++;
1386
                     restore_flags(flags);
1387
                     return;
1388
                 }
1389
                 skb->dev = dev;
1390
 
1391
                 /* KISS kludge = prefix with a 0 byte */
1392
                 cfix=skb_put(skb,pkt_len);
1393
                 *cfix++=0;
1394
                 /* skb->data points to the start of sk_buff area */
1395
                 if (lp->dmachan)
1396
                        memcpy(cfix, (char*)cur_buf->data, pkt_len - 1);
1397
                 else
1398
                    memcpy(cfix, lp->rcvbuf->data, pkt_len - 1);
1399
                 skb->protocol = ntohs(ETH_P_AX25);
1400
                 skb->mac.raw=skb->data;
1401
                 IS_SKB(skb);
1402
                 netif_rx(skb);
1403
                 lp->stats.rx_packets++;
1404
                 if (!lp->dmachan)
1405
                 {
1406
                         /* packet queued - wind back buffer for next frame */
1407
                     lp->rcp = lp->rcvbuf->data;
1408
                         lp->rcvbuf->cnt = 0;
1409
                     }
1410
             } /* good frame */
1411
         } /* check active Rx */
1412
         /* Clear error status */
1413
         lp->rstate = ACTIVE;
1414
         /* Reset error latch */
1415
     } /* end EOF check */
1416
     wrtscc(lp->cardbase, cmd, R0, ERR_RES);
1417
     restore_flags(flags);
1418
} /* pt_rxisr() */
1419
 
1420
/*
1421
 * This handles the two timer interrupts.
1422
 * This is a real bugger, cause you have to rip it out of the pi's
1423
 * external status code.  They use the CTS line or something.
1424
 */
1425
static void pt_tmrisr(struct pt_local *lp)
1426
{
1427
    unsigned long flags;
1428
 
1429
#ifdef PT_DEBUG
1430
        printk(KERN_DEBUG "PT: pt_tmrisr(): tstate = %d (%d).\n", lp->tstate, lp->base & CHANA);
1431
#endif          
1432
 
1433
    save_flags(flags);
1434
    cli();
1435
 
1436
 
1437
    switch (lp->tstate)
1438
    {
1439
    /* Most of this stuff is in pt_exisr() */
1440
    case FLAGOUT:
1441
    case ST_TXDELAY:
1442
    case DEFER:
1443
/*    case ACTIVE:
1444
    case UNDERRUN:*/
1445
        pt_exisr(lp);
1446
        break;
1447
 
1448
    default:
1449
        if (lp->base & CHANA)
1450
            printk(KERN_ERR "PT: pt_tmrisr(): Invalid tstate %d for Channel A\n", lp->tstate);
1451
        else
1452
            printk(KERN_ERR "PT: pt_tmrisr(): Invalid tstate %d for Channel B\n", lp->tstate);
1453
        break;
1454
    } /* end switch */
1455
    restore_flags(flags);
1456
} /* pt_tmrisr() */
1457
 
1458
 
1459
/*
1460
 * This routine is called by the kernel when there is an interrupt for the
1461
 * PT.
1462
 */
1463
static void pt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1464
{
1465
    /* It's a tad dodgy here, but we assume pt0a until proven otherwise */
1466
    struct device *dev = &pt0a;
1467
    struct pt_local *lp = dev->priv;
1468
    unsigned char intreg;
1469
    unsigned char st;
1470
    register int cbase = dev->base_addr & 0x3f0;
1471
    unsigned long flags;
1472
 
1473
    /* Read the PT's interrupt register, this is not the SCC one! */
1474
    intreg = inb_p(cbase + INT_REG);
1475
    while(( intreg & 0x07) != 0x07) {
1476
        /* Read interrupt register pending from Channel A */
1477
        while ((st = rdscc(cbase, cbase + CHANA + CTL, R3)) != 0)
1478
        {
1479
                /* Read interrupt vector from R2, channel B */
1480
#ifdef PT_DEBUG
1481
                printk(KERN_DEBUG "PT: pt_interrupt(): R3 = %#3x", st);
1482
#endif                  
1483
/*              st = rdscc(lp->cardbase, cbase + CHANB + CTL, R2) & 0x0e;*/
1484
#ifdef PT_DEBUG
1485
                printk(KERN_DEBUG "PI: R2 = %#3x.\n", st);
1486
#endif  
1487
                        if (st & CHARxIP) {
1488
                            /* Channel A Rx */
1489
                    lp = (struct pt_local*)pt0a.priv;
1490
                    pt_rxisr(&pt0a);
1491
                } else if (st & CHATxIP) {
1492
                    /* Channel A Tx */
1493
                    lp = (struct pt_local*)pt0a.priv;
1494
                    pt_txisr(lp);
1495
                } else if (st & CHAEXT) {
1496
                        /* Channel A External Status */
1497
                        lp = (struct pt_local*)pt0a.priv;
1498
                        pt_exisr(lp);
1499
                } else if (st & CHBRxIP) {
1500
                        /* Channel B Rx */
1501
                    lp= (struct pt_local*)pt0b.priv;
1502
                    pt_rxisr(&pt0b);
1503
                } else if (st & CHBTxIP) {
1504
                /* Channel B Tx */
1505
                    lp = (struct pt_local*)pt0b.priv;
1506
                    pt_txisr(lp);
1507
                        } else if (st & CHBEXT) {
1508
                        /* Channel B External Status */
1509
                        lp = (struct pt_local*)pt0b.priv;
1510
                        pt_exisr(lp);
1511
                }
1512
            /* Reset highest interrupt under service */
1513
            save_flags(flags);
1514
            cli();
1515
            wrtscc(lp->cardbase, lp->base + CTL, R0, RES_H_IUS);
1516
            restore_flags(flags);
1517
        }  /* end of SCC ints */
1518
 
1519
        if (!(intreg & PT_TMR1_MSK))
1520
        {
1521
            /* Clear timer 1 */
1522
            inb_p(cbase + TMR1CLR);
1523
 
1524
            pt_tmrisr( (struct pt_local*)pt0a.priv);
1525
        }
1526
 
1527
        if (!(intreg & PT_TMR2_MSK))
1528
        {
1529
            /* Clear timer 2 */
1530
            inb_p(cbase + TMR2CLR);
1531
 
1532
            pt_tmrisr( (struct pt_local*)pt0b.priv);
1533
        }
1534
 
1535
        /* Get the next PT interrupt vector */
1536
        intreg = inb_p(cbase + INT_REG);
1537
    } /* while (intreg) */
1538
} /* pt_interrupt() */
1539
 
1540
 
1541
static void pt_exisr(struct pt_local *lp)
1542
{
1543
    unsigned long flags;
1544
    int cmd = lp->base + CTL;
1545
    unsigned char st;
1546
    char c;
1547
    int length;
1548
 
1549
    save_flags(flags);
1550
    cli();
1551
 
1552
    /* Get external status */
1553
    st = rdscc(lp->cardbase, cmd, R0);
1554
 
1555
#ifdef PT_DEBUG
1556
        printk(KERN_DEBUG "PT: exisr(): R0 = %#3x tstate = %d (%d).\n", st, lp->tstate, lp->base & CHANA);
1557
#endif  
1558
    /* Reset external status latch */
1559
    wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
1560
 
1561
    if ((lp->rstate >= ACTIVE) && (st & BRK_ABRT) && lp->dmachan)
1562
    {
1563
        setup_rx_dma(lp);
1564
        lp->rstate = ACTIVE;
1565
    }
1566
 
1567
    switch (lp->tstate)
1568
    {
1569
    case ACTIVE:                /* Unexpected underrun */
1570
#ifdef PT_DEBUG
1571
        printk(KERN_DEBUG "PT: exisr(): unexpected underrun detected.\n");
1572
#endif      
1573
        free_p(lp->sndbuf);
1574
        lp->sndbuf = NULL;
1575
        if (!lp->dmachan)
1576
        {
1577
                wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);
1578
                lp->stats.tx_errors++;
1579
                lp->stats.tx_fifo_errors++;
1580
            }
1581
        lp->tstate = FLAGOUT;
1582
        tdelay(lp, lp->squeldelay);
1583
        restore_flags(flags);
1584
        return;
1585
    case UNDERRUN:
1586
        lp->tstate = CRCOUT;
1587
        restore_flags(flags);
1588
        return;
1589
    case FLAGOUT:
1590
        /* squeldelay has timed out */
1591
        /* Find a frame for transmission */
1592
        if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL)
1593
        {
1594
            /* Nothing to send - return to Rx mode */
1595
            pt_rts(lp, OFF);
1596
            lp->tstate = IDLE;
1597
            restore_flags(flags);
1598
            return;
1599
        }
1600
        if (!lp->dmachan)
1601
        {
1602
                lp->txptr = lp->sndbuf->data;
1603
            lp->txptr++;                /* Ignore KISS control byte */
1604
                lp->txcnt = (int) lp->sndbuf->len - 1;
1605
            }
1606
        /* Fall through if we have a packet */
1607
 
1608
    case ST_TXDELAY:
1609
        if (lp->dmachan)
1610
        {
1611
                /* Disable DMA chan */
1612
                disable_dma(lp->dmachan);
1613
 
1614
                /* Set up for TX dma */
1615
                wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);
1616
 
1617
                length = lp->sndbuf->len - 1;
1618
                memcpy(lp->txdmabuf, &lp->sndbuf->data[1], length);
1619
 
1620
                /* Setup DMA controller for Tx */
1621
                setup_tx_dma(lp, length);
1622
 
1623
                enable_dma(lp->dmachan);
1624
 
1625
                /* Reset CRC, Txint pending */
1626
                wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC | RES_Tx_P);
1627
 
1628
                /* Allow underrun only */
1629
                wrtscc(lp->cardbase, cmd, R15, TxUIE);
1630
 
1631
                /* Enable TX DMA */
1632
                wrtscc(lp->cardbase, cmd, R1, WT_RDY_ENAB | WT_FN_RDYFN | EXT_INT_ENAB);
1633
 
1634
                /* Send CRC on underrun */
1635
                wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);
1636
 
1637
                lp->tstate = ACTIVE;
1638
                break;
1639
        }
1640
        /* Get first char to send */
1641
        lp->txcnt--;
1642
        c = *lp->txptr++;
1643
        /* Reset CRC for next frame */
1644
        wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC);
1645
 
1646
        /* send abort on underrun */
1647
        if (lp->nrzi)
1648
        {
1649
            wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER);
1650
        } else {
1651
            wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZ | ABUNDER);
1652
        }
1653
        /* send first char */
1654
        wrtscc(lp->cardbase, cmd, R8, c);
1655
 
1656
        /* Reset end of message latch */
1657
        wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);
1658
 
1659
        /* stuff an extra one in */
1660
/*        while ((rdscc(lp->cardbase, cmd, R0) & Tx_BUF_EMP) && lp->txcnt)
1661
        {
1662
            lp->txcnt--;
1663
            c = *lp->txptr++;
1664
            wrtscc(lp->cardbase, cmd, R8, c);
1665
        }*/
1666
 
1667
        /* select Tx interrupts to enable */
1668
        /* Allow underrun int only */
1669
        wrtscc(lp->cardbase, cmd, R15, TxUIE);
1670
 
1671
        /* Reset external interrupts */
1672
        wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
1673
 
1674
        /* Tx and Rx ints enabled */
1675
        wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB);
1676
 
1677
        lp->tstate = ACTIVE;
1678
        restore_flags(flags);
1679
        return;
1680
 
1681
        /* slotime has timed out */
1682
    case DEFER:
1683
        /* Check DCD - debounce it
1684
         * see Intel Microcommunications Handbook, p2-308
1685
         */
1686
        wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
1687
        wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
1688
        if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0)
1689
        {
1690
            lp->tstate = DEFER;
1691
            tdelay(lp, 100);
1692
            /* DEFER until DCD transition or timeout */
1693
            wrtscc(lp->cardbase, cmd, R15, DCDIE);
1694
            restore_flags(flags);
1695
            return;
1696
        }
1697
        if (random() > lp->persist)
1698
        {
1699
            lp->tstate = DEFER;
1700
            tdelay(lp, lp->slotime);
1701
            restore_flags(flags);
1702
            return;
1703
        }
1704
        if (lp->dmachan)
1705
                wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);
1706
        pt_rts(lp, ON);                 /* Tx on */
1707
        lp->tstate = ST_TXDELAY;
1708
        tdelay(lp, lp->txdelay);
1709
        restore_flags(flags);
1710
        return;
1711
 
1712
        /* Only for int driven parts */
1713
        if (lp->dmachan)
1714
        {
1715
                restore_flags(flags);
1716
                return;
1717
        }
1718
 
1719
    } /* end switch */
1720
    /*
1721
     * Rx mode only
1722
     * This triggers when hunt mode is entered, & since an ABORT
1723
     * automatically enters hunt mode, we use that to clean up
1724
     * any waiting garbage
1725
     */
1726
    if ((lp->rstate == ACTIVE) && (st & BRK_ABRT) )
1727
    {
1728
#ifdef PT_DEBUG
1729
        printk(KERN_DEBUG "PT: exisr(): abort detected.\n");
1730
#endif        
1731
                /* read and dump all of SCC Rx FIFO */
1732
        (void) rdscc(lp->cardbase, cmd, R8);
1733
        (void) rdscc(lp->cardbase, cmd, R8);
1734
        (void) rdscc(lp->cardbase, cmd, R8);
1735
 
1736
        lp->rcp = lp->rcvbuf->data;
1737
        lp->rcvbuf->cnt = 0;
1738
 
1739
                /* Re-sync the SCC */
1740
                wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
1741
 
1742
    }
1743
 
1744
    /* Check for DCD transitions */
1745
    if ( (st & DCD) != (lp->saved_RR0 & DCD))
1746
    {
1747
#ifdef PT_DEBUG    
1748
        printk(KERN_DEBUG "PT: pt_exisr(): DCD is now %s.\n", (st & DCD)? "ON" : "OFF" );
1749
#endif
1750
                if (st & DCD)
1751
                {
1752
                        /* Check that we don't already have some data */
1753
                        if (lp->rcvbuf->cnt > 0)
1754
                        {
1755
#ifdef PT_DEBUG
1756
                                printk(KERN_DEBUG "PT: pt_exisr() dumping %u bytes from buffer.\n", lp->rcvbuf->cnt);
1757
#endif                                  
1758
                                /* wind back buffers */
1759
                                lp->rcp = lp->rcvbuf->data;
1760
                                lp->rcvbuf->cnt = 0;
1761
                        }
1762
                } else {  /* DCD off */
1763
 
1764
                        /* read and dump al SCC FIFO */
1765
                        (void)rdscc(lp->cardbase, cmd, R8);
1766
                        (void)rdscc(lp->cardbase, cmd, R8);
1767
                        (void)rdscc(lp->cardbase, cmd, R8);
1768
 
1769
                        /* wind back buffers */
1770
                        lp->rcp = lp->rcvbuf->data;
1771
                        lp->rcvbuf->cnt = 0;
1772
 
1773
                        /* Re-sync the SCC */
1774
                        wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
1775
                }
1776
 
1777
    }
1778
    /* Update the saved version of register RR) */
1779
    lp->saved_RR0 = st &~ ZCOUNT;
1780
    restore_flags(flags);
1781
 
1782
} /* pt_exisr() */
1783
 
1784
#ifdef MODULE
1785
int init_module(void)
1786
{
1787
    register_symtab(NULL);
1788
    return pt_init();
1789
}
1790
 
1791
void cleanup_module(void)
1792
{
1793
    free_irq(pt0a.irq, NULL);   /* IRQs and IO Ports are shared */
1794
    release_region(pt0a.base_addr & 0x3f0, PT_TOTAL_SIZE);
1795
    irq2dev_map[pt0a.irq] = NULL;
1796
 
1797
    kfree(pt0a.priv);
1798
    pt0a.priv = NULL;
1799
    unregister_netdev(&pt0a);
1800
 
1801
    kfree(pt0b.priv);
1802
    pt0b.priv = NULL;
1803
    unregister_netdev(&pt0b);
1804
}
1805
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.