|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Chris Torek. ! 7: * ! 8: * Redistribution and use in source and binary forms are permitted ! 9: * provided that the above copyright notice and this paragraph are ! 10: * duplicated in all such forms and that any documentation, ! 11: * advertising materials, and other materials related to such ! 12: * distribution and use acknowledge that the software was developed ! 13: * by the University of California, Berkeley. The name of the ! 14: * University may not be used to endorse or promote products derived ! 15: * from this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 17: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 18: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)kdb.c 7.6 (Berkeley) 7/9/88 ! 21: */ ! 22: ! 23: /* ! 24: * KDB50/MSCP device driver ! 25: */ ! 26: ! 27: /* ! 28: * TODO ! 29: * rethink BI software interface ! 30: * write bad block forwarding code ! 31: */ ! 32: ! 33: #include "kra.h" /* XXX */ ! 34: ! 35: #define DRIVENAMES "kra" /* XXX */ ! 36: ! 37: #if NKDB > 0 ! 38: ! 39: /* ! 40: * CONFIGURATION OPTIONS. The next three defines are tunable -- tune away! ! 41: * ! 42: * NRSPL2 and NCMDL2 control the number of response and command ! 43: * packets respectively. They may be any value from 0 to 7, though ! 44: * setting them higher than 5 is unlikely to be of any value. ! 45: * If you get warnings about your command ring being too small, ! 46: * try increasing the values by one. ! 47: * ! 48: * MAXUNIT controls the maximum slave number (and hence number of drives ! 49: * per controller) we are prepared to handle. ! 50: */ ! 51: #define NRSPL2 5 /* log2 number of response packets */ ! 52: #define NCMDL2 5 /* log2 number of command packets */ ! 53: #define MAXUNIT 8 /* maximum allowed unit number */ ! 54: ! 55: #include "param.h" ! 56: #include "systm.h" ! 57: #include "malloc.h" ! 58: #include "map.h" ! 59: #include "buf.h" ! 60: #include "conf.h" ! 61: #include "dir.h" ! 62: #include "user.h" ! 63: #include "proc.h" ! 64: #include "vm.h" ! 65: #include "dkstat.h" ! 66: #include "cmap.h" ! 67: #include "syslog.h" ! 68: #include "kernel.h" ! 69: ! 70: #define NRSP (1 << NRSPL2) ! 71: #define NCMD (1 << NCMDL2) ! 72: ! 73: #include "../vax/pte.h" ! 74: #include "../vax/cpu.h" ! 75: #include "../vax/mscp.h" ! 76: #include "../vax/mscpvar.h" ! 77: #include "../vax/mtpr.h" ! 78: ! 79: #include "bireg.h" ! 80: #include "kdbreg.h" ! 81: ! 82: #include "../vaxuba/ubavar.h" ! 83: ! 84: /* ! 85: * Conversions from kernel virtual to physical and page table addresses. ! 86: * PHYS works only for kernel text and primary (compile time) data addresses. ! 87: */ ! 88: #define PHYS(cast, addr) \ ! 89: ((cast) ((int)(addr) & 0x7fffffff)) ! 90: ! 91: /* ! 92: * KDB variables, per controller. ! 93: */ ! 94: struct kdbinfo { ! 95: /* software info, per KDB */ ! 96: struct kdb_regs *ki_kdb; /* KDB registers */ ! 97: struct kdb_regs *ki_physkdb; /* phys address of KDB registers */ ! 98: short ki_state; /* KDB50 state; see below */ ! 99: short ki_flags; /* flags; see below */ ! 100: int ki_micro; /* microcode revision */ ! 101: short ki_vec; /* scb vector offset */ ! 102: short ki_wticks; /* watchdog timer ticks */ ! 103: ! 104: /* ! 105: * KDB PTEs must be contiguous. Some I/O is done on addresses ! 106: * for which this is true (PTEs in Sysmap and Usrptmap), but ! 107: * other transfers may have PTEs that are scattered in physical ! 108: * space. Ki_map maps a physically contiguous PTE space used ! 109: * for these transfers. ! 110: */ ! 111: #define KI_MAPSIZ (NCMD + 2) ! 112: struct map *ki_map; /* resource map */ ! 113: #define KI_PTES 256 ! 114: struct pte ki_pte[KI_PTES]; /* contiguous PTE space */ ! 115: long ki_ptephys; /* phys address of &ki_pte[0] */ ! 116: ! 117: struct mscp_info ki_mi; /* MSCP info (per mscpvar.h) */ ! 118: struct buf ki_tab; /* controller queue */ ! 119: ! 120: /* stuff read and written by hardware */ ! 121: struct kdbca ki_ca; /* communications area */ ! 122: struct mscp ki_rsp[NRSP]; /* response packets */ ! 123: struct mscp ki_cmd[NCMD]; /* command packets */ ! 124: } kdbinfo[NKDB]; ! 125: ! 126: #define ki_ctlr ki_mi.mi_ctlr ! 127: ! 128: /* ! 129: * Controller states ! 130: */ ! 131: #define ST_IDLE 0 /* uninitialised */ ! 132: #define ST_STEP1 1 /* in `STEP 1' */ ! 133: #define ST_STEP2 2 /* in `STEP 2' */ ! 134: #define ST_STEP3 3 /* in `STEP 3' */ ! 135: #define ST_SETCHAR 4 /* in `Set Controller Characteristics' */ ! 136: #define ST_RUN 5 /* up and running */ ! 137: ! 138: /* ! 139: * Flags ! 140: */ ! 141: #define KDB_ALIVE 0x01 /* this KDB50 exists */ ! 142: #define KDB_GRIPED 0x04 /* griped about cmd ring too small */ ! 143: #define KDB_INSLAVE 0x08 /* inside kdbslave() */ ! 144: #define KDB_DOWAKE 0x10 /* wakeup when ctlr init done */ ! 145: ! 146: struct kdbstats kdbstats; /* statistics */ ! 147: ! 148: /* ! 149: * Device to unit number and partition: ! 150: */ ! 151: #define UNITSHIFT 3 ! 152: #define UNITMASK 7 ! 153: #define kdbunit(dev) (minor(dev) >> UNITSHIFT) ! 154: #define kdbpart(dev) (minor(dev) & UNITMASK) ! 155: ! 156: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ ! 157: /* THESE SHOULD BE SHARED WITH uda.c (but not yet) */ ! 158: struct size { ! 159: daddr_t nblocks; ! 160: daddr_t blkoff; ! 161: } kra81_sizes[8] = { ! 162: #ifdef MARYLAND ! 163: 67832, 0, /* A=cyl 0 thru 94 + 2 sectors */ ! 164: 67828, 67832, /* B=cyl 95 thru 189 - 2 sectors */ ! 165: -1, 0, /* C=cyl 0 thru 1247 */ ! 166: -1, 135660, /* D=cyl 190 thru 1247 */ ! 167: 449466, 49324, /* E xxx */ ! 168: 64260, 498790, /* F xxx */ ! 169: 328022, 563050, /* G xxx */ ! 170: 0, 0, ! 171: #else ! 172: 15884, 0, /* a */ ! 173: 33440, 15884, /* b */ ! 174: -1, 0, /* c */ ! 175: -1, 49324, /* d */ ! 176: 449466, 49324, /* e */ ! 177: 64260, 498790, /* f */ ! 178: 328022, 563050, /* g */ ! 179: 0, 0, ! 180: #endif ! 181: }, kra80_sizes[8] = { ! 182: 15884, 0, /* A=blk 0 thru 15883 */ ! 183: 33440, 15884, /* B=blk 15884 thru 49323 */ ! 184: -1, 0, /* C=blk 0 thru end */ ! 185: 0, 0, ! 186: 0, 0, ! 187: 0, 0, ! 188: 82080, 49324, /* G=blk 49324 thru 131403 */ ! 189: -1, 131404, /* H=blk 131404 thru end */ ! 190: }, kra60_sizes[8] = { ! 191: 15884, 0, /* A=blk 0 thru 15883 */ ! 192: 33440, 15884, /* B=blk 15884 thru 49323 */ ! 193: -1, 0, /* C=blk 0 thru end */ ! 194: -1, 49324, /* D=blk 49324 thru end */ ! 195: 0, 0, ! 196: 0, 0, ! 197: 82080, 49324, /* G=blk 49324 thru 131403 */ ! 198: -1, 131404, /* H=blk 131404 thru end */ ! 199: }; ! 200: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ ! 201: ! 202: /* ! 203: * Drive type index decoding table. `ut_name' is null iff the ! 204: * type is not known. ! 205: */ ! 206: struct kdbtypes { ! 207: char *ut_name; /* drive type name */ ! 208: struct size *ut_sizes; /* partition tables */ ! 209: } kdbtypes[] = { ! 210: NULL, NULL, ! 211: "ra80", kra80_sizes, /* 1 = ra80 */ ! 212: NULL, NULL, ! 213: NULL, NULL, ! 214: "ra60", kra60_sizes, /* 4 = ra60 */ ! 215: "ra81", kra81_sizes, /* 5 = ra81 */ ! 216: }; ! 217: ! 218: #define NTYPES 6 ! 219: ! 220: /* ! 221: * Definition of the driver for autoconf and generic MSCP code. ! 222: * SOME OF THIS IS BOGUS (must fix config) ! 223: */ ! 224: ! 225: #ifdef notdef /* not when driver is for kra disks */ ! 226: /* ! 227: * Some of these variables (per-drive stuff) are shared ! 228: * with the UDA50 code (why not, they are the same drives). ! 229: * N.B.: kdbdinfo must not be shared. ! 230: */ ! 231: #define kdbutab udautab /* shared */ ! 232: #define kdbslavereply udaslavereply /* shared */ ! 233: #endif ! 234: ! 235: int kdbprobe(); /* XXX */ ! 236: int kdbslave(), kdbattach(); ! 237: ! 238: int kdbdgram(), kdbctlrdone(), kdbunconf(), kdbiodone(); ! 239: int kdbonline(), kdbgotstatus(), kdbioerror(); ! 240: ! 241: struct uba_device *kdbdinfo[NKRA]; /* uba_device indeed! */ ! 242: struct buf kdbutab[NKRA]; /* per drive transfer queue */ ! 243: ! 244: u_short kdbstd[] = { 0 }; /* XXX */ ! 245: struct uba_driver kdbdriver = /* XXX */ ! 246: { kdbprobe, kdbslave, kdbattach, 0, kdbstd, DRIVENAMES, kdbdinfo, "kdb" }; ! 247: ! 248: struct mscp_driver kdbmscpdriver = ! 249: { MAXUNIT, NKRA, UNITSHIFT, kdbutab, (struct disklabel *)0, kdbdinfo, ! 250: kdbdgram, kdbctlrdone, kdbunconf, kdbiodone, ! 251: kdbonline, kdbgotstatus, NULL, kdbioerror, NULL, ! 252: "kdb", DRIVENAMES }; ! 253: ! 254: /* ! 255: * Miscellaneous private variables. ! 256: */ ! 257: char kdbsr_bits[] = KDBSR_BITS; ! 258: ! 259: struct uba_device *kdbip[NKDB][MAXUNIT]; ! 260: /* inverting pointers: ctlr & unit => `Unibus' ! 261: device pointer */ ! 262: ! 263: daddr_t ra_dsize[NKRA]; /* drive sizes, from on line end packets */ ! 264: ! 265: struct mscp kdbslavereply; /* get unit status response packet, set ! 266: for kdbslave by kdbunconf, via kdbintr */ ! 267: ! 268: int kdbwstart, kdbwatch(); /* watchdog timer */ ! 269: int wakeup(); ! 270: ! 271: /* ! 272: * If kdbprobe is called, return 0 to keep Unibus code from attempting ! 273: * to use this device. XXX rethink ! 274: */ ! 275: /* ARGSUSED */ ! 276: kdbprobe(reg, ctlr) ! 277: caddr_t reg; ! 278: int ctlr; ! 279: { ! 280: ! 281: return (0); ! 282: } ! 283: ! 284: /* ! 285: * Configure in a KDB50 controller. ! 286: */ ! 287: kdbconfig(kdbnum, va, pa, vec) ! 288: int kdbnum; ! 289: struct biiregs *va, *pa; ! 290: int vec; ! 291: { ! 292: register struct kdbinfo *ki; ! 293: #define mi (&ki->ki_mi) ! 294: ! 295: #ifdef lint ! 296: extern int (*kdbint0[])(); ! 297: ! 298: (*kdbint0[0])(0); /* this is a config botch */ ! 299: kdbintr(0); ! 300: #endif ! 301: ! 302: /* ! 303: * Set up local KDB status. ! 304: */ ! 305: ki = &kdbinfo[kdbnum]; ! 306: ki->ki_kdb = (struct kdb_regs *)va; ! 307: ki->ki_physkdb = (struct kdb_regs *)pa; ! 308: ki->ki_vec = vec; ! 309: ki->ki_map = ! 310: (struct map *)malloc((u_long)(KI_MAPSIZ * sizeof(struct map)), ! 311: M_DEVBUF, M_NOWAIT); ! 312: if (ki->ki_map == NULL) { ! 313: printf("kdb%d: cannot get memory for ptes\n", kdbnum); ! 314: return; ! 315: } ! 316: ki->ki_ptephys = PHYS(long, ki->ki_pte); /* kvtophys(ki->ki_pte) */ ! 317: ki->ki_flags = KDB_ALIVE; ! 318: ! 319: /* THE FOLLOWING IS ONLY NEEDED TO CIRCUMVENT A BUG IN rminit */ ! 320: bzero((caddr_t)ki->ki_map, KI_MAPSIZ * sizeof(struct map)); ! 321: ! 322: rminit(ki->ki_map, (long)KI_PTES, (long)1, "kdb", KI_MAPSIZ); ! 323: ! 324: /* ! 325: * Set up the generic MSCP structures. ! 326: */ ! 327: mi->mi_md = &kdbmscpdriver; ! 328: mi->mi_ctlr = kdbnum; /* also sets ki->ki_ctlr */ ! 329: mi->mi_tab = &ki->ki_tab; ! 330: mi->mi_ip = kdbip[kdbnum]; ! 331: mi->mi_cmd.mri_size = NCMD; ! 332: mi->mi_cmd.mri_desc = ki->ki_ca.ca_cmddsc; ! 333: mi->mi_cmd.mri_ring = ki->ki_cmd; ! 334: mi->mi_rsp.mri_size = NRSP; ! 335: mi->mi_rsp.mri_desc = ki->ki_ca.ca_rspdsc; ! 336: mi->mi_rsp.mri_ring = ki->ki_rsp; ! 337: mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab; ! 338: #undef mi ! 339: } ! 340: ! 341: /* ! 342: * Find a slave. ! 343: * Note that by the time kdbslave is called, the interrupt vector ! 344: * for the KDB50 has been set up (so that kdbunconf() will be called). ! 345: */ ! 346: kdbslave(ui) ! 347: register struct uba_device *ui; ! 348: { ! 349: register struct kdbinfo *ki; ! 350: register struct mscp *mp; ! 351: int next = 0, type, timeout, tries, i; ! 352: ! 353: #ifdef lint ! 354: i = 0; i = i; ! 355: #endif ! 356: /* ! 357: * Make sure the controller is fully initialised, by waiting ! 358: * for it if necessary. ! 359: */ ! 360: ki = &kdbinfo[ui->ui_ctlr]; ! 361: if (ki->ki_state == ST_RUN) ! 362: goto findunit; ! 363: tries = 0; ! 364: again: ! 365: if (kdbinit(ki)) ! 366: return (0); ! 367: timeout = todr() + 1000; /* 10 seconds */ ! 368: while (todr() < timeout) ! 369: if (ki->ki_state == ST_RUN) /* made it */ ! 370: goto findunit; ! 371: if (++tries < 2) ! 372: goto again; ! 373: printf("kdb%d: controller hung\n", ki->ki_ctlr); ! 374: return (0); ! 375: ! 376: /* ! 377: * The controller is all set; go find the unit. Grab an ! 378: * MSCP packet and send out a Get Unit Status command, with ! 379: * the `next unit' modifier if we are looking for a generic ! 380: * unit. We set the `in slave' flag so that kdbunconf() ! 381: * knows to copy the response to `kdbslavereply'. ! 382: */ ! 383: findunit: ! 384: kdbslavereply.mscp_opcode = 0; ! 385: ki->ki_flags |= KDB_INSLAVE; ! 386: if ((mp = mscp_getcp(&ki->ki_mi, MSCP_DONTWAIT)) == NULL) ! 387: panic("kdbslave"); /* `cannot happen' */ ! 388: mp->mscp_opcode = M_OP_GETUNITST; ! 389: if (ui->ui_slave == '?') { ! 390: mp->mscp_unit = next; ! 391: mp->mscp_modifier = M_GUM_NEXTUNIT; ! 392: } else { ! 393: mp->mscp_unit = ui->ui_slave; ! 394: mp->mscp_modifier = 0; ! 395: } ! 396: *mp->mscp_addr |= MSCP_OWN | MSCP_INT; ! 397: i = ki->ki_kdb->kdb_ip; /* initiate polling */ ! 398: mp = &kdbslavereply; ! 399: timeout = todr() + 1000; ! 400: while (todr() < timeout) ! 401: if (mp->mscp_opcode) ! 402: goto gotit; ! 403: printf("kdb%d: no response to Get Unit Status request\n", ! 404: ki->ki_ctlr); ! 405: ki->ki_flags &= ~KDB_INSLAVE; ! 406: return (0); ! 407: ! 408: gotit: ! 409: ki->ki_flags &= ~KDB_INSLAVE; ! 410: ! 411: /* ! 412: * Got a slave response. If the unit is there, use it. ! 413: */ ! 414: switch (mp->mscp_status & M_ST_MASK) { ! 415: ! 416: case M_ST_SUCCESS: /* worked */ ! 417: case M_ST_AVAILABLE: /* found another drive */ ! 418: break; /* use it */ ! 419: ! 420: case M_ST_OFFLINE: ! 421: /* ! 422: * Figure out why it is off line. It may be because ! 423: * it is nonexistent, or because it is spun down, or ! 424: * for some other reason. ! 425: */ ! 426: switch (mp->mscp_status & ~M_ST_MASK) { ! 427: ! 428: case M_OFFLINE_UNKNOWN: ! 429: /* ! 430: * No such drive, and there are none with ! 431: * higher unit numbers either, if we are ! 432: * using M_GUM_NEXTUNIT. ! 433: */ ! 434: return (0); ! 435: ! 436: case M_OFFLINE_UNMOUNTED: ! 437: /* ! 438: * The drive is not spun up. Use it anyway. ! 439: * ! 440: * N.B.: this seems to be a common occurrance ! 441: * after a power failure. The first attempt ! 442: * to bring it on line seems to spin it up ! 443: * (and thus takes several minutes). Perhaps ! 444: * we should note here that the on-line may ! 445: * take longer than usual. ! 446: */ ! 447: break; ! 448: ! 449: default: ! 450: /* ! 451: * In service, or something else equally unusable. ! 452: */ ! 453: printf("kdb%d: unit %d off line:", ki->ki_ctlr, ! 454: mp->mscp_unit); ! 455: mscp_printevent(mp); ! 456: goto try_another; ! 457: } ! 458: break; ! 459: ! 460: default: ! 461: printf("kdb%d: unable to get unit status:", ki->ki_ctlr); ! 462: mscp_printevent(mp); ! 463: return (0); ! 464: } ! 465: ! 466: /* ! 467: * Does this ever happen? What (if anything) does it mean? ! 468: */ ! 469: if (mp->mscp_unit < next) { ! 470: printf("kdb%d: unit %d, next %d\n", ! 471: ki->ki_ctlr, mp->mscp_unit, next); ! 472: return (0); ! 473: } ! 474: ! 475: if (mp->mscp_unit >= MAXUNIT) { ! 476: printf("kdb%d: cannot handle unit number %d (max is %d)\n", ! 477: ki->ki_ctlr, mp->mscp_unit, MAXUNIT - 1); ! 478: return (0); ! 479: } ! 480: ! 481: /* ! 482: * See if we already handle this drive. ! 483: * (Only likely if ui->ui_slave=='?'.) ! 484: */ ! 485: if (kdbip[ki->ki_ctlr][mp->mscp_unit] != NULL) ! 486: goto try_another; ! 487: ! 488: /* ! 489: * Make sure we know about this kind of drive. ! 490: * Others say we should treat unknowns as RA81s; I am ! 491: * not sure this is safe. ! 492: */ ! 493: type = mp->mscp_guse.guse_drivetype; ! 494: if (type >= NTYPES || kdbtypes[type].ut_name == 0) { ! 495: register long id = mp->mscp_guse.guse_mediaid; ! 496: ! 497: printf("kdb%d: unit %d: media ID `", ki->ki_ctlr, ! 498: mp->mscp_unit); ! 499: printf("%c%c %c%c%c%d", ! 500: MSCP_MID_CHAR(4, id), MSCP_MID_CHAR(3, id), ! 501: MSCP_MID_CHAR(2, id), MSCP_MID_CHAR(1, id), ! 502: MSCP_MID_CHAR(0, id), MSCP_MID_NUM(id)); ! 503: printf("' is of unknown type %d; ignored\n", type); ! 504: try_another: ! 505: if (ui->ui_slave != '?') ! 506: return (0); ! 507: next = mp->mscp_unit + 1; ! 508: goto findunit; ! 509: } ! 510: ! 511: /* ! 512: * Voila! ! 513: */ ! 514: ui->ui_type = type; ! 515: ui->ui_flags = 0; /* not on line, nor anything else */ ! 516: ui->ui_slave = mp->mscp_unit; ! 517: return (1); ! 518: } ! 519: ! 520: /* ! 521: * Attach a found slave. Make sure the watchdog timer is running. ! 522: * If this disk is being profiled, fill in the `mspw' value (used by ! 523: * what?). Set up the inverting pointer, and attempt to bring the ! 524: * drive on line. ! 525: */ ! 526: kdbattach(ui) ! 527: register struct uba_device *ui; ! 528: { ! 529: ! 530: if (kdbwstart == 0) { ! 531: timeout(kdbwatch, (caddr_t)0, hz); ! 532: kdbwstart++; ! 533: } ! 534: if (ui->ui_dk >= 0) ! 535: dk_mspw[ui->ui_dk] = 1.0 / (60 * 31 * 256); /* approx */ ! 536: kdbip[ui->ui_ctlr][ui->ui_slave] = ui; ! 537: (void) kdb_bringonline(ui, 1); ! 538: /* should we get its status too? */ ! 539: } ! 540: ! 541: /* ! 542: * Initialise a KDB50. Return true iff something goes wrong. ! 543: */ ! 544: kdbinit(ki) ! 545: register struct kdbinfo *ki; ! 546: { ! 547: register struct kdb_regs *ka = ki->ki_kdb; ! 548: int timo; ! 549: ! 550: /* ! 551: * While we are thinking about it, reset the next command ! 552: * and response indicies. ! 553: */ ! 554: ki->ki_mi.mi_cmd.mri_next = 0; ! 555: ki->ki_mi.mi_rsp.mri_next = 0; ! 556: ! 557: /* ! 558: * Start up the hardware initialisation sequence. ! 559: */ ! 560: #define STEP0MASK (KDB_ERR | KDB_STEP4 | KDB_STEP3 | KDB_STEP2 | KDB_STEP1) ! 561: ! 562: ki->ki_state = ST_IDLE; /* in case init fails */ ! 563: ! 564: bi_reset(&ka->kdb_bi); /* reset bi node (but not the BI itself) */ ! 565: ! 566: timo = todr() + 1000; ! 567: while ((ka->kdb_sa & STEP0MASK) == 0) { ! 568: if (todr() > timo) { ! 569: printf("kdb%d: timeout during init\n", ki->ki_ctlr); ! 570: return (-1); ! 571: } ! 572: } ! 573: if ((ka->kdb_sa & STEP0MASK) != KDB_STEP1) { ! 574: printf("kdb%d: init failed, sa=%b\n", ki->ki_ctlr, ! 575: ka->kdb_sa, kdbsr_bits); ! 576: return (-1); ! 577: } ! 578: ! 579: /* ! 580: * Success! Record new state, and start step 1 initialisation. ! 581: * The rest is done in the interrupt handler. ! 582: */ ! 583: ki->ki_state = ST_STEP1; ! 584: ka->kdb_bi.bi_intrdes = 1 << mastercpu; ! 585: #ifdef unneeded /* is it? */ ! 586: ka->kdb_bi.bi_csr = (ka->kdb_bi.bi_csr&~BICSR_ARB_MASK)|BICSR_ARB_???; ! 587: #endif ! 588: ka->kdb_bi.bi_bcicsr |= BCI_STOPEN | BCI_IDENTEN | BCI_UINTEN | ! 589: BCI_INTEN; ! 590: ! 591: /* I THINK THIS IS WRONG */ ! 592: /* Mach uses 0x601d0, which includes IPL16, but 1d0 is IPL17, nexzvec...? */ ! 593: ka->kdb_bi.bi_eintrcsr = BIEIC_IPL15 | ki->ki_vec; /* ??? */ ! 594: /* END I THINK WRONG */ ! 595: ! 596: ka->kdb_bi.bi_uintrcsr = ki->ki_vec; ! 597: ka->kdb_sw = KDB_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | KDB_IE | ! 598: (ki->ki_vec >> 2); ! 599: return (0); ! 600: } ! 601: ! 602: /* ! 603: * Open a drive. ! 604: */ ! 605: /*ARGSUSED*/ ! 606: kdbopen(dev, flag) ! 607: dev_t dev; ! 608: int flag; ! 609: { ! 610: register int unit; ! 611: register struct uba_device *ui; ! 612: register struct kdbinfo *ki; ! 613: int s; ! 614: ! 615: /* ! 616: * Make sure this is a reasonable open request. ! 617: */ ! 618: unit = kdbunit(dev); ! 619: if (unit >= NKRA || (ui = kdbdinfo[unit]) == 0 || ui->ui_alive == 0) ! 620: return (ENXIO); ! 621: ! 622: /* ! 623: * Make sure the controller is running, by (re)initialising it if ! 624: * necessary. ! 625: */ ! 626: ki = &kdbinfo[ui->ui_ctlr]; ! 627: s = spl5(); ! 628: if (ki->ki_state != ST_RUN) { ! 629: if (ki->ki_state == ST_IDLE && kdbinit(ki)) { ! 630: splx(s); ! 631: return (EIO); ! 632: } ! 633: /* ! 634: * In case it does not come up, make sure we will be ! 635: * restarted in 10 seconds. This corresponds to the ! 636: * 10 second timeouts in kdbprobe() and kdbslave(). ! 637: */ ! 638: ki->ki_flags |= KDB_DOWAKE; ! 639: timeout(wakeup, (caddr_t)&ki->ki_flags, 10 * hz); ! 640: sleep((caddr_t)&ki->ki_flags, PRIBIO); ! 641: if (ki->ki_state != ST_RUN) { ! 642: splx(s); ! 643: printf("kdb%d: controller hung\n", ui->ui_ctlr); ! 644: return (EIO); ! 645: } ! 646: untimeout(wakeup, (caddr_t)&ki->ki_flags); ! 647: } ! 648: if ((ui->ui_flags & UNIT_ONLINE) == 0) { ! 649: /* ! 650: * Bring the drive on line so we can find out how ! 651: * big it is. If it is not spun up, it will not ! 652: * come on line; this cannot really be considered ! 653: * an `error condition'. ! 654: */ ! 655: if (kdb_bringonline(ui, 0)) { ! 656: splx(s); ! 657: printf("%s%d: drive will not come on line\n", ! 658: kdbdriver.ud_dname, unit); ! 659: return (EIO); ! 660: } ! 661: } ! 662: splx(s); ! 663: return (0); ! 664: } ! 665: ! 666: /* ! 667: * Bring a drive on line. In case it fails to respond, we set ! 668: * a timeout on it. The `nosleep' parameter should be set if ! 669: * we are to spin-wait; otherwise this must be called at spl5(). ! 670: */ ! 671: kdb_bringonline(ui, nosleep) ! 672: register struct uba_device *ui; ! 673: int nosleep; ! 674: { ! 675: register struct kdbinfo *ki = &kdbinfo[ui->ui_ctlr]; ! 676: register struct mscp *mp; ! 677: int i; ! 678: ! 679: if (nosleep) { ! 680: mp = mscp_getcp(&ki->ki_mi, MSCP_DONTWAIT); ! 681: if (mp == NULL) ! 682: return (-1); ! 683: } else ! 684: mp = mscp_getcp(&ki->ki_mi, MSCP_WAIT); ! 685: mp->mscp_opcode = M_OP_ONLINE; ! 686: mp->mscp_unit = ui->ui_slave; ! 687: mp->mscp_cmdref = (long)&ui->ui_flags; ! 688: *mp->mscp_addr |= MSCP_OWN | MSCP_INT; ! 689: i = ki->ki_kdb->kdb_ip; ! 690: ! 691: if (nosleep) { ! 692: i = todr() + 1000; ! 693: while ((ui->ui_flags & UNIT_ONLINE) == 0) ! 694: if (todr() > i) ! 695: return (-1); ! 696: } else { ! 697: timeout(wakeup, (caddr_t)&ui->ui_flags, 10 * hz); ! 698: sleep((caddr_t)&ui->ui_flags, PRIBIO); ! 699: if ((ui->ui_flags & UNIT_ONLINE) == 0) ! 700: return (-1); ! 701: untimeout(wakeup, (caddr_t)&ui->ui_flags); ! 702: } ! 703: return (0); /* made it */ ! 704: } ! 705: ! 706: /* ! 707: * Queue a transfer request, and if possible, hand it to the controller. ! 708: * ! 709: * This routine is broken into two so that the internal version ! 710: * kdbstrat1() can be called by the (nonexistent, as yet) bad block ! 711: * revectoring routine. ! 712: */ ! 713: kdbstrategy(bp) ! 714: register struct buf *bp; ! 715: { ! 716: register int unit; ! 717: register struct uba_device *ui; ! 718: register struct size *st; ! 719: daddr_t sz, maxsz; ! 720: ! 721: /* ! 722: * Make sure this is a reasonable drive to use. ! 723: */ ! 724: if ((unit = kdbunit(bp->b_dev)) >= NKRA || ! 725: (ui = kdbdinfo[unit]) == NULL || ui->ui_alive == 0) { ! 726: bp->b_error = ENXIO; ! 727: bp->b_flags |= B_ERROR; ! 728: biodone(bp); ! 729: return; ! 730: } ! 731: ! 732: /* ! 733: * Determine the size of the transfer, and make sure it is ! 734: * within the boundaries of the drive. ! 735: */ ! 736: sz = (bp->b_bcount + 511) >> 9; ! 737: st = &kdbtypes[ui->ui_type].ut_sizes[kdbpart(bp->b_dev)]; ! 738: if ((maxsz = st->nblocks) < 0) ! 739: maxsz = ra_dsize[unit] - st->blkoff; ! 740: if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz || ! 741: st->blkoff >= ra_dsize[unit]) { ! 742: /* if exactly at end of disk, return an EOF */ ! 743: if (bp->b_blkno == maxsz) ! 744: bp->b_resid = bp->b_bcount; ! 745: else { ! 746: bp->b_error = EINVAL; ! 747: bp->b_flags |= B_ERROR; ! 748: } ! 749: biodone(bp); ! 750: return; ! 751: } ! 752: kdbstrat1(bp); ! 753: } ! 754: ! 755: /* ! 756: * Work routine for kdbstrategy. ! 757: */ ! 758: kdbstrat1(bp) ! 759: register struct buf *bp; ! 760: { ! 761: register int unit = kdbunit(bp->b_dev); ! 762: register struct buf *dp; ! 763: register struct kdbinfo *ki; ! 764: struct uba_device *ui; ! 765: int s; ! 766: ! 767: /* ! 768: * Append the buffer to the drive queue, and if it is not ! 769: * already there, the drive to the controller queue. (However, ! 770: * if the drive queue is marked to be requeued, we must be ! 771: * awaiting an on line or get unit status command; in this ! 772: * case, leave it off the controller queue.) ! 773: */ ! 774: ui = kdbdinfo[unit]; ! 775: ki = &kdbinfo[ui->ui_ctlr]; ! 776: dp = &kdbutab[unit]; ! 777: s = spl5(); ! 778: APPEND(bp, dp, av_forw); ! 779: if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) { ! 780: APPEND(dp, &ki->ki_tab, b_forw); ! 781: dp->b_active++; ! 782: } ! 783: ! 784: /* ! 785: * Start activity on the controller. ! 786: */ ! 787: kdbstart(ki); ! 788: splx(s); ! 789: } ! 790: ! 791: /* ! 792: * Find the physical address of some contiguous PTEs that map the ! 793: * transfer described in `bp', creating them (by copying) if ! 794: * necessary. Store the physical base address of the map through ! 795: * mapbase, and the page offset through offset, and any resource ! 796: * information in *info (or 0 if none). ! 797: * ! 798: * If we cannot allocate space, return a nonzero status. ! 799: */ ! 800: int ! 801: kdbmap(ki, bp, mapbase, offset, info) ! 802: struct kdbinfo *ki; ! 803: register struct buf *bp; ! 804: long *mapbase, *offset; ! 805: int *info; ! 806: { ! 807: register struct pte *spte, *dpte; ! 808: register struct proc *rp; ! 809: register int i, a, o; ! 810: u_int v; ! 811: int npf; ! 812: ! 813: o = (int)bp->b_un.b_addr & PGOFSET; ! 814: ! 815: /* handle contiguous cases */ ! 816: if ((bp->b_flags & B_PHYS) == 0) { ! 817: spte = kvtopte(bp->b_un.b_addr); ! 818: kdbstats.ks_sys++; ! 819: *mapbase = PHYS(long, spte); ! 820: *offset = o; ! 821: *info = 0; ! 822: return (0); ! 823: } ! 824: if (bp->b_flags & B_PAGET) { ! 825: spte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; ! 826: if (spte->pg_v == 0) panic("kdbmap"); ! 827: kdbstats.ks_paget++; ! 828: *mapbase = PHYS(long, spte); ! 829: *offset = o; ! 830: *info = 0; ! 831: return (0); ! 832: } ! 833: ! 834: /* potentially discontiguous or invalid ptes */ ! 835: v = btop(bp->b_un.b_addr); ! 836: rp = bp->b_flags & B_DIRTY ? &proc[2] : bp->b_proc; ! 837: if (bp->b_flags & B_UAREA) ! 838: spte = &rp->p_addr[v]; ! 839: else ! 840: spte = vtopte(rp, v); ! 841: npf = btoc(bp->b_bcount + o); ! 842: ! 843: #ifdef notdef ! 844: /* ! 845: * The current implementation of the VM system requires ! 846: * that all of these be done with a copy. Even if the ! 847: * PTEs could be used now, they may be snatched out from ! 848: * under us later. It would be nice if we could stop that.... ! 849: */ ! 850: ! 851: /* check for invalid */ ! 852: /* CONSIDER CHANGING VM TO VALIDATE PAGES EARLIER */ ! 853: for (dpte = spte, i = npf; --i >= 0; dpte++) ! 854: if (dpte->pg_v == 0) ! 855: goto copy1; ! 856: /* ! 857: * Check for discontiguous physical pte addresses. It is ! 858: * not necessary to check each pte, since they come in clumps ! 859: * of pages. ! 860: */ ! 861: i = howmany(npf + (((int)spte & PGOFSET) / sizeof (*spte)), NPTEPG); ! 862: /* often i==1, and we can avoid work */ ! 863: if (--i > 0) { ! 864: dpte = kvtopte(spte); ! 865: a = dpte->pg_pfnum; ! 866: while (--i >= 0) ! 867: if ((++dpte)->pg_pfnum != ++a) ! 868: goto copy2; ! 869: } ! 870: ! 871: /* made it */ ! 872: kdbstats.ks_contig++; ! 873: *mapbase = kvtophys(spte); ! 874: *offset = o; ! 875: *info = 0; ! 876: return (0); ! 877: ! 878: copy1: ! 879: kdbstats.ks_inval++; /* temp */ ! 880: copy2: ! 881: #endif /* notdef */ ! 882: kdbstats.ks_copies++; ! 883: i = npf + 1; ! 884: if ((a = rmalloc(ki->ki_map, (long)i)) == 0) { ! 885: kdbstats.ks_mapwait++; ! 886: return (-1); ! 887: } ! 888: *info = (i << 16) | a; ! 889: a--; ! 890: /* if offset > PGOFSET, btop(offset) indexes mapbase */ ! 891: *mapbase = ki->ki_ptephys; ! 892: *offset = (a << PGSHIFT) | o; ! 893: dpte = &ki->ki_pte[a]; ! 894: while (--i > 0) ! 895: *(int *)dpte++ = PG_V | *(int *)spte++; ! 896: *(int *)dpte = 0; ! 897: return (0); ! 898: } ! 899: ! 900: #define KDBFREE(ki, info) if (info) \ ! 901: rmfree((ki)->ki_map, (long)((info) >> 16), (long)((info) & 0xffff)) ! 902: ! 903: /* ! 904: * Start up whatever transfers we can find. ! 905: * Note that kdbstart() must be called at spl5(). ! 906: */ ! 907: kdbstart(ki) ! 908: register struct kdbinfo *ki; ! 909: { ! 910: register struct buf *bp, *dp; ! 911: register struct mscp *mp; ! 912: register struct uba_device *ui; ! 913: long mapbase, offset; ! 914: int info, ncmd = 0; ! 915: ! 916: /* ! 917: * If it is not running, try (again and again...) to initialise ! 918: * it. If it is currently initialising just ignore it for now. ! 919: */ ! 920: if (ki->ki_state != ST_RUN) { ! 921: if (ki->ki_state == ST_IDLE && kdbinit(ki)) ! 922: printf("kdb%d: still hung\n", ki->ki_ctlr); ! 923: return; ! 924: } ! 925: ! 926: loop: ! 927: /* if insufficient credit, avoid overhead */ ! 928: if (ki->ki_mi.mi_credits <= MSCP_MINCREDITS) ! 929: goto out; ! 930: ! 931: /* ! 932: * Service the drive at the head of the queue. It may not ! 933: * need anything; eventually this will finish up the close ! 934: * protocol, but that is yet to be implemented here. ! 935: */ ! 936: if ((dp = ki->ki_tab.b_actf) == NULL) ! 937: goto out; ! 938: if ((bp = dp->b_actf) == NULL) { ! 939: dp->b_active = 0; ! 940: ki->ki_tab.b_actf = dp->b_forw; ! 941: goto loop; ! 942: } ! 943: ! 944: if (ki->ki_kdb->kdb_sa & KDB_ERR) { /* ctlr fatal error */ ! 945: kdbsaerror(ki); ! 946: goto out; ! 947: } ! 948: ! 949: /* find or create maps for this transfer */ ! 950: if (kdbmap(ki, bp, &mapbase, &offset, &info)) ! 951: goto out; /* effectively, resource wait */ ! 952: ! 953: /* ! 954: * Get an MSCP packet, then figure out what to do. If ! 955: * we cannot get a command packet, the command ring may ! 956: * be too small: We should have at least as many command ! 957: * packets as credits, for best performance. ! 958: */ ! 959: if ((mp = mscp_getcp(&ki->ki_mi, MSCP_DONTWAIT)) == NULL) { ! 960: if (ki->ki_mi.mi_credits > MSCP_MINCREDITS && ! 961: (ki->ki_flags & KDB_GRIPED) == 0) { ! 962: log(LOG_NOTICE, "kdb%d: command ring too small\n", ! 963: ki->ki_ctlr); ! 964: ki->ki_flags |= KDB_GRIPED;/* complain only once */ ! 965: } ! 966: KDBFREE(ki, info); ! 967: goto out; ! 968: } ! 969: ! 970: /* ! 971: * Bring the drive on line if it is not already. Get its status ! 972: * if we do not already have it. Otherwise just start the transfer. ! 973: */ ! 974: ui = kdbdinfo[kdbunit(bp->b_dev)]; ! 975: if ((ui->ui_flags & UNIT_ONLINE) == 0) { ! 976: mp->mscp_opcode = M_OP_ONLINE; ! 977: goto common; ! 978: } ! 979: if ((ui->ui_flags & UNIT_HAVESTATUS) == 0) { ! 980: mp->mscp_opcode = M_OP_GETUNITST; ! 981: common: ! 982: if (ui->ui_flags & UNIT_REQUEUE) panic("kdbstart"); ! 983: /* ! 984: * Take the drive off the controller queue. When the ! 985: * command finishes, make sure the drive is requeued. ! 986: * Give up any mapping (not needed now). This last is ! 987: * not efficient, but is rare. ! 988: */ ! 989: KDBFREE(ki, info); ! 990: ki->ki_tab.b_actf = dp->b_forw; ! 991: dp->b_active = 0; ! 992: ui->ui_flags |= UNIT_REQUEUE; ! 993: mp->mscp_unit = ui->ui_slave; ! 994: *mp->mscp_addr |= MSCP_OWN | MSCP_INT; ! 995: ncmd++; ! 996: goto loop; ! 997: } ! 998: ! 999: mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE; ! 1000: mp->mscp_unit = ui->ui_slave; ! 1001: mp->mscp_seq.seq_lbn = bp->b_blkno + ! 1002: kdbtypes[ui->ui_type].ut_sizes[kdbpart(bp->b_dev)].blkoff; ! 1003: mp->mscp_seq.seq_bytecount = bp->b_bcount; ! 1004: ! 1005: mp->mscp_seq.seq_buffer = offset | KDB_MAP; ! 1006: mp->mscp_seq.seq_mapbase = mapbase; ! 1007: ! 1008: /* profile the drive */ ! 1009: if (ui->ui_dk >= 0) { ! 1010: dk_busy |= 1 << ui->ui_dk; ! 1011: dk_xfer[ui->ui_dk]++; ! 1012: dk_wds[ui->ui_dk] += bp->b_bcount >> 6; ! 1013: } ! 1014: ! 1015: /* ! 1016: * Fill in the rest of the MSCP packet and move the buffer to the ! 1017: * I/O wait queue. ! 1018: */ ! 1019: mscp_go(&ki->ki_mi, mp, info); ! 1020: ncmd++; /* note the transfer */ ! 1021: ki->ki_tab.b_active++; /* another one going */ ! 1022: goto loop; ! 1023: ! 1024: out: ! 1025: if (ncmd >= KS_MAXC) ! 1026: ncmd = KS_MAXC - 1; ! 1027: kdbstats.ks_cmd[ncmd]++; ! 1028: if (ncmd) /* start some transfers */ ! 1029: ncmd = ki->ki_kdb->kdb_ip; ! 1030: } ! 1031: ! 1032: /* ARGSUSED */ ! 1033: kdbiodone(mi, bp, info) ! 1034: struct mscp_info *mi; ! 1035: struct buf *bp; ! 1036: int info; ! 1037: { ! 1038: register struct kdbinfo *ki = &kdbinfo[mi->mi_ctlr]; ! 1039: ! 1040: KDBFREE(ki, info); ! 1041: biodone(bp); ! 1042: ki->ki_tab.b_active--; /* another one done */ ! 1043: } ! 1044: ! 1045: /* ! 1046: * The error bit was set in the controller status register. Gripe, ! 1047: * reset the controller, requeue pending transfers. ! 1048: */ ! 1049: kdbsaerror(ki) ! 1050: register struct kdbinfo *ki; ! 1051: { ! 1052: ! 1053: printf("kdb%d: controller error, sa=%b\n", ki->ki_ctlr, ! 1054: ki->ki_kdb->kdb_sa, kdbsr_bits); ! 1055: mscp_requeue(&ki->ki_mi); ! 1056: (void) kdbinit(ki); ! 1057: } ! 1058: ! 1059: /* ! 1060: * Interrupt routine. Depending on the state of the controller, ! 1061: * continue initialisation, or acknowledge command and response ! 1062: * interrupts, and process responses. ! 1063: */ ! 1064: kdbintr(ctlr) ! 1065: int ctlr; ! 1066: { ! 1067: register struct kdbinfo *ki = &kdbinfo[ctlr]; ! 1068: register struct kdb_regs *kdbaddr = ki->ki_kdb; ! 1069: register struct mscp *mp; ! 1070: register int i; ! 1071: ! 1072: ki->ki_wticks = 0; /* reset interrupt watchdog */ ! 1073: ! 1074: /* ! 1075: * Combinations during steps 1, 2, and 3: STEPnMASK ! 1076: * corresponds to which bits should be tested; ! 1077: * STEPnGOOD corresponds to the pattern that should ! 1078: * appear after the interrupt from STEPn initialisation. ! 1079: * All steps test the bits in ALLSTEPS. ! 1080: */ ! 1081: #define ALLSTEPS (KDB_ERR|KDB_STEP4|KDB_STEP3|KDB_STEP2|KDB_STEP1) ! 1082: ! 1083: #define STEP1MASK (ALLSTEPS | KDB_IE | KDB_NCNRMASK) ! 1084: #define STEP1GOOD (KDB_STEP2 | KDB_IE | (NCMDL2 << 3) | NRSPL2) ! 1085: ! 1086: #define STEP2MASK (ALLSTEPS | KDB_IE | KDB_IVECMASK) ! 1087: #define STEP2GOOD (KDB_STEP3 | KDB_IE | (ki->ki_vec >> 2)) ! 1088: ! 1089: #define STEP3MASK ALLSTEPS ! 1090: #define STEP3GOOD KDB_STEP4 ! 1091: ! 1092: switch (ki->ki_state) { ! 1093: ! 1094: case ST_IDLE: ! 1095: /* ! 1096: * Ignore unsolicited interrupts. ! 1097: */ ! 1098: log(LOG_WARNING, "kdb%d: stray intr\n", ctlr); ! 1099: return; ! 1100: ! 1101: case ST_STEP1: ! 1102: /* ! 1103: * Begin step two initialisation. ! 1104: */ ! 1105: if ((kdbaddr->kdb_sa & STEP1MASK) != STEP1GOOD) { ! 1106: i = 1; ! 1107: initfailed: ! 1108: printf("kdb%d: init step %d failed, sa=%b\n", ! 1109: ctlr, i, kdbaddr->kdb_sa, kdbsr_bits); ! 1110: ki->ki_state = ST_IDLE; ! 1111: if (ki->ki_flags & KDB_DOWAKE) { ! 1112: ki->ki_flags &= ~KDB_DOWAKE; ! 1113: wakeup((caddr_t)&ki->ki_flags); ! 1114: } ! 1115: return; ! 1116: } ! 1117: kdbaddr->kdb_sw = PHYS(int, &ki->ki_ca.ca_rspdsc[0]); ! 1118: ki->ki_state = ST_STEP2; ! 1119: return; ! 1120: ! 1121: case ST_STEP2: ! 1122: /* ! 1123: * Begin step 3 initialisation. ! 1124: */ ! 1125: if ((kdbaddr->kdb_sa & STEP2MASK) != STEP2GOOD) { ! 1126: i = 2; ! 1127: goto initfailed; ! 1128: } ! 1129: kdbaddr->kdb_sw = PHYS(int, &ki->ki_ca.ca_rspdsc[0]) >> 16; ! 1130: ki->ki_state = ST_STEP3; ! 1131: return; ! 1132: ! 1133: case ST_STEP3: ! 1134: /* ! 1135: * Set controller characteristics (finish initialisation). ! 1136: */ ! 1137: if ((kdbaddr->kdb_sa & STEP3MASK) != STEP3GOOD) { ! 1138: i = 3; ! 1139: goto initfailed; ! 1140: } ! 1141: i = kdbaddr->kdb_sa & 0xff; ! 1142: if (i != ki->ki_micro) { ! 1143: ki->ki_micro = i; ! 1144: printf("kdb%d: version %d model %d\n", ! 1145: ctlr, i & 0xf, i >> 4); ! 1146: } ! 1147: ! 1148: kdbaddr->kdb_sw = KDB_GO; ! 1149: ! 1150: /* initialise hardware data structures */ ! 1151: for (i = 0, mp = ki->ki_rsp; i < NRSP; i++, mp++) { ! 1152: ki->ki_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT | ! 1153: PHYS(long, &ki->ki_rsp[i].mscp_cmdref); ! 1154: mp->mscp_addr = &ki->ki_ca.ca_rspdsc[i]; ! 1155: mp->mscp_msglen = MSCP_MSGLEN; ! 1156: } ! 1157: for (i = 0, mp = ki->ki_cmd; i < NCMD; i++, mp++) { ! 1158: ki->ki_ca.ca_cmddsc[i] = MSCP_INT | ! 1159: PHYS(long, &ki->ki_cmd[i].mscp_cmdref); ! 1160: mp->mscp_addr = &ki->ki_ca.ca_cmddsc[i]; ! 1161: mp->mscp_msglen = MSCP_MSGLEN; ! 1162: } ! 1163: ! 1164: /* ! 1165: * Before we can get a command packet, we need some ! 1166: * credits. Fake some up to keep mscp_getcp() happy, ! 1167: * get a packet, and cancel all credits (the right ! 1168: * number should come back in the response to the ! 1169: * SCC packet). ! 1170: */ ! 1171: ki->ki_mi.mi_credits = MSCP_MINCREDITS + 1; ! 1172: mp = mscp_getcp(&ki->ki_mi, MSCP_DONTWAIT); ! 1173: if (mp == NULL) /* `cannot happen' */ ! 1174: panic("kdbintr"); ! 1175: ki->ki_mi.mi_credits = 0; ! 1176: mp->mscp_opcode = M_OP_SETCTLRC; ! 1177: mp->mscp_unit = 0; ! 1178: mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | ! 1179: M_CF_THIS; ! 1180: *mp->mscp_addr |= MSCP_OWN | MSCP_INT; ! 1181: i = kdbaddr->kdb_ip; ! 1182: ki->ki_state = ST_SETCHAR; ! 1183: return; ! 1184: ! 1185: case ST_SETCHAR: ! 1186: case ST_RUN: ! 1187: /* ! 1188: * Handle Set Ctlr Characteristics responses and operational ! 1189: * responses (via mscp_dorsp). ! 1190: */ ! 1191: break; ! 1192: ! 1193: default: ! 1194: log(LOG_ERR, "kdb%d: driver bug, state %d\n", ctlr, ! 1195: ki->ki_state); ! 1196: return; ! 1197: } ! 1198: ! 1199: if (kdbaddr->kdb_sa & KDB_ERR) {/* ctlr fatal error */ ! 1200: kdbsaerror(ki); ! 1201: return; ! 1202: } ! 1203: ! 1204: /* ! 1205: * Handle buffer purge requests. ! 1206: * KDB DOES NOT HAVE BDPs ! 1207: */ ! 1208: if (ki->ki_ca.ca_bdp) { ! 1209: printf("kdb%d: purge bdp %d\n", ctlr, ki->ki_ca.ca_bdp); ! 1210: panic("kdb purge"); ! 1211: } ! 1212: ! 1213: /* ! 1214: * Check for response and command ring transitions. ! 1215: */ ! 1216: if (ki->ki_ca.ca_rspint) { ! 1217: ki->ki_ca.ca_rspint = 0; ! 1218: mscp_dorsp(&ki->ki_mi); ! 1219: } ! 1220: if (ki->ki_ca.ca_cmdint) { ! 1221: ki->ki_ca.ca_cmdint = 0; ! 1222: MSCP_DOCMD(&ki->ki_mi); ! 1223: } ! 1224: if (ki->ki_tab.b_actf != NULL) ! 1225: kdbstart(ki); ! 1226: } ! 1227: ! 1228: /* ! 1229: * Handle an error datagram. All we do now is decode it. ! 1230: */ ! 1231: kdbdgram(mi, mp) ! 1232: struct mscp_info *mi; ! 1233: struct mscp *mp; ! 1234: { ! 1235: ! 1236: mscp_decodeerror(mi->mi_md->md_mname, mi->mi_ctlr, mp); ! 1237: } ! 1238: ! 1239: /* ! 1240: * The Set Controller Characteristics command finished. ! 1241: * Record the new state of the controller. ! 1242: */ ! 1243: kdbctlrdone(mi, mp) ! 1244: struct mscp_info *mi; ! 1245: struct mscp *mp; ! 1246: { ! 1247: register struct kdbinfo *ki = &kdbinfo[mi->mi_ctlr]; ! 1248: ! 1249: if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) ! 1250: ki->ki_state = ST_RUN; ! 1251: else { ! 1252: printf("kdb%d: SETCTLRC failed, status 0x%x\n", ! 1253: ki->ki_ctlr, mp->mscp_status); ! 1254: ki->ki_state = ST_IDLE; ! 1255: } ! 1256: if (ki->ki_flags & KDB_DOWAKE) { ! 1257: ki->ki_flags &= ~KDB_DOWAKE; ! 1258: wakeup((caddr_t)&ki->ki_flags); ! 1259: } ! 1260: } ! 1261: ! 1262: /* ! 1263: * Received a response from an as-yet unconfigured drive. Configure it ! 1264: * in, if possible. ! 1265: */ ! 1266: kdbunconf(mi, mp) ! 1267: struct mscp_info *mi; ! 1268: register struct mscp *mp; ! 1269: { ! 1270: ! 1271: /* ! 1272: * If it is a slave response, copy it to kdbslavereply for ! 1273: * kdbslave() to look at. ! 1274: */ ! 1275: if (mp->mscp_opcode == (M_OP_GETUNITST | M_OP_END) && ! 1276: (kdbinfo[mi->mi_ctlr].ki_flags & KDB_INSLAVE) != 0) { ! 1277: kdbslavereply = *mp; ! 1278: return (MSCP_DONE); ! 1279: } ! 1280: ! 1281: /* ! 1282: * Otherwise, it had better be an available attention response. ! 1283: */ ! 1284: if (mp->mscp_opcode != M_OP_AVAILATTN) ! 1285: return (MSCP_FAILED); ! 1286: ! 1287: /* do what autoconf does */ ! 1288: return (MSCP_FAILED); /* not yet */ ! 1289: } ! 1290: ! 1291: /* ! 1292: * A drive came on line. Check its type and size. Return DONE if ! 1293: * we think the drive is truly on line. In any case, awaken anyone ! 1294: * sleeping on the drive on-line-ness. ! 1295: */ ! 1296: kdbonline(ui, mp) ! 1297: register struct uba_device *ui; ! 1298: struct mscp *mp; ! 1299: { ! 1300: register int type; ! 1301: ! 1302: wakeup((caddr_t)&ui->ui_flags); ! 1303: if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { ! 1304: printf("kdb%d: attempt to bring %s%d on line failed:", ! 1305: ui->ui_ctlr, kdbdriver.ud_dname, ui->ui_unit); ! 1306: mscp_printevent(mp); ! 1307: return (MSCP_FAILED); ! 1308: } ! 1309: ! 1310: type = mp->mscp_onle.onle_drivetype; ! 1311: if (type >= NTYPES || kdbtypes[type].ut_name == 0) { ! 1312: printf("kdb%d: %s%d: unknown type %d\n", ! 1313: ui->ui_ctlr, kdbdriver.ud_dname, ui->ui_unit, type); ! 1314: return (MSCP_FAILED); ! 1315: } ! 1316: /* ! 1317: * Note any change of types. Not sure if we should do ! 1318: * something special about them, or if so, what.... ! 1319: */ ! 1320: if (type != ui->ui_type) { ! 1321: printf("%s%d: changed types! was %s\n", ! 1322: kdbdriver.ud_dname, ui->ui_unit, ! 1323: kdbtypes[ui->ui_type].ut_name); ! 1324: ui->ui_type = type; ! 1325: } ! 1326: ra_dsize[ui->ui_unit] = (daddr_t) mp->mscp_onle.onle_unitsize; ! 1327: printf("%s%d: %s, size = %d sectors\n", ! 1328: kdbdriver.ud_dname, ui->ui_unit, ! 1329: kdbtypes[type].ut_name, ra_dsize[ui->ui_unit]); ! 1330: return (MSCP_DONE); ! 1331: } ! 1332: ! 1333: /* ! 1334: * We got some (configured) unit's status. Return DONE if it succeeded. ! 1335: */ ! 1336: kdbgotstatus(ui, mp) ! 1337: register struct uba_device *ui; ! 1338: register struct mscp *mp; ! 1339: { ! 1340: ! 1341: if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { ! 1342: printf("kdb%d: attempt to get status for %s%d failed:", ! 1343: ui->ui_ctlr, kdbdriver.ud_dname, ui->ui_unit); ! 1344: mscp_printevent(mp); ! 1345: return (MSCP_FAILED); ! 1346: } ! 1347: /* need to record later for bad block forwarding - for now, print */ ! 1348: printf("\ ! 1349: %s%d: unit %d, nspt %d, group %d, ngpc %d, rctsize %d, nrpt %d, nrct %d\n", ! 1350: kdbdriver.ud_dname, ui->ui_unit, mp->mscp_unit, ! 1351: mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group, ! 1352: mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize, ! 1353: mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct); ! 1354: return (MSCP_DONE); ! 1355: } ! 1356: ! 1357: /* ! 1358: * A transfer failed. We get a chance to fix or restart it. ! 1359: * Need to write the bad block forwaring code first.... ! 1360: */ ! 1361: /*ARGSUSED*/ ! 1362: kdbioerror(ui, mp, bp) ! 1363: register struct uba_device *ui; ! 1364: register struct mscp *mp; ! 1365: struct buf *bp; ! 1366: { ! 1367: ! 1368: if (mp->mscp_flags & M_EF_BBLKR) { ! 1369: /* ! 1370: * A bad block report. Eventually we will ! 1371: * restart this transfer, but for now, just ! 1372: * log it and give up. ! 1373: */ ! 1374: log(LOG_ERR, "%s%d: bad block report: %d%s\n", ! 1375: kdbdriver.ud_dname, ui->ui_unit, mp->mscp_seq.seq_lbn, ! 1376: mp->mscp_flags & M_EF_BBLKU ? " + others" : ""); ! 1377: } else { ! 1378: /* ! 1379: * What the heck IS a `serious exception' anyway? ! 1380: */ ! 1381: if (mp->mscp_flags & M_EF_SEREX) ! 1382: log(LOG_ERR, "%s%d: serious exception reported\n", ! 1383: kdbdriver.ud_dname, ui->ui_unit); ! 1384: } ! 1385: return (MSCP_FAILED); ! 1386: } ! 1387: ! 1388: ! 1389: #ifdef notyet ! 1390: /* ! 1391: * I/O controls. Not yet! ! 1392: */ ! 1393: kdbioctl(dev, cmd, flag, data) ! 1394: dev_t dev; ! 1395: int cmd, flag; ! 1396: caddr_t data; ! 1397: { ! 1398: int error = 0; ! 1399: register int unit = kdbunit(dev); ! 1400: ! 1401: if (unit >= NKRA || uddinfo[unit] == NULL) ! 1402: return (ENXIO); ! 1403: ! 1404: switch (cmd) { ! 1405: ! 1406: case KDBIOCREPLACE: ! 1407: /* ! 1408: * Initiate bad block replacement for the given LBN. ! 1409: * (Should we allow modifiers?) ! 1410: */ ! 1411: error = EOPNOTSUPP; ! 1412: break; ! 1413: ! 1414: case KDBIOCGMICRO: ! 1415: /* ! 1416: * Return the microcode revision for the KDB50 running ! 1417: * this drive. ! 1418: */ ! 1419: *(int *)data = kdbinfo[kdbdinfo[unit]->ui_ctlr].ki_micro; ! 1420: break; ! 1421: ! 1422: case KDBIOCGSIZE: ! 1423: /* ! 1424: * Return the size (in 512 byte blocks) of this ! 1425: * disk drive. ! 1426: */ ! 1427: *(daddr_t *)data = ra_dsize[unit]; ! 1428: break; ! 1429: ! 1430: default: ! 1431: error = EINVAL; ! 1432: break; ! 1433: } ! 1434: return (error); ! 1435: } ! 1436: #endif ! 1437: ! 1438: #ifdef notyet ! 1439: /* ! 1440: * Reset a KDB50 (self test and all). ! 1441: * What if it fails? ! 1442: */ ! 1443: kdbreset(ki) ! 1444: register struct kdbinfo *ki; ! 1445: { ! 1446: ! 1447: printf("reset kdb%d", ki->ki_ctlr); ! 1448: bi_selftest(&ki->ki_kdb.kdb_bi); ! 1449: ki->ki_state = ST_IDLE; ! 1450: rminit(ki->ki_map, (long)KI_PTES, (long)1, "kdb", KI_MAPSIZ); ! 1451: mscp_requeue(&ki->ki_mi); ! 1452: if (kdbinit(ctlr)) ! 1453: printf(" (hung)"); ! 1454: printf("\n"); ! 1455: } ! 1456: #endif ! 1457: ! 1458: /* ! 1459: * Watchdog timer: If the controller is active, and no interrupts ! 1460: * have occurred for 30 seconds, assume it has gone away. ! 1461: */ ! 1462: kdbwatch() ! 1463: { ! 1464: register struct kdbinfo *ki; ! 1465: register int i; ! 1466: ! 1467: timeout(kdbwatch, (caddr_t)0, hz); /* every second */ ! 1468: for (i = 0, ki = kdbinfo; i < NKDB; i++, ki++) { ! 1469: if ((ki->ki_flags & KDB_ALIVE) == 0) ! 1470: continue; ! 1471: if (ki->ki_state == ST_IDLE) ! 1472: continue; ! 1473: if (ki->ki_state == ST_RUN && !ki->ki_tab.b_active) ! 1474: ki->ki_wticks = 0; ! 1475: else if (++ki->ki_wticks >= 30) { ! 1476: ki->ki_wticks = 0; ! 1477: printf("kdb%d: lost interrupt\n", i); ! 1478: /* kdbreset(ki); */ ! 1479: panic("kdb lost interrupt"); ! 1480: } ! 1481: } ! 1482: } ! 1483: ! 1484: /* ! 1485: * Do a panic dump. ! 1486: */ ! 1487: #define DBSIZE 32 /* dump 16K at a time */ ! 1488: ! 1489: struct kdbdumpspace { ! 1490: struct kdb1ca kd_ca; ! 1491: struct mscp kd_rsp; ! 1492: struct mscp kd_cmd; ! 1493: } kdbdumpspace; ! 1494: ! 1495: kdbdump(dev) ! 1496: dev_t dev; ! 1497: { ! 1498: register struct kdbdumpspace *kd; ! 1499: register struct kdb_regs *k; ! 1500: register int i; ! 1501: struct uba_device *ui; ! 1502: char *start; ! 1503: int num, blk, unit, maxsz, blkoff; ! 1504: ! 1505: /* ! 1506: * Make sure the device is a reasonable place on which to dump. ! 1507: */ ! 1508: unit = kdbunit(dev); ! 1509: if (unit >= NKRA) ! 1510: return (ENXIO); ! 1511: ui = PHYS(struct uba_device *, kdbdinfo[unit]); ! 1512: if (ui == NULL || ui->ui_alive == 0) ! 1513: return (ENXIO); ! 1514: ! 1515: /* ! 1516: * Find and initialise the KDB; get the physical address of the ! 1517: * device registers, and of communications area and command and ! 1518: * response packet. ! 1519: */ ! 1520: k = PHYS(struct kdbinfo *, &kdbinfo[ui->ui_ctlr])->ki_physkdb; ! 1521: kd = PHYS(struct kdbdumpspace *, &kdbdumpspace); ! 1522: ! 1523: /* ! 1524: * Initialise the controller, with one command and one response ! 1525: * packet. ! 1526: */ ! 1527: bi_reset(&k->kdb_bi); ! 1528: if (kdbdumpwait(k, KDB_STEP1)) ! 1529: return (EFAULT); ! 1530: k->kdb_sw = KDB_ERR; ! 1531: if (kdbdumpwait(k, KDB_STEP2)) ! 1532: return (EFAULT); ! 1533: k->kdb_sw = (int)&kd->kd_ca.ca_rspdsc; ! 1534: if (kdbdumpwait(k, KDB_STEP3)) ! 1535: return (EFAULT); ! 1536: k->kdb_sw = ((int)&kd->kd_ca.ca_rspdsc) >> 16; ! 1537: if (kdbdumpwait(k, KDB_STEP4)) ! 1538: return (EFAULT); ! 1539: k->kdb_sw = KDB_GO; ! 1540: ! 1541: /* ! 1542: * Set up the command and response descriptor, then set the ! 1543: * controller characteristics and bring the drive on line. ! 1544: * Note that all uninitialised locations in kd_cmd are zero. ! 1545: */ ! 1546: kd->kd_ca.ca_rspdsc = (long)&kd->kd_rsp.mscp_cmdref; ! 1547: kd->kd_ca.ca_cmddsc = (long)&kd->kd_cmd.mscp_cmdref; ! 1548: /* kd->kd_cmd.mscp_sccc.sccc_ctlrflags = 0; */ ! 1549: /* kd->kd_cmd.mscp_sccc.sccc_version = 0; */ ! 1550: if (kdbdumpcmd(M_OP_SETCTLRC, k, kd, ui->ui_ctlr)) ! 1551: return (EFAULT); ! 1552: kd->kd_cmd.mscp_unit = ui->ui_slave; ! 1553: if (kdbdumpcmd(M_OP_ONLINE, k, kd, ui->ui_ctlr)) ! 1554: return (EFAULT); ! 1555: ! 1556: /* ! 1557: * Pick up the drive type from the on line end packet; ! 1558: * convert that to a dump area size and a disk offset. ! 1559: * Note that the assembler uses pc-relative addressing ! 1560: * to get at kdbtypes[], no need for PHYS(). ! 1561: */ ! 1562: i = kd->kd_rsp.mscp_onle.onle_drivetype; ! 1563: if (i >= NTYPES || kdbtypes[i].ut_name == 0) { ! 1564: printf("disk type %d unknown\ndump "); ! 1565: return (EINVAL); ! 1566: } ! 1567: printf("on %s ", kdbtypes[i].ut_name); ! 1568: ! 1569: maxsz = kdbtypes[i].ut_sizes[kdbpart(dev)].nblocks; ! 1570: blkoff = kdbtypes[i].ut_sizes[kdbpart(dev)].blkoff; ! 1571: ! 1572: /* ! 1573: * Dump all of physical memory, or as much as will fit in the ! 1574: * space provided. ! 1575: */ ! 1576: start = 0; ! 1577: num = maxfree; ! 1578: if (dumplo < 0) ! 1579: return (EINVAL); ! 1580: if (dumplo + num >= maxsz) ! 1581: num = maxsz - dumplo; ! 1582: blkoff += dumplo; ! 1583: ! 1584: /* ! 1585: * Write out memory, DBSIZE pages at a time. ! 1586: * N.B.: this code depends on the fact that the sector ! 1587: * size == the page size. ! 1588: */ ! 1589: while (num > 0) { ! 1590: blk = num > DBSIZE ? DBSIZE : num; ! 1591: kd->kd_cmd.mscp_unit = ui->ui_slave; ! 1592: kd->kd_cmd.mscp_seq.seq_lbn = btop(start) + blkoff; ! 1593: kd->kd_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT; ! 1594: kd->kd_cmd.mscp_seq.seq_buffer = (long)start | KDB_PHYS; ! 1595: if (kdbdumpcmd(M_OP_WRITE, k, kd, ui->ui_ctlr)) ! 1596: return (EIO); ! 1597: start += blk << PGSHIFT; ! 1598: num -= blk; ! 1599: } ! 1600: return (0); /* made it! */ ! 1601: } ! 1602: ! 1603: /* ! 1604: * Wait for some of the bits in `bits' to come on. If the error bit ! 1605: * comes on, or ten seconds pass without response, return true (error). ! 1606: */ ! 1607: kdbdumpwait(k, bits) ! 1608: register struct kdb_regs *k; ! 1609: register int bits; ! 1610: { ! 1611: register int timo = todr() + 1000; ! 1612: ! 1613: while ((k->kdb_sa & bits) == 0) { ! 1614: if (k->kdb_sa & KDB_ERR) { ! 1615: printf("kdb_sa=%b\ndump ", k->kdb_sa, kdbsr_bits); ! 1616: return (1); ! 1617: } ! 1618: if (todr() >= timo) { ! 1619: printf("timeout\ndump "); ! 1620: return (1); ! 1621: } ! 1622: } ! 1623: return (0); ! 1624: } ! 1625: ! 1626: /* ! 1627: * Feed a command to the KDB50, wait for its response, and return ! 1628: * true iff something went wrong. ! 1629: */ ! 1630: kdbdumpcmd(op, k, kd, ctlr) ! 1631: int op; ! 1632: register struct kdb_regs *k; ! 1633: register struct kdbdumpspace *kd; ! 1634: int ctlr; ! 1635: { ! 1636: register int n; ! 1637: #define mp (&kd->kd_rsp) ! 1638: ! 1639: kd->kd_cmd.mscp_opcode = op; ! 1640: kd->kd_cmd.mscp_msglen = MSCP_MSGLEN; ! 1641: kd->kd_rsp.mscp_msglen = MSCP_MSGLEN; ! 1642: kd->kd_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; ! 1643: kd->kd_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT; ! 1644: if (k->kdb_sa & KDB_ERR) { ! 1645: printf("kdb_sa=%b\ndump ", k->kdb_sa, kdbsr_bits); ! 1646: return (1); ! 1647: } ! 1648: n = k->kdb_ip; ! 1649: n = todr() + 1000; ! 1650: for (;;) { ! 1651: if (todr() > n) { ! 1652: printf("timeout\ndump "); ! 1653: return (1); ! 1654: } ! 1655: if (kd->kd_ca.ca_cmdint) ! 1656: kd->kd_ca.ca_cmdint = 0; ! 1657: if (kd->kd_ca.ca_rspint == 0) ! 1658: continue; ! 1659: kd->kd_ca.ca_rspint = 0; ! 1660: if (mp->mscp_opcode == (op | M_OP_END)) ! 1661: break; ! 1662: printf("\n"); ! 1663: switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { ! 1664: ! 1665: case MSCPT_SEQ: ! 1666: printf("sequential"); ! 1667: break; ! 1668: ! 1669: case MSCPT_DATAGRAM: ! 1670: mscp_decodeerror("kdb", ctlr, mp); ! 1671: printf("datagram"); ! 1672: break; ! 1673: ! 1674: case MSCPT_CREDITS: ! 1675: printf("credits"); ! 1676: break; ! 1677: ! 1678: case MSCPT_MAINTENANCE: ! 1679: printf("maintenance"); ! 1680: break; ! 1681: ! 1682: default: ! 1683: printf("unknown (type 0x%x)", ! 1684: MSCP_MSGTYPE(mp->mscp_msgtc)); ! 1685: break; ! 1686: } ! 1687: printf(" ignored\ndump "); ! 1688: kd->kd_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; ! 1689: } ! 1690: if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { ! 1691: printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op, ! 1692: mp->mscp_opcode, mp->mscp_status); ! 1693: return (1); ! 1694: } ! 1695: return (0); ! 1696: #undef mp ! 1697: } ! 1698: ! 1699: /* ! 1700: * Return the size of a partition, if known, or -1 if not. ! 1701: */ ! 1702: kdbsize(dev) ! 1703: dev_t dev; ! 1704: { ! 1705: register int unit = kdbunit(dev); ! 1706: register struct uba_device *ui; ! 1707: register struct size *st; ! 1708: ! 1709: if (unit >= NKRA || (ui = kdbdinfo[unit]) == NULL || ui->ui_alive == 0) ! 1710: return (-1); ! 1711: st = &kdbtypes[ui->ui_type].ut_sizes[kdbpart(dev)]; ! 1712: if (st->nblocks == -1) { ! 1713: int s = spl5(); ! 1714: ! 1715: /* ! 1716: * We need to have the drive on line to find the size ! 1717: * of this particular partition. ! 1718: * IS IT OKAY TO GO TO SLEEP IN THIS ROUTINE? ! 1719: * (If not, better not page on one of these...) ! 1720: */ ! 1721: if ((ui->ui_flags & UNIT_ONLINE) == 0) { ! 1722: if (kdb_bringonline(ui, 0)) { ! 1723: splx(s); ! 1724: return (-1); ! 1725: } ! 1726: } ! 1727: splx(s); ! 1728: if (st->blkoff > ra_dsize[unit]) ! 1729: return (-1); ! 1730: return (ra_dsize[unit] - st->blkoff); ! 1731: } ! 1732: return (st->nblocks); ! 1733: } ! 1734: ! 1735: #endif NKDB > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.