/* * Write or sendto a socket. We don't yet handle message addresses * sensible and that needs fixing */ arg_t net_write(struct socket * s, uint8_t flag) { usize_t n = 0; uint8_t p = 0; struct sockdata *sd = s->s_priv; irqflags_t irq; uint8_t st; irq = di(); while (1) { netstat = s->s_num; st = status(s); if (s->s_state == SS_CLOSED || (s->s_iflag & SI_SHUTW)) { udata.u_error = EPIPE; break; } /* Error or EOF */ if (st & 0xC0) break; /* Good status after a write means byte ok */ n += p; if (n == udata.u_count) { irqrestore(irq); return n; } /* Can we send more bytes ? */ p = 0; if (st & 2) { /* Count bytes sent. The byte we just loaded isn't sent until we check the status of it and it is clean */ p = 1; netdata = ugetc(udata.u_base++); continue; } s->s_iflag |= SI_THROTTLE; if (psleep_flags_io(&s->s_iflag, flag, &n)) { irqrestore(irq); return n; } di(); } /* It broke mummy ! */ irqrestore(irq); if (n) { s->s_error = udata.u_error; udata.u_error = 0; return n; } err_xlate(s); if (udata.u_error == EPIPE) ssig(udata.u_ptab, SIGPIPE); return -1; }
/* * Read or recvfrom a socket. We don't yet handle message addresses * sensibly and that needs fixing */ arg_t net_read(struct socket *s, uint8_t flag) { usize_t n = 0; struct sockdata *sd = s->s_priv; irqflags_t irq; uint8_t st; volatile uint8_t data; while (1) { irq = di(); netstat = s->s_num; st = status(s); /* Error */ if (st & 0xC0) break; if (s->s_state < SS_CONNECTED) { irqrestore(irq); udata.u_error = EINVAL; return -1; } /* We hit the EOF */ if (s->s_state > SS_CLOSEWAIT) break; /* Check our status */ /* Data ready */ if (st & 0x01) { data = netdata; /* Could be an error */ if (data == 0) { st = status(s); if (st & 0xC0) break; } uputc(data, udata.u_base++); n++; if (n < udata.u_count) continue; } if (n) break; s->s_iflag &= ~SI_DATA; if (psleep_flags_io(&s->s_iflag, flag, &n)) { irqrestore(irq); return -1; } } if (n) return n; if (st & 0x80) { err_xlate(s); return -1; } return 0; }
int tty_write(uint8_t minor, uint8_t rawflag, uint8_t flag) { struct tty *t; usize_t written = 0; uint8_t c; used(rawflag); used(flag); t = &ttydata[minor]; while (udata.u_count-- != 0) { for (;;) { /* Wait on the ^S/^Q flag */ if (t->flag & TTYF_DEAD) { udata.u_error = ENXIO; return -1; } if (!(t->flag & TTYF_STOP)) break; if (psleep_flags_io(&t->flag, flag, &written)) return written; jobcontrol_out(minor, t); } if (!(t->flag & TTYF_DISCARD)) { if (udata.u_sysio) c = *udata.u_base; else c = ugetc(udata.u_base); if (t->termios.c_oflag & OPOST) { if (c == '\n' && (t->termios.c_oflag & ONLCR)) tty_putc_wait(minor, '\r'); else if (c == '\r' && (t->termios.c_oflag & OCRNL)) c = '\n'; } tty_putc_wait(minor, c); } ++udata.u_base; ++written; } return written; }
int lpr_write(uint8_t minor, uint8_t rawflag, uint8_t flag) { used(minor); used(rawflag); /* Unusually for an 8bit micro the MicroBee has interrupt driven parallel managed via the Z80PIOA. It's not always used for a printer so we do need to fix interactions if we add other devices for that port and interlock them */ while(udata.u_done < udata.u_count) { /* Avoid IRQ race */ irqflags_t irq = di(); if (!lpready && psleep_flags_io(&lpready, flag)) { irqrestore(irq); break; } irqrestore(irq); lpready = 0; lpdata = ugetc(udata.u_base++); udata.u_done++; } return udata.u_done; }
int psleep_flags(void *p, unsigned char flags) { usize_t dummy = 0; return psleep_flags_io(p, flags, &dummy); }
int tty_read(uint8_t minor, uint8_t rawflag, uint8_t flag) { usize_t nread; unsigned char c; struct s_queue *q; struct tty *t; used(rawflag); used(flag); /* shut up compiler */ q = &ttyinq[minor]; t = &ttydata[minor]; nread = 0; while (nread < udata.u_count) { for (;;) { if ((t->flag & TTYF_DEAD)&&(!q->q_count)) { udata.u_error = ENXIO; return -1; } jobcontrol_in(minor, t); if (remq(q, &c)) { if (udata.u_sysio) *udata.u_base = c; else uputc(c, udata.u_base); break; } if (!(t->termios.c_lflag & ICANON)) { uint8_t n = t->termios.c_cc[VTIME]; if (n) udata.u_ptab->p_timeout = n + 1; } if (psleep_flags_io(q, flag, &nread)) return nread; /* timer expired */ if (udata.u_ptab->p_timeout == 1) goto out; } ++nread; /* return according to mode */ if (!(t->termios.c_lflag & ICANON)) { if (nread >= t->termios.c_cc[VMIN]) break; } else { if (nread == 1 && (c == t->termios.c_cc[VEOF])) { /* ^D */ nread = 0; break; } if (c == '\n') break; } ++udata.u_base; } out: wakeup(&q->q_count); return nread; }