blob: 3818fb61f837f38db3f460504f9fcf0d6b9af507 [file] [log] [blame]
Kevin O'Connor3491e8b2008-02-29 00:22:27 -05001#include "ata.h" // ATA_*
2#include "types.h" // u8
3#include "ioport.h" // inb
4#include "util.h" // BX_INFO
5
6#define TIMEOUT 0
7#define BSY 1
8#define NOT_BSY 2
9#define NOT_BSY_DRQ 3
10#define NOT_BSY_NOT_DRQ 4
11#define NOT_BSY_RDY 5
12
13#define IDE_TIMEOUT 32000u //32 seconds max for IDE ops
14
15#define BX_DEBUG_ATA BX_INFO
16
17static int
18await_ide(u8 when_done, u16 base, u16 timeout)
19{
20 u32 time=0,last=0;
21 // for the times you're supposed to throw one away
22 u16 status = inb(base + ATA_CB_STAT);
23 for (;;) {
24 status = inb(base+ATA_CB_STAT);
25 time++;
26 u8 result;
27 if (when_done == BSY)
28 result = status & ATA_CB_STAT_BSY;
29 else if (when_done == NOT_BSY)
30 result = !(status & ATA_CB_STAT_BSY);
31 else if (when_done == NOT_BSY_DRQ)
32 result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_DRQ);
33 else if (when_done == NOT_BSY_NOT_DRQ)
34 result = !(status & ATA_CB_STAT_BSY) && !(status & ATA_CB_STAT_DRQ);
35 else if (when_done == NOT_BSY_RDY)
36 result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_RDY);
37 else if (when_done == TIMEOUT)
38 result = 0;
39
40 if (result)
41 return 0;
42 // mod 2048 each 16 ms
43 if (time>>16 != last) {
44 last = time >>16;
45 BX_DEBUG_ATA("await_ide: (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %d timeout= %d\n",when_done,time>>11, timeout);
46 }
47 if (status & ATA_CB_STAT_ERR) {
48 BX_DEBUG_ATA("await_ide: ERROR (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %d timeout= %d\n",when_done,time>>11, timeout);
49 return -1;
50 }
51 if ((timeout == 0) || ((time>>11) > timeout))
52 break;
53 }
54 BX_INFO("IDE time out\n");
55 return -1;
56}
57
58
59// ---------------------------------------------------------------------------
60// ATA/ATAPI driver : software reset
61// ---------------------------------------------------------------------------
62// ATA-3
63// 8.2.1 Software reset - Device 0
64
65void
66ata_reset(u16 device)
67{
68 u16 iobase1, iobase2;
69 u8 channel, slave, sn, sc;
70 u8 type;
71
72 channel = device / 2;
73 slave = device % 2;
74
75 iobase1 = GET_EBDA(ata.channels[channel].iobase1);
76 iobase2 = GET_EBDA(ata.channels[channel].iobase2);
77
78 // Reset
79
80 // 8.2.1 (a) -- set SRST in DC
81 outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST, iobase2+ATA_CB_DC);
82
83 // 8.2.1 (b) -- wait for BSY
84 await_ide(BSY, iobase1, 20);
85
86 // 8.2.1 (f) -- clear SRST
87 outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC);
88
89 type=GET_EBDA(ata.devices[device].type);
90 if (type != ATA_TYPE_NONE) {
91
92 // 8.2.1 (g) -- check for sc==sn==0x01
93 // select device
94 outb(slave?ATA_CB_DH_DEV1:ATA_CB_DH_DEV0, iobase1+ATA_CB_DH);
95 sc = inb(iobase1+ATA_CB_SC);
96 sn = inb(iobase1+ATA_CB_SN);
97
98 if ( (sc==0x01) && (sn==0x01) ) {
99 if (type == ATA_TYPE_ATA) //ATA
100 await_ide(NOT_BSY_RDY, iobase1, IDE_TIMEOUT);
101 else //ATAPI
102 await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
103 }
104
105 // 8.2.1 (h) -- wait for not BSY
106 await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
107 }
108
109 // Enable interrupts
110 outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
111}
112
113static void
114insw(u16 port, u16 segment, u16 offset, u16 count)
115{
116 u16 i;
117 for (i=0; i<count; i++) {
118 u16 d = inw(port);
119 SET_FARVAR(segment, *(u16*)(offset + i), d);
120 }
121}
122
123static void
124insl(u16 port, u16 segment, u16 offset, u16 count)
125{
126 u16 i;
127 for (i=0; i<count; i++) {
128 u32 d = inl(port);
129 SET_FARVAR(segment, *(u32*)(offset + i), d);
130 }
131}
132
133static void
134outsw(u16 port, u16 segment, u16 offset, u16 count)
135{
136 u16 i;
137 for (i=0; i<count; i++) {
138 u16 d = GET_FARVAR(segment, *(u16*)(offset + i));
139 outw(d, port);
140 }
141}
142
143static void
144outsl(u16 port, u16 segment, u16 offset, u16 count)
145{
146 u16 i;
147 for (i=0; i<count; i++) {
148 u32 d = GET_FARVAR(segment, *(u32*)(offset + i));
149 outl(d, port);
150 }
151}
152
153
154// ---------------------------------------------------------------------------
155// ATA/ATAPI driver : execute a data-in command
156// ---------------------------------------------------------------------------
157 // returns
158 // 0 : no error
159 // 1 : BUSY bit set
160 // 2 : read error
161 // 3 : expected DRQ=1
162 // 4 : no sectors left to read/verify
163 // 5 : more sectors to read/verify
164 // 6 : no sectors left to write
165 // 7 : more sectors to write
166u16
167ata_cmd_data_in(u16 device, u16 command, u16 count, u16 cylinder
168 , u16 head, u16 sector, u32 lba, u16 segment, u16 offset)
169{
170 u16 iobase1, iobase2, blksize;
171 u8 channel, slave;
172 u8 status, current, mode;
173
174 channel = device / 2;
175 slave = device % 2;
176
177 iobase1 = GET_EBDA(ata.channels[channel].iobase1);
178 iobase2 = GET_EBDA(ata.channels[channel].iobase2);
179 mode = GET_EBDA(ata.devices[device].mode);
180 blksize = 0x200;
181 if (mode == ATA_MODE_PIO32) blksize>>=2;
182 else blksize>>=1;
183
184 // Reset count of transferred data
185 SET_EBDA(ata.trsfsectors,0);
186 SET_EBDA(ata.trsfbytes,0L);
187 current = 0;
188
189 status = inb(iobase1 + ATA_CB_STAT);
190 if (status & ATA_CB_STAT_BSY)
191 return 1;
192
193 outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
194
195 // sector will be 0 only on lba access. Convert to lba-chs
196 if (sector == 0) {
197 if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) {
198 outb(0x00, iobase1 + ATA_CB_FR);
199 outb((count >> 8) & 0xff, iobase1 + ATA_CB_SC);
200 outb(lba >> 24, iobase1 + ATA_CB_SN);
201 outb(0, iobase1 + ATA_CB_CL);
202 outb(0, iobase1 + ATA_CB_CH);
203 command |= 0x04;
204 count &= (1UL << 8) - 1;
205 lba &= (1UL << 24) - 1;
206 }
207 sector = (u16) (lba & 0x000000ffL);
208 cylinder = (u16) ((lba>>8) & 0x0000ffffL);
209 head = ((u16) ((lba>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
210 }
211
212 outb(0x00, iobase1 + ATA_CB_FR);
213 outb(count, iobase1 + ATA_CB_SC);
214 outb(sector, iobase1 + ATA_CB_SN);
215 outb(cylinder & 0x00ff, iobase1 + ATA_CB_CL);
216 outb(cylinder >> 8, iobase1 + ATA_CB_CH);
217 outb((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (u8) head
218 , iobase1 + ATA_CB_DH);
219 outb(command, iobase1 + ATA_CB_CMD);
220
221 await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
222 status = inb(iobase1 + ATA_CB_STAT);
223
224 if (status & ATA_CB_STAT_ERR) {
225 BX_DEBUG_ATA("ata_cmd_data_in : read error\n");
226 return 2;
227 } else if ( !(status & ATA_CB_STAT_DRQ) ) {
228 BX_DEBUG_ATA("ata_cmd_data_in : DRQ not set (status %02x)\n"
229 , (unsigned) status);
230 return 3;
231 }
232
233 // FIXME : move seg/off translation here
234
235 irq_enable();
236
237 while (1) {
238
239 if (offset > 0xf800) {
240 offset -= 0x800;
241 segment += 0x80;
242 }
243
244 if (mode == ATA_MODE_PIO32)
245 insw(iobase1, segment, offset, blksize);
246 else
247 insl(iobase1, segment, offset, blksize);
248
249 current++;
250 SET_EBDA(ata.trsfsectors,current);
251 count--;
252 await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
253 status = inb(iobase1 + ATA_CB_STAT);
254 if (count == 0) {
255 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ
256 | ATA_CB_STAT_ERR) )
257 != ATA_CB_STAT_RDY ) {
258 BX_DEBUG_ATA("ata_cmd_data_in : no sectors left (status %02x)\n"
259 , (unsigned) status);
260 return 4;
261 }
262 break;
263 }
264 else {
265 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ
266 | ATA_CB_STAT_ERR) )
267 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
268 BX_DEBUG_ATA("ata_cmd_data_in : more sectors left (status %02x)\n"
269 , (unsigned) status);
270 return 5;
271 }
272 continue;
273 }
274 }
275 // Enable interrupts
276 outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
277 return 0;
278}
279
280// ---------------------------------------------------------------------------
281// ATA/ATAPI driver : execute a data-out command
282// ---------------------------------------------------------------------------
283 // returns
284 // 0 : no error
285 // 1 : BUSY bit set
286 // 2 : read error
287 // 3 : expected DRQ=1
288 // 4 : no sectors left to read/verify
289 // 5 : more sectors to read/verify
290 // 6 : no sectors left to write
291 // 7 : more sectors to write
292u16
293ata_cmd_data_out(u16 device, u16 command, u16 count, u16 cylinder
294 , u16 head, u16 sector, u32 lba, u16 segment, u16 offset)
295{
296 u16 iobase1, iobase2, blksize;
297 u8 channel, slave;
298 u8 status, current, mode;
299
300 channel = device / 2;
301 slave = device % 2;
302
303 iobase1 = GET_EBDA(ata.channels[channel].iobase1);
304 iobase2 = GET_EBDA(ata.channels[channel].iobase2);
305 mode = GET_EBDA(ata.devices[device].mode);
306 blksize = 0x200;
307 if (mode == ATA_MODE_PIO32)
308 blksize>>=2;
309 else
310 blksize>>=1;
311
312 // Reset count of transferred data
313 SET_EBDA(ata.trsfsectors,0);
314 SET_EBDA(ata.trsfbytes,0L);
315 current = 0;
316
317 status = inb(iobase1 + ATA_CB_STAT);
318 if (status & ATA_CB_STAT_BSY)
319 return 1;
320
321 outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
322
323 // sector will be 0 only on lba access. Convert to lba-chs
324 if (sector == 0) {
325 if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) {
326 outb(0x00, iobase1 + ATA_CB_FR);
327 outb((count >> 8) & 0xff, iobase1 + ATA_CB_SC);
328 outb(lba >> 24, iobase1 + ATA_CB_SN);
329 outb(0, iobase1 + ATA_CB_CL);
330 outb(0, iobase1 + ATA_CB_CH);
331 command |= 0x04;
332 count &= (1UL << 8) - 1;
333 lba &= (1UL << 24) - 1;
334 }
335 sector = (u16) (lba & 0x000000ffL);
336 cylinder = (u16) ((lba>>8) & 0x0000ffffL);
337 head = ((u16) ((lba>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
338 }
339
340 outb(0x00, iobase1 + ATA_CB_FR);
341 outb(count, iobase1 + ATA_CB_SC);
342 outb(sector, iobase1 + ATA_CB_SN);
343 outb(cylinder & 0x00ff, iobase1 + ATA_CB_CL);
344 outb(cylinder >> 8, iobase1 + ATA_CB_CH);
345 outb((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (u8) head
346 , iobase1 + ATA_CB_DH);
347 outb(command, iobase1 + ATA_CB_CMD);
348
349 await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
350 status = inb(iobase1 + ATA_CB_STAT);
351
352 if (status & ATA_CB_STAT_ERR) {
353 BX_DEBUG_ATA("ata_cmd_data_out : read error\n");
354 return 2;
355 } else if ( !(status & ATA_CB_STAT_DRQ) ) {
356 BX_DEBUG_ATA("ata_cmd_data_out : DRQ not set (status %02x)\n"
357 , (unsigned) status);
358 return 3;
359 }
360
361 // FIXME : move seg/off translation here
362
363 irq_enable();
364
365 while (1) {
366
367 if (offset > 0xf800) {
368 offset -= 0x800;
369 segment += 0x80;
370 }
371
372 if (mode == ATA_MODE_PIO32)
373 outsw(iobase1, segment, offset, blksize);
374 else
375 outsl(iobase1, segment, offset, blksize);
376
377 current++;
378 SET_EBDA(ata.trsfsectors,current);
379 count--;
380 status = inb(iobase1 + ATA_CB_STAT);
381 if (count == 0) {
382 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF
383 | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
384 != ATA_CB_STAT_RDY ) {
385 BX_DEBUG_ATA("ata_cmd_data_out : no sectors left (status %02x)\n"
386 , (unsigned) status);
387 return 6;
388 }
389 break;
390 } else {
391 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ
392 | ATA_CB_STAT_ERR) )
393 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
394 BX_DEBUG_ATA("ata_cmd_data_out : more sectors left (status %02x)\n"
395 , (unsigned) status);
396 return 7;
397 }
398 continue;
399 }
400 }
401 // Enable interrupts
402 outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
403 return 0;
404}
405
406// ---------------------------------------------------------------------------
407// ATA/ATAPI driver : execute a packet command
408// ---------------------------------------------------------------------------
409 // returns
410 // 0 : no error
411 // 1 : error in parameters
412 // 2 : BUSY bit set
413 // 3 : error
414 // 4 : not ready
415u16
416ata_cmd_packet(u16 device, u8 cmdlen, u16 cmdseg, u16 cmdoff, u16 header
417 , u32 length, u8 inout, u16 bufseg, u16 bufoff)
418{
419 u16 iobase1, iobase2;
420 u16 lcount, lbefore, lafter, count;
421 u8 channel, slave;
422 u8 status, mode, lmode;
423 u32 transfer;
424
425 channel = device / 2;
426 slave = device % 2;
427
428 // Data out is not supported yet
429 if (inout == ATA_DATA_OUT) {
430 BX_INFO("ata_cmd_packet: DATA_OUT not supported yet\n");
431 return 1;
432 }
433
434 // The header length must be even
435 if (header & 1) {
436 BX_DEBUG_ATA("ata_cmd_packet : header must be even (%04x)\n",header);
437 return 1;
438 }
439
440 iobase1 = GET_EBDA(ata.channels[channel].iobase1);
441 iobase2 = GET_EBDA(ata.channels[channel].iobase2);
442 mode = GET_EBDA(ata.devices[device].mode);
443 transfer= 0L;
444
445 if (cmdlen < 12)
446 cmdlen=12;
447 if (cmdlen > 12)
448 cmdlen=16;
449 cmdlen>>=1;
450
451 // Reset count of transferred data
452 SET_EBDA(ata.trsfsectors,0);
453 SET_EBDA(ata.trsfbytes,0L);
454
455 status = inb(iobase1 + ATA_CB_STAT);
456 if (status & ATA_CB_STAT_BSY)
457 return 2;
458
459 outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
460 outb(0x00, iobase1 + ATA_CB_FR);
461 outb(0x00, iobase1 + ATA_CB_SC);
462 outb(0x00, iobase1 + ATA_CB_SN);
463 outb(0xfff0 & 0x00ff, iobase1 + ATA_CB_CL);
464 outb(0xfff0 >> 8, iobase1 + ATA_CB_CH);
465 outb(slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0, iobase1 + ATA_CB_DH);
466 outb(ATA_CMD_PACKET, iobase1 + ATA_CB_CMD);
467
468 // Device should ok to receive command
469 await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
470 status = inb(iobase1 + ATA_CB_STAT);
471
472 if (status & ATA_CB_STAT_ERR) {
473 BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status);
474 return 3;
475 } else if ( !(status & ATA_CB_STAT_DRQ) ) {
476 BX_DEBUG_ATA("ata_cmd_packet : DRQ not set (status %02x)\n"
477 , (unsigned) status);
478 return 4;
479 }
480
481 // Normalize address
482 cmdseg += (cmdoff / 16);
483 cmdoff %= 16;
484
485 // Send command to device
486 irq_enable();
487
488 outsw(iobase1, cmdseg, cmdoff, cmdlen);
489
490 if (inout == ATA_DATA_NO) {
491 await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
492 status = inb(iobase1 + ATA_CB_STAT);
493 }
494 else {
495 u16 loops = 0;
496 u8 sc;
497 while (1) {
498
499 if (loops == 0) {//first time through
500 status = inb(iobase2 + ATA_CB_ASTAT);
501 await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
502 }
503 else
504 await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
505 loops++;
506
507 status = inb(iobase1 + ATA_CB_STAT);
508 sc = inb(iobase1 + ATA_CB_SC);
509
510 // Check if command completed
511 if(((inb(iobase1 + ATA_CB_SC)&0x7)==0x3) &&
512 ((status & (ATA_CB_STAT_RDY | ATA_CB_STAT_ERR)) == ATA_CB_STAT_RDY))
513 break;
514
515 if (status & ATA_CB_STAT_ERR) {
516 BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status);
517 return 3;
518 }
519
520 // Normalize address
521 bufseg += (bufoff / 16);
522 bufoff %= 16;
523
524 // Get the byte count
525 lcount = ((u16)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL);
526
527 // adjust to read what we want
528 if(header>lcount) {
529 lbefore=lcount;
530 header-=lcount;
531 lcount=0;
532 }
533 else {
534 lbefore=header;
535 header=0;
536 lcount-=lbefore;
537 }
538
539 if(lcount>length) {
540 lafter=lcount-length;
541 lcount=length;
542 length=0;
543 }
544 else {
545 lafter=0;
546 length-=lcount;
547 }
548
549 // Save byte count
550 count = lcount;
551
552 BX_DEBUG_ATA("Trying to read %04x bytes (%04x %04x %04x) "
553 ,lbefore+lcount+lafter,lbefore,lcount,lafter);
554 BX_DEBUG_ATA("to 0x%04x:0x%04x\n",bufseg,bufoff);
555
556 // If counts not dividable by 4, use 16bits mode
557 lmode = mode;
558 if (lbefore & 0x03) lmode=ATA_MODE_PIO16;
559 if (lcount & 0x03) lmode=ATA_MODE_PIO16;
560 if (lafter & 0x03) lmode=ATA_MODE_PIO16;
561
562 // adds an extra byte if count are odd. before is always even
563 if (lcount & 0x01) {
564 lcount+=1;
565 if ((lafter > 0) && (lafter & 0x01)) {
566 lafter-=1;
567 }
568 }
569
570 if (lmode == ATA_MODE_PIO32) {
571 lcount>>=2; lbefore>>=2; lafter>>=2;
572 }
573 else {
574 lcount>>=1; lbefore>>=1; lafter>>=1;
575 }
576
577 int i;
578 for (i=0; i<lbefore; i++)
579 if (lmode == ATA_MODE_PIO32)
580 inl(iobase1);
581 else
582 inw(iobase1);
583
584 if (lmode == ATA_MODE_PIO32)
585 insl(iobase1, bufoff, bufseg, lcount);
586 else
587 insw(iobase1, bufoff, bufseg, lcount);
588
589 for (i=0; i<lafter; i++)
590 if (lmode == ATA_MODE_PIO32)
591 inl(iobase1);
592 else
593 inw(iobase1);
594
595 // Compute new buffer address
596 bufoff += count;
597
598 // Save transferred bytes count
599 transfer += count;
600 SET_EBDA(ata.trsfbytes,transfer);
601 }
602 }
603
604 // Final check, device must be ready
605 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF
606 | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
607 != ATA_CB_STAT_RDY ) {
608 BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n"
609 , (unsigned) status);
610 return 4;
611 }
612
613 // Enable interrupts
614 outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
615 return 0;
616}