📄 sdc.c
字号:
sd_seek(){ register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem; register struct nb_regs *sdiaddr = (struct nb_regs *)nexus; register count = 0; u_char status; sdiaddr->nb_int_msk &= ~SINT_DC; if(cpu == C_VAXSTAR) sdaddr->dkc_cmd = (SD_SEEK | SK_STEP ); else sdaddr->dkc_cmd = (SD_SEEK | SK_STEP | SK_VERFY); DELAY(64); /* Cannot RESET the controller to cancel the comand if it * did not complete within a time frame. */ while(!(sdiaddr->nb_int_reqclr & SINT_DC)) { DELAY(10); if(++count >= LOOP_DELAY) break; } if(count >= LOOP_DELAY) { if(sddebug) cprintf("sd_seek: SEEK not done within count = %d\n",count); sd_st.sd_cmd = SD_RESET; /* Since seek cannot be cancelled by a * RESET, even if the seek cmd finishes * later, sdintr will ignore due to this */ if (sdiaddr->nb_int_reqclr & SINT_DC) sdiaddr->nb_int_reqclr = SINT_DC; DELAY(1); sdiaddr->nb_int_msk |= SINT_DC; return(1); } if(cpu == C_VAXSTAR) /* GMM */ DELAY(100); status = sdaddr->dkc_stat; if ( (status & DKC_TERMCOD) != DKC_SUCCESS) { if(sddebug) cprintf("sd_seek: command failed: status = %o\n",status); if (sdiaddr->nb_int_reqclr & SINT_DC) sdiaddr->nb_int_reqclr = SINT_DC; DELAY(1); sdiaddr->nb_int_msk |= SINT_DC; return(1); } if (sdiaddr->nb_int_reqclr & SINT_DC) sdiaddr->nb_int_reqclr = SINT_DC; DELAY(1); sdiaddr->nb_int_msk |= SINT_DC; return(0);} /* Resets the controller */sd_reset(){ register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem; register count= 0; sdaddr->dkc_cmd = SD_RESET; DELAY(64); while(count < DELAYTEN) { if((sdaddr->dkc_stat & DKC_DONE) != 0) break; DELAY(10); count++; } if (count == DELAYTEN){ cprintf("sd_reset: RESET failed\n"); sd_st.sd_cmd = SD_RESET; /* This should take care if the * * cancelled command finishes later */ } sdaddr->dkc_cmd = (SD_SETREG | UDC_TERM); sdc_delay(); sdaddr->dkc_reg = (TERM_CRC | TERM_INT | TERM_DEL | TERM_WRPR | TERM_WRFL); return(0);}/* * Reset the ST506 controller (if present). * The VMB boot driver requires this reset to kill off * any DMA that might be in progress at the time of a crash. * This routine is called from dumpsys() in machdep.c. * We wait 1 second for any DMA in progress to run down. */sdreset(){ register struct nb1_regs *sdaddr; register int i; if (mfpr(MAPEN) & 1) /* memory management must be off, just */ return; /* return if m/m on. */ if ((vs_cfgtst & VS_SC_TYPE) != VS_ST506_SCSI) return; sdaddr = (struct nb1_regs *)QMEMVAXSTAR; /* delay about 1 second (DO NOT use DELAY() in physical mode */ for (i = 0; i < 5000000; i++) ; sdaddr->dkc_cmd = SD_RESET; for (i = 0; i < 5000; i++) ; /* delay */}sdstart(){ register struct buf *bp, *dp; register cylin; register struct pt *pt; register struct sdst *st; struct uba_device *ui; short sn; u_char tmphd; u_char udc_dhead,udc_dcyl,udc_scnt,udc_dsect,cmd ; int unit,xunit,logical_sn; if( (bp = sd_st.sd_buf) == NULL) { cprintf("bp is NULL\n"); return(1); } unit = dkunit(bp); dp = &sdutab[unit]; xunit = minor(bp->b_dev) & 07; pt = &sd_part[unit]; ui = sddinfo[unit]; if(sd_st.sd_blkno > (sd_st.ucb[unit].lbnbase + sd_st.ucb[unit].hostsize)) { cprintf("%s%d:%s: Wrong block no %d\n",DEV_ID,unit,SOFT_ERR,sd_st.sd_blkno); bp->b_flags |= B_ERROR; dp->b_actf = bp->av_forw; iodone(bp); return(1); } if( (sd_st.sd_blkno - sd_st.ucb[unit].lbnbase) < pt->pt_part[xunit].pi_blkoff) { cprintf("%s%d:%s: Wrong partition: %d,block = %d\n",DEV_ID,unit,SOFT_ERR,xunit,sd_st.sd_blkno); bp->b_flags |= B_ERROR; dp->b_actf = bp->av_forw; iodone(bp); return(1); } st = &sdst[sd_st.sd_type[unit]]; sd_st.ucb[unit].blk_type = BLK_HOST; cylin = sd_st.sd_blkno/st->nspc ; if(cylin >= st->ncyl) { printf("%s%d:%s: Invalid cylinder: %d\n",DEV_ID,unit,HARD_ERR,sd_st.sd_cyl.sd_word); panic("invalid cylinder"); } if(unit == DRV_NUM2) sd_rxcyl = cylin; if(sd_st.sd_type[unit] == DT_RX50) { /* use DEC's ten sector format */ sn = rx_table[sd_st.sd_blkno % 50]; if( ++cylin > 79) cylin = 0; sd_st.sd_hd = 0; /* only one head */ sd_st.sd_nsect = st->nsect; rx50nsect = (sd_st.sd_bleft + 511) >> 9; /* required no. of sectors */ if(rx50nsect > sd_st.sd_nsect) if(sd_st.sd_blkno % st->nsect) rx50nsect = st->nsect - (sd_st.sd_blkno % st->nsect); else rx50nsect = sd_st.sd_nsect; logical_sn = sd_st.sd_blkno%st->nspc; logical_sn %= st->nsect; if((logical_sn + rx50nsect) > st->nsect) rx50nsect = st->nsect - logical_sn; rx50blk = sd_st.sd_blkno; if(rx50nsect == 1) { sd_st.sd_nsect = 1; } else { sn = 1; if(!(bp->b_flags & B_READ)) { /* If to write, first read the full track and replace only the * sectors to be written into */ sd_st.sd_cyl.sd_word = cylin; tmphd = 0160 & (sd_st.sd_cyl.sd_byte[1] << 4); sd_st.sd_cmd = SD_RDLOG; cmd = (SD_RDLOG | RD_XFER); udc_dsect = (0377&sn); /* UDC_DSECT */ udc_dhead = (tmphd | (0017 & sd_st.sd_hd)); /* UDC_DHEAD */ udc_dcyl = sd_st.sd_cyl.sd_byte[0]; /* UDC_DCYL */ udc_scnt = 0377 & sd_st.sd_nsect ; if(rx50read(udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd,sd_st.ucb[unit].blk_type) ) { bp->b_flags |= B_ERROR; dp->b_actf = bp->av_forw; iodone(bp); return(1); } } } sd_st.sd_bcount = rx50nsect * SD_SIZE; sd_st.sd_blkno += rx50nsect; } else { sd_st.sd_hd = (sd_st.sd_blkno -(cylin*st->nspc))/st->nsect; if(sd_st.sd_hd >= st->nheads) { printf("%s%d:%s: Invalid head:%d \n",DEV_ID,unit,HARD_ERR,sd_st.sd_hd); panic("invalid head"); } sn = sd_st.sd_blkno%st->nspc; sn %= st->nsect; sd_st.sd_nsect = (sd_st.sd_bleft +511) >> 9; if( (sn+sd_st.sd_nsect) > st->nsect) sd_st.sd_nsect = st->nsect - sn; if(unit == DRV_NUM2) sn++; /* for diskette, sn starts with 1 */ sd_st.sd_bcount = sd_st.sd_nsect * SD_SIZE; sd_st.sd_blkno += sd_st.sd_nsect; } start_sn = sn; sd_st.sd_cyl.sd_word = cylin; tmphd = 0160 & (sd_st.sd_cyl.sd_byte[1] << 4); if (bp->b_flags & B_READ) { sd_st.sd_cmd = SD_RDLOG; cmd = (SD_RDLOG | RD_XFER); } else { sd_st.sd_cmd = SD_WRLOG; if(sd_st.sd_type[unit] == DT_RX50) cmd = (SD_WRLOG | RX50_PCOMP); else if(sd_st.sd_type[unit] == DT_RX33) cmd = (SD_WRLOG | RX33_PCOMP); else { if(cylin > sd_uib[unit].pccyl) cmd = (SD_WRLOG | RD31_PCOMP); else cmd = SD_WRLOG ; } if((sd_st.sd_type[unit] == DT_RX50) && (rx50nsect > 1) ) rx50transfer(sd_st.sd_addr,FILL); else sdtransfer(sd_st.sd_addr,FILL); } udc_dsect = (0377&sn); /* UDC_DSECT */ udc_dhead = (tmphd | (0017 & sd_st.sd_hd)); /* UDC_DHEAD */ udc_dcyl = sd_st.sd_cyl.sd_byte[0]; /* UDC_DCYL */ udc_scnt = 0377 & sd_st.sd_nsect ;#ifdef BBR_TST if(bp->b_flags & B_BAD) { sd_st.ucb[sd_st.sd_drno].badsect = 0 ; sd_st.ucb[sd_st.sd_drno].badbn = sd_st.sd_blkno - sd_st.sd_nsect + sd_st.ucb[sd_st.sd_drno].badsect - sd_st.ucb[sd_st.sd_drno].lbnbase ; sd_st.ucb[sd_st.sd_drno].blk_type = BLK_BAL; if(sdbbrdbug) cprintf("B_BAD: in sdstart: badsect = %d,badbn = %d,sd_blkno = %d, sd_nsect = %d\n",sn,sd_st.ucb[sd_st.sd_drno].badbn,sd_st.sd_blkno,sd_st.sd_nsect); if(put_rbn(sd_st.ucb[sd_st.sd_drno].badbn)) { cprintf("B_BAD: put_rbn failed\n"); } bbr_sleep = 0; dp->b_actf = bp->av_forw; vd->vsd_action = ST_WANTBACK; if ((cpu == C_VAXSTAR) && cvs_exmode_on) sdustart(); else vs_bufctl(vd); /*sdustart() gets called from vs_bufctl*/ return(0); }#endif BBR_TST if(sd_rdwr(udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd,sd_st.ucb[unit].blk_type)) { if(cpu == C_VAXSTAR) cprintf("sdstart: sd_rdwr failed\n"); /* GMM */ if(sddebug) cprintf("sdstart: sd_rdwr failed\n"); bp->b_flags |= B_ERROR; dp->b_actf = bp->av_forw; iodone(bp); return(1); } if(ui->ui_dk >= 0) { dk_busy |= 1<<ui->ui_dk; dk_xfer[ui->ui_dk]++; dk_wds[ui->ui_dk] += sd_st.sd_bcount>>6; } return(0);}/* This routine does the actual read/write. All the registers are updated here again just to be safe. (Sometimes causes syncerror otherwise) */sd_rdwr(udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd,flag) u_char udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd; short flag;{ register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem; register struct nb_regs *sdiaddr = (struct nb_regs *)nexus; u_char sel_cmd; sdaddr->dkc_cmd = (SD_SETREG | UDC_DMA7); sdc_delay(); if(flag) { /* not host area block */ sdaddr->dkc_reg = rbn_addr1; /* UDC_DMA7 */ sdc_delay(); sdaddr->dkc_reg = rbn_addr2; /*UDC_DMA15 */ } else { sdaddr->dkc_reg = 0; /* UDC_DMA7 */ sdc_delay(); sdaddr->dkc_reg = 0; /* UDC_DMA15 */ } sdc_delay(); sdaddr->dkc_reg = 0; /* UDC_DMA23 */ sdc_delay(); sdaddr->dkc_reg = udc_dsect; /* UDC_DSECT */ sdc_delay(); sdaddr->dkc_reg = udc_dhead ; /* UDC_DHEAD */ sdc_delay(); sdaddr->dkc_reg = udc_dcyl; /* UDC_DCYL */ sdc_delay(); sdaddr->dkc_reg = udc_scnt; sdc_delay(); if(sd_st.sd_drno == DRV_NUM2) { if ((sd_st.sd_type[sd_st.sd_drno] == DT_RX50) || (sd_st.sd_type[sd_st.sd_drno] == DT_RX23D) ) { sdaddr->dkc_reg = (RT_CNT | RT_INVRDY |RT_MOTOR | RT_LOSPD); /* UDC_RTCNT */ sdc_delay(); sdaddr->dkc_reg = (MOD_HD | MOD_CHKCRC | MOD_SRTRXL); /* UDC_MODE */ sel_cmd = (SD_SELECT | DTRT_RX50 | DRV_NUM2); } else if( (sd_st.sd_type[sd_st.sd_drno] == DT_RX33) || (sd_st.sd_type[sd_st.sd_drno] == DT_RX23H) ) { sdaddr->dkc_reg = (RT_CNT | RT_INVRDY | RT_MOTOR); /* UDC_RTCNT */ sdc_delay(); sdaddr->dkc_reg = (MOD_HD | MOD_CHKCRC | MOD_SRTRXH); /* UDC_MODE */ sel_cmd = (SD_SELECT | DTRT_RX33 | DRV_NUM2); } else { printf("sd_rdwr: Wrong type in Drive 2: %d\n",sd_st.sd_type[sd_st.sd_drno]); return(1); } sdaddr->dkc_cmd = (SD_SETREG | UDC_TERM); sdc_delay(); sdaddr->dkc_reg = (TERM_CRC | TERM_INT | TERM_DEL | TERM_WRPR | TERM_WRFL); rx_reselect = 0; if(sd_select(sel_cmd,1)) { printf("%s%d:%s: Drive select failed\n",DEV_ID,sd_st.sd_drno,HARD_ERR); if(sd_poll) { sd_poll = 0; sdiaddr->nb_int_msk &= ~SINT_DC; } return(1); } if(sd_poll) { sd_poll = 0; sdiaddr->nb_int_msk &= ~SINT_DC; } } else { sdaddr->dkc_reg = RT_CNT; /* UDC_RTCNT */ sdc_delay(); sdaddr->dkc_reg = (MOD_HD | MOD_CHKECC | MOD_SRTRDN); /* UDC_MODE */ sdc_delay(); sdaddr->dkc_cmd = (SD_SETREG | UDC_TERM); sdc_delay(); sdaddr->dkc_reg = (TERM_CRC | TERM_INT | TERM_DEL | TERM_WRPR | TERM_WRFL); sel_cmd = (SD_SELECT | DTRT_HDSK | sd_st.sd_drno); if(sd_select(sel_cmd,0)) { printf("%s%d:%s: Drive select failed\n",DEV_ID,sd_st.sd_drno,HARD_ERR); sd_st.sd_flags[sd_st.sd_drno] |= DEV_OFFLINE; if(sd_poll) { sd_poll = 0; sdiaddr->nb_int_msk &= ~SINT_DC; } return(1); } if(sd_poll) { sd_poll = 0; sdiaddr->nb_int_msk &= ~SINT_DC; } } /*if( (cpu == C_VAXSTAR) && (sd_st.sd_drno == DRV_NUM2) ) { if(sd_seek()) { cprintf("RX23 seek failed\n"); return(1); } DELAY(18000); } */ sdaddr->dkc_cmd = (SD_SETREG | UDC_DATA); sdc_delay(); DELAY(100); sdaddr->dkc_cmd = cmd; return(0);}rx50read(udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd,type) u_char udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd;short type;{ register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem; register struct nb_regs *sdiaddr = (struct nb_regs *)nexus; register count = 0; u_char status,udc_cstat,udc_dstat; int retry; for(retry=0; retry< 10; retry++) { count = 0; sd_poll = 1; sdiaddr->nb_int_msk &= ~SINT_DC; if(sd_rdwr(udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd,type) ) { if (sdiaddr->nb_int_reqclr & SINT_DC) sdiaddr->nb_int_reqclr = SINT_DC; continue; } while(!(sdiaddr->nb_int_reqclr & SINT_DC)) { DELAY(10); if(++count >= LOOP_DELAY) break; } if(count >= LOOP_DELAY) { if (sdiaddr->nb_int_reqclr & SINT_DC) sdiaddr->nb_int_reqclr = SINT_DC; continue; } sdc_delay(); /* to make sure status is correct */ status = sdaddr->dkc_stat; if( (status & DKC_TERMCOD) != DKC_SUCCESS) { 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(sddebug) cprintf("rx50read: status = %o, udc_cstat = %o, udc_dstat = %o\n",status,udc_cstat,udc_dstat); if (sdiaddr->nb_int_reqclr & SINT_DC) sdiaddr->nb_int_reqclr = SINT_DC; continue; } break; } if(count >= LOOP_DELAY) { sd_st.sd_cmd = SD_RESET; /* This should take care if the * * cancelled command finishes later */ } if (sdiaddr->nb_int_reqclr & SINT_DC) sdiaddr->nb_int_reqclr = SINT_DC; DELAY(1); sdiaddr->nb_int_msk |= SINT_DC; if(retry >=10) { if(udc_cstat & CST_CMPER) printf("%s%d:%s: compare error\n",DEV_ID,sd_st.sd_drno,HARD_ERR); else if(udc_cstat & CST_ECCER) printf("%s%d:%s: eccerror\n",DEV_ID,sd_st.sd_drno,HARD_ERR); else if (udc_cstat & CST_SYNER) { printf("%s%d:%s: syncerr\n",DEV_ID,sd_st.sd_drno,HARD_ERR); } return(1); } return(0);}int sd_stray = 0; /* TODO1: debug */sdintr(star) int star;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -