02fb756c105facb7821c795de64873a96c80b7e9
[people/mcb30/legacybios.git] / src / disk.c
1 // 16bit code to access hard drives.
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 "disk.h" // floppy_13
9 #include "biosvar.h" // struct bregs
10 #include "config.h" // CONFIG_*
11 #include "cmos.h" // inb_cmos
12 #include "util.h" // debug_enter
13 #include "ata.h" // ATA_*
14
15
16 // ---------------------------------------------------------------------------
17 // ATA/ATAPI driver : device detection
18 // ---------------------------------------------------------------------------
19
20 void
21 ata_detect()
22 {
23     u8  hdcount, cdcount, device, type;
24     u8  buffer[0x0200];
25
26 #if CONFIG_MAX_ATA_INTERFACES > 0
27     SET_EBDA(ata.channels[0].iface,ATA_IFACE_ISA);
28     SET_EBDA(ata.channels[0].iobase1,0x1f0);
29     SET_EBDA(ata.channels[0].iobase2,0x3f0);
30     SET_EBDA(ata.channels[0].irq,14);
31 #endif
32 #if CONFIG_MAX_ATA_INTERFACES > 1
33     SET_EBDA(ata.channels[1].iface,ATA_IFACE_ISA);
34     SET_EBDA(ata.channels[1].iobase1,0x170);
35     SET_EBDA(ata.channels[1].iobase2,0x370);
36     SET_EBDA(ata.channels[1].irq,15);
37 #endif
38 #if CONFIG_MAX_ATA_INTERFACES > 2
39     SET_EBDA(ata.channels[2].iface,ATA_IFACE_ISA);
40     SET_EBDA(ata.channels[2].iobase1,0x1e8);
41     SET_EBDA(ata.channels[2].iobase2,0x3e0);
42     SET_EBDA(ata.channels[2].irq,12);
43 #endif
44 #if CONFIG_MAX_ATA_INTERFACES > 3
45     SET_EBDA(ata.channels[3].iface,ATA_IFACE_ISA);
46     SET_EBDA(ata.channels[3].iobase1,0x168);
47     SET_EBDA(ata.channels[3].iobase2,0x360);
48     SET_EBDA(ata.channels[3].irq,11);
49 #endif
50 #if CONFIG_MAX_ATA_INTERFACES > 4
51 #error Please fill the ATA interface informations
52 #endif
53
54     // Device detection
55     hdcount=cdcount=0;
56
57     for(device=0; device<CONFIG_MAX_ATA_DEVICES; device++) {
58         u16 iobase1, iobase2;
59         u8  channel, slave, shift;
60         u8  sc, sn, cl, ch, st;
61
62         channel = device / 2;
63         slave = device % 2;
64
65         iobase1 =GET_EBDA(ata.channels[channel].iobase1);
66         iobase2 =GET_EBDA(ata.channels[channel].iobase2);
67
68         // Disable interrupts
69         outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC);
70
71         // Look for device
72         outb(slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0, iobase1+ATA_CB_DH);
73         outb(0x55, iobase1+ATA_CB_SC);
74         outb(0xaa, iobase1+ATA_CB_SN);
75         outb(0xaa, iobase1+ATA_CB_SC);
76         outb(0x55, iobase1+ATA_CB_SN);
77         outb(0x55, iobase1+ATA_CB_SC);
78         outb(0xaa, iobase1+ATA_CB_SN);
79
80         // If we found something
81         sc = inb(iobase1+ATA_CB_SC);
82         sn = inb(iobase1+ATA_CB_SN);
83
84         if ( (sc == 0x55) && (sn == 0xaa) ) {
85             SET_EBDA(ata.devices[device].type,ATA_TYPE_UNKNOWN);
86
87             // reset the channel
88             ata_reset(device);
89
90             // check for ATA or ATAPI
91             outb(slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0, iobase1+ATA_CB_DH);
92             sc = inb(iobase1+ATA_CB_SC);
93             sn = inb(iobase1+ATA_CB_SN);
94             if ((sc==0x01) && (sn==0x01)) {
95                 cl = inb(iobase1+ATA_CB_CL);
96                 ch = inb(iobase1+ATA_CB_CH);
97                 st = inb(iobase1+ATA_CB_STAT);
98
99                 if ((cl==0x14) && (ch==0xeb)) {
100                     SET_EBDA(ata.devices[device].type,ATA_TYPE_ATAPI);
101                 } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) {
102                     SET_EBDA(ata.devices[device].type,ATA_TYPE_ATA);
103                 } else if ((cl==0xff) && (ch==0xff)) {
104                     SET_EBDA(ata.devices[device].type,ATA_TYPE_NONE);
105                 }
106             }
107         }
108
109         type=GET_EBDA(ata.devices[device].type);
110
111         // Now we send a IDENTIFY command to ATA device
112         if(type == ATA_TYPE_ATA) {
113             u32 sectors;
114             u16 cylinders, heads, spt, blksize;
115             u8  translation, removable, mode;
116
117             //Temporary values to do the transfer
118             SET_EBDA(ata.devices[device].device,ATA_DEVICE_HD);
119             SET_EBDA(ata.devices[device].mode, ATA_MODE_PIO16);
120
121             u16 ret = ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE
122                                       , 1, 0, 0, 0, 0L
123                                       , GET_SEG(SS), (u32)buffer);
124             if (ret !=0)
125                 BX_PANIC("ata-detect: Failed to detect ATA device\n");
126
127             removable = (buffer[0] & 0x80) ? 1 : 0;
128             mode      = buffer[96] ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
129             blksize   = *(u16*)&buffer[10];
130
131             cylinders = *(u16*)&buffer[1*2]; // word 1
132             heads     = *(u16*)&buffer[3*2]; // word 3
133             spt       = *(u16*)&buffer[6*2]; // word 6
134
135             sectors   = *(u32*)&buffer[60*2]; // word 60 and word 61
136
137             SET_EBDA(ata.devices[device].device,ATA_DEVICE_HD);
138             SET_EBDA(ata.devices[device].removable, removable);
139             SET_EBDA(ata.devices[device].mode, mode);
140             SET_EBDA(ata.devices[device].blksize, blksize);
141             SET_EBDA(ata.devices[device].pchs.heads, heads);
142             SET_EBDA(ata.devices[device].pchs.cylinders, cylinders);
143             SET_EBDA(ata.devices[device].pchs.spt, spt);
144             SET_EBDA(ata.devices[device].sectors, sectors);
145             BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt);
146
147             translation = inb_cmos(0x39 + channel/2);
148             for (shift=device%4; shift>0; shift--)
149                 translation >>= 2;
150             translation &= 0x03;
151
152             SET_EBDA(ata.devices[device].translation, translation);
153
154             switch (translation) {
155             case ATA_TRANSLATION_NONE:
156                 BX_INFO("none");
157                 break;
158             case ATA_TRANSLATION_LBA:
159                 BX_INFO("lba");
160                 break;
161             case ATA_TRANSLATION_LARGE:
162                 BX_INFO("large");
163                 break;
164             case ATA_TRANSLATION_RECHS:
165                 BX_INFO("r-echs");
166                 break;
167             }
168             switch (translation) {
169             case ATA_TRANSLATION_NONE:
170                 break;
171             case ATA_TRANSLATION_LBA:
172                 spt = 63;
173                 sectors /= 63;
174                 heads = sectors / 1024;
175                 if (heads>128) heads = 255;
176                 else if (heads>64) heads = 128;
177                 else if (heads>32) heads = 64;
178                 else if (heads>16) heads = 32;
179                 else heads=16;
180                 cylinders = sectors / heads;
181                 break;
182             case ATA_TRANSLATION_RECHS:
183                 // Take care not to overflow
184                 if (heads==16) {
185                     if(cylinders>61439) cylinders=61439;
186                     heads=15;
187                     cylinders = (u16)((u32)(cylinders)*16/15);
188                 }
189                 // then go through the large bitshift process
190             case ATA_TRANSLATION_LARGE:
191                 while(cylinders > 1024) {
192                     cylinders >>= 1;
193                     heads <<= 1;
194
195                     // If we max out the head count
196                     if (heads > 127) break;
197                 }
198                 break;
199             }
200             // clip to 1024 cylinders in lchs
201             if (cylinders > 1024) cylinders=1024;
202             BX_INFO(" LCHS=%d/%d/%d\n", cylinders, heads, spt);
203
204             SET_EBDA(ata.devices[device].lchs.heads, heads);
205             SET_EBDA(ata.devices[device].lchs.cylinders, cylinders);
206             SET_EBDA(ata.devices[device].lchs.spt, spt);
207
208             // fill hdidmap
209             SET_EBDA(ata.hdidmap[hdcount], device);
210             hdcount++;
211         }
212
213         // Now we send a IDENTIFY command to ATAPI device
214         if(type == ATA_TYPE_ATAPI) {
215
216             u8  type, removable, mode;
217             u16 blksize;
218
219             //Temporary values to do the transfer
220             SET_EBDA(ata.devices[device].device,ATA_DEVICE_CDROM);
221             SET_EBDA(ata.devices[device].mode, ATA_MODE_PIO16);
222
223             u16 ret = ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET
224                                       , 1, 0, 0, 0, 0L
225                                       , GET_SEG(SS), (u32)buffer);
226             if (ret != 0)
227                 BX_PANIC("ata-detect: Failed to detect ATAPI device\n");
228
229             type      = buffer[1] & 0x1f;
230             removable = (buffer[0] & 0x80) ? 1 : 0;
231             mode      = buffer[96] ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
232             blksize   = 2048;
233
234             SET_EBDA(ata.devices[device].device, type);
235             SET_EBDA(ata.devices[device].removable, removable);
236             SET_EBDA(ata.devices[device].mode, mode);
237             SET_EBDA(ata.devices[device].blksize, blksize);
238
239             // fill cdidmap
240             SET_EBDA(ata.cdidmap[cdcount], device);
241             cdcount++;
242         }
243
244         u32 sizeinmb = 0;
245         u16 ataversion;
246         u8  c, i, version=0, model[41];
247
248         switch (type) {
249         case ATA_TYPE_ATA:
250             sizeinmb = GET_EBDA(ata.devices[device].sectors);
251             sizeinmb >>= 11;
252         case ATA_TYPE_ATAPI:
253             // Read ATA/ATAPI version
254             ataversion=((u16)(buffer[161])<<8) | buffer[160];
255             for(version=15;version>0;version--) {
256                 if ((ataversion&(1<<version))!=0)
257                     break;
258             }
259
260             // Read model name
261             for (i=0;i<20;i++) {
262                 model[i*2] = buffer[(i*2)+54+1];
263                 model[(i*2)+1] = buffer[(i*2)+54];
264             }
265
266             // Reformat
267             model[40] = 0x00;
268             for (i=39;i>0;i--) {
269                 if (model[i]==0x20)
270                     model[i] = 0x00;
271                 else
272                     break;
273             }
274             break;
275         }
276
277         switch (type) {
278         case ATA_TYPE_ATA:
279             printf("ata%d %s: ",channel,slave?" slave":"master");
280             i=0;
281             while ((c=model[i++]))
282                 printf("%c",c);
283             if (sizeinmb < (1UL<<16))
284                 printf(" ATA-%d Hard-Disk (%4u MBytes)\n", version, (u16)sizeinmb);
285             else
286                 printf(" ATA-%d Hard-Disk (%4u GBytes)\n", version, (u16)(sizeinmb>>10));
287             break;
288         case ATA_TYPE_ATAPI:
289             printf("ata%d %s: ",channel,slave?" slave":"master");
290             i=0;
291             while ((c=model[i++]))
292                 printf("%c",c);
293             if (GET_EBDA(ata.devices[device].device)==ATA_DEVICE_CDROM)
294                 printf(" ATAPI-%d CD-Rom/DVD-Rom\n",version);
295             else
296                 printf(" ATAPI-%d Device\n",version);
297             break;
298         case ATA_TYPE_UNKNOWN:
299             printf("ata%d %s: Unknown device\n",channel,slave?" slave":"master");
300             break;
301         }
302     }
303
304     // Store the devices counts
305     SET_EBDA(ata.hdcount, hdcount);
306     SET_EBDA(ata.cdcount, cdcount);
307     SET_BDA(disk_count, hdcount);
308
309     printf("\n");
310
311     // FIXME : should use bios=cmos|auto|disable bits
312     // FIXME : should know about translation bits
313     // FIXME : move hard_drive_post here
314
315 }
316
317
318 static inline void
319 disk_ret(struct bregs *regs, u8 code)
320 {
321     regs->ah = code;
322     SET_BDA(disk_last_status, code);
323     set_cf(regs, code);
324 }
325
326 // disk controller reset
327 static void
328 disk_1300(struct bregs *regs, u8 device)
329 {
330     ata_reset(device);
331 }
332
333 // read disk status
334 static void
335 disk_1301(struct bregs *regs, u8 device)
336 {
337     regs->ah = GET_BDA(disk_last_status);
338     disk_ret(regs, DISK_RET_SUCCESS);
339 }
340
341 static int
342 check_params(struct bregs *regs, u8 device)
343 {
344     debug_stub(regs);
345
346     u16 count       = regs->al;
347     u16 cylinder    = regs->ch | ((((u16) regs->cl) << 2) & 0x300);
348     u16 sector      = regs->cl & 0x3f;
349     u16 head        = regs->dh;
350
351     if ((count > 128) || (count == 0) || (sector == 0)) {
352         BX_INFO("int13_harddisk: function %02x, parameter out of range!\n"
353                 , regs->ah);
354         disk_ret(regs, DISK_RET_EPARAM);
355         return -1;
356     }
357
358     u16 nlc   = GET_EBDA(ata.devices[device].lchs.cylinders);
359     u16 nlh   = GET_EBDA(ata.devices[device].lchs.heads);
360     u16 nlspt = GET_EBDA(ata.devices[device].lchs.spt);
361
362     bprintf(0, "dev=%d c=%d h=%d s=%d nc=%d nh=%d ns=%d\n"
363             , device, cylinder, head, sector
364             , nlc, nlh, nlspt);
365
366     // sanity check on cyl heads, sec
367     if ( (cylinder >= nlc) || (head >= nlh) || (sector > nlspt )) {
368         BX_INFO("int13_harddisk: function %02x, parameters out of"
369                 " range %04x/%04x/%04x!\n"
370                 , regs->ah, cylinder, head, sector);
371         disk_ret(regs, DISK_RET_EPARAM);
372         return -1;
373     }
374     return 0;
375 }
376
377 static void
378 disk_1302(struct bregs *regs, u8 device)
379 {
380     debug_stub(regs);
381     int ret = check_params(regs, device);
382     if (ret)
383         return;
384     u16 count       = regs->al;
385     u16 cylinder    = regs->ch | ((((u16) regs->cl) << 2) & 0x300);
386     u16 sector      = regs->cl & 0x3f;
387     u16 head        = regs->dh;
388     u16 nph   = GET_EBDA(ata.devices[device].pchs.heads);
389     u16 npspt = GET_EBDA(ata.devices[device].pchs.spt);
390
391     u16 nlh   = GET_EBDA(ata.devices[device].lchs.heads);
392     u16 nlspt = GET_EBDA(ata.devices[device].lchs.spt);
393
394     u32 lba = 0;
395     // if needed, translate lchs to lba, and execute command
396     if ( (nph != nlh) || (npspt != nlspt)) {
397         lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt)
398                + (u32)sector - 1);
399         sector = 0; // this forces the command to be lba
400     }
401
402     u16 segment = regs->es;
403     u16 offset  = regs->bx;
404
405     u8 status = ata_cmd_data_in(device, ATA_CMD_READ_SECTORS
406                                 , count, cylinder, head, sector
407                                 , lba, segment, offset);
408
409     // Set nb of sector transferred
410     regs->al = GET_EBDA(ata.trsfsectors);
411
412     if (status != 0) {
413         BX_INFO("int13_harddisk: function %02x, error %02x !\n",regs->ah,status);
414         disk_ret(regs, DISK_RET_EBADTRACK);
415     }
416     disk_ret(regs, DISK_RET_SUCCESS);
417 }
418
419 static void
420 disk_1303(struct bregs *regs, u8 device)
421 {
422     debug_stub(regs);
423     int ret = check_params(regs, device);
424     if (ret)
425         return;
426     u16 count       = regs->al;
427     u16 cylinder    = regs->ch | ((((u16) regs->cl) << 2) & 0x300);
428     u16 sector      = regs->cl & 0x3f;
429     u16 head        = regs->dh;
430     u16 nph   = GET_EBDA(ata.devices[device].pchs.heads);
431     u16 npspt = GET_EBDA(ata.devices[device].pchs.spt);
432
433     u16 nlh   = GET_EBDA(ata.devices[device].lchs.heads);
434     u16 nlspt = GET_EBDA(ata.devices[device].lchs.spt);
435
436     u32 lba = 0;
437     // if needed, translate lchs to lba, and execute command
438     if ( (nph != nlh) || (npspt != nlspt)) {
439         lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt)
440                + (u32)sector - 1);
441         sector = 0; // this forces the command to be lba
442     }
443
444     u16 segment = regs->es;
445     u16 offset  = regs->bx;
446
447     u8 status = ata_cmd_data_out(device, ATA_CMD_READ_SECTORS
448                                  , count, cylinder, head, sector
449                                  , lba, segment, offset);
450
451     // Set nb of sector transferred
452     regs->al = GET_EBDA(ata.trsfsectors);
453
454     if (status != 0) {
455         BX_INFO("int13_harddisk: function %02x, error %02x !\n",regs->ah,status);
456         disk_ret(regs, DISK_RET_EBADTRACK);
457     }
458     disk_ret(regs, DISK_RET_SUCCESS);
459 }
460
461 static void
462 disk_1304(struct bregs *regs, u8 device)
463 {
464     int ret = check_params(regs, device);
465     if (ret)
466         return;
467     // FIXME verify
468     disk_ret(regs, DISK_RET_SUCCESS);
469 }
470
471 #define DISK_STUB(regs) do {                    \
472         struct bregs *__regs = (regs);          \
473         debug_stub(__regs);                     \
474         disk_ret(__regs, DISK_RET_SUCCESS);     \
475     } while (0)
476
477 // format disk track
478 static void
479 disk_1305(struct bregs *regs, u8 device)
480 {
481     DISK_STUB(regs);
482 }
483
484 // read disk drive parameters
485 static void
486 disk_1308(struct bregs *regs, u8 device)
487 {
488     // Get logical geometry from table
489     u16 nlc = GET_EBDA(ata.devices[device].lchs.cylinders);
490     u16 nlh = GET_EBDA(ata.devices[device].lchs.heads);
491     u16 nlspt = GET_EBDA(ata.devices[device].lchs.spt);
492     u16 count = GET_EBDA(ata.hdcount);
493
494     nlc = nlc - 2; /* 0 based , last sector not used */
495     regs->al = 0;
496     regs->ch = nlc & 0xff;
497     regs->cl = ((nlc >> 2) & 0xc0) | (nlspt & 0x3f);
498     regs->dh = nlh - 1;
499     regs->dl = count; /* FIXME returns 0, 1, or n hard drives */
500
501     // FIXME should set ES & DI
502     disk_ret(regs, DISK_RET_SUCCESS);
503
504     debug_stub(regs);
505 }
506
507 // check drive ready
508 static void
509 disk_1310(struct bregs *regs, u8 device)
510 {
511     // should look at 40:8E also???
512
513     // Read the status from controller
514     u8 status = inb(GET_EBDA(ata.channels[device/2].iobase1) + ATA_CB_STAT);
515     if ( (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY )
516         disk_ret(regs, DISK_RET_SUCCESS);
517     else
518         disk_ret(regs, DISK_RET_ENOTREADY);
519 }
520
521 // read disk drive size
522 static void
523 disk_1315(struct bregs *regs, u8 device)
524 {
525     // Get logical geometry from table
526     u16 nlc   = GET_EBDA(ata.devices[device].lchs.cylinders);
527     u16 nlh   = GET_EBDA(ata.devices[device].lchs.heads);
528     u16 nlspt = GET_EBDA(ata.devices[device].lchs.spt);
529
530     // Compute sector count seen by int13
531     u32 lba = (u32)(nlc - 1) * (u32)nlh * (u32)nlspt;
532     regs->cx = lba >> 16;
533     regs->dx = lba & 0xffff;
534
535     disk_ret(regs, 0);
536     regs->ah = 3; // hard disk accessible
537 }
538
539 static void
540 disk_13XX(struct bregs *regs, u8 device)
541 {
542     BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", regs->ah);
543     disk_ret(regs, DISK_RET_EPARAM);
544 }
545
546 static void
547 disk_13(struct bregs *regs, u8 drive)
548 {
549     if (! CONFIG_ATA) {
550         disk_13XX(regs, drive);
551         return;
552     }
553
554     debug_stub(regs);
555
556     // clear completion flag
557     SET_BDA(disk_interrupt_flag, 0);
558
559     // basic check : device has to be defined
560     if (drive < 0x80 || drive >= 0x80 + CONFIG_MAX_ATA_DEVICES) {
561         disk_13XX(regs, drive);
562         return;
563     }
564
565     // Get the ata channel
566     u8 device = GET_EBDA(ata.hdidmap[drive-0x80]);
567
568     // basic check : device has to be valid
569     if (device >= CONFIG_MAX_ATA_DEVICES) {
570         disk_13XX(regs, drive);
571         return;
572     }
573
574     switch (regs->ah) {
575     case 0x00: disk_1300(regs, device); break;
576     case 0x01: disk_1301(regs, device); break;
577     case 0x02: disk_1302(regs, device); break;
578     case 0x03: disk_1303(regs, device); break;
579     case 0x04: disk_1304(regs, device); break;
580     case 0x05: disk_1305(regs, device); break;
581     case 0x08: disk_1308(regs, device); break;
582     case 0x10: disk_1310(regs, device); break;
583     case 0x15: disk_1315(regs, device); break;
584     // XXX - several others defined
585     default:   disk_13XX(regs, device); break;
586     }
587 }
588
589 static void
590 handle_legacy_disk(struct bregs *regs, u8 drive)
591 {
592     if (drive < 0x80) {
593         floppy_13(regs, drive);
594         return;
595     }
596 #if BX_USE_ATADRV
597     if (drive >= 0xE0) {
598         int13_cdrom(regs); // xxx
599         return;
600     }
601 #endif
602
603     disk_13(regs, drive);
604 }
605
606 void VISIBLE
607 handle_40(struct bregs *regs)
608 {
609     debug_enter(regs);
610     handle_legacy_disk(regs, regs->dl);
611     debug_exit(regs);
612 }
613
614 // INT 13h Fixed Disk Services Entry Point
615 void VISIBLE
616 handle_13(struct bregs *regs)
617 {
618     //debug_enter(regs);
619     u8 drive = regs->dl;
620     // XXX
621 #if BX_ELTORITO_BOOT
622     if (regs->ah >= 0x4a || regs->ah <= 0x4d) {
623         int13_eltorito(regs);
624     } else if (cdemu_isactive() && cdrom_emulated_drive()) {
625         int13_cdemu(regs);
626     } else
627 #endif
628         handle_legacy_disk(regs, drive);
629     debug_exit(regs);
630 }
631
632 // record completion in BIOS task complete flag
633 void VISIBLE
634 handle_76(struct bregs *regs)
635 {
636     debug_enter(regs);
637     SET_BDA(floppy_harddisk_info, 0xff);
638     eoi_both_pics();
639 }