floppy.c

00001 /***************************************************************************
00002                           floppy.c  -  description
00003                              -------------------
00004     begin                : 
00005     copyright            : (C) 2004 by Dynacube Team
00006     email                : 
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
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   //disable int
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   //enable int
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   // dma_setup(&r);
00289          if(r.opcode == 2)
00290         {
00291         // copy memory physical copy
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 }

Generated on Thu Jul 27 23:52:26 2006 for Dynacube by  doxygen 1.4.7