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"
10 #define QUEUE_BUFSIZE 8
14 enum intr_level old_level;
17 struct thread *not_full, *not_empty;
18 uint8_t buf[QUEUE_BUFSIZE];
22 static struct queue recv_queue, xmit_queue;
23 static bool polled_io;
25 static void set_serial (int bps, int bits, enum parity_type parity, int stop);
26 static void update_ier (void);
27 static intr_handler_func serial_interrupt;
29 static void queue_init (struct queue *, const char *);
30 static void queue_lock (struct queue *);
31 static void queue_unlock (struct queue *);
32 static bool queue_empty (const struct queue *);
33 static bool queue_full (const struct queue *);
34 static uint8_t queue_getc (struct queue *);
35 static void queue_putc (struct queue *, uint8_t);
37 /* Initializes the serial port device for polling mode.
38 Polling mode busy-waits for the serial port to become free
39 before writing to it. It's slow, but until interrupts have
40 been initialized it's all we can do. */
42 serial_init_poll (void)
46 outb (IER_REG, 0); /* Turn off all interrupts. */
47 outb (FCR_REG, 0); /* Disable FIFO. */
48 set_serial (9600, 8, NONE, 1); /* 9600 bps, N-8-1. */
49 outb (MCR_REG, 8); /* Turn on OUT2 output line. */
52 /* Initializes the serial port device for queued interrupt-driven
53 I/O. With interrupt-driven I/O we don't waste CPU time
54 waiting for the serial device to become ready. */
56 serial_init_queue (void)
60 queue_init (&recv_queue, "serial recv");
61 queue_init (&xmit_queue, "serial xmit");
62 intr_register (0x20 + 4, 0, INTR_OFF, serial_interrupt, "serial");
65 static void putc_poll (uint8_t);
66 static void putc_queue (uint8_t);
68 /* Sends BYTE to the serial port. */
70 serial_putc (uint8_t byte)
72 if (polled_io || intr_context ())
79 putc_poll (uint8_t byte)
81 while ((inb (LSR_REG) & LSR_THRE) == 0)
87 putc_queue (uint8_t byte)
89 queue_lock (&xmit_queue);
91 queue_putc (&xmit_queue, byte);
94 queue_unlock (&xmit_queue);
97 /* Reads and returns a byte from the serial port. */
102 queue_lock (&recv_queue);
105 byte = queue_getc (&recv_queue);
108 queue_unlock (&recv_queue);
112 /* Configures the first serial port for BPS bits per second,
113 BITS bits per byte, the given PARITY, and STOP stop bits. */
115 set_serial (int bps, int bits, enum parity_type parity, int stop)
117 int baud_base = 1843200 / 16; /* Base rate of 16550A. */
118 uint16_t divisor = baud_base / bps; /* Clock rate divisor. */
121 outb (LCR_REG, make_lcr (bits, parity, stop, false, true));
124 outb (LS_REG, divisor & 0xff);
125 outb (MS_REG, divisor >> 8);
128 outb (LCR_REG, make_lcr (bits, parity, stop, false, false));
131 /* Update interrupt enable register.
132 If our transmit queue is empty, turn off transmit interrupt.
133 If our receive queue is full, turn off receive interrupt. */
139 ASSERT (intr_get_level () == INTR_OFF);
141 if (!queue_empty (&xmit_queue))
143 if (!queue_full (&recv_queue))
149 serial_interrupt (struct intr_frame *f UNUSED)
151 /* As long as we have space in our buffer for a byte,
152 and the hardware has a byte to give us,
154 while (!queue_full (&recv_queue) && (inb (LSR_REG) & LSR_DR) != 0)
156 uint8_t byte = inb (RBR_REG);
157 //outb (0x0402, byte);
158 queue_putc (&recv_queue, byte);
161 /* As long as we have a byte to transmit,
162 and the hardware is ready to accept a byte for transmission,
164 while (!queue_empty (&xmit_queue) && (inb (LSR_REG) & LSR_THRE) != 0)
165 outb (THR_REG, queue_getc (&xmit_queue));
167 /* Update interrupt enable register based on queue status. */
171 static int next (int pos);
172 static bool owned_by_current_thread (const struct queue *);
173 static void wait (struct queue *q, struct thread **waiter);
174 static void signal (struct queue *q, struct thread **waiter);
177 queue_init (struct queue *q, const char *name)
179 lock_init (&q->lock, name);
180 q->not_full = q->not_empty = NULL;
181 q->head = q->tail = 0;
185 queue_lock (struct queue *q)
187 lock_acquire (&q->lock);
188 q->old_level = intr_disable ();
192 queue_unlock (struct queue *q)
194 ASSERT (!intr_context ());
195 ASSERT (owned_by_current_thread (q));
197 lock_release (&q->lock);
198 intr_set_level (q->old_level);
202 queue_empty (const struct queue *q)
204 ASSERT (intr_get_level () == INTR_OFF);
205 return q->head == q->tail;
209 queue_full (const struct queue *q)
211 ASSERT (intr_get_level () == INTR_OFF);
212 return next (q->head) == q->tail;
216 queue_getc (struct queue *q)
220 ASSERT (owned_by_current_thread (q));
221 while (queue_empty (q))
222 wait (q, &q->not_empty);
224 byte = q->buf[q->tail];
225 q->tail = next (q->tail);
226 signal (q, &q->not_full);
231 queue_putc (struct queue *q, uint8_t byte)
233 ASSERT (owned_by_current_thread (q));
234 while (queue_full (q))
235 wait (q, &q->not_full);
237 q->buf[q->head] = byte;
238 q->head = next (q->head);
239 signal (q, &q->not_empty);
245 return (pos + 1) % QUEUE_BUFSIZE;
249 owned_by_current_thread (const struct queue *q)
251 return (intr_context ()
252 || (lock_held_by_current_thread (&q->lock)
253 && intr_get_level () == INTR_OFF));
257 wait (struct queue *q, struct thread **waiter)
259 ASSERT (!intr_context ());
260 ASSERT (owned_by_current_thread (q));
262 *waiter = thread_current ();
267 signal (struct queue *q, struct thread **waiter)
269 ASSERT (owned_by_current_thread (q));
273 thread_unblock (*waiter);