|
|
#include <linux/types.h>
|
#include <linux/types.h>
|
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
#include <linux/mm.h>
|
#include <linux/mm.h>
|
#include <asm/bootinfo.h>
|
#include <asm/bootinfo.h>
|
#include <asm/atarihw.h>
|
#include <asm/atarihw.h>
|
#include <asm/page.h>
|
#include <asm/page.h>
|
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
|
|
#if 0
|
#if 0
|
|
|
struct stram_desc
|
struct stram_desc
|
{
|
{
|
unsigned first:1;
|
unsigned first:1;
|
unsigned last:1;
|
unsigned last:1;
|
unsigned alloced:1;
|
unsigned alloced:1;
|
unsigned length:24;
|
unsigned length:24;
|
};
|
};
|
|
|
#define DP(ptr) ((struct stram_desc *) (ptr))
|
#define DP(ptr) ((struct stram_desc *) (ptr))
|
|
|
static unsigned long stramsize;
|
static unsigned long stramsize;
|
static unsigned long stramaddr;
|
static unsigned long stramaddr;
|
|
|
void
|
void
|
atari_stram_init (void)
|
atari_stram_init (void)
|
{
|
{
|
struct stram_desc *dp;
|
struct stram_desc *dp;
|
stramaddr = boot_info.bi_atari.stram_start;
|
stramaddr = boot_info.bi_atari.stram_start;
|
stramsize = boot_info.bi_atari.stram_size;
|
stramsize = boot_info.bi_atari.stram_size;
|
|
|
/* initialize start boundary */
|
/* initialize start boundary */
|
dp = DP (stramaddr);
|
dp = DP (stramaddr);
|
dp->first = 1;
|
dp->first = 1;
|
dp->alloced = 0;
|
dp->alloced = 0;
|
dp->length = stramsize - 2 * sizeof (*dp);
|
dp->length = stramsize - 2 * sizeof (*dp);
|
|
|
/* initialize end boundary */
|
/* initialize end boundary */
|
dp = DP (stramaddr + stramsize) - 1;
|
dp = DP (stramaddr + stramsize) - 1;
|
dp->last = 1;
|
dp->last = 1;
|
dp->alloced = 0;
|
dp->alloced = 0;
|
dp->length = stramsize - 2 * sizeof (*dp);
|
dp->length = stramsize - 2 * sizeof (*dp);
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk ("stram end boundary is %p, length is %d\n", dp,
|
printk ("stram end boundary is %p, length is %d\n", dp,
|
dp->length);
|
dp->length);
|
#endif
|
#endif
|
}
|
}
|
|
|
void *
|
void *
|
atari_stram_alloc (long size)
|
atari_stram_alloc (long size)
|
{
|
{
|
/* last chunk */
|
/* last chunk */
|
struct stram_desc *dp;
|
struct stram_desc *dp;
|
void *ptr;
|
void *ptr;
|
|
|
/* round off */
|
/* round off */
|
size = (size + 3) & ~3;
|
size = (size + 3) & ~3;
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk ("stram_alloc: allocate %ld bytes\n", size);
|
printk ("stram_alloc: allocate %ld bytes\n", size);
|
#endif
|
#endif
|
|
|
/*
|
/*
|
* get pointer to descriptor for last chunk by
|
* get pointer to descriptor for last chunk by
|
* going backwards from end chunk
|
* going backwards from end chunk
|
*/
|
*/
|
dp = DP (stramaddr + stramsize) - 1;
|
dp = DP (stramaddr + stramsize) - 1;
|
dp = DP ((unsigned long) dp - dp->length) - 1;
|
dp = DP ((unsigned long) dp - dp->length) - 1;
|
|
|
while ((dp->alloced || dp->length < size) && !dp->first)
|
while ((dp->alloced || dp->length < size) && !dp->first)
|
dp = DP ((unsigned long) dp - dp[-1].length) - 2;
|
dp = DP ((unsigned long) dp - dp[-1].length) - 2;
|
|
|
if (dp->alloced || dp->length < size)
|
if (dp->alloced || dp->length < size)
|
{
|
{
|
printk ("no stram available for %ld allocation\n", size);
|
printk ("no stram available for %ld allocation\n", size);
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
if (dp->length < size + 2 * sizeof (*dp))
|
if (dp->length < size + 2 * sizeof (*dp))
|
{
|
{
|
/* length too small to split; allocate the whole thing */
|
/* length too small to split; allocate the whole thing */
|
dp->alloced = 1;
|
dp->alloced = 1;
|
ptr = (void *) (dp + 1);
|
ptr = (void *) (dp + 1);
|
dp = DP ((unsigned long) ptr + dp->length);
|
dp = DP ((unsigned long) ptr + dp->length);
|
dp->alloced = 1;
|
dp->alloced = 1;
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk ("stram_alloc: no split\n");
|
printk ("stram_alloc: no split\n");
|
#endif
|
#endif
|
}
|
}
|
else
|
else
|
{
|
{
|
/* split the extent; use the end part */
|
/* split the extent; use the end part */
|
long newsize = dp->length - (2 * sizeof (*dp) + size);
|
long newsize = dp->length - (2 * sizeof (*dp) + size);
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk ("stram_alloc: splitting %d to %ld\n", dp->length,
|
printk ("stram_alloc: splitting %d to %ld\n", dp->length,
|
newsize);
|
newsize);
|
#endif
|
#endif
|
dp->length = newsize;
|
dp->length = newsize;
|
dp = DP ((unsigned long) (dp + 1) + newsize);
|
dp = DP ((unsigned long) (dp + 1) + newsize);
|
dp->first = dp->last = 0;
|
dp->first = dp->last = 0;
|
dp->alloced = 0;
|
dp->alloced = 0;
|
dp->length = newsize;
|
dp->length = newsize;
|
dp++;
|
dp++;
|
dp->first = dp->last = 0;
|
dp->first = dp->last = 0;
|
dp->alloced = 1;
|
dp->alloced = 1;
|
dp->length = size;
|
dp->length = size;
|
ptr = (void *) (dp + 1);
|
ptr = (void *) (dp + 1);
|
dp = DP ((unsigned long) ptr + size);
|
dp = DP ((unsigned long) ptr + size);
|
dp->alloced = 1;
|
dp->alloced = 1;
|
dp->length = size;
|
dp->length = size;
|
}
|
}
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk ("stram_alloc: returning %p\n", ptr);
|
printk ("stram_alloc: returning %p\n", ptr);
|
#endif
|
#endif
|
return ptr;
|
return ptr;
|
}
|
}
|
|
|
void
|
void
|
atari_stram_free (void *ptr)
|
atari_stram_free (void *ptr)
|
{
|
{
|
struct stram_desc *sdp = DP (ptr) - 1, *dp2;
|
struct stram_desc *sdp = DP (ptr) - 1, *dp2;
|
struct stram_desc *edp = DP ((unsigned long) ptr + sdp->length);
|
struct stram_desc *edp = DP ((unsigned long) ptr + sdp->length);
|
|
|
/* deallocate the chunk */
|
/* deallocate the chunk */
|
sdp->alloced = edp->alloced = 0;
|
sdp->alloced = edp->alloced = 0;
|
|
|
/* check if we should merge with the previous chunk */
|
/* check if we should merge with the previous chunk */
|
if (!sdp->first && !sdp[-1].alloced)
|
if (!sdp->first && !sdp[-1].alloced)
|
{
|
{
|
dp2 = DP ((unsigned long) sdp - sdp[-1].length) - 2;
|
dp2 = DP ((unsigned long) sdp - sdp[-1].length) - 2;
|
dp2->length += sdp->length + 2 * sizeof (*sdp);
|
dp2->length += sdp->length + 2 * sizeof (*sdp);
|
edp->length = dp2->length;
|
edp->length = dp2->length;
|
sdp = dp2;
|
sdp = dp2;
|
}
|
}
|
|
|
/* check if we should merge with the following chunk */
|
/* check if we should merge with the following chunk */
|
if (!edp->last && !edp[1].alloced)
|
if (!edp->last && !edp[1].alloced)
|
{
|
{
|
dp2 = DP ((unsigned long) edp + edp[1].length) + 2;
|
dp2 = DP ((unsigned long) edp + edp[1].length) + 2;
|
dp2->length += edp->length + 2 * sizeof (*sdp);
|
dp2->length += edp->length + 2 * sizeof (*sdp);
|
sdp->length = dp2->length;
|
sdp->length = dp2->length;
|
edp = dp2;
|
edp = dp2;
|
}
|
}
|
}
|
}
|
|
|
#else
|
#else
|
|
|
#include <linux/mm.h>
|
#include <linux/mm.h>
|
|
|
/* ++roman:
|
/* ++roman:
|
*
|
*
|
* New version of ST-Ram buffer allocation. Instead of using the
|
* New version of ST-Ram buffer allocation. Instead of using the
|
* 1 MB - 4 KB that remain when the ST-Ram chunk starts at $1000
|
* 1 MB - 4 KB that remain when the ST-Ram chunk starts at $1000
|
* (1 MB granularity!), such buffers are reserved like this:
|
* (1 MB granularity!), such buffers are reserved like this:
|
*
|
*
|
* - If the kernel resides in ST-Ram anyway, we can take the buffer
|
* - If the kernel resides in ST-Ram anyway, we can take the buffer
|
* from behind the current kernel data space the normal way
|
* from behind the current kernel data space the normal way
|
* (incrementing start_mem).
|
* (incrementing start_mem).
|
*
|
*
|
* - If the kernel is in TT-Ram, stram_init() initializes start and
|
* - If the kernel is in TT-Ram, stram_init() initializes start and
|
* end of the available region. Buffers are allocated from there
|
* end of the available region. Buffers are allocated from there
|
* and mem_init() later marks the such used pages as reserved.
|
* and mem_init() later marks the such used pages as reserved.
|
* Since each TT-Ram chunk is at least 4 MB in size, I hope there
|
* Since each TT-Ram chunk is at least 4 MB in size, I hope there
|
* won't be an overrun of the ST-Ram region by normal kernel data
|
* won't be an overrun of the ST-Ram region by normal kernel data
|
* space.
|
* space.
|
*
|
*
|
* For that, ST-Ram may only be allocated while kernel initialization
|
* For that, ST-Ram may only be allocated while kernel initialization
|
* is going on, or exactly: before mem_init() is called. There is also
|
* is going on, or exactly: before mem_init() is called. There is also
|
* no provision now for freeing ST-Ram buffers. It seems that isn't
|
* no provision now for freeing ST-Ram buffers. It seems that isn't
|
* really needed.
|
* really needed.
|
*
|
*
|
* ToDo:
|
* ToDo:
|
* Check the high level scsi code what is done when the
|
* Check the high level scsi code what is done when the
|
* UNCHECKED_ISA_DMA flag is set. It guess, it is just a test for adr
|
* UNCHECKED_ISA_DMA flag is set. It guess, it is just a test for adr
|
* < 16 Mega. There should be call to atari_stram_alloc() instead.
|
* < 16 Mega. There should be call to atari_stram_alloc() instead.
|
*
|
*
|
* Also ToDo:
|
* Also ToDo:
|
* Go through head.S and delete parts no longer needed (transparent
|
* Go through head.S and delete parts no longer needed (transparent
|
* mapping of ST-Ram etc.)
|
* mapping of ST-Ram etc.)
|
*
|
*
|
*/
|
*/
|
|
|
|
|
unsigned long rsvd_stram_beg, rsvd_stram_end;
|
unsigned long rsvd_stram_beg, rsvd_stram_end;
|
/* Start and end of the reserved ST-Ram region */
|
/* Start and end of the reserved ST-Ram region */
|
static unsigned long stram_end;
|
static unsigned long stram_end;
|
/* Overall end of ST-Ram */
|
/* Overall end of ST-Ram */
|
|
|
|
|
void atari_stram_init( void )
|
void atari_stram_init( void )
|
|
|
{ int i;
|
{ int i;
|
|
|
for( i = 0; i < boot_info.num_memory; ++i ) {
|
for( i = 0; i < boot_info.num_memory; ++i ) {
|
if (boot_info.memory[i].addr == 0) {
|
if (boot_info.memory[i].addr == 0) {
|
rsvd_stram_beg = PTOV( 0x800 ); /* skip super-only first 2 KB! */
|
rsvd_stram_beg = PTOV( 0x800 ); /* skip super-only first 2 KB! */
|
rsvd_stram_end = rsvd_stram_beg;
|
rsvd_stram_end = rsvd_stram_beg;
|
stram_end = rsvd_stram_beg - 0x800 + boot_info.memory[i].size;
|
stram_end = rsvd_stram_beg - 0x800 + boot_info.memory[i].size;
|
return;
|
return;
|
}
|
}
|
}
|
}
|
/* Should never come here! (There is always ST-Ram!) */
|
/* Should never come here! (There is always ST-Ram!) */
|
}
|
}
|
|
|
|
|
void *atari_stram_alloc( long size, unsigned long *start_mem )
|
void *atari_stram_alloc( long size, unsigned long *start_mem )
|
|
|
{
|
{
|
static int kernel_in_stram = -1;
|
static int kernel_in_stram = -1;
|
|
|
void *adr = 0;
|
void *adr = 0;
|
|
|
if (kernel_in_stram < 0)
|
if (kernel_in_stram < 0)
|
kernel_in_stram = (PTOV( 0 ) == 0);
|
kernel_in_stram = (PTOV( 0 ) == 0);
|
|
|
if (kernel_in_stram) {
|
if (kernel_in_stram) {
|
/* Get memory from kernel data space */
|
/* Get memory from kernel data space */
|
adr = (void *) *start_mem;
|
adr = (void *) *start_mem;
|
*start_mem += size;
|
*start_mem += size;
|
}
|
}
|
else {
|
else {
|
/* Get memory from rsvd_stram_beg */
|
/* Get memory from rsvd_stram_beg */
|
if (rsvd_stram_end + size < stram_end) {
|
if (rsvd_stram_end + size < stram_end) {
|
adr = (void *) rsvd_stram_end;
|
adr = (void *) rsvd_stram_end;
|
rsvd_stram_end += size;
|
rsvd_stram_end += size;
|
}
|
}
|
}
|
}
|
|
|
return( adr );
|
return( adr );
|
}
|
}
|
|
|
void atari_stram_free( void *ptr )
|
void atari_stram_free( void *ptr )
|
|
|
{
|
{
|
/* Sorry, this is a dummy. It isn't needed anyway. */
|
/* Sorry, this is a dummy. It isn't needed anyway. */
|
}
|
}
|
|
|
#endif
|
#endif
|
|
|
|
|
|
|