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/pc/main.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        "ureg.h"
    8 #include        "init.h"
    9 #include        "pool.h"
   10 #include        "reboot.h"
   11 
   12 Mach *m;
   13 
   14 /*
   15  * Where configuration info is left for the loaded programme.
   16  * This will turn into a structure as more is done by the boot loader
   17  * (e.g. why parse the .ini file twice?).
   18  * There are 3584 bytes available at CONFADDR.
   19  */
   20 #define BOOTLINE        ((char*)CONFADDR)
   21 #define BOOTLINELEN     64
   22 #define BOOTARGS        ((char*)(CONFADDR+BOOTLINELEN))
   23 #define BOOTARGSLEN     (4096-0x200-BOOTLINELEN)
   24 #define MAXCONF         64
   25 
   26 char bootdisk[KNAMELEN];
   27 Conf conf;
   28 char *confname[MAXCONF];
   29 char *confval[MAXCONF];
   30 int nconf;
   31 uchar *sp;      /* user stack of init proc */
   32 int delaylink;
   33 
   34 static void
   35 options(void)
   36 {
   37         long i, n;
   38         char *cp, *line[MAXCONF], *p, *q;
   39 
   40         /*
   41          *  parse configuration args from dos file plan9.ini
   42          */
   43         cp = BOOTARGS;  /* where b.com leaves its config */
   44         cp[BOOTARGSLEN-1] = 0;
   45 
   46         /*
   47          * Strip out '\r', change '\t' -> ' '.
   48          */
   49         p = cp;
   50         for(q = cp; *q; q++){
   51                 if(*q == '\r')
   52                         continue;
   53                 if(*q == '\t')
   54                         *q = ' ';
   55                 *p++ = *q;
   56         }
   57         *p = 0;
   58 
   59         n = getfields(cp, line, MAXCONF, 1, "\n");
   60         for(i = 0; i < n; i++){
   61                 if(*line[i] == '#')
   62                         continue;
   63                 cp = strchr(line[i], '=');
   64                 if(cp == nil)
   65                         continue;
   66                 *cp++ = '\0';
   67                 confname[nconf] = line[i];
   68                 confval[nconf] = cp;
   69                 nconf++;
   70         }
   71 }
   72 
   73 extern void mmuinit0(void);
   74 extern void (*i8237alloc)(void);
   75 
   76 void
   77 main(void)
   78 {
   79         mach0init();
   80         options();
   81         ioinit();
   82         i8250console();
   83         quotefmtinstall();
   84         screeninit();
   85 
   86         print("\nPlan 9\n");
   87 
   88         trapinit0();
   89         mmuinit0();
   90 
   91         kbdinit();
   92         i8253init();
   93         cpuidentify();
   94         meminit();
   95         confinit();
   96         archinit();
   97         xinit();
   98         if(i8237alloc != nil)
   99                 i8237alloc();
  100         trapinit();
  101         printinit();
  102         cpuidprint();
  103         mmuinit();
  104         if(arch->intrinit)      /* launches other processors on an mp */
  105                 arch->intrinit();
  106         timersinit();
  107         mathinit();
  108         kbdenable();
  109         if(arch->clockenable)
  110                 arch->clockenable();
  111         procinit0();
  112         initseg();
  113         if(delaylink){
  114                 bootlinks();
  115                 pcimatch(0, 0, 0);
  116         }else
  117                 links();
  118         conf.monitor = 1;
  119         chandevreset();
  120         pageinit();
  121         i8253link();
  122         swapinit();
  123         userinit();
  124         active.thunderbirdsarego = 1;
  125         schedinit();
  126 }
  127 
  128 void
  129 mach0init(void)
  130 {
  131         conf.nmach = 1;
  132         MACHP(0) = (Mach*)CPU0MACH;
  133         m->pdb = (ulong*)CPU0PDB;
  134         m->gdt = (Segdesc*)CPU0GDT;
  135 
  136         machinit();
  137 
  138         active.machs = 1;
  139         active.exiting = 0;
  140 }
  141 
  142 void
  143 machinit(void)
  144 {
  145         int machno;
  146         ulong *pdb;
  147         Segdesc *gdt;
  148 
  149         machno = m->machno;
  150         pdb = m->pdb;
  151         gdt = m->gdt;
  152         memset(m, 0, sizeof(Mach));
  153         m->machno = machno;
  154         m->pdb = pdb;
  155         m->gdt = gdt;
  156         m->perf.period = 1;
  157 
  158         /*
  159          * For polled uart output at boot, need
  160          * a default delay constant. 100000 should
  161          * be enough for a while. Cpuidentify will
  162          * calculate the real value later.
  163          */
  164         m->loopconst = 100000;
  165 }
  166 
  167 void
  168 init0(void)
  169 {
  170         int i;
  171         char buf[2*KNAMELEN];
  172 
  173         up->nerrlab = 0;
  174 
  175         spllo();
  176 
  177         /*
  178          * These are o.k. because rootinit is null.
  179          * Then early kproc's will have a root and dot.
  180          */
  181         up->slash = namec("#/", Atodir, 0, 0);
  182         pathclose(up->slash->path);
  183         up->slash->path = newpath("/");
  184         up->dot = cclone(up->slash);
  185 
  186         chandevinit();
  187 
  188         if(!waserror()){
  189                 snprint(buf, sizeof(buf), "%s %s", arch->id, conffile);
  190                 ksetenv("terminal", buf, 0);
  191                 ksetenv("cputype", "386", 0);
  192                 if(cpuserver)
  193                         ksetenv("service", "cpu", 0);
  194                 else
  195                         ksetenv("service", "terminal", 0);
  196                 for(i = 0; i < nconf; i++){
  197                         if(confname[i][0] != '*')
  198                                 ksetenv(confname[i], confval[i], 0);
  199                         ksetenv(confname[i], confval[i], 1);
  200                 }
  201                 poperror();
  202         }
  203         kproc("alarm", alarmkproc, 0);
  204         touser(sp);
  205 }
  206 
  207 void
  208 userinit(void)
  209 {
  210         void *v;
  211         Proc *p;
  212         Segment *s;
  213         Page *pg;
  214 
  215         p = newproc();
  216         p->pgrp = newpgrp();
  217         p->egrp = smalloc(sizeof(Egrp));
  218         p->egrp->ref = 1;
  219         p->fgrp = dupfgrp(nil);
  220         p->rgrp = newrgrp();
  221         p->procmode = 0640;
  222 
  223         kstrdup(&eve, "");
  224         kstrdup(&p->text, "*init*");
  225         kstrdup(&p->user, eve);
  226 
  227         p->fpstate = FPinit;
  228         fpoff();
  229 
  230         /*
  231          * Kernel Stack
  232          *
  233          * N.B. make sure there's enough space for syscall to check
  234          *      for valid args and 
  235          *      4 bytes for gotolabel's return PC
  236          */
  237         p->sched.pc = (ulong)init0;
  238         p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
  239 
  240         /*
  241          * User Stack
  242          *
  243          * N.B. cannot call newpage() with clear=1, because pc kmap
  244          * requires up != nil.  use tmpmap instead.
  245          */
  246         s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
  247         p->seg[SSEG] = s;
  248         pg = newpage(0, 0, USTKTOP-BY2PG);
  249         v = tmpmap(pg);
  250         memset(v, 0, BY2PG);
  251         segpage(s, pg);
  252         bootargs(v);
  253         tmpunmap(v);
  254 
  255         /*
  256          * Text
  257          */
  258         s = newseg(SG_TEXT, UTZERO, 1);
  259         s->flushme++;
  260         p->seg[TSEG] = s;
  261         pg = newpage(0, 0, UTZERO);
  262         memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
  263         segpage(s, pg);
  264         v = tmpmap(pg);
  265         memset(v, 0, BY2PG);
  266         memmove(v, initcode, sizeof initcode);
  267         tmpunmap(v);
  268 
  269         ready(p);
  270 }
  271 
  272 uchar *
  273 pusharg(char *p)
  274 {
  275         int n;
  276 
  277         n = strlen(p)+1;
  278         sp -= n;
  279         memmove(sp, p, n);
  280         return sp;
  281 }
  282 
  283 void
  284 bootargs(void *base)
  285 {
  286         int i, ac;
  287         uchar *av[32];
  288         uchar **lsp;
  289         char *cp = BOOTLINE;
  290         char buf[64];
  291 
  292         sp = (uchar*)base + BY2PG - MAXSYSARG*BY2WD;
  293 
  294         ac = 0;
  295         av[ac++] = pusharg("/386/9dos");
  296 
  297         /* when boot is changed to only use rc, this code can go away */
  298         cp[BOOTLINELEN-1] = 0;
  299         buf[0] = 0;
  300         if(strncmp(cp, "fd", 2) == 0){
  301                 sprint(buf, "local!#f/fd%lddisk", strtol(cp+2, 0, 0));
  302                 av[ac++] = pusharg(buf);
  303         } else if(strncmp(cp, "sd", 2) == 0){
  304                 sprint(buf, "local!#S/sd%c%c/fs", *(cp+2), *(cp+3));
  305                 av[ac++] = pusharg(buf);
  306         } else if(strncmp(cp, "ether", 5) == 0)
  307                 av[ac++] = pusharg("-n");
  308 
  309         /* 4 byte word align stack */
  310         sp = (uchar*)((ulong)sp & ~3);
  311 
  312         /* build argc, argv on stack */
  313         sp -= (ac+1)*sizeof(sp);
  314         lsp = (uchar**)sp;
  315         for(i = 0; i < ac; i++)
  316                 *lsp++ = av[i] + ((USTKTOP - BY2PG) - (ulong)base);
  317         *lsp = 0;
  318         sp += (USTKTOP - BY2PG) - (ulong)base - sizeof(ulong);
  319 }
  320 
  321 char*
  322 getconf(char *name)
  323 {
  324         int i;
  325 
  326         for(i = 0; i < nconf; i++)
  327                 if(cistrcmp(confname[i], name) == 0)
  328                         return confval[i];
  329         return 0;
  330 }
  331 
  332 static void
  333 writeconf(void)
  334 {
  335         char *p, *q;
  336         int n;
  337 
  338         p = getconfenv();
  339 
  340         if(waserror()) {
  341                 free(p);
  342                 nexterror();
  343         }
  344 
  345         /* convert to name=value\n format */
  346         for(q=p; *q; q++) {
  347                 q += strlen(q);
  348                 *q = '=';
  349                 q += strlen(q);
  350                 *q = '\n';
  351         }
  352         n = q - p + 1;
  353         if(n >= BOOTARGSLEN)
  354                 error("kernel configuration too large");
  355         memset(BOOTLINE, 0, BOOTLINELEN);
  356         memmove(BOOTARGS, p, n);
  357         poperror();
  358         free(p);
  359 }
  360 
  361 void
  362 confinit(void)
  363 {
  364         char *p;
  365         int i, userpcnt;
  366         ulong kpages;
  367 
  368         if(p = getconf("*kernelpercent"))
  369                 userpcnt = 100 - strtol(p, 0, 0);
  370         else
  371                 userpcnt = 0;
  372 
  373         conf.npage = 0;
  374         for(i=0; i<nelem(conf.mem); i++)
  375                 conf.npage += conf.mem[i].npage;
  376 
  377         conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
  378         if(cpuserver)
  379                 conf.nproc *= 3;
  380         if(conf.nproc > 2000)
  381                 conf.nproc = 2000;
  382         conf.nimage = 200;
  383         conf.nswap = conf.nproc*80;
  384         conf.nswppo = 4096;
  385 
  386         if(cpuserver) {
  387                 if(userpcnt < 10)
  388                         userpcnt = 70;
  389                 kpages = conf.npage - (conf.npage*userpcnt)/100;
  390 
  391                 /*
  392                  * Hack for the big boys. Only good while physmem < 4GB.
  393                  * Give the kernel fixed max + enough to allocate the
  394                  * page pool.
  395                  * This is an overestimate as conf.upages < conf.npages.
  396                  * The patch of nimage is a band-aid, scanning the whole
  397                  * page list in imagereclaim just takes too long.
  398                  */
  399                 if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
  400                         kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
  401                         conf.nimage = 2000;
  402                         kpages += (conf.nproc*KSTACK)/BY2PG;
  403                 }
  404         } else {
  405                 if(userpcnt < 10) {
  406                         if(conf.npage*BY2PG < 16*MB)
  407                                 userpcnt = 40;
  408                         else
  409                                 userpcnt = 60;
  410                 }
  411                 kpages = conf.npage - (conf.npage*userpcnt)/100;
  412 
  413                 /*
  414                  * Make sure terminals with low memory get at least
  415                  * 4MB on the first Image chunk allocation.
  416                  */
  417                 if(conf.npage*BY2PG < 16*MB)
  418                         imagmem->minarena = 4*1024*1024;
  419         }
  420 
  421         /*
  422          * can't go past the end of virtual memory
  423          * (ulong)-KZERO is 2^32 - KZERO
  424          */
  425         if(kpages > ((ulong)-KZERO)/BY2PG)
  426                 kpages = ((ulong)-KZERO)/BY2PG;
  427 
  428         conf.upages = conf.npage - kpages;
  429         conf.ialloc = (kpages/2)*BY2PG;
  430 
  431         /*
  432          * Guess how much is taken by the large permanent
  433          * datastructures. Mntcache and Mntrpc are not accounted for
  434          * (probably ~300KB).
  435          */
  436         kpages *= BY2PG;
  437         kpages -= conf.upages*sizeof(Page)
  438                 + conf.nproc*sizeof(Proc)
  439                 + conf.nimage*sizeof(Image)
  440                 + conf.nswap
  441                 + conf.nswppo*sizeof(Page);
  442         mainmem->maxsize = kpages;
  443         if(!cpuserver){
  444                 /*
  445                  * give terminals lots of image memory, too; the dynamic
  446                  * allocation will balance the load properly, hopefully.
  447                  * be careful with 32-bit overflow.
  448                  */
  449                 imagmem->maxsize = kpages;
  450         }
  451 }
  452 
  453 static char* mathmsg[] =
  454 {
  455         nil,    /* handled below */
  456         "denormalized operand",
  457         "division by zero",
  458         "numeric overflow",
  459         "numeric underflow",
  460         "precision loss",
  461 };
  462 
  463 static void
  464 mathnote(void)
  465 {
  466         int i;
  467         ulong status;
  468         char *msg, note[ERRMAX];
  469 
  470         status = up->fpsave.status;
  471 
  472         /*
  473          * Some attention should probably be paid here to the
  474          * exception masks and error summary.
  475          */
  476         msg = "unknown exception";
  477         for(i = 1; i <= 5; i++){
  478                 if(!((1<<i) & status))
  479                         continue;
  480                 msg = mathmsg[i];
  481                 break;
  482         }
  483         if(status & 0x01){
  484                 if(status & 0x40){
  485                         if(status & 0x200)
  486                                 msg = "stack overflow";
  487                         else
  488                                 msg = "stack underflow";
  489                 }else
  490                         msg = "invalid operation";
  491         }
  492         snprint(note, sizeof note, "sys: fp: %s fppc=0x%lux status=0x%lux",
  493                 msg, up->fpsave.pc, status);
  494         postnote(up, 1, note, NDebug);
  495 }
  496 
  497 /*
  498  *  math coprocessor error
  499  */
  500 static void
  501 matherror(Ureg *ur, void*)
  502 {
  503         /*
  504          *  a write cycle to port 0xF0 clears the interrupt latch attached
  505          *  to the error# line from the 387
  506          */
  507         if(!(m->cpuiddx & 0x01))
  508                 outb(0xF0, 0xFF);
  509 
  510         /*
  511          *  save floating point state to check out error
  512          */
  513         fpenv(&up->fpsave);
  514         mathnote();
  515 
  516         if((ur->pc & 0xf0000000) == KZERO)
  517                 panic("fp: status %ux fppc=0x%lux pc=0x%lux",
  518                         up->fpsave.status, up->fpsave.pc, ur->pc);
  519 }
  520 
  521 /*
  522  *  math coprocessor emulation fault
  523  */
  524 static void
  525 mathemu(Ureg *ureg, void*)
  526 {
  527         if(up->fpstate & FPillegal){
  528                 /* someone did floating point in a note handler */
  529                 postnote(up, 1, "sys: floating point in note handler", NDebug);
  530                 return;
  531         }
  532         switch(up->fpstate){
  533         case FPinit:
  534                 fpinit();
  535                 up->fpstate = FPactive;
  536                 break;
  537         case FPinactive:
  538                 /*
  539                  * Before restoring the state, check for any pending
  540                  * exceptions, there's no way to restore the state without
  541                  * generating an unmasked exception.
  542                  * More attention should probably be paid here to the
  543                  * exception masks and error summary.
  544                  */
  545                 if((up->fpsave.status & ~up->fpsave.control) & 0x07F){
  546                         mathnote();
  547                         break;
  548                 }
  549                 fprestore(&up->fpsave);
  550                 up->fpstate = FPactive;
  551                 break;
  552         case FPactive:
  553                 panic("math emu pid %ld %s pc 0x%lux", 
  554                         up->pid, up->text, ureg->pc);
  555                 break;
  556         }
  557 }
  558 
  559 /*
  560  *  math coprocessor segment overrun
  561  */
  562 static void
  563 mathover(Ureg*, void*)
  564 {
  565         pexit("math overrun", 0);
  566 }
  567 
  568 void
  569 mathinit(void)
  570 {
  571         trapenable(VectorCERR, matherror, 0, "matherror");
  572         if(X86FAMILY(m->cpuidax) == 3)
  573                 intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror");
  574         trapenable(VectorCNA, mathemu, 0, "mathemu");
  575         trapenable(VectorCSO, mathover, 0, "mathover");
  576 }
  577 
  578 /*
  579  *  set up floating point for a new process
  580  */
  581 void
  582 procsetup(Proc*p)
  583 {
  584         p->fpstate = FPinit;
  585         fpoff();
  586 }
  587 
  588 void
  589 procrestore(Proc *p)
  590 {
  591         uvlong t;
  592 
  593         if(p->kp)
  594                 return;
  595         cycles(&t);
  596         p->pcycles -= t;
  597 }
  598 
  599 /*
  600  *  Save the mach dependent part of the process state.
  601  */
  602 void
  603 procsave(Proc *p)
  604 {
  605         uvlong t;
  606 
  607         cycles(&t);
  608         p->pcycles += t;
  609         if(p->fpstate == FPactive){
  610                 if(p->state == Moribund)
  611                         fpclear();
  612                 else{
  613                         /*
  614                          * Fpsave() stores without handling pending
  615                          * unmasked exeptions. Postnote() can't be called
  616                          * here as sleep() already has up->rlock, so
  617                          * the handling of pending exceptions is delayed
  618                          * until the process runs again and generates an
  619                          * emulation fault to activate the FPU.
  620                          */
  621                         fpsave(&p->fpsave);
  622                 }
  623                 p->fpstate = FPinactive;
  624         }
  625 
  626         /*
  627          * While this processor is in the scheduler, the process could run
  628          * on another processor and exit, returning the page tables to
  629          * the free list where they could be reallocated and overwritten.
  630          * When this processor eventually has to get an entry from the
  631          * trashed page tables it will crash.
  632          *
  633          * If there's only one processor, this can't happen.
  634          * You might think it would be a win not to do this in that case,
  635          * especially on VMware, but it turns out not to matter.
  636          */
  637         mmuflushtlb(PADDR(m->pdb));
  638 }
  639 
  640 static void
  641 shutdown(int ispanic)
  642 {
  643         int ms, once;
  644 
  645         lock(&active);
  646         if(ispanic)
  647                 active.ispanic = ispanic;
  648         else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
  649                 active.ispanic = 0;
  650         once = active.machs & (1<<m->machno);
  651         active.machs &= ~(1<<m->machno);
  652         active.exiting = 1;
  653         unlock(&active);
  654 
  655         if(once)
  656                 iprint("cpu%d: exiting\n", m->machno);
  657         spllo();
  658         for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
  659                 delay(TK2MS(2));
  660                 if(active.machs == 0 && consactive() == 0)
  661                         break;
  662         }
  663 
  664         if(getconf("*debug"))
  665                 delay(5*60*1000);
  666 
  667         if(active.ispanic){
  668                 if(!cpuserver)
  669                         for(;;)
  670                                 halt();
  671                 delay(10000);
  672         }else
  673                 delay(1000);
  674 }
  675 
  676 void
  677 reboot(void *entry, void *code, ulong size)
  678 {
  679         void (*f)(ulong, ulong, ulong);
  680         ulong *pdb;
  681 
  682         writeconf();
  683 
  684         shutdown(0);
  685 
  686         /*
  687          * should be the only processor running now
  688          */
  689 
  690         print("shutting down...\n");
  691         delay(200);
  692 
  693         splhi();
  694 
  695         /* turn off buffered serial console */
  696         serialoq = nil;
  697 
  698         /* shutdown devices */
  699         chandevshutdown();
  700 
  701         /*
  702          * Modify the machine page table to directly map the low 4MB of memory
  703          * This allows the reboot code to turn off the page mapping
  704          */
  705         pdb = m->pdb;
  706         pdb[PDX(0)] = pdb[PDX(KZERO)];
  707         mmuflushtlb(PADDR(pdb));
  708 
  709         /* setup reboot trampoline function */
  710         f = (void*)REBOOTADDR;
  711         memmove(f, rebootcode, sizeof(rebootcode));
  712 
  713         print("rebooting...\n");
  714 
  715         /* off we go - never to return */
  716         coherence();
  717         (*f)(PADDR(entry), PADDR(code), size);
  718 }
  719 
  720 
  721 void
  722 exit(int ispanic)
  723 {
  724         shutdown(ispanic);
  725         arch->reset();
  726 }
  727 
  728 int
  729 isaconfig(char *class, int ctlrno, ISAConf *isa)
  730 {
  731         char cc[32], *p;
  732         int i;
  733 
  734         snprint(cc, sizeof cc, "%s%d", class, ctlrno);
  735         p = getconf(cc);
  736         if(p == nil)
  737                 return 0;
  738 
  739         isa->type = "";
  740         isa->nopt = tokenize(p, isa->opt, NISAOPT);
  741         for(i = 0; i < isa->nopt; i++){
  742                 p = isa->opt[i];
  743                 if(cistrncmp(p, "type=", 5) == 0)
  744                         isa->type = p + 5;
  745                 else if(cistrncmp(p, "port=", 5) == 0)
  746                         isa->port = strtoul(p+5, &p, 0);
  747                 else if(cistrncmp(p, "irq=", 4) == 0)
  748                         isa->irq = strtoul(p+4, &p, 0);
  749                 else if(cistrncmp(p, "dma=", 4) == 0)
  750                         isa->dma = strtoul(p+4, &p, 0);
  751                 else if(cistrncmp(p, "mem=", 4) == 0)
  752                         isa->mem = strtoul(p+4, &p, 0);
  753                 else if(cistrncmp(p, "size=", 5) == 0)
  754                         isa->size = strtoul(p+5, &p, 0);
  755                 else if(cistrncmp(p, "freq=", 5) == 0)
  756                         isa->freq = strtoul(p+5, &p, 0);
  757         }
  758         return 1;
  759 }
  760 
  761 int
  762 cistrcmp(char *a, char *b)
  763 {
  764         int ac, bc;
  765 
  766         for(;;){
  767                 ac = *a++;
  768                 bc = *b++;
  769         
  770                 if(ac >= 'A' && ac <= 'Z')
  771                         ac = 'a' + (ac - 'A');
  772                 if(bc >= 'A' && bc <= 'Z')
  773                         bc = 'a' + (bc - 'A');
  774                 ac -= bc;
  775                 if(ac)
  776                         return ac;
  777                 if(bc == 0)
  778                         break;
  779         }
  780         return 0;
  781 }
  782 
  783 int
  784 cistrncmp(char *a, char *b, int n)
  785 {
  786         unsigned ac, bc;
  787 
  788         while(n > 0){
  789                 ac = *a++;
  790                 bc = *b++;
  791                 n--;
  792 
  793                 if(ac >= 'A' && ac <= 'Z')
  794                         ac = 'a' + (ac - 'A');
  795                 if(bc >= 'A' && bc <= 'Z')
  796                         bc = 'a' + (bc - 'A');
  797 
  798                 ac -= bc;
  799                 if(ac)
  800                         return ac;
  801                 if(bc == 0)
  802                         break;
  803         }
  804 
  805         return 0;
  806 }
  807 
  808 /*
  809  *  put the processor in the halt state if we've no processes to run.
  810  *  an interrupt will get us going again.
  811  */
  812 void
  813 idlehands(void)
  814 {
  815         if(conf.nmach == 1)
  816                 halt();
  817 }

Cache object: 1e4d089e807ab005fae53ff6cbff02ab


[ 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.