Line 44... |
Line 44... |
#include "board.h"
|
#include "board.h"
|
#include "taskp.h"
|
#include "taskp.h"
|
#include "syspipe.h"
|
#include "syspipe.h"
|
#include "zipsys.h"
|
#include "zipsys.h"
|
#include "ktraps.h"
|
#include "ktraps.h"
|
|
#include "string.h"
|
|
|
#ifndef NULL
|
#ifndef NULL
|
#define NULL (void *)0
|
#define NULL (void *)0
|
#endif
|
#endif
|
|
|
void kpush_syspipe(SYSPIPE *pipe, int val) {
|
void kpush_syspipe(SYSPIPE *pipe, char val) {
|
int tst = (pipe->m_head+1)&pipe->m_mask;
|
int tst = (pipe->m_head+1)&pipe->m_mask;
|
if (tst != pipe->m_tail) {
|
if (tst != pipe->m_tail) {
|
pipe->m_buf[pipe->m_head] = val;
|
pipe->m_buf[pipe->m_head] = val;
|
pipe->m_head = tst; // Increment the head pointer
|
pipe->m_head = tst; // Increment the head pointer
|
if ((pipe->m_rdtask)&&(pipe->m_rdtask != INTERRUPT_READ_TASK))
|
if ((pipe->m_rdtask)&&(pipe->m_rdtask != INTERRUPT_READ_TASK))
|
pipe->m_rdtask->state = SCHED_READY;
|
pipe->m_rdtask->state = SCHED_READY;
|
} else pipe->m_error = 1;
|
} else pipe->m_error = 1;
|
}
|
}
|
|
|
extern void pipe_panic(SYSPIPE *p);
|
extern void pipe_panic(SYSPIPE *p);
|
int kpop_syspipe(SYSPIPE *pipe, int *vl) {
|
/*
|
|
* kpop_syspipe
|
|
*
|
|
* Called from an interrupt context to pop one byte off of the syspipe.
|
|
*/
|
|
int kpop_syspipe(SYSPIPE *pipe, char *vl) {
|
if (pipe->m_head != pipe->m_tail) {
|
if (pipe->m_head != pipe->m_tail) {
|
|
// The head will *only* equal the tail if the pipe is empty.
|
|
// We come in here, therefore, if the pipe is non-empty
|
*vl = pipe->m_buf[pipe->m_tail];
|
*vl = pipe->m_buf[pipe->m_tail];
|
pipe->m_tail = (pipe->m_tail+1)&pipe->m_mask;
|
pipe->m_tail = (pipe->m_tail+1)&pipe->m_mask;
|
if (pipe->m_wrtask)
|
if (pipe->m_wrtask)
|
pipe->m_wrtask->state = SCHED_READY;
|
pipe->m_wrtask->state = SCHED_READY;
|
return 0;
|
return 0;
|
}
|
}
|
return 1; // Error condition
|
return 1; // Error condition
|
}
|
}
|
|
|
/* Returns how many values are in the pipe
|
/*
|
|
* kpop_short_syspipe
|
|
*
|
|
* This is identical to kpop_syspipe, save that we are pulling a short value
|
|
* off of the syspipe (i.e. a pair of chars), not just a single char.
|
*/
|
*/
|
/* Of course ... if it's not used, why include it?
|
int kpop_short_syspipe(SYSPIPE *pipe, unsigned short *vl) {
|
|
if (pipe->m_head == pipe->m_tail)
|
|
return 1; // Error condition
|
|
|
|
unsigned short *sptr = (unsigned short *)&pipe->m_buf[pipe->m_tail];
|
|
// sv = pipe->m_buf[pipe->m_tail];
|
|
*vl = *sptr;;
|
|
pipe->m_tail = (pipe->m_tail+2)&pipe->m_mask;
|
|
if (pipe->m_wrtask)
|
|
pipe->m_wrtask->state = SCHED_READY;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
int len_syspipe(SYSPIPE *p) {
|
int len_syspipe(SYSPIPE *p) {
|
return (p->m_head-p->m_tail) & p->m_mask;
|
return (p->m_head-p->m_tail) & p->m_mask;
|
} */
|
} */
|
|
|
/* Returns how many empty spaces are in the pipe
|
/* Returns how many empty spaces are in the pipe
|
*/
|
*/
|
int num_avail_syspipe(SYSPIPE *p) {
|
int num_avail_syspipe(SYSPIPE *p) {
|
// if (head+1 == tail) PIPE is full
|
// if (head+1 == tail) PIPE is full
|
// (mask+tail-tail+1)=mask+1 &mask = 0
|
// (mask+tail-tail+1)=mask+1 &mask = 0
|
Line 94... |
Line 120... |
|
|
// This will be called from a user context.
|
// This will be called from a user context.
|
// Another task may write to the pipe during this call. If the pipe becomes
|
// Another task may write to the pipe during this call. If the pipe becomes
|
// full, that task will block.
|
// full, that task will block.
|
//
|
//
|
static int uread_syspipe(TASKP tsk __attribute__((__unused__)), SYSPIPE *p, int *dst, int len) {
|
static int uread_syspipe(TASKP tsk __attribute__((__unused__)),
|
|
SYSPIPE *p, char *dst, int len) {
|
int nleft= len, h;
|
int nleft= len, h;
|
if (len == 0) {
|
if (len == 0) {
|
// We'll only get here if we were released from within a
|
// We'll only get here if we were released from within a
|
// writing task.
|
// writing task.
|
return p->m_nread;
|
return p->m_nread;
|
Line 114... |
Line 141... |
// The buffer wraps around the end. Thus, we first
|
// The buffer wraps around the end. Thus, we first
|
// read anything between the tail pointer and the end
|
// read anything between the tail pointer and the end
|
int ln1 = p->m_mask+1 - p->m_tail; // Navail to be read
|
int ln1 = p->m_mask+1 - p->m_tail; // Navail to be read
|
ln1 = (ln1 > nleft) ? nleft : ln1;
|
ln1 = (ln1 > nleft) ? nleft : ln1;
|
if (ln1 > 0) {
|
if (ln1 > 0) {
|
register int *src = &p->m_buf[p->m_tail];
|
memcpy(dst, &p->m_buf[p->m_tail], ln1);
|
for(int i=0; i<ln1; i++)
|
dst += ln1;
|
*dst++ = *src++;
|
|
|
|
p->m_nread += ln1;
|
p->m_nread += ln1;
|
nleft -= ln1;
|
nleft -= ln1;
|
|
|
int nt = p->m_tail+ln1;
|
int nt = p->m_tail+ln1;
|
Line 142... |
Line 168... |
// Still need to do more, wrap around our buffer and
|
// Still need to do more, wrap around our buffer and
|
// restart
|
// restart
|
int ln1 = h - p->m_tail;
|
int ln1 = h - p->m_tail;
|
ln1 = (ln1 < nleft) ? ln1 : nleft;
|
ln1 = (ln1 < nleft) ? ln1 : nleft;
|
|
|
int *src = &p->m_buf[p->m_tail];
|
memcpy(dst, &p->m_buf[p->m_tail], ln1);
|
for(int i=0; i<ln1; i++)
|
dst += ln1;
|
*dst++ = *src++;
|
|
|
|
p->m_nread += ln1;
|
p->m_nread += ln1;
|
nleft -= ln1;
|
nleft -= ln1;
|
int nt = p->m_tail+ln1; // nt = new tail value
|
int nt = p->m_tail+ln1; // nt = new tail value
|
if ((unsigned)nt > p->m_mask)
|
if ((unsigned)nt > p->m_mask)
|
Line 170... |
Line 195... |
// we are active, then it is blocked and waiting for us to
|
// we are active, then it is blocked and waiting for us to
|
// complete. Note also that this is treated as a volatile
|
// complete. Note also that this is treated as a volatile
|
// pointer. It can change from one time through our loop
|
// pointer. It can change from one time through our loop
|
// to the next.
|
// to the next.
|
if (((volatile SYSPIPE *)p)->m_wrtask) {
|
if (((volatile SYSPIPE *)p)->m_wrtask) {
|
int *src, ln;
|
int ln;
|
|
char *src;
|
|
|
// If the head changed before the write task blocked,
|
// If the head changed before the write task blocked,
|
// then go around again and copy some more before
|
// then go around again and copy some more before
|
// getting started
|
// getting started
|
//
|
//
|
Line 187... |
Line 213... |
// continue;
|
// continue;
|
|
|
ln = nleft;
|
ln = nleft;
|
if (p->m_wrtask->context[4] < nleft)
|
if (p->m_wrtask->context[4] < nleft)
|
ln = p->m_wrtask->context[4];
|
ln = p->m_wrtask->context[4];
|
src = (int *)p->m_wrtask->context[3];
|
src = (char *)p->m_wrtask->context[3];
|
|
memcpy(dst, src, ln);
|
for(int i=0; i<ln; i++)
|
dst += ln;
|
*dst++ = *src++;
|
src += ln;
|
|
|
p->m_nwritten += ln;
|
p->m_nwritten += ln;
|
p->m_nread += ln;
|
p->m_nread += ln;
|
|
|
nleft -= ln;
|
nleft -= ln;
|
Line 242... |
Line 268... |
//
|
//
|
return len;
|
return len;
|
}
|
}
|
|
|
static int uwrite_syspipe(TASKP tsk __attribute__((__unused__)),
|
static int uwrite_syspipe(TASKP tsk __attribute__((__unused__)),
|
SYSPIPE *p, int *src, int len) {
|
SYSPIPE *p, char *src, int len) {
|
int nleft = len;
|
int nleft = len;
|
|
|
// The kernel guarantees, before we come into here, that we have a
|
// The kernel guarantees, before we come into here, that we have a
|
// valid write request.
|
// valid write request.
|
do {
|
do {
|
Line 261... |
Line 287... |
// We need to copy everything to the buffer
|
// We need to copy everything to the buffer
|
} else if (rdtask) {
|
} else if (rdtask) {
|
int ln = nleft;
|
int ln = nleft;
|
if (ln > p->m_rdtask->context[4])
|
if (ln > p->m_rdtask->context[4])
|
ln = p->m_rdtask->context[4];
|
ln = p->m_rdtask->context[4];
|
int *dst = (int *)p->m_rdtask->context[3];
|
memcpy((char *)p->m_rdtask->context[3], src, ln);
|
for(int i=0; i<ln; i++)
|
src += ln;
|
*dst++ = *src++;
|
|
p->m_nread += ln;
|
p->m_nread += ln;
|
p->m_rdtask->context[3]+= ln;
|
p->m_rdtask->context[3]+= ln;
|
p->m_rdtask->context[4]-= ln;
|
p->m_rdtask->context[4]-= ln;
|
nleft -= ln;
|
nleft -= ln;
|
p->m_nwritten += ln;
|
p->m_nwritten += ln;
|
Line 316... |
Line 341... |
{ // Write into the first half of the pipe
|
{ // Write into the first half of the pipe
|
// Be careful not to change head until all is written
|
// Be careful not to change head until all is written
|
// so that it remains consistent under interrupt
|
// so that it remains consistent under interrupt
|
// conditions.
|
// conditions.
|
int ln = p->m_mask+1-p->m_head;
|
int ln = p->m_mask+1-p->m_head;
|
int *dst = &p->m_buf[p->m_head];
|
|
if (ln > nleft) ln = nleft;
|
if (ln > nleft) ln = nleft;
|
if (ln > navail) ln = navail;
|
if (ln > navail) ln = navail;
|
|
|
for(int i=0; i<ln; i++)
|
memcpy((void *)&p->m_buf[p->m_head], src, ln);
|
*dst++ = *src++;
|
src += ln;
|
|
|
p->m_head = (p->m_head+ln)&p->m_mask;
|
p->m_head = (p->m_head+ln)&p->m_mask;
|
nleft -= ln;
|
nleft -= ln;
|
p->m_nwritten += ln;
|
p->m_nwritten += ln;
|
navail -= ln;
|
navail -= ln;
|
}
|
}
|
|
|
/*
|
|
// Write into the rest of the pipe
|
|
if ((0 == p->m_head)&&(nleft>0)&&(navail>0)) {
|
|
int ln = navail;
|
|
if (nleft < ln)
|
|
ln = nleft;
|
|
int *dst = &p->m_buf[p->m_head];
|
|
|
|
for(int i=0; i<ln; i++)
|
|
*dst++ = *src++;
|
|
|
|
p->m_head += ln;
|
|
p->m_nwritten += ln;
|
|
nleft -= ln;
|
|
}*/
|
|
}
|
}
|
|
|
if ((nleft > 0)&&(navail == 0)) {
|
if ((nleft > 0)&&(navail == 0)) {
|
if (rdtask == INTERRUPT_READ_TASK) {
|
if (rdtask == INTERRUPT_READ_TASK) {
|
DISABLE_INTS();
|
DISABLE_INTS();
|
Line 369... |
Line 377... |
p->m_wrtask = 0;
|
p->m_wrtask = 0;
|
return nw;
|
return nw;
|
}
|
}
|
|
|
// This will be called from a kernel (interrupt) context
|
// This will be called from a kernel (interrupt) context
|
void kread_syspipe(TASKP tsk, int dev, int *dst, int len) {
|
void kread_syspipe(TASKP tsk, int dev, char *dst, int len) {
|
SYSPIPE *p = (SYSPIPE *)dev;
|
SYSPIPE *p = (SYSPIPE *)dev;
|
if (p->m_rdtask != NULL) {
|
if (p->m_rdtask != NULL) {
|
// If the pipe already has a read task, then we fail
|
// If the pipe already has a read task, then we fail
|
tsk->context[1] = -EBUSY;
|
tsk->context[1] = -EBUSY;
|
zip_halt();
|
zip_halt();
|
Line 413... |
Line 421... |
// On return, this will bring us back to user space, inside our
|
// On return, this will bring us back to user space, inside our
|
// user space version of the read system call
|
// user space version of the read system call
|
}
|
}
|
}
|
}
|
|
|
void kwrite_syspipe(TASKP tsk, int dev, int *src, int len) {
|
void kwrite_syspipe(TASKP tsk, int dev, char *src, int len) {
|
SYSPIPE *p = (SYSPIPE *)dev;
|
SYSPIPE *p = (SYSPIPE *)dev;
|
if (p->m_wrtask != NULL) {
|
if (p->m_wrtask != NULL) {
|
// If the pipe already has a write task, then we fail
|
// If the pipe already has a write task, then we fail
|
tsk->context[1] = -EBUSY;
|
tsk->context[1] = -EBUSY;
|
} else if (len <= 0) {
|
} else if (len <= 0) {
|