home *** CD-ROM | disk | FTP | other *** search
- ///////////////////////////////////////////////////////////////////////////
- // //
- // File: serialse.cpp //
- // started on: 5/2/92 //
- // //
- ///////////////////////////////////////////////////////////////////////////
- // //
- // This class sends and receives data via interrupt driven Serial //
- // engine. very comfortable interface (I think). Might not work on //
- // slow machines in high baud rates (after all it's written in a high //
- // level language). //
- // //
- ///////////////////////////////////////////////////////////////////////////
- // //
- // by Ofer Laor (AKA LeucroTTA) //
- // //
- ///////////////////////////////////////////////////////////////////////////
-
- #include "serial.h" // SERIAL_PORT
- #include <dos.h> // outportb, inportb
-
- const unsigned long SERIAL_PORT::BAUD_CONST = 115200L;
-
- const unsigned BUFF_SIZE= 256; // communication buffer size.
-
- // sets the imr to enable the hardware interrupt request line.
- //
- void SERIAL_PORT::set_imr(void)
- {
- outportb (com_pic_port+ PIC_IMR, (inportb (com_pic_port+ PIC_IMR) & com_imr_mask));
- }
-
- // sends an eoi to the pic.
- //
- void SERIAL_PORT::eoi(void)
- {
- outportb (com_pic_port+ PIC_DATA, 0x20); // send pic eoi message.
- }
-
- // update flow_enabled.
- //
- void SERIAL_PORT::flow_check(void)
- {
- flow_enabled= TRUE;
- }
-
- // error has been received.
- //
- void SERIAL_PORT::com_error(void)
- {
- // read twice to try and free the error.
- inportb(com_port+ DATA);
- inportb(com_port+ DATA);
- }
-
- // set up the serial port.
- //
- void SERIAL_PORT::set_up_port( const long baud_rate, const BYTE word_len,
- const BYTE parity, const BYTE stop_bits)
- {
- // if already initialized, exit.
- //
- if (InitFlag)
- return;
-
- outportb (com_port+ LCR, 0x80); // set DLAB
-
- outport (com_port+ BAUDLOW, (unsigned)(BAUD_CONST / baud_rate));
-
- // LCR is eventual going to be set to temp.
- //
- BYTE temp= 0; // DLAB= 0;
-
- temp&=0xc7; // clear parity.
- switch (parity) {
- case 'N': // no parity
- temp|= 0x0;
- break;
- case 'O': // ODD parity.
- temp|= 0x8;
- break;
- case 'E': // EVEN parity.
- temp|= 0x18;
- break;
- case 'M': // MARK.
- temp|= 0x28;
- break;
- case 'S': // SPACE.
- temp|= 0x38;
- break;
- }
-
- temp&=0xfb; // clear stop bits.
- switch (stop_bits) {
- case 1: // one stop bit.
- break;
- case 2: // two stop bits.
- temp|= 0x4;
- }
-
- temp&=0xfc; // clear word len.
- switch (word_len) {
- case 5: // word len= 5.
- break;
- case 6: // word len= 6.
- temp|= 0x1;
- break;
- case 7: // word len= 7.
- temp|= 0x2;
- break;
- case 8: // word len= 8.
- temp|= 0x3;
- break;
- }
-
- outportb (com_port+ LCR, temp); // set LCR to options.
-
- }
-
- // the constructor gets as parameters- the port number associated with the
- // serial port, as well as the HARDWARE interrupt number it is attached to,
- // the software interrupt it generates and the PIC port that holds it.
- //
-
- SERIAL_PORT::SERIAL_PORT (const unsigned port_num,
- const unsigned irq_line_num,
- const unsigned int_num,
- const unsigned pic_port_num= 0x20) : ISC()
- {
- InitFlag= FALSE;
-
- // setup serial_port parameters.
- activate(port_num, irq_line_num, int_num, pic_port_num);
- }
-
- void SERIAL_PORT::activate (const unsigned port_num,
- const unsigned irq_line_num,
- const unsigned int_num,
- const unsigned pic_port_num= 0x20)
- {
- // if already initialized, exit.
- //
- if (InitFlag)
- return;
-
- // initializing do_send vars.
- do_send_recursive_count= 0;
- do_send_recursive_flag= FALSE;
-
- // resize I/O buffers.
-
- in_buff.reset_size(BUFF_SIZE, TRUE);
- out_buff.reset_size(BUFF_SIZE, TRUE);
-
- // the serial's port.
- com_port= port_num;
-
- // hardware interrupt request line num.
-
- com_imr_mask= ~(0x1 << irq_line_num); // all "1" except a "0" on the line request...
-
- // hardware interrupt num.
- com_int= int_num;
-
- // default imr_port is 0x20.
- //
- com_pic_port= pic_port_num;
-
- // now hook interrupts via ISC.
- //
- ISC::activate(com_int);
-
- outportb (com_port+ IER, 0xF); // enable UART interrupts on all calls!!!
-
- // clear RCV buffers
- inportb (com_port+ LSR); // clear LSR.
- inportb (com_port+ DATA); // clear RX register.
- inportb (com_port+ MSR); // clear MSR register.
-
- inportb (com_port+ IID); // read IID register (to clear it's Flip-Flop flag).
-
- // repeat all readings to be sure they are clear.
- if (inportb (com_port+ IID) & 1) {
- // repeat the clearing...
- inportb (com_port+ LSR); // clear LSR
- inportb (com_port+ DATA); // clear RX register
- inportb (com_port+ MSR); // clear MSR register
- }
-
- // and now enable the modem's interrupt enable.
-
- outportb (com_port+ MCR, (inportb(com_port+ MCR)| 8)); // write it into MCR. (turn on OUT2).
-
- // 8259A programming...
- set_imr(); // setup imr.
-
- eoi(); // send pic an EOI just to be sure.
-
- // allow derived classes to extend the initialization of the port.
- //
- extended_init();
-
- // default port settings.
- set_up_port (9600,8,'N',1);
- }
-
- // this constructor gets a single number from 1 to 4 (must be a legal serial
- // port- it does not test it's validity), and hooks to it.
- //
- SERIAL_PORT::SERIAL_PORT (const unsigned com_num) : ISC()
- {
- InitFlag= FALSE;
-
- // setup serial port parameters.
- activate(com_num);
- }
-
- // setup parameters.
- //
- void SERIAL_PORT::activate(const unsigned com)
- {
- unsigned com_num= com;
-
- // exit if already initialized.
- if (InitFlag)
- return;
-
- com_num--;
- com_num%= 4; // now com_num is between 0-3 (and can be used for offsets!).
-
- unsigned huge *port_num= (unsigned huge *)0x00000400L; // bios data area.
-
- com_port= *(port_num+ com_num); // access bios data area and retrieve the com port...
-
- unsigned com_irq_line;
- switch (com_num) {
-
- // com1 & com3.
-
- case 0:
- case 2:
- com_irq_line= 4;
- com_int= 0xc;
- break;
-
- // com2 & com4.
-
- case 1:
- case 3:
- com_irq_line= 3;
- com_int= 0xb;
- break;
- }
-
-
- // now reuse activate.
- //
- activate(com_port, com_irq_line, com_int);
- }
-
- SERIAL_PORT::SERIAL_PORT() : ISC()
- {
- InitFlag= FALSE;
- }
-
- SERIAL_PORT::~SERIAL_PORT()
- {
- outportb (com_port+ IER, 0); // disable UART interrupts on all calls!!!
- }