@@ 12,51 12,27 @@ static void * pciPhysBaseAddr;
static ulong pciBaseAddr;
static Pcidev * pcidev;
-#define DBGREGS 0x01
-#define DBGREAD 0x02
-#define DBGWRIT 0x04
-#define DBG819 0x08
-#define DBGINTR 0x10
-#define DBGINTS 0x20
+#define DBGREAD 0x01
+#define DBGWRIT 0x02
+#define DBGINTR 0x04
+#define DBGINTS 0x08
int debug = 0;
// Lml 22 driver
-#ifdef MEMMAP
-struct {
- ulong pci;
- ulong statcom;
- ulong codedata;
-} lmlmap;
-#endif
-
enum{
Qdir,
-#ifdef MEMMAP
- Q060,
- Q819,
- Q856,
- Qreg,
- Qmap,
- Qbuf,
-#endif
Qjvideo,
Qjframe,
+ Qjcount,
};
static Dirtab lmldir[]={
// name, qid, size, mode
-#ifdef MEMMAP
- "lml060", {Q060}, 0x400, 0644,
- "lml819", {Q819}, 0, 0644,
- "lml856", {Q856}, 0, 0644,
- "lmlreg", {Qreg}, 0x400, 0644,
- "lmlmap", {Qmap}, sizeof lmlmap, 0444,
- "lmlbuf", {Qbuf}, 0, 0644,
-#endif
"jvideo", {Qjvideo}, 0, 0666,
"jframe", {Qjframe}, 0, 0666,
+ "jcount", {Qjcount}, 0, 0444,
};
CodeData * codeData;
@@ 82,402 58,34 @@ static FrameHeader frameHeader = {
};
-#ifndef MEMMAP
#define writel(v, a) *(ulong *)(a) = (v)
#define readl(a) *(ulong*)(a)
-#else
-ulong
-writel(ulong v, ulong a) {
- if (debug&DBGREGS)
- pprint("%.8lux (%.8lux) <-- %.8lux\n",
- a, (ulong)a-pciBaseAddr, v);
- return *(ulong *)a = v;
-}
-
-ulong
-readl(ulong a) {
- ulong v;
-
- v = *(ulong*)a;
- if (debug&DBGREGS)
- pprint("%.8lux (%.8lux) --> %.8lux\n",
- a, (ulong)a-pciBaseAddr, v);
- return v;
-}
-ushort
-writew(ushort v, ulong a) {
- if (debug&DBGREGS)
- pprint("%.8lux (%.8lux) <-- %.4ux\n",
- a, (ulong)a-pciBaseAddr, v);
- return *(ushort *)a = v;
-}
-
-uchar
-writeb(uchar v, ulong a) {
- if (debug&DBGREGS)
- pprint("%.8lux (%.8lux) <-- %.2ux\n",
- a, (ulong)a-pciBaseAddr, v);
- return *(uchar *)a = v;
-}
-
-ushort
-readw(ulong a) {
- ushort v;
-
- v = *(ushort*)a;
- if (debug&DBGREGS)
- pprint("%.8lux (%.8lux) --> %.4ux\n",
- a, (ulong)a-pciBaseAddr, v);
- return v;
-}
-
-uchar
-readb(ulong a) {
- uchar v;
-
- v = *(uchar*)a;
- if (debug&DBGREGS)
- pprint("%.8lux (%.8lux) --> %.2ux\n",
- a, (ulong)a-pciBaseAddr, v);
- return v;
-}
-
-static void
-i2c_pause(void) {
-
- microdelay(I2C_DELAY);
-}
-
-static void
-i2c_waitscl(void) {
- int i;
-
- for (i = 0; i < I2C_TIMEOUT; i++)
- if (readl(pciBaseAddr + I2C_BUS) & I2C_SCL)
- return;
- error(Eio);
-}
-
-static void
-i2c_start(void) {
-
- writel(I2C_SCL|I2C_SDA, pciBaseAddr + I2C_BUS);
- i2c_waitscl();
- i2c_pause();
-
- writel(I2C_SCL, pciBaseAddr + I2C_BUS);
- i2c_pause();
-
- writel(0, pciBaseAddr + I2C_BUS);
- i2c_pause();
-}
-
-static void
-i2c_stop(void) {
- // the clock should already be low, make sure data is
- writel(0, pciBaseAddr + I2C_BUS);
- i2c_pause();
-
- // set clock high and wait for device to catch up
- writel(I2C_SCL, pciBaseAddr + I2C_BUS);
- i2c_waitscl();
- i2c_pause();
-
- // set the data high to indicate the stop bit
- writel(I2C_SCL|I2C_SDA, pciBaseAddr + I2C_BUS);
- i2c_pause();
-}
-
-static void i2c_wrbit(int bit) {
- if (bit){
- writel(I2C_SDA, pciBaseAddr + I2C_BUS); // set data
- i2c_pause();
- writel(I2C_SDA|I2C_SCL, pciBaseAddr + I2C_BUS);
- i2c_waitscl();
- i2c_pause();
- writel(I2C_SDA, pciBaseAddr + I2C_BUS);
- i2c_pause();
- } else {
- writel(0, pciBaseAddr + I2C_BUS); // clr data
- i2c_pause();
- writel(I2C_SCL, pciBaseAddr + I2C_BUS);
- i2c_waitscl();
- i2c_pause();
- writel(0, pciBaseAddr + I2C_BUS);
- i2c_pause();
- }
-}
static int
-i2c_rdbit(void) {
- int bit;
- // the clk line should be low
-
- // ensure we are not asserting the data line
- writel(I2C_SDA, pciBaseAddr + I2C_BUS);
- i2c_pause();
-
- // set the clock high and wait for device to catch up
- writel(I2C_SDA|I2C_SCL, pciBaseAddr + I2C_BUS);
- i2c_waitscl();
- i2c_pause();
-
- // the data line should be a valid bit
- bit = readl(pciBaseAddr+I2C_BUS);
- if (bit & I2C_SDA){
- bit = 1;
- } else {
- bit = 0;
+getbuffer(void){
+ static last = NBUF-1;
+ int l = last;
+
+ for (;;) {
+ last = (last+1) % NBUF;
+ if (codeData->statCom[last] & STAT_BIT)
+ return last;
+ if (last == l)
+ sleep(&sleeper, return0, 0);
}
-
- // set the clock low to indicate end of cycle
- writel(I2C_SDA, pciBaseAddr + I2C_BUS);
- i2c_pause();
-
- return bit;
+ return 0;
}
-static int
-i2c_rdbyte(uchar *v) {
- int i, ack;
- uchar res;
-
- res = 0;
- for (i = 0; i < 8; i++) {
- res = res << 1;
- res += i2c_rdbit();
- }
-
- ack = i2c_rdbit();
-
- *v = res;
-
- return ack;
-}
-
-static int
-i2c_wrbyte(uchar v) {
- int i, ack;
-
- for (i = 0; i < 8; i++) {
- i2c_wrbit(v & 0x80);
- v = v << 1;
- }
-
- ack = i2c_rdbit();
-
- return ack;
-}
-
-static void
-i2c_write_bytes(uchar addr, uchar sub, uchar *bytes, long num) {
- int ack;
- long i;
-
- i2c_start();
-
- ack = i2c_wrbyte(addr);
- if (ack == 1) error(Eio);
-
- ack = i2c_wrbyte(sub);
- if (ack == 1) error(Eio);
-
- for (i = 0; i < num; i++) {
- ack = i2c_wrbyte(bytes[i]);
- if (ack == 1) error(Eio);
- }
-
- i2c_stop();
-}
-
-static int
-i2c_bt856rd8(void) {
- uchar ret;
-
- i2c_start ();
-
- if (i2c_wrbyte(BT856Addr + 1) == 1
- || i2c_rdbyte(&ret) == 0) {
- i2c_stop ();
- return -1;
- }
-
- i2c_stop ();
- return ret;
-}
-
-static int
-i2c_rd8(int addr, int sub)
-{
- uchar msb;
-
- i2c_start();
-
- if (i2c_wrbyte(addr) == 1
- || i2c_wrbyte(sub) == 1) {
- if (debug&DBGREGS) pprint("i2c_rd8, failure 1\n");
- i2c_stop();
- return -1;
- }
-
- i2c_start();
-
- if (i2c_wrbyte(addr+1) == 1
- || i2c_rdbyte(&msb) == 0){
- if (debug&DBGREGS) pprint("i2c_rd8, failure 2\n");
- i2c_stop();
- return -1;
- }
-
- i2c_stop();
-
- return msb;
-}
-
-static int
-i2c_wr8(uchar addr, uchar sub, uchar msb) {
-
- i2c_start();
+static long
+vcount(Chan *, void *va, long nbytes, vlong) {
+ char *p = (char *)va;
- if (i2c_wrbyte(addr) == 1
- || i2c_wrbyte(sub) == 1
- || i2c_wrbyte(msb) == 1)
- return 0;
-
- i2c_stop();
-
+ // reads always return one byte: the next available buffer number
+ if (nbytes <= 0) return 0;
+ *p = getbuffer();
return 1;
}
-/*
- * The following mapping applies for the guests in the LML33
- *
- * Guest Device
- * 0 zr36060
- * uses subaddress GADR[0..1]
- * 1 zr36060 START#
- * 2 -
- * 3 zr36060 RESET#
- * 4 -
- * 5 -
- * 6 -
- * 7 -
- */
-
-// post_idle waits for the guest bus to become free
-static int
-post_idle(void) {
- ulong a;
- int timeout;
-
- for (timeout = 0; timeout < GUEST_TIMEOUT; timeout++){
- a = readl(pciBaseAddr + POST_OFFICE);
- if ((a & POST_PEND) == 0)
- return a;
- }
- pprint("post_idle timeout\n");
- return -1;
-}
-
-// post_write writes a byte to a guest using postoffice mechanism
-int
-post_write(unsigned int guest, unsigned int reg, unsigned int v) {
- int w;
-
- // wait for postoffice not busy
- post_idle();
-
- // Trim the values, just in case
- guest &= 0x07;
- reg &= 0x07;
- v &= 0xFF;
-
- // write postoffice operation
- w = POST_DIR | (guest<<20) | (reg<<16) | v;
- writel(w, pciBaseAddr + POST_OFFICE);
-
- // wait for postoffice not busy
- return post_idle() == -1;
-}
-
-// post_read reads a byte from a guest using postoffice mechanism
-int
-post_read(int guest, int reg) {
- int w;
-
- // wait for postoffice not busy
- post_idle();
-
- // Trim the values, just in case
- guest &= 0x07;
- reg &= 0x07;
-
- // write postoffice operation
- w = (guest<<20) + (reg<<16);
- writel(w, pciBaseAddr + POST_OFFICE);
-
- // wait for postoffice not busy, get result
- w = post_idle();
-
- // decide if read went ok
- if (w == -1) return -1;
-
- return w & 0xFF;
-}
-
-static int
-zr060_write(int reg, int v) {
-
- if (post_write(GID060, 1, (reg>>8) & 0x03)
- || post_write(GID060, 2, reg & 0xff)
- || post_write(GID060, 3, v))
- return -1;
-}
-
-static int
-zr060_read(int reg) {
-
- if (post_write(GID060, 1, (reg>>8) & 0x03)
- || post_write(GID060, 2, reg & 0xff))
- return -1;
- return post_read(GID060, 3);
-}
-#endif
-
-static int
-prepareBuffer(int i) {
- if (i >= 0 && i < NBUF && (codeData->statCom[i] & STAT_BIT)) {
- codeData->statCom[i] = PADDR(&(codeData->fragdesc[i]));
- return codeData->fragdesc[i].leng;
- } else
- return -1;
-}
-
-static int
-getProcessedBuffer(void){
- static lastBuffer = NBUF-1;
- int l = lastBuffer;
-
- while (1) {
- lastBuffer = (lastBuffer+1) % NBUF;
- if (codeData->statCom[lastBuffer] & STAT_BIT)
- return lastBuffer;
- if (lastBuffer == l)
- break;
- }
- return -1;
-}
-
-static int
-getBuffer(int i, int* frameNo) {
-
- if(codeData->statCom[i] & STAT_BIT) {
- *frameNo = codeData->statCom[i] >> 24;
- return (codeData->statCom[i] & 0x00FFFFFF) >> 1;
- } else
- return -1;
-}
-
static long
vread(Chan *, void *va, long nbytes, vlong) {
static int bufpos;
@@ 495,20 103,20 @@ vread(Chan *, void *va, long nbytes, vlong) {
while (count > 0) {
switch (state) {
case New:
- while ((curbuf = getProcessedBuffer()) == -1)
- sleep(&sleeper, return0, 0);
- fragsize = getBuffer(curbuf, &frameno);
+ curbuf = getbuffer();
+ frameNo = codeData->statCom[curbuf] >> 24;
+ fragsize = (codeData->statCom[curbuf] & 0x00ffffff)>>1;
if (debug & DBGREAD)
pprint("devlml: got read buf %d, fr %d, size %d\n",
curbuf, frameNo, fragsize);
- if (frameno != (frameprev + 1) % 256)
+ if (!singleFrame && frameno != (frameprev + 1) % 256)
pprint("Frame out of sequence: %d %d\n",
frameprev, frameno);
frameprev = frameno;
if (fragsize <= 0 || fragsize > sizeof(Fragment)) {
pprint("Wrong sized fragment, %d (ignored)\n",
fragsize);
- prepareBuffer(curbuf);
+ codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf]));
break;
}
// Fill in APP marker fields here
@@ 550,7 158,7 @@ vread(Chan *, void *va, long nbytes, vlong) {
p += i;
// Allow reuse of current buffer
- prepareBuffer(curbuf);
+ codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf]));
state = New;
if (singleFrame) {
state = Error;
@@ 577,11 185,7 @@ vwrite(Chan *, void *va, long nbytes, vlong) {
while (count > 0) {
switch (state) {
case New:
- while((curbuf = getProcessedBuffer()) == -1) {
- if (debug&DBGWRIT)
- pprint("devlml::sleep\n");
- sleep(&sleeper, return0, 0);
- }
+ curbuf = getbuffer();
if (debug&DBGWRIT)
pprint("current buffer %d\n", curbuf);
bufptr = codeData->frag[curbuf].fb;
@@ 638,9 242,9 @@ vwrite(Chan *, void *va, long nbytes, vlong) {
p += i;
count -= i;
// We have written the frame, time to display it
- i = prepareBuffer(curbuf);
+ codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf]));
if (debug&DBGWRIT)
- pprint("Sending buffer %d: %d\n", curbuf, i);
+ pprint("Sending buffer %d\n", curbuf);
if (singleFrame) {
state = Error;
return nbytes - count;
@@ 658,10 262,8 @@ static void lmlintr(Ureg *, void *);
static void
lmlreset(void)
{
-// LMLSEG
Physseg segbuf;
Physseg segreg;
-//
ulong regpa;
ulong cdsize;
int i;
@@ 682,7 284,7 @@ lmlreset(void)
// Get access to DMA memory buffer
memset(codeData, 0xAA, sizeof(CodeData));
- codeData->physaddr = PADDR(&(codeData->statCom[0]));
+ codeData->physaddr = PADDR(codeData->statCom);
for (i = 0; i < NBUF; i++) {
codeData->statCom[i] = PADDR(&(codeData->fragdesc[i]));
codeData->fragdesc[i].addr = PADDR(&(codeData->frag[i]));
@@ 704,23 306,9 @@ lmlreset(void)
pciBaseAddr = (ulong)KADDR(regpa);
print(", mapped at 0x%.8lux\n", pciBaseAddr);
- // make sure the device will respond to mem accesses
- // (pcicmd_master | pcicmd_memory) -- probably superfluous
-// pcicfgw32(pcidev, PciPCR, 0x04 | 0x02);
-
- // set bus latency -- probably superfluous
-// pcicfgw8(pcidev, PciLTR, 64);
-
// Interrupt handler
intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf);
-#ifdef MEMMAP
- lmlmap.pci = pciBaseAddr;
- lmlmap.statcom = PADDR(codeData->statCom);
- lmlmap.codedata = (ulong)codeData;
-#endif
-
-// LMLSEG
memset(&segbuf, 0, sizeof(segbuf));
segbuf.attr = SG_PHYSICAL;
segbuf.name = smalloc(NAMELEN);
@@ 742,8 330,6 @@ lmlreset(void)
print("lml: physsegment: lmlmjpg\n");
return;
}
-//
-
return;
}
@@ 771,17 357,9 @@ lmlopen(Chan *c, int omode) {
c->aux = 0;
switch(c->qid.path){
-#ifdef MEMMAP
- case Q060:
- case Q819:
- case Q856:
- case Qreg:
- case Qmap:
- case Qbuf:
- break;
-#endif
case Qjframe:
case Qjvideo:
+ case Qjcount:
if (nopens)
error(Einuse);
nopens = 1;
@@ 800,18 378,9 @@ static void
lmlclose(Chan *c) {
switch(c->qid.path){
-#ifdef MEMMAP
- case Q060:
- case Q819:
- case Q856:
- case Qreg:
- case Qmap:
- case Qbuf:
- authclose(c);
- break;
-#endif
case Qjvideo:
case Qjframe:
+ case Qjcount:
nopens = 0;
authclose(c);
}
@@ 819,9 388,6 @@ lmlclose(Chan *c) {
static long
lmlread(Chan *c, void *va, long n, vlong voff) {
-#ifdef MEMMAP
- int i, d;
-#endif
uchar *buf = va;
long off = voff;
@@ 829,188 395,23 @@ lmlread(Chan *c, void *va, long n, vlong voff) {
case Qdir:
return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen);
-
-#ifdef MEMMAP
- case Q060:
- if (off < 0 || off + n > 0x400)
- return 0;
- for (i = 0; i < n; i++) {
- if ((d = zr060_read(off + i)) < 0) break;
- *buf++ = d;
- }
- return i;
- case Q819:
- if (off < 0 || off + n > 0x20)
- return 0;
- for (i = 0; i < n; i++) {
- if ((d = i2c_rd8(BT819Addr, off++)) < 0) break;
- *buf++ = d;
- }
- return i;
- case Q856:
- if (n != 1)
- return 0;
- switch ((int)off) {
- case 0:
- if ((d = i2c_bt856rd8()) < 0)
- return 0;
- *buf = d;
- break;
- case 0xDA:
- *buf = q856[0];
- break;
- case 0xDC:
- *buf = q856[1];
- break;
- case 0xDE:
- *buf = q856[2];
- break;
- default:
- return 0;
- }
- return 1;
- case Qmap:
- if (off < 0)
- return 0;
- for (i = 0; i < n; i++) {
- if (off + i >= sizeof lmlmap)
- break;
- buf[i] = ((uchar *)&lmlmap)[off + i];
- }
- return i;
- case Qreg:
- if (off < 0 || off + n >= 0x400)
- return 0;
- switch(n) {
- case 1:
- *buf = readb(pciBaseAddr + off);
- break;
- case 2:
- if (off & (n-1)) return 0;
- *(short *)buf = readw(pciBaseAddr + off);
- break;
- case 4:
- if (off & (n-1)) return 0;
- *(long *)buf = readl(pciBaseAddr + off);
- break;
- default:
- return 0;
- }
- return n;
- case Qbuf:
- if (off < 0 || off + n >= sizeof *codeData)
- return 0;
- switch(n) {
- case 1:
- *buf = readb((ulong)codeData + off);
- break;
- case 2:
- if (off & (n-1)) return 0;
- *(short *)buf = readw((ulong)codeData + off);
- break;
- case 4:
- if (off & (n-1)) return 0;
- *(long *)buf = readl((ulong)codeData + off);
- break;
- default:
- return 0;
- }
- return n;
-#endif
case Qjvideo:
case Qjframe:
return vread(c, buf, n, off);
+ case Qjcount:
+ return vcount(c, buf, n, off);
}
}
static long
lmlwrite(Chan *c, void *va, long n, vlong voff) {
-#ifdef MEMMAP
- int i;
-#endif
uchar *buf = va;
long off = voff;
switch(c->qid.path & ~CHDIR){
-
case Qdir:
+ case Qjcount:
error(Eperm);
-
-#ifdef MEMMAP
- case Q060:
- if (off < 0 || off + n > 0x400)
- return 0;
- for (i = 0; i < n; i++) {
- if (zr060_write(off + i, *buf++) < 0) break;
- }
- return i;
- case Q819:
- if (off < 0 || off + n >= 0x20)
- return 0;
- for (i = 0; i < n; i++)
- if (i2c_wr8(BT819Addr, off + i, *buf++) == 0)
- break;
- return i;
- case Q856:
- if (n != 1 || off < 0xda || off + n > 0xe0)
- return 0;
- if (i2c_wr8(BT856Addr, off, *buf) == 0)
- return 0;
- switch ((int)off) {
- case 0xDA:
- q856[0] = *buf;
- break;
- case 0xDC:
- q856[1] = *buf;
- break;
- case 0xDE:
- q856[2] = *buf;
- break;
- }
- return 1;
- case Qreg:
- if (off < 0 || off + n >= 0x400)
- return 0;
- switch (n) {
- case 1:
- writeb(*buf, pciBaseAddr + off);
- break;
- case 2:
- if (off & 0x1)
- return 0;
- writew(*(short *)buf, pciBaseAddr + off);
- break;
- case 4:
- if (off & 0x3)
- return 0;
- writel(*(long *)buf, pciBaseAddr + off);
- break;
- default:
- return 0;
- }
- return n;
- case Qbuf:
- if (off < 0 || off + n >= sizeof *codeData)
- return 0;
- switch (n) {
- case 1:
- writeb(*buf, (ulong)codeData + off);
- break;
- case 2:
- if (off & 0x1)
- return 0;
- writew(*(short *)buf, (ulong)codeData + off);
- break;
- case 4:
- if (off & 0x3)
- return 0;
- writel(*(long *)buf, (ulong)codeData + off);
- break;
- default:
- return 0;
- }
- return n;
-#endif
case Qjvideo:
case Qjframe:
return vwrite(c, buf, n, off);