# 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  ***/