Пример #1
0
static void init_82586_mem(struct net_device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;
	short ioaddr = dev->base_addr;
	unsigned long shmem = dev->mem_start;

	/* Enable loopback to protect the wire while starting up,
	   and hold the 586 in reset during the memory initialization. */
	outb(0x20, ioaddr + MISC_CTRL);

	/* Fix the ISCP address and base. */
	init_words[3] = SCB_BASE;
	init_words[7] = SCB_BASE;

	/* Write the words at 0xfff6 (address-aliased to 0xfffff6). */
	isa_memcpy_toio(dev->mem_end-10, init_words, 10);

	/* Write the words at 0x0000. */
	isa_memcpy_toio(dev->mem_start, init_words + 5, sizeof(init_words) - 10);

	/* Fill in the station address. */
	isa_memcpy_toio(dev->mem_start+SA_OFFSET, dev->dev_addr,
		   sizeof(dev->dev_addr));

	/* The Tx-block list is written as needed.  We just set up the values. */
	lp->tx_cmd_link = IDLELOOP + 4;
	lp->tx_head = lp->tx_reap = TX_BUF_START;

	init_rx_bufs(dev);

	/* Start the 586 by releasing the reset line, but leave loopback. */
	outb(0xA0, ioaddr + MISC_CTRL);

	/* This was time consuming to track down: you need to give two channel
	   attention signals to reliably start up the i82586. */
	outb(0, ioaddr + SIGNAL_CA);

	{
		int boguscnt = 50;
		while (isa_readw(shmem+iSCB_STATUS) == 0)
			if (--boguscnt == 0) {
				printk("%s: i82586 initialization timed out with status %04x,"
					   "cmd %04x.\n", dev->name,
					   isa_readw(shmem+iSCB_STATUS), isa_readw(shmem+iSCB_CMD));
				break;
			}
		/* Issue channel-attn -- the 82586 won't start. */
		outb(0, ioaddr + SIGNAL_CA);
	}

	/* Disable loopback and enable interrupts. */
	outb(0x84, ioaddr + MISC_CTRL);
	if (net_debug > 4)
		printk("%s: Initialized 82586, status %04x.\n", dev->name,
			   isa_readw(shmem+iSCB_STATUS));
	return;
}
Пример #2
0
int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len)
{
	int count = 0;

	while ((count < len) && (f->len > 0)) {

		int nread;

		if (f->tail <= f->head) {
			nread = len - count;
			if (nread > f->n - f->head)
				nread = f->n - f->head;
		}
		else {
			nread = f->tail - f->head;
			if (nread > len - count)
				nread = len - count;
		}

		isa_memcpy_toio((unsigned long) buf, f->data + f->head, nread);

		count += nread;
		buf += nread;
		f->len -= nread;
		f->head += nread;
		f->head %= f->n;
	}

	return count;
}
static void ultramca_block_output(struct net_device *dev, int count, const unsigned char *buf,
                int start_page)
{
	unsigned long shmem = dev->mem_start + ((start_page - START_PG) << 8);

	isa_memcpy_toio(shmem, buf, count);
}
Пример #4
0
static void es_block_output(struct net_device *dev, int count,
				const unsigned char *buf, int start_page)
{
	unsigned long shmem = dev->mem_start + ((start_page - ES_START_PG)<<8);

	count = (count + 3) & ~3;     /* Round up to doubleword */
	isa_memcpy_toio(shmem, buf, count);
}
Пример #5
0
static void
hpp_mem_block_output(struct net_device *dev, int count,
				const unsigned char *buf, int start_page)
{
	int ioaddr = dev->base_addr - NIC_OFFSET;
	int option_reg = inw(ioaddr + HPP_OPTION);

	outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
	outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
	isa_memcpy_toio(dev->mem_start, buf, (count + 3) & ~3);
	outw(option_reg, ioaddr + HPP_OPTION);

	return;
}
Пример #6
0
static void hardware_send_packet(struct net_device *dev, void *buf, short length)
{
	struct net_local *lp = (struct net_local *)dev->priv;
	short ioaddr = dev->base_addr;
	ushort tx_block = lp->tx_head;
	unsigned long write_ptr = dev->mem_start + tx_block;

	/* Set the write pointer to the Tx block, and put out the header. */
	isa_writew(0x0000,write_ptr);			/* Tx status */
	isa_writew(CMD_INTR|CmdTx,write_ptr+=2);		/* Tx command */
	isa_writew(tx_block+16,write_ptr+=2);		/* Next command is a NoOp. */
	isa_writew(tx_block+8,write_ptr+=2);			/* Data Buffer offset. */

	/* Output the data buffer descriptor. */
	isa_writew(length | 0x8000,write_ptr+=2);		/* Byte count parameter. */
	isa_writew(-1,write_ptr+=2);			/* No next data buffer. */
	isa_writew(tx_block+22+SCB_BASE,write_ptr+=2);	/* Buffer follows the NoOp command. */
	isa_writew(0x0000,write_ptr+=2);			/* Buffer address high bits (always zero). */

	/* Output the Loop-back NoOp command. */
	isa_writew(0x0000,write_ptr+=2);			/* Tx status */
	isa_writew(CmdNOp,write_ptr+=2);			/* Tx command */
	isa_writew(tx_block+16,write_ptr+=2);		/* Next is myself. */

	/* Output the packet at the write pointer. */
	isa_memcpy_toio(write_ptr+2, buf, length);

	/* Set the old command link pointing to this send packet. */
	isa_writew(tx_block,dev->mem_start + lp->tx_cmd_link);
	lp->tx_cmd_link = tx_block + 20;

	/* Set the next free tx region. */
	lp->tx_head = tx_block + TX_BUF_SIZE;
	if (lp->tx_head > RX_BUF_START - TX_BUF_SIZE)
		lp->tx_head = TX_BUF_START;

	if (net_debug > 4) {
		printk("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n",
			   dev->name, ioaddr, length, tx_block, lp->tx_head);
	}

	/* Grimly block further packets if there has been insufficient reaping. */
	if (++lp->tx_pkts_in_ring < NUM_TX_BUFS) 
		netif_wake_queue(dev);
}
Пример #7
0
/*
 * Either use the shared memory (if enabled on the board) or put the packet
 * out through the ASIC FIFO.
 */
static void
el2_block_output(struct net_device *dev, int count,
		 const unsigned char *buf, int start_page)
{
    unsigned short int *wrd;
    int boguscount;		/* timeout counter */
    unsigned short word;	/* temporary for better machine code */

    if (ei_status.word16)      /* Tx packets go into bank 0 on EL2/16 card */
	outb(EGACFR_RSEL|EGACFR_TCM, E33G_GACFR);
    else
	outb(EGACFR_NORM, E33G_GACFR);

    if (dev->mem_start) {	/* Shared memory transfer */
	unsigned long dest_addr = dev->mem_start +
	    ((start_page - ei_status.tx_start_page) << 8);
	isa_memcpy_toio(dest_addr, buf, count);
	outb(EGACFR_NORM, E33G_GACFR);	/* Back to bank1 in case on bank0 */
	return;
    }

/*
 *  No shared memory, put the packet out the other way.
 *  Set up then start the internal memory transfer to Tx Start Page
 */

    word = (unsigned short)start_page;
    outb(word&0xFF, E33G_DMAAH);
    outb(word>>8, E33G_DMAAL);

    outb_p((ei_status.interface_num ? ECNTRL_AUI : ECNTRL_THIN ) | ECNTRL_OUTPUT
	   | ECNTRL_START, E33G_CNTRL);

/*
 *  Here I am going to write data to the FIFO as quickly as possible.
 *  Note that E33G_FIFOH is defined incorrectly. It is really
 *  E33G_FIFOL, the lowest port address for both the byte and
 *  word write. Variable 'count' is NOT checked. Caller must supply a
 *  valid count. Note that I may write a harmless extra byte to the
 *  8390 if the byte-count was not even.
 */
    wrd = (unsigned short int *) buf;
    count  = (count + 1) >> 1;
    for(;;)
    {
        boguscount = 0x1000;
        while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
        {
            if(!boguscount--)
            {
                printk("%s: FIFO blocked in el2_block_output.\n", dev->name);
                el2_reset_8390(dev);
                goto blocked;
            }
        }
        if(count > WRD_COUNT)
        {
            outsw(E33G_FIFOH, wrd, WRD_COUNT);
            wrd   += WRD_COUNT;
            count -= WRD_COUNT;
        }
        else
        {
            outsw(E33G_FIFOH, wrd, count);
            break;
        }
    }
    blocked:;
    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
    return;
}
Пример #8
0
static int ibmlana_tx(struct sk_buff *skb, struct net_device *dev)
{
	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
	int retval = 0, tmplen, addr;
	unsigned long flags;
	tda_t tda;
	int baddr;

	/* find out if there are free slots for a frame to transmit. If not,
	   the upper layer is in deep desperation and we simply ignore the frame. */

	if (priv->txusedcnt >= TXBUFCNT) {
		retval = -EIO;
		priv->stat.tx_dropped++;
		goto tx_done;
	}

	/* copy the frame data into the next free transmit buffer - fillup missing */
	tmplen = skb->len;
	if (tmplen < 60)
		tmplen = 60;
	baddr = priv->txbufstart + (priv->nexttxdescr * PKTSIZE);
	isa_memcpy_toio(dev->mem_start + baddr, skb->data, skb->len);

	/* copy filler into RAM - in case we're filling up... 
	   we're filling a bit more than necessary, but that doesn't harm
	   since the buffer is far larger... 
	   Sorry Linus for the filler string but I couldn't resist ;-) */

	if (tmplen > skb->len) {
		char *fill = "NetBSD is a nice OS too! ";
		unsigned int destoffs = skb->len, l = strlen(fill);

		while (destoffs < tmplen) {
			isa_memcpy_toio(dev->mem_start + baddr + destoffs, fill, l);
			destoffs += l;
		}
	}

	/* set up the new frame descriptor */
	addr = priv->tdastart + (priv->nexttxdescr * sizeof(tda_t));
	isa_memcpy_fromio(&tda, dev->mem_start + addr, sizeof(tda_t));
	tda.length = tda.fraglength = tmplen;
	isa_memcpy_toio(dev->mem_start + addr, &tda, sizeof(tda_t));

	/* if there were no active descriptors, trigger the SONIC */
	spin_lock_irqsave(&priv->lock, flags);

	priv->txusedcnt++;
	priv->txused[priv->nexttxdescr] = 1;

	/* are all transmission slots used up ? */
	if (priv->txusedcnt >= TXBUFCNT)
		netif_stop_queue(dev);

	if (priv->txusedcnt == 1)
		StartTx(dev, priv->nexttxdescr);
	priv->nexttxdescr = (priv->nexttxdescr + 1) % TXBUFCNT;

	spin_unlock_irqrestore(&priv->lock, flags);
tx_done:
	dev_kfree_skb(skb);
	return retval;
}
Пример #9
0
static void irqrx_handler(struct net_device *dev)
{
	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
	rda_t rda;
	u32 rdaaddr, lrdaaddr;

	/* loop until ... */

	while (1) {
		/* read descriptor that was next to be filled by SONIC */

		rdaaddr = priv->rdastart + (priv->nextrxdescr * sizeof(rda_t));
		lrdaaddr = priv->rdastart + (priv->lastrxdescr * sizeof(rda_t));
		isa_memcpy_fromio(&rda, dev->mem_start + rdaaddr, sizeof(rda_t));

		/* iron out upper word halves of fields we use - SONIC will duplicate 
		   bits 0..15 to 16..31 */

		rda.status &= 0xffff;
		rda.length &= 0xffff;
		rda.startlo &= 0xffff;

		/* stop if the SONIC still owns it, i.e. there is no data for us */

		if (rda.inuse)
			break;

		/* good packet? */

		else if (rda.status & RCREG_PRX) {
			struct sk_buff *skb;

			/* fetch buffer */

			skb = dev_alloc_skb(rda.length + 2);
			if (skb == NULL)
				priv->stat.rx_dropped++;
			else {
				/* copy out data */

				isa_memcpy_fromio(skb_put(skb, rda.length),
					       dev->mem_start +
					       rda.startlo, rda.length);

				/* set up skb fields */

				skb->dev = dev;
				skb->protocol = eth_type_trans(skb, dev);
				skb->ip_summed = CHECKSUM_NONE;

				/* bookkeeping */
				dev->last_rx = jiffies;
				priv->stat.rx_packets++;
				priv->stat.rx_bytes += rda.length;

				/* pass to the upper layers */
				netif_rx(skb);
			}
		}

		/* otherwise check error status bits and increase statistics */

		else {
			priv->stat.rx_errors++;
			if (rda.status & RCREG_FAER)
				priv->stat.rx_frame_errors++;
			if (rda.status & RCREG_CRCR)
				priv->stat.rx_crc_errors++;
		}

		/* descriptor processed, will become new last descriptor in queue */

		rda.link = 1;
		rda.inuse = 1;
		isa_memcpy_toio(dev->mem_start + rdaaddr, &rda,
			     sizeof(rda_t));

		/* set up link and EOL = 0 in currently last descriptor. Only write
		   the link field since the SONIC may currently already access the
		   other fields. */

		isa_memcpy_toio(dev->mem_start + lrdaaddr + 20, &rdaaddr, 4);

		/* advance indices */

		priv->lastrxdescr = priv->nextrxdescr;
		if ((++priv->nextrxdescr) >= priv->rxbufcnt)
			priv->nextrxdescr = 0;
	}
}
Пример #10
0
static void InitBoard(struct net_device *dev)
{
	int camcnt;
	camentry_t cams[16];
	u32 cammask;
	struct dev_mc_list *mcptr;
	u16 rcrval;

	/* reset the SONIC */

	outw(CMDREG_RST, dev->base_addr + SONIC_CMDREG);
	udelay(10);

	/* clear all spurious interrupts */

	outw(inw(dev->base_addr + SONIC_ISREG), dev->base_addr + SONIC_ISREG);

	/* set up the SONIC's bus interface - constant for this adapter -
	   must be done while the SONIC is in reset */

	outw(DCREG_USR1 | DCREG_USR0 | DCREG_WC1 | DCREG_DW32, dev->base_addr + SONIC_DCREG);
	outw(0, dev->base_addr + SONIC_DCREG2);

	/* remove reset form the SONIC */

	outw(0, dev->base_addr + SONIC_CMDREG);
	udelay(10);

	/* data sheet requires URRA to be programmed before setting up the CAM contents */

	outw(0, dev->base_addr + SONIC_URRA);

	/* program the CAM entry 0 to the device address */

	camcnt = 0;
	putcam(cams, &camcnt, dev->dev_addr);

	/* start putting the multicast addresses into the CAM list.  Stop if
	   it is full. */

	for (mcptr = dev->mc_list; mcptr != NULL; mcptr = mcptr->next) {
		putcam(cams, &camcnt, mcptr->dmi_addr);
		if (camcnt == 16)
			break;
	}

	/* calculate CAM mask */

	cammask = (1 << camcnt) - 1;

	/* feed CDA into SONIC, initialize RCR value (always get broadcasts) */

	isa_memcpy_toio(dev->mem_start, cams, sizeof(camentry_t) * camcnt);
	isa_memcpy_toio(dev->mem_start + (sizeof(camentry_t) * camcnt), &cammask, sizeof(cammask));

#ifdef DEBUG
	printk("CAM setup:\n");
	dumpmem(dev, 0, sizeof(camentry_t) * camcnt + sizeof(cammask));
#endif

	outw(0, dev->base_addr + SONIC_CAMPTR);
	outw(camcnt, dev->base_addr + SONIC_CAMCNT);
	outw(CMDREG_LCAM, dev->base_addr + SONIC_CMDREG);
	if (!wait_timeout(dev, SONIC_CMDREG, CMDREG_LCAM, 0, 2)) {
		printk(KERN_ERR "%s:SONIC did not respond on LCAM command - giving up.", dev->name);
		return;
	} else {
		/* clear interrupt condition */

		outw(ISREG_LCD, dev->base_addr + SONIC_ISREG);

#ifdef DEBUG
		printk("Loading CAM done, address pointers %04x:%04x\n",
		       inw(dev->base_addr + SONIC_URRA),
		       inw(dev->base_addr + SONIC_CAMPTR));
		{
			int z;

			printk("\n-->CAM: PTR %04x CNT %04x\n",
			       inw(dev->base_addr + SONIC_CAMPTR),
			       inw(dev->base_addr + SONIC_CAMCNT));
			outw(CMDREG_RST, dev->base_addr + SONIC_CMDREG);
			for (z = 0; z < camcnt; z++) {
				outw(z, dev->base_addr + SONIC_CAMEPTR);
				printk("Entry %d: %04x %04x %04x\n", z,
				       inw(dev->base_addr + SONIC_CAMADDR0),
				       inw(dev->base_addr + SONIC_CAMADDR1),
				       inw(dev->base_addr + SONIC_CAMADDR2));
			}
			outw(0, dev->base_addr + SONIC_CMDREG);
		}
#endif
	}

	rcrval = RCREG_BRD | RCREG_LB_NONE;

	/* if still multicast addresses left or ALLMULTI is set, set the multicast
	   enable bit */

	if ((dev->flags & IFF_ALLMULTI) || (mcptr != NULL))
		rcrval |= RCREG_AMC;

	/* promiscous mode ? */

	if (dev->flags & IFF_PROMISC)
		rcrval |= RCREG_PRO;

	/* program receive mode */

	outw(rcrval, dev->base_addr + SONIC_RCREG);
#ifdef DEBUG
	printk("\nRCRVAL: %04x\n", rcrval);
#endif

	/* set up descriptors in shared memory + feed them into SONIC registers */

	InitDscrs(dev);
	if (!InitSONIC(dev))
		return;

	/* reset all pending interrupts */

	outw(0xffff, dev->base_addr + SONIC_ISREG);

	/* enable transmitter + receiver interrupts */

	outw(CMDREG_RXEN, dev->base_addr + SONIC_CMDREG);
	outw(IMREG_PRXEN | IMREG_RBEEN | IMREG_PTXEN | IMREG_TXEREN, dev->base_addr + SONIC_IMREG);

	/* turn on card interrupts */

	outb(inb(dev->base_addr + BCMREG) | BCMREG_IEN, dev->base_addr + BCMREG);

#ifdef DEBUG
	printk("Register dump after initialization:\n");
	dumpregs(dev);
#endif
}
Пример #11
0
static void InitDscrs(struct net_device *dev)
{
	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
	u32 addr, baddr, raddr;
	int z;
	tda_t tda;
	rda_t rda;
	rra_t rra;

	/* initialize RAM */

	isa_memset_io(dev->mem_start, 0xaa,
		      dev->mem_start - dev->mem_start);

	/* setup n TX descriptors - independent of RAM size */

	priv->tdastart = addr = 0;
	priv->txbufstart = baddr = sizeof(tda_t) * TXBUFCNT;
	for (z = 0; z < TXBUFCNT; z++) {
		tda.status = 0;
		tda.config = 0;
		tda.length = 0;
		tda.fragcount = 1;
		tda.startlo = baddr;
		tda.starthi = 0;
		tda.fraglength = 0;
		if (z == TXBUFCNT - 1)
			tda.link = priv->tdastart;
		else
			tda.link = addr + sizeof(tda_t);
		tda.link |= 1;
		isa_memcpy_toio(dev->mem_start + addr, &tda, sizeof(tda_t));
		addr += sizeof(tda_t);
		baddr += PKTSIZE;
	}

	/* calculate how many receive buffers fit into remaining memory */

	priv->rxbufcnt = (dev->mem_end - dev->mem_start - baddr) / (sizeof(rra_t) + sizeof(rda_t) + PKTSIZE);

	/* calculate receive addresses */

	priv->rrastart = raddr = priv->txbufstart + (TXBUFCNT * PKTSIZE);
	priv->rdastart = addr = priv->rrastart + (priv->rxbufcnt * sizeof(rra_t));
	priv->rxbufstart = baddr = priv->rdastart + (priv->rxbufcnt * sizeof(rda_t));
	
	for (z = 0; z < priv->rxbufcnt; z++) {
		rra.startlo = baddr;
		rra.starthi = 0;
		rra.cntlo = PKTSIZE >> 1;
		rra.cnthi = 0;
		isa_memcpy_toio(dev->mem_start + raddr, &rra, sizeof(rra_t));

		rda.status = 0;
		rda.length = 0;
		rda.startlo = 0;
		rda.starthi = 0;
		rda.seqno = 0;
		if (z < priv->rxbufcnt - 1)
			rda.link = addr + sizeof(rda_t);
		else
			rda.link = 1;
		rda.inuse = 1;
		isa_memcpy_toio(dev->mem_start + addr, &rda, sizeof(rda_t));

		baddr += PKTSIZE;
		raddr += sizeof(rra_t);
		addr += sizeof(rda_t);
	}

	/* initialize current pointers */

	priv->nextrxdescr = 0;
	priv->lastrxdescr = priv->rxbufcnt - 1;
	priv->nexttxdescr = 0;
	priv->currtxdescr = 0;
	priv->txusedcnt = 0;
	memset(priv->txused, 0, sizeof(priv->txused));
}