📄 sdc.c
字号:
register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem; register struct buf *bp ,*dp; register err = 0; register struct uba_device *ui; register struct vsdev *vd; int xunit; u_char status,udc_cstat,udc_dstat;#ifdef lint star = star;#endif vd = &vsdiskdev; sdc_delay(); status = sdaddr->dkc_stat; if( ((status & DKC_INTPEND) != DKC_INTPEND) || ((status & DKC_DONE) != DKC_DONE) ) {/* TODO1: debug mprintf("%s:%s: stray interrupt \n",DEV_ID,SOFT_ERR);*/ sd_stray++; return; } if(!xbnflag) { if( (bp = sd_st.sd_buf) == NULL) { mprintf("%s:%s: No valid buffer\n",DEV_ID,SOFT_ERR); if(sddebug >=2) cprintf("sdintr:No valid buffer: cmd = %o, dkc_stat = %o\n",sd_st.sd_cmd,status); return; } dp = &sdutab[dkunit(bp)]; xunit = minor(bp->b_dev) & 07; } switch(sd_st.sd_cmd) { case SD_STEP: case SD_DESEL: case SD_SELECT: case SD_SEEK: case SD_RESTOR: case SD_FMT: case SD_RDTR: mprintf("%s%d:%s: Command not yet implemented thru interrupt, command = %c\n",DEV_ID,sd_st.sd_drno,SOFT_ERR,sd_st.sd_cmd); return; /* break; */ case SD_RDPHY: case SD_RDLOG: case SD_WRPHY: case SD_WRLOG: if(!xbnflag) { ui = sddinfo[dkunit(bp)]; if(ui->ui_dk >= 0) dk_busy &= ~(1 << ui->ui_dk); } sdaddr->dkc_cmd = (SD_SETREG | UDC_CSTAT); sdc_delay(); udc_cstat = sdaddr->dkc_reg; /* read UDC_CSTAT */ sdc_delay(); sdaddr->dkc_cmd = (SD_SETREG | UDC_DSTAT); sdc_delay(); udc_dstat = sdaddr->dkc_reg; if( (status & DKC_TERMCOD) != DKC_SUCCESS) { if( (sddebug) && (rtr_cnt == 0)) { cprintf("sdintr: udc_cstat = %o ",udc_cstat); cprintf("sdintr: drive = %d, block = %d, head = %o,cyln = %o,bleft = %d,bcount = %d\n",sd_st.sd_drno,sd_st.sd_blkno,sd_st.sd_hd,sd_st.sd_cyl.sd_word,sd_st.sd_bleft,sd_st.sd_bcount); sdaddr->dkc_cmd = (SD_SETREG | UDC_DMA7); cprintf("sdintr:DMA7 = %o ",sdaddr->dkc_reg); /* DMA7*/ cprintf("sdintr:DMA15 = %o ",sdaddr->dkc_reg); /* DMA15 */ cprintf("sdintr:DMA23 = %o\n",sdaddr->dkc_reg); /* DMA23 */ sd_st.ucb[sd_st.sd_drno].badsect = 0; cprintf("sdintr:DSECT = %o ",sdaddr->dkc_reg); /* DSECT */ cprintf("sdintr:CHEAD = %o ",sdaddr->dkc_reg); /* CHEAD */ cprintf("sdintr:CCYL = %o ",sdaddr->dkc_reg); /* CCYL */ sdaddr->dkc_cmd = (SD_SETREG | UDC_DSTAT); cprintf("sdintr:DSTAT = %o\n",sdaddr->dkc_reg); /* DSTAT */ } else { sdc_delay(); sdaddr->dkc_cmd = (SD_SETREG | UDC_DSECT); sd_st.ucb[sd_st.sd_drno].badsect = 0; } if ( (udc_cstat & CST_ECCER) || (udc_cstat & CST_CMPER) ){ if(rtr_cnt == 0)sd_st.sd_softcnt[sd_st.sd_drno]++; if(!xbnflag) if(++rtr_cnt < RTRY_CNT){ if(sd_st.sd_type[sd_st.sd_drno] == DT_RX50) sd_st.sd_blkno -= rx50nsect; else sd_st.sd_blkno -= sd_st.sd_nsect; if(!sdstart()) return; } rtr_cnt = 0; if( (sd_st.sd_drno == DRV_NUM2) || xbnflag ) err++; else if(sd_retry(0)) err++; if(err) { if(ddm_err) { printf("%s%d%c: hard error sn %d\n",DEV_ID,sd_st.sd_drno,'a'+xunit,BAD_SECT(sd_st.sd_drno,xunit)); printf("%s%d: Forced Error Modifier set LBN %d\n",DEV_ID,sd_st.sd_drno,BAD_LBN(sd_st.sd_drno)); ddm_err = 0; sd_st.sd_bleft -= (sd_st.ucb[sd_st.sd_drno].badsect + 1 ) * SD_SIZE; } else if(udc_cstat & CST_CMPER) printf("%s%d:%s: compare error\n",DEV_ID,sd_st.sd_drno,HARD_ERR); else printf("%s%d:%s: eccerror\n",DEV_ID,sd_st.sd_drno,HARD_ERR); if(sdbbrdbug) { cprintf("%s%d: block = %d, head = %o, cylinder = %o\n",DEV_ID,sd_st.sd_drno,sd_st.sd_blkno-sd_st.sd_nsect,sd_st.sd_hd,sd_st.sd_cyl.sd_word); sdaddr->dkc_cmd = (SD_SETREG | UDC_DSECT); cprintf("sdintr:DSECT = %o ",sdaddr->dkc_reg); /* DSECT */ cprintf("sdintr:CHEAD = %o ",sdaddr->dkc_reg); /* CHEAD */ cprintf("sdintr:CCYL = %o ",sdaddr->dkc_reg); /* CCYL */ cprintf("sdintr:CSTAT = %o ",udc_cstat); sdaddr->dkc_cmd = (SD_SETREG | UDC_DSTAT); cprintf("sdintr:DSTAT = %o\n",sdaddr->dkc_reg); /* DSTAT */ } } } else if ((udc_cstat & CST_SYNER) ) { if(rtr_cnt == 0)sd_st.sd_softcnt[sd_st.sd_drno]++; if(!xbnflag) if(++rtr_cnt < RTRY_CNT){ if(sd_st.sd_type[sd_st.sd_drno] == DT_RX50) { sd_st.sd_blkno -= rx50nsect; } else sd_st.sd_blkno -= sd_st.sd_nsect; if(!sdstart()) return; } rtr_cnt = 0; printf("%s%d:%s: syncerr\n",DEV_ID,sd_st.sd_drno,HARD_ERR); err++; } else if ( (status & DKC_OVRUN) == DKC_OVRUN) { printf("%s%d:%s: overrun/underrun\n",DEV_ID,sd_st.sd_drno,HARD_ERR); err++; sd_reset(); } else if( (udc_dstat & DST_WRFAULT) == DST_WRFAULT) { if(rtr_cnt == 0)sd_st.sd_softcnt[sd_st.sd_drno]++; if(!xbnflag) if(++rtr_cnt < RTRY_CNT){ if(!sd_deselect()) { DELAY(100); /* Select the drive and start all over again */ if(sd_st.sd_type[sd_st.sd_drno] == DT_RX50) sd_st.sd_blkno -= rx50nsect; else sd_st.sd_blkno -= sd_st.sd_nsect; if(!sdstart()) return; } } printf("%s%d:%s: WRITE FAULT\n",DEV_ID,sd_st.sd_drno,HARD_ERR); rtr_cnt = 0; err++; } else if ( (udc_cstat & CST_DELDT) == CST_DELDT) { DELAY(10); sd_reset(); if(rtr_cnt == 0)sd_st.sd_softcnt[sd_st.sd_drno]++; if(!xbnflag) if(++rtr_cnt < RTRY_CNT){ if(sd_st.sd_type[sd_st.sd_drno] == DT_RX50) sd_st.sd_blkno -= rx50nsect; else sd_st.sd_blkno -= sd_st.sd_nsect; if(!sdstart()) return; } rtr_cnt = 0; if( (sd_st.sd_drno == DRV_NUM2) || xbnflag ) err++; else if(sd_retry(1)) { if(ddm_err) { printf("%s%d%c: hard error sn %d\n",DEV_ID,sd_st.sd_drno,'a'+xunit,BAD_SECT(sd_st.sd_drno,xunit)); printf("%s%d: Forced Error Modifier set LBN %d\n",DEV_ID,sd_st.sd_drno,BAD_LBN(sd_st.sd_drno)); ddm_err = 0; sd_st.sd_bleft -= (sd_st.ucb[sd_st.sd_drno].badsect + 1 ) * SD_SIZE; } else printf("%s%d:%s:\n",DEV_ID,sd_st.sd_drno,HARD_ERR); err++; } } else if ( (status & DKC_BADSECT) == DKC_BADSECT) { if( (sd_st.sd_drno == DRV_NUM2) || xbnflag ) { printf("%s%d:%s: bad sector\n",DEV_ID,sd_st.sd_drno,HARD_ERR); err++; } else if(sd_retry(0)) err++; } else if( (udc_dstat & DST_WRPROT) == DST_WRPROT) { cprintf("%s%d: WRITE PROTECTED\n",DEV_ID,sd_st.sd_drno); sd_st.sd_flags[sd_st.sd_drno] |= DEV_WRTLCK; err++; } else { mprintf("%s%d:%s: Unknown error type, UDC_CSTAT = %o, UDC_DSTAT = %o,DKC_STAT = %o\n",DEV_ID,sd_st.sd_drno,SOFT_ERR,udc_cstat,udc_dstat,status); err++; } } rtr_cnt = 0; if(sd_st.sd_drno == DRV_NUM2) { if( (udc_dstat & DST_WRPROT) == DST_WRPROT) { sd_st.sd_flags[sd_st.sd_drno] |= DEV_WRTLCK; } } if(err) { if(!xbnflag) { bp->b_flags |= B_ERROR; dp->b_actf = bp->av_forw; bp->b_resid = sd_st.sd_bleft; iodone(bp); sd_st.sd_status |= (CNT_DONE | CNT_ERR); /*sdustart() gets called from vs_bufctl*/ vd->vsd_action = VS_WANTBACK; if ((cpu == C_VAXSTAR) && cvs_exmode_on) sdustart(); else vs_bufctl(vd); } sd_st.sd_hardcnt[sd_st.sd_drno]++; sd_st.sd_status |= (CNT_DONE | CNT_ERR); return; } break; default: mprintf("%s%d:%s: wrong command: %o\n",DEV_ID,sd_st.sd_drno,SOFT_ERR,sd_st.sd_cmd); return; } if(xbnflag) { sdtransfer(xbnbuf,EMPTY); sd_st.sd_status &= ~CNT_ERR; sd_st.sd_status |= CNT_DONE; return; } if(bp->b_flags & B_READ) if((sd_st.sd_type[sd_st.sd_drno] == DT_RX50) && (rx50nsect > 1) ) rx50transfer(sd_st.sd_addr,EMPTY); else sdtransfer(sd_st.sd_addr,EMPTY); if(sd_st.sd_bleft > sd_st.sd_bcount) sd_st.sd_bleft -= sd_st.sd_bcount; else sd_st.sd_bleft = 0; sd_st.sd_addr += sd_st.sd_bcount; if(sd_st.sd_bleft > 0) { if(!(bp->b_flags & B_READ)) { /* Diskette drive requires some time to complete tunnel * erasure of data just written */ if(sd_st.sd_type[sd_st.sd_drno] == DT_RX50) DELAY(700); if(sd_st.sd_type[sd_st.sd_drno] == DT_RX33) DELAY(400); } if(sdstart()) { /*sdustart() gets called from vs_bufctl*/ vd->vsd_action = VS_WANTBACK; if ((cpu == C_VAXSTAR) && cvs_exmode_on) sdustart(); else vs_bufctl(vd); } } else { dp->b_actf = bp->av_forw; bp->b_resid = sd_st.sd_bleft; iodone(bp); sd_st.sd_status |= CNT_DONE; sd_st.sd_status &= ~(CNT_BSY | CNT_ERR); vd->vsd_action = VS_WANTBACK; if ((cpu == C_VAXSTAR) && cvs_exmode_on) sdustart(); else vs_bufctl(vd); /*sdustart() gets called from vs_bufctl*/ } return;}sdwait(){ register count = 0; while(!(sd_st.sd_status & CNT_DONE )) /* wait for status change */ if(++count >= LOOP_DELAY) return(1); sd_st.sd_status &= ~CNT_DONE; return(0);}/* This routine transfers the data from/to the controller's buffer to/from the * user buffer ( for RDs and RX33 diskette) */sdtransfer(bpp,op) char *bpp; short op;{ register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem; register short nbytes; register char *buf0, *buf1; buf0 = bpp; if (sd_st.sd_bleft >= sd_st.sd_bcount) nbytes = sd_st.sd_bcount; else nbytes=sd_st.sd_bleft; if ((cpu == C_VAXSTAR) && cvs_exmode_on) buf1 = (char *)cvseddbmem; else buf1 = (char *)sdaddr->nb_ddb; if( op == FILL) bcopy (buf0, buf1, nbytes); else bcopy (buf1, buf0, nbytes);}/* This routine transfers the data from/to the controller's buffer to/from the * user buffer ( for RX50 diskette) */rx50transfer(bpp,op) char *bpp; short op;{ register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem; register char *buf0, *buf1; register i,sector; int last,nbytes; buf0 = bpp; if(sd_st.sd_bleft >= sd_st.sd_bcount) last = sd_st.sd_bcount % SD_SIZE; else last = sd_st.sd_bleft % SD_SIZE; nbytes = SD_SIZE; for(i=0; i< rx50nsect; i++) { if( i== (rx50nsect-1)) if (last) { nbytes = last; } sector = rx_table[rx50blk % 50]; if ((cpu == C_VAXSTAR) && cvs_exmode_on) buf1 = (char *)cvseddbmem + SD_SIZE*(sector - 1); else buf1 = (char *)sdaddr->nb_ddb + SD_SIZE*(sector - 1); if(op == FILL) bcopy (buf0, buf1, nbytes); else bcopy (buf1, buf0, nbytes); buf0 += nbytes; rx50blk++; } return;}/* This routine reads the XBNs (first 3 blocks) to get all format information */sd_rdfmt(unit) register int unit;{ register sector,i; register struct sd_uib *uibptr; register char *char_ptr, *buf_ptr; short *data_ptr; u_char sect,head,cylin,scnt,cmd; short sd_sum; sd_st.sd_hd = sd_st.sd_cyl.sd_word = 0; head = cylin = 0; scnt =1; cmd = (SD_RDLOG | RD_XFER); sd_st.sd_drno = unit; uibptr = &sd_uib[unit]; for( sector = 0; sector < 3; sector++ ) { xbnflag = 1; sect = sector & 0377; sd_st.sd_cmd = SD_RDLOG; sd_st.sd_bleft = sd_st.sd_bcount = SD_SIZE; sd_st.sd_status = 0; if(sd_rdwr(sect,head,cylin,scnt,cmd,0)) continue; if(sdwait()) continue;; xbnflag = 0; if(sd_st.sd_status & CNT_ERR) { sd_st.sd_status &= ~CNT_ERR; cprintf("sd_rdfmt: reading XBN %d failed\n",sector); continue; } for( i = 0; i < 9; i++ ) if( xbnbuf[i] != 0x00 ){ cprintf("sd_rdfmt:bytes 0-8 not zero in xbn %d\n",sector); goto repeat; } if( xbnbuf[9] != 0x36 ) { cprintf("sd_rdfmt: byte 9 not 0x36 in xbn %d\n",sector); continue; } sd_sum = 0; data_ptr = (short *)&xbnbuf[0]; for( i = 255; --i >= 0; ) sd_sum += *data_ptr++; if( *data_ptr == sd_sum ) { char_ptr = (char *)uibptr; buf_ptr = &xbnbuf[0]; for(i=0; i<UIBSIZE; i++) { /* This is done because the filler is only 10 bytes long * and the next element is int which should be word * aligned */ *char_ptr++ = *buf_ptr++; } sd_st.ucb[unit].xbn_un.xbn_short[0] = sd_uib[unit].xbnsize[0]; sd_st.ucb[unit].xbn_un.xbn_short[1] = sd_uib[unit].xbnsize[1]; sd_st.ucb[unit].dbn_un.dbn_short[0] = sd_uib[unit].dbnsize[0]; sd_st.ucb[unit].dbn_un.dbn_short[1] = sd_uib[unit].dbnsize[1]; sd_st.ucb[unit].lbn_un.lbn_short[0] = sd_uib[unit].lbnsize[0]; sd_st.ucb[unit].lbn_un.lbn_short[1] = sd_uib[unit].lbnsize[1]; sd_st.ucb[unit].rbn_un.rbn_short[0] = sd_uib[unit].rbnsize[0]; sd_st.ucb[unit].rbn_un.rbn_short[1] = sd_uib[unit].rbnsize[1]; sd_st.ucb[unit].med_un.med_short[0] = sd_uib[unit].media[0]; sd_st.ucb[unit].med_un.med_short[1] = sd_uib[unit].media[1]; sd_st.ucb[uni
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -