Kernel - Slight reworks to timer code
[tpg/acess2.git] / Modules / Storage / ATA / io.c
1 /*
2  * Acess2 IDE Harddisk Driver
3  * - io.c
4  *
5  * Disk Input/Output control
6  */
7 #define DEBUG   0
8 #include <acess.h>
9 #include <modules.h>    // Needed for error codes
10 #include <drv_pci.h>
11 #include "common.h"
12
13 // === MACROS ===
14 #define IO_DELAY()      do{inb(0x80); inb(0x80); inb(0x80); inb(0x80);}while(0)
15
16 // === Constants ===
17 #define IDE_PRI_BASE    0x1F0
18 #define IDE_PRI_CTRL    0x3F6
19 #define IDE_SEC_BASE    0x170
20 #define IDE_SEC_CTRL    0x376
21
22 #define IDE_PRDT_LAST   0x8000
23 /**
24  \enum HddControls
25  \brief Commands to be sent to HDD_CMD
26 */
27 enum HddControls {
28         HDD_PIO_R28 = 0x20,
29         HDD_PIO_R48 = 0x24,
30         HDD_DMA_R48 = 0x25,
31         HDD_PIO_W28 = 0x30,
32         HDD_PIO_W48 = 0x34,
33         HDD_DMA_W48 = 0x35,
34         HDD_DMA_R28 = 0xC8,
35         HDD_DMA_W28 = 0xCA,
36         HDD_IDENTIFY = 0xEC
37 };
38
39 // === TYPES ===
40 /**
41  * \brief PRDT Entry
42  */
43 typedef struct
44 {
45         Uint32  PBufAddr;       // Physical Buffer Address
46         Uint16  Bytes;  // Size of transfer entry
47         Uint16  Flags;  // Flags
48 } __attribute__ ((packed))      tPRDT_Ent;
49
50 /**
51  * \brief Structure returned by the ATA IDENTIFY command
52  */
53 typedef struct
54 {
55         Uint16  Flags;          // 1
56         Uint16  Usused1[9];     // 10
57         char    SerialNum[20];  // 20
58         Uint16  Usused2[3];     // 23
59         char    FirmwareVer[8]; // 27
60         char    ModelNumber[40];        // 47
61         Uint16  SectPerInt;     // 48 - Low byte only
62         Uint16  Unused3;        // 49
63         Uint16  Capabilities[2];        // 51
64         Uint16  Unused4[2];     // 53
65         Uint16  ValidExtData;   // 54
66         Uint16  Unused5[5];      // 59
67         Uint16  SizeOfRWMultiple;       // 60
68         Uint32  Sectors28;      // LBA 28 Sector Count
69         Uint16  Unused6[100-62];
70         Uint64  Sectors48;      // LBA 48 Sector Count
71         Uint16  Unused7[256-104];
72 } __attribute__ ((packed))      tIdentify;
73
74 // === PROTOTYPES ===
75  int    ATA_SetupIO(void);
76 Uint64  ATA_GetDiskSize(int Disk);
77 Uint16  ATA_GetBasePort(int Disk);
78 // Read/Write DMA
79  int    ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
80  int    ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, const void *Buffer);
81 // IRQs
82 void    ATA_IRQHandlerPri(int UNUSED(IRQ), void *UNUSED(Ptr));
83 void    ATA_IRQHandlerSec(int UNUSED(IRQ), void *UNUSED(Ptr));
84 // Controller IO
85 Uint8   ATA_int_BusMasterReadByte(int Ofs);
86 Uint32  ATA_int_BusMasterReadDWord(int Ofs);
87 void    ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value);
88 void    ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value);
89
90 // === GLOBALS ===
91 // - BusMaster IO Addresses
92 Uint32  gATA_BusMasterBase;     //!< True Address (IO/MMIO)
93 Uint8   *gATA_BusMasterBasePtr; //!< Paging Mapped MMIO (If needed)
94 // - IRQs
95  int    gATA_IRQPri = 14;
96  int    gATA_IRQSec = 15;
97 volatile int    gaATA_IRQs[2] = {0};
98 // - Locks to avoid tripping
99 tMutex  glaATA_ControllerLock[2];
100 // - Buffers!
101 Uint8   gATA_Buffers[2][(MAX_DMA_SECTORS+0xFFF)&~0xFFF] __attribute__ ((section(".padata")));
102 // - PRDTs
103 tPRDT_Ent       gATA_PRDTs[2] = {
104         {0, 512, IDE_PRDT_LAST},
105         {0, 512, IDE_PRDT_LAST}
106 };
107 tPAddr  gaATA_PRDT_PAddrs[2];
108
109 // === CODE ===
110 /**
111  * \brief Sets up the ATA controller's DMA mode
112  */
113 int ATA_SetupIO(void)
114 {
115          int    ent;
116
117         ENTER("");
118
119         // Get IDE Controller's PCI Entry
120         ent = PCI_GetDeviceByClass(0x010100, 0xFFFF00, -1);
121         LOG("ent = %i", ent);
122         gATA_BusMasterBase = PCI_GetBAR(ent, 4);
123         if( gATA_BusMasterBase == 0 ) {
124                 Log_Warning("ATA", "It seems that there is no Bus Master Controller on this machine. Get one");
125                 // TODO: Use PIO mode instead
126                 LEAVE('i', MODULE_ERR_NOTNEEDED);
127                 return MODULE_ERR_NOTNEEDED;
128         }
129         
130         LOG("BAR5 = 0x%x", PCI_GetBAR(ent, 5));
131         LOG("IRQ = %i", PCI_GetIRQ(ent));
132         
133         // Map memory
134         if( !(gATA_BusMasterBase & 1) )
135         {
136                 if( gATA_BusMasterBase < 0x100000 )
137                         gATA_BusMasterBasePtr = (void*)(KERNEL_BASE | (tVAddr)gATA_BusMasterBase);
138                 else
139                         gATA_BusMasterBasePtr = (void*)( MM_MapHWPages( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) );
140                 LOG("gATA_BusMasterBasePtr = %p", gATA_BusMasterBasePtr);
141         }
142         else {
143                 // Bit 0 is left set as a flag to other functions
144                 LOG("gATA_BusMasterBase = IO 0x%x", gATA_BusMasterBase & ~1);
145         }
146
147         // Register IRQs and get Buffers
148         IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri, NULL );
149         IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec, NULL );
150
151         gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (tVAddr)&gATA_Buffers[0] );
152         gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (tVAddr)&gATA_Buffers[1] );
153
154         LOG("gATA_PRDTs = {PBufAddr: 0x%x, PBufAddr: 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr);
155
156         gaATA_PRDT_PAddrs[0] = MM_GetPhysAddr( (tVAddr)&gATA_PRDTs[0] );
157         LOG("gaATA_PRDT_PAddrs[0] = 0x%x", gaATA_PRDT_PAddrs[0]);
158         ATA_int_BusMasterWriteDWord(4, gaATA_PRDT_PAddrs[0]);
159         
160         gaATA_PRDT_PAddrs[1] = MM_GetPhysAddr( (tVAddr)&gATA_PRDTs[1] );
161         LOG("gaATA_PRDT_PAddrs[1] = 0x%x", gaATA_PRDT_PAddrs[1]);
162         ATA_int_BusMasterWriteDWord(12, gaATA_PRDT_PAddrs[1]);
163
164         // Enable controllers
165         outb(IDE_PRI_BASE+1, 1);
166         outb(IDE_SEC_BASE+1, 1);
167         outb(IDE_PRI_CTRL, 0);
168         outb(IDE_SEC_CTRL, 0);
169         
170         // Make sure interrupts are ACKed
171         ATA_int_BusMasterWriteByte(2, 0x4);
172         ATA_int_BusMasterWriteByte(10, 0x4);
173
174         // return
175         LEAVE('i', MODULE_ERR_OK);
176         return MODULE_ERR_OK;
177 }
178
179 /**
180  * \brief Get the size (in sectors) of a disk
181  * \param Disk  Disk to get size of
182  * \return Number of sectors reported
183  * 
184  * Does an ATA IDENTIFY
185  */
186 Uint64 ATA_GetDiskSize(int Disk)
187 {
188         union {
189                 Uint16  buf[256];
190                 tIdentify       identify;
191         }       data;
192         Uint16  base;
193         Uint8   val;
194          int    i;
195         ENTER("iDisk", Disk);
196
197         base = ATA_GetBasePort( Disk );
198
199         // Send Disk Selector
200         if(Disk & 1)    // Slave
201                 outb(base+6, 0xB0);
202         else    // Master
203                 outb(base+6, 0xA0);
204         IO_DELAY();
205         
206         // Check for a floating bus
207         if( 0xFF == inb(base+7) ) {
208                 LOG("Floating bus");
209                 LEAVE('i', 0);
210                 return 0;
211         }
212         
213         // Check for the controller
214         // - Write to two RW ports and attempt to read back
215         outb(base+0x02, 0x66);
216         outb(base+0x03, 0xFF);
217         if(inb(base+0x02) != 0x66 || inb(base+0x03) != 0xFF) {
218                 LOG("No controller");
219                 LEAVE('i', 0);
220                 return 0;
221         }
222
223         // Send ATA IDENTIFY
224         outb(base+7, HDD_IDENTIFY);
225         IO_DELAY();
226         val = inb(base+7);      // Read status
227         LOG("val = 0x%02x", val);
228         if(val == 0) {
229                 LEAVE('i', 0);
230                 return 0;       // Disk does not exist
231         }
232
233         // Poll until BSY clears or ERR is set
234         // TODO: Timeout?
235         while( (val & 0x80) && !(val & 1) )
236                 val = inb(base+7);
237         LOG("BSY unset (0x%x)", val);
238         // and, wait for DRQ to set
239         while( !(val & 0x08) && !(val & 1))
240                 val = inb(base+7);
241         LOG("DRQ set (0x%x)", val);
242
243         // Check for an error
244         if(val & 1) {
245                 LEAVE('i', 0);
246                 return 0;       // Error occured, so return false
247         }
248
249         // Read Data
250         for( i = 0; i < 256; i++ )
251                 data.buf[i] = inw(base);
252
253         // Return the disk size
254         if(data.identify.Sectors48 != 0) {
255                 LEAVE('X', data.identify.Sectors48);
256                 return data.identify.Sectors48;
257         }
258         else {
259                 LEAVE('x', data.identify.Sectors28);
260                 return data.identify.Sectors28;
261         }
262 }
263
264 /**
265  * \fn Uint16 ATA_GetPortBase(int Disk)
266  * \brief Returns the base port for a given disk
267  */
268 Uint16 ATA_GetBasePort(int Disk)
269 {
270         switch(Disk)
271         {
272         case 0: case 1:         return IDE_PRI_BASE;
273         case 2: case 3:         return IDE_SEC_BASE;
274         }
275         return 0;
276 }
277
278 /**
279  * \fn int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
280  * \return Boolean Failure
281  */
282 int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
283 {
284          int    cont = (Disk>>1)&1;     // Controller ID
285          int    disk = Disk & 1;
286         Uint16  base;
287         Sint64  timeoutTime;
288
289         ENTER("iDisk XAddress iCount pBuffer", Disk, Address, Count, Buffer);
290
291         // Check if the count is small enough
292         if(Count > MAX_DMA_SECTORS) {
293                 Log_Warning("ATA", "Passed too many sectors for a bulk DMA read (%i > %i)",
294                         Count, MAX_DMA_SECTORS);
295                 LEAVE('i');
296                 return 1;
297         }
298         
299         // Hack to make debug hexdump noticable
300         #if 1
301         memset(Buffer, 0xFF, Count*SECTOR_SIZE);
302         #endif
303
304         // Get exclusive access to the disk controller
305         Mutex_Acquire( &glaATA_ControllerLock[ cont ] );
306
307         // Set Size
308         gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
309
310         // Get Port Base
311         base = ATA_GetBasePort(Disk);
312
313         // Reset IRQ Flag
314         gaATA_IRQs[cont] = 0;
315
316         #if 1
317         if( cont == 0 ) {
318                 outb(IDE_PRI_CTRL, 4);
319                 IO_DELAY();
320                 outb(IDE_PRI_CTRL, 0);
321         }
322         else {
323                 outb(IDE_SEC_CTRL, 4);
324                 IO_DELAY();
325                 outb(IDE_SEC_CTRL, 0);
326         }
327         #endif
328
329         // Set up transfer
330         if( Address > 0x0FFFFFFF )      // Use LBA48
331         {
332                 outb(base+0x6, 0x40 | (disk << 4));
333                 IO_DELAY();
334                 outb(base+0x2, 0 >> 8); // Upper Sector Count
335                 outb(base+0x3, Address >> 24);  // Low 2 Addr
336                 outb(base+0x4, Address >> 28);  // Mid 2 Addr
337                 outb(base+0x5, Address >> 32);  // High 2 Addr
338         }
339         else
340         {
341                 // Magic, Disk, High Address nibble
342                 outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F));
343                 //outb(base+0x06, 0xA0 | (disk << 4) | ((Address >> 24) & 0x0F));
344                 IO_DELAY();
345         }
346
347         //outb(base+0x01, 0x01);        //?
348         outb(base+0x02, Count & 0xFF);          // Sector Count
349         outb(base+0x03, Address & 0xFF);                // Low Addr
350         outb(base+0x04, (Address >> 8) & 0xFF); // Middle Addr
351         outb(base+0x05, (Address >> 16) & 0xFF);        // High Addr
352
353         LOG("Starting Transfer");
354         
355         // HACK: Ensure the PRDT is reset
356         ATA_int_BusMasterWriteDWord(cont*8+4, gaATA_PRDT_PAddrs[cont]);
357         ATA_int_BusMasterWriteByte(cont*8, 4);  // Reset IRQ
358         
359         LOG("gATA_PRDTs[%i].Bytes = %i", cont, gATA_PRDTs[cont].Bytes);
360         if( Address > 0x0FFFFFFF )
361                 outb(base+0x07, HDD_DMA_R48);   // Read Command (LBA48)
362         else
363                 outb(base+0x07, HDD_DMA_R28);   // Read Command (LBA28)
364
365         // Start transfer
366         ATA_int_BusMasterWriteByte( cont * 8, 9 );      // Read and start
367
368         // Wait for transfer to complete
369         timeoutTime = now() + ATA_TIMEOUT;
370         while( gaATA_IRQs[cont] == 0 && now() < timeoutTime)
371         {
372                 HALT();
373         }
374
375         // Complete Transfer
376         ATA_int_BusMasterWriteByte( cont * 8, 8 );      // Read and stop
377
378         #if DEBUG
379         {
380                 Uint8   val = inb(base+0x7);
381                 LOG("Status byte = 0x%02x, Controller Status = 0x%02x",
382                         val, ATA_int_BusMasterReadByte(cont * 8 + 2));
383         }
384         #else
385         inb(base+0x7);
386         #endif
387
388         if( gaATA_IRQs[cont] == 0 )
389         {
390                 if( ATA_int_BusMasterReadByte(cont * 8 + 2) & 0x4 ) {
391                         Log_Error("ATA", "BM Status reports an interrupt, but none recieved");
392                         ATA_int_BusMasterWriteByte(cont*8 + 2, 4);      // Clear interrupt
393                         memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
394                         Mutex_Release( &glaATA_ControllerLock[ cont ] );
395                         LEAVE('i', 0);
396                         return 0;
397                 }
398
399                 #if 1
400                 Debug_HexDump("ATA", Buffer, 512);
401                 #endif
402                 
403                 // Release controller lock
404                 Mutex_Release( &glaATA_ControllerLock[ cont ] );
405                 Log_Warning("ATA",
406                         "Read timeout on disk %i (Reading sector 0x%llx)",
407                         Disk, Address);
408                 // Return error
409                 LEAVE('i', 1);
410                 return 1;
411         }
412         else {
413                 LOG("Transfer Completed & Acknowledged");
414                 // Copy to destination buffer
415                 memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
416                 // Release controller lock
417                 Mutex_Release( &glaATA_ControllerLock[ cont ] );
418
419                 LEAVE('i', 0);
420                 return 0;
421         }
422 }
423
424 /**
425  * \fn int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
426  * \brief Write up to \a MAX_DMA_SECTORS to a disk
427  * \param Disk  Disk ID to write to
428  * \param Address       LBA of first sector
429  * \param Count Number of sectors to write (must be >= \a MAX_DMA_SECTORS)
430  * \param Buffer        Source buffer for data
431  * \return Boolean Failure
432  */
433 int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, const void *Buffer)
434 {
435          int    cont = (Disk>>1)&1;     // Controller ID
436          int    disk = Disk & 1;
437         Uint16  base;
438         Sint64  timeoutTime;
439
440         // Check if the count is small enough
441         if(Count > MAX_DMA_SECTORS)     return 1;
442
443         // Get exclusive access to the disk controller
444         Mutex_Acquire( &glaATA_ControllerLock[ cont ] );
445
446         // Set Size
447         gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
448
449         // Get Port Base
450         base = ATA_GetBasePort(Disk);
451
452         // Reset IRQ Flag
453         gaATA_IRQs[cont] = 0;
454         
455         // Set up transfer
456         outb(base+0x01, 0x00);
457         if( Address > 0x0FFFFFFF )      // Use LBA48
458         {
459                 outb(base+0x6, 0x40 | (disk << 4));
460                 outb(base+0x2, 0 >> 8); // Upper Sector Count
461                 outb(base+0x3, Address >> 24);  // Low 2 Addr
462                 outb(base+0x3, Address >> 28);  // Mid 2 Addr
463                 outb(base+0x3, Address >> 32);  // High 2 Addr
464         }
465         else
466         {
467                 // Magic, Disk, High Address nibble
468                 outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F));
469         }
470
471         outb(base+0x02, (Uint8) Count);         // Sector Count
472         outb(base+0x03, (Uint8) Address);               // Low Addr
473         outb(base+0x04, (Uint8) (Address >> 8));        // Middle Addr
474         outb(base+0x05, (Uint8) (Address >> 16));       // High Addr
475         if( Address > 0x0FFFFFFF )
476                 outb(base+0x07, HDD_DMA_W48);   // Write Command (LBA48)
477         else
478                 outb(base+0x07, HDD_DMA_W28);   // Write Command (LBA28)
479
480         // Copy to output buffer
481         memcpy( gATA_Buffers[cont], Buffer, Count*SECTOR_SIZE );
482
483         // Start transfer
484         ATA_int_BusMasterWriteByte( cont << 3, 1 );     // Write and start
485
486         // Wait for transfer to complete
487         timeoutTime = now() + ATA_TIMEOUT;
488         while( gaATA_IRQs[cont] == 0 && now() < timeoutTime)
489         {
490                 HALT();
491         }
492
493         // Complete Transfer
494         ATA_int_BusMasterWriteByte( cont << 3, 0 );     // Write and stop
495
496         // If the IRQ is unset, return error
497         if( gaATA_IRQs[cont] == 0 ) {
498                 // Release controller lock
499                 Mutex_Release( &glaATA_ControllerLock[ cont ] );
500                 return 1;       // Error
501         }
502         else {
503                 Mutex_Release( &glaATA_ControllerLock[ cont ] );
504                 return 0;
505         }
506 }
507
508 /**
509  * \brief Primary ATA Channel IRQ handler
510  */
511 void ATA_IRQHandlerPri(int UNUSED(IRQ), void *UNUSED(Ptr))
512 {
513         Uint8   val;
514
515         // IRQ bit set for Primary Controller
516         val = ATA_int_BusMasterReadByte( 0x2 );
517         LOG("IRQ val = 0x%x", val);
518         if(val & 4) {
519                 LOG("IRQ hit (val = 0x%x)", val);
520                 ATA_int_BusMasterWriteByte( 0x2, 4 );
521                 gaATA_IRQs[0] = 1;
522                 return ;
523         }
524 }
525
526 /**
527  * \brief Second ATA Channel IRQ handler
528  */
529 void ATA_IRQHandlerSec(int UNUSED(IRQ), void *UNUSED(Ptr))
530 {
531         Uint8   val;
532         // IRQ bit set for Secondary Controller
533         val = ATA_int_BusMasterReadByte( 0xA );
534         LOG("IRQ val = 0x%x", val);
535         if(val & 4) {
536                 LOG("IRQ hit (val = 0x%x)", val);
537                 ATA_int_BusMasterWriteByte( 0xA, 4 );
538                 gaATA_IRQs[1] = 1;
539                 return ;
540         }
541 }
542
543 /**
544  * \brief Read an 8-bit value from a Bus Master register
545  * \param Ofs   Register offset
546  */
547 Uint8 ATA_int_BusMasterReadByte(int Ofs)
548 {
549         if( gATA_BusMasterBase & 1 )
550                 return inb( (gATA_BusMasterBase & ~1) + Ofs );
551         else
552                 return *(Uint8*)(gATA_BusMasterBasePtr + Ofs);
553 }
554
555 /**
556  * \brief Read an 32-bit value from a Bus Master register
557  * \param Ofs   Register offset
558  */
559 Uint32 ATA_int_BusMasterReadDWord(int Ofs)
560 {
561         if( gATA_BusMasterBase & 1 )
562                 return ind( (gATA_BusMasterBase & ~1) + Ofs );
563         else
564                 return *(Uint32*)(gATA_BusMasterBasePtr + Ofs);
565 }
566
567 /**
568  * \brief Writes a byte to a Bus Master Register
569  * \param Ofs   Register Offset
570  * \param Value Value to write
571  */
572 void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
573 {
574         if( gATA_BusMasterBase & 1 )
575                 outb( (gATA_BusMasterBase & ~1) + Ofs, Value );
576         else
577                 *(Uint8*)(gATA_BusMasterBasePtr + Ofs) = Value;
578 }
579
580 /**
581  * \brief Writes a 32-bit value to a Bus Master Register
582  * \param Ofs   Register offset
583  * \param Value Value to write
584  */
585 void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
586 {
587         if( gATA_BusMasterBase & 1 )
588                 outd( (gATA_BusMasterBase & ~1) + Ofs, Value );
589         else
590                 *(Uint32*)(gATA_BusMasterBasePtr + Ofs) = Value;
591 }

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