[Krafton Jungle] PintOS 2.0.0
크래프톤 정글 PintOS
 
Loading...
Searching...
No Matches
serial.c File Reference
#include "devices/serial.h"
#include <debug.h>
#include "devices/input.h"
#include "devices/intq.h"
#include "devices/timer.h"
#include "threads/io.h"
#include "threads/interrupt.h"
#include "threads/synch.h"
#include "threads/thread.h"
Include dependency graph for serial.c:

Macros

#define IO_BASE   0x3f8
 
#define RBR_REG   (IO_BASE + 0) /* Receiver Buffer Reg. (read-only). */
 
#define THR_REG   (IO_BASE + 0) /* Transmitter Holding Reg. (write-only). */
 
#define IER_REG   (IO_BASE + 1) /* Interrupt Enable Reg.. */
 
#define LS_REG   (IO_BASE + 0) /* Divisor Latch (LSB). */
 
#define MS_REG   (IO_BASE + 1) /* Divisor Latch (MSB). */
 
#define IIR_REG   (IO_BASE + 2) /* Interrupt Identification Reg. (read-only) */
 
#define FCR_REG   (IO_BASE + 2) /* FIFO Control Reg. (write-only). */
 
#define LCR_REG   (IO_BASE + 3) /* Line Control Register. */
 
#define MCR_REG   (IO_BASE + 4) /* MODEM Control Register. */
 
#define LSR_REG   (IO_BASE + 5) /* Line Status Register (read-only). */
 
#define IER_RECV   0x01 /* Interrupt when data received. */
 
#define IER_XMIT   0x02 /* Interrupt when transmit finishes. */
 
#define LCR_N81   0x03 /* No parity, 8 data bits, 1 stop bit. */
 
#define LCR_DLAB   0x80 /* Divisor Latch Access Bit (DLAB). */
 
#define MCR_OUT2   0x08 /* Output line 2. */
 
#define LSR_DR   0x01 /* Data Ready: received data byte is in RBR. */
 
#define LSR_THRE   0x20 /* THR Empty. */
 

Enumerations

enum  { UNINIT , POLL , QUEUE }
 

Functions

static void set_serial (int bps)
 
static void putc_poll (uint8_t)
 
static void write_ier (void)
 
static void init_poll (void)
 
void serial_init_queue (void)
 
void serial_putc (uint8_t byte)
 
void serial_flush (void)
 
void serial_notify (void)
 
static void serial_interrupt (struct intr_frame *f UNUSED)
 

Variables

static enum { ... }  mode
 
static struct intq txq
 
static intr_handler_func serial_interrupt
 

Macro Definition Documentation

◆ FCR_REG

#define FCR_REG   (IO_BASE + 2) /* FIFO Control Reg. (write-only). */

◆ IER_RECV

#define IER_RECV   0x01 /* Interrupt when data received. */

◆ IER_REG

#define IER_REG   (IO_BASE + 1) /* Interrupt Enable Reg.. */

◆ IER_XMIT

#define IER_XMIT   0x02 /* Interrupt when transmit finishes. */

◆ IIR_REG

#define IIR_REG   (IO_BASE + 2) /* Interrupt Identification Reg. (read-only) */

◆ IO_BASE

#define IO_BASE   0x3f8

◆ LCR_DLAB

#define LCR_DLAB   0x80 /* Divisor Latch Access Bit (DLAB). */

◆ LCR_N81

#define LCR_N81   0x03 /* No parity, 8 data bits, 1 stop bit. */

◆ LCR_REG

#define LCR_REG   (IO_BASE + 3) /* Line Control Register. */

◆ LS_REG

#define LS_REG   (IO_BASE + 0) /* Divisor Latch (LSB). */

◆ LSR_DR

#define LSR_DR   0x01 /* Data Ready: received data byte is in RBR. */

◆ LSR_REG

#define LSR_REG   (IO_BASE + 5) /* Line Status Register (read-only). */

◆ LSR_THRE

#define LSR_THRE   0x20 /* THR Empty. */

◆ MCR_OUT2

#define MCR_OUT2   0x08 /* Output line 2. */

◆ MCR_REG

#define MCR_REG   (IO_BASE + 4) /* MODEM Control Register. */

◆ MS_REG

#define MS_REG   (IO_BASE + 1) /* Divisor Latch (MSB). */

◆ RBR_REG

#define RBR_REG   (IO_BASE + 0) /* Receiver Buffer Reg. (read-only). */

◆ THR_REG

#define THR_REG   (IO_BASE + 0) /* Transmitter Holding Reg. (write-only). */

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
UNINIT 
POLL 
QUEUE 
52{ UNINIT, POLL, QUEUE } mode;
@ QUEUE
Definition: serial.c:52
@ UNINIT
Definition: serial.c:52
@ POLL
Definition: serial.c:52
static enum @0 mode

Function Documentation

◆ init_poll()

static void init_poll ( void  )
static
67 {
68 ASSERT (mode == UNINIT);
69 outb (IER_REG, 0); /* Turn off all interrupts. */
70 outb (FCR_REG, 0); /* Disable FIFO. */
71 set_serial (115200); /* 115.2 kbps, N-8-1. */
72 outb (MCR_REG, MCR_OUT2); /* Required to enable interrupts. */
73 intq_init (&txq);
74 mode = POLL;
75}
#define ASSERT(CONDITION)
Definition: debug.h:30
void intq_init(struct intq *q)
Definition: intq.c:11
static void outb(uint16_t port, uint8_t data)
Definition: io.h:109
#define MCR_OUT2
Definition: serial.c:45
static struct intq txq
Definition: serial.c:55
#define FCR_REG
Definition: serial.c:31
#define IER_REG
Definition: serial.c:23
#define MCR_REG
Definition: serial.c:33
static void set_serial(int bps)
Definition: serial.c:148
Here is the call graph for this function:
Here is the caller graph for this function:

◆ putc_poll()

static void putc_poll ( uint8_t  byte)
static
188 {
190
191 while ((inb (LSR_REG) & LSR_THRE) == 0)
192 continue;
193 outb (THR_REG, byte);
194}
@ INTR_OFF
Definition: interrupt.h:9
enum intr_level intr_get_level(void)
Definition: interrupt.c:115
static uint8_t inb(uint16_t port)
Definition: io.h:49
#define LSR_REG
Definition: serial.c:34
#define THR_REG
Definition: serial.c:22
#define LSR_THRE
Definition: serial.c:49
Here is the call graph for this function:
Here is the caller graph for this function:

◆ serial_flush()

void serial_flush ( void  )
128 {
129 enum intr_level old_level = intr_disable ();
130 while (!intq_empty (&txq))
132 intr_set_level (old_level);
133}
enum intr_level intr_set_level(enum intr_level)
Definition: interrupt.c:130
enum intr_level intr_disable(void)
Definition: interrupt.c:151
intr_level
Definition: interrupt.h:8
bool intq_empty(const struct intq *q)
Definition: intq.c:19
uint8_t intq_getc(struct intq *q)
Definition: intq.c:36
static void putc_poll(uint8_t)
Definition: serial.c:188
Here is the call graph for this function:
Here is the caller graph for this function:

◆ serial_init_queue()

void serial_init_queue ( void  )
81 {
82 enum intr_level old_level;
83
84 if (mode == UNINIT)
85 init_poll ();
86 ASSERT (mode == POLL);
87
88 intr_register_ext (0x20 + 4, serial_interrupt, "serial");
89 mode = QUEUE;
90 old_level = intr_disable ();
91 write_ier ();
92 intr_set_level (old_level);
93}
void intr_register_ext(uint8_t vec, intr_handler_func *, const char *name)
Definition: interrupt.c:228
static intr_handler_func serial_interrupt
Definition: serial.c:60
static void init_poll(void)
Definition: serial.c:67
static void write_ier(void)
Definition: serial.c:167
Here is the call graph for this function:
Here is the caller graph for this function:

◆ serial_interrupt()

static void serial_interrupt ( struct intr_frame *f  UNUSED)
static
198 {
199 /* Inquire about interrupt in UART. Without this, we can
200 occasionally miss an interrupt running under QEMU. */
201 inb (IIR_REG);
202
203 /* As long as we have room to receive a byte, and the hardware
204 has a byte for us, receive a byte. */
205 while (!input_full () && (inb (LSR_REG) & LSR_DR) != 0)
207
208 /* As long as we have a byte to transmit, and the hardware is
209 ready to accept a byte for transmission, transmit a byte. */
210 while (!intq_empty (&txq) && (inb (LSR_REG) & LSR_THRE) != 0)
212
213 /* Update interrupt enable register based on queue status. */
214 write_ier ();
215}
bool input_full(void)
Definition: input.c:45
void input_putc(uint8_t key)
Definition: input.c:18
#define RBR_REG
Definition: serial.c:21
#define IIR_REG
Definition: serial.c:30
#define LSR_DR
Definition: serial.c:48
Here is the call graph for this function:

◆ serial_notify()

void serial_notify ( void  )
140 {
142 if (mode == QUEUE)
143 write_ier ();
144}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ serial_putc()

void serial_putc ( uint8_t  byte)
97 {
98 enum intr_level old_level = intr_disable ();
99
100 if (mode != QUEUE) {
101 /* If we're not set up for interrupt-driven I/O yet,
102 use dumb polling to transmit a byte. */
103 if (mode == UNINIT)
104 init_poll ();
105 putc_poll (byte);
106 } else {
107 /* Otherwise, queue a byte and update the interrupt enable
108 register. */
109 if (old_level == INTR_OFF && intq_full (&txq)) {
110 /* Interrupts are off and the transmit queue is full.
111 If we wanted to wait for the queue to empty,
112 we'd have to reenable interrupts.
113 That's impolite, so we'll send a character via
114 polling instead. */
116 }
117
118 intq_putc (&txq, byte);
119 write_ier ();
120 }
121
122 intr_set_level (old_level);
123}
void intq_putc(struct intq *q, uint8_t byte)
Definition: intq.c:58
bool intq_full(const struct intq *q)
Definition: intq.c:26
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_serial()

static void set_serial ( int  bps)
static
148 {
149 int base_rate = 1843200 / 16; /* Base rate of 16550A, in Hz. */
150 uint16_t divisor = base_rate / bps; /* Clock rate divisor. */
151
152 ASSERT (bps >= 300 && bps <= 115200);
153
154 /* Enable DLAB. */
156
157 /* Set data rate. */
158 outb (LS_REG, divisor & 0xff);
159 outb (MS_REG, divisor >> 8);
160
161 /* Reset DLAB. */
163}
#define LCR_DLAB
Definition: serial.c:42
#define MS_REG
Definition: serial.c:27
#define LCR_REG
Definition: serial.c:32
#define LCR_N81
Definition: serial.c:41
#define LS_REG
Definition: serial.c:26
unsigned short int uint16_t
Definition: stdint.h:23
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_ier()

static void write_ier ( void  )
static
167 {
168 uint8_t ier = 0;
169
171
172 /* Enable transmit interrupt if we have any characters to
173 transmit. */
174 if (!intq_empty (&txq))
175 ier |= IER_XMIT;
176
177 /* Enable receive interrupt if we have room to store any
178 characters we receive. */
179 if (!input_full ())
180 ier |= IER_RECV;
181
182 outb (IER_REG, ier);
183}
#define IER_XMIT
Definition: serial.c:38
#define IER_RECV
Definition: serial.c:37
unsigned char uint8_t
Definition: stdint.h:20
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ 

enum { ... } mode

◆ serial_interrupt

intr_handler_func serial_interrupt
static

◆ txq

struct intq txq
static