hd.c

Go to the documentation of this file.
00001 /*****************************************************************************************
00002  Copyright (c) 2002-2004 The UbixOS Project
00003  All rights reserved.
00004 
00005  Redistribution and use in source and binary forms, with or without modification, are
00006  permitted provided that the following conditions are met:
00007 
00008  Redistributions of source code must retain the above copyright notice, this list of
00009  conditions, the following disclaimer and the list of authors.  Redistributions in binary
00010  form must reproduce the above copyright notice, this list of conditions, the following
00011  disclaimer and the list of authors in the documentation and/or other materials provided
00012  with the distribution. Neither the name of the UbixOS Project nor the names of its
00013  contributors may be used to endorse or promote products derived from this software
00014  without specific prior written permission.
00015 
00016  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
00017  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00018  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
00019  THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00020  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00021  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00022  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
00023  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00024  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00025 
00026  $Id: hd_8c-source.html 88 2016-01-12 00:11:29Z reddawg $
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   /* Alloc memory for device structure and set it up correctly */
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             //Why do i need to add 1?
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                 //New Nodes
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                 //hdd2->parOffset = d[i].dp_start + bsdd->d_partitions[x].p_offset;
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; /* hdd->hdMask; */
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); //Test As Per TJ
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; /* hdd->hdMask); */
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); //Test as per TJ
00320     //retVal |= hdd->hdDev; //retVal |= (hdd->hdDev | 0xA0); //Test as per TJ
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  $Log: hd_8c-source.html,v $
00349  Revision 1.7  2006/12/15 17:47:05  reddawg
00349  Updates
00349 
00350  Revision 1.5  2006/10/12 15:00:26  reddawg
00351  More changes
00352 
00353  Revision 1.4  2006/10/10 14:14:01  reddawg
00354  UFS Reading
00355 
00356  Revision 1.3  2006/10/09 02:58:05  reddawg
00357  Fixing UFS
00358 
00359  Revision 1.2  2006/10/06 15:48:01  reddawg
00360  Starting to make ubixos work with UFS2
00361 
00362  Revision 1.1.1.1  2006/06/01 12:46:16  reddawg
00363  ubix2
00364 
00365  Revision 1.2  2005/10/12 00:13:37  reddawg
00366  Removed
00367 
00368  Revision 1.1.1.1  2005/09/26 17:24:34  reddawg
00369  no message
00370 
00371  Revision 1.16  2004/08/26 22:51:19  reddawg
00372  TCA touched me :( i think he likes men....
00373 
00374 
00375  sched.h:        kTask_t added parentPid
00376  endtask.c:     fixed term back to parentPid
00377  exec.c:          cleaned warnings
00378  fork.c:            fixed term to childPid
00379  sched.c:         clean up for dead tasks
00380  systemtask.c: clean up dead tasks
00381  kmalloc.c:       cleaned up warnings
00382  udp.c:            cleaned up warnings
00383  bot.c:             cleaned up warnings
00384  shell.c:           cleaned up warnings
00385  tcpdump.c:     took a dump
00386  hd.c:             cleaned up warnings
00387  ubixfs.c:        stopped prning debug info
00388 
00389  Revision 1.15  2004/08/15 00:33:02  reddawg
00390  Wow the ide driver works again
00391 
00392  Revision 1.14  2004/08/14 21:56:44  reddawg
00393  Added initialized byte to the device system to make it easy to add child devices which use parent hardware.
00394 
00395  Revision 1.13  2004/08/02 11:43:17  reddawg
00396  Fixens
00397 
00398  Revision 1.12  2004/07/21 10:02:09  reddawg
00399  devfs: renamed functions
00400  device system: renamed functions
00401  fdc: fixed a few potential bugs and cleaned up some unused variables
00402  strol: fixed definition
00403  endtask: made it print out freepage debug info
00404  kmalloc: fixed a huge memory leak we had some unhandled descriptor insertion so some descriptors were lost
00405  ld: fixed a pointer conversion
00406  file: cleaned up a few unused variables
00407  sched: broke task deletion
00408  kprintf: fixed ogPrintf definition
00409 
00410  Revision 1.11  2004/05/19 23:36:52  reddawg
00411  Bug Fixes
00412 
00413  Revision 1.10  2004/05/19 15:20:06  reddawg
00414  Fixed reference problems due to changes in drive subsystem
00415 
00416  Revision 1.9  2004/05/19 15:07:59  reddawg
00417  Typo defInfo should of been devInfo
00418 
00419  Revision 1.7  2004/05/19 04:07:43  reddawg
00420  kmalloc(size,pid) no more it is no kmalloc(size); the way it should of been
00421 
00422  Revision 1.6  2004/04/28 21:10:40  reddawg
00423  Lots Of changes to make it work with existing os
00424 
00425  Revision 1.5  2004/04/28 02:37:34  reddawg
00426  More updates for using the new driver subsystem
00427 
00428  Revision 1.4  2004/04/28 02:22:54  reddawg
00429  This is a fiarly large commit but we are starting to use new driver model
00430  all around
00431 
00432  Revision 1.3  2004/04/27 21:05:19  reddawg
00433  Updating drivers to use new model
00434 
00435  Revision 1.2  2004/04/26 22:22:33  reddawg
00436  DevFS now uses correct size of device
00437 
00438  Revision 1.1.1.1  2004/04/15 12:07:16  reddawg
00439  UbixOS v1.0
00440 
00441  Revision 1.12  2004/04/13 16:36:33  reddawg
00442  Changed our copyright, it is all now under a BSD-Style license
00443 
00444  END
00445  ***/

Generated on Fri Dec 15 11:18:55 2006 for UbixOS V2 by  doxygen 1.4.7