xref: /OK3568_Linux_fs/u-boot/drivers/block/ide.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2000-2011
3*4882a593Smuzhiyun  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <ata.h>
10*4882a593Smuzhiyun #include <dm.h>
11*4882a593Smuzhiyun #include <ide.h>
12*4882a593Smuzhiyun #include <watchdog.h>
13*4882a593Smuzhiyun #include <asm/io.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #ifdef __PPC__
16*4882a593Smuzhiyun # define EIEIO		__asm__ volatile ("eieio")
17*4882a593Smuzhiyun # define SYNC		__asm__ volatile ("sync")
18*4882a593Smuzhiyun #else
19*4882a593Smuzhiyun # define EIEIO		/* nothing */
20*4882a593Smuzhiyun # define SYNC		/* nothing */
21*4882a593Smuzhiyun #endif
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun /* Current offset for IDE0 / IDE1 bus access	*/
24*4882a593Smuzhiyun ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = {
25*4882a593Smuzhiyun #if defined(CONFIG_SYS_ATA_IDE0_OFFSET)
26*4882a593Smuzhiyun 	CONFIG_SYS_ATA_IDE0_OFFSET,
27*4882a593Smuzhiyun #endif
28*4882a593Smuzhiyun #if defined(CONFIG_SYS_ATA_IDE1_OFFSET) && (CONFIG_SYS_IDE_MAXBUS > 1)
29*4882a593Smuzhiyun 	CONFIG_SYS_ATA_IDE1_OFFSET,
30*4882a593Smuzhiyun #endif
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS];
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE];
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #define IDE_TIME_OUT	2000	/* 2 sec timeout */
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #define ATAPI_TIME_OUT	7000	/* 7 sec timeout (5 sec seems to work...) */
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #ifndef CONFIG_SYS_ATA_PORT_ADDR
44*4882a593Smuzhiyun #define CONFIG_SYS_ATA_PORT_ADDR(port) (port)
45*4882a593Smuzhiyun #endif
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun #ifdef CONFIG_IDE_RESET
48*4882a593Smuzhiyun extern void ide_set_reset(int idereset);
49*4882a593Smuzhiyun 
ide_reset(void)50*4882a593Smuzhiyun static void ide_reset(void)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun 	int i;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i)
55*4882a593Smuzhiyun 		ide_bus_ok[i] = 0;
56*4882a593Smuzhiyun 	for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i)
57*4882a593Smuzhiyun 		ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	ide_set_reset(1);	/* assert reset */
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	/* the reset signal shall be asserted for et least 25 us */
62*4882a593Smuzhiyun 	udelay(25);
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	WATCHDOG_RESET();
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	/* de-assert RESET signal */
67*4882a593Smuzhiyun 	ide_set_reset(0);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	/* wait 250 ms */
70*4882a593Smuzhiyun 	for (i = 0; i < 250; ++i)
71*4882a593Smuzhiyun 		udelay(1000);
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun #else
74*4882a593Smuzhiyun #define ide_reset()	/* dummy */
75*4882a593Smuzhiyun #endif /* CONFIG_IDE_RESET */
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun /*
78*4882a593Smuzhiyun  * Wait until Busy bit is off, or timeout (in ms)
79*4882a593Smuzhiyun  * Return last status
80*4882a593Smuzhiyun  */
ide_wait(int dev,ulong t)81*4882a593Smuzhiyun static uchar ide_wait(int dev, ulong t)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun 	ulong delay = 10 * t;	/* poll every 100 us */
84*4882a593Smuzhiyun 	uchar c;
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
87*4882a593Smuzhiyun 		udelay(100);
88*4882a593Smuzhiyun 		if (delay-- == 0)
89*4882a593Smuzhiyun 			break;
90*4882a593Smuzhiyun 	}
91*4882a593Smuzhiyun 	return c;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun /*
95*4882a593Smuzhiyun  * copy src to dest, skipping leading and trailing blanks and null
96*4882a593Smuzhiyun  * terminate the string
97*4882a593Smuzhiyun  * "len" is the size of available memory including the terminating '\0'
98*4882a593Smuzhiyun  */
ident_cpy(unsigned char * dst,unsigned char * src,unsigned int len)99*4882a593Smuzhiyun static void ident_cpy(unsigned char *dst, unsigned char *src,
100*4882a593Smuzhiyun 		      unsigned int len)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	unsigned char *end, *last;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	last = dst;
105*4882a593Smuzhiyun 	end = src + len - 1;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	/* reserve space for '\0' */
108*4882a593Smuzhiyun 	if (len < 2)
109*4882a593Smuzhiyun 		goto OUT;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	/* skip leading white space */
112*4882a593Smuzhiyun 	while ((*src) && (src < end) && (*src == ' '))
113*4882a593Smuzhiyun 		++src;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	/* copy string, omitting trailing white space */
116*4882a593Smuzhiyun 	while ((*src) && (src < end)) {
117*4882a593Smuzhiyun 		*dst++ = *src;
118*4882a593Smuzhiyun 		if (*src++ != ' ')
119*4882a593Smuzhiyun 			last = dst;
120*4882a593Smuzhiyun 	}
121*4882a593Smuzhiyun OUT:
122*4882a593Smuzhiyun 	*last = '\0';
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun #ifdef CONFIG_ATAPI
126*4882a593Smuzhiyun /****************************************************************************
127*4882a593Smuzhiyun  * ATAPI Support
128*4882a593Smuzhiyun  */
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun #if defined(CONFIG_IDE_SWAP_IO)
131*4882a593Smuzhiyun /* since ATAPI may use commands with not 4 bytes alligned length
132*4882a593Smuzhiyun  * we have our own transfer functions, 2 bytes alligned */
ide_output_data_shorts(int dev,ushort * sect_buf,int shorts)133*4882a593Smuzhiyun __weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	ushort *dbuf;
136*4882a593Smuzhiyun 	volatile ushort *pbuf;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
139*4882a593Smuzhiyun 	dbuf = (ushort *)sect_buf;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	debug("in output data shorts base for read is %lx\n",
142*4882a593Smuzhiyun 	      (unsigned long) pbuf);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	while (shorts--) {
145*4882a593Smuzhiyun 		EIEIO;
146*4882a593Smuzhiyun 		*pbuf = *dbuf++;
147*4882a593Smuzhiyun 	}
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
ide_input_data_shorts(int dev,ushort * sect_buf,int shorts)150*4882a593Smuzhiyun __weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun 	ushort *dbuf;
153*4882a593Smuzhiyun 	volatile ushort *pbuf;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
156*4882a593Smuzhiyun 	dbuf = (ushort *)sect_buf;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	debug("in input data shorts base for read is %lx\n",
159*4882a593Smuzhiyun 	      (unsigned long) pbuf);
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	while (shorts--) {
162*4882a593Smuzhiyun 		EIEIO;
163*4882a593Smuzhiyun 		*dbuf++ = *pbuf;
164*4882a593Smuzhiyun 	}
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun #else  /* ! CONFIG_IDE_SWAP_IO */
ide_output_data_shorts(int dev,ushort * sect_buf,int shorts)168*4882a593Smuzhiyun __weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun 	outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun 
ide_input_data_shorts(int dev,ushort * sect_buf,int shorts)173*4882a593Smuzhiyun __weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun 	insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun #endif /* CONFIG_IDE_SWAP_IO */
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun /*
181*4882a593Smuzhiyun  * Wait until (Status & mask) == res, or timeout (in ms)
182*4882a593Smuzhiyun  * Return last status
183*4882a593Smuzhiyun  * This is used since some ATAPI CD ROMs clears their Busy Bit first
184*4882a593Smuzhiyun  * and then they set their DRQ Bit
185*4882a593Smuzhiyun  */
atapi_wait_mask(int dev,ulong t,uchar mask,uchar res)186*4882a593Smuzhiyun static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	ulong delay = 10 * t;	/* poll every 100 us */
189*4882a593Smuzhiyun 	uchar c;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	/* prevents to read the status before valid */
192*4882a593Smuzhiyun 	c = ide_inb(dev, ATA_DEV_CTL);
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) {
195*4882a593Smuzhiyun 		/* break if error occurs (doesn't make sense to wait more) */
196*4882a593Smuzhiyun 		if ((c & ATA_STAT_ERR) == ATA_STAT_ERR)
197*4882a593Smuzhiyun 			break;
198*4882a593Smuzhiyun 		udelay(100);
199*4882a593Smuzhiyun 		if (delay-- == 0)
200*4882a593Smuzhiyun 			break;
201*4882a593Smuzhiyun 	}
202*4882a593Smuzhiyun 	return c;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun /*
206*4882a593Smuzhiyun  * issue an atapi command
207*4882a593Smuzhiyun  */
atapi_issue(int device,unsigned char * ccb,int ccblen,unsigned char * buffer,int buflen)208*4882a593Smuzhiyun unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen,
209*4882a593Smuzhiyun 			  unsigned char *buffer, int buflen)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun 	unsigned char c, err, mask, res;
212*4882a593Smuzhiyun 	int n;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	/* Select device
215*4882a593Smuzhiyun 	 */
216*4882a593Smuzhiyun 	mask = ATA_STAT_BUSY | ATA_STAT_DRQ;
217*4882a593Smuzhiyun 	res = 0;
218*4882a593Smuzhiyun 	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
219*4882a593Smuzhiyun 	c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
220*4882a593Smuzhiyun 	if ((c & mask) != res) {
221*4882a593Smuzhiyun 		printf("ATAPI_ISSUE: device %d not ready status %X\n", device,
222*4882a593Smuzhiyun 		       c);
223*4882a593Smuzhiyun 		err = 0xFF;
224*4882a593Smuzhiyun 		goto AI_OUT;
225*4882a593Smuzhiyun 	}
226*4882a593Smuzhiyun 	/* write taskfile */
227*4882a593Smuzhiyun 	ide_outb(device, ATA_ERROR_REG, 0);	/* no DMA, no overlaped */
228*4882a593Smuzhiyun 	ide_outb(device, ATA_SECT_CNT, 0);
229*4882a593Smuzhiyun 	ide_outb(device, ATA_SECT_NUM, 0);
230*4882a593Smuzhiyun 	ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF));
231*4882a593Smuzhiyun 	ide_outb(device, ATA_CYL_HIGH,
232*4882a593Smuzhiyun 		 (unsigned char) ((buflen >> 8) & 0xFF));
233*4882a593Smuzhiyun 	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET);
236*4882a593Smuzhiyun 	udelay(50);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR;
239*4882a593Smuzhiyun 	res = ATA_STAT_DRQ;
240*4882a593Smuzhiyun 	c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	if ((c & mask) != res) {	/* DRQ must be 1, BSY 0 */
243*4882a593Smuzhiyun 		printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n",
244*4882a593Smuzhiyun 		       device, c);
245*4882a593Smuzhiyun 		err = 0xFF;
246*4882a593Smuzhiyun 		goto AI_OUT;
247*4882a593Smuzhiyun 	}
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	/* write command block */
250*4882a593Smuzhiyun 	ide_output_data_shorts(device, (unsigned short *)ccb, ccblen / 2);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	/* ATAPI Command written wait for completition */
253*4882a593Smuzhiyun 	udelay(5000);		/* device must set bsy */
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR;
256*4882a593Smuzhiyun 	/*
257*4882a593Smuzhiyun 	 * if no data wait for DRQ = 0 BSY = 0
258*4882a593Smuzhiyun 	 * if data wait for DRQ = 1 BSY = 0
259*4882a593Smuzhiyun 	 */
260*4882a593Smuzhiyun 	res = 0;
261*4882a593Smuzhiyun 	if (buflen)
262*4882a593Smuzhiyun 		res = ATA_STAT_DRQ;
263*4882a593Smuzhiyun 	c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
264*4882a593Smuzhiyun 	if ((c & mask) != res) {
265*4882a593Smuzhiyun 		if (c & ATA_STAT_ERR) {
266*4882a593Smuzhiyun 			err = (ide_inb(device, ATA_ERROR_REG)) >> 4;
267*4882a593Smuzhiyun 			debug("atapi_issue 1 returned sense key %X status %02X\n",
268*4882a593Smuzhiyun 			      err, c);
269*4882a593Smuzhiyun 		} else {
270*4882a593Smuzhiyun 			printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x)  status 0x%02x\n",
271*4882a593Smuzhiyun 			       ccb[0], c);
272*4882a593Smuzhiyun 			err = 0xFF;
273*4882a593Smuzhiyun 		}
274*4882a593Smuzhiyun 		goto AI_OUT;
275*4882a593Smuzhiyun 	}
276*4882a593Smuzhiyun 	n = ide_inb(device, ATA_CYL_HIGH);
277*4882a593Smuzhiyun 	n <<= 8;
278*4882a593Smuzhiyun 	n += ide_inb(device, ATA_CYL_LOW);
279*4882a593Smuzhiyun 	if (n > buflen) {
280*4882a593Smuzhiyun 		printf("ERROR, transfer bytes %d requested only %d\n", n,
281*4882a593Smuzhiyun 		       buflen);
282*4882a593Smuzhiyun 		err = 0xff;
283*4882a593Smuzhiyun 		goto AI_OUT;
284*4882a593Smuzhiyun 	}
285*4882a593Smuzhiyun 	if ((n == 0) && (buflen < 0)) {
286*4882a593Smuzhiyun 		printf("ERROR, transfer bytes %d requested %d\n", n, buflen);
287*4882a593Smuzhiyun 		err = 0xff;
288*4882a593Smuzhiyun 		goto AI_OUT;
289*4882a593Smuzhiyun 	}
290*4882a593Smuzhiyun 	if (n != buflen) {
291*4882a593Smuzhiyun 		debug("WARNING, transfer bytes %d not equal with requested %d\n",
292*4882a593Smuzhiyun 		      n, buflen);
293*4882a593Smuzhiyun 	}
294*4882a593Smuzhiyun 	if (n != 0) {		/* data transfer */
295*4882a593Smuzhiyun 		debug("ATAPI_ISSUE: %d Bytes to transfer\n", n);
296*4882a593Smuzhiyun 		/* we transfer shorts */
297*4882a593Smuzhiyun 		n >>= 1;
298*4882a593Smuzhiyun 		/* ok now decide if it is an in or output */
299*4882a593Smuzhiyun 		if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) {
300*4882a593Smuzhiyun 			debug("Write to device\n");
301*4882a593Smuzhiyun 			ide_output_data_shorts(device, (unsigned short *)buffer,
302*4882a593Smuzhiyun 					       n);
303*4882a593Smuzhiyun 		} else {
304*4882a593Smuzhiyun 			debug("Read from device @ %p shorts %d\n", buffer, n);
305*4882a593Smuzhiyun 			ide_input_data_shorts(device, (unsigned short *)buffer,
306*4882a593Smuzhiyun 					      n);
307*4882a593Smuzhiyun 		}
308*4882a593Smuzhiyun 	}
309*4882a593Smuzhiyun 	udelay(5000);		/* seems that some CD ROMs need this... */
310*4882a593Smuzhiyun 	mask = ATA_STAT_BUSY | ATA_STAT_ERR;
311*4882a593Smuzhiyun 	res = 0;
312*4882a593Smuzhiyun 	c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
313*4882a593Smuzhiyun 	if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
314*4882a593Smuzhiyun 		err = (ide_inb(device, ATA_ERROR_REG) >> 4);
315*4882a593Smuzhiyun 		debug("atapi_issue 2 returned sense key %X status %X\n", err,
316*4882a593Smuzhiyun 		      c);
317*4882a593Smuzhiyun 	} else {
318*4882a593Smuzhiyun 		err = 0;
319*4882a593Smuzhiyun 	}
320*4882a593Smuzhiyun AI_OUT:
321*4882a593Smuzhiyun 	return err;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun /*
325*4882a593Smuzhiyun  * sending the command to atapi_issue. If an status other than good
326*4882a593Smuzhiyun  * returns, an request_sense will be issued
327*4882a593Smuzhiyun  */
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun #define ATAPI_DRIVE_NOT_READY	100
330*4882a593Smuzhiyun #define ATAPI_UNIT_ATTN		10
331*4882a593Smuzhiyun 
atapi_issue_autoreq(int device,unsigned char * ccb,int ccblen,unsigned char * buffer,int buflen)332*4882a593Smuzhiyun unsigned char atapi_issue_autoreq(int device,
333*4882a593Smuzhiyun 				  unsigned char *ccb,
334*4882a593Smuzhiyun 				  int ccblen,
335*4882a593Smuzhiyun 				  unsigned char *buffer, int buflen)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun 	unsigned char sense_data[18], sense_ccb[12];
338*4882a593Smuzhiyun 	unsigned char res, key, asc, ascq;
339*4882a593Smuzhiyun 	int notready, unitattn;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	unitattn = ATAPI_UNIT_ATTN;
342*4882a593Smuzhiyun 	notready = ATAPI_DRIVE_NOT_READY;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun retry:
345*4882a593Smuzhiyun 	res = atapi_issue(device, ccb, ccblen, buffer, buflen);
346*4882a593Smuzhiyun 	if (res == 0)
347*4882a593Smuzhiyun 		return 0;	/* Ok */
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	if (res == 0xFF)
350*4882a593Smuzhiyun 		return 0xFF;	/* error */
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	debug("(auto_req)atapi_issue returned sense key %X\n", res);
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	memset(sense_ccb, 0, sizeof(sense_ccb));
355*4882a593Smuzhiyun 	memset(sense_data, 0, sizeof(sense_data));
356*4882a593Smuzhiyun 	sense_ccb[0] = ATAPI_CMD_REQ_SENSE;
357*4882a593Smuzhiyun 	sense_ccb[4] = 18;	/* allocation Length */
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	res = atapi_issue(device, sense_ccb, 12, sense_data, 18);
360*4882a593Smuzhiyun 	key = (sense_data[2] & 0xF);
361*4882a593Smuzhiyun 	asc = (sense_data[12]);
362*4882a593Smuzhiyun 	ascq = (sense_data[13]);
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	debug("ATAPI_CMD_REQ_SENSE returned %x\n", res);
365*4882a593Smuzhiyun 	debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n",
366*4882a593Smuzhiyun 	      sense_data[0], key, asc, ascq);
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	if ((key == 0))
369*4882a593Smuzhiyun 		return 0;	/* ok device ready */
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */
372*4882a593Smuzhiyun 		if (unitattn-- > 0) {
373*4882a593Smuzhiyun 			udelay(200 * 1000);
374*4882a593Smuzhiyun 			goto retry;
375*4882a593Smuzhiyun 		}
376*4882a593Smuzhiyun 		printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN);
377*4882a593Smuzhiyun 		goto error;
378*4882a593Smuzhiyun 	}
379*4882a593Smuzhiyun 	if ((asc == 0x4) && (ascq == 0x1)) {
380*4882a593Smuzhiyun 		/* not ready, but will be ready soon */
381*4882a593Smuzhiyun 		if (notready-- > 0) {
382*4882a593Smuzhiyun 			udelay(200 * 1000);
383*4882a593Smuzhiyun 			goto retry;
384*4882a593Smuzhiyun 		}
385*4882a593Smuzhiyun 		printf("Drive not ready, tried %d times\n",
386*4882a593Smuzhiyun 		       ATAPI_DRIVE_NOT_READY);
387*4882a593Smuzhiyun 		goto error;
388*4882a593Smuzhiyun 	}
389*4882a593Smuzhiyun 	if (asc == 0x3a) {
390*4882a593Smuzhiyun 		debug("Media not present\n");
391*4882a593Smuzhiyun 		goto error;
392*4882a593Smuzhiyun 	}
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc,
395*4882a593Smuzhiyun 	       ascq);
396*4882a593Smuzhiyun error:
397*4882a593Smuzhiyun 	debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq);
398*4882a593Smuzhiyun 	return 0xFF;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun /*
402*4882a593Smuzhiyun  * atapi_read:
403*4882a593Smuzhiyun  * we transfer only one block per command, since the multiple DRQ per
404*4882a593Smuzhiyun  * command is not yet implemented
405*4882a593Smuzhiyun  */
406*4882a593Smuzhiyun #define ATAPI_READ_MAX_BYTES	2048	/* we read max 2kbytes */
407*4882a593Smuzhiyun #define ATAPI_READ_BLOCK_SIZE	2048	/* assuming CD part */
408*4882a593Smuzhiyun #define ATAPI_READ_MAX_BLOCK	(ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE)
409*4882a593Smuzhiyun 
atapi_read(struct blk_desc * block_dev,lbaint_t blknr,lbaint_t blkcnt,void * buffer)410*4882a593Smuzhiyun ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
411*4882a593Smuzhiyun 		 void *buffer)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun 	int device = block_dev->devnum;
414*4882a593Smuzhiyun 	ulong n = 0;
415*4882a593Smuzhiyun 	unsigned char ccb[12];	/* Command descriptor block */
416*4882a593Smuzhiyun 	ulong cnt;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	debug("atapi_read dev %d start " LBAF " blocks " LBAF
419*4882a593Smuzhiyun 	      " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	do {
422*4882a593Smuzhiyun 		if (blkcnt > ATAPI_READ_MAX_BLOCK)
423*4882a593Smuzhiyun 			cnt = ATAPI_READ_MAX_BLOCK;
424*4882a593Smuzhiyun 		else
425*4882a593Smuzhiyun 			cnt = blkcnt;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 		ccb[0] = ATAPI_CMD_READ_12;
428*4882a593Smuzhiyun 		ccb[1] = 0;	/* reserved */
429*4882a593Smuzhiyun 		ccb[2] = (unsigned char) (blknr >> 24) & 0xFF;	/* MSB Block */
430*4882a593Smuzhiyun 		ccb[3] = (unsigned char) (blknr >> 16) & 0xFF;	/*  */
431*4882a593Smuzhiyun 		ccb[4] = (unsigned char) (blknr >> 8) & 0xFF;
432*4882a593Smuzhiyun 		ccb[5] = (unsigned char) blknr & 0xFF;	/* LSB Block */
433*4882a593Smuzhiyun 		ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */
434*4882a593Smuzhiyun 		ccb[7] = (unsigned char) (cnt >> 16) & 0xFF;
435*4882a593Smuzhiyun 		ccb[8] = (unsigned char) (cnt >> 8) & 0xFF;
436*4882a593Smuzhiyun 		ccb[9] = (unsigned char) cnt & 0xFF;	/* LSB Block */
437*4882a593Smuzhiyun 		ccb[10] = 0;	/* reserved */
438*4882a593Smuzhiyun 		ccb[11] = 0;	/* reserved */
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 		if (atapi_issue_autoreq(device, ccb, 12,
441*4882a593Smuzhiyun 					(unsigned char *)buffer,
442*4882a593Smuzhiyun 					cnt * ATAPI_READ_BLOCK_SIZE)
443*4882a593Smuzhiyun 		    == 0xFF) {
444*4882a593Smuzhiyun 			return n;
445*4882a593Smuzhiyun 		}
446*4882a593Smuzhiyun 		n += cnt;
447*4882a593Smuzhiyun 		blkcnt -= cnt;
448*4882a593Smuzhiyun 		blknr += cnt;
449*4882a593Smuzhiyun 		buffer += (cnt * ATAPI_READ_BLOCK_SIZE);
450*4882a593Smuzhiyun 	} while (blkcnt > 0);
451*4882a593Smuzhiyun 	return n;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun 
atapi_inquiry(struct blk_desc * dev_desc)454*4882a593Smuzhiyun static void atapi_inquiry(struct blk_desc *dev_desc)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun 	unsigned char ccb[12];	/* Command descriptor block */
457*4882a593Smuzhiyun 	unsigned char iobuf[64];	/* temp buf */
458*4882a593Smuzhiyun 	unsigned char c;
459*4882a593Smuzhiyun 	int device;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	device = dev_desc->devnum;
462*4882a593Smuzhiyun 	dev_desc->type = DEV_TYPE_UNKNOWN;	/* not yet valid */
463*4882a593Smuzhiyun #ifndef CONFIG_BLK
464*4882a593Smuzhiyun 	dev_desc->block_read = atapi_read;
465*4882a593Smuzhiyun #endif
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	memset(ccb, 0, sizeof(ccb));
468*4882a593Smuzhiyun 	memset(iobuf, 0, sizeof(iobuf));
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	ccb[0] = ATAPI_CMD_INQUIRY;
471*4882a593Smuzhiyun 	ccb[4] = 40;		/* allocation Legnth */
472*4882a593Smuzhiyun 	c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 40);
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 	debug("ATAPI_CMD_INQUIRY returned %x\n", c);
475*4882a593Smuzhiyun 	if (c != 0)
476*4882a593Smuzhiyun 		return;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	/* copy device ident strings */
479*4882a593Smuzhiyun 	ident_cpy((unsigned char *)dev_desc->vendor, &iobuf[8], 8);
480*4882a593Smuzhiyun 	ident_cpy((unsigned char *)dev_desc->product, &iobuf[16], 16);
481*4882a593Smuzhiyun 	ident_cpy((unsigned char *)dev_desc->revision, &iobuf[32], 5);
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	dev_desc->lun = 0;
484*4882a593Smuzhiyun 	dev_desc->lba = 0;
485*4882a593Smuzhiyun 	dev_desc->blksz = 0;
486*4882a593Smuzhiyun 	dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz));
487*4882a593Smuzhiyun 	dev_desc->type = iobuf[0] & 0x1f;
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 	if ((iobuf[1] & 0x80) == 0x80)
490*4882a593Smuzhiyun 		dev_desc->removable = 1;
491*4882a593Smuzhiyun 	else
492*4882a593Smuzhiyun 		dev_desc->removable = 0;
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	memset(ccb, 0, sizeof(ccb));
495*4882a593Smuzhiyun 	memset(iobuf, 0, sizeof(iobuf));
496*4882a593Smuzhiyun 	ccb[0] = ATAPI_CMD_START_STOP;
497*4882a593Smuzhiyun 	ccb[4] = 0x03;		/* start */
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0);
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	debug("ATAPI_CMD_START_STOP returned %x\n", c);
502*4882a593Smuzhiyun 	if (c != 0)
503*4882a593Smuzhiyun 		return;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	memset(ccb, 0, sizeof(ccb));
506*4882a593Smuzhiyun 	memset(iobuf, 0, sizeof(iobuf));
507*4882a593Smuzhiyun 	c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0);
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c);
510*4882a593Smuzhiyun 	if (c != 0)
511*4882a593Smuzhiyun 		return;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	memset(ccb, 0, sizeof(ccb));
514*4882a593Smuzhiyun 	memset(iobuf, 0, sizeof(iobuf));
515*4882a593Smuzhiyun 	ccb[0] = ATAPI_CMD_READ_CAP;
516*4882a593Smuzhiyun 	c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 8);
517*4882a593Smuzhiyun 	debug("ATAPI_CMD_READ_CAP returned %x\n", c);
518*4882a593Smuzhiyun 	if (c != 0)
519*4882a593Smuzhiyun 		return;
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n",
522*4882a593Smuzhiyun 	      iobuf[0], iobuf[1], iobuf[2], iobuf[3],
523*4882a593Smuzhiyun 	      iobuf[4], iobuf[5], iobuf[6], iobuf[7]);
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	dev_desc->lba = ((unsigned long) iobuf[0] << 24) +
526*4882a593Smuzhiyun 		((unsigned long) iobuf[1] << 16) +
527*4882a593Smuzhiyun 		((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]);
528*4882a593Smuzhiyun 	dev_desc->blksz = ((unsigned long) iobuf[4] << 24) +
529*4882a593Smuzhiyun 		((unsigned long) iobuf[5] << 16) +
530*4882a593Smuzhiyun 		((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]);
531*4882a593Smuzhiyun 	dev_desc->log2blksz = LOG2(dev_desc->blksz);
532*4882a593Smuzhiyun #ifdef CONFIG_LBA48
533*4882a593Smuzhiyun 	/* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */
534*4882a593Smuzhiyun 	dev_desc->lba48 = 0;
535*4882a593Smuzhiyun #endif
536*4882a593Smuzhiyun 	return;
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun #endif /* CONFIG_ATAPI */
540*4882a593Smuzhiyun 
ide_ident(struct blk_desc * dev_desc)541*4882a593Smuzhiyun static void ide_ident(struct blk_desc *dev_desc)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun 	unsigned char c;
544*4882a593Smuzhiyun 	hd_driveid_t iop;
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun #ifdef CONFIG_ATAPI
547*4882a593Smuzhiyun 	int retries = 0;
548*4882a593Smuzhiyun #endif
549*4882a593Smuzhiyun 	int device;
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	device = dev_desc->devnum;
552*4882a593Smuzhiyun 	printf("  Device %d: ", device);
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	/* Select device
555*4882a593Smuzhiyun 	 */
556*4882a593Smuzhiyun 	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
557*4882a593Smuzhiyun 	dev_desc->if_type = IF_TYPE_IDE;
558*4882a593Smuzhiyun #ifdef CONFIG_ATAPI
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	retries = 0;
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 	/* Warning: This will be tricky to read */
563*4882a593Smuzhiyun 	while (retries <= 1) {
564*4882a593Smuzhiyun 		/* check signature */
565*4882a593Smuzhiyun 		if ((ide_inb(device, ATA_SECT_CNT) == 0x01) &&
566*4882a593Smuzhiyun 		    (ide_inb(device, ATA_SECT_NUM) == 0x01) &&
567*4882a593Smuzhiyun 		    (ide_inb(device, ATA_CYL_LOW) == 0x14) &&
568*4882a593Smuzhiyun 		    (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) {
569*4882a593Smuzhiyun 			/* ATAPI Signature found */
570*4882a593Smuzhiyun 			dev_desc->if_type = IF_TYPE_ATAPI;
571*4882a593Smuzhiyun 			/*
572*4882a593Smuzhiyun 			 * Start Ident Command
573*4882a593Smuzhiyun 			 */
574*4882a593Smuzhiyun 			ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT);
575*4882a593Smuzhiyun 			/*
576*4882a593Smuzhiyun 			 * Wait for completion - ATAPI devices need more time
577*4882a593Smuzhiyun 			 * to become ready
578*4882a593Smuzhiyun 			 */
579*4882a593Smuzhiyun 			c = ide_wait(device, ATAPI_TIME_OUT);
580*4882a593Smuzhiyun 		} else
581*4882a593Smuzhiyun #endif
582*4882a593Smuzhiyun 		{
583*4882a593Smuzhiyun 			/*
584*4882a593Smuzhiyun 			 * Start Ident Command
585*4882a593Smuzhiyun 			 */
586*4882a593Smuzhiyun 			ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT);
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 			/*
589*4882a593Smuzhiyun 			 * Wait for completion
590*4882a593Smuzhiyun 			 */
591*4882a593Smuzhiyun 			c = ide_wait(device, IDE_TIME_OUT);
592*4882a593Smuzhiyun 		}
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 		if (((c & ATA_STAT_DRQ) == 0) ||
595*4882a593Smuzhiyun 		    ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) {
596*4882a593Smuzhiyun #ifdef CONFIG_ATAPI
597*4882a593Smuzhiyun 			{
598*4882a593Smuzhiyun 				/*
599*4882a593Smuzhiyun 				 * Need to soft reset the device
600*4882a593Smuzhiyun 				 * in case it's an ATAPI...
601*4882a593Smuzhiyun 				 */
602*4882a593Smuzhiyun 				debug("Retrying...\n");
603*4882a593Smuzhiyun 				ide_outb(device, ATA_DEV_HD,
604*4882a593Smuzhiyun 					 ATA_LBA | ATA_DEVICE(device));
605*4882a593Smuzhiyun 				udelay(100000);
606*4882a593Smuzhiyun 				ide_outb(device, ATA_COMMAND, 0x08);
607*4882a593Smuzhiyun 				udelay(500000);	/* 500 ms */
608*4882a593Smuzhiyun 			}
609*4882a593Smuzhiyun 			/*
610*4882a593Smuzhiyun 			 * Select device
611*4882a593Smuzhiyun 			 */
612*4882a593Smuzhiyun 			ide_outb(device, ATA_DEV_HD,
613*4882a593Smuzhiyun 				 ATA_LBA | ATA_DEVICE(device));
614*4882a593Smuzhiyun 			retries++;
615*4882a593Smuzhiyun #else
616*4882a593Smuzhiyun 			return;
617*4882a593Smuzhiyun #endif
618*4882a593Smuzhiyun 		}
619*4882a593Smuzhiyun #ifdef CONFIG_ATAPI
620*4882a593Smuzhiyun 		else
621*4882a593Smuzhiyun 			break;
622*4882a593Smuzhiyun 	}			/* see above - ugly to read */
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 	if (retries == 2)	/* Not found */
625*4882a593Smuzhiyun 		return;
626*4882a593Smuzhiyun #endif
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS);
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	ident_cpy((unsigned char *)dev_desc->revision, iop.fw_rev,
631*4882a593Smuzhiyun 		  sizeof(dev_desc->revision));
632*4882a593Smuzhiyun 	ident_cpy((unsigned char *)dev_desc->vendor, iop.model,
633*4882a593Smuzhiyun 		  sizeof(dev_desc->vendor));
634*4882a593Smuzhiyun 	ident_cpy((unsigned char *)dev_desc->product, iop.serial_no,
635*4882a593Smuzhiyun 		  sizeof(dev_desc->product));
636*4882a593Smuzhiyun #ifdef __LITTLE_ENDIAN
637*4882a593Smuzhiyun 	/*
638*4882a593Smuzhiyun 	 * firmware revision, model, and serial number have Big Endian Byte
639*4882a593Smuzhiyun 	 * order in Word. Convert all three to little endian.
640*4882a593Smuzhiyun 	 *
641*4882a593Smuzhiyun 	 * See CF+ and CompactFlash Specification Revision 2.0:
642*4882a593Smuzhiyun 	 * 6.2.1.6: Identify Drive, Table 39 for more details
643*4882a593Smuzhiyun 	 */
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun 	strswab(dev_desc->revision);
646*4882a593Smuzhiyun 	strswab(dev_desc->vendor);
647*4882a593Smuzhiyun 	strswab(dev_desc->product);
648*4882a593Smuzhiyun #endif /* __LITTLE_ENDIAN */
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	if ((iop.config & 0x0080) == 0x0080)
651*4882a593Smuzhiyun 		dev_desc->removable = 1;
652*4882a593Smuzhiyun 	else
653*4882a593Smuzhiyun 		dev_desc->removable = 0;
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun #ifdef CONFIG_ATAPI
656*4882a593Smuzhiyun 	if (dev_desc->if_type == IF_TYPE_ATAPI) {
657*4882a593Smuzhiyun 		atapi_inquiry(dev_desc);
658*4882a593Smuzhiyun 		return;
659*4882a593Smuzhiyun 	}
660*4882a593Smuzhiyun #endif /* CONFIG_ATAPI */
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun #ifdef __BIG_ENDIAN
663*4882a593Smuzhiyun 	/* swap shorts */
664*4882a593Smuzhiyun 	dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16);
665*4882a593Smuzhiyun #else  /* ! __BIG_ENDIAN */
666*4882a593Smuzhiyun 	/*
667*4882a593Smuzhiyun 	 * do not swap shorts on little endian
668*4882a593Smuzhiyun 	 *
669*4882a593Smuzhiyun 	 * See CF+ and CompactFlash Specification Revision 2.0:
670*4882a593Smuzhiyun 	 * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details.
671*4882a593Smuzhiyun 	 */
672*4882a593Smuzhiyun 	dev_desc->lba = iop.lba_capacity;
673*4882a593Smuzhiyun #endif /* __BIG_ENDIAN */
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun #ifdef CONFIG_LBA48
676*4882a593Smuzhiyun 	if (iop.command_set_2 & 0x0400) {	/* LBA 48 support */
677*4882a593Smuzhiyun 		dev_desc->lba48 = 1;
678*4882a593Smuzhiyun 		dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] |
679*4882a593Smuzhiyun 			((unsigned long long) iop.lba48_capacity[1] << 16) |
680*4882a593Smuzhiyun 			((unsigned long long) iop.lba48_capacity[2] << 32) |
681*4882a593Smuzhiyun 			((unsigned long long) iop.lba48_capacity[3] << 48);
682*4882a593Smuzhiyun 	} else {
683*4882a593Smuzhiyun 		dev_desc->lba48 = 0;
684*4882a593Smuzhiyun 	}
685*4882a593Smuzhiyun #endif /* CONFIG_LBA48 */
686*4882a593Smuzhiyun 	/* assuming HD */
687*4882a593Smuzhiyun 	dev_desc->type = DEV_TYPE_HARDDISK;
688*4882a593Smuzhiyun 	dev_desc->blksz = ATA_BLOCKSIZE;
689*4882a593Smuzhiyun 	dev_desc->log2blksz = LOG2(dev_desc->blksz);
690*4882a593Smuzhiyun 	dev_desc->lun = 0;	/* just to fill something in... */
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun #if 0				/* only used to test the powersaving mode,
693*4882a593Smuzhiyun 				 * if enabled, the drive goes after 5 sec
694*4882a593Smuzhiyun 				 * in standby mode */
695*4882a593Smuzhiyun 	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
696*4882a593Smuzhiyun 	c = ide_wait(device, IDE_TIME_OUT);
697*4882a593Smuzhiyun 	ide_outb(device, ATA_SECT_CNT, 1);
698*4882a593Smuzhiyun 	ide_outb(device, ATA_LBA_LOW, 0);
699*4882a593Smuzhiyun 	ide_outb(device, ATA_LBA_MID, 0);
700*4882a593Smuzhiyun 	ide_outb(device, ATA_LBA_HIGH, 0);
701*4882a593Smuzhiyun 	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
702*4882a593Smuzhiyun 	ide_outb(device, ATA_COMMAND, 0xe3);
703*4882a593Smuzhiyun 	udelay(50);
704*4882a593Smuzhiyun 	c = ide_wait(device, IDE_TIME_OUT);	/* can't take over 500 ms */
705*4882a593Smuzhiyun #endif
706*4882a593Smuzhiyun }
707*4882a593Smuzhiyun 
ide_outb(int dev,int port,unsigned char val)708*4882a593Smuzhiyun __weak void ide_outb(int dev, int port, unsigned char val)
709*4882a593Smuzhiyun {
710*4882a593Smuzhiyun 	debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n",
711*4882a593Smuzhiyun 	      dev, port, val,
712*4882a593Smuzhiyun 	      (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun #if defined(CONFIG_IDE_AHB)
715*4882a593Smuzhiyun 	if (port) {
716*4882a593Smuzhiyun 		/* write command */
717*4882a593Smuzhiyun 		ide_write_register(dev, port, val);
718*4882a593Smuzhiyun 	} else {
719*4882a593Smuzhiyun 		/* write data */
720*4882a593Smuzhiyun 		outb(val, (ATA_CURR_BASE(dev)));
721*4882a593Smuzhiyun 	}
722*4882a593Smuzhiyun #else
723*4882a593Smuzhiyun 	outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
724*4882a593Smuzhiyun #endif
725*4882a593Smuzhiyun }
726*4882a593Smuzhiyun 
ide_inb(int dev,int port)727*4882a593Smuzhiyun __weak unsigned char ide_inb(int dev, int port)
728*4882a593Smuzhiyun {
729*4882a593Smuzhiyun 	uchar val;
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun #if defined(CONFIG_IDE_AHB)
732*4882a593Smuzhiyun 	val = ide_read_register(dev, port);
733*4882a593Smuzhiyun #else
734*4882a593Smuzhiyun 	val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
735*4882a593Smuzhiyun #endif
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n",
738*4882a593Smuzhiyun 	      dev, port,
739*4882a593Smuzhiyun 	      (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val);
740*4882a593Smuzhiyun 	return val;
741*4882a593Smuzhiyun }
742*4882a593Smuzhiyun 
ide_init(void)743*4882a593Smuzhiyun void ide_init(void)
744*4882a593Smuzhiyun {
745*4882a593Smuzhiyun 	unsigned char c;
746*4882a593Smuzhiyun 	int i, bus;
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun #ifdef CONFIG_IDE_PREINIT
749*4882a593Smuzhiyun 	WATCHDOG_RESET();
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	if (ide_preinit()) {
752*4882a593Smuzhiyun 		puts("ide_preinit failed\n");
753*4882a593Smuzhiyun 		return;
754*4882a593Smuzhiyun 	}
755*4882a593Smuzhiyun #endif /* CONFIG_IDE_PREINIT */
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	WATCHDOG_RESET();
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 	/* ATAPI Drives seems to need a proper IDE Reset */
760*4882a593Smuzhiyun 	ide_reset();
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 	/*
763*4882a593Smuzhiyun 	 * Wait for IDE to get ready.
764*4882a593Smuzhiyun 	 * According to spec, this can take up to 31 seconds!
765*4882a593Smuzhiyun 	 */
766*4882a593Smuzhiyun 	for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) {
767*4882a593Smuzhiyun 		int dev =
768*4882a593Smuzhiyun 			bus * (CONFIG_SYS_IDE_MAXDEVICE /
769*4882a593Smuzhiyun 			       CONFIG_SYS_IDE_MAXBUS);
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun 		printf("Bus %d: ", bus);
772*4882a593Smuzhiyun 
773*4882a593Smuzhiyun 		ide_bus_ok[bus] = 0;
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 		/* Select device
776*4882a593Smuzhiyun 		 */
777*4882a593Smuzhiyun 		udelay(100000);	/* 100 ms */
778*4882a593Smuzhiyun 		ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
779*4882a593Smuzhiyun 		udelay(100000);	/* 100 ms */
780*4882a593Smuzhiyun 		i = 0;
781*4882a593Smuzhiyun 		do {
782*4882a593Smuzhiyun 			udelay(10000);	/* 10 ms */
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 			c = ide_inb(dev, ATA_STATUS);
785*4882a593Smuzhiyun 			i++;
786*4882a593Smuzhiyun 			if (i > (ATA_RESET_TIME * 100)) {
787*4882a593Smuzhiyun 				puts("** Timeout **\n");
788*4882a593Smuzhiyun 				return;
789*4882a593Smuzhiyun 			}
790*4882a593Smuzhiyun 			if ((i >= 100) && ((i % 100) == 0))
791*4882a593Smuzhiyun 				putc('.');
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 		} while (c & ATA_STAT_BUSY);
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun 		if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
796*4882a593Smuzhiyun 			puts("not available  ");
797*4882a593Smuzhiyun 			debug("Status = 0x%02X ", c);
798*4882a593Smuzhiyun #ifndef CONFIG_ATAPI		/* ATAPI Devices do not set DRDY */
799*4882a593Smuzhiyun 		} else if ((c & ATA_STAT_READY) == 0) {
800*4882a593Smuzhiyun 			puts("not available  ");
801*4882a593Smuzhiyun 			debug("Status = 0x%02X ", c);
802*4882a593Smuzhiyun #endif
803*4882a593Smuzhiyun 		} else {
804*4882a593Smuzhiyun 			puts("OK ");
805*4882a593Smuzhiyun 			ide_bus_ok[bus] = 1;
806*4882a593Smuzhiyun 		}
807*4882a593Smuzhiyun 		WATCHDOG_RESET();
808*4882a593Smuzhiyun 	}
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 	putc('\n');
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 	for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) {
813*4882a593Smuzhiyun 		ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
814*4882a593Smuzhiyun 		ide_dev_desc[i].if_type = IF_TYPE_IDE;
815*4882a593Smuzhiyun 		ide_dev_desc[i].devnum = i;
816*4882a593Smuzhiyun 		ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
817*4882a593Smuzhiyun 		ide_dev_desc[i].blksz = 0;
818*4882a593Smuzhiyun 		ide_dev_desc[i].log2blksz =
819*4882a593Smuzhiyun 			LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz));
820*4882a593Smuzhiyun 		ide_dev_desc[i].lba = 0;
821*4882a593Smuzhiyun #ifndef CONFIG_BLK
822*4882a593Smuzhiyun 		ide_dev_desc[i].block_read = ide_read;
823*4882a593Smuzhiyun 		ide_dev_desc[i].block_write = ide_write;
824*4882a593Smuzhiyun #endif
825*4882a593Smuzhiyun 		if (!ide_bus_ok[IDE_BUS(i)])
826*4882a593Smuzhiyun 			continue;
827*4882a593Smuzhiyun 		ide_ident(&ide_dev_desc[i]);
828*4882a593Smuzhiyun 		dev_print(&ide_dev_desc[i]);
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun #ifndef CONFIG_BLK
831*4882a593Smuzhiyun 		if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) {
832*4882a593Smuzhiyun 			/* initialize partition type */
833*4882a593Smuzhiyun 			part_init(&ide_dev_desc[i]);
834*4882a593Smuzhiyun 		}
835*4882a593Smuzhiyun #endif
836*4882a593Smuzhiyun 	}
837*4882a593Smuzhiyun 	WATCHDOG_RESET();
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun #ifdef CONFIG_BLK
840*4882a593Smuzhiyun 	struct udevice *dev;
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun 	uclass_first_device(UCLASS_IDE, &dev);
843*4882a593Smuzhiyun #endif
844*4882a593Smuzhiyun }
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun /* We only need to swap data if we are running on a big endian cpu. */
847*4882a593Smuzhiyun #if defined(__LITTLE_ENDIAN)
ide_input_swap_data(int dev,ulong * sect_buf,int words)848*4882a593Smuzhiyun __weak void ide_input_swap_data(int dev, ulong *sect_buf, int words)
849*4882a593Smuzhiyun {
850*4882a593Smuzhiyun 	ide_input_data(dev, sect_buf, words);
851*4882a593Smuzhiyun }
852*4882a593Smuzhiyun #else
ide_input_swap_data(int dev,ulong * sect_buf,int words)853*4882a593Smuzhiyun __weak void ide_input_swap_data(int dev, ulong *sect_buf, int words)
854*4882a593Smuzhiyun {
855*4882a593Smuzhiyun 	volatile ushort *pbuf =
856*4882a593Smuzhiyun 		(ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
857*4882a593Smuzhiyun 	ushort *dbuf = (ushort *)sect_buf;
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun 	debug("in input swap data base for read is %lx\n",
860*4882a593Smuzhiyun 	      (unsigned long) pbuf);
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun 	while (words--) {
863*4882a593Smuzhiyun #ifdef __MIPS__
864*4882a593Smuzhiyun 		*dbuf++ = swab16p((u16 *)pbuf);
865*4882a593Smuzhiyun 		*dbuf++ = swab16p((u16 *)pbuf);
866*4882a593Smuzhiyun #else
867*4882a593Smuzhiyun 		*dbuf++ = ld_le16(pbuf);
868*4882a593Smuzhiyun 		*dbuf++ = ld_le16(pbuf);
869*4882a593Smuzhiyun #endif /* !MIPS */
870*4882a593Smuzhiyun 	}
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun #endif /* __LITTLE_ENDIAN */
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 
875*4882a593Smuzhiyun #if defined(CONFIG_IDE_SWAP_IO)
ide_output_data(int dev,const ulong * sect_buf,int words)876*4882a593Smuzhiyun __weak void ide_output_data(int dev, const ulong *sect_buf, int words)
877*4882a593Smuzhiyun {
878*4882a593Smuzhiyun 	ushort *dbuf;
879*4882a593Smuzhiyun 	volatile ushort *pbuf;
880*4882a593Smuzhiyun 
881*4882a593Smuzhiyun 	pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
882*4882a593Smuzhiyun 	dbuf = (ushort *)sect_buf;
883*4882a593Smuzhiyun 	while (words--) {
884*4882a593Smuzhiyun 		EIEIO;
885*4882a593Smuzhiyun 		*pbuf = *dbuf++;
886*4882a593Smuzhiyun 		EIEIO;
887*4882a593Smuzhiyun 		*pbuf = *dbuf++;
888*4882a593Smuzhiyun 	}
889*4882a593Smuzhiyun }
890*4882a593Smuzhiyun #else  /* ! CONFIG_IDE_SWAP_IO */
ide_output_data(int dev,const ulong * sect_buf,int words)891*4882a593Smuzhiyun __weak void ide_output_data(int dev, const ulong *sect_buf, int words)
892*4882a593Smuzhiyun {
893*4882a593Smuzhiyun #if defined(CONFIG_IDE_AHB)
894*4882a593Smuzhiyun 	ide_write_data(dev, sect_buf, words);
895*4882a593Smuzhiyun #else
896*4882a593Smuzhiyun 	outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1);
897*4882a593Smuzhiyun #endif
898*4882a593Smuzhiyun }
899*4882a593Smuzhiyun #endif /* CONFIG_IDE_SWAP_IO */
900*4882a593Smuzhiyun 
901*4882a593Smuzhiyun #if defined(CONFIG_IDE_SWAP_IO)
ide_input_data(int dev,ulong * sect_buf,int words)902*4882a593Smuzhiyun __weak void ide_input_data(int dev, ulong *sect_buf, int words)
903*4882a593Smuzhiyun {
904*4882a593Smuzhiyun 	ushort *dbuf;
905*4882a593Smuzhiyun 	volatile ushort *pbuf;
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun 	pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
908*4882a593Smuzhiyun 	dbuf = (ushort *)sect_buf;
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun 	debug("in input data base for read is %lx\n", (unsigned long) pbuf);
911*4882a593Smuzhiyun 
912*4882a593Smuzhiyun 	while (words--) {
913*4882a593Smuzhiyun 		EIEIO;
914*4882a593Smuzhiyun 		*dbuf++ = *pbuf;
915*4882a593Smuzhiyun 		EIEIO;
916*4882a593Smuzhiyun 		*dbuf++ = *pbuf;
917*4882a593Smuzhiyun 	}
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun #else  /* ! CONFIG_IDE_SWAP_IO */
ide_input_data(int dev,ulong * sect_buf,int words)920*4882a593Smuzhiyun __weak void ide_input_data(int dev, ulong *sect_buf, int words)
921*4882a593Smuzhiyun {
922*4882a593Smuzhiyun #if defined(CONFIG_IDE_AHB)
923*4882a593Smuzhiyun 	ide_read_data(dev, sect_buf, words);
924*4882a593Smuzhiyun #else
925*4882a593Smuzhiyun 	insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1);
926*4882a593Smuzhiyun #endif
927*4882a593Smuzhiyun }
928*4882a593Smuzhiyun 
929*4882a593Smuzhiyun #endif /* CONFIG_IDE_SWAP_IO */
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun #ifdef CONFIG_BLK
ide_read(struct udevice * dev,lbaint_t blknr,lbaint_t blkcnt,void * buffer)932*4882a593Smuzhiyun ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
933*4882a593Smuzhiyun 	       void *buffer)
934*4882a593Smuzhiyun #else
935*4882a593Smuzhiyun ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
936*4882a593Smuzhiyun 	       void *buffer)
937*4882a593Smuzhiyun #endif
938*4882a593Smuzhiyun {
939*4882a593Smuzhiyun #ifdef CONFIG_BLK
940*4882a593Smuzhiyun 	struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
941*4882a593Smuzhiyun #endif
942*4882a593Smuzhiyun 	int device = block_dev->devnum;
943*4882a593Smuzhiyun 	ulong n = 0;
944*4882a593Smuzhiyun 	unsigned char c;
945*4882a593Smuzhiyun 	unsigned char pwrsave = 0;	/* power save */
946*4882a593Smuzhiyun 
947*4882a593Smuzhiyun #ifdef CONFIG_LBA48
948*4882a593Smuzhiyun 	unsigned char lba48 = 0;
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 	if (blknr & 0x0000fffff0000000ULL) {
951*4882a593Smuzhiyun 		/* more than 28 bits used, use 48bit mode */
952*4882a593Smuzhiyun 		lba48 = 1;
953*4882a593Smuzhiyun 	}
954*4882a593Smuzhiyun #endif
955*4882a593Smuzhiyun 	debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n",
956*4882a593Smuzhiyun 	      device, blknr, blkcnt, (ulong) buffer);
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	/* Select device
959*4882a593Smuzhiyun 	 */
960*4882a593Smuzhiyun 	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
961*4882a593Smuzhiyun 	c = ide_wait(device, IDE_TIME_OUT);
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 	if (c & ATA_STAT_BUSY) {
964*4882a593Smuzhiyun 		printf("IDE read: device %d not ready\n", device);
965*4882a593Smuzhiyun 		goto IDE_READ_E;
966*4882a593Smuzhiyun 	}
967*4882a593Smuzhiyun 
968*4882a593Smuzhiyun 	/* first check if the drive is in Powersaving mode, if yes,
969*4882a593Smuzhiyun 	 * increase the timeout value */
970*4882a593Smuzhiyun 	ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR);
971*4882a593Smuzhiyun 	udelay(50);
972*4882a593Smuzhiyun 
973*4882a593Smuzhiyun 	c = ide_wait(device, IDE_TIME_OUT);	/* can't take over 500 ms */
974*4882a593Smuzhiyun 
975*4882a593Smuzhiyun 	if (c & ATA_STAT_BUSY) {
976*4882a593Smuzhiyun 		printf("IDE read: device %d not ready\n", device);
977*4882a593Smuzhiyun 		goto IDE_READ_E;
978*4882a593Smuzhiyun 	}
979*4882a593Smuzhiyun 	if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
980*4882a593Smuzhiyun 		printf("No Powersaving mode %X\n", c);
981*4882a593Smuzhiyun 	} else {
982*4882a593Smuzhiyun 		c = ide_inb(device, ATA_SECT_CNT);
983*4882a593Smuzhiyun 		debug("Powersaving %02X\n", c);
984*4882a593Smuzhiyun 		if (c == 0)
985*4882a593Smuzhiyun 			pwrsave = 1;
986*4882a593Smuzhiyun 	}
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun 
989*4882a593Smuzhiyun 	while (blkcnt-- > 0) {
990*4882a593Smuzhiyun 		c = ide_wait(device, IDE_TIME_OUT);
991*4882a593Smuzhiyun 
992*4882a593Smuzhiyun 		if (c & ATA_STAT_BUSY) {
993*4882a593Smuzhiyun 			printf("IDE read: device %d not ready\n", device);
994*4882a593Smuzhiyun 			break;
995*4882a593Smuzhiyun 		}
996*4882a593Smuzhiyun #ifdef CONFIG_LBA48
997*4882a593Smuzhiyun 		if (lba48) {
998*4882a593Smuzhiyun 			/* write high bits */
999*4882a593Smuzhiyun 			ide_outb(device, ATA_SECT_CNT, 0);
1000*4882a593Smuzhiyun 			ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
1001*4882a593Smuzhiyun #ifdef CONFIG_SYS_64BIT_LBA
1002*4882a593Smuzhiyun 			ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
1003*4882a593Smuzhiyun 			ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
1004*4882a593Smuzhiyun #else
1005*4882a593Smuzhiyun 			ide_outb(device, ATA_LBA_MID, 0);
1006*4882a593Smuzhiyun 			ide_outb(device, ATA_LBA_HIGH, 0);
1007*4882a593Smuzhiyun #endif
1008*4882a593Smuzhiyun 		}
1009*4882a593Smuzhiyun #endif
1010*4882a593Smuzhiyun 		ide_outb(device, ATA_SECT_CNT, 1);
1011*4882a593Smuzhiyun 		ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
1012*4882a593Smuzhiyun 		ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
1013*4882a593Smuzhiyun 		ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
1014*4882a593Smuzhiyun 
1015*4882a593Smuzhiyun #ifdef CONFIG_LBA48
1016*4882a593Smuzhiyun 		if (lba48) {
1017*4882a593Smuzhiyun 			ide_outb(device, ATA_DEV_HD,
1018*4882a593Smuzhiyun 				 ATA_LBA | ATA_DEVICE(device));
1019*4882a593Smuzhiyun 			ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT);
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun 		} else
1022*4882a593Smuzhiyun #endif
1023*4882a593Smuzhiyun 		{
1024*4882a593Smuzhiyun 			ide_outb(device, ATA_DEV_HD, ATA_LBA |
1025*4882a593Smuzhiyun 				 ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
1026*4882a593Smuzhiyun 			ide_outb(device, ATA_COMMAND, ATA_CMD_READ);
1027*4882a593Smuzhiyun 		}
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 		udelay(50);
1030*4882a593Smuzhiyun 
1031*4882a593Smuzhiyun 		if (pwrsave) {
1032*4882a593Smuzhiyun 			/* may take up to 4 sec */
1033*4882a593Smuzhiyun 			c = ide_wait(device, IDE_SPIN_UP_TIME_OUT);
1034*4882a593Smuzhiyun 			pwrsave = 0;
1035*4882a593Smuzhiyun 		} else {
1036*4882a593Smuzhiyun 			/* can't take over 500 ms */
1037*4882a593Smuzhiyun 			c = ide_wait(device, IDE_TIME_OUT);
1038*4882a593Smuzhiyun 		}
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun 		if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
1041*4882a593Smuzhiyun 		    ATA_STAT_DRQ) {
1042*4882a593Smuzhiyun 			printf("Error (no IRQ) dev %d blk " LBAF
1043*4882a593Smuzhiyun 			       ": status %#02x\n", device, blknr, c);
1044*4882a593Smuzhiyun 			break;
1045*4882a593Smuzhiyun 		}
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun 		ide_input_data(device, buffer, ATA_SECTORWORDS);
1048*4882a593Smuzhiyun 		(void) ide_inb(device, ATA_STATUS);	/* clear IRQ */
1049*4882a593Smuzhiyun 
1050*4882a593Smuzhiyun 		++n;
1051*4882a593Smuzhiyun 		++blknr;
1052*4882a593Smuzhiyun 		buffer += ATA_BLOCKSIZE;
1053*4882a593Smuzhiyun 	}
1054*4882a593Smuzhiyun IDE_READ_E:
1055*4882a593Smuzhiyun 	return n;
1056*4882a593Smuzhiyun }
1057*4882a593Smuzhiyun 
1058*4882a593Smuzhiyun #ifdef CONFIG_BLK
ide_write(struct udevice * dev,lbaint_t blknr,lbaint_t blkcnt,const void * buffer)1059*4882a593Smuzhiyun ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
1060*4882a593Smuzhiyun 		const void *buffer)
1061*4882a593Smuzhiyun #else
1062*4882a593Smuzhiyun ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
1063*4882a593Smuzhiyun 		const void *buffer)
1064*4882a593Smuzhiyun #endif
1065*4882a593Smuzhiyun {
1066*4882a593Smuzhiyun #ifdef CONFIG_BLK
1067*4882a593Smuzhiyun 	struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
1068*4882a593Smuzhiyun #endif
1069*4882a593Smuzhiyun 	int device = block_dev->devnum;
1070*4882a593Smuzhiyun 	ulong n = 0;
1071*4882a593Smuzhiyun 	unsigned char c;
1072*4882a593Smuzhiyun 
1073*4882a593Smuzhiyun #ifdef CONFIG_LBA48
1074*4882a593Smuzhiyun 	unsigned char lba48 = 0;
1075*4882a593Smuzhiyun 
1076*4882a593Smuzhiyun 	if (blknr & 0x0000fffff0000000ULL) {
1077*4882a593Smuzhiyun 		/* more than 28 bits used, use 48bit mode */
1078*4882a593Smuzhiyun 		lba48 = 1;
1079*4882a593Smuzhiyun 	}
1080*4882a593Smuzhiyun #endif
1081*4882a593Smuzhiyun 
1082*4882a593Smuzhiyun 	/* Select device
1083*4882a593Smuzhiyun 	 */
1084*4882a593Smuzhiyun 	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
1085*4882a593Smuzhiyun 
1086*4882a593Smuzhiyun 	while (blkcnt-- > 0) {
1087*4882a593Smuzhiyun 		c = ide_wait(device, IDE_TIME_OUT);
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun 		if (c & ATA_STAT_BUSY) {
1090*4882a593Smuzhiyun 			printf("IDE read: device %d not ready\n", device);
1091*4882a593Smuzhiyun 			goto WR_OUT;
1092*4882a593Smuzhiyun 		}
1093*4882a593Smuzhiyun #ifdef CONFIG_LBA48
1094*4882a593Smuzhiyun 		if (lba48) {
1095*4882a593Smuzhiyun 			/* write high bits */
1096*4882a593Smuzhiyun 			ide_outb(device, ATA_SECT_CNT, 0);
1097*4882a593Smuzhiyun 			ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
1098*4882a593Smuzhiyun #ifdef CONFIG_SYS_64BIT_LBA
1099*4882a593Smuzhiyun 			ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
1100*4882a593Smuzhiyun 			ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
1101*4882a593Smuzhiyun #else
1102*4882a593Smuzhiyun 			ide_outb(device, ATA_LBA_MID, 0);
1103*4882a593Smuzhiyun 			ide_outb(device, ATA_LBA_HIGH, 0);
1104*4882a593Smuzhiyun #endif
1105*4882a593Smuzhiyun 		}
1106*4882a593Smuzhiyun #endif
1107*4882a593Smuzhiyun 		ide_outb(device, ATA_SECT_CNT, 1);
1108*4882a593Smuzhiyun 		ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
1109*4882a593Smuzhiyun 		ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
1110*4882a593Smuzhiyun 		ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
1111*4882a593Smuzhiyun 
1112*4882a593Smuzhiyun #ifdef CONFIG_LBA48
1113*4882a593Smuzhiyun 		if (lba48) {
1114*4882a593Smuzhiyun 			ide_outb(device, ATA_DEV_HD,
1115*4882a593Smuzhiyun 				 ATA_LBA | ATA_DEVICE(device));
1116*4882a593Smuzhiyun 			ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT);
1117*4882a593Smuzhiyun 
1118*4882a593Smuzhiyun 		} else
1119*4882a593Smuzhiyun #endif
1120*4882a593Smuzhiyun 		{
1121*4882a593Smuzhiyun 			ide_outb(device, ATA_DEV_HD, ATA_LBA |
1122*4882a593Smuzhiyun 				 ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
1123*4882a593Smuzhiyun 			ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE);
1124*4882a593Smuzhiyun 		}
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun 		udelay(50);
1127*4882a593Smuzhiyun 
1128*4882a593Smuzhiyun 		/* can't take over 500 ms */
1129*4882a593Smuzhiyun 		c = ide_wait(device, IDE_TIME_OUT);
1130*4882a593Smuzhiyun 
1131*4882a593Smuzhiyun 		if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
1132*4882a593Smuzhiyun 		    ATA_STAT_DRQ) {
1133*4882a593Smuzhiyun 			printf("Error (no IRQ) dev %d blk " LBAF
1134*4882a593Smuzhiyun 			       ": status %#02x\n", device, blknr, c);
1135*4882a593Smuzhiyun 			goto WR_OUT;
1136*4882a593Smuzhiyun 		}
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun 		ide_output_data(device, buffer, ATA_SECTORWORDS);
1139*4882a593Smuzhiyun 		c = ide_inb(device, ATA_STATUS);	/* clear IRQ */
1140*4882a593Smuzhiyun 		++n;
1141*4882a593Smuzhiyun 		++blknr;
1142*4882a593Smuzhiyun 		buffer += ATA_BLOCKSIZE;
1143*4882a593Smuzhiyun 	}
1144*4882a593Smuzhiyun WR_OUT:
1145*4882a593Smuzhiyun 	return n;
1146*4882a593Smuzhiyun }
1147*4882a593Smuzhiyun 
1148*4882a593Smuzhiyun #if defined(CONFIG_OF_IDE_FIXUP)
ide_device_present(int dev)1149*4882a593Smuzhiyun int ide_device_present(int dev)
1150*4882a593Smuzhiyun {
1151*4882a593Smuzhiyun 	if (dev >= CONFIG_SYS_IDE_MAXBUS)
1152*4882a593Smuzhiyun 		return 0;
1153*4882a593Smuzhiyun 	return ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1;
1154*4882a593Smuzhiyun }
1155*4882a593Smuzhiyun #endif
1156*4882a593Smuzhiyun 
1157*4882a593Smuzhiyun #ifdef CONFIG_BLK
ide_blk_probe(struct udevice * udev)1158*4882a593Smuzhiyun static int ide_blk_probe(struct udevice *udev)
1159*4882a593Smuzhiyun {
1160*4882a593Smuzhiyun 	struct blk_desc *desc = dev_get_uclass_platdata(udev);
1161*4882a593Smuzhiyun 
1162*4882a593Smuzhiyun 	/* fill in device vendor/product/rev strings */
1163*4882a593Smuzhiyun 	strncpy(desc->vendor, ide_dev_desc[desc->devnum].vendor,
1164*4882a593Smuzhiyun 		BLK_VEN_SIZE);
1165*4882a593Smuzhiyun 	desc->vendor[BLK_VEN_SIZE] = '\0';
1166*4882a593Smuzhiyun 	strncpy(desc->product, ide_dev_desc[desc->devnum].product,
1167*4882a593Smuzhiyun 		BLK_PRD_SIZE);
1168*4882a593Smuzhiyun 	desc->product[BLK_PRD_SIZE] = '\0';
1169*4882a593Smuzhiyun 	strncpy(desc->revision, ide_dev_desc[desc->devnum].revision,
1170*4882a593Smuzhiyun 		BLK_REV_SIZE);
1171*4882a593Smuzhiyun 	desc->revision[BLK_REV_SIZE] = '\0';
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun 	part_init(desc);
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun 	return 0;
1176*4882a593Smuzhiyun }
1177*4882a593Smuzhiyun 
1178*4882a593Smuzhiyun static const struct blk_ops ide_blk_ops = {
1179*4882a593Smuzhiyun 	.read	= ide_read,
1180*4882a593Smuzhiyun 	.write	= ide_write,
1181*4882a593Smuzhiyun };
1182*4882a593Smuzhiyun 
1183*4882a593Smuzhiyun U_BOOT_DRIVER(ide_blk) = {
1184*4882a593Smuzhiyun 	.name		= "ide_blk",
1185*4882a593Smuzhiyun 	.id		= UCLASS_BLK,
1186*4882a593Smuzhiyun 	.ops		= &ide_blk_ops,
1187*4882a593Smuzhiyun 	.probe		= ide_blk_probe,
1188*4882a593Smuzhiyun };
1189*4882a593Smuzhiyun 
ide_probe(struct udevice * udev)1190*4882a593Smuzhiyun static int ide_probe(struct udevice *udev)
1191*4882a593Smuzhiyun {
1192*4882a593Smuzhiyun 	struct udevice *blk_dev;
1193*4882a593Smuzhiyun 	char name[20];
1194*4882a593Smuzhiyun 	int blksz;
1195*4882a593Smuzhiyun 	lbaint_t size;
1196*4882a593Smuzhiyun 	int i;
1197*4882a593Smuzhiyun 	int ret;
1198*4882a593Smuzhiyun 
1199*4882a593Smuzhiyun 	for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; i++) {
1200*4882a593Smuzhiyun 		if (ide_dev_desc[i].type != DEV_TYPE_UNKNOWN) {
1201*4882a593Smuzhiyun 			sprintf(name, "blk#%d", i);
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun 			blksz = ide_dev_desc[i].blksz;
1204*4882a593Smuzhiyun 			size = blksz * ide_dev_desc[i].lba;
1205*4882a593Smuzhiyun 
1206*4882a593Smuzhiyun 			/*
1207*4882a593Smuzhiyun 			 * With CDROM, if there is no CD inserted, blksz will
1208*4882a593Smuzhiyun 			 * be zero, don't bother to create IDE block device.
1209*4882a593Smuzhiyun 			 */
1210*4882a593Smuzhiyun 			if (!blksz)
1211*4882a593Smuzhiyun 				continue;
1212*4882a593Smuzhiyun 			ret = blk_create_devicef(udev, "ide_blk", name,
1213*4882a593Smuzhiyun 						 IF_TYPE_IDE, i,
1214*4882a593Smuzhiyun 						 blksz, size, &blk_dev);
1215*4882a593Smuzhiyun 			if (ret)
1216*4882a593Smuzhiyun 				return ret;
1217*4882a593Smuzhiyun 		}
1218*4882a593Smuzhiyun 	}
1219*4882a593Smuzhiyun 
1220*4882a593Smuzhiyun 	return 0;
1221*4882a593Smuzhiyun }
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun U_BOOT_DRIVER(ide) = {
1224*4882a593Smuzhiyun 	.name		= "ide",
1225*4882a593Smuzhiyun 	.id		= UCLASS_IDE,
1226*4882a593Smuzhiyun 	.probe		= ide_probe,
1227*4882a593Smuzhiyun };
1228*4882a593Smuzhiyun 
1229*4882a593Smuzhiyun struct pci_device_id ide_supported[] = {
1230*4882a593Smuzhiyun 	{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xffff00) },
1231*4882a593Smuzhiyun 	{ }
1232*4882a593Smuzhiyun };
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun U_BOOT_PCI_DEVICE(ide, ide_supported);
1235*4882a593Smuzhiyun 
1236*4882a593Smuzhiyun UCLASS_DRIVER(ide) = {
1237*4882a593Smuzhiyun 	.name		= "ide",
1238*4882a593Smuzhiyun 	.id		= UCLASS_IDE,
1239*4882a593Smuzhiyun };
1240*4882a593Smuzhiyun #else
1241*4882a593Smuzhiyun U_BOOT_LEGACY_BLK(ide) = {
1242*4882a593Smuzhiyun 	.if_typename	= "ide",
1243*4882a593Smuzhiyun 	.if_type	= IF_TYPE_IDE,
1244*4882a593Smuzhiyun 	.max_devs	= CONFIG_SYS_IDE_MAXDEVICE,
1245*4882a593Smuzhiyun 	.desc		= ide_dev_desc,
1246*4882a593Smuzhiyun };
1247*4882a593Smuzhiyun #endif
1248