/** * TTY's interrupt handler. Functinality depends on status of TTY's * status port. On WIRQ status writes internal buffer from * tty_real_device_t data structure to data port. On RIRQ * status reads data from data port to the internal buffer. * Implements read from the gbd interface. * * @param device Pointer to the TTY device. */ void tty_interrupt_handle(device_t *device) { volatile tty_io_area_t *iobase = (tty_io_area_t *)device->io_address; volatile tty_real_device_t *tty_rd = (tty_real_device_t *)device->real_device; if(TTY_STATUS_WIRQ(iobase->status)) { spinlock_acquire(tty_rd->slock); iobase->command = TTY_COMMAND_WIRQD; iobase->command = TTY_COMMAND_WIRQ; while(!TTY_STATUS_WBUSY(iobase->status) && tty_rd->write_count > 0) { iobase->command = TTY_COMMAND_WIRQ; iobase->data = tty_rd->write_buf[tty_rd->write_head]; tty_rd->write_head = (tty_rd->write_head + 1) % TTY_BUF_SIZE; tty_rd->write_count--; } iobase->command = TTY_COMMAND_WIRQE; if (tty_rd->write_count == 0) sleepq_wake_all((void *)tty_rd->write_buf); spinlock_release(tty_rd->slock); } if(TTY_STATUS_RIRQ(iobase->status)) { spinlock_acquire(tty_rd->slock); iobase->command = TTY_COMMAND_RIRQ; if (TTY_STATUS_ERROR(iobase->status)) KERNEL_PANIC("Could not issue RIRQ to TTY."); while (TTY_STATUS_RAVAIL(iobase->status)) { char data = iobase->data; int index; if (tty_rd->read_count > TTY_BUF_SIZE) continue; index = (tty_rd->read_head + tty_rd->read_count) % TTY_BUF_SIZE; tty_rd->read_buf[index] = data; tty_rd->read_count++; } spinlock_release(tty_rd->slock); sleepq_wake_all((void *)tty_rd->read_buf); } }
/** * Gets one character from the TTY. * * @return The character read from the TTY. If the * \texttt{polltty_iobase} is invalid, returns 0. * */ int polltty_getchar() { /* Check that the iobase is valid */ if (polltty_iobase == 0) return 0; /* Wait until there is a character available */ while(TTY_STATUS_RAVAIL(polltty_iobase->status) == 0); /* Clear interrupt */ polltty_iobase->command = TTY_COMMAND_RIRQ; return polltty_iobase->data; }