00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "dev/floppy/floppy.h"
00019 #include "core/message.h"
00020 #include "dev/device.h"
00021 #include "common/ds/queue.h"
00022 #include "dev/core/kpic.h"
00023
00024
00025 char f_results[MAX_RESULTS];
00026 int no_sectors = 18;
00027 int no_tracks = 80;
00028 int rate = 300;
00029 int motor_status = 0;
00030 int motorgoal;
00031 int need_reset = FALSE;
00032 int f_intr = 0;
00033 int l_base = 0;
00034 int no_blocks = 2880;
00035 int size = 2880 << SECTOR_SHIFT;
00036 int steps_per_cyl = 1;
00037 int no_heads = 2;
00038 int gap = 0x1b;
00039 request freqs[MAX_FL_REQ];
00040 int fr_req = 0;
00041 volatile int no_req = 0;
00042 int en_req = 0;
00043 int tmp;
00044
00045
00046 unsigned char dma_buf[512] __attribute__((aligned (_4KB)));
00047
00048 struct floppy fp;
00049 void fdc_out(int val)
00050 {
00051 int i =0;
00052 if (need_reset) return;
00053 while ((inb(FDC_STATUS) & (MASTER | DIRECTION)) != (MASTER | 0)) {
00054 if (i>= 1000) {
00055 need_reset = TRUE;
00056 return;
00057 }
00058 i++;
00059 }
00060 outb(FDC_DATA, val);
00061 }
00062
00063 int startmotor()
00064 {
00065 int running;
00066 motorgoal = 0x1;
00067 running = motor_status & motorgoal;
00068
00069 if(!running)
00070 {
00071 cli();
00072 outb(DOR,motorgoal << 4 | ENABLE_DMA);
00073 sti();
00074 }
00075 printf("Motor Started\n");
00076 motor_status = motorgoal;
00077
00078 return 0;
00079 }
00080
00081 void stopmotor()
00082 {
00083 if(motor_status != motorgoal)
00084 {
00085 outb(DOR,motorgoal << 4 | ENABLE_DMA);
00086 motor_status = motorgoal;
00087 }
00088 }
00089 void dma_setup(request *req)
00090 {
00091 int r_or_w,i;
00092 short page;
00093 unsigned long offs;
00094
00095 page=(long)((DD)dma_buf>>16);
00096 offs =(short)((DD)dma_buf & 0xffff);
00097
00098 if(req->opcode == 1)
00099 r_or_w = DMA_READ;
00100 else
00101 r_or_w = DMA_WRITE;
00102 outb(DMA_INIT, DMA_RESET_VAL);
00103 outb(DMA_FLIPFLOP, 0);
00104 outb(DMA_MODE, r_or_w);
00105
00106 outb(DMA_ADDR, offs & 0xff);
00107 outb(DMA_ADDR, ( offs >> 8) & 0xff);
00108 outb(DMA_TOP, page);
00109
00110 outb(DMA_COUNT, (req->r_count - 1) >> 0);
00111 outb(DMA_COUNT, (req->r_count - 1) >> 8);
00112 outb(DMA_INIT, 2);
00113 }
00114 int do_transfer(request *req)
00115 {
00116 int r, s;
00117 if (fp.fl_calibration == FALSE) return(ERR_TRANSFER);
00118 if ((motor_status) == 0) return(ERR_TRANSFER);
00119
00120 cli();
00121 fdc_out(req->opcode == 1 ? FDC_READ : FDC_WRITE);
00122 fdc_out(fp.fl_head << 2);
00123 fdc_out(fp.fl_cylinder);
00124 fdc_out(fp.fl_head);
00125 fdc_out(fp.fl_sector);
00126 fdc_out(SECTOR_SIZE_CODE);
00127 fdc_out(no_sectors);
00128 fdc_out(gap);
00129 fdc_out(DTL);
00130
00131
00132 if (need_reset) return(ERR_TRANSFER);
00133
00134 if((tmp=wait_for_intr()) == -1)
00135 return ERR_TIMEOUT;
00136 sti();
00137 printf("Transfer\n");
00138 r = fdc_results();
00139 if (r != OK) return(r);
00140
00141 if (f_results[ST1] & WRITE_PROTECT)
00142 {
00143 printf("floppy is write protected.\n" );
00144 return(ERR_WR_PROTECT);
00145 }
00146
00147 if ((f_results[ST0] & ST0_BITS) != TRANS_ST0) return(ERR_TRANSFER);
00148
00149
00150 if (f_results[ST1] | f_results[ST2]) return(ERR_TRANSFER);
00151
00152
00153 s = (f_results[ST_CYL] - fp.fl_cylinder) * no_heads * no_sectors;
00154 s += (f_results[ST_HEAD] - fp.fl_head) * no_sectors;
00155 s += (f_results[ST_SEC] - fp.fl_sector);
00156
00157 if ((s << SECTOR_SHIFT) != req->r_count) return(ERR_TRANSFER);
00158
00159 return(OK);
00160 }
00161
00162 int perform_oper(request *req)
00163 {
00164 int block;
00165 if(req->r_count == 0) return OK;
00166 block = (l_base + req->offset) >> SECTOR_SHIFT;
00167 fp.fl_cylinder = block / (no_heads * no_sectors);
00168 fp.fl_hardcyl = fp.fl_cylinder * steps_per_cyl;
00169 fp.fl_head = (block % (no_heads * no_sectors)) / no_sectors;
00170 fp.fl_sector = (block % no_sectors) +1;
00171
00172 if (need_reset) reset();
00173
00174
00175 if (seek() != OK) return ERR_SEEK;
00176
00177 dma_setup(req);
00178 printf("\n%d %d %d %d", fp.fl_cylinder, fp.fl_hardcyl, fp.fl_head, fp.fl_sector);
00179 return do_transfer(req);
00180 }
00181
00182 int fdc_results()
00183 {
00184 int result_nr, status;
00185 int i=0;
00186 result_nr = 0;
00187 do {
00188 status = inb(FDC_STATUS) & (MASTER | DIRECTION | CTL_BUSY);
00189 if (status == (MASTER | DIRECTION | CTL_BUSY))
00190 {
00191 if (result_nr >= MAX_RESULTS)
00192 break;
00193 f_results[result_nr++] = inb(FDC_DATA);
00194 continue;
00195 }
00196 if (status == MASTER) {
00197 for(i=0;i<result_nr;i++)
00198 printf("%x\n ",f_results[i]);
00199 return(OK);
00200 }
00201 i++;
00202 } while (i<1000);
00203 need_reset = TRUE;
00204 return(ERR_STATUS);
00205 }
00206
00207
00208 int recalibrate()
00209 {
00210 int r;
00211 printf("Recalibrating\n");
00212 startmotor();
00213 cli();
00214 fdc_out(FDC_RECALIBRATE);
00215 fdc_out(0);
00216 if (need_reset) return(ERR_SEEK);
00217
00218 if((tmp= wait_for_intr()) == -1)
00219 return ERR_TIMEOUT;
00220 sti();
00221
00222 fdc_out(FDC_SENSE);
00223 r = fdc_results();
00224 fp.fl_curcyl = NO_CYL;
00225 if (r != OK || (f_results[ST0] & ST0_BITS) != SEEK_ST0 || f_results[ST_PCN] != 0)
00226 {
00227 need_reset = TRUE;
00228 return(ERR_RECALIBRATE);
00229 }
00230 else
00231 {
00232 fp.fl_calibration = TRUE;
00233 return(OK);
00234 }
00235 }
00236
00237 int seek()
00238 {
00239 int r;
00240
00241 if (fp.fl_calibration == 0)
00242 if (recalibrate() != OK) return(ERR_SEEK);
00243 if (fp.fl_curcyl == fp.fl_hardcyl) return(OK);
00244 cli();
00245 fdc_out(FDC_SEEK);
00246 fdc_out((fp.fl_head << 2));
00247 fdc_out(fp.fl_hardcyl);
00248
00249 if (need_reset) return(ERR_SEEK);
00250
00251 if((tmp = wait_for_intr()) == -1)
00252 return ERR_TIMEOUT;
00253 sti();
00254
00255 fdc_out(FDC_SENSE);
00256 r = fdc_results();
00257 if (r != OK || (f_results[ST0] & ST0_BITS) != SEEK_ST0
00258 || f_results[ST1] != fp.fl_hardcyl) {
00259
00260 return(ERR_SEEK);
00261 }
00262 fp.fl_curcyl = fp.fl_hardcyl;
00263 return(OK);
00264
00265 }
00266 int reset()
00267 {
00268
00269 need_reset = FALSE;
00270 motor_status = 0;
00271 motorgoal = 0;
00272 cli();
00273 outb(DOR, 0);
00274 outb(DOR, ENABLE_DMA);
00275 sti();
00276
00277 }
00278 int transfer(request r)
00279 {
00280 unsigned char *d;
00281 int res,i,count;
00282
00283 count = r.r_count;
00284 r.r_count = (r.r_count/512)*512;
00285
00286 if(startmotor() == 0)
00287 {
00288
00289 if(r.opcode == 2)
00290 {
00291
00292 phys_mem_copy(r.pid,(void *)r.r_dma,FLOPPY_PID,(void *)dma_buf,r.r_count);
00293 cli();
00294 cls();
00295 printf("write buffer:\n");
00296 for(i=0;i<10;i++)
00297 printf("%x ",dma_buf[i]);
00298 sti();
00299 printf("\n");
00300 }
00301
00302 res = perform_oper(&r);
00303 printf("\nfloppy res: %d\n",res);
00304 motorgoal = 0;
00305 stopmotor();
00306
00307 if(r.opcode == 1 && res == 0)
00308 {
00309 cli();
00310 cls();
00311 printf("buffer:\n");
00312 for(i=0;i<10;i++)
00313 printf("%x ",dma_buf[i]);
00314
00315 sti();
00316 printf("\n");
00317 phys_mem_copy(FLOPPY_PID,(void *)dma_buf,r.pid,(void *)r.r_dma,r.r_count);
00318 }
00319 }
00320 else
00321 {
00322 motorgoal = 0;
00323 stopmotor();
00324 }
00325
00326 if(res != 0)
00327 return -1;
00328 else
00329 return 0;
00330 }
00331 void runFloppy()
00332 {
00333 while(1)
00334 {
00335 if(no_req != 0)
00336 {
00337 cli();
00338 cls();
00339
00340 _proc[freqs[fr_req].pid].eax = transfer(freqs[fr_req]);
00341 remove(&device_q[FLOPPY_DEV],freqs[fr_req].pid);
00342 enq(&ready_q,freqs[fr_req].pid);
00343 fr_req = (fr_req +1) %MAX_FL_REQ;
00344 no_req--;
00345 }
00346 }
00347 }
00348 int wait_for_intr()
00349 {
00350 int tmp;
00351 wait_intr_timer(0x26,TIME_OUT);
00352
00353 asm("pushl %eax");
00354 asm("popl %0"::"r"(tmp));
00355
00356 return tmp;
00357 }
00358 int addreq(request *r)
00359 {
00360 if(no_req == MAX_FL_REQ)
00361 return -1;
00362
00363 freqs[en_req].offset = r->offset;
00364 freqs[en_req].opcode = r->opcode;
00365 freqs[en_req].r_count = r->r_count;
00366 freqs[en_req].r_dma = r->r_dma;
00367 freqs[en_req].pid = r->pid;
00368 en_req = (en_req +1) %MAX_FL_REQ;
00369 no_req++;
00370 }