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