285 lines
7.1 KiB
C
285 lines
7.1 KiB
C
inline static Byte
|
|
InISAC(struct _dumb * dumb, char offset) {
|
|
if(offset >= 0x20)
|
|
return ByteIn(dumb->info.ioaddr+0x1400-0x20+offset);
|
|
else
|
|
return ByteIn(dumb->info.ioaddr+0x1000+offset); /* ?? */
|
|
}
|
|
inline static void
|
|
OutISAC(struct _dumb * dumb, char offset, Byte data) {
|
|
if(offset >= 0x20)
|
|
ByteOut(dumb->info.ioaddr+0x1400-0x20+offset,data);
|
|
else
|
|
ByteOut(dumb->info.ioaddr+0x1000+offset,data); /* ?? */
|
|
}
|
|
|
|
inline static Byte
|
|
InHSCX(struct _dumb * dumb, u_char hscx, char offset) {
|
|
if(hscx&1) {
|
|
if(offset >= 0x20)
|
|
return ByteIn(dumb->info.ioaddr+0x400-0x20+offset);
|
|
else
|
|
return ByteIn(dumb->info.ioaddr+0x000+offset);
|
|
} else {
|
|
if(offset >= 0x20)
|
|
return ByteIn(dumb->info.ioaddr+0xC00-0x20+offset);
|
|
else
|
|
return ByteIn(dumb->info.ioaddr+0x800+offset);
|
|
}
|
|
}
|
|
|
|
inline static void
|
|
OutHSCX(struct _dumb * dumb, u_char hscx, char offset, Byte data) {
|
|
if(hscx&1) {
|
|
if(offset >= 0x20)
|
|
ByteOut(dumb->info.ioaddr+0x400-0x20+offset, data);
|
|
else
|
|
ByteOut(dumb->info.ioaddr+0x000+offset, data);
|
|
} else {
|
|
if(offset >= 0x20)
|
|
ByteOut(dumb->info.ioaddr+0xC00-0x20+offset, data);
|
|
else
|
|
ByteOut(dumb->info.ioaddr+0x800+offset, data);
|
|
}
|
|
}
|
|
|
|
inline static Byte
|
|
Slot(struct _dumb * dumb, u_char hscx) {
|
|
printf(" Slot %d: ",hscx);
|
|
return (hscx&1) ? 0x2F : 0x03;
|
|
}
|
|
|
|
static int
|
|
Init(struct _dumb * dumb) {
|
|
int timout;
|
|
long flags;
|
|
Byte foo;
|
|
unsigned int step = 0;
|
|
|
|
if(dumb->info.ioaddr == 0)
|
|
return -EINVAL;
|
|
dumb->numHSCX = 2;
|
|
save_flags(flags);
|
|
sti();
|
|
timout = jiffies+1;
|
|
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x00); while(jiffies <= timout) ; timout = jiffies;
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x10); while(jiffies <= timout) ; timout = jiffies;
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x00); while(jiffies <= timout) ; timout = jiffies;
|
|
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x00); while(jiffies <= timout) ; timout = jiffies;
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x01); while(jiffies <= timout) ; timout = jiffies;
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x00); while(jiffies <= timout) ;
|
|
|
|
timout = jiffies+(HZ/20);
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x01);
|
|
while(jiffies <= timout) ;
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x00);
|
|
timout = jiffies+(HZ/20);
|
|
while(jiffies <= timout) ;
|
|
restore_flags(flags);
|
|
|
|
/* 1 2 3 4 5 6 7 8 9 */
|
|
/* 17 07 13 03 17 07 13 03 */
|
|
while(++step) {
|
|
ByteOut(dumb->info.ioaddr+0x1800,(step&1)?0x10:0x00);
|
|
switch((foo = ByteIn(dumb->info.ioaddr+0x1800)) & 0xFE) {
|
|
case 0x06:
|
|
if(step & 1)
|
|
goto def;
|
|
if (step == 4)
|
|
step += 2;
|
|
break;
|
|
case 0x16:
|
|
if (!(step & 1))
|
|
goto def;
|
|
if (step == 3)
|
|
step += 2;
|
|
break;
|
|
case 0x02:
|
|
if(step & 1)
|
|
goto def;
|
|
if (step == 2)
|
|
step += 2;
|
|
else if (step >= 10)
|
|
goto Exit;
|
|
break;
|
|
case 0x12:
|
|
if (!(step & 1))
|
|
goto def;
|
|
if (step == 1)
|
|
step += 2;
|
|
break;
|
|
default:
|
|
def:
|
|
printf(" AIRQR %02x, step %d ",foo,step);
|
|
return -EIO;
|
|
}
|
|
}
|
|
Exit:
|
|
|
|
save_flags(flags);
|
|
timout = jiffies+(HZ/20)+1;
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x01);
|
|
sti();
|
|
while(jiffies <= timout) ;
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x00);
|
|
timout = jiffies+(HZ/20)+1;
|
|
while(jiffies <= timout) ;
|
|
restore_flags(flags);
|
|
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x04);
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x08);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
InitISAC(struct _dumb * dumb)
|
|
{
|
|
dumb->chan[0].mode = M_OFF;
|
|
dumb->chan[0].listen = 0;
|
|
ByteOutISAC(dumb, ADF2, 0x80);
|
|
ByteOutISAC(dumb, SPCR, 0x00);
|
|
ByteOutISAC(dumb, ADF1, 0x00);
|
|
ByteOutISAC(dumb, STCR, 0x70);
|
|
ByteOutISAC(dumb, TIMR, 0xFF);
|
|
ByteOutISAC(dumb, MASK, 0x00);
|
|
ByteOutISAC(dumb, MODE, 0xC9);
|
|
|
|
ByteOutISAC(dumb, SQXR, 0x0F);
|
|
ByteOutISAC(dumb, CIX0, 0x03);
|
|
}
|
|
|
|
static void
|
|
InitHSCX_(struct _dumb * dumb, u_char hscx)
|
|
{
|
|
ByteOutHSCX(dumb,hscx,TSAX, Slot(dumb,hscx));
|
|
ByteOutHSCX(dumb,hscx,TSAR, Slot(dumb,hscx));
|
|
ByteOutHSCX(dumb,hscx,XCCR, 7);
|
|
ByteOutHSCX(dumb,hscx,RCCR, 7);
|
|
ByteOutHSCX(dumb,hscx,MODE, 0x06);
|
|
ByteOutHSCX(dumb,hscx,CCR1, 0x85); /* 0x85 */
|
|
ByteOutHSCX(dumb,hscx,CCR2, 0x32); /* 0x38 */
|
|
ByteOutHSCX(dumb,hscx,XAD1, 0x01);
|
|
ByteOutHSCX(dumb,hscx,XAD2, 0x03);
|
|
ByteOutHSCX(dumb,hscx,RAL1, 0x03);
|
|
ByteOutHSCX(dumb,hscx,RAL2, 0x01);
|
|
ByteOutHSCX(dumb,hscx,RAH1, 0);
|
|
ByteOutHSCX(dumb,hscx,RAH2, 0);
|
|
#if 0
|
|
ByteOutHSCX(dumb,hscx,TIMR, 0x70);
|
|
#endif
|
|
ByteOutHSCX(dumb,hscx,MASK, 0x00);
|
|
}
|
|
|
|
static int
|
|
HSCX_mode(struct _dumb * dumb, u_char hscx, Byte mode, Byte listen)
|
|
{
|
|
unsigned long ms = SetSPL(dumb->info.ipl);
|
|
if(dumb->chan[hscx].m_in != NULL) {
|
|
freemsg(dumb->chan[hscx].m_in);
|
|
dumb->chan[hscx].m_in = dumb->chan[hscx].m_in_run = NULL;
|
|
}
|
|
if(dumb->chan[hscx].m_out != NULL) {
|
|
freemsg(dumb->chan[hscx].m_out);
|
|
dumb->chan[hscx].m_out = dumb->chan[hscx].m_out_run = NULL;
|
|
}
|
|
|
|
ByteOutHSCX(dumb,hscx,CCR2, 0x32);
|
|
ByteOutHSCX(dumb,hscx,TSAX, Slot(dumb,hscx));
|
|
ByteOutHSCX(dumb,hscx,TSAR, Slot(dumb,hscx));
|
|
ByteOutHSCX(dumb,hscx,XCCR, 7);
|
|
ByteOutHSCX(dumb,hscx,RCCR, 7);
|
|
ByteOutHSCX(dumb,hscx,CCR1, 0x05);
|
|
|
|
if (mode > M_OFF && !(hscx & 1) && (dumb->chan[hscx-1].mode >= M_HDLC_16))
|
|
return -EIO;
|
|
|
|
switch(mode) {
|
|
case M_OFF:
|
|
case M_STANDBY:
|
|
ByteOutHSCX(dumb,hscx,MASK, 0x00);
|
|
ByteOutHSCX(dumb,hscx,MODE, 0x96);
|
|
ByteOutHSCX(dumb,hscx,XAD1, 0xFF);
|
|
ByteOutHSCX(dumb,hscx,XAD2, 0xFF);
|
|
ByteOutHSCX(dumb,hscx,RAH2, 0xFF);
|
|
ByteOutHSCX(dumb,hscx,CMDR, 0x41);
|
|
dumb->chan[hscx].mode = mode;
|
|
dumb->chan[hscx].locked = 0;
|
|
dumb->chan[hscx].listen = listen;
|
|
break;
|
|
case M_TRANS_HDLC:
|
|
case M_TRANS_ALAW:
|
|
case M_TRANS_V110:
|
|
case M_TRANSPARENT:
|
|
ByteOutHSCX(dumb,hscx,MODE, 0xE6);
|
|
ByteOutHSCX(dumb,hscx,CMDR, 0x41);
|
|
ByteOutHSCX(dumb,hscx,MASK, 0x00);
|
|
dumb->chan[hscx].mode = mode;
|
|
dumb->chan[hscx].locked = 0;
|
|
dumb->chan[hscx].listen = listen;
|
|
break;
|
|
case M_HDLC_16:
|
|
if(!(hscx & 1))
|
|
return -EIO;
|
|
if(dumb->chan[hscx+1].mode != M_OFF)
|
|
return -ENXIO;
|
|
ByteOutHSCX(dumb,hscx,XCCR, 15);
|
|
ByteOutHSCX(dumb,hscx,RCCR, 15);
|
|
goto HDLC_common;
|
|
case M_HDLC_7H:
|
|
ByteOutHSCX(dumb,hscx,CCR2, 0x02);
|
|
ByteOutHSCX(dumb,hscx,TSAX, Slot(dumb,hscx)+1);
|
|
ByteOutHSCX(dumb,hscx,TSAR, Slot(dumb,hscx)+1);
|
|
/* FALL THRU */
|
|
case M_HDLC_7L:
|
|
ByteOutHSCX(dumb,hscx,XCCR, 6);
|
|
ByteOutHSCX(dumb,hscx,RCCR, 6);
|
|
/* FALL THRU */
|
|
case M_HDLC:
|
|
HDLC_common:
|
|
ByteOutHSCX(dumb,hscx,MODE, 0x8E);
|
|
ByteOutHSCX(dumb,hscx,CMDR, 0x41);
|
|
ByteOutHSCX(dumb,hscx,MASK, 0x00);
|
|
dumb->chan[hscx].mode = mode;
|
|
dumb->chan[hscx].locked = 0;
|
|
dumb->chan[hscx].listen = listen;
|
|
break;
|
|
default:
|
|
printf("HSCX unknown mode %x\n",mode);
|
|
}
|
|
|
|
splx(ms);
|
|
return -EIO;
|
|
}
|
|
|
|
inline static void
|
|
PostIRQ(struct _dumb * dumb)
|
|
{
|
|
Byte foo = ByteIn(dumb->info.ioaddr+0x1800);
|
|
unsigned int doagain=0;
|
|
do {
|
|
switch(foo) {
|
|
case 0x07: return;
|
|
case 0x03:
|
|
if(doagain & 1) {
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x00);
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x10);
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x00);
|
|
} else {
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x04);
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x08);
|
|
ByteOut(dumb->info.ioaddr+0x1800,0x00);
|
|
}
|
|
printf(".");
|
|
if(doagain < 10)
|
|
break;
|
|
/* FALL THRU */
|
|
default:
|
|
printf (" AIRQ %d ISAC %d HSCX %x %x: %02x ",doagain,ByteInISAC(dumb,ISTA),ByteInHSCX(dumb,1,ISTA),ByteInHSCX(dumb,2,ISTA),foo);
|
|
return;
|
|
}
|
|
} while(++doagain); /* always true */
|
|
}
|
|
|