📄 fd.c
字号:
*/Fdread(dev, uio) /* character read routine */dev_t dev;struct uio *uio;{ int unit = FDUNIT(minor(dev)) ; if (unit >= NFD) return(ENXIO); return(physio(Fdstrategy,&fd_unit[unit].rhead,dev,B_READ,minphys,uio));}Fdwrite(dev, uio) /* character write routine */dev_t dev;struct uio *uio;{ int unit = FDUNIT(minor(dev)) ; if (unit >= NFD) return(ENXIO); return(physio(Fdstrategy,&fd_unit[unit].rhead,dev,B_WRITE,minphys,uio));}/****************************************************************************//* fdstart *//****************************************************************************/fdstart(unit)int unit;{ register struct buf *dp,*bp; int s;#ifdef FDTESTprintf("fd%d|",unit);#endif s = splbio(); if (!fd_unit[unit].motor) { fd_turnon(unit); /* Wait for 1 sec */ timeout(fdstart,unit,hz); /*DELAY(1000000);*/ }else { /* make sure drive is selected as well as on */ /*set_motor(unit,0);*/ dp = &fd_unit[unit].head; bp = dp->b_actf; fd_retry = 0; if (fd_unit[unit].reset) fd_state = 1; else { /* DO a RESET */ fd_unit[unit].reset = 1; fd_state = 5; } fd_skip = 0;#ifdef FDDEBUGprintf("Seek %d %d\n", bp->b_cylin, dp->b_step);#endif if (bp->b_cylin != fd_track) { /* Seek necessary, never quite sure where head is at! */ out_fdc(15); /* Seek function */ out_fdc(unit); /* Drive number */ out_fdc(bp->b_cylin * dp->b_step); } else fdintr(0xff); } splx(s);}fd_timeout(x)int x;{ int i,j; struct buf *dp,*bp; dp = &fd_unit[fd_drive].head; bp = dp->b_actf; out_fdc(0x4); out_fdc(fd_drive); i = in_fdc(); printf("Timeout drive status %lx\n",i); out_fdc(0x8); i = in_fdc(); j = in_fdc(); printf("ST0 = %lx, PCN = %lx\n",i,j); if (bp) badtrans(dp,bp);}/****************************************************************************//* fdintr *//****************************************************************************/fdintr(unit){ register struct buf *dp,*bp; struct buf *dpother; int read,head,trac,sec,i,s,sectrac,cyl; unsigned long blknum; struct fd_type *ft;#ifdef FDTEST printf("state %d, unit %d, dr %d|",fd_state,unit,fd_drive);#endif dp = &fd_unit[fd_drive].head; bp = dp->b_actf; read = bp->b_flags & B_READ; ft = &fd_types[FDTYPE(bp->b_dev)]; switch (fd_state) { case 1 : /* SEEK DONE, START DMA */ /* Make sure seek really happened*/ if (unit != 0xff) { out_fdc(0x8); i = in_fdc(); cyl = in_fdc(); if (!(i&0x20) || (cyl != bp->b_cylin*dp->b_step)) {printf("Stray int ST0 = %lx, PCN = %lx:",i,cyl); return; } } fd_track = bp->b_cylin; at_dma(read,bp->b_un.b_addr+fd_skip,FDBLK, fd_dmachan); blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK + fd_skip/FDBLK; sectrac = ft->sectrac; sec = blknum % (sectrac * 2); head = sec / sectrac; sec = sec % sectrac + 1; if (read) out_fdc(0xE6); /* READ */ else out_fdc(0xC5); /* WRITE */ out_fdc(head << 2 | fd_drive); /* head & unit */ out_fdc(fd_track); /* track */ out_fdc(head); out_fdc(sec); /* sector XXX +1? */ out_fdc(ft->secsize); /* sector size */ out_fdc(sectrac); /* sectors/track */ out_fdc(ft->gap); /* gap size */ out_fdc(ft->datalen); /* data length */ fd_state = 2; /* XXX PARANOIA */ untimeout(fd_timeout,2); timeout(fd_timeout,2,hz); break; case 2 : /* IO DONE, post-analyze */ untimeout(fd_timeout,2); for(i=0;i<7;i++) { fd_status[i] = in_fdc(); } if (fd_status[0]&0xF8) {#ifdef FDOTHERprintf("status0 err %d:",fd_status[0]);#endif goto retry; }/* if (fd_status[1]){ printf("status1 err %d:",fd_status[0]); goto retry; } if (fd_status[2]){ printf("status2 err %d:",fd_status[0]); goto retry; }*/ /* All OK */ if (!kernel_space(bp->b_un.b_addr+fd_skip)) { /* RAW transfer */ if (read) bcopy(dma_bounce[fd_dmachan]->b_un.b_addr, bp->b_un.b_addr+fd_skip, FDBLK); } fd_skip += FDBLK; if (fd_skip >= bp->b_bcount) {#ifdef FDTESTprintf("DONE %d|", bp->b_blkno);#endif /* ALL DONE */ fd_skip = 0; bp->b_resid = 0; dp->b_actf = bp->av_forw; biodone(bp); nextstate(dp); } else {#ifdef FDDEBUGprintf("next|");#endif /* set up next transfer */ blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK + fd_skip/FDBLK; fd_state = 1; bp->b_cylin = (blknum / (ft->sectrac * 2)); if (bp->b_cylin != fd_track) {#ifdef FDTESTprintf("Seek|");#endif /* SEEK Necessary */ out_fdc(15); /* Seek function */ out_fdc(fd_drive);/* Drive number */ out_fdc(bp->b_cylin * dp->b_step); break; } else fdintr(0xff); } break; case 3:#ifdef FDOTHERprintf("Seek %d %d\n", bp->b_cylin, dp->b_step);#endif /* Seek necessary */ out_fdc(15); /* Seek function */ out_fdc(fd_drive);/* Drive number */ out_fdc(bp->b_cylin * dp->b_step); fd_state = 1; break; case 4: out_fdc(3); /* specify command */ out_fdc(0xDF); out_fdc(2); out_fdc(7); /* Recalibrate Function */ out_fdc(fd_drive); fd_state = 3; break; case 5:#ifdef FDOTHER printf("**RESET**\n");#endif /* Try a reset, keep motor on */ set_motor(fd_drive,1); set_motor(fd_drive,0); outb(fdc+fdctl,ft->trans); fd_retry++; fd_state = 4; break; default: printf("Unexpected FD int->"); out_fdc(0x8); i = in_fdc(); sec = in_fdc(); printf("ST0 = %lx, PCN = %lx\n",i,sec); out_fdc(0x4A); out_fdc(fd_drive); for(i=0;i<7;i++) { fd_status[i] = in_fdc(); } printf("intr status :%lx %lx %lx %lx %lx %lx %lx ", fd_status[0], fd_status[1], fd_status[2], fd_status[3], fd_status[4], fd_status[5], fd_status[6] ); break; } return;retry: switch(fd_retry) { case 0: case 1: case 2: case 3: break; case 4: fd_retry++; fd_state = 5; fdintr(0xff); return; case 5: case 6: case 7: break; default: printf("FD err %lx %lx %lx %lx %lx %lx %lx\n", fd_status[0], fd_status[1], fd_status[2], fd_status[3], fd_status[4], fd_status[5], fd_status[6] ); badtrans(dp,bp); return; } fd_state = 1; fd_retry++; fdintr(0xff);}badtrans(dp,bp)struct buf *dp,*bp;{ bp->b_flags |= B_ERROR; bp->b_error = EIO; bp->b_resid = bp->b_bcount - fd_skip; dp->b_actf = bp->av_forw; fd_skip = 0; biodone(bp); nextstate(dp);}/* nextstate : After a transfer is done, continue processing requests on the current drive queue. If empty, go to the other drives queue. If that is empty too, timeout to turn off the current drive in 5 seconds, and go to state 0 (not expecting any interrupts).*/nextstate(dp)struct buf *dp;{ if (dp->b_actf) fdstart(fd_drive); else {#if NFD > 1 struct buf *dpother; dpother = &fd_unit[fd_drive ? 0 : 1].head; if (dpother->b_actf) {#ifdef FDTESTprintf("switch|");#endif untimeout(fd_turnoff,fd_drive); timeout(fd_turnoff,fd_drive,5*hz); fd_drive = 1 - fd_drive; dp->b_active = 0; dpother->b_active = 1; fdstart(fd_drive); } else #endif {#ifdef FDTESTprintf("off|");#endif untimeout(fd_turnoff,fd_drive); timeout(fd_turnoff,fd_drive,5*hz); fd_state = 0; dp->b_active = 0; } }}Fdioctl() {}Fddump() {}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -