📄 sdc.c
字号:
sdopen(dev,flag) dev_t dev; int flag;{ register int unit = minor(dev) >> 3; register struct uba_device *ui; register int i; int sdstrategy(); if (unit >= nNSD || (ui = sddinfo[unit]) == 0 || ui->ui_alive == 0) return (ENXIO); sd_st.sd_flags[unit] = 0; /* The diskette is checked to be on line everytime it is opened */ if( (unit == DRV_NUM2) && (flag & FNDELAY) ) sd_nodelay = 1; else sd_nodelay = 0; if(unit == DRV_NUM2) { dsket_type = -1; sd_rxcyl = 0; } /* * See if we need to read in the partition table from the disk. * The conditions we will have to read from the disk is if the * partition table valid bit has not been set for the volume * is invalid. */ /* * Assume that the default values before trying to * see if the partition tables are on the pack. The * reason that we do this is that the strategy routine * is used to read in the superblock but uses the * partition info. So we must first assume the * default values. */ /* If opening drive 2 (Diskette), read the partition table every time * since it can be either RX50/RX33/RX23H/RX23D diskette */ if ( (sd_part[unit].pt_valid == 0) || (unit == DRV_NUM2) ) { for( i = 0; i <= 7; i++ ) { sd_part[unit].pt_part[i].pi_nblocks = sdst[ui->ui_type].sizes[i].nblocks; sd_part[unit].pt_part[i].pi_blkoff = sdst[ui->ui_type].sizes[i].blkoffs; } sd_part[unit].pt_valid = PT_VALID; /* * Default partition are now set. Call rsblk to set * the driver's partition tables, if any exists, from * the "a" partition superblock */ rsblk( sdstrategy, dev, &sd_part[unit] ); if(sd_openerr) { sd_openerr = 0; if(sd_nodelay) { sd_nodelay = 0; return(0); } else return(EIO); } } return (0);}sdstrategy(bp) register struct buf *bp;{ register int unit; register struct buf *dp; register struct pt *pt; register s; register xunit = minor(bp->b_dev) & 07; register struct uba_device *ui; register struct vsdev *vd; vd = &vsdiskdev; unit = dkunit(bp); pt = &sd_part[unit]; if (unit >= nNSD) { printf("%s%d:%s: sdstrategy: unit number wrong\n",DEV_ID,unit,SOFT_ERR); goto bad; } ui = sddinfo[unit]; if (ui == 0 || ui->ui_alive == 0) goto bad; /* * Get partition table for the pack */ if ( sd_part[unit].pt_valid != PT_VALID ) if(sd_st.sd_flags[unit] & DEV_OFFLINE) goto bad; else panic("sdstrategy: invalid partition table "); s = spl5(); /* First link the buffer onto the drive queue */ dp = &sdutab[unit]; /* if it is a diskette, no sorting done since the type of diskette found * out only later */ if( unit == DRV_NUM2) { if(dp->b_actf == 0) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; bp->av_forw = 0; } else {#define b_cylin b_resid bp->b_cylin = (bp->b_blkno + sd_st.ucb[unit].lbnbase + pt->pt_part[xunit].pi_blkoff)/sdst[sd_st.sd_type[unit]].nspc; disksort(dp,bp); } /* Link the drive onto the controller queue */ if (dp->b_active == 0) { dp->b_forw = NULL; if (sdcbuf.b_actf == NULL ) sdcbuf.b_actf = dp; else sdcbuf.b_actl->b_forw = dp; sdcbuf.b_actl = dp; dp->b_active = 1; } if(sdcbuf.b_active == 0) { sdcbuf.b_active = 1; /* sdustart() gets called from vs_bufctl() which allows * * the disk controller and TK50 controller to share the * * 16K buffer */ vd->vsd_action = VS_ALLOC; if ((cpu == C_VAXSTAR) && cvs_exmode_on) sdustart(); else vs_bufctl(vd); } splx(s); return;bad: bp->b_flags |= B_ERROR; iodone(bp); return;}sdustart(){ register struct buf *bp,*dp; register int unit; register struct pt *pt; register npf,o; register struct vsdev *vd; struct pte *pte, *mpte; struct proc *rp; struct uba_device *ui; int maxsize; int xunit,i; long sz; unsigned v; vd = &vsdiskdev;loop: /* Check if any request pending for the controller */ if ((dp = sdcbuf.b_actf) == NULL) { sdcbuf.b_active = 0; /* deallocate the 16K shared buffer */ return(VS_DEALLOC); } /* Check if any request pending for the drive */ if ((bp = dp->b_actf) == NULL) { dp->b_active = 0; sdcbuf.b_actf = dp->b_forw; goto loop; } /* Move drive to the end of the controller queue */ if( dp->b_forw != NULL ) { sdcbuf.b_actf = dp->b_forw; sdcbuf.b_actl->b_forw = dp; sdcbuf.b_actl = dp; dp->b_forw = NULL; } unit = dkunit(bp); xunit = minor(bp->b_dev) & 07; sz = (bp->b_bcount+511) >> 9; sd_st.sd_buf = bp; sd_st.sd_bleft = bp->b_bcount; sd_st.ucb[unit].blk_type = BLK_HOST; pt = &sd_part[unit]; /* following code figures out the proper ptes to remap into system space so interrupt routine can copy into buf structure. */ v = btop(bp->b_un.b_addr); o = (int)bp->b_un.b_addr & PGOFSET; npf = btoc(sd_st.sd_bleft + o) ; rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; if ((bp->b_flags & B_PHYS) == 0) { sd_st.sd_addr = bp->b_un.b_addr; } else { if (bp->b_flags & B_UAREA) pte = &rp->p_addr[v]; else if (bp->b_flags & B_PAGET) pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; else if ((bp->b_flags & B_SMEM) && /* SHMEM */ ((bp->b_flags & B_DIRTY) == 0)) pte = ((struct smem *)rp)->sm_ptaddr + v; else { pte = vtopte(rp, v); } sd_st.sd_addr = (char *)((int)SD_bufmap + (int)o); mpte = (struct pte *)sdbufmap; for (i = 0; i< npf; i++) { if(pte->pg_pfnum == 0) panic("sdc: zero pfn in pte"); *(int *)mpte++ = pte++->pg_pfnum | PG_V | PG_KW; mtpr(TBIS, (char *) SD_bufmap + (i*NBPG)); } *(int *)mpte = 0; mtpr(TBIS, (char *)SD_bufmap + (i * NBPG)); } switch(sd_st.sd_type[unit]) { case DT_RD31: case DT_RD32: case DT_RD33: case DT_RD53: case DT_RD54: if(pt->pt_part[xunit].pi_nblocks == -1) maxsize = sd_st.ucb[unit].hostsize - pt->pt_part[xunit].pi_blkoff; else maxsize = pt->pt_part[xunit].pi_nblocks; if (bp->b_blkno < 0 || ( dkblock(bp)+sz) > maxsize){ if(sddebug) cprintf("%s%d:%s: Accessing beyond block %d\n",DEV_ID,unit,SOFT_ERR,maxsize); sd_st.sd_flags[unit] |= DEV_EOM; goto bad; } sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + pt->pt_part[xunit].pi_blkoff; sd_st.sd_drno = unit; break; case DT_RX50: case DT_RX33: ui = sddinfo[unit]; sd_st.sd_drno = unit; /* Check if the diskette type has to be detected. If the * device is opened the diskette type will have to be * identified again. */ if(dsket_type == DT_RX33) { /* last diskette in was RX33 */ if(sdst[DT_RX33].sizes[xunit].nblocks == -1) maxsize = sd_st.ucb[unit].hostsize- sdst[DT_RX33].sizes[xunit].blkoffs; else maxsize = sdst[DT_RX33].sizes[xunit].nblocks; if (bp->b_blkno < 0 || (dkblock(bp)+sz) > maxsize){ if(sddebug) cprintf("%s%d:%s: Accessing beyond block %d\n",DEV_ID,unit,SOFT_ERR,maxsize); sd_st.sd_flags[unit] |= DEV_EOM; goto bad; } sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + sdst[DT_RX33].sizes[xunit].blkoffs; if(sdstart()) goto loop; /* return keeping the 16K shared buffer */ return(VS_KEEP); } else if(dsket_type == DT_RX50){ /* last diskette in was RX50 */ if(sdst[DT_RX50].sizes[xunit].nblocks == -1) maxsize = sd_st.ucb[unit].hostsize- sdst[DT_RX50].sizes[xunit].blkoffs; else maxsize = sdst[DT_RX50].sizes[xunit].nblocks; if (bp->b_blkno < 0 || (dkblock(bp)+sz) > maxsize){ if(sddebug) cprintf("%s%d:%s: Accessing beyond block %d\n",DEV_ID,unit,SOFT_ERR,maxsize); sd_st.sd_flags[unit] |= DEV_EOM; goto bad; } sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + sdst[DT_RX50].sizes[xunit].blkoffs; if(sdstart()) goto loop; /* return keeping the 16K shared buffer */ return(VS_KEEP); } /* The diskette type is unknown. First SELECT * * with parameters for RX33 (head 1). If the SELECT fails * * do the magic to see if the drive is really ready * (done in sd_diskette) */ if(sddebug) cprintf("sdustart: SELECTING DISKETTE ALL OVER\n"); if(sd_diskette()) { if(!sd_nodelay)printf("%s%d:%s: Drive select failed\n",DEV_ID,unit,HARD_ERR); sd_st.sd_flags[unit] |= DEV_OFFLINE; sd_st.sd_cmd = SD_RESET; /* Just to be safe so that * interrupt routine will take care*/ sd_openerr = 1; goto bad; } /* Delay 70 milliseconds for the data recovery circuit to * * stabilize whenever diskette drive select line is changed * * from not-selected to selected */ DELAY(70000); /* should be 70000?? */ sd_restore(1); /* SEEK with head 1 to check if the diskette is an RX33. * * RX50 will fail with head 1 */ if(sd_seek()) { if(sddebug) cprintf("sdustart: assuming RX50 diskette\n"); /* UDC_RTCNT, UDC_MODE regs and DRIVE SELECT done * in sd_rdwr() for RX50, since that seems to be the only * way to make it work, for now */ /* Change the drive parameters if the previous diskette * * type was not RX50 */ if(dsket_type != DT_RX50) { sd_rx50type(unit); sd_st.sd_type[unit] = DT_RX50; dsket_type = DT_RX50; ui->ui_type = DT_RX50; } if(sdst[DT_RX50].sizes[xunit].nblocks == -1) maxsize = sd_st.ucb[unit].hostsize - sdst[DT_RX50].sizes[xunit].blkoffs; else maxsize = sdst[DT_RX50].sizes[xunit].nblocks; if (bp->b_blkno < 0 || (dkblock(bp)+sz) > maxsize){ if(sddebug) cprintf("%s%d:%s: Accessing beyond block %d\n",DEV_ID,unit,SOFT_ERR,maxsize); sd_st.sd_flags[unit] |= DEV_EOM; goto bad; } sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + sdst[DT_RX50].sizes[xunit].blkoffs; } else { /* diskette is RX33 */ if(sddebug) cprintf("sdustart: RX33 diskette\n"); /* Change the drive parameters if the previous diskette * * type was not RX33 */ if(dsket_type != DT_RX33) { sd_rx33type(unit); sd_st.sd_type[unit] = DT_RX33; dsket_type = DT_RX33; ui->ui_type = DT_RX33; } if(sdst[DT_RX33].sizes[xunit].nblocks == -1) maxsize = sd_st.ucb[unit].hostsize - sdst[DT_RX33].sizes[xunit].blkoffs; else maxsize = sdst[DT_RX33].sizes[xunit].nblocks; if (bp->b_blkno < 0 || (dkblock(bp)+sz) > maxsize){ if(sddebug) cprintf("%s%d:%s: Accessing beyond block %d\n",DEV_ID,unit,SOFT_ERR,maxsize); sd_st.sd_flags[unit] |= DEV_EOM; goto bad; } sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + sdst[DT_RX33].sizes[xunit].blkoffs; /* Delay for 500 milliseconds for the drive speed * * to stabilize at 360 rpm (for RX33) (only for proto)*/ DELAY(300000); } break; case DT_RX23H: case DT_RX23D: ui = sddinfo[unit]; sd_st.sd_drno = unit; /* Check if the diskette type has to be detected. If the * device is opened the diskette type will have to be * identified again. */ if( (dsket_type == DT_RX23H) || (dsket_type == DT_RX23D) ) { /* there is a diskette present */ if(sdst[dsket_type].sizes[xunit].nblocks == -1) maxsize = sd_st.ucb[unit].hostsize- sdst[dsket_type].sizes[xunit].blkoffs; else maxsize = sdst[dsket_type].sizes[xunit].nblocks; if (bp->b_blkno < 0 || (dkblock(bp)+sz) > maxsize){ if(sddebug) cprintf("%s%d:%s: Accessing beyond block %d\n",DEV_ID,unit,SOFT_ERR,maxsize); sd_st.sd_flags[unit] |= DEV_EOM; goto bad; } sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + sdst[dsket_type].sizes[xunit].blkoffs; if(sdstart()) goto loop; /* return keeping the 16K shared buffer */ return(VS_KEEP); } /* Find if there is a diskette in the RX23 drive */ if(sd_diskette()) { if(!sd_nodelay) printf("%s%d:%s: Drive select failed\n",DEV_ID,unit,HARD_ERR); sd_st.sd_flags[unit] |= DEV_OFFLINE; sd_st.sd_cmd = SD_RESET; sd_openerr = 1; goto bad; } /* Delay for 700 milliseconds for the drive speed * * to stabilize at 300 rpm (for RX23) */ timeout(sd_rx23wakeup,(caddr_t)bp,7*(hz/10)); return(VS_KEEP); break; default: printf("%s%d:%s: Unknown Disk type : %d\n",DEV_ID,unit,SOFT_ERR,sd_st.sd_type[unit]); goto bad; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -