|
|
1.1 root 1: /* machdep.c 4.36 81/05/09 */
2:
3: #include "../h/param.h"
4: #include "../h/systm.h"
5: #include "../h/dir.h"
6: #include "../h/user.h"
7: #include "../h/map.h"
8: #include "../h/reg.h"
9: #include "../h/mtpr.h"
10: #include "../h/clock.h"
11: #include "../h/pte.h"
12: #include "../h/vm.h"
13: #include "../h/lnode.h"
14: #include "../h/proc.h"
15: #include "../h/psl.h"
16: #include "../h/buf.h"
17: #include "../h/nexus.h"
18: #include "../h/ubavar.h"
19: #include "../h/ubareg.h"
20: #include "../h/cons.h"
21: #include "../h/reboot.h"
22: #include "../h/conf.h"
23: #include "../h/mem.h"
24: #include "../h/cpu.h"
25: #include "../h/inode.h"
26: #include "../h/file.h"
27: #include "../h/text.h"
28: #include "../h/callout.h"
29: #include "../h/cmap.h"
30: #include <frame.h>
31: #include "../h/rpb.h"
32: #include <time.h>
33:
34: int icode[] =
35: {
36: 0x9f19af9f, /* pushab [&"init",0]; pushab */
37: 0x02dd09af, /* "/etc/init"; pushl $2 */
38: 0xbc5c5ed0, /* movl sp,ap; chmk */
39: 0x2ffe110b, /* $exec; brb .; "/ */
40: 0x2f637465, /* etc/ */
41: 0x74696e69, /* init" */
42: 0x00000000, /* \0\0\0"; 0 */
43: 0x00000014, /* [&"init", */
44: 0x00000000, /* 0] */
45: };
46: int szicode = sizeof(icode);
47:
48: /*
49: * Declare these as initialized data so we can patch them.
50: */
51: int nbuf = 0;
52: int nswbuf = 0;
53:
54: /*
55: * Machine-dependent startup code
56: */
57: startup(firstaddr)
58: int firstaddr;
59: {
60: register int unixsize;
61: register unsigned i;
62: register struct pte *pte;
63: register caddr_t v;
64:
65: /*
66: * Initialize error message buffer (at end of core).
67: */
68: maxmem -= CLSIZE;
69: pte = msgbufmap;
70: for (i = 0; i < CLSIZE; i++)
71: *(int *)pte++ = PG_V | PG_KW | (maxmem + i);
72: mtpr(TBIA, 1);
73:
74: /*
75: * Good {morning,afternoon,evening,night}.
76: */
77: printf(version);
78:
79: /*
80: * First determine how many buffers are reasonable.
81: * Current alg is 32 per megabyte, with min of 32.
82: * We allocate 1/2 as many swap buffer headers as file i/o buffers.
83: */
84: if (nbuf == 0) {
85: nbuf = (32 * physmem) / btoc(1024*1024);
86: if (nbuf < 32)
87: nbuf = 32;
88: }
89: if (nswbuf == 0) {
90: nswbuf = (nbuf / 2) &~ 1; /* force even */
91: if (nswbuf > 256)
92: nswbuf = 256; /* sanity */
93: }
94: printf("real mem = %d nbuf = %d nswbuf = %d\n", ctob(maxmem),
95: nbuf, nswbuf);
96:
97: /*
98: * Allocate space for system data structures.
99: */
100: v = (caddr_t)(0x80000000 | (firstaddr * NBPG));
101: #define valloc(name, type, num) \
102: (name) = (type *)(v); (v) = (caddr_t)((name)+(num))
103: #define valloclim(name, type, num, lim) \
104: (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num)))
105: valloc(buffers, char, BUFSIZE*nbuf);
106: valloc(buf, struct buf, nbuf);
107: valloc(swbuf, struct buf, nswbuf);
108: valloc(swsize, short, nswbuf); /* note: nswbuf is even */
109: valloc(swpf, int, nswbuf);
110: valloclim(inode, struct inode, ninode, inodeNINODE);
111: valloclim(file, struct file, nfile, fileNFILE);
112: valloclim(proc, struct proc, nproc, procNPROC);
113: valloclim(text, struct text, ntext, textNTEXT);
114: valloclim(lnodes, struct kern_lnode, maxusers, lnodesMAXUSERS);
115: valloc(callout, struct callout, ncallout);
116: valloc(swapmap, struct map, nswapmap = nproc * 2);
117: valloc(argmap, struct map, ARGMAPSIZE);
118: valloc(kernelmap, struct map, nproc);
119:
120: /*
121: * Now allocate space for core map
122: */
123: ncmap = (physmem*NBPG - ((int)v &~ 0x80000000)) /
124: (NBPG*CLSIZE + sizeof (struct cmap));
125: valloclim(cmap, struct cmap, ncmap, ecmap);
126: if ((((int)(ecmap+1))&~0x80000000) > SYSPTSIZE*NBPG)
127: panic("sys pt too small");
128:
129: /*
130: * Clear allocated space, and make r/w entries
131: * for the space in the kernel map.
132: */
133: unixsize = btoc((int)(ecmap+1) &~ 0x80000000);
134: if (unixsize >= physmem - 8*UPAGES)
135: panic("no memory");
136: for (i = firstaddr; i < unixsize; i++) {
137: *(int *)(&Sysmap[i]) = PG_V | PG_KW | i;
138: clearseg(i);
139: }
140: mtpr(TBIA, 1);
141:
142: /*
143: * Initialize callouts
144: */
145: callfree = callout;
146: for (i = 1; i < ncallout; i++)
147: callout[i-1].c_next = &callout[i];
148:
149: /*
150: * Initialize memory allocator and swap
151: * and user page table maps.
152: *
153: * THE USER PAGE TABLE MAP IS CALLED ``kernelmap''
154: * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME.
155: */
156: meminit(unixsize, maxmem);
157: maxmem = freemem;
158: printf("avail mem = %d\n", ctob(maxmem));
159: rminit(kernelmap, USRPTSIZE, 1, "usrpt", nproc);
160:
161: /*
162: * Configure the system.
163: */
164: configure();
165:
166: /*
167: * Clear restart inhibit flags.
168: */
169: tocons(TXDB_CWSI);
170: tocons(TXDB_CCSI);
171: }
172:
173: /*
174: * set up a physical address
175: * into users virtual address space.
176: */
177: sysphys()
178: {
179:
180: if(!suser())
181: return;
182: u.u_error = EINVAL;
183: }
184:
185: /*
186: * Initialze the clock, based on the time base which is, e.g.
187: * from a filesystem. Base provides the time to within six months,
188: * and the time of year clock provides the rest.
189: */
190: clkinit(base)
191: time_t base;
192: {
193: register unsigned todr = mfpr(TODR);
194: long deltat;
195: int year = YRREF;
196: unsigned secyr;
197:
198: #ifdef MVAX
199: /*
200: * Get the MicroVAX-II's toy register.
201: * Convert it to the time format that the todr is
202: * normally kept in.
203: */
204: if( cpu == M_VAX ) {
205: todr = gettoy();
206: for (;;) {
207: secyr = SECYR;
208: if (LEAPYEAR(year))
209: secyr += SECDAY;
210: if (todr < secyr)
211: break;
212: todr -= secyr;
213: year++;
214: }
215: year = YRREF;
216: todr = TODRZERO + todr*100;
217: }
218: #endif MVAX
219: if (base < 5*SECYR) {
220: printf("WARNING: preposterous time in file system");
221: time = 6*SECYR + 186*SECDAY + SECDAY/2;
222: clkset();
223: goto check;
224: }
225: /*
226: * Have been told that VMS keeps time internally with base TODRZERO.
227: * If this is correct, then this routine and VMS should maintain
228: * the same date, and switching shouldn't be painful.
229: * (Unfortunately, VMS keeps local time, so when you run UNIX
230: * and VMS, VMS runs on GMT...).
231: */
232: if (todr < TODRZERO) {
233: printf("WARNING: todr too small");
234: time = base;
235: /*
236: * Believe the time in the file system for lack of
237: * anything better, resetting the TODR.
238: */
239: clkset();
240: goto check;
241: }
242: /*
243: * Sneak to within 6 month of the time in the filesystem,
244: * by starting with the time of the year suggested by the TODR,
245: * and advancing through succesive years. Adding the number of
246: * seconds in the current year takes us to the end of the current year
247: * and then around into the next year to the same position.
248: */
249: for (time = (todr-TODRZERO)/100; time < base-SECYR/2; time += SECYR) {
250: if (LEAPYEAR(year))
251: time += SECDAY;
252: year++;
253: }
254:
255: /*
256: * The hardware and software clocks are now in sync, so it is
257: * safe to call clkset() to get its side effect, which is to
258: * initialize yearbase.
259: */
260: clkset();
261:
262: /*
263: * See if we gained/lost two or more days;
264: * if so, assume something is amiss.
265: */
266: deltat = time - base;
267: if (deltat < 0)
268: deltat = -deltat;
269: if (deltat < 2*SECDAY)
270: return;
271: printf("WARNING: clock %s %d days",
272: time < base ? "lost" : "gained", deltat / SECDAY);
273: check:
274: printf(" -- CHECK AND RESET THE DATE!\n");
275: }
276:
277: /* Time in seconds from the epoch to the start of the current year */
278: time_t yearbase;
279:
280: /*
281: * Reset the TODR based on the time value; used when the TODR
282: * has a preposterous value and also when the time is reset
283: * by the stime system call. Also called when the TODR goes past
284: * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight)
285: * to wrap the TODR around.
286: *
287: * Side effect: yearbase is set appropriately.
288: */
289:
290: clkset()
291: {
292: int year = YRREF;
293: unsigned secyr;
294: unsigned yrtime = time;
295:
296: yearbase = 0;
297:
298: /*
299: * Whittle the time down to an offset in the current year,
300: * by subtracting off whole years as long as possible.
301: */
302: #ifdef MVAX
303: if( cpu == M_VAX ) {
304: settoy( yrtime );
305: return;
306: }
307: #endif MVAX
308: for (;;) {
309: secyr = SECYR;
310: if (LEAPYEAR(year))
311: secyr += SECDAY;
312: if (yrtime < secyr)
313: break;
314: yrtime -= secyr;
315: yearbase += secyr;
316: year++;
317: }
318: mtpr(TODR, TODRZERO + yrtime*100);
319: }
320:
321: #ifdef MVAX
322: /*
323: * This routine sets the time of year clock on the MicroVAX-II.
324: */
325: static int dmsize[12] =
326: { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
327:
328: #define dysize(A) (((A)%4)? 365: 366)
329:
330: gettoy()
331: {
332: int i, sec=0;
333: struct tm tm;
334: int s;
335: register struct qb_regs *qb_regs = (struct qb_regs *)nexus;
336:
337: /*
338: * Copy the toy register contents into tm so that we can
339: * work with. The toy must be completely read in 2.5 millisecs.
340: *
341: *
342: * Wait for update in progress to be done.
343: */
344: while( qb_regs->qb_toycsra & QBT_UIP )
345: ;
346: s = spl7();
347: tm.tm_sec = qb_regs->qb_toysecs;
348: tm.tm_min = qb_regs->qb_toymins;
349: tm.tm_hour = qb_regs->qb_toyhours;
350: tm.tm_mday = qb_regs->qb_toyday;
351: tm.tm_mon = qb_regs->qb_toymonth;
352: tm.tm_year = qb_regs->qb_toyyear;
353: splx( s );
354: /*
355: * sanity check the clock
356: */
357: if( tm.tm_sec < 0 || tm.tm_sec >59 ||
358: tm.tm_min < 0 || tm.tm_min > 59 ||
359: tm.tm_hour < 0 || tm.tm_hour > 23 ||
360: tm.tm_mday < 1 || tm.tm_mday > 31 ||
361: tm.tm_mon < 1 || tm.tm_mon >12 ||
362: tm.tm_year < 70 || tm.tm_year > 99 )
363: return 0;
364: /*
365: * Added up the seconds since the epoch
366: */
367: tm.tm_year += 1900;
368: for (i = 1970; i < tm.tm_year; i++)
369: sec += dysize(i);
370: /*
371: * Leap tm.tm_year
372: */
373: if (dysize(tm.tm_year) == 366 && tm.tm_mon >= 3)
374: sec++;
375: /*
376: * Do the current tm.tm_year
377: */
378: for( i=0 ; i < tm.tm_mon-1 ; i++ )
379: sec += dmsize[i];
380: sec += tm.tm_mday-1;
381: sec = 24*sec + tm.tm_hour;
382: sec = 60*sec + tm.tm_min;
383: sec = 60*sec + tm.tm_sec;
384: return (sec);
385: }
386:
387: /*
388: * This routine is used to set the MicroVAX-II toy register.
389: */
390: settoy( tim )
391: {
392: register int d0, d1;
393: long hms, day;
394: register int *tp;
395: struct tm xtime;
396: int s;
397: register struct qb_regs *qb_regs = (struct qb_regs *)nexus;
398:
399: /*
400: * break initial number into days
401: */
402: hms = tim % 86400;
403: day = tim / 86400;
404: if (hms<0) {
405: hms += 86400;
406: day -= 1;
407: }
408: tp = (int *)&xtime;
409:
410: /*
411: * generate hours:minutes:seconds
412: */
413: *tp++ = hms%60;
414: d1 = hms/60;
415: *tp++ = d1%60;
416: d1 /= 60;
417: *tp++ = d1;
418:
419: /*
420: * year number
421: */
422: if (day>=0) for(d1=70; day >= dysize(d1); d1++)
423: day -= dysize(d1);
424: else for (d1=70; day<0; d1--)
425: day += dysize(d1-1);
426: xtime.tm_year = d1;
427: xtime.tm_yday = d0 = day;
428:
429: /*
430: * generate month
431: */
432:
433: if (dysize(d1)==366)
434: dmsize[1] = 29;
435: for(d1=0; d0 >= dmsize[d1]; d1++)
436: d0 -= dmsize[d1];
437: dmsize[1] = 28;
438: *tp++ = d0+1;
439: *tp++ = d1+1;
440: xtime.tm_isdst = 0;
441: /*
442: * Copy the time into the toy.
443: */
444: qb_regs->qb_toycsrb = QBT_SETUP;
445: s = spl7();
446: qb_regs->qb_toysecs = xtime.tm_sec;
447: qb_regs->qb_toymins = xtime.tm_min;
448: qb_regs->qb_toyhours = xtime.tm_hour;
449: qb_regs->qb_toyday = xtime.tm_mday;
450: qb_regs->qb_toymonth = xtime.tm_mon;
451: qb_regs->qb_toyyear = xtime.tm_year;
452: splx( s );
453: /*
454: * Start the clock again.
455: */
456: qb_regs->qb_toycsra = QBT_SETA;
457: qb_regs->qb_toycsrb = QBT_SETB;
458: }
459: #endif MVAX
460:
461:
462: unsigned trimprof[3];
463:
464: /*
465: * Tweak the rate of the software clock
466: * to track the hardware clock accurately.
467: * This routine is called once a second,
468: * immediately after 'time' has been incremented.
469: */
470: clktrim()
471: {
472: register long delta;
473: register long incr;
474: register unsigned todr = mfpr(TODR);
475:
476: #ifdef MVAX
477: /*
478: * Get the MicroVAX-II's toy register.
479: * Convert it to the time format that the todr is
480: * normally kept in.
481: */
482: if( cpu == M_VAX ) {
483: int year = YRREF;
484: unsigned secyr;
485:
486: todr = gettoy();
487: for (;;) {
488: secyr = SECYR;
489: if (LEAPYEAR(year))
490: secyr += SECDAY;
491: if (todr < secyr)
492: break;
493: todr -= secyr;
494: year++;
495: }
496: todr = TODRZERO + todr*100;
497: }
498: #endif MVAX
499:
500: delta = 100 * (time - yearbase) - todr + TODRZERO;
501:
502: /*
503: * If delta > 0, the software clock is running fast.
504: * It is measured in centiseconds, the units of the
505: * hardware clock. If delta is non-zero, we will
506: * stretch or shrink each tick by 111 microseconds
507: * from the nominal, for a drift of about 2/3 of a
508: * percent. This should result by changing delta by
509: * about 2/3 each second, thus making it very unlikely
510: * that we will overshoot delta == 0. On the other
511: * hand, we will be able to absorb 16 minutes of drift
512: * each day. We also count each kind of tweak.
513: */
514:
515: incr = -16667; /* -1/60 of a second, in microseconds */
516: if (delta > 0) {
517: incr -= 111;
518: trimprof[2]++;
519: } else if (delta < 0) {
520: incr += 111;
521: trimprof[0]++;
522: } else {
523: trimprof[1]++;
524: }
525:
526: /* tell the hardware about it */
527: /* unfortunately this does nothing on the MVAX */
528: mtpr (NICR, incr);
529: }
530:
531: /*
532: * This system call sets the time of year clock without touching
533: * the software clock. It returns the previous clock value. If
534: * the argument is zero or the caller is not the super-user, it
535: * does not change the clock.
536: */
537: settod()
538: {
539: register struct a {
540: long unsigned tod;
541: } *uap;
542: register unsigned todr = mfpr(TODR);
543:
544: #ifdef MVAX
545: /*
546: * Get the MicroVAX-II's toy register.
547: * Convert it to the time format that the todr is
548: * normally kept in.
549: */
550: if( cpu == M_VAX ) {
551: int year = YRREF;
552: unsigned secyr;
553:
554: todr = gettoy();
555: for (;;) {
556: secyr = SECYR;
557: if (LEAPYEAR(year))
558: secyr += SECDAY;
559: if (todr < secyr)
560: break;
561: todr -= secyr;
562: year++;
563: }
564: todr = TODRZERO + todr*100;
565: }
566: #endif MVAX
567:
568: uap = (struct a *) u.u_ap;
569: u.u_r.r_val1 = todr;
570: #ifdef MVAX
571: if (uap->tod != 0 && suser() && cpu == M_VAX) {
572: settoy(uap->tod);
573: return;
574: }
575: #endif MVAX
576: if (uap->tod != 0 && suser())
577: mtpr (TODR, uap->tod);
578: }
579:
580: /*
581: * Return the difference (in microseconds)
582: * between the current time and a previous
583: * time as represented by the arguments.
584: * If there is a pending clock interrupt
585: * which has not been serviced due to high
586: * ipl, return error code.
587: */
588: vmtime(otime, olbolt, oicr)
589: register int otime, olbolt, oicr;
590: {
591:
592: if (mfpr(ICCS)&ICCS_INT)
593: return(-1);
594: else
595: return(((time-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr);
596: }
597:
598: /*
599: * Send an interrupt to process
600: *
601: * SHOULD CHANGE THIS TO PASS ONE MORE WORK SO THAT ALL INFORMATION
602: * PROVIDED BY HARDWARE IS AVAILABLE TO THE USER PROCESS.
603: */
604: sendsig(p, n)
605: int (*p)();
606: {
607: register int *usp, *regs;
608:
609: regs = u.u_ar0;
610: usp = (int *)regs[SP];
611: usp -= 5;
612: if ((int)usp <= USRSTACK - ctob(u.u_ssize))
613: (void) grow((unsigned)usp);
614: ; /* Avoid asm() label botch */
615: #ifndef lint
616: asm("probew $3,$20,(r11)");
617: asm("beql bad");
618: #else
619: if (useracc((caddr_t)usp, 0x20, 1))
620: goto bad;
621: #endif
622: *usp++ = n;
623: if (n == SIGILL || n == SIGFPE) {
624: *usp++ = u.u_code;
625: u.u_code = 0;
626: } else
627: *usp++ = 0;
628: *usp++ = (int)p;
629: *usp++ = regs[PC];
630: *usp++ = regs[PS];
631: regs[SP] = (int)(usp - 5);
632: regs[PS] &= ~(PSL_CM|PSL_FPD);
633: regs[PC] = (int)u.u_pcb.pcb_sigc;
634: return;
635:
636: asm("bad:");
637: bad:
638: /*
639: * Process has trashed its stack; give it an illegal
640: * instruction to halt it in its tracks.
641: */
642: u.u_signal[SIGILL] = SIG_DFL;
643: u.u_procp->p_siga0 &= ~(1<<(SIGILL-1));
644: u.u_procp->p_siga1 &= ~(1<<(SIGILL-1));
645: psignal(u.u_procp, SIGILL);
646: }
647:
648: int userreg[] = {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC};
649:
650: dorti()
651: {
652: struct frame frame;
653: register int sp;
654: register int reg, mask;
655:
656: (void) copyin((caddr_t)u.u_ar0[FP], (caddr_t)&frame, sizeof (frame));
657: sp = u.u_ar0[FP] + sizeof (frame);
658: u.u_ar0[PC] = frame.fr_savpc;
659: u.u_ar0[FP] = frame.fr_savfp;
660: u.u_ar0[AP] = frame.fr_savap;
661: mask = frame.fr_mask;
662: for (reg = 0; reg <= 11; reg++) {
663: if (mask&1) {
664: u.u_ar0[userreg[reg]] = fuword((caddr_t)sp);
665: sp += 4;
666: }
667: mask >>= 1;
668: }
669: sp += frame.fr_spa;
670: u.u_ar0[PS] = (u.u_ar0[PS] & 0xffff0000) | frame.fr_psw;
671: if (frame.fr_s)
672: sp += 4 + 4 * (fuword((caddr_t)sp) & 0xff);
673: /* phew, now the rei */
674: u.u_ar0[PC] = fuword((caddr_t)sp);
675: sp += 4;
676: u.u_ar0[PS] = fuword((caddr_t)sp);
677: sp += 4;
678: u.u_ar0[PS] |= PSL_USERSET;
679: u.u_ar0[PS] &= ~PSL_USERCLR;
680: u.u_ar0[SP] = (int)sp;
681: }
682:
683: /*
684: * Invalidate single all pte's in a cluster
685: */
686: tbiscl(v)
687: unsigned v;
688: {
689: register caddr_t addr; /* must be first reg var */
690: register int i;
691:
692: asm(".set TBIS,58");
693: addr = ptob(v);
694: for (i = 0; i < CLSIZE; i++) {
695: #ifdef lint
696: mtpr(TBIS, addr);
697: #else
698: asm("mtpr r11,$TBIS");
699: #endif
700: addr += NBPG;
701: }
702: }
703:
704: int waittime = -1;
705:
706: boot(arghowto)
707: int arghowto;
708: {
709: register int howto; /* r11 == how to boot */
710: register int devtype; /* r10 == major of root dev */
711:
712: howto = arghowto;
713: if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) {
714: waittime = 0;
715: update();
716: printf("syncing disks... ");
717: while (++waittime <= 5)
718: sleep((caddr_t)&lbolt, PZERO);
719: printf("done\n");
720: }
721: splx(0x1f); /* extreme priority */
722: devtype = major(rootdev);
723: if (howto&RB_HALT) {
724: #ifdef MVAX
725: if( cpu == M_VAX ) {
726: ((struct qb_regs *)nexus)->qb_cpmbx = RB_HALTMD;
727: for (;;)
728: asm ("halt");
729: }
730: #endif MVAX
731: printf("halting (in tight loop); hit\n\t^P\n\tHALT\n\n");
732: mtpr(IPL, 0x1f);
733: for (;;)
734: ;
735: } else {
736: if ((howto & RB_PANIC) != 0)
737: doadump();
738: tocons(TXDB_BOOT);
739: }
740: #if defined(VAX750) || defined(VAX7ZZ) || defined(MVAX)
741: if (cpu != VAX_780)
742: { asm("movl r11,r5"); } /* boot flags go in r5 */
743: #endif
744: #ifdef MVAX
745: if( cpu == M_VAX )
746: ((struct qb_regs *)nexus)->qb_cpmbx = RB_REBOOT;
747: #endif
748: for (;;)
749: asm("halt");
750: /*NOTREACHED*/
751: }
752:
753: tocons(c)
754: {
755:
756: while ((mfpr(TXCS)&TXCS_RDY) == 0)
757: continue;
758: mtpr(TXDB, c);
759: }
760:
761: /*
762: * Doadump comes here after turning off memory management and
763: * getting on the dump stack, either when called above, or by
764: * the auto-restart code.
765: */
766: dumpsys()
767: {
768: int dstat;
769: rpb.rp_flag = 1;
770: if ((minor(dumpdev)&07) != 1)
771: return;
772: printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
773: printf("dump ");
774: switch (dstat = (*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
775:
776: case ENXIO:
777: printf("device bad\n");
778: break;
779:
780: case EFAULT:
781: printf("device not ready\n");
782: break;
783:
784: case EINVAL:
785: printf("area improper\n");
786: break;
787:
788: case EIO:
789: printf("i/o error\n");
790: break;
791:
792: default:
793: printf("unexpected error %d\n", dstat);
794: break;
795:
796: case 0:
797: printf("succeeded\n");
798: break;
799: }
800: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.