📄 fdc.c
字号:
/******************************************************************************* * Fdc.c High level floppy disk driver ******************************************************************************* * * Handler for Codata Format 5.25in Floppy Disks * as well as rpa type 5.25in disks (ie 10 sect * per surface vs 9 * the codata type floppy will be read from minor device * numbers 0,1,2,3 and the ibm double sided 40 track will be assumed * for minor device nos 4,5,6,7 * the minor device values of 4,5,6,7 are only used in this * file, values of 0 1 2 3 will be passed on to the select * routine. * Robin Alston 5.85 */#include "buffer.h"#include "flformat.h"#include "numbers.h"#include <errno.h>#include "../../include/buf.h"#include <sys/ioctl.h>#define LAST_TRACK (79)int nofdopen; /* Total Number of devices open */struct drive_info fdstatus[4];struct fd_buffer fdb[NO_BUFS]; /* the track buffer */short P_TRK, fdcerror;struct buf tmpb; /* used in the ioctl and full track buffering */int dtype;/* * this implements at the moment a simple track buffering scheme * of NO_BUFS buffers. Buffers are write thru ie a write of one * block will update the relevant buffer (if one exists) and * will allways write to the disk as well */fdopen(drive){ /* If first open initialise bits */ if(!nofdopen++){ /* Init the buffering and device handler */ ibuffers(); fdcinit(); } if(!fdstatus[drive & 0x3].d_nopen++){ /* Sets drive type */ if(drive & 0x04){ fdstatus[drive & 0x3].d_type = DTYPE40 | DTYPEINTEL; } else fdstatus[drive & 0x3].d_type = DTYPE80; if(select(drive & 0x3) == ERROR){ printf("Deverr: drive %d unavailiable\n", drive); return ERROR; } restor(0); fdstatus[drive & 0x3].d_curtrk = 0; } return NOERROR;}fdclose(drive){ register short p = 0; nofdopen--; fdstatus[drive & 0x3].d_nopen--; if(fdstatus[drive & 0x3].d_nopen <= 0){ fdstatus[drive & 0x3].d_nopen = 0; /* Release all system buffers */ sync(); while(p < NO_BUFS){ /* release all the allocated buffers */ if(fdb[p].d_minor == drive){ /* When a real buffering scheme is worked * out a buffer flush will go in here */#ifdef FULLBUFFERING if(fdb[p].type & WRITTEN) /* Attempt to flush a dirty buffer */ if(flush1(p) == ERROR) /* Oh well it was a good try * for the mo leave its state * alone */ return ERROR;#endif FULLBUFFERING fdb[p].type = AVAILABLE; /* make it the oldest buffer */ oldest(fdb[p].age); } p++; } } return NOERROR;}ibuffers(){ /* init the buffering scheme */ register short p = 0; while(p < NO_BUFS){ fdb[p].age = p; fdb[p++].type = AVAILABLE; }}fdstrat(buf)struct buf *buf;{ register short blk, dev, p; int err; blk = buf->b_bno; dev = buf->b_dev; /* verify track number and minor device no */ if(blk > CD_B_MAX){ deverr("block no. too large", 1, buf); buf->b_flags |= ABORT; return error(ENXIO); } if((dev < 0) || (dev > 7)){ deverr("minor dev out of range", 1, buf); buf->b_flags |= ABORT; return error(ENXIO); } dtype = fdstatus[buf->b_dev & 0x3].d_type; /* Check if write if so put straight to disk */ if(buf->b_flags & WRITE) err = write_1(buf); /* copy to disk */ else err = read_1(buf); /* go get a buffer */ /* Test if error occured if so report it and return -1 */ if(err == ERROR){ buf->b_flags |= ABORT; return error(EIO); } else return err;}write_1(b)struct buf *b;{ /* If no full buffering then write a buffer to the disk AND write thru the disk buffer if it has one for the relevant track If full buffering write into already existing buffer or first get one from a disk */ register short p;#ifdef TFLOPPYprintf("write_1: ");printf("block: %d\n\r",b->b_bno);#endif TFLOPPY#ifdef FULLBUFFERING /* may have to read the track then do a thru_write */ if(((p = inbuffers(b)) == NOTFOUND) && ((getfdisk(b,"pre-read") == ERROR) || ((p = inbuffers(b)) == NOTFOUND))) /* problems */ return ERROR; thru_write(b,p); return NOERROR;#else if((p = inbuffers(b)) != NOTFOUND) thru_write(b,p); return puttdisk(b);#endif FULLBUFFERING }read_1(b)struct buf *b;{ /* attempt to obtain a buffer from track buffering, if failed then try and get a track from a disk itself */ register short p, offset; if(((p = inbuffers(b)) == NOTFOUND) && ((getfdisk(b,"read") == ERROR) || ((p = inbuffers(b)) == NOTFOUND))){ b->b_flags |= ABORT; return ERROR; } offset = (b->b_bno - fdb[p].bstart) * SIZE;#ifdef TFLOPPYprintf("read_1: block %d buffer %d offset %x\n\r",b->b_bno,p,offset);#endif TFLOPPY bytecp((fdb[p].fdata + offset),b->b_buf,SIZE); return NOERROR;}inbuffers(b)struct buf *b;{ /* * tells whether the buffer b is in the disk buffering (fdb) * if so returns in which one eles returns NOTFOUND */ register short p = 0; while(p < NO_BUFS){ /* wander thru the whole set of buffers */ if((fdb[p].type != AVAILABLE) && INBUF(fdb[p],b)){ /* found it, make it youngest too */#ifdef TFLOPPYprintf("Found %d in buffer %d\n\r",b->b_bno,p);#endif TFLOPPY youngest(fdb[p].age); return p; } else p++; }#ifdef TFLOPPYprintf("%d not found in buffers\n\r",b->b_bno);#endif TFLOPPY return NOTFOUND;}thru_write(b,p)struct buf *b;short p;{ /* * writes the buffer b into the buffer fdb[p] */ register short offset; offset = (b->b_bno - fdb[p].bstart) * SIZE;#ifdef TFLOPPYprintf("Write thru: block %d buffer %d offset %x\n\r",b->b_bno,p,offset);#endif TFLOPPY bytecp(b->b_buf,fdb[p].fdata + offset,SIZE); /* copy the buf */ fdb[p].type |= WRITTEN; youngest(fdb[p].age); /* make this buffer the youngest */}diskset(b,trackn)struct buf *b;short trackn;{ /* select disk side etc using info in b returns which sector this buffer should be on this disk track and also sets the global P_TRK to how many sectors per track surface there are on this device if trackn <> NOTATRACK then the seek will be to that track else will seek to where the block should be */ register short p_trk, trk, blk; short sideno, drive, reps; struct drive_info *fds; int rtrack; char twostep; drive = b->b_dev; blk = b->b_bno; switch(drive){ case 0: case 1: case 2: case 3: /* codata type */ p_trk = CD_PERTRK; break; case 4: case 5: case 6: case 7: /* codata type */ p_trk = CD_PERTRK; break; } trk = rtrack = (trackn == NOTATRACK)? (blk / p_trk) : trackn; /* Checks if single sided */ if(!(fdstatus[drive & 0x3].d_type & DTYPESS)){ sideno = (trk & 1)? ONE : ZERO; trk /= 2; rtrack /= 2; } else{ sideno = ZERO; } /* Checks if 40 track */ if(fdstatus[drive & 0x3].d_type & DTYPE40){ trk *= 2; twostep = 1; } else twostep = 0;#ifdef TFLOPPYprintf("diskset: blk %d, trk %d, rtrk %d, side %d, twostep %d\n",blk,trk,rtrack,sideno,twostep);#endif TFLOPPY if(trk > LAST_TRACK){ deverr("track number too big",1,b); b->b_flags |= ABORT; return ERROR; } /* select drive */ if (select(drive & 0x3) == ERROR){ deverr("drive not ready", 1, b); b->b_flags |= ABORT; return ERROR; } /* find current position */ fds = &fdstatus[drive & 0x3]; if ((set_track(fds->d_curtrk)) != trk){ if(reps = doseek(trk, twostep)) { if (reps >= 10) b->b_flags |= ABORT; deverr("seek", reps, b); if (reps >= 10) return ERROR; } fds->d_curtrk = trk; } side(sideno); /* get correct side */ P_TRK = p_trk; set_track(rtrack); /* Sets real track required 40/80 */ return ((blk % p_trk) + 1); /* return the sector number */}getfdisk(b,errmsg)struct buf *b;char *errmsg;{ short p, reps; p = oldest(NO_BUFS - 1); /* get LRU buffer */#ifdef FULLBUFFERING if(fdb[p].type & WRITTEN) /* attempt to write out a dirty buffer */ if(flush1(p) == ERROR) /* Oh heck, what do we do now, anything we do might f..k up the buffering scheme so for the mo do nowt. */ return ERROR; else /* mark this buffer as available, so no matter what happens it will be available in the worst case */ fdb[p].type = AVAILABLE;#endif FULLBUFFERING if(diskset(b,NOTATRACK) == ERROR) /* sets the side. track and drive */ return ERROR; reps = tr_read(fdb[p].fdata, P_TRK); /* read the whole track */ /* errors? */ if (reps) { deverr(errmsg, reps, b); if (reps >= 10){ b->b_flags |= ABORT; fdb[p].type = AVAILABLE; return ERROR; } } /* no fatal errors */ youngest(fdb[p].age); /* make this one the youngest */ fdb[p].bstart = (b->b_bno / P_TRK) * P_TRK; fdb[p].bend = fdb[p].bstart + P_TRK - 1; fdb[p].type = READABLE; fdb[p].d_minor = b->b_dev; b->b_flags &= ~WRITE;#ifdef TFLOPPYprintf("Read: block %d, buffer %d, start %d end %d\n\r",b->b_bno,p,fdb[p].bstart,fdb[p].bend);#endif TFLOPPY return NOERROR;}puttdisk(b)struct buf *b;{ /* write the buffer to the disk */ register short p, reps, sect; if((sect = diskset(b,NOTATRACK)) == ERROR) return ERROR; reps = se_write(b->b_buf,sect); /* write the sector out */ /* errors? */ if (reps) { deverr("write", reps, b); if (reps >= 10){ b->b_flags |= ABORT; return ERROR; } } /* no fatal errors */ b->b_flags &= ~WRITE; return NOERROR;}se_write(b,s)char *b;short s;{ /* writes one sector from b to sect s assumes that the disk side, track already correct */ register short count = 0,err; while(count < 10){ if(err = write_sect(b,s,1,0)){ fdcerror = err; count++; } else break; } return count;}tr_read(buffer,nsects)char *buffer;short nsects;{ /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -