From 2606e8aa4b40fb4d9a664b7681a49a56a0633434 Mon Sep 17 00:00:00 2001 From: jim Date: Thu, 11 Aug 2005 03:19:46 +0000 Subject: Added driver support for UART output in VHDL on each channel git-svn-id: http://svn.digium.com/svn/zaptel/trunk@728 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- pciradio.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------- zaptel.h | 7 +++- 2 files changed, 112 insertions(+), 14 deletions(-) diff --git a/pciradio.c b/pciradio.c index 002a9a3..4702a6e 100755 --- a/pciradio.c +++ b/pciradio.c @@ -63,6 +63,10 @@ With driver: 303826 (1.5 %) #define NUM_CODES 15 +#define SERIAL_BUFLEN 128 + +#define SRX_TIMEOUT 300 + #define RAD_CNTL 0x00 #define RAD_OPER 0x01 #define RAD_AUXC 0x02 @@ -149,7 +153,13 @@ struct pciradio { int freeregion; int nchans; spinlock_t lock; - spinlock_t rbilock; + spinlock_t remotelock; + unsigned char rxbuf[SERIAL_BUFLEN]; + unsigned short rxindex; + unsigned long srxtimer; + unsigned char txbuf[SERIAL_BUFLEN]; + unsigned short txindex; + unsigned short txlen; unsigned char pasave; unsigned char pfsave; volatile unsigned long ioaddr; @@ -464,7 +474,7 @@ int x; DECLARE_WAIT_QUEUE_HEAD(mywait); - spin_lock(&rad->rbilock); + spin_lock(&rad->remotelock); while(__pciradio_getcreg(rad,0xc) & 2) interruptible_sleep_on_timeout(&mywait,2); /* enable and address RBI serializer */ __pciradio_setcreg(rad,0xf,rad->pfsave | (n << 4) | 0x40); @@ -472,7 +482,7 @@ DECLARE_WAIT_QUEUE_HEAD(mywait); for(x = 0; x < 5; x++) __pciradio_setcreg(rad,0xc,rbicmd[x]); /* output it */ __pciradio_setcreg(rad,0xb,1); - spin_unlock(&rad->rbilock); + spin_unlock(&rad->remotelock); return; } @@ -891,6 +901,28 @@ static void pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs) } } } +/* process serial if any */ + /* send byte if there is one in buffer to send */ + if (rad->txlen && (rad->txlen != rad->txindex)) + { + /* if tx not busy */ + if (!(__pciradio_getcreg(rad,9) & 0x80)) + { + __pciradio_setcreg(rad, 4, rad->txbuf[rad->txindex++]); + } + } + rad->srxtimer++; + /* if something in rx to read */ + while(__pciradio_getcreg(rad,9) & 0x10) + { + unsigned char c = __pciradio_getcreg(rad,4); + rad->srxtimer = 0; + if (rad->rxindex < RAD_SERIAL_BUFLEN) + { + rad->rxbuf[rad->rxindex++] = c; + } + udelay(1); + } pciradio_receiveprep(rad, ints); pciradio_transmitprep(rad, ints); } @@ -1162,29 +1194,90 @@ static int pciradio_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long rad->remmode[chan->chanpos - 1] = stack.p.data; break; case ZT_RADPAR_REMCOMMAND: + /* if no remote mode, return an error */ + if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_NONE) + { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } i = 0; + if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_RBI1) + { + /* set UIOA and UIOB for output */ + spin_lock_irqsave(&rad->lock,flags); + byte1 = __pciradio_getcreg(rad,0xe); + mask = (1 << (chan->chanpos - 1)) | + (1 << (chan->chanpos + 3)); + byte2 = byte1 & (~mask); + i = (byte2 != byte1); + __pciradio_setcreg(rad,0xe,byte2); + byte1 = __pciradio_getcreg(rad,8); + mask = 1 << (chan->chanpos - 1); + byte2 = byte1 | mask; + i = (byte2 != byte1); + __pciradio_setcreg(rad,8,byte2); + spin_unlock_irqrestore(&rad->lock,flags); + if (i || (jiffies < rad->lastremcmd + 10)) + interruptible_sleep_on_timeout(&mywait,10); + rad->lastremcmd = jiffies; + rbi_out(rad,chan->chanpos - 1,(unsigned char *)&stack.p.data); + break; + } /* set UIOA and UIOB for output */ spin_lock_irqsave(&rad->lock,flags); byte1 = __pciradio_getcreg(rad,0xe); - mask = (1 << (chan->chanpos - 1)) | - (1 << (chan->chanpos + 3)); + mask = 1 << (chan->chanpos + 3); /* B an output */ byte2 = byte1 & (~mask); - i = (byte2 != byte1); + byte2 |= 1 << (chan->chanpos - 1); /* A in input */ __pciradio_setcreg(rad,0xe,byte2); byte1 = __pciradio_getcreg(rad,8); - mask = 1 << (chan->chanpos - 1); byte2 = byte1 | mask; - i = (byte2 != byte1); + byte2 |= 1 << (chan->chanpos - 1); __pciradio_setcreg(rad,8,byte2); spin_unlock_irqrestore(&rad->lock,flags); - if (i || (jiffies < rad->lastremcmd + 10)) + if (byte1 != byte2) + interruptible_sleep_on_timeout(&mywait,100); + while (jiffies < rad->lastremcmd + 10) interruptible_sleep_on_timeout(&mywait,10); rad->lastremcmd = jiffies; - if (rad->remmode[chan->chanpos - 1]) - { - rbi_out(rad,chan->chanpos - 1,(unsigned char *)&stack.p.data); + spin_lock(&rad->remotelock); + while(__pciradio_getcreg(rad,0xc) & 2) interruptible_sleep_on_timeout(&mywait,2); + spin_unlock(&rad->remotelock); + spin_lock_irqsave(&rad->lock,flags); + /* enable and address async serializer */ + __pciradio_setcreg(rad,0xf,rad->pfsave | ((chan->chanpos - 1) << 4) | 0x80); + /* copy tx buffer */ + memcpy(rad->txbuf,stack.p.buf,stack.p.index); + rad->txlen = stack.p.index; + rad->txindex = 0; + rad->rxindex = 0; + rad->srxtimer = 0; + memset(stack.p.buf,0,SERIAL_BUFLEN); + stack.p.index = 0; + for(;;) + { + rad->rxbuf[rad->rxindex] = 0; + if (((!stack.p.data) || (rad->rxindex < stack.p.data)) && + (rad->srxtimer < SRX_TIMEOUT) && + ((rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_SERIAL) || + (!strchr(rad->rxbuf,'\r')))) + { + spin_unlock_irqrestore(&rad->lock,flags); + interruptible_sleep_on_timeout(&mywait,2); + spin_lock_irqsave(&rad->lock,flags); + continue; + } + memset(stack.p.buf,0,SERIAL_BUFLEN); + if (stack.p.data && (rad->rxindex > stack.p.data)) + rad->rxindex = stack.p.data; + if (rad->rxindex) + memcpy(stack.p.buf,rad->rxbuf,rad->rxindex); + stack.p.index = rad->rxindex; + break; } - break; + if (copy_to_user((struct zt_radio_stat *)data,&stack.p,sizeof(struct zt_radio_param))) return -EFAULT; + spin_unlock_irqrestore(&rad->lock,flags); + return 0; default: spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; diff --git a/zaptel.h b/zaptel.h index ff3d06b..9632397 100755 --- a/zaptel.h +++ b/zaptel.h @@ -1492,11 +1492,14 @@ struct zt_radio_stat { unsigned char radstat; /* status bits of radio */ }; +#define RAD_SERIAL_BUFLEN 128 + struct zt_radio_param { unsigned short radpar; /* param identifier */ unsigned short index; /* tone number */ int data; /* param */ int data2; /* param 2 */ + unsigned char buf[RAD_SERIAL_BUFLEN]; }; @@ -1557,7 +1560,9 @@ struct zt_radio_param { #define ZT_RADPAR_REMMODE 16 /* Remote control data mode */ #define ZT_RADPAR_REM_NONE 0 /* no remote control data mode */ - #define ZT_RADPAR_REM_RBI1 1 /* Doug Hall RBI-1 data mode */ + #define ZT_RADPAR_REM_RBI1 1 /* Doug Hall RBI-1 data mode */ + #define ZT_RADPAR_REM_SERIAL 2 /* Serial Data, 9600 BPS */ + #define ZT_RADPAR_REM_SERIAL_ASCII 3 /* Serial Ascii Data, 9600 BPS */ #define ZT_RADPAR_REMCOMMAND 17 /* Remote conrtol write data block & do cmd */ -- cgit v1.2.3