From dd7e4eebb79a4d3f7c27ef6fa3d61db46030ffc9 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 24 Apr 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-04-24 --- alphapc/arch164.c | 33 +++- alphapc/dma.c | 15 +- alphapc/io.h | 2 + ip/il.c | 34 +++- pc/devlml.c | 385 +++++++++++++++++++++++++++++++++++++--------- pc/devlml.h | 40 ++--- 6 files changed, 405 insertions(+), 104 deletions(-) diff --git a/alphapc/arch164.c b/alphapc/arch164.c index 467aece130ead151dfcd747c2c17c3950ec8cd99..6c817623da56787dbbad4bd911fb5970a19492e2 100644 --- a/alphapc/arch164.c +++ b/alphapc/arch164.c @@ -27,6 +27,26 @@ ident(void) return 0; /* bug! */ } +static uvlong* sgmap; + +static void +sginit(void) +{ + ulong pa; + uvlong *pte; + + sgmap = xspanalloc(BY2PG, BY2PG, 0); + memset(sgmap, 0, BY2PG); + + pte = sgmap; + for(pa = 0; pa < 8*1024*1024; pa += BY2PG) + *pte++ = ((pa>>PGSHIFT)<<1)|1; + + wind[0x400/4] = ISAWINDOW|2; + wind[0x440/4] = 0x00700000; + wind[0x480/4] = PADDR(sgmap); +} + static void * kmapio(ulong space, ulong offset, int size) { @@ -54,17 +74,18 @@ coreinit(void) } coresave[0] = core[0x140/4]; -#ifdef notdef + /* disable windows */ + wind[0x400/4] = 0; + wind[0x500/4] = 0; + wind[0x600/4] = 0; + wind[0x700/4] = 0; + /* direct map bottom 1G PCI target space to KZERO in window 1 */ wind[0x500/4] = PCIWINDOW|1; wind[0x540/4] = 0x3ff00000; wind[0x580/4] = 0; - /* disable other windows */ - wind[0x400/4] = 0; - wind[0x600/4] = 0; - wind[0x700/4] = 0; -#endif /* notdef */ +sginit(); /* clear error state */ core[0x8200/4] = 0x7ff; diff --git a/alphapc/dma.c b/alphapc/dma.c index da9d2107dfdb12c32c79b156f41c2e1c375ffb72..d91246998183ab4fe2274d61ba6a14ec26182141 100644 --- a/alphapc/dma.c +++ b/alphapc/dma.c @@ -132,6 +132,7 @@ dmasetup(int chan, void *va, long len, int isread) * if this isn't kernel memory or crossing 64k boundary or above 16 meg * use the bounce buffer. */ +print("va%lux+", va); #ifdef notdef pa = PADDR(va); if((((ulong)va)&0xF0000000) != KZERO @@ -151,7 +152,7 @@ dmasetup(int chan, void *va, long len, int isread) else xp->len = 0; #else - pa = PCIWADDR(va); + pa = ISAWADDR(va); #endif /* notdef */ /* @@ -164,11 +165,12 @@ dmasetup(int chan, void *va, long len, int isread) outb(dp->addr[chan], pa>>dp->shift); /* set address */ outb(dp->addr[chan], pa>>(8+dp->shift)); outb(dp->page[chan], pa>>16); -outb(0x400|dp->page[chan], pa>>24); +//outb(0x400|dp->page[chan], pa>>24); outb(dp->count[chan], (len>>dp->shift)-1); /* set count */ outb(dp->count[chan], ((len>>dp->shift)-1)>>8); outb(dp->sbm, chan); /* enable the channel */ iunlock(dp); +print("pa%lux+", pa); return len; } @@ -207,6 +209,15 @@ dmaend(int chan) outb(dp->sbm, 4|chan); iunlock(dp); +{ int i; +outb(dp->cbp, 0); +i = inb(dp->addr[chan]); +i |= inb(dp->addr[chan])<<8; +i |= inb(dp->page[chan])<<16; +i |= inb(0x400|dp->page[chan])<<24; +print("X%uX+", i); +} + xp = &dp->x[chan]; if(xp->len == 0 || !xp->isread) return; diff --git a/alphapc/io.h b/alphapc/io.h index e6e2a484d2254de7eca81c6ba9a3086e3167d979..e9aeebd51aedda8f280ab346fe2c036979dd78aa 100644 --- a/alphapc/io.h +++ b/alphapc/io.h @@ -205,3 +205,5 @@ typedef struct SCSIdev { #define PCIWINDOW 0x40000000 #define PCIWADDR(va) (PADDR(va)+PCIWINDOW) +#define ISAWINDOW 0x00800000 +#define ISAWADDR(va) (PADDR(va)+ISAWINDOW) diff --git a/ip/il.c b/ip/il.c index 93db3e1fb25ceb99b05c002b3c29cce3349c721f..a15fab4e63be4e846993c571983bfe82a2eb8657 100644 --- a/ip/il.c +++ b/ip/il.c @@ -1024,6 +1024,26 @@ ilbackoff(Ilcb *ic) ic->rexmit++; } +// complain if two numbers not within an hour of each other +#define Tfuture (1000*60*60) +int +later(ulong t1, ulong t2, char *x) +{ + int dt; + + dt = t1 - t2; + if(dt > 0) { + if(dt > Tfuture) + print("%s: way future %d\n", x, dt); + return 1; + } + if(dt < -Tfuture) { + print("%s: way past %d\n", x, -dt); + return 1; + } + return 0; +} + void ilackproc(void *x) { @@ -1046,7 +1066,7 @@ loop: case Illistening: break; case Ilclosing: - if(ic->timeout <= msec) { + if(later(msec, ic->timeout, "timeout")) { if(ic->rexmit > MaxRexmit){ ilhangup(p, nil); break; @@ -1058,7 +1078,7 @@ loop: case Ilsyncee: case Ilsyncer: - if(ic->timeout <= msec) { + if(later(msec, ic->timeout, "timeout")) { if(ic->rexmit > MaxRexmit){ ilhangup(p, etime); break; @@ -1069,11 +1089,12 @@ loop: break; case Ilestablished: - if(ic->recvd != ic->acksent && ic->acktime <= msec) + if(ic->recvd != ic->acksent) + if(later(msec, ic->acktime, "acktime")) ilsendctl(p, nil, Ilack, ic->next, ic->recvd, 0); - if(ic->querytime <= msec){ - if(msec - ic->lastrecv > DeathTime){ + if(later(msec, ic->querytime, "querytime")){ + if(later(msec, ic->lastrecv+DeathTime, "deathtime")){ netlog(il->f, Logil, "il: hangup: deathtime\n"); ilhangup(p, etime); break; @@ -1082,7 +1103,8 @@ loop: ic->querytime = msec + QueryTime; } - if(ic->unacked != nil && ic->timeout <= msec) { + if(ic->unacked != nil) + if(later(msec, ic->timeout, "timeout")) { if(ic->rexmit > MaxRexmit){ netlog(il->f, Logil, "il: hangup: too many rexmits\n"); ilhangup(p, etime); diff --git a/pc/devlml.c b/pc/devlml.c index c9efa05bb5f106ec6f150586f3c91c6792625013..ac696000f53e244777cb776ce8680986ab1ab790 100644 --- a/pc/devlml.c +++ b/pc/devlml.c @@ -30,7 +30,22 @@ static Dirtab viddir[]={ }; CodeData * codeData; -MjpgDrv * mjpgDrv; + +int currentBuffer; +int currentBufferLength; +void * currentBufferPtr; +int frameNo; +Rendez sleeper; +int singleFrame; +int bufferPrepared; +int hdrPos; +int nopens; + +static FrameHeader frameHeader = { + MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8, + { 'L', 'M', 'L', '\0'}, + -1, 0, 0, 0, 0 +}; static void lml33_i2c_pause(void) { @@ -182,38 +197,25 @@ lml33_i2c_write_bytes(uchar addr, uchar sub, uchar *bytes, long num) { lml33_i2c_stop(); } -static uchar +static int lml33_i2c_rd8(int addr, int sub) { - int ack; uchar msb; lml33_i2c_start(); - ack = lml33_i2c_wrbyte(addr); - if (ack == 1){ - lml33_i2c_stop(); - error(Eio); - } - - ack = lml33_i2c_wrbyte(sub); - if (ack == 1){ + if (lml33_i2c_wrbyte(addr) == 1 + || lml33_i2c_wrbyte(sub) == 1) { lml33_i2c_stop(); - error(Eio); + return -1; } lml33_i2c_start(); - ack = lml33_i2c_wrbyte(addr+1); - if (ack == 1){ - lml33_i2c_stop(); - error(Eio); - } - - ack = lml33_i2c_rdbyte(&msb); - if (ack == 0){ + if (lml33_i2c_wrbyte(addr+1) == 1 + || lml33_i2c_rdbyte(&msb) == 0){ lml33_i2c_stop(); - error(Eio); + return -1; } lml33_i2c_stop(); @@ -221,6 +223,21 @@ lml33_i2c_rd8(int addr, int sub) return msb; } +static int +lml33_i2c_wr8(uchar addr, uchar sub, uchar msb) { + + lml33_i2c_start(); + + if (lml33_i2c_wrbyte(addr) == 1 + || lml33_i2c_wrbyte(sub) == 1 + || lml33_i2c_wrbyte(msb) == 1) + return 0; + + lml33_i2c_stop(); + + return 1; +} + /* * The following mapping applies for the guests in the LML33 * @@ -252,7 +269,7 @@ lml33_post_idle(void) { } // lml33_post_write writes a byte to a guest using postoffice mechanism -static void +static int lml33_post_write(int guest, int reg, int v) { int w; @@ -269,14 +286,11 @@ lml33_post_write(int guest, int reg, int v) { writel(w, pciBaseAddr + ZR36057_POST_OFFICE); // wait for postoffice not busy - w = lml33_post_idle(); - - // decide if write went ok - if (w == -1) error(Eio); + return lml33_post_idle() == -1; } // lml33_post_read reads a byte from a guest using postoffice mechanism -static uchar +static int lml33_post_read(int guest, int reg) { int w; @@ -295,12 +309,12 @@ lml33_post_read(int guest, int reg) { w = lml33_post_idle(); // decide if read went ok - if (w == -1) error(Eio); + if (w == -1) return -1; - return (uchar)(w & 0xFF); + return w & 0xFF; } -static void +static int lml33_zr060_write(int reg, int v) { int guest_id; @@ -308,10 +322,10 @@ lml33_zr060_write(int reg, int v) { lml33_post_write(guest_id, 1, reg>>8 & 0x03); lml33_post_write(guest_id, 2, reg & 0xff); - lml33_post_write(guest_id, 3, v); + return lml33_post_write(guest_id, 3, v); } -static uchar +static int lml33_zr060_read(int reg) { int guest_id; @@ -323,24 +337,203 @@ lml33_zr060_read(int reg) { return lml33_post_read(guest_id, 3); } -long -chipread(long addr, char *buf, long n, long off) { - long i; +static int +prepareBuffer(CodeData * this, int bufferNo) { + if(bufferNo >= 0 && bufferNo < NBUF && (this->statCom[bufferNo] & STAT_BIT)) { + this->statCom[bufferNo] = this->statComInitial[bufferNo]; + return this->fragmDescr[bufferNo].fragmLength; + } else + return -1; +} - for (i = 0; i < n; i++) { - *buf++ = lml33_i2c_rd8(addr, off++); +static int +getProcessedBuffer(CodeData* this){ + static lastBuffer=NBUF-1; + int lastBuffer0 = lastBuffer; + + while (1) { + lastBuffer = (lastBuffer+1) % NBUF; + if(this->statCom[lastBuffer]&STAT_BIT) + return lastBuffer; + if(lastBuffer==lastBuffer0) + break; } - return i; + return -1; } -long -post060read(char *buf, long n, long off) { - long i; +static int +getBuffer(CodeData *this, int bufferNo, void** bufferPtr, int* frameNo) { + int codeLength; + if(this->statCom[bufferNo] & STAT_BIT) { + *bufferPtr = (void*)this->fragmDescr[bufferNo].fragmAddress; + *frameNo = this->statCom[bufferNo] >> 24; + codeLength=((this->statCom[bufferNo] & 0x00FFFFFF) >> 1); + return codeLength; + } else + return -1; +} + +static long +vread(Chan *, void *va, long count, vlong pos) { + int prevFrame; + // how much bytes left to transfer for the header + int hdrLeft; + // Count of bytes that we need to copy into buf from code-buffer + // (different from count only while in header reading mode) + int cpcount = count; + // Count of bytes that we copied into buf altogether and will return + int retcount=0; + vlong thetime; + uchar *buf = va; + + //print("devlml::vread() count=%ld pos=%lld\n", count, pos); + + // If we just begin reading a file, pos would never be 0 otherwise + if (pos == 0 && hdrPos == -1) { + currentBuffer = -1; + currentBufferLength = 0; + frameNo = -1; + } + prevFrame = frameNo; + + // We get to the end of the current buffer, also covers just + // open file, since 0 >= -1 + if(hdrPos == -1 && pos >= currentBufferLength) { + prepareBuffer(codeData, currentBuffer); + // if not the first buffer read and single frame mode - return EOF + if (currentBuffer != -1 && singleFrame) + return 0; + while((currentBuffer = getProcessedBuffer(codeData)) == -1) + sleep(&sleeper, return0, 0); + currentBufferLength = getBuffer(codeData, currentBuffer, + ¤tBufferPtr, &frameNo); + + pos = 0; // ?????????????? + + // print("getBufffer %d -> %d 0x%x %d\n",currentBuffer, currentBufferLength, currentBufferPtr, frameNo); + if(frameNo != (prevFrame + 1) % 256) + print("Frames out of sequence: %d %d\n", prevFrame, frameNo); + // Fill in APP marker fields here + thetime = todget(); + frameHeader.sec = (ulong)(thetime / 1000000000LL); + frameHeader.usec = (ulong)(thetime % 1000000000LL) / 1000; + frameHeader.frameSize = currentBufferLength - 2 + sizeof(FrameHeader); + frameHeader.frameSeqNo++; + frameHeader.frameNo = frameNo; + hdrPos=0; + } + + if (hdrPos != -1) { + hdrLeft = sizeof(FrameHeader) - hdrPos; + // Write the frame size here + if (count >= hdrLeft) { + memmove(buf, (char*)&frameHeader + hdrPos, hdrLeft); + retcount += hdrLeft; + cpcount = count - hdrLeft; + pos = sizeof(frameHeader.mrkSOI); + hdrPos = -1; + } else { + memmove(buf, (char*)&frameHeader + hdrPos, count); + hdrPos += count; + return count; + } + } + + if(cpcount + pos > currentBufferLength) + cpcount = currentBufferLength - pos; + + memmove(buf + retcount, (char *)currentBufferPtr + pos, cpcount); + retcount += cpcount; + + //pr_debug("return %d %d\n",cpcount,retcount); + return retcount; +} + +static long +vwrite(Chan *, void *va, long count, vlong pos) { + // how much bytes left to transfer for the header + int hdrLeft; + char *buf = va; + + //print("devlml::vwrite() count=0x%x pos=0x%x\n", count, pos); + + // We just started writing, not into the header copy + if(pos==0 && hdrPos == -1) { + currentBuffer=-1; + currentBufferLength=0; + frameNo=-1; + bufferPrepared = 0; + } + + // We need next buffer to fill (either because we're done with the + // current buffer) of because we're just beginning (but not into the header) + if (hdrPos == -1 && pos >= currentBufferLength) { + while((currentBuffer = getProcessedBuffer(codeData)) == -1) + sleep(&sleeper, return0, 0); + // print("current buffer %d\n",currentBuffer); - for (i = 0; i < n; i++) { - *buf++ = lml33_zr060_read(off++); + getBuffer(codeData, currentBuffer, ¤tBufferPtr, &frameNo); + // We need to receive the header now + hdrPos = 0; } - return i; + + // We're into the header processing + if (hdrPos != -1) { + // Calculate how many bytes we need to receive to fill the header + hdrLeft = sizeof(FrameHeader) - hdrPos; + + // If we complete or go over the header with this count + if (count >= hdrLeft) { + // Adjust count of bytes that remain to be copied into video buffer + count = count - hdrLeft; + memmove((char*)&frameHeader + hdrPos, buf, hdrLeft); + // Make sure we have a standard LML33 header + if (frameHeader.mrkSOI == MRK_SOI + && frameHeader.mrkAPP3==MRK_APP3 + && strcmp(frameHeader.nm,APP_NAME) == 0) { + //print("Starting new buffer len=0x%x frame=%d\n", frameHeader.frameSize, frameHeader.frameSeqNo); + // Obtain values we need for playback process from the header + currentBufferLength = frameHeader.frameSize; + } else if (singleFrame) { + currentBufferLength = FRAGSIZE; + } else { + // We MUST have header for motion video decompression + print("No frame size (APP3 marker) in MJPEG file\n"); + error(Eio); + } + // Finish header processing + hdrPos = -1; + // Copy the header into the playback buffer + memmove(currentBufferPtr, (char*)&frameHeader, sizeof(FrameHeader)); + // And set position just behind header for playback buffer write + pos = sizeof(FrameHeader); + } else { + memmove((char*)&frameHeader + hdrPos, buf, count); + hdrPos += count; + return count; + } + } else + hdrLeft = 0; + + if(count + pos > currentBufferLength) { + count = currentBufferLength - pos; + } + + memmove((char *)currentBufferPtr + pos, buf + hdrLeft, count); + + pos += count; + // print("return 0x%x 0x%x\n",pos,count); + + // Now is the right moment to initiate playback of the frame (if it's full) + if(pos >= currentBufferLength) { + // We have written the frame, time to display it + //print("Passing written buffer to 067\n"); + prepareBuffer(codeData, currentBuffer); + bufferPrepared = 1; + } + //print("return 0x%lx 0x%x 0x%x 0x%x\n",pos,count,hdrLeft+count,currentBufferLength); + + return hdrLeft + count; } static void lmlintr(Ureg *, void *); @@ -378,12 +571,6 @@ vidreset(void) codeData->fragmDescr[i].fragmLength = (FRAGSIZE >> 1) | FRAGM_FINAL_B; } - // Get dynamic kernel memory allocaton for the driver - if((mjpgDrv = xallocz(sizeof(MjpgDrv), 0)) == nil) { - print("LML33: can't allocate dynamic memory for MjpgDrv\n"); - return; - } - print("initializing LML33 board..."); pciPhysBaseAddr = (void *)(pcidev->mem[0].bar & ~0x0F); @@ -438,10 +625,19 @@ vidopen(Chan *c, int omode) case Q856: case Q060: case Q067: - // allow one open per file break; case Qvideo: case Qjframe: + if (nopens) + error(Einuse); + nopens = 1; + singleFrame = (c->qid.path == Qjframe) ? 1 : 0;; + currentBuffer = 0; + currentBufferLength = 0; + currentBufferPtr = 0; + frameNo = 0; + bufferPrepared = 0; + hdrPos = -1; // allow one open total for these two break; } @@ -463,51 +659,89 @@ vidclose(Chan *c) } static long -vidread(Chan *c, void *buf, long n, vlong off) { +vidread(Chan *c, void *va, long n, vlong off) { + int i, d; + uchar *buf = va; switch(c->qid.path){ case Q819: - if (off < 0 || off + n > 20) + if (off < 0 || off + n > 0x20) return 0; - return chipread(BT819Addr, buf, n, off); + for (i = 0; i < n; i++) { + if ((d = lml33_i2c_rd8(BT819Addr, off++)) < 0) break; + *buf++ = d; + } + return n - i; case Q856: if (off < 0xda || off + n > 0xe0) return 0; - return chipread(BT856Addr, buf, n, off); + for (i = 0; i < n; i++) { + if ((d = lml33_i2c_rd8(BT856Addr, off++)) < 0) break; + *buf++ = d; + } + return n - i; case Q060: - return post060read(buf, n, off); + if (off < 0 || off + n > 0x60) + return 0; + for (i = 0; i < n; i++) { + if ((d = lml33_zr060_read(off++)) < 0) break; + *buf++ = d; + } + return n - i; case Q067: - if (off < 0 || off + n > 20 || (off & 0x3) || n != 4) return 0; - *(long *)buf = readl(pciBaseAddr + off); - return 4; + if (off < 0 || off + n > 0x200 || (off & 0x3)) + return 0; + for (i = n; i >= 4; i -= 4) { + *(long *)buf = readl(pciBaseAddr + off); + buf += 4; + off += 4; + } + return n-i; case Qvideo: case Qjframe: - return videoread(c, buf, n, off); + return vread(c, buf, n, off); } } static long -vidwrite(Chan *c, void *va, long n, vlong off) -{ +vidwrite(Chan *c, void *va, long n, vlong off) { + int i; + uchar *buf = va; switch(c->qid.path){ case Q819: - if (off < 0 || off + n > 20) + if (off < 0 || off + n > 0x20) return 0; - return chipwrite(BT819Addr, buf, n, off); + for (i = n; i > 0; i--) + if (lml33_i2c_wr8(BT819Addr, off++, *buf++) == 0) + break; + return n - i; case Q856: if (off < 0xda || off + n > 0xe0) return 0; - return chipwrite(BT856Addr, buf, n, off); + for (i = n; i > 0; i--) + if (lml33_i2c_wr8(BT856Addr, off++, *buf++) == 0) + break; + return n - i; case Q060: - return post060write(buf, n, off); + if (off < 0 || off + n > 0x60) + return 0; + for (i = 0; i < n; i++) + if (lml33_zr060_write(off++, *buf++) < 0) + break; + return n - i; case Q067: - if (off < 0 || off + n > 20 || (off & 0x3) || n != 4) return 0; - writel(*(long *)buf, pciBaseAddr + off); - return 4; + if (off < 0 || off + n > 0x200 || (off & 0x3)) + return 0; + for (i = n; i >= 4; i -= 4) { + writel(*(long *)buf, pciBaseAddr + off); + buf += 4; + off += 4; + } + return n-i; case Qvideo: case Qjframe: - return videowrite(c, buf, n, off); + return vwrite(c, buf, n, off); } } @@ -533,8 +767,15 @@ Dev viddevtab = { }; static void -lmlintr(Ureg *ur, void *) -{ +lmlintr(Ureg *, void *) { + ulong flags = readl(pciBaseAddr+ZR36057_INTR_STAT); + +// print("MjpgDrv_intrHandler stat=0x%08x\n", flags); + // Reset all interrupts from 067 + writel(0xff000000, pciBaseAddr + ZR36057_INTR_STAT); + if(flags & ZR36057_INTR_JPEGREP) + wakeup(&sleeper); + return; } diff --git a/pc/devlml.h b/pc/devlml.h index 4e93d87feb38e5a2c9e328f31048f9489bbfbddd..70b66f041a1cb65a7c3436a28b644ed341e6076e 100644 --- a/pc/devlml.h +++ b/pc/devlml.h @@ -87,6 +87,8 @@ typedef struct { #define ZR36057_POST_PEND 0x02000000 #define ZR36057_POST_TIME 0x01000000 #define ZR36057_POST_DIR 0x00800000 +#define ZR36057_INTR_JPEGREP 0x08000000 +#define ZR36057_INTR_STAT 0x03c #define MB 0x100000 #define NBUF 4 @@ -101,6 +103,7 @@ typedef struct { #define readw(a) (*(ushort *)(a)) #define readb(a) (*(uchar *)(a)) +typedef struct FrameHeader FrameHeader; typedef struct MjpgDrv MjpgDrv; typedef struct Fragment Fragment; typedef struct FragmentTable FragmentTable; @@ -113,12 +116,12 @@ struct Fragment { uchar fragbytes[FRAGSIZE]; }; -struct FragmentTable { +struct FragmentTable { // Don't modify this struct, used by h/w Fragment * fragmAddress; // Physical address ulong fragmLength; }; -struct CodeData { +struct CodeData { // Don't modify this struct, used by h/w char idString[16]; ulong statCom[4]; // Physical address ulong statComInitial[4]; // Physical address @@ -126,23 +129,24 @@ struct CodeData { Fragment frag[4]; }; -extern char static_MjpgDrv_GPL_Notice[]; -extern struct file_operations static_MjpgDrv_fOps; - -struct MjpgDrv { - int openCount; - int sleepFlag; - struct wait_queue * intrWaitQ; -}; - static void * pciPhysBaseAddr; static ulong pciBaseAddr; static Pcidev * pcidev; -void LML33Board_mjpegGo(LML33Board*); - -void MjpgDrv_ctor(MjpgDrv*); -void MjpgDrv_dtor(MjpgDrv*); -int MjpgDrv_open(struct inode *iNode, struct file *filePtr); -void MjpgDrv_release(struct inode *iNode, struct file *filePtr); -void MjpgDrv_intrHandler(int irqNo, void *devId, struct pt_regs *ptRegs); +//If we're on the little endian architecture, then 0xFF, 0xD8 byte sequence is +#define MRK_SOI 0xD8FF +#define MRK_APP3 0xE3FF +#define APP_NAME "LML" + +struct FrameHeader // Don't modify this struct, used by h/w +{ + short mrkSOI; + short mrkAPP3; + short lenAPP3; + char nm[4]; + short frameNo; + ulong sec; + ulong usec; + ulong frameSize; + ulong frameSeqNo; +};