7c1b3a867d53c701e769dcb37c8aa6bf2676446b
[tpg/acess2.git] / KernelLand / Modules / Storage / ATA / main.c
1 /*
2  * Acess2 IDE Harddisk Driver
3  * - main.c
4  */
5 #define DEBUG   0
6 #define VERSION 0x0032
7 #include <acess.h>
8 #include <modules.h>
9 #include <vfs.h>
10 #include <fs_devfs.h>
11 #include <api_drv_common.h>
12 #include <api_drv_disk.h>
13 #include "common.h"
14 #include <Storage/LVM/include/lvm.h>
15
16 // === MACROS ===
17 #define IO_DELAY()      do{inb(0x80); inb(0x80); inb(0x80); inb(0x80);}while(0)
18
19 // === PROTOTYPES ===
20  int    ATA_Install(char **Arguments);
21 void    ATA_SetupPartitions(void);
22  int    ATA_ScanDisk(int Disk);
23 void    ATA_ParseGPT(int Disk);
24 void    ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length);
25 Uint16  ATA_GetBasePort(int Disk);
26 // Read/Write Interface/Quantiser
27 int     ATA_ReadRaw(void *Ptr, Uint64 Address, size_t Count, void *Buffer);
28 int     ATA_WriteRaw(void *Ptr, Uint64 Address, size_t Count, const void *Buffer);
29
30 // === GLOBALS ===
31 MODULE_DEFINE(0, VERSION, i386ATA, ATA_Install, NULL, "PCI", "LVM", NULL);
32 tLVM_VolType    gATA_VolType = {
33         .Name = "ATA",
34         .Read = ATA_ReadRaw,
35         .Write = ATA_WriteRaw
36         };
37
38 // === CODE ===
39 /**
40  * \brief Initialise the ATA driver
41  */
42 int ATA_Install(char **Arguments)
43 {
44         int     ret;
45
46         ret = ATA_SetupIO();
47         if(ret) return ret;
48
49         ATA_SetupPartitions();
50
51         return MODULE_ERR_OK;
52 }
53
54 /**
55  * \brief Scan all disks, looking for partitions
56  */
57 void ATA_SetupPartitions(void)
58 {
59          int    i;
60         for( i = 0; i < MAX_ATA_DISKS; i ++ )
61         {
62                 if( !ATA_ScanDisk(i) ) {
63                         continue;
64                 }
65         }
66 }
67
68 /**
69  * \brief Scan a disk, getting the size and any paritions
70  * \param Disk  Disk ID to scan
71  */
72 int ATA_ScanDisk(int Disk)
73 {
74         Uint64  sector_count;
75         ENTER("iDisk", Disk);
76         
77         // Get the disk size
78         sector_count = ATA_GetDiskSize(Disk);
79         if(sector_count == 0)
80         {
81                 LEAVE('i', 0);
82                 return 0;
83         }
84
85         #if 1
86         {
87                 Uint64  val = sector_count / 2;
88                 char    *units = "KiB";
89                 if( val > 4*1024 ) {
90                         val /= 1024;
91                         units = "MiB";
92                 }
93                 else if( val > 4*1024 ) {
94                         val /= 1024;
95                         units = "GiB";
96                 }
97                 else if( val > 4*1024 ) {
98                         val /= 1024;
99                         units = "TiB";
100                 }
101                 Log_Notice("ATA", "Disk %i: 0x%llx Sectors (%lli %s)",
102                         Disk, sector_count, val, units);
103         }
104         #endif
105
106         char name[] = "ata0";
107         sprintf(name, "ata%i", Disk);
108         LVM_AddVolume(&gATA_VolType, name, (void*)(Uint*)Disk, 512, sector_count);
109
110         #if DEBUG >= 2
111         {
112         char    mbr[512];
113         ATA_ReadDMA( Disk, 1, 1, &mbr );
114         Debug_HexDump("ATA_ScanDisk", &mbr, 512);
115         }
116         #endif
117
118         LEAVE('i', 1);
119         return 1;
120 }
121
122 // --- Disk Access ---
123 /**
124  * \fn Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
125  */
126 int ATA_ReadRaw(void *Ptr, Uint64 Address, Uint Count, void *Buffer)
127 {
128          int    Disk = (tVAddr)Ptr;
129          int    ret;
130         Uint    offset;
131         Uint    done = 0;
132
133         LOG("Reading %i sectors from 0x%llx of disk %i", Count, Address, Disk);
134
135         // Pass straight on to ATA_ReadDMAPage if we can
136         if(Count <= MAX_DMA_SECTORS)
137         {
138                 ret = ATA_ReadDMA(Disk, Address, Count, Buffer);
139                 if(ret) return 0;
140                 return Count;
141         }
142
143         // Else we will have to break up the transfer
144         offset = 0;
145         while(Count > MAX_DMA_SECTORS)
146         {
147                 ret = ATA_ReadDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset);
148                 // Check for errors
149                 if(ret != 1)    return done;
150                 // Change Position
151                 done += MAX_DMA_SECTORS;
152                 Count -= MAX_DMA_SECTORS;
153                 offset += MAX_DMA_SECTORS*SECTOR_SIZE;
154         }
155
156         ret = ATA_ReadDMA(Disk, Address+done, Count, Buffer+offset);
157         if(ret) return 0;
158         return done+Count;
159 }
160
161 /**
162  * \fn Uint ATA_WriteRaw(Uint64 Address, Uint Count, const void *Buffer, Uint Disk)
163  */
164 int ATA_WriteRaw(void *Ptr, Uint64 Address, Uint Count, const void *Buffer)
165 {
166          int    Disk = (tVAddr)Ptr;
167          int    ret;
168         Uint    offset;
169         Uint    done = 0;
170
171         // Pass straight on to ATA_WriteDMA, if we can
172         if(Count <= MAX_DMA_SECTORS)
173         {
174                 ret = ATA_WriteDMA(Disk, Address, Count, Buffer);
175                 if(ret == 0)    return 0;
176                 return Count;
177         }
178
179         // Else we will have to break up the transfer
180         offset = 0;
181         while(Count > MAX_DMA_SECTORS)
182         {
183                 ret = ATA_WriteDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset);
184                 // Check for errors
185                 if(ret != 1)    return done;
186                 // Change Position
187                 done += MAX_DMA_SECTORS;
188                 Count -= MAX_DMA_SECTORS;
189                 offset += MAX_DMA_SECTORS*SECTOR_SIZE;
190         }
191
192         ret = ATA_WriteDMA(Disk, Address+offset, Count, Buffer+offset);
193         if(ret != 1)    return 0;
194         return done+Count;
195 }

UCC git Repository :: git.ucc.asn.au