VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/BIOS-new/ata.c@ 38699

Last change on this file since 38699 was 38699, checked in by vboxsync, 13 years ago

Converted system BIOS to Watcom C.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.6 KB
Line 
1/*
2 * Copyright (C) 2006-2011 Oracle Corporation
3 *
4 * This file is part of VirtualBox Open Source Edition (OSE), as
5 * available from http://www.virtualbox.org. This file is free software;
6 * you can redistribute it and/or modify it under the terms of the GNU
7 * General Public License (GPL) as published by the Free Software
8 * Foundation, in version 2 as it comes in the "COPYING" file of the
9 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
10 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
11 * --------------------------------------------------------------------
12 *
13 * This code is based on:
14 *
15 * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
16 *
17 * Copyright (C) 2002 MandrakeSoft S.A.
18 *
19 * MandrakeSoft S.A.
20 * 43, rue d'Aboukir
21 * 75002 Paris - France
22 * http://www.linux-mandrake.com/
23 * http://www.mandrakesoft.com/
24 *
25 * This library is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU Lesser General Public
27 * License as published by the Free Software Foundation; either
28 * version 2 of the License, or (at your option) any later version.
29 *
30 * This library is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 * Lesser General Public License for more details.
34 *
35 * You should have received a copy of the GNU Lesser General Public
36 * License along with this library; if not, write to the Free Software
37 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
38 *
39 */
40
41
42#include <stdint.h>
43#include <stdarg.h>
44#include "inlines.h"
45#include "biosint.h"
46#include "ebda.h"
47#include "ata.h"
48
49#if DEBUG_ATA
50# define BX_DEBUG_ATA(...) BX_DEBUG(__VA_ARGS__)
51#else
52# define BX_DEBUG_ATA(...)
53#endif
54
55
56// ---------------------------------------------------------------------------
57// Start of ATA/ATAPI Driver
58// ---------------------------------------------------------------------------
59
60void insw_discard(unsigned nwords, unsigned port);
61#pragma aux insw_discard = \
62 ".286" \
63 "again:" \
64 "in ax,dx" \
65 "loop again" \
66 parm [cx] [dx] modify exact [cx ax] nomemory;
67
68void insd_discard(unsigned ndwords, unsigned port);
69#pragma aux insd_discard = \
70 ".386" \
71 "push eax" \
72 "again:" \
73 "in eax,dx" \
74 "loop again" \
75 "pop eax" \
76 parm [cx] [dx] modify exact [cx] nomemory;
77
78// ---------------------------------------------------------------------------
79// ATA/ATAPI driver : initialization
80// ---------------------------------------------------------------------------
81void BIOSCALL ata_init(void)
82{
83 uint16_t ebda_seg=read_word(0x0040,0x000E);
84 uint8_t channel, device;
85 ata_t __far *AtaData;
86
87 AtaData = ebda_seg :> &EbdaData->ata;
88
89 // Channels info init.
90 for (channel=0; channel<BX_MAX_ATA_INTERFACES; channel++) {
91 AtaData->channels[channel].iface = ATA_IFACE_NONE;
92 AtaData->channels[channel].iobase1 = 0x0;
93 AtaData->channels[channel].iobase2 = 0x0;
94 AtaData->channels[channel].irq = 0;
95 }
96
97 // Devices info init.
98 for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
99 AtaData->devices[device].type = ATA_TYPE_NONE;
100 AtaData->devices[device].device = ATA_DEVICE_NONE;
101 AtaData->devices[device].removable = 0;
102 AtaData->devices[device].lock = 0;
103 AtaData->devices[device].mode = ATA_MODE_NONE;
104 AtaData->devices[device].blksize = 0x200;
105 AtaData->devices[device].translation = ATA_TRANSLATION_NONE;
106 AtaData->devices[device].lchs.heads = 0;
107 AtaData->devices[device].lchs.cylinders = 0;
108 AtaData->devices[device].lchs.spt = 0;
109 AtaData->devices[device].pchs.heads = 0;
110 AtaData->devices[device].pchs.cylinders = 0;
111 AtaData->devices[device].pchs.spt = 0;
112 AtaData->devices[device].sectors = 0;
113 }
114
115 // hdidmap and cdidmap init.
116 for (device=0; device<BX_MAX_STORAGE_DEVICES; device++) {
117 AtaData->hdidmap[device] = BX_MAX_STORAGE_DEVICES;
118 AtaData->cdidmap[device] = BX_MAX_STORAGE_DEVICES;
119 }
120
121 AtaData->hdcount = 0;
122 AtaData->cdcount = 0;
123}
124
125// ---------------------------------------------------------------------------
126// ATA/ATAPI driver : software reset
127// ---------------------------------------------------------------------------
128// ATA-3
129// 8.2.1 Software reset - Device 0
130
131void ata_reset(uint16_t device)
132{
133 uint16_t ebda_seg = read_word(0x0040,0x000E);
134 uint16_t iobase1, iobase2;
135 uint8_t channel, slave, sn, sc;
136 uint16_t max;
137 uint16_t pdelay;
138 ata_t __far *AtaData;
139
140 AtaData = ebda_seg :> &EbdaData->ata;
141 channel = device / 2;
142 slave = device % 2;
143
144 iobase1 = AtaData->channels[channel].iobase1;
145 iobase2 = AtaData->channels[channel].iobase2;
146
147 // Reset
148
149 // 8.2.1 (a) -- set SRST in DC
150 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST);
151
152 // 8.2.1 (b) -- wait for BSY
153 max=0xff;
154 while(--max>0) {
155 uint8_t status = inb(iobase1+ATA_CB_STAT);
156 if ((status & ATA_CB_STAT_BSY) != 0)
157 break;
158 }
159
160 // 8.2.1 (f) -- clear SRST
161 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
162
163 if (AtaData->devices[device].type != ATA_TYPE_NONE) {
164 // 8.2.1 (g) -- check for sc==sn==0x01
165 // select device
166 outb(iobase1+ATA_CB_DH, slave?ATA_CB_DH_DEV1:ATA_CB_DH_DEV0);
167 sc = inb(iobase1+ATA_CB_SC);
168 sn = inb(iobase1+ATA_CB_SN);
169
170 if ( (sc==0x01) && (sn==0x01) ) {
171 // 8.2.1 (h) -- wait for not BSY
172 max=0xffff; /* The ATA specification says that the drive may be busy for up to 30 seconds. */
173 while(--max>0) {
174 uint8_t status = inb(iobase1+ATA_CB_STAT);
175 if ((status & ATA_CB_STAT_BSY) == 0)
176 break;
177 pdelay=0xffff;
178 while (--pdelay>0) {
179 /* nothing */
180 }
181 }
182 }
183 }
184
185 // 8.2.1 (i) -- wait for DRDY
186 max = 0x10; /* Speed up for virtual drives. Disks are immediately ready, CDs never */
187 while(--max>0) {
188 uint8_t status = inb(iobase1+ATA_CB_STAT);
189 if ((status & ATA_CB_STAT_RDY) != 0)
190 break;
191 }
192
193 // Enable interrupts
194 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
195}
196
197// ---------------------------------------------------------------------------
198// ATA/ATAPI driver : execute a data-in command
199// ---------------------------------------------------------------------------
200 // returns
201 // 0 : no error
202 // 1 : BUSY bit set
203 // 2 : read error
204 // 3 : expected DRQ=1
205 // 4 : no sectors left to read/verify
206 // 5 : more sectors to read/verify
207 // 6 : no sectors left to write
208 // 7 : more sectors to write
209uint16_t ata_cmd_data_in(uint16_t device, uint16_t command, uint16_t count, uint16_t cylinder,
210 uint16_t head, uint16_t sector, uint32_t lba, char __far *buffer)
211{
212 uint16_t ebda_seg = read_word(0x0040,0x000E);
213 uint16_t iobase1, iobase2, blksize, mult_blk_cnt;
214 uint8_t channel, slave;
215 uint8_t status, current, mode;
216 ata_t __far *AtaData;
217
218 AtaData = ebda_seg :> &EbdaData->ata;
219
220 channel = device / 2;
221 slave = device % 2;
222
223 iobase1 = AtaData->channels[channel].iobase1;
224 iobase2 = AtaData->channels[channel].iobase2;
225 mode = AtaData->devices[device].mode;
226 blksize = AtaData->devices[device].blksize;
227 if (blksize == 0) { /* If transfer size is exactly 64K */
228 if (mode == ATA_MODE_PIO32)
229 blksize = 0x4000;
230 else
231 blksize = 0x8000;
232 } else {
233 if (mode == ATA_MODE_PIO32)
234 blksize >>= 2;
235 else
236 blksize >>= 1;
237 }
238
239 status = inb(iobase1 + ATA_CB_STAT);
240 if (status & ATA_CB_STAT_BSY)
241 {
242 BX_DEBUG_ATA("%s: disk busy\n", __func__);
243 // Enable interrupts
244 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
245 return 1;
246 }
247
248 // sector will be 0 only on lba access. Convert to lba-chs
249 if (sector == 0) {
250 if (lba + count >= 268435456)
251 {
252 sector = (lba & 0xff000000L) >> 24;
253 cylinder = 0; /* The parameter lba is just a 32 bit value. */
254 outb(iobase1 + ATA_CB_SC, (count & 0xff00) >> 8);
255 outb(iobase1 + ATA_CB_SN, sector);
256 outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
257 outb(iobase1 + ATA_CB_CH, cylinder >> 8);
258 /* Leave the bottom 24 bits as is, they are treated correctly by the
259 * LBA28 code path. */
260 lba &= 0xffffff;
261 }
262 sector = (uint16_t) (lba & 0x000000ffL);
263 lba >>= 8;
264 cylinder = (uint16_t) (lba & 0x0000ffffL);
265 lba >>= 16;
266 head = ((uint16_t) (lba & 0x0000000fL)) | 0x40;
267 }
268
269 // Reset count of transferred data
270 AtaData->trsfsectors = 0;
271 AtaData->trsfbytes = 0;
272 current = 0;
273
274 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
275 outb(iobase1 + ATA_CB_FR, 0x00);
276 outb(iobase1 + ATA_CB_SC, count);
277 outb(iobase1 + ATA_CB_SN, sector);
278 outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
279 outb(iobase1 + ATA_CB_CH, cylinder >> 8);
280 outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (uint8_t) head );
281 outb(iobase1 + ATA_CB_CMD, command);
282
283 if (command == ATA_CMD_READ_MULTIPLE || command == ATA_CMD_READ_MULTIPLE_EXT) {
284 mult_blk_cnt = count;
285 count = 1;
286 } else {
287 mult_blk_cnt = 1;
288 }
289
290 while (1) {
291 status = inb(iobase1 + ATA_CB_STAT);
292 if ( !(status & ATA_CB_STAT_BSY) )
293 break;
294 }
295
296 if (status & ATA_CB_STAT_ERR) {
297 BX_DEBUG_ATA("%s: read error\n", __func__);
298 // Enable interrupts
299 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
300 return 2;
301 } else if ( !(status & ATA_CB_STAT_DRQ) ) {
302 BX_DEBUG_ATA("%s: DRQ not set (status %02x)\n", __func__, (unsigned) status);
303 // Enable interrupts
304 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
305 return 3;
306 }
307
308 // FIXME : move seg/off translation here
309
310 int_enable(); // enable higher priority interrupts
311
312 while (1) {
313
314 // adjust if there will be an overrun. 2K max sector size
315 if (FP_OFF(buffer) >= 0xF800)
316 buffer = MK_FP(FP_SEG(buffer) + 0x80, FP_OFF(buffer) - 0x800);
317
318 if (mode == ATA_MODE_PIO32) {
319 buffer = rep_insd(buffer, blksize, iobase1);
320 } else {
321 buffer = rep_insw(buffer, blksize, iobase1);
322 }
323 current += mult_blk_cnt;
324 AtaData->trsfsectors = current;
325 count--;
326 while (1) {
327 status = inb(iobase1 + ATA_CB_STAT);
328 if ( !(status & ATA_CB_STAT_BSY) )
329 break;
330 }
331 if (count == 0) {
332 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
333 != ATA_CB_STAT_RDY ) {
334 BX_DEBUG_ATA("%s: no sectors left (status %02x)\n", __func__, (unsigned) status);
335 // Enable interrupts
336 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
337 return 4;
338 }
339 break;
340 }
341 else {
342 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
343 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
344 BX_DEBUG_ATA("%s: more sectors left (status %02x)\n", __func__, (unsigned) status);
345 // Enable interrupts
346 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
347 return 5;
348 }
349 continue;
350 }
351 }
352 // Enable interrupts
353 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
354 return 0;
355}
356
357// ---------------------------------------------------------------------------
358// ATA/ATAPI driver : device detection
359// ---------------------------------------------------------------------------
360
361void BIOSCALL ata_detect(void)
362{
363 uint16_t ebda_seg = read_word(0x0040,0x000E);
364 uint8_t hdcount, cdcount, device, type;
365 uint8_t buffer[0x0200];
366 ata_t __far *AtaData;
367
368 AtaData = ebda_seg :> &EbdaData->ata;
369
370#if BX_MAX_ATA_INTERFACES > 0
371 AtaData->channels[0].iface = ATA_IFACE_ISA;
372 AtaData->channels[0].iobase1 = 0x1f0;
373 AtaData->channels[0].iobase2 = 0x3f0;
374 AtaData->channels[0].irq = 14;
375#endif
376#if BX_MAX_ATA_INTERFACES > 1
377 AtaData->channels[1].iface = ATA_IFACE_ISA;
378 AtaData->channels[1].iobase1 = 0x170;
379 AtaData->channels[1].iobase2 = 0x370;
380 AtaData->channels[1].irq = 15;
381#endif
382#if BX_MAX_ATA_INTERFACES > 2
383 AtaData->channels[2].iface = ATA_IFACE_ISA;
384 AtaData->channels[2].iobase1 = 0x1e8;
385 AtaData->channels[2].iobase2 = 0x3e0;
386 AtaData->channels[2].irq = 12;
387#endif
388#if BX_MAX_ATA_INTERFACES > 3
389 AtaData->channels[3].iface = ATA_IFACE_ISA;
390 AtaData->channels[3].iobase1 = 0x168;
391 AtaData->channels[3].iobase2 = 0x360;
392 AtaData->channels[3].irq = 11;
393#endif
394#if BX_MAX_ATA_INTERFACES > 4
395#error Please fill the ATA interface informations
396#endif
397
398 // Device detection
399 hdcount = cdcount = 0;
400
401 for (device = 0; device < BX_MAX_ATA_DEVICES; device++) {
402 uint16_t iobase1, iobase2;
403 uint8_t channel, slave;
404 uint8_t sc, sn, cl, ch, st;
405
406 channel = device / 2;
407 slave = device % 2;
408
409 iobase1 = AtaData->channels[channel].iobase1;
410 iobase2 = AtaData->channels[channel].iobase2;
411
412 // Disable interrupts
413 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
414
415 // Look for device
416 outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
417 outb(iobase1+ATA_CB_SC, 0x55);
418 outb(iobase1+ATA_CB_SN, 0xaa);
419 outb(iobase1+ATA_CB_SC, 0xaa);
420 outb(iobase1+ATA_CB_SN, 0x55);
421 outb(iobase1+ATA_CB_SC, 0x55);
422 outb(iobase1+ATA_CB_SN, 0xaa);
423
424 // If we found something
425 sc = inb(iobase1+ATA_CB_SC);
426 sn = inb(iobase1+ATA_CB_SN);
427
428 if ( (sc == 0x55) && (sn == 0xaa) ) {
429 AtaData->devices[device].type = ATA_TYPE_UNKNOWN;
430
431 // reset the channel
432 ata_reset(device);
433
434 // check for ATA or ATAPI
435 outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
436 sc = inb(iobase1+ATA_CB_SC);
437 sn = inb(iobase1+ATA_CB_SN);
438 if ((sc==0x01) && (sn==0x01)) {
439 cl = inb(iobase1+ATA_CB_CL);
440 ch = inb(iobase1+ATA_CB_CH);
441 st = inb(iobase1+ATA_CB_STAT);
442
443 if ((cl==0x14) && (ch==0xeb)) {
444 AtaData->devices[device].type = ATA_TYPE_ATAPI;
445 } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) {
446 AtaData->devices[device].type = ATA_TYPE_ATA;
447 } else if ((cl==0xff) && (ch==0xff)) {
448 AtaData->devices[device].type = ATA_TYPE_NONE;
449 }
450 }
451 }
452
453 // Enable interrupts
454 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
455
456 type = AtaData->devices[device].type;
457
458 // Now we send a IDENTIFY command to ATA device
459 if (type == ATA_TYPE_ATA) {
460 uint32_t sectors;
461 uint16_t cylinders, heads, spt, blksize;
462 uint16_t lcylinders, lheads, lspt;
463 uint8_t chsgeo_base;
464 uint8_t removable, mode;
465
466 //Temporary values to do the transfer
467 AtaData->devices[device].device = ATA_DEVICE_HD;
468 AtaData->devices[device].mode = ATA_MODE_PIO16;
469
470 if (ata_cmd_data_in(device, ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, buffer) !=0 )
471 BX_PANIC("ata-detect: Failed to detect ATA device\n");
472
473 removable = (*(buffer+0) & 0x80) ? 1 : 0;
474 mode = *(buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
475 blksize = 512; /* There is no sector size field any more. */
476
477 cylinders = *(uint16_t *)(buffer+(1*2)); // word 1
478 heads = *(uint16_t *)(buffer+(3*2)); // word 3
479 spt = *(uint16_t *)(buffer+(6*2)); // word 6
480
481 sectors = *(uint32_t *)(buffer+(60*2)); // word 60 and word 61
482 /** @todo update sectors to be a 64 bit number (also lba...). */
483 if (sectors == 268435455)
484 sectors = *(uint32_t *)(buffer+(100*2)); // words 100 to 103 (someday)
485 switch (device)
486 {
487 case 0:
488 chsgeo_base = 0x1e;
489 break;
490 case 1:
491 chsgeo_base = 0x26;
492 break;
493 case 2:
494 chsgeo_base = 0x67;
495 break;
496 case 3:
497 chsgeo_base = 0x70;
498 break;
499 case 4:
500 chsgeo_base = 0x40;
501 break;
502 case 5:
503 chsgeo_base = 0x48;
504 break;
505 case 6:
506 chsgeo_base = 0x50;
507 break;
508 case 7:
509 chsgeo_base = 0x58;
510 break;
511 default:
512 chsgeo_base = 0;
513 }
514 if (chsgeo_base != 0)
515 {
516 lcylinders = inb_cmos(chsgeo_base) + (inb_cmos(chsgeo_base+1) << 8);
517 lheads = inb_cmos(chsgeo_base+2);
518 lspt = inb_cmos(chsgeo_base+7);
519 }
520 else
521 {
522 lcylinders = 0;
523 lheads = 0;
524 lspt = 0;
525 }
526 BX_INFO("ata%d-%d: PCHS=%u/%d/%d LCHS=%u/%u/%u\n", channel, slave,
527 cylinders,heads, spt, lcylinders, lheads, lspt);
528
529 AtaData->devices[device].device = ATA_DEVICE_HD;
530 AtaData->devices[device].removable = removable;
531 AtaData->devices[device].mode = mode;
532 AtaData->devices[device].blksize = blksize;
533 AtaData->devices[device].pchs.heads = heads;
534 AtaData->devices[device].pchs.cylinders = cylinders;
535 AtaData->devices[device].pchs.spt = spt;
536 AtaData->devices[device].sectors = sectors;
537 AtaData->devices[device].lchs.heads = lheads;
538 AtaData->devices[device].lchs.cylinders = lcylinders;
539 AtaData->devices[device].lchs.spt = lspt;
540 if (device < 2)
541 {
542 uint8_t sum, i;
543 fdpt_t __far *fdpt;
544
545 if (device == 0)
546 fdpt = ebda_seg :> &EbdaData->fdpt0;
547 else
548 fdpt = ebda_seg :> &EbdaData->fdpt1;
549
550 /* Update the DPT for drive 0/1 pointed to by Int41/46. This used
551 * to be done at POST time with lots of ugly assembler code, which
552 * isn't worth the effort of converting from AMI to Award CMOS
553 * format. Just do it here. */
554 fdpt->lcyl = lcylinders;
555 fdpt->lhead = lheads;
556 fdpt->sig = 0xa0;
557 fdpt->spt = spt;
558 fdpt->cyl = cylinders;
559 fdpt->head = heads;
560 fdpt->lspt = spt;
561 sum = 0;
562 for (i = 0; i < 0xf; i++)
563 sum += *((uint8_t __far *)fdpt + i);
564 sum = -sum;
565 fdpt->csum = sum;
566 }
567
568 // fill hdidmap
569 AtaData->hdidmap[hdcount] = device;
570 hdcount++;
571 }
572
573 // Now we send an IDENTIFY command to ATAPI device
574 if (type == ATA_TYPE_ATAPI) {
575 uint8_t type, removable, mode;
576 uint16_t blksize;
577
578 // Temporary values to do the transfer
579 AtaData->devices[device].device = ATA_DEVICE_CDROM;
580 AtaData->devices[device].mode = ATA_MODE_PIO16;
581
582 if (ata_cmd_data_in(device, ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, buffer) != 0)
583 BX_PANIC("ata-detect: Failed to detect ATAPI device\n");
584
585 type = *(buffer+1) & 0x1f;
586 removable = (*(buffer+0) & 0x80) ? 1 : 0;
587 mode = *(buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
588 blksize = 2048;
589
590 AtaData->devices[device].device = type;
591 AtaData->devices[device].removable = removable;
592 AtaData->devices[device].mode = mode;
593 AtaData->devices[device].blksize = blksize;
594
595 // fill cdidmap
596 AtaData->cdidmap[cdcount] = device;
597 cdcount++;
598 }
599
600 {
601 uint32_t sizeinmb;
602 uint16_t ataversion;
603 uint8_t version, model[41];
604 int i;
605
606 switch (type) {
607 case ATA_TYPE_ATA:
608 sizeinmb = AtaData->devices[device].sectors;
609 sizeinmb >>= 11;
610 case ATA_TYPE_ATAPI:
611 // Read ATA/ATAPI version
612 ataversion = ((uint16_t)(*(buffer+161))<<8) | *(buffer+160);
613 for (version = 15; version > 0; version--) {
614 if ((ataversion & (1 << version)) !=0 )
615 break;
616 }
617
618 // Read model name
619 for (i = 0; i < 20; i++ ) {
620 *(model+(i*2)) = *(buffer+(i*2)+54+1);
621 *(model+(i*2)+1) = *(buffer+(i*2)+54);
622 }
623
624 // Reformat
625 *(model+40) = 0x00;
626 for ( i = 39; i > 0; i-- ){
627 if (*(model+i) == 0x20)
628 *(model+i) = 0x00;
629 else
630 break;
631 }
632 break;
633 }
634
635#ifdef VBOXz
636 // we don't want any noisy output for now
637#else /* !VBOX */
638 switch (type) {
639 int c;
640 case ATA_TYPE_ATA:
641 printf("ata%d %s: ", channel, slave ? " slave" : "master");
642 i=0;
643 while(c=*(model+i++))
644 printf("%c", c);
645 printf(" ATA-%d Hard-Disk (%lu MBytes)\n", version, sizeinmb);
646 break;
647 case ATA_TYPE_ATAPI:
648 printf("ata%d %s: ", channel, slave ? " slave" : "master");
649 i=0;
650 while(c=*(model+i++))
651 printf("%c", c);
652 if (AtaData->devices[device].device == ATA_DEVICE_CDROM)
653 printf(" ATAPI-%d CD-ROM/DVD-ROM\n", version);
654 else
655 printf(" ATAPI-%d Device\n", version);
656 break;
657 case ATA_TYPE_UNKNOWN:
658 printf("ata%d %s: Unknown device\n", channel , slave ? " slave" : "master");
659 break;
660 }
661#endif /* !VBOX */
662 }
663 }
664
665 // Store the devices counts
666 AtaData->hdcount = hdcount;
667 AtaData->cdcount = cdcount;
668 write_byte(0x40,0x75, hdcount);
669
670#ifdef VBOX
671 // we don't want any noisy output for now
672#else /* !VBOX */
673 printf("\n");
674#endif /* !VBOX */
675
676 // FIXME : should use bios=cmos|auto|disable bits
677 // FIXME : should know about translation bits
678 // FIXME : move hard_drive_post here
679
680}
681
682// ---------------------------------------------------------------------------
683// ATA/ATAPI driver : execute a data-out command
684// ---------------------------------------------------------------------------
685 // returns
686 // 0 : no error
687 // 1 : BUSY bit set
688 // 2 : read error
689 // 3 : expected DRQ=1
690 // 4 : no sectors left to read/verify
691 // 5 : more sectors to read/verify
692 // 6 : no sectors left to write
693 // 7 : more sectors to write
694uint16_t ata_cmd_data_out(uint16_t device, uint16_t command, uint16_t count, uint16_t cylinder,
695 uint16_t head, uint16_t sector, uint32_t lba, char __far *buffer)
696{
697 uint16_t ebda_seg = read_word(0x0040,0x000E);
698 uint16_t iobase1, iobase2, blksize;
699 uint8_t channel, slave;
700 uint8_t status, current, mode;
701 ata_t __far *AtaData;
702
703 AtaData = ebda_seg :> &EbdaData->ata;
704
705 channel = device / 2;
706 slave = device % 2;
707
708 iobase1 = AtaData->channels[channel].iobase1;
709 iobase2 = AtaData->channels[channel].iobase2;
710 mode = AtaData->devices[device].mode;
711 blksize = 0x200; // was = AtaData->devices[device].blksize;
712 if (mode == ATA_MODE_PIO32)
713 blksize >>= 2;
714 else
715 blksize >>= 1;
716
717 status = inb(iobase1 + ATA_CB_STAT);
718 if (status & ATA_CB_STAT_BSY)
719 {
720 // Enable interrupts
721 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
722 return 1;
723 }
724
725 // sector will be 0 only on lba access. Convert to lba-chs
726 if (sector == 0) {
727 if (lba + count >= 268435456)
728 {
729 sector = (lba & 0xff000000L) >> 24;
730 cylinder = 0; /* The parameter lba is just a 32 bit value. */
731 outb(iobase1 + ATA_CB_SC, (count & 0xff00) >> 8);
732 outb(iobase1 + ATA_CB_SN, sector);
733 outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
734 outb(iobase1 + ATA_CB_CH, cylinder >> 8);
735 /* Leave the bottom 24 bits as is, they are treated correctly by the
736 * LBA28 code path. */
737 lba &= 0xffffff;
738 }
739 sector = (uint16_t) (lba & 0x000000ffL);
740 lba >>= 8;
741 cylinder = (uint16_t) (lba & 0x0000ffffL);
742 lba >>= 16;
743 head = ((uint16_t) (lba & 0x0000000fL)) | 0x40;
744 }
745
746 // Reset count of transferred data
747 AtaData->trsfsectors = 0;
748 AtaData->trsfbytes = 0;
749 current = 0;
750
751 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
752 outb(iobase1 + ATA_CB_FR, 0x00);
753 outb(iobase1 + ATA_CB_SC, count);
754 outb(iobase1 + ATA_CB_SN, sector);
755 outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
756 outb(iobase1 + ATA_CB_CH, cylinder >> 8);
757 outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (uint8_t) head );
758 outb(iobase1 + ATA_CB_CMD, command);
759
760 while (1) {
761 status = inb(iobase1 + ATA_CB_STAT);
762 if ( !(status & ATA_CB_STAT_BSY) )
763 break;
764 }
765
766 if (status & ATA_CB_STAT_ERR) {
767 BX_DEBUG_ATA("%s: read error\n", __func__);
768 // Enable interrupts
769 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
770 return 2;
771 } else if ( !(status & ATA_CB_STAT_DRQ) ) {
772 BX_DEBUG_ATA("%s: DRQ not set (status %02x)\n", __func__, (unsigned) status);
773 // Enable interrupts
774 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
775 return 3;
776 }
777
778 // FIXME : move seg/off translation here
779
780 int_enable(); // enable higher priority interrupts
781
782 while (1) {
783
784 // adjust if there will be an overrun. 2K max sector size
785 if (FP_OFF(buffer) >= 0xF800)
786 buffer = MK_FP(FP_SEG(buffer) + 0x80, FP_OFF(buffer) - 0x800);
787
788 if (mode == ATA_MODE_PIO32) {
789 buffer = rep_outsd(buffer, blksize, iobase1);
790 } else {
791 buffer = rep_outsw(buffer, blksize, iobase1);
792 }
793
794 current++;
795 AtaData->trsfsectors = current;
796 count--;
797 while (1) {
798 status = inb(iobase1 + ATA_CB_STAT);
799 if ( !(status & ATA_CB_STAT_BSY) )
800 break;
801 }
802 if (count == 0) {
803 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
804 != ATA_CB_STAT_RDY ) {
805 BX_DEBUG_ATA("%s: no sectors left (status %02x)\n", __func__, (unsigned) status);
806 // Enable interrupts
807 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
808 return 6;
809 }
810 break;
811 }
812 else {
813 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
814 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
815 BX_DEBUG_ATA("%s: more sectors left (status %02x)\n", __func__, (unsigned) status);
816 // Enable interrupts
817 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
818 return 7;
819 }
820 continue;
821 }
822 }
823 // Enable interrupts
824 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
825 return 0;
826}
827
828// ---------------------------------------------------------------------------
829// ATA/ATAPI driver : execute a packet command
830// ---------------------------------------------------------------------------
831 // returns
832 // 0 : no error
833 // 1 : error in parameters
834 // 2 : BUSY bit set
835 // 3 : error
836 // 4 : not ready
837uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
838 uint16_t header, uint32_t length, uint8_t inout, char __far *buffer)
839{
840 uint16_t ebda_seg = read_word(0x0040,0x000E);
841 uint16_t iobase1, iobase2;
842 uint16_t lcount, lbefore, lafter, count;
843 uint8_t channel, slave;
844 uint8_t status, mode, lmode;
845 uint32_t transfer;
846 ata_t __far *AtaData;
847
848 AtaData = ebda_seg :> &EbdaData->ata;
849
850 channel = device / 2;
851 slave = device % 2;
852
853 // Data out is not supported yet
854 if (inout == ATA_DATA_OUT) {
855 BX_INFO("%s: DATA_OUT not supported yet\n", __func__);
856 return 1;
857 }
858
859 // The header length must be even
860 if (header & 1) {
861 BX_DEBUG_ATA("%s: header must be even (%04x)\n", __func__, header);
862 return 1;
863 }
864
865 iobase1 = AtaData->channels[channel].iobase1;
866 iobase2 = AtaData->channels[channel].iobase2;
867 mode = AtaData->devices[device].mode;
868 transfer = 0L;
869
870 if (cmdlen < 12)
871 cmdlen = 12;
872 if (cmdlen > 12)
873 cmdlen = 16;
874 cmdlen >>= 1;
875
876 // Reset count of transferred data
877 AtaData->trsfsectors = 0;
878 AtaData->trsfbytes = 0;
879
880 status = inb(iobase1 + ATA_CB_STAT);
881 if (status & ATA_CB_STAT_BSY)
882 return 2;
883
884 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
885 // outb(iobase1 + ATA_CB_FR, 0x00);
886 // outb(iobase1 + ATA_CB_SC, 0x00);
887 // outb(iobase1 + ATA_CB_SN, 0x00);
888 outb(iobase1 + ATA_CB_CL, 0xfff0 & 0x00ff);
889 outb(iobase1 + ATA_CB_CH, 0xfff0 >> 8);
890 outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
891 outb(iobase1 + ATA_CB_CMD, ATA_CMD_PACKET);
892
893 // Device should ok to receive command
894 while (1) {
895 status = inb(iobase1 + ATA_CB_STAT);
896 if ( !(status & ATA_CB_STAT_BSY) ) break;
897 }
898
899 if (status & ATA_CB_STAT_ERR) {
900 BX_DEBUG_ATA("%s: error, status is %02x\n", __func__, status);
901 // Enable interrupts
902 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
903 return 3;
904 } else if ( !(status & ATA_CB_STAT_DRQ) ) {
905 BX_DEBUG_ATA("%s: DRQ not set (status %02x)\n", __func__, (unsigned) status);
906 // Enable interrupts
907 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
908 return 4;
909 }
910
911 int_enable(); // enable higher priority interrupts
912
913 // Normalize address
914 BX_DEBUG_ATA("acp1 buffer ptr: %04x:%04x wlen %04x\n", FP_SEG(cmdbuf), FP_OFF(cmdbuf), cmdlen);
915 cmdbuf = MK_FP(FP_SEG(cmdbuf) + FP_OFF(cmdbuf) / 16 , FP_OFF(cmdbuf) % 16);
916 // cmdseg += (cmdoff / 16);
917 // cmdoff %= 16;
918
919 // Send command to device
920 rep_outsw(cmdbuf, cmdlen, iobase1);
921
922 if (inout == ATA_DATA_NO) {
923 status = inb(iobase1 + ATA_CB_STAT);
924 }
925 else {
926 while (1) {
927
928 while (1) {
929 status = inb(iobase1 + ATA_CB_STAT);
930 if ( !(status & ATA_CB_STAT_BSY) )
931 break;
932 }
933
934 // Check if command completed
935 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ) ) ==0 )
936 break;
937
938 if (status & ATA_CB_STAT_ERR) {
939 BX_DEBUG_ATA("%s: error (status %02x)\n", __func__, status);
940 // Enable interrupts
941 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
942 return 3;
943 }
944
945 // Device must be ready to send data
946 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
947 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
948 BX_DEBUG_ATA("%s: not ready (status %02x)\n", __func__, status);
949 // Enable interrupts
950 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
951 return 4;
952 }
953
954 // Normalize address
955 BX_DEBUG_ATA("acp2 buffer ptr: %04x:%04x\n", FP_SEG(buffer), FP_OFF(buffer));
956 buffer = MK_FP(FP_SEG(buffer) + FP_OFF(buffer) / 16 , FP_OFF(buffer) % 16);
957 // bufseg += (bufoff / 16);
958 // bufoff %= 16;
959
960 // Get the byte count
961 lcount = ((uint16_t)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL);
962
963 // adjust to read what we want
964 if (header>lcount) {
965 lbefore = lcount;
966 header -= lcount;
967 lcount = 0;
968 }
969 else {
970 lbefore = header;
971 header = 0;
972 lcount -= lbefore;
973 }
974
975 if (lcount>length) {
976 lafter = lcount - length;
977 lcount = length;
978 length = 0;
979 }
980 else {
981 lafter = 0;
982 length -= lcount;
983 }
984
985 // Save byte count
986 count = lcount;
987
988 BX_DEBUG_ATA("Trying to read %04x bytes (%04x %04x %04x) ",lbefore+lcount+lafter,lbefore,lcount,lafter);
989 BX_DEBUG_ATA("to 0x%04x:0x%04x\n",FP_SEG(buffer),FP_OFF(buffer));
990
991 // If counts not dividable by 4, use 16bits mode
992 lmode = mode;
993 if (lbefore & 0x03)
994 lmode = ATA_MODE_PIO16;
995 if (lcount & 0x03)
996 lmode = ATA_MODE_PIO16;
997 if (lafter & 0x03)
998 lmode = ATA_MODE_PIO16;
999
1000 // adds an extra byte if count are odd. before is always even
1001 if (lcount & 0x01) {
1002 lcount += 1;
1003 if ((lafter > 0) && (lafter & 0x01)) {
1004 lafter -= 1;
1005 }
1006 }
1007
1008 if (lmode == ATA_MODE_PIO32) {
1009 lcount >>= 2;
1010 lbefore >>= 2;
1011 lafter >>= 2;
1012 }
1013 else {
1014 lcount >>= 1;
1015 lbefore >>= 1;
1016 lafter >>= 1;
1017 }
1018
1019 if (lmode == ATA_MODE_PIO32) {
1020 if (lbefore)
1021 insd_discard(lbefore, iobase1);
1022 rep_insd(buffer, lcount, iobase1);
1023 if (lafter)
1024 insd_discard(lafter, iobase1);
1025 } else {
1026 if (lbefore)
1027 insw_discard(lbefore, iobase1);
1028 rep_insw(buffer, lcount, iobase1);
1029 if (lafter)
1030 insw_discard(lafter, iobase1);
1031 }
1032
1033
1034 // Compute new buffer address
1035 buffer += count;
1036
1037 // Save transferred bytes count
1038 transfer += count;
1039 AtaData->trsfbytes = transfer;
1040 }
1041 }
1042
1043 // Final check, device must be ready
1044 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
1045 != ATA_CB_STAT_RDY ) {
1046 BX_DEBUG_ATA("%s: not ready (status %02x)\n", __func__, (unsigned) status);
1047 // Enable interrupts
1048 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
1049 return 4;
1050 }
1051
1052 // Enable interrupts
1053 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
1054 return 0;
1055}
1056
1057
1058// ---------------------------------------------------------------------------
1059// End of ATA/ATAPI Driver
1060// ---------------------------------------------------------------------------
1061
1062uint16_t atapi_is_cdrom(uint8_t device)
1063{
1064 uint16_t ebda_seg = read_word(0x0040,0x000E);
1065 ata_t __far *AtaData;
1066
1067 AtaData = ebda_seg :> &EbdaData->ata;
1068
1069 if (device >= BX_MAX_ATA_DEVICES)
1070 return 0;
1071
1072 if (AtaData->devices[device].type != ATA_TYPE_ATAPI)
1073 return 0;
1074
1075 if (AtaData->devices[device].device != ATA_DEVICE_CDROM)
1076 return 0;
1077
1078 return 1;
1079}
1080
1081// ---------------------------------------------------------------------------
1082// End of ATA/ATAPI generic functions
1083// ---------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use