19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier #include "../port/error.h"
79ef1f84bSDavid du Colombier
89ef1f84bSDavid du Colombier #include "ureg.h"
99ef1f84bSDavid du Colombier
109ef1f84bSDavid du Colombier typedef struct IOMap IOMap;
119ef1f84bSDavid du Colombier struct IOMap
129ef1f84bSDavid du Colombier {
139ef1f84bSDavid du Colombier IOMap *next;
149ef1f84bSDavid du Colombier int reserved;
159ef1f84bSDavid du Colombier char tag[13];
169ef1f84bSDavid du Colombier ulong start;
179ef1f84bSDavid du Colombier ulong end;
189ef1f84bSDavid du Colombier };
199ef1f84bSDavid du Colombier
209ef1f84bSDavid du Colombier static struct
219ef1f84bSDavid du Colombier {
229ef1f84bSDavid du Colombier Lock;
239ef1f84bSDavid du Colombier IOMap *map;
249ef1f84bSDavid du Colombier IOMap *free;
259ef1f84bSDavid du Colombier IOMap maps[32]; // some initial free maps
269ef1f84bSDavid du Colombier
279ef1f84bSDavid du Colombier QLock ql; // lock for reading map
289ef1f84bSDavid du Colombier } iomap;
299ef1f84bSDavid du Colombier
309ef1f84bSDavid du Colombier enum {
319ef1f84bSDavid du Colombier Qdir = 0,
329ef1f84bSDavid du Colombier Qioalloc = 1,
339ef1f84bSDavid du Colombier Qiob,
349ef1f84bSDavid du Colombier Qiow,
359ef1f84bSDavid du Colombier Qiol,
369ef1f84bSDavid du Colombier Qbase,
379ef1f84bSDavid du Colombier
389ef1f84bSDavid du Colombier Qmax = 16,
399ef1f84bSDavid du Colombier };
409ef1f84bSDavid du Colombier
419ef1f84bSDavid du Colombier typedef long Rdwrfn(Chan*, void*, long, vlong);
429ef1f84bSDavid du Colombier
439ef1f84bSDavid du Colombier static Rdwrfn *readfn[Qmax];
449ef1f84bSDavid du Colombier static Rdwrfn *writefn[Qmax];
459ef1f84bSDavid du Colombier
469ef1f84bSDavid du Colombier static Dirtab archdir[Qmax] = {
479ef1f84bSDavid du Colombier ".", { Qdir, 0, QTDIR }, 0, 0555,
489ef1f84bSDavid du Colombier "ioalloc", { Qioalloc, 0 }, 0, 0444,
499ef1f84bSDavid du Colombier "iob", { Qiob, 0 }, 0, 0660,
509ef1f84bSDavid du Colombier "iow", { Qiow, 0 }, 0, 0660,
519ef1f84bSDavid du Colombier "iol", { Qiol, 0 }, 0, 0660,
529ef1f84bSDavid du Colombier };
539ef1f84bSDavid du Colombier Lock archwlock; /* the lock is only for changing archdir */
549ef1f84bSDavid du Colombier int narchdir = Qbase;
559ef1f84bSDavid du Colombier
569ef1f84bSDavid du Colombier /*
579ef1f84bSDavid du Colombier * Add a file to the #P listing. Once added, you can't delete it.
589ef1f84bSDavid du Colombier * You can't add a file with the same name as one already there,
599ef1f84bSDavid du Colombier * and you get a pointer to the Dirtab entry so you can do things
609ef1f84bSDavid du Colombier * like change the Qid version. Changing the Qid path is disallowed.
619ef1f84bSDavid du Colombier */
629ef1f84bSDavid du Colombier Dirtab*
addarchfile(char * name,int perm,Rdwrfn * rdfn,Rdwrfn * wrfn)639ef1f84bSDavid du Colombier addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
649ef1f84bSDavid du Colombier {
659ef1f84bSDavid du Colombier int i;
669ef1f84bSDavid du Colombier Dirtab d;
679ef1f84bSDavid du Colombier Dirtab *dp;
689ef1f84bSDavid du Colombier
699ef1f84bSDavid du Colombier memset(&d, 0, sizeof d);
709ef1f84bSDavid du Colombier strcpy(d.name, name);
719ef1f84bSDavid du Colombier d.perm = perm;
729ef1f84bSDavid du Colombier
739ef1f84bSDavid du Colombier lock(&archwlock);
749ef1f84bSDavid du Colombier if(narchdir >= Qmax){
759ef1f84bSDavid du Colombier unlock(&archwlock);
769ef1f84bSDavid du Colombier return nil;
779ef1f84bSDavid du Colombier }
789ef1f84bSDavid du Colombier
799ef1f84bSDavid du Colombier for(i=0; i<narchdir; i++)
809ef1f84bSDavid du Colombier if(strcmp(archdir[i].name, name) == 0){
819ef1f84bSDavid du Colombier unlock(&archwlock);
829ef1f84bSDavid du Colombier return nil;
839ef1f84bSDavid du Colombier }
849ef1f84bSDavid du Colombier
859ef1f84bSDavid du Colombier d.qid.path = narchdir;
869ef1f84bSDavid du Colombier archdir[narchdir] = d;
879ef1f84bSDavid du Colombier readfn[narchdir] = rdfn;
889ef1f84bSDavid du Colombier writefn[narchdir] = wrfn;
899ef1f84bSDavid du Colombier dp = &archdir[narchdir++];
909ef1f84bSDavid du Colombier unlock(&archwlock);
919ef1f84bSDavid du Colombier
929ef1f84bSDavid du Colombier return dp;
939ef1f84bSDavid du Colombier }
949ef1f84bSDavid du Colombier
959ef1f84bSDavid du Colombier void
ioinit(void)969ef1f84bSDavid du Colombier ioinit(void)
979ef1f84bSDavid du Colombier {
989ef1f84bSDavid du Colombier char *excluded;
999ef1f84bSDavid du Colombier int i;
1009ef1f84bSDavid du Colombier
1019ef1f84bSDavid du Colombier for(i = 0; i < nelem(iomap.maps)-1; i++)
1029ef1f84bSDavid du Colombier iomap.maps[i].next = &iomap.maps[i+1];
1039ef1f84bSDavid du Colombier iomap.maps[i].next = nil;
1049ef1f84bSDavid du Colombier iomap.free = iomap.maps;
1059ef1f84bSDavid du Colombier
1069ef1f84bSDavid du Colombier /*
1079ef1f84bSDavid du Colombier * Someone needs to explain why this was here...
1089ef1f84bSDavid du Colombier */
1099ef1f84bSDavid du Colombier ioalloc(0x0fff, 1, 0, "dummy"); // i82557 is at 0x1000, the dummy
1109ef1f84bSDavid du Colombier // entry is needed for swappable devs.
1119ef1f84bSDavid du Colombier
1129ef1f84bSDavid du Colombier if ((excluded = getconf("ioexclude")) != nil) {
1139ef1f84bSDavid du Colombier char *s;
1149ef1f84bSDavid du Colombier
1159ef1f84bSDavid du Colombier s = excluded;
1169ef1f84bSDavid du Colombier while (s && *s != '\0' && *s != '\n') {
1179ef1f84bSDavid du Colombier char *ends;
1189ef1f84bSDavid du Colombier int io_s, io_e;
1199ef1f84bSDavid du Colombier
1209ef1f84bSDavid du Colombier io_s = (int)strtol(s, &ends, 0);
1219ef1f84bSDavid du Colombier if (ends == nil || ends == s || *ends != '-') {
1229ef1f84bSDavid du Colombier print("ioinit: cannot parse option string\n");
1239ef1f84bSDavid du Colombier break;
1249ef1f84bSDavid du Colombier }
1259ef1f84bSDavid du Colombier s = ++ends;
1269ef1f84bSDavid du Colombier
1279ef1f84bSDavid du Colombier io_e = (int)strtol(s, &ends, 0);
1289ef1f84bSDavid du Colombier if (ends && *ends == ',')
1299ef1f84bSDavid du Colombier *ends++ = '\0';
1309ef1f84bSDavid du Colombier s = ends;
1319ef1f84bSDavid du Colombier
1329ef1f84bSDavid du Colombier ioalloc(io_s, io_e - io_s + 1, 0, "pre-allocated");
1339ef1f84bSDavid du Colombier }
1349ef1f84bSDavid du Colombier }
1359ef1f84bSDavid du Colombier
1369ef1f84bSDavid du Colombier }
1379ef1f84bSDavid du Colombier
1389ef1f84bSDavid du Colombier // Reserve a range to be ioalloced later.
1399ef1f84bSDavid du Colombier // This is in particular useful for exchangable cards, such
1409ef1f84bSDavid du Colombier // as pcmcia and cardbus cards.
1419ef1f84bSDavid du Colombier int
ioreserve(int,int size,int align,char * tag)1429ef1f84bSDavid du Colombier ioreserve(int, int size, int align, char *tag)
1439ef1f84bSDavid du Colombier {
1449ef1f84bSDavid du Colombier IOMap *map, **l;
1459ef1f84bSDavid du Colombier int i, port;
1469ef1f84bSDavid du Colombier
1479ef1f84bSDavid du Colombier lock(&iomap);
1489ef1f84bSDavid du Colombier // find a free port above 0x400 and below 0x1000
1499ef1f84bSDavid du Colombier port = 0x400;
1509ef1f84bSDavid du Colombier for(l = &iomap.map; *l; l = &(*l)->next){
1519ef1f84bSDavid du Colombier map = *l;
1529ef1f84bSDavid du Colombier if (map->start < 0x400)
1539ef1f84bSDavid du Colombier continue;
1549ef1f84bSDavid du Colombier i = map->start - port;
1559ef1f84bSDavid du Colombier if(i > size)
1569ef1f84bSDavid du Colombier break;
1579ef1f84bSDavid du Colombier if(align > 0)
1589ef1f84bSDavid du Colombier port = ((port+align-1)/align)*align;
1599ef1f84bSDavid du Colombier else
1609ef1f84bSDavid du Colombier port = map->end;
1619ef1f84bSDavid du Colombier }
1629ef1f84bSDavid du Colombier if(*l == nil){
1639ef1f84bSDavid du Colombier unlock(&iomap);
1649ef1f84bSDavid du Colombier return -1;
1659ef1f84bSDavid du Colombier }
1669ef1f84bSDavid du Colombier map = iomap.free;
1679ef1f84bSDavid du Colombier if(map == nil){
1689ef1f84bSDavid du Colombier print("ioalloc: out of maps");
1699ef1f84bSDavid du Colombier unlock(&iomap);
1709ef1f84bSDavid du Colombier return port;
1719ef1f84bSDavid du Colombier }
1729ef1f84bSDavid du Colombier iomap.free = map->next;
1739ef1f84bSDavid du Colombier map->next = *l;
1749ef1f84bSDavid du Colombier map->start = port;
1759ef1f84bSDavid du Colombier map->end = port + size;
1769ef1f84bSDavid du Colombier map->reserved = 1;
1779ef1f84bSDavid du Colombier strncpy(map->tag, tag, sizeof(map->tag));
1789ef1f84bSDavid du Colombier map->tag[sizeof(map->tag)-1] = 0;
1799ef1f84bSDavid du Colombier *l = map;
1809ef1f84bSDavid du Colombier
1819ef1f84bSDavid du Colombier archdir[0].qid.vers++;
1829ef1f84bSDavid du Colombier
1839ef1f84bSDavid du Colombier unlock(&iomap);
1849ef1f84bSDavid du Colombier return map->start;
1859ef1f84bSDavid du Colombier }
1869ef1f84bSDavid du Colombier
1879ef1f84bSDavid du Colombier //
1889ef1f84bSDavid du Colombier // alloc some io port space and remember who it was
1899ef1f84bSDavid du Colombier // alloced to. if port < 0, find a free region.
1909ef1f84bSDavid du Colombier //
1919ef1f84bSDavid du Colombier int
ioalloc(int port,int size,int align,char * tag)1929ef1f84bSDavid du Colombier ioalloc(int port, int size, int align, char *tag)
1939ef1f84bSDavid du Colombier {
1949ef1f84bSDavid du Colombier IOMap *map, **l;
1959ef1f84bSDavid du Colombier int i;
1969ef1f84bSDavid du Colombier
1979ef1f84bSDavid du Colombier lock(&iomap);
1989ef1f84bSDavid du Colombier if(port < 0){
1999ef1f84bSDavid du Colombier // find a free port above 0x400 and below 0x1000
2009ef1f84bSDavid du Colombier port = 0x400;
2019ef1f84bSDavid du Colombier for(l = &iomap.map; *l; l = &(*l)->next){
2029ef1f84bSDavid du Colombier map = *l;
2039ef1f84bSDavid du Colombier if (map->start < 0x400)
2049ef1f84bSDavid du Colombier continue;
2059ef1f84bSDavid du Colombier i = map->start - port;
2069ef1f84bSDavid du Colombier if(i > size)
2079ef1f84bSDavid du Colombier break;
2089ef1f84bSDavid du Colombier if(align > 0)
2099ef1f84bSDavid du Colombier port = ((port+align-1)/align)*align;
2109ef1f84bSDavid du Colombier else
2119ef1f84bSDavid du Colombier port = map->end;
2129ef1f84bSDavid du Colombier }
2139ef1f84bSDavid du Colombier if(*l == nil){
2149ef1f84bSDavid du Colombier unlock(&iomap);
2159ef1f84bSDavid du Colombier return -1;
2169ef1f84bSDavid du Colombier }
2179ef1f84bSDavid du Colombier } else {
2189ef1f84bSDavid du Colombier // Only 64KB I/O space on the x86.
2199ef1f84bSDavid du Colombier if((port+size) > 0x10000){
2209ef1f84bSDavid du Colombier unlock(&iomap);
2219ef1f84bSDavid du Colombier return -1;
2229ef1f84bSDavid du Colombier }
2239ef1f84bSDavid du Colombier // see if the space clashes with previously allocated ports
2249ef1f84bSDavid du Colombier for(l = &iomap.map; *l; l = &(*l)->next){
2259ef1f84bSDavid du Colombier map = *l;
2269ef1f84bSDavid du Colombier if(map->end <= port)
2279ef1f84bSDavid du Colombier continue;
2289ef1f84bSDavid du Colombier if(map->reserved && map->start == port && map->end == port + size) {
2299ef1f84bSDavid du Colombier map->reserved = 0;
2309ef1f84bSDavid du Colombier unlock(&iomap);
2319ef1f84bSDavid du Colombier return map->start;
2329ef1f84bSDavid du Colombier }
2339ef1f84bSDavid du Colombier if(map->start >= port+size)
2349ef1f84bSDavid du Colombier break;
2359ef1f84bSDavid du Colombier unlock(&iomap);
2369ef1f84bSDavid du Colombier return -1;
2379ef1f84bSDavid du Colombier }
2389ef1f84bSDavid du Colombier }
2399ef1f84bSDavid du Colombier map = iomap.free;
2409ef1f84bSDavid du Colombier if(map == nil){
2419ef1f84bSDavid du Colombier print("ioalloc: out of maps");
2429ef1f84bSDavid du Colombier unlock(&iomap);
2439ef1f84bSDavid du Colombier return port;
2449ef1f84bSDavid du Colombier }
2459ef1f84bSDavid du Colombier iomap.free = map->next;
2469ef1f84bSDavid du Colombier map->next = *l;
2479ef1f84bSDavid du Colombier map->start = port;
2489ef1f84bSDavid du Colombier map->end = port + size;
2499ef1f84bSDavid du Colombier strncpy(map->tag, tag, sizeof(map->tag));
2509ef1f84bSDavid du Colombier map->tag[sizeof(map->tag)-1] = 0;
2519ef1f84bSDavid du Colombier *l = map;
2529ef1f84bSDavid du Colombier
2539ef1f84bSDavid du Colombier archdir[0].qid.vers++;
2549ef1f84bSDavid du Colombier
2559ef1f84bSDavid du Colombier unlock(&iomap);
2569ef1f84bSDavid du Colombier return map->start;
2579ef1f84bSDavid du Colombier }
2589ef1f84bSDavid du Colombier
2599ef1f84bSDavid du Colombier void
iofree(int port)2609ef1f84bSDavid du Colombier iofree(int port)
2619ef1f84bSDavid du Colombier {
2629ef1f84bSDavid du Colombier IOMap *map, **l;
2639ef1f84bSDavid du Colombier
2649ef1f84bSDavid du Colombier lock(&iomap);
2659ef1f84bSDavid du Colombier for(l = &iomap.map; *l; l = &(*l)->next){
2669ef1f84bSDavid du Colombier if((*l)->start == port){
2679ef1f84bSDavid du Colombier map = *l;
2689ef1f84bSDavid du Colombier *l = map->next;
2699ef1f84bSDavid du Colombier map->next = iomap.free;
2709ef1f84bSDavid du Colombier iomap.free = map;
2719ef1f84bSDavid du Colombier break;
2729ef1f84bSDavid du Colombier }
2739ef1f84bSDavid du Colombier if((*l)->start > port)
2749ef1f84bSDavid du Colombier break;
2759ef1f84bSDavid du Colombier }
2769ef1f84bSDavid du Colombier archdir[0].qid.vers++;
2779ef1f84bSDavid du Colombier unlock(&iomap);
2789ef1f84bSDavid du Colombier }
2799ef1f84bSDavid du Colombier
2809ef1f84bSDavid du Colombier int
iounused(int start,int end)2819ef1f84bSDavid du Colombier iounused(int start, int end)
2829ef1f84bSDavid du Colombier {
2839ef1f84bSDavid du Colombier IOMap *map;
2849ef1f84bSDavid du Colombier
2859ef1f84bSDavid du Colombier for(map = iomap.map; map; map = map->next){
2869ef1f84bSDavid du Colombier if(start >= map->start && start < map->end
2879ef1f84bSDavid du Colombier || start <= map->start && end > map->start)
2889ef1f84bSDavid du Colombier return 0;
2899ef1f84bSDavid du Colombier }
2909ef1f84bSDavid du Colombier return 1;
2919ef1f84bSDavid du Colombier }
2929ef1f84bSDavid du Colombier
2939ef1f84bSDavid du Colombier static void
checkport(int start,int end)2949ef1f84bSDavid du Colombier checkport(int start, int end)
2959ef1f84bSDavid du Colombier {
2969ef1f84bSDavid du Colombier /* standard vga regs are OK */
2979ef1f84bSDavid du Colombier if(start >= 0x2b0 && end <= 0x2df+1)
2989ef1f84bSDavid du Colombier return;
2999ef1f84bSDavid du Colombier if(start >= 0x3c0 && end <= 0x3da+1)
3009ef1f84bSDavid du Colombier return;
3019ef1f84bSDavid du Colombier
3029ef1f84bSDavid du Colombier if(iounused(start, end))
3039ef1f84bSDavid du Colombier return;
3049ef1f84bSDavid du Colombier error(Eperm);
3059ef1f84bSDavid du Colombier }
3069ef1f84bSDavid du Colombier
3079ef1f84bSDavid du Colombier static Chan*
archattach(char * spec)3089ef1f84bSDavid du Colombier archattach(char* spec)
3099ef1f84bSDavid du Colombier {
3109ef1f84bSDavid du Colombier return devattach('P', spec);
3119ef1f84bSDavid du Colombier }
3129ef1f84bSDavid du Colombier
3139ef1f84bSDavid du Colombier Walkqid*
archwalk(Chan * c,Chan * nc,char ** name,int nname)3149ef1f84bSDavid du Colombier archwalk(Chan* c, Chan *nc, char** name, int nname)
3159ef1f84bSDavid du Colombier {
3169ef1f84bSDavid du Colombier return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
3179ef1f84bSDavid du Colombier }
3189ef1f84bSDavid du Colombier
3199ef1f84bSDavid du Colombier static long
archstat(Chan * c,uchar * dp,long n)3209ef1f84bSDavid du Colombier archstat(Chan* c, uchar* dp, long n)
3219ef1f84bSDavid du Colombier {
3229ef1f84bSDavid du Colombier return devstat(c, dp, n, archdir, narchdir, devgen);
3239ef1f84bSDavid du Colombier }
3249ef1f84bSDavid du Colombier
3259ef1f84bSDavid du Colombier static Chan*
archopen(Chan * c,int omode)3269ef1f84bSDavid du Colombier archopen(Chan* c, int omode)
3279ef1f84bSDavid du Colombier {
3289ef1f84bSDavid du Colombier return devopen(c, omode, archdir, narchdir, devgen);
3299ef1f84bSDavid du Colombier }
3309ef1f84bSDavid du Colombier
3319ef1f84bSDavid du Colombier static void
archclose(Chan *)3329ef1f84bSDavid du Colombier archclose(Chan*)
3339ef1f84bSDavid du Colombier {
3349ef1f84bSDavid du Colombier }
3359ef1f84bSDavid du Colombier
3369ef1f84bSDavid du Colombier enum
3379ef1f84bSDavid du Colombier {
3389ef1f84bSDavid du Colombier Linelen= 31,
3399ef1f84bSDavid du Colombier };
3409ef1f84bSDavid du Colombier
3419ef1f84bSDavid du Colombier static long
archread(Chan * c,void * a,long n,vlong offset)3429ef1f84bSDavid du Colombier archread(Chan *c, void *a, long n, vlong offset)
3439ef1f84bSDavid du Colombier {
3449ef1f84bSDavid du Colombier char *buf, *p;
3459ef1f84bSDavid du Colombier int port;
3469ef1f84bSDavid du Colombier ushort *sp;
3479ef1f84bSDavid du Colombier ulong *lp;
3489ef1f84bSDavid du Colombier IOMap *map;
3499ef1f84bSDavid du Colombier Rdwrfn *fn;
3509ef1f84bSDavid du Colombier
3519ef1f84bSDavid du Colombier switch((ulong)c->qid.path){
3529ef1f84bSDavid du Colombier
3539ef1f84bSDavid du Colombier case Qdir:
3549ef1f84bSDavid du Colombier return devdirread(c, a, n, archdir, narchdir, devgen);
3559ef1f84bSDavid du Colombier
3569ef1f84bSDavid du Colombier case Qiob:
3579ef1f84bSDavid du Colombier port = offset;
3589ef1f84bSDavid du Colombier checkport(offset, offset+n);
3599ef1f84bSDavid du Colombier for(p = a; port < offset+n; port++)
3609ef1f84bSDavid du Colombier *p++ = inb(port);
3619ef1f84bSDavid du Colombier return n;
3629ef1f84bSDavid du Colombier
3639ef1f84bSDavid du Colombier case Qiow:
3649ef1f84bSDavid du Colombier if(n & 1)
3659ef1f84bSDavid du Colombier error(Ebadarg);
3669ef1f84bSDavid du Colombier checkport(offset, offset+n);
3679ef1f84bSDavid du Colombier sp = a;
3689ef1f84bSDavid du Colombier for(port = offset; port < offset+n; port += 2)
3699ef1f84bSDavid du Colombier *sp++ = ins(port);
3709ef1f84bSDavid du Colombier return n;
3719ef1f84bSDavid du Colombier
3729ef1f84bSDavid du Colombier case Qiol:
3739ef1f84bSDavid du Colombier if(n & 3)
3749ef1f84bSDavid du Colombier error(Ebadarg);
3759ef1f84bSDavid du Colombier checkport(offset, offset+n);
3769ef1f84bSDavid du Colombier lp = a;
3779ef1f84bSDavid du Colombier for(port = offset; port < offset+n; port += 4)
3789ef1f84bSDavid du Colombier *lp++ = inl(port);
3799ef1f84bSDavid du Colombier return n;
3809ef1f84bSDavid du Colombier
3819ef1f84bSDavid du Colombier case Qioalloc:
3829ef1f84bSDavid du Colombier break;
3839ef1f84bSDavid du Colombier
3849ef1f84bSDavid du Colombier default:
3859ef1f84bSDavid du Colombier if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
3869ef1f84bSDavid du Colombier return fn(c, a, n, offset);
3879ef1f84bSDavid du Colombier error(Eperm);
3889ef1f84bSDavid du Colombier break;
3899ef1f84bSDavid du Colombier }
3909ef1f84bSDavid du Colombier
3919ef1f84bSDavid du Colombier if((buf = malloc(n)) == nil)
3929ef1f84bSDavid du Colombier error(Enomem);
3939ef1f84bSDavid du Colombier p = buf;
3949ef1f84bSDavid du Colombier n = n/Linelen;
3959ef1f84bSDavid du Colombier offset = offset/Linelen;
3969ef1f84bSDavid du Colombier
3979ef1f84bSDavid du Colombier lock(&iomap);
3989ef1f84bSDavid du Colombier for(map = iomap.map; n > 0 && map != nil; map = map->next){
3999ef1f84bSDavid du Colombier if(offset-- > 0)
4009ef1f84bSDavid du Colombier continue;
4019ef1f84bSDavid du Colombier sprint(p, "%#8lux %#8lux %-12.12s\n", map->start, map->end-1, map->tag);
4029ef1f84bSDavid du Colombier p += Linelen;
4039ef1f84bSDavid du Colombier n--;
4049ef1f84bSDavid du Colombier }
4059ef1f84bSDavid du Colombier unlock(&iomap);
4069ef1f84bSDavid du Colombier
4079ef1f84bSDavid du Colombier n = p - buf;
4089ef1f84bSDavid du Colombier memmove(a, buf, n);
4099ef1f84bSDavid du Colombier free(buf);
4109ef1f84bSDavid du Colombier
4119ef1f84bSDavid du Colombier return n;
4129ef1f84bSDavid du Colombier }
4139ef1f84bSDavid du Colombier
4149ef1f84bSDavid du Colombier static long
archwrite(Chan * c,void * a,long n,vlong offset)4159ef1f84bSDavid du Colombier archwrite(Chan *c, void *a, long n, vlong offset)
4169ef1f84bSDavid du Colombier {
4179ef1f84bSDavid du Colombier char *p;
4189ef1f84bSDavid du Colombier int port;
4199ef1f84bSDavid du Colombier ushort *sp;
4209ef1f84bSDavid du Colombier ulong *lp;
4219ef1f84bSDavid du Colombier Rdwrfn *fn;
4229ef1f84bSDavid du Colombier
4239ef1f84bSDavid du Colombier switch((ulong)c->qid.path){
4249ef1f84bSDavid du Colombier
4259ef1f84bSDavid du Colombier case Qiob:
4269ef1f84bSDavid du Colombier p = a;
4279ef1f84bSDavid du Colombier checkport(offset, offset+n);
4289ef1f84bSDavid du Colombier for(port = offset; port < offset+n; port++)
4299ef1f84bSDavid du Colombier outb(port, *p++);
4309ef1f84bSDavid du Colombier return n;
4319ef1f84bSDavid du Colombier
4329ef1f84bSDavid du Colombier case Qiow:
4339ef1f84bSDavid du Colombier if(n & 1)
4349ef1f84bSDavid du Colombier error(Ebadarg);
4359ef1f84bSDavid du Colombier checkport(offset, offset+n);
4369ef1f84bSDavid du Colombier sp = a;
4379ef1f84bSDavid du Colombier for(port = offset; port < offset+n; port += 2)
4389ef1f84bSDavid du Colombier outs(port, *sp++);
4399ef1f84bSDavid du Colombier return n;
4409ef1f84bSDavid du Colombier
4419ef1f84bSDavid du Colombier case Qiol:
4429ef1f84bSDavid du Colombier if(n & 3)
4439ef1f84bSDavid du Colombier error(Ebadarg);
4449ef1f84bSDavid du Colombier checkport(offset, offset+n);
4459ef1f84bSDavid du Colombier lp = a;
4469ef1f84bSDavid du Colombier for(port = offset; port < offset+n; port += 4)
4479ef1f84bSDavid du Colombier outl(port, *lp++);
4489ef1f84bSDavid du Colombier return n;
4499ef1f84bSDavid du Colombier
4509ef1f84bSDavid du Colombier default:
4519ef1f84bSDavid du Colombier if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
4529ef1f84bSDavid du Colombier return fn(c, a, n, offset);
4539ef1f84bSDavid du Colombier error(Eperm);
4549ef1f84bSDavid du Colombier break;
4559ef1f84bSDavid du Colombier }
4569ef1f84bSDavid du Colombier return 0;
4579ef1f84bSDavid du Colombier }
4589ef1f84bSDavid du Colombier
4599ef1f84bSDavid du Colombier Dev archdevtab = {
4609ef1f84bSDavid du Colombier 'P',
4619ef1f84bSDavid du Colombier "arch",
4629ef1f84bSDavid du Colombier
4639ef1f84bSDavid du Colombier devreset,
4649ef1f84bSDavid du Colombier devinit,
4659ef1f84bSDavid du Colombier devshutdown,
4669ef1f84bSDavid du Colombier archattach,
4679ef1f84bSDavid du Colombier archwalk,
4689ef1f84bSDavid du Colombier archstat,
4699ef1f84bSDavid du Colombier archopen,
4709ef1f84bSDavid du Colombier devcreate,
4719ef1f84bSDavid du Colombier archclose,
4729ef1f84bSDavid du Colombier archread,
4739ef1f84bSDavid du Colombier devbread,
4749ef1f84bSDavid du Colombier archwrite,
4759ef1f84bSDavid du Colombier devbwrite,
4769ef1f84bSDavid du Colombier devremove,
4779ef1f84bSDavid du Colombier devwstat,
4789ef1f84bSDavid du Colombier };
4799ef1f84bSDavid du Colombier
4809ef1f84bSDavid du Colombier /*
4819ef1f84bSDavid du Colombier */
4829ef1f84bSDavid du Colombier void
nop(void)4839ef1f84bSDavid du Colombier nop(void)
4849ef1f84bSDavid du Colombier {
4859ef1f84bSDavid du Colombier }
4869ef1f84bSDavid du Colombier
4879ef1f84bSDavid du Colombier void (*coherence)(void) = mfence;
4889ef1f84bSDavid du Colombier
4899ef1f84bSDavid du Colombier static long
cputyperead(Chan *,void * a,long n,vlong off)4909ef1f84bSDavid du Colombier cputyperead(Chan*, void *a, long n, vlong off)
4919ef1f84bSDavid du Colombier {
4929ef1f84bSDavid du Colombier char str[32];
4939ef1f84bSDavid du Colombier
4949ef1f84bSDavid du Colombier snprint(str, sizeof(str), "%s %ud\n", "AMD64", m->cpumhz);
4959ef1f84bSDavid du Colombier return readstr(off, a, n, str);
4969ef1f84bSDavid du Colombier }
4979ef1f84bSDavid du Colombier
4989ef1f84bSDavid du Colombier void
archinit(void)4999ef1f84bSDavid du Colombier archinit(void)
5009ef1f84bSDavid du Colombier {
5019ef1f84bSDavid du Colombier addarchfile("cputype", 0444, cputyperead, nil);
5029ef1f84bSDavid du Colombier }
5039ef1f84bSDavid du Colombier
5049ef1f84bSDavid du Colombier void
archreset(void)5059ef1f84bSDavid du Colombier archreset(void)
5069ef1f84bSDavid du Colombier {
5079ef1f84bSDavid du Colombier int i;
5089ef1f84bSDavid du Colombier
5099ef1f84bSDavid du Colombier /*
5109ef1f84bSDavid du Colombier * And sometimes there is no keyboard...
5119ef1f84bSDavid du Colombier *
5129ef1f84bSDavid du Colombier * The reset register (0xcf9) is usually in one of the bridge
5139ef1f84bSDavid du Colombier * chips. The actual location and sequence could be extracted from
5149ef1f84bSDavid du Colombier * ACPI but why bother, this is the end of the line anyway.
5159ef1f84bSDavid du Colombier print("Takes a licking and keeps on ticking...\n");
5169ef1f84bSDavid du Colombier */
5179ef1f84bSDavid du Colombier i = inb(0xcf9); /* ICHx reset control */
5189ef1f84bSDavid du Colombier i &= 0x06;
5199ef1f84bSDavid du Colombier outb(0xcf9, i|0x02); /* SYS_RST */
5209ef1f84bSDavid du Colombier millidelay(1);
5219ef1f84bSDavid du Colombier outb(0xcf9, i|0x06); /* RST_CPU transition */
5229ef1f84bSDavid du Colombier
5239ef1f84bSDavid du Colombier for(;;)
524*6c88371cSDavid du Colombier pause();
5259ef1f84bSDavid du Colombier }
5269ef1f84bSDavid du Colombier
5279ef1f84bSDavid du Colombier /*
5289ef1f84bSDavid du Colombier * return value and speed of timer
5299ef1f84bSDavid du Colombier */
5309ef1f84bSDavid du Colombier uvlong
fastticks(uvlong * hz)5319ef1f84bSDavid du Colombier fastticks(uvlong* hz)
5329ef1f84bSDavid du Colombier {
5339ef1f84bSDavid du Colombier if(hz != nil)
5349ef1f84bSDavid du Colombier *hz = m->cpuhz;
5359ef1f84bSDavid du Colombier return rdtsc();
5369ef1f84bSDavid du Colombier }
5379ef1f84bSDavid du Colombier
5389ef1f84bSDavid du Colombier ulong
s(void)5399ef1f84bSDavid du Colombier µs(void)
5409ef1f84bSDavid du Colombier {
5419ef1f84bSDavid du Colombier return fastticks2us(rdtsc());
5429ef1f84bSDavid du Colombier }
5439ef1f84bSDavid du Colombier
5449ef1f84bSDavid du Colombier /*
5459ef1f84bSDavid du Colombier * set next timer interrupt
5469ef1f84bSDavid du Colombier */
5479ef1f84bSDavid du Colombier void
timerset(uvlong x)5489ef1f84bSDavid du Colombier timerset(uvlong x)
5499ef1f84bSDavid du Colombier {
5509ef1f84bSDavid du Colombier extern void apictimerset(uvlong);
5519ef1f84bSDavid du Colombier
5529ef1f84bSDavid du Colombier apictimerset(x);
5539ef1f84bSDavid du Colombier }
5549ef1f84bSDavid du Colombier
5559ef1f84bSDavid du Colombier void
cycles(uvlong * t)5569ef1f84bSDavid du Colombier cycles(uvlong* t)
5579ef1f84bSDavid du Colombier {
5589ef1f84bSDavid du Colombier *t = rdtsc();
5599ef1f84bSDavid du Colombier }
5609ef1f84bSDavid du Colombier
5619ef1f84bSDavid du Colombier void
delay(int millisecs)5629ef1f84bSDavid du Colombier delay(int millisecs)
5639ef1f84bSDavid du Colombier {
5649ef1f84bSDavid du Colombier u64int r, t;
5659ef1f84bSDavid du Colombier
5669ef1f84bSDavid du Colombier if(millisecs <= 0)
5679ef1f84bSDavid du Colombier millisecs = 1;
5689ef1f84bSDavid du Colombier r = rdtsc();
5699ef1f84bSDavid du Colombier for(t = r + m->cpumhz*1000ull*millisecs; r < t; r = rdtsc())
5709ef1f84bSDavid du Colombier ;
5719ef1f84bSDavid du Colombier }
5729ef1f84bSDavid du Colombier
5739ef1f84bSDavid du Colombier /*
5749ef1f84bSDavid du Colombier * performance measurement ticks. must be low overhead.
5759ef1f84bSDavid du Colombier * doesn't have to count over a second.
5769ef1f84bSDavid du Colombier */
5779ef1f84bSDavid du Colombier ulong
perfticks(void)5789ef1f84bSDavid du Colombier perfticks(void)
5799ef1f84bSDavid du Colombier {
5809ef1f84bSDavid du Colombier uvlong x;
5819ef1f84bSDavid du Colombier
5829ef1f84bSDavid du Colombier // if(m->havetsc)
5839ef1f84bSDavid du Colombier cycles(&x);
5849ef1f84bSDavid du Colombier // else
5859ef1f84bSDavid du Colombier // x = 0;
5869ef1f84bSDavid du Colombier return x;
5879ef1f84bSDavid du Colombier }
588