/*! Update interrupt enable register. */ static void write_ier(void) { uint8_t ier = 0; ASSERT(intr_get_level() == INTR_OFF); /* Enable transmit interrupt if we have any characters to transmit. */ if (!intq_empty(&txq)) ier |= IER_XMIT; /* Enable receive interrupt if we have room to store any characters we receive. */ if (!input_full()) ier |= IER_RECV; outb(IER_REG, ier); }
/* Removes a byte from Q and returns it. Q must not be empty if called from an interrupt handler. Otherwise, if Q is empty, first sleeps until a byte is added. */ uint8_t intq_getc (struct intq *q) { uint8_t byte; ASSERT (intr_get_level () == INTR_OFF); while (intq_empty (q)) { ASSERT (!intr_context ()); lock_acquire (&q->lock); wait (q, &q->not_empty); lock_release_with_preemption (&q->lock); } byte = q->buf[q->tail]; q->tail = next (q->tail); signal (q, &q->not_full); return byte; }
/* Returns the position after POS within an intq. */ static int next (int pos) { return (pos + 1) % INTQ_BUFSIZE; } /* WAITER must be the address of Q's not_empty or not_full member. Waits until the given condition is true. */ static void wait (struct intq *q UNUSED, struct thread **waiter) { ASSERT (!intr_context ()); ASSERT (intr_get_level () == INTR_OFF); ASSERT ((waiter == &q->not_empty && intq_empty (q)) || (waiter == &q->not_full && intq_full (q))); *waiter = thread_current (); thread_block (); } /* WAITER must be the address of Q's not_empty or not_full member, and the associated condition must be true. If a thread is waiting for the condition, wakes it up and resets the waiting thread. */ static void signal (struct intq *q UNUSED, struct thread **waiter) { ASSERT (intr_get_level () == INTR_OFF); ASSERT ((waiter == &q->not_empty && !intq_empty (q))
/*! Flushes anything in the serial buffer out the port in polling mode. */ void serial_flush(void) { enum intr_level old_level = intr_disable(); while (!intq_empty(&txq)) putc_poll(intq_getc(&txq)); intr_set_level(old_level); }