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