#include #include #include #include #include #include #include #include #include #define NRTTY \ (sizeof(ttys) / sizeof(struct tty_struct*)) static struct tty_struct *ttys[] = { NULL, &tty_rs }; /* check if the buffer's empty and if so, go to sleep */ static int sleep_while_empty(struct tty_queue *q) { if(q->pread != q->pwrite) return 0; cli(); while(1) { if(q->pread == q->pwrite) interruptible_sleep_on(&q->waiting); /* check again to see if anything was read, or we were interrupted */ if(q->pread == q->pwrite) { sti(); return -1; } sti(); return 0; } } ssize_t tty_read(unsigned tty, void *buf, size_t len) { size_t i; char *b = buf; struct tty_queue *q = &ttys[tty]->rqueue; if(tty > NRTTY || ttys[tty] == NULL) return -1; if(len == 0) return 0; if(len > SSIZE_MAX) len = SSIZE_MAX; for(i = 0; i < len; i++) { /* check if the buffer's empty and if so, go to sleep */ if(sleep_while_empty(q) < 0) { if(i == 0) return -EINTR; return i; } *b++ = q->buf[q->pread]; q->pread = q->pread + 1 % TTY_BUF_SIZE; } return len; } void tty_init(void) { int i; for(i = 0; i < NRTTY; i++) { if(!ttys[i]) continue; memset(&ttys[i]->rqueue, 0, sizeof(struct tty_queue)); memset(&ttys[i]->wqueue, 0, sizeof(struct tty_queue)); ttys[i]->rqueue.pwrite = 1; ttys[i]->wqueue.pwrite = 1; if(ttys[i]->init) ttys[i]->init(); } }