Reorganised the modules directory, started serious work on GUI support
[tpg/acess2.git] / Modules / Storage / ATA / main.c
1 /*
2  * Acess2 IDE Harddisk Driver
3  * - main.c
4  */
5 #define DEBUG   0
6 #include <acess.h>
7 #include <modules.h>
8 #include <vfs.h>
9 #include <fs_devfs.h>
10 #include <drv_pci.h>
11 #include <tpl_drv_common.h>
12 #include <tpl_drv_disk.h>
13 #include "common.h"
14
15 // --- Flags ---
16 #define START_BEFORE_CMD        0
17
18 // === STRUCTURES ===
19 typedef struct
20 {
21         Uint32  PBufAddr;
22         Uint16  Bytes;
23         Uint16  Flags;
24 } __attribute__ ((packed))      tPRDT_Ent;
25 typedef struct
26 {
27         Uint16  Flags;          // 1
28         Uint16  Usused1[9];     // 10
29         char    SerialNum[20];  // 20
30         Uint16  Usused2[3];     // 23
31         char    FirmwareVer[8]; // 27
32         char    ModelNumber[40];        // 47
33         Uint16  SectPerInt;     // 48 - AND with 0xFF to get true value;
34         Uint16  Unused3;        // 49
35         Uint16  Capabilities[2];        // 51
36         Uint16  Unused4[2];     // 53
37         Uint16  ValidExtData;   // 54
38         Uint16  Unused5[5];      // 59
39         Uint16  SizeOfRWMultiple;       // 60
40         Uint32  Sectors28;      // 62
41         Uint16  Unused6[100-62];
42         Uint64  Sectors48;
43         Uint16  Unused7[256-104];
44 } __attribute__ ((packed))      tIdentify;
45
46 // === IMPORTS ===
47 extern void     ATA_ParseMBR(int Disk);
48
49 // === PROTOTYPES ===
50  int    ATA_Install();
51  int    ATA_SetupIO();
52 void    ATA_SetupPartitions();
53 void    ATA_SetupVFS();
54  int    ATA_ScanDisk(int Disk);
55 void    ATA_ParseGPT(int Disk);
56 void    ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length);
57 Uint16  ATA_GetBasePort(int Disk);
58 // Filesystem Interface
59 char    *ATA_ReadDir(tVFS_Node *Node, int Pos);
60 tVFS_Node       *ATA_FindDir(tVFS_Node *Node, char *Name);
61 Uint64  ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
62 Uint64  ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
63  int    ATA_IOCtl(tVFS_Node *Node, int Id, void *Data);
64 // Read/Write Interface/Quantiser
65 Uint    ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk);
66 Uint    ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk);
67 // Read/Write DMA
68  int    ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
69  int    ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
70 // IRQs
71 void    ATA_IRQHandlerPri(int unused);
72 void    ATA_IRQHandlerSec(int unused);
73 // Controller IO
74 Uint8   ATA_int_BusMasterReadByte(int Ofs);
75 void    ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value);
76 void    ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value);
77
78 // === GLOBALS ===
79 MODULE_DEFINE(0, 0x0032, i386ATA, ATA_Install, NULL, NULL);
80 tDevFS_Driver   gATA_DriverInfo = {
81         NULL, "ata",
82         {
83                 .NumACLs = 1,
84                 .Size = -1,
85                 .Flags = VFS_FFLAG_DIRECTORY,
86                 .ACLs = &gVFS_ACL_EveryoneRX,
87                 .ReadDir = ATA_ReadDir,
88                 .FindDir = ATA_FindDir
89         }
90 };
91 tATA_Disk       gATA_Disks[MAX_ATA_DISKS];
92  int    giATA_NumNodes;
93 tVFS_Node       **gATA_Nodes;
94 Uint16  gATA_BusMasterBase = 0;
95 Uint8   *gATA_BusMasterBasePtr = 0;
96  int    gATA_IRQPri = 14;
97  int    gATA_IRQSec = 15;
98  int    giaATA_ControllerLock[2] = {0}; //!< Spinlocks for each controller
99 Uint8   gATA_Buffers[2][4096] __attribute__ ((section(".padata")));
100  int    gaATA_IRQs[2] = {0};
101 tPRDT_Ent       gATA_PRDTs[2] = {
102         {0, 512, IDE_PRDT_LAST},
103         {0, 512, IDE_PRDT_LAST}
104 };
105
106 // === CODE ===
107 /**
108  * \fn int ATA_Install()
109  */
110 int ATA_Install()
111 {
112         int     ret;
113         
114         ret = ATA_SetupIO();
115         if(ret != 1)    return ret;
116         
117         ATA_SetupPartitions();
118         
119         ATA_SetupVFS();
120         
121         if( DevFS_AddDevice( &gATA_DriverInfo ) == 0 )
122                 return MODULE_INIT_FAILURE;
123         
124         return MODULE_INIT_SUCCESS;
125 }
126
127 /**
128  * \fn int ATA_SetupIO()
129  * \brief Sets up the ATA controller's DMA mode
130  */
131 int ATA_SetupIO()
132 {
133          int    ent;
134         tPAddr  addr;
135         
136         ENTER("");
137         
138         // Get IDE Controller's PCI Entry
139         ent = PCI_GetDeviceByClass(0x0101, 0xFFFF, -1);
140         LOG("ent = %i", ent);
141         gATA_BusMasterBase = PCI_GetBAR4( ent );
142         if( gATA_BusMasterBase == 0 ) {
143                 Warning("It seems that there is no Bus Master Controller on this machine. Get one");
144                 LEAVE('i', MODULE_INIT_FAILURE);
145                 return MODULE_INIT_FAILURE;
146         }
147         if( !(gATA_BusMasterBase & 1) )
148         {
149                 if( gATA_BusMasterBase < 0x100000 )
150                         gATA_BusMasterBasePtr = (void*)(0xC0000000|gATA_BusMasterBase);
151                 else
152                         gATA_BusMasterBasePtr = (void*)( MM_MapHWPage( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) );
153                 LOG("gATA_BusMasterBasePtr = %p", gATA_BusMasterBasePtr);
154         }
155         else {
156                 // Bit 0 is left set as a flag to other functions
157                 LOG("gATA_BusMasterBase = 0x%x", gATA_BusMasterBase & ~1);
158         }
159         
160         IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri );
161         IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec );
162         
163         gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[0] );
164         gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[1] );
165         
166         LOG("gATA_PRDTs = {PBufAddr: 0x%x, PBufAddr: 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr);
167         
168         addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[0] );
169         LOG("addr = 0x%x", addr);
170         ATA_int_BusMasterWriteDWord(4, addr);
171         addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[1] );
172         LOG("addr = 0x%x", addr);
173         ATA_int_BusMasterWriteDWord(12, addr);
174         
175         outb(IDE_PRI_BASE+1, 1);
176         outb(IDE_SEC_BASE+1, 1);
177         
178         LEAVE('i', MODULE_INIT_SUCCESS);
179         return MODULE_INIT_SUCCESS;
180 }
181
182 /**
183  * \fn void ATA_SetupPartitions()
184  */
185 void ATA_SetupPartitions()
186 {
187          int    i;
188         for( i = 0; i < MAX_ATA_DISKS; i ++ )
189         {
190                 if( !ATA_ScanDisk(i) ) {
191                         gATA_Disks[i].Name[0] = '\0';   // Mark as unused
192                         continue;
193                 }
194         }
195 }
196
197 /**
198  * \fn void ATA_SetupVFS()
199  * \brief Sets up the ATA drivers VFS information and registers with DevFS
200  */
201 void ATA_SetupVFS()
202 {
203          int    i, j, k;
204         
205         // Count number of nodes needed
206         giATA_NumNodes = 0;
207         for( i = 0; i < MAX_ATA_DISKS; i++ )
208         {
209                 if(gATA_Disks[i].Name[0] == '\0')       continue;       // Ignore
210                 giATA_NumNodes ++;
211                 giATA_NumNodes += gATA_Disks[i].NumPartitions;
212         }
213         
214         // Allocate Node space
215         gATA_Nodes = malloc( giATA_NumNodes * sizeof(void*) );
216         
217         // Set nodes
218         k = 0;
219         for( i = 0; i < MAX_ATA_DISKS; i++ )
220         {
221                 if(gATA_Disks[i].Name[0] == '\0')       continue;       // Ignore
222                 gATA_Nodes[ k++ ] = &gATA_Disks[i].Node;
223                 for( j = 0; j < gATA_Disks[i].NumPartitions; j ++ )
224                         gATA_Nodes[ k++ ] = &gATA_Disks[i].Partitions[j].Node;
225         }
226         
227         gATA_DriverInfo.RootNode.Size = giATA_NumNodes;
228 }
229
230 /**
231  * \fn int ATA_ScanDisk(int Disk)
232  */
233 int ATA_ScanDisk(int Disk)
234 {
235         Uint16  buf[256];
236         tIdentify       *identify = (void*)buf;
237         tMBR    *mbr = (void*)buf;
238         Uint16  base;
239         Uint8   val;
240          int    i;
241         tVFS_Node       *node;
242         
243         ENTER("iDisk", Disk);
244         
245         base = ATA_GetBasePort( Disk );
246         
247         LOG("base = 0x%x", base);
248         
249         // Send Disk Selector
250         if(Disk == 1 || Disk == 3)
251                 outb(base+6, 0xB0);
252         else
253                 outb(base+6, 0xA0);
254         
255         // Send IDENTIFY
256         outb(base+7, 0xEC);
257         val = inb(base+7);      // Read status
258         if(val == 0) {
259                 LEAVE('i', 0);
260                 return 0;       // Disk does not exist
261         }
262         
263         // Poll until BSY clears and DRQ sets or ERR is set
264         while( ((val & 0x80) || !(val & 0x08)) && !(val & 1))   val = inb(base+7);
265         
266         if(val & 1) {
267                 LEAVE('i', 0);
268                 return 0;       // Error occured, so return false
269         }
270         
271         // Read Data
272         for(i=0;i<256;i++)      buf[i] = inw(base);
273         
274         // Populate Disk Structure
275         if(identify->Sectors48 != 0)
276                 gATA_Disks[ Disk ].Sectors = identify->Sectors48;
277         else
278                 gATA_Disks[ Disk ].Sectors = identify->Sectors28;
279         
280         
281         LOG("gATA_Disks[ Disk ].Sectors = 0x%x", gATA_Disks[ Disk ].Sectors);
282         
283         if( gATA_Disks[ Disk ].Sectors / (2048*1024) )
284                 Log("Disk %i: 0x%llx Sectors (%i GiB)", Disk,
285                         gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / (2048*1024));
286         else if( gATA_Disks[ Disk ].Sectors / 2048 )
287                 Log("Disk %i: 0x%llx Sectors (%i MiB)", Disk,
288                         gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / 2048);
289         else
290                 Log("Disk %i: 0x%llx Sectors (%i KiB)", Disk,
291                         gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / 2);
292         
293         // Create Name
294         gATA_Disks[ Disk ].Name[0] = 'A'+Disk;
295         gATA_Disks[ Disk ].Name[1] = '\0';
296         
297         // Get pointer to vfs node and populate it
298         node = &gATA_Disks[ Disk ].Node;
299         node->Size = gATA_Disks[Disk].Sectors * SECTOR_SIZE;
300         node->NumACLs = 0;      // Means Superuser only can access it
301         node->Inode = (Disk << 8) | 0xFF;
302         node->ImplPtr = gATA_Disks[ Disk ].Name;
303         
304         node->ATime = node->MTime
305                 = node->CTime = now();
306         
307         node->Read = ATA_ReadFS;
308         node->Write = ATA_WriteFS;
309         node->IOCtl = ATA_IOCtl;
310
311
312         // --- Scan Partitions ---
313         LOG("Reading MBR");
314         // Read Boot Sector
315         ATA_ReadDMA( Disk, 0, 1, mbr );
316         
317         // Check for a GPT table
318         if(mbr->Parts[0].SystemID == 0xEE)
319                 ATA_ParseGPT(Disk);
320         else    // No? Just parse the MBR
321                 ATA_ParseMBR(Disk);
322         
323         LEAVE('i', 0);
324         return 1;
325 }
326
327 /**
328  * \fn void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length)
329  * \brief Fills a parition's information structure
330  */
331 void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length)
332 {
333         ENTER("pPart iDisk iNum XStart XLength", Part, Disk, Num, Start, Length);
334         Part->Start = Start;
335         Part->Length = Length;
336         Part->Name[0] = 'A'+Disk;
337         if(Num >= 10) {
338                 Part->Name[1] = '1'+Num/10;
339                 Part->Name[2] = '1'+Num%10;
340                 Part->Name[3] = '\0';
341         } else {
342                 Part->Name[1] = '1'+Num;
343                 Part->Name[2] = '\0';
344         }
345         Part->Node.NumACLs = 0; // Only root can read/write raw block devices
346         Part->Node.Inode = (Disk << 8) | Num;
347         Part->Node.ImplPtr = Part->Name;
348         
349         Part->Node.Read = ATA_ReadFS;
350         Part->Node.Write = ATA_WriteFS;
351         Part->Node.IOCtl = ATA_IOCtl;
352         LOG("Made '%s' (&Node=%p)", Part->Name, &Part->Node);
353         LEAVE('-');
354 }
355
356 /**
357  * \fn void ATA_ParseGPT(int Disk)
358  * \brief Parses the GUID Partition Table
359  */
360 void ATA_ParseGPT(int Disk)
361 {
362         ///\todo Support GPT Disks
363         Warning("GPT Disks are currently unsupported");
364 }
365
366 /**
367  * \fn Uint16 ATA_GetPortBase(int Disk)
368  * \brief Returns the base port for a given disk
369  */
370 Uint16 ATA_GetBasePort(int Disk)
371 {
372         switch(Disk)
373         {
374         case 0: case 1:         return IDE_PRI_BASE;
375         case 2: case 3:         return IDE_SEC_BASE;
376         }
377         return 0;
378 }
379
380 /**
381  * \fn char *ATA_ReadDir(tVFS_Node *Node, int Pos)
382  */
383 char *ATA_ReadDir(tVFS_Node *Node, int Pos)
384 {
385         if(Pos >= giATA_NumNodes || Pos < 0)    return NULL;
386         return strdup( gATA_Nodes[Pos]->ImplPtr );
387 }
388
389 /**
390  * \fn tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name)
391  */
392 tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name)
393 {
394          int    part;
395         // Check first character
396         if(Name[0] < 'A' || Name[0] > 'A'+MAX_ATA_DISKS)
397                 return NULL;
398         // Raw Disk
399         if(Name[1] == '\0') {
400                 if( gATA_Disks[Name[0]-'A'].Sectors == 0 )
401                         return NULL;
402                 return &gATA_Disks[Name[0]-'A'].Node;
403         }
404         
405         // Partitions
406         if(Name[1] < '0' || '9' < Name[1])      return NULL;
407         if(Name[2] == '\0') {   // <= 9
408                 part = Name[1] - '0';
409                 part --;
410                 return &gATA_Disks[Name[0]-'A'].Partitions[part].Node;
411         }
412         // > 9
413         if('0' > Name[2] || '9' < Name[2])      return NULL;
414         if(Name[3] != '\0')     return NULL;
415         
416         part = (Name[1] - '0') * 10;
417         part += Name[2] - '0';
418         part --;
419         return &gATA_Disks[Name[0]-'A'].Partitions[part].Node;
420         
421 }
422
423 /**
424  * \fn Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
425  */
426 Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
427 {
428          int    disk = Node->Inode >> 8;
429          int    part = Node->Inode & 0xFF;
430         
431         // Raw Disk Access
432         if(part == 0xFF)
433         {
434                 if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE )
435                         return 0;
436                 if( Offset + Length > gATA_Disks[disk].Sectors*SECTOR_SIZE )
437                         Length = gATA_Disks[disk].Sectors*SECTOR_SIZE - Offset;
438         }
439         // Partition
440         else
441         {
442                 if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
443                         return 0;
444                 if( Offset + Length > gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
445                         Length = gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE - Offset;
446                 Offset += gATA_Disks[disk].Partitions[part].Start * SECTOR_SIZE;
447         }
448         
449         //Log("ATA_ReadFS: (Node=%p, Offset=0x%llx, Length=0x%llx, Buffer=%p)", Node, Offset, Length, Buffer);
450         return DrvUtil_ReadBlock(Offset, Length, Buffer, ATA_ReadRaw, SECTOR_SIZE, disk);
451 }
452
453 /**
454  * \fn Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
455  */
456 Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
457 {
458          int    disk = Node->Inode >> 8;
459          int    part = Node->Inode & 0xFF;
460         
461         // Raw Disk Access
462         if(part == 0xFF)
463         {
464                 if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE )
465                         return 0;
466                 if( Offset + Length > gATA_Disks[disk].Sectors*SECTOR_SIZE )
467                         Length = gATA_Disks[disk].Sectors*SECTOR_SIZE - Offset;
468         }
469         // Partition
470         else
471         {
472                 if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
473                         return 0;
474                 if( Offset + Length > gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
475                         Length = gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE - Offset;
476                 Offset += gATA_Disks[disk].Partitions[part].Start * SECTOR_SIZE;
477         }
478         
479         Log("ATA_WriteFS: (Node=%p, Offset=0x%llx, Length=0x%llx, Buffer=%p)", Node, Offset, Length, Buffer);
480         Debug_HexDump("ATA_WriteFS", Buffer, Length);
481         return DrvUtil_WriteBlock(Offset, Length, Buffer, ATA_ReadRaw, ATA_WriteRaw, SECTOR_SIZE, disk);
482 }
483
484 /**
485  * \fn int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data)
486  * \brief IO Control Funtion
487  */
488 int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data)
489 {
490         switch(Id)
491         {
492         case DRV_IOCTL_TYPE:    return DRV_TYPE_DISK;
493         }
494         return 0;
495 }
496
497 // --- Disk Access ---
498 /**
499  * \fn Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
500  */
501 Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
502 {
503          int    ret;
504         Uint    offset;
505         Uint    done = 0;
506          
507         // Pass straight on to ATA_ReadDMAPage if we can
508         if(Count <= MAX_DMA_SECTORS)
509         {
510                 ret = ATA_ReadDMA(Disk, Address, Count, Buffer);
511                 if(ret == 0)    return 0;
512                 return Count;
513         }
514         
515         // Else we will have to break up the transfer
516         offset = 0;
517         while(Count > MAX_DMA_SECTORS)
518         {
519                 ret = ATA_ReadDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset);
520                 // Check for errors
521                 if(ret != 1)    return done;
522                 // Change Position
523                 done += MAX_DMA_SECTORS;
524                 Count -= MAX_DMA_SECTORS;
525                 offset += MAX_DMA_SECTORS*SECTOR_SIZE;
526         }
527         
528         ret = ATA_ReadDMA(Disk, Address+offset, Count, Buffer+offset);
529         if(ret != 1)    return 0;
530         return done+Count;
531 }
532
533 /**
534  * \fn Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
535  */
536 Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
537 {
538          int    ret;
539         Uint    offset;
540         Uint    done = 0;
541          
542         // Pass straight on to ATA_WriteDMA if we can
543         if(Count <= MAX_DMA_SECTORS)
544         {
545                 ret = ATA_WriteDMA(Disk, Address, Count, Buffer);
546                 if(ret == 0)    return 0;
547                 return Count;
548         }
549         
550         // Else we will have to break up the transfer
551         offset = 0;
552         while(Count > MAX_DMA_SECTORS)
553         {
554                 ret = ATA_WriteDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset);
555                 // Check for errors
556                 if(ret != 1)    return done;
557                 // Change Position
558                 done += MAX_DMA_SECTORS;
559                 Count -= MAX_DMA_SECTORS;
560                 offset += MAX_DMA_SECTORS*SECTOR_SIZE;
561         }
562         
563         ret = ATA_WriteDMA(Disk, Address+offset, Count, Buffer+offset);
564         if(ret != 1)    return 0;
565         return done+Count;
566 }
567
568 /**
569  * \fn int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
570  */
571 int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
572 {
573          int    cont = (Disk>>1)&1;     // Controller ID
574          int    disk = Disk & 1;
575         Uint16  base;
576         
577         ENTER("iDisk XAddress iCount pBuffer", Disk, Address, Count, Buffer);
578         
579         // Check if the count is small enough
580         if(Count > MAX_DMA_SECTORS) {
581                 Warning("Passed too many sectors for a bulk DMA read (%i > %i)",
582                         Count, MAX_DMA_SECTORS);
583                 LEAVE('i');
584                 return 0;
585         }
586         
587         // Get exclusive access to the disk controller
588         LOCK( &giaATA_ControllerLock[ cont ] );
589         
590         // Set Size
591         gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
592         
593         // Get Port Base
594         base = ATA_GetBasePort(Disk);
595         
596         // Reset IRQ Flag
597         gaATA_IRQs[cont] = 0;
598         
599         // Set up transfer
600         outb(base+0x01, 0x00);
601         if( Address > 0x0FFFFFFF )      // Use LBA48
602         {
603                 outb(base+0x6, 0x40 | (disk << 4));
604                 outb(base+0x2, 0 >> 8); // Upper Sector Count
605                 outb(base+0x3, Address >> 24);  // Low 2 Addr
606                 outb(base+0x3, Address >> 28);  // Mid 2 Addr
607                 outb(base+0x3, Address >> 32);  // High 2 Addr
608         }
609         else
610         {
611                 outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr
612         }
613         
614         outb(base+0x02, (Uint8) Count);         // Sector Count
615         outb(base+0x03, (Uint8) Address);               // Low Addr
616         outb(base+0x04, (Uint8) (Address >> 8));        // Middle Addr
617         outb(base+0x05, (Uint8) (Address >> 16));       // High Addr
618         
619         LOG("Starting Transfer");
620         #if START_BEFORE_CMD
621         // Start transfer
622         ATA_int_BusMasterWriteByte( cont << 3, 9 );     // Read and start
623         if( Address > 0x0FFFFFFF )
624                 outb(base+0x07, HDD_DMA_R48);   // Read Command (LBA48)
625         else
626                 outb(base+0x07, HDD_DMA_R28);   // Read Command (LBA28)
627         #else
628         if( Address > 0x0FFFFFFF )
629                 outb(base+0x07, HDD_DMA_R48);   // Read Command (LBA48)
630         else
631                 outb(base+0x07, HDD_DMA_R28);   // Read Command (LBA28)
632         // Start transfer
633         ATA_int_BusMasterWriteByte( cont << 3, 9 );     // Read and start
634         #endif
635         
636         // Wait for transfer to complete
637         //ATA_int_BusMasterWriteByte( (cont << 3) + 2, 0x4 );
638         while( gaATA_IRQs[cont] == 0 ) {
639                 //Uint8 val = ATA_int_BusMasterReadByte( (cont << 3) + 2, 0x4 );
640                 //LOG("val = 0x%02x", val);
641                 Threads_Yield();
642         }
643         
644         // Complete Transfer
645         ATA_int_BusMasterWriteByte( cont << 3, 0 );     // Write and stop
646         
647         LOG("Transfer Completed & Acknowledged");
648         
649         // Copy to destination buffer
650         memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
651         
652         // Release controller lock
653         RELEASE( &giaATA_ControllerLock[ cont ] );
654         
655         LEAVE('i', 1);
656         return 1;
657 }
658
659 /**
660  * \fn int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
661  */
662 int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
663 {
664          int    cont = (Disk>>1)&1;     // Controller ID
665          int    disk = Disk & 1;
666         Uint16  base;
667         
668         // Check if the count is small enough
669         if(Count > MAX_DMA_SECTORS)     return 0;
670         
671         // Get exclusive access to the disk controller
672         LOCK( &giaATA_ControllerLock[ cont ] );
673         
674         // Set Size
675         gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
676         
677         // Get Port Base
678         base = ATA_GetBasePort(Disk);
679         
680         // Set up transfer
681         outb(base+0x01, 0x00);
682         if( Address > 0x0FFFFFFF )      // Use LBA48
683         {
684                 outb(base+0x6, 0x40 | (disk << 4));
685                 outb(base+0x2, 0 >> 8); // Upper Sector Count
686                 outb(base+0x3, Address >> 24);  // Low 2 Addr
687                 outb(base+0x3, Address >> 28);  // Mid 2 Addr
688                 outb(base+0x3, Address >> 32);  // High 2 Addr
689         }
690         else
691         {
692                 outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr
693         }
694         
695         outb(base+0x02, (Uint8) Count);         // Sector Count
696         outb(base+0x03, (Uint8) Address);               // Low Addr
697         outb(base+0x04, (Uint8) (Address >> 8));        // Middle Addr
698         outb(base+0x05, (Uint8) (Address >> 16));       // High Addr
699         if( Address > 0x0FFFFFFF )
700                 outb(base+0x07, HDD_DMA_W48);   // Write Command (LBA48)
701         else
702                 outb(base+0x07, HDD_DMA_W28);   // Write Command (LBA28)
703         
704         // Reset IRQ Flag
705         gaATA_IRQs[cont] = 0;
706         
707         // Copy to output buffer
708         memcpy( gATA_Buffers[cont], Buffer, Count*SECTOR_SIZE );
709         
710         // Start transfer
711         ATA_int_BusMasterWriteByte( cont << 3, 1 );     // Write and start
712         
713         // Wait for transfer to complete
714         while( gaATA_IRQs[cont] == 0 )  Threads_Yield();
715         
716         // Complete Transfer
717         ATA_int_BusMasterWriteByte( cont << 3, 0 );     // Write and stop
718         
719         // Release controller lock
720         RELEASE( &giaATA_ControllerLock[ cont ] );
721         
722         return 1;
723 }
724
725 /**
726  * \fn void ATA_IRQHandlerPri(int unused)
727  */
728 void ATA_IRQHandlerPri(int unused)
729 {
730         Uint8   val;
731         
732         // IRQ bit set for Primary Controller
733         val = ATA_int_BusMasterReadByte( 0x2 );
734         LOG("IRQ val = 0x%x", val);
735         if(val & 4) {
736                 LOG("IRQ hit (val = 0x%x)", val);
737                 ATA_int_BusMasterWriteByte( 0x2, 4 );
738                 gaATA_IRQs[0] = 1;
739                 return ;
740         }
741 }
742
743 /**
744  * \fn void ATA_IRQHandlerSec(int unused)
745  */
746 void ATA_IRQHandlerSec(int unused)
747 {
748         Uint8   val;
749         // IRQ bit set for Secondary Controller
750         val = ATA_int_BusMasterReadByte( 0xA );
751         if(val & 4) {
752                 LOG("IRQ hit (val = 0x%x)", val);
753                 ATA_int_BusMasterWriteByte( 0xA, 4 );
754                 gaATA_IRQs[1] = 1;
755                 return ;
756         }
757 }
758
759 /**
760  * \fn Uint8 ATA_int_BusMasterReadByte(int Ofs)
761  */
762 Uint8 ATA_int_BusMasterReadByte(int Ofs)
763 {
764         if( gATA_BusMasterBase & 1 )
765                 return inb( (gATA_BusMasterBase & ~1) + Ofs );
766         else
767                 return *(Uint8*)(gATA_BusMasterBasePtr + Ofs);
768 }
769
770 /**
771  * \fn void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
772  * \brief Writes a byte to a Bus Master Register
773  */
774 void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
775 {
776         if( gATA_BusMasterBase & 1 )
777                 outb( (gATA_BusMasterBase & ~1) + Ofs, Value );
778         else
779                 *(Uint8*)(gATA_BusMasterBasePtr + Ofs) = Value;
780 }
781
782 /**
783  * \fn void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
784  * \brief Writes a dword to a Bus Master Register
785  */
786 void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
787 {
788         
789         if( gATA_BusMasterBase & 1 )
790                 outd( (gATA_BusMasterBase & ~1) + Ofs, Value );
791         else
792                 *(Uint32*)(gATA_BusMasterBasePtr + Ofs) = Value;
793 }

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