The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/alphapc/devarch.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include "u.h"
    2 #include "../port/lib.h"
    3 #include "mem.h"
    4 #include "dat.h"
    5 #include "fns.h"
    6 #include "io.h"
    7 #include "../port/error.h"
    8 #include        "axp.h"
    9 
   10 typedef struct IOMap IOMap;
   11 struct IOMap
   12 {
   13         IOMap   *next;
   14         char    tag[13];
   15         ulong   start;
   16         ulong   end;
   17 };
   18 
   19 static struct
   20 {
   21         Lock;
   22         IOMap   *m;
   23         IOMap   *free;
   24         IOMap   maps[32];               // some initial free maps
   25 
   26         QLock   ql;                     // lock for reading map
   27 } iomap;
   28 
   29 enum {
   30         Qdir = 0,
   31         Qioalloc = 1,
   32         Qiob,
   33         Qiow,
   34         Qiol,
   35         Qbase,
   36 
   37         Qmax = 16,
   38 };
   39 
   40 typedef long Rdwrfn(Chan*, void*, long, vlong);
   41 
   42 static Rdwrfn *readfn[Qmax];
   43 static Rdwrfn *writefn[Qmax];
   44 
   45 static Dirtab archdir[] = {
   46         ".",    { Qdir, 0, QTDIR },     0,      0555,
   47         "ioalloc",      { Qioalloc, 0 },        0,      0444,
   48         "iob",          { Qiob, 0 },            0,      0660,
   49         "iow",          { Qiow, 0 },            0,      0660,
   50         "iol",          { Qiol, 0 },            0,      0660,
   51 };
   52 Lock archwlock; /* the lock is only for changing archdir */
   53 int narchdir = Qbase;
   54 int (*_pcmspecial)(char *, ISAConf *);
   55 void (*_pcmspecialclose)(int);
   56 
   57 /*
   58  * Add a file to the #P listing.  Once added, you can't delete it.
   59  * You can't add a file with the same name as one already there,
   60  * and you get a pointer to the Dirtab entry so you can do things
   61  * like change the Qid version.  Changing the Qid path is disallowed.
   62  */
   63 Dirtab*
   64 addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
   65 {
   66         int i;
   67         Dirtab d;
   68         Dirtab *dp;
   69 
   70         memset(&d, 0, sizeof d);
   71         strcpy(d.name, name);
   72         d.perm = perm;
   73 
   74         lock(&archwlock);
   75         if(narchdir >= Qmax){
   76                 unlock(&archwlock);
   77                 return nil;
   78         }
   79 
   80         for(i=0; i<narchdir; i++)
   81                 if(strcmp(archdir[i].name, name) == 0){
   82                         unlock(&archwlock);
   83                         return nil;
   84                 }
   85 
   86         d.qid.path = narchdir;
   87         archdir[narchdir] = d;
   88         readfn[narchdir] = rdfn;
   89         writefn[narchdir] = wrfn;
   90         dp = &archdir[narchdir++];
   91         unlock(&archwlock);
   92 
   93         return dp;
   94 }
   95 
   96 void
   97 ioinit(void)
   98 {
   99         int i;
  100 
  101         for(i = 0; i < nelem(iomap.maps)-1; i++)
  102                 iomap.maps[i].next = &iomap.maps[i+1];
  103         iomap.maps[i].next = nil;
  104         iomap.free = iomap.maps;
  105 
  106         // a dummy entry at 2^17
  107         ioalloc(0x20000, 1, 0, "dummy");
  108 }
  109 
  110 //
  111 //      alloc some io port space and remember who it was
  112 //      alloced to.  if port < 0, find a free region.
  113 //
  114 int
  115 ioalloc(int port, int size, int align, char *tag)
  116 {
  117         IOMap *m, **l;
  118         int i;
  119 
  120         lock(&iomap);
  121         if(port < 0){
  122                 // find a free port above 0x400 and below 0x1000
  123                 port = 0x400;
  124                 for(l = &iomap.m; *l; l = &(*l)->next){
  125                         m = *l;
  126                         i = m->start - port;
  127                         if(i > size)
  128                                 break;
  129                         if(align > 0)
  130                                 port = ((port+align-1)/align)*align;
  131                         else
  132                                 port = m->end;
  133                 }
  134                 if(*l == nil){
  135                         unlock(&iomap);
  136                         return -1;
  137                 }
  138         } else {
  139                 // see if the space clashes with previously allocated ports
  140                 for(l = &iomap.m; *l; l = &(*l)->next){
  141                         m = *l;
  142                         if(m->end <= port)
  143                                 continue;
  144                         if(m->start >= port+size)
  145                                 break;
  146                         unlock(&iomap);
  147                         return -1;
  148                 }
  149         }
  150         m = iomap.free;
  151         if(m == nil){
  152                 print("ioalloc: out of maps");
  153                 unlock(&iomap);
  154                 return port;
  155         }
  156         iomap.free = m->next;
  157         m->next = *l;
  158         m->start = port;
  159         m->end = port + size;
  160         strncpy(m->tag, tag, sizeof(m->tag));
  161         m->tag[sizeof(m->tag)-1] = 0;
  162         *l = m;
  163 
  164         archdir[0].qid.vers++;
  165 
  166         unlock(&iomap);
  167         return m->start;
  168 }
  169 
  170 void
  171 iofree(int port)
  172 {
  173         IOMap *m, **l;
  174 
  175         lock(&iomap);
  176         for(l = &iomap.m; *l; l = &(*l)->next){
  177                 if((*l)->start == port){
  178                         m = *l;
  179                         *l = m->next;
  180                         m->next = iomap.free;
  181                         iomap.free = m;
  182                         break;
  183                 }
  184                 if((*l)->start > port)
  185                         break;
  186         }
  187         archdir[0].qid.vers++;
  188         unlock(&iomap);
  189 }
  190 
  191 int
  192 iounused(int start, int end)
  193 {
  194         IOMap *m;
  195 
  196         for(m = iomap.m; m; m = m->next){
  197                 if(start >= m->start && start < m->end
  198                 || start <= m->start && end > m->start)
  199                         return 0; 
  200         }
  201         return 1;
  202 }
  203 
  204 static void
  205 checkport(int start, int end)
  206 {
  207         /* standard vga regs are OK */
  208         if(start >= 0x2b0 && end <= 0x2df+1)
  209                 return;
  210         if(start >= 0x3c0 && end <= 0x3da+1)
  211                 return;
  212 
  213         if(iounused(start, end))
  214                 return;
  215         error(Eperm);
  216 }
  217 
  218 static Chan*
  219 archattach(char* spec)
  220 {
  221         return devattach('P', spec);
  222 }
  223 
  224 Walkqid*
  225 archwalk(Chan* c, Chan *nc, char** name, int nname)
  226 {
  227         return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
  228 }
  229 
  230 static int
  231 archstat(Chan* c, uchar* dp, int n)
  232 {
  233         return devstat(c, dp, n, archdir, narchdir, devgen);
  234 }
  235 
  236 static Chan*
  237 archopen(Chan* c, int omode)
  238 {
  239         return devopen(c, omode, archdir, nelem(archdir), devgen);
  240 }
  241 
  242 static void
  243 archclose(Chan*)
  244 {
  245 }
  246 
  247 enum
  248 {
  249         Linelen= 31,
  250 };
  251 
  252 static long
  253 archread(Chan *c, void *a, long n, vlong offset)
  254 {
  255         char buf[Linelen+1], *p;
  256         int port;
  257         ushort *sp;
  258         ulong *lp;
  259         IOMap *m;
  260         Rdwrfn *fn;
  261 
  262         switch((ulong)c->qid.path){
  263 
  264         case Qdir:
  265                 return devdirread(c, a, n, archdir, nelem(archdir), devgen);
  266 
  267         case Qiob:
  268                 port = offset;
  269                 checkport(offset, offset+n);
  270                 for(p = a; port < offset+n; port++)
  271                         *p++ = inb(port);
  272                 return n;
  273 
  274         case Qiow:
  275                 if((n & 0x01) || (offset & 0x01))
  276                         error(Ebadarg);
  277                 checkport(offset, offset+n+1);
  278                 n /= 2;
  279                 sp = a;
  280                 for(port = offset; port < offset+n; port += 2)
  281                         *sp++ = ins(port);
  282                 return n*2;
  283 
  284         case Qiol:
  285                 if((n & 0x03) || (offset & 0x03))
  286                         error(Ebadarg);
  287                 checkport(offset, offset+n+3);
  288                 n /= 4;
  289                 lp = a;
  290                 for(port = offset; port < offset+n; port += 4)
  291                         *lp++ = inl(port);
  292                 return n*4;
  293 
  294         case Qioalloc:
  295                 break;
  296 
  297         default:
  298                 if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
  299                         return fn(c, a, n, offset);
  300                 error(Eperm);
  301                 break;
  302         }
  303 
  304         offset = offset/Linelen;
  305         n = n/Linelen;
  306         p = a;
  307         lock(&iomap);
  308         for(m = iomap.m; n > 0 && m != nil; m = m->next){
  309                 if(offset-- > 0)
  310                         continue;
  311                 if(strcmp(m->tag, "dummy") == 0)
  312                         break;
  313                 sprint(buf, "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag);
  314                 memmove(p, buf, Linelen);
  315                 p += Linelen;
  316                 n--;
  317         }
  318         unlock(&iomap);
  319 
  320         return p - (char*)a;
  321 }
  322 
  323 static long
  324 archwrite(Chan *c, void *a, long n, vlong offset)
  325 {
  326         char *p;
  327         int port;
  328         ushort *sp;
  329         ulong *lp;
  330         Rdwrfn *fn;
  331 
  332         switch((ulong)c->qid.path){
  333 
  334         case Qiob:
  335                 p = a;
  336                 checkport(offset, offset+n);
  337                 for(port = offset; port < offset+n; port++)
  338                         outb(port, *p++);
  339                 return n;
  340 
  341         case Qiow:
  342                 if((n & 01) || (offset & 01))
  343                         error(Ebadarg);
  344                 checkport(offset, offset+n+1);
  345                 n /= 2;
  346                 sp = a;
  347                 for(port = offset; port < offset+n; port += 2)
  348                         outs(port, *sp++);
  349                 return n*2;
  350 
  351         case Qiol:
  352                 if((n & 0x03) || (offset & 0x03))
  353                         error(Ebadarg);
  354                 checkport(offset, offset+n+3);
  355                 n /= 4;
  356                 lp = a;
  357                 for(port = offset; port < offset+n; port += 4)
  358                         outl(port, *lp++);
  359                 return n*4;
  360 
  361         default:
  362                 if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
  363                         return fn(c, a, n, offset);
  364                 error(Eperm);
  365                 break;
  366         }
  367         return 0;
  368 }
  369 
  370 Dev archdevtab = {
  371         'P',
  372         "arch",
  373 
  374         devreset,
  375         devinit,        
  376         devshutdown,
  377         archattach,
  378         archwalk,
  379         archstat,
  380         archopen,
  381         devcreate,
  382         archclose,
  383         archread,
  384         devbread,
  385         archwrite,
  386         devbwrite,
  387         devremove,
  388         devwstat,
  389 };
  390 
  391 PCArch* arch;
  392 extern PCArch* knownarch[];
  393 
  394 PCArch archgeneric = {
  395         "generic",                              /* id */
  396         0,                                      /* ident */
  397 
  398         0,                                      /* coreinit */
  399         0,                                      /* coredetach */
  400 };
  401 
  402 static char     *sysnames[] =
  403 {
  404 [1]             "Alpha Demo. Unit",
  405 [2]             "DEC 4000; Cobra",
  406 [3]             "DEC 7000; Ruby",
  407 [4]             "DEC 3000/500; Flamingo family (TC)",
  408 [6]             "DEC 2000/300; Jensen (EISA/ISA)",
  409 [7]             "DEC 3000/300; Pelican (TC)",
  410 [8]             "Avalon A12; Avalon Multicomputer",
  411 [9]             "DEC 2100/A500; Sable",
  412 [10]            "DEC APXVME/64; AXPvme (VME?)",
  413 [11]            "DEC AXPPCI/33; NoName (PCI/ISA)",
  414 [12]            "DEC 21000; TurboLaser (PCI/EISA)",
  415 [13]            "DEC 2100/A50; Avanti (PCI/ISA)",
  416 [14]            "DEC MUSTANG; Mustang",
  417 [15]            "DEC KN20AA; kn20aa (PCI/EISA)",
  418 [17]            "DEC 1000; Mikasa (PCI/ISA?)",
  419 [19]            "EB66; EB66 (PCI/ISA?)",                // DEC?
  420 [20]            "EB64P; EB64+ (PCI/ISA?)",              // DEC?
  421 [21]            "Alphabook1; Alphabook",
  422 [22]            "DEC 4100; Rawhide (PCI/EISA)",
  423 [23]            "DEC EV45/PBP; Lego",
  424 [24]            "DEC 2100A/A500; Lynx",
  425 [26]            "DEC AlphaPC 164",      // only supported one: "EB164 (PCI/ISA)"
  426 [27]            "DEC 1000A; Noritake",
  427 [28]            "DEC AlphaVME/224; Cortex",
  428 [30]            "DEC 550; Miata (PCI/ISA)",
  429 [32]            "DEC EV56/PBP; Takara",
  430 [33]            "DEC AlphaVME/320; Yukon (VME?)",
  431 [34]            "DEC 6600; MonetGoldrush",
  432 // 200 and up is Alpha Processor Inc. machines
  433 // [201]        "API UP1000; Nautilus",
  434 };
  435 
  436 static char     *cpunames[] =
  437 {
  438 [1]             "EV3",
  439 [2]             "EV4: 21064",
  440 [3]             "Simulation",
  441 [4]             "LCA4: 2106[68]",
  442 [5]             "EV5: 21164",
  443 [6]             "EV45: 21064A",
  444 [7]             "21164A",               /* only supported one: EV56 */
  445 [8]             "EV6: 21264",
  446 [9]             "PCA256: 21164PC",
  447 };
  448 
  449 void
  450 cpuidprint(void)
  451 {
  452         int i, maj, min;
  453         Hwcpu *cpu;
  454         Hwdsr *dsr;
  455         char *s;
  456 
  457         print("\n");
  458 
  459         if (hwrpb->rev >= 6) {
  460                 dsr = (Hwdsr*)((ulong)hwrpb + hwrpb->dsroff);
  461 
  462                 s = (char*)dsr + dsr->sysnameoff + 8;
  463                 print("%s\n", s);
  464         }
  465         else {
  466                 s = "<unknown>";
  467                 if (hwrpb->systype < nelem(sysnames))
  468                         s = sysnames[hwrpb->systype];
  469                 print("%s (%llux, %llux, %llux)\n", s, hwrpb->systype, hwrpb->sysvar, hwrpb->sysrev);
  470         }
  471 
  472         for (i = 0; i < hwrpb->ncpu; i++) {
  473                 cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff + i*hwrpb->cpulen);
  474                 s = "<unknown>";
  475                 maj = (ulong)cpu->cputype;
  476                 min = (ulong)(cpu->cputype>>32);
  477                 if (maj < nelem(cpunames))
  478                         s = cpunames[maj];
  479                 print("cpu%d: %s-%d (%d.%d, %llux, %llux)\n",
  480                         i, s, min, maj, min, cpu->cpuvar, cpu->cpurev);
  481         }
  482 
  483         print("\n");
  484 }
  485 
  486 static long
  487 cputyperead(Chan*, void *a, long n, vlong offset)
  488 {
  489         char str[32], *cputype;
  490         ulong mhz, maj;
  491         Hwcpu *cpu;
  492 
  493         mhz = (m->cpuhz+999999)/1000000;
  494         cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff);  /* NB CPU 0 */
  495         cputype = "unknown";
  496         maj = (ulong)cpu->cputype;
  497         if (maj < nelem(cpunames))
  498                 cputype = cpunames[maj];
  499 
  500         snprint(str, sizeof(str), "%s %lud\n", cputype, mhz);
  501         return readstr(offset, a, n, str);
  502 }
  503 
  504 void
  505 archinit(void)
  506 {
  507         PCArch **p;
  508 
  509         arch = 0;
  510         for(p = knownarch; *p; p++){
  511                 if((*p)->ident && (*p)->ident() == 0){
  512                         arch = *p;
  513                         break;
  514                 }
  515         }
  516         if(arch == 0)
  517                 arch = &archgeneric;
  518 
  519         addarchfile("cputype", 0444, cputyperead, nil);
  520 }
  521 
  522 int
  523 pcmspecial(char *idstr, ISAConf *isa)
  524 {
  525         return (_pcmspecial  != nil)? _pcmspecial(idstr, isa): -1;
  526 }
  527 
  528 void
  529 pcmspecialclose(int a)
  530 {
  531         if (_pcmspecialclose != nil)
  532                 _pcmspecialclose(a);
  533 }

Cache object: e4b91f38cd0d9e6ef59b5495526c4b4e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.