📄 serial.c
字号:
static char _[] = "@(#)serial.c 5.21 93/10/26 09:47:06, Srini, AMD.";/****************************************************************************** * Copyright 1991 Advanced Micro Devices, Inc. * * This software is the property of Advanced Micro Devices, Inc (AMD) which * specifically grants the user the right to modify, use and distribute this * software provided this notice is not removed or altered. All other rights * are reserved by AMD. * * AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS * SOFTWARE. IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL * DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR * USE OF THIS SOFTWARE. * * So that all may benefit from your experience, please report any problems * or suggestions about this software to the 29K Technical Support Center at * 800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131 in the UK, or * 0031-11-1129 in Japan, toll free. The direct dial number is 512-462-4118. * * Advanced Micro Devices, Inc. * 29K Support Products * Mail Stop 573 * 5900 E. Ben White Blvd. * Austin, TX 78741 * 800-292-9263 ***************************************************************************** * Engineer: Srini Subramanian. ***************************************************************************** * This module contains the functions to initialize, read, and write to the * serial ports (COM1, COM2,...) on a PC. ***************************************************************************** */#include <stdio.h>#include <conio.h>#include <bios.h>#include <dos.h> #include <string.h>#include "types.h"#include "memspcs.h"#include "messages.h"#include "mtip.h"#include "tdfunc.h"/* Serial Port Defs */ /* * Divisors for different baud rates to be used to initialize DLA * register. */#define _DIV_COM_110 1047#define _DIV_COM_150 768#define _DIV_COM_300 384#define _DIV_COM_600 192#define _DIV_COM_1200 96#define _DIV_COM_2400 48#define _DIV_COM_4800 24#define _DIV_COM_9600 12#define _DIV_COM_19200 6#define _DIV_COM_38400 3#define _DIV_COM_115200 1#define LCR_DLAB 0x80#define DLA_LOW_OFFSET 0x0/*** Definitions*/#define BUF_SIZE 2048/*** This data structure is used by the interrupt driven** serial I/O.*/struct serial_io_t { int error; /* Error code */ unsigned int port; /* Port number */ unsigned int port_code; /* Port code (for bios calls) */ unsigned int int_number; /* Port interrupt number */ unsigned int int_mask; /* Port interrupt mask */ unsigned int baud; /* Port baud rate */ unsigned int old_vector_ds; /* Interrupt vector (old) */ unsigned int old_vector_dx; volatile unsigned char *start; /* Start of ring buffer */ volatile unsigned char *end; /* End of ring buffer */ };static unsigned char serial_io_buffer[BUF_SIZE];/* These definitions are from bios.h */#define CHAR_SIZE _COM_CHR8#define STOP_BITS _COM_STOP1#define PARITY _COM_NOPARITY/*** Serial port definitions*/#define INTR_MASK 0x21 /* 8259 Interrupt Mask Port */#define INTR_EOI 0x20 /* 8259 EOI Port */#define COM1 0x3f8 /* COM1 Port Base */#define COM1_CODE 0x00 /* COM1 Port Code */#define COM1_INT 0x0c /* COM1 Interrupt Number */#define COM1_MASK 0x10 /* COM1 Interrupt Mask (IRQ4) */#define COM2 0x2f8 /* COM2 Port Base */#define COM2_CODE 0x01 /* COM2 Port Code */#define COM2_INT 0x0b /* COM2 Interrupt Number */#define COM2_MASK 0x08 /* COM2 Interrupt Mask (IRQ3) */#define MSR_OFFSET 0x6 /* Modem Status Register offset */#define LSR_OFFSET 0x5 /* Line status Register offset */#define MCR_OFFSET 0x4 /* Modem Control Register offset */#define LCR_OFFSET 0x3 /* Line Control Register offest */#define IID_OFFSET 0x2 /* Interrupt pending register */#define IER_OFFSET 0x1 /* Interrupt Enable Register offest *//* Bits in Line Status Register (LSR) */#define AC1 0x80 /* Always clear */#define TSRE 0x40 /* Transmitter Shift Register Empty */#define THRE 0x20 /* Transmitter Holding Register Empty */#define BI 0x10 /* Break Interrupt */#define FE 0x08 /* Framing Error */#define PE 0x04 /* Parity Error */#define OE 0x02 /* Overrun Error */#define DR 0x01 /* Data Ready *//* Bits in Modem Control Register */#define CD 0x80#define RI 0x40#define DSR 0x20#define CTS 0x10#define OUT2 0x08#define RTS 0x02#define DTR 0x01#define MAX_BLOCK 1000 /* function prototypes */void endian_cvt PARAMS((union msg_t *, int));void tip_convert32 PARAMS((BYTE *));INT32 init_parport (char *);void interrupt far serial_int PARAMS((void));void (interrupt far *OldVector)();int get_byte_serial PARAMS((void));extern int BlockCount;extern int lpt_initialize;/* globals */struct serial_io_t serial_io;INT32 in_msg_length=0;INT32 in_byte_count=0;/*** Serial Port functions*//*** This function is used to initialize the communication** channel. First the serial_io data structure is** initialized. Then the new interrupt vector is installed.** Finally, the port is initialized, with DTR, RTS and OUT2** set.***/INT32 write_memory_serial (ignore1, ignore2, ignore3, ignore4, ignore5, ignore6) INT32 ignore1; ADDR32 ignore2; BYTE *ignore3; INT32 ignore4; INT32 ignore5; INT32 ignore6; { return(-1); }INT32 read_memory_serial (ignore1, ignore2, ignore3, ignore4, ignore5, ignore6) INT32 ignore1; ADDR32 ignore2; BYTE *ignore3; INT32 ignore4; INT32 ignore5; INT32 ignore6;{ return(-1); }INT32 fill_memory_serial() { return(-1); }INT32init_comm_serial(ignore1, ignore2)INT32 ignore1;INT32 ignore2; { unsigned result; unsigned config; unsigned int comm_status; /* Initialize serial_io */ serial_io.error = FALSE; /* Set up port number */ if ((strcmp(tip_config.comm_port, "com1") == 0) || (strcmp(tip_config.comm_port, "com1:") == 0)) { serial_io.port = COM1; serial_io.port_code = COM1_CODE; serial_io.int_number = COM1_INT; serial_io.int_mask = COM1_MASK; } else if ((strcmp(tip_config.comm_port, "com2") == 0) || (strcmp(tip_config.comm_port, "com2:") == 0)) { serial_io.port = COM2; serial_io.port_code = COM2_CODE; serial_io.int_number = COM2_INT; serial_io.int_mask = COM2_MASK; } else return((INT32) -1); /* Check status */ comm_status = inp(serial_io.port+LSR_OFFSET);#if 0 /* reset any communication errors */ outp(serial_io.port+LSR_OFFSET, (unsigned int) (comm_status & ~(FE|PE|OE)));#endif /* Get baud rate (Note: MS-DOS only goes to 9600) */ outp (serial_io.port+LCR_OFFSET, LCR_DLAB); if (strcmp(tip_config.baud_rate, "110") == 0) outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_110); else if (strcmp(tip_config.baud_rate, "150") == 0) outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_150); else if (strcmp(tip_config.baud_rate, "300") == 0) outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_300); else if (strcmp(tip_config.baud_rate, "600") == 0) outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_600); else if (strcmp(tip_config.baud_rate, "1200") == 0) outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_1200); else if (strcmp(tip_config.baud_rate, "2400") == 0) outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_2400); else if (strcmp(tip_config.baud_rate, "4800") == 0) outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_4800); else if (strcmp(tip_config.baud_rate, "9600") == 0) outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_9600); else if (strcmp(tip_config.baud_rate, "19200") == 0) outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_19200); else if (strcmp(tip_config.baud_rate, "38400") == 0) outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_38400); else if (strcmp(tip_config.baud_rate, "115200") == 0) outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_115200); else return((INT32) -1); /* EMBAUD); */ /* Set LCR */ outp (serial_io.port+LCR_OFFSET, (unsigned int) (_COM_CHR8|_COM_STOP1|_COM_NOPARITY)); /* Save old interrupt vector */ OldVector = _dos_getvect (serial_io.int_number); /* Initialize ring buffer */ serial_io.start = serial_io_buffer; serial_io.end = serial_io_buffer; /* Install interrupt vector */ /* Note: the interrupt handler should be in the same code */ /* segment as this function. We will use CS for */ /* the segment offset value. */ _dos_setvect(serial_io.int_number, serial_int); /* new handler */ /* Turn on DTR, RTS and OUT2 */ result = outp((serial_io.port+MCR_OFFSET), (DTR | RTS | OUT2)); /* Enable interrupt on serial port controller */ result = outp((serial_io.port+IER_OFFSET), 0x01); /* Set interrupt mask on 8259 */ config = inp(INTR_MASK); /* Get current 8259 mask */ result = outp(INTR_MASK, (config & ~serial_io.int_mask)); /* Set global message indices */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -