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

📄 amd7930.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 4 页
字号:
static int amd7930_get_input_rate(struct sparcaudio_driver *drv){	return AMD7930_RATE;}static intamd7930_set_input_rate(struct sparcaudio_driver *drv, int value){	return (value == AMD7930_RATE) ? 0 : -EINVAL;}static int amd7930_get_output_muted(struct sparcaudio_driver *drv){      return 0;}static void amd7930_loopback(struct sparcaudio_driver *drv, unsigned int value){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	if (value)		info->map.mmr1 |= AM_MAP_MMR1_LOOPBACK;	else		info->map.mmr1 &= ~AM_MAP_MMR1_LOOPBACK;	amd7930_update_map(drv);}static int amd7930_ioctl(struct inode * inode, struct file * file,                         unsigned int cmd, unsigned long arg,                          struct sparcaudio_driver *drv){	int retval = 0;  	switch (cmd) {	case AUDIO_DIAG_LOOPBACK:		amd7930_loopback(drv, (unsigned int)arg);		break;	default:		retval = -EINVAL;	};	return retval;}/* *       ISDN operations * * Many of these routines take an "int dev" argument, which is simply * an index into the drivers[] array.  Currently, we only support a * single AMD 7930 chip, so the value should always be 0.  B channel * operations require an "int chan", which should be 0 for channel B1 * and 1 for channel B2 * * int amd7930_get_irqnum(int dev) * *   returns the interrupt number being used by the chip.  ISDN4linux *   uses this number to watch the interrupt during initialization and *   make sure something is happening. * * int amd7930_get_liu_state(int dev) * *   returns the current state of the ISDN Line Interface Unit (LIU) *   as a number between 2 (state F2) and 7 (state F7).  0 may also be *   returned if the chip doesn't exist or the LIU hasn't been *   activated.  The meanings of the states are defined in I.430, ISDN *   BRI Physical Layer Interface.  The most important two states are *   F3 (shutdown) and F7 (syncronized). * * void amd7930_liu_init(int dev, void (*callback)(), void *callback_arg) * *   initializes the LIU and optionally registers a callback to be *   signaled upon a change of LIU state.  The callback will be called *   with a single opaque callback_arg Once the callback has been *   triggered, amd7930_get_liu_state can be used to determine the LIU *   current state. * * void amd7930_liu_activate(int dev, int priority) * *   requests LIU activation at a given D-channel priority. *   Successful activatation is achieved upon entering state F7, which *   will trigger any callback previously registered with *   amd7930_liu_init. * * void amd7930_liu_deactivate(int dev) * *   deactivates LIU.  Outstanding D and B channel transactions are *   terminated rudely and without callback notification.  LIU change *   of state callback will be triggered, however. * * void amd7930_dxmit(int dev, __u8 *buffer, unsigned int count, *               void (*callback)(void *, int), void *callback_arg) * *   transmits a packet - specified with buffer, count - over the D-channel *   interface.  Buffer should begin with the LAPD address field and *   end with the information field.  FCS and flag sequences should not *   be included, nor is bit-stuffing required - all these functions are *   performed by the chip.  The callback function will be called *   DURING THE TOP HALF OF AN INTERRUPT HANDLER and will be passed *   both the arbitrary callback_arg and an integer error indication: * *       0 - successful transmission; ready for next packet *   non-0 - error value from chip's DER (D-Channel Error Register): *       4 - collision detect *     128 - underrun; irq routine didn't service chip fast enough * *   The callback routine should defer any time-consuming operations *   to a bottom-half handler; however, amd7930_dxmit may be called *   from within the callback to request back-to-back transmission of *   a second packet (without repeating the priority/collision mechanism) * *   A comment about the "collision detect" error, which is signalled *   whenever the echoed D-channel data didn't match the transmitted *   data.  This is part of ISDN's normal multi-drop T-interface *   operation, indicating that another device has attempted simultaneous *   transmission, but can also result from line noise.  An immediate *   requeue via amd7930_dxmit is suggested, but repeated collision *   errors may indicate a more serious problem. * * void amd7930_drecv(int dev, __u8 *buffer, unsigned int size, *               void (*callback)(void *, int, unsigned int), *               void *callback_arg) * *   register a buffer - buffer, size - into which a D-channel packet *   can be received.  The callback function will be called DURING *   THE TOP HALF OF AN INTERRUPT HANDLER and will be passed an *   arbitrary callback_arg, an integer error indication and the length *   of the received packet, which will start with the address field, *   end with the information field, and not contain flag or FCS *   bytes.  Bit-stuffing will already have been corrected for. *   Possible values of second callback argument "error": * *       0 - successful reception *   non-0 - error value from chip's DER (D-Channel Error Register): *       1 - received packet abort *       2 - framing error; non-integer number of bytes received *       8 - FCS error; CRC sequence indicated corrupted data *      16 - overflow error; packet exceeded size of buffer *      32 - underflow error; packet smaller than required five bytes *      64 - overrun error; irq routine didn't service chip fast enough * * int amd7930_bopen(int dev, int chan, u_char xmit_idle_char) * *   This function should be called before any other operations on a B *   channel.  In addition to arranging for interrupt handling and *   channel multiplexing, it sets the xmit_idle_char which is *   transmitted on the interface when no data buffer is available. *   Suggested values are: 0 for ISDN audio; FF for HDLC mark idle; 7E *   for HDLC flag idle.  Returns 0 on a successful open; -1 on error, *   which is quite possible if audio and the other ISDN channel are *   already in use, since the Am7930 can only send two of the three *   channels to the processor * * void amd7930_bclose(int dev, int chan) * *   Shuts down a B channel when no longer in use. * * void amd7930_bxmit(int dev, int chan, __u8 *buffer, unsigned int count, *               void (*callback)(void *), void *callback_arg) * *   transmits a raw data block - specified with buffer, count - over *   the B channel interface specified by dev/chan.  The callback *   function will be called DURING THE TOP HALF OF AN INTERRUPT *   HANDLER and will be passed the arbitrary callback_arg * *   The callback routine should defer any time-consuming operations *   to a bottom-half handler; however, amd7930_bxmit may be called *   from within the callback to request back-to-back transmission of *   another data block * * void amd7930_brecv(int dev, int chan, __u8 *buffer, unsigned int size, *               void (*callback)(void *), void *callback_arg) * *   receive a raw data block - specified with buffer, size - over the *   B channel interface specified by dev/chan.  The callback function *   will be called DURING THE TOP HALF OF AN INTERRUPT HANDLER and *   will be passed the arbitrary callback_arg * *   The callback routine should defer any time-consuming operations *   to a bottom-half handler; however, amd7930_brecv may be called *   from within the callback to register another buffer and ensure *   continuous B channel reception without loss of data * */#if defined (AMD79C30_ISDN)static int amd7930_get_irqnum(int dev){	struct amd7930_info *info;	if (dev > num_drivers)		return(0);	info = (struct amd7930_info *) drivers[dev].private;	return info->irq;}static int amd7930_get_liu_state(int dev){	struct amd7930_info *info;	if (dev > num_drivers)		return(0);	info = (struct amd7930_info *) drivers[dev].private;	return info->liu_state;}static void amd7930_liu_init(int dev, void (*callback)(), void *callback_arg){	struct amd7930_info *info;	unsigned long flags;	if (dev > num_drivers)		return;	info = (struct amd7930_info *) drivers[dev].private;	save_and_cli(flags);	/* Set callback for LIU state change */        info->liu_callback = callback;	info->liu_callback_arg = callback_arg;	/* De-activate the ISDN Line Interface Unit (LIU) */	sbus_writeb(AMR_LIU_LMR1, info->regs + CR);	sbus_writeb(0, info->regs + DR);	/* Request interrupt when LIU changes state from/to F3/F7/F8 */	sbus_writeb(AMR_LIU_LMR2, info->regs + CR);	sbus_writeb(AM_LIU_LMR2_EN_F3_INT |		    AM_LIU_LMR2_EN_F7_INT |		    AM_LIU_LMR2_EN_F8_INT,		    info->regs + DR);	/* amd7930_enable_ints(info); */	/* Activate the ISDN Line Interface Unit (LIU) */	sbus_writeb(AMR_LIU_LMR1, info->regs + CR);	sbus_writeb(AM_LIU_LMR1_LIU_ENABL, info->regs + DR);	restore_flags(flags);}static void amd7930_liu_activate(int dev, int priority){	struct amd7930_info *info;	unsigned long flags;	if (dev > num_drivers)		return;	info = (struct amd7930_info *) drivers[dev].private;	save_and_cli(flags);        /* Set D-channel access priority         *         * I.430 defines a priority mechanism based on counting 1s         * in the echo channel before transmitting         *         * Priority 0 is eight 1s; priority 1 is ten 1s; etc         */        sbus_writeb(AMR_LIU_LPR, info->regs + CR);        sbus_writeb(priority & 0x0f, info->regs + DR);	/* request LIU activation */	sbus_writeb(AMR_LIU_LMR1, info->regs + CR);	sbus_writeb(AM_LIU_LMR1_LIU_ENABL | AM_LIU_LMR1_REQ_ACTIV,		    info->regs + DR);	restore_flags(flags);}static void amd7930_liu_deactivate(int dev){	struct amd7930_info *info;	unsigned long flags;	if (dev > num_drivers)		return;	info = (struct amd7930_info *) drivers[dev].private;	save_and_cli(flags);	/* deactivate LIU */	sbus_writeb(AMR_LIU_LMR1, info->regs + CR);	sbus_writeb(0, info->regs + DR);	restore_flags(flags);}static void amd7930_dxmit(int dev, __u8 *buffer, unsigned int count,			  void (*callback)(void *, int), void *callback_arg){	struct amd7930_info *info;	unsigned long flags;	__u8 dmr1;	if (dev > num_drivers)		return;	info = (struct amd7930_info *) drivers[dev].private;	save_and_cli(flags);	if (info->D.output_ptr) {		restore_flags(flags);		printk("amd7930_dxmit: transmitter in use\n");		return;	}	info->D.output_ptr = buffer;	info->D.output_count = count;	info->D.output_callback = callback;	info->D.output_callback_arg = callback_arg;	/* Enable D-channel Transmit Threshold interrupt; disable addressing */	sbus_writeb(AMR_DLC_DMR1, info->regs + CR);	dmr1 = sbus_readb(info->regs + DR);	dmr1 |= AMR_DLC_DMR1_DTTHRSH_INT;	dmr1 &= ~AMR_DLC_DMR1_EN_ADDRS;	sbus_writeb(dmr1, info->regs + DR);	/* Begin xmit by setting D-channel Transmit Byte Count Reg (DTCR) */	sbus_writeb(AMR_DLC_DTCR, info->regs + CR);	sbus_writeb(count & 0xff, info->regs + DR);	sbus_writeb((count >> 8) & 0xff, info->regs + DR);	/* Prime xmit FIFO */	/* fill_D_xmit_fifo(info); */	transceive_Dchannel(info);	restore_flags(flags);}static void amd7930_drecv(int dev, __u8 *buffer, unsigned int size,			  void (*callback)(void *, int, unsigned int),			  void *callback_arg){	struct amd7930_info *info;	unsigned long flags;	__u8 dmr1;	if (dev > num_drivers)		return;	info = (struct amd7930_info *) drivers[dev].private;	save_and_cli(flags);	if (info->D.input_ptr) {		restore_flags(flags);		printk("amd7930_drecv: receiver already has buffer!\n");		return;	}	info->D.input_ptr = buffer;	info->D.input_count = 0;	info->D.input_limit = size;	info->D.input_callback = callback;	info->D.input_callback_arg = callback_arg;	/* Enable D-channel Receive Threshold interrupt;	 * Enable D-channel End of Receive Packet interrupt;	 * Disable address recognition	 */	sbus_writeb(AMR_DLC_DMR1, info->regs + CR);	dmr1 = sbus_readb(info->regs + DR);	dmr1 |= AMR_DLC_DMR1_DRTHRSH_INT | AMR_DLC_DMR1_EORP_INT;	dmr1 &= ~AMR_DLC_DMR1_EN_ADDRS;	sbus_writeb(dmr1, info->regs + DR);	/* Set D-channel Receive Byte Count Limit Register */	sbus_writeb(AMR_DLC_DRCR, info->regs + CR);	sbus_writeb(size & 0xff, info->regs + DR);	sbus_writeb((size >> 8) & 0xff, info->regs + DR);	restore_flags(flags);}static int amd7930_bopen(int dev, unsigned int chan,                          int mode, u_char xmit_idle_char){	struct amd7930_info *info;	unsigned long flags;	u8 tmp;	if (dev > num_drivers || chan<0 || chan>1)		return -1;	if (mode == L1_MODE_HDLC)		return -1; 	info = (struct amd7930_info *) drivers[dev].private;	save_and_cli(flags);	if (info->Bb.channel_status == CHANNEL_AVAILABLE) {		info->Bb.channel_status = CHANNEL_INUSE;		info->Bb.xmit_idle_char = xmit_idle_char;		info->Bisdn[chan] = &info->Bb;		/* Multiplexor map - isdn (B1/2) to Bb */		sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR);		sbus_writeb((AM_MUX_CHANNEL_B1 + chan) |			    (AM_MUX_CHANNEL_Bb << 4),			    info->regs + DR);	} else if (info->Bc.channel_status == CHANNEL_AVAILABLE) {		info->Bc.channel_status = CHANNEL_INUSE;		info->Bc.xmit_idle_char = xmit_idle_char;		info->Bisdn[chan] = &info->Bc;		/* Multiplexor map - isdn (B1/2) to Bc */		sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR);		sbus_writeb((AM_MUX_CHANNEL_B1 + chan) |			    (AM_MUX_CHANNEL_Bc << 4),			    info->regs + DR);	} else {		restore_flags(flags);		return (-1);	}	/* Enable B channel transmit */	sbus_writeb(AMR_LIU_LMR1, info->regs + CR);	tmp = sbus_readb(info->regs + DR);	tmp |= AM_LIU_LMR1_B1_ENABL + chan;	sbus_writeb(tmp, info->regs + DR);	/* Enable B channel interrupts */	sbus_writeb(AMR_MUX_MCR4, info->regs + CR);	sbus_writeb(AM_MUX_MCR4_ENABLE_INTS |		    AM_MUX_MCR4_REVERSE_Bb |		    AM_MUX_MCR4_REVERSE_Bc,		    info->regs + DR);	restore_flags(flags);	return 0;}static void amd7930_bclose(int dev, unsigned int chan){	struct amd7930_info *info;	unsigned long flags;	if (dev > num_drivers || chan<0 || chan>1)		return;	info = (struct amd7930_info *) drivers[dev].private;	save_and_cli(flags);	if (info->Bisdn[chan]) {		u8 tmp;		info->Bisdn[chan]->channel_status = CHANNEL_AVAILABLE;		sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR);		sbus_writeb(0, info->regs + DR);		info->Bisdn[chan] = NULL;		/* Disable B channel transmit */		sbus_writeb(AMR_LIU_LMR1, info->regs + CR);		tmp = sbus_readb(info->regs + DR);		tmp &= ~(AM_LIU_LMR1_B1_ENABL + chan);		sbus_writeb(tmp, info->regs + DR);		if (info->Bb.channel_status == CHANNEL_AVAILABLE &&		    info->Bc.channel_status == CHANNEL_AVAILABLE) {			/* Disable B channel interrupts */

⌨️ 快捷键说明

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