예제 #1
0
static netdev_tx_t send_packet(struct net_device *dev, struct sk_buff *skb)
{
	elp_device *adapter = netdev_priv(dev);
	unsigned long target;
	unsigned long flags;

	unsigned int nlen = (((skb->len < 60) ? 60 : skb->len) + 1) & (~1);

	if (test_and_set_bit(0, (void *) &adapter->busy)) {
		if (elp_debug >= 2)
			pr_debug("%s: transmit blocked\n", dev->name);
		return false;
	}

	dev->stats.tx_bytes += nlen;

	adapter->tx_pcb.command = CMD_TRANSMIT_PACKET;
	adapter->tx_pcb.length = sizeof(struct Xmit_pkt);
	adapter->tx_pcb.data.xmit_pkt.buf_ofs
	    = adapter->tx_pcb.data.xmit_pkt.buf_seg = 0;	
	adapter->tx_pcb.data.xmit_pkt.pkt_len = nlen;

	if (!send_pcb(dev, &adapter->tx_pcb)) {
		adapter->busy = 0;
		return false;
	}
	
	if (test_and_set_bit(0, (void *) &adapter->dmaing))
		pr_debug("%s: tx: DMA %d in progress\n", dev->name, adapter->current_dma.direction);

	adapter->current_dma.direction = 1;
	adapter->current_dma.start_time = jiffies;

	if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS || nlen != skb->len) {
		skb_copy_from_linear_data(skb, adapter->dma_buffer, nlen);
		memset(adapter->dma_buffer+skb->len, 0, nlen-skb->len);
		target = isa_virt_to_bus(adapter->dma_buffer);
	}
	else {
		target = isa_virt_to_bus(skb->data);
	}
	adapter->current_dma.skb = skb;

	flags=claim_dma_lock();
	disable_dma(dev->dma);
	clear_dma_ff(dev->dma);
	set_dma_mode(dev->dma, 0x48);	
	set_dma_addr(dev->dma, target);
	set_dma_count(dev->dma, nlen);
	outb_control(adapter->hcr_val | DMAE | TCEN, dev);
	enable_dma(dev->dma);
	release_dma_lock(flags);

	if (elp_debug >= 3)
		pr_debug("%s: DMA transfer started\n", dev->name);

	return true;
}
static int mc32_load_rx_ring(struct net_device *dev)
{
    struct mc32_local *lp = netdev_priv(dev);
    int i;
    u16 rx_base;
    volatile struct skb_header *p;

    rx_base=lp->rx_chain;

    for(i=0; i<RX_RING_LEN; i++) {
        lp->rx_ring[i].skb=alloc_skb(1532, GFP_KERNEL);
        if (lp->rx_ring[i].skb==NULL) {
            for (; i>=0; i--)
                kfree_skb(lp->rx_ring[i].skb);
            return -ENOBUFS;
        }
        skb_reserve(lp->rx_ring[i].skb, 18);

        p=isa_bus_to_virt(lp->base+rx_base);

        p->control=0;
        p->data=isa_virt_to_bus(lp->rx_ring[i].skb->data);
        p->status=0;
        p->length=1532;

        lp->rx_ring[i].p=p;
        rx_base=p->next;
    }

    lp->rx_ring[i-1].p->control |= CONTROL_EOL;

    lp->rx_ring_tail=0;

    return 0;
}
예제 #3
0
/*
 * Routine used to find the iSCSI Boot Format Table. The logical
 * kernel address is set in the ibft_addr global variable.
 */
unsigned long __init find_ibft_region(unsigned long *sizep)
{

	ibft_addr = NULL;

#ifdef CONFIG_ACPI
	/*
	 * One spec says "IBFT", the other says "iBFT". We have to check
	 * for both.
	 */
	if (!ibft_addr)
		acpi_table_parse(ACPI_SIG_IBFT, acpi_find_ibft);
	if (!ibft_addr)
		acpi_table_parse(IBFT_SIGN, acpi_find_ibft);
#endif /* CONFIG_ACPI */

	/* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
	 * only use ACPI for this */

	if (!ibft_addr && !efi_enabled)
		find_ibft_in_mem();

	if (ibft_addr) {
		*sizep = PAGE_ALIGN(ibft_addr->header.length);
		return (u64)isa_virt_to_bus(ibft_addr);
	}

	*sizep = 0;
	return 0;
}
예제 #4
0
static void receive_packet(struct net_device *dev, int len)
{
	int rlen;
	elp_device *adapter = dev->priv;
	void *target;
	struct sk_buff *skb;
	unsigned long flags;

	rlen = (len + 1) & ~1;
	skb = dev_alloc_skb(rlen + 2);

	if (!skb) {
		printk(KERN_WARNING "%s: memory squeeze, dropping packet\n", dev->name);
		target = adapter->dma_buffer;
		adapter->current_dma.target = NULL;
		/* FIXME: stats */
		return;
	}

	skb_reserve(skb, 2);
	target = skb_put(skb, rlen);
	if ((unsigned long)(target + rlen) >= MAX_DMA_ADDRESS) {
		adapter->current_dma.target = target;
		target = adapter->dma_buffer;
	} else {
		adapter->current_dma.target = NULL;
	}

	/* if this happens, we die */
	if (test_and_set_bit(0, (void *) &adapter->dmaing))
		printk(KERN_ERR "%s: rx blocked, DMA in progress, dir %d\n", dev->name, adapter->current_dma.direction);

	skb->dev = dev;
	adapter->current_dma.direction = 0;
	adapter->current_dma.length = rlen;
	adapter->current_dma.skb = skb;
	adapter->current_dma.start_time = jiffies;

	outb_control(adapter->hcr_val | DIR | TCEN | DMAE, dev);

	flags=claim_dma_lock();
	disable_dma(dev->dma);
	clear_dma_ff(dev->dma);
	set_dma_mode(dev->dma, 0x04);	/* dma read */
	set_dma_addr(dev->dma, isa_virt_to_bus(target));
	set_dma_count(dev->dma, rlen);
	enable_dma(dev->dma);
	release_dma_lock(flags);

	if (elp_debug >= 3) {
		printk(KERN_DEBUG "%s: rx DMA transfer started\n", dev->name);
	}

	if (adapter->rx_active)
		adapter->rx_active--;

	if (!adapter->busy)
		printk(KERN_WARNING "%s: receive_packet called, busy not set.\n", dev->name);
}
예제 #5
0
파일: wbsd.c 프로젝트: prime5711/blackbox
static void wbsd_init_dma(struct wbsd_host* host)
{
	host->dma = -1;
	
	if (dma < 0)
		return;
	
	if (request_dma(dma, DRIVER_NAME))
		goto err;
	
	/*
	 * We need to allocate a special buffer in
	 * order for ISA to be able to DMA to it.
	 */
	host->dma_buffer = kmalloc(65536,
		GFP_NOIO | GFP_DMA | __GFP_REPEAT | __GFP_NOWARN);
	if (!host->dma_buffer)
		goto free;

	/*
	 * Translate the address to a physical address.
	 */
	host->dma_addr = isa_virt_to_bus(host->dma_buffer);
			
	/*
	 * ISA DMA must be aligned on a 64k basis.
	 */
	if ((host->dma_addr & 0xffff) != 0)
		goto kfree;
	/*
	 * ISA cannot access memory above 16 MB.
	 */
	else if (host->dma_addr >= 0x1000000)
		goto kfree;

	host->dma = dma;
	
	return;
	
kfree:
	/*
	 * If we've gotten here then there is some kind of alignment bug
	 */
	BUG_ON(1);
	
	kfree(host->dma_buffer);
	host->dma_buffer = NULL;

free:
	free_dma(dma);

err:
	printk(KERN_WARNING DRIVER_NAME ": Unable to allocate DMA %d. "
		"Falling back on FIFO.\n", dma);
}
예제 #6
0
파일: 3c527.c 프로젝트: OpenHMR/Open-HMR600
static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev)
{
	struct mc32_local *lp = netdev_priv(dev);
	u32 head = atomic_read(&lp->tx_ring_head);
	
	volatile struct skb_header *p, *np;

	netif_stop_queue(dev);

	if(atomic_read(&lp->tx_count)==0) {
		return 1;
	}

	skb = skb_padto(skb, ETH_ZLEN);
	if (skb == NULL) {
		netif_wake_queue(dev);
		return 0;
	}

	atomic_dec(&lp->tx_count); 

	/* P is the last sending/sent buffer as a pointer */
	p=lp->tx_ring[head].p;
		
	head = next_tx(head);

	/* NP is the buffer we will be loading */
	np=lp->tx_ring[head].p; 
	
	/* We will need this to flush the buffer out */
	lp->tx_ring[head].skb=skb;

	np->length      = unlikely(skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;			
	np->data	= isa_virt_to_bus(skb->data);
	np->status	= 0;
	np->control     = CONTROL_EOP | CONTROL_EOL;     
	wmb();
		
	/*
	 * The new frame has been setup; we can now
	 * let the interrupt handler and card "see" it
	 */

	atomic_set(&lp->tx_ring_head, head); 
	p->control     &= ~CONTROL_EOL;

	netif_wake_queue(dev);
	return 0;
}
예제 #7
0
/* iSCSI는 IP기반의 저장 네트워크 표준이다. ibft는 iscsi boot format table */
unsigned long __init find_ibft_region(unsigned long *sizep)
{
	ibft_addr = NULL;

	/* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
	 * only use ACPI for this */

	if (!efi_enabled)
		find_ibft_in_mem();

	if (ibft_addr) {
		*sizep = PAGE_ALIGN(ibft_addr->header.length);
		return (u64)isa_virt_to_bus(ibft_addr);
	}

	*sizep = 0;
	return 0;
}
예제 #8
0
파일: 3c505.c 프로젝트: smx-smx/dsl-n55u
static int send_packet(struct net_device *dev, struct sk_buff *skb)
{
	elp_device *adapter = dev->priv;
	unsigned long target;
	unsigned long flags;

	/*
	 * make sure the length is even and no shorter than 60 bytes
	 */
	unsigned int nlen = (((skb->len < 60) ? 60 : skb->len) + 1) & (~1);

	if (test_and_set_bit(0, (void *) &adapter->busy)) {
		if (elp_debug >= 2)
			printk(KERN_DEBUG "%s: transmit blocked\n", dev->name);
		return FALSE;
	}

	adapter->stats.tx_bytes += nlen;

	/*
	 * send the adapter a transmit packet command. Ignore segment and offset
	 * and make sure the length is even
	 */
	adapter->tx_pcb.command = CMD_TRANSMIT_PACKET;
	adapter->tx_pcb.length = sizeof(struct Xmit_pkt);
	adapter->tx_pcb.data.xmit_pkt.buf_ofs
	    = adapter->tx_pcb.data.xmit_pkt.buf_seg = 0;	/* Unused */
	adapter->tx_pcb.data.xmit_pkt.pkt_len = nlen;

	if (!send_pcb(dev, &adapter->tx_pcb)) {
		adapter->busy = 0;
		return FALSE;
	}
	/* if this happens, we die */
	if (test_and_set_bit(0, (void *) &adapter->dmaing))
		printk(KERN_DEBUG "%s: tx: DMA %d in progress\n", dev->name, adapter->current_dma.direction);

	adapter->current_dma.direction = 1;
	adapter->current_dma.start_time = jiffies;

	if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS || nlen != skb->len) {
		skb_copy_from_linear_data(skb, adapter->dma_buffer, nlen);
		memset(adapter->dma_buffer+skb->len, 0, nlen-skb->len);
		target = isa_virt_to_bus(adapter->dma_buffer);
	}
	else {
		target = isa_virt_to_bus(skb->data);
	}
	adapter->current_dma.skb = skb;

	flags=claim_dma_lock();
	disable_dma(dev->dma);
	clear_dma_ff(dev->dma);
	set_dma_mode(dev->dma, 0x48);	/* dma memory -> io */
	set_dma_addr(dev->dma, target);
	set_dma_count(dev->dma, nlen);
	outb_control(adapter->hcr_val | DMAE | TCEN, dev);
	enable_dma(dev->dma);
	release_dma_lock(flags);

	if (elp_debug >= 3)
		printk(KERN_DEBUG "%s: DMA transfer started\n", dev->name);

	return TRUE;
}
static void mc32_rx_ring(struct net_device *dev)
{
    struct mc32_local *lp = netdev_priv(dev);
    volatile struct skb_header *p;
    u16 rx_ring_tail;
    u16 rx_old_tail;
    int x=0;

    rx_old_tail = rx_ring_tail = lp->rx_ring_tail;

    do
    {
        p=lp->rx_ring[rx_ring_tail].p;

        if(!(p->status & (1<<7))) { /* Not COMPLETED */
            break;
        }
        if(p->status & (1<<6)) /* COMPLETED_OK */
        {

            u16 length=p->length;
            struct sk_buff *skb;
            struct sk_buff *newskb;

            /* Try to save time by avoiding a copy on big frames */

            if ((length > RX_COPYBREAK)
                    && ((newskb=dev_alloc_skb(1532)) != NULL))
            {
                skb=lp->rx_ring[rx_ring_tail].skb;
                skb_put(skb, length);

                skb_reserve(newskb,18);
                lp->rx_ring[rx_ring_tail].skb=newskb;
                p->data=isa_virt_to_bus(newskb->data);
            }
            else
            {
                skb=dev_alloc_skb(length+2);

                if(skb==NULL) {
                    dev->stats.rx_dropped++;
                    goto dropped;
                }

                skb_reserve(skb,2);
                memcpy(skb_put(skb, length),
                       lp->rx_ring[rx_ring_tail].skb->data, length);
            }

            skb->protocol=eth_type_trans(skb,dev);
            dev->stats.rx_packets++;
            dev->stats.rx_bytes += length;
            netif_rx(skb);
        }

dropped:
        p->length = 1532;
        p->status = 0;

        rx_ring_tail=next_rx(rx_ring_tail);
    }
    while(x++<48);

    /* If there was actually a frame to be processed, place the EOL bit */
    /* at the descriptor prior to the one to be filled next */

    if (rx_ring_tail != rx_old_tail)
    {
        lp->rx_ring[prev_rx(rx_ring_tail)].p->control |=  CONTROL_EOL;
        lp->rx_ring[prev_rx(rx_old_tail)].p->control  &= ~CONTROL_EOL;

        lp->rx_ring_tail=rx_ring_tail;
    }
}
예제 #10
0
static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
{
    struct aha1542_hostdata *aha1542 = shost_priv(sh);
    u8 direction;
    u8 target = cmd->device->id;
    u8 lun = cmd->device->lun;
    unsigned long flags;
    int bufflen = scsi_bufflen(cmd);
    int mbo, sg_count;
    struct mailbox *mb = aha1542->mb;
    struct ccb *ccb = aha1542->ccb;
    struct chain *cptr;

    if (*cmd->cmnd == REQUEST_SENSE) {
        /* Don't do the command - we have the sense data already */
        cmd->result = 0;
        cmd->scsi_done(cmd);
        return 0;
    }
#ifdef DEBUG
    {
        int i = -1;
        if (*cmd->cmnd == READ_10 || *cmd->cmnd == WRITE_10)
            i = xscsi2int(cmd->cmnd + 2);
        else if (*cmd->cmnd == READ_6 || *cmd->cmnd == WRITE_6)
            i = scsi2int(cmd->cmnd + 2);
        shost_printk(KERN_DEBUG, sh, "aha1542_queuecommand: dev %d cmd %02x pos %d len %d",
                     target, *cmd->cmnd, i, bufflen);
        print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, cmd->cmd_len);
    }
#endif
    if (bufflen) {	/* allocate memory before taking host_lock */
        sg_count = scsi_sg_count(cmd);
        cptr = kmalloc(sizeof(*cptr) * sg_count, GFP_KERNEL | GFP_DMA);
        if (!cptr)
            return SCSI_MLQUEUE_HOST_BUSY;
    } else {
        sg_count = 0;
        cptr = NULL;
    }

    /* Use the outgoing mailboxes in a round-robin fashion, because this
       is how the host adapter will scan for them */

    spin_lock_irqsave(sh->host_lock, flags);
    mbo = aha1542->aha1542_last_mbo_used + 1;
    if (mbo >= AHA1542_MAILBOXES)
        mbo = 0;

    do {
        if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
            break;
        mbo++;
        if (mbo >= AHA1542_MAILBOXES)
            mbo = 0;
    } while (mbo != aha1542->aha1542_last_mbo_used);

    if (mb[mbo].status || aha1542->int_cmds[mbo])
        panic("Unable to find empty mailbox for aha1542.\n");

    aha1542->int_cmds[mbo] = cmd;	/* This will effectively prevent someone else from
					   screwing with this cdb. */

    aha1542->aha1542_last_mbo_used = mbo;

#ifdef DEBUG
    shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, cmd->scsi_done);
#endif

    any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo]));	/* This gets trashed for some reason */

    memset(&ccb[mbo], 0, sizeof(struct ccb));

    ccb[mbo].cdblen = cmd->cmd_len;

    direction = 0;
    if (*cmd->cmnd == READ_10 || *cmd->cmnd == READ_6)
        direction = 8;
    else if (*cmd->cmnd == WRITE_10 || *cmd->cmnd == WRITE_6)
        direction = 16;

    memcpy(ccb[mbo].cdb, cmd->cmnd, ccb[mbo].cdblen);

    if (bufflen) {
        struct scatterlist *sg;
        int i;

        ccb[mbo].op = 2;	/* SCSI Initiator Command  w/scatter-gather */
        cmd->host_scribble = (void *)cptr;
        scsi_for_each_sg(cmd, sg, sg_count, i) {
            any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg))
                     + sg->offset);
            any2scsi(cptr[i].datalen, sg->length);
        };
        any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
        any2scsi(ccb[mbo].dataptr, isa_virt_to_bus(cptr));
#ifdef DEBUG
        shost_printk(KERN_DEBUG, sh, "cptr %p: ", cptr);
        print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, cptr, 18);
#endif
    } else {
예제 #11
0
static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
{
    struct Scsi_Host *sh = dev_id;
    struct aha1542_hostdata *aha1542 = shost_priv(sh);
    void (*my_done)(struct scsi_cmnd *) = NULL;
    int errstatus, mbi, mbo, mbistatus;
    int number_serviced;
    unsigned long flags;
    struct scsi_cmnd *tmp_cmd;
    int flag;
    struct mailbox *mb = aha1542->mb;
    struct ccb *ccb = aha1542->ccb;

#ifdef DEBUG
    {
        flag = inb(INTRFLAGS(sh->io_port));
        shost_printk(KERN_DEBUG, sh, "aha1542_intr_handle: ");
        if (!(flag & ANYINTR))
            printk("no interrupt?");
        if (flag & MBIF)
            printk("MBIF ");
        if (flag & MBOA)
            printk("MBOF ");
        if (flag & HACC)
            printk("HACC ");
        if (flag & SCRD)
            printk("SCRD ");
        printk("status %02x\n", inb(STATUS(sh->io_port)));
    };
#endif
    number_serviced = 0;

    spin_lock_irqsave(sh->host_lock, flags);
    while (1) {
        flag = inb(INTRFLAGS(sh->io_port));

        /* Check for unusual interrupts.  If any of these happen, we should
           probably do something special, but for now just printing a message
           is sufficient.  A SCSI reset detected is something that we really
           need to deal with in some way. */
        if (flag & ~MBIF) {
            if (flag & MBOA)
                printk("MBOF ");
            if (flag & HACC)
                printk("HACC ");
            if (flag & SCRD)
                printk("SCRD ");
        }
        aha1542_intr_reset(sh->io_port);

        mbi = aha1542->aha1542_last_mbi_used + 1;
        if (mbi >= 2 * AHA1542_MAILBOXES)
            mbi = AHA1542_MAILBOXES;

        do {
            if (mb[mbi].status != 0)
                break;
            mbi++;
            if (mbi >= 2 * AHA1542_MAILBOXES)
                mbi = AHA1542_MAILBOXES;
        } while (mbi != aha1542->aha1542_last_mbi_used);

        if (mb[mbi].status == 0) {
            spin_unlock_irqrestore(sh->host_lock, flags);
            /* Hmm, no mail.  Must have read it the last time around */
            if (!number_serviced)
                shost_printk(KERN_WARNING, sh, "interrupt received, but no mail.\n");
            return IRQ_HANDLED;
        };

        mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / sizeof(struct ccb);
        mbistatus = mb[mbi].status;
        mb[mbi].status = 0;
        aha1542->aha1542_last_mbi_used = mbi;

#ifdef DEBUG
        if (ccb[mbo].tarstat | ccb[mbo].hastat)
            shost_printk(KERN_DEBUG, sh, "aha1542_command: returning %x (status %d)\n",
                         ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
#endif

        if (mbistatus == 3)
            continue;	/* Aborted command not found */

#ifdef DEBUG
        shost_printk(KERN_DEBUG, sh, "...done %d %d\n", mbo, mbi);
#endif

        tmp_cmd = aha1542->int_cmds[mbo];

        if (!tmp_cmd || !tmp_cmd->scsi_done) {
            spin_unlock_irqrestore(sh->host_lock, flags);
            shost_printk(KERN_WARNING, sh, "Unexpected interrupt\n");
            shost_printk(KERN_WARNING, sh, "tarstat=%x, hastat=%x idlun=%x ccb#=%d\n", ccb[mbo].tarstat,
                         ccb[mbo].hastat, ccb[mbo].idlun, mbo);
            return IRQ_HANDLED;
        }
        my_done = tmp_cmd->scsi_done;
        kfree(tmp_cmd->host_scribble);
        tmp_cmd->host_scribble = NULL;
        /* Fetch the sense data, and tuck it away, in the required slot.  The
           Adaptec automatically fetches it, and there is no guarantee that
           we will still have it in the cdb when we come back */
        if (ccb[mbo].tarstat == 2)
            memcpy(tmp_cmd->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
                   SCSI_SENSE_BUFFERSIZE);


        /* is there mail :-) */

        /* more error checking left out here */
        if (mbistatus != 1)
            /* This is surely wrong, but I don't know what's right */
            errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
        else
            errstatus = 0;

#ifdef DEBUG
        if (errstatus)
            shost_printk(KERN_DEBUG, sh, "(aha1542 error:%x %x %x) ", errstatus,
                         ccb[mbo].hastat, ccb[mbo].tarstat);
        if (ccb[mbo].tarstat == 2)
            print_hex_dump_bytes("sense: ", DUMP_PREFIX_NONE, &ccb[mbo].cdb[ccb[mbo].cdblen], 12);
        if (errstatus)
            printk("aha1542_intr_handle: returning %6x\n", errstatus);
#endif
        tmp_cmd->result = errstatus;
        aha1542->int_cmds[mbo] = NULL;	/* This effectively frees up the mailbox slot, as
						   far as queuecommand is concerned */
        my_done(tmp_cmd);
        number_serviced++;
    };
}