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