Optimize insb/outsb/insw/etc. functions.
[people/mcb30/legacybios.git] / src / ata.c
1 // Low level ATA disk access
2 //
3 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2002  MandrakeSoft S.A.
5 //
6 // This file may be distributed under the terms of the GNU GPLv3 license.
7
8 #include "ata.h" // ATA_*
9 #include "types.h" // u8
10 #include "ioport.h" // inb
11 #include "util.h" // BX_INFO
12 #include "cmos.h" // inb_cmos
13
14 #define TIMEOUT 0
15 #define BSY 1
16 #define NOT_BSY 2
17 #define NOT_BSY_DRQ 3
18 #define NOT_BSY_NOT_DRQ 4
19 #define NOT_BSY_RDY 5
20
21 #define IDE_TIMEOUT 32000u //32 seconds max for IDE ops
22
23 #define DEBUGF1(fmt, args...) bprintf(0, fmt , ##args)
24 #define DEBUGF(fmt, args...)
25
26 // XXX - lots of redundancy in this file.
27
28 static int
29 await_ide(u8 when_done, u16 base, u16 timeout)
30 {
31     u32 time=0,last=0;
32     // for the times you're supposed to throw one away
33     u16 status = inb(base + ATA_CB_STAT);
34     for (;;) {
35         status = inb(base+ATA_CB_STAT);
36         time++;
37         u8 result;
38         if (when_done == BSY)
39             result = status & ATA_CB_STAT_BSY;
40         else if (when_done == NOT_BSY)
41             result = !(status & ATA_CB_STAT_BSY);
42         else if (when_done == NOT_BSY_DRQ)
43             result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_DRQ);
44         else if (when_done == NOT_BSY_NOT_DRQ)
45             result = !(status & ATA_CB_STAT_BSY) && !(status & ATA_CB_STAT_DRQ);
46         else if (when_done == NOT_BSY_RDY)
47             result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_RDY);
48         else if (when_done == TIMEOUT)
49             result = 0;
50
51         if (result)
52             return 0;
53         // mod 2048 each 16 ms
54         if (time>>16 != last) {
55             last = time >>16;
56             DEBUGF("await_ide: (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY)"
57                    " %d time= %d timeout= %d\n"
58                    , when_done, time>>11, timeout);
59         }
60         if (status & ATA_CB_STAT_ERR) {
61             DEBUGF("await_ide: ERROR (TIMEOUT,BSY,!BSY,!BSY_DRQ"
62                    ",!BSY_!DRQ,!BSY_RDY) %d time= %d timeout= %d\n"
63                    , when_done, time>>11, timeout);
64             return -1;
65         }
66         if ((timeout == 0) || ((time>>11) > timeout))
67             break;
68     }
69     BX_INFO("IDE time out\n");
70     return -1;
71 }
72
73
74 // ---------------------------------------------------------------------------
75 // ATA/ATAPI driver : software reset
76 // ---------------------------------------------------------------------------
77 // ATA-3
78 // 8.2.1 Software reset - Device 0
79
80 void
81 ata_reset(u16 device)
82 {
83     u16 iobase1, iobase2;
84     u8  channel, slave, sn, sc;
85     u8  type;
86
87     channel = device / 2;
88     slave = device % 2;
89
90     iobase1 = GET_EBDA(ata.channels[channel].iobase1);
91     iobase2 = GET_EBDA(ata.channels[channel].iobase2);
92
93     // Reset
94
95     // 8.2.1 (a) -- set SRST in DC
96     outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST, iobase2+ATA_CB_DC);
97
98     // 8.2.1 (b) -- wait for BSY
99     await_ide(BSY, iobase1, 20);
100
101     // 8.2.1 (f) -- clear SRST
102     outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC);
103
104     type=GET_EBDA(ata.devices[device].type);
105     if (type != ATA_TYPE_NONE) {
106
107         // 8.2.1 (g) -- check for sc==sn==0x01
108         // select device
109         outb(slave?ATA_CB_DH_DEV1:ATA_CB_DH_DEV0, iobase1+ATA_CB_DH);
110         sc = inb(iobase1+ATA_CB_SC);
111         sn = inb(iobase1+ATA_CB_SN);
112
113         if ( (sc==0x01) && (sn==0x01) ) {
114             if (type == ATA_TYPE_ATA) //ATA
115                 await_ide(NOT_BSY_RDY, iobase1, IDE_TIMEOUT);
116             else //ATAPI
117                 await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
118         }
119
120         // 8.2.1 (h) -- wait for not BSY
121         await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
122     }
123
124     // Enable interrupts
125     outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
126 }
127
128
129 // ---------------------------------------------------------------------------
130 // ATA/ATAPI driver : execute a data-in command
131 // ---------------------------------------------------------------------------
132       // returns
133       // 0 : no error
134       // 1 : BUSY bit set
135       // 2 : read error
136       // 3 : expected DRQ=1
137       // 4 : no sectors left to read/verify
138       // 5 : more sectors to read/verify
139       // 6 : no sectors left to write
140       // 7 : more sectors to write
141 u16
142 ata_cmd_data_in(u16 device, u16 command, u16 count, u16 cylinder
143                 , u16 head, u16 sector, u32 lba, u16 segment, u16 offset)
144 {
145     DEBUGF("ata_cmd_data_in d=%d cmd=%d count=%d c=%d h=%d s=%d"
146            " lba=%d seg=%x off=%x\n"
147            , device, command, count, cylinder, head, sector
148            , lba, segment, offset);
149
150     u8 channel = device / 2;
151     u8 slave   = device % 2;
152
153     u16 iobase1 = GET_EBDA(ata.channels[channel].iobase1);
154     u16 iobase2 = GET_EBDA(ata.channels[channel].iobase2);
155     u8 mode     = GET_EBDA(ata.devices[device].mode);
156
157     // Reset count of transferred data
158     SET_EBDA(ata.trsfsectors,0);
159     SET_EBDA(ata.trsfbytes,0L);
160     u8 current = 0;
161
162     u8 status = inb(iobase1 + ATA_CB_STAT);
163     if (status & ATA_CB_STAT_BSY)
164         return 1;
165
166     outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
167
168     // sector will be 0 only on lba access. Convert to lba-chs
169     if (sector == 0) {
170         if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) {
171             outb(0x00, iobase1 + ATA_CB_FR);
172             outb((count >> 8) & 0xff, iobase1 + ATA_CB_SC);
173             outb(lba >> 24, iobase1 + ATA_CB_SN);
174             outb(0, iobase1 + ATA_CB_CL);
175             outb(0, iobase1 + ATA_CB_CH);
176             command |= 0x04;
177             count &= (1UL << 8) - 1;
178             lba &= (1UL << 24) - 1;
179         }
180         sector = (u16) (lba & 0x000000ffL);
181         cylinder = (u16) ((lba>>8) & 0x0000ffffL);
182         head = ((u16) ((lba>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
183     }
184
185     outb(0x00, iobase1 + ATA_CB_FR);
186     outb(count, iobase1 + ATA_CB_SC);
187     outb(sector, iobase1 + ATA_CB_SN);
188     outb(cylinder & 0x00ff, iobase1 + ATA_CB_CL);
189     outb(cylinder >> 8, iobase1 + ATA_CB_CH);
190     outb((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (u8) head
191          , iobase1 + ATA_CB_DH);
192     outb(command, iobase1 + ATA_CB_CMD);
193
194     await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
195     status = inb(iobase1 + ATA_CB_STAT);
196
197     if (status & ATA_CB_STAT_ERR) {
198         DEBUGF("ata_cmd_data_in : read error\n");
199         return 2;
200     } else if ( !(status & ATA_CB_STAT_DRQ) ) {
201         DEBUGF("ata_cmd_data_in : DRQ not set (status %02x)\n"
202                , (unsigned) status);
203         return 3;
204     }
205
206     // FIXME : move seg/off translation here
207
208     irq_enable();
209
210     while (1) {
211
212         if (offset > 0xf800) {
213             offset -= 0x800;
214             segment += 0x80;
215         }
216
217         if (mode == ATA_MODE_PIO32)
218             insl_seg(iobase1, segment, offset, 512 / 4);
219         else
220             insw_seg(iobase1, segment, offset, 512 / 2);
221         offset += 512;
222
223         current++;
224         SET_EBDA(ata.trsfsectors,current);
225         count--;
226         await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
227         status = inb(iobase1 + ATA_CB_STAT);
228         if (count == 0) {
229             if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ
230                             | ATA_CB_STAT_ERR) )
231                  != ATA_CB_STAT_RDY ) {
232                 DEBUGF("ata_cmd_data_in : no sectors left (status %02x)\n"
233                        , (unsigned) status);
234                 return 4;
235             }
236             break;
237         }
238         else {
239             if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ
240                             | ATA_CB_STAT_ERR) )
241                  != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
242                 DEBUGF("ata_cmd_data_in : more sectors left (status %02x)\n"
243                        , (unsigned) status);
244                 return 5;
245             }
246             continue;
247         }
248     }
249     // Enable interrupts
250     outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
251     return 0;
252 }
253
254 // ---------------------------------------------------------------------------
255 // ATA/ATAPI driver : execute a data-out command
256 // ---------------------------------------------------------------------------
257       // returns
258       // 0 : no error
259       // 1 : BUSY bit set
260       // 2 : read error
261       // 3 : expected DRQ=1
262       // 4 : no sectors left to read/verify
263       // 5 : more sectors to read/verify
264       // 6 : no sectors left to write
265       // 7 : more sectors to write
266 u16
267 ata_cmd_data_out(u16 device, u16 command, u16 count, u16 cylinder
268                  , u16 head, u16 sector, u32 lba, u16 segment, u16 offset)
269 {
270     DEBUGF("ata_cmd_data_out d=%d cmd=%d count=%d c=%d h=%d s=%d"
271            " lba=%d seg=%x off=%x\n"
272            , device, command, count, cylinder, head, sector
273            , lba, segment, offset);
274
275     u8 channel = device / 2;
276     u8 slave   = device % 2;
277
278     u16 iobase1 = GET_EBDA(ata.channels[channel].iobase1);
279     u16 iobase2 = GET_EBDA(ata.channels[channel].iobase2);
280     u8 mode     = GET_EBDA(ata.devices[device].mode);
281
282     // Reset count of transferred data
283     SET_EBDA(ata.trsfsectors,0);
284     SET_EBDA(ata.trsfbytes,0L);
285     u8 current = 0;
286
287     u8 status = inb(iobase1 + ATA_CB_STAT);
288     if (status & ATA_CB_STAT_BSY)
289         return 1;
290
291     outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
292
293     // sector will be 0 only on lba access. Convert to lba-chs
294     if (sector == 0) {
295         if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) {
296             outb(0x00, iobase1 + ATA_CB_FR);
297             outb((count >> 8) & 0xff, iobase1 + ATA_CB_SC);
298             outb(lba >> 24, iobase1 + ATA_CB_SN);
299             outb(0, iobase1 + ATA_CB_CL);
300             outb(0, iobase1 + ATA_CB_CH);
301             command |= 0x04;
302             count &= (1UL << 8) - 1;
303             lba &= (1UL << 24) - 1;
304         }
305         sector = (u16) (lba & 0x000000ffL);
306         cylinder = (u16) ((lba>>8) & 0x0000ffffL);
307         head = ((u16) ((lba>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
308     }
309
310     outb(0x00, iobase1 + ATA_CB_FR);
311     outb(count, iobase1 + ATA_CB_SC);
312     outb(sector, iobase1 + ATA_CB_SN);
313     outb(cylinder & 0x00ff, iobase1 + ATA_CB_CL);
314     outb(cylinder >> 8, iobase1 + ATA_CB_CH);
315     outb((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (u8) head
316          , iobase1 + ATA_CB_DH);
317     outb(command, iobase1 + ATA_CB_CMD);
318
319     await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
320     status = inb(iobase1 + ATA_CB_STAT);
321
322     if (status & ATA_CB_STAT_ERR) {
323         DEBUGF("ata_cmd_data_out : read error\n");
324         return 2;
325     } else if ( !(status & ATA_CB_STAT_DRQ) ) {
326         DEBUGF("ata_cmd_data_out : DRQ not set (status %02x)\n"
327                , (unsigned) status);
328         return 3;
329     }
330
331     // FIXME : move seg/off translation here
332
333     irq_enable();
334
335     while (1) {
336
337         if (offset > 0xf800) {
338             offset -= 0x800;
339             segment += 0x80;
340         }
341
342         if (mode == ATA_MODE_PIO32)
343             outsl_seg(iobase1, segment, offset, 512 / 4);
344         else
345             outsw_seg(iobase1, segment, offset, 512 / 2);
346         offset += 512;
347
348         current++;
349         SET_EBDA(ata.trsfsectors,current);
350         count--;
351         status = inb(iobase1 + ATA_CB_STAT);
352         if (count == 0) {
353             if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF
354                             | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
355                  != ATA_CB_STAT_RDY ) {
356                 DEBUGF("ata_cmd_data_out : no sectors left (status %02x)\n"
357                        , (unsigned) status);
358                 return 6;
359             }
360             break;
361         } else {
362             if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ
363                             | ATA_CB_STAT_ERR) )
364                  != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
365                 DEBUGF("ata_cmd_data_out : more sectors left (status %02x)\n"
366                        , (unsigned) status);
367                 return 7;
368             }
369             continue;
370         }
371     }
372     // Enable interrupts
373     outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
374     return 0;
375 }
376
377 // ---------------------------------------------------------------------------
378 // ATA/ATAPI driver : execute a packet command
379 // ---------------------------------------------------------------------------
380       // returns
381       // 0 : no error
382       // 1 : error in parameters
383       // 2 : BUSY bit set
384       // 3 : error
385       // 4 : not ready
386 u16
387 ata_cmd_packet(u16 device, u8 *cmdbuf, u8 cmdlen, u16 header
388                , u32 length, u8 inout, u16 bufseg, u16 bufoff)
389 {
390     u16 iobase1, iobase2;
391     u16 lcount, lbefore, lafter, count;
392     u8  channel, slave;
393     u8  status, mode, lmode;
394     u32 transfer;
395
396     channel = device / 2;
397     slave = device % 2;
398
399     // Data out is not supported yet
400     if (inout == ATA_DATA_OUT) {
401         BX_INFO("ata_cmd_packet: DATA_OUT not supported yet\n");
402         return 1;
403     }
404
405     // The header length must be even
406     if (header & 1) {
407         DEBUGF("ata_cmd_packet : header must be even (%04x)\n", header);
408         return 1;
409     }
410
411     iobase1 = GET_EBDA(ata.channels[channel].iobase1);
412     iobase2 = GET_EBDA(ata.channels[channel].iobase2);
413     mode    = GET_EBDA(ata.devices[device].mode);
414     transfer= 0L;
415
416     if (cmdlen < 12)
417         cmdlen=12;
418     if (cmdlen > 12)
419         cmdlen=16;
420     cmdlen>>=1;
421
422     // Reset count of transferred data
423     SET_EBDA(ata.trsfsectors,0);
424     SET_EBDA(ata.trsfbytes,0L);
425
426     status = inb(iobase1 + ATA_CB_STAT);
427     if (status & ATA_CB_STAT_BSY)
428         return 2;
429
430     outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
431     outb(0x00, iobase1 + ATA_CB_FR);
432     outb(0x00, iobase1 + ATA_CB_SC);
433     outb(0x00, iobase1 + ATA_CB_SN);
434     outb(0xfff0 & 0x00ff, iobase1 + ATA_CB_CL);
435     outb(0xfff0 >> 8, iobase1 + ATA_CB_CH);
436     outb(slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0, iobase1 + ATA_CB_DH);
437     outb(ATA_CMD_PACKET, iobase1 + ATA_CB_CMD);
438
439     // Device should ok to receive command
440     await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
441     status = inb(iobase1 + ATA_CB_STAT);
442
443     if (status & ATA_CB_STAT_ERR) {
444         DEBUGF("ata_cmd_packet : error, status is %02x\n", status);
445         return 3;
446     } else if ( !(status & ATA_CB_STAT_DRQ) ) {
447         DEBUGF("ata_cmd_packet : DRQ not set (status %02x)\n"
448                , (unsigned) status);
449         return 4;
450     }
451
452     // Send command to device
453     irq_enable();
454
455     outsw_seg(iobase1, GET_SEG(SS), (u32)cmdbuf, cmdlen);
456
457     if (inout == ATA_DATA_NO) {
458         await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
459         status = inb(iobase1 + ATA_CB_STAT);
460     } else {
461         u16 loops = 0;
462         u8 sc;
463         while (1) {
464
465             if (loops == 0) {//first time through
466                 status = inb(iobase2 + ATA_CB_ASTAT);
467                 await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
468             } else
469                 await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
470             loops++;
471
472             status = inb(iobase1 + ATA_CB_STAT);
473             sc = inb(iobase1 + ATA_CB_SC);
474
475             // Check if command completed
476             if(((inb(iobase1 + ATA_CB_SC)&0x7)==0x3) &&
477                ((status & (ATA_CB_STAT_RDY | ATA_CB_STAT_ERR)) == ATA_CB_STAT_RDY))
478                 break;
479
480             if (status & ATA_CB_STAT_ERR) {
481                 DEBUGF("ata_cmd_packet : error (status %02x)\n", status);
482                 return 3;
483             }
484
485             // Normalize address
486             bufseg += (bufoff / 16);
487             bufoff %= 16;
488
489             // Get the byte count
490             lcount =  ((u16)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL);
491
492             // adjust to read what we want
493             if (header > lcount) {
494                 lbefore=lcount;
495                 header-=lcount;
496                 lcount=0;
497             } else {
498                 lbefore=header;
499                 header=0;
500                 lcount-=lbefore;
501             }
502
503             if (lcount > length) {
504                 lafter=lcount-length;
505                 lcount=length;
506                 length=0;
507             } else {
508                 lafter=0;
509                 length-=lcount;
510             }
511
512             // Save byte count
513             count = lcount;
514
515             DEBUGF("Trying to read %04x bytes (%04x %04x %04x) "
516                    , lbefore+lcount+lafter, lbefore, lcount, lafter);
517             DEBUGF("to 0x%04x:0x%04x\n", bufseg, bufoff);
518
519             // If counts not dividable by 4, use 16bits mode
520             lmode = mode;
521             if (lbefore & 0x03) lmode=ATA_MODE_PIO16;
522             if (lcount  & 0x03) lmode=ATA_MODE_PIO16;
523             if (lafter  & 0x03) lmode=ATA_MODE_PIO16;
524
525             // adds an extra byte if count are odd. before is always even
526             if (lcount & 0x01) {
527                 lcount+=1;
528                 if ((lafter > 0) && (lafter & 0x01)) {
529                     lafter-=1;
530                 }
531             }
532
533             if (lmode == ATA_MODE_PIO32) {
534                 lcount>>=2; lbefore>>=2; lafter>>=2;
535             } else {
536                 lcount>>=1; lbefore>>=1; lafter>>=1;
537             }
538
539             int i;
540             for (i=0; i<lbefore; i++)
541                 if (lmode == ATA_MODE_PIO32)
542                     inl(iobase1);
543                 else
544                     inw(iobase1);
545
546             if (lmode == ATA_MODE_PIO32)
547                 insl_seg(iobase1, bufseg, bufoff, lcount);
548             else
549                 insw_seg(iobase1, bufseg, bufoff, lcount);
550
551             for (i=0; i<lafter; i++)
552                 if (lmode == ATA_MODE_PIO32)
553                     inl(iobase1);
554                 else
555                     inw(iobase1);
556
557             // Compute new buffer address
558             bufoff += count;
559
560             // Save transferred bytes count
561             transfer += count;
562             SET_EBDA(ata.trsfbytes,transfer);
563         }
564     }
565
566     // Final check, device must be ready
567     if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF
568                     | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
569          != ATA_CB_STAT_RDY ) {
570         DEBUGF("ata_cmd_packet : not ready (status %02x)\n"
571                , (unsigned) status);
572         return 4;
573     }
574
575     // Enable interrupts
576     outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
577     return 0;
578 }
579
580 u16
581 cdrom_read(u16 device, u32 lba, u32 count, u16 segment, u16 offset, u16 skip)
582 {
583     u16 sectors = (count + 2048 - 1) / 2048;
584
585     u8 atacmd[12];
586     memset(atacmd, 0, sizeof(atacmd));
587     atacmd[0]=0x28;                      // READ command
588     atacmd[7]=(sectors & 0xff00) >> 8;   // Sectors
589     atacmd[8]=(sectors & 0x00ff);        // Sectors
590     atacmd[2]=(lba & 0xff000000) >> 24;  // LBA
591     atacmd[3]=(lba & 0x00ff0000) >> 16;
592     atacmd[4]=(lba & 0x0000ff00) >> 8;
593     atacmd[5]=(lba & 0x000000ff);
594
595     return ata_cmd_packet(device, atacmd, sizeof(atacmd)
596                           , skip, count, ATA_DATA_IN
597                           , segment, offset);
598 }
599
600 // ---------------------------------------------------------------------------
601 // ATA/ATAPI driver : device detection
602 // ---------------------------------------------------------------------------
603
604 void
605 ata_detect()
606 {
607     u8  hdcount, cdcount, device, type;
608     u8  buffer[0x0200];
609     memset(buffer, 0, sizeof(buffer));
610
611 #if CONFIG_MAX_ATA_INTERFACES > 0
612     SET_EBDA(ata.channels[0].iface,ATA_IFACE_ISA);
613     SET_EBDA(ata.channels[0].iobase1,0x1f0);
614     SET_EBDA(ata.channels[0].iobase2,0x3f0);
615     SET_EBDA(ata.channels[0].irq,14);
616 #endif
617 #if CONFIG_MAX_ATA_INTERFACES > 1
618     SET_EBDA(ata.channels[1].iface,ATA_IFACE_ISA);
619     SET_EBDA(ata.channels[1].iobase1,0x170);
620     SET_EBDA(ata.channels[1].iobase2,0x370);
621     SET_EBDA(ata.channels[1].irq,15);
622 #endif
623 #if CONFIG_MAX_ATA_INTERFACES > 2
624     SET_EBDA(ata.channels[2].iface,ATA_IFACE_ISA);
625     SET_EBDA(ata.channels[2].iobase1,0x1e8);
626     SET_EBDA(ata.channels[2].iobase2,0x3e0);
627     SET_EBDA(ata.channels[2].irq,12);
628 #endif
629 #if CONFIG_MAX_ATA_INTERFACES > 3
630     SET_EBDA(ata.channels[3].iface,ATA_IFACE_ISA);
631     SET_EBDA(ata.channels[3].iobase1,0x168);
632     SET_EBDA(ata.channels[3].iobase2,0x360);
633     SET_EBDA(ata.channels[3].irq,11);
634 #endif
635 #if CONFIG_MAX_ATA_INTERFACES > 4
636 #error Please fill the ATA interface informations
637 #endif
638
639     // Device detection
640     hdcount=cdcount=0;
641
642     for(device=0; device<CONFIG_MAX_ATA_DEVICES; device++) {
643         u16 iobase1, iobase2;
644         u8  channel, slave, shift;
645         u8  sc, sn, cl, ch, st;
646
647         channel = device / 2;
648         slave = device % 2;
649
650         iobase1 =GET_EBDA(ata.channels[channel].iobase1);
651         iobase2 =GET_EBDA(ata.channels[channel].iobase2);
652
653         // Disable interrupts
654         outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC);
655
656         // Look for device
657         outb(slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0, iobase1+ATA_CB_DH);
658         outb(0x55, iobase1+ATA_CB_SC);
659         outb(0xaa, iobase1+ATA_CB_SN);
660         outb(0xaa, iobase1+ATA_CB_SC);
661         outb(0x55, iobase1+ATA_CB_SN);
662         outb(0x55, iobase1+ATA_CB_SC);
663         outb(0xaa, iobase1+ATA_CB_SN);
664
665         // If we found something
666         sc = inb(iobase1+ATA_CB_SC);
667         sn = inb(iobase1+ATA_CB_SN);
668
669         if ( (sc == 0x55) && (sn == 0xaa) ) {
670             SET_EBDA(ata.devices[device].type,ATA_TYPE_UNKNOWN);
671
672             // reset the channel
673             ata_reset(device);
674
675             // check for ATA or ATAPI
676             outb(slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0, iobase1+ATA_CB_DH);
677             sc = inb(iobase1+ATA_CB_SC);
678             sn = inb(iobase1+ATA_CB_SN);
679             if ((sc==0x01) && (sn==0x01)) {
680                 cl = inb(iobase1+ATA_CB_CL);
681                 ch = inb(iobase1+ATA_CB_CH);
682                 st = inb(iobase1+ATA_CB_STAT);
683
684                 if ((cl==0x14) && (ch==0xeb)) {
685                     SET_EBDA(ata.devices[device].type,ATA_TYPE_ATAPI);
686                 } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) {
687                     SET_EBDA(ata.devices[device].type,ATA_TYPE_ATA);
688                 } else if ((cl==0xff) && (ch==0xff)) {
689                     SET_EBDA(ata.devices[device].type,ATA_TYPE_NONE);
690                 }
691             }
692         }
693
694         type=GET_EBDA(ata.devices[device].type);
695
696         // Now we send a IDENTIFY command to ATA device
697         if(type == ATA_TYPE_ATA) {
698             u32 sectors;
699             u16 cylinders, heads, spt, blksize;
700             u8  translation, removable, mode;
701
702             //Temporary values to do the transfer
703             SET_EBDA(ata.devices[device].device,ATA_DEVICE_HD);
704             SET_EBDA(ata.devices[device].mode, ATA_MODE_PIO16);
705
706             u16 ret = ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE
707                                       , 1, 0, 0, 0, 0L
708                                       , GET_SEG(SS), (u32)buffer);
709             if (ret)
710                 BX_PANIC("ata-detect: Failed to detect ATA device\n");
711
712             removable = (buffer[0] & 0x80) ? 1 : 0;
713             mode      = buffer[96] ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
714             blksize   = *(u16*)&buffer[10];
715
716             cylinders = *(u16*)&buffer[1*2]; // word 1
717             heads     = *(u16*)&buffer[3*2]; // word 3
718             spt       = *(u16*)&buffer[6*2]; // word 6
719
720             sectors   = *(u32*)&buffer[60*2]; // word 60 and word 61
721
722             SET_EBDA(ata.devices[device].device,ATA_DEVICE_HD);
723             SET_EBDA(ata.devices[device].removable, removable);
724             SET_EBDA(ata.devices[device].mode, mode);
725             SET_EBDA(ata.devices[device].blksize, blksize);
726             SET_EBDA(ata.devices[device].pchs.heads, heads);
727             SET_EBDA(ata.devices[device].pchs.cylinders, cylinders);
728             SET_EBDA(ata.devices[device].pchs.spt, spt);
729             SET_EBDA(ata.devices[device].sectors, sectors);
730             BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt);
731
732             translation = inb_cmos(CMOS_BIOS_DISKTRANSFLAG + channel/2);
733             for (shift=device%4; shift>0; shift--)
734                 translation >>= 2;
735             translation &= 0x03;
736
737             SET_EBDA(ata.devices[device].translation, translation);
738
739             switch (translation) {
740             case ATA_TRANSLATION_NONE:
741                 BX_INFO("none");
742                 break;
743             case ATA_TRANSLATION_LBA:
744                 BX_INFO("lba");
745                 break;
746             case ATA_TRANSLATION_LARGE:
747                 BX_INFO("large");
748                 break;
749             case ATA_TRANSLATION_RECHS:
750                 BX_INFO("r-echs");
751                 break;
752             }
753             switch (translation) {
754             case ATA_TRANSLATION_NONE:
755                 break;
756             case ATA_TRANSLATION_LBA:
757                 spt = 63;
758                 sectors /= 63;
759                 heads = sectors / 1024;
760                 if (heads>128) heads = 255;
761                 else if (heads>64) heads = 128;
762                 else if (heads>32) heads = 64;
763                 else if (heads>16) heads = 32;
764                 else heads=16;
765                 cylinders = sectors / heads;
766                 break;
767             case ATA_TRANSLATION_RECHS:
768                 // Take care not to overflow
769                 if (heads==16) {
770                     if(cylinders>61439) cylinders=61439;
771                     heads=15;
772                     cylinders = (u16)((u32)(cylinders)*16/15);
773                 }
774                 // then go through the large bitshift process
775             case ATA_TRANSLATION_LARGE:
776                 while(cylinders > 1024) {
777                     cylinders >>= 1;
778                     heads <<= 1;
779
780                     // If we max out the head count
781                     if (heads > 127) break;
782                 }
783                 break;
784             }
785             // clip to 1024 cylinders in lchs
786             if (cylinders > 1024)
787                 cylinders=1024;
788             BX_INFO(" LCHS=%d/%d/%d\n", cylinders, heads, spt);
789
790             SET_EBDA(ata.devices[device].lchs.heads, heads);
791             SET_EBDA(ata.devices[device].lchs.cylinders, cylinders);
792             SET_EBDA(ata.devices[device].lchs.spt, spt);
793
794             // fill hdidmap
795             SET_EBDA(ata.idmap[0][hdcount], device);
796             hdcount++;
797         }
798
799         // Now we send a IDENTIFY command to ATAPI device
800         if(type == ATA_TYPE_ATAPI) {
801
802             u8  type, removable, mode;
803             u16 blksize;
804
805             //Temporary values to do the transfer
806             SET_EBDA(ata.devices[device].device,ATA_DEVICE_CDROM);
807             SET_EBDA(ata.devices[device].mode, ATA_MODE_PIO16);
808
809             u16 ret = ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET
810                                       , 1, 0, 0, 0, 0L
811                                       , GET_SEG(SS), (u32)buffer);
812             if (ret != 0)
813                 BX_PANIC("ata-detect: Failed to detect ATAPI device\n");
814
815             type      = buffer[1] & 0x1f;
816             removable = (buffer[0] & 0x80) ? 1 : 0;
817             mode      = buffer[96] ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
818             blksize   = 2048;
819
820             SET_EBDA(ata.devices[device].device, type);
821             SET_EBDA(ata.devices[device].removable, removable);
822             SET_EBDA(ata.devices[device].mode, mode);
823             SET_EBDA(ata.devices[device].blksize, blksize);
824
825             // fill cdidmap
826             SET_EBDA(ata.idmap[1][cdcount], device);
827             cdcount++;
828         }
829
830         u32 sizeinmb = 0;
831         u16 ataversion;
832         u8  c, i, version=0, model[41];
833
834         switch (type) {
835         case ATA_TYPE_ATA:
836             sizeinmb = GET_EBDA(ata.devices[device].sectors);
837             sizeinmb >>= 11;
838         case ATA_TYPE_ATAPI:
839             // Read ATA/ATAPI version
840             ataversion=((u16)(buffer[161])<<8) | buffer[160];
841             for(version=15;version>0;version--) {
842                 if ((ataversion&(1<<version))!=0)
843                     break;
844             }
845
846             // Read model name
847             for (i=0;i<20;i++) {
848                 model[i*2] = buffer[(i*2)+54+1];
849                 model[(i*2)+1] = buffer[(i*2)+54];
850             }
851
852             // Reformat
853             model[40] = 0x00;
854             for (i=39;i>0;i--) {
855                 if (model[i]==0x20)
856                     model[i] = 0x00;
857                 else
858                     break;
859             }
860             break;
861         }
862
863         switch (type) {
864         case ATA_TYPE_ATA:
865             printf("ata%d %s: ",channel,slave?" slave":"master");
866             i=0;
867             while ((c=model[i++]))
868                 printf("%c",c);
869             if (sizeinmb < (1UL<<16))
870                 printf(" ATA-%d Hard-Disk (%u MBytes)\n", version, (u16)sizeinmb);
871             else
872                 printf(" ATA-%d Hard-Disk (%u GBytes)\n", version, (u16)(sizeinmb>>10));
873             break;
874         case ATA_TYPE_ATAPI:
875             printf("ata%d %s: ",channel,slave?" slave":"master");
876             i=0;
877             while ((c=model[i++]))
878                 printf("%c",c);
879             if (GET_EBDA(ata.devices[device].device)==ATA_DEVICE_CDROM)
880                 printf(" ATAPI-%d CD-Rom/DVD-Rom\n",version);
881             else
882                 printf(" ATAPI-%d Device\n",version);
883             break;
884         case ATA_TYPE_UNKNOWN:
885             printf("ata%d %s: Unknown device\n",channel,slave?" slave":"master");
886             break;
887         }
888     }
889
890     // Store the devices counts
891     SET_EBDA(ata.hdcount, hdcount);
892     SET_EBDA(ata.cdcount, cdcount);
893     SET_BDA(disk_count, hdcount);
894
895     printf("\n");
896
897     // FIXME : should use bios=cmos|auto|disable bits
898     // FIXME : should know about translation bits
899     // FIXME : move hard_drive_post here
900 }