File:
[DVB] /
margi2 /
dram.c
Revision
1.2:
download - view:
text,
annotated -
select for diffs
Wed Apr 25 15:31:08 2001 UTC (23 years, 1 month ago) by
mocm
Branches:
MAIN
CVS tags:
HEAD
- various fixes
- more support for DVB API
- support for setting video stream type (works with ntuxplayer and AC3 playback)
- started with support for separate writing in audio and video buffer
/*
dram.c
Copyright (C) Christian Wolff for convergence integrated media.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/////////////////////////////////
// //
// L64021 DRAM Memory Access //
// //
/////////////////////////////////
#define __NO_VERSION__
#include "dram.h"
#include "l64021.h"
#define EMERGENCYCOUNTER 5
// where: 21 bit DRAM Word-Address, 4 word aligned
// size: bytes (8 byte aligned, remainder will be filled with fill value)
// data: fill value
// returns 0 on success, -1 on collision with DMA transfer
int DRAMFillByte(struct cvdv_cards *card, u32 where, int size, u8 data)
{
int i, j, k, n;
u8 volatile flag;
size = (size >> 3) + ((size & 7) ? 1 : 0); // 8 bytes at a time, padding with garbage
where >>= 2; // 8 byte aligned data
DecoderSetByte(card, 0x0C1, 0x08);
//TODO: 0x80?
DecoderWriteByte(card, 0x0C6, (u8) ((where >> 16) & 0x00000007L));
DecoderWriteByte(card, 0x0C5, (u8) ((where >> 8) & 0x000000FFL));
DecoderWriteByte(card, 0x0C4, (u8) (where & 0x000000FFL));
i = 0;
for (j = 0; j < size; j++) {
for (k = 0; k < 8; k++) {
n = EMERGENCYCOUNTER;
do { // wait if FIFO full
flag = DecoderReadByte(card, 0x0C0);
} while ((flag & 0x08) && n--);
if (n<0)
return -1;
DecoderWriteByte(card, 0x0C3, data);
}
}
flag = DecoderReadByte(card, 0x0C0);
n = EMERGENCYCOUNTER;
do { // wait for FIFO empty
flag = DecoderReadByte(card, 0x0C0);
} while (!(flag & 0x04) && n--);
return ((n>=0) ? 0 : -1);
}
// where: 21 bit DRAM Word-Address, 8 byte aligned
// size: bytes (8 byte aligned, remainder will be filled with garbage)
// swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.)
// returns 0 on success, -1 on collision with DMA transfer
int DRAMWriteByte(struct cvdv_cards *card, u32 where, int size, u8 * data,
int swapburst)
{
int i, j, k, n;
u8 volatile flag;
size = (size >> 3) + ((size & 7) ? 1 : 0); // 8 bytes at a time, padding with garbage
where >>= 2; // 8 byte aligned data
MDEBUG(4, ": Moving %d 64-bit-words to DRAM 0x%08X\n",size,where);
//if (swap) DecoderDelByte(card,0x0C1,0x08); // byte swapping of 8 byte bursts
//else DecoderSetByte(card,0x0C1,0x08); // no byte swapping
DecoderSetByte(card, 0x0C1, 0x08); // no byte swapping
DecoderWriteByte(card, 0x0C6, (u8) ((where >> 16) & 0x00000007L));
DecoderWriteByte(card, 0x0C5, (u8) ((where >> 8) & 0x000000FFL));
DecoderWriteByte(card, 0x0C4, (u8) (where & 0x000000FFL));
i = 0;
if (swapburst) {
for (j = 0; j < size; j++) {
for (k = 7; k >= 0; k--) {
n = EMERGENCYCOUNTER;
do { // wait if FIFO full
flag =
DecoderReadByte(card, 0x0C0);
} while ((flag & 0x08) && n--);
if (n<0)
return -1;
DecoderWriteByte(card, 0x0C3, data[i + k]);
}
i += 8;
}
} else {
for (j = 0; j < size; j++) {
for (k = 0; k < 8; k++) {
n = EMERGENCYCOUNTER;
do { // wait if FIFO full
flag =
DecoderReadByte(card, 0x0C0);
} while ((flag & 0x08) && n--);
if (n<0)
return -1;
DecoderWriteByte(card, 0x0C3, data[i++]);
}
}
}
flag = DecoderReadByte(card, 0x0C0);
n = EMERGENCYCOUNTER;
do { // wait for FIFO empty
flag = DecoderReadByte(card, 0x0C0);
} while (!(flag & 0x04) && n--);
return ((n>=0) ? 0 : -1);
}
// where: 21 bit DRAM Word-Address, 4 word aligned
// size: words (4 word aligned, remainder will be filled with garbage)
// swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.)
// returns 0 on success, -1 on collision with DMA transfer
int DRAMWriteWord(struct cvdv_cards *card, u32 where, int size, u16 * data,
int swap)
{
int i, j, k, n;
u8 volatile flag;
size = (size >> 2) + ((size & 3) ? 1 : 0); // 4 words at a time, padding with garbage
where >>= 2; // 8 byte aligned data
MDEBUG(4, ": Moving %d 64-bit-words to DRAM 0x%08X\n",size,where);
//TODO: swap manually
if (swap)
DecoderDelByte(card, 0x0C1, 0x08); // byte swapping of 8 byte bursts
else
DecoderSetByte(card, 0x0C1, 0x08); // no byte swapping
DecoderWriteByte(card, 0x0C6, (u8) ((where >> 16) & 0x00000007L));
DecoderWriteByte(card, 0x0C5, (u8) ((where >> 8) & 0x000000FFL));
DecoderWriteByte(card, 0x0C4, (u8) (where & 0x000000FFL));
i = 0;
for (j = 0; j < size; j++) {
for (k = 0; k < 4; k++) {
n = EMERGENCYCOUNTER;
do { // wait if FIFO full
flag = DecoderReadByte(card, 0x0C0);
} while ((flag & 0x08) && n--);
if (n<0)
return -1;
DecoderWriteByte(card, 0x0C3, data[i] >> 8);
n = EMERGENCYCOUNTER;
do { // wait if FIFO full
flag = DecoderReadByte(card, 0x0C0);
} while ((flag & 0x08) && n--);
if (n<0)
return -1;
DecoderWriteByte(card, 0x0C3, data[i++]);
}
}
flag = DecoderReadByte(card, 0x0C0);
n = EMERGENCYCOUNTER;
do { // wait for FIFO empty
flag = DecoderReadByte(card, 0x0C0);
} while (!(flag & 0x04) && n--);
return ((n>=0) ? 0 : -1);
}
// where: 21 bit DRAM Word-Address, 8 byte aligned
// size: bytes
// swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.)
// returns 0 on success, -1 on collision with DMA transfer
int DRAMReadByte(struct cvdv_cards *card, u32 where, int size, u8 * data,
int swap)
{
int i, j, rsize, n;
u8 volatile flag;
rsize = size & 7; // padding bytes
size = size >> 3; // 8 bytes at a time
where >>= 2; // 8 byte aligned data
MDEBUG(4, ": Moving %d 64-bit-words to DRAM 0x%08X\n",size,where);
//TODO: swap manually
if (swap)
DecoderDelByte(card, 0x0C1, 0x08); // byte swapping of 8 byte bursts
else
DecoderSetByte(card, 0x0C1, 0x08); // no byte swapping
DecoderWriteByte(card, 0x0C9, (u8) ((where >> 16) & 0x00000007L));
DecoderWriteByte(card, 0x0C8, (u8) ((where >> 8) & 0x000000FFL));
DecoderWriteByte(card, 0x0C7, (u8) (where & 0x000000FFL));
i = 0;
for (j = 0; j < size; j++) {
n = EMERGENCYCOUNTER;
do { // wait if FIFO empty
flag = DecoderReadByte(card, 0x0C0);
} while ((flag & 0x01) && n--);
if (n<0) // WARNING nicht if(!n)
return -1;
data[i++] = DecoderReadByte(card, 0x0C2);
data[i++] = DecoderReadByte(card, 0x0C2);
data[i++] = DecoderReadByte(card, 0x0C2);
data[i++] = DecoderReadByte(card, 0x0C2);
data[i++] = DecoderReadByte(card, 0x0C2);
data[i++] = DecoderReadByte(card, 0x0C2);
data[i++] = DecoderReadByte(card, 0x0C2);
data[i++] = DecoderReadByte(card, 0x0C2);
}
n = EMERGENCYCOUNTER;
do { // wait if FIFO empty
flag = DecoderReadByte(card, 0x0C0);
} while ((flag & 0x01) && n--);
if (n<0)
return -1;
for (j = 0; j < rsize; j++)
data[i++] = DecoderReadByte(card, 0x0C2);
flag = DecoderReadByte(card, 0x0C0);
n = EMERGENCYCOUNTER;
do { // wait for FIFO full
flag = DecoderReadByte(card, 0x0C0);
} while (!(flag & 0x02) && n--);
return ((n>=0) ? 0 : -1);
}
// where: 21 bit DRAM Word-Address, 4 word aligned
// size: words
// swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.)
// returns 0 on success, -1 on collision with DMA transfer
int DRAMReadWord(struct cvdv_cards *card, u32 where, int size, u16 * data,
int swap)
{
int i, j, rsize, n;
u8 volatile flag;
u8 b;
rsize = size & 3; // padding words
size >>= 2; // 4 words at a time
where >>= 2; // 8 byte aligned data
MDEBUG(4, ": Reading %d 64-bit-words and %d 16-bit-words from DRAM 0x%08X\n",
size,rsize,where);
//TODO: swap manually
if (swap)
DecoderDelByte(card, 0x0C1, 0x08); // byte swapping of 8 byte bursts
else
DecoderSetByte(card, 0x0C1, 0x08); // no byte swapping
DecoderWriteByte(card, 0x0C9, (u8) ((where >> 16) & 0x00000007L));
DecoderWriteByte(card, 0x0C8, (u8) ((where >> 8) & 0x000000FFL));
DecoderWriteByte(card, 0x0C7, (u8) (where & 0x000000FFL));
i = 0;
for (j = 0; j < size; j++) {
n = EMERGENCYCOUNTER;
do { // wait if FIFO empty
flag = DecoderReadByte(card, 0x0C0);
} while ((flag & 0x01) && n--);
if (n<0)
return -1;
b = DecoderReadByte(card, 0x0C2);
data[i++] = ((b << 8) | DecoderReadByte(card, 0x0C2));
b = DecoderReadByte(card, 0x0C2);
data[i++] = ((b << 8) | DecoderReadByte(card, 0x0C2));
b = DecoderReadByte(card, 0x0C2);
data[i++] = ((b << 8) | DecoderReadByte(card, 0x0C2));
b = DecoderReadByte(card, 0x0C2);
data[i++] = ((b << 8) | DecoderReadByte(card, 0x0C2));
}
n = EMERGENCYCOUNTER;
do { // wait if FIFO empty
flag = DecoderReadByte(card, 0x0C0);
} while ((flag & 0x01) && n--);
if (n<0)
return -1;
for (j = 0; j < rsize; j++) {
b = DecoderReadByte(card, 0x0C2);
data[i++] = ((b << 8) | DecoderReadByte(card, 0x0C2));
}
flag = DecoderReadByte(card, 0x0C0);
n = EMERGENCYCOUNTER;
do { // wait for FIFO full
flag = DecoderReadByte(card, 0x0C0);
} while (!(flag & 0x02) && n--);
return ((n>=0) ? 0 : -1);
}
// where: 21 bit DRAM Word-Address, 4 word aligned
// size: words
// swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.)
// returns -1 on success (equal content),
// word position on error (compare failure),
// -2 on collision with DMA transfer
int DRAMVerifyWord(struct cvdv_cards *card, u32 where, int size,
u16 * data, int swap)
{
int i, j, rsize, n;
u8 volatile flag, b;
rsize = size & 3; // padding words
size >>= 2; // 4 words at a time
where >>= 2; // 8 byte aligned data, now 19 bit 64-bit-word-address
//TODO: swap manually
if (swap)
DecoderDelByte(card, 0x0C1, 0x08); // byte swapping of 8 byte bursts
else
DecoderSetByte(card, 0x0C1, 0x08); // no byte swapping
DecoderWriteByte(card, 0x0C9, (u8) ((where >> 16) & 0x00000007L));
DecoderWriteByte(card, 0x0C8, (u8) ((where >> 8) & 0x000000FFL));
DecoderWriteByte(card, 0x0C7, (u8) (where & 0x000000FFL));
i = 0;
for (j = 0; j < size; j++) {
n = EMERGENCYCOUNTER;
do { // wait if FIFO empty
flag = DecoderReadByte(card, 0x0C0);
} while ((flag & 0x01) && n--);
b = DecoderReadByte(card, 0x0C2);
if (data[i++] != ((b << 8) | DecoderReadByte(card, 0x0C2)))
return i;
b = DecoderReadByte(card, 0x0C2);
if (data[i++] != ((b << 8) | DecoderReadByte(card, 0x0C2)))
return i;
b = DecoderReadByte(card, 0x0C2);
if (data[i++] != ((b << 8) | DecoderReadByte(card, 0x0C2)))
return i;
b = DecoderReadByte(card, 0x0C2);
if (data[i++] != ((b << 8) | DecoderReadByte(card, 0x0C2)))
return i;
}
n = EMERGENCYCOUNTER;
do { // wait if FIFO empty
flag = DecoderReadByte(card, 0x0C0);
} while ((flag & 0x01) && n--);
for (j = 0; j < rsize; j++) {
b = DecoderReadByte(card, 0x0C2);
if (data[i++] != ((b << 8) | DecoderReadByte(card, 0x0C2)))
return i;
}
flag = DecoderReadByte(card, 0x0C0);
n = EMERGENCYCOUNTER;
do { // wait for FIFO full
flag = DecoderReadByte(card, 0x0C0);
} while (!(flag & 0x02) && n--);
return -1;
}
// WARNING: better not use this one. It can collide with normal DRAM access and other DMA transfers
// If you want to use it, implement card->DMAMoveBusy in all other DMA functions, initialisation, and header file
// source, destination: 21 bit DRAM Word-Address, 4 word aligned
// size: byte (8 byte aligned, hang over bytes will NOT be moved)
// returns 0 on success on success,
// -1 on collision with DMA transfer,
// -2 on interrupt handler not installed
int DRAMMove(struct cvdv_cards *card, u32 source, u32 destination,
int size)
{
if (!card->IntInstalled)
return -2;
if (card->DMAABusy || card->DMABBusy)
return -1;
size >>= 3; // 64-bit-words
source >>= 2; // 8 byte aligned data,
destination >>= 2; // now 19 bit 64-bit-word-address
DecoderDelByte(card, 0x0C1, 0x06); // DMA idle
DecoderWriteByte(card, 0x0DA, (u8) ((source >> 16) & 0x00000007L));
DecoderWriteByte(card, 0x0D9, (u8) ((source >> 8) & 0x000000FFL));
DecoderWriteByte(card, 0x0D8, (u8) (source & 0x000000FFL));
DecoderWriteByte(card, 0x0D7,
(u8) ((destination >> 16) & 0x00000007L));
DecoderWriteByte(card, 0x0D6,
(u8) ((destination >> 8) & 0x000000FFL));
DecoderWriteByte(card, 0x0D5, (u8) (destination & 0x000000FFL));
//card->DMAMoveBusy=1; // would have to catch that in all the other DMA routines
DecoderSetByte(card, 0x0C1, 0x06); // DMA block move
return 0;
}
// size in words
// align: number of words on wich start of block will be aligned
// return value is 21 bit word address, or 0xFFFFFFFF on error
u32 DRAMAlloc(struct cvdv_cards * card, u32 size, int align)
{
struct DRAMBlock *ptr, *ptr2;
u32 addr = 0;
u32 alignmask = align - 1;
int valid = 0;
if (size == 0)
return BLANK;
if (size & 3)
size = (size & ~3) + 4; // increase size if not 64 bit aligned
if (card->DRAMFirstBlock == NULL) { // virgin territory?
valid = ((addr + size) <= card->DRAMSize); // does it fit at all?
} else {
addr = 0;
valid = ((addr + size) <= card->DRAMSize); // does it fit at all?
for (ptr2 = card->DRAMFirstBlock;
(ptr2 != NULL) && (valid); ptr2 = ptr2->next) { // check against all existing blocks
if ((ptr2->start >= addr)
&& (ptr2->start < (addr + size)))
valid = 0; // existing block start inside new block?
else if (((ptr2->start + ptr2->length) > addr)
&& ((ptr2->start + ptr2->length) <=
(addr + size)))
valid = 0; // existing block end inside new block?
else if ((ptr2->start < addr)
&& ((ptr2->start + ptr2->length) >
(addr + size))) valid = 0; // new block inside existing block?
}
for (ptr = card->DRAMFirstBlock; (ptr != NULL) && (!valid);
ptr = ptr->next) { // check all existing blocks
addr = ptr->start + ptr->length; // assume, after this block is free space
if (addr & alignmask)
addr = (addr & ~alignmask) + align; // round up to alignation border
valid = ((addr + size) <= card->DRAMSize); // does it fit at all?
for (ptr2 = card->DRAMFirstBlock;
(ptr2 != NULL) && (valid); ptr2 = ptr2->next) { // check against all existing blocks
if ((ptr2->start >= addr)
&& (ptr2->start < (addr + size)))
valid = 0; // existing block start inside new block?
else
if (
((ptr2->start + ptr2->length) >
addr)
&& ((ptr2->start + ptr2->length) <=
(addr + size)))
valid = 0; // existing block end inside new block?
else if ((ptr2->start < addr)
&& ((ptr2->start + ptr2->length) >
(addr + size)))
valid = 0; // new block inside existing block?
}
}
}
if (valid) { // The new block fits
ptr =
(struct DRAMBlock *) kmalloc(sizeof(struct DRAMBlock),
GFP_KERNEL);
if (ptr == NULL) {
printk(KERN_INFO LOGNAME
": ERROR: out of kernel memory. Please reboot if possible.\n");
return BLANK; // out of kernel mem
}
if (card->DRAMFirstBlock == NULL) {
card->DRAMFirstBlock = ptr;
} else {
ptr2 = card->DRAMFirstBlock;
while (ptr2->next != NULL)
ptr2 = ptr2->next;
ptr2->next = ptr;
}
ptr->next = NULL;
ptr->start = addr;
ptr->length = size;
MDEBUG(1,": DRAM Allocate 0x%08X-0x%08X\n", addr,
addr + size - 1);
return addr;
}
return BLANK;
}
// addr is the return value of that resp. DRAMAlloc call
// returns 0 on success (always)
int DRAMFree(struct cvdv_cards *card, u32 addr)
{
struct DRAMBlock *ptr, *ptr2;
ptr2 = NULL;
for (ptr = card->DRAMFirstBlock; ptr != NULL; ptr = ptr->next) { // check all existent blocks
if (addr == ptr->start) { // this is our block to be removed
if (ptr2 == NULL)
card->DRAMFirstBlock = ptr->next;
else
ptr2->next = ptr->next;
kfree(ptr);
MDEBUG(1, ": DRAM Free 0x%08X\n", addr);
} else
ptr2 = ptr;
}
return 0;
}
// free all blocks
// returns 0 on success (always)
int DRAMRelease(struct cvdv_cards *card)
{
struct DRAMBlock *ptr, *ptr2;
MDEBUG(1, ": -- DRAMRelease\n");
for (ptr = card->DRAMFirstBlock; ptr != NULL; ptr = ptr2) { // check all existent blocks
ptr2 = ptr->next;
MDEBUG(4, ": kfree(0x%08X)\n",(int)ptr);
kfree(ptr);
}
card->DRAMFirstBlock = NULL;
return 0;
}
LinuxTV legacy CVS <linuxtv.org/cvs>