cmd_ide.c 38.9 KB
Newer Older
W
wdenk 已提交
1
/*
2
 * (C) Copyright 2000-2011
W
wdenk 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 *
 */

/*
 * IDE support
 */
28

W
wdenk 已提交
29 30 31 32 33 34
#include <common.h>
#include <config.h>
#include <watchdog.h>
#include <command.h>
#include <image.h>
#include <asm/byteorder.h>
35
#include <asm/io.h>
36

W
wdenk 已提交
37 38 39
#if defined(CONFIG_IDE_8xx_DIRECT) || defined(CONFIG_IDE_PCMCIA)
# include <pcmcia.h>
#endif
40

W
wdenk 已提交
41 42
#include <ide.h>
#include <ata.h>
43

W
wdenk 已提交
44 45 46
#ifdef CONFIG_STATUS_LED
# include <status_led.h>
#endif
47

48 49
#ifdef __PPC__
# define EIEIO		__asm__ volatile ("eieio")
50
# define SYNC		__asm__ volatile ("sync")
51 52
#else
# define EIEIO		/* nothing */
53
# define SYNC		/* nothing */
W
wdenk 已提交
54 55 56 57 58 59 60 61
#endif

/* ------------------------------------------------------------------------- */

/* Current I/O Device	*/
static int curr_device = -1;

/* Current offset for IDE0 / IDE1 bus access	*/
62 63 64
ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = {
#if defined(CONFIG_SYS_ATA_IDE0_OFFSET)
	CONFIG_SYS_ATA_IDE0_OFFSET,
W
wdenk 已提交
65
#endif
66 67
#if defined(CONFIG_SYS_ATA_IDE1_OFFSET) && (CONFIG_SYS_IDE_MAXBUS > 1)
	CONFIG_SYS_ATA_IDE1_OFFSET,
W
wdenk 已提交
68 69 70
#endif
};

71
static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS];
W
wdenk 已提交
72

73
block_dev_desc_t ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE];
W
wdenk 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
/* ------------------------------------------------------------------------- */

#ifdef CONFIG_IDE_RESET
static void  ide_reset (void);
#else
#define ide_reset()	/* dummy */
#endif

static void  ide_ident (block_dev_desc_t *dev_desc);
static uchar ide_wait  (int dev, ulong t);

#define IDE_TIME_OUT	2000	/* 2 sec timeout */

#define ATAPI_TIME_OUT	7000	/* 7 sec timeout (5 sec seems to work...) */

#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */

static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);

93 94
#ifndef CONFIG_SYS_ATA_PORT_ADDR
#define CONFIG_SYS_ATA_PORT_ADDR(port) (port)
95
#endif
W
wdenk 已提交
96 97 98

#ifdef CONFIG_ATAPI
static void	atapi_inquiry(block_dev_desc_t *dev_desc);
99 100
static ulong atapi_read(int device, ulong blknr, lbaint_t blkcnt,
			void *buffer);
W
wdenk 已提交
101 102 103 104 105
#endif


/* ------------------------------------------------------------------------- */

106
int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
W
wdenk 已提交
107
{
108 109 110 111 112
	int rcode = 0;

	switch (argc) {
	case 0:
	case 1:
113
		return CMD_RET_USAGE;
114 115 116
	case 2:
		if (strncmp(argv[1], "res", 3) == 0) {
			puts("\nReset IDE"
W
wdenk 已提交
117
#ifdef CONFIG_IDE_8xx_DIRECT
118
			     " on PCMCIA " PCMCIA_SLOT_MSG
W
wdenk 已提交
119
#endif
120
			     ": ");
W
wdenk 已提交
121

122 123 124 125
			ide_init();
			return 0;
		} else if (strncmp(argv[1], "inf", 3) == 0) {
			int i;
W
wdenk 已提交
126

127
			putc('\n');
W
wdenk 已提交
128

129 130 131 132 133 134 135
			for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) {
				if (ide_dev_desc[i].type == DEV_TYPE_UNKNOWN)
					continue;  /* list only known devices */
				printf("IDE device %d: ", i);
				dev_print(&ide_dev_desc[i]);
			}
			return 0;
W
wdenk 已提交
136

137 138 139 140 141
		} else if (strncmp(argv[1], "dev", 3) == 0) {
			if ((curr_device < 0)
			    || (curr_device >= CONFIG_SYS_IDE_MAXDEVICE)) {
				puts("\nno IDE devices available\n");
				return 1;
W
wdenk 已提交
142
			}
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
			printf("\nIDE device %d: ", curr_device);
			dev_print(&ide_dev_desc[curr_device]);
			return 0;
		} else if (strncmp(argv[1], "part", 4) == 0) {
			int dev, ok;

			for (ok = 0, dev = 0;
			     dev < CONFIG_SYS_IDE_MAXDEVICE;
			     ++dev) {
				if (ide_dev_desc[dev].part_type !=
				    PART_TYPE_UNKNOWN) {
					++ok;
					if (dev)
						putc('\n');
					print_part(&ide_dev_desc[dev]);
				}
			}
			if (!ok) {
				puts("\nno IDE devices available\n");
				rcode++;
			}
			return rcode;
W
wdenk 已提交
165
		}
166
		return CMD_RET_USAGE;
167 168 169
	case 3:
		if (strncmp(argv[1], "dev", 3) == 0) {
			int dev = (int) simple_strtoul(argv[2], NULL, 10);
W
wdenk 已提交
170

171 172 173 174 175 176 177
			printf("\nIDE device %d: ", dev);
			if (dev >= CONFIG_SYS_IDE_MAXDEVICE) {
				puts("unknown device\n");
				return 1;
			}
			dev_print(&ide_dev_desc[dev]);
			/*ide_print (dev); */
W
wdenk 已提交
178

179 180
			if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN)
				return 1;
W
wdenk 已提交
181

182
			curr_device = dev;
W
wdenk 已提交
183

184 185 186 187 188
			puts("... is now current device\n");

			return 0;
		} else if (strncmp(argv[1], "part", 4) == 0) {
			int dev = (int) simple_strtoul(argv[2], NULL, 10);
W
wdenk 已提交
189

190
			if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) {
W
wdenk 已提交
191
				print_part(&ide_dev_desc[dev]);
192 193 194 195 196 197
			} else {
				printf("\nIDE device %d not available\n",
				       dev);
				rcode = 1;
			}
			return rcode;
W
wdenk 已提交
198 199
		}

200
		return CMD_RET_USAGE;
201 202
	default:
		/* at least 4 args */
W
wdenk 已提交
203

204 205 206 207
		if (strcmp(argv[1], "read") == 0) {
			ulong addr = simple_strtoul(argv[2], NULL, 16);
			ulong cnt = simple_strtoul(argv[4], NULL, 16);
			ulong n;
W
wdenk 已提交
208

209
#ifdef CONFIG_SYS_64BIT_LBA
210
			lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
W
wdenk 已提交
211

212 213
			printf("\nIDE read: device %d block # %lld, count %ld ... ",
				curr_device, blk, cnt);
214
#else
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
			lbaint_t blk = simple_strtoul(argv[3], NULL, 16);

			printf("\nIDE read: device %d block # %ld, count %ld ... ",
				curr_device, blk, cnt);
#endif

			n = ide_dev_desc[curr_device].block_read(curr_device,
								 blk, cnt,
								 (ulong *)addr);
			/* flush cache after read */
			flush_cache(addr,
				    cnt * ide_dev_desc[curr_device].blksz);

			printf("%ld blocks read: %s\n",
			       n, (n == cnt) ? "OK" : "ERROR");
			if (n == cnt)
				return 0;
			else
				return 1;
		} else if (strcmp(argv[1], "write") == 0) {
			ulong addr = simple_strtoul(argv[2], NULL, 16);
			ulong cnt = simple_strtoul(argv[4], NULL, 16);
			ulong n;
W
wdenk 已提交
238

239
#ifdef CONFIG_SYS_64BIT_LBA
240
			lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
W
wdenk 已提交
241

242 243
			printf("\nIDE write: device %d block # %lld, count %ld ... ",
				curr_device, blk, cnt);
244
#else
245
			lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
246

247 248
			printf("\nIDE write: device %d block # %ld, count %ld ... ",
				curr_device, blk, cnt);
249
#endif
250
			n = ide_write(curr_device, blk, cnt, (ulong *) addr);
W
wdenk 已提交
251

252 253 254 255 256 257 258
			printf("%ld blocks written: %s\n",
				n, (n == cnt) ? "OK" : "ERROR");
			if (n == cnt)
				return 0;
			else
				return 1;
		} else {
259
			return CMD_RET_USAGE;
260
		}
W
wdenk 已提交
261

262
		return rcode;
W
wdenk 已提交
263 264 265
	}
}

266
int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
W
wdenk 已提交
267
{
268
	return common_diskboot(cmdtp, "ide", argc, argv);
W
wdenk 已提交
269 270 271 272
}

/* ------------------------------------------------------------------------- */

P
Pavel Herrmann 已提交
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
void __ide_led(uchar led, uchar status)
{
#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */
	static uchar led_buffer;	/* Buffer for current LED status */

	uchar *led_port = LED_PORT;

	if (status)		/* switch LED on        */
		led_buffer |= led;
	else			/* switch LED off       */
		led_buffer &= ~led;

	*led_port = led_buffer;
#endif
}

void ide_led(uchar led, uchar status)
	__attribute__ ((weak, alias("__ide_led")));

#ifndef CONFIG_IDE_LED	/* define LED macros, they are not used anyways */
# define DEVICE_LED(x) 0
# define LED_IDE1 1
# define LED_IDE2 2
#endif

/* ------------------------------------------------------------------------- */

300
inline void __ide_outb(int dev, int port, unsigned char val)
S
Stefan Roese 已提交
301
{
302 303 304
	debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n",
	      dev, port, val,
	      (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
305 306 307 308 309 310 311 312 313 314

#if defined(CONFIG_IDE_AHB)
	if (port) {
		/* write command */
		ide_write_register(dev, port, val);
	} else {
		/* write data */
		outb(val, (ATA_CURR_BASE(dev)));
	}
#else
315
	outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
316
#endif
S
Stefan Roese 已提交
317
}
318

319 320
void ide_outb(int dev, int port, unsigned char val)
	__attribute__ ((weak, alias("__ide_outb")));
S
Stefan Roese 已提交
321

322
inline unsigned char __ide_inb(int dev, int port)
S
Stefan Roese 已提交
323 324
{
	uchar val;
325 326 327 328

#if defined(CONFIG_IDE_AHB)
	val = ide_read_register(dev, port);
#else
329
	val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
330 331
#endif

332 333 334
	debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n",
	      dev, port,
	      (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val);
S
Stefan Roese 已提交
335 336
	return val;
}
337

338
unsigned char ide_inb(int dev, int port)
339
	__attribute__ ((weak, alias("__ide_inb")));
S
Stefan Roese 已提交
340

341
#ifdef CONFIG_TUNE_PIO
342
inline int __ide_set_piomode(int pio_mode)
343 344 345
{
	return 0;
}
346 347 348

inline int ide_set_piomode(int pio_mode)
	__attribute__ ((weak, alias("__ide_set_piomode")));
349 350
#endif

351
void ide_init(void)
W
wdenk 已提交
352 353 354
{
	unsigned char c;
	int i, bus;
355

W
wdenk 已提交
356
#ifdef CONFIG_IDE_8xx_PCCARD
357 358
	extern int ide_devices_found;	/* Initialized in check_ide_device() */
#endif /* CONFIG_IDE_8xx_PCCARD */
W
wdenk 已提交
359 360 361 362

#ifdef CONFIG_IDE_PREINIT
	WATCHDOG_RESET();

363 364
	if (ide_preinit()) {
		puts("ide_preinit failed\n");
W
wdenk 已提交
365 366
		return;
	}
367
#endif /* CONFIG_IDE_PREINIT */
W
wdenk 已提交
368 369 370

	WATCHDOG_RESET();

371 372
	/*
	 * Reset the IDE just to be sure.
W
wdenk 已提交
373 374
	 * Light LED's to show
	 */
375 376 377 378
	ide_led((LED_IDE1 | LED_IDE2), 1);	/* LED's on     */

	/* ATAPI Drives seems to need a proper IDE Reset */
	ide_reset();
W
wdenk 已提交
379

P
Pavel Herrmann 已提交
380 381
#ifdef CONFIG_IDE_INIT_POSTRESET
	WATCHDOG_RESET();
W
wdenk 已提交
382

P
Pavel Herrmann 已提交
383 384 385 386 387
	if (ide_init_postreset()) {
		puts("ide_preinit_postreset failed\n");
		return;
	}
#endif /* CONFIG_IDE_INIT_POSTRESET */
W
wdenk 已提交
388 389 390 391 392

	/*
	 * Wait for IDE to get ready.
	 * According to spec, this can take up to 31 seconds!
	 */
393 394 395 396
	for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) {
		int dev =
			bus * (CONFIG_SYS_IDE_MAXDEVICE /
			       CONFIG_SYS_IDE_MAXBUS);
W
wdenk 已提交
397

398 399 400
#ifdef CONFIG_IDE_8xx_PCCARD
		/* Skip non-ide devices from probing */
		if ((ide_devices_found & (1 << bus)) == 0) {
401
			ide_led((LED_IDE1 | LED_IDE2), 0);	/* LED's off */
402 403 404
			continue;
		}
#endif
405
		printf("Bus %d: ", bus);
W
wdenk 已提交
406 407 408 409 410

		ide_bus_ok[bus] = 0;

		/* Select device
		 */
411 412 413
		udelay(100000);	/* 100 ms */
		ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
		udelay(100000);	/* 100 ms */
W
wdenk 已提交
414 415
		i = 0;
		do {
416
			udelay(10000);	/* 10 ms */
W
wdenk 已提交
417

418
			c = ide_inb(dev, ATA_STATUS);
W
wdenk 已提交
419 420
			i++;
			if (i > (ATA_RESET_TIME * 100)) {
421 422 423
				puts("** Timeout **\n");
				/* LED's off */
				ide_led((LED_IDE1 | LED_IDE2), 0);
W
wdenk 已提交
424 425
				return;
			}
426 427 428
			if ((i >= 100) && ((i % 100) == 0))
				putc('.');

W
wdenk 已提交
429 430 431
		} while (c & ATA_STAT_BUSY);

		if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
432 433 434 435 436 437
			puts("not available  ");
			debug("Status = 0x%02X ", c);
#ifndef CONFIG_ATAPI		/* ATAPI Devices do not set DRDY */
		} else if ((c & ATA_STAT_READY) == 0) {
			puts("not available  ");
			debug("Status = 0x%02X ", c);
W
wdenk 已提交
438 439
#endif
		} else {
440
			puts("OK ");
W
wdenk 已提交
441 442 443 444
			ide_bus_ok[bus] = 1;
		}
		WATCHDOG_RESET();
	}
W
wdenk 已提交
445

446
	putc('\n');
W
wdenk 已提交
447

448
	ide_led((LED_IDE1 | LED_IDE2), 0);	/* LED's off    */
W
wdenk 已提交
449 450

	curr_device = -1;
451
	for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) {
W
wdenk 已提交
452
		int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2;
453 454 455 456 457
		ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
		ide_dev_desc[i].if_type = IF_TYPE_IDE;
		ide_dev_desc[i].dev = i;
		ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
		ide_dev_desc[i].blksz = 0;
458 459
		ide_dev_desc[i].log2blksz =
			LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz));
460 461
		ide_dev_desc[i].lba = 0;
		ide_dev_desc[i].block_read = ide_read;
462
		ide_dev_desc[i].block_write = ide_write;
W
wdenk 已提交
463 464
		if (!ide_bus_ok[IDE_BUS(i)])
			continue;
465
		ide_led(led, 1);	/* LED on       */
W
wdenk 已提交
466
		ide_ident(&ide_dev_desc[i]);
467
		ide_led(led, 0);	/* LED off      */
W
wdenk 已提交
468
		dev_print(&ide_dev_desc[i]);
469

W
wdenk 已提交
470
		if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) {
471 472
			/* initialize partition type */
			init_part(&ide_dev_desc[i]);
W
wdenk 已提交
473 474 475 476 477 478 479 480 481
			if (curr_device < 0)
				curr_device = i;
		}
	}
	WATCHDOG_RESET();
}

/* ------------------------------------------------------------------------- */

482
#ifdef CONFIG_PARTITIONS
483
block_dev_desc_t *ide_get_dev(int dev)
W
wdenk 已提交
484
{
485
	return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL;
W
wdenk 已提交
486
}
487
#endif
W
wdenk 已提交
488 489 490

/* ------------------------------------------------------------------------- */

491 492 493 494 495 496 497 498 499
void ide_input_swap_data(int dev, ulong *sect_buf, int words)
	__attribute__ ((weak, alias("__ide_input_swap_data")));

void ide_input_data(int dev, ulong *sect_buf, int words)
	__attribute__ ((weak, alias("__ide_input_data")));

void ide_output_data(int dev, const ulong *sect_buf, int words)
	__attribute__ ((weak, alias("__ide_output_data")));

W
wdenk 已提交
500
/* We only need to swap data if we are running on a big endian cpu. */
501
#if defined(__LITTLE_ENDIAN)
502 503 504 505
void __ide_input_swap_data(int dev, ulong *sect_buf, int words)
{
	ide_input_data(dev, sect_buf, words);
}
W
wdenk 已提交
506
#else
507
void __ide_input_swap_data(int dev, ulong *sect_buf, int words)
W
wdenk 已提交
508
{
509 510 511
	volatile ushort *pbuf =
		(ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
	ushort *dbuf = (ushort *) sect_buf;
512

513 514
	debug("in input swap data base for read is %lx\n",
	      (unsigned long) pbuf);
515 516

	while (words--) {
W
Wolfgang Denk 已提交
517
#ifdef __MIPS__
518 519
		*dbuf++ = swab16p((u16 *) pbuf);
		*dbuf++ = swab16p((u16 *) pbuf);
W
Wolfgang Denk 已提交
520
#else
521 522
		*dbuf++ = ld_le16(pbuf);
		*dbuf++ = ld_le16(pbuf);
W
Wolfgang Denk 已提交
523
#endif /* !MIPS */
524
	}
W
wdenk 已提交
525
}
526
#endif /* __LITTLE_ENDIAN */
W
wdenk 已提交
527 528


A
Albert Aribaud 已提交
529
#if defined(CONFIG_IDE_SWAP_IO)
530
void __ide_output_data(int dev, const ulong *sect_buf, int words)
W
wdenk 已提交
531
{
532 533
	ushort *dbuf;
	volatile ushort *pbuf;
534

535 536
	pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
	dbuf = (ushort *) sect_buf;
537 538 539 540 541 542
	while (words--) {
		EIEIO;
		*pbuf = *dbuf++;
		EIEIO;
		*pbuf = *dbuf++;
	}
W
wdenk 已提交
543
}
544
#else  /* ! CONFIG_IDE_SWAP_IO */
545
void __ide_output_data(int dev, const ulong *sect_buf, int words)
W
wdenk 已提交
546
{
547 548 549
#if defined(CONFIG_IDE_AHB)
	ide_write_data(dev, sect_buf, words);
#else
550
	outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1);
551
#endif
W
wdenk 已提交
552
}
553
#endif /* CONFIG_IDE_SWAP_IO */
W
wdenk 已提交
554

A
Albert Aribaud 已提交
555
#if defined(CONFIG_IDE_SWAP_IO)
556
void __ide_input_data(int dev, ulong *sect_buf, int words)
W
wdenk 已提交
557
{
558 559
	ushort *dbuf;
	volatile ushort *pbuf;
560

561 562
	pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
	dbuf = (ushort *) sect_buf;
563 564 565 566

	debug("in input data base for read is %lx\n", (unsigned long) pbuf);

	while (words--) {
567
		EIEIO;
568
		*dbuf++ = *pbuf;
569
		EIEIO;
570
		*dbuf++ = *pbuf;
571
	}
W
wdenk 已提交
572
}
573
#else  /* ! CONFIG_IDE_SWAP_IO */
574
void __ide_input_data(int dev, ulong *sect_buf, int words)
W
wdenk 已提交
575
{
576 577 578
#if defined(CONFIG_IDE_AHB)
	ide_read_data(dev, sect_buf, words);
#else
579
	insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1);
580
#endif
W
wdenk 已提交
581 582
}

583
#endif /* CONFIG_IDE_SWAP_IO */
W
wdenk 已提交
584 585 586

/* -------------------------------------------------------------------------
 */
587
static void ide_ident(block_dev_desc_t *dev_desc)
W
wdenk 已提交
588 589
{
	unsigned char c;
590
	hd_driveid_t iop;
W
wdenk 已提交
591

592 593
#ifdef CONFIG_ATAPI
	int retries = 0;
W
wdenk 已提交
594 595
#endif

596 597 598 599
#ifdef CONFIG_TUNE_PIO
	int pio_mode;
#endif

W
wdenk 已提交
600 601 602 603 604
#if 0
	int mode, cycle_time;
#endif
	int device;

605 606 607 608
	device = dev_desc->dev;
	printf("  Device %d: ", device);

	ide_led(DEVICE_LED(device), 1);	/* LED on       */
W
wdenk 已提交
609 610
	/* Select device
	 */
611 612
	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
	dev_desc->if_type = IF_TYPE_IDE;
W
wdenk 已提交
613
#ifdef CONFIG_ATAPI
W
wdenk 已提交
614

615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
	retries = 0;

	/* Warning: This will be tricky to read */
	while (retries <= 1) {
		/* check signature */
		if ((ide_inb(device, ATA_SECT_CNT) == 0x01) &&
		    (ide_inb(device, ATA_SECT_NUM) == 0x01) &&
		    (ide_inb(device, ATA_CYL_LOW) == 0x14) &&
		    (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) {
			/* ATAPI Signature found */
			dev_desc->if_type = IF_TYPE_ATAPI;
			/*
			 * Start Ident Command
			 */
			ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT);
			/*
			 * Wait for completion - ATAPI devices need more time
			 * to become ready
			 */
			c = ide_wait(device, ATAPI_TIME_OUT);
		} else
W
wdenk 已提交
636
#endif
637
		{
638 639 640 641 642 643 644 645 646
			/*
			 * Start Ident Command
			 */
			ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT);

			/*
			 * Wait for completion
			 */
			c = ide_wait(device, IDE_TIME_OUT);
647
		}
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
		ide_led(DEVICE_LED(device), 0);	/* LED off      */

		if (((c & ATA_STAT_DRQ) == 0) ||
		    ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) {
#ifdef CONFIG_ATAPI
			{
				/*
				 * Need to soft reset the device
				 * in case it's an ATAPI...
				 */
				debug("Retrying...\n");
				ide_outb(device, ATA_DEV_HD,
					 ATA_LBA | ATA_DEVICE(device));
				udelay(100000);
				ide_outb(device, ATA_COMMAND, 0x08);
				udelay(500000);	/* 500 ms */
			}
			/*
			 * Select device
			 */
			ide_outb(device, ATA_DEV_HD,
				 ATA_LBA | ATA_DEVICE(device));
			retries++;
671
#else
672
			return;
673
#endif
674
		}
675
#ifdef CONFIG_ATAPI
676 677 678
		else
			break;
	}			/* see above - ugly to read */
679

680
	if (retries == 2)	/* Not found */
681 682
		return;
#endif
W
wdenk 已提交
683

684
	ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS);
W
wdenk 已提交
685

686 687 688 689 690 691
	ident_cpy((unsigned char *) dev_desc->revision, iop.fw_rev,
		  sizeof(dev_desc->revision));
	ident_cpy((unsigned char *) dev_desc->vendor, iop.model,
		  sizeof(dev_desc->vendor));
	ident_cpy((unsigned char *) dev_desc->product, iop.serial_no,
		  sizeof(dev_desc->product));
W
wdenk 已提交
692 693
#ifdef __LITTLE_ENDIAN
	/*
694 695
	 * firmware revision, model, and serial number have Big Endian Byte
	 * order in Word. Convert all three to little endian.
W
wdenk 已提交
696 697
	 *
	 * See CF+ and CompactFlash Specification Revision 2.0:
698
	 * 6.2.1.6: Identify Drive, Table 39 for more details
W
wdenk 已提交
699 700
	 */

701 702 703
	strswab(dev_desc->revision);
	strswab(dev_desc->vendor);
	strswab(dev_desc->product);
W
wdenk 已提交
704
#endif /* __LITTLE_ENDIAN */
W
wdenk 已提交
705

706
	if ((iop.config & 0x0080) == 0x0080)
W
wdenk 已提交
707 708 709 710
		dev_desc->removable = 1;
	else
		dev_desc->removable = 0;

711 712
#ifdef CONFIG_TUNE_PIO
	/* Mode 0 - 2 only, are directly determined by word 51. */
713
	pio_mode = iop.tPIO;
714 715
	if (pio_mode > 2) {
		printf("WARNING: Invalid PIO (word 51 = %d).\n", pio_mode);
716 717
		/* Force it to dead slow, and hope for the best... */
		pio_mode = 0;
718 719 720 721 722 723
	}

	/* Any CompactFlash Storage Card that supports PIO mode 3 or above
	 * shall set bit 1 of word 53 to one and support the fields contained
	 * in words 64 through 70.
	 */
724
	if (iop.field_valid & 0x02) {
725 726
		/*
		 * Mode 3 and above are possible.  Check in order from slow
727 728
		 * to fast, so we wind up with the highest mode allowed.
		 */
729
		if (iop.eide_pio_modes & 0x01)
730
			pio_mode = 3;
731
		if (iop.eide_pio_modes & 0x02)
732
			pio_mode = 4;
733 734
		if (ata_id_is_cfa((u16 *)&iop)) {
			if ((iop.cf_advanced_caps & 0x07) == 0x01)
735
				pio_mode = 5;
736
			if ((iop.cf_advanced_caps & 0x07) == 0x02)
737 738 739 740 741 742 743 744
				pio_mode = 6;
		}
	}

	/* System-specific, depends on bus speeds, etc. */
	ide_set_piomode(pio_mode);
#endif /* CONFIG_TUNE_PIO */

W
wdenk 已提交
745 746 747 748
#if 0
	/*
	 * Drive PIO mode autoselection
	 */
749
	mode = iop.tPIO;
W
wdenk 已提交
750

751
	printf("tPIO = 0x%02x = %d\n", mode, mode);
W
wdenk 已提交
752 753
	if (mode > 2) {		/* 2 is maximum allowed tPIO value */
		mode = 2;
754
		debug("Override tPIO -> 2\n");
W
wdenk 已提交
755
	}
756
	if (iop.field_valid & 2) {	/* drive implements ATA2? */
757
		debug("Drive implements ATA2\n");
758 759
		if (iop.capability & 8) {	/* drive supports use_iordy? */
			cycle_time = iop.eide_pio_iordy;
W
wdenk 已提交
760
		} else {
761
			cycle_time = iop.eide_pio;
W
wdenk 已提交
762
		}
763
		debug("cycle time = %d\n", cycle_time);
W
wdenk 已提交
764
		mode = 4;
765 766 767 768 769 770 771 772
		if (cycle_time > 120)
			mode = 3;	/* 120 ns for PIO mode 4 */
		if (cycle_time > 180)
			mode = 2;	/* 180 ns for PIO mode 3 */
		if (cycle_time > 240)
			mode = 1;	/* 240 ns for PIO mode 4 */
		if (cycle_time > 383)
			mode = 0;	/* 383 ns for PIO mode 4 */
W
wdenk 已提交
773
	}
774
	printf("PIO mode to use: PIO %d\n", mode);
W
wdenk 已提交
775 776 777
#endif /* 0 */

#ifdef CONFIG_ATAPI
778
	if (dev_desc->if_type == IF_TYPE_ATAPI) {
W
wdenk 已提交
779 780 781 782 783
		atapi_inquiry(dev_desc);
		return;
	}
#endif /* CONFIG_ATAPI */

W
wdenk 已提交
784
#ifdef __BIG_ENDIAN
W
wdenk 已提交
785
	/* swap shorts */
786
	dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16);
787
#else  /* ! __BIG_ENDIAN */
W
wdenk 已提交
788 789 790 791 792 793
	/*
	 * do not swap shorts on little endian
	 *
	 * See CF+ and CompactFlash Specification Revision 2.0:
	 * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details.
	 */
794
	dev_desc->lba = iop.lba_capacity;
795
#endif /* __BIG_ENDIAN */
W
wdenk 已提交
796

797
#ifdef CONFIG_LBA48
798
	if (iop.command_set_2 & 0x0400) {	/* LBA 48 support */
W
wdenk 已提交
799
		dev_desc->lba48 = 1;
800 801 802 803
		dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] |
			((unsigned long long) iop.lba48_capacity[1] << 16) |
			((unsigned long long) iop.lba48_capacity[2] << 32) |
			((unsigned long long) iop.lba48_capacity[3] << 48);
W
wdenk 已提交
804 805 806 807
	} else {
		dev_desc->lba48 = 0;
	}
#endif /* CONFIG_LBA48 */
W
wdenk 已提交
808
	/* assuming HD */
809 810
	dev_desc->type = DEV_TYPE_HARDDISK;
	dev_desc->blksz = ATA_BLOCKSIZE;
811
	dev_desc->log2blksz = LOG2(dev_desc->blksz);
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
	dev_desc->lun = 0;	/* just to fill something in... */

#if 0				/* only used to test the powersaving mode,
				 * if enabled, the drive goes after 5 sec
				 * in standby mode */
	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
	c = ide_wait(device, IDE_TIME_OUT);
	ide_outb(device, ATA_SECT_CNT, 1);
	ide_outb(device, ATA_LBA_LOW, 0);
	ide_outb(device, ATA_LBA_MID, 0);
	ide_outb(device, ATA_LBA_HIGH, 0);
	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
	ide_outb(device, ATA_COMMAND, 0xe3);
	udelay(50);
	c = ide_wait(device, IDE_TIME_OUT);	/* can't take over 500 ms */
W
wdenk 已提交
827 828 829 830 831 832
#endif
}


/* ------------------------------------------------------------------------- */

833
ulong ide_read(int device, lbaint_t blknr, lbaint_t blkcnt, void *buffer)
W
wdenk 已提交
834 835 836
{
	ulong n = 0;
	unsigned char c;
837 838
	unsigned char pwrsave = 0;	/* power save */

839
#ifdef CONFIG_LBA48
W
wdenk 已提交
840
	unsigned char lba48 = 0;
W
wdenk 已提交
841

842
	if (blknr & 0x0000fffff0000000ULL) {
W
wdenk 已提交
843 844 845 846
		/* more than 28 bits used, use 48bit mode */
		lba48 = 1;
	}
#endif
847
	debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n",
848
	      device, blknr, blkcnt, (ulong) buffer);
W
wdenk 已提交
849

850
	ide_led(DEVICE_LED(device), 1);	/* LED on       */
W
wdenk 已提交
851 852 853

	/* Select device
	 */
854 855
	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
	c = ide_wait(device, IDE_TIME_OUT);
W
wdenk 已提交
856 857

	if (c & ATA_STAT_BUSY) {
858
		printf("IDE read: device %d not ready\n", device);
W
wdenk 已提交
859 860 861 862 863
		goto IDE_READ_E;
	}

	/* first check if the drive is in Powersaving mode, if yes,
	 * increase the timeout value */
864 865
	ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR);
	udelay(50);
W
wdenk 已提交
866

867
	c = ide_wait(device, IDE_TIME_OUT);	/* can't take over 500 ms */
W
wdenk 已提交
868 869

	if (c & ATA_STAT_BUSY) {
870
		printf("IDE read: device %d not ready\n", device);
W
wdenk 已提交
871 872 873
		goto IDE_READ_E;
	}
	if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
874
		printf("No Powersaving mode %X\n", c);
W
wdenk 已提交
875
	} else {
876 877 878 879
		c = ide_inb(device, ATA_SECT_CNT);
		debug("Powersaving %02X\n", c);
		if (c == 0)
			pwrsave = 1;
W
wdenk 已提交
880 881 882 883 884
	}


	while (blkcnt-- > 0) {

885
		c = ide_wait(device, IDE_TIME_OUT);
W
wdenk 已提交
886 887

		if (c & ATA_STAT_BUSY) {
888
			printf("IDE read: device %d not ready\n", device);
W
wdenk 已提交
889 890
			break;
		}
891
#ifdef CONFIG_LBA48
W
wdenk 已提交
892 893
		if (lba48) {
			/* write high bits */
894 895
			ide_outb(device, ATA_SECT_CNT, 0);
			ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
896
#ifdef CONFIG_SYS_64BIT_LBA
897 898
			ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
			ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
899
#else
900 901
			ide_outb(device, ATA_LBA_MID, 0);
			ide_outb(device, ATA_LBA_HIGH, 0);
902
#endif
W
wdenk 已提交
903 904
		}
#endif
905 906 907 908
		ide_outb(device, ATA_SECT_CNT, 1);
		ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
		ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
		ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
W
wdenk 已提交
909

910
#ifdef CONFIG_LBA48
W
wdenk 已提交
911
		if (lba48) {
912 913 914
			ide_outb(device, ATA_DEV_HD,
				 ATA_LBA | ATA_DEVICE(device));
			ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT);
W
wdenk 已提交
915 916 917 918

		} else
#endif
		{
919 920 921
			ide_outb(device, ATA_DEV_HD, ATA_LBA |
				 ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
			ide_outb(device, ATA_COMMAND, ATA_CMD_READ);
W
wdenk 已提交
922
		}
W
wdenk 已提交
923

924
		udelay(50);
W
wdenk 已提交
925

926 927 928 929
		if (pwrsave) {
			/* may take up to 4 sec */
			c = ide_wait(device, IDE_SPIN_UP_TIME_OUT);
			pwrsave = 0;
W
wdenk 已提交
930
		} else {
931 932
			/* can't take over 500 ms */
			c = ide_wait(device, IDE_TIME_OUT);
W
wdenk 已提交
933 934
		}

935 936
		if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
		    ATA_STAT_DRQ) {
937 938
			printf("Error (no IRQ) dev %d blk " LBAF ": status "
			       "%#02x\n", device, blknr, c);
W
wdenk 已提交
939 940 941
			break;
		}

942
		ide_input_data(device, buffer, ATA_SECTORWORDS);
943
		(void) ide_inb(device, ATA_STATUS);	/* clear IRQ */
W
wdenk 已提交
944 945 946

		++n;
		++blknr;
947
		buffer += ATA_BLOCKSIZE;
W
wdenk 已提交
948 949
	}
IDE_READ_E:
950
	ide_led(DEVICE_LED(device), 0);	/* LED off      */
W
wdenk 已提交
951 952 953 954 955 956
	return (n);
}

/* ------------------------------------------------------------------------- */


957
ulong ide_write(int device, lbaint_t blknr, lbaint_t blkcnt, const void *buffer)
W
wdenk 已提交
958 959 960
{
	ulong n = 0;
	unsigned char c;
961

962
#ifdef CONFIG_LBA48
W
wdenk 已提交
963 964
	unsigned char lba48 = 0;

965
	if (blknr & 0x0000fffff0000000ULL) {
W
wdenk 已提交
966 967 968 969
		/* more than 28 bits used, use 48bit mode */
		lba48 = 1;
	}
#endif
W
wdenk 已提交
970

971
	ide_led(DEVICE_LED(device), 1);	/* LED on       */
W
wdenk 已提交
972 973 974

	/* Select device
	 */
975
	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
W
wdenk 已提交
976 977 978

	while (blkcnt-- > 0) {

979
		c = ide_wait(device, IDE_TIME_OUT);
W
wdenk 已提交
980 981

		if (c & ATA_STAT_BUSY) {
982
			printf("IDE read: device %d not ready\n", device);
W
wdenk 已提交
983 984
			goto WR_OUT;
		}
985
#ifdef CONFIG_LBA48
W
wdenk 已提交
986 987
		if (lba48) {
			/* write high bits */
988 989
			ide_outb(device, ATA_SECT_CNT, 0);
			ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
990
#ifdef CONFIG_SYS_64BIT_LBA
991 992
			ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
			ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
993
#else
994 995
			ide_outb(device, ATA_LBA_MID, 0);
			ide_outb(device, ATA_LBA_HIGH, 0);
996
#endif
W
wdenk 已提交
997 998
		}
#endif
999 1000 1001 1002
		ide_outb(device, ATA_SECT_CNT, 1);
		ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
		ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
		ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
W
wdenk 已提交
1003

1004
#ifdef CONFIG_LBA48
W
wdenk 已提交
1005
		if (lba48) {
1006 1007 1008
			ide_outb(device, ATA_DEV_HD,
				 ATA_LBA | ATA_DEVICE(device));
			ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT);
W
wdenk 已提交
1009 1010 1011 1012

		} else
#endif
		{
1013 1014 1015
			ide_outb(device, ATA_DEV_HD, ATA_LBA |
				 ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
			ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE);
W
wdenk 已提交
1016
		}
W
wdenk 已提交
1017

1018
		udelay(50);
W
wdenk 已提交
1019

1020 1021
		/* can't take over 500 ms */
		c = ide_wait(device, IDE_TIME_OUT);
W
wdenk 已提交
1022

1023 1024
		if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
		    ATA_STAT_DRQ) {
1025 1026
			printf("Error (no IRQ) dev %d blk " LBAF ": status "
				"%#02x\n", device, blknr, c);
W
wdenk 已提交
1027 1028 1029
			goto WR_OUT;
		}

1030
		ide_output_data(device, buffer, ATA_SECTORWORDS);
1031
		c = ide_inb(device, ATA_STATUS);	/* clear IRQ */
W
wdenk 已提交
1032 1033
		++n;
		++blknr;
1034
		buffer += ATA_BLOCKSIZE;
W
wdenk 已提交
1035 1036
	}
WR_OUT:
1037
	ide_led(DEVICE_LED(device), 0);	/* LED off      */
W
wdenk 已提交
1038 1039 1040 1041 1042 1043 1044 1045
	return (n);
}

/* ------------------------------------------------------------------------- */

/*
 * copy src to dest, skipping leading and trailing blanks and null
 * terminate the string
W
wdenk 已提交
1046
 * "len" is the size of available memory including the terminating '\0'
W
wdenk 已提交
1047
 */
1048 1049
static void ident_cpy(unsigned char *dst, unsigned char *src,
		      unsigned int len)
W
wdenk 已提交
1050
{
W
wdenk 已提交
1051 1052 1053
	unsigned char *end, *last;

	last = dst;
1054
	end = src + len - 1;
W
wdenk 已提交
1055 1056 1057 1058

	/* reserve space for '\0' */
	if (len < 2)
		goto OUT;
1059

W
wdenk 已提交
1060
	/* skip leading white space */
1061
	while ((*src) && (src < end) && (*src == ' '))
W
wdenk 已提交
1062 1063 1064
		++src;

	/* copy string, omitting trailing white space */
1065
	while ((*src) && (src < end)) {
W
wdenk 已提交
1066 1067 1068
		*dst++ = *src;
		if (*src++ != ' ')
			last = dst;
W
wdenk 已提交
1069
	}
W
wdenk 已提交
1070 1071
OUT:
	*last = '\0';
W
wdenk 已提交
1072 1073 1074 1075 1076 1077 1078 1079
}

/* ------------------------------------------------------------------------- */

/*
 * Wait until Busy bit is off, or timeout (in ms)
 * Return last status
 */
1080
static uchar ide_wait(int dev, ulong t)
W
wdenk 已提交
1081
{
1082
	ulong delay = 10 * t;	/* poll every 100 us */
W
wdenk 已提交
1083 1084
	uchar c;

W
wdenk 已提交
1085
	while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
1086 1087
		udelay(100);
		if (delay-- == 0)
W
wdenk 已提交
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
			break;
	}
	return (c);
}

/* ------------------------------------------------------------------------- */

#ifdef CONFIG_IDE_RESET
extern void ide_set_reset(int idereset);

1098
static void ide_reset(void)
W
wdenk 已提交
1099 1100 1101 1102
{
	int i;

	curr_device = -1;
1103
	for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i)
W
wdenk 已提交
1104
		ide_bus_ok[i] = 0;
1105
	for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i)
W
wdenk 已提交
1106 1107
		ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;

1108
	ide_set_reset(1);	/* assert reset */
W
wdenk 已提交
1109

M
Martin Krause 已提交
1110 1111 1112
	/* the reset signal shall be asserted for et least 25 us */
	udelay(25);

W
wdenk 已提交
1113 1114 1115 1116 1117 1118
	WATCHDOG_RESET();

	/* de-assert RESET signal */
	ide_set_reset(0);

	/* wait 250 ms */
1119 1120
	for (i = 0; i < 250; ++i)
		udelay(1000);
W
wdenk 已提交
1121 1122
}

1123
#endif /* CONFIG_IDE_RESET */
W
wdenk 已提交
1124 1125 1126

/* ------------------------------------------------------------------------- */

1127 1128 1129 1130 1131 1132 1133 1134
#if defined(CONFIG_OF_IDE_FIXUP)
int ide_device_present(int dev)
{
	if (dev >= CONFIG_SYS_IDE_MAXBUS)
		return 0;
	return (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1);
}
#endif
W
wdenk 已提交
1135 1136 1137 1138 1139 1140 1141
/* ------------------------------------------------------------------------- */

#ifdef CONFIG_ATAPI
/****************************************************************************
 * ATAPI Support
 */

1142 1143 1144 1145 1146 1147 1148
void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
	__attribute__ ((weak, alias("__ide_input_data_shorts")));

void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
	__attribute__ ((weak, alias("__ide_output_data_shorts")));


A
Albert Aribaud 已提交
1149
#if defined(CONFIG_IDE_SWAP_IO)
W
wdenk 已提交
1150 1151
/* since ATAPI may use commands with not 4 bytes alligned length
 * we have our own transfer functions, 2 bytes alligned */
1152
void __ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
W
wdenk 已提交
1153
{
1154 1155
	ushort *dbuf;
	volatile ushort *pbuf;
W
wdenk 已提交
1156

1157 1158
	pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
	dbuf = (ushort *) sect_buf;
1159

1160 1161
	debug("in output data shorts base for read is %lx\n",
	      (unsigned long) pbuf);
1162

W
wdenk 已提交
1163
	while (shorts--) {
1164
		EIEIO;
1165
		*pbuf = *dbuf++;
W
wdenk 已提交
1166
	}
1167 1168
}

1169
void __ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
1170
{
1171 1172
	ushort *dbuf;
	volatile ushort *pbuf;
1173

1174 1175
	pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
	dbuf = (ushort *) sect_buf;
1176

1177 1178
	debug("in input data shorts base for read is %lx\n",
	      (unsigned long) pbuf);
1179 1180 1181 1182 1183

	while (shorts--) {
		EIEIO;
		*dbuf++ = *pbuf;
	}
W
wdenk 已提交
1184 1185
}

1186
#else  /* ! CONFIG_IDE_SWAP_IO */
1187
void __ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
W
wdenk 已提交
1188
{
1189
	outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
W
wdenk 已提交
1190 1191
}

1192
void __ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
W
wdenk 已提交
1193
{
1194
	insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
W
wdenk 已提交
1195 1196
}

1197
#endif /* CONFIG_IDE_SWAP_IO */
W
wdenk 已提交
1198

W
wdenk 已提交
1199 1200 1201 1202 1203 1204
/*
 * Wait until (Status & mask) == res, or timeout (in ms)
 * Return last status
 * This is used since some ATAPI CD ROMs clears their Busy Bit first
 * and then they set their DRQ Bit
 */
1205
static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res)
W
wdenk 已提交
1206
{
1207
	ulong delay = 10 * t;	/* poll every 100 us */
W
wdenk 已提交
1208 1209
	uchar c;

1210 1211 1212
	/* prevents to read the status before valid */
	c = ide_inb(dev, ATA_DEV_CTL);

W
wdenk 已提交
1213
	while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) {
W
wdenk 已提交
1214
		/* break if error occurs (doesn't make sense to wait more) */
1215
		if ((c & ATA_STAT_ERR) == ATA_STAT_ERR)
W
wdenk 已提交
1216
			break;
1217 1218
		udelay(100);
		if (delay-- == 0)
W
wdenk 已提交
1219 1220 1221 1222 1223 1224 1225 1226
			break;
	}
	return (c);
}

/*
 * issue an atapi command
 */
1227 1228
unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen,
			  unsigned char *buffer, int buflen)
W
wdenk 已提交
1229
{
1230
	unsigned char c, err, mask, res;
W
wdenk 已提交
1231
	int n;
1232 1233

	ide_led(DEVICE_LED(device), 1);	/* LED on       */
W
wdenk 已提交
1234 1235 1236

	/* Select device
	 */
1237
	mask = ATA_STAT_BUSY | ATA_STAT_DRQ;
W
wdenk 已提交
1238
	res = 0;
1239 1240
	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
	c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
W
wdenk 已提交
1241
	if ((c & mask) != res) {
1242 1243 1244
		printf("ATAPI_ISSUE: device %d not ready status %X\n", device,
		       c);
		err = 0xFF;
W
wdenk 已提交
1245 1246 1247
		goto AI_OUT;
	}
	/* write taskfile */
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
	ide_outb(device, ATA_ERROR_REG, 0);	/* no DMA, no overlaped */
	ide_outb(device, ATA_SECT_CNT, 0);
	ide_outb(device, ATA_SECT_NUM, 0);
	ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF));
	ide_outb(device, ATA_CYL_HIGH,
		 (unsigned char) ((buflen >> 8) & 0xFF));
	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));

	ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET);
	udelay(50);

	mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR;
W
wdenk 已提交
1260
	res = ATA_STAT_DRQ;
1261
	c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
W
wdenk 已提交
1262

1263 1264 1265 1266
	if ((c & mask) != res) {	/* DRQ must be 1, BSY 0 */
		printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n",
			device, c);
		err = 0xFF;
W
wdenk 已提交
1267 1268 1269
		goto AI_OUT;
	}

1270
	/* write command block */
1271
	ide_output_data_shorts(device, (unsigned short *) ccb, ccblen / 2);
1272

W
Wolfgang Denk 已提交
1273
	/* ATAPI Command written wait for completition */
1274
	udelay(5000);		/* device must set bsy */
W
wdenk 已提交
1275

1276 1277 1278 1279 1280 1281 1282
	mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR;
	/*
	 * if no data wait for DRQ = 0 BSY = 0
	 * if data wait for DRQ = 1 BSY = 0
	 */
	res = 0;
	if (buflen)
W
wdenk 已提交
1283
		res = ATA_STAT_DRQ;
1284 1285
	c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
	if ((c & mask) != res) {
W
wdenk 已提交
1286
		if (c & ATA_STAT_ERR) {
1287 1288 1289
			err = (ide_inb(device, ATA_ERROR_REG)) >> 4;
			debug("atapi_issue 1 returned sense key %X status %02X\n",
				err, c);
W
wdenk 已提交
1290
		} else {
1291 1292 1293
			printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x)  status 0x%02x\n",
				ccb[0], c);
			err = 0xFF;
W
wdenk 已提交
1294 1295 1296
		}
		goto AI_OUT;
	}
1297 1298 1299 1300 1301 1302 1303
	n = ide_inb(device, ATA_CYL_HIGH);
	n <<= 8;
	n += ide_inb(device, ATA_CYL_LOW);
	if (n > buflen) {
		printf("ERROR, transfer bytes %d requested only %d\n", n,
		       buflen);
		err = 0xff;
W
wdenk 已提交
1304 1305
		goto AI_OUT;
	}
1306 1307 1308
	if ((n == 0) && (buflen < 0)) {
		printf("ERROR, transfer bytes %d requested %d\n", n, buflen);
		err = 0xff;
W
wdenk 已提交
1309 1310
		goto AI_OUT;
	}
1311 1312 1313
	if (n != buflen) {
		debug("WARNING, transfer bytes %d not equal with requested %d\n",
			n, buflen);
W
wdenk 已提交
1314
	}
1315 1316 1317 1318
	if (n != 0) {		/* data transfer */
		debug("ATAPI_ISSUE: %d Bytes to transfer\n", n);
		/* we transfer shorts */
		n >>= 1;
W
wdenk 已提交
1319
		/* ok now decide if it is an in or output */
1320 1321
		if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) {
			debug("Write to device\n");
1322 1323
			ide_output_data_shorts(device,
				(unsigned short *) buffer, n);
W
wdenk 已提交
1324
		} else {
1325
			debug("Read from device @ %p shorts %d\n", buffer, n);
1326 1327
			ide_input_data_shorts(device,
				(unsigned short *) buffer, n);
W
wdenk 已提交
1328 1329
		}
	}
1330 1331 1332 1333
	udelay(5000);		/* seems that some CD ROMs need this... */
	mask = ATA_STAT_BUSY | ATA_STAT_ERR;
	res = 0;
	c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
W
wdenk 已提交
1334
	if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
1335 1336 1337
		err = (ide_inb(device, ATA_ERROR_REG) >> 4);
		debug("atapi_issue 2 returned sense key %X status %X\n", err,
		      c);
W
wdenk 已提交
1338 1339 1340 1341
	} else {
		err = 0;
	}
AI_OUT:
1342
	ide_led(DEVICE_LED(device), 0);	/* LED off      */
W
wdenk 已提交
1343 1344 1345 1346 1347 1348 1349 1350
	return (err);
}

/*
 * sending the command to atapi_issue. If an status other than good
 * returns, an request_sense will be issued
 */

W
Wolfgang Denk 已提交
1351
#define ATAPI_DRIVE_NOT_READY	100
W
wdenk 已提交
1352 1353
#define ATAPI_UNIT_ATTN		10

1354 1355 1356 1357
unsigned char atapi_issue_autoreq(int device,
				  unsigned char *ccb,
				  int ccblen,
				  unsigned char *buffer, int buflen)
W
wdenk 已提交
1358
{
1359 1360 1361
	unsigned char sense_data[18], sense_ccb[12];
	unsigned char res, key, asc, ascq;
	int notready, unitattn;
W
wdenk 已提交
1362

1363 1364
	unitattn = ATAPI_UNIT_ATTN;
	notready = ATAPI_DRIVE_NOT_READY;
W
wdenk 已提交
1365 1366

retry:
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
	res = atapi_issue(device, ccb, ccblen, buffer, buflen);
	if (res == 0)
		return 0;	/* Ok */

	if (res == 0xFF)
		return 0xFF;	/* error */

	debug("(auto_req)atapi_issue returned sense key %X\n", res);

	memset(sense_ccb, 0, sizeof(sense_ccb));
	memset(sense_data, 0, sizeof(sense_data));
	sense_ccb[0] = ATAPI_CMD_REQ_SENSE;
	sense_ccb[4] = 18;	/* allocation Length */

	res = atapi_issue(device, sense_ccb, 12, sense_data, 18);
	key = (sense_data[2] & 0xF);
	asc = (sense_data[12]);
	ascq = (sense_data[13]);

	debug("ATAPI_CMD_REQ_SENSE returned %x\n", res);
	debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n",
	      sense_data[0], key, asc, ascq);

	if ((key == 0))
		return 0;	/* ok device ready */

	if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */
		if (unitattn-- > 0) {
			udelay(200 * 1000);
W
wdenk 已提交
1396 1397
			goto retry;
		}
1398
		printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN);
W
wdenk 已提交
1399 1400
		goto error;
	}
1401 1402 1403 1404
	if ((asc == 0x4) && (ascq == 0x1)) {
		/* not ready, but will be ready soon */
		if (notready-- > 0) {
			udelay(200 * 1000);
W
wdenk 已提交
1405 1406
			goto retry;
		}
1407 1408
		printf("Drive not ready, tried %d times\n",
		       ATAPI_DRIVE_NOT_READY);
W
wdenk 已提交
1409 1410
		goto error;
	}
1411 1412
	if (asc == 0x3a) {
		debug("Media not present\n");
W
wdenk 已提交
1413 1414
		goto error;
	}
W
wdenk 已提交
1415

1416 1417
	printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc,
	       ascq);
W
wdenk 已提交
1418
error:
1419
	debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq);
W
wdenk 已提交
1420 1421 1422 1423
	return (0xFF);
}


1424
static void atapi_inquiry(block_dev_desc_t *dev_desc)
W
wdenk 已提交
1425
{
1426 1427
	unsigned char ccb[12];	/* Command descriptor block */
	unsigned char iobuf[64];	/* temp buf */
W
wdenk 已提交
1428 1429 1430
	unsigned char c;
	int device;

1431 1432 1433
	device = dev_desc->dev;
	dev_desc->type = DEV_TYPE_UNKNOWN;	/* not yet valid */
	dev_desc->block_read = atapi_read;
W
wdenk 已提交
1434

1435 1436
	memset(ccb, 0, sizeof(ccb));
	memset(iobuf, 0, sizeof(iobuf));
W
wdenk 已提交
1437

1438 1439 1440
	ccb[0] = ATAPI_CMD_INQUIRY;
	ccb[4] = 40;		/* allocation Legnth */
	c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 40);
W
wdenk 已提交
1441

1442 1443
	debug("ATAPI_CMD_INQUIRY returned %x\n", c);
	if (c != 0)
W
wdenk 已提交
1444 1445 1446
		return;

	/* copy device ident strings */
1447 1448 1449
	ident_cpy((unsigned char *) dev_desc->vendor, &iobuf[8], 8);
	ident_cpy((unsigned char *) dev_desc->product, &iobuf[16], 16);
	ident_cpy((unsigned char *) dev_desc->revision, &iobuf[32], 5);
W
wdenk 已提交
1450

1451 1452 1453
	dev_desc->lun = 0;
	dev_desc->lba = 0;
	dev_desc->blksz = 0;
1454
	dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz));
1455
	dev_desc->type = iobuf[0] & 0x1f;
W
wdenk 已提交
1456

1457
	if ((iobuf[1] & 0x80) == 0x80)
W
wdenk 已提交
1458 1459 1460 1461
		dev_desc->removable = 1;
	else
		dev_desc->removable = 0;

1462 1463 1464 1465
	memset(ccb, 0, sizeof(ccb));
	memset(iobuf, 0, sizeof(iobuf));
	ccb[0] = ATAPI_CMD_START_STOP;
	ccb[4] = 0x03;		/* start */
W
wdenk 已提交
1466

1467
	c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0);
W
wdenk 已提交
1468

1469 1470
	debug("ATAPI_CMD_START_STOP returned %x\n", c);
	if (c != 0)
W
wdenk 已提交
1471 1472
		return;

1473 1474 1475
	memset(ccb, 0, sizeof(ccb));
	memset(iobuf, 0, sizeof(iobuf));
	c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0);
W
wdenk 已提交
1476

1477 1478
	debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c);
	if (c != 0)
W
wdenk 已提交
1479 1480
		return;

1481 1482 1483 1484 1485 1486
	memset(ccb, 0, sizeof(ccb));
	memset(iobuf, 0, sizeof(iobuf));
	ccb[0] = ATAPI_CMD_READ_CAP;
	c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 8);
	debug("ATAPI_CMD_READ_CAP returned %x\n", c);
	if (c != 0)
W
wdenk 已提交
1487 1488
		return;

1489 1490 1491 1492 1493 1494 1495 1496 1497 1498
	debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n",
	      iobuf[0], iobuf[1], iobuf[2], iobuf[3],
	      iobuf[4], iobuf[5], iobuf[6], iobuf[7]);

	dev_desc->lba = ((unsigned long) iobuf[0] << 24) +
		((unsigned long) iobuf[1] << 16) +
		((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]);
	dev_desc->blksz = ((unsigned long) iobuf[4] << 24) +
		((unsigned long) iobuf[5] << 16) +
		((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]);
1499
	dev_desc->log2blksz = LOG2(dev_desc->blksz);
1500
#ifdef CONFIG_LBA48
1501 1502
	/* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */
	dev_desc->lba48 = 0;
1503
#endif
W
wdenk 已提交
1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514
	return;
}


/*
 * atapi_read:
 * we transfer only one block per command, since the multiple DRQ per
 * command is not yet implemented
 */
#define ATAPI_READ_MAX_BYTES	2048	/* we read max 2kbytes */
#define ATAPI_READ_BLOCK_SIZE	2048	/* assuming CD part */
1515
#define ATAPI_READ_MAX_BLOCK	(ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE)
W
wdenk 已提交
1516

1517
ulong atapi_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
W
wdenk 已提交
1518 1519
{
	ulong n = 0;
1520
	unsigned char ccb[12];	/* Command descriptor block */
W
wdenk 已提交
1521 1522
	ulong cnt;

1523
	debug("atapi_read dev %d start %lX, blocks " LBAF " buffer at %lX\n",
1524
	      device, blknr, blkcnt, (ulong) buffer);
W
wdenk 已提交
1525 1526

	do {
1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548
		if (blkcnt > ATAPI_READ_MAX_BLOCK)
			cnt = ATAPI_READ_MAX_BLOCK;
		else
			cnt = blkcnt;

		ccb[0] = ATAPI_CMD_READ_12;
		ccb[1] = 0;	/* reserved */
		ccb[2] = (unsigned char) (blknr >> 24) & 0xFF;	/* MSB Block */
		ccb[3] = (unsigned char) (blknr >> 16) & 0xFF;	/*  */
		ccb[4] = (unsigned char) (blknr >> 8) & 0xFF;
		ccb[5] = (unsigned char) blknr & 0xFF;	/* LSB Block */
		ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */
		ccb[7] = (unsigned char) (cnt >> 16) & 0xFF;
		ccb[8] = (unsigned char) (cnt >> 8) & 0xFF;
		ccb[9] = (unsigned char) cnt & 0xFF;	/* LSB Block */
		ccb[10] = 0;	/* reserved */
		ccb[11] = 0;	/* reserved */

		if (atapi_issue_autoreq(device, ccb, 12,
					(unsigned char *) buffer,
					cnt * ATAPI_READ_BLOCK_SIZE)
		    == 0xFF) {
W
wdenk 已提交
1549 1550
			return (n);
		}
1551 1552 1553 1554
		n += cnt;
		blkcnt -= cnt;
		blknr += cnt;
		buffer += (cnt * ATAPI_READ_BLOCK_SIZE);
W
wdenk 已提交
1555 1556 1557 1558 1559 1560 1561 1562
	} while (blkcnt > 0);
	return (n);
}

/* ------------------------------------------------------------------------- */

#endif /* CONFIG_ATAPI */

1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575
U_BOOT_CMD(ide, 5, 1, do_ide,
	   "IDE sub-system",
	   "reset - reset IDE controller\n"
	   "ide info  - show available IDE devices\n"
	   "ide device [dev] - show or set current device\n"
	   "ide part [dev] - print partition table of one or all IDE devices\n"
	   "ide read  addr blk# cnt\n"
	   "ide write addr blk# cnt - read/write `cnt'"
	   " blocks starting at block `blk#'\n"
	   "    to/from memory address `addr'");

U_BOOT_CMD(diskboot, 3, 1, do_diskboot,
	   "boot from IDE device", "loadAddr dev:part");