summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjim <jim@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2005-08-11 03:19:46 +0000
committerjim <jim@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2005-08-11 03:19:46 +0000
commit2606e8aa4b40fb4d9a664b7681a49a56a0633434 (patch)
tree1cc5d9992d10fb0200edb5e7518018156dedfbf5
parentb7d628e4e33e98cf73cf3c4877afe321825a65e7 (diff)
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
-rwxr-xr-xpciradio.c119
-rwxr-xr-xzaptel.h7
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 */