/*============ serial_access.h =====================================

  PURPOSE - this module allows direct accesses a serial port.

     NOTE - this implementation is only useful if just one serial
            port is being controlled.  An object solution would
            be much better for multiple ports.
          - IO access must have been enabled to get access to serial
            addresses.

   PUBLIC - serial_init(short lp_num) gets the serial base address,
            saves registers, and disables interrupts.
          - serial_restore() returns all registers to their previous
            state, including the interrupt status.
          - routines could be written for setting ports, bit set 
            and clear,  and reading ports.
*/

#ifndef SERIAL_ACCESS
#define SERIAL_ACCESS

#include <sys/io.h>

//--- possible serial port addresses.

#define ttyS0 0x3F8       // ttyS (COM) port base addresses.
#define ttyS1 0x2F8
#define ttyS2 0x3E8
#define ttyS3 0x2E8
#define ttyS_length 8

//--- registers and bits.
#define IER_offset  1
#define LCR_offset  3
#define MCR_offset  4
#define LSR_offset  5
#define MSR_offset  6

#define MCR_RTS     2  // RTS, DTR bits in MCR.   
#define MCR_DTR     1
#define MSR_CD   0x80  // inputs in MSR. 
#define MSR_RI   0x40
#define MSR_DSR  0x20
#define MSR_CTS  0x10
#define MSR_DCD  0x08  // edge detectors in MSR.
#define MSR_DRI  0x04
#define MSR_DDSR 0x02
#define MSR_DCTS 0x01
#define LCR_TX0  0x40  // bit set -> TX to low, +12v out. 
#define LSR_RX0  0x10  // bit set-> RX has received a string of 0, +3v.

//--- variables : here and not static so macros can access them.
short serial_base ; // save base addr of serial port. 
unsigned char save_IER ;     // save of original values.
unsigned char save_LCR ;
unsigned char save_MCR ;
unsigned char image_IER ;    // use image as master record of port.
unsigned char image_LCR ;
unsigned char image_MCR ;


/*--- initialise and restore serial port by number (0,1,2,3).*/
void serial_init(short tty_num) ;
void serial_restore() ;


/*--- MACROs. */
#define SET_RTS outb((image_control |= 0x02), serial_base + MCR_offset)
#define CLR_RTS outb((image_control &= 0xFD), serial_base + MCR_offset)
#define SET_DTR outb((image_control |= 0x01), serial_base + MCR_offset)
#define CLR_DTR outb((image_control &= 0xFE), serial_base + MCR_offset)

#define GET_DSR ( inb( serial_base + MSR_offset) & 0x20)

#define WR_MCR( sdata) outb( sdata, serial_base + MCR_offset)  
#define RD_MCR         ( inb( serial_base + MCR_offset))  

#endif 
