blob: 2202009f5f22aff7be45cab29d538d7824eb2df6 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
wdenkf1276d42005-02-03 23:00:49 +00002 * (C) Copyright 2000-2005
wdenkc6097192002-11-03 00:24:07 +00003 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 *
23 */
24
25/*
26 * IDE support
27 */
28#include <common.h>
29#include <config.h>
30#include <watchdog.h>
31#include <command.h>
32#include <image.h>
33#include <asm/byteorder.h>
Heiko Schocher2559e0f2007-08-28 17:39:14 +020034#include <asm/io.h>
Grant Likelyffc2dd72007-02-20 09:04:34 +010035
wdenkc6097192002-11-03 00:24:07 +000036#if defined(CONFIG_IDE_8xx_DIRECT) || defined(CONFIG_IDE_PCMCIA)
37# include <pcmcia.h>
38#endif
Grant Likelyffc2dd72007-02-20 09:04:34 +010039
wdenkc6097192002-11-03 00:24:07 +000040#ifdef CONFIG_8xx
41# include <mpc8xx.h>
42#endif
Grant Likelyffc2dd72007-02-20 09:04:34 +010043
wdenk6ea1cf02004-02-27 08:20:54 +000044#ifdef CONFIG_MPC5xxx
45#include <mpc5xxx.h>
46#endif
Grant Likelyffc2dd72007-02-20 09:04:34 +010047
wdenkc6097192002-11-03 00:24:07 +000048#include <ide.h>
49#include <ata.h>
Grant Likelyffc2dd72007-02-20 09:04:34 +010050
wdenkc6097192002-11-03 00:24:07 +000051#ifdef CONFIG_STATUS_LED
52# include <status_led.h>
53#endif
Grant Likelyffc2dd72007-02-20 09:04:34 +010054
wdenk9f837932003-10-09 19:00:25 +000055#ifndef __PPC__
wdenk591dda52002-11-18 00:14:45 +000056#include <asm/io.h>
57#endif
wdenkc6097192002-11-03 00:24:07 +000058
Wolfgang Denk6405a152006-03-31 18:32:53 +020059#ifdef CONFIG_IDE_8xx_DIRECT
60DECLARE_GLOBAL_DATA_PTR;
61#endif
62
wdenk20c98a62004-04-23 20:32:05 +000063#ifdef __PPC__
64# define EIEIO __asm__ volatile ("eieio")
wdenkf1276d42005-02-03 23:00:49 +000065# define SYNC __asm__ volatile ("sync")
wdenk20c98a62004-04-23 20:32:05 +000066#else
67# define EIEIO /* nothing */
wdenkf1276d42005-02-03 23:00:49 +000068# define SYNC /* nothing */
wdenk20c98a62004-04-23 20:32:05 +000069#endif
wdenkc6097192002-11-03 00:24:07 +000070
Jon Loeligerd76b5c12007-07-08 18:02:23 -050071#if defined(CONFIG_CMD_IDE)
wdenkc6097192002-11-03 00:24:07 +000072
wdenk9f837932003-10-09 19:00:25 +000073#ifdef CONFIG_IDE_8xx_DIRECT
wdenkc6097192002-11-03 00:24:07 +000074/* Timings for IDE Interface
75 *
76 * SETUP / LENGTH / HOLD - cycles valid for 50 MHz clk
77 * 70 165 30 PIO-Mode 0, [ns]
78 * 4 9 2 [Cycles]
79 * 50 125 20 PIO-Mode 1, [ns]
80 * 3 7 2 [Cycles]
81 * 30 100 15 PIO-Mode 2, [ns]
82 * 2 6 1 [Cycles]
83 * 30 80 10 PIO-Mode 3, [ns]
84 * 2 5 1 [Cycles]
85 * 25 70 10 PIO-Mode 4, [ns]
86 * 2 4 1 [Cycles]
87 */
88
89const static pio_config_t pio_config_ns [IDE_MAX_PIO_MODE+1] =
90{
91 /* Setup Length Hold */
92 { 70, 165, 30 }, /* PIO-Mode 0, [ns] */
93 { 50, 125, 20 }, /* PIO-Mode 1, [ns] */
94 { 30, 101, 15 }, /* PIO-Mode 2, [ns] */
95 { 30, 80, 10 }, /* PIO-Mode 3, [ns] */
96 { 25, 70, 10 }, /* PIO-Mode 4, [ns] */
97};
98
99static pio_config_t pio_config_clk [IDE_MAX_PIO_MODE+1];
100
101#ifndef CFG_PIO_MODE
102#define CFG_PIO_MODE 0 /* use a relaxed default */
103#endif
104static int pio_mode = CFG_PIO_MODE;
105
106/* Make clock cycles and always round up */
107
108#define PCMCIA_MK_CLKS( t, T ) (( (t) * (T) + 999U ) / 1000U )
109
wdenk9f837932003-10-09 19:00:25 +0000110#endif /* CONFIG_IDE_8xx_DIRECT */
111
wdenkc6097192002-11-03 00:24:07 +0000112/* ------------------------------------------------------------------------- */
113
114/* Current I/O Device */
115static int curr_device = -1;
116
117/* Current offset for IDE0 / IDE1 bus access */
118ulong ide_bus_offset[CFG_IDE_MAXBUS] = {
119#if defined(CFG_ATA_IDE0_OFFSET)
120 CFG_ATA_IDE0_OFFSET,
121#endif
122#if defined(CFG_ATA_IDE1_OFFSET) && (CFG_IDE_MAXBUS > 1)
123 CFG_ATA_IDE1_OFFSET,
124#endif
125};
126
wdenkc6097192002-11-03 00:24:07 +0000127
wdenk452cfd62002-11-19 11:04:11 +0000128#ifndef CONFIG_AMIGAONEG3SE
wdenkf1276d42005-02-03 23:00:49 +0000129static int ide_bus_ok[CFG_IDE_MAXBUS];
wdenk452cfd62002-11-19 11:04:11 +0000130#else
wdenkf1276d42005-02-03 23:00:49 +0000131static int ide_bus_ok[CFG_IDE_MAXBUS] = {0,};
wdenk452cfd62002-11-19 11:04:11 +0000132#endif
wdenkc6097192002-11-03 00:24:07 +0000133
stroesebaef2512004-12-16 17:40:30 +0000134block_dev_desc_t ide_dev_desc[CFG_IDE_MAXDEVICE];
wdenkc6097192002-11-03 00:24:07 +0000135/* ------------------------------------------------------------------------- */
136
137#ifdef CONFIG_IDE_LED
wdenk54070ab2004-12-31 09:32:47 +0000138#if !defined(CONFIG_KUP4K) && !defined(CONFIG_KUP4X) &&!defined(CONFIG_BMS2003) &&!defined(CONFIG_CPC45)
wdenkc6097192002-11-03 00:24:07 +0000139static void ide_led (uchar led, uchar status);
140#else
wdenk90e7e422002-12-04 23:39:58 +0000141extern void ide_led (uchar led, uchar status);
142#endif
143#else
wdenk452cfd62002-11-19 11:04:11 +0000144#ifndef CONFIG_AMIGAONEG3SE
wdenkc6097192002-11-03 00:24:07 +0000145#define ide_led(a,b) /* dummy */
wdenk452cfd62002-11-19 11:04:11 +0000146#else
147extern void ide_led(uchar led, uchar status);
148#define LED_IDE1 1
149#define LED_IDE2 2
150#define CONFIG_IDE_LED 1
151#define DEVICE_LED(x) 1
152#endif
wdenkc6097192002-11-03 00:24:07 +0000153#endif
154
155#ifdef CONFIG_IDE_RESET
156static void ide_reset (void);
157#else
158#define ide_reset() /* dummy */
159#endif
160
161static void ide_ident (block_dev_desc_t *dev_desc);
162static uchar ide_wait (int dev, ulong t);
163
164#define IDE_TIME_OUT 2000 /* 2 sec timeout */
165
166#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */
167
168#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */
169
Heiko Schocher2559e0f2007-08-28 17:39:14 +0200170void inline ide_outb(int dev, int port, unsigned char val);
171unsigned char inline ide_inb(int dev, int port);
wdenkc6097192002-11-03 00:24:07 +0000172static void input_data(int dev, ulong *sect_buf, int words);
173static void output_data(int dev, ulong *sect_buf, int words);
174static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);
175
Heiko Schocher633e03a2007-06-22 19:11:54 +0200176#ifndef CFG_ATA_PORT_ADDR
177#define CFG_ATA_PORT_ADDR(port) (port)
178#endif
wdenkc6097192002-11-03 00:24:07 +0000179
180#ifdef CONFIG_ATAPI
181static void atapi_inquiry(block_dev_desc_t *dev_desc);
Grant Likely2089cab2007-02-20 09:05:45 +0100182ulong atapi_read (int device, lbaint_t blknr, ulong blkcnt, void *buffer);
wdenkc6097192002-11-03 00:24:07 +0000183#endif
184
185
186#ifdef CONFIG_IDE_8xx_DIRECT
187static void set_pcmcia_timing (int pmode);
wdenkc6097192002-11-03 00:24:07 +0000188#endif
189
190/* ------------------------------------------------------------------------- */
191
192int do_ide (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
193{
194 int rcode = 0;
195
196 switch (argc) {
197 case 0:
198 case 1:
199 printf ("Usage:\n%s\n", cmdtp->usage);
200 return 1;
201 case 2:
202 if (strncmp(argv[1],"res",3) == 0) {
203 puts ("\nReset IDE"
204#ifdef CONFIG_IDE_8xx_DIRECT
205 " on PCMCIA " PCMCIA_SLOT_MSG
206#endif
207 ": ");
208
209 ide_init ();
210 return 0;
211 } else if (strncmp(argv[1],"inf",3) == 0) {
212 int i;
213
214 putc ('\n');
215
216 for (i=0; i<CFG_IDE_MAXDEVICE; ++i) {
217 if (ide_dev_desc[i].type==DEV_TYPE_UNKNOWN)
218 continue; /* list only known devices */
219 printf ("IDE device %d: ", i);
220 dev_print(&ide_dev_desc[i]);
221 }
222 return 0;
223
224 } else if (strncmp(argv[1],"dev",3) == 0) {
225 if ((curr_device < 0) || (curr_device >= CFG_IDE_MAXDEVICE)) {
226 puts ("\nno IDE devices available\n");
227 return 1;
228 }
229 printf ("\nIDE device %d: ", curr_device);
230 dev_print(&ide_dev_desc[curr_device]);
231 return 0;
232 } else if (strncmp(argv[1],"part",4) == 0) {
233 int dev, ok;
234
235 for (ok=0, dev=0; dev<CFG_IDE_MAXDEVICE; ++dev) {
236 if (ide_dev_desc[dev].part_type!=PART_TYPE_UNKNOWN) {
237 ++ok;
238 if (dev)
239 putc ('\n');
240 print_part(&ide_dev_desc[dev]);
241 }
242 }
243 if (!ok) {
244 puts ("\nno IDE devices available\n");
245 rcode ++;
246 }
247 return rcode;
248 }
249 printf ("Usage:\n%s\n", cmdtp->usage);
250 return 1;
251 case 3:
252 if (strncmp(argv[1],"dev",3) == 0) {
253 int dev = (int)simple_strtoul(argv[2], NULL, 10);
254
255 printf ("\nIDE device %d: ", dev);
256 if (dev >= CFG_IDE_MAXDEVICE) {
257 puts ("unknown device\n");
258 return 1;
259 }
260 dev_print(&ide_dev_desc[dev]);
261 /*ide_print (dev);*/
262
263 if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
264 return 1;
265 }
266
267 curr_device = dev;
268
269 puts ("... is now current device\n");
270
271 return 0;
272 } else if (strncmp(argv[1],"part",4) == 0) {
273 int dev = (int)simple_strtoul(argv[2], NULL, 10);
274
275 if (ide_dev_desc[dev].part_type!=PART_TYPE_UNKNOWN) {
276 print_part(&ide_dev_desc[dev]);
277 } else {
278 printf ("\nIDE device %d not available\n", dev);
279 rcode = 1;
280 }
281 return rcode;
282#if 0
283 } else if (strncmp(argv[1],"pio",4) == 0) {
284 int mode = (int)simple_strtoul(argv[2], NULL, 10);
285
286 if ((mode >= 0) && (mode <= IDE_MAX_PIO_MODE)) {
287 puts ("\nSetting ");
288 pio_mode = mode;
289 ide_init ();
290 } else {
291 printf ("\nInvalid PIO mode %d (0 ... %d only)\n",
292 mode, IDE_MAX_PIO_MODE);
293 }
294 return;
295#endif
296 }
297
298 printf ("Usage:\n%s\n", cmdtp->usage);
299 return 1;
300 default:
301 /* at least 4 args */
302
303 if (strcmp(argv[1],"read") == 0) {
304 ulong addr = simple_strtoul(argv[2], NULL, 16);
wdenkc6097192002-11-03 00:24:07 +0000305 ulong cnt = simple_strtoul(argv[4], NULL, 16);
306 ulong n;
wdenkc35ba4e2004-03-14 22:25:36 +0000307#ifdef CFG_64BIT_STRTOUL
308 lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
wdenkc6097192002-11-03 00:24:07 +0000309
wdenkf602aa02004-03-13 23:29:43 +0000310 printf ("\nIDE read: device %d block # %qd, count %ld ... ",
wdenkc6097192002-11-03 00:24:07 +0000311 curr_device, blk, cnt);
wdenkc35ba4e2004-03-14 22:25:36 +0000312#else
313 lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
314
315 printf ("\nIDE read: device %d block # %ld, count %ld ... ",
316 curr_device, blk, cnt);
317#endif
wdenkc6097192002-11-03 00:24:07 +0000318
319 n = ide_dev_desc[curr_device].block_read (curr_device,
320 blk, cnt,
321 (ulong *)addr);
322 /* flush cache after read */
323 flush_cache (addr, cnt*ide_dev_desc[curr_device].blksz);
324
325 printf ("%ld blocks read: %s\n",
326 n, (n==cnt) ? "OK" : "ERROR");
327 if (n==cnt) {
328 return 0;
329 } else {
330 return 1;
331 }
332 } else if (strcmp(argv[1],"write") == 0) {
333 ulong addr = simple_strtoul(argv[2], NULL, 16);
wdenkc6097192002-11-03 00:24:07 +0000334 ulong cnt = simple_strtoul(argv[4], NULL, 16);
335 ulong n;
wdenkc35ba4e2004-03-14 22:25:36 +0000336#ifdef CFG_64BIT_STRTOUL
337 lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
wdenkc6097192002-11-03 00:24:07 +0000338
wdenkf602aa02004-03-13 23:29:43 +0000339 printf ("\nIDE write: device %d block # %qd, count %ld ... ",
wdenkc6097192002-11-03 00:24:07 +0000340 curr_device, blk, cnt);
wdenkc35ba4e2004-03-14 22:25:36 +0000341#else
342 lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
343
344 printf ("\nIDE write: device %d block # %ld, count %ld ... ",
345 curr_device, blk, cnt);
346#endif
wdenkc6097192002-11-03 00:24:07 +0000347
348 n = ide_write (curr_device, blk, cnt, (ulong *)addr);
349
350 printf ("%ld blocks written: %s\n",
351 n, (n==cnt) ? "OK" : "ERROR");
352 if (n==cnt) {
353 return 0;
354 } else {
355 return 1;
356 }
357 } else {
358 printf ("Usage:\n%s\n", cmdtp->usage);
359 rcode = 1;
360 }
361
362 return rcode;
363 }
364}
365
366int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
367{
368 char *boot_device = NULL;
369 char *ep;
370 int dev, part = 0;
wdenkf1276d42005-02-03 23:00:49 +0000371 ulong addr, cnt, checksum;
wdenkc6097192002-11-03 00:24:07 +0000372 disk_partition_t info;
373 image_header_t *hdr;
374 int rcode = 0;
375
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200376 show_boot_progress (41);
wdenkc6097192002-11-03 00:24:07 +0000377 switch (argc) {
378 case 1:
379 addr = CFG_LOAD_ADDR;
380 boot_device = getenv ("bootdevice");
381 break;
382 case 2:
383 addr = simple_strtoul(argv[1], NULL, 16);
384 boot_device = getenv ("bootdevice");
385 break;
386 case 3:
387 addr = simple_strtoul(argv[1], NULL, 16);
388 boot_device = argv[2];
389 break;
390 default:
391 printf ("Usage:\n%s\n", cmdtp->usage);
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200392 show_boot_progress (-42);
wdenkc6097192002-11-03 00:24:07 +0000393 return 1;
394 }
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200395 show_boot_progress (42);
wdenkc6097192002-11-03 00:24:07 +0000396
397 if (!boot_device) {
398 puts ("\n** No boot device **\n");
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200399 show_boot_progress (-43);
wdenkc6097192002-11-03 00:24:07 +0000400 return 1;
401 }
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200402 show_boot_progress (43);
wdenkc6097192002-11-03 00:24:07 +0000403
404 dev = simple_strtoul(boot_device, &ep, 16);
405
406 if (ide_dev_desc[dev].type==DEV_TYPE_UNKNOWN) {
407 printf ("\n** Device %d not available\n", dev);
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200408 show_boot_progress (-44);
wdenkc6097192002-11-03 00:24:07 +0000409 return 1;
410 }
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200411 show_boot_progress (44);
wdenkc6097192002-11-03 00:24:07 +0000412
413 if (*ep) {
414 if (*ep != ':') {
415 puts ("\n** Invalid boot device, use `dev[:part]' **\n");
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200416 show_boot_progress (-45);
wdenkc6097192002-11-03 00:24:07 +0000417 return 1;
418 }
419 part = simple_strtoul(++ep, NULL, 16);
420 }
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200421 show_boot_progress (45);
Denis Peter3957bc12007-04-13 09:13:33 +0200422 if (get_partition_info (&ide_dev_desc[dev], part, &info)) {
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200423 show_boot_progress (-46);
wdenkc6097192002-11-03 00:24:07 +0000424 return 1;
425 }
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200426 show_boot_progress (46);
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200427 if ((strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) &&
428 (strncmp((char *)info.type, BOOT_PART_COMP, sizeof(info.type)) != 0)) {
wdenkc6097192002-11-03 00:24:07 +0000429 printf ("\n** Invalid partition type \"%.32s\""
430 " (expect \"" BOOT_PART_TYPE "\")\n",
431 info.type);
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200432 show_boot_progress (-47);
wdenkc6097192002-11-03 00:24:07 +0000433 return 1;
434 }
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200435 show_boot_progress (47);
wdenkc6097192002-11-03 00:24:07 +0000436
437 printf ("\nLoading from IDE device %d, partition %d: "
438 "Name: %.32s Type: %.32s\n",
439 dev, part, info.name, info.type);
440
wdenkf1276d42005-02-03 23:00:49 +0000441 debug ("First Block: %ld, # of blocks: %ld, Block Size: %ld\n",
wdenkc6097192002-11-03 00:24:07 +0000442 info.start, info.size, info.blksz);
443
444 if (ide_dev_desc[dev].block_read (dev, info.start, 1, (ulong *)addr) != 1) {
445 printf ("** Read error on %d:%d\n", dev, part);
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200446 show_boot_progress (-48);
wdenkc6097192002-11-03 00:24:07 +0000447 return 1;
448 }
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200449 show_boot_progress (48);
wdenkc6097192002-11-03 00:24:07 +0000450
451 hdr = (image_header_t *)addr;
452
wdenkf1276d42005-02-03 23:00:49 +0000453 if (ntohl(hdr->ih_magic) != IH_MAGIC) {
wdenkc6097192002-11-03 00:24:07 +0000454 printf("\n** Bad Magic Number **\n");
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200455 show_boot_progress (-49);
wdenkc6097192002-11-03 00:24:07 +0000456 return 1;
457 }
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200458 show_boot_progress (49);
wdenkc6097192002-11-03 00:24:07 +0000459
wdenkf1276d42005-02-03 23:00:49 +0000460 checksum = ntohl(hdr->ih_hcrc);
461 hdr->ih_hcrc = 0;
462
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200463 if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) {
wdenkf1276d42005-02-03 23:00:49 +0000464 puts ("\n** Bad Header Checksum **\n");
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200465 show_boot_progress (-50);
wdenkf1276d42005-02-03 23:00:49 +0000466 return 1;
467 }
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200468 show_boot_progress (50);
wdenk424f2712005-02-08 15:29:01 +0000469 hdr->ih_hcrc = htonl(checksum); /* restore checksum for later use */
wdenkf1276d42005-02-03 23:00:49 +0000470
471 print_image_hdr (hdr);
472
473 cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
474 cnt += info.blksz - 1;
475 cnt /= info.blksz;
476 cnt -= 1;
477
wdenkc6097192002-11-03 00:24:07 +0000478 if (ide_dev_desc[dev].block_read (dev, info.start+1, cnt,
479 (ulong *)(addr+info.blksz)) != cnt) {
480 printf ("** Read error on %d:%d\n", dev, part);
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200481 show_boot_progress (-51);
wdenkc6097192002-11-03 00:24:07 +0000482 return 1;
483 }
Heiko Schocher8a8ec532007-07-13 09:54:17 +0200484 show_boot_progress (51);
wdenkc6097192002-11-03 00:24:07 +0000485
486
487 /* Loading ok, update default load address */
488
489 load_addr = addr;
490
491 /* Check if we should attempt an auto-start */
492 if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
493 char *local_args[2];
494 extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
495
496 local_args[0] = argv[0];
497 local_args[1] = NULL;
498
499 printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
500
501 do_bootm (cmdtp, 0, 1, local_args);
502 rcode = 1;
503 }
504 return rcode;
505}
506
507/* ------------------------------------------------------------------------- */
508
509void ide_init (void)
510{
wdenkc6097192002-11-03 00:24:07 +0000511
512#ifdef CONFIG_IDE_8xx_DIRECT
513 volatile immap_t *immr = (immap_t *)CFG_IMMR;
514 volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
515#endif
516 unsigned char c;
517 int i, bus;
Wolfgang Denk15c6b152007-04-11 17:22:55 +0200518#if defined(CONFIG_AMIGAONEG3SE) || defined(CONFIG_SC3)
Wolfgang Denkd2a7a742007-06-08 10:24:58 +0200519 unsigned int ata_reset_time = ATA_RESET_TIME;
520 char *s;
Wolfgang Denk15c6b152007-04-11 17:22:55 +0200521#endif
wdenk452cfd62002-11-19 11:04:11 +0000522#ifdef CONFIG_AMIGAONEG3SE
523 unsigned int max_bus_scan;
wdenk452cfd62002-11-19 11:04:11 +0000524#endif
wdenk7f00b942003-12-07 23:55:12 +0000525#ifdef CONFIG_IDE_8xx_PCCARD
526 extern int pcmcia_on (void);
527 extern int ide_devices_found; /* Initialized in check_ide_device() */
528#endif /* CONFIG_IDE_8xx_PCCARD */
529
530#ifdef CONFIG_IDE_PREINIT
wdenk369d43d2004-03-14 14:09:05 +0000531 extern int ide_preinit (void);
wdenk7f00b942003-12-07 23:55:12 +0000532 WATCHDOG_RESET();
533
534 if (ide_preinit ()) {
535 puts ("ide_preinit failed\n");
536 return;
537 }
538#endif /* CONFIG_IDE_PREINIT */
wdenkc6097192002-11-03 00:24:07 +0000539
540#ifdef CONFIG_IDE_8xx_PCCARD
541 extern int pcmcia_on (void);
wdenk4fc95692003-02-28 00:49:47 +0000542 extern int ide_devices_found; /* Initialized in check_ide_device() */
wdenkc6097192002-11-03 00:24:07 +0000543
544 WATCHDOG_RESET();
545
wdenk4fc95692003-02-28 00:49:47 +0000546 ide_devices_found = 0;
wdenkc6097192002-11-03 00:24:07 +0000547 /* initialize the PCMCIA IDE adapter card */
wdenk4fc95692003-02-28 00:49:47 +0000548 pcmcia_on();
549 if (!ide_devices_found)
wdenkc6097192002-11-03 00:24:07 +0000550 return;
551 udelay (1000000); /* 1 s */
552#endif /* CONFIG_IDE_8xx_PCCARD */
553
554 WATCHDOG_RESET();
555
wdenk9f837932003-10-09 19:00:25 +0000556#ifdef CONFIG_IDE_8xx_DIRECT
wdenkc6097192002-11-03 00:24:07 +0000557 /* Initialize PIO timing tables */
558 for (i=0; i <= IDE_MAX_PIO_MODE; ++i) {
wdenkf1276d42005-02-03 23:00:49 +0000559 pio_config_clk[i].t_setup = PCMCIA_MK_CLKS(pio_config_ns[i].t_setup,
560 gd->bus_clk);
561 pio_config_clk[i].t_length = PCMCIA_MK_CLKS(pio_config_ns[i].t_length,
562 gd->bus_clk);
563 pio_config_clk[i].t_hold = PCMCIA_MK_CLKS(pio_config_ns[i].t_hold,
564 gd->bus_clk);
565 debug ( "PIO Mode %d: setup=%2d ns/%d clk"
566 " len=%3d ns/%d clk"
567 " hold=%2d ns/%d clk\n",
568 i,
569 pio_config_ns[i].t_setup, pio_config_clk[i].t_setup,
570 pio_config_ns[i].t_length, pio_config_clk[i].t_length,
571 pio_config_ns[i].t_hold, pio_config_clk[i].t_hold);
wdenkc6097192002-11-03 00:24:07 +0000572 }
wdenk9f837932003-10-09 19:00:25 +0000573#endif /* CONFIG_IDE_8xx_DIRECT */
wdenkc6097192002-11-03 00:24:07 +0000574
575 /* Reset the IDE just to be sure.
576 * Light LED's to show
577 */
578 ide_led ((LED_IDE1 | LED_IDE2), 1); /* LED's on */
579 ide_reset (); /* ATAPI Drives seems to need a proper IDE Reset */
580
581#ifdef CONFIG_IDE_8xx_DIRECT
582 /* PCMCIA / IDE initialization for common mem space */
583 pcmp->pcmc_pgcrb = 0;
wdenkc6097192002-11-03 00:24:07 +0000584
585 /* start in PIO mode 0 - most relaxed timings */
586 pio_mode = 0;
587 set_pcmcia_timing (pio_mode);
wdenk9f837932003-10-09 19:00:25 +0000588#endif /* CONFIG_IDE_8xx_DIRECT */
wdenkc6097192002-11-03 00:24:07 +0000589
590 /*
591 * Wait for IDE to get ready.
592 * According to spec, this can take up to 31 seconds!
593 */
wdenk452cfd62002-11-19 11:04:11 +0000594#ifndef CONFIG_AMIGAONEG3SE
wdenkc6097192002-11-03 00:24:07 +0000595 for (bus=0; bus<CFG_IDE_MAXBUS; ++bus) {
596 int dev = bus * (CFG_IDE_MAXDEVICE / CFG_IDE_MAXBUS);
wdenk452cfd62002-11-19 11:04:11 +0000597#else
598 s = getenv("ide_maxbus");
599 if (s)
wdenkf1276d42005-02-03 23:00:49 +0000600 max_bus_scan = simple_strtol(s, NULL, 10);
wdenk452cfd62002-11-19 11:04:11 +0000601 else
wdenkf1276d42005-02-03 23:00:49 +0000602 max_bus_scan = CFG_IDE_MAXBUS;
wdenk452cfd62002-11-19 11:04:11 +0000603
604 for (bus=0; bus<max_bus_scan; ++bus) {
605 int dev = bus * (CFG_IDE_MAXDEVICE / max_bus_scan);
606#endif
wdenkc6097192002-11-03 00:24:07 +0000607
wdenk4fc95692003-02-28 00:49:47 +0000608#ifdef CONFIG_IDE_8xx_PCCARD
609 /* Skip non-ide devices from probing */
610 if ((ide_devices_found & (1 << bus)) == 0) {
611 ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */
612 continue;
613 }
614#endif
wdenkc6097192002-11-03 00:24:07 +0000615 printf ("Bus %d: ", bus);
616
617 ide_bus_ok[bus] = 0;
618
619 /* Select device
620 */
621 udelay (100000); /* 100 ms */
wdenk591dda52002-11-18 00:14:45 +0000622 ide_outb (dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
wdenkc6097192002-11-03 00:24:07 +0000623 udelay (100000); /* 100 ms */
Wolfgang Denk15c6b152007-04-11 17:22:55 +0200624#if defined(CONFIG_AMIGAONEG3SE) || defined(CONFIG_SC3)
625 if ((s = getenv("ide_reset_timeout")) != NULL)
626 ata_reset_time = simple_strtol(s, NULL, 10);
wdenk452cfd62002-11-19 11:04:11 +0000627#endif
wdenkc6097192002-11-03 00:24:07 +0000628 i = 0;
629 do {
630 udelay (10000); /* 10 ms */
631
wdenk591dda52002-11-18 00:14:45 +0000632 c = ide_inb (dev, ATA_STATUS);
wdenkc6097192002-11-03 00:24:07 +0000633 i++;
Wolfgang Denk15c6b152007-04-11 17:22:55 +0200634#if defined(CONFIG_AMIGAONEG3SE) || defined(CONFIG_SC3)
wdenk452cfd62002-11-19 11:04:11 +0000635 if (i > (ata_reset_time * 100)) {
636#else
wdenkc6097192002-11-03 00:24:07 +0000637 if (i > (ATA_RESET_TIME * 100)) {
wdenk452cfd62002-11-19 11:04:11 +0000638#endif
wdenkc6097192002-11-03 00:24:07 +0000639 puts ("** Timeout **\n");
640 ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */
wdenk452cfd62002-11-19 11:04:11 +0000641#ifdef CONFIG_AMIGAONEG3SE
642 /* If this is the second bus, the first one was OK */
wdenkf602aa02004-03-13 23:29:43 +0000643 if (bus != 0) {
wdenkf1276d42005-02-03 23:00:49 +0000644 ide_bus_ok[bus] = 0;
645 goto skip_bus;
wdenk452cfd62002-11-19 11:04:11 +0000646 }
647#endif
wdenkc6097192002-11-03 00:24:07 +0000648 return;
649 }
650 if ((i >= 100) && ((i%100)==0)) {
651 putc ('.');
652 }
653 } while (c & ATA_STAT_BUSY);
654
655 if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
656 puts ("not available ");
wdenkf1276d42005-02-03 23:00:49 +0000657 debug ("Status = 0x%02X ", c);
wdenkc6097192002-11-03 00:24:07 +0000658#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */
659 } else if ((c & ATA_STAT_READY) == 0) {
660 puts ("not available ");
wdenkf1276d42005-02-03 23:00:49 +0000661 debug ("Status = 0x%02X ", c);
wdenkc6097192002-11-03 00:24:07 +0000662#endif
663 } else {
664 puts ("OK ");
665 ide_bus_ok[bus] = 1;
666 }
667 WATCHDOG_RESET();
668 }
wdenk452cfd62002-11-19 11:04:11 +0000669
670#ifdef CONFIG_AMIGAONEG3SE
671 skip_bus:
672#endif
wdenkc6097192002-11-03 00:24:07 +0000673 putc ('\n');
674
675 ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */
676
677 curr_device = -1;
678 for (i=0; i<CFG_IDE_MAXDEVICE; ++i) {
679#ifdef CONFIG_IDE_LED
680 int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2;
681#endif
wdenk4b16c2e2003-11-07 13:42:26 +0000682 ide_dev_desc[i].type=DEV_TYPE_UNKNOWN;
wdenkc6097192002-11-03 00:24:07 +0000683 ide_dev_desc[i].if_type=IF_TYPE_IDE;
684 ide_dev_desc[i].dev=i;
685 ide_dev_desc[i].part_type=PART_TYPE_UNKNOWN;
686 ide_dev_desc[i].blksz=0;
687 ide_dev_desc[i].lba=0;
688 ide_dev_desc[i].block_read=ide_read;
689 if (!ide_bus_ok[IDE_BUS(i)])
690 continue;
691 ide_led (led, 1); /* LED on */
692 ide_ident(&ide_dev_desc[i]);
693 ide_led (led, 0); /* LED off */
694 dev_print(&ide_dev_desc[i]);
695/* ide_print (i); */
696 if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) {
697 init_part (&ide_dev_desc[i]); /* initialize partition type */
698 if (curr_device < 0)
699 curr_device = i;
700 }
701 }
702 WATCHDOG_RESET();
703}
704
705/* ------------------------------------------------------------------------- */
706
707block_dev_desc_t * ide_get_dev(int dev)
708{
Grant Likelyffc2dd72007-02-20 09:04:34 +0100709 return (dev < CFG_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL;
wdenkc6097192002-11-03 00:24:07 +0000710}
711
712
713#ifdef CONFIG_IDE_8xx_DIRECT
714
715static void
716set_pcmcia_timing (int pmode)
717{
718 volatile immap_t *immr = (immap_t *)CFG_IMMR;
719 volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
720 ulong timings;
721
wdenkf1276d42005-02-03 23:00:49 +0000722 debug ("Set timing for PIO Mode %d\n", pmode);
wdenkc6097192002-11-03 00:24:07 +0000723
724 timings = PCMCIA_SHT(pio_config_clk[pmode].t_hold)
725 | PCMCIA_SST(pio_config_clk[pmode].t_setup)
726 | PCMCIA_SL (pio_config_clk[pmode].t_length)
727 ;
728
729 /* IDE 0
730 */
731 pcmp->pcmc_pbr0 = CFG_PCMCIA_PBR0;
732 pcmp->pcmc_por0 = CFG_PCMCIA_POR0
733#if (CFG_PCMCIA_POR0 != 0)
734 | timings
735#endif
736 ;
wdenkf1276d42005-02-03 23:00:49 +0000737 debug ("PBR0: %08x POR0: %08x\n", pcmp->pcmc_pbr0, pcmp->pcmc_por0);
wdenkc6097192002-11-03 00:24:07 +0000738
739 pcmp->pcmc_pbr1 = CFG_PCMCIA_PBR1;
740 pcmp->pcmc_por1 = CFG_PCMCIA_POR1
741#if (CFG_PCMCIA_POR1 != 0)
742 | timings
743#endif
744 ;
wdenkf1276d42005-02-03 23:00:49 +0000745 debug ("PBR1: %08x POR1: %08x\n", pcmp->pcmc_pbr1, pcmp->pcmc_por1);
wdenkc6097192002-11-03 00:24:07 +0000746
747 pcmp->pcmc_pbr2 = CFG_PCMCIA_PBR2;
748 pcmp->pcmc_por2 = CFG_PCMCIA_POR2
749#if (CFG_PCMCIA_POR2 != 0)
750 | timings
751#endif
752 ;
wdenkf1276d42005-02-03 23:00:49 +0000753 debug ("PBR2: %08x POR2: %08x\n", pcmp->pcmc_pbr2, pcmp->pcmc_por2);
wdenkc6097192002-11-03 00:24:07 +0000754
755 pcmp->pcmc_pbr3 = CFG_PCMCIA_PBR3;
756 pcmp->pcmc_por3 = CFG_PCMCIA_POR3
757#if (CFG_PCMCIA_POR3 != 0)
758 | timings
759#endif
760 ;
wdenkf1276d42005-02-03 23:00:49 +0000761 debug ("PBR3: %08x POR3: %08x\n", pcmp->pcmc_pbr3, pcmp->pcmc_por3);
wdenkc6097192002-11-03 00:24:07 +0000762
763 /* IDE 1
764 */
765 pcmp->pcmc_pbr4 = CFG_PCMCIA_PBR4;
766 pcmp->pcmc_por4 = CFG_PCMCIA_POR4
767#if (CFG_PCMCIA_POR4 != 0)
768 | timings
769#endif
770 ;
wdenkf1276d42005-02-03 23:00:49 +0000771 debug ("PBR4: %08x POR4: %08x\n", pcmp->pcmc_pbr4, pcmp->pcmc_por4);
wdenkc6097192002-11-03 00:24:07 +0000772
773 pcmp->pcmc_pbr5 = CFG_PCMCIA_PBR5;
774 pcmp->pcmc_por5 = CFG_PCMCIA_POR5
775#if (CFG_PCMCIA_POR5 != 0)
776 | timings
777#endif
778 ;
wdenkf1276d42005-02-03 23:00:49 +0000779 debug ("PBR5: %08x POR5: %08x\n", pcmp->pcmc_pbr5, pcmp->pcmc_por5);
wdenkc6097192002-11-03 00:24:07 +0000780
781 pcmp->pcmc_pbr6 = CFG_PCMCIA_PBR6;
782 pcmp->pcmc_por6 = CFG_PCMCIA_POR6
783#if (CFG_PCMCIA_POR6 != 0)
784 | timings
785#endif
786 ;
wdenkf1276d42005-02-03 23:00:49 +0000787 debug ("PBR6: %08x POR6: %08x\n", pcmp->pcmc_pbr6, pcmp->pcmc_por6);
wdenkc6097192002-11-03 00:24:07 +0000788
789 pcmp->pcmc_pbr7 = CFG_PCMCIA_PBR7;
790 pcmp->pcmc_por7 = CFG_PCMCIA_POR7
791#if (CFG_PCMCIA_POR7 != 0)
792 | timings
793#endif
794 ;
wdenkf1276d42005-02-03 23:00:49 +0000795 debug ("PBR7: %08x POR7: %08x\n", pcmp->pcmc_pbr7, pcmp->pcmc_por7);
wdenkc6097192002-11-03 00:24:07 +0000796
797}
798
799#endif /* CONFIG_IDE_8xx_DIRECT */
800
801/* ------------------------------------------------------------------------- */
802
Heiko Schocher2559e0f2007-08-28 17:39:14 +0200803void inline
804__ide_outb(int dev, int port, unsigned char val)
wdenkc6097192002-11-03 00:24:07 +0000805{
wdenkf1276d42005-02-03 23:00:49 +0000806 debug ("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n",
Heiko Schocher2559e0f2007-08-28 17:39:14 +0200807 dev, port, val, (ATA_CURR_BASE(dev)+CFG_ATA_PORT_ADDR(port)));
808 outb(val, (ATA_CURR_BASE(dev)+CFG_ATA_PORT_ADDR(port)));
wdenk591dda52002-11-18 00:14:45 +0000809}
Heiko Schocher2559e0f2007-08-28 17:39:14 +0200810void inline ide_outb (int dev, int port, unsigned char val)
811 __attribute__((weak, alias("__ide_outb")));
wdenkc6097192002-11-03 00:24:07 +0000812
Heiko Schocher2559e0f2007-08-28 17:39:14 +0200813unsigned char inline
814__ide_inb(int dev, int port)
wdenkc6097192002-11-03 00:24:07 +0000815{
816 uchar val;
Heiko Schocher2559e0f2007-08-28 17:39:14 +0200817 val = inb((ATA_CURR_BASE(dev)+CFG_ATA_PORT_ADDR(port)));
wdenkf1276d42005-02-03 23:00:49 +0000818 debug ("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n",
Heiko Schocher2559e0f2007-08-28 17:39:14 +0200819 dev, port, (ATA_CURR_BASE(dev)+CFG_ATA_PORT_ADDR(port)), val);
820 return val;
wdenk591dda52002-11-18 00:14:45 +0000821}
Heiko Schocher2559e0f2007-08-28 17:39:14 +0200822unsigned char inline ide_inb(int dev, int port)
823 __attribute__((weak, alias("__ide_inb")));
wdenkc6097192002-11-03 00:24:07 +0000824
wdenk591dda52002-11-18 00:14:45 +0000825#ifdef __PPC__
wdenk88d2ba92003-06-23 18:12:28 +0000826# ifdef CONFIG_AMIGAONEG3SE
wdenk452cfd62002-11-19 11:04:11 +0000827static void
828output_data_short(int dev, ulong *sect_buf, int words)
829{
830 ushort *dbuf;
831 volatile ushort *pbuf;
wdenk57b2d802003-06-27 21:31:46 +0000832
wdenk452cfd62002-11-19 11:04:11 +0000833 pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
834 dbuf = (ushort *)sect_buf;
835 while (words--) {
wdenk20c98a62004-04-23 20:32:05 +0000836 EIEIO;
wdenk452cfd62002-11-19 11:04:11 +0000837 *pbuf = *dbuf++;
wdenk20c98a62004-04-23 20:32:05 +0000838 EIEIO;
wdenk452cfd62002-11-19 11:04:11 +0000839 }
840
841 if (words&1)
wdenkf1276d42005-02-03 23:00:49 +0000842 *pbuf = 0;
wdenk452cfd62002-11-19 11:04:11 +0000843}
wdenk88d2ba92003-06-23 18:12:28 +0000844# endif /* CONFIG_AMIGAONEG3SE */
wdenk9b7f3842003-10-09 20:09:04 +0000845#endif /* __PPC_ */
wdenk452cfd62002-11-19 11:04:11 +0000846
wdenk9b7f3842003-10-09 20:09:04 +0000847/* We only need to swap data if we are running on a big endian cpu. */
848/* But Au1x00 cpu:s already swaps data in big endian mode! */
Wolfgang Denk39c76422006-06-16 17:32:31 +0200849#if defined(__LITTLE_ENDIAN) || ( defined(CONFIG_AU1X00) && !defined(CONFIG_GTH2) )
wdenk9b7f3842003-10-09 20:09:04 +0000850#define input_swap_data(x,y,z) input_data(x,y,z)
851#else
wdenkc6097192002-11-03 00:24:07 +0000852static void
853input_swap_data(int dev, ulong *sect_buf, int words)
854{
wdenkf1276d42005-02-03 23:00:49 +0000855#if defined(CONFIG_HMI10) || defined(CONFIG_CPC45)
wdenk2f99a692004-01-04 22:51:12 +0000856 uchar i;
857 volatile uchar *pbuf_even = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_EVEN);
858 volatile uchar *pbuf_odd = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_ODD);
859 ushort *dbuf = (ushort *)sect_buf;
860
861 while (words--) {
862 for (i=0; i<2; i++) {
863 *(((uchar *)(dbuf)) + 1) = *pbuf_even;
864 *(uchar *)dbuf = *pbuf_odd;
865 dbuf+=1;
866 }
867 }
wdenkb995b0f2005-03-06 01:21:30 +0000868#else
wdenkf1276d42005-02-03 23:00:49 +0000869 volatile ushort *pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
870 ushort *dbuf = (ushort *)sect_buf;
871
872 debug("in input swap data base for read is %lx\n", (unsigned long) pbuf);
873
874 while (words--) {
Wolfgang Denk39c76422006-06-16 17:32:31 +0200875#ifdef __MIPS__
876 *dbuf++ = swab16p((u16*)pbuf);
877 *dbuf++ = swab16p((u16*)pbuf);
Heiko Schocher633e03a2007-06-22 19:11:54 +0200878#elif defined(CONFIG_PCS440EP)
879 *dbuf++ = *pbuf;
880 *dbuf++ = *pbuf;
Wolfgang Denk39c76422006-06-16 17:32:31 +0200881#else
wdenkf1276d42005-02-03 23:00:49 +0000882 *dbuf++ = ld_le16(pbuf);
883 *dbuf++ = ld_le16(pbuf);
Wolfgang Denk39c76422006-06-16 17:32:31 +0200884#endif /* !MIPS */
wdenkf1276d42005-02-03 23:00:49 +0000885 }
886#endif
wdenkc6097192002-11-03 00:24:07 +0000887}
wdenk9b7f3842003-10-09 20:09:04 +0000888#endif /* __LITTLE_ENDIAN || CONFIG_AU1X00 */
wdenk591dda52002-11-18 00:14:45 +0000889
890
wdenk634d2f72004-04-15 23:14:49 +0000891#if defined(__PPC__) || defined(CONFIG_PXA_PCMCIA)
wdenkc6097192002-11-03 00:24:07 +0000892static void
893output_data(int dev, ulong *sect_buf, int words)
894{
wdenkf1276d42005-02-03 23:00:49 +0000895#if defined(CONFIG_HMI10) || defined(CONFIG_CPC45)
wdenk2f99a692004-01-04 22:51:12 +0000896 uchar *dbuf;
897 volatile uchar *pbuf_even;
898 volatile uchar *pbuf_odd;
899
900 pbuf_even = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_EVEN);
901 pbuf_odd = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_ODD);
902 dbuf = (uchar *)sect_buf;
903 while (words--) {
wdenk20c98a62004-04-23 20:32:05 +0000904 EIEIO;
wdenk2f99a692004-01-04 22:51:12 +0000905 *pbuf_even = *dbuf++;
wdenk20c98a62004-04-23 20:32:05 +0000906 EIEIO;
wdenk2f99a692004-01-04 22:51:12 +0000907 *pbuf_odd = *dbuf++;
wdenk20c98a62004-04-23 20:32:05 +0000908 EIEIO;
wdenk2f99a692004-01-04 22:51:12 +0000909 *pbuf_even = *dbuf++;
wdenk20c98a62004-04-23 20:32:05 +0000910 EIEIO;
wdenk2f99a692004-01-04 22:51:12 +0000911 *pbuf_odd = *dbuf++;
912 }
wdenkf1276d42005-02-03 23:00:49 +0000913#else
914 ushort *dbuf;
915 volatile ushort *pbuf;
916
917 pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
918 dbuf = (ushort *)sect_buf;
919 while (words--) {
Heiko Schocher633e03a2007-06-22 19:11:54 +0200920#if defined(CONFIG_PCS440EP)
921 /* not tested, because CF was write protected */
922 EIEIO;
923 *pbuf = ld_le16(dbuf++);
924 EIEIO;
925 *pbuf = ld_le16(dbuf++);
926#else
wdenkf1276d42005-02-03 23:00:49 +0000927 EIEIO;
928 *pbuf = *dbuf++;
929 EIEIO;
930 *pbuf = *dbuf++;
Heiko Schocher633e03a2007-06-22 19:11:54 +0200931#endif
wdenkf1276d42005-02-03 23:00:49 +0000932 }
933#endif
wdenkc6097192002-11-03 00:24:07 +0000934}
wdenk591dda52002-11-18 00:14:45 +0000935#else /* ! __PPC__ */
936static void
937output_data(int dev, ulong *sect_buf, int words)
938{
wdenk9f837932003-10-09 19:00:25 +0000939 outsw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, words<<1);
wdenk591dda52002-11-18 00:14:45 +0000940}
941#endif /* __PPC__ */
wdenkc6097192002-11-03 00:24:07 +0000942
wdenk634d2f72004-04-15 23:14:49 +0000943#if defined(__PPC__) || defined(CONFIG_PXA_PCMCIA)
wdenkc6097192002-11-03 00:24:07 +0000944static void
945input_data(int dev, ulong *sect_buf, int words)
946{
wdenkf1276d42005-02-03 23:00:49 +0000947#if defined(CONFIG_HMI10) || defined(CONFIG_CPC45)
wdenk2f99a692004-01-04 22:51:12 +0000948 uchar *dbuf;
949 volatile uchar *pbuf_even;
950 volatile uchar *pbuf_odd;
951
952 pbuf_even = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_EVEN);
953 pbuf_odd = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_ODD);
954 dbuf = (uchar *)sect_buf;
955 while (words--) {
wdenkf1276d42005-02-03 23:00:49 +0000956 *dbuf++ = *pbuf_even;
wdenk20c98a62004-04-23 20:32:05 +0000957 EIEIO;
wdenkf1276d42005-02-03 23:00:49 +0000958 SYNC;
959 *dbuf++ = *pbuf_odd;
wdenkf6925c72005-01-22 18:26:04 +0000960 EIEIO;
wdenkf1276d42005-02-03 23:00:49 +0000961 SYNC;
wdenk2f99a692004-01-04 22:51:12 +0000962 *dbuf++ = *pbuf_even;
wdenk20c98a62004-04-23 20:32:05 +0000963 EIEIO;
wdenkf1276d42005-02-03 23:00:49 +0000964 SYNC;
wdenk2f99a692004-01-04 22:51:12 +0000965 *dbuf++ = *pbuf_odd;
wdenk20c98a62004-04-23 20:32:05 +0000966 EIEIO;
wdenkf1276d42005-02-03 23:00:49 +0000967 SYNC;
968 }
969#else
970 ushort *dbuf;
971 volatile ushort *pbuf;
972
973 pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
974 dbuf = (ushort *)sect_buf;
975
976 debug("in input data base for read is %lx\n", (unsigned long) pbuf);
977
978 while (words--) {
Heiko Schocher633e03a2007-06-22 19:11:54 +0200979#if defined(CONFIG_PCS440EP)
980 EIEIO;
981 *dbuf++ = ld_le16(pbuf);
982 EIEIO;
983 *dbuf++ = ld_le16(pbuf);
984#else
wdenk20c98a62004-04-23 20:32:05 +0000985 EIEIO;
wdenkf1276d42005-02-03 23:00:49 +0000986 *dbuf++ = *pbuf;
wdenkf6925c72005-01-22 18:26:04 +0000987 EIEIO;
wdenkf1276d42005-02-03 23:00:49 +0000988 *dbuf++ = *pbuf;
Heiko Schocher633e03a2007-06-22 19:11:54 +0200989#endif
wdenk2f99a692004-01-04 22:51:12 +0000990 }
wdenkf1276d42005-02-03 23:00:49 +0000991#endif
wdenkc6097192002-11-03 00:24:07 +0000992}
wdenk591dda52002-11-18 00:14:45 +0000993#else /* ! __PPC__ */
994static void
995input_data(int dev, ulong *sect_buf, int words)
996{
wdenk9f837932003-10-09 19:00:25 +0000997 insw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, words << 1);
wdenk591dda52002-11-18 00:14:45 +0000998}
999
1000#endif /* __PPC__ */
wdenkc6097192002-11-03 00:24:07 +00001001
wdenk452cfd62002-11-19 11:04:11 +00001002#ifdef CONFIG_AMIGAONEG3SE
1003static void
1004input_data_short(int dev, ulong *sect_buf, int words)
1005{
1006 ushort *dbuf;
1007 volatile ushort *pbuf;
1008
1009 pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
1010 dbuf = (ushort *)sect_buf;
1011 while (words--) {
wdenk20c98a62004-04-23 20:32:05 +00001012 EIEIO;
wdenk452cfd62002-11-19 11:04:11 +00001013 *dbuf++ = *pbuf;
wdenk20c98a62004-04-23 20:32:05 +00001014 EIEIO;
wdenk452cfd62002-11-19 11:04:11 +00001015 }
1016
wdenkf602aa02004-03-13 23:29:43 +00001017 if (words&1) {
wdenkf1276d42005-02-03 23:00:49 +00001018 ushort dummy;
1019 dummy = *pbuf;
wdenk452cfd62002-11-19 11:04:11 +00001020 }
1021}
1022#endif
1023
wdenkc6097192002-11-03 00:24:07 +00001024/* -------------------------------------------------------------------------
1025 */
1026static void ide_ident (block_dev_desc_t *dev_desc)
1027{
1028 ulong iobuf[ATA_SECTORWORDS];
1029 unsigned char c;
1030 hd_driveid_t *iop = (hd_driveid_t *)iobuf;
1031
wdenk452cfd62002-11-19 11:04:11 +00001032#ifdef CONFIG_AMIGAONEG3SE
1033 int max_bus_scan;
wdenk452cfd62002-11-19 11:04:11 +00001034 char *s;
wdenke2d6d742004-09-28 20:34:50 +00001035#endif
1036#ifdef CONFIG_ATAPI
1037 int retries = 0;
wdenk452cfd62002-11-19 11:04:11 +00001038 int do_retry = 0;
1039#endif
1040
wdenkc6097192002-11-03 00:24:07 +00001041#if 0
1042 int mode, cycle_time;
1043#endif
1044 int device;
1045 device=dev_desc->dev;
1046 printf (" Device %d: ", device);
1047
wdenk452cfd62002-11-19 11:04:11 +00001048#ifdef CONFIG_AMIGAONEG3SE
1049 s = getenv("ide_maxbus");
1050 if (s) {
1051 max_bus_scan = simple_strtol(s, NULL, 10);
1052 } else {
1053 max_bus_scan = CFG_IDE_MAXBUS;
1054 }
1055 if (device >= max_bus_scan*2) {
1056 dev_desc->type=DEV_TYPE_UNKNOWN;
1057 return;
1058 }
1059#endif
1060
wdenkc6097192002-11-03 00:24:07 +00001061 ide_led (DEVICE_LED(device), 1); /* LED on */
1062 /* Select device
1063 */
wdenk591dda52002-11-18 00:14:45 +00001064 ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
wdenkc6097192002-11-03 00:24:07 +00001065 dev_desc->if_type=IF_TYPE_IDE;
1066#ifdef CONFIG_ATAPI
wdenk452cfd62002-11-19 11:04:11 +00001067
wdenk452cfd62002-11-19 11:04:11 +00001068 do_retry = 0;
1069 retries = 0;
1070
1071 /* Warning: This will be tricky to read */
wdenkf602aa02004-03-13 23:29:43 +00001072 while (retries <= 1) {
wdenkc6097192002-11-03 00:24:07 +00001073 /* check signature */
wdenk591dda52002-11-18 00:14:45 +00001074 if ((ide_inb(device,ATA_SECT_CNT) == 0x01) &&
1075 (ide_inb(device,ATA_SECT_NUM) == 0x01) &&
1076 (ide_inb(device,ATA_CYL_LOW) == 0x14) &&
1077 (ide_inb(device,ATA_CYL_HIGH) == 0xEB)) {
wdenkc6097192002-11-03 00:24:07 +00001078 /* ATAPI Signature found */
1079 dev_desc->if_type=IF_TYPE_ATAPI;
1080 /* Start Ident Command
1081 */
wdenk591dda52002-11-18 00:14:45 +00001082 ide_outb (device, ATA_COMMAND, ATAPI_CMD_IDENT);
wdenkc6097192002-11-03 00:24:07 +00001083 /*
1084 * Wait for completion - ATAPI devices need more time
1085 * to become ready
1086 */
1087 c = ide_wait (device, ATAPI_TIME_OUT);
wdenkf602aa02004-03-13 23:29:43 +00001088 } else
wdenkc6097192002-11-03 00:24:07 +00001089#endif
1090 {
1091 /* Start Ident Command
1092 */
wdenk591dda52002-11-18 00:14:45 +00001093 ide_outb (device, ATA_COMMAND, ATA_CMD_IDENT);
wdenkc6097192002-11-03 00:24:07 +00001094
1095 /* Wait for completion
1096 */
1097 c = ide_wait (device, IDE_TIME_OUT);
1098 }
1099 ide_led (DEVICE_LED(device), 0); /* LED off */
1100
1101 if (((c & ATA_STAT_DRQ) == 0) ||
1102 ((c & (ATA_STAT_FAULT|ATA_STAT_ERR)) != 0) ) {
wdenke2d6d742004-09-28 20:34:50 +00001103#ifdef CONFIG_ATAPI
wdenk452cfd62002-11-19 11:04:11 +00001104#ifdef CONFIG_AMIGAONEG3SE
wdenke2d6d742004-09-28 20:34:50 +00001105 s = getenv("ide_doreset");
1106 if (s && strcmp(s, "on") == 0)
1107#endif
wdenkf1276d42005-02-03 23:00:49 +00001108 {
1109 /* Need to soft reset the device in case it's an ATAPI... */
1110 debug ("Retrying...\n");
1111 ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
1112 udelay(100000);
1113 ide_outb (device, ATA_COMMAND, 0x08);
1114 udelay (500000); /* 500 ms */
1115 }
wdenke2d6d742004-09-28 20:34:50 +00001116 /* Select device
1117 */
wdenk452cfd62002-11-19 11:04:11 +00001118 ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
wdenk452cfd62002-11-19 11:04:11 +00001119 retries++;
wdenke2d6d742004-09-28 20:34:50 +00001120#else
1121 return;
1122#endif
wdenkc6097192002-11-03 00:24:07 +00001123 }
wdenke2d6d742004-09-28 20:34:50 +00001124#ifdef CONFIG_ATAPI
1125 else
1126 break;
wdenk452cfd62002-11-19 11:04:11 +00001127 } /* see above - ugly to read */
wdenke2d6d742004-09-28 20:34:50 +00001128
1129 if (retries == 2) /* Not found */
1130 return;
1131#endif
wdenkc6097192002-11-03 00:24:07 +00001132
1133 input_swap_data (device, iobuf, ATA_SECTORWORDS);
1134
Jean-Christophe PLAGNIOL-VILLARD1fa3e362007-11-07 08:19:19 +01001135 ident_cpy ((unsigned char*)dev_desc->revision, iop->fw_rev, sizeof(dev_desc->revision));
1136 ident_cpy ((unsigned char*)dev_desc->vendor, iop->model, sizeof(dev_desc->vendor));
1137 ident_cpy ((unsigned char*)dev_desc->product, iop->serial_no, sizeof(dev_desc->product));
wdenkacd9b102004-03-14 00:59:59 +00001138#ifdef __LITTLE_ENDIAN
1139 /*
1140 * firmware revision and model number have Big Endian Byte
1141 * order in Word. Convert both to little endian.
1142 *
1143 * See CF+ and CompactFlash Specification Revision 2.0:
1144 * 6.2.1.6: Identfy Drive, Table 39 for more details
1145 */
1146
1147 strswab (dev_desc->revision);
1148 strswab (dev_desc->vendor);
1149#endif /* __LITTLE_ENDIAN */
wdenkc6097192002-11-03 00:24:07 +00001150
1151 if ((iop->config & 0x0080)==0x0080)
1152 dev_desc->removable = 1;
1153 else
1154 dev_desc->removable = 0;
1155
1156#if 0
1157 /*
1158 * Drive PIO mode autoselection
1159 */
1160 mode = iop->tPIO;
1161
1162 printf ("tPIO = 0x%02x = %d\n",mode, mode);
1163 if (mode > 2) { /* 2 is maximum allowed tPIO value */
1164 mode = 2;
wdenkf1276d42005-02-03 23:00:49 +00001165 debug ("Override tPIO -> 2\n");
wdenkc6097192002-11-03 00:24:07 +00001166 }
1167 if (iop->field_valid & 2) { /* drive implements ATA2? */
wdenkf1276d42005-02-03 23:00:49 +00001168 debug ("Drive implements ATA2\n");
wdenkc6097192002-11-03 00:24:07 +00001169 if (iop->capability & 8) { /* drive supports use_iordy? */
1170 cycle_time = iop->eide_pio_iordy;
1171 } else {
1172 cycle_time = iop->eide_pio;
1173 }
wdenkf1276d42005-02-03 23:00:49 +00001174 debug ("cycle time = %d\n", cycle_time);
wdenkc6097192002-11-03 00:24:07 +00001175 mode = 4;
1176 if (cycle_time > 120) mode = 3; /* 120 ns for PIO mode 4 */
1177 if (cycle_time > 180) mode = 2; /* 180 ns for PIO mode 3 */
1178 if (cycle_time > 240) mode = 1; /* 240 ns for PIO mode 4 */
1179 if (cycle_time > 383) mode = 0; /* 383 ns for PIO mode 4 */
1180 }
1181 printf ("PIO mode to use: PIO %d\n", mode);
1182#endif /* 0 */
1183
1184#ifdef CONFIG_ATAPI
1185 if (dev_desc->if_type==IF_TYPE_ATAPI) {
1186 atapi_inquiry(dev_desc);
1187 return;
1188 }
1189#endif /* CONFIG_ATAPI */
1190
wdenkacd9b102004-03-14 00:59:59 +00001191#ifdef __BIG_ENDIAN
wdenkc6097192002-11-03 00:24:07 +00001192 /* swap shorts */
1193 dev_desc->lba = (iop->lba_capacity << 16) | (iop->lba_capacity >> 16);
wdenkacd9b102004-03-14 00:59:59 +00001194#else /* ! __BIG_ENDIAN */
1195 /*
1196 * do not swap shorts on little endian
1197 *
1198 * See CF+ and CompactFlash Specification Revision 2.0:
1199 * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details.
1200 */
1201 dev_desc->lba = iop->lba_capacity;
1202#endif /* __BIG_ENDIAN */
wdenkf602aa02004-03-13 23:29:43 +00001203
wdenkc35ba4e2004-03-14 22:25:36 +00001204#ifdef CONFIG_LBA48
wdenkf602aa02004-03-13 23:29:43 +00001205 if (iop->command_set_2 & 0x0400) { /* LBA 48 support */
wdenk05939202004-04-18 17:39:38 +00001206 dev_desc->lba48 = 1;
1207 dev_desc->lba = (unsigned long long)iop->lba48_capacity[0] |
wdenkf602aa02004-03-13 23:29:43 +00001208 ((unsigned long long)iop->lba48_capacity[1] << 16) |
1209 ((unsigned long long)iop->lba48_capacity[2] << 32) |
1210 ((unsigned long long)iop->lba48_capacity[3] << 48);
1211 } else {
wdenkf602aa02004-03-13 23:29:43 +00001212 dev_desc->lba48 = 0;
1213 }
1214#endif /* CONFIG_LBA48 */
wdenkc6097192002-11-03 00:24:07 +00001215 /* assuming HD */
1216 dev_desc->type=DEV_TYPE_HARDDISK;
1217 dev_desc->blksz=ATA_BLOCKSIZE;
1218 dev_desc->lun=0; /* just to fill something in... */
1219
1220#if 0 /* only used to test the powersaving mode,
1221 * if enabled, the drive goes after 5 sec
1222 * in standby mode */
wdenk591dda52002-11-18 00:14:45 +00001223 ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
wdenkc6097192002-11-03 00:24:07 +00001224 c = ide_wait (device, IDE_TIME_OUT);
wdenk591dda52002-11-18 00:14:45 +00001225 ide_outb (device, ATA_SECT_CNT, 1);
1226 ide_outb (device, ATA_LBA_LOW, 0);
1227 ide_outb (device, ATA_LBA_MID, 0);
1228 ide_outb (device, ATA_LBA_HIGH, 0);
wdenkf1276d42005-02-03 23:00:49 +00001229 ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
wdenk591dda52002-11-18 00:14:45 +00001230 ide_outb (device, ATA_COMMAND, 0xe3);
wdenkc6097192002-11-03 00:24:07 +00001231 udelay (50);
1232 c = ide_wait (device, IDE_TIME_OUT); /* can't take over 500 ms */
1233#endif
1234}
1235
1236
1237/* ------------------------------------------------------------------------- */
1238
Grant Likely2089cab2007-02-20 09:05:45 +01001239ulong ide_read (int device, lbaint_t blknr, ulong blkcnt, void *buffer)
wdenkc6097192002-11-03 00:24:07 +00001240{
1241 ulong n = 0;
1242 unsigned char c;
1243 unsigned char pwrsave=0; /* power save */
wdenkc35ba4e2004-03-14 22:25:36 +00001244#ifdef CONFIG_LBA48
wdenkf602aa02004-03-13 23:29:43 +00001245 unsigned char lba48 = 0;
wdenkc6097192002-11-03 00:24:07 +00001246
wdenkf602aa02004-03-13 23:29:43 +00001247 if (blknr & 0x0000fffff0000000) {
1248 /* more than 28 bits used, use 48bit mode */
1249 lba48 = 1;
1250 }
1251#endif
wdenkf1276d42005-02-03 23:00:49 +00001252 debug ("ide_read dev %d start %qX, blocks %lX buffer at %lX\n",
wdenkc6097192002-11-03 00:24:07 +00001253 device, blknr, blkcnt, (ulong)buffer);
1254
1255 ide_led (DEVICE_LED(device), 1); /* LED on */
1256
1257 /* Select device
1258 */
wdenk591dda52002-11-18 00:14:45 +00001259 ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
wdenkc6097192002-11-03 00:24:07 +00001260 c = ide_wait (device, IDE_TIME_OUT);
1261
1262 if (c & ATA_STAT_BUSY) {
1263 printf ("IDE read: device %d not ready\n", device);
1264 goto IDE_READ_E;
1265 }
1266
1267 /* first check if the drive is in Powersaving mode, if yes,
1268 * increase the timeout value */
wdenk591dda52002-11-18 00:14:45 +00001269 ide_outb (device, ATA_COMMAND, ATA_CMD_CHK_PWR);
wdenkc6097192002-11-03 00:24:07 +00001270 udelay (50);
1271
1272 c = ide_wait (device, IDE_TIME_OUT); /* can't take over 500 ms */
1273
1274 if (c & ATA_STAT_BUSY) {
1275 printf ("IDE read: device %d not ready\n", device);
1276 goto IDE_READ_E;
1277 }
1278 if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
1279 printf ("No Powersaving mode %X\n", c);
1280 } else {
wdenk591dda52002-11-18 00:14:45 +00001281 c = ide_inb(device,ATA_SECT_CNT);
wdenkf1276d42005-02-03 23:00:49 +00001282 debug ("Powersaving %02X\n",c);
wdenkc6097192002-11-03 00:24:07 +00001283 if(c==0)
1284 pwrsave=1;
1285 }
1286
1287
1288 while (blkcnt-- > 0) {
1289
1290 c = ide_wait (device, IDE_TIME_OUT);
1291
1292 if (c & ATA_STAT_BUSY) {
1293 printf ("IDE read: device %d not ready\n", device);
1294 break;
1295 }
wdenkc35ba4e2004-03-14 22:25:36 +00001296#ifdef CONFIG_LBA48
wdenkf602aa02004-03-13 23:29:43 +00001297 if (lba48) {
1298 /* write high bits */
1299 ide_outb (device, ATA_SECT_CNT, 0);
1300 ide_outb (device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
1301 ide_outb (device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
1302 ide_outb (device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
1303 }
1304#endif
wdenk591dda52002-11-18 00:14:45 +00001305 ide_outb (device, ATA_SECT_CNT, 1);
1306 ide_outb (device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
1307 ide_outb (device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
1308 ide_outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
wdenkf602aa02004-03-13 23:29:43 +00001309
wdenkc35ba4e2004-03-14 22:25:36 +00001310#ifdef CONFIG_LBA48
wdenkf602aa02004-03-13 23:29:43 +00001311 if (lba48) {
1312 ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device) );
1313 ide_outb (device, ATA_COMMAND, ATA_CMD_READ_EXT);
1314
1315 } else
1316#endif
1317 {
1318 ide_outb (device, ATA_DEV_HD, ATA_LBA |
1319 ATA_DEVICE(device) |
1320 ((blknr >> 24) & 0xF) );
1321 ide_outb (device, ATA_COMMAND, ATA_CMD_READ);
1322 }
wdenkc6097192002-11-03 00:24:07 +00001323
1324 udelay (50);
1325
1326 if(pwrsave) {
1327 c = ide_wait (device, IDE_SPIN_UP_TIME_OUT); /* may take up to 4 sec */
1328 pwrsave=0;
1329 } else {
1330 c = ide_wait (device, IDE_TIME_OUT); /* can't take over 500 ms */
1331 }
1332
1333 if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) {
wdenkc35ba4e2004-03-14 22:25:36 +00001334#if defined(CFG_64BIT_LBA) && defined(CFG_64BIT_VSPRINTF)
wdenkf602aa02004-03-13 23:29:43 +00001335 printf ("Error (no IRQ) dev %d blk %qd: status 0x%02x\n",
wdenkc6097192002-11-03 00:24:07 +00001336 device, blknr, c);
wdenkf602aa02004-03-13 23:29:43 +00001337#else
1338 printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n",
1339 device, (ulong)blknr, c);
1340#endif
wdenkc6097192002-11-03 00:24:07 +00001341 break;
1342 }
1343
1344 input_data (device, buffer, ATA_SECTORWORDS);
wdenk591dda52002-11-18 00:14:45 +00001345 (void) ide_inb (device, ATA_STATUS); /* clear IRQ */
wdenkc6097192002-11-03 00:24:07 +00001346
1347 ++n;
1348 ++blknr;
Greg Lopp50abf9f2007-04-13 08:02:24 +02001349 buffer += ATA_BLOCKSIZE;
wdenkc6097192002-11-03 00:24:07 +00001350 }
1351IDE_READ_E:
1352 ide_led (DEVICE_LED(device), 0); /* LED off */
1353 return (n);
1354}
1355
1356/* ------------------------------------------------------------------------- */
1357
1358
Grant Likely2089cab2007-02-20 09:05:45 +01001359ulong ide_write (int device, lbaint_t blknr, ulong blkcnt, void *buffer)
wdenkc6097192002-11-03 00:24:07 +00001360{
1361 ulong n = 0;
1362 unsigned char c;
wdenkc35ba4e2004-03-14 22:25:36 +00001363#ifdef CONFIG_LBA48
wdenkf602aa02004-03-13 23:29:43 +00001364 unsigned char lba48 = 0;
1365
1366 if (blknr & 0x0000fffff0000000) {
1367 /* more than 28 bits used, use 48bit mode */
1368 lba48 = 1;
1369 }
1370#endif
wdenkc6097192002-11-03 00:24:07 +00001371
1372 ide_led (DEVICE_LED(device), 1); /* LED on */
1373
1374 /* Select device
1375 */
wdenk591dda52002-11-18 00:14:45 +00001376 ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
wdenkc6097192002-11-03 00:24:07 +00001377
1378 while (blkcnt-- > 0) {
1379
1380 c = ide_wait (device, IDE_TIME_OUT);
1381
1382 if (c & ATA_STAT_BUSY) {
1383 printf ("IDE read: device %d not ready\n", device);
1384 goto WR_OUT;
1385 }
wdenkc35ba4e2004-03-14 22:25:36 +00001386#ifdef CONFIG_LBA48
wdenkf602aa02004-03-13 23:29:43 +00001387 if (lba48) {
1388 /* write high bits */
1389 ide_outb (device, ATA_SECT_CNT, 0);
1390 ide_outb (device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
1391 ide_outb (device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
1392 ide_outb (device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
1393 }
1394#endif
wdenk591dda52002-11-18 00:14:45 +00001395 ide_outb (device, ATA_SECT_CNT, 1);
1396 ide_outb (device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
1397 ide_outb (device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
1398 ide_outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
wdenkf602aa02004-03-13 23:29:43 +00001399
wdenkc35ba4e2004-03-14 22:25:36 +00001400#ifdef CONFIG_LBA48
wdenkf602aa02004-03-13 23:29:43 +00001401 if (lba48) {
1402 ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device) );
1403 ide_outb (device, ATA_COMMAND, ATA_CMD_WRITE_EXT);
1404
1405 } else
1406#endif
1407 {
1408 ide_outb (device, ATA_DEV_HD, ATA_LBA |
1409 ATA_DEVICE(device) |
1410 ((blknr >> 24) & 0xF) );
1411 ide_outb (device, ATA_COMMAND, ATA_CMD_WRITE);
1412 }
wdenkc6097192002-11-03 00:24:07 +00001413
1414 udelay (50);
1415
1416 c = ide_wait (device, IDE_TIME_OUT); /* can't take over 500 ms */
1417
1418 if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) {
wdenkc35ba4e2004-03-14 22:25:36 +00001419#if defined(CFG_64BIT_LBA) && defined(CFG_64BIT_VSPRINTF)
wdenkf602aa02004-03-13 23:29:43 +00001420 printf ("Error (no IRQ) dev %d blk %qd: status 0x%02x\n",
wdenkc6097192002-11-03 00:24:07 +00001421 device, blknr, c);
wdenkf602aa02004-03-13 23:29:43 +00001422#else
1423 printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n",
1424 device, (ulong)blknr, c);
1425#endif
wdenkc6097192002-11-03 00:24:07 +00001426 goto WR_OUT;
1427 }
1428
1429 output_data (device, buffer, ATA_SECTORWORDS);
wdenk591dda52002-11-18 00:14:45 +00001430 c = ide_inb (device, ATA_STATUS); /* clear IRQ */
wdenkc6097192002-11-03 00:24:07 +00001431 ++n;
1432 ++blknr;
Greg Lopp50abf9f2007-04-13 08:02:24 +02001433 buffer += ATA_BLOCKSIZE;
wdenkc6097192002-11-03 00:24:07 +00001434 }
1435WR_OUT:
1436 ide_led (DEVICE_LED(device), 0); /* LED off */
1437 return (n);
1438}
1439
1440/* ------------------------------------------------------------------------- */
1441
1442/*
1443 * copy src to dest, skipping leading and trailing blanks and null
1444 * terminate the string
wdenk18bd81e2004-03-17 01:13:07 +00001445 * "len" is the size of available memory including the terminating '\0'
wdenkc6097192002-11-03 00:24:07 +00001446 */
wdenk18bd81e2004-03-17 01:13:07 +00001447static void ident_cpy (unsigned char *dst, unsigned char *src, unsigned int len)
wdenkc6097192002-11-03 00:24:07 +00001448{
wdenk18bd81e2004-03-17 01:13:07 +00001449 unsigned char *end, *last;
wdenkc6097192002-11-03 00:24:07 +00001450
wdenk18bd81e2004-03-17 01:13:07 +00001451 last = dst;
wdenkeec9a3d2004-03-23 23:20:24 +00001452 end = src + len - 1;
wdenk18bd81e2004-03-17 01:13:07 +00001453
1454 /* reserve space for '\0' */
1455 if (len < 2)
1456 goto OUT;
wdenkc12081a2004-03-23 20:18:25 +00001457
wdenk18bd81e2004-03-17 01:13:07 +00001458 /* skip leading white space */
1459 while ((*src) && (src<end) && (*src==' '))
1460 ++src;
1461
1462 /* copy string, omitting trailing white space */
1463 while ((*src) && (src<end)) {
1464 *dst++ = *src;
1465 if (*src++ != ' ')
1466 last = dst;
wdenkc6097192002-11-03 00:24:07 +00001467 }
wdenk18bd81e2004-03-17 01:13:07 +00001468OUT:
1469 *last = '\0';
wdenkc6097192002-11-03 00:24:07 +00001470}
1471
1472/* ------------------------------------------------------------------------- */
1473
1474/*
1475 * Wait until Busy bit is off, or timeout (in ms)
1476 * Return last status
1477 */
1478static uchar ide_wait (int dev, ulong t)
1479{
1480 ulong delay = 10 * t; /* poll every 100 us */
1481 uchar c;
1482
wdenk591dda52002-11-18 00:14:45 +00001483 while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
wdenkc6097192002-11-03 00:24:07 +00001484 udelay (100);
1485 if (delay-- == 0) {
1486 break;
1487 }
1488 }
1489 return (c);
1490}
1491
1492/* ------------------------------------------------------------------------- */
1493
1494#ifdef CONFIG_IDE_RESET
1495extern void ide_set_reset(int idereset);
1496
1497static void ide_reset (void)
1498{
1499#if defined(CFG_PB_12V_ENABLE) || defined(CFG_PB_IDE_MOTOR)
1500 volatile immap_t *immr = (immap_t *)CFG_IMMR;
1501#endif
1502 int i;
1503
1504 curr_device = -1;
1505 for (i=0; i<CFG_IDE_MAXBUS; ++i)
1506 ide_bus_ok[i] = 0;
1507 for (i=0; i<CFG_IDE_MAXDEVICE; ++i)
1508 ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
1509
1510 ide_set_reset (1); /* assert reset */
1511
1512 WATCHDOG_RESET();
1513
1514#ifdef CFG_PB_12V_ENABLE
1515 immr->im_cpm.cp_pbdat &= ~(CFG_PB_12V_ENABLE); /* 12V Enable output OFF */
1516 immr->im_cpm.cp_pbpar &= ~(CFG_PB_12V_ENABLE);
1517 immr->im_cpm.cp_pbodr &= ~(CFG_PB_12V_ENABLE);
1518 immr->im_cpm.cp_pbdir |= CFG_PB_12V_ENABLE;
1519
1520 /* wait 500 ms for the voltage to stabilize
1521 */
1522 for (i=0; i<500; ++i) {
1523 udelay (1000);
1524 }
1525
1526 immr->im_cpm.cp_pbdat |= CFG_PB_12V_ENABLE; /* 12V Enable output ON */
1527#endif /* CFG_PB_12V_ENABLE */
1528
1529#ifdef CFG_PB_IDE_MOTOR
1530 /* configure IDE Motor voltage monitor pin as input */
1531 immr->im_cpm.cp_pbpar &= ~(CFG_PB_IDE_MOTOR);
1532 immr->im_cpm.cp_pbodr &= ~(CFG_PB_IDE_MOTOR);
1533 immr->im_cpm.cp_pbdir &= ~(CFG_PB_IDE_MOTOR);
1534
1535 /* wait up to 1 s for the motor voltage to stabilize
1536 */
1537 for (i=0; i<1000; ++i) {
1538 if ((immr->im_cpm.cp_pbdat & CFG_PB_IDE_MOTOR) != 0) {
1539 break;
1540 }
1541 udelay (1000);
1542 }
1543
1544 if (i == 1000) { /* Timeout */
1545 printf ("\nWarning: 5V for IDE Motor missing\n");
1546# ifdef CONFIG_STATUS_LED
1547# ifdef STATUS_LED_YELLOW
1548 status_led_set (STATUS_LED_YELLOW, STATUS_LED_ON );
1549# endif
1550# ifdef STATUS_LED_GREEN
1551 status_led_set (STATUS_LED_GREEN, STATUS_LED_OFF);
1552# endif
1553# endif /* CONFIG_STATUS_LED */
1554 }
1555#endif /* CFG_PB_IDE_MOTOR */
1556
1557 WATCHDOG_RESET();
1558
1559 /* de-assert RESET signal */
1560 ide_set_reset(0);
1561
1562 /* wait 250 ms */
1563 for (i=0; i<250; ++i) {
1564 udelay (1000);
1565 }
1566}
1567
1568#endif /* CONFIG_IDE_RESET */
1569
1570/* ------------------------------------------------------------------------- */
1571
wdenk54070ab2004-12-31 09:32:47 +00001572#if defined(CONFIG_IDE_LED) && \
1573 !defined(CONFIG_AMIGAONEG3SE)&& \
1574 !defined(CONFIG_CPC45) && \
1575 !defined(CONFIG_HMI10) && \
1576 !defined(CONFIG_KUP4K) && \
1577 !defined(CONFIG_KUP4X)
wdenkc6097192002-11-03 00:24:07 +00001578
1579static uchar led_buffer = 0; /* Buffer for current LED status */
1580
1581static void ide_led (uchar led, uchar status)
1582{
1583 uchar *led_port = LED_PORT;
1584
1585 if (status) { /* switch LED on */
1586 led_buffer |= led;
1587 } else { /* switch LED off */
1588 led_buffer &= ~led;
1589 }
1590
1591 *led_port = led_buffer;
1592}
1593
1594#endif /* CONFIG_IDE_LED */
1595
1596/* ------------------------------------------------------------------------- */
1597
1598#ifdef CONFIG_ATAPI
1599/****************************************************************************
1600 * ATAPI Support
1601 */
1602
wdenk634d2f72004-04-15 23:14:49 +00001603#if defined(__PPC__) || defined(CONFIG_PXA_PCMCIA)
wdenkc6097192002-11-03 00:24:07 +00001604/* since ATAPI may use commands with not 4 bytes alligned length
1605 * we have our own transfer functions, 2 bytes alligned */
1606static void
1607output_data_shorts(int dev, ushort *sect_buf, int shorts)
1608{
wdenkf1276d42005-02-03 23:00:49 +00001609#if defined(CONFIG_HMI10) || defined(CONFIG_CPC45)
wdenk2f99a692004-01-04 22:51:12 +00001610 uchar *dbuf;
1611 volatile uchar *pbuf_even;
1612 volatile uchar *pbuf_odd;
1613
1614 pbuf_even = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_EVEN);
1615 pbuf_odd = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_ODD);
1616 while (shorts--) {
wdenk20c98a62004-04-23 20:32:05 +00001617 EIEIO;
wdenk2f99a692004-01-04 22:51:12 +00001618 *pbuf_even = *dbuf++;
wdenk20c98a62004-04-23 20:32:05 +00001619 EIEIO;
wdenk2f99a692004-01-04 22:51:12 +00001620 *pbuf_odd = *dbuf++;
1621 }
wdenkf1276d42005-02-03 23:00:49 +00001622#else
wdenkc6097192002-11-03 00:24:07 +00001623 ushort *dbuf;
1624 volatile ushort *pbuf;
1625
1626 pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
1627 dbuf = (ushort *)sect_buf;
wdenk634d2f72004-04-15 23:14:49 +00001628
wdenkf1276d42005-02-03 23:00:49 +00001629 debug ("in output data shorts base for read is %lx\n", (unsigned long) pbuf);
wdenk634d2f72004-04-15 23:14:49 +00001630
wdenkc6097192002-11-03 00:24:07 +00001631 while (shorts--) {
wdenk20c98a62004-04-23 20:32:05 +00001632 EIEIO;
wdenkf1276d42005-02-03 23:00:49 +00001633 *pbuf = *dbuf++;
wdenkc6097192002-11-03 00:24:07 +00001634 }
wdenkf1276d42005-02-03 23:00:49 +00001635#endif
1636}
1637
1638static void
1639input_data_shorts(int dev, ushort *sect_buf, int shorts)
1640{
1641#if defined(CONFIG_HMI10) || defined(CONFIG_CPC45)
wdenk2f99a692004-01-04 22:51:12 +00001642 uchar *dbuf;
1643 volatile uchar *pbuf_even;
1644 volatile uchar *pbuf_odd;
1645
1646 pbuf_even = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_EVEN);
1647 pbuf_odd = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_ODD);
1648 while (shorts--) {
wdenk20c98a62004-04-23 20:32:05 +00001649 EIEIO;
wdenk2f99a692004-01-04 22:51:12 +00001650 *dbuf++ = *pbuf_even;
wdenk20c98a62004-04-23 20:32:05 +00001651 EIEIO;
wdenk2f99a692004-01-04 22:51:12 +00001652 *dbuf++ = *pbuf_odd;
1653 }
wdenkf1276d42005-02-03 23:00:49 +00001654#else
1655 ushort *dbuf;
1656 volatile ushort *pbuf;
1657
1658 pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
1659 dbuf = (ushort *)sect_buf;
1660
1661 debug("in input data shorts base for read is %lx\n", (unsigned long) pbuf);
1662
1663 while (shorts--) {
1664 EIEIO;
1665 *dbuf++ = *pbuf;
1666 }
1667#endif
wdenkc6097192002-11-03 00:24:07 +00001668}
1669
wdenk591dda52002-11-18 00:14:45 +00001670#else /* ! __PPC__ */
1671static void
1672output_data_shorts(int dev, ushort *sect_buf, int shorts)
1673{
wdenk9f837932003-10-09 19:00:25 +00001674 outsw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, shorts);
wdenk591dda52002-11-18 00:14:45 +00001675}
1676
wdenk591dda52002-11-18 00:14:45 +00001677static void
1678input_data_shorts(int dev, ushort *sect_buf, int shorts)
1679{
wdenk9f837932003-10-09 19:00:25 +00001680 insw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, shorts);
wdenk591dda52002-11-18 00:14:45 +00001681}
1682
1683#endif /* __PPC__ */
1684
wdenkc6097192002-11-03 00:24:07 +00001685/*
1686 * Wait until (Status & mask) == res, or timeout (in ms)
1687 * Return last status
1688 * This is used since some ATAPI CD ROMs clears their Busy Bit first
1689 * and then they set their DRQ Bit
1690 */
1691static uchar atapi_wait_mask (int dev, ulong t,uchar mask, uchar res)
1692{
1693 ulong delay = 10 * t; /* poll every 100 us */
1694 uchar c;
1695
wdenk591dda52002-11-18 00:14:45 +00001696 c = ide_inb(dev,ATA_DEV_CTL); /* prevents to read the status before valid */
1697 while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) {
wdenkc6097192002-11-03 00:24:07 +00001698 /* break if error occurs (doesn't make sense to wait more) */
1699 if((c & ATA_STAT_ERR)==ATA_STAT_ERR)
1700 break;
1701 udelay (100);
1702 if (delay-- == 0) {
1703 break;
1704 }
1705 }
1706 return (c);
1707}
1708
1709/*
1710 * issue an atapi command
1711 */
1712unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned char * buffer,int buflen)
1713{
1714 unsigned char c,err,mask,res;
1715 int n;
1716 ide_led (DEVICE_LED(device), 1); /* LED on */
1717
1718 /* Select device
1719 */
1720 mask = ATA_STAT_BUSY|ATA_STAT_DRQ;
1721 res = 0;
wdenk452cfd62002-11-19 11:04:11 +00001722#ifdef CONFIG_AMIGAONEG3SE
1723# warning THF: Removed LBA mode ???
1724#endif
wdenk591dda52002-11-18 00:14:45 +00001725 ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
wdenkc6097192002-11-03 00:24:07 +00001726 c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
1727 if ((c & mask) != res) {
1728 printf ("ATAPI_ISSUE: device %d not ready status %X\n", device,c);
1729 err=0xFF;
1730 goto AI_OUT;
1731 }
1732 /* write taskfile */
wdenk591dda52002-11-18 00:14:45 +00001733 ide_outb (device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */
wdenk452cfd62002-11-19 11:04:11 +00001734 ide_outb (device, ATA_SECT_CNT, 0);
1735 ide_outb (device, ATA_SECT_NUM, 0);
wdenk591dda52002-11-18 00:14:45 +00001736 ide_outb (device, ATA_CYL_LOW, (unsigned char)(buflen & 0xFF));
wdenk452cfd62002-11-19 11:04:11 +00001737 ide_outb (device, ATA_CYL_HIGH, (unsigned char)((buflen>>8) & 0xFF));
1738#ifdef CONFIG_AMIGAONEG3SE
1739# warning THF: Removed LBA mode ???
1740#endif
wdenk591dda52002-11-18 00:14:45 +00001741 ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
wdenkc6097192002-11-03 00:24:07 +00001742
wdenk591dda52002-11-18 00:14:45 +00001743 ide_outb (device, ATA_COMMAND, ATAPI_CMD_PACKET);
wdenkc6097192002-11-03 00:24:07 +00001744 udelay (50);
1745
1746 mask = ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR;
1747 res = ATA_STAT_DRQ;
1748 c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
1749
1750 if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */
1751 printf ("ATTAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n",device,c);
1752 err=0xFF;
1753 goto AI_OUT;
1754 }
1755
1756 output_data_shorts (device, (unsigned short *)ccb,ccblen/2); /* write command block */
1757 /* ATAPI Command written wait for completition */
1758 udelay (5000); /* device must set bsy */
1759
1760 mask = ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR;
1761 /* if no data wait for DRQ = 0 BSY = 0
1762 * if data wait for DRQ = 1 BSY = 0 */
1763 res=0;
1764 if(buflen)
1765 res = ATA_STAT_DRQ;
1766 c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
1767 if ((c & mask) != res ) {
1768 if (c & ATA_STAT_ERR) {
wdenk591dda52002-11-18 00:14:45 +00001769 err=(ide_inb(device,ATA_ERROR_REG))>>4;
wdenkf1276d42005-02-03 23:00:49 +00001770 debug ("atapi_issue 1 returned sense key %X status %02X\n",err,c);
wdenkc6097192002-11-03 00:24:07 +00001771 } else {
1772 printf ("ATTAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", ccb[0],c);
1773 err=0xFF;
1774 }
1775 goto AI_OUT;
1776 }
wdenk591dda52002-11-18 00:14:45 +00001777 n=ide_inb(device, ATA_CYL_HIGH);
wdenkc6097192002-11-03 00:24:07 +00001778 n<<=8;
wdenk591dda52002-11-18 00:14:45 +00001779 n+=ide_inb(device, ATA_CYL_LOW);
wdenkc6097192002-11-03 00:24:07 +00001780 if(n>buflen) {
1781 printf("ERROR, transfer bytes %d requested only %d\n",n,buflen);
1782 err=0xff;
1783 goto AI_OUT;
1784 }
1785 if((n==0)&&(buflen<0)) {
1786 printf("ERROR, transfer bytes %d requested %d\n",n,buflen);
1787 err=0xff;
1788 goto AI_OUT;
1789 }
1790 if(n!=buflen) {
wdenkf1276d42005-02-03 23:00:49 +00001791 debug ("WARNING, transfer bytes %d not equal with requested %d\n",n,buflen);
wdenkc6097192002-11-03 00:24:07 +00001792 }
1793 if(n!=0) { /* data transfer */
wdenkf1276d42005-02-03 23:00:49 +00001794 debug ("ATAPI_ISSUE: %d Bytes to transfer\n",n);
wdenkc6097192002-11-03 00:24:07 +00001795 /* we transfer shorts */
1796 n>>=1;
1797 /* ok now decide if it is an in or output */
wdenk591dda52002-11-18 00:14:45 +00001798 if ((ide_inb(device, ATA_SECT_CNT)&0x02)==0) {
wdenkf1276d42005-02-03 23:00:49 +00001799 debug ("Write to device\n");
wdenkc6097192002-11-03 00:24:07 +00001800 output_data_shorts(device,(unsigned short *)buffer,n);
1801 } else {
wdenkf1276d42005-02-03 23:00:49 +00001802 debug ("Read from device @ %p shorts %d\n",buffer,n);
wdenkc6097192002-11-03 00:24:07 +00001803 input_data_shorts(device,(unsigned short *)buffer,n);
1804 }
1805 }
1806 udelay(5000); /* seems that some CD ROMs need this... */
1807 mask = ATA_STAT_BUSY|ATA_STAT_ERR;
1808 res=0;
1809 c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
1810 if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
wdenk591dda52002-11-18 00:14:45 +00001811 err=(ide_inb(device,ATA_ERROR_REG) >> 4);
wdenkf1276d42005-02-03 23:00:49 +00001812 debug ("atapi_issue 2 returned sense key %X status %X\n",err,c);
wdenkc6097192002-11-03 00:24:07 +00001813 } else {
1814 err = 0;
1815 }
1816AI_OUT:
1817 ide_led (DEVICE_LED(device), 0); /* LED off */
1818 return (err);
1819}
1820
1821/*
1822 * sending the command to atapi_issue. If an status other than good
1823 * returns, an request_sense will be issued
1824 */
1825
1826#define ATAPI_DRIVE_NOT_READY 100
1827#define ATAPI_UNIT_ATTN 10
1828
1829unsigned char atapi_issue_autoreq (int device,
1830 unsigned char* ccb,
1831 int ccblen,
1832 unsigned char *buffer,
1833 int buflen)
1834{
1835 unsigned char sense_data[18],sense_ccb[12];
1836 unsigned char res,key,asc,ascq;
1837 int notready,unitattn;
1838
wdenk452cfd62002-11-19 11:04:11 +00001839#ifdef CONFIG_AMIGAONEG3SE
1840 char *s;
1841 unsigned int timeout, retrycnt;
1842
1843 s = getenv("ide_cd_timeout");
1844 timeout = s ? (simple_strtol(s, NULL, 10)*1000000)/5 : 0;
1845
1846 retrycnt = 0;
1847#endif
1848
wdenkc6097192002-11-03 00:24:07 +00001849 unitattn=ATAPI_UNIT_ATTN;
1850 notready=ATAPI_DRIVE_NOT_READY;
1851
1852retry:
1853 res= atapi_issue(device,ccb,ccblen,buffer,buflen);
1854 if (res==0)
1855 return (0); /* Ok */
1856
1857 if (res==0xFF)
1858 return (0xFF); /* error */
1859
wdenkf1276d42005-02-03 23:00:49 +00001860 debug ("(auto_req)atapi_issue returned sense key %X\n",res);
wdenkc6097192002-11-03 00:24:07 +00001861
1862 memset(sense_ccb,0,sizeof(sense_ccb));
1863 memset(sense_data,0,sizeof(sense_data));
1864 sense_ccb[0]=ATAPI_CMD_REQ_SENSE;
wdenk452cfd62002-11-19 11:04:11 +00001865 sense_ccb[4]=18; /* allocation Length */
wdenkc6097192002-11-03 00:24:07 +00001866
1867 res=atapi_issue(device,sense_ccb,12,sense_data,18);
1868 key=(sense_data[2]&0xF);
1869 asc=(sense_data[12]);
1870 ascq=(sense_data[13]);
1871
wdenkf1276d42005-02-03 23:00:49 +00001872 debug ("ATAPI_CMD_REQ_SENSE returned %x\n",res);
1873 debug (" Sense page: %02X key %02X ASC %02X ASCQ %02X\n",
wdenkc6097192002-11-03 00:24:07 +00001874 sense_data[0],
1875 key,
1876 asc,
1877 ascq);
1878
1879 if((key==0))
1880 return 0; /* ok device ready */
1881
1882 if((key==6)|| (asc==0x29) || (asc==0x28)) { /* Unit Attention */
1883 if(unitattn-->0) {
1884 udelay(200*1000);
1885 goto retry;
1886 }
1887 printf("Unit Attention, tried %d\n",ATAPI_UNIT_ATTN);
1888 goto error;
1889 }
1890 if((asc==0x4) && (ascq==0x1)) { /* not ready, but will be ready soon */
1891 if (notready-->0) {
1892 udelay(200*1000);
1893 goto retry;
1894 }
1895 printf("Drive not ready, tried %d times\n",ATAPI_DRIVE_NOT_READY);
1896 goto error;
1897 }
1898 if(asc==0x3a) {
wdenkf1276d42005-02-03 23:00:49 +00001899 debug ("Media not present\n");
wdenkc6097192002-11-03 00:24:07 +00001900 goto error;
1901 }
wdenk452cfd62002-11-19 11:04:11 +00001902
1903#ifdef CONFIG_AMIGAONEG3SE
1904 if ((sense_data[2]&0xF)==0x0B) {
wdenkf1276d42005-02-03 23:00:49 +00001905 debug ("ABORTED COMMAND...retry\n");
wdenk452cfd62002-11-19 11:04:11 +00001906 if (retrycnt++ < 4)
1907 goto retry;
1908 return (0xFF);
1909 }
1910
1911 if ((sense_data[2]&0xf) == 0x02 &&
1912 sense_data[12] == 0x04 &&
1913 sense_data[13] == 0x01 ) {
wdenkf1276d42005-02-03 23:00:49 +00001914 debug ("Waiting for unit to become active\n");
wdenk452cfd62002-11-19 11:04:11 +00001915 udelay(timeout);
1916 if (retrycnt++ < 4)
1917 goto retry;
1918 return 0xFF;
1919 }
1920#endif /* CONFIG_AMIGAONEG3SE */
1921
wdenkc6097192002-11-03 00:24:07 +00001922 printf ("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n",key,asc,ascq);
1923error:
wdenkf1276d42005-02-03 23:00:49 +00001924 debug ("ERROR Sense key %02X ASC %02X ASCQ %02X\n",key,asc,ascq);
wdenkc6097192002-11-03 00:24:07 +00001925 return (0xFF);
1926}
1927
1928
wdenkc6097192002-11-03 00:24:07 +00001929static void atapi_inquiry(block_dev_desc_t * dev_desc)
1930{
1931 unsigned char ccb[12]; /* Command descriptor block */
1932 unsigned char iobuf[64]; /* temp buf */
1933 unsigned char c;
1934 int device;
1935
1936 device=dev_desc->dev;
1937 dev_desc->type=DEV_TYPE_UNKNOWN; /* not yet valid */
1938 dev_desc->block_read=atapi_read;
1939
1940 memset(ccb,0,sizeof(ccb));
1941 memset(iobuf,0,sizeof(iobuf));
1942
1943 ccb[0]=ATAPI_CMD_INQUIRY;
1944 ccb[4]=40; /* allocation Legnth */
1945 c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,40);
1946
wdenkf1276d42005-02-03 23:00:49 +00001947 debug ("ATAPI_CMD_INQUIRY returned %x\n",c);
wdenkc6097192002-11-03 00:24:07 +00001948 if (c!=0)
1949 return;
1950
1951 /* copy device ident strings */
Jean-Christophe PLAGNIOL-VILLARD1fa3e362007-11-07 08:19:19 +01001952 ident_cpy((unsigned char*)dev_desc->vendor,&iobuf[8],8);
1953 ident_cpy((unsigned char*)dev_desc->product,&iobuf[16],16);
1954 ident_cpy((unsigned char*)dev_desc->revision,&iobuf[32],5);
wdenkc6097192002-11-03 00:24:07 +00001955
1956 dev_desc->lun=0;
1957 dev_desc->lba=0;
1958 dev_desc->blksz=0;
1959 dev_desc->type=iobuf[0] & 0x1f;
1960
1961 if ((iobuf[1]&0x80)==0x80)
1962 dev_desc->removable = 1;
1963 else
1964 dev_desc->removable = 0;
1965
1966 memset(ccb,0,sizeof(ccb));
1967 memset(iobuf,0,sizeof(iobuf));
1968 ccb[0]=ATAPI_CMD_START_STOP;
1969 ccb[4]=0x03; /* start */
1970
1971 c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,0);
1972
wdenkf1276d42005-02-03 23:00:49 +00001973 debug ("ATAPI_CMD_START_STOP returned %x\n",c);
wdenkc6097192002-11-03 00:24:07 +00001974 if (c!=0)
1975 return;
1976
1977 memset(ccb,0,sizeof(ccb));
1978 memset(iobuf,0,sizeof(iobuf));
1979 c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,0);
1980
wdenkf1276d42005-02-03 23:00:49 +00001981 debug ("ATAPI_CMD_UNIT_TEST_READY returned %x\n",c);
wdenkc6097192002-11-03 00:24:07 +00001982 if (c!=0)
1983 return;
1984
1985 memset(ccb,0,sizeof(ccb));
1986 memset(iobuf,0,sizeof(iobuf));
1987 ccb[0]=ATAPI_CMD_READ_CAP;
1988 c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,8);
wdenkf1276d42005-02-03 23:00:49 +00001989 debug ("ATAPI_CMD_READ_CAP returned %x\n",c);
wdenkc6097192002-11-03 00:24:07 +00001990 if (c!=0)
1991 return;
1992
wdenkf1276d42005-02-03 23:00:49 +00001993 debug ("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n",
wdenkc6097192002-11-03 00:24:07 +00001994 iobuf[0],iobuf[1],iobuf[2],iobuf[3],
1995 iobuf[4],iobuf[5],iobuf[6],iobuf[7]);
1996
1997 dev_desc->lba =((unsigned long)iobuf[0]<<24) +
1998 ((unsigned long)iobuf[1]<<16) +
1999 ((unsigned long)iobuf[2]<< 8) +
2000 ((unsigned long)iobuf[3]);
2001 dev_desc->blksz=((unsigned long)iobuf[4]<<24) +
2002 ((unsigned long)iobuf[5]<<16) +
2003 ((unsigned long)iobuf[6]<< 8) +
2004 ((unsigned long)iobuf[7]);
wdenkc35ba4e2004-03-14 22:25:36 +00002005#ifdef CONFIG_LBA48
wdenkf602aa02004-03-13 23:29:43 +00002006 dev_desc->lba48 = 0; /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */
wdenkc35ba4e2004-03-14 22:25:36 +00002007#endif
wdenkc6097192002-11-03 00:24:07 +00002008 return;
2009}
2010
2011
2012/*
2013 * atapi_read:
2014 * we transfer only one block per command, since the multiple DRQ per
2015 * command is not yet implemented
2016 */
2017#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */
2018#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */
2019#define ATAPI_READ_MAX_BLOCK ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE /* max blocks */
2020
Grant Likely2089cab2007-02-20 09:05:45 +01002021ulong atapi_read (int device, lbaint_t blknr, ulong blkcnt, void *buffer)
wdenkc6097192002-11-03 00:24:07 +00002022{
2023 ulong n = 0;
2024 unsigned char ccb[12]; /* Command descriptor block */
2025 ulong cnt;
2026
wdenkf1276d42005-02-03 23:00:49 +00002027 debug ("atapi_read dev %d start %lX, blocks %lX buffer at %lX\n",
wdenkc6097192002-11-03 00:24:07 +00002028 device, blknr, blkcnt, (ulong)buffer);
2029
2030 do {
2031 if (blkcnt>ATAPI_READ_MAX_BLOCK) {
2032 cnt=ATAPI_READ_MAX_BLOCK;
2033 } else {
2034 cnt=blkcnt;
2035 }
2036 ccb[0]=ATAPI_CMD_READ_12;
2037 ccb[1]=0; /* reserved */
2038 ccb[2]=(unsigned char) (blknr>>24) & 0xFF; /* MSB Block */
2039 ccb[3]=(unsigned char) (blknr>>16) & 0xFF; /* */
2040 ccb[4]=(unsigned char) (blknr>> 8) & 0xFF;
2041 ccb[5]=(unsigned char) blknr & 0xFF; /* LSB Block */
2042 ccb[6]=(unsigned char) (cnt >>24) & 0xFF; /* MSB Block count */
2043 ccb[7]=(unsigned char) (cnt >>16) & 0xFF;
2044 ccb[8]=(unsigned char) (cnt >> 8) & 0xFF;
2045 ccb[9]=(unsigned char) cnt & 0xFF; /* LSB Block */
2046 ccb[10]=0; /* reserved */
2047 ccb[11]=0; /* reserved */
2048
2049 if (atapi_issue_autoreq(device,ccb,12,
2050 (unsigned char *)buffer,
2051 cnt*ATAPI_READ_BLOCK_SIZE) == 0xFF) {
2052 return (n);
2053 }
2054 n+=cnt;
2055 blkcnt-=cnt;
2056 blknr+=cnt;
Greg Lopp50abf9f2007-04-13 08:02:24 +02002057 buffer+=(cnt*ATAPI_READ_BLOCK_SIZE);
wdenkc6097192002-11-03 00:24:07 +00002058 } while (blkcnt > 0);
2059 return (n);
2060}
2061
2062/* ------------------------------------------------------------------------- */
2063
2064#endif /* CONFIG_ATAPI */
2065
wdenkf287a242003-07-01 21:06:45 +00002066U_BOOT_CMD(
2067 ide, 5, 1, do_ide,
wdenk57b2d802003-06-27 21:31:46 +00002068 "ide - IDE sub-system\n",
2069 "reset - reset IDE controller\n"
2070 "ide info - show available IDE devices\n"
2071 "ide device [dev] - show or set current device\n"
2072 "ide part [dev] - print partition table of one or all IDE devices\n"
2073 "ide read addr blk# cnt\n"
2074 "ide write addr blk# cnt - read/write `cnt'"
2075 " blocks starting at block `blk#'\n"
2076 " to/from memory address `addr'\n"
2077);
2078
wdenkf287a242003-07-01 21:06:45 +00002079U_BOOT_CMD(
2080 diskboot, 3, 1, do_diskboot,
wdenk57b2d802003-06-27 21:31:46 +00002081 "diskboot- boot from IDE device\n",
2082 "loadAddr dev:part\n"
2083);
2084
Jon Loeligerd76b5c12007-07-08 18:02:23 -05002085#endif