version 1.1.1.1, 2008/06/03 10:38:41 |
version 1.1.1.1.2.1, 2008/08/13 17:12:23 |
|
|
#include <driver.h> |
#include <driver.h> |
#include <sys/signal.h> |
#include <sys/signal.h> |
#include <sys/tty.h> |
#include <sys/tty.h> |
#include <sys/ttycom.h> |
|
#include <sys/termios.h> |
#include <sys/termios.h> |
|
|
#define FREAD 0x0001 |
#define FREAD 0x0001 |
|
|
*/ |
*/ |
#define ttyq_next(i) (((i) + 1) & (TTYQ_SIZE - 1)) |
#define ttyq_next(i) (((i) + 1) & (TTYQ_SIZE - 1)) |
#define ttyq_prev(i) (((i) - 1) & (TTYQ_SIZE - 1)) |
#define ttyq_prev(i) (((i) - 1) & (TTYQ_SIZE - 1)) |
#define ttyq_full(q) ((q)->count >= TTYQ_SIZE) |
#define ttyq_full(q) ((q)->tq_count >= TTYQ_SIZE) |
#define ttyq_empty(q) ((q)->count == 0) |
#define ttyq_empty(q) ((q)->tq_count == 0) |
|
|
/* |
/* |
* Get a character from a queue. |
* Get a character from a queue. |
|
|
if (ttyq_empty(tq)) |
if (ttyq_empty(tq)) |
return -1; |
return -1; |
irq_lock(); |
irq_lock(); |
c = tq->buf[tq->head]; |
c = tq->tq_buf[tq->tq_head]; |
tq->head = ttyq_next(tq->head); |
tq->tq_head = ttyq_next(tq->tq_head); |
tq->count--; |
tq->tq_count--; |
irq_unlock(); |
irq_unlock(); |
return c; |
return c; |
} |
} |
|
|
if (ttyq_full(tq)) |
if (ttyq_full(tq)) |
return; |
return; |
irq_lock(); |
irq_lock(); |
tq->buf[tq->tail] = c; |
tq->tq_buf[tq->tq_tail] = c; |
tq->tail = ttyq_next(tq->tail); |
tq->tq_tail = ttyq_next(tq->tq_tail); |
tq->count++; |
tq->tq_count++; |
irq_unlock(); |
irq_unlock(); |
} |
} |
|
|
|
|
if (ttyq_empty(tq)) |
if (ttyq_empty(tq)) |
return -1; |
return -1; |
irq_lock(); |
irq_lock(); |
tq->tail = ttyq_prev(tq->tail); |
tq->tq_tail = ttyq_prev(tq->tq_tail); |
c = tq->buf[tq->tail]; |
c = tq->tq_buf[tq->tq_tail]; |
tq->count--; |
tq->tq_count--; |
irq_unlock(); |
irq_unlock(); |
return c; |
return c; |
} |
} |
|
|
/* |
/* |
* Start output. |
* Start output. |
*/ |
*/ |
void |
static void |
tty_start(struct tty *tp) |
tty_start(struct tty *tp) |
{ |
{ |
|
|
|
|
/* |
/* |
* Flush tty read and/or write queues, notifying anyone waiting. |
* Flush tty read and/or write queues, notifying anyone waiting. |
*/ |
*/ |
void |
static void |
tty_flush(struct tty *tp, int rw) |
tty_flush(struct tty *tp, int rw) |
{ |
{ |
|
|
|
|
} |
} |
|
|
/* |
/* |
* Read |
* Process a read call on a tty device. |
*/ |
*/ |
int |
int |
tty_read(struct tty *tp, char *buf, size_t *nbytes) |
tty_read(struct tty *tp, char *buf, size_t *nbyte) |
{ |
{ |
unsigned char *cc; |
unsigned char *cc; |
struct tty_queue *qp; |
struct tty_queue *qp; |
|
|
if (rc == SLP_INTR) |
if (rc == SLP_INTR) |
return EINTR; |
return EINTR; |
} |
} |
while (count < *nbytes) { |
while (count < *nbyte) { |
if ((c = ttyq_getc(qp)) == -1) |
if ((c = ttyq_getc(qp)) == -1) |
break; |
break; |
count++; |
|
if (c == cc[VEOF] && (lflag & ICANON)) |
if (c == cc[VEOF] && (lflag & ICANON)) |
break; |
break; |
*buf = c; |
count++; |
|
if (umem_copyout(&c, buf, 1)) |
|
return EFAULT; |
if ((lflag & ICANON) && (c == '\n' || c == cc[VEOL])) |
if ((lflag & ICANON) && (c == '\n' || c == cc[VEOL])) |
break; |
break; |
buf++; |
buf++; |
} |
} |
*nbytes = count; |
*nbyte = count; |
return 0; |
return 0; |
} |
} |
|
|
/* |
/* |
* Write |
* Process a write call on a tty device. |
*/ |
*/ |
int |
int |
tty_write(struct tty *tp, char *buf, size_t *nbyte) |
tty_write(struct tty *tp, char *buf, size_t *nbyte) |
{ |
{ |
size_t remain, count = 0; |
size_t remain, count = 0; |
|
int c; |
|
|
remain = *nbyte; |
remain = *nbyte; |
while (remain > 0) { |
while (remain > 0) { |
if (tp->t_outq.count >= TTYQ_HIWAT) { |
if (tp->t_outq.tq_count >= TTYQ_HIWAT) { |
tty_start(tp); |
tty_start(tp); |
continue; |
continue; |
} |
} |
tty_output(*buf, tp); |
if (umem_copyin(buf, &c, 1)) |
|
return EFAULT; |
|
tty_output(c, tp); |
buf++; |
buf++; |
remain--; |
remain--; |
count++; |
count++; |
|
|
case TIOCSETAW: |
case TIOCSETAW: |
case TIOCSETAF: |
case TIOCSETAF: |
tty_flush(tp, flags); |
tty_flush(tp, flags); |
/* fallthrouth */ |
/* FALLTHROUGH */ |
case TIOCSETA: |
case TIOCSETA: |
if (umem_copyin(data, &tp->t_termios, |
if (umem_copyin(data, &tp->t_termios, |
sizeof(struct termios))) |
sizeof(struct termios))) |
|
|
{ |
{ |
|
|
/* We support only one tty device */ |
/* We support only one tty device */ |
if (tty_dev != NULL_DEVICE) |
if (tty_dev != DEVICE_NULL) |
return -1; |
return -1; |
|
|
/* Create TTY device as an alias of the registered device. */ |
/* Create TTY device as an alias of the registered device. */ |
tty_dev = device_create(io, "tty", DF_CHR); |
tty_dev = device_create(io, "tty", DF_CHR); |
if (tty_dev == NULL_DEVICE) |
if (tty_dev == DEVICE_NULL) |
return -1; |
return -1; |
|
|
/* Initialize tty */ |
/* Initialize tty */ |