1: /*
   2:  * BR disk driver
   3:  * modified from the UNIX RP03 driver for BR disk drive -JM
   4:  * 11/11/84 - Added dump routine for taking 2.9 crash dumps in swap. -SMS
   5:  * 9/28/85  - Use brreg.h so as to look more like a 2.9 disk handler. -SMS
   6:  * 2/16/86  - Rewrite!  Drop the bropen, brclose and brgch functions.  Do
   7:  *	      initialization on a per drive basis rather than controller.
   8:  *	      The bropen and brclose functions were only used to perform
   9:  *	      the init'ing of a drive, and there was a problem in single
  10:  *	      user mode where a 'umount' could close the device before all
  11:  *	      data for that filesystem was written out thereby giving offline
  12:  *	      errors and causing corruption of the disc.  Also defined a
  13:  *	      disc slice that encompassed the whole drive for ease in copying,
  14:  *	      several other mods made because this was done.  Overall, several
  15:  *	      pages of code were removed. -SMS
  16:  *	      Just discovered that bropen() and brclose() were defined as
  17:  *	      nulldev() in c.c!  Wasted code all this time!  The offline errors
  18:  *	      observed were a result of entry into brstrategy() during a
  19:  *	      'umount' when bropen() had never been called in the first place!!!
  20:  * 12/6/87  - Changes to run under 2.10bsd.  Still single controller only.
  21:  *	      Considering we don't make the controller any more that's fairly
  22:  *	      safe to assume.  Partitions drastically changed to allow room
  23:  *	      on T300 and T200 to hold the source distribution.
  24:  *	      Autoconfigure logic finally added though. -SMS
  25:  * 2/17/89  - For 2.10.1BSD added old 2.9BSD /usr,/userfiles, and /minkie
  26:  *	      partitions as partitions 'e', 'f', and 'g' as an aid in
  27:  *	      converting the systems.  BE CAREFUL!  For T300 only.
  28:  * 8/4/89   - Use the log() function to record soft errors.
  29:  * 9/22/91  - remove read and write entry - use common raw read/write routine.
  30:  * 12/23/92 - add the partition size routine.
  31:  * 1/2/93   - remove unibus map ifdefs, the run time check using 'ubmap' is
  32:  *	      sufficient and does the right thing.
  33:  * 1995/04/13 - change reference to dkunit.
  34:  */
  35: 
  36: #include "br.h"
  37: #if NBR > 0
  38: 
  39: #include "param.h"
  40: #include "../machine/seg.h"
  41: 
  42: #include "systm.h"
  43: #include "buf.h"
  44: #include "conf.h"
  45: #include "user.h"
  46: #include "brreg.h"
  47: #include "dk.h"
  48: #include "disklabel.h"
  49: #include "disk.h"
  50: #include "syslog.h"
  51: #include "map.h"
  52: #include "uba.h"
  53: 
  54: #define BRADDR ((struct brdevice *) 0176710)
  55: #define brunit(dev) ((dev >> 3) & 7)
  56: #define SECTRK  brc->sectrk
  57: #define TRKCYL  brc->trkcyl
  58: 
  59: struct br_char {
  60:     struct br_dsz {
  61:         daddr_t nblocks;
  62:         int cyloff;
  63:     } br_sizes[8];
  64:     int sectrk, trkcyl;
  65: } br_chars[] =
  66: {               /* T300 */
  67:     18240,   0,     /* cyl 000 - 029 */
  68:     12160,  30,     /* cyl 030 - 049 */
  69:     232256, 50,     /* cyl 050 - 431 */
  70:     232256, 432,        /* cyl 432 - 813 */
  71:     154432,  50,        /* 'e' is old 2.9 'c' partition */
  72:     154432,  304,       /* 'f' is old 2.9 'd' partition */
  73:     154432,  558,       /* 'g' is old 2.9 'e' partition */
  74:     495520,  0,     /* cyl 000 - 814 */
  75:     32,  19,        /* 32 sectrk, 19 trkcyl */
  76:  /* T200 */
  77:     18392,  0,      /* cyl 000 - 043 */
  78:     12122,  43,     /* cyl 044 - 072 */
  79:     231990, 73,     /* cyl 073 - 627 */
  80:     78166,  443,            /* cyl 628 - 814 */
  81:     0,  0,
  82:     0,  0,
  83:     0,      0,
  84:     340670, 0,      /* cyl 000 - 814  */
  85:     22,     19,     /* 22 sectrk, 19 trkcyl */
  86: /* T80 */
  87:     18400,    0,        /* cyl 000 - 114 */
  88:     12320,  115,        /* cyl 115 - 190 */
  89:     99840,  191,        /* cyl 191 - 814 */
  90:     0,    0,
  91:     0,    0,
  92:     0,    0,
  93:     0,    0,
  94:     130300,   0,
  95:     32,   5,        /* 32 sectrk, 5 trkcyl */
  96: /* T50 */
  97:     18260,    0,        /* cyl 000 - 165 */
  98:     12210,  166,        /* cyl 166 - 276 */
  99:     59180,  277,        /* cyl 277 - 814 */
 100:     0,    0,
 101:     0,    0,
 102:     0,    0,
 103:     0,    0,
 104:     89650,    0,
 105:     22,   5,        /* 22 sectrk, 5 trkcyl */
 106: };
 107: 
 108: /*
 109:  * Define the recovery strobes and offsets in br_da
 110:  */
 111: static int br_offs[] = {
 112:     0,      0,      0,      STBE,
 113:     STBE,       STBL,       STBL,       OFFP+STBL,
 114:     OFFP+STBL,  OFFP,       OFFP,       OFFP+STBE,
 115:     OFFP+STBE,  OFFM+STBE,  OFFM+STBE,  OFFP,
 116:     OFFP,       OFFP+STBL,  OFFP+STBL,  0
 117: };
 118: 
 119: #ifdef UCB_METER
 120: static int br_dkn = -1;
 121: #endif
 122: struct buf brtab;
 123: struct br_char *br_disk[NBR];
 124: struct brdevice *Br_addr;
 125: 
 126: brroot()
 127: {
 128:     brattach((struct brdevice *)BRADDR, 0);
 129: }
 130: 
 131: brattach(braddr, unit)
 132:     register struct brdevice *braddr;
 133:     int unit;
 134: {
 135: 
 136: #ifdef UCB_METER
 137:     if (br_dkn < 0)
 138:         dk_alloc(&br_dkn, NBR, "br", 0L);
 139: #endif
 140:     if (unit >= NBR)
 141:         return(0);
 142:     if (braddr && (fioword(braddr) != -1)) {
 143:         Br_addr = braddr;
 144:         return(1);
 145:     }
 146:     return(0);
 147: }
 148: 
 149: bropen(dev, flag)
 150:     dev_t   dev;
 151:     int flag;
 152: {
 153:     register int dn = brunit(dev);
 154: 
 155:     if  (dn >= NBR || !Br_addr)
 156:         return(ENXIO);
 157:     if  (!br_disk[dn])
 158:         brinit(dn);
 159:     if  (!br_disk[dn])
 160:         return(EIO);
 161:     return(0);
 162: }
 163: 
 164: brstrategy(bp)
 165:     register struct buf *bp;
 166: {
 167:     register struct buf *dp;
 168:     register int unit;
 169:     struct br_char *brc;
 170:     struct br_dsz *brz;
 171:     long sz;
 172:     int drive, s;
 173: 
 174:     unit = bp->b_dev & 07;
 175:     drive = brunit(bp->b_dev);
 176:     if  (!(brc = br_disk[drive])) {
 177:         brinit(drive);
 178:         if (!(brc = br_disk[drive])) {
 179:             bp->b_error = ENODEV;
 180:             bp->b_flags |= B_ERROR;
 181:             iodone(bp);
 182:             return;
 183:         }
 184:     }
 185:     brz = &brc->br_sizes[unit];
 186:     sz = (bp->b_bcount + 511L) >> 9;
 187:     if (bp->b_blkno == brz->nblocks) {
 188:         bp->b_resid = bp->b_bcount;
 189:         iodone(bp);
 190:         return;
 191:     }
 192:     if (bp->b_blkno + sz > brz->nblocks) {
 193:         bp->b_error = EINVAL;
 194:         bp->b_flags |= B_ERROR;
 195:         iodone(bp);
 196:         return;
 197:     }
 198:     if (Br_addr->brae >= 0)
 199:         mapalloc(bp);
 200:     bp->b_cylin = bp->b_blkno/(SECTRK*TRKCYL) + brz->cyloff;
 201:     s = splbio();
 202:     dp = &brtab;
 203:     disksort(dp, bp);
 204:     if (dp->b_active == NULL)
 205:         brstart();
 206:     splx(s);
 207: }
 208: 
 209: static
 210: brstart()
 211: {
 212:     register struct buf *bp;
 213:     register int unit;
 214:     int com,cn,tn,sn,dn;
 215:     daddr_t bn;
 216:     struct br_char *brc;
 217:     struct br_dsz *brz;
 218: 
 219:     if ((bp = brtab.b_actf) == NULL)
 220:         return;
 221:     Br_addr->brds = -1;
 222:     brtab.b_active++;
 223:     if (!(Br_addr->brcs.w & BR_RDY)) {
 224:         timeout(brstart, 0, 4);
 225:         return;
 226:     }
 227:     unit = bp->b_dev & 07;
 228:     dn = brunit(bp->b_dev);
 229:     if (!(brc = br_disk[dn])) {
 230:         brinit(dn);
 231:         if (!(brc = br_disk[dn])) {
 232:             bp->b_flags |= B_ERROR;
 233:             brdone(bp);
 234:             return;
 235:         }
 236:     }
 237:     brz = &brc->br_sizes[unit];
 238:     bn = bp->b_blkno;
 239:     cn = bn/(SECTRK*TRKCYL) + brz->cyloff;
 240:     sn = bn%(SECTRK*TRKCYL);
 241:     tn = sn/SECTRK;
 242:     sn = sn%SECTRK;
 243:     if (Br_addr->brae < 0)
 244:         Br_addr->brae = bp->b_xmem;
 245:     Br_addr->brcs.w = (dn<<8);
 246:     Br_addr->brda = (tn<<8) | sn;
 247:     cn |= br_offs[brtab.b_errcnt];
 248:     Br_addr->brca = cn;
 249:     Br_addr->brba = bp->b_un.b_addr;
 250:     Br_addr->brwc = -(bp->b_bcount>>1);
 251:     com = ((bp->b_xmem&3)<<4) | BR_IDE | BR_GO;
 252:     if (bp->b_flags & B_READ)
 253:         com |= BR_RCOM;
 254:     else
 255:         com |= BR_WCOM;
 256:     Br_addr->brcs.w |= com;
 257: #ifdef UCB_METER
 258:     if (br_dkn >= 0) {
 259:         dk_busy |= 1 << (br_dkn + dn);
 260:         dk_xfer[br_dkn + dn]++;
 261:         dk_seek[br_dkn + dn]++;
 262:         dk_wds[br_dkn + dn] += (bp->b_bcount >> 6);
 263:     }
 264: #endif
 265: }
 266: 
 267: static
 268: brinit(drive)
 269:     register int drive;
 270: {
 271:     register int ctr = 0;
 272:     register struct br_char **br = &br_disk[drive];
 273: 
 274:     /*
 275: 	 * Clear the drive's entry in br_disk.  Select the unit.  If the
 276: 	 * unit exists, switch on the spindle type. and set the br_disk
 277: 	 * table entry
 278: 	 */
 279:     *br = (struct br_char *)NULL;
 280:     do {
 281:         Br_addr->brcs.w = (drive << 8) | BR_HSEEK | BR_GO;
 282:         while ((Br_addr->brcs.w & BR_RDY) == 0 && --ctr) ;
 283:     } while (Br_addr->brer & BRER_SUBUSY);
 284:     if ((Br_addr->brcs.w & BR_HE) == 0) {
 285:         switch (Br_addr->brae & AE_DTYP) {
 286:         case AE_T300:
 287:             *br = &br_chars[0];
 288:             break;
 289:         case AE_T200:
 290:             *br = &br_chars[1];
 291:             break;
 292:         case AE_T80:
 293:             *br = &br_chars[2];
 294:             break;
 295:         case AE_T50:
 296:             *br = &br_chars[3];
 297:             break;
 298:         }
 299: #ifdef UCB_METER
 300:         if (br_dkn >= 0)
 301:             dk_wps[br_dkn + drive] =
 302:                 (long)(*br)->sectrk * (60L * 256L);
 303: #endif
 304:     }
 305: }
 306: 
 307: brintr(dev)
 308:     int dev;
 309: {
 310:     register struct buf *bp;
 311:     register int ctr = 0;
 312:     struct brdevice brsave;
 313: 
 314:     if (brtab.b_active == NULL)
 315:         return;
 316:     brsave = *Br_addr;
 317:     bp = brtab.b_actf;
 318:     if (!(brsave.brcs.w & BR_RDY))
 319:         return;
 320: #ifdef UCB_METER
 321:     if (br_dkn >= 0)
 322:         dk_busy &= ~(1<<(br_dkn + dev));
 323: #endif
 324:     if (brsave.brcs.w < 0) {
 325:         if (brsave.brer & BRER_SUBUSY) {
 326:             timeout(brstart, 0, 5);
 327:             return;
 328:         }
 329:         if (brsave.brds & (BRDS_SUFU|BRDS_SUSI|BRDS_HNF)) {
 330:             Br_addr->brcs.c[0] = BR_HSEEK|BR_GO;
 331:             while (((Br_addr->brds&BRDS_SURDY) == 0) && --ctr);
 332:         }
 333:         Br_addr->brcs.w = BR_IDLE|BR_GO;
 334:         ctr = 0;
 335:         while (((Br_addr->brcs.w&BR_RDY) == 0) && --ctr) ;
 336:         if (brtab.b_errcnt == 0) {
 337:             log(LOG_WARNING,"br%d%c ds:%b er:%b cs:%b wc:%o ba:%o ca:%o da:%o bae:%o\n",
 338:                 dkunit(bp->b_dev), 'a'+ dkpart(bp->b_dev),
 339:                 brsave.brds, BRDS_BITS, brsave.brer, BRER_BITS,
 340:                 brsave.brcs.w, BR_BITS, brsave.brwc,brsave.brba,
 341:                 brsave.brca, brsave.brda, brsave.brae);
 342:         }
 343:         brtab.b_errcnt++;
 344:         if (brtab.b_errcnt < 20) {
 345:             brstart();
 346:             return;
 347:         }
 348:         harderr(bp,"br");
 349:         bp->b_flags |= B_ERROR;
 350:     }
 351:     brdone(bp);
 352: }
 353: 
 354: static
 355: brdone (bp)
 356:     register struct buf *bp;
 357: {
 358:     brtab.b_active = NULL;
 359:     brtab.b_errcnt = 0;
 360:     brtab.b_actf = bp->av_forw;
 361:     bp->b_resid = 0;
 362:     iodone(bp);
 363:     brstart();
 364: }
 365: 
 366: #ifdef BR_DUMP
 367: /*
 368:  * Dump routine.  Dumps from dumplo to end of memory/end of disk section for
 369:  * minor(dev).
 370:  */
 371: #define DBSIZE  16          /* unit of transfer, same number */
 372: 
 373: brdump(dev)
 374:     dev_t dev;
 375: {
 376:     struct br_char *brc;
 377:     struct ubmap *ubp;
 378:     daddr_t bn, dumpsize;
 379:     long paddr;
 380:     int count, cyl, dn, cn, tn, sn, unit, com;
 381: 
 382:     unit = dev & 07;
 383:     dn = brunit(dev);
 384:     if ((bdevsw[major(dev)].d_strategy != brstrategy) || dn >= NBR)
 385:         return(EINVAL);
 386:     if (!Br_addr || !(brc = br_disk[dn]))
 387:         return(ENXIO);
 388:     dumpsize = brc->br_sizes[unit].nblocks;
 389:     cyl = brc->br_sizes[unit].cyloff;
 390:     if ((dumplo < 0) || (dumplo >= dumpsize))
 391:         return(EINVAL);
 392:     dumpsize -= dumplo;
 393:     while (!(Br_addr->brcs.w & BR_RDY));
 394:     ubp = &UBMAP[0];
 395:     for (paddr = 0L; dumpsize > 0; dumpsize -= count) {
 396:         count = dumpsize > DBSIZE ? DBSIZE : dumpsize;
 397:         bn = dumplo + (paddr >> PGSHIFT);
 398:         cn = (bn / (SECTRK * TRKCYL)) + cyl;
 399:         sn = bn % (SECTRK * TRKCYL);
 400:         tn = sn / SECTRK;
 401:         sn = sn % SECTRK;
 402:         Br_addr->brca = cn;
 403:         Br_addr->brda = (tn << 8) | sn;
 404:         Br_addr->brwc = -(count << (PGSHIFT-1));
 405:         com = (dn << 8) | BR_GO | BR_WCOM;
 406:         if (ubmap && Br_addr->brae >= 0) {
 407:             ubp->ub_lo = loint(paddr);
 408:             ubp->ub_hi = hiint(paddr);
 409:             Br_addr->brba = 0;
 410:         }
 411:         else {
 412:             Br_addr->brba = (caddr_t)loint(paddr);
 413:             Br_addr->brae = hiint(paddr);
 414:             com |= ((hiint(paddr) & 3) << 4);
 415:         }
 416:         Br_addr->brcs.w = com;
 417:         while (!(Br_addr->brcs.w & BR_RDY));
 418:         if (Br_addr->brcs.w < 0) {
 419:             if (Br_addr->brer & BRER_NXME)
 420:                 return(0);  /* end of memory */
 421:             return(EIO);
 422:         }
 423:         paddr += (DBSIZE << PGSHIFT);
 424:     }
 425:     return(0);              /* filled disk */
 426: }
 427: #endif /* BR_DUMP */
 428: 
 429: /*
 430:  * Assumes the 'open' entry point has been called to validate the unit
 431:  * number and fill in the drive type structure.
 432: */
 433: daddr_t
 434: brsize(dev)
 435:     register dev_t dev;
 436:     {
 437:     register struct br_char *brc;
 438: 
 439:     brc = br_disk[brunit(dev)];
 440:     return(brc->br_sizes[dev & 7].nblocks);
 441:     }
 442: #endif /* NBR */

Defined functions

brattach defined in line 131; used 1 times
brdone defined in line 354; used 2 times
brdump defined in line 373; never used
brinit defined in line 267; used 3 times
brintr defined in line 307; used 1 times
bropen defined in line 149; never used
brroot defined in line 126; never used
brsize defined in line 433; never used
brstart defined in line 209; used 5 times
brstrategy defined in line 164; used 1 times

Defined variables

Br_addr defined in line 124; used 36 times
br_chars defined in line 65; used 4 times
br_disk defined in line 123; used 9 times
br_dkn defined in line 120; used 11 times
br_offs defined in line 111; used 1 times
brtab defined in line 122; used 12 times

Defined struct's

br_char defined in line 59; used 14 times
br_dsz defined in line 60; used 4 times

Defined macros

BRADDR defined in line 54; used 1 times
DBSIZE defined in line 371; used 3 times
SECTRK defined in line 56; used 9 times
TRKCYL defined in line 57; used 5 times
brunit defined in line 55; used 5 times
Last modified: 1995-04-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4020
Valid CSS Valid XHTML 1.0 Strict