diff options
Diffstat (limited to 'os/boot/rpcg/cpm.c')
| -rw-r--r-- | os/boot/rpcg/cpm.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/os/boot/rpcg/cpm.c b/os/boot/rpcg/cpm.c new file mode 100644 index 00000000..a9a45d60 --- /dev/null +++ b/os/boot/rpcg/cpm.c @@ -0,0 +1,162 @@ +#include "u.h" +#include "lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +enum { + BDSIZE= 1024, /* TO DO: check this */ +}; + +static Map bdmapv[BDSIZE/sizeof(BD)]; +static RMap bdmap = {"buffer descriptors"}; + +void +cpminit(void) +{ + IMM *io; + + io = m->iomem; + io->sdcr = 1; + io->lccr &= ~1; /* disable LCD */ + io->pcint = 0; /* disable all port C interrupts */ + io->pcso = 0; + io->pcdir =0; + io->pcpar = 0; + io->pcdat = 0; + io->papar = 0; + io->padir = 0; + io->paodr = 0; + io->padat = 0; + io->pbpar = 0; + io->pbdir = 0; + io->pbodr = 0; + io->pbdat = 0; + eieio(); + + for(io->cpcr = 0x8001; io->cpcr & 1;) /* reset all CPM channels */ + eieio(); + + mapinit(&bdmap, bdmapv, sizeof(bdmapv)); + mapfree(&bdmap, DPBASE, BDSIZE); +} + +void +cpmop(int op, int cno, int param) +{ + IMM *io; + int s; + + s = splhi(); + io = m->iomem; + eieio(); + while(io->cpcr & 1) + eieio(); + io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1; + eieio(); + while(io->cpcr & 1) + eieio(); + splx(s); +} + +/* + * connect SCCx clocks in NSMI mode (x=1 for USB) + */ +void +sccnmsi(int x, int rcs, int tcs) +{ + IMM *io; + ulong v; + int sh; + + sh = (x-1)*8; /* each SCCx field in sicr is 8 bits */ + v = (((rcs&7)<<3) | (tcs&7)) << sh; + io = ioplock(); + io->sicr = (io->sicr & ~(0xFF<<sh)) | v; + iopunlock(); +} + +void +scc2stop(void) +{ + SCC *scc; + + scc = IOREGS(0xA20, SCC); + if(scc->gsmrl & (3<<4)){ + cpmop(GracefulStopTx, SCC2ID, 0); + cpmop(CloseRxBD, SCC2ID, 0); + delay(1); + scc->gsmrl &= ~(3<<4); /* disable current use */ + archetherdisable(SCC2ID); + } +} + +BD * +bdalloc(int n) +{ + ulong a; + + a = mapalloc(&bdmap, 0, n*sizeof(BD), 0); + if(a == 0) + panic("bdalloc"); + return KADDR(a); +} + +void +bdfree(BD *b, int n) +{ + if(b){ + eieio(); + mapfree(&bdmap, PADDR(b), n*sizeof(BD)); + } +} + +/* + * initialise receive and transmit buffer rings. + */ +int +ioringinit(Ring* r, int nrdre, int ntdre, int bufsize) +{ + int i, x; + + /* the ring entries must be aligned on sizeof(BD) boundaries */ + r->nrdre = nrdre; + if(r->rdr == nil) + r->rdr = bdalloc(nrdre); + /* the buffer size must align with cache lines since the cache doesn't snoop */ + bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1); + if(r->rrb == nil) + r->rrb = malloc(nrdre*bufsize); + if(r->rdr == nil || r->rrb == nil) + return -1; + dcflush(r->rrb, nrdre*bufsize); + x = PADDR(r->rrb); + for(i = 0; i < nrdre; i++){ + r->rdr[i].length = 0; + r->rdr[i].addr = x; + r->rdr[i].status = BDEmpty|BDInt; + x += bufsize; + } + r->rdr[i-1].status |= BDWrap; + r->rdrx = 0; + + r->ntdre = ntdre; + if(r->tdr == nil) + r->tdr = bdalloc(ntdre); + if(r->txb == nil) + r->txb = malloc(ntdre*sizeof(Block*)); + if(r->tdr == nil || r->txb == nil) + return -1; + for(i = 0; i < ntdre; i++){ + r->txb[i] = nil; + r->tdr[i].addr = 0; + r->tdr[i].length = 0; + r->tdr[i].status = 0; + } + r->tdr[i-1].status |= BDWrap; + r->tdrh = 0; + r->tdri = 0; + r->ntq = 0; + return 0; +} |
