Пример #1
0
void au1xxx_ddma_del_device(u32 devid)
{
	dbdev_tab_t *p = find_dbdev_id(devid);

	if (p != NULL) {
		memset(p, 0, sizeof(dbdev_tab_t));
		p->dev_id = ~0;
	}
}
Пример #2
0
u32 au1xxx_ddma_add_device(dbdev_tab_t *dev)
{
	u32 ret = 0;
	dbdev_tab_t *p;
	static u16 new_id = 0x1000;

	p = find_dbdev_id(~0);
	if (NULL != p) {
		memcpy(p, dev, sizeof(dbdev_tab_t));
		p->dev_id = DSCR_DEV2CUSTOM_ID(new_id, dev->dev_id);
		ret = p->dev_id;
		new_id++;
#if 0
		printk(KERN_DEBUG "add_device: id:%x flags:%x padd:%x\n",
				  p->dev_id, p->dev_flags, p->dev_physaddr);
#endif
	}

	return ret;
}
Пример #3
0
/* Allocate a channel and return a non-zero descriptor if successful. */
u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
       void (*callback)(int, void *), void *callparam)
{
	unsigned long	flags;
	u32		used, chan;
	u32		dcp;
	int		i;
	dbdev_tab_t	*stp, *dtp;
	chan_tab_t	*ctp;
	au1x_dma_chan_t *cp;

	/*
	 * We do the initialization on the first channel allocation.
	 * We have to wait because of the interrupt handler initialization
	 * which can't be done successfully during board set up.
	 */
	if (!dbdma_initialized)
		return 0;

	stp = find_dbdev_id(srcid);
	if (stp == NULL)
		return 0;
	dtp = find_dbdev_id(destid);
	if (dtp == NULL)
		return 0;

	used = 0;

	/* Check to see if we can get both channels. */
	spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags);
	if (!(stp->dev_flags & DEV_FLAGS_INUSE) ||
	     (stp->dev_flags & DEV_FLAGS_ANYUSE)) {
		/* Got source */
		stp->dev_flags |= DEV_FLAGS_INUSE;
		if (!(dtp->dev_flags & DEV_FLAGS_INUSE) ||
		     (dtp->dev_flags & DEV_FLAGS_ANYUSE)) {
			/* Got destination */
			dtp->dev_flags |= DEV_FLAGS_INUSE;
		} else {
			/* Can't get dest.  Release src. */
			stp->dev_flags &= ~DEV_FLAGS_INUSE;
			used++;
		}
	} else
		used++;
	spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags);

	if (used)
		return 0;

	/* Let's see if we can allocate a channel for it. */
	ctp = NULL;
	chan = 0;
	spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags);
	for (i = 0; i < NUM_DBDMA_CHANS; i++)
		if (chan_tab_ptr[i] == NULL) {
			/*
			 * If kmalloc fails, it is caught below same
			 * as a channel not available.
			 */
			ctp = kmalloc(sizeof(chan_tab_t), GFP_ATOMIC);
			chan_tab_ptr[i] = ctp;
			break;
		}
	spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags);

	if (ctp != NULL) {
		memset(ctp, 0, sizeof(chan_tab_t));
		ctp->chan_index = chan = i;
		dcp = KSEG1ADDR(AU1550_DBDMA_PHYS_ADDR);
		dcp += (0x0100 * chan);
		ctp->chan_ptr = (au1x_dma_chan_t *)dcp;
		cp = (au1x_dma_chan_t *)dcp;
		ctp->chan_src = stp;
		ctp->chan_dest = dtp;
		ctp->chan_callback = callback;
		ctp->chan_callparam = callparam;

		/* Initialize channel configuration. */
		i = 0;
		if (stp->dev_intlevel)
			i |= DDMA_CFG_SED;
		if (stp->dev_intpolarity)
			i |= DDMA_CFG_SP;
		if (dtp->dev_intlevel)
			i |= DDMA_CFG_DED;
		if (dtp->dev_intpolarity)
			i |= DDMA_CFG_DP;
		if ((stp->dev_flags & DEV_FLAGS_SYNC) ||
			(dtp->dev_flags & DEV_FLAGS_SYNC))
				i |= DDMA_CFG_SYNC;
		cp->ddma_cfg = i;
		wmb(); /* drain writebuffer */

		/*
		 * Return a non-zero value that can be used to find the channel
		 * information in subsequent operations.
		 */
		return (u32)(&chan_tab_ptr[chan]);
	}

	/* Release devices */
	stp->dev_flags &= ~DEV_FLAGS_INUSE;
	dtp->dev_flags &= ~DEV_FLAGS_INUSE;

	return 0;
}
Пример #4
0
/* Allocate a channel and return a non-zero descriptor if successful.
*/
u32
au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
       void (*callback)(int, void *, struct pt_regs *), void *callparam)
{
	unsigned long   flags;
	u32		used, chan, rv;
	u32		dcp;
	int		i;
	dbdev_tab_t	*stp, *dtp;
	chan_tab_t	*ctp;
	volatile au1x_dma_chan_t *cp;

	/* We do the intialization on the first channel allocation.
	 * We have to wait because of the interrupt handler initialization
	 * which can't be done successfully during board set up.
	 */
	if (!dbdma_initialized)
		au1xxx_dbdma_init();
	dbdma_initialized = 1;

	if ((srcid > DSCR_NDEV_IDS) || (destid > DSCR_NDEV_IDS))
		return 0;
	
	if ((stp = find_dbdev_id(srcid)) == NULL) return 0;
	if ((dtp = find_dbdev_id(destid)) == NULL) return 0;

	used = 0;
	rv = 0;

	/* Check to see if we can get both channels.
	*/
	spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags);
	if (!(stp->dev_flags & DEV_FLAGS_INUSE) ||
	     (stp->dev_flags & DEV_FLAGS_ANYUSE)) {
	     	/* Got source */
		stp->dev_flags |= DEV_FLAGS_INUSE;
		if (!(dtp->dev_flags & DEV_FLAGS_INUSE) ||
		     (dtp->dev_flags & DEV_FLAGS_ANYUSE)) {
			/* Got destination */
			dtp->dev_flags |= DEV_FLAGS_INUSE;
		}
		else {
			/* Can't get dest.  Release src.
			*/
			stp->dev_flags &= ~DEV_FLAGS_INUSE;
			used++;
		}
	}
	else {
		used++;
	}
	spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags);

	if (!used) {
		/* Let's see if we can allocate a channel for it.
		*/
		ctp = NULL;
		chan = 0;
		spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags);
		for (i=0; i<NUM_DBDMA_CHANS; i++) {
			if (chan_tab_ptr[i] == NULL) {
				/* If kmalloc fails, it is caught below same
				 * as a channel not available.
				 */
				ctp = (chan_tab_t *)kmalloc(sizeof(chan_tab_t), GFP_KERNEL);
				chan_tab_ptr[i] = ctp;
				ctp->chan_index = chan = i;
				break;
			}
		}
		spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags);

		if (ctp != NULL) {
			memset(ctp, 0, sizeof(chan_tab_t));
			dcp = DDMA_CHANNEL_BASE;
			dcp += (0x0100 * chan);
			ctp->chan_ptr = (au1x_dma_chan_t *)dcp;
			cp = (volatile au1x_dma_chan_t *)dcp;
			ctp->chan_src = stp;
			ctp->chan_dest = dtp;
			ctp->chan_callback = callback;
			ctp->chan_callparam = callparam;

			/* Initialize channel configuration.
			*/
			i = 0;
			if (stp->dev_intlevel)
				i |= DDMA_CFG_SED;
			if (stp->dev_intpolarity)
				i |= DDMA_CFG_SP;
			if (dtp->dev_intlevel)
				i |= DDMA_CFG_DED;
			if (dtp->dev_intpolarity)
				i |= DDMA_CFG_DP;
			cp->ddma_cfg = i;
			au_sync();

			/* Return a non-zero value that can be used to
			 * find the channel information in subsequent
			 * operations.
			 */
			rv = (u32)(&chan_tab_ptr[chan]);
		}
		else {
			/* Release devices.
			*/
			stp->dev_flags &= ~DEV_FLAGS_INUSE;
			dtp->dev_flags &= ~DEV_FLAGS_INUSE;
		}
	}
	return rv;
}