summaryrefslogtreecommitdiff
path: root/pciradio.c
diff options
context:
space:
mode:
authorjim <jim@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2004-12-22 04:44:26 +0000
committerjim <jim@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2004-12-22 04:44:26 +0000
commit5ccad649b6fbb917cecf9530ba64814459dfe565 (patch)
treed4290c0877018d339fda18f5323952c88239b157 /pciradio.c
parent35c0c5037ea5cb43b560d93137e4fef09fd1f3da (diff)
Changed out VHDL code so that interrupt handling would be much more efficient
and fully handle all functions git-svn-id: http://svn.digium.com/svn/zaptel/trunk@513 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'pciradio.c')
-rwxr-xr-xpciradio.c550
1 files changed, 298 insertions, 252 deletions
diff --git a/pciradio.c b/pciradio.c
index 3351bb7..84e2507 100755
--- a/pciradio.c
+++ b/pciradio.c
@@ -37,9 +37,8 @@
/* Latency tests:
-Without driver: 308208
-Without int: 304096 (1.3 %)
-With PL check: 267722 (13.2 % -- will be much improved with new Xilinx)
+Without driver: 308496
+With driver: 303826 (1.5 %)
*/
@@ -90,11 +89,6 @@ With PL check: 267722 (13.2 % -- will be much improved with new Xilinx)
#define RAD_REGBASE 0xc0
-#define BIT_CS (1 << 2)
-#define BIT_SCLK (1 << 3)
-#define BIT_SDI (1 << 4)
-#define BIT_SDO (1 << 5)
-
#define RAD_CTCSSMASK 0xf
#define RAD_CTCSSOTHER 0xf
#define RAD_CTCSSVALID 0x10
@@ -103,16 +97,6 @@ With PL check: 267722 (13.2 % -- will be much improved with new Xilinx)
#define RAD_GOTRX_DEBOUNCE_TIME 75
-/* bits for port 0 in */
-#define MX828_DOUT 0x10 /* Data from MX828 */
-/* bits for port 0 out */
-#define MX828_DIN 0x2 /* Data to MX828 */
-#define MX828_CS0 0x10 /* MX828 CS Channel 0 */
-#define MX828_CS1 0x20 /* MX828 CS Channel 1 */
-#define MX828_CS2 0x40 /* MX828 CS Channel 2 */
-#define MX828_CS3 0x80 /* MX828 CS Channel 3 */
-#define MX828_SCLK 0x1 /* MX828 Serial Clock */
-
/*
* MX828 Commands
*/
@@ -134,6 +118,22 @@ With PL check: 267722 (13.2 % -- will be much improved with new Xilinx)
#define MX828_IRQ_FLAG 0x8F /* R */
+struct encdec
+{
+ unsigned char state; /* 0 = idle */
+ int chan;
+ unsigned char req[NUM_CHANS];
+ unsigned char dcsrx[NUM_CHANS];
+ unsigned char ctrx[NUM_CHANS];
+ unsigned char dcstx[NUM_CHANS];
+ unsigned char cttx[NUM_CHANS];
+ unsigned char saudio_ctrl[NUM_CHANS];
+ unsigned char saudio_setup[NUM_CHANS];
+ unsigned char txcode[NUM_CHANS];
+ int myindex[NUM_CHANS];
+} ;
+
+
struct pciradio {
struct pci_dev *dev;
struct zt_span span;
@@ -145,9 +145,9 @@ struct pciradio {
int freeregion;
int nchans;
spinlock_t lock;
- unsigned char p0save;
- unsigned char p1save;
- unsigned char p2save;
+ spinlock_t rbilock;
+ unsigned char pasave;
+ unsigned char pfsave;
unsigned long ioaddr;
dma_addr_t readdma;
dma_addr_t writedma;
@@ -164,6 +164,7 @@ struct pciradio {
int debouncetime[NUM_CHANS];
int bursttime[NUM_CHANS];
int bursttimer[NUM_CHANS];
+ unsigned char remmode[NUM_CHANS];
unsigned short present_code[NUM_CHANS];
unsigned short last_code[NUM_CHANS];
unsigned short rxcode[NUM_CHANS][NUM_CODES + 1];
@@ -178,6 +179,9 @@ struct pciradio {
#define RADMODE_NOENCODE 32
unsigned char corthresh[NUM_CHANS];
struct zt_chan chans[NUM_CHANS];
+ unsigned char mx828_addr;
+ struct encdec encdec;
+ unsigned long lastremcmd;
};
@@ -449,35 +453,25 @@ static unsigned char __pciradio_getcreg(struct pciradio *rad, unsigned char reg)
return inb(rad->ioaddr + RAD_REGBASE + ((reg & 0xf) << 2));
}
-static void wait_just_a_bit(int foo)
-{
- long newjiffies;
- newjiffies = jiffies + foo;
- while(jiffies < newjiffies);
-}
-
-/*
-* Output a byte to the MX828 PL encoder/decoder chip
-*/
-void mx828_set_serdata(struct pciradio *rad,int bit)
+void rbi_out(struct pciradio *rad, int n, unsigned char *rbicmd)
{
- rad->p0save &= ~MX828_DIN;
- if(bit)
- rad->p0save |= MX828_DIN;
- __pciradio_setcreg(rad,0,rad->p0save);
+int x;
+DECLARE_WAIT_QUEUE_HEAD(mywait);
+
+
+ spin_lock(&rad->rbilock);
+ 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);
+ /* output commands */
+ for(x = 0; x < 5; x++) __pciradio_setcreg(rad,0xc,rbicmd[x]);
+ /* output it */
+ __pciradio_setcreg(rad,0xb,1);
+ spin_unlock(&rad->rbilock);
+ return;
}
-void mx828_wiggle_sclk(struct pciradio *rad)
-{
- rad->p0save &= ~MX828_SCLK; /* SCLK 1 -> 0 */
- __pciradio_setcreg(rad,0,rad->p0save);
- udelay(1);
- rad->p0save |= MX828_SCLK; /* SCLK 0 -> 1 */
- __pciradio_setcreg(rad,0,rad->p0save);
- udelay(1);
-}
-
/*
* Output a command to the MX828 over the serial bus
@@ -487,192 +481,156 @@ void mx828_wiggle_sclk(struct pciradio *rad)
void mx828_command(struct pciradio *rad,int channel, unsigned char command, unsigned char *byte1, unsigned char *byte2)
{
- int i, param = 1, wr = 1, word = 0;
- unsigned char byte;
-
if(channel > 3)
return;
- /* Pull the transfer info from the command code */
-
- switch(command){
- case MX828_GEN_RESET: /* Commands with no param */
- param = 0;
- break;
-
- case MX828_SAUDIO_CTRL: /* 8 bit write commands */
- case MX828_SAUDIO_SETUP:
- case MX828_DCS1:
- case MX828_DCS2:
- case MX828_DCS3:
- case MX828_IRQ_MASK:
- case MX828_GEN_CTRL:
- case MX828_GPT:
- break;
-
- case MX828_SAUDIO_STATUS: /* 8 bit read commands */
- case MX828_IRQ_FLAG:
- case 0:
- wr = 0;
- break;
+ rad->mx828_addr = channel;
+ __pciradio_setcreg(rad,0,channel);
+ if (byte1) __pciradio_setcreg(rad,1,*byte1);
+ if (byte2) __pciradio_setcreg(rad,2,*byte2);
+ __pciradio_setcreg(rad,3,command);
+
+}
- case MX828_TX_TONE: /* 16 bit write commands */
- case MX828_RX_TONE:
- case MX828_AUD_CTRL:
- case MX828_SELCALL:
- word = 1;
- break;
+void mx828_command_wait(struct pciradio *rad,int channel, unsigned char command, unsigned char *byte1, unsigned char *byte2)
+{
+unsigned int flags;
+DECLARE_WAIT_QUEUE_HEAD(mywait);
- default:
+ for(;;)
+ {
+ spin_lock_irqsave(&rad->lock,flags);
+ if ((!(__pciradio_getcreg(rad,0xc) & 1)) &&
+ (!(rad->encdec.state)))
+ {
+ mx828_command(rad,channel,command,byte1,byte2);
+ spin_unlock_irqrestore(&rad->lock,flags);
return;
+ }
+ spin_unlock_irqrestore(&rad->lock,flags);
+ interruptible_sleep_on_timeout(&mywait,5);
}
-
-
- mx828_set_serdata(rad,1); /* Start with data = 1 */
-
- udelay(2);
-
- /* Set the proper CS */
+}
- byte = (unsigned char ) 1 << (channel + 4);
-
- rad->p0save |= (MX828_CS0 | MX828_CS1 | MX828_CS2 | MX828_CS3);
- rad->p0save &= ~byte;
- __pciradio_setcreg(rad,0,rad->p0save);
-
- udelay(2);
-
- /* Output the command byte */
+static void _do_encdec(struct pciradio *rad, int n)
+{
+int i;
+unsigned char byte1,byte2;
- byte = command;
-
- for( i = 0 ; i < 8 ; i++){
- udelay(2);
- mx828_set_serdata(rad,0x80 & byte); /* MSB first */
- byte <<= 1;
- mx828_wiggle_sclk(rad);
- }
- if(param){
- udelay(4);
- if(wr){
- byte = *byte1;
- for( i = 0 ; i < 8 ; i++){
- udelay(2);
- mx828_set_serdata(rad,0x80 & byte);
- byte <<= 1;
- mx828_wiggle_sclk(rad);
- }
- if(word){
- udelay(4);
- byte = *byte2;
- for( i = 0 ; i < 8 ; i++){
- udelay(2);
- mx828_set_serdata(rad,0x80 & byte);
- byte <<= 1;
- mx828_wiggle_sclk(rad);
- }
+ /* return doing nothing if busy */
+ if (__pciradio_getcreg(rad,0xc) & 1) return;
+ switch(rad->encdec.state)
+ {
+ case 0:
+ if (!rad->encdec.req[n]) return;
+ rad->encdec.req[n] = 0;
+ rad->encdec.dcsrx[n] = 0;
+ rad->encdec.ctrx[n] = 0;
+ rad->encdec.dcstx[n] = 0;
+ rad->encdec.cttx[n] = 0;
+ rad->encdec.myindex[n] = 0;
+ rad->encdec.req[n] = 0;
+ rad->encdec.chan = n;
+
+ /* if something in code 0 for rx, is DCS */
+ if (rad->rxcode[n][0]) rad->encdec.dcsrx[n] = 1;
+ else { /* otherwise, if something in other codes, is CT rx */
+ for(i = 1; i <= NUM_CODES; i++)
+ {
+ if (rad->rxcode[n][1]) rad->encdec.ctrx[n] = 1;
}
+ }
+ /* get index for tx code. Will be 0 if not receiving a CT */
+ rad->encdec.myindex[n] = 0;
+ if (rad->gotrx[n] && rad->encdec.ctrx[n] && (rad->present_code[n]))
+ rad->encdec.myindex[n] = rad->present_code[n];
+ /* get actual tx code from array */
+ rad->encdec.txcode[n] = rad->txcode[n][rad->encdec.myindex[n]];
+ if (rad->encdec.txcode[n] & 0x8000) rad->encdec.dcstx[n] = 1;
+ else if (rad->encdec.txcode[n]) rad->encdec.cttx[n] = 1;
+ if (rad->radmode[n] & RADMODE_NOENCODE)
+ rad->encdec.dcstx[n] = rad->encdec.cttx[n] = 0;
+ if ((!rad->gottx[n]) || rad->bursttimer[n])
+ rad->encdec.dcstx[n] = rad->encdec.cttx[n] = 0;
+ rad->encdec.saudio_ctrl[n] = 0;
+ rad->encdec.saudio_setup[n] = 0;
+ rad->encdec.state = 1;
+ break;
+ case 1:
+ if (rad->encdec.dcstx[rad->encdec.chan] && (!rad->encdec.dcsrx[rad->encdec.chan])) /* if to transmit DCS */
+ {
+ rad->encdec.saudio_setup[rad->encdec.chan] |= 3;
+ rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x80;
+ byte1 = dcstable[rad->encdec.txcode[rad->encdec.chan] & 0x7fff].b1;
+ mx828_command(rad,rad->encdec.chan, MX828_DCS1, &byte1, &byte2 );
+ rad->encdec.state = 2;
+ break;
+ }
+ rad->encdec.state = 4;
+ break;
+ case 2:
+ byte1 = dcstable[rad->encdec.txcode[rad->encdec.chan] & 0x7fff].b2;
+ mx828_command(rad,rad->encdec.chan, MX828_DCS2, &byte1, &byte2 );
+ rad->encdec.state = 3;
+ break;
+ case 3:
+ byte1 = dcstable[rad->encdec.txcode[rad->encdec.chan] & 0x7fff].b3;
+ mx828_command(rad,rad->encdec.chan, MX828_DCS3, &byte1, &byte2 );
+ rad->encdec.state = 4;
+ break;
+ case 4:
+ if (rad->encdec.cttx[rad->encdec.chan])
+ {
+ rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x80;
+ byte1 = cttable_tx[rad->encdec.txcode[rad->encdec.chan]].b1;
+ byte2 = cttable_tx[rad->encdec.txcode[rad->encdec.chan]].b2;
+ mx828_command(rad,rad->encdec.chan, MX828_TX_TONE, &byte1, &byte2 );
}
- else { /* rd */
- byte = 0;
- for( i = 0 ; i < 8 ; i++){
- mx828_wiggle_sclk(rad);
- byte <<= 1;
- udelay(2);
- if(__pciradio_getcreg(rad,0) & MX828_DOUT)
- byte |= 0x01;
- }
- *byte1 = byte;
- if(word){
- byte = 0;
- udelay(4);
- for( i = 0 ; i < 8 ; i++){
- mx828_wiggle_sclk(rad);
- byte <<= 1;
- udelay(2);
- if(__pciradio_getcreg(rad,0) & MX828_DOUT)
- byte |= 0x01;
- }
- *byte2 = byte;
- }
-
+ rad->encdec.state = 5;
+ break;
+ case 5:
+ if (rad->encdec.dcsrx[rad->encdec.chan])
+ {
+ rad->encdec.saudio_setup[rad->encdec.chan] |= 1;
+ rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x41;
+ byte1 = dcstable[rad->rxcode[rad->encdec.chan][0]].b1;
+ mx828_command(rad,rad->encdec.chan, MX828_DCS1, &byte1, &byte2 );
+ rad->encdec.state = 6;
+ break;
}
- }
-
- udelay(4);
-
- /* Release chip selects */
- rad->p0save |= (MX828_CS0 | MX828_CS1 | MX828_CS2 | MX828_CS3);
- __pciradio_setcreg(rad,0,rad->p0save);
-}
-
-
-static void _set_encdec(struct pciradio *rad, int n)
-{
-int i,myindex;
-char dcsrx = 0, ctrx = 0, dcstx = 0, cttx = 0;
-unsigned char byte1,byte2,saudio_ctrl,saudio_setup;
-unsigned short txcode;
-
-
- /* if something in code 0 for rx, is DCS */
- if (rad->rxcode[n][0]) dcsrx = 1;
- else { /* otherwise, if something in other codes, is CT rx */
- for(i = 1; i <= NUM_CODES; i++)
+ rad->encdec.state = 8;
+ break;
+ case 6:
+ byte1 = dcstable[rad->rxcode[rad->encdec.chan][0]].b2;
+ mx828_command(rad,rad->encdec.chan, MX828_DCS2, &byte1, &byte2 );
+ rad->encdec.state = 7;
+ break;
+ case 7:
+ byte1 = dcstable[rad->rxcode[rad->encdec.chan][0]].b3;
+ mx828_command(rad,rad->encdec.chan, MX828_DCS3, &byte1, &byte2 );
+ rad->encdec.state = 8;
+ break;
+ case 8:
+ if (rad->encdec.ctrx[rad->encdec.chan])
{
- if (rad->rxcode[n][1]) ctrx = 1;
+ rad->encdec.saudio_setup[rad->encdec.chan] |= 0x80;
+ rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x60;
}
- }
- /* get index for tx code. Will be 0 if not receiving a CT */
- myindex = 0;
- if (rad->gotrx[n] && ctrx && (rad->present_code[n])) myindex = rad->present_code[n];
- /* get actual tx code from array */
- txcode = rad->txcode[n][myindex];
- if (txcode & 0x8000) dcstx = 1; else if (txcode) cttx = 1;
- if (rad->radmode[n] & RADMODE_NOENCODE) dcstx = cttx = 0;
- if ((!rad->gottx[n]) || rad->bursttimer[n]) dcstx = cttx = 0;
- saudio_ctrl = 0;
- saudio_setup = 0;
- if (dcstx && (!dcsrx)) /* if to transmit DCS */
- {
- saudio_setup |= 3;
- saudio_ctrl |= 0x80;
- byte1 = dcstable[txcode & 0x7fff].b1;
- mx828_command(rad,n, MX828_DCS1, &byte1, &byte2 );
- byte1 = dcstable[txcode & 0x7fff].b2;
- mx828_command(rad,n, MX828_DCS2, &byte1, &byte2 );
- byte1 = dcstable[txcode & 0x7fff].b3;
- mx828_command(rad,n, MX828_DCS3, &byte1, &byte2 );
- }
- if (cttx)
- {
- saudio_ctrl |= 0x80;
- byte1 = cttable_tx[txcode].b1;
- byte2 = cttable_tx[txcode].b2;
- mx828_command(rad,n, MX828_TX_TONE, &byte1, &byte2 );
- }
- if (dcsrx)
- {
- saudio_setup |= 1;
- saudio_ctrl |= 0x41;
- byte1 = dcstable[rad->rxcode[n][0]].b1;
- mx828_command(rad,n, MX828_DCS1, &byte1, &byte2 );
- byte1 = dcstable[rad->rxcode[n][0]].b2;
- mx828_command(rad,n, MX828_DCS2, &byte1, &byte2 );
- byte1 = dcstable[rad->rxcode[n][0]].b3;
- mx828_command(rad,n, MX828_DCS3, &byte1, &byte2 );
- }
- if (ctrx)
- {
- saudio_setup |= 0x80;
- saudio_ctrl |= 0x60;
+ byte1 = rad->encdec.saudio_setup[rad->encdec.chan];
+ mx828_command(rad,rad->encdec.chan, MX828_SAUDIO_SETUP, &byte1, &byte2 );
+ rad->encdec.state = 9;
+ break;
+ case 9:
+ byte1 = rad->encdec.saudio_ctrl[rad->encdec.chan];
+ mx828_command(rad,rad->encdec.chan, MX828_SAUDIO_CTRL, &byte1, &byte2 );
+ rad->encdec.state = 10;
+ break;
+ case 10:
+ rad->encdec.chan = 0;
+ rad->encdec.state = 0;
+ break;
}
- byte1 = saudio_setup;
- mx828_command(rad,n, MX828_SAUDIO_SETUP, &byte1, &byte2 );
- byte1 = saudio_ctrl;
- mx828_command(rad,n, MX828_SAUDIO_CTRL, &byte1, &byte2 );
- return;
}
static inline void pciradio_transmitprep(struct pciradio *rad, unsigned char ints)
@@ -767,10 +725,15 @@ static void pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (ints & 0x0f) {
rad->intcount++;
x = rad->intcount % rad->nchans;
- mx828_command(rad, x, MX828_SAUDIO_STATUS, &byte1, &byte2);
+ /* freeze */
+ __pciradio_setcreg(rad,0,rad->mx828_addr | 4);
+ /* read SAUDIO_STATUS for the proper channel */
+ byte1 = __pciradio_getcreg(rad,x);
+ /* thaw */
+ __pciradio_setcreg(rad,0,rad->mx828_addr);
rad->saudio_status[x] = byte1;
/* get COR input */
- byte2 = __pciradio_getcreg(rad,0);
+ byte2 = __pciradio_getcreg(rad,9);
/* get bit for this channel */
gotcor = byte2 & (1 << x);
if (rad->radmode[x] & RADMODE_INVERTCOR) gotcor = !gotcor;
@@ -805,18 +768,22 @@ static void pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
} else if (gotslowctcss) rad->present_code[x] = (byte1 & RAD_CTCSSMASK) + 1;
if (rad->radmode[x] & RADMODE_EXTTONE)
{
- unsigned mask = 1 << (x + 4);
+ unsigned mask = 1 << (x + 4); /* they're on the UIOB's */
unsigned char byteuio;
+ /* set UIOB as input */
+ byteuio = __pciradio_getcreg(rad,0xe);
+ byteuio |= mask;
+ __pciradio_setcreg(rad,0xe,byteuio);
/* get UIO input */
- byteuio = __pciradio_getcreg(rad,1);
+ byteuio = __pciradio_getcreg(rad,8);
if (rad->radmode[x] & RADMODE_EXTINVERT)
gotctcss = gotslowctcss = ((byteuio & mask) == 0);
else
gotctcss = gotslowctcss = ((byteuio & mask) != 0);
}
rad->gotct[x] = gotslowctcss;
- if (rad->radmode[x] & RADMODE_IGNORECT)
+ if ((rad->radmode[x] & RADMODE_IGNORECT) || (!ctcss))
{
gotctcss = 1;
gotslowctcss = 1;
@@ -830,9 +797,10 @@ static void pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
rad->gotrx[x] = gotrx;
if (rad->present_code[x] != rad->last_code[x])
{
- _set_encdec(rad,x);
+ rad->encdec.req[x] = 1;
rad->last_code[x] = rad->present_code[x];
}
+ _do_encdec(rad,x);
for(x = 0; x < rad->nchans; x++)
{
unsigned char mask = 1 << x;
@@ -842,22 +810,22 @@ static void pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (rad->gottx[x])
{
rad->bursttimer[x] = 0;
- rad->p1save |= mask;
- __pciradio_setcreg(rad, 1, rad->p1save);
+ rad->pasave |= mask;
+ __pciradio_setcreg(rad, 0xa, rad->pasave);
}
else
{
if (!rad->bursttime[x])
{
- rad->p1save &= ~mask;
- __pciradio_setcreg(rad, 1, rad->p1save);
+ rad->pasave &= ~mask;
+ __pciradio_setcreg(rad, 0xa, rad->pasave);
}
else
{
rad->bursttimer[x] = rad->bursttime[x];
}
}
- _set_encdec(rad,x);
+ rad->encdec.req[x] = 1;
rad->lasttx[x] = rad->gottx[x];
}
if (rad->bursttimer[x])
@@ -867,8 +835,8 @@ static void pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char mask = 1 << x;
- rad->p1save &= ~mask;
- __pciradio_setcreg(rad, 1, rad->p1save);
+ rad->pasave &= ~mask;
+ __pciradio_setcreg(rad, 0xa, rad->pasave);
}
}
@@ -881,9 +849,9 @@ static void pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned char mask;
mask = 1 << (x + 4);
- rad->p1save &= ~mask;
- if (gotctcss) rad->p1save |= mask;
- __pciradio_setcreg(rad, 1, rad->p1save);
+ rad->pasave &= ~mask;
+ if (gotctcss) rad->pasave |= mask;
+ __pciradio_setcreg(rad, 0xa, rad->pasave);
if (rad->gotrx[x] != rad->gotrx1[x])
{
@@ -901,7 +869,7 @@ static void pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (debug) printk("Chan %d lost rx\n",x + 1);
zt_qevent_lock(&rad->chans[x], ZT_EVENT_ONHOOK);
}
- _set_encdec(rad,x);
+ rad->encdec.req[x] = 1;
}
rad->gotrx1[x] = rad->gotrx[x];
}
@@ -920,13 +888,14 @@ static int pciradio_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long
{
int i,mycode;
unsigned long flags;
- unsigned char byte1,byte2;
+ unsigned char byte1,byte2,mask;
union {
struct zt_radio_stat s;
struct zt_radio_param p;
} stack;
struct pciradio *rad = chan->pvt;
+ DECLARE_WAIT_QUEUE_HEAD(mywait);
switch (cmd) {
case ZT_RADIO_GETPARAM:
@@ -997,6 +966,21 @@ static int pciradio_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long
case ZT_RADPAR_BURSTTIME:
stack.p.data = rad->bursttime[chan->chanpos - 1];
break;
+ case ZT_RADPAR_UIODATA:
+ stack.p.data = 0;
+ byte1 = __pciradio_getcreg(rad,8);
+ if (byte1 & (1 << (chan->chanpos - 1))) stack.p.data |= 1;
+ if (byte1 & (1 << (chan->chanpos + 3))) stack.p.data |= 2;
+ break;
+ case ZT_RADPAR_UIOMODE:
+ stack.p.data = 0;
+ byte1 = __pciradio_getcreg(rad,0xe);
+ if (byte1 & (1 << (chan->chanpos - 1))) stack.p.data |= 1;
+ if (byte1 & (1 << (chan->chanpos + 3))) stack.p.data |= 2;
+ break;
+ case ZT_RADPAR_REMMODE:
+ stack.p.data = rad->remmode[chan->chanpos - 1];
+ break;
default:
spin_unlock_irqrestore(&rad->lock,flags);
return -EINVAL;
@@ -1038,6 +1022,8 @@ static int pciradio_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long
return -EINVAL;
}
rad->corthresh[chan->chanpos - 1] = stack.p.data;
+ byte1 = 0xc0 | (rad->corthresh[chan->chanpos - 1] << 2);
+ mx828_command_wait(rad,chan->chanpos - 1, MX828_GEN_CTRL, &byte1, &byte2);
break;
case ZT_RADPAR_EXTRXTONE:
if (stack.p.data)
@@ -1061,11 +1047,11 @@ static int pciradio_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long
{
/* set to no encode/decode */
byte1 = 0;
- mx828_command(rad,chan->chanpos - 1, MX828_SAUDIO_CTRL, &byte1, &byte2 );
+ mx828_command_wait(rad,chan->chanpos - 1, MX828_SAUDIO_CTRL, &byte1, &byte2 );
/* set rx tone to none */
byte1 = i << 4;
byte2 = 0;
- mx828_command(rad,chan->chanpos - 1, MX828_RX_TONE, &byte1, &byte2 );
+ mx828_command_wait(rad,chan->chanpos - 1, MX828_RX_TONE, &byte1, &byte2 );
}
case ZT_RADPAR_RXTONE:
if (!stack.p.index) /* if RX DCS mode */
@@ -1080,7 +1066,7 @@ static int pciradio_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long
return -EINVAL;
}
rad->rxcode[chan->chanpos - 1][0] = mycode;
- _set_encdec(rad,chan->chanpos - 1);
+ rad->encdec.req[chan->chanpos - 1] = 1;
break;
}
if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) {
@@ -1095,10 +1081,10 @@ static int pciradio_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long
rad->rxcode[chan->chanpos - 1][stack.p.index] = mycode;
byte1 = cttable_rx[mycode].b1 | ((stack.p.index - 1) << 4);
byte2 = cttable_rx[mycode].b2;
- mx828_command(rad,chan->chanpos - 1, MX828_RX_TONE, &byte1, &byte2 );
+ mx828_command_wait(rad,chan->chanpos - 1, MX828_RX_TONE, &byte1, &byte2 );
/* zot out DCS one if there */
rad->rxcode[chan->chanpos - 1][0] = 0;
- _set_encdec(rad,chan->chanpos - 1);
+ rad->encdec.req[chan->chanpos - 1] = 1;
break;
case ZT_RADPAR_RXTONECLASS:
if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) {
@@ -1122,7 +1108,7 @@ static int pciradio_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long
}
if (stack.p.data & 0x8000) mycode |= 0x8000;
rad->txcode[chan->chanpos - 1][stack.p.index] = mycode;
- _set_encdec(rad,chan->chanpos - 1);
+ rad->encdec.req[chan->chanpos - 1] = 1;
break;
case ZT_RADPAR_DEBOUNCETIME:
rad->debouncetime[chan->chanpos - 1] = stack.p.data;
@@ -1130,6 +1116,53 @@ static int pciradio_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long
case ZT_RADPAR_BURSTTIME:
rad->bursttime[chan->chanpos - 1] = stack.p.data;
break;
+ case ZT_RADPAR_UIODATA:
+ spin_lock_irqsave(&rad->lock,flags);
+ byte1 = __pciradio_getcreg(rad,8);
+ byte1 &= ~(1 << (chan->chanpos - 1));
+ byte1 &= ~(1 << (chan->chanpos + 3));
+ if (stack.p.data & 1) byte1 |= (1 << (chan->chanpos - 1));
+ if (stack.p.data & 2) byte1 |= (1 << (chan->chanpos + 3));
+ __pciradio_setcreg(rad,8,byte1);
+ spin_unlock_irqrestore(&rad->lock,flags);
+ break;
+ case ZT_RADPAR_UIOMODE:
+ spin_lock_irqsave(&rad->lock,flags);
+ byte1 = __pciradio_getcreg(rad,0xe);
+ byte1 &= ~(1 << (chan->chanpos - 1));
+ byte1 &= ~(1 << (chan->chanpos + 3));
+ if (stack.p.data & 1) byte1 |= (1 << (chan->chanpos - 1));
+ if (stack.p.data & 2) byte1 |= (1 << (chan->chanpos + 3));
+ __pciradio_setcreg(rad,0xe,byte1);
+ spin_unlock_irqrestore(&rad->lock,flags);
+ break;
+ case ZT_RADPAR_REMMODE:
+ rad->remmode[chan->chanpos - 1] = stack.p.data;
+ break;
+ case ZT_RADPAR_REMCOMMAND:
+ i = 0;
+ /* 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;
+ if (rad->remmode[chan->chanpos - 1])
+ {
+ rbi_out(rad,chan->chanpos - 1,(unsigned char *)&stack.p.data);
+ }
+ break;
default:
spin_unlock_irqrestore(&rad->lock,flags);
return -EINVAL;
@@ -1243,7 +1276,7 @@ static int pciradio_hooksig(struct zt_chan *chan, zt_txsig_t txsig)
break;
}
if (debug)
- printk("pciradio: Setting Radio hook state to %d\n", txsig);
+ printk("pciradio: Setting Radio hook state to %d on chan %d\n", txsig, chan->chanpos);
return 0;
}
@@ -1280,6 +1313,13 @@ static int pciradio_initialize(struct pciradio *rad)
return 0;
}
+static void wait_just_a_bit(int foo)
+{
+ long newjiffies;
+ newjiffies = jiffies + foo;
+ while(jiffies < newjiffies);
+}
+
static int pciradio_hardware_init(struct pciradio *rad)
{
unsigned char byte1,byte2;
@@ -1367,11 +1407,16 @@ unsigned long endjif;
printk("Xilinx Chip successfully loaded, configured and started!!\n");
- rad->p0save = 0xf0;
- __pciradio_setcreg(rad,0,rad->p0save);
+ rad->pasave = 0;
+ __pciradio_setcreg(rad,0xa,rad->pasave);
+
+ __pciradio_setcreg(rad,8,0);
+ __pciradio_setcreg(rad,9,0x55);
+ __pciradio_setcreg(rad,0xe,0);
+ rad->pfsave = 0;
+ __pciradio_setcreg(rad,0xf,rad->pfsave);
+
- rad->p1save = 0;
- __pciradio_setcreg(rad,1,rad->p1save);
/* Back to normal, with automatic DMA wrap around */
outb(0x30 | 0x01, rad->ioaddr + RAD_CNTL);
@@ -1402,20 +1447,20 @@ unsigned long endjif;
for(x = 0; x < rad->nchans; x++)
{
- mx828_command(rad,x, MX828_GEN_RESET, &byte1, &byte2 );
+ mx828_command_wait(rad,x, MX828_GEN_RESET, &byte1, &byte2 );
byte1 = 0x3f;
byte2 = 0x3f;
- mx828_command(rad,x, MX828_AUD_CTRL, &byte1, &byte2 );
+ mx828_command_wait(rad,x, MX828_AUD_CTRL, &byte1, &byte2 );
byte1 = 0;
- mx828_command(rad,x, MX828_SAUDIO_SETUP, &byte1, &byte2 );
+ mx828_command_wait(rad,x, MX828_SAUDIO_SETUP, &byte1, &byte2 );
byte1 = 0;
- mx828_command(rad,x, MX828_SAUDIO_CTRL, &byte1, &byte2 );
- byte1 = 0xc0;
- mx828_command(rad,x, MX828_GEN_CTRL, &byte1, &byte2);
+ mx828_command_wait(rad,x, MX828_SAUDIO_CTRL, &byte1, &byte2 );
+ byte1 = 0xc8; /* default COR thresh is 2 */
+ mx828_command_wait(rad,x, MX828_GEN_CTRL, &byte1, &byte2);
+ rad->corthresh[x] = 2;
}
-
return 0;
}
@@ -1489,6 +1534,7 @@ static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_de
ifaces[x] = rad;
memset(rad, 0, sizeof(struct pciradio));
spin_lock_init(&rad->lock);
+ spin_lock_init(&rad->rbilock);
rad->nchans = 4;
rad->ioaddr = pci_resource_start(pdev, 0);
rad->dev = pdev;