sdram: experimental ramdisk driver
this driver makes regions of physical memory accessible as a disk. to use it, ramdiskinit() has to be called before confinit(), so that conf.mem[] banks can be reserved. currently, only pc and pc64 kernel use it, but otherwise the implementation is portable. ramdisks are not zeroed when allocated, so that the contents are preserved across warm reboots. to not waste memory, physical segments do not allocate Page structures or populate the segment pte's anymore. theres also a new SG_CHACHED attribute.
This commit is contained in:
parent
ad7390dda8
commit
5da4f0fc0f
12 changed files with 376 additions and 85 deletions
|
@ -500,6 +500,15 @@ on AoE
|
||||||
and
|
and
|
||||||
.I slot
|
.I slot
|
||||||
to use as a root device for bootstrapping.
|
to use as a root device for bootstrapping.
|
||||||
|
.SS \fLramdisk\fIX\fL=\fIsize\fP
|
||||||
|
.SS \fLramdisk\fIX\fL=\fIsize sectorsize\fP
|
||||||
|
.SS \fLramdisk\fIX\fL=\fIaddress size sectorsize\fP
|
||||||
|
This reserves physical memory as a ramdisk that will appear as an
|
||||||
|
.IR sd(3)
|
||||||
|
device. When the
|
||||||
|
.I address
|
||||||
|
argument is omited or zero, then the ramdisk will be allocated
|
||||||
|
from the top of physical memory.
|
||||||
.SS AUDIO
|
.SS AUDIO
|
||||||
.SS \fLaudio\fIX\fL=\fIvalue\fP
|
.SS \fLaudio\fIX\fL=\fIvalue\fP
|
||||||
This defines a sound interface. PCI based audio devices such as
|
This defines a sound interface. PCI based audio devices such as
|
||||||
|
|
|
@ -126,8 +126,6 @@ struct Conf
|
||||||
ulong nimage; /* number of page cache image headers */
|
ulong nimage; /* number of page cache image headers */
|
||||||
ulong nswap; /* number of swap pages */
|
ulong nswap; /* number of swap pages */
|
||||||
int nswppo; /* max # of pageouts per segment pass */
|
int nswppo; /* max # of pageouts per segment pass */
|
||||||
ulong base0; /* base of bank 0 */
|
|
||||||
ulong base1; /* base of bank 1 */
|
|
||||||
ulong copymode; /* 0 is copy on write, 1 is copy on reference */
|
ulong copymode; /* 0 is copy on write, 1 is copy on reference */
|
||||||
ulong ialloc; /* max interrupt time allocation in bytes */
|
ulong ialloc; /* max interrupt time allocation in bytes */
|
||||||
ulong pipeqsize; /* size in bytes of pipe queues */
|
ulong pipeqsize; /* size in bytes of pipe queues */
|
||||||
|
|
|
@ -36,6 +36,7 @@ main(void)
|
||||||
i8253init();
|
i8253init();
|
||||||
cpuidentify();
|
cpuidentify();
|
||||||
meminit();
|
meminit();
|
||||||
|
ramdiskinit();
|
||||||
confinit();
|
confinit();
|
||||||
xinit();
|
xinit();
|
||||||
archinit();
|
archinit();
|
||||||
|
|
|
@ -106,6 +106,7 @@ misc
|
||||||
sdmmc pci pmmc
|
sdmmc pci pmmc
|
||||||
sdnvme pci
|
sdnvme pci
|
||||||
sdloop
|
sdloop
|
||||||
|
sdram
|
||||||
|
|
||||||
uarti8250
|
uarti8250
|
||||||
uartisa
|
uartisa
|
||||||
|
|
|
@ -305,6 +305,7 @@ main()
|
||||||
i8253init();
|
i8253init();
|
||||||
cpuidentify();
|
cpuidentify();
|
||||||
meminit();
|
meminit();
|
||||||
|
ramdiskinit();
|
||||||
confinit();
|
confinit();
|
||||||
xinit();
|
xinit();
|
||||||
archinit();
|
archinit();
|
||||||
|
|
|
@ -104,6 +104,7 @@ misc
|
||||||
sdmmc pci pmmc
|
sdmmc pci pmmc
|
||||||
sdnvme pci
|
sdnvme pci
|
||||||
sdloop
|
sdloop
|
||||||
|
sdram
|
||||||
|
|
||||||
uarti8250
|
uarti8250
|
||||||
uartisa
|
uartisa
|
||||||
|
|
|
@ -5,63 +5,6 @@
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
#include "../port/error.h"
|
#include "../port/error.h"
|
||||||
|
|
||||||
int
|
|
||||||
fault(uintptr addr, int read)
|
|
||||||
{
|
|
||||||
Segment *s;
|
|
||||||
char *sps;
|
|
||||||
int pnd, attr;
|
|
||||||
|
|
||||||
if(up == nil)
|
|
||||||
panic("fault: nil up");
|
|
||||||
if(up->nlocks){
|
|
||||||
Lock *l = up->lastlock;
|
|
||||||
print("fault: nlocks %d, proc %lud %s, addr %#p, lock %#p, lpc %#p\n",
|
|
||||||
up->nlocks, up->pid, up->text, addr, l, l ? l->pc : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pnd = up->notepending;
|
|
||||||
sps = up->psstate;
|
|
||||||
up->psstate = "Fault";
|
|
||||||
|
|
||||||
m->pfault++;
|
|
||||||
for(;;) {
|
|
||||||
spllo();
|
|
||||||
|
|
||||||
s = seg(up, addr, 1); /* leaves s locked if seg != nil */
|
|
||||||
if(s == nil) {
|
|
||||||
up->psstate = sps;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
attr = s->type;
|
|
||||||
if((attr & SG_TYPE) == SG_PHYSICAL)
|
|
||||||
attr |= s->pseg->attr;
|
|
||||||
if((attr & SG_FAULT) != 0 || !read && (attr & SG_RONLY) != 0) {
|
|
||||||
qunlock(s);
|
|
||||||
up->psstate = sps;
|
|
||||||
if(up->kp && up->nerrlab) /* for segio */
|
|
||||||
error(Eio);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fixfault(s, addr, read) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
splhi();
|
|
||||||
switch(up->procctl){
|
|
||||||
case Proc_exitme:
|
|
||||||
case Proc_exitbig:
|
|
||||||
procctl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
up->psstate = sps;
|
|
||||||
up->notepending |= pnd;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
faulterror(char *s, Chan *c)
|
faulterror(char *s, Chan *c)
|
||||||
{
|
{
|
||||||
|
@ -196,10 +139,7 @@ done:
|
||||||
(*p)->txtflush = ~0;
|
(*p)->txtflush = ~0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*checkaddr)(uintptr, Segment *, Page *);
|
static int
|
||||||
uintptr addr2check;
|
|
||||||
|
|
||||||
int
|
|
||||||
fixfault(Segment *s, uintptr addr, int read)
|
fixfault(Segment *s, uintptr addr, int read)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
@ -276,19 +216,8 @@ fixfault(Segment *s, uintptr addr, int read)
|
||||||
(*pg)->modref = PG_MOD|PG_REF;
|
(*pg)->modref = PG_MOD|PG_REF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SG_PHYSICAL:
|
|
||||||
if(*pg == nil){
|
|
||||||
new = smalloc(sizeof(Page));
|
|
||||||
new->va = addr;
|
|
||||||
new->pa = s->pseg->pa+(addr-s->base);
|
|
||||||
new->ref = 1;
|
|
||||||
*pg = new;
|
|
||||||
}
|
|
||||||
/* wet floor */
|
|
||||||
case SG_FIXED: /* Never paged out */
|
case SG_FIXED: /* Never paged out */
|
||||||
if (checkaddr && addr == addr2check)
|
mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEUNCACHED | PTEVALID;
|
||||||
(*checkaddr)(addr, s, *pg);
|
|
||||||
mmuphys = PPN((*pg)->pa) |PTEWRITE|PTEUNCACHED|PTEVALID;
|
|
||||||
(*pg)->modref = PG_MOD|PG_REF;
|
(*pg)->modref = PG_MOD|PG_REF;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -299,6 +228,90 @@ fixfault(Segment *s, uintptr addr, int read)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mapphys(Segment *s, uintptr addr, int attr)
|
||||||
|
{
|
||||||
|
uintptr mmuphys;
|
||||||
|
Page pg = {0};
|
||||||
|
|
||||||
|
addr &= ~(BY2PG-1);
|
||||||
|
pg.ref = 1;
|
||||||
|
pg.va = addr;
|
||||||
|
pg.pa = s->pseg->pa+(addr-s->base);
|
||||||
|
|
||||||
|
mmuphys = PPN(pg.pa) | PTEVALID;
|
||||||
|
if((attr & SG_RONLY) == 0)
|
||||||
|
mmuphys |= PTEWRITE;
|
||||||
|
if((attr & SG_CACHED) == 0)
|
||||||
|
mmuphys |= PTEUNCACHED;
|
||||||
|
qunlock(s);
|
||||||
|
|
||||||
|
putmmu(addr, mmuphys, &pg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fault(uintptr addr, int read)
|
||||||
|
{
|
||||||
|
Segment *s;
|
||||||
|
char *sps;
|
||||||
|
int pnd, attr;
|
||||||
|
|
||||||
|
if(up == nil)
|
||||||
|
panic("fault: nil up");
|
||||||
|
if(up->nlocks){
|
||||||
|
Lock *l = up->lastlock;
|
||||||
|
print("fault: nlocks %d, proc %lud %s, addr %#p, lock %#p, lpc %#p\n",
|
||||||
|
up->nlocks, up->pid, up->text, addr, l, l ? l->pc : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pnd = up->notepending;
|
||||||
|
sps = up->psstate;
|
||||||
|
up->psstate = "Fault";
|
||||||
|
|
||||||
|
m->pfault++;
|
||||||
|
for(;;) {
|
||||||
|
spllo();
|
||||||
|
|
||||||
|
s = seg(up, addr, 1); /* leaves s locked if seg != nil */
|
||||||
|
if(s == nil) {
|
||||||
|
up->psstate = sps;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr = s->type;
|
||||||
|
if((attr & SG_TYPE) == SG_PHYSICAL)
|
||||||
|
attr |= s->pseg->attr;
|
||||||
|
|
||||||
|
if((attr & SG_FAULT) != 0 || !read && (attr & SG_RONLY) != 0) {
|
||||||
|
qunlock(s);
|
||||||
|
up->psstate = sps;
|
||||||
|
if(up->kp && up->nerrlab) /* for segio */
|
||||||
|
error(Eio);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((attr & SG_TYPE) == SG_PHYSICAL){
|
||||||
|
mapphys(s, addr, attr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fixfault(s, addr, read) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
splhi();
|
||||||
|
switch(up->procctl){
|
||||||
|
case Proc_exitme:
|
||||||
|
case Proc_exitbig:
|
||||||
|
procctl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
up->psstate = sps;
|
||||||
|
up->notepending |= pnd;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called only in a system call
|
* Called only in a system call
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -43,9 +43,11 @@ collect && section == "misc"{
|
||||||
arch[narch++] = $1;
|
arch[narch++] = $1;
|
||||||
else if($1 ~ "^ad.*")
|
else if($1 ~ "^ad.*")
|
||||||
adifc[nadifc++] = $1;
|
adifc[nadifc++] = $1;
|
||||||
else if($1 ~ "^sd.*")
|
else if($1 ~ "^sd.*"){
|
||||||
sdifc[nsdifc++] = $1;
|
sdifc[nsdifc++] = $1;
|
||||||
else if($1 ~ "^uart.*")
|
if($1 == "sdram")
|
||||||
|
ramdisk = 1;
|
||||||
|
}else if($1 ~ "^uart.*")
|
||||||
physuart[nphysuart++] = substr($1, 5, length($1)-4) "physuart";
|
physuart[nphysuart++] = substr($1, 5, length($1)-4) "physuart";
|
||||||
else if($1 ~ "^vga.*"){
|
else if($1 ~ "^vga.*"){
|
||||||
if(NF == 1)
|
if(NF == 1)
|
||||||
|
@ -136,6 +138,8 @@ END{
|
||||||
printf "\t&%sifc,\n", sdifc[i];
|
printf "\t&%sifc,\n", sdifc[i];
|
||||||
printf "\tnil,\n};\n\n";
|
printf "\tnil,\n};\n\n";
|
||||||
}
|
}
|
||||||
|
if(!ramdisk)
|
||||||
|
printf "void ramdiskinit(void)\n{\n}\n\n";
|
||||||
|
|
||||||
if(devuart){
|
if(devuart){
|
||||||
for(i = 0; i < nphysuart; i++)
|
for(i = 0; i < nphysuart; i++)
|
||||||
|
|
|
@ -373,6 +373,7 @@ enum
|
||||||
SG_RONLY = 0040, /* Segment is read only */
|
SG_RONLY = 0040, /* Segment is read only */
|
||||||
SG_CEXEC = 0100, /* Detach at exec */
|
SG_CEXEC = 0100, /* Detach at exec */
|
||||||
SG_FAULT = 0200, /* Fault on access */
|
SG_FAULT = 0200, /* Fault on access */
|
||||||
|
SG_CACHED = 0400,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PG_ONSWAP 1
|
#define PG_ONSWAP 1
|
||||||
|
|
|
@ -109,7 +109,6 @@ int fault(uintptr, int);
|
||||||
void fdclose(int, int);
|
void fdclose(int, int);
|
||||||
Chan* fdtochan(int, int, int, int);
|
Chan* fdtochan(int, int, int, int);
|
||||||
int findmount(Chan**, Mhead**, int, int, Qid);
|
int findmount(Chan**, Mhead**, int, int, Qid);
|
||||||
int fixfault(Segment*, uintptr, int);
|
|
||||||
void flushmmu(void);
|
void flushmmu(void);
|
||||||
void forceclosefgrp(void);
|
void forceclosefgrp(void);
|
||||||
void forkchild(Proc*, Ureg*);
|
void forkchild(Proc*, Ureg*);
|
||||||
|
@ -284,6 +283,7 @@ int qwrite(Queue*, void*, int);
|
||||||
void qnoblock(Queue*, int);
|
void qnoblock(Queue*, int);
|
||||||
void randominit(void);
|
void randominit(void);
|
||||||
ulong randomread(void*, ulong);
|
ulong randomread(void*, ulong);
|
||||||
|
void ramdiskinit(void);
|
||||||
void rdb(void);
|
void rdb(void);
|
||||||
long readblist(Block*, uchar*, long, ulong);
|
long readblist(Block*, uchar*, long, ulong);
|
||||||
int readnum(ulong, char*, ulong, ulong, int);
|
int readnum(ulong, char*, ulong, ulong, int);
|
||||||
|
|
256
sys/src/9/port/sdram.c
Normal file
256
sys/src/9/port/sdram.c
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
/*
|
||||||
|
* ramdisk driver
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "u.h"
|
||||||
|
#include "../port/lib.h"
|
||||||
|
#include "../port/error.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "dat.h"
|
||||||
|
#include "fns.h"
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
#include "../port/sd.h"
|
||||||
|
|
||||||
|
typedef struct Ctlr Ctlr;
|
||||||
|
struct Ctlr {
|
||||||
|
SDev *dev;
|
||||||
|
Segment *seg;
|
||||||
|
Segio sio;
|
||||||
|
|
||||||
|
ulong nb;
|
||||||
|
ulong ss;
|
||||||
|
ulong off;
|
||||||
|
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
|
Physseg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Ctlr ctlrs[4];
|
||||||
|
|
||||||
|
extern SDifc sdramifc;
|
||||||
|
|
||||||
|
static uvlong
|
||||||
|
ramdiskalloc(uvlong base, ulong pages)
|
||||||
|
{
|
||||||
|
uvlong limit, mbase, mlimit;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if(pages == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(base == 0){
|
||||||
|
/* allocate pages from the end of memoy banks */
|
||||||
|
for(i=nelem(conf.mem)-1; i>=0; i--)
|
||||||
|
if(conf.mem[i].npage >= pages){
|
||||||
|
conf.mem[i].npage -= pages;
|
||||||
|
return (uvlong)conf.mem[i].base + (uvlong)conf.mem[i].npage*BY2PG;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* exclude pages from memory banks */
|
||||||
|
limit = base + (uvlong)pages*BY2PG;
|
||||||
|
for(i=0; i<nelem(conf.mem); i++){
|
||||||
|
mbase = conf.mem[i].base;
|
||||||
|
mlimit = mbase + (uvlong)conf.mem[i].npage*BY2PG;
|
||||||
|
if(base >= mlimit || limit <= mbase)
|
||||||
|
continue;
|
||||||
|
if(base >= mbase)
|
||||||
|
conf.mem[i].npage = (base - mbase) / BY2PG;
|
||||||
|
if(limit < mlimit){
|
||||||
|
for(j=0; j<nelem(conf.mem); j++){
|
||||||
|
if(conf.mem[j].npage == 0){
|
||||||
|
conf.mem[j].base = limit;
|
||||||
|
conf.mem[j].npage = (mlimit - limit) / BY2PG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ramdiskinit0(Ctlr *ctlr, uvlong base, uvlong size, ulong ss)
|
||||||
|
{
|
||||||
|
ulong nb, off;
|
||||||
|
|
||||||
|
if(ss == 0)
|
||||||
|
ss = 512;
|
||||||
|
|
||||||
|
nb = size / ss;
|
||||||
|
off = base & (BY2PG-1);
|
||||||
|
size = (uvlong)nb*ss;
|
||||||
|
size += off;
|
||||||
|
size += BY2PG-1;
|
||||||
|
size &= ~(BY2PG-1);
|
||||||
|
base &= ~(BY2PG-1);
|
||||||
|
|
||||||
|
if(size == 0 || size != (uintptr)size){
|
||||||
|
print("%s: invalid parameters\n", ctlr->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = ramdiskalloc(base, size/BY2PG);
|
||||||
|
if(base == 0){
|
||||||
|
print("%s: allocation failed\n", ctlr->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctlr->nb = nb;
|
||||||
|
ctlr->ss = ss;
|
||||||
|
ctlr->off = off;
|
||||||
|
ctlr->pa = base;
|
||||||
|
ctlr->size = size;
|
||||||
|
print("%s: %llux+%lud %llud %lud (%lud sectors)\n",
|
||||||
|
ctlr->name, (uvlong)ctlr->pa, ctlr->off, (uvlong)ctlr->size, ctlr->ss, ctlr->nb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static vlong
|
||||||
|
getsizenum(char **p)
|
||||||
|
{
|
||||||
|
vlong v = strtoll(*p, p, 0);
|
||||||
|
switch(**p){
|
||||||
|
case 'T': case 't': v <<= 10;
|
||||||
|
case 'G': case 'g': v <<= 10;
|
||||||
|
case 'M': case 'm': v <<= 10;
|
||||||
|
case 'K': case 'k': v <<= 10;
|
||||||
|
(*p)++;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ramdiskinit(void)
|
||||||
|
{
|
||||||
|
Ctlr *ctlr;
|
||||||
|
uvlong a[3];
|
||||||
|
char *p;
|
||||||
|
int ctlrno, n;
|
||||||
|
|
||||||
|
for(ctlrno=0; ctlrno<nelem(ctlrs); ctlrno++){
|
||||||
|
ctlr = &ctlrs[ctlrno];
|
||||||
|
if(ctlr->nb != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprint(ctlr->name = ctlr->buf, sizeof(ctlr->buf), "ramdisk%d", ctlrno);
|
||||||
|
if((p = getconf(ctlr->name)) == nil)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for(n = 0; n < nelem(a); n++){
|
||||||
|
while(*p == ' ' || *p == '\t')
|
||||||
|
p++;
|
||||||
|
if(*p == 0)
|
||||||
|
break;
|
||||||
|
a[n] = getsizenum(&p);
|
||||||
|
switch(*p){
|
||||||
|
case '-': case '+':
|
||||||
|
a[n] += getsizenum(&p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch(n){
|
||||||
|
case 1: /* ramdiskX=size */
|
||||||
|
ramdiskinit0(ctlr, 0, a[0], 0);
|
||||||
|
break;
|
||||||
|
case 2: /* ramdiskX=size ss */
|
||||||
|
ramdiskinit0(ctlr, 0, a[0], (ulong)a[1]);
|
||||||
|
break;
|
||||||
|
case 3: /* ramdiskX=base size ss */
|
||||||
|
ramdiskinit0(ctlr, a[0], a[1], (ulong)a[2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDev*
|
||||||
|
rampnp(void)
|
||||||
|
{
|
||||||
|
SDev *sdev;
|
||||||
|
Ctlr *ctlr;
|
||||||
|
|
||||||
|
for(ctlr = ctlrs; ctlr < &ctlrs[nelem(ctlrs)]; ctlr++){
|
||||||
|
if(ctlr->nb == 0 || ctlr->dev != nil)
|
||||||
|
continue;
|
||||||
|
sdev = malloc(sizeof(SDev));
|
||||||
|
if(sdev == nil)
|
||||||
|
break;
|
||||||
|
sdev->idno = 'Z';
|
||||||
|
sdev->ifc = &sdramifc;
|
||||||
|
sdev->nunit = 1;
|
||||||
|
sdev->ctlr = ctlr;
|
||||||
|
ctlr->dev = sdev;
|
||||||
|
return sdev;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ramenable(SDev* dev)
|
||||||
|
{
|
||||||
|
Ctlr *ctlr = dev->ctlr;
|
||||||
|
|
||||||
|
ctlr->attr = SG_CACHED;
|
||||||
|
ctlr->seg = newseg(SG_PHYSICAL, UTZERO, ctlr->size/BY2PG);
|
||||||
|
if(ctlr->seg == nil)
|
||||||
|
return 0;
|
||||||
|
ctlr->seg->pseg = ctlr;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ramverify(SDunit*)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ramonline(SDunit *unit)
|
||||||
|
{
|
||||||
|
Ctlr *ctlr = unit->dev->ctlr;
|
||||||
|
unit->sectors = ctlr->nb;
|
||||||
|
unit->secsize = ctlr->ss;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ramrctl(SDunit *unit, char *p, int l)
|
||||||
|
{
|
||||||
|
return snprint(p, l, "geometry %llud %ld\n",
|
||||||
|
unit->sectors, unit->secsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
rambio(SDunit *unit, int, int write, void *data, long nb, uvlong bno)
|
||||||
|
{
|
||||||
|
Ctlr *ctlr = unit->dev->ctlr;
|
||||||
|
long secsize = unit->secsize;
|
||||||
|
return segio(&ctlr->sio, ctlr->seg, data, nb*secsize, bno*secsize + ctlr->off, !write);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ramrio(SDreq *r)
|
||||||
|
{
|
||||||
|
int i, rw, count;
|
||||||
|
uvlong lba;
|
||||||
|
|
||||||
|
if((i = sdfakescsi(r)) != SDnostatus)
|
||||||
|
return r->status = i;
|
||||||
|
if((i = sdfakescsirw(r, &lba, &count, &rw)) != SDnostatus)
|
||||||
|
return i;
|
||||||
|
r->rlen = rambio(r->unit, r->lun, rw == SDwrite, r->data, count, lba);
|
||||||
|
return r->status = SDok;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDifc sdramifc = {
|
||||||
|
.name = "ram",
|
||||||
|
.pnp = rampnp,
|
||||||
|
.enable = ramenable,
|
||||||
|
.verify = ramverify,
|
||||||
|
.online = ramonline,
|
||||||
|
.rctl = ramrctl,
|
||||||
|
.bio = rambio,
|
||||||
|
.rio = ramrio,
|
||||||
|
};
|
|
@ -64,6 +64,9 @@ newseg(int type, uintptr base, ulong size)
|
||||||
s->sema.prev = &s->sema;
|
s->sema.prev = &s->sema;
|
||||||
s->sema.next = &s->sema;
|
s->sema.next = &s->sema;
|
||||||
|
|
||||||
|
if((type & SG_TYPE) == SG_PHYSICAL)
|
||||||
|
return s;
|
||||||
|
|
||||||
mapsize = ROUND(size, PTEPERTAB)/PTEPERTAB;
|
mapsize = ROUND(size, PTEPERTAB)/PTEPERTAB;
|
||||||
if(mapsize > nelem(s->ssegmap)){
|
if(mapsize > nelem(s->ssegmap)){
|
||||||
s->map = malloc(mapsize*sizeof(Pte*));
|
s->map = malloc(mapsize*sizeof(Pte*));
|
||||||
|
@ -104,6 +107,7 @@ putseg(Segment *s)
|
||||||
} else if(decref(s) != 0)
|
} else if(decref(s) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(s->mapsize > 0){
|
||||||
emap = &s->map[s->mapsize];
|
emap = &s->map[s->mapsize];
|
||||||
for(pte = s->map; pte < emap; pte++)
|
for(pte = s->map; pte < emap; pte++)
|
||||||
if(*pte != nil)
|
if(*pte != nil)
|
||||||
|
@ -111,6 +115,8 @@ putseg(Segment *s)
|
||||||
|
|
||||||
if(s->map != s->ssegmap)
|
if(s->map != s->ssegmap)
|
||||||
free(s->map);
|
free(s->map);
|
||||||
|
}
|
||||||
|
|
||||||
if(s->profile != nil)
|
if(s->profile != nil)
|
||||||
free(s->profile);
|
free(s->profile);
|
||||||
|
|
||||||
|
@ -212,7 +218,7 @@ segpage(Segment *s, Page *p)
|
||||||
uintptr soff;
|
uintptr soff;
|
||||||
Page **pg;
|
Page **pg;
|
||||||
|
|
||||||
if(p->va < s->base || p->va >= s->top)
|
if(p->va < s->base || p->va >= s->top || s->mapsize == 0)
|
||||||
panic("segpage");
|
panic("segpage");
|
||||||
|
|
||||||
soff = p->va - s->base;
|
soff = p->va - s->base;
|
||||||
|
|
Loading…
Reference in a new issue