# 2.11BSD#431 - /usr/src/sys/pdpuba/hk.c

##### Functions

    hkattach          X
    hkclose           X
    hkdfltlbl         X
    hkdump            X
    hkecc             X
    hkgetinfo         X
    hkintr            X
    hkopen            X
    hkroot            X
    hksize            X
    hkstart           X
    hkstrategy        X
    hkustart          X

##### Variables

    HKADDR            X
    bhkbuf            X
    hk                X
    hk_cyl            X
    hk_dk             X
    hk_offset         X
    hk_type           X
    hkbad             X
    hktab             X
    hkutab            X

##### Macros

    DBSIZE            X
    HK_NSECT          X
    HK_NSPC           X
    HK_NTRAC          X
    NHK6CYL           X
    NHK7CYL           X
    exadr             X
    hkncyl            X
    hkwait            X

##### struct's

    hk_softc          X

       1: /*
       2:  * Copyright (c) 1986 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  *
       6:  *	@(#)hk.c	2.3 (2.11BSD GTE) 1998/4/3
       7:  */
       8:
       9: /*
      10:  * RK611/RK0[67] disk driver
      11:  *
      12:  * Heavily modified for disklabel support.  Still only supports 1 controller
      13:  * (but who'd have more than one of these on a system anyhow?) - 1997/11/11 sms
      14:  *
      15:  * This driver mimics the 4.1bsd rk driver.
      16:  * It does overlapped seeks, ECC, and bad block handling.
      17:  * 	salkind@nyu
      18:  *
      19:  * dkunit() takes a 'dev_t' now instead of 'buf *'.  1995/04/13 - sms
      20:  *
      21:  * Removed ifdefs on both Q22 and UNIBUS_MAP, substituting a runtime
      22:  * test for presence of a Unibus Map.  Reworked the partition logic,
      23:  * the 'e' partiton no longer overlaps the 'a'+'b' partitions - a separate
      24:  * 'b' partition is now present.  Old root filesystems can still be used
      25:  * because the size is the same, but user data will have to be saved and
      26:  * then reloaded.  12/28/92 -- sms@wlv.iipo.gtegsc.com
      27:  *
      28:  * Modified to correctly handle 22 bit addressing available on DILOG
      29:  * DQ615 controller. 05/31/90 -- tymann@oswego.edu
      30:  *
      31:  */
      32:
      33: #include "hk.h"
      34: #if NHK > 0
      35: #include "param.h"
      36: #include "systm.h"
      37: #include "buf.h"
      38: #include "machine/seg.h"
      39: #include "conf.h"
      40: #include "user.h"
      41: #include "map.h"
      42: #include "uba.h"
      43: #include "hkreg.h"
      44: #include "dkbad.h"
      45: #include "dk.h"
      46: #include "stat.h"
      47: #include "file.h"
      48: #include "disklabel.h"
      49: #include "disk.h"
      50: #include "syslog.h"
      51:
      52: #define NHK7CYL 815
      53: #define NHK6CYL 411
      54: #define HK_NSECT    22
      55: #define HK_NTRAC    3
      56: #define HK_NSPC     (HK_NTRAC*HK_NSECT)
      57:
      58: struct  hkdevice *HKADDR;
      59:
      60:     daddr_t hksize();
      61:     void    hkdfltlbl();
      62:     int hkstrategy();
      63:
      64: /* Can be u_char because all are less than 0377 */
      65: u_char  hk_offset[] =
      66:     {
      67:     HKAS_P400,  HKAS_M400,  HKAS_P400,  HKAS_M400,
      68:     HKAS_P800,  HKAS_M800,  HKAS_P800,  HKAS_M800,
      69:     HKAS_P1200, HKAS_M1200, HKAS_P1200, HKAS_M1200,
      70:     0,      0,      0,      0,
      71:     };
      72:
      73:     int hk_type[NHK];
      74:     int hk_cyl[NHK];
      75:
      76: struct hk_softc
      77:     {
      78:     int sc_softas;
      79:     int sc_recal;
      80:     } hk;
      81:
      82:     struct  buf hktab;
      83:     struct  buf hkutab[NHK];
      84:     struct  dkdevice hk_dk[NHK];
      85:
      86: #ifdef BADSECT
      87:     struct  dkbad   hkbad[NHK];
      88:     struct  buf bhkbuf[NHK];
      89: #endif
      90:
      91: #ifdef UCB_METER
      92:     static  int     hk_dkn = -1;    /* number for iostat */
      93: #endif
      94:
      95: #define hkwait(hkaddr)      while ((hkaddr->hkcs1 & HK_CRDY) == 0)
      96: #define hkncyl(unit)        (hk_type[unit] ? NHK7CYL : NHK6CYL)
      97:
      98: void
      99: hkroot()
     100:     {
     101:     hkattach((struct hkdevice *)0177440, 0);
     102:     }
     103:
     104: hkattach(addr, unit)
     105: struct hkdevice *addr;
     106:     {
     107: #ifdef UCB_METER
     108:     if  (hk_dkn < 0)
     109:         {
     110:         dk_alloc(&hk_dkn, NHK+1, "hk", 60L * (long)HK_NSECT * 256L);
     111:         if  (hk_dkn >= 0)
     112:             dk_wps[hk_dkn+NHK] = 0L;
     113:         }
     114: #endif
     115:     if (unit != 0)
     116:         return(0);
     117:     HKADDR = addr;
     118:     return(1);
     119:     }
     120:
     121: hkopen(dev, flag, mode)
     122:     dev_t   dev;
     123:     int flag;
     124:     int mode;
     125:     {
     126:     register int unit = dkunit(dev);
     127:     register struct hkdevice *hkaddr = HKADDR;
     128:     register struct dkdevice *disk;
     129:     int i, mask;
     130:
     131:     if  (unit >= NHK || !HKADDR)
     132:         return(ENXIO);
     133:     disk = &hk_dk[unit];
     134:
     135:     if  ((disk->dk_flags & DKF_ALIVE) == 0)
     136:         {
     137:         hk_type[unit] = 0;
     138:         hkaddr->hkcs1 = HK_CCLR;
     139:         hkaddr->hkcs2 = unit;
     140:         hkaddr->hkcs1 = HK_DCLR | HK_GO;
     141:         hkwait(hkaddr);
     142:         if  (hkaddr->hkcs2&HKCS2_NED || !(hkaddr->hkds&HKDS_SVAL))
     143:             {
     144:             hkaddr->hkcs1 = HK_CCLR;
     145:             hkwait(hkaddr);
     146:             return(ENXIO);
     147:             }
     148:         disk->dk_flags |= DKF_ALIVE;
     149:         if  ((hkaddr->hkcs1&HK_CERR) && (hkaddr->hker&HKER_DTYE))
     150:             {
     151:             hk_type[unit] = HK_CDT;
     152:             hkaddr->hkcs1 = HK_CCLR;
     153:             hkwait(hkaddr);
     154:             }
     155:         }
     156: /*
     157:  * The drive has responded to a probe (is alive).  Now we read the
     158:  * label.  Allocate an external label structure if one has not already
     159:  * been assigned to this drive.  First wait for any pending opens/closes
     160:  * to complete.
     161: */
     162:     while   (disk->dk_flags & (DKF_OPENING | DKF_CLOSING))
     163:         sleep(disk, PRIBIO);
     164:
     165: /*
     166:  * Next if an external label buffer has not already been allocated do so now.
     167:  * This "can not fail" because if the initial pool of label buffers has
     168:  * been exhausted the allocation takes place from main memory.  The return
     169:  * value is the 'click' address to be used when mapping in the label.
     170: */
     171:
     172:     if  (disk->dk_label == 0)
     173:         disk->dk_label = disklabelalloc();
     174:
     175: /*
     176:  * On first open get label and partition info.  We may block reading the
     177:  * label so be careful to stop any other opens.
     178: */
     179:     if  (disk->dk_openmask == 0)
     180:         {
     181:         disk->dk_flags |= DKF_OPENING;
     182:         hkgetinfo(disk, dev);
     183:         disk->dk_flags &= ~DKF_OPENING;
     184:         wakeup(disk);
     185:         hk_cyl[unit] = -1;
     186:         }
     187: /*
     188:  * Need to make sure the partition is not out of bounds.  This requires
     189:  * mapping in the external label.  This only happens when a partition
     190:  * is opened (at mount time) and isn't an efficiency problem.
     191: */
     192:     mapseg5(disk->dk_label, LABELDESC);
     193:     i = ((struct disklabel *)SEG5)->d_npartitions;
     194:     normalseg5();
     195:     if  (dkpart(dev) >= i)
     196:         return(ENXIO);
     197:     mask = 1 << dkpart(dev);
     198:     dkoverlapchk(disk->dk_openmask, dev, disk->dk_label, "hk");
     199:     if  (mode == S_IFCHR)
     200:         disk->dk_copenmask |= mask;
     201:     else if (mode == S_IFBLK)
     202:         disk->dk_bopenmask |= mask;
     203:     else
     204:         return(EINVAL);
     205:     disk->dk_openmask |= mask;
     206:     return(0);
     207:     }
     208:
     209: /*
     210:  * Disk drivers now have to have close entry points in order to keep
     211:  * track of what partitions are still active on a drive.
     212: */
     213: hkclose(dev, flag, mode)
     214: register dev_t  dev;
     215:     int     flag, mode;
     216:     {
     217:     int     s, drive = dkunit(dev);
     218:     register int    mask;
     219:     register struct dkdevice *disk;
     220:
     221:     disk = &hk_dk[drive];
     222:     mask = 1 << dkpart(dev);
     223:     if  (mode == S_IFCHR)
     224:         disk->dk_copenmask &= ~mask;
     225:     else if (mode == S_IFBLK)
     226:         disk->dk_bopenmask &= ~mask;
     227:     else
     228:         return(EINVAL);
     229:     disk->dk_openmask = disk->dk_bopenmask | disk->dk_copenmask;
     230:     if  (disk->dk_openmask == 0)
     231:         {
     232:         disk->dk_flags |= DKF_CLOSING;
     233:         s = splbio();
     234:         while   (hkutab[drive].b_actf)
     235:             {
     236:             disk->dk_flags |= DKF_WANTED;
     237:             sleep(&hkutab[drive], PRIBIO);
     238:             }
     239:         splx(s);
     240: /*
     241:  * On last close of a drive we declare it not alive and offline to force a
     242:  * probe on the next open in order to handle diskpack changes.
     243: */
     244:         disk->dk_flags &=
     245:             ~(DKF_CLOSING | DKF_WANTED | DKF_ALIVE | DKF_ONLINE);
     246:         wakeup(disk);
     247:         }
     248:     return(0);
     249:     }
     250:
     251: /*
     252:  * This code moved here from hkgetinfo() because it is fairly large and used
     253:  * twice - once to initialize for reading the label and a second time if
     254:  * there is no valid label present on the drive and the default one must be
     255:  * used to span the drive.
     256: */
     257:
     258: void
     259: hkdfltlbl(disk, lp, dev)
     260:     struct dkdevice *disk;
     261:     register struct disklabel *lp;
     262:     dev_t   dev;
     263:     {
     264:     register struct partition *pi = &lp->d_partitions[0];
     265:
     266:     bzero(lp, sizeof (*lp));
     267:         lp->d_type = DTYPE_DEC;
     268:     lp->d_secsize = 512;            /* XXX */
     269:     lp->d_nsectors = HK_NSECT;
     270:     lp->d_ntracks = HK_NTRAC;
     271:     lp->d_secpercyl = HK_NSPC;
     272:     lp->d_npartitions = 1;          /* 'a' */
     273:     lp->d_ncylinders = hkncyl(dkunit(dev));
     274:     pi->p_size = lp->d_ncylinders * lp->d_secpercyl;     /* entire volume */
     275:     pi->p_fstype = FS_V71K;
     276:     pi->p_frag = 1;
     277:     pi->p_fsize = 1024;
     278: /*
     279:  * Put where hkstrategy() will look.
     280: */
     281:     bcopy(pi, disk->dk_parts, sizeof (lp->d_partitions));
     282:     }
     283:
     284: /*
     285:  * Read disklabel.  It is tempting to generalize this routine so that
     286:  * all disk drivers could share it.  However by the time all of the
     287:  * necessary parameters are setup and passed the savings vanish.  Also,
     288:  * each driver has a different method of calculating the number of blocks
     289:  * to use if one large partition must cover the disk.
     290:  *
     291:  * This routine used to always return success and callers carefully checked
     292:  * the return status.  Silly.  This routine will fake a label (a single
     293:  * partition spanning the drive) if necessary but will never return an error.
     294:  *
     295:  * It is the caller's responsibility to check the validity of partition
     296:  * numbers, etc.
     297: */
     298:
     299: void
     300: hkgetinfo(disk, dev)
     301: register struct dkdevice *disk;
     302:     dev_t   dev;
     303:     {
     304:     struct  disklabel locallabel;
     305:     char    *msg;
     306:     register struct disklabel *lp = &locallabel;
     307: /*
     308:  * NOTE: partition 0 ('a') is used to read the label.  Therefore 'a' must
     309:  * start at the beginning of the disk!  If there is no label or the label
     310:  * is corrupted then 'a' will span the entire disk
     311: */
     312:     hkdfltlbl(disk, lp, dev);
     313:     msg = readdisklabel((dev & ~7) | 0, hkstrategy, lp);    /* 'a' */
     314:     if      (msg != 0)
     315:         {
     316:         log(LOG_NOTICE, "hk%da is entire disk: %s\n", dkunit(dev), msg);
     317:         hkdfltlbl(disk, lp, dev);
     318:         }
     319:     mapseg5(disk->dk_label, LABELDESC)
     320:     bcopy(lp, (struct disklabel *)SEG5, sizeof (struct disklabel));
     321:     normalseg5();
     322:     bcopy(lp->d_partitions, disk->dk_parts, sizeof (lp->d_partitions));
     323:     return;
     324:     }
     325:
     326: hkstrategy(bp)
     327: register struct buf *bp;
     328: {
     329:     register struct buf *dp;
     330:     int s, drive;
     331:     register struct dkdevice *disk;
     332:
     333:     drive = dkunit(bp->b_dev);
     334:     disk = &hk_dk[drive];
     335:
     336:     if  (drive >= NHK || !HKADDR  || !(disk->dk_flags & DKF_ALIVE))
     337:         {
     338:         bp->b_error = ENXIO;
     339:         goto bad;
     340:         }
     341:     s = partition_check(bp, disk);
     342:     if  (s < 0)
     343:         goto bad;
     344:     if  (s == 0)
     345:         goto done;
     346:
     347:     bp->b_cylin = bp->b_blkno / HK_NSPC;
     348:     mapalloc(bp);
     349:     dp = &hkutab[drive];
     350:     s = splbio();
     351:     disksort(dp, bp);
     352:     if  (dp->b_active == 0)
     353:         {
     354:         hkustart(drive);
     355:         if  (hktab.b_active == 0)
     356:             hkstart();
     357:         }
     358:     splx(s);
     359:     return;
     360: bad:
     361:     bp->b_flags |= B_ERROR;
     362: done:
     363:     iodone(bp);
     364:     }
     365:
     366: hkustart(unit)
     367:     int unit;
     368: {
     369:     register struct hkdevice *hkaddr = HKADDR;
     370:     register struct buf *bp, *dp;
     371:     struct dkdevice *disk;
     372:     int didie = 0;
     373:
     374: #ifdef UCB_METER
     375:     if (hk_dkn >= 0)
     376:         dk_busy &= ~(1 << (hk_dkn + unit));
     377: #endif
     378:     if (hktab.b_active) {
     379:         hk.sc_softas |= (1 << unit);
     380:         return(0);
     381:     }
     382:
     383:     hkaddr->hkcs1 = HK_CCLR;
     384:     hkaddr->hkcs2 = unit;
     385:     hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO;
     386:     hkwait(hkaddr);
     387:
     388:     dp = &hkutab[unit];
     389:     disk = &hk_dk[unit];
     390:     if ((bp = dp->b_actf) == NULL)
     391:         return(0);
     392:     if (dp->b_active)
     393:         goto done;
     394:     dp->b_active = 1;
     395:     if  (!(hkaddr->hkds & HKDS_VV) || !(disk->dk_flags & DKF_ONLINE))
     396:         {
     397:         /* SHOULD WARN SYSTEM THAT THIS HAPPENED */
     398: #ifdef BADSECT
     399:         struct buf *bbp = &bhkbuf[unit];
     400: #endif
     401:
     402:         hkaddr->hkcs1 = hk_type[unit]|HK_PACK|HK_GO;
     403:         disk->dk_flags |= DKF_ONLINE;
     404: /*
     405:  * XXX - The 'c' partition is used below to access the bad block area.  This
     406:  * XXX - is DIFFERENT than the XP driver (which should have used 'c' but could
     407:  * XXX - not due to historical reasons).  The 'c' partition MUST span the entire
     408:  * XXX - disk including the bad sector track.  The 'h' partition should be
     409:  * XXX - used for user data.
     410: */
     411: #ifdef BADSECT
     412:         bbp->b_flags = B_READ|B_BUSY|B_PHYS;
     413:         bbp->b_dev = (bp->b_dev & ~7) | ('c' - 'a');
     414:         bbp->b_bcount = sizeof(struct dkbad);
     415:         bbp->b_un.b_addr = (caddr_t)&hkbad[unit];
     416:         bbp->b_blkno = (long)hkncyl(unit)*HK_NSPC - HK_NSECT;
     417:         bbp->b_cylin = hkncyl(unit) - 1;
     418:         mapalloc(bbp);
     419:         dp->b_actf = bbp;
     420:         bbp->av_forw = bp;
     421:         bp = bbp;
     422: #endif
     423:         hkwait(hkaddr);
     424:         }
     425:     if  ((hkaddr->hkds & HKDS_DREADY) != HKDS_DREADY)
     426:         {
     427:         disk->dk_flags &= ~DKF_ONLINE;
     428:         goto done;
     429:         }
     430: #ifdef NHK > 1
     431:     if (bp->b_cylin == hk_cyl[unit])
     432:         goto done;
     433:     hkaddr->hkcyl = bp->b_cylin;
     434:     hk_cyl[unit] = bp->b_cylin;
     435:     hkaddr->hkcs1 = hk_type[unit] | HK_IE | HK_SEEK | HK_GO;
     436:     didie = 1;
     437: #ifdef UCB_METER
     438:     if (hk_dkn >= 0) {
     439:         int dkn = hk_dkn + unit;
     440:
     441:         dk_busy |= 1<<dkn;
     442:         dk_seek[dkn]++;
     443:     }
     444: #endif
     445:     return (didie);
     446: #endif NHK > 1
     447:
     448: done:
     449:     if (dp->b_active != 2) {
     450:         dp->b_forw = NULL;
     451:         if (hktab.b_actf == NULL)
     452:             hktab.b_actf = dp;
     453:         else
     454:             hktab.b_actl->b_forw = dp;
     455:         hktab.b_actl = dp;
     456:         dp->b_active = 2;
     457:     }
     458:     return (didie);
     459: }
     460:
     461: hkstart()
     462: {
     463:     register struct buf *bp, *dp;
     464:     register struct hkdevice *hkaddr = HKADDR;
     465:     register struct dkdevice *disk;
     466:     daddr_t bn;
     467:     int sn, tn, cmd, unit;
     468:
     469: loop:
     470:     if ((dp = hktab.b_actf) == NULL)
     471:         return(0);
     472:     if ((bp = dp->b_actf) == NULL) {
     473: /*
     474:  * No more requests for this drive, remove from controller queue and
     475:  * look at next drive.  We know we're at the head of the controller queue.
     476:  * The drive may not need anything, in which case it might be shutting
     477:  * down in hkclose() and a wakeup is done.
     478: */
     479:         hktab.b_actf = dp->b_forw;
     480:         unit = dp - hkutab;
     481:         disk = &hk_dk[unit];
     482:         if  (disk->dk_flags & DKF_WANTED)
     483:             {
     484:             disk->dk_flags &= ~DKF_WANTED;
     485:             wakeup(dp); /* finish the close protocol */
     486:             }
     487:         goto loop;
     488:     }
     489:     hktab.b_active++;
     490:     unit = dkunit(bp->b_dev);
     491:     disk = &hk_dk[unit];
     492:     bn = bp->b_blkno;
     493:
     494:     sn = bn % HK_NSPC;
     495:     tn = sn / HK_NSECT;
     496:     sn %= HK_NSECT;
     497: retry:
     498:     hkaddr->hkcs1 = HK_CCLR;
     499:     hkaddr->hkcs2 = unit;
     500:     hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO;
     501:     hkwait(hkaddr);
     502:
     503:     if ((hkaddr->hkds & HKDS_SVAL) == 0)
     504:         goto nosval;
     505:     if (hkaddr->hkds & HKDS_PIP)
     506:         goto retry;
     507:     if ((hkaddr->hkds&HKDS_DREADY) != HKDS_DREADY) {
     508:         disk->dk_flags &= ~DKF_ONLINE;
     509:         log(LOG_WARNING, "hk%d: !ready\n", unit);
     510:         if ((hkaddr->hkds&HKDS_DREADY) != HKDS_DREADY) {
     511:             hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO;
     512:             hkwait(hkaddr);
     513:             hkaddr->hkcs1 = HK_CCLR;
     514:             hkwait(hkaddr);
     515:             hktab.b_active = 0;
     516:             hktab.b_errcnt = 0;
     517:             dp->b_actf = bp->av_forw;
     518:             dp->b_active = 0;
     519:             bp->b_flags |= B_ERROR;
     520:             iodone(bp);
     521:             goto loop;
     522:         }
     523:     }
     524:     disk->dk_flags |= DKF_ONLINE;
     525: nosval:
     526:     hkaddr->hkcyl = bp->b_cylin;
     527:     hk_cyl[unit] = bp->b_cylin;
     528:     hkaddr->hkda = (tn << 8) + sn;
     529:     hkaddr->hkwc = -(bp->b_bcount >> 1);
     530:     hkaddr->hkba = bp->b_un.b_addr;
     531:     if  (!ubmap)
     532:         hkaddr->hkxmem=bp->b_xmem;
     533:
     534:     cmd = hk_type[unit] | ((bp->b_xmem & 3) << 8) | HK_IE | HK_GO;
     535:     if (bp->b_flags & B_READ)
     536:         cmd |= HK_READ;
     537:     else
     538:         cmd |= HK_WRITE;
     539:     hkaddr->hkcs1 = cmd;
     540: #ifdef UCB_METER
     541:     if (hk_dkn >= 0) {
     542:         int dkn = hk_dkn + NHK;
     543:
     544:         dk_busy |= 1<<dkn;
     545:         dk_xfer[dkn]++;
     546:         dk_wds[dkn] += bp->b_bcount>>6;
     547:     }
     548: #endif
     549:     return(1);
     550: }
     551:
     552: hkintr()
     553: {
     554:     register struct hkdevice *hkaddr = HKADDR;
     555:     register struct buf *bp, *dp;
     556:     int unit;
     557:     int as = (hkaddr->hkatt >> 8) | hk.sc_softas;
     558:     int needie = 1;
     559:
     560:     hk.sc_softas = 0;
     561:     if (hktab.b_active) {
     562:         dp = hktab.b_actf;
     563:         bp = dp->b_actf;
     564:         unit = dkunit(bp->b_dev);
     565: #ifdef UCB_METER
     566:         if (hk_dkn >= 0)
     567:             dk_busy &= ~(1 << (hk_dkn + NHK));
     568: #endif
     569: #ifdef BADSECT
     570:         if (bp->b_flags&B_BAD)
     571:             if (hkecc(bp, CONT))
     572:                 return;
     573: #endif
     574:         if (hkaddr->hkcs1 & HK_CERR) {
     575:             int recal;
     576:             u_short ds = hkaddr->hkds;
     577:             u_short cs2 = hkaddr->hkcs2;
     578:             u_short er = hkaddr->hker;
     579:
     580:             if (er & HKER_WLE) {
     581:                 log(LOG_WARNING, "hk%d: wrtlck\n", unit);
     582:                 bp->b_flags |= B_ERROR;
     583:             } else if (++hktab.b_errcnt > 28 ||
     584:                 ds&HKDS_HARD || er&HKER_HARD || cs2&HKCS2_HARD) {
     585: hard:
     586:                 harderr(bp, "hk");
     587:                 log(LOG_WARNING, "cs2=%b ds=%b er=%b\n",
     588:                     cs2, HKCS2_BITS, ds,
     589:                     HKDS_BITS, er, HKER_BITS);
     590:                 bp->b_flags |= B_ERROR;
     591:                 hk.sc_recal = 0;
     592:             } else if (er & HKER_BSE) {
     593: #ifdef BADSECT
     594:                 if (hkecc(bp, BSE))
     595:                     return;
     596:                 else
     597: #endif
     598:                     goto hard;
     599:             } else
     600:                 hktab.b_active = 0;
     601:             if (cs2&HKCS2_MDS) {
     602:                 hkaddr->hkcs2 = HKCS2_SCLR;
     603:                 goto retry;
     604:             }
     605:             recal = 0;
     606:             if (ds&HKDS_DROT || er&(HKER_OPI|HKER_SKI|HKER_UNS) ||
     607:                 (hktab.b_errcnt&07) == 4)
     608:                 recal = 1;
     609:             if ((er & (HKER_DCK|HKER_ECH)) == HKER_DCK)
     610:                 if (hkecc(bp, ECC))
     611:                     return;
     612:             hkaddr->hkcs1 = HK_CCLR;
     613:             hkaddr->hkcs2 = unit;
     614:             hkaddr->hkcs1 = hk_type[unit]|HK_DCLR|HK_GO;
     615:             hkwait(hkaddr);
     616:             if (recal && hktab.b_active == 0) {
     617:                 hkaddr->hkcs1 = hk_type[unit]|HK_IE|HK_RECAL|HK_GO;
     618:                 hk_cyl[unit] = -1;
     619:                 hk.sc_recal = 0;
     620:                 goto nextrecal;
     621:             }
     622:         }
     623: retry:
     624:         switch (hk.sc_recal) {
     625:
     626:         case 1:
     627:             hkaddr->hkcyl = bp->b_cylin;
     628:             hk_cyl[unit] = bp->b_cylin;
     629:             hkaddr->hkcs1 = hk_type[unit]|HK_IE|HK_SEEK|HK_GO;
     630:             goto nextrecal;
     631:         case 2:
     632:             if (hktab.b_errcnt < 16 ||
     633:                 (bp->b_flags&B_READ) == 0)
     634:                 goto donerecal;
     635:             hkaddr->hkatt = hk_offset[hktab.b_errcnt & 017];
     636:             hkaddr->hkcs1 = hk_type[unit]|HK_IE|HK_OFFSET|HK_GO;
     637:             /* fall into ... */
     638:         nextrecal:
     639:             hk.sc_recal++;
     640:             hkwait(hkaddr);
     641:             hktab.b_active = 1;
     642:             return;
     643:         donerecal:
     644:         case 3:
     645:             hk.sc_recal = 0;
     646:             hktab.b_active = 0;
     647:             break;
     648:         }
     649:         if (hktab.b_active) {
     650:             hktab.b_active = 0;
     651:             hktab.b_errcnt = 0;
     652:             hktab.b_actf = dp->b_forw;
     653:             dp->b_active = 0;
     654:             dp->b_errcnt = 0;
     655:             dp->b_actf = bp->av_forw;
     656:             bp->b_resid = -(hkaddr->hkwc << 1);
     657:             iodone(bp);
     658:             if (dp->b_actf)
     659:                 if (hkustart(unit))
     660:                     needie = 0;
     661:         }
     662:         as &= ~(1<<unit);
     663:     }
     664:     for (unit = 0; as; as >>= 1, unit++)
     665:         if (as & 1) {
     666:             if (unit < NHK && (hk_dk[unit].dk_flags & DKF_ALIVE)) {
     667:                 if (hkustart(unit))
     668:                     needie = 0;
     669:             } else {
     670:                 hkaddr->hkcs1 = HK_CCLR;
     671:                 hkaddr->hkcs2 = unit;
     672:                 hkaddr->hkcs1 = HK_DCLR | HK_GO;
     673:                 hkwait(hkaddr);
     674:                 hkaddr->hkcs1 = HK_CCLR;
     675:             }
     676:         }
     677:     if (hktab.b_actf && hktab.b_active == 0)
     678:         if (hkstart())
     679:             needie = 0;
     680:     if (needie)
     681:         hkaddr->hkcs1 = HK_IE;
     682: }
     683:
     684: #ifdef HK_DUMP
     685: /*
     686:  *  Dump routine for RK06/07
     687:  *  Dumps from dumplo to end of memory/end of disk section for minor(dev).
     688:  *  It uses the UNIBUS map to dump all of memory if there is a UNIBUS map.
     689:  */
     690: #define DBSIZE  (UBPAGE/NBPG)       /* unit of transfer, one UBPAGE */
     691:
     692: hkdump(dev)
     693:     dev_t dev;
     694:     {
     695:     register struct hkdevice *hkaddr = HKADDR;
     696:     daddr_t bn, dumpsize;
     697:     long paddr;
     698:     register struct ubmap *ubp;
     699:     int count, memblks;
     700:     register struct partition *pi;
     701:     struct dkdevice *disk;
     702:     int com, cn, tn, sn, unit;
     703:
     704:     unit = dkunit(dev);
     705:     if  (unit >= NHK)
     706:         return(EINVAL);
     707:
     708:     disk = &hk_dk[unit];
     709:     if  ((disk->dk_flags & DKF_ALIVE) == 0)
     710:         return(ENXIO);
     711:     pi = &disk->dk_parts[dkpart(dev)];
     712:     if  (pi->p_fstype != FS_SWAP)
     713:         return(EFTYPE);
     714:
     715:     dumpsize = hksize(dev) - dumplo;
     716:     memblks = ctod(physmem);
     717:     if  (dumplo < 0 || dumpsize <= 0)
     718:         return(EINVAL);
     719:     bn = dumplo + pi->p_offset;
     720:
     721:     hkaddr->hkcs1 = HK_CCLR;
     722:     hkwait(hkaddr);
     723:     hkaddr->hkcs2 = unit;
     724:     hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO;
     725:     hkwait(hkaddr);
     726:     if  ((hkaddr->hkds & HKDS_VV) == 0)
     727:         {
     728:         hkaddr->hkcs1 = hk_type[unit]|HK_IE|HK_PACK|HK_GO;
     729:         hkwait(hkaddr);
     730:         }
     731:     ubp = &UBMAP[0];
     732:     for (paddr = 0L; memblks > 0; )
     733:         {
     734:         count = MIN(memblks, DBSIZE);
     735:         cn = bn/HK_NSPC;
     736:         sn = bn%HK_NSPC;
     737:         tn = sn/HK_NSECT;
     738:         sn = sn%HK_NSECT;
     739:         hkaddr->hkcyl = cn;
     740:         hkaddr->hkda = (tn << 8) | sn;
     741:         hkaddr->hkwc = -(count << (PGSHIFT-1));
     742:         com = hk_type[unit]|HK_GO|HK_WRITE;
     743:         if  (ubmap)
     744:             {
     745:             ubp->ub_lo = loint(paddr);
     746:             ubp->ub_hi = hiint(paddr);
     747:             hkaddr->hkba = 0;
     748:             }
     749:         else
     750:             {
     751:             /* non UNIBUS map */
     752:             hkaddr->hkba = loint(paddr);
     753:             hkaddr->hkxmem = hiint(paddr);
     754:             com |= ((paddr >> 8) & (03 << 8));
     755:             }
     756:         hkaddr->hkcs2 = unit;
     757:         hkaddr->hkcs1 = com;
     758:         hkwait(hkaddr);
     759:         if  (hkaddr->hkcs1 & HK_CERR)
     760:             {
     761:             if (hkaddr->hkcs2 & HKCS2_NEM)
     762:                 return(0);  /* made it to end of memory */
     763:             return(EIO);
     764:             }
     765:         paddr += (count << PGSHIFT);
     766:         bn += count;
     767:         memblks -= count;
     768:         }
     769:     return(0);      /* filled disk minor dev */
     770: }
     771: #endif HK_DUMP
     772:
     773: #define exadr(x,y)  (((long)(x) << 16) | (unsigned)(y))
     774:
     775: /*
     776:  * Correct an ECC error and restart the i/o to complete
     777:  * the transfer if necessary.  This is quite complicated because
     778:  * the transfer may be going to an odd memory address base
     779:  * and/or across a page boundary.
     780:  */
     781: hkecc(bp, flag)
     782: register struct buf *bp;
     783: {
     784:     register struct hkdevice *hkaddr = HKADDR;
     785:     ubadr_t addr;
     786:     int npx, wc;
     787:     int cn, tn, sn;
     788:     daddr_t bn;
     789:     unsigned ndone;
     790:     int cmd;
     791:     int unit;
     792:
     793: #ifdef BADSECT
     794:     if (flag == CONT) {
     795:         npx = bp->b_error;
     796:         ndone = npx * NBPG;
     797:         wc = ((int)(ndone - bp->b_bcount)) / NBPW;
     798:     } else
     799: #endif
     800:         {
     801:         wc = hkaddr->hkwc;
     802:         ndone = (wc * NBPW) + bp->b_bcount;
     803:         npx = ndone / NBPG;
     804:         }
     805:     unit = dkunit(bp->b_dev);
     806:     bn = bp->b_blkno;
     807:     cn = bp->b_cylin - bn / HK_NSPC;
     808:     bn += npx;
     809:     cn += bn / HK_NSPC;
     810:     sn = bn % HK_NSPC;
     811:     tn = sn / HK_NSECT;
     812:     sn %= HK_NSECT;
     813:     hktab.b_active++;
     814:
     815:     switch (flag) {
     816:     case ECC:
     817:         {
     818:         register byte;
     819:         int bit;
     820:         long mask;
     821:         ubadr_t bb;
     822:         unsigned o;
     823:         struct ubmap *ubp;
     824:
     825:         log(LOG_WARNING, "hk%d%c:  soft ecc sn %D\n",
     826:             unit, 'a' + (bp->b_dev & 07), bp->b_blkno + npx - 1);
     827:         mask = hkaddr->hkecpt;
     828:         byte = hkaddr->hkecps - 1;
     829:         bit = byte & 07;
     830:         byte >>= 3;
     831:         mask <<= bit;
     832:         o = (ndone - NBPG) + byte;
     833:         bb = exadr(bp->b_xmem, bp->b_un.b_addr);
     834:         bb += o;
     835:         if (ubmap && (bp->b_flags & (B_MAP|B_UBAREMAP))) {
     836:             ubp = UBMAP + ((bb >> 13) & 037);
     837:             bb = exadr(ubp->ub_hi, ubp->ub_lo) + (bb & 017777);
     838:         }
     839:         /*
     840: 		 * Correct until mask is zero or until end of
     841: 		 * sector or transfer, whichever comes first.
     842: 		 */
     843:         while (byte < NBPG && o < bp->b_bcount && mask != 0) {
     844:             putmemc(bb, getmemc(bb) ^ (int)mask);
     845:             byte++;
     846:             o++;
     847:             bb++;
     848:             mask >>= 8;
     849:         }
     850:         if (wc == 0)
     851:             return(0);
     852:         break;
     853:     }
     854:
     855: #ifdef BADSECT
     856:     case BSE:
     857:         if ((bn = isbad(&hkbad[unit], cn, tn, sn)) < 0)
     858:             return(0);
     859:         bp->b_flags |= B_BAD;
     860:         bp->b_error = npx + 1;
     861:         bn = (long)hkncyl(unit)*HK_NSPC - HK_NSECT - 1 - bn;
     862:         cn = bn/HK_NSPC;
     863:         sn = bn%HK_NSPC;
     864:         tn = sn/HK_NSECT;
     865:         sn %= HK_NSECT;
     866:         wc = -(NBPG / NBPW);
     867:         break;
     868:
     869:     case CONT:
     870:         bp->b_flags &= ~B_BAD;
     871:         if (wc == 0)
     872:             return(0);
     873:         break;
     874: #endif BADSECT
     875:     }
     876:     /*
     877: 	 * Have to continue the transfer.  Clear the drive
     878: 	 * and compute the position where the transfer is to continue.
     879: 	 * We have completed npx sectors of the transfer already.
     880: 	 */
     881:     hkaddr->hkcs1 = HK_CCLR;
     882:     hkwait(hkaddr);
     883:     hkaddr->hkcs2 = unit;
     884:     hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO;
     885:     hkwait(hkaddr);
     886:
     887:     addr = exadr(bp->b_xmem, bp->b_un.b_addr);
     888:     addr += ndone;
     889:     hkaddr->hkcyl = cn;
     890:     hkaddr->hkda = (tn << 8) + sn;
     891:     hkaddr->hkwc = wc;
     892:     hkaddr->hkba = (caddr_t)addr;
     893:
     894:     if  (!ubmap)
     895:         hkaddr->hkxmem=hiint(addr);
     896:     cmd = hk_type[unit] | ((hiint(addr) & 3) << 8) | HK_IE | HK_GO;
     897:     if (bp->b_flags & B_READ)
     898:         cmd |= HK_READ;
     899:     else
     900:         cmd |= HK_WRITE;
     901:     hkaddr->hkcs1 = cmd;
     902:     hktab.b_errcnt = 0; /* error has been corrected */
     903:     return (1);
     904: }
     905:
     906: /*
     907:  * Return the number of blocks in a partition.  Call hkopen() to read the
     908:  * label if necessary.  If an open is necessary then a matching close
     909:  * will be done.
     910: */
     911:
     912: daddr_t
     913: hksize(dev)
     914: register dev_t dev;
     915:     {
     916:     register struct dkdevice *disk;
     917:     daddr_t psize;
     918:     int     didopen = 0;
     919:
     920:     disk = &hk_dk[dkunit(dev)];
     921: /*
     922:  * This should never happen but if we get called early in the kernel's
     923:  * life (before opening the swap or root devices) then we have to do
     924:  * the open here.
     925: */
     926:
     927:     if      (disk->dk_openmask == 0)
     928:         {
     929:         if      (hkopen(dev, FREAD|FWRITE, S_IFBLK))
     930:             return(-1);
     931:         didopen = 1;
     932:         }
     933:     psize = disk->dk_parts[dkpart(dev)].p_size;
     934:     if      (didopen)
     935:         hkclose(dev, FREAD|FWRITE, S_IFBLK);
     936:     return(psize);
     937:     }
     938: #endif NHK > 0

#### Defined functions

hkattach defined in line 104; used 1 times

- in line 101

hkclose defined in line 213; used 1 times

- in line 935

hkdfltlbl defined in line 258; used 3 times

- in line 61, 312-317(2)

hkdump defined in line 692; never used
hkecc defined in line 781; used 3 times

- in line 571, 594, 610

hkgetinfo defined in line 299; used 1 times

- in line 182

hkintr defined in line 552; used 1 times

- in /usr/src/sys/pdp/scb.s line 348

hkopen defined in line 121; used 1 times

- in line 929

hkroot defined in line 98; never used
hksize defined in line 912; used 2 times

- in line 60, 715

hkstart defined in line 461; used 2 times

- in line 356, 678

hkstrategy defined in line 326; used 2 times

- in line 62, 313

hkustart defined in line 366; used 3 times

- in line 354, 659, 667

#### Defined variables

HKADDR defined in line 58; used 9 times

- in line 117, 127-131(2), 336, 369, 464, 554, 695, 784

bhkbuf defined in line 88; used 1 times

- in line 399

hk defined in line 80; used 8 times

- in line 379, 557-560(2), 591, 619-624(2), 639, 645

hk_cyl defined in line 74; used 6 times

- in line 185, 431-434(2), 527, 618, 628

hk_dk defined in line 84; used 9 times

- in line 133, 221, 334, 389, 481, 491, 666, 708, 920

hk_dkn defined in line 92; used 12 times

- in line 108-112(4), 375-376(2), 438-439(2), 541-542(2), 566-567(2)

hk_offset defined in line 65; used 1 times

- in line 635

hk_type defined in line 73; used 18 times

- in line 96, 137, 151, 385, 402, 435, 500, 511, 534, 614-617(2), 629, 636, 724-728(2), 742, 884, 896

hkbad defined in line 87; used 2 times

- in line 415, 857

hktab defined in line 82; used 29 times

- in line 355, 378, 451-455(4), 470, 479, 489, 515-516(2), 561-562(2), 583, 600, 607, 616, 632-635(2), 641-652(6), 677(2), 813, 902

hkutab defined in line 83; used 5 times

- in line 234-237(2), 349, 388, 480

#### Defined struct's

hk_softc defined in line 76; never used

#### Defined macros

DBSIZE defined in line 690; used 1 times

- in line 734

HK_NSECT defined in line 54; used 13 times

- in line 56, 110, 269, 416, 495-496(2), 737-738(2), 811-812(2), 861-865(3)

HK_NSPC defined in line 56; used 12 times

- in line 271, 347, 416, 494, 735-736(2), 807-810(3), 861-863(3)

HK_NTRAC defined in line 55; used 2 times

- in line 56, 270

NHK6CYL defined in line 53; used 1 times

- in line 96

NHK7CYL defined in line 52; used 1 times

- in line 96

exadr defined in line 773; used 3 times

- in line 833-837(2), 887

hkncyl defined in line 96; used 4 times

- in line 273, 416-417(2), 861

hkwait defined in line 95; used 17 times

- in line 141-145(2), 153, 386, 423, 501, 512-514(2), 615, 640, 673, 722-729(3), 758, 882-885(2)

Last modified: 1998-04-04 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2099 |