/*
	PRO_ASYN.C     Asynchronous communication program     

   Test Program for IAB212 BL1300/PROTOCOL SWITCH      09-16-91       

   Test SCC Z85C30 interrupt to z180 INT1 on asynchronous transmission
   Test Z180 DMA memory to SCC Z85C30 transfer.
    
   There is no hardware reset designed for the BL1300/Protocol Switch, so
   always use a software reset at the beginning of a user program.

   The SCC generates an interrupt to the SmartBlock /INT1 pin. Before using
   the SCC in a interrupt driven operation the user must enable INT1 from the
   CPU ITC register and redirect the vector table using the following function
   call and macro.
            outport(ITC,0x02|inport(ITC));
            #INT_VEC INT1_VEC sccint

   There is no interrupt acknowledge hardware designed for BL1300/Protocol Switch.
   Interrupt operation is performed without interrupt acknowledge to the
   SmartBlock INT1. In the PRO_ASYN.C interrupt service routine, RR2 is read
   from channel B to get the interrupt vector and interrupt status.

      The vector is not latched so that subsequent reads might produce a
   different vector if another interrupt occurs. The interrupt service routine
   must decode the IP and clear the condition. When an IP is cleared, RR2 can
   be read again, allowing interrupt service routine to clear all IP bits within
   one interrupt to the CPU.
   
   	Do not use x1 clk for async communication!
   	
      Connections:
      P41=P42  P46=P48  P31=P32  P36=P38
      
	   Pushbutton Hardware Reset first
*/   

/*   int asyn_init_scc0   (char mode, char baud);      initialize */
/*   int asyn_send_scc0   (char *buf, char * count);   interrupt send */
/*   int asyn_rec_scc0    (char *buf, char *count);    interrupt receive */
/*   int asyn_kill_scc0   ();                          abort all */
/*   int dma_mem_scc0  (long mem, int size);          dma send   */
/*   int dma_scc0_mem  (long mem, int size);          dma receive   */
/*   int nodma_req_scc0();                            disable DREQ   */
/*   int asyn_init_scc1   (char mode, char baud);      initialize */
/*   int asyn_send_scc1   (char *buf, char * count);   interrupt send */
/*   int asyn_rec_scc1    (char *buf, char *count);    interrupt receive */
/*   int asyn_kill_scc1   ();                          abort all */
/*   int dma_mem_scc1  (long mem, int size);          dma send   */
/*   int dma_scc1_mem  (long mem, int size);          dma receive   */
/*   int nodma_req_scc1();                            disable DREQ   */
/*    int scc_rst( int ch );                          reset scc0/1   */

#define PIO1A_VEC 0x12  /* compatible with LG PIO */
#define PIO1B_VEC 0x14
#define PIO2A_VEC 0x32  /* New vector for PIO2 */
#define PIO2B_VEC 0x34
#define PIO1DA 0x80
#define PIO1DB 0x81
#define PIO1CA 0x82
#define PIO1CB 0x83
#define PIO2DA 0x90
#define PIO2DB 0x91
#define PIO2CA 0x92
#define PIO2CB 0x93
/* the following are already defined in scc232.lib
#define SCCCB  0xA0
#define SCCCA  0xA1
#define SCCDB  0xA2
#define SCCDA  0xA3
#define EN12 0xB0
#define EN34 0xC0
#define LD1 0xD0
*/
#define SAR0 0x20
#define DAR0 0x23
#define BCR0 0x26
#define MAR1 0x28
#define IAR1 0x2B
#define BCR1 0x2E

extern int CLOCKSPEED;
static char flag,vec,sccatx,sccarx,sccbtx,sccbrx;
char cc,rcc;
int err,dma0,dma1,size,baud,ch,mode,tt;
static int i,j,k,l;
char buf[]="This message sent over serial line!";
char rbuf[1000];
long buf_phyadr,rbuf_phyadr;
char *scc0_send_count;
char *scc0_send_buf;
char *scc0_rec_count;
char *scc0_rec_buf;
char scc0_wreg0; /* keep state of SCC0 registers   */
char scc0_wreg1;
char scc0_wreg2;
char scc0_wreg3;
char scc0_wreg4;
char scc0_wreg5;
char scc0_wreg6;
char scc0_wreg7;
char scc0_wreg8;
char scc0_wreg9;
char scc0_wreg10;
char scc0_wreg11;
char scc0_wreg12;
char scc0_wreg13;
char scc0_wreg14;
char scc0_wreg15;
char *scc1_send_count;
char *scc1_send_buf;
char *scc1_rec_count;
char *scc1_rec_buf;
char scc1_wreg0; /* keep state of SCC1 registers   */
char scc1_wreg1;
char scc1_wreg2;
char scc1_wreg3;
char scc1_wreg4;
char scc1_wreg5;
char scc1_wreg6;
char scc1_wreg7;
char scc1_wreg8;
char scc1_wreg9;
char scc1_wreg10;
char scc1_wreg11;
char scc1_wreg12;
char scc1_wreg13;
char scc1_wreg14;
char scc1_wreg15;

main()
{

/* Try interrupt driven scc0 send out, interrupt driven scc0 receive  */
/* FOR RS232, Port 4 pin 6 connects to Port 4 pin 8  */
	hitwd();
   ch=2;
   scc_rst(ch);  /* always first reset ch a and ch b by software  */ 
   
   /* Test RTS/CTS P41=P42, DTR/DCD P21=P22  */
   outport(SCCCA,0x0f); /* must disable Ext Int.   */
   outport(SCCCA,0x00);
   SET(&scc0_wreg5,1); /* /RTS */
   SET(&scc0_wreg5,7); /* /DTR */
   outport(SCCCA,0x05);
   outport(SCCCA,scc0_wreg5);
   if(!IBIT(SCCCA,5)){  printf("RTS=CTS?\n");   }
   if(!IBIT(SCCCA,3)){  printf("DTR=DCD?\n");   }
   RES(&scc0_wreg5,1); /* RTS */
   RES(&scc0_wreg5,7); /* DTR */
   outport(SCCCA,0x05);
   outport(SCCCA,scc0_wreg5);
   if(IBIT(SCCCA,5)){  printf("RTS=CTS?\n");   }
   if(IBIT(SCCCA,3)){  printf("DTR=DCD?\n");   }
   
   baud=8;        /* baud rate in unit of 1200, so 9600=1200*8 */
   mode=0x14;   /* 00010100, x16 sys clk, 8 bits, 1 stop, no DMA  */
   asyn_init_scc0(mode,baud);     /* initial ch0  */
   rbuf[0]=0;           /* in case print null string */
   cc=sizeof(buf);
   rcc=cc;
   outport(ITC,0x02|inport(ITC)); /* enable INT1 */
   asyn_rec_scc0(rbuf,&rcc);
   asyn_send_scc0(buf,&cc);

   tt=0;
   while(rcc && --tt) hitwd();
   if(!tt) printf("Timed out - port not loop conncted?\n");
   printf("SCC0 rbuf= %s\n",rbuf);
   outport(ITC,0xfd&inport(ITC)); /* disable INT1 */

 /* try use xtal clock  */
   baud=8;        /* baud rate in unit of 1200, so 9600=1200*8 */
   mode=0x54;   /* 01010100, x16 xtal clk, 8 bits, 1 stop, no DMA  */
   asyn_init_scc0(mode,baud);     /* initial ch0  */
   rbuf[0]=0;           /* in case print null string */
   cc=sizeof(buf);
   rcc=cc;
   outport(ITC,0x02|inport(ITC)); /* enable INT1 */
   asyn_rec_scc0(rbuf,&rcc);
   asyn_send_scc0(buf,&cc);

   tt=0;
   while(rcc && --tt) hitwd();
   if(!tt) printf("Timed out - port not loop conncted?\n");
   printf("SCC0 xtal rbuf= %s\n",rbuf);
   outport(ITC,0xfd&inport(ITC)); /* disable INT1 */

/* Try interrupt driven scc1 send out, interrupt driven scc1 receive  */
/* Port 3 pin 8 connects to Port 3 pin 6  */

   /* Test RTS/CTS P31=P32  */
   outport(SCCCB,0x0f); /* must disable Ext Int.   */
   outport(SCCCB,0x00);
   SET(&scc1_wreg5,1); /* /RTS */
   outport(SCCCB,0x05);
   outport(SCCCB,scc1_wreg5);
   if(!IBIT(SCCCB,5)){  printf("RTS=CTS?\n");   }
   RES(&scc1_wreg5,1); /* RTS */
   outport(SCCCB,0x05);
   outport(SCCCB,scc1_wreg5);
   if(IBIT(SCCCB,5)){  printf("RTS=CTS?\n");   }
   
   ch=2;
   scc_rst(ch);  /* always first reset ch a and ch b by software  */ 
   baud=8;        /* baud rate in unit of 1200, so 9600=1200*8 */
   mode=0x14;   /* 00010100, x16 sysclk, 8 bits, 1 stop, no DMA  */
   asyn_init_scc1(mode,baud);     /* initial ch1  */
   rbuf[0]=0;           /* in case print null string */
   cc=sizeof(buf);
   rcc=cc;
   outport(ITC,0x02|inport(ITC)); /* enable INT1 */
   asyn_rec_scc1(rbuf,&rcc);
   asyn_send_scc1(buf,&cc);

   tt=0;
   while(rcc && --tt) hitwd();
   if(!tt) printf("Timed out - port not loop conncted?\n");
   printf("SCC1 rbuf= %s\n",rbuf);
   outport(ITC,0xfd&inport(ITC)); /* disable INT1 */

/* Try DMA memory to I/O   */
   ch=2;
   scc_rst(ch);  /* always first reset ch a and ch b by software  */ 

   ch=0;
   mode=0x14;   /* 00010100, x16 sysclk, 8 bits, 1 stop, no DMA  */
   baud=8;        /* baud rate in unit of 1200, so 9600=1200*8 */
   nodma_req_scc0();    /* disable dma request  */
   asyn_init_scc0(mode,baud);  /* initial ch0, DMA enable */
   buf_phyadr = phy_adr (buf); /* get physical address of buffer */
   size=sizeof(buf);
   dma_mem_scc0(buf_phyadr,size);  
   dma0=1;  
   while(dma0){
   		hitwd();
         printf("DMA0 transfer is in progress \n");
         if(!IBIT(DSTAT,6)){
                         printf("     DMA0 transfer is completed ! \n"); 
                        dma0=0;
                        nodma_req_scc0();    /* disable dma request  */
                           }
            }
   
   nodma_req_scc1();    /* disable dma request  */
   asyn_init_scc1(mode,baud);  /* initial ch1, DMA enable */
   buf_phyadr = phy_adr (buf); /* get physical address of buffer */
   size=sizeof(buf);
   dma_mem_scc1(buf_phyadr,size); 

   dma1=1;  
   while(dma1){
   		hitwd();
         printf("DMA1 transfer is in progress \n");
         if(!IBIT(DSTAT,7)){
               printf("     DMA1 transfer is completed ! \n"); 
               dma1=0;
               nodma_req_scc1();    /* disable dma request  */
               }
            }
   outport(ITC,0xfd&inport(ITC)); /* disable INT1 */

/* Try use scc0 interrupt driven send out, use scc0 DMA receive  */

   ch=2;
   scc_rst(ch);  /* always first reset ch a and ch b by software  */ 
   baud=8;        /* baud rate in unit of 1200, so 9600=1200*8 */
   mode=0x14;   /* 00010100, x16 sysclk, 8 bits, 1 stop, no DMA  */
   asyn_init_scc0(mode,baud);     /* initial ch0  */
   rbuf[0]=0;           /* in case print null string */
   size=sizeof(buf);
   cc=size;
   rbuf_phyadr = phy_adr (rbuf); /* get physical address of buffer */
   dma_scc0_mem (rbuf_phyadr,size); /* ready to receive  */
   outport(ITC,0x02|inport(ITC)); /* enable INT1 */
   asyn_send_scc0(buf,&cc);
   tt=0;
   while(cc && --tt) hitwd();
   if(!tt) printf("Timed out - port not loop conncted?\n");
   printf("SCC0 int. send SCC0 dma rec.= %s\n",rbuf);
   outport(ITC,0xfd&inport(ITC)); /* disable INT1 */
   nodma_req_scc0();


/* Try use scc1 interrupt driven send out, use scc1 DMA receive  */

   ch=2;
   scc_rst(ch);  /* always first reset ch a and ch b by software  */ 

   baud=8;        /* baud rate in unit of 1200, so 9600=1200*8 */
   mode=0x14;   /* 00010100, x16 sysclk, 8 bits, 1 stop, no DMA  */
   asyn_init_scc1(mode,baud);     /* initial ch1  */
   rbuf[0]=0;           /* in case print null string */
   size=sizeof(buf);
   cc=size;
   rbuf_phyadr = phy_adr (rbuf); /* get physical address of buffer */
   dma_scc1_mem(rbuf_phyadr,size);
   outport(ITC,0x02|inport(ITC)); /* enable INT1 */
   asyn_send_scc1(buf,&cc);
   tt=0;
   while(cc && --tt) hitwd();
   if(!tt) printf("Timed out - port not loop conncted?\n");
   printf("SCC1 int. send SCC1 dma rec.= %s\n",rbuf);
   outport(ITC,0xfd&inport(ITC)); /* disable INT1 */
   nodma_req_scc1();

return(0);
}

#INT_VEC INT1_VEC sccint
interrupt reti sccint()
{
   int noip;
   noip=1;
   while(noip){
   hitwd();
   outport(SCCCB,0x02); /* read CHB rr2 modified int. vector */
   vec = 0x0e & inport(SCCCB);     
   /* reset IUS, always last operation in an interrupt service routing */ 
   /* allow use internal daisy chain and lower priority int.  */      
/* vec=0x06 V3, V2, V1=011, if no interrupt pending   */
      switch(vec){


                     case 0x06:
                                 noip=0;
                                 break;

                     case 0x0c:  
                                 charx();
                                 break;
                     case 0x08:  
                                 chatx();
                                 break;
                     case 0x0a:
                                 chaex();
                                 break;
                     case 0x00:
                                 chbtx();
                                 break;
                     case 0x04:
                                 chbrx();
                                 break;
                     case 0x02:
                                 chbex();
                                 break;
                     case 0x0e:
                                 special();
                                 break;

                     default: printf("unknown int. vector= %x \n",vec);
                                 noip=0;
                  }
            }
   return;
}

/* interrupt service routines */

int chatx(){
      sccatx=1;
      if(! *scc0_send_count) { 
               sccatx=0;
               scc0_wreg5=scc0_wreg5 & 0x70; /* Tx disable */
               RES(&scc0_wreg1,1); /* Tx int. disable */
               outport(SCCCA,0x01); /* write reg. WR1  */
               outport(SCCCA,scc0_wreg1);
               outport(SCCCA,0x05); /* write reg. WR5  */
               outport(SCCCA,scc0_wreg5);
               outport(SCCCA,0xe8); /* reset Tx */
                              }
      else  {
        outport(SCCDA,*scc0_send_buf++); /* send next character */
                                          /* clear TX INT Pending */
         --*scc0_send_count;             /* dec count of characters */
            }
       /* reset highest IUS, allow lower-priority INTs */
     outport(SCCCA,0x38); 
   }

int chaex(){
      printf("CH A External/Status IP  vec= %x\n",vec);
     outport(SCCCB,0x38); 
           }
int charx(){
      int rr1;
      sccarx=1;
      *scc0_rec_buf++=inport(SCCDA); /* input character */
      if(! --*scc0_rec_count)   {  /* count down, if done disable */
               RES(&scc0_wreg3,0); /* Rx disable */
               RES(&scc0_wreg1,3); /* Rx int. disable */
               RES(&scc0_wreg1,4); /* Rx int. disable */
               outport(SCCCA,0x01); /* write reg. WR1  */
               outport(SCCCA,scc0_wreg1);
               outport(SCCCA,0x03); /* write reg. WR3  */
               outport(SCCCA,scc0_wreg3);
               outport(SCCCA,0x70); /* reset error, Rx CRC */
                              }
       /* reset highest IUS, allow lower-priority INTs */
     outport(SCCCA,0x38); 
    }

int chbtx(){
      sccbtx=1;
      if(! *scc1_send_count) { 
               sccbtx=0;
               scc1_wreg5=scc1_wreg5 & 0x70; /* Tx disable */
               RES(&scc1_wreg1,1); /* Tx int. disable */
               outport(SCCCB,0x01); /* write reg. WR1  */
               outport(SCCCB,scc1_wreg1);
               outport(SCCCB,0x05); /* write reg. WR5  */
               outport(SCCCB,scc1_wreg5);
               outport(SCCCB,0xe8); /* reset Tx */
                              }
      else  {
        outport(SCCDB,*scc1_send_buf++); /* send next character */
                                          /* clear TX INT Pending */
         --*scc1_send_count;             /* dec count of characters */
            }
       /* reset highest IUS, allow lower-priority INTs */
     outport(SCCCB,0x38); 
   }
int chbex(){
      printf("CH B External/Status IP  vec= %x\n",vec);
     outport(SCCCB,0x38); 
            }
int chbrx(){
      int rr1;
      sccbrx=1;
      *scc1_rec_buf++=inport(SCCDB); /* input character */
      if(! --*scc1_rec_count)   {  /* count down, if done disable */
               RES(&scc1_wreg3,0); /* Rx disable */
               RES(&scc1_wreg1,3); /* Rx int. disable */
               RES(&scc1_wreg1,4); /* Rx int. disable */
               outport(SCCCB,0x01); /* write reg. WR1  */
               outport(SCCCB,scc1_wreg1);
               outport(SCCCB,0x03); /* write reg. WR3  */
               outport(SCCCB,scc1_wreg3);
               outport(SCCCB,0x70); /* reset error, Rx CRC */
                              }
       /* reset highest IUS, allow lower-priority INTs */
     outport(SCCCB,0x38); 
   }



nodebug int special(){
            err++;
      /* find out Special Receive Condition  */
/*
            outport(SCCCA,0x01);
            rr1a=inport(SCCCA);     
            if(BIT(&rr1a,5)) rxoverruna();
            if(BIT(&rr1a,6)) crcframea();
            outport(SCCCB,0x01); 
            rr1b=inport(SCCCB);     
            if(BIT(&rr1b,5)) rxoverrunb();
            if(BIT(&rr1b,6)) crcframeb();
*/
            
            outport(SCCCA,0x30); /* reset error */
            outport(SCCCA,0x70); /* reset RxCRC and error */
            printf("err=%d\n",err);
     outport(SCCCA,0x38); 
            }


nodebug rxoverruna(){
            outport(SCCCA,0x30); /* reset error */
            printf("cha Rx Over Run\n");
            }

nodebug rxoverrunb(){
            outport(SCCCB,0x30); /* reset error */
            printf("chb Rx Over Run\n");
            }

nodebug crcframea(){
            outport(SCCCA,0x70); /* reset RxCRC and error */
            printf("cha CRC/framing error\n");
            }

nodebug crcframeb(){
            outport(SCCCB,0x70); /* reset RxCRC and error */
            printf("chb CRC/framing error\n");
            }


/*    scc_rst(char ch)                                               */
/*       Reset SCC by software                                       */
/*       There is no hardware reset on SCC of IAB212 Protocol Switch */
/*       ch = 0      SCC CHA                                         */
/*       ch = 1      SCC CHB                                         */
/*       ch = 2      CHA+CHB                                         */    
/*    return 1    errors in setting ch                               */

scc_rst(c){
   if(c==0) { 
            outport(SCCCA,0x09); /* write reg. WR9  */
            outport(SCCCA,0X80); /* reset ch a  */
            return(0);
            }
   if(c==1) { 
            outport(SCCCA,0x09); /* write reg. WR9  */
            outport(SCCCA,0X40); /* reset ch b  */
            return(0);
            }
   if(c==2) { 
            outport(SCCCA,0x09); /* write reg. WR9  */
            outport(SCCCA,0Xc0); /* reset ch a and ch b  */
            return(0);
            }
   else return(1);
         }
         
/*
    Async Initialization Driver for SCC serial port 

   *buf is a pointer to buffer for sending or receiving chars

   *count is a pointer to count of characters, counted to zero
    as characters are received/sent. Operation over when reaches zero.

   baud - baud rate expressed in units of 1200 baud. (8 == 9600 baud )

   mode - a bit code which determines:

      bit 0 -  0- 1 stop bit
               1- 2 stop bits
      bit 1 -  0- no parity
               1- parity on
      bit 2 -  0- 7 bit data
               1- 8 bit data
      bit 3 -  0- even parity
               1- odd parity

      bit 4, bit 5      clock rate
         0     0           1x mode   do not use for async communication
         1     0           16x mode    clock rate = 16 times data rate
         0     1           32x mode    clock rate = 32 times data rate
         1     1           64x mode    clock rate = 64 times data rate

      bit 6 -  0- use system clock
               1- use xtal 7.3728 MHz ? note: baud rate will be ?
   Note: baud rate calculation will be based on CLOCKSPEED=?

      bit 7 -  0- no auto enable, /CTS and /DCD are merely inputs (RR0)
               1- auto enable, /CTS is transmit enable
                               /DCD is receive enable

   SCC registers can be programed as following: 
      1 = set to one,      0 = reset to zero
      x = user defined     s = same as previously programed
        
   Part1. Modes and Constants
      wr9   11000000    hardware reset
      wr0   000000xx    select shift mode(8030 only)
      wr4   xxxxxxxx    Tx/Rx con, Async or Sync mode
      wr1   0xx00x00    select W/REQ 
      wr2   xxxxxxxx    Int. Vector
      wr3   xxxxxxx0    Rx control
      wr5   xxxx0xxx    Tx control
      wr6   xxxxxxxx    Program sync character
      wr7   xxxxxxxx    Program sync character
      wr9   000x0xxx    Int. control
      wr10  xxxxxxxx    miscellaneous control
      wr11  xxxxxxxx    clock control
      wr12  xxxxxxxx    timer constant lower byte
      wr13  xxxxxxxx    timer constant high byte
      wr14  xxxxxxx0    miscellaneous control
      wr14  xxxsssss    commands

   Part2. Enables
      wr14  000ssss1    Baud rate enable
      wr3   sssssss1    Rx enable
      wr5   ssss1sss    Tx enable
      wr0   10000000    reset Tx CRG
      wr1   xss00s00    DMA enable

   Part3. Interrupt Status
      wr15  xxxxxxxx    enable External/Status
      wr0   00010000    reset external status
      wr0   00010000    reset external status twice
      wr1   sssxxsxx    enable Rx, Tx and Ext/Status
      wr9   00ssxsss    enable Master Int. Enable, software int. ack.

*/

int asyn_init_scc0( char mode, char baud){
   extern int CLOCKSPEED;  /* 7680 for 18.432 MHz crystal   */
   int pclk,timec,clkrate;
   pclk = CLOCKSPEED;     /* system clock or RTxc in unit of 1200  */
/*    CLKRATE is x1, x16, x32, x64 as selected in Write reg.4 bit6+bit7 */
   clkrate = 16; /* do not use x1 clk for async communication  */        
      if(BIT(&mode,4)&&!BIT(&mode,5)) clkrate=16;
      if(!BIT(&mode,4)&&BIT(&mode,5)) clkrate=32;
      if(BIT(&mode,4)&&BIT(&mode,5)) clkrate=64;

/*    time constant = pclk/2(baud)*(clkrate) - 2         */
   timec = (pclk/(2*baud*clkrate)) - 2;    /*  set baud rate time constant   */
   scc_rst(0);
   scc0_wreg4=0x04; 
      if(BIT(&mode,0)) SET(&scc0_wreg4,3); /* stop bits */
      if(BIT(&mode,1)) SET(&scc0_wreg4,0); /* parity enable */
      if(BIT(&mode,3)) SET(&scc0_wreg4,1); /* parity even/odd */
      if(BIT(&mode,4)) SET(&scc0_wreg4,6); /* x1 x16 x32 or x64 */
      if(BIT(&mode,5)) SET(&scc0_wreg4,7);

   scc0_wreg1=0x40;     /* no dma operation */

   scc0_wreg2=0x00;     /* INT. vector ? */
   scc0_wreg3=0x40;     /* Rx 7 bits, no Auto */
      if(BIT(&mode,2)) SET(&scc0_wreg3,7); /* Rx 8 bits */
      if(BIT(&mode,7)) SET(&scc0_wreg3,5); /* auto enable transmit by /CTS */
                                          /* auto enable receive by /DCD   */
   scc0_wreg5=0x20;     /* Tx 7 bits, disabled */
      if(BIT(&mode,2)) SET(&scc0_wreg5,6); /* Tx 8 bits */
   scc0_wreg9=0x03;     /* VIS V1-V3, MIE disable */
   scc0_wreg10=0x00;    /* NRZ */
   scc0_wreg11=0x56;    /* no xtal, Tx,Rx,RTxC = BRG  */
      if(BIT(&mode,6)) {
                        SET(&scc0_wreg11,7); /* xtal */
                        }

   scc0_wreg12=timec;      /* timer low byte=028 for 9600 */
   scc0_wreg13=timec>>8;   /* timer high byte */
   scc0_wreg14=0x03;    /* No DPLL, BRG in=PCLK, BRG on, /DTR */
      if(BIT(&mode,6)) RES(&scc0_wreg14,1); /* BRG in=xtal */
   scc0_wreg15=0x00;    /* no Ext int. */

/* write registers   */
   outport(SCCCA,0x09); /* write reg. WR9  */
   outport(SCCCA,scc0_wreg9); /* reset ch a, No INT.  */
   outport(SCCCA,0x01); /* write reg. WR1  */
   outport(SCCCA,scc0_wreg1); 
   outport(SCCCA,0x04); /* write reg. WR4  */
   outport(SCCCA,scc0_wreg4); 
   outport(SCCCA,0x03); /* write reg. WR3  */
   outport(SCCCA,scc0_wreg3); 
   outport(SCCCA,0x05); /* write reg. WR5  */
   outport(SCCCA,scc0_wreg5); 
   outport(SCCCA,0x0a); /* write reg. WR10  */
   outport(SCCCA,scc0_wreg10); 
   outport(SCCCA,0x0b); /* write reg. WR11  */
   outport(SCCCA,scc0_wreg11); 
   outport(SCCCA,0x0c); /* write reg. WR12  */
   outport(SCCCA,scc0_wreg12); 
   outport(SCCCA,0x0d); /* write reg. WR13  */
   outport(SCCCA,scc0_wreg13); 
   outport(SCCCA,0x0e); /* write reg. WR14  */
   outport(SCCCA,scc0_wreg14);
   outport(SCCCA,0x0f); /* write reg. WR15  */
   outport(SCCCA,scc0_wreg15);

   scc0_send_count=NULL;
   scc0_rec_count=NULL;
   }



int asyn_send_scc0( char *buf, char *count) {
   static char var;
   scc0_send_buf=buf;
   scc0_send_count=count;
   /* fix ++*scc0_send_count;  */
   intoff(&var);            /* disable interrupts if on */

   SET(&scc0_wreg9,3);   /* Master int. enable   */
   SET(&scc0_wreg1,1); /* int on Tx */
   scc0_wreg5=scc0_wreg5 | 0x88; /* Tx enable */
   outport(SCCCA,0x05); /* write reg. WR5  */
   outport(SCCCA,scc0_wreg5);
   outport(SCCCA,0x01); /* write reg. WR1  */
   outport(SCCCA,scc0_wreg1);
   outport(SCCCA,0x09); /* write reg. WR9  */
   outport(SCCCA,scc0_wreg9);
   doint();             /* give interrupts a chance */
   /* send the first character */
   outport(SCCDA,*scc0_send_buf++); /* send next character */
   --*scc0_send_count;             /* dec count of characters */
   inton(&var);             /* restore interrupt state */
   }

int asyn_rec_scc0( char *buf, char *count) {

   static char var;
   scc0_rec_buf=buf;
   scc0_rec_count=count;
   intoff(&var);            /* disable interrupts if on */
   SET(&scc0_wreg1,4); /* int. on all Rx */
   SET(&scc0_wreg3,0); /* Rx enable */
   outport(SCCCA,0x03); /* write reg. WR3  */
   outport(SCCCA,scc0_wreg3);
   outport(SCCCA,0x01); /* write reg. WR1  */
   outport(SCCCA,scc0_wreg1);
   inton(&var);
   }

/* disable SCC port 0 */

int asyn_kill_scc0() {
   static char var;
   scc_rst(0);       /* reset channel  */
   }
         
/*
; DMA_MEM_SCC0 : Z180 DMA ch0 Memory to SCC0
; 
;  dma_mem_scc0 ( long mem, int size );
;
; INPUT  :
;           mem   source memory physical addr
;           size  counts of data
; OUTPUT :
;           DMA0 enabled and timed by /DREQ0(cpu) = W/REQA(scc) 
;           data transfer from memory to scc at the sequence of
;     1 cpu machine cycle - 1 DMA byte transfer - 1 cpu machine cycle...
;           DMA use edge sense. The last statment force DREQ0 high to low
;           start DMA transmit
;           Note: After DMA completion, DREQ0 stays low following the state
;                 of transmit buffer. DREQ0 can be disable by 
;                 nodma_req_scc0();
;
*/

dma_mem_scc0 (long m,int size){

char  flags;
        while (IBIT ( DSTAT,6 )) hitwd();      /* Wait for DMA0 Free           */
   outport ( DCNTL, 0x04|inport(DCNTL) ); 
     /* edge sense  */
        outport ( SAR0,(int)m );    /* Setup Source Reg. with mem addr. */
        outport ( SAR0+1,(int)(m>>8) );
        outport ( SAR0+2,(int)(m>>16) );
        outport ( DAR0,SCCDA); /* Setup Destination Reg. with I/O addr. */
        outport ( DAR0+1,SCCDA>>8 );
        outport ( DAR0+2,SCCDA>>16 );
        outport ( DMODE,0x30 );        /* mem to io SAR0+1, DAR0 fixed */
        outport ( BCR0,size );         /* Set Byte Count for Transmit  */
        outport ( BCR0+1,size>>8 );
        flags = inport ( DSTAT );      /* Set DE0 and Reset /DWE0      */
        SET(&flags,6);
        RES(&flags,4);
        outport ( DSTAT,flags ); /* waiting for high to low on /DREQ0   */
   scc0_wreg5=scc0_wreg5 | 0x88; /* Tx enable */
   RES(&scc0_wreg1,5);           /* DMA request on Tx */
   SET(&scc0_wreg1,7);         /* DMA request enable   */
   outport(SCCCA,0xe8); /* write reg. WR0, reset Tx  */
   outport(SCCCA,0x90); /* write reg. WR0, reset Tx CRC, EXT int.  */
   outport(SCCCA,0x90); /* write reg. WR0  */
   outport(SCCCA,0x05); /* write reg. WR5  */
   outport(SCCCA,scc0_wreg5);
   outport(SCCCA,0x01); /* write reg. WR1  */
   outport(SCCCA,scc0_wreg1);  /* DREQ0 goes low here */
}

/* 
;     nodma_req_scc0()      disable DMA request       
;             disable DMA request from scc0
;              DREQ0 goes to high
*/
int nodma_req_scc0(){
   RES(&scc0_wreg1,7);         /* DMA request disable   */
   outport(SCCCA,0x01); /* write reg. WR1  */
   outport(SCCCA,scc0_wreg1);  /* DREQ0 goes to high here */
                  }


/*
; DMA_SCC0_MEM : Z180 DMA ch0 SCC0 to Memory
; 
;  dma_scc0_mem ( long mem, int size );
;
; INPUT  :
;           mem   destination memory physical addr
;           size  counts of data
; OUTPUT :
;           DMA0 enabled and timed by /DREQ0(cpu) = W/REQA(scc) 
;           data transfer from scc0 to memory at the sequence of
;     1 cpu machine cycle - 1 DMA byte transfer - 1 cpu machine cycle...
;     The status of DMA transfer i.e. completed or in progress, can be 
;     determined by reading DSTAT register
*/

dma_scc0_mem (long m,int size){

char    flags;

        while (IBIT ( DSTAT,6 )) hitwd();      /* Wait for DMA0 Free           */
        outport ( DCNTL, 0x04|inport(DCNTL) );  /* edge sense  */
        outport ( SAR0,SCCDA );    /* Setup Source Reg. with I/O addr. */
        outport ( SAR0+1,SCCDA>>8 );
        outport ( SAR0+2,SCCDA>>16 );
        outport ( DAR0,(int)m ); /* Setup Destination Reg. with mem addr. */
        outport ( DAR0+1,(int)(m>>8) );
        outport ( DAR0+2,(int)(m>>16) );
        outport ( DMODE,0x0c );        /* io to mem DAR0+1, SAR0 fixed */
        outport ( BCR0,size );         /* Set Byte Count for Transmit  */
        outport ( BCR0+1,size>>8 );
   SET(&scc0_wreg1,5);           /* DMA request on Rx */
   SET(&scc0_wreg1,7);           /* DMA request enable   */
   SET(&scc0_wreg3,0); /* Rx enable */
   outport(SCCCA,0x03); /* write reg. WR3  */
   outport(SCCCA,scc0_wreg3);
   outport(SCCCA,0x70); /* write reg. WR0, reset Rx, error  */
   outport(SCCCA,0x10); /* write reg. WR0, reset EXT int.  */
   outport(SCCCA,0x10); /* write reg. WR0  */
   outport(SCCCA,0x01); /* write reg. WR1  */
   outport(SCCCA,scc0_wreg1);    /* receive DREQ0 enable */

/* DMA must be enabled after DREQ0 set, otherwise a dummy byte dma occur */
        flags = inport ( DSTAT );      /* Set DE0 and Reset /DWE0      */
        SET(&flags,6);
        RES(&flags,4);
        outport ( DSTAT,flags );       /* DMA receive enabled  */
}

/* Specifications of Mode and Baud same as asyn_init_scc0(mode,baud) */
                                     
int asyn_init_scc1( char mode, char baud){
   extern int CLOCKSPEED;  /* 7680 for 18.432 MHz crystal   */
   int pclk,timec,clkrate;
   pclk = CLOCKSPEED;     /* system clock or RTxc in unit of 1200  */
/*    CLKRATE is x1, x16, x32, x64 as selected in Write reg.4 bit6+bit7 */
   clkrate = 16;  /* do not use x1 clk for async communication */         
      if(BIT(&mode,4)&&!BIT(&mode,5)) clkrate=16;
      if(!BIT(&mode,4)&&BIT(&mode,5)) clkrate=32;
      if(BIT(&mode,4)&&BIT(&mode,5)) clkrate=64;

/*    time constant = pclk/2(baud)*(clkrate) - 2         */
   timec = (pclk/(2*baud*clkrate)) - 2;    /*  set baud rate time constant   */
   scc_rst(0);
   scc1_wreg4=0x04; 
      if(BIT(&mode,0)) SET(&scc1_wreg4,3); /* stop bits */
      if(BIT(&mode,1)) SET(&scc1_wreg4,0); /* parity enable */
      if(BIT(&mode,3)) SET(&scc1_wreg4,1); /* parity even/odd */
      if(BIT(&mode,4)) SET(&scc1_wreg4,6); /* x1 x16 x32 or x64 */
      if(BIT(&mode,5)) SET(&scc1_wreg4,7);

   scc1_wreg1=0x40;     /* no dma function */
   scc1_wreg2=0x00;     /* INT. vector ? */
   scc1_wreg3=0x40;     /* Rx, no Auto */
      if(BIT(&mode,2)) SET(&scc1_wreg3,7); /* Rx 8 bits */
      if(BIT(&mode,7)) SET(&scc1_wreg3,5); /* auto enable transmit by /CTS */
                                          /* auto enable receive by /DCD   */
   scc1_wreg5=0x20;     /* Tx disabled */
      if(BIT(&mode,2)) SET(&scc1_wreg5,6); /* Tx 8 bits */
   scc1_wreg9=0x03;     /* VIS V1-V3, MIE disable */
   scc1_wreg10=0x00;    /* NRZ */
   scc1_wreg11=0x56;    /* no xtal, Tx,Rx,RTxC = BRG  */
      if(BIT(&mode,6)) {
                        SET(&scc1_wreg11,7); /* xtal */
                        }

   scc1_wreg12=timec;      /* timer low byte=028 for 9600 */
   scc1_wreg13=timec>>8;   /* timer high byte */
   scc1_wreg14=0x03;    /* No DPLL, BRG in=PCLK, BRG on, /DTR */
      if(BIT(&mode,6)) RES(&scc1_wreg14,1); /* BRG in=xtal */
   scc1_wreg15=0x00;    /* no Ext int. */

/* write registers   */
   outport(SCCCB,0x09); /* write reg. WR9  */
   outport(SCCCB,scc1_wreg9); /* reset ch a, No INT.  */
   outport(SCCCB,0x01); /* write reg. WR1  */
   outport(SCCCB,scc1_wreg1); 
   outport(SCCCB,0x04); /* write reg. WR4  */
   outport(SCCCB,scc1_wreg4); 
   outport(SCCCB,0x03); /* write reg. WR3  */
   outport(SCCCB,scc1_wreg3); 
   outport(SCCCB,0x05); /* write reg. WR5  */
   outport(SCCCB,scc1_wreg5); 
   outport(SCCCB,0x0a); /* write reg. WR10  */
   outport(SCCCB,scc1_wreg10); 
   outport(SCCCB,0x0b); /* write reg. WR11  */
   outport(SCCCB,scc1_wreg11); 
   outport(SCCCB,0x0c); /* write reg. WR12  */
   outport(SCCCB,scc1_wreg12); 
   outport(SCCCB,0x0d); /* write reg. WR13  */
   outport(SCCCB,scc1_wreg13); 
   outport(SCCCB,0x0e); /* write reg. WR14  */
   outport(SCCCB,scc1_wreg14);
   outport(SCCCB,0x0f); /* write reg. WR15  */
   outport(SCCCB,scc1_wreg15);

   scc1_send_count=NULL;
   scc1_rec_count=NULL;
   }



int asyn_send_scc1( char *buf, char *count) {
   static char var;
   scc1_send_buf=buf;
   scc1_send_count=count;
   /* fix ++*scc1_send_count;  */
   intoff(&var);            /* disable interrupts if on */

   SET(&scc1_wreg9,3);   /* Master int. enable   */
   SET(&scc1_wreg1,1); /* int on Tx */
   scc1_wreg5=scc1_wreg5 | 0x88; /* Tx enable */
   outport(SCCCB,0x05); /* write reg. WR5  */
   outport(SCCCB,scc1_wreg5);
   outport(SCCCB,0x01); /* write reg. WR1  */
   outport(SCCCB,scc1_wreg1);
   outport(SCCCB,0x09); /* write reg. WR9  */
   outport(SCCCB,scc1_wreg9);
   doint();             /* give interrupts a chance */
   /* send the first character */
   outport(SCCDB,*scc1_send_buf++); /* send next character */
   --*scc1_send_count;             /* dec count of characters */
   inton(&var);             /* restore interrupt state */
   }

int asyn_rec_scc1( char *buf, char *count) {

   static char var;
   scc1_rec_buf=buf;
   scc1_rec_count=count;
   intoff(&var);            /* disable interrupts if on */
   SET(&scc1_wreg1,4); /* int. on all Rx */
   SET(&scc1_wreg3,0); /* Rx enable */
   outport(SCCCB,0x03); /* write reg. WR3  */
   outport(SCCCB,scc1_wreg3);
   outport(SCCCB,0x01); /* write reg. WR1  */
   outport(SCCCB,scc1_wreg1);
   inton(&var);
   }

/* disable SCC port 1 */

int asyn_kill_scc1() {
   static char var;
   scc_rst(1);       /* reset channel  */
   }


/*
; DMA_MEM_SCC1 : Z180 DMA ch1 Memory to SCC1
; 
;  dma_mem_scc1 ( long mem, int size );
;
; INPUT  :
;           mem   source memory physical addr
;           size  counts of data
; OUTPUT :
;           DMA1 enabled and timed by /DREQ1(cpu) = W/REQB(scc) 
;           data transfer from memory to scc at the sequence of
;     1 cpu machine cycle - 1 DMA byte transfer - 1 cpu machine cycle...
;           DMA use edge sense. The last statment force DREQ1 high to low
;           start DMA transmit
;           Note: After DMA completion, DREQ1 stays low following the state
;                 of transmit buffer. DREQ1 can be disable by 
;                 nodma_req_scc1();
*/

dma_mem_scc1(long m,int size){
char    flags;
        while (IBIT ( DSTAT,7 )) hitwd();      /* Wait for DMA1 Free           */
        outport ( MAR1,(int)m );     /* Setup Source Reg. with mem addr. */
        outport ( MAR1+1,(int)(m>>8) );
        outport ( MAR1+2,(int)(m>>16) );
        outport ( IAR1,SCCDB ); /* Setup Destination Reg. with I/O addr. */
        outport ( IAR1+1,SCCDB>>8 );
        outport ( IAR1+2,SCCDB>>16 );
        outport ( BCR1,size );         /* Set Byte Count for Transmit  */
        outport ( BCR1+1,size>>8 );
   /* Set control register for DMA ch1 */
      flags=inport(DCNTL);
   /* mem to I/O, DIM1=DIM0=0, MAR1+1, IAR1 fixed  */
      SET(&flags,4);    /* dma1 edge sence   */
      RES(&flags,0);    /* memory to I/O, MAR1+1   */
      RES(&flags,1);    
        outport ( DCNTL, flags ); 
        flags = inport ( DSTAT );      /* Set DE1 and Reset /DWE1      */
        SET(&flags,7);
        RES(&flags,5);
        outport ( DSTAT,flags );       /* waiting for DREQ1 high to low */
   RES(&scc1_wreg1,5);           /* DMA request on Tx */
   SET(&scc1_wreg1,7);         /* DMA request enable   */
   scc1_wreg5=scc1_wreg5 | 0x88; /* Tx enable */
   outport(SCCCB,0xe8); /* write reg. WR0, reset Tx  */
   outport(SCCCB,0x90); /* write reg. WR0, reset Tx CRC, EXT int.  */
   outport(SCCCB,0x90); /* write reg. WR0  */
   outport(SCCCB,0x05); /* write reg. WR5  */
   outport(SCCCB,scc1_wreg5);
   outport(SCCCB,0x01); /* write reg. WR1  */
   outport(SCCCB,scc1_wreg1);   /* DREQ1 high to low here   */
}
/*
; DMA_SCC1_MEM : Z180 DMA ch1 SCC1 to Memory
; 
;  dma_scc1_mem ( long mem, int size );
;
; INPUT  :
;           mem   destination memory physical addr
;           size  counts of data
; OUTPUT :
;           DMA1 enabled and timed by /DREQ1(cpu) = W/REQB(scc) 
;           data transfer from scc1 to memory at the sequence of
;     1 cpu machine cycle - 1 DMA byte transfer - 1 cpu machine cycle...
*/

dma_scc1_mem(long m,int size){
char    flags;               
        while (IBIT ( DSTAT,7 )) hitwd();      /* Wait for DMA1 Free           */
        outport ( IAR1,SCCDB );    /* Setup Source Reg. with I/O addr. */
        outport ( IAR1+1,SCCDB>>8 );
        outport ( IAR1+2,SCCDB>>16 );
        outport ( MAR1,(int)m ); /* Setup Destination Reg. with mem addr. */
        outport ( MAR1+1,(int)(m>>8) );
        outport ( MAR1+2,(int)(m>>16) );
        outport ( BCR1,size );         /* Set Byte Count for Transmit  */
        outport ( BCR1+1,size>>8 );
   /* Set control register for DMA ch1 */
   /* I/O to mem, DIM1=DIM0=1, MAR1+1, IAR1 fixed  */
      flags=inport(DCNTL);
      SET(&flags,3);    /* dma1 edge sence   */
      SET(&flags,1);    /* I/O to memory   */
      RES(&flags,0);    /* I/O to memory   */
        outport ( DCNTL, flags ); 
   SET(&scc1_wreg1,5);           /* DMA request on Rx */
   SET(&scc1_wreg1,7);           /* DMA request enable   */
   SET(&scc1_wreg3,0); /* Rx enable */
   outport(SCCCB,0x03); /* write reg. WR3  */
   outport(SCCCB,scc1_wreg3);
   outport(SCCCB,0x70); /* write reg. WR0, reset Rx, error  */
   outport(SCCCB,0x10); /* write reg. WR0, reset EXT int.  */
   outport(SCCCB,0x10); /* write reg. WR0  */
   outport(SCCCB,0x01); /* write reg. WR1  */
   outport(SCCCB,scc1_wreg1);    /* receive DREQ1 enable */

/* DMA must be enabled after DREQ0 set, otherwise a dummy byte dma occur */
        flags = inport ( DSTAT );      /* Set DE1 and Reset /DWE1      */
        SET(&flags,7);
        RES(&flags,5);
        outport ( DSTAT,flags );
}

/* 
;     nodma_req_scc1()      disable DMA request       
;             disable DMA request from scc1
;              DREQ1 goes to high
*/
int nodma_req_scc1(){
   RES(&scc1_wreg1,7);         /* DMA request disable   */
   outport(SCCCB,0x01); /* write reg. WR1  */
   outport(SCCCB,scc1_wreg1);  /* DREQ1 goes to high here */
                  }
