00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 #include <pci/hd.h>
00031 #include <sys/video.h>
00032 #include <sys/device.h>
00033 #include <sys/io.h>
00034 #include <lib/kmalloc.h>
00035 #include <lib/kprintf.h>
00036 #include <devfs/devfs.h>
00037 #include <string.h>
00038   
00039 int initHardDisk() {
00040   int                      i        = 0x0;
00041   int                      x        = 0x0;
00042   int                      minor    = 0x0;
00043   struct device_interface *devInfo  = 0x0;
00044   struct device_interface *devInfo2 = 0x0;
00045   struct dos_partition    *d        = 0x0;
00046   struct driveInfo        *hdd      = 0x0;
00047   struct driveInfo        *hdd2     = 0x0;
00048   char                    *data     = 0x0;
00049   char                    *data2    = 0x0;
00050   char                     name[16];
00051   struct bsd_disklabel     *bsdd     = 0x0;
00052   
00053   hdd            = (struct driveInfo *)kmalloc(sizeof(struct driveInfo));  
00054   hdd->hdPort    = 0x1F0;
00055   hdd->hdDev     = 0x40;
00056   hdd->parOffset = 0x0;
00057 
00058 
00059   
00060   devInfo = (struct device_interface *)kmalloc(sizeof(struct device_interface));
00061   devInfo->read    = (void *)&hdRead;
00062   devInfo->write   = (void *)&hdWrite;
00063   devInfo->reset   = (void *)&hdReset;
00064   devInfo->init    = (void *)&hdInit;
00065   devInfo->ioctl   = (void *)&hdIoctl;
00066   devInfo->stop    = (void *)&hdStop;
00067   devInfo->start   = (void *)&hdStart;
00068   devInfo->standby = (void *)&hdStandby;
00069   devInfo->info    = hdd;
00070   
00071   devInfo->major   = 0x1;
00072   
00073   data = (char *)kmalloc(512);
00074   d = (struct dos_partition *)(data + 0x1BE);
00075 
00076   data2 = (char *)kmalloc(512);
00077   bsdd = (struct bsd_disklabel *)data2;
00078 
00079   if (device_add(0,'c',devInfo) == 0x0) {
00080     kprintf("ad0 - Start: [0x0], Size: [0x%x/0x%X]\n",hdd->hdSize,hdd->hdSize*512);
00081     devfs_makeNode("ad0",'b',0x1,0x0);
00082     hdRead(devInfo->info,data,0x0,0x1);
00083     for (i = 0x0;i < 0x4;i++) {
00084       if (d[i].dp_type != 0x0) {  
00085         devInfo2 = (struct device_interface *)kmalloc(sizeof(struct device_interface));
00086         hdd2     = (struct driveInfo *)kmalloc(sizeof(struct driveInfo));
00087         memcpy(devInfo2,devInfo,sizeof(struct device_interface));
00088         memcpy(hdd2,hdd,sizeof(struct driveInfo));
00089         hdd2->parOffset = d[i].dp_start;
00090         devInfo2->info  = hdd2;
00091         minor++;
00092         if (device_add(minor,'c',devInfo2) == 0x0) {
00093           sprintf(name,"ad0s%i",i + 1);
00094           kprintf("%s - Type: [0x%X], Start: [0x%X], Size: [0x%X]\n",name,d[i].dp_type,d[i].dp_start,d[i].dp_size);
00095           devfs_makeNode(name,'c',0x1,minor);
00096           if (d[i].dp_type == 0xA5) {
00097             
00098             hdRead(devInfo->info,data2,d[i].dp_start + 1,0x1);
00099             for (x = 0;x < bsdd->d_npartitions;x++) {
00100               if (bsdd->d_partitions[x].p_size > 0) {
00101                 sprintf(name,"ad0s%i%c",i + 1,'a' + x);
00102                 
00103                 devInfo2 = (struct device_interface *)kmalloc(sizeof(struct device_interface));
00104                 hdd2     = (struct driveInfo *)kmalloc(sizeof(struct driveInfo));
00105                 memcpy(devInfo2,devInfo,sizeof(struct device_interface));
00106                 memcpy(hdd2,hdd,sizeof(struct driveInfo));
00107                 
00108                 hdd2->parOffset = bsdd->d_partitions[x].p_offset;
00109                 devInfo2->info   = hdd2;
00110                 minor++;
00111                 device_add(minor,'c',devInfo2);
00112                 devfs_makeNode(name,'c',0x1,minor);
00113                 kprintf("%s - Type: [%s], Start: [0x%X], Size: [0x%X], MM: [%i:%i]\n",name,fstypenames[bsdd->d_partitions[x].p_fstype],bsdd->d_partitions[x].p_offset,bsdd->d_partitions[x].p_size,devInfo->major,minor);
00114                 }
00115               }
00116             }
00117           }
00118         }
00119       }
00120     }
00121   kfree(data);
00122   return(0x0);
00123   }
00124 
00125 int hdStandby() {
00126   return(0x0);
00127   }
00128 
00129 int hdStart() {
00130   return(0x0);
00131   }
00132 
00133 int hdStop() {
00134   return(0x0);
00135   }
00136 
00137 int hdIoctl() {
00138   return(0x0);
00139   }
00140 
00141 int hdReset() {
00142   return(0x0);
00143   }
00144   
00145 int hdInit(struct device_node *dev) {
00146   char retVal  = 0x0;
00147   long counter = 0x0;
00148   short *tmp    = 0x0;
00149   struct driveInfo *hdd = dev->devInfo->info;
00150   for (counter = 1000000;counter >= 0;counter--) {
00151     retVal = inportByte(hdd->hdPort + hdStat) & 0x80;
00152     if (!retVal) goto ready;
00153     }
00154   kprintf("Error Initializing Drive\n");
00155   return(1);
00156   ready:
00157   outportByte(hdd->hdPort + hdHead,hdd->hdDev);
00158   outportByte(hdd->hdPort + hdCmd,0xEC);
00159   for (counter = 1000000;counter >= 0;counter--) {
00160     retVal = inportByte(hdd->hdPort + hdStat);
00161     if ((retVal & 1) != 0x0) {
00162       kprintf("Error Drive Not Available\n");
00163       return(1);
00164       }
00165     if ((retVal & 8) != 0x0) {
00166       goto go;
00167       }
00168     }
00169   kprintf("Time Out Waiting On Drive\n");
00170   return(1);
00171   go:
00172   tmp = (short *)hdd->hdSector;
00173   for (counter = 0;counter < (512/2);counter++) {
00174     tmp[counter] = inportWord(hdd->hdPort + hdData);
00175     }
00176   retVal = tmp[0x2F] & 0xFF;
00177   switch (retVal) {
00178     case 0:
00179       hdd->hdShift = 0;
00180       hdd->hdMulti = 1;
00181       break;
00182     case 2:
00183       hdd->hdShift = 1;
00184       hdd->hdMulti = retVal;
00185       break;
00186     case 4:
00187       hdd->hdShift = 2;
00188       hdd->hdMulti = retVal;
00189       break;
00190     case 8:
00191       hdd->hdShift = 3;
00192       hdd->hdMulti = retVal;
00193       break;
00194     case 16:
00195       hdd->hdShift = 4;
00196       hdd->hdMulti = retVal;
00197       break;
00198     case 32:
00199       hdd->hdShift = 5;
00200       hdd->hdMulti = retVal;
00201       break;
00202     case 64:
00203       hdd->hdShift = 6;
00204       hdd->hdMulti = retVal;
00205       break;
00206     default:
00207       kprintf("Error BLOCK Mode Unavailable: [%i]\n",retVal);
00208       return(1);
00209     }
00210   outportByte(hdd->hdPort + hdSecCount,retVal);
00211   outportByte(hdd->hdPort + hdHead,hdd->hdDev);
00212   outportByte(hdd->hdPort + hdCmd,0xC6);
00213   hdd->hdMask = retVal;
00214   hdd->hdSize = (hdd->hdSector[0x7B] * 256 * 256 * 256) + (hdd->hdSector[0x7A] * 256 * 256) + (hdd->hdSector[0x79] * 256) + hdd->hdSector[0x78];
00215   hdd->hdEnable = 1;
00216   kprintf("Drive: [0x%X/0x%X], Size: [%iSectors/%iKBytes]\n",hdd->hdPort,hdd->hdDev,hdd->hdSize,((hdd->hdSize*512)/1024));
00217   dev->devInfo->size        = hdd->hdSize*512;
00218   dev->devInfo->initialized = 0x1;
00219   return(0x0);
00220   }
00221 
00222 void hdWrite(struct driveInfo *hdd,void *baseAddr,uInt32 startSector,uInt32 sectorCount) {
00223   long counter           = 0x0;
00224   long retVal            = 0x0;
00225   short transactionCount = 0x0;
00226   short *tmp             = (short *)baseAddr;
00227   startSector += hdd->parOffset;
00228   if (hdd->hdEnable == 0x0) {
00229     kprintf("Invalid Drive\n");
00230     return;
00231     }
00232   if ((sectorCount >> hdd->hdShift) == 0x0) {
00233     hdd->hdCalc = sectorCount; 
00234     transactionCount = 1;
00235     }
00236   else {
00237     hdd->hdCalc = hdd->hdMulti;
00238     transactionCount = sectorCount >> hdd->hdShift;
00239     }
00240   for (;transactionCount > 0;transactionCount--) {
00241     for (counter = 1000000;counter >= 0;counter--) {
00242       retVal = inportByte(hdd->hdPort + hdStat) & 0x80;
00243       if (!retVal) goto ready;
00244       }
00245     kprintf("Time Out Waiting On Drive\n");
00246     return;
00247     ready:
00248     outportByte(hdd->hdPort + hdSecCount,hdd->hdCalc);
00249     outportByte(hdd->hdPort + hdSecNum,(startSector & 0xFF));
00250     retVal = startSector >> 8;
00251     outportByte(hdd->hdPort + hdCylLow,(retVal & 0xFF));
00252     retVal >>= 8;
00253     outportByte(hdd->hdPort + hdCylHi,(retVal & 0xFF));
00254     retVal >>= 8;
00255     retVal &= 0x0F;
00256     retVal |= (hdd->hdDev | 0xA0); 
00257     outportByte(hdd->hdPort + hdHead,(retVal & 0xFF));
00258     if (hdd->hdShift > 0)
00259       outportByte(hdd->hdPort + hdCmd,0xC5);
00260     else
00261       outportByte(hdd->hdPort + hdCmd,0x30);
00262     for (counter = 1000000;counter >= 0;counter--) {
00263       retVal = inportByte(hdd->hdPort + hdStat);
00264       if ((retVal & 1) != 0x0) {
00265         kprintf("HD Write Error\n");
00266         return;
00267         }
00268       if ((retVal & 8) != 0x0) {
00269         goto go;
00270         }
00271       }
00272     kprintf("Time Out Waiting On Drive\n");
00273     return;
00274     go:
00275     for (counter = 0;counter < (hdd->hdCalc << 8);counter++) {
00276       outportWord(hdd->hdPort + hdData,(short)tmp[counter]);
00277       }
00278     tmp += (counter + 0);
00279     startSector += hdd->hdCalc;
00280     }
00281   return;
00282   }
00283 
00284 void hdRead(struct driveInfo *hdd,void *baseAddr,uInt32 startSector,uInt32 sectorCount) {
00285   long counter           = 0x0;
00286   long retVal            = 0x0;
00287   short transactionCount = 0x0;
00288   short *tmp             = (short *)baseAddr;
00289   startSector += hdd->parOffset;
00290 
00291   if (hdd->hdEnable == 0x0) {
00292     kprintf("Invalid Drive\n");
00293     return;
00294     }
00295   if ((sectorCount >> hdd->hdShift) == 0x0) {
00296     hdd->hdCalc = sectorCount; 
00297     transactionCount = 1;
00298     }
00299   else {
00300     hdd->hdCalc = hdd->hdMulti;
00301     transactionCount = sectorCount >> hdd->hdShift;
00302     }
00303   for (;transactionCount > 0;transactionCount--) {
00304     for (counter = 1000000;counter >= 0;counter--) {
00305       retVal = inportByte(hdd->hdPort + hdStat) & 0x80;
00306       if (!retVal) goto ready;
00307       }
00308     kprintf("Time Out Waiting On Drive\n");
00309     return;
00310     ready:
00311     outportByte(hdd->hdPort + hdSecCount,hdd->hdCalc);
00312     outportByte(hdd->hdPort + hdSecNum,(startSector & 0xFF));
00313     retVal = startSector >> 8;
00314     outportByte(hdd->hdPort + hdCylLow,(retVal & 0xFF));
00315     retVal >>= 8;
00316     outportByte(hdd->hdPort + hdCylHi,(retVal & 0xFF));
00317     retVal >>= 8;
00318     retVal &= 0x0F;
00319     retVal |= (hdd->hdDev | 0xA0); 
00320     
00321     outportByte(hdd->hdPort + hdHead,(retVal & 0xFF));
00322     if (hdd->hdShift > 0)
00323       outportByte(hdd->hdPort + hdCmd,0xC4);
00324     else 
00325       outportByte(hdd->hdPort + hdCmd,0x20);
00326     for (counter = 1000000;counter >= 0;counter--) {
00327       retVal = inportByte(hdd->hdPort + hdStat);
00328       if ((retVal & 1) != 0x0) {
00329         kprintf("HD Read Error: [%i:0x%X:%i]\n",counter,(uInt32)baseAddr,startSector);
00330         return;
00331         }
00332       if ((retVal & 8) != 0x0) {
00333         goto go;
00334         }
00335       }
00336     kprintf("Error: Time Out Waiting On Drive\n");
00337     return;
00338     go:
00339     for (counter = 0;counter < (hdd->hdCalc << 8);counter++) {
00340       tmp[counter] = inportWord(hdd->hdPort + hdData);
00341       }
00342     tmp += (counter + 0);
00343     startSector += hdd->hdCalc;
00344     }
00345   return;
00346   }  
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445