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