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

##### Functions

    getsi             X
    siattach          X
    sidump            X
    siintr            X
    siopen            X
    siroot            X
    sisize            X
    sistart           X
    sistrategy        X
    siustart          X

##### Variables

    SIADDR            X
    dualsi            X
    rm5_sizes         X
    si_offset         X
    sicc              X
    sitab             X
    siutab            X

##### Macros

    DBSIZE            X
    SI_NSECT          X
    SI_NTRAC          X

##### struct's

    size              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:  *	@(#)si.c	1.5 (2.11BSD GTE) 1995/04/13
       7:  */
       8:
       9: /*
      10:  *	SI 9500 driver for CDC 9766 disks
      11:  */
      12:
      13: #include "si.h"
      14: #if NSI > 0
      15: #include "param.h"
      16: #include "../machine/seg.h"
      17:
      18: #include "systm.h"
      19: #include "buf.h"
      20: #include "conf.h"
      21: #include "sireg.h"
      22: #include "map.h"
      23: #include "uba.h"
      24: #include "dk.h"
      25: #include "disklabel.h"
      26: #include "disk.h"
      27: #include "xp.h"
      28: #include "errno.h"
      29:
      30: #define SI_NSECT    32
      31: #define SI_NTRAC    19
      32:
      33: #if NXPD > 0
      34: extern struct size {
      35:     daddr_t nblocks;
      36:     int cyloff;
      37: } rm5_sizes[8];
      38: #else !NXPD
      39: /*
      40:  * We reserve room for bad block forwarding information even though this
      41:  * driver doesn't support bad block forwarding.  This allows us to simply
      42:  * copy the table from xp.c.
      43:  */
      44: struct size {
      45:     daddr_t nblocks;
      46:     int cyloff;
      47: } rm5_sizes[8] = {  /* RM05, CDC 9766 */
      48:     9120,     0,    /* a: cyl   0 -  14 */
      49:     9120,    15,    /* b: cyl  15 -  29 */
      50:     234080,  30,    /* c: cyl  30 - 414 */
      51:     247906, 415,    /* d: cyl 415 - 822, reserve 1 track + 126 */
      52:     164160,  30,    /* e: cyl  30 - 299 */
      53:     152000, 300,    /* f: cyl 300 - 549 */
      54:     165826, 550,    /* g: cyl 550 - 822, reserve 1 track + 126 */
      55:     500384,   0,    /* h: cyl   0 - 822 */
      56: };
      57: #endif NXPD
      58:
      59: struct  sidevice *SIADDR;
      60:
      61: int si_offset[] = { SI_OFP, SI_OFM };
      62:
      63: struct  buf sitab;
      64: struct  buf siutab[NSI];
      65:
      66: int sicc[NSI];  /* Current cylinder */
      67: int dualsi = 0; /* dual port flag */
      68:
      69: #ifdef UCB_METER
      70: static  int     si_dkn = -1;    /* number for iostat */
      71: #endif
      72:
      73: void
      74: siroot()
      75: {
      76:     siattach((struct sidevice *)0176700, 0);
      77: }
      78:
      79: siattach(addr, unit)
      80: register struct sidevice *addr;
      81: {
      82: #ifdef UCB_METER
      83:     if (si_dkn < 0) {
      84:         dk_alloc(&si_dkn, NSI+1, "si", 60L * 32L * 256L);
      85:         if (si_dkn >= 0)
      86:             dk_wps[si_dkn+NSI] = 0L;
      87:     }
      88: #endif
      89:
      90:     if (unit != 0)
      91:         return(0);
      92:     if ((addr != (struct sidevice *) NULL) && (fioword(addr) != -1))
      93:     {
      94:         SIADDR = addr;
      95:         if(addr ->siscr != 0)
      96:             dualsi++;   /* dual port controller */
      97:         if((addr->sierr & (SIERR_ERR | SIERR_CNT)) == (SIERR_ERR | SIERR_CNT))
      98:             dualsi++;
      99:         return(1);
     100:     }
     101:     SIADDR = (struct sidevice *) NULL;
     102:     return(0);
     103: }
     104:
     105: siopen(dev, flag)
     106:     dev_t dev;
     107:     int flag;
     108: {
     109:     register int unit;
     110:
     111:     unit = minor(dev) & 077;
     112:     if (unit >= (NSI << 3) || !SIADDR)
     113:         return (ENXIO);
     114:     return (0);
     115: }
     116:
     117: sistrategy(bp)
     118: register struct buf *bp;
     119: {
     120:     register struct buf *dp;
     121:     register int unit;
     122:     long bn;
     123:     int s;
     124:
     125:     unit = minor(bp->b_dev) & 077;
     126:     if (unit >= (NSI << 3) || (SIADDR == (struct sidevice *) NULL)) {
     127:         bp->b_error = ENXIO;
     128:         goto errexit;
     129:     }
     130:     if (bp->b_blkno < 0 ||
     131:         (bn = bp->b_blkno) + (long) ((bp->b_bcount + 511) >> 9)
     132:         > rm5_sizes[unit & 07].nblocks) {
     133:         bp->b_error = EINVAL;
     134: errexit:
     135:         bp->b_flags |= B_ERROR;
     136:         iodone(bp);
     137:         return;
     138:     }
     139:     mapalloc(bp);
     140:     bp->b_cylin = bn / (SI_NSECT * SI_NTRAC) + rm5_sizes[unit & 07].cyloff;
     141:     unit = dkunit(bp->b_dev);
     142:     dp = &siutab[unit];
     143:     s = splbio();
     144:     disksort(dp, bp);
     145:     if (dp->b_active == 0) {
     146:         siustart(unit);
     147:         if (sitab.b_active == 0)
     148:             sistart();
     149:     }
     150:     splx(s);
     151: }
     152:
     153: /*
     154:  * Unit start routine.
     155:  * Seek the drive to where the data is
     156:  * and then generate another interrupt
     157:  * to actually start the transfer.
     158:  * If there is only one drive on the controller
     159:  * or we are very close to the data, don't
     160:  * bother with the search.  If called after
     161:  * searching once, don't bother to look
     162:  * where we are, just queue for transfer (to avoid
     163:  * positioning forever without transferring).
     164:  */
     165: siustart(unit)
     166: register unit;
     167: {
     168:     register struct sidevice *siaddr = SIADDR;
     169:     register struct buf *dp;
     170:     struct  buf *bp;
     171:     daddr_t bn;
     172:     int sn, cn, csn;
     173:
     174:     if (unit >= NSI)
     175:         return;
     176: #ifdef UCB_METER
     177:     if (si_dkn >= 0)
     178:         dk_busy &= ~(1 << (si_dkn + unit));
     179: #endif
     180:     dp = &siutab[unit];
     181:     if ((bp = dp->b_actf) == NULL)
     182:         return;
     183:     /*
     184: 	 * If we have already positioned this drive,
     185: 	 * then just put it on the ready queue.
     186: 	 */
     187:     if (dp->b_active)
     188:         goto done;
     189:     dp->b_active++;
     190:
     191: #if NSI >   1
     192:     /*
     193: 	 * If drive is not ready, forget about positioning.
     194: 	 */
     195:     if(dualsi)
     196:         getsi();
     197:     if ((siaddr->sissr >> (unit*4)) & SISSR_NRDY)
     198:         goto done;
     199:
     200:     /*
     201: 	 * Figure out where this transfer is going to
     202: 	 * and see if we are close enough to justify not searching.
     203: 	 */
     204:     bn = bp->b_blkno;
     205:     cn = bp->b_cylin;
     206:     sn = bn % (SI_NSECT * SI_NTRAC);
     207:     sn = (sn + SI_NSECT) % SI_NSECT;
     208:
     209:     if (sicc[unit] == cn)
     210:         goto done;
     211:
     212: search:
     213:     siaddr->sisar = (unit << 10) | cn;
     214:     if(dualsi)
     215:         SIADDR->siscr = 0;
     216:     sicc[unit] = cn;
     217: #ifdef UCB_METER
     218:     /*
     219: 	 * Mark unit busy for iostat.
     220: 	 */
     221:     if (si_dkn >= 0) {
     222:         int dkn = si_dkn + unit;
     223:
     224:         dk_busy |= 1<<dkn;
     225:         dk_seek[dkn]++;
     226:     }
     227: #endif
     228:     return;
     229: #endif	NSI > 1
     230:
     231: done:
     232:     /*
     233: 	 * Device is ready to go.
     234: 	 * Put it on the ready queue for the controller.
     235: 	 */
     236:     dp->b_forw = NULL;
     237:     if (sitab.b_actf == NULL)
     238:         sitab.b_actf = dp;
     239:     else
     240:         sitab.b_actl->b_forw = dp;
     241:     sitab.b_actl = dp;
     242: }
     243:
     244: /*
     245:  * Start up a transfer on a drive.
     246:  */
     247: sistart()
     248: {
     249:     register struct sidevice *siaddr = SIADDR;
     250:     register struct buf *bp;
     251:     register unit;
     252:     struct  buf *dp;
     253:     daddr_t bn;
     254:     int dn, sn, tn, cn;
     255:     int offset;
     256:
     257: loop:
     258:     /*
     259: 	 * Pull a request off the controller queue.
     260: 	 */
     261:     if ((dp = sitab.b_actf) == NULL)
     262:         return;
     263:     if ((bp = dp->b_actf) == NULL) {
     264:         sitab.b_actf = dp->b_forw;
     265:         goto loop;
     266:     }
     267:     /*
     268: 	 * Mark controller busy and
     269: 	 * determine destination of this request.
     270: 	 */
     271:     sitab.b_active++;
     272:     unit = minor(bp->b_dev) & 077;
     273:     dn = dkunit(bp->b_dev);
     274:     bn = bp->b_blkno;
     275:     cn = bn / (SI_NSECT * SI_NTRAC) + rm5_sizes[unit & 07].cyloff;
     276:     sn = bn % (SI_NSECT * SI_NTRAC);
     277:     tn = sn / SI_NSECT;
     278:     sn = sn % SI_NSECT;
     279:
     280:     /*
     281: 	 * Check that drive is ready.
     282: 	 */
     283:     if(dualsi)
     284:         getsi();
     285:     if ((siaddr->sissr >> (dn*4)) & SISSR_NRDY) {
     286:         sitab.b_active = 0;
     287:         sitab.b_errcnt = 0;
     288:         dp->b_actf = bp->av_forw;
     289:         bp->b_flags |= B_ERROR;
     290:         iodone(bp);
     291:         goto loop;
     292:     }
     293:
     294:     offset = 0;
     295:     if (sitab.b_errcnt >= 16 && (bp->b_flags & B_READ))
     296:         offset = si_offset[sitab.b_errcnt & 1];
     297:
     298:     siaddr->sipcr = (dn << 10) | cn;
     299:     siaddr->sihsr = (tn << 5) + sn;
     300:     siaddr->simar = bp->b_un.b_addr;
     301:     siaddr->siwcr = bp->b_bcount >> 1;
     302:     /*
     303: 	 * Warning:  unit is being used as a temporary.
     304: 	 */
     305:     unit = offset | ((bp->b_xmem & 3) << 4) | SI_IE | SI_GO;
     306:     if (bp->b_flags & B_READ)
     307:         unit |= SI_READ;
     308:     else
     309:         unit |= SI_WRITE;
     310:     siaddr->sicnr = unit;
     311:
     312: #ifdef UCB_METER
     313:     if (si_dkn >= 0) {
     314:         int dkn = si_dkn + NSI;
     315:
     316:         dk_busy |= 1<<dkn;
     317:         dk_seek[dkn]++;
     318:         dk_wds[dkn] += bp->b_bcount >> 6;
     319:     }
     320: #endif
     321: }
     322:
     323: /*
     324:  * Handle a disk interrupt.
     325:  */
     326: siintr()
     327: {
     328:     register struct sidevice *siaddr = SIADDR;
     329:     register struct buf *dp;
     330:     register unit;
     331:     struct  buf *bp;
     332:     int ss, ssr;
     333:
     334:     ssr = siaddr->sissr;
     335:     if (sitab.b_active) {
     336: #ifdef UCB_METER
     337:         if (si_dkn >= 0)
     338:             dk_busy &= ~(1 << (si_dkn + NSI));
     339: #endif
     340:         /*
     341: 		 * Get device and block structures.
     342: 		 */
     343:         dp = sitab.b_actf;
     344:         bp = dp->b_actf;
     345:         unit = dkunit(bp->b_dev);
     346:         /*
     347: 		 * Check for and process errors.
     348: 		 */
     349:         if (siaddr->sierr & SIERR_ERR) {
     350:             /*
     351: 			 * After 18 retries (16 without offset and
     352: 			 * 2 with offset positioning), give up.
     353: 			 */
     354:             if (++sitab.b_errcnt > 18) {
     355:                 bp->b_flags |= B_ERROR;
     356:                 harderr(bp, "si");
     357:                 printf("cnr=%b err=%b\n", siaddr->sicnr,
     358:                 SI_BITS, siaddr->sierr, SIERR_BITS);
     359:             } else
     360:                 sitab.b_active = 0;
     361:
     362:             siaddr->sicnr = SI_RESET;
     363:             if(dualsi)
     364:                 getsi();
     365:             siaddr->sicnr = SI_IE;
     366:
     367:             sicc[unit] = -1;
     368:         }
     369:
     370:         if(dualsi)
     371:             SIADDR->siscr = 0;
     372:         if (sitab.b_active) {
     373:             sitab.b_active = 0;
     374:             sitab.b_errcnt = 0;
     375:             sitab.b_actf = dp->b_forw;
     376:             dp->b_active = 0;
     377:             dp->b_actf = bp->av_forw;
     378:             bp->b_resid = ~siaddr->siwcr;
     379:             if (bp->b_resid == 0xffff) bp->b_resid = 0;
     380:             bp->b_resid <<= 1;
     381:             iodone(bp);
     382:             if (dp->b_actf)
     383:                 siustart(unit);
     384:         }
     385:     }
     386:
     387:     for (unit = 0; unit < NSI; unit++) {
     388:         ss = (ssr >> unit*4) & 017;
     389:         if (ss & (SISSR_BUSY|SISSR_ERR)) {
     390:             harderr(bp, "si");
     391:             printf("ssr=%b err=%b\n", ssr,
     392:                 SISSR_BITS, siaddr->sierr, SIERR_BITS);
     393:             sicc[unit] = -1;
     394:             siustart(unit);
     395:         }
     396:         else if (ss & SISSR_DONE)
     397:             siustart(unit);
     398:     }
     399:
     400:     sistart();
     401: }
     402:
     403: #ifdef SI_DUMP
     404: /*
     405:  *  Dump routine for SI 9500
     406:  *  Dumps from dumplo to end of memory/end of disk section for minor(dev).
     407:  */
     408:
     409: #define DBSIZE  16          /* number of blocks to write */
     410:
     411: sidump(dev)
     412: dev_t   dev;
     413: {
     414:     register struct sidevice *siaddr = SIADDR;
     415:     daddr_t bn, dumpsize;
     416:     long    paddr;
     417:     register count;
     418:     register struct ubmap *ubp;
     419:     int cn, tn, sn, unit;
     420:
     421:     unit = minor(dev) >> 3;
     422:     if ((bdevsw[major(dev)].d_strategy != sistrategy)   /* paranoia */
     423:         || unit > NSI)
     424:         return(EINVAL);
     425:     dumpsize = rm5_sizes[dev & 07].nblocks;
     426:     if ((dumplo < 0) || (dumplo >= dumpsize))
     427:         return(EINVAL);
     428:     dumpsize -= dumplo;
     429:
     430:     /*
     431: 	 * reset the 9500
     432: 	 */
     433:     siaddr->sicnr = SI_RESET;
     434:     ubp = &UBMAP[0];
     435:     for (paddr = 0L; dumpsize > 0; dumpsize -= count) {
     436:         count = dumpsize>DBSIZE? DBSIZE: dumpsize;
     437:         bn = dumplo + (paddr >> PGSHIFT);
     438:         cn = (bn/(SI_NSECT*SI_NTRAC)) + rm5_sizes[minor(dev)&07].cyloff;
     439:         sn = bn % (SI_NSECT * SI_NTRAC);
     440:         tn = sn / SI_NSECT;
     441:         sn = sn % SI_NSECT;
     442:         if(dualsi)
     443:             getsi();
     444:         siaddr->sipcr = (unit << 10) | cn;
     445:         siaddr->sihsr = (tn << 5) + sn;
     446:         siaddr->siwcr = count << (PGSHIFT-1);
     447:
     448:         if (ubmap) {
     449:             ubp->ub_lo = loint(paddr);
     450:             ubp->ub_hi = hiint(paddr);
     451:             siaddr->simar = 0;
     452:             siaddr->sicnr = SI_WRITE | SI_GO;
     453:         }
     454:         else
     455:             {
     456:             siaddr->simar = loint(paddr);
     457:             siaddr->sicnr = SI_WRITE|SI_GO|((paddr >> 8)&(03 << 4));
     458:         }
     459:         while (!(siaddr->sicnr & SI_DONE))
     460:             ;
     461:         if (siaddr->sierr & SIERR_ERR) {
     462:             if (siaddr->sierr & SIERR_TIMO)
     463:                 return(0);  /* made it to end of memory */
     464:             return(EIO);
     465:         }
     466:         paddr += (DBSIZE << PGSHIFT);
     467:     }
     468:     return(0);      /* filled disk minor dev */
     469: }
     470: #endif SI_DUMP
     471:
     472: getsi()
     473: {
     474:     register struct sidevice *siaddr = SIADDR;
     475:
     476:     while(!(siaddr->siscr & 0200))
     477:     {
     478:         siaddr->sicnr = SI_RESET;
     479:         siaddr->siscr = 1;
     480:     }
     481: }
     482:
     483: /*
     484:  * Simple minded but effective. Likely none of these are still around or in use.
     485: */
     486: daddr_t
     487: sisize(dev)
     488:     dev_t   dev;
     489:     {
     490:
     491:     return(rm5_sizes[dev & 07].nblocks);
     492:     }
     493: #endif NSI

#### Defined functions

getsi defined in line 472; used 4 times

- in line 196, 284, 364, 443

siattach defined in line 79; used 1 times

- in line 76

sidump defined in line 411; never used
siintr defined in line 326; used 1 times

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

siopen defined in line 105; never used
siroot defined in line 73; never used
sisize defined in line 486; never used
sistart defined in line 247; used 2 times

- in line 148, 400

sistrategy defined in line 117; used 1 times

- in line 422

siustart defined in line 165; used 4 times

- in line 146, 383, 394-397(2)

#### Defined variables

SIADDR defined in line 59; used 11 times

- in line 94, 101, 112, 126, 168, 215, 249, 328, 371, 414, 474

dualsi defined in line 67; used 8 times

- in line 96-98(2), 195, 214, 283, 363, 370, 442

rm5_sizes declared in line 37; defined in line 47; used 12 times

- in line 132, 140, 275, 425, 438, 491
- in /usr/src/sys/pdpuba/si.c line 132, 140, 275, 425, 438, 491

si_dkn defined in line 70; used 12 times

- in line 83-86(4), 177-178(2), 221-222(2), 313-314(2), 337-338(2)

si_offset defined in line 61; used 1 times

- in line 296

sicc defined in line 66; used 4 times

- in line 209, 216, 367, 393

sitab defined in line 63; used 20 times

- in line 147, 237-241(4), 261-264(2), 271, 286-287(2), 295-296(2), 335, 343, 354, 360, 372-375(4)

siutab defined in line 64; used 2 times

- in line 142, 180

#### Defined struct's

size defined in line 44; never used

#### Defined macros

DBSIZE defined in line 409; used 3 times

- in line 436(2), 466

SI_NSECT defined in line 30; used 12 times

- in line 140, 206-207(3), 275-278(4), 438-441(4)

SI_NTRAC defined in line 31; used 6 times

- in line 140, 206, 275-276(2), 438-439(2)

Last modified: 1995-04-14 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1414 |