www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1998/09/17/18:30:41

From: Leif <LeifDude AT hotmail DOT com>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: Serial ISRs
Date: Thu, 17 Sep 1998 15:19:39 -0700
Organization: NorthWest Nexus Inc.
Lines: 413
Message-ID: <36018AFB.3FC8@hotmail.com>
References: <35F52BDC DOT A7402210 AT res DOT raytheon DOT com>
NNTP-Posting-Host: blv-pm105-ip19.halcyon.com
Mime-Version: 1.0
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

This is a multi-part message in MIME format.

--------------62E86F2B32FE
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Heres my modem Include File I made.

> I can't seem to get a buzz from my ports. Does anyone have some sample
> code for doing this sort of thing so that I can stop chasing my tail?
> I'm using a pentium under DOS (yeah, yeah, I know) with plenty of memory

There might be a couple bugs in it still. U might need to change the ISR
a little.
When I was writing it however, it took me forever to figure out why it
wasnt responding.. I dont know if its related to yer problem but...
My problem was I had to set -OUT2 high in order to send the interupts to
the PIC.
Also make sure U got the IMR set up appropriately and mask the PIC
correctly.
Well either way. All U have to do is include this file and call
InitModem()

InitModem(ComPortNumber,IRQNumber,BAUDRATE,DataFormat);
my modem is on Com3 Irq9 and is 56K so I do   InitModem(3,9,56000,D_8 |
P_None | S_1);
At end of program do UnInitModem(3);   3 because its com3

In yer loop to find out if U got some data check if Modem[3].RCVHead ==
Modem[3].RCVTail
if they dont equal each other then U got some data.
To get the next char do:
BYTE=Modem[3].Modem[Modem[3].RCVTail++];
if(Modem[3].RCVTail>=Circular) Modem[3].RCVTail=0;

If U having problems with my include ask me at LeifDude AT Hotmail DOT com

--------------62E86F2B32FE
Content-Type: text/plain; charset=us-ascii; name="mymodem.h"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="mymodem.h"

#include <dos.h>
#include <dpmi.h>
#include <go32.h>
#include <sys/movedata.h>

#define Circular        32768
#define BYTE    unsigned char

//------Register BaseAddress Offsets------
#define R_IORegister        0
#define R_Divisor           0
#define R_IntEnable         1
#define R_IntID             2
#define R_FifoControl       2
#define R_LineControl       3
#define R_ModemControl      4
#define R_LineStatus        5
#define R_ModemStatus       6
#define R_Scratch           7

//------Parity------
#define P_None              0
#define P_Odd               8
#define P_Even             24
#define P_Mark             40
#define P_Space            56
//------StopBits------
#define S_1                 0
#define S_2                 4
//------DataBits------
#define D_5                 0
#define D_6                 3
#define D_7                 2
#define D_8                 3

BYTE InitModem(BYTE ComPort,BYTE IRQ,unsigned long BaudRate,BYTE DataFlags);
void UnInitModem(int ComPort);
void InitUART(int LineNum);
void UnInitUART(int LineNum);
void ModemIntOn(int LineNum);
void ModemIntOff(int LineNum);
void ModemHandler2(void);
void ModemHandler3(void);
void SendChar(int LineNum,BYTE Char);
void SendString(int ComPort,BYTE *Buff,unsigned int Length);
BYTE GrabChar(int ComPort);
BYTE GrabString(int ComPort);

BYTE PicIRQOn[16]  = {254,253,251,247,239,223,191,127,
                      254,253,251,247,239,223,191,127};
BYTE PicIRQOff[16] = {1,2,4,8,16,32,64,128,
                      1,2,4,8,16,32,64,128};
BYTE IRQVector[16] = {8,9,10,11,12,13,14,15,
                      112,113,114,115,116,117,118,119};

struct MyModem{
  unsigned int Address,Divisor,RCVHead,RCVTail,TRNSHead,TRNSTail;
  __dpmi_paddr OldHandler,NewHandler;
  _go32_dpmi_seginfo ModemWrapper;
  BYTE Active,IRQOn,IRQOff,IRQVector,IRQ,DataFlags,Status,FIFOOn;
  BYTE ModemRCV[Circular],ModemTRNS[Circular],Temp[Circular];
} Modem[4];

void ModemIntOn(int LineNum){
  switch(LineNum){
//    case 1: Modem[LineNum].ModemWrapper.pm_offset=(int)ModemHandler1; break;
    case 2: Modem[LineNum].ModemWrapper.pm_offset=(int)ModemHandler2; break;
    case 3: Modem[LineNum].ModemWrapper.pm_offset=(int)ModemHandler3; break;
//    case 4: Modem[LineNum].ModemWrapper.pm_offset=(int)ModemHandler4; break;
  }
  Modem[LineNum].ModemWrapper.pm_selector=_my_cs();

  _go32_dpmi_allocate_iret_wrapper(&Modem[LineNum].ModemWrapper);

  Modem[LineNum].NewHandler.offset32=Modem[LineNum].ModemWrapper.pm_offset;
  Modem[LineNum].NewHandler.selector=Modem[LineNum].ModemWrapper.pm_selector;

  __dpmi_get_protected_mode_interrupt_vector(Modem[LineNum].IRQVector, &Modem[LineNum].OldHandler); // save old
  __dpmi_set_protected_mode_interrupt_vector(Modem[LineNum].IRQVector, &Modem[LineNum].NewHandler); // set new
}

void ModemIntOff(int LineNum){
  __dpmi_set_protected_mode_interrupt_vector(Modem[LineNum].IRQVector, &Modem[LineNum].OldHandler); // set old
  _go32_dpmi_free_iret_wrapper(&Modem[LineNum].ModemWrapper);             // free wrapper
}

void InitUART(int LineNum){
  BYTE Val;
  int Port;

  outp(Modem[LineNum].Address+R_LineControl,128);//DLAB=1
  outpw(Modem[LineNum].Address+R_Divisor,Modem[LineNum].Divisor);//Send Divisor
  outp(Modem[LineNum].Address+R_LineControl,Modem[LineNum].DataFlags);//DLAB=0 & send DataFormat
  //             8                       4-NoFunctionOnPC    2     1
  //ModemControl:OUT2=SendInteruptsToPic OUT1=BestToBeActive RTS=1 DTR=1
  outp(Modem[LineNum].Address+R_ModemControl,15);
  outp(Modem[LineNum].Address+R_IntEnable,15);//Interupts we want to receive

  if(Modem[LineNum].IRQ>7) Port = 0xa1;//Slave PIC OCW1
  else Port = 0x21;//Master PIC OCW1
  Val=inp(Port);//Get Current OCW1
  outp(Port,Val&Modem[LineNum].IRQOn);//Enable IRQ on PIC

  outp(Modem[LineNum].Address+R_FifoControl,0x0c7);//Try to turn ON FIFO
  Val=inp(Modem[LineNum].Address+R_FifoControl);//Fifo Support? D6=Yes
  if((Val & 64)>0) Modem[LineNum].FIFOOn = 1;
  else{
    Modem[LineNum].FIFOOn = 0;
    outp(Modem[LineNum].Address+R_FifoControl,0);//Turn off FIFO
  }
}

void UnInitUART(int LineNum){
  BYTE Val;
  int Port;

  outp(Modem[LineNum].Address+R_ModemControl,0);//StopIntsToPIC DropRTS
  outp(Modem[LineNum].Address+R_IntEnable,0);//Clear Interupt Flags

  if(Modem[LineNum].IRQ>7) Port = 0xa1;//Slave PIC OCW1
  else Port = 0x21;//Master PIC OCW1
  Val=inp(Port);//Get Current OCW1
  outp(Port,Val|Modem[LineNum].IRQOff);//Disable IRQ on PIC
}


BYTE InitModem(BYTE ComPort,BYTE IRQ,unsigned long BaudRate,BYTE DataFlags){
  union REGS r;
  BYTE Com[8],Ret,LineNumber;

  LineNumber=ComPort;
  Ret=0;
  //---Valid COM Port?---
  if((ComPort<1)||(ComPort>4)) return(2);
  //---Already Initialized?---
  if(Modem[LineNumber].Active) Ret=1;
  //---Usable IRQ Line?---
  if((IRQ<3)||(IRQ==6)||(IRQ==8)||(IRQ==14)||(IRQ==13)) Ret+=4;
  if(Ret) return(Ret);

  //---Setup all the IRQ junk---
  Modem[LineNumber].IRQ = IRQ;//IRQ Number
  Modem[LineNumber].IRQOn = PicIRQOn[IRQ];//Mask to Enable IRQ on PIC
  Modem[LineNumber].IRQOff = PicIRQOff[IRQ];//Mask to Disable IRQ on PIC
  Modem[LineNumber].IRQVector = IRQVector[IRQ];//Interupt Vector Number
  //---Install ModemHandler---
  ModemIntOn(LineNumber);
  //---Get Base Address of UART from BIOS---
  dosmemget(0x00400,8,Com);
  r.h.al = Com[ (ComPort-1)*2   ];//LSB
  r.h.ah = Com[ (ComPort-1)*2+1 ];//MSB
  Modem[LineNumber].Address = r.x.ax;
  //---Store DataFormat Bits---
  Modem[LineNumber].DataFlags = DataFlags;
  //---Setup the Divisor---
  Modem[LineNumber].Divisor = (unsigned int)(115200/BaudRate);
  //---Setup The UART and the PIC to start getting Interupts---
  InitUART(LineNumber);
  //---Set Current Status---
  Modem[LineNumber].Status = inp(Modem[LineNumber].Address+R_ModemStatus);
  //---Flag this structure instance as initialized---
  Modem[LineNumber].Active=1;

                        /*
  WriteChar(LineNumber,13);
  WriteChar(LineNumber,10);
  WriteChar(LineNumber,'a');//atz=DefaultModemState
  WriteChar(LineNumber,'t');
  WriteChar(LineNumber,'z');
  WriteChar(LineNumber,13);
  WriteChar(LineNumber,10);
  delay(20);
  Modem[LineNumber].RCVTail = Modem[LineNumber].RCVHead;//Clear RCVBuffer
                          */
  return(0);//No Error
}

void UnInitModem(int ComPort){
  if(Modem[ComPort].Active==0) return;
  Modem[ComPort].Active = 0;
  UnInitUART(ComPort);
  ModemIntOff(ComPort);
}


//If U wanna use COM 1 or 4 copy this loop and change all the  Modem[2] to
// Modem[4] or Modem[1]   and name the loop ModemHandler1 etc..
void ModemHandler2( void ){
  int Port,Status;
  BYTE Value,Bit0,Bit1,Bit2;

  if(Modem[2].IRQ>7){
    Value=inp(0xa1);                       //Remove IRQ on Slave PIC
    outp(0xa1,Value|Modem[2].IRQOff);
    outp(0xa0,0x20);  //EOI Slave
    outp(0x20,0x20);  //EOI Master : Master gets interupted when slave does
  }
  else{
    Value=inp(0x21);                       //Remove IRQ on Master PIC
    outp(0x21,Value|Modem[2].IRQOff);
    outp(0x20,0x20);  //EOI Master
  }

  //----Which Interupt was it?----
  Value = inp(Modem[2].Address+R_IntID);
  Bit0 = Value & 1;
  Bit1 = Value & 2; if(Bit1) Bit1=1;
  Bit2 = Value & 4; if(Bit2) Bit2=1;

  while(!Bit0){
    if(Bit2 && Bit1){//----------Serialization Error or Break------------
      printf("Error\n");
      outp(Modem[2].Address+R_LineStatus,0);   //Clear LineStatusRegister
      Value=inp(Modem[2].Address+R_LineStatus);//Read  LineStatusRegister
    }

    if(Bit2 && !Bit1){//---------Data is Waiting to be Read--------------
      Value = inp(Modem[2].Address+R_IORegister);
      Modem[2].ModemRCV[Modem[2].RCVHead++] = Value;
      if(Modem[2].RCVHead>=Circular) Modem[2].RCVHead=0;
    }

    if(!Bit2 && Bit1){//---------Transmit Buffer Empty-------------------
      Value=1;
      if(Modem[2].FIFOOn) Value=16;
      for(Bit0=0;Bit0<Value;Bit0++){
        if(Modem[2].TRNSHead!=Modem[2].TRNSTail){
          outp(Modem[2].Address+R_IORegister,Modem[2].ModemTRNS[Modem[2].TRNSTail++]);
          if(Modem[2].TRNSTail>=Circular) Modem[2].TRNSTail=0;
        }
      }
    }

    if(!Bit2 && !Bit1){//--------Modem Status Change---------------------
      Modem[2].Status = inp(Modem[2].Address+R_ModemStatus);
    }

    //----Another Interupt?----
    Value = inp(Modem[2].Address+R_IntID);
    Bit0 = Value & 1;
    Bit1 = Value & 2; if(Bit1) Bit1=1;
    Bit2 = Value & 4; if(Bit2) Bit2=1;
  }

  if(Modem[2].IRQ>7){
    Value=inp(0xa1);                       //Enable IRQ on PIC Slave
    outp(0xa1,Value&Modem[2].IRQOn);
  }
  else{
    Value=inp(0x21);                       //Enable IRQ on PIC Master
    outp(0x21,Value&Modem[2].IRQOn);
  }
}

void ModemHandler3( void ){
  int Port,Status;
  BYTE Value,Bit0,Bit1,Bit2,Bit6,Bit7;

  //Remove IRQ on Slave PIC & Send EOI
  if(Modem[3].IRQ>7){
    Value=inp(0xa1);
    outp(0xa1,Value|Modem[3].IRQOff);
    outp(0xa0,0x20);  //EOI Slave
    outp(0x20,0x20);  //EOI Master : Master gets interupted when slave does
  }
  //Remove IRQ on Master PIC & Send EOI
  else{
    Value=inp(0x21);
    outp(0x21,Value|Modem[3].IRQOff);
    outp(0x20,0x20);  //EOI Master
  }

  //----Which Interupt was it?----
  Value = inp(Modem[3].Address+R_IntID);
  Bit0 = Value & 1;
  Bit1 = Value & 2; if(Bit1) Bit1=1;
  Bit2 = Value & 4; if(Bit2) Bit2=1;

  while(!Bit0){
    //----------Serialization Error or Break------------
    if(Bit2 && Bit1){
      outp(Modem[3].Address+R_LineStatus,0);   //Clear LineStatusRegister
      Value=inp(Modem[3].Address+R_LineStatus);//Read  LineStatusRegister
    }
    //---------Data is Waiting to be Read--------------
    if(Bit2 && !Bit1){
      Value = inp(Modem[3].Address+R_IORegister);
      Modem[3].ModemRCV[Modem[3].RCVHead++] = Value;
      if(Modem[3].RCVHead>=Circular) Modem[3].RCVHead=0;
    }
    //-------------Transmiter Holding Register Empty-------------
    if(!Bit2 && Bit1){
      Value=1;
      if(Modem[3].FIFOOn) Value=16;
      for(Bit0=0;Bit0<Value;Bit0++){
        if(Modem[3].TRNSHead!=Modem[3].TRNSTail){
          outp(Modem[3].Address+R_IORegister,Modem[3].ModemTRNS[Modem[3].TRNSTail++]);
          if(Modem[3].TRNSTail>=Circular) Modem[3].TRNSTail=0;
        }
      }
    }
    //---------------------Modem Status Change---------------------
    if(!Bit2 && !Bit1) Modem[3].Status = inp(Modem[3].Address+R_ModemStatus);

    //----Another Interupt?----
    Value = inp(Modem[3].Address+R_IntID);
    Bit0 = Value & 1;
    Bit1 = Value & 2; if(Bit1) Bit1=1;
    Bit2 = Value & 4; if(Bit2) Bit2=1;
  }
  if(Modem[3].IRQ>7){
    Value=inp(0xa1);                       //Enable IRQ on PIC Slave
    outp(0xa1,Value&Modem[3].IRQOn);
  }
  else{
    Value=inp(0x21);                       //Enable IRQ on PIC Master
    outp(0x21,Value&Modem[3].IRQOn);
  }
}

void SendChar(int LineNum,BYTE Char){
  BYTE Val;
  Val=inp(Modem[LineNum].Address+R_LineStatus) & 32;
  if((Val>0)&&(Modem[LineNum].TRNSHead==Modem[LineNum].TRNSTail)) outp(Modem[LineNum].Address+R_IORegister,Char);
  else Modem[LineNum].ModemTRNS[Modem[LineNum].TRNSHead++]=Char;
}

void SendString(int ComPort,BYTE *Buff,unsigned int Length){
  unsigned int Head,Flag,t,V;
  BYTE *Src,*Dest;

  Src=Buff;
  Dest=Modem[ComPort].ModemTRNS;
  Head=Modem[ComPort].TRNSHead;

  Flag=0;
  if(Head==Modem[ComPort].TRNSTail) Flag=1;

  while(Length--){
    *(Dest+Head++)=*Src++;
    if(Head>=Circular) Head=0;
  }
  Modem[ComPort].TRNSHead = Head;

  if(Flag){
    while ((inp(Modem[ComPort].Address+R_LineStatus) & 32) == 0);
    V=1;
    if(Modem[ComPort].FIFOOn) V=16;
    for(t=0;t<V;t++){
      if(Modem[ComPort].TRNSHead!=Modem[ComPort].TRNSTail){
        outp(Modem[ComPort].Address+R_IORegister,Modem[ComPort].ModemTRNS[Modem[ComPort].TRNSTail++]);
        if(Modem[ComPort].TRNSTail>=Circular) Modem[ComPort].TRNSTail=0;
      }
    }
  }
}

BYTE GrabChar(int ComPort){


}


BYTE GrabString(int ComPort){

}

//--- EndPad ---//

--------------62E86F2B32FE--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019