📄 ibmcom3.c
字号:
disable(); /* Interrupts off */
outportb(uart_lcr, /* Set up to load baud rate */
inportb(uart_lcr) | 0x80); /* divisor into UART */
outport(uart_data, divisor); /* Do so */
outportb(uart_lcr, /* Back to normal UART ops */
inportb(uart_lcr) & ~0x80);
enable(); /* Interrupts back on */
} /* End "comm installed" */
} /* End com_set_speed() */
/*****************************************************************************
* com_set_parity() *
*****************************************************************************
* DESCRIPTION: Sets the parity and stop bits. *
* *
* SYNOPSIS: void com_set_parity(enum par_code parity, int stop_bits); *
* int code; COM_NONE = 8 data bits, no parity *
* COM_EVEN = 7 data, even parity *
* COM_ODD = 7 data, odd parity *
* COM_ZERO = 7 data, parity bit = zero *
* COM_ONE = 7 data, parity bit = one *
* int stop_bits; Must be 1 or 2 *
* *
* REVISIONS: 18 OCT 89 - RAC - Translated from the Pascal *
*****************************************************************************/
const char lcr_vals[] = {
DATA8 + NOPAR,
DATA7 + EVNPAR,
DATA7 + ODDPAR,
DATA7 + STKPAR,
DATA7 + ZROPAR
} ;
void com_set_parity(enum par_code parity, int stop_bits) {
disable();
outportb(uart_lcr, lcr_vals[parity] | ((stop_bits == 2) ? STOP2 : STOP1));
enable();
} /* End com_set_parity() */
/*****************************************************************************
* com_raise_dtr() *
* com_lower_dtr() *
*****************************************************************************
* DESCRIPTION: These routines raise and lower the DTR line. Lowering DTR *
* causes most modems to hang up. *
* *
* REVISIONS: 18 OCT 89 - RAC - Transltated from the Pascal. *
*****************************************************************************/
void com_lower_dtr(void) {
if (com_installed) {
disable();
outportb(uart_mcr, inportb(uart_mcr) & ~DTR);
enable();
} /* End 'comm installed' */
} /* End com_raise_dtr() */
void com_raise_dtr(void) {
if (com_installed) {
disable();
outportb(uart_mcr, inportb(uart_mcr) | DTR);
enable();
} /* End 'comm installed' */
} /* End com_lower_dtr() */
/*****************************************************************************
* com_tx() *
* com_tx_string() *
*****************************************************************************
* DESCRIPTION: Transmit routines. com_tx() sends a single character by *
* waiting until the transmit buffer isn't full, then putting *
* the character into it. The interrupt driver will then send *
* the character once it is at the head of the transmit queue *
* and a transmit interrupt occurs. com_tx_string() sends a *
* string by repeatedly calling com_tx(). *
* *
* SYNOPSES: void com_tx(char c); Send the character c *
* void com_tx_string(char *s); Send the string s *
* *
* REVISIONS: 18 OCT 89 - RAC - Translated from the Pascal *
*****************************************************************************/
void com_tx(char c) {
if (com_installed) {
while (!com_tx_ready()) ; /* Wait for non-full buffer */
disable(); /* Interrupts off */
tx_queue[tx_in++] = c; /* Stuff character in queue */
if (tx_in == TX_QUEUE_SIZE) tx_in = 0; /* Wrap index if needed */
tx_chars++; /* Number of char's in queue */
outportb(uart_ier, /* Enable UART tx interrupt */
inportb(uart_ier) | THRE);
enable(); /* Interrupts back on */
} /* End 'comm installed' */
} /* End com_tx() */
void com_tx_string(char *s) {
while (*s) com_tx(*s++); /* Send the string! */
} /* End com_tx_string() */
/*****************************************************************************
* com_rx() *
*****************************************************************************
* DESCRIPTION: Returns the next character from the receive buffer, or a *
* NULL character ('\0') if the buffer is empty. *
* *
* SYNOPSIS: c = com_rx(); *
* char c; The returned character *
* *
* REVISIONS: 18 OCT 89 - RAC - Translated from the Pascal. *
*****************************************************************************/
char com_rx(void) {
char rv; /* Local temp */
if (!rx_chars || !com_installed) /* Return NULL if receive */
return '\0'; /* buffer is empty */
disable(); /* Interrupts off */
rv = rx_queue[rx_out++]; /* Grab char from queue */
if (rx_out == RX_QUEUE_SIZE) /* Wrap index if needed */
rx_out = 0;
rx_chars--; /* One less char in queue */
enable(); /* Interrupts back on */
return rv; /* The answer! */
} /* End com_rx() */
char com_rx2(void) {
char rv; /* Local temp */
do {
} while (!rx_chars || !com_installed); /* Return NULL if receive */
/* buffer is empty */
disable(); /* Interrupts off */
rv = rx_queue[rx_out++]; /* Grab char from queue */
if (rx_out == RX_QUEUE_SIZE) /* Wrap index if needed */
rx_out = 0;
rx_chars--; /* One less char in queue */
enable(); /* Interrupts back on */
return rv; /* The answer! */
} /* End com_rx() */
/*****************************************************************************
* Queue Status Routines *
*****************************************************************************
* DESCRIPTION: Small routines to return status of the transmit and receive *
* queues. *
* *
* REVISIONS: 18 OCT 89 - RAC - Translated from the Pascal. *
*****************************************************************************/
int com_tx_ready(void) { /* Return TRUE if the */
return ((tx_chars < TX_QUEUE_SIZE) || /* transmit queue can */
(!com_installed)); /* accept a character */
} /* End com_tx_ready() */
int com_tx_empty(void) { /* Return TRUE if the */
return (!tx_chars || (!com_installed)); /* transmit queue is empty */
} /* End com_tx_empty() */
int com_rx_empty(void) { /* Return TRUE if the */
return (!rx_chars || (!com_installed)); /* receive queue is empty */
} /* End com_tx_empty() */
/*****************************************************************************
* com_flush_tx() *
* com_flush_rx() *
*****************************************************************************
* DESCRIPTION: Buffer flushers! These guys just initialize the transmit *
* and receive queues (respectively) to their empty state. *
* *
* REVISIONS: 18 OCT 89 - RAC - Translated from the Pascal *
*****************************************************************************/
void com_flush_tx() { disable(); tx_chars = tx_in = tx_out = 0; enable(); }
void com_flush_rx() { disable(); rx_chars = rx_in = rx_out = 0; enable(); }
/*****************************************************************************
* com_carrier() *
*****************************************************************************
* DESCRIPTION: Returns TRUE if a carrier is present. *
* *
* REVISIONS: 18 OCT 89 - RAC - Translated from the Pascal. *
*****************************************************************************/
int com_carrier(void) {
return com_installed && (inportb(uart_msr) & RLSD);
} /* End com_carrier() */
/*****************************************************************************
* com_interrupt_driver() *
*****************************************************************************
* DESCRIPTION: Handles communications interrupts. The UART will interrupt *
* whenever a character has been received or when it is ready *
* to transmit another character. This routine responds by *
* sticking received characters into the receive queue and *
* yanking characters to be transmitted from the transmit queue *
* *
* REVISIOSN: 18 OCT 89 - RAC - Translated from the Pascal. *
*****************************************************************************/
void interrupt com_interrupt_driver() {
char iir; /* Local copy if IIR */
char c; /* Local character variable */
/* While bit 0 of the IIR is 0, there remains an interrupt to process */
while (!((iir = inportb(uart_iir)) & 1)) { /* While there is an int ... */
switch (iir) { /* Branch on interrupt type */
case 0: /* Modem status interrupt */
inportb(uart_msr); /* Just clear the interrupt */
break;
case 2: /* Transmit register empty */
/*****************************************************************************
* NOTE: The test of the line status register is to see if the transmit *
* holding register is truly empty. Some UARTS seem to cause *
* transmit interrupts when the holding register isn't empty, *
* causing transmitted characters to be lost. *
*****************************************************************************/
if (tx_chars <= 0) /* If tx buffer empty, turn */
outportb(uart_ier, /* off transmit interrupts */
inportb(uart_ier) & ~2);
else { /* Tx buffer not empty */
if (inportb(uart_lsr) & TXR) {
outportb(uart_data, tx_queue[tx_out++]);
if (tx_out == TX_QUEUE_SIZE)
tx_out = 0;
tx_chars--;
}
} /* End 'tx buffer not empty */
break;
case 4: /* Received data interrupt */
c = inportb(uart_data); /* Grab received character */
if (rx_chars < RX_QUEUE_SIZE) { /* If queue not full, save */
rx_queue[rx_in++] = c; /* the new character */
if (rx_in == RX_QUEUE_SIZE) /* Wrap index if needed */
rx_in = 0;
rx_chars++; /* Count the new character */
} /* End queue not full */
break;
case 6: /* Line status interrupt */
inportb(uart_lsr); /* Just clear the interrupt */
break;
} /* End switch */
} /* End 'is an interrupt' */
outportb(0x20, 0x20); /* Send EOI to 8259 */
} /* End com_interrupt_driver() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -