⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pt.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
static void chipset_init(struct device *dev){	struct pt_local *lp = (struct pt_local*) dev->priv;#ifdef PT_DEBUG	printk(KERN_DEBUG "PT: chipset_init(): pt0a tstate = %d.\n", ((struct pt_local*)pt0a.priv)->tstate);	printk(KERN_DEBUG "PT: chipset_init(): pt0b tstate = %d.\n", ((struct pt_local*)pt0b.priv)->tstate);#endif	/* Reset SCC if both channels are to be canned */	if ( ((lp->base & CHANA) && !(pt_sercfg & PT_DTRB_ON)) ||			(!(lp->base & CHANA) && !(pt_sercfg & PT_DTRA_ON)) )	{		wrtscc(lp->cardbase, lp->base + CTL, R9, FHWRES);        	/* Reset int and dma registers */	        outb_p((pt_sercfg = 0), lp->cardbase + SERIAL_CFG);	        outb_p((pt_dmacfg = 0), lp->cardbase + DMA_CFG);#ifdef PT_DEBUG		printk(KERN_DEBUG "PT: chipset_init() Resetting SCC, called by ch (%d).\n", lp->base & CHANA);#endif	}	/* Reset individual channel */    	if (lp->base & CHANA) {        	wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | DLC | NV | CHRA);        	outb_p( (pt_sercfg &= ~PT_DTRA_ON), lp->cardbase + SERIAL_CFG);    	} else {        	wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | DLC | NV | CHRB);			outb_p( (pt_sercfg &= ~PT_DTRB_ON), lp->cardbase + SERIAL_CFG);	}} /* chipset_init() */__initfunc(int pt_init(void)){    int *port;    int ioaddr = 0;    int card_type = 0;    int ports[] =    { 0x230, 0x240, 0x250, 0x260, 0x270, 0x280, 0x290, 0x2a0,      0x2b0, 0x300, 0x330, 0x3f0,  0};    printk(KERN_INFO "PT: 0.41 ALPHA 07 October 1995 Craig Small (csmall@small.dropbear.id.au)\n");    for (port = &ports[0]; *port && !card_type; port++) {        ioaddr = *port;        if (check_region(ioaddr, PT_TOTAL_SIZE) == 0) {            printk(KERN_INFO "PT: Probing for card at address %#3x\n", ioaddr);            card_type = hw_probe(ioaddr);        }    }    if (card_type) {        printk(KERN_INFO "PT: Found a PT at address %#3x\n",ioaddr);    } else {        printk(KERN_ERR "PT: ERROR: No card found.\n");        return -EIO;    }    /*     * Link a couple of device structures into the chain     *     * For the A port     * Allocate space for 4 buffers even though we only need 3,     * because one of them may cross a DMA page boundary and     * be rejected by get_dma_buffer().     */    register_netdev(&pt0a);    pt0a.priv= kmalloc(sizeof(struct pt_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);    pt0a.dma = 0;	/* wizzer - no dma yet */    pt0a.base_addr = ioaddr + CHANA;    pt0a.irq = 0;    /* And B port */    register_netdev(&pt0b);    pt0b.priv= kmalloc(sizeof(struct pt_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);    pt0b.base_addr = ioaddr + CHANB;    pt0b.irq = 0;    /* Now initialise them */    pt_probe(&pt0a);    pt_probe(&pt0b);    pt0b.irq = pt0a.irq;	/* IRQ is shared */    return 0;} /* pt_init() *//* * Probe for PT card.  Also initialises the timers */__initfunc(static int hw_probe(int ioaddr)){    int time = 1000;		/* Number of milliseconds to test */    int a = 1;    int b = 1;    unsigned long start_time, end_time;    inb_p(ioaddr + TMR1CLR);    inb_p(ioaddr + TMR2CLR);    /* Timer counter channel 0, 1mS period */    outb_p(SC0 | LSB_MSB | MODE3, ioaddr + TMRCMD);    outb_p(0x00, ioaddr + TMR0);    outb_p(0x18, ioaddr + TMR0);    /* Setup timer control word for timer 1 */    outb_p(SC1 | LSB_MSB | MODE0, ioaddr + TMRCMD);    outb_p((time << 1) & 0xff, ioaddr + TMR1);    outb_p((time >> 7) & 0xff, ioaddr + TMR1);    /* wait until counter reg is loaded */    do {        /* Latch count for reading */        outb_p(SC1, ioaddr + TMRCMD);        a = inb_p(ioaddr + TMR1);        b = inb_p(ioaddr + TMR1);    } while (b == 0);    start_time = jiffies;    while(b != 0)    {        /* Latch count for reading */        outb_p(SC1, ioaddr + TMRCMD);        a = inb_p(ioaddr + TMR1);        b = inb_p(ioaddr + TMR1);        end_time = jiffies;        /* Don't wait forever - there may be no card here */        if ((end_time - start_time) > 200)        {        	inb_p(ioaddr + TMR1CLR);            return 0;        }    }    /* Now fix the timers up for general operation */    /* Clear the timers */    inb_p(ioaddr + TMR1CLR);    inb_p(ioaddr + TMR2CLR);    outb_p(SC1 | LSB_MSB | MODE0, ioaddr + TMRCMD);    inb_p(ioaddr + TMR1CLR);    outb_p(SC2 | LSB_MSB | MODE0, ioaddr + TMRCMD);    /* Should this be tmr1 or tmr2? wiz3*/    inb_p(ioaddr + TMR1CLR);    return 1;} /* hw_probe() */static void pt_rts(struct pt_local *lp, int x){	int tc;	long br;	int cmd = lp->base + CTL;#ifdef PT_DEBUG	printk(KERN_DEBUG "PT: pt_rts(): Transmitter status will be %d (%d).\n", x, lp->base & CHANA);#endif	if (x == ON) {	    /* Ex ints off to avoid int */	    wrtscc(lp->cardbase, cmd, R15, 0);	    wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8);	/* Rx off */	    lp->rstate = IDLE;	    if(lp->dmachan)	    {	        /* Setup for Tx DMA */	        wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);	    } else {	        /* No interrupts */	        wrtscc(lp->cardbase, cmd, R1, 0);	    }            if (!lp->clockmode)            {                if (lp->speed)                {                    br = lp->speed;                    tc = (lp->xtal / (br * 2)) - 2;                    wrtscc(lp->cardbase, cmd, R12, tc & 0xff);                    wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);                }            }            /* Turn on Tx by raising RTS */            wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8 | DTR);            /* Transmitter on now */        } else {		/* turning off Tx */            lp->tstate = IDLE;            /* Turn off Tx by dropping RTS */            wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR);            if (!lp->clockmode)            {                if (lp->speed)		/* internally clocked */                {                    /* Reprogram BRG from 32x clock for Rx DPLL */                    /* BRG off, keep PClk source */                    wrtscc(lp->cardbase, cmd, R14, BRSRC);                    br = lp->speed;                    tc = ((lp->xtal / 32) / (br * 2)) - 2;                    wrtscc(lp->cardbase, cmd, R12, tc & 0xff);                    wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);                    /* SEARCH mode, BRG source */                    wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH);                    /* Enable the BRG */                    wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL);                }            }            /* Flush Rx fifo */            /* Turn Rx off */            wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8);            /* Reset error latch */            wrtscc(lp->cardbase, cmd, R0, ERR_RES);            /* get status byte from R1 */            (void) rdscc(lp->cardbase, cmd, R1);            /* Read and dump data in queue */            (void) rdscc(lp->cardbase, cmd, R8);            (void) rdscc(lp->cardbase, cmd, R8);            (void) rdscc(lp->cardbase, cmd, R8);            /* Now, turn on Rx and hunt for a flag */              wrtscc(lp->cardbase, cmd, R3, RxENABLE | AUTO_ENAB | Rx8 );            lp->rstate = ACTIVE;            if (lp->dmachan)            {                setup_rx_dma(lp);            } else {                /* Reset buffer pointers */                lp->rcp = lp->rcvbuf->data;                lp->rcvbuf->cnt = 0;                /* Allow aborts to interrupt us */                wrtscc(lp->cardbase, cmd, R1, INT_ALL_Rx | EXT_INT_ENAB);	}	wrtscc(lp->cardbase, cmd, R15, BRKIE );    }} /* pt_rts() */static int valid_dma_page(unsigned long addr, unsigned long dev_bufsize){    if (((addr & 0xffff) + dev_bufsize) <= 0x10000)        return 1;    else        return 0;}static int pt_set_mac_address(struct device *dev, void *addr){	struct sockaddr *sa = (struct sockaddr *)addr;	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);		/* addr is an AX.25 shifted ASCII */	return 0;		/* mac address */}/* Allocate a buffer which does not cross a DMA page boundary */static char * get_dma_buffer(unsigned long *mem_ptr){    char *ret;    ret = (char *) *mem_ptr;    if (!valid_dma_page(*mem_ptr, DMA_BUFF_SIZE + sizeof(struct mbuf))) {        *mem_ptr += (DMA_BUFF_SIZE + sizeof(struct mbuf));        ret = (char *) *mem_ptr;    }    *mem_ptr += (DMA_BUFF_SIZE + sizeof(struct mbuf));    return (ret);} /* get_dma_buffer() *//* * Sets up all the structures for the PT device */static int pt_probe(struct device *dev){    short ioaddr;    struct pt_local *lp;    unsigned long flags;    unsigned long mem_ptr;    ioaddr = dev->base_addr;    /*     * Initialise the device structure.     * Must be done before chipset_init()     * Make sure data structures used by  the PT are aligned     */    dev->priv = (void *) (((int) dev->priv + 7) & ~7);    lp = (struct pt_local*) dev->priv;    memset(dev->priv, 0, sizeof(struct pt_local));    /* Allocate some buffers which do not cross DMA boundaries */    mem_ptr = (unsigned long) dev->priv + sizeof(struct pt_local);    lp->txdmabuf = get_dma_buffer(&mem_ptr);    lp->rxdmabuf1 = (struct mbuf *) get_dma_buffer(&mem_ptr);    lp->rxdmabuf2 = (struct mbuf *) get_dma_buffer(&mem_ptr);    /* Initialise the Rx buffer */    lp->rcvbuf = lp->rxdmabuf1;    lp->rcp = lp->rcvbuf->data;    lp->rcvbuf->cnt = 0;    /* Initialise the transmit queue head structure */    skb_queue_head_init(&lp->sndq);    lp->base = dev->base_addr;    lp->cardbase = dev->base_addr & 0x3f0;    /* These need to be initialised before scc_init() is called.     */    lp->xtal = XTAL;    if (dev->base_addr & CHANA) {        lp->speed = DEF_A_SPEED;        lp->txdelay = DEF_A_TXDELAY;        lp->persist = DEF_A_PERSIST;        lp->slotime = DEF_A_SLOTIME;        lp->squeldelay = DEF_A_SQUELDELAY;        lp->clockmode = DEF_A_CLOCKMODE;        lp->nrzi = DEF_A_NRZI;    } else {        lp->speed = DEF_B_SPEED;        lp->txdelay = DEF_B_TXDELAY;        lp->persist = DEF_B_PERSIST;        lp->slotime = DEF_B_SLOTIME;        lp->squeldelay = DEF_B_SQUELDELAY;        lp->clockmode = DEF_B_CLOCKMODE;        lp->nrzi = DEF_B_NRZI;    }    lp->bufsiz = DMA_BUFF_SIZE;    lp->tstate = IDLE;    chipset_init(dev);    if (dev->base_addr & CHANA) {        /* Note that a single IRQ services 2 devices (A and B channels)        */	/*	 * We disable the dma for a while, we have to get ints working	 * properly first!!	 */	lp->dmachan = 0;        if (dev->irq < 2) {            autoirq_setup(0);            /* Turn on PT interrupts */            save_flags(flags);            cli();            outb_p( pt_sercfg |= PT_EI, lp->cardbase + INT_CFG);            restore_flags(flags);            /* Set a timer interrupt */            tdelay(lp, 1);            dev->irq = autoirq_report(20);	    /* Turn off PT interrupts */	    save_flags(flags);	    cli();            outb_p( (pt_sercfg  &= ~ PT_EI), lp->cardbase + INT_CFG);            restore_flags(flags);            if (!dev->irq) {                printk(KERN_ERR "PT: ERROR: Failed to detect IRQ line, assuming IRQ7.\n");            }        }        printk(KERN_INFO "PT: Autodetected IRQ %d, assuming DMA %d\n", dev->irq, dev->dma);        /* This board has jumpered interrupts. Snarf the interrupt vector         * now.  There is no point in waiting since no other device can use         * the interrupt, and this marks the 'irqaction' as busy.         */        {            int irqval = request_irq(dev->irq, &pt_interrupt,0, "pt", dev);            if (irqval) {                printk(KERN_ERR "PT: ERROR: Unable to get IRQ %d (irqval = %d).\n",                    dev->irq, irqval);                return EAGAIN;            }        }        /* Grab the region */        request_region(ioaddr & 0x3f0, PT_TOTAL_SIZE, "pt" );    } /* A port */    dev->open = pt_open;    dev->stop = pt_close;    dev->do_ioctl = pt_ioctl;    dev->hard_start_xmit = pt_send_packet;    dev->get_stats = pt_get_stats;    /* Fill in the fields of the device structure */    dev_init_buffers(dev);#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)    dev->hard_header    = ax25_encapsulate;    dev->rebuild_header = ax25_rebuild_header;#endif    dev->set_mac_address = pt_set_mac_address;    dev->type = ARPHRD_AX25;            /* AF_AX25 device */    dev->hard_header_len = 73;      /* We do digipeaters now */    dev->mtu = 1500;                /* eth_mtu is default */    dev->addr_len = 7;               /* sizeof an ax.25 address */    memcpy(dev->broadcast, ax25_bcast, 7);    memcpy(dev->dev_addr, ax25_test, 7);    /* New style flags */    dev->flags = 0;    return 0;} /* pt_probe() *//* Open/initialise the board.  This is called (in the current kernel) * sometime after booting when the 'ifconfig' program is run. * * This routine should set everything up anew at each open, even * registers that 'should' only be set once at boot, so that there is * a non-reboot way to recover if something goes wrong. * derived from last half of tsync_attach() */static int pt_open(struct device *dev){    unsigned long flags;    struct pt_local *lp = dev->priv;    static first_time = 1;    if (dev->base_addr & CHANA)    {        if (first_time)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -