Пример #1
0
void alloc586(struct net_device *dev)
{
	struct priv *p = (struct priv *) dev->priv;

	elmc_id_reset586();
	DELAY(2);

	p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
	p->scb = (struct scb_struct *) bus_to_virt(dev->mem_start);
	p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct));

	memset((char *) p->iscp, 0, sizeof(struct iscp_struct));
	memset((char *) p->scp, 0, sizeof(struct scp_struct));

	p->scp->iscp = make24(p->iscp);
	p->scp->sysbus = SYSBUSVAL;
	p->iscp->scb_offset = make16(p->scb);

	p->iscp->busy = 1;
	elmc_id_reset586();
	elmc_id_attn586();

	DELAY(2);

	if (p->iscp->busy) {
		printk(KERN_ERR "%s: Init-Problems (alloc).\n", dev->name);
	}
	memset((char *) p->scb, 0, sizeof(struct scb_struct));
}
Пример #2
0
// helper function, mmap's the allocated area which is physically contiguous
int mmap_kmem(struct file *filp, struct vm_area_struct *vma)
{
        int ret;
        long length = vma->vm_end - vma->vm_start;

        /* check length - do not allow larger mappings than the number of
           pages allocated */
        if (length > NPAGES * PAGE_SIZE)
                return -EIO;
/* #ifdef ARCH_HAS_DMA_MMAP_COHERENT */
	if (vma->vm_pgoff == 0) {
		printk(KERN_INFO "Using dma_mmap_coherent\n");
		ret = dma_mmap_coherent(NULL, vma, alloc_ptr,
					dma_handle, length);
	} else
/* #else */
	{
		printk(KERN_INFO "Using remap_pfn_range\n");
		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
		vma->vm_flags |= VM_IO;
		printk(KERN_INFO "off=%d\n", vma->vm_pgoff);
	        ret = remap_pfn_range(vma, vma->vm_start,
			      PFN_DOWN(virt_to_phys(bus_to_virt(dma_handle))) +
			      vma->vm_pgoff, length, vma->vm_page_prot);
	}
/* #endif */
        /* map the whole physically contiguous area in one piece */
        if (ret < 0) {
		printk(KERN_ERR "mmap_alloc: remap failed (%d)\n", ret);
		return ret;
        }
        
        return 0;
}
Пример #3
0
/* module initialization - called at module load time */
static int __init mmap_alloc_init(void)
{
        int ret = 0;
        int i;

	/* Allocate not-cached memory area with dma_map_coherent. */
	printk(KERN_INFO "Use dma_alloc_coherent\n");
	alloc_ptr = dma_alloc_coherent (NULL, (NPAGES + 2) * PAGE_SIZE,
					&dma_handle, GFP_KERNEL);

	if (!alloc_ptr) {
                printk(KERN_ERR
		    "mmap_alloc: dma_alloc_coherent error\n");
                ret = -ENOMEM;
                goto out;
        }
	printk(KERN_INFO "mmap_alloc: physical address is %lu\n",
	    dma_handle);
	printk(KERN_INFO "mmap_alloc: bus_to_virt %lu\n",
	    virt_to_phys(bus_to_virt(dma_handle)));

	alloc_area = alloc_ptr;

        /* get the major number of the character device */
        if ((ret = alloc_chrdev_region(&mmap_dev, 0, 1, "mmap_alloc")) < 0) {
                printk(KERN_ERR
		    "mmap_alloc: could not allocate major number for mmap\n");
                goto out_vfree;
        }

        /* initialize the device structure and register the device with the
	 * kernel */
        cdev_init(&mmap_cdev, &mmap_fops);
        if ((ret = cdev_add(&mmap_cdev, mmap_dev, 1)) < 0) {
                printk(KERN_ERR
		    "mmap_alloc: could not allocate chrdev for mmap\n");
                goto out_unalloc_region;
        }

	/* store a pattern in the memory.
	 * the test application will check for it */
        for (i = 0; i < (NPAGES * PAGE_SIZE / sizeof(int)); i += 2) {
                alloc_area[i] = (0xdead << 16) + i;
                alloc_area[i + 1] = (0xbeef << 16) + i;
        }
        
        return ret;
        
  out_unalloc_region:
        unregister_chrdev_region(mmap_dev, 1);
  out_vfree:
	dma_free_coherent (NULL, (NPAGES + 2) * PAGE_SIZE, alloc_ptr,
	    dma_handle);
  out:
        return ret;
}
Пример #4
0
static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg)
{
	Scsi_Cmnd *current_command;
	spinlock_t *lock;
	u32 *m = (u32 *)msg;
	u8 as,ds,st;

	if(m[0] & (1<<13))
	{
		printk("IOP fail.\n");
		printk("From %d To %d Cmd %d.\n",
			(m[1]>>12)&0xFFF,
			m[1]&0xFFF,
			m[1]>>24);
		printk("Failure Code %d.\n", m[4]>>24);
		if(m[4]&(1<<16))
			printk("Format error.\n");
		if(m[4]&(1<<17))
			printk("Path error.\n");
		if(m[4]&(1<<18))
			printk("Path State.\n");
		if(m[4]&(1<<18))
			printk("Congestion.\n");
		
		m=(u32 *)bus_to_virt(m[7]);
		printk("Failing message is %p.\n", m);
		
		if((m[4]&(1<<18)) && retry_ct < 32)
		{
			retry_ctrl[retry_ct]=c;
			retry[retry_ct]=m;
			if(!retry_ct++)
			{
				retry_timer.expires=jiffies+1;
				add_timer(&retry_timer);
			}
		}
		else
		{
			/* Create a scsi error for this */
			current_command = (Scsi_Cmnd *)m[3];
			lock = &current_command->host->host_lock;
			printk("Aborted %ld\n", current_command->serial_number);

			spin_lock_irq(lock);
			current_command->result = DID_ERROR << 16;
			current_command->scsi_done(current_command);
			spin_unlock_irq(lock);
			
			/* Now flush the message by making it a NOP */
			m[0]&=0x00FFFFFF;
			m[0]|=(I2O_CMD_UTIL_NOP)<<24;
			i2o_post_message(c,virt_to_bus(m));
		}
		return;
	}
Пример #5
0
/**********************************************
 * Check to see if there's an 82586 out there.
 */
static int check586(struct net_device *dev,char *where,unsigned size)
{
	struct priv pb;
	struct priv *p = /* (struct priv *) dev->priv*/ &pb;
	char *iscp_addrs[2];
	int i;

	p->base = (unsigned long) bus_to_virt((unsigned long)where) + size - 0x01000000;
	p->memtop = bus_to_virt((unsigned long)where) + size;
	p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
	memset((char *)p->scp,0, sizeof(struct scp_struct));
	for(i=0;i<sizeof(struct scp_struct);i++) /* memory was writeable? */
		if(((char *)p->scp)[i])
			return 0;
	p->scp->sysbus = SYSBUSVAL;				/* 1 = 8Bit-Bus, 0 = 16 Bit */
	if(p->scp->sysbus != SYSBUSVAL)
		return 0;

	iscp_addrs[0] = bus_to_virt((unsigned long)where);
	iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct);

	for(i=0;i<2;i++)
	{
		p->iscp = (struct iscp_struct *) iscp_addrs[i];
		memset((char *)p->iscp,0, sizeof(struct iscp_struct));

		p->scp->iscp = make24(p->iscp);
		p->iscp->busy = 1;

		ni_reset586();
		ni_attn586();
		DELAY(1);	/* wait a while... */

		if(p->iscp->busy) /* i82586 clears 'busy' after successful init */
			return 0;
	}
	return 1;
}
Пример #6
0
/* Set DMA address
 *
 * Copy address to the structure, and set the invalid bit
 */
void set_dma_addr (dmach_t channel, unsigned long physaddr)
{
	dma_t *dma = dma_chan + channel;

	if (dma->active)
		printk(KERN_ERR "dma%d: altering DMA address while "
		       "DMA active\n", channel);

	dma->sg = &dma->buf;
	dma->sgcount = 1;
	dma->buf.__address = bus_to_virt(physaddr);
	dma->using_sg = 0;
	dma->invalid = 1;
}
Пример #7
0
static int __init check586(struct net_device *dev, unsigned long where, unsigned size)
{
	struct priv *p = (struct priv *) dev->priv;
	char *iscp_addrs[2];
	int i = 0;

	p->base = (unsigned long) bus_to_virt((unsigned long)where) + size - 0x01000000;
	p->memtop = bus_to_virt((unsigned long)where) + size;
	p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
	memset((char *) p->scp, 0, sizeof(struct scp_struct));
	p->scp->sysbus = SYSBUSVAL;	/* 1 = 8Bit-Bus, 0 = 16 Bit */

	iscp_addrs[0] = bus_to_virt((unsigned long)where);
	iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct);

	for (i = 0; i < 2; i++) {
		p->iscp = (struct iscp_struct *) iscp_addrs[i];
		memset((char *) p->iscp, 0, sizeof(struct iscp_struct));

		p->scp->iscp = make24(p->iscp);
		p->iscp->busy = 1;

		elmc_id_reset586();

		/* reset586 does an implicit CA */

		/* apparently, you sometimes have to kick the 82586 twice... */
		elmc_id_attn586();
		DELAY(1);

		if (p->iscp->busy) {	/* i82586 clears 'busy' after successful init */
			return 0;
		}
	}
	return 1;
}
static inline unsigned long ad1889_get_dma_addr(ad1889_state_t *state)
{
	struct dmabuf *dmabuf = &state->dmabuf;
	u32 offset;

	if (!(dmabuf->enable & (DAC_RUNNING | ADC_RUNNING))) {
		printk(KERN_ERR DEVNAME ": get_dma_addr called without dma enabled\n");
		return 0;
	}
	
	if (dmabuf->enable & DAC_RUNNING)
		offset = le32_to_cpu(AD1889_READL(state->card, AD_DMAWAVBA));
	else
		offset = le32_to_cpu(AD1889_READL(state->card, AD_DMAADCBA));

	return (unsigned long)bus_to_virt((unsigned long)offset) - (unsigned long)dmabuf->rawbuf;
}
Пример #9
0
static void do_cache_op(dma_addr_t dma_handle, size_t size,
			void (*fn)(unsigned long, unsigned long))
{
	unsigned long off = dma_handle & (PAGE_SIZE - 1);
	unsigned long pfn = PFN_DOWN(dma_handle);
	struct page *page = pfn_to_page(pfn);

	if (!PageHighMem(page))
		fn((unsigned long)bus_to_virt(dma_handle), size);
	else
		while (size > 0) {
			size_t sz = min_t(size_t, size, PAGE_SIZE - off);
			void *vaddr = kmap_atomic(page);

			fn((unsigned long)vaddr + off, sz);
			kunmap_atomic(vaddr);
			off = 0;
			++page;
			size -= sz;
		}
}
Пример #10
0
static int pms_capture(struct pms_device *dev, char *buf, int rgb555, int count)
{
	int y;
	int dw = 2*dev->width;
	char *src = (char *)bus_to_virt(mem_base);

	char tmp[dw+32]; /* using a temp buffer is faster than direct  */
	int cnt = 0;
	int len=0;
	unsigned char r8 = 0x5;  /* value for reg8  */

	if (rgb555)
		r8 |= 0x20; /* else use untranslated rgb = 565 */
	mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */

/*	printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
  
	for (y = 0; y < dev->height; y++ ) 
	{
		*src = 0;  /* synchronisiert neue Zeile */
		memcpy(tmp, src, dw+32); /* discard 16 word   */
		cnt -= dev->height;
		while (cnt <= 0) 
		{ 
			/*
			 *	Don't copy too far
			 */
			int dt=dw;
			if(dt+len>count)
				dt=count-len;
			cnt += dev->height;
			copy_to_user(buf, tmp+32, dt);
			buf += dt;    
			len += dt;
		}
	}
	return len;
}
Пример #11
0
static inline void *cpm2cpu_addr(unsigned long addr)
{
	if (addr >= CPM_ADDR)
		return (void *)addr;
	return bus_to_virt(addr);
}
Пример #12
0
/*
 * This function is very similar to ctl_ioctl_do_datamove().  Is there a
 * way to combine the functionality?
 *
 * XXX KDM may need to move this into a thread.  We're doing a bcopy in the
 * caller's context, which will usually be the backend.  That may not be a
 * good thing.
 */
static void
cfcs_datamove(union ctl_io *io)
{
	union ccb *ccb;
	bus_dma_segment_t cam_sg_entry, *cam_sglist;
	struct ctl_sg_entry ctl_sg_entry, *ctl_sglist;
	int cam_sg_count, ctl_sg_count, cam_sg_start;
	int cam_sg_offset;
	int len_to_copy, len_copied;
	int ctl_watermark, cam_watermark;
	int i, j;


	cam_sg_offset = 0;
	cam_sg_start = 0;

	ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;

	/*
	 * Note that we have a check in cfcs_action() to make sure that any
	 * CCBs with "bad" flags are returned with CAM_REQ_INVALID.  This
	 * is just to make sure no one removes that check without updating
	 * this code to provide the additional functionality necessary to
	 * support those modes of operation.
	 */
	KASSERT(((ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS) == 0), ("invalid "
		  "CAM flags %#x", (ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS)));

	/*
	 * Simplify things on both sides by putting single buffers into a
	 * single entry S/G list.
	 */
	switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) {
	case CAM_DATA_SG: {
		int len_seen;

		cam_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr;
		cam_sg_count = ccb->csio.sglist_cnt;

		for (i = 0, len_seen = 0; i < cam_sg_count; i++) {
			if ((len_seen + cam_sglist[i].ds_len) >=
			     io->scsiio.kern_rel_offset) {
				cam_sg_start = i;
				cam_sg_offset = io->scsiio.kern_rel_offset -
					len_seen;
				break;
			}
			len_seen += cam_sglist[i].ds_len;
		}
		break;
	}
	case CAM_DATA_VADDR:
		cam_sglist = &cam_sg_entry;
		cam_sglist[0].ds_len = ccb->csio.dxfer_len;
		cam_sglist[0].ds_addr = (bus_addr_t)ccb->csio.data_ptr;
		cam_sg_count = 1;
		cam_sg_start = 0;
		cam_sg_offset = io->scsiio.kern_rel_offset;
		break;
	default:
		panic("Invalid CAM flags %#x", ccb->ccb_h.flags);
	}

	if (io->scsiio.kern_sg_entries > 0) {
		ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
		ctl_sg_count = io->scsiio.kern_sg_entries;
	} else {
		ctl_sglist = &ctl_sg_entry;
		ctl_sglist->addr = io->scsiio.kern_data_ptr;
		ctl_sglist->len = io->scsiio.kern_data_len;
		ctl_sg_count = 1;
	}

	ctl_watermark = 0;
	cam_watermark = cam_sg_offset;
	len_copied = 0;
	for (i = cam_sg_start, j = 0;
	     i < cam_sg_count && j < ctl_sg_count;) {
		uint8_t *cam_ptr, *ctl_ptr;

		len_to_copy = ctl_min(cam_sglist[i].ds_len - cam_watermark,
				      ctl_sglist[j].len - ctl_watermark);

		cam_ptr = (uint8_t *)cam_sglist[i].ds_addr;
		cam_ptr = cam_ptr + cam_watermark;
		if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) {
			/*
			 * XXX KDM fix this!
			 */
			panic("need to implement bus address support");
#if 0
			kern_ptr = bus_to_virt(kern_sglist[j].addr);
#endif
		} else
			ctl_ptr = (uint8_t *)ctl_sglist[j].addr;
		ctl_ptr = ctl_ptr + ctl_watermark;

		ctl_watermark += len_to_copy;
		cam_watermark += len_to_copy;

		if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) ==
		     CTL_FLAG_DATA_IN) {
			CTL_DEBUG_PRINT(("%s: copying %d bytes to CAM\n",
					 __func__, len_to_copy));
			CTL_DEBUG_PRINT(("%s: from %p to %p\n", ctl_ptr,
					 __func__, cam_ptr));
			bcopy(ctl_ptr, cam_ptr, len_to_copy);
		} else {
			CTL_DEBUG_PRINT(("%s: copying %d bytes from CAM\n",
					 __func__, len_to_copy));
			CTL_DEBUG_PRINT(("%s: from %p to %p\n", cam_ptr,
					 __func__, ctl_ptr));
			bcopy(cam_ptr, ctl_ptr, len_to_copy);
		}

		len_copied += len_to_copy;

		if (cam_sglist[i].ds_len == cam_watermark) {
			i++;
			cam_watermark = 0;
		}

		if (ctl_sglist[j].len == ctl_watermark) {
			j++;
			ctl_watermark = 0;
		}
	}

	io->scsiio.ext_data_filled += len_copied;

	io->scsiio.be_move_done(io);
}
Пример #13
0
/*
 *	Print a string to the serial port trying not to disturb
 *	any possible real use of the port...
 *
 *	Note that this is called with interrupts already disabled
 */
static void cpm_uart_console_write(struct console *co, const char *s,
                                   u_int count)
{
    struct uart_cpm_port *pinfo =
            &cpm_uart_ports[cpm_uart_port_map[co->index]];
    unsigned int i;
    volatile cbd_t *bdp, *bdbase;
    volatile unsigned char *cp;

    /* Get the address of the host memory buffer.
     */
    bdp = pinfo->tx_cur;
    bdbase = pinfo->tx_bd_base;

    /*
     * Now, do each character.  This is not as bad as it looks
     * since this is a holding FIFO and not a transmitting FIFO.
     * We could add the complexity of filling the entire transmit
     * buffer, but we would just wait longer between accesses......
     */
    for (i = 0; i < count; i++, s++) {
        /* Wait for transmitter fifo to empty.
         * Ready indicates output is ready, and xmt is doing
         * that, not that it is ready for us to send.
         */
        while ((bdp->cbd_sc & BD_SC_READY) != 0)
            ;

        /* Send the character out.
         * If the buffer address is in the CPM DPRAM, don't
         * convert it.
         */
        if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
            cp = (unsigned char *) (bdp->cbd_bufaddr);
        else
            cp = bus_to_virt(bdp->cbd_bufaddr);

        *cp = *s;

        bdp->cbd_datlen = 1;
        bdp->cbd_sc |= BD_SC_READY;

        if (bdp->cbd_sc & BD_SC_WRAP)
            bdp = bdbase;
        else
            bdp++;

        /* if a LF, also do CR... */
        if (*s == 10) {
            while ((bdp->cbd_sc & BD_SC_READY) != 0)
                ;

            if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
                cp = (unsigned char *) (bdp->cbd_bufaddr);
            else
                cp = bus_to_virt(bdp->cbd_bufaddr);

            *cp = 13;
            bdp->cbd_datlen = 1;
            bdp->cbd_sc |= BD_SC_READY;

            if (bdp->cbd_sc & BD_SC_WRAP)
                bdp = bdbase;
            else
                bdp++;
        }
    }

    /*
     * Finally, Wait for transmitter & holding register to empty
     *  and restore the IER
     */
    while ((bdp->cbd_sc & BD_SC_READY) != 0)
        ;

    pinfo->tx_cur = (volatile cbd_t *) bdp;
}
Пример #14
0
/*
 * Transmit characters, refill buffer descriptor, if possible
 */
static int cpm_uart_tx_pump(struct uart_port *port)
{
    volatile cbd_t *bdp;
    unsigned char *p;
    int count;
    struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
    struct circ_buf *xmit = &port->info->xmit;

    /* Handle xon/xoff */
    if (port->x_char) {
        /* Pick next descriptor and fill from buffer */
        bdp = pinfo->tx_cur;

        p = bus_to_virt(bdp->cbd_bufaddr);
        *p++ = xmit->buf[xmit->tail];
        bdp->cbd_datlen = 1;
        bdp->cbd_sc |= BD_SC_READY;
        /* Get next BD. */
        if (bdp->cbd_sc & BD_SC_WRAP)
            bdp = pinfo->tx_bd_base;
        else
            bdp++;
        pinfo->tx_cur = bdp;

        port->icount.tx++;
        port->x_char = 0;
        return 1;
    }

    if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
        cpm_uart_stop_tx(port, 0);
        return 0;
    }

    /* Pick next descriptor and fill from buffer */
    bdp = pinfo->tx_cur;

    while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
        count = 0;
        p = bus_to_virt(bdp->cbd_bufaddr);
        while (count < pinfo->tx_fifosize) {
            *p++ = xmit->buf[xmit->tail];
            xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
            port->icount.tx++;
            count++;
            if (xmit->head == xmit->tail)
                break;
        }
        bdp->cbd_datlen = count;
        bdp->cbd_sc |= BD_SC_READY;
        /* Get next BD. */
        if (bdp->cbd_sc & BD_SC_WRAP)
            bdp = pinfo->tx_bd_base;
        else
            bdp++;
    }
    pinfo->tx_cur = bdp;

    if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
        uart_write_wakeup(port);

    if (uart_circ_empty(xmit)) {
        cpm_uart_stop_tx(port, 0);
        return 0;
    }

    return 1;
}
Пример #15
0
static void execute_release_code(pci_list* x)
{
  int pos;
  u8* releasecode;

  if (!x->releasecode)
    return;
  pos=0;
  releasecode=x->releasecode;

  cli();
  while (1) {
    int basenum=releasecode[pos];
    int type=releasecode[pos+2];
    unsigned int base=x->dev->resource[basenum].start;
    int io=(x->dev->resource[basenum].flags&1);
    unsigned int offset;
    unsigned int val;
    int len;
    unsigned int i;
    int op=releasecode[pos+1];

    pos+=2; /* skip base/op */
    if (type&0x40) {
      offset=((u32)releasecode[pos+2]<<8)|
	((u32)releasecode[pos+3]<<0);
      pos+=2;
    }
    else {
      offset=releasecode[pos+1];
    }      
    pos+=2; /* skip type/offset */
    switch(type) {
    case 0x80:
    case 0xc0: len=4; break;
    case 0x90:
    case 0xd0: len=2; break;
    case 0xa0:
    case 0xe0: len=1; break;
    default:
      sti();
      return;
    }
    val=0;
    for (i=0;i<len;i++)
      val=(val<<8)+releasecode[pos+i];

    printk("op %d: base %x, offset %x, val %x, io=%d, len=%d\n",op,base,offset,val,io,len);

    switch(op) {
    case 0x00: 
      {/* write */
	if (io) {
	  switch(len) {
	  case 4: outl(val,base+offset); break;
	  case 2: outw(val,base+offset); break;
	  case 1: outb(val,base+offset); break;
	  }
	}
	else { /* memory */
	  unsigned long paddr=(unsigned long)bus_to_virt(base+offset);
	  void* addr=ioremap(paddr,4);

	  switch(len) {
	  case 4: *((u32*)addr)=val; break;
	  case 2: *((u16*)addr)=val; break;
	  case 1: *((u8*)addr)=val; break;
	  }
	  iounmap(addr);
	}
      }
      break;

    case 0x01: 
      { /* read */
	if (io) {
	  switch(len) {
	  case 4: dummy+=inl(base+offset); break;
	  case 2: dummy+=inw(base+offset); break;
	  case 1: dummy+=inb(base+offset); break;
	  }
	}
	else { /* memory */
	  unsigned long paddr=(unsigned long)bus_to_virt(base+offset);
	  void* addr=ioremap(paddr,4);

	  switch(len) {
	  case 4: dummy+=*((u32*)addr); break;
	  case 2: dummy+=*((u16*)addr); break;
	  case 1: dummy+=*((u8*)addr); break;
	  }
	  iounmap(addr);
	}
      }
      break;

    case 0x02: 
      { /* sleep */
	for (i=0;i<val;i++)
	  outb(0,0x80);
      }
      break;

    default:
      break;
    }
    
    if (len==1)
      pos+=2;
    else
      pos+=len;
  }
  sti();
}
/*
 *  Returns number of bytes left to be transferred from the entire sgl list.
 *  *src_addr and *dst_addr get set to the source/destination address of
 *  the sgl descriptor where the DMA stopped.
 *
 *  An sgl transfer must NOT be active when this function is called.
 */
static __inline__ int
ppc4xx_get_dma_sgl_residue(sgl_handle_t handle, phys_addr_t * src_addr,
			   phys_addr_t * dst_addr)
{
	sgl_list_info_t *psgl = (sgl_list_info_t *) handle;
	ppc_dma_ch_t *p_dma_ch;
	ppc_sgl_t *pnext, *sgl_addr;
	uint32_t count_left;

	if (!handle) {
		printk("ppc4xx_get_dma_sgl_residue: null handle\n");
		return DMA_STATUS_BAD_HANDLE;
	} else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) {
		printk("ppc4xx_get_dma_sgl_residue: bad channel in handle %d\n",
		       psgl->dmanr);
		return DMA_STATUS_BAD_CHANNEL;
	}

	switch (psgl->dmanr) {
	case 0:
		sgl_addr = (ppc_sgl_t *) bus_to_virt(mfdcr(DCRN_ASG0));
		count_left = mfdcr(DCRN_DMACT0);
		break;
	case 1:
		sgl_addr = (ppc_sgl_t *) bus_to_virt(mfdcr(DCRN_ASG1));
		count_left = mfdcr(DCRN_DMACT1);
		break;
	case 2:
		sgl_addr = (ppc_sgl_t *) bus_to_virt(mfdcr(DCRN_ASG2));
		count_left = mfdcr(DCRN_DMACT2);
		break;
	case 3:
		sgl_addr = (ppc_sgl_t *) bus_to_virt(mfdcr(DCRN_ASG3));
		count_left = mfdcr(DCRN_DMACT3);
		break;
	default:
		printk("ppc4xx_get_dma_sgl_residue: bad channel %d\n", psgl->dmanr);
		goto error;
	}

	if (!sgl_addr) {
		printk("ppc4xx_get_dma_sgl_residue: sgl addr register is null\n");
		goto error;
	}

	pnext = psgl->phead;
	while (pnext &&
	       ((unsigned) pnext < ((unsigned) psgl + SGL_LIST_SIZE) &&
		(pnext != sgl_addr))
	    ) {
		pnext++;
	}

	if (pnext == sgl_addr) {	/* found the sgl descriptor */

		*src_addr = pnext->src_addr;
		*dst_addr = pnext->dst_addr;

		/*
		 * Now search the remaining descriptors and add their count.
		 * We already have the remaining count from this descriptor in
		 * count_left.
		 */
		pnext++;

		while ((pnext != psgl->ptail) &&
		       ((unsigned) pnext < ((unsigned) psgl + SGL_LIST_SIZE))
		    ) {
			count_left += pnext->control_count & SG_COUNT_MASK;
		}

		if (pnext != psgl->ptail) {	/* should never happen */
			printk
			    ("ppc4xx_get_dma_sgl_residue error (1) psgl->ptail 0x%x handle 0x%x\n",
			     (unsigned int) psgl->ptail, (unsigned int) handle);
			goto error;
		}

		/* success */
		p_dma_ch = &dma_channels[psgl->dmanr];
		return (count_left << p_dma_ch->shift);	/* count in bytes */

	} else {
		/* this shouldn't happen */
		printk
		    ("get_dma_sgl_residue, unable to match current address 0x%x, handle 0x%x\n",
		     (unsigned int) sgl_addr, (unsigned int) handle);

	}

      error:
	*src_addr = (phys_addr_t) NULL;
	*dst_addr = (phys_addr_t) NULL;
	return 0;
}
Пример #17
0
static unsigned long neo_sdram_dma_read_bus_direct
(zion_params_t *params, unsigned long offset_addr, void *buf, unsigned long size, int ch)
{
  unsigned long left_size;
  unsigned long entry_size;
  unsigned long upper = 0, lower = 0;
  int ret;

  /* check DWORD Alignment */
  if( (offset_addr%4)||(size%4) )
    {
      PERROR("Invalid Size or Address.\n");
      return 0;
    }

  /* check Setting of DMA Region */
  neo_get_region(params, ch, &lower, &upper);

  if(lower >= upper)
    {
      PERROR("No Region Specified.\n");
      return 0;
    }

  /* check size of area and size of IO */
  if(lower+offset_addr+size > upper)
    {
      size = upper - (lower + offset_addr);
    }

  if(size<=0)
    {
      return 0;
    }

  /* size to be read */
  left_size = size;

  /* Initalize SG table etc. */
  init_dma_ch(params,ch);

 DMA_READ:

  entry_size = DMA_MAX_ENTRY_SIZE;

  ret = make_sg_table_bus_direct(params, ch, &left_size, buf);

  if(ret)
    {
      size=0;
      left_size = 0;
      goto READ_RELEASE;
    }

  /* Set Registers and Set Timeout */
  neo_dma_prepare_bus_direct(params, ch, ZION_DMA_READ, (lower+offset_addr));

  /* Inv Cache */
//  dma_cache_inv(bus_to_virt((unsigned long)buf), size);
  dma_cache_sync(&params->dev->dev, bus_to_virt((unsigned long)buf), size, DMA_FROM_DEVICE);

  disable_irq(params->dev->irq);

  /* DMA Run */
  pci_write_config_word(params->dev, NEO_PCI_DMA_COMMAND(ch), 
			NEO_IO_DERECTION_READ|NEO_DMA_RUN|NEO_DMA_OPEN);

  ZION_PCI_PARAM(params)->dma_params[ch].timer.expires = jiffies + NEO_DMA_TIMEOUT;  
  add_timer(&(ZION_PCI_PARAM(params)->dma_params[ch].timer));

  enable_irq(params->dev->irq);
  
  /* Sleep */
  wait_event(ZION_PCI_PARAM(params)->dma_params[ch].neo_dma_wait_queue,
	     ZION_PCI_PARAM(params)->dma_params[ch].condition != ZION_PCI_INT_DISPATCH_PENDING);
  
  /* DMA End */
  if(ZION_PCI_PARAM(params)->dma_params[ch].condition == ZION_PCI_INT_DISPATCH_TIMEOUT)
    {
      PERROR("ZION DMA READ Timeout.\n");
      size = 0;
      left_size = 0;
      goto READ_RELEASE;
    }

 READ_RELEASE:

  release_dma_entry_bus_direct(params, ch);

  if(left_size)
    {
      //((u8 *)buf) += (size-left_size);
      buf += (size-left_size);
      goto  DMA_READ;
    }

  return size;
}
Пример #18
0
static void *_bus_to_virt(unsigned long ma)
{
	return is_ISA_range(ma, ma) ? isa_bus_to_virt(ma) : bus_to_virt(ma);
}
Пример #19
0
/* This routine is logically part of the interrupt handler, but isolated
   for clarity and better register allocation. */
static int netdev_rx(struct device *dev)
{
	struct netdev_private *np = (struct netdev_private *)dev->priv;
	int entry = np->cur_rx % RX_RING_SIZE;
	int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx;

	if (debug > 4) {
		printk(KERN_DEBUG " In netdev_rx(), entry %d status %4.4x.\n",
			   entry, np->rx_head_desc->rx_length);
	}

	/* If EOP is set on the next entry, it's a new packet. Send it up. */
	while ( ! (np->rx_head_desc->rx_length & DescOwn)) {
		struct rx_desc *desc = np->rx_head_desc;
		int data_size = desc->rx_length;
		u16 desc_status = desc->rx_status;

		if (debug > 4)
			printk(KERN_DEBUG "  netdev_rx() status is %4.4x.\n",
				   desc_status);
		if (--boguscnt < 0)
			break;
		if ( (desc_status & (RxWholePkt | RxErr)) !=  RxWholePkt) {
			if ((desc_status & RxWholePkt) !=  RxWholePkt) {
				printk(KERN_WARNING "%s: Oversized Ethernet frame spanned "
					   "multiple buffers, entry %#x length %d status %4.4x!\n",
					   dev->name, np->cur_rx, data_size, desc_status);
				printk(KERN_WARNING "%s: Oversized Ethernet frame %p vs %p.\n",
					   dev->name, np->rx_head_desc,
					   &np->rx_ring[np->cur_rx % RX_RING_SIZE]);
				np->stats.rx_length_errors++;
			} else if (desc_status & RxErr) {
				/* There was a error. */
				if (debug > 2)
					printk(KERN_DEBUG "  netdev_rx() Rx error was %8.8x.\n",
						   desc_status);
				np->stats.rx_errors++;
				if (desc_status & 0x0030) np->stats.rx_length_errors++;
				if (desc_status & 0x0048) np->stats.rx_fifo_errors++;
				if (desc_status & 0x0004) np->stats.rx_frame_errors++;
				if (desc_status & 0x0002) np->stats.rx_crc_errors++;
			}
		} else {
			struct sk_buff *skb;
			/* Length should omit the CRC */
			u16 pkt_len = data_size - 4;

			/* Check if the packet is long enough to accept without copying
			   to a minimally-sized skbuff. */
			if (pkt_len < rx_copybreak
				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
				skb->dev = dev;
				skb_reserve(skb, 2);	/* 16 byte align the IP header */
#if ! defined(__alpha__) || USE_IP_COPYSUM		/* Avoid misaligned on Alpha */
				eth_copy_and_sum(skb, bus_to_virt(desc->addr),
								 pkt_len, 0);
				skb_put(skb, pkt_len);
#else
				memcpy(skb_put(skb,pkt_len), bus_to_virt(desc->addr), pkt_len);
#endif
			} else {
				skb_put(skb = np->rx_skbuff[entry], pkt_len);
				np->rx_skbuff[entry] = NULL;
			}
			skb->protocol = eth_type_trans(skb, dev);
			np->stats.rx_bytes+=skb->len;
			netif_rx(skb);
			dev->last_rx = jiffies;
			np->stats.rx_packets++;
		}
		entry = (++np->cur_rx) % RX_RING_SIZE;
		np->rx_head_desc = &np->rx_ring[entry];
	}

	/* Refill the Rx ring buffers. */
	for (; np->cur_rx - np->dirty_rx > 0; np->dirty_rx++) {
		struct sk_buff *skb;
		entry = np->dirty_rx % RX_RING_SIZE;
		if (np->rx_skbuff[entry] == NULL) {
			skb = dev_alloc_skb(np->rx_buf_sz);
			np->rx_skbuff[entry] = skb;
			if (skb == NULL)
				break;			/* Better luck next round. */
			skb->dev = dev;			/* Mark as being used by this device. */
			np->rx_ring[entry].addr = virt_to_bus(skb->tail);
		}
		np->rx_ring[entry].rx_status = 0;
		np->rx_ring[entry].rx_length = DescOwn;
	}

	/* Pre-emptively restart Rx engine. */
	writew(CmdRxDemand | np->chip_cmd, dev->base_addr + ChipCmd);
	return 0;
}
Пример #20
0
BOOL cif_drv_load ( void)
{
  int            result = 0;
  BOOL           bSuccess = FALSE; // no board available
  unsigned short usIdx = 0;
  DEV_INSTANCE * dev = NULL;
  // Driver is loaded for the very first time
  DBG_PRN("Boards altogether: %X\n", cif_nr_devs);

  // get memory for global driver data, delete content
  if ( cif_nr_devs > 0) {
      for ( usIdx = 0; usIdx < cif_nr_devs/*CIF_MAX_BOARDS*/; usIdx++) {
        DBG_PRN("Install instance Number = %d\n", usIdx);
	dev = cif_dev_get_at( usIdx); 
	DBG_PRN("Board %d, dev: %p\n", usIdx, dev);

        if ( dev->bActive == TRUE) {
              DBG_PRN("DPM Adresses AVAILABLE,  Board - %X, DPMsize: %lX\n", usIdx, dev->ulDPMByteSize);
              DBG_PRN("Physical-> DPMBase: %lX, DPMAdd: %lX, SndAdd: %lX, RcvAdd: %lX\n", 
		      dev->ulBoardAddress, 
		      dev->ulBoardAddress + dev->ulDPMByteSize - 1024, 
		      dev->ulBoardAddress, 
		      dev->ulBoardAddress + (dev->ulDPMByteSize - 1024)/2);

          if ( (dev->pDpmBase = (unsigned char *)bus_to_virt(dev->ulBoardAddress)) == NULL) { 
             DBG_PRN("No virtual DPM base address\n");
             // no virtual board address is allocated
             dev->bActive = FALSE;

          // get handle to message area, last Kbyte of the DPM
          } else if ( (dev->ptDpmAddress = (DPM_MEMORY *)ioremap(dev->ulBoardAddress + 
							         dev->ulDPMByteSize - 1024, 1024)) == NULL) { 
             DBG_PRN("No virtual DPM address for last DPM Kbyte\n");
             // no virtual board address is allocated
              dev->bActive = FALSE;

          // get handle to send data area (start of DPM)
          } else if ( (dev->pbDpmSendArea = (unsigned char *)ioremap(dev->ulBoardAddress,
								     (dev->ulDPMByteSize - 1024) / 2)) == NULL) { 
            DBG_PRN("No virtual DPM address for send data area\n");
            // no virtual board address is allocated
            dev->bActive = FALSE;

          // get handle to receive data area (middle of the DPM)
          } else if ( (dev->pbDpmReceiveArea = (unsigned char *)ioremap(dev->ulBoardAddress + 
									(dev->ulDPMByteSize - 1024) / 2 , 
									(dev->ulDPMByteSize - 1024) / 2)) == NULL) { 
            DBG_PRN("No virtual DPM address for receive data area\n");
            // no virtual board address is allocated
            dev->bActive = FALSE;

          // install interrupt while IRQ number not 0
          } else {
              DBG_PRN("DPM Adresses AVAILABLE\n");
              DBG_PRN("Remapped-> DPMBase: %lX, DPMAdd: %lX, SndAdd: %lX, RcvAdd: %lX\n", 
		      (unsigned long)dev->pDpmBase, 
		      (unsigned long)dev->ptDpmAddress, 
		      (unsigned long)dev->pbDpmSendArea, 
		      (unsigned long)dev->pbDpmReceiveArea);

            // all parameters successfully read. Initialize instance No. usIdx
            dev->usRcsError    = 0;  // RCS-Error during startup
            dev->sDrvInitError = 0;  // DRV-Error during startup
            // pointers to the DEV dpm cells
            dev->pbHostFlags = &(dev->ptDpmAddress->HostFlags);
            dev->pbDevFlags  = &(dev->ptDpmAddress->DevFlags);
            // initialize start states
            dev->usOpenCounter  = 0;
            dev->bInitMsgFlag   = INI_MSG_WAIT;       // Init state
            dev->bReadMsgFlag   = HOST_MBX_EMPTY;     // Read state
            dev->bWriteMsgFlag  = DEVICE_MBX_EMPTY;   // write state
            dev->bExIOFlag      = EXCHGIO_NON;        // IO state
            dev->bStateFlag     = STATE_ERR_NON;      // State field

	    init_waitqueue_head( &dev->pInitSemaphore);
	    init_waitqueue_head( &dev->pReadSemaphore);
	    init_waitqueue_head( &dev->pWriteSemaphore);
	    init_waitqueue_head( &dev->pExIOSemaphore);
	    spin_lock_init     (&dev->mutex);

	    // request IRQ, register interrupt handler and BHs
	    if (dev->usBoardIrq != 0) {
	      //free_irq(dev->usBoardIrq, dev);
	      if( dev->ucBusType == BUS_TYPE_PCI) {
		  if(strncmp(pci_irq, "y", 1) == 0) {
		    DBG_PRN("Board %d, activating irq %d\n", usIdx, dev->usBoardIrq);
		    result = request_irq( (unsigned int)(dev->usBoardIrq), cif_interrupt, SA_SHIRQ, "cif", dev);
		    cif_set_irq_state( HW_INTERRUPT_ENABLE, dev);
		  }
		  else {/* poll */
		    DBG_PRN("Board %d, disabling irq %d\n", usIdx, dev->usBoardIrq);
		    cif_set_irq_state( HW_INTERRUPT_DISABLE, dev);
		    result = -EBUSY;
		  }
	      }
	      else // ISA bus supports no irq sharing
		result = request_irq( (unsigned int)(dev->usBoardIrq), cif_interrupt, 0, "cif", dev);
	      if (result) {
		DBG_PRN("can't get assigned irq %i\n", dev->usBoardIrq);
		dev->usBoardIrq = 0;
	      }
	      else {
		DBG_PRN("interrupt handler registration OK. Board = %d, dev = 0x%p, request_irq() = %d\n", usIdx, dev, result);
		if( dev->ucBusType == BUS_TYPE_PCI)
		  cif_set_irq_state( HW_INTERRUPT_ENABLE, dev);
	      }
	    }
            // board is configured, test hardware
            cif_test_hardware( dev);

            // virtual board address is allocated
            DBG_PRN("V-IRQ                     = %p \n", dev->pvVirtualIrq );
            DBG_PRN("V-DPM base address        = %p \n", dev->pDpmBase );
            DBG_PRN("V-DPM send area address   = %p \n", dev->pbDpmSendArea);
            DBG_PRN("V-DPM recive area address = %p \n", dev->pbDpmReceiveArea);
            DBG_PRN("V-DPM last kByte          = %p \n", dev->ptDpmAddress);

            DBG_PRN("Initialisation OK\n");

            // one board is initialized
            bSuccess = TRUE;
        }
      }  // end for
    }
  }

  DBG_PRN("Leave %d \n", bSuccess);

  if( !bSuccess) {
    iounmap( dev->ptDpmAddress);
    iounmap( dev->pbDpmReceiveArea);
    iounmap( dev->pbDpmReceiveArea);
  }
  return bSuccess;
}
Пример #21
0
int zd1205_zd_dbg_ioctl(struct zd1205_private *macp, struct zdap_ioctl *zdreq)
{
	void *regp = macp->regp;
	u16 zd_cmd;
	u32 tmp_value;
    
	zd_cmd = zdreq->cmd;
	switch(zd_cmd) {
        case ZD_IOCTL_REG_READ:
	        acquire_ctrl_of_phy_req(regp);
	        tmp_value = readl(regp + zdreq->addr);
	        release_ctrl_of_phy_req(regp);
	        zdreq->value = tmp_value;

            printk(KERN_DEBUG "zd1205 read register:  reg = %4x, value = %4x\n",
                zdreq->addr, zdreq->value);
	        //if (copy_to_user(ifr->ifr_data, &zdreq, sizeof (zdreq)))
	            //return -EFAULT;
	        break;

	    case ZD_IOCTL_REG_WRITE:
	        acquire_ctrl_of_phy_req(regp);
	        writel(zdreq->value, regp + zdreq->addr);
	        release_ctrl_of_phy_req(regp);
            if (zdreq->addr == RX_OFFSET_BYTE)
                macp->rx_offset = zdreq->value;
	        break;

	    case ZD_IOCTL_MEM_DUMP:
	        zd1205_dump_data("mem", (u8 *)zdreq->addr, zdreq->value);
	        //memcpy(&zdreq->data[0], (u8 *)zdreq->addr, zdreq->value);
	        //if (copy_to_user(ifr->ifr_data, &zdreq, sizeof (zdreq)))
	            //return -EFAULT;
	        break;

	    case ZD_IOCTL_REGS_DUMP:
	        zd1205_dump_regs(macp);
	        break;

        case ZD_IOCTL_DBG_MESSAGE:
            macp->dbg_flag =  zdreq->value;
            printk(KERN_DEBUG "zd1205: dbg_flag = %x\n", macp->dbg_flag);
            break;

        case ZD_IOCTL_DBG_COUNTER:
            zd1205_dump_cnters(macp);
            break;

        case ZD_IOCTL_LB_MODE:
            macp->lb_mode = zdreq->value;
            printk(KERN_DEBUG "zd1205: lb_mode = %x\n", macp->lb_mode);
            zd1205_lb_mode(macp);
            break;

        case ZD_IOCTL_TX_ON:
            macp->txOn = zdreq->value;
            printk(KERN_DEBUG "zd1205: txOn = %x\n", macp->txOn);
            break;

	case ZD_IOCTL_RATE:
            /* Check for the validation of vale */
            if(zdreq->value > 3 || zdreq->value < 0)
            {
                printk(KERN_DEBUG "zd1205: Basic Rate %x doesn't support\n", zdreq->value);
                break;
            }
                                                                                       
            printk(KERN_DEBUG "zd1205: Basic Rate = %x\n", zdreq->value);
            zd1205_update_brate(macp, zdreq->value);
            break;

        case ZD_IOCTL_SNIFFER:
            macp->sniffer_on = zdreq->value;
            printk(KERN_DEBUG "zd1205: sniffer_on = %x\n", macp->sniffer_on);
            zd1205_set_sniffer_mode(macp);
            break;

        case ZD_IOCTL_WEP_ON_OFF:
            printk(KERN_DEBUG "zd1205: wep_on_off = %x\n", zdreq->value);
            zd1205_wep_on_off(macp, zdreq->value);
            break;

#if 0                        
        case ZD_IOCTL_CAM:
            printk(KERN_DEBUG "zd1205: cam = %x\n", zdreq->value);
            zd1205_do_cam(macp, zdreq->value);
            break;

        case ZD_IOCTL_VAP:
            printk(KERN_DEBUG "zd1205: vap\n");
            zd1205_do_vap(macp, zdreq->value);
            break;

        case ZD_IOCTL_APC:
            printk(KERN_DEBUG "zd1205: apc\n");
            zd1205_do_apc(macp, zdreq->value);
            break;    

        case ZD_IOCTL_CAM_DUMP:
            printk(KERN_DEBUG "zd1205: cam_dump\n");
            zd1205_cam_dump(macp);
            break;

        case ZD_IOCTL_CAM_CLEAR:
            printk(KERN_DEBUG "zd1205: cam_clear\n");
            zd1205_cam_clear(macp);
            break;
#endif            
#if 0
        case ZD_IOCTL_WDS:
            printk(KERN_DEBUG "zd1205: wds\n");
            zd1205_do_wds(macp);
            break;
#endif
        case ZD_IOCTL_FIFO:
            printk(KERN_DEBUG "zd1205: fifo\n");
            zd1205_dbg_fifo(macp);
            break;

        case ZD_IOCTL_FRAG:
            printk(KERN_DEBUG "zd1205: frag = %x\n", zdreq->value);
            zd1205_set_frag(macp, zdreq->value);
            break;

        case ZD_IOCTL_RTS:
            printk(KERN_DEBUG "zd1205: rts = %x\n", zdreq->value);
            zd1205_set_rts(macp, zdreq->value);
            break;

        case ZD_IOCTL_PREAMBLE:
            printk(KERN_DEBUG "zd1205: pre = %x\n", zdreq->value);
            zd1205_set_preamble(macp, zdreq->value);
            break;

        case ZD_IOCTL_DUMP_PHY:
            printk(KERN_DEBUG "zd1205: dump phy\n");
            zd1205_dump_phy(macp);
            break;

        case ZD_IOCTL_DBG_PORT:
            printk(KERN_DEBUG "zd1205: port = %x\n", zdreq->value);
            zd1205_dbg_port(macp, zdreq->value);
            break;

        case ZD_IOCTL_CARD_SETTING:
            printk(KERN_DEBUG "zd1205: card setting\n");
            zd1205_show_card_setting(macp);
            break;

        case ZD_IOCTL_RESET:
            printk(KERN_DEBUG "zd1205: card reset\n");
            zd1205_sleep_reset(macp);
            break;
            
        case ZD_IOCTL_SW_CIPHER:
            printk(KERN_DEBUG "zd1205: sc = %x\n", zdreq->value);
            zd1205_set_sc(macp, zdreq->value);
            break;    
            
        case ZD_IOCTL_HASH_DUMP:
            printk(KERN_DEBUG "zd1205: aid = %x\n", zdreq->value);
            zd1205_show_hash(macp, zdreq->value);
            break;    

        case ZD_IOCTL_RFD_DUMP:
            printk(KERN_DEBUG "===== zd1205 rfd dump =====\n");
            zd1205_dump_rfds(macp);
            break;
                                            
        case ZD_IOCTL_CHANNEL:
            printk(KERN_DEBUG "zd1205: channel = %d\n", zdreq->value);
            macp->card_setting.Channel = zdreq->value;
            zd_UpdateCardSetting(&macp->card_setting);
            break;
        
        case ZD_IOCTL_MEM_READ: {
            u32 *p;
            p = (u32 *) bus_to_virt(zdreq->addr);
            printk(KERN_DEBUG "zd1205: read memory addr: 0x%08x value: 0x%08x\n", zdreq->addr, *p);
            break;
        }

        case ZD_IOCTL_MEM_WRITE: {
            u32 *p;
            p = (u32 *) bus_to_virt(zdreq->addr);
            *p = zdreq->value;
            printk(KERN_DEBUG "zd1205: write value: 0x%08x to memory addr: 0x%08x\n", zdreq->value, zdreq->addr);
            break;
        }

        case ZD_IOCTL_KEY_ID:
            printk(KERN_DEBUG "zd1205: keyid = %d\n", zdreq->value);
            macp->card_setting.EncryKeyId = zdreq->value;
            break;

        case ZD_IOCTL_KEY: {
            if(zdreq->value < 0 || zdreq->value > 3)
            {
                printk(KERN_DEBUG "zd1205: Only KeyIds between 0 and 3 are support\n");
                break;
            }

            /* We always copy the maximum key length to the key descriptor */
            memcpy(macp->card_setting.keyVector[zdreq->value], zdreq->data, 16);
            zd1205_config_wep_keys(macp);
        }
        break;            

        case ZD_IOCTL_ENC_MODE:
            if(zdreq->value < WEP64 || zdreq->value > WEP128)
            {
                printk(KERN_DEBUG "zd1205: Encrypt Mode: %d not support\n", zdreq->value);
                break;
            }
                                                                            
            printk(KERN_DEBUG "zd1205: encrypt mode = %d\n", zdreq->value);
            macp->card_setting.EncryMode = zdreq->value;
            break;

        case ZD_IOCTL_SSID:
            if(zd1205_set_ssid(macp, zdreq->data, zdreq->value) == 0)
            {
                printk(KERN_DEBUG "zd1205: SSID = %s\n", zdreq->data);
                zd_UpdateCardSetting(&macp->card_setting);
            }
            break;


        case ZD_IOCTL_AUTH:
            if(zdreq->value < 0 || zdreq->value > 2)
                printk(KERN_DEBUG "zd1205: Auth Type: %d doesn't support\n", zdreq->value);
            else
                macp->card_setting.AuthMode = zdreq->value;
            break;

        default :
            printk(KERN_ERR "zd1205: error command = %x\n", zd_cmd);
	        break;
	}
    
    return 0;
    
}    
Пример #22
0
static inline void *
pa_to_va(phys_addr x) {
	return (x == I596_NULL) ? NULL : bus_to_virt(x);
}
Пример #23
0
int __init elmc_probe(struct net_device *dev)
{
	static int slot;
	int base_addr = dev->base_addr;
	int irq = dev->irq;
	u_char status = 0;
	u_char revision = 0;
	int i = 0;
	unsigned int size = 0;
	int retval;
	struct priv *pr;

	SET_MODULE_OWNER(dev);
	if (MCA_bus == 0) {
		return -ENODEV;
	}
	/* search through the slots for the 3c523. */
	slot = mca_find_adapter(ELMC_MCA_ID, 0);
	while (slot != -1) {
		status = mca_read_stored_pos(slot, 2);

		dev->irq=irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6];
		dev->base_addr=csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1];
		
		/*
		   If we're trying to match a specified irq or IO address,
		   we'll reject a match unless it's what we're looking for.
		   Also reject it if the card is already in use.
		 */

		if ((irq && irq != dev->irq) || 
		    (base_addr && base_addr != dev->base_addr)) {
			slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
			continue;
		}
		if (!request_region(dev->base_addr, ELMC_IO_EXTENT, dev->name)) {
			slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
			continue;
		}

		/* found what we're looking for... */
		break;
	}

	/* we didn't find any 3c523 in the slots we checked for */
	if (slot == MCA_NOTFOUND) {
		retval = ((base_addr || irq) ? -ENXIO : -ENODEV);
		goto err_out;
	}
	mca_set_adapter_name(slot, "3Com 3c523 Etherlink/MC");
	mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev);

	/* if we get this far, adapter has been found - carry on */
	printk(KERN_INFO "%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1);

	/* Now we extract configuration info from the card.
	   The 3c523 provides information in two of the POS registers, but
	   the second one is only needed if we want to tell the card what IRQ
	   to use.  I suspect that whoever sets the thing up initially would
	   prefer we don't screw with those things.

	   Note that we read the status info when we found the card...

	   See 3c523.h for more details.
	 */

	/* revision is stored in the first 4 bits of the revision register */
	revision = inb(dev->base_addr + ELMC_REVISION) & 0xf;

	/* according to docs, we read the interrupt and write it back to
	   the IRQ select register, since the POST might not configure the IRQ
	   properly. */
	switch (dev->irq) {
	case 3:
		mca_write_pos(slot, 3, 0x04);
		break;
	case 7:
		mca_write_pos(slot, 3, 0x02);
		break;
	case 9:
		mca_write_pos(slot, 3, 0x08);
		break;
	case 12:
		mca_write_pos(slot, 3, 0x01);
		break;
	}

	pr = dev->priv = kmalloc(sizeof(struct priv), GFP_KERNEL);
	if (dev->priv == NULL) {
		retval = -ENOMEM;
		goto err_out;
	}
	memset(pr, 0, sizeof(struct priv));

	pr->slot = slot;

	printk(KERN_INFO "%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
	       dev->base_addr);

	/* Determine if we're using the on-board transceiver (i.e. coax) or
	   an external one.  The information is pretty much useless, but I
	   guess it's worth brownie points. */
	dev->if_port = (status & ELMC_STATUS_DISABLE_THIN);

	/* The 3c523 has a 24K chunk of memory.  The first 16K is the
	   shared memory, while the last 8K is for the EtherStart BIOS ROM.
	   Which we don't care much about here.  We'll just tell Linux that
	   we're using 16K.  MCA won't permit address space conflicts caused
	   by not mapping the other 8K. */
	dev->mem_start = shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3];

	/* We're using MCA, so it's a given that the information about memory
	   size is correct.  The Crynwr drivers do something like this. */

	elmc_id_reset586();	/* seems like a good idea before checking it... */

	size = 0x4000;		/* check for 16K mem */
	if (!check586(dev, dev->mem_start, size)) {
		printk(KERN_ERR "%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
		       dev->mem_start);
		kfree(dev->priv);
		dev->priv = NULL;
		retval = -ENODEV;
		goto err_out;
	}
	dev->mem_end = dev->mem_start + size;	/* set mem_end showed by 'ifconfig' */

	pr->memtop = bus_to_virt(dev->mem_start) + size;
	pr->base = (unsigned long) bus_to_virt(dev->mem_start) + size - 0x01000000;
	alloc586(dev);

	elmc_id_reset586();	/* make sure it doesn't generate spurious ints */

	/* set number of receive-buffs according to memsize */
	pr->num_recv_buffs = NUM_RECV_BUFFS_16;

	/* dump all the assorted information */
	printk(KERN_INFO "%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
	       dev->irq, dev->if_port ? "ex" : "in", 
	       dev->mem_start, dev->mem_end - 1);

	/* The hardware address for the 3c523 is stored in the first six
	   bytes of the IO address. */
	printk(KERN_INFO "%s: hardware address ", dev->name);
	for (i = 0; i < 6; i++) {
		dev->dev_addr[i] = inb(dev->base_addr + i);
		printk(" %02x", dev->dev_addr[i]);
	}
	printk("\n");

	dev->open = &elmc_open;
	dev->stop = &elmc_close;
	dev->get_stats = &elmc_get_stats;
	dev->hard_start_xmit = &elmc_send_packet;
	dev->tx_timeout = &elmc_timeout;
	dev->watchdog_timeo = HZ;
#ifdef ELMC_MULTICAST
	dev->set_multicast_list = &set_multicast_list;
#else
	dev->set_multicast_list = NULL;
#endif
	dev->ethtool_ops = &netdev_ethtool_ops;
	
	ether_setup(dev);

	/* note that we haven't actually requested the IRQ from the kernel.
	   That gets done in elmc_open().  I'm not sure that's such a good idea,
	   but it works, so I'll go with it. */

#ifndef ELMC_MULTICAST
        dev->flags&=~IFF_MULTICAST;     /* Multicast doesn't work */
#endif

	return 0;
err_out:
	release_region(dev->base_addr, ELMC_IO_EXTENT);
	return retval;
}
Пример #24
0
static void poll_rx(struct atm_dev *dev,int mbx)
{
	struct zatm_dev *zatm_dev;
	unsigned long pos;
	u32 x;
	int error;

	EVENT("poll_rx\n",0,0);
	zatm_dev = ZATM_DEV(dev);
	pos = (zatm_dev->mbx_start[mbx] & ~0xffffUL) | zin(MTA(mbx));
	while (x = zin(MWA(mbx)), (pos & 0xffff) != x) {
		u32 *here;
		struct sk_buff *skb;
		struct atm_vcc *vcc;
		int cells,size,chan;

		EVENT("MBX: host 0x%lx, nic 0x%x\n",pos,x);
		here = (u32 *) pos;
		if (((pos += 16) & 0xffff) == zatm_dev->mbx_end[mbx])
			pos = zatm_dev->mbx_start[mbx];
		cells = here[0] & uPD98401_AAL5_SIZE;
#if 0
printk("RX IND: 0x%x, 0x%x, 0x%x, 0x%x\n",here[0],here[1],here[2],here[3]);
{
unsigned long *x;
		printk("POOL: 0x%08x, 0x%08x\n",zpeekl(zatm_dev,
		      zatm_dev->pool_base),
		      zpeekl(zatm_dev,zatm_dev->pool_base+1));
		x = (unsigned long *) here[2];
		printk("[0..3] = 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n",
		    x[0],x[1],x[2],x[3]);
}
#endif
		error = 0;
		if (here[3] & uPD98401_AAL5_ERR) {
			error = (here[3] & uPD98401_AAL5_ES) >>
			    uPD98401_AAL5_ES_SHIFT;
			if (error == uPD98401_AAL5_ES_DEACT ||
			    error == uPD98401_AAL5_ES_FREE) continue;
		}
EVENT("error code 0x%x/0x%x\n",(here[3] & uPD98401_AAL5_ES) >>
  uPD98401_AAL5_ES_SHIFT,error);
		skb = ((struct rx_buffer_head *) bus_to_virt(here[2]))->skb;
		__net_timestamp(skb);
#if 0
printk("[-3..0] 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n",((unsigned *) skb->data)[-3],
  ((unsigned *) skb->data)[-2],((unsigned *) skb->data)[-1],
  ((unsigned *) skb->data)[0]);
#endif
		EVENT("skb 0x%lx, here 0x%lx\n",(unsigned long) skb,
		    (unsigned long) here);
#if 0
printk("dummy: 0x%08lx, 0x%08lx\n",dummy[0],dummy[1]);
#endif
		size = error ? 0 : ntohs(((__be16 *) skb->data)[cells*
		    ATM_CELL_PAYLOAD/sizeof(u16)-3]);
		EVENT("got skb 0x%lx, size %d\n",(unsigned long) skb,size);
		chan = (here[3] & uPD98401_AAL5_CHAN) >>
		    uPD98401_AAL5_CHAN_SHIFT;
		if (chan < zatm_dev->chans && zatm_dev->rx_map[chan]) {
			int pos;
			vcc = zatm_dev->rx_map[chan];
			pos = ZATM_VCC(vcc)->pool;
			if (skb == zatm_dev->last_free[pos])
				zatm_dev->last_free[pos] = NULL;
			skb_unlink(skb, zatm_dev->pool + pos);
		}
		else {
			printk(KERN_ERR DEV_LABEL "(itf %d): RX indication "
			    "for non-existing channel\n",dev->number);
			size = 0;
			vcc = NULL;
			event_dump();
		}
		if (error) {
			static unsigned long silence = 0;
			static int last_error = 0;

			if (error != last_error ||
			    time_after(jiffies, silence)  || silence == 0){
				printk(KERN_WARNING DEV_LABEL "(itf %d): "
				    "chan %d error %s\n",dev->number,chan,
				    err_txt[error]);
				last_error = error;
				silence = (jiffies+2*HZ)|1;
			}
			size = 0;
		}
		if (size && (size > cells*ATM_CELL_PAYLOAD-ATM_AAL5_TRAILER ||
		    size <= (cells-1)*ATM_CELL_PAYLOAD-ATM_AAL5_TRAILER)) {
			printk(KERN_ERR DEV_LABEL "(itf %d): size %d with %d "
			    "cells\n",dev->number,size,cells);
			size = 0;
			event_dump();
		}
		if (size > ATM_MAX_AAL5_PDU) {
			printk(KERN_ERR DEV_LABEL "(itf %d): size too big "
			    "(%d)\n",dev->number,size);
			size = 0;
			event_dump();
		}
		if (!size) {
			dev_kfree_skb_irq(skb);
			if (vcc) atomic_inc(&vcc->stats->rx_err);
			continue;
		}
		if (!atm_charge(vcc,skb->truesize)) {
			dev_kfree_skb_irq(skb);
			continue;
		}
		skb->len = size;
		ATM_SKB(skb)->vcc = vcc;
		vcc->push(vcc,skb);
		atomic_inc(&vcc->stats->rx);
	}
Пример #25
0
/*
 * Receive characters
 */
static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
{
    int i;
    unsigned char ch, *cp;
    struct tty_struct *tty = port->info->tty;
    struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
    volatile cbd_t *bdp;
    u16 status;
    unsigned int flg;

    pr_debug("CPM uart[%d]:RX INT\n", port->line);

    /* Just loop through the closed BDs and copy the characters into
     * the buffer.
     */
    bdp = pinfo->rx_cur;
    for (;;) {
        /* get status */
        status = bdp->cbd_sc;
        /* If this one is empty, return happy */
        if (status & BD_SC_EMPTY)
            break;

        /* get number of characters, and check spce in flip-buffer */
        i = bdp->cbd_datlen;

        /* If we have not enough room in tty flip buffer, then we try
         * later, which will be the next rx-interrupt or a timeout
         */
        if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
            tty->flip.work.func((void *)tty);
            if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
                printk(KERN_WARNING "TTY_DONT_FLIP set\n");
                return;
            }
        }

        /* get pointer */
        cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr);

        /* loop through the buffer */
        while (i-- > 0) {
            ch = *cp++;
            port->icount.rx++;
            flg = TTY_NORMAL;

            if (status &
                    (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV))
                goto handle_error;
            if (uart_handle_sysrq_char(port, ch, regs))
                continue;

error_return:
            *tty->flip.char_buf_ptr++ = ch;
            *tty->flip.flag_buf_ptr++ = flg;
            tty->flip.count++;

        }		/* End while (i--) */

        /* This BD is ready to be used again. Clear status. get next */
        bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
        bdp->cbd_sc |= BD_SC_EMPTY;

        if (bdp->cbd_sc & BD_SC_WRAP)
            bdp = pinfo->rx_bd_base;
        else
            bdp++;
    } /* End for (;;) */

    /* Write back buffer pointer */
    pinfo->rx_cur = (volatile cbd_t *) bdp;

    /* activate BH processing */
    tty_flip_buffer_push(tty);

    return;

    /* Error processing */

handle_error:
    /* Statistics */
    if (status & BD_SC_BR)
        port->icount.brk++;
    if (status & BD_SC_PR)
        port->icount.parity++;
    if (status & BD_SC_FR)
        port->icount.frame++;
    if (status & BD_SC_OV)
        port->icount.overrun++;

    /* Mask out ignored conditions */
    status &= port->read_status_mask;

    /* Handle the remaining ones */
    if (status & BD_SC_BR)
        flg = TTY_BREAK;
    else if (status & BD_SC_PR)
        flg = TTY_PARITY;
    else if (status & BD_SC_FR)
        flg = TTY_FRAME;

    /* overrun does not affect the current character ! */
    if (status & BD_SC_OV) {
        ch = 0;
        flg = TTY_OVERRUN;
        /* We skip this buffer */
        /* CHECK: Is really nothing senseful there */
        /* ASSUMPTION: it contains nothing valid */
        i = 0;
    }
#ifdef SUPPORT_SYSRQ
    port->sysrq = 0;
#endif
    goto error_return;
}
Пример #26
0
static int __init ni52_probe1(struct net_device *dev,int ioaddr)
{
	int i, size, retval;

	if (!request_region(ioaddr, NI52_TOTAL_SIZE, dev->name))
		return -EBUSY;

	if( !(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) ||
	    !(inb(ioaddr+NI52_MAGIC2) == NI52_MAGICVAL2)) {
		retval = -ENODEV;
		goto out;
	}

	for(i=0;i<ETH_ALEN;i++)
		dev->dev_addr[i] = inb(dev->base_addr+i);

	if(dev->dev_addr[0] != NI52_ADDR0 || dev->dev_addr[1] != NI52_ADDR1
		 || dev->dev_addr[2] != NI52_ADDR2) {
		retval = -ENODEV;
		goto out;
	}

	printk("%s: NI5210 found at %#3lx, ",dev->name,dev->base_addr);

	/*
	 * check (or search) IO-Memory, 8K and 16K
	 */
#ifdef MODULE
	size = dev->mem_end - dev->mem_start;
	if(size != 0x2000 && size != 0x4000) {
		printk("\n%s: Illegal memory size %d. Allowed is 0x2000 or 0x4000 bytes.\n",dev->name,size);
		retval = -ENODEV;
		goto out;
	}
	if(!check586(dev,(char *) dev->mem_start,size)) {
		printk("?memcheck, Can't find memory at 0x%lx with size %d!\n",dev->mem_start,size);
		retval = -ENODEV;
		goto out;
	}
#else
	if(dev->mem_start != 0) /* no auto-mem-probe */
	{
		size = 0x4000; /* check for 16K mem */
		if(!check586(dev,(char *) dev->mem_start,size)) {
			size = 0x2000; /* check for 8K mem */
			if(!check586(dev,(char *) dev->mem_start,size)) {
				printk("?memprobe, Can't find memory at 0x%lx!\n",dev->mem_start);
				retval = -ENODEV;
				goto out;
			}
		}
	}
	else
	{
		static long memaddrs[] = { 0xc8000,0xca000,0xcc000,0xce000,0xd0000,0xd2000,
					0xd4000,0xd6000,0xd8000,0xda000,0xdc000, 0 };
		for(i=0;;i++)
		{
			if(!memaddrs[i]) {
				printk("?memprobe, Can't find io-memory!\n");
				retval = -ENODEV;
				goto out;
			}
			dev->mem_start = memaddrs[i];
			size = 0x2000; /* check for 8K mem */
			if(check586(dev,(char *)dev->mem_start,size)) /* 8K-check */
				break;
			size = 0x4000; /* check for 16K mem */
			if(check586(dev,(char *)dev->mem_start,size)) /* 16K-check */
				break;
		}
	}
	dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */
#endif

	dev->priv = (void *) kmalloc(sizeof(struct priv),GFP_KERNEL);
	if(dev->priv == NULL) {
		printk("%s: Ooops .. can't allocate private driver memory.\n",dev->name);
		retval = -ENOMEM;
		goto out;
	}
																	/* warning: we don't free it on errors */
	memset((char *) dev->priv,0,sizeof(struct priv));

	((struct priv *) (dev->priv))->memtop = bus_to_virt(dev->mem_start) + size;
	((struct priv *) (dev->priv))->base =	(unsigned long) bus_to_virt(dev->mem_start) + size - 0x01000000;
	alloc586(dev);

	/* set number of receive-buffs according to memsize */
	if(size == 0x2000)
		((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8;
	else
		((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;

	printk("Memaddr: 0x%lx, Memsize: %d, ",dev->mem_start,size);

	if(dev->irq < 2)
	{
		autoirq_setup(0);
		ni_reset586();
		ni_attn586();
		if(!(dev->irq = autoirq_report(2)))
		{
			printk("?autoirq, Failed to detect IRQ line!\n");
			kfree(dev->priv);
			dev->priv = NULL;
			retval = -EAGAIN;
			goto out;
		}
		printk("IRQ %d (autodetected).\n",dev->irq);
	}
	else	{
		if(dev->irq == 2)
			dev->irq = 9;
		printk("IRQ %d (assigned and not checked!).\n",dev->irq);
	}

	dev->open		= ni52_open;
	dev->stop		= ni52_close;
	dev->get_stats		= ni52_get_stats;
	dev->tx_timeout 	= ni52_timeout;
	dev->watchdog_timeo	= HZ/20;
	dev->hard_start_xmit 	= ni52_send_packet;
	dev->set_multicast_list = set_multicast_list;

	dev->if_port 		= 0;

	ether_setup(dev);

	return 0;
out:
	release_region(ioaddr, NI52_TOTAL_SIZE);
	return retval;
}
Пример #27
0
/*
 * ps2_ide_build_dmatable() prepares a dma request.
 * Returns 0 if all went okay, returns 1 otherwise.
 */
static int ps2_ide_build_dmatable(int rw, ide_drive_t *drive)
{
	struct request *rq = HWGROUP(drive)->rq;
	struct buffer_head *bh = rq->bh;
	unsigned int size, addr;
	unsigned int count = 0, totalsize = 0;
	struct ps2_dmatable *t = (struct ps2_dmatable *)HWIF(drive)->dmatable;
	struct ata_dma_request *req = &t->ata_dma_request;
	unsigned int iopaddr = t->ata_iop_buffer;
#ifdef GATHER_WRITE_DATA
	unsigned char *dma_buffer = t->dma_buffer;
#endif

	DPRINT("nr_sectors %ld\n", rq->nr_sectors);
	do {
		/*
		 * Determine addr and size of next buffer area.  We assume that
		 * individual virtual buffers are always composed linearly in
		 * physical memory.  For example, we assume that any 8kB buffer
		 * is always composed of two adjacent physical 4kB pages rather
		 * than two possibly non-adjacent physical 4kB pages.
		 */
		if (bh == NULL) {  /* paging requests have (rq->bh == NULL) */
			addr = virt_to_bus (rq->buffer);
			size = rq->nr_sectors << 9;
		} else {
			/* group sequential buffers into one large buffer */
			addr = virt_to_bus (bh->b_data);
			size = bh->b_size;
			while ((bh = bh->b_reqnext) != NULL) {
				if ((addr + size) != virt_to_bus (bh->b_data))
					break;
				size += bh->b_size;
			}
		}
		/*
		 * Fill in the dma table.
		 * EE requires 128-bit alignment of all blocks,
		 */
		if ((addr & 0x0f)) {
			printk("%s: misaligned DMA buffer\n", drive->name);
			return 0;
		}
		if (count >= ATA_MAX_ENTRIES) {
			printk("%s: DMA table too small\n", drive->name);
			return 0; /* revert to PIO for this request */
		}
		DPRINT("ps2_ide_build_dmatable: %08x->%08x %d\n", addr, iopaddr, size);
#if !defined(GATHER_WRITE_DATA)
		if (rw) {	/* write */
			req->sdd[count].data = addr;
			req->sdd[count].addr = iopaddr;
		} else {	/* read */
			req->sdd[count].data = iopaddr;
			req->sdd[count].addr = addr;
		}
		req->sdd[count].size = size;
		req->sdd[count].mode = 0;
#else
		if (rw) {
			memcpy(dma_buffer, (void *)bus_to_virt(addr), size);
			dma_buffer += size;
		} else {
			req->sdd[count].data = iopaddr;
			req->sdd[count].addr = addr;
			req->sdd[count].size = size;
			req->sdd[count].mode = 0;
		}
#endif
		iopaddr += size;
		totalsize += size;
		count++;
	} while (bh != NULL);
	if (totalsize > ATA_BUFFER_SIZE) {
		printk("%s: DMA buffer too small\n", drive->name);
		return 0; /* revert to PIO for this request */
	}
	req->count = count;
	req->size = totalsize;
	if (!count)
		printk("%s: empty DMA table?\n", drive->name);
	return count;
}