1 #include "devices/serial.h"
3 #include "devices/16550a.h"
4 #include "devices/timer.h"
5 #include "threads/io.h"
6 #include "threads/interrupt.h"
7 #include "threads/synch.h"
8 #include "threads/thread.h"
11 #include "devices/vga.h"
14 #define QUEUE_BUFSIZE 8
18 enum intr_level old_level;
21 struct thread *not_full, *not_empty;
22 uint8_t buf[QUEUE_BUFSIZE];
26 static struct queue recv_queue, xmit_queue;
27 static int init_level;
29 static void set_serial (int bps, int bits, enum parity_type parity, int stop);
30 static void update_ier (void);
31 static intr_handler_func serial_interrupt;
33 static void queue_init (struct queue *, const char *);
34 static void queue_lock (struct queue *);
35 static void queue_unlock (struct queue *);
36 static bool queue_empty (const struct queue *);
37 static bool queue_full (const struct queue *);
38 static uint8_t queue_getc (struct queue *);
39 static void queue_putc (struct queue *, uint8_t);
41 /* Initializes the serial port device. */
43 serial_init (int level)
49 outb (IER_REG, 0); /* Turn off all interrupts. */
50 outb (FCR_REG, 0); /* Disable FIFO. */
51 set_serial (9600, 8, NONE, 1); /* 9600 bps, N-8-1. */
52 outb (MCR_REG, 8); /* Turn off output lines. */
56 /* Prepare interrupt handler. */
57 queue_init (&recv_queue, "serial recv");
58 queue_init (&xmit_queue, "serial xmit");
59 intr_register (0x20 + 4, 0, INTR_OFF, serial_interrupt, "serial");
60 outb (IER_REG, IER_RECV);
68 static void putc_busy_wait (uint8_t);
69 static void putc_queue (uint8_t);
71 /* Sends BYTE to the serial port. */
73 serial_putc (uint8_t byte)
75 if (init_level == 1 || intr_context ())
76 putc_busy_wait (byte);
82 putc_busy_wait (uint8_t byte)
84 while ((inb (LSR_REG) & LSR_THRE) == 0)
90 putc_queue (uint8_t byte)
92 queue_lock (&xmit_queue);
94 queue_putc (&xmit_queue, byte);
97 queue_unlock (&xmit_queue);
100 /* Reads and returns a byte from the serial port. */
105 queue_lock (&recv_queue);
108 byte = queue_getc (&recv_queue);
111 queue_unlock (&recv_queue);
115 /* Configures the first serial port for BPS bits per second,
116 BITS bits per byte, the given PARITY, and STOP stop bits. */
118 set_serial (int bps, int bits, enum parity_type parity, int stop)
120 int baud_base = 1843200 / 16; /* Base rate of 16550A. */
121 uint16_t divisor = baud_base / bps; /* Clock rate divisor. */
124 outb (LCR_REG, make_lcr (bits, parity, stop, false, true));
127 outb (LS_REG, divisor & 0xff);
128 outb (MS_REG, divisor >> 8);
131 outb (LCR_REG, make_lcr (bits, parity, stop, false, false));
134 /* Update interrupt enable register.
135 If our transmit queue is empty, turn off transmit interrupt.
136 If our receive queue is full, turn off receive interrupt. */
142 ASSERT (intr_get_level () == INTR_OFF);
144 if (!queue_empty (&xmit_queue))
146 if (!queue_full (&recv_queue))
152 serial_interrupt (struct intr_frame *f UNUSED)
154 /* As long as the hardware is ready to take a byte
155 and we have a byte to give it,
157 while ((inb (LSR_REG) & LSR_THRE) != 0 && !queue_empty (&xmit_queue))
158 outb (THR_REG, queue_getc (&xmit_queue));
160 /* As long as the hardware has a byte to give us
161 and we have space in our buffer for a byte,
163 while ((inb (LSR_REG) & LSR_DR) != 0 && !queue_full (&recv_queue))
164 queue_putc (&recv_queue, inb (RBR_REG));
166 /* Update interrupt enable register based on queue status. */
170 static size_t next (size_t pos);
171 static bool owned_by_current_thread (const struct queue *);
172 static void wait (struct queue *q, struct thread **waiter);
173 static void signal (struct queue *q, struct thread **waiter);
176 queue_init (struct queue *q, const char *name)
178 lock_init (&q->lock, name);
179 q->not_full = q->not_empty = NULL;
180 q->head = q->tail = 0;
184 queue_lock (struct queue *q)
186 lock_acquire (&q->lock);
187 q->old_level = intr_disable ();
191 queue_unlock (struct queue *q)
193 ASSERT (!intr_context ());
194 ASSERT (owned_by_current_thread (q));
196 lock_release (&q->lock);
197 intr_set_level (q->old_level);
201 queue_empty (const struct queue *q)
203 ASSERT (intr_get_level () == INTR_OFF);
204 return q->head == q->tail;
208 queue_full (const struct queue *q)
210 ASSERT (intr_get_level () == INTR_OFF);
211 return q->head == next (q->tail);
215 queue_getc (struct queue *q)
219 ASSERT (owned_by_current_thread (q));
220 while (queue_empty (q))
221 wait (q, &q->not_empty);
223 byte = q->buf[q->head];
224 q->head = next (q->head);
225 signal (q, &q->not_full);
230 queue_putc (struct queue *q, uint8_t byte)
232 ASSERT (intr_get_level () == INTR_OFF);
234 ASSERT (owned_by_current_thread (q));
235 while (queue_full (q))
236 wait (q, &q->not_full);
238 q->buf[q->tail] = byte;
239 q->tail = next (q->tail);
240 signal (q, &q->not_empty);
246 return (pos + 1) % QUEUE_BUFSIZE;
250 owned_by_current_thread (const struct queue *q)
252 return (intr_context ()
253 || (lock_held_by_current_thread (&q->lock)
254 && intr_get_level () == INTR_OFF));
258 wait (struct queue *q, struct thread **waiter)
260 ASSERT (!intr_context ());
261 ASSERT (owned_by_current_thread (q));
263 *waiter = thread_current ();
268 signal (struct queue *q, struct thread **waiter)
270 ASSERT (owned_by_current_thread (q));
274 thread_unblock (*waiter);