00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "src/common/shared.hpp"
00018 #include "src/memory/memset.hpp"
00019 #include "src/memory/align.hpp"
00020 #include "src/memory/heap.hpp"
00021 #include "src/common/io.hpp"
00022 #include "src/ipc/lock.hpp"
00023 #include "src/ata.hpp"
00024
00025
00026
00027
00028 struct ATAData
00029 {
00030 uint8 SectorCount, SectorCountExt;
00031 uint8 SectorNum, SectorNumExt;
00032 uint16 Cylinder, CylinderExt;
00033 uint8 DriveHead;
00034 };
00035
00036 void ATADelay()
00037 {
00038 }
00039
00040 void ATAIssueCommand(uint16 BasePort, uint8 Command, struct ATAData *dt)
00041 {
00042
00043 class IPC::Lock::lock_t l("ataissue");
00044
00045 l.lock();
00046 IOPorts::inb(BasePort+PORT_STATUS) && ATA_BUSY;
00047
00048
00049
00050
00051
00052 IOPorts::outb(BasePort+PORT_SECTORCOUNT, dt->SectorCountExt);
00053 IOPorts::outb(BasePort+PORT_SECTORNUM, dt->SectorNumExt);
00054 IOPorts::outb(BasePort+PORT_CYLLOW, dt->CylinderExt & 0xff);
00055 IOPorts::outb(BasePort+PORT_CYLHIGH, dt->CylinderExt >> 8);
00056
00057 IOPorts::outb(BasePort+PORT_SECTORCOUNT, dt->SectorCount);
00058 IOPorts::outb(BasePort+PORT_SECTORNUM, dt->SectorNum);
00059 IOPorts::outb(BasePort+PORT_CYLLOW, dt->Cylinder & 0xff);
00060 IOPorts::outb(BasePort+PORT_CYLHIGH, dt->Cylinder >> 8);
00061
00062 IOPorts::outb(BasePort+PORT_DRIVEHEAD, dt->DriveHead);
00063 IOPorts::outb(BasePort+PORT_CMD, Command);
00064
00065 ATADelay();
00066
00067
00068
00069 asm volatile ("still_going:");
00070 asm volatile ("inb %dx, %al");
00071 asm volatile ("testb $8, %al ");
00072
00073 asm volatile("jz still_going");
00074
00075 l.ulock();
00076 }
00077
00078
00079 void ATAReadSector(int nDriveIndex, void *buf, uint64 block, int byte_offset, int nbytes)
00080 {
00081 ATAData dt;
00082 uint8 ATAReadCommand;
00083
00084 if( block >= 0x10000000 )
00085
00086 {
00087 dt.SectorCountExt= (nbytes/512)>>8;
00088 dt.SectorCountExt= (nbytes/512)&0xff;
00089 dt.CylinderExt= block>>32;
00090 dt.SectorNumExt= (block>>24)&0xff;
00091 dt.Cylinder= (block>>8)&0xffff;
00092 dt.SectorNum= block&0xff;
00093 dt.DriveHead= 16*nDriveIndex | ATA_LBA;
00094 ATAReadCommand= ATA_READMULTIPLEEXT;
00095 } else
00096 {
00097 dt.SectorNum=block&0xff;
00098 dt.Cylinder=(block>>8)&0xffff;
00099 dt.DriveHead=0xa0|((block>>24)&0xf)|16*nDriveIndex|ATA_LBA;
00100 ATAReadCommand= ATA_READWRETRY;
00101 }
00102 dt.SectorCount=(nbytes/512)&0xff;
00103 ATAIssueCommand(ATA_PORT, ATAReadCommand, &dt);
00104 int i;for(i=0;i<nbytes/2;i++)
00105 {
00106 unsigned short x;
00107 asm volatile ("in %%dx, %%ax":"=a"(x):"d"(0x1f0));
00108
00109 if (i<byte_offset) continue;
00110 ((char*)buf)[i*2-byte_offset]=(char)x;
00111 ((char*)buf)[i*2+1-byte_offset]=(char)(x>>8);
00112 }
00113 }
00114
00115
00116 void ATAReadSectorWRetryCHS(bool primarysecondary, char *buf, char head, uint32 SectorCount, char SecNum, uint16 Cylinder)
00117 {
00118
00119
00120
00121
00122
00123 IOPorts::outb(ATA_PORT+PORT_DRIVEHEAD, 0xa0 + (primarysecondary?0x10:0) + head & 15);
00124
00125
00126
00127
00128 IOPorts::outb(ATA_PORT+PORT_SECTORCOUNT, (SectorCount==256?0:SectorCount));
00129
00130
00131
00132
00133 IOPorts::outb(ATA_PORT+PORT_SECTORNUM, SecNum);
00134
00135
00136
00137
00138 IOPorts::outb(ATA_PORT+PORT_CYLLOW, (char)Cylinder);
00139
00140
00141
00142
00143 IOPorts::outb(ATA_PORT+PORT_CYLHIGH, (char)(Cylinder>>8));
00144
00145
00146
00147 IOPorts::outb(ATA_PORT+PORT_CMD, ATA_READWRETRY);
00148
00149 asm("still_going2:");
00150 asm("inb %dx, %al");
00151 asm("testb $8, %al ");
00152
00153 asm("jz still_going2");
00154
00155
00156
00157
00158
00159
00160 int i;for(i=0;i<(signed int)SectorCount*256;i++)
00161 {
00162 unsigned short x;
00163 asm volatile ("in %%dx, %%ax":"=a"(x):"d"(0x1f0));
00164 ((char*)buf)[i*2]=(char)x;
00165 ((char*)buf)[i*2+1]=(char)(x>>8);
00166
00167
00168 }
00169 }
00170
00171 void sub()
00172 {
00173 char buf[512*16];
00174
00175 ATAReadSector(ATA_PRIMARY, buf,0x0,0,512*2);
00176
00177 int i;
00178 kprintf("Dd");
00179 for (i=0;i<512*2;i++)putch((char)buf[i]);
00180 kprintf("D");
00181 for(;;);
00182 }
00183
00184
00185
00186
00187
00188
00189