RT-AC56 3.0.0.4.374.37 core
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / dev / dev_ide_common.c
blob66562b1e5ad02b316fed1c9de2b146b7069e4c81
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * Generic IDE disk driver File: dev_ide_common.c
5 *
6 * This is a simple driver for IDE hard disks. The mechanics
7 * of talking to the I/O ports are abstracted sufficiently to make
8 * this driver usable for various bus interfaces.
9 *
10 * Author: Mitch Lichtenberg (mpl@broadcom.com)
12 *********************************************************************
14 * Copyright 2000,2001,2002,2003
15 * Broadcom Corporation. All rights reserved.
17 * This software is furnished under license and may be used and
18 * copied only in accordance with the following terms and
19 * conditions. Subject to these conditions, you may download,
20 * copy, install, use, modify and distribute modified or unmodified
21 * copies of this software in source and/or binary form. No title
22 * or ownership is transferred hereby.
24 * 1) Any source code used, modified or distributed must reproduce
25 * and retain this copyright notice and list of conditions
26 * as they appear in the source file.
28 * 2) No right is granted to use any trade name, trademark, or
29 * logo of Broadcom Corporation. The "Broadcom Corporation"
30 * name may not be used to endorse or promote products derived
31 * from this software without the prior written permission of
32 * Broadcom Corporation.
34 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
35 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
36 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
37 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
38 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
39 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
40 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
45 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
46 * THE POSSIBILITY OF SUCH DAMAGE.
47 ********************************************************************* */
50 #include "lib_types.h"
51 #include "lib_malloc.h"
52 #include "lib_printf.h"
53 #include "lib_string.h"
54 #include "cfe_timer.h"
55 #include "cfe_iocb.h"
56 #include "cfe_device.h"
57 #include "cfe_ioctl.h"
58 #include "cfe_error.h"
60 #include "dev_ide_common.h"
62 #include "dev_ide.h"
64 /* *********************************************************************
65 * Macros
66 ********************************************************************* */
68 #define DISK_MASTER 0
69 #define DISK_SLAVE 1
71 #define IDE_WRITEREG8(ide,reg,val) IDEDISP_WRITEREG8(ide->idecommon_dispatch,reg,val)
72 #define IDE_WRITEREG16(ide,reg,val) IDEDISP_WRITEREG8(ide->idecommon_dispatch,reg,val)
73 #define IDE_WRITEBUF(ide,reg,buf,len) IDEDISP_WRITEBUF(ide->idecommon_dispatch,reg,buf,len)
74 #define IDE_READREG8(ide,reg) IDEDISP_READREG8(ide->idecommon_dispatch,reg)
75 #define IDE_READREG16(ide,reg) IDEDISP_READREG16(ide->idecommon_dispatch,reg)
76 #define IDE_READBUF(ide,reg,buf,len) IDEDISP_READBUF(ide->idecommon_dispatch,reg,buf,len)
78 #define GETWORD_LE(buf,wordidx) (((unsigned int) (buf)[(wordidx)*2]) + \
79 (((unsigned int) (buf)[(wordidx)*2+1]) << 8))
81 #define _IDE_DEBUG_
84 static void idecommon_testdrq(idecommon_t *ide);
86 /* *********************************************************************
87 * idecommon_sectorshift(size)
89 * Given a sector size, return log2(size). We cheat; this is
90 * only needed for 2048 and 512-byte sectors.
91 * Explicitly using shifts and masks in sector number calculations
92 * helps on 32-bit-only platforms, since we probably won't need
93 * a helper library.
95 * Input parameters:
96 * size - sector size
98 * Return value:
99 * # of bits to shift
100 ********************************************************************* */
102 #define idecommon_sectorshift(size) (((size)==2048)?11:9)
104 /* *********************************************************************
105 * idecommon_waitnotbusy(ide)
107 * Wait for an IDE device to report "not busy"
109 * Input parameters:
110 * ide - IDE interface
112 * Return value:
113 * 0 if ok, else -1 if timeout
114 ********************************************************************* */
116 static int idecommon_waitnotbusy(idecommon_t *ide)
118 int32_t timer;
119 uint8_t status;
121 TIMER_SET(timer,10*CFE_HZ);
123 while (!TIMER_EXPIRED(timer)) {
124 status = IDE_READREG8(ide,IDE_REG_STATUS);
125 if (!(status & IDE_STS_BSY) && (status & IDE_STS_DRQ)) {
126 idecommon_testdrq(ide);
127 continue;
129 if ((status & (IDE_STS_BSY | IDE_STS_DRQ )) == 0) return 0;
130 POLL();
133 #ifdef _IDE_DEBUG_
134 xprintf("Device did not become unbusy\n");
135 #endif
136 return -1;
140 /* *********************************************************************
141 * idecommon_waitbusy(idx)
143 * Wait for an IDE disk to start processing a command, or at
144 * least long enough to indicate that it is doing so.
145 * The code below looks suspiciously like a timing loop.
146 * unfortunately, that's what it is, determined empirically
147 * for certain ATA flash cards. Without this many reads to the
148 * ALTSTAT register, the PCMCIA controller deasserts the
149 * card detect pins briefly. Anyone have any clues?
151 * Input parameters:
152 * ide - IDE interface
154 * Return value:
155 * void
156 ********************************************************************* */
158 static void idecommon_waitbusy(idecommon_t *ide)
160 int idx;
162 for (idx = 0; idx < 10; idx++) {
163 IDE_READREG8(ide,IDE_REG_ALTSTAT);
164 IDE_READREG8(ide,IDE_REG_ALTSTAT);
165 IDE_READREG8(ide,IDE_REG_ALTSTAT);
166 IDE_READREG8(ide,IDE_REG_ALTSTAT);
171 /* *********************************************************************
172 * idecommon_wait_drq(ide)
174 * Wait for the BUSY bit to be clear and the DRQ bit to be set.
175 * This is usually the indication that it's time to transfer data.
177 * Input parameters:
178 * ide - IDE interface
179 * 0 if DRQ is set
180 * -1 if timeout occured
181 ********************************************************************* */
183 static int idecommon_wait_drq(idecommon_t *ide)
185 int32_t timer;
186 uint8_t status;
188 TIMER_SET(timer,10*CFE_HZ);
190 while (!TIMER_EXPIRED(timer)) {
191 POLL();
192 status = IDE_READREG8(ide,IDE_REG_STATUS);
193 if (!(status & IDE_STS_BSY) && (status & IDE_STS_ERR)) {
194 xprintf("Drive status: %02X error %02X\n",status,
195 IDE_READREG8(ide,IDE_REG_ERROR));
196 return -1;
198 if (!(status & IDE_STS_BSY) && (status & IDE_STS_DRQ)) return 0;
201 #ifdef _IDE_DEBUG_
202 xprintf("Timeout waiting for disk\n");
203 #endif
205 return -1;
208 /* *********************************************************************
209 * idecommon_testdrq(ide)
211 * Debug routine. Check the DRQ bit. If it's set, it is not
212 * supposed to be, so transfer data until it clears and report
213 * how much we had to transfer.
215 * Input parameters:
216 * ide - IDE interface
218 * Return value:
219 * nothing
220 ********************************************************************* */
222 #ifdef _IDE_DEBUG_
223 static void idecommon_testdrq(idecommon_t *ide)
225 uint8_t status;
226 uint16_t data;
227 int idx;
229 status = IDE_READREG8(ide,IDE_REG_STATUS);
230 if (status & IDE_STS_DRQ) {
231 xprintf("Error: DRQ should be zero\n");
232 idx = 0;
233 while (status & IDE_STS_DRQ) {
234 data = IDE_READREG16(ide,IDE_REG_DATA);
235 idx++;
236 status = IDE_READREG8(ide,IDE_REG_STATUS);
238 xprintf("Had to read data %d times to clear DRQ\n",idx);
241 #else
242 #define idecommon_testdrq(ide)
243 #endif
246 /* *********************************************************************
247 * idecommon_dumpregs(ide)
249 * Dump out the IDE registers. (debug routine)
251 * Input parameters:
252 * ide - ide disk
254 * Return value:
255 * nothing
256 ********************************************************************* */
258 static void idecommon_dumpregs(idecommon_t *ide)
263 /* *********************************************************************
264 * idecommon_reset(ide)
266 * Reset the IDE interface.
268 * Input parameters:
269 * ide - IDE interface
271 * Return value:
272 * 0 if ok, else -1 if a timeout occured
273 ********************************************************************* */
275 static int idecommon_reset(idecommon_t *ide)
277 return 0;
280 /* *********************************************************************
281 * idecommon_identify(ide,buffer)
283 * Execute an IDENTIFY command to get information about the disk.
285 * Input parameters:
286 * ide - IDE interface
287 * buffer - pointer to 512 byte buffer
289 * Return value:
290 * 0 if ok
291 * else error code
292 ********************************************************************* */
294 int idecommon_identify(idecommon_t *ide,unsigned char *buffer)
297 /* Device Select Protocol; see ATAPI-4 sect 9.6 */
299 if (idecommon_waitnotbusy(ide) < 0) return -1;
300 IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4)|0);
301 if (idecommon_waitnotbusy(ide) < 0) return -1;
303 /* Set device registers */
305 IDE_WRITEREG8(ide,IDE_REG_CYLLSB,0);
306 IDE_WRITEREG8(ide,IDE_REG_CYLMSB,0);
307 IDE_WRITEREG8(ide,IDE_REG_SECNUM,1);
308 IDE_WRITEREG8(ide,IDE_REG_SECCNT,1);
310 idecommon_testdrq(ide);
312 /* Issue command, then read ALT STATUS (9.7) */
314 if (ide->idecommon_atapi) {
315 IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_ATAPI_IDENTIFY);
317 else {
318 IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_DRIVE_INFO);
321 IDE_READREG8(ide,IDE_REG_ALTSTAT);
322 idecommon_waitbusy(ide); /* should not be necessary */
324 /* Wait BSY=0 && DRQ=1, then read buffer, see sect 9.7 */
326 if (idecommon_wait_drq(ide) < 0) return -1;
327 IDE_READBUF(ide,IDE_REG_DATA,buffer,DISK_SECTORSIZE);
329 idecommon_testdrq(ide);
331 return 0;
334 /* *********************************************************************
335 * idecommon_packet(ide,packet,pktlen,databuf,datalen)
337 * Process an IDE "packet" command, for ATAPI devices
339 * Input parameters:
340 * ide - IDE interface
341 * packet,pktlen - command packet
342 * databuf,datalen - data buffer
344 * Return value:
345 * 0 if ok
346 * else error code
347 ********************************************************************* */
349 static int idecommon_packet(idecommon_t *ide,
350 uint8_t *packet,int pktlen,
351 uint8_t *databuf,int datalen)
353 uint8_t status;
356 * Not valid on non-ATAPI disks
359 if (!ide->idecommon_atapi) return -1;
362 * Set up the standard IDE registers for an ATAPI PACKET command
365 /* Device Select Protocol */
366 if (idecommon_waitnotbusy(ide) < 0) return -1;
367 IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4));
368 if (idecommon_waitnotbusy(ide) < 0) return -1;
370 /* Device Registers */
371 IDE_WRITEREG8(ide,IDE_REG_BCLSB,(datalen & 0xFF));
372 IDE_WRITEREG8(ide,IDE_REG_BCMSB,((datalen >> 8) & 0xFF));
373 IDE_WRITEREG8(ide,IDE_REG_SECNUM,0);
374 IDE_WRITEREG8(ide,IDE_REG_SECCNT,0);
375 IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_ATAPI_PACKET);
378 * Wait for the DRQ bit to indicate that we should send
379 * the packet.
382 if (idecommon_wait_drq(ide) < 0) return -1;
384 status = IDE_READREG8(ide,IDE_REG_IR);
387 * Send the packet to the device
390 IDE_WRITEBUF(ide,IDE_REG_DATA,packet,pktlen);
393 * Wait for BSY to be cleared and DRQ to be set.
396 if (idecommon_wait_drq(ide) < 0) return -1;
397 status = IDE_READREG8(ide,IDE_REG_ALTSTAT);
398 if (idecommon_wait_drq(ide) < 0) return -1;
399 status = IDE_READREG8(ide,IDE_REG_IR);
403 * Transfer data, if necessary. The direction will depend
404 * on what the drive says. If this is a non-data command,
405 * passing databuf == NULL can avoid all this.
408 if (databuf) {
409 status = IDE_READREG8(ide,IDE_REG_IR);
410 if (status & IDE_IR_CD) {
411 xprintf("Error: Command/data should be zero\n");
414 if (status & IDE_IR_IO) { /* from device (READ) */
415 IDE_READBUF(ide,IDE_REG_DATA,databuf,datalen);
417 else { /* to device (WRITE) */
418 IDE_WRITEBUF(ide,IDE_REG_DATA,databuf,datalen);
424 idecommon_testdrq(ide);
426 return 0;
431 /* *********************************************************************
432 * idecommon_request_sense(ide)
434 * Request sense data. This also clears a UNIT_ATTENTION condition
436 * Input parameters:
437 * ide - IDE interface
439 * Return value:
440 * 0 if ok
441 * else error code
442 ********************************************************************* */
443 static int idecommon_request_sense(idecommon_t *ide)
445 uint8_t cdb[12];
446 uint8_t sensedata[32];
447 int res;
448 int numbytes;
450 numbytes = sizeof(sensedata);
452 cdb[0] = CDB_CMD_REQSENSE;
453 cdb[1] = 0;
454 cdb[2] = 0;
455 cdb[3] = 0;
456 cdb[4] = sizeof(sensedata);
457 cdb[5] = 0;
458 cdb[6] = 0;
459 cdb[7] = 0;
460 cdb[8] = 0;
461 cdb[9] = 0;
462 cdb[10] = 0;
463 cdb[11] = 0;
465 memset(sensedata,0,sizeof(sensedata));
467 res = idecommon_packet(ide,cdb,sizeof(cdb),sensedata,numbytes);
470 idecommon_testdrq(ide);
472 return res;
476 /* *********************************************************************
477 * idecommon_read_atapi(ide,lba,numsec,buffer)
479 * Read sector(s) from the device. This version is for ATAPI devs.
481 * Input parameters:
482 * ide - IDE interface
483 * lba - logical block address
484 * numsec - number of sectors
485 * buffer - buffer address
487 * Return value:
488 * 0 if ok
489 * else error code
490 ********************************************************************* */
492 static int idecommon_read_atapi(idecommon_t *ide,uint64_t lba,
493 int numsec,unsigned char *buffer)
495 uint8_t cdb[12];
496 int res = 0;
497 int numbytes;
498 int idx;
500 numbytes = numsec << idecommon_sectorshift(ide->idecommon_sectorsize);
502 cdb[0] = CDB_CMD_READ;
503 cdb[1] = 0;
504 cdb[2] = ((lba >> 24) & 0xFF);
505 cdb[3] = ((lba >> 16) & 0xFF);
506 cdb[4] = ((lba >> 8) & 0xFF);
507 cdb[5] = ((lba >> 0) & 0xFF);
508 cdb[6] = 0;
509 cdb[7] = ((numsec >> 8) & 0xFF);
510 cdb[8] = ((numsec >> 0) & 0xFF);
511 cdb[9] = 0;
512 cdb[10] = 0;
513 cdb[11] = 0;
515 for (idx = 0; idx < 4; idx++) {
516 res = idecommon_packet(ide,cdb,sizeof(cdb),buffer,numbytes);
517 if (res < 0) {
518 idecommon_request_sense(ide);
519 continue;
521 break;
524 return res;
528 /* *********************************************************************
529 * idecommon_write_atapi(ide,lba,numsec,buffer)
531 * Write sector(s) to the device. This version is for ATAPI disks
533 * Input parameters:
534 * ide - IDE interface
535 * lba - logical block address
536 * numsec - number of sectors
537 * buffer - buffer address
539 * Return value:
540 * 0 if ok
541 * else error code
542 ********************************************************************* */
544 static int idecommon_write_atapi(idecommon_t *ide,uint64_t lba,
545 int numsec,unsigned char *buffer)
547 uint8_t cdb[12];
548 int res;
549 int numbytes;
551 numbytes = numsec << idecommon_sectorshift(ide->idecommon_sectorsize);
553 cdb[0] = CDB_CMD_WRITE;
554 cdb[1] = 0;
555 cdb[2] = ((lba >> 24) & 0xFF);
556 cdb[3] = ((lba >> 16) & 0xFF);
557 cdb[4] = ((lba >> 8) & 0xFF);
558 cdb[5] = ((lba >> 0) & 0xFF);
559 cdb[6] = 0;
560 cdb[7] = ((numsec >> 8) & 0xFF);
561 cdb[8] = ((numsec >> 0) & 0xFF);
562 cdb[9] = 0;
563 cdb[10] = 0;
564 cdb[11] = 0;
566 res = idecommon_packet(ide,cdb,sizeof(cdb),buffer,numbytes);
568 return res;
572 /* *********************************************************************
573 * idecommon_read_lba(ide,lba,numsec,buffer)
575 * Read sector(s) from the device.
577 * Input parameters:
578 * ide - IDE interface
579 * lba - logical block address
580 * numsec - number of sectors
581 * buffer - buffer address
583 * Return value:
584 * 0 if ok
585 * else error code
586 ********************************************************************* */
588 static int idecommon_read_lba(idecommon_t *ide,uint64_t lba,int numsec,unsigned char *buffer)
590 int secidx;
591 unsigned char *ptr;
593 if (idecommon_waitnotbusy(ide) < 0) return -1;
594 IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4) | ((lba >> 24) & 0x0F) | 0x40);
595 if (idecommon_waitnotbusy(ide) < 0) return -1;
597 IDE_WRITEREG8(ide,IDE_REG_CYLMSB,((lba >> 16) & 0xFF));
598 IDE_WRITEREG8(ide,IDE_REG_CYLLSB,((lba >> 8) & 0xFF));
599 IDE_WRITEREG8(ide,IDE_REG_SECNUM,(lba & 0xFF));
600 IDE_WRITEREG8(ide,IDE_REG_SECCNT,numsec);
602 idecommon_testdrq(ide);
604 IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_READ);
606 idecommon_waitbusy(ide);
607 if (idecommon_wait_drq(ide) < 0) return -1;
609 ptr = buffer;
611 for (secidx = 0; secidx < numsec; secidx++) {
612 IDE_READBUF(ide,IDE_REG_DATA,ptr,ide->idecommon_sectorsize);
613 ptr += ide->idecommon_sectorsize;
616 idecommon_testdrq(ide);
618 return 0;
622 /* *********************************************************************
623 * idecommon_write_lba(ide,lba,numsec,buffer)
625 * Write sector(s) from the device.
627 * Input parameters:
628 * ide - IDE interface
629 * lba - logical block address
630 * numsec - number of sectors
631 * buffer - buffer address
633 * Return value:
634 * 0 if ok
635 * else error code
636 ********************************************************************* */
638 static int idecommon_write_lba(idecommon_t *ide,uint64_t lba,int numsec,unsigned char *buffer)
640 int secidx;
641 uint8_t *ptr;
643 if (idecommon_waitnotbusy(ide) < 0) return -1;
644 IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4) | ((lba >> 24) & 0x0F) | 0x40);
645 if (idecommon_waitnotbusy(ide) < 0) return -1;
647 IDE_WRITEREG8(ide,IDE_REG_CYLMSB,((lba >> 16) & 0xFF));
648 IDE_WRITEREG8(ide,IDE_REG_CYLLSB,((lba >> 8) & 0xFF));
649 IDE_WRITEREG8(ide,IDE_REG_SECNUM,(lba & 0xFF));
650 IDE_WRITEREG8(ide,IDE_REG_SECCNT,numsec);
652 IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_WRITE);
654 if (idecommon_wait_drq(ide) < 0) return -1;
656 ptr = buffer;
658 for (secidx = 0; secidx < numsec; secidx++) {
659 IDE_WRITEBUF(ide,IDE_REG_DATA,ptr,ide->idecommon_sectorsize);
660 ptr += ide->idecommon_sectorsize;
663 idecommon_testdrq(ide);
665 return 0;
669 /* *********************************************************************
670 * idecommon_diagnostic(ide)
672 * run the device diagnostics on the IDE device. This also
673 * helps us determine if it's an IDE or ATAPI disk, since the
674 * diagnostic will leave a signature in the registers.
676 * Input parameters:
677 * softc - IDE interface
679 * Return value:
680 * 0 if ok
681 * else error code
682 ********************************************************************* */
684 static int idecommon_diagnostic(idecommon_t *softc)
686 if (idecommon_waitnotbusy(softc) < 0) return -1;
687 IDE_WRITEREG8(softc,IDE_REG_DRVHD,(softc->idecommon_unit<<4));
688 if (idecommon_waitnotbusy(softc) < 0) return -1;
690 IDE_WRITEREG8(softc,IDE_REG_COMMAND,IDE_CMD_DIAGNOSTIC);
691 if (idecommon_waitnotbusy(softc) < 0) return -1;
693 cfe_sleep(CFE_HZ/2);
694 idecommon_dumpregs(softc);
696 return 0;
700 /* *********************************************************************
701 * idecommon_getmodel(buffer,model)
703 * Get the ASCII model name out of an IDE identify buffer. some
704 * byte swapping is involved here. The trailing blanks are trimmed.
706 * Input parameters:
707 * buffer - 512-byte buffer from IDENTIFY command
708 * model - 41-byte string (max) for model name
710 * Return value:
711 * nothing
712 ********************************************************************* */
714 static void idecommon_getmodel(uint8_t *buffer,char *model)
716 uint16_t w;
717 int idx;
719 for (idx = 0; idx < 20; idx++) {
720 w = GETWORD_LE(buffer,27+idx);
721 model[idx*2] = w >> 8;
722 model[idx*2+1] = w & 0xFF;
724 for (idx = 39; idx > 0; idx--) {
725 if (model[idx] != ' ') {
726 model[idx+1] = '\0';
727 break;
733 /* *********************************************************************
734 * idecommon_devprobe(softc)
736 * Probe the IDE device, to determine if it's actually present
737 * or not. If present, determine if it's IDE or ATAPI and
738 * get the device size. Init our internal structures so we know
739 * how to talk to the device.
741 * Input parameters:
742 * softc - IDE structure
743 * noisy - display stuff as we probe
745 * Return value:
746 * 0 if ok, else error code
747 ********************************************************************* */
749 int idecommon_devprobe(idecommon_t *softc,int noisy)
751 int res;
752 int atapi;
753 unsigned char buffer[DISK_SECTORSIZE];
754 unsigned char model[41];
755 uint64_t ttlsect;
756 int devtype;
757 uint16_t w;
758 char *typename;
761 * Reset the drive
764 res = idecommon_reset(softc);
765 if (res < 0) return -1;
768 * Run diagnostic to get the signature.
771 res = idecommon_diagnostic(softc);
772 if (res < 0) return res;
775 * Test signature
778 atapi = 0;
779 if ((IDE_READREG8(softc,IDE_REG_CYLLSB) == ATAPI_SIG_LSB) &&
780 (IDE_READREG8(softc,IDE_REG_CYLMSB) == ATAPI_SIG_MSB)) {
781 atapi = 1;
784 if (noisy) {
785 if (atapi) xprintf("ATAPI: ");
786 else xprintf("IDE: ");
790 * Do tha appropriate IDENTIFY command to get device information
793 softc->idecommon_atapi = atapi;
794 res = idecommon_identify(softc,buffer);
795 if (res < 0) return -1;
798 * Using that information, determine our device type
801 if (!atapi) {
802 devtype = IDE_DEVTYPE_DISK;
803 typename = "Disk";
805 else {
806 w = GETWORD_LE(buffer,0);
807 switch ((w >> 8) & 31) {
808 case 5: /* CD-ROM */
809 devtype = IDE_DEVTYPE_CDROM;
810 typename = "CD-ROM";
811 break;
812 default:
813 devtype = IDE_DEVTYPE_ATAPIDISK;
814 typename = "Disk";
815 break;
820 * Say nice things about the device.
823 idecommon_getmodel(buffer,(char *)model);
824 if (noisy) xprintf("%s, \"%s\"",typename,model);
827 #ifdef _IDE_DEBUG_
828 if (!softc->idecommon_atapi) {
829 ttlsect = (GETWORD_LE(buffer,57) + (GETWORD_LE(buffer,58) << 16));
830 if (noisy) xprintf(", Sectors: %llu (%lld MB)",ttlsect,
831 (uint64_t) (ttlsect/2048));
833 else {
834 ttlsect = 0;
836 #endif
837 if (noisy) xprintf("\n");
840 * Initialize internal structure info, especially pointers to the
841 * read/write routines and the sector size.
844 softc->idecommon_ttlsect = ttlsect;
845 idecommon_init(softc,devtype);
847 return res;
850 /* *********************************************************************
851 * idecommon_open(ctx)
853 * Process the CFE OPEN call for this device. For IDE disks,
854 * the device is reset and identified, and the geometry is
855 * determined.
857 * Input parameters:
858 * ctx - device context
860 * Return value:
861 * 0 if ok, else error code
862 ********************************************************************* */
865 int idecommon_open(cfe_devctx_t *ctx)
867 idecommon_t *softc = ctx->dev_softc;
868 int res;
870 if (softc->idecommon_deferprobe) {
871 res = idecommon_devprobe(softc,0);
872 if (res < 0) return res;
875 return 0;
878 /* *********************************************************************
879 * idecommon_read(ctx,buffer)
881 * Process a CFE READ command for the IDE device. This is
882 * more complex than it looks, since CFE offsets are byte offsets
883 * and we may need to read partial sectors.
885 * Input parameters:
886 * ctx - device context
887 * buffer - buffer descriptor
889 * Return value:
890 * number of bytes read, or <0 if an error occured
891 ********************************************************************* */
893 int idecommon_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
895 idecommon_t *softc = ctx->dev_softc;
896 unsigned char *bptr;
897 int blen;
898 int numsec;
899 int res = 0;
900 int amtcopy;
901 uint64_t lba;
902 uint64_t offset;
903 unsigned char sector[MAX_SECTORSIZE];
904 int sectorshift;
906 sectorshift = idecommon_sectorshift(softc->idecommon_sectorsize);
908 bptr = buffer->buf_ptr;
909 blen = buffer->buf_length;
910 offset = buffer->buf_offset;
911 numsec = (blen + softc->idecommon_sectorsize - 1) >> sectorshift;
913 if (offset & (softc->idecommon_sectorsize-1)) {
914 lba = (offset >> sectorshift);
915 res = (*softc->idecommon_readfunc)(softc,lba,1,sector);
916 if (res < 0) goto out;
917 amtcopy = softc->idecommon_sectorsize - (offset & (softc->idecommon_sectorsize-1));
918 if (amtcopy > blen) amtcopy = blen;
919 memcpy(bptr,&sector[offset & (softc->idecommon_sectorsize-1)],amtcopy);
920 bptr += amtcopy;
921 offset += amtcopy;
922 blen -= amtcopy;
925 while (blen >= softc->idecommon_sectorsize) {
926 lba = (offset >> sectorshift);
927 amtcopy = softc->idecommon_sectorsize;
928 res = (*softc->idecommon_readfunc)(softc,lba,1,bptr);
929 if (res < 0) goto out;
930 bptr += amtcopy;
931 offset += amtcopy;
932 blen -= amtcopy;
935 if (blen) {
936 lba = (offset >> sectorshift);
937 res = (*softc->idecommon_readfunc)(softc,lba,1,sector);
938 if (res < 0) goto out;
939 amtcopy = blen;
940 memcpy(bptr,sector,amtcopy);
941 bptr += amtcopy;
942 offset += amtcopy;
943 blen -= amtcopy;
946 out:
947 buffer->buf_retlen = bptr - buffer->buf_ptr;
949 return res;
952 /* *********************************************************************
953 * idecommon_inpstat(ctx,inpstat)
955 * Test input status for the IDE disk. Disks are always ready
956 * to read.
958 * Input parameters:
959 * ctx - device context
960 * inpstat - input status structure
962 * Return value:
964 ********************************************************************* */
966 int idecommon_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
968 /* idecommon_t *softc = ctx->dev_softc; */
970 inpstat->inp_status = 1;
971 return 0;
974 /* *********************************************************************
975 * idecommon_write(ctx,buffer)
977 * Process a CFE WRITE command for the IDE device. If the write
978 * involves partial sectors, the affected sectors are read first
979 * and the changes are merged in.
981 * Input parameters:
982 * ctx - device context
983 * buffer - buffer descriptor
985 * Return value:
986 * number of bytes write, or <0 if an error occured
987 ********************************************************************* */
989 int idecommon_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
991 idecommon_t *softc = ctx->dev_softc;
992 unsigned char *bptr;
993 int blen;
994 int numsec;
995 int res = 0;
996 int amtcopy;
997 uint64_t offset;
998 uint64_t lba;
999 unsigned char sector[MAX_SECTORSIZE];
1000 int sectorshift;
1002 sectorshift = (softc->idecommon_sectorsize == 2048) ? 11 : 9;
1004 bptr = buffer->buf_ptr;
1005 blen = buffer->buf_length;
1006 offset = buffer->buf_offset;
1007 numsec = (blen + softc->idecommon_sectorsize - 1) >> sectorshift;
1009 if (offset & (softc->idecommon_sectorsize-1)) {
1010 lba = (offset >> sectorshift);
1011 res = (*softc->idecommon_readfunc)(softc,lba,1,sector);
1012 if (res < 0) goto out;
1013 amtcopy = softc->idecommon_sectorsize - (offset & (softc->idecommon_sectorsize-1));
1014 if (amtcopy > blen) amtcopy = blen;
1015 memcpy(&sector[offset & (softc->idecommon_sectorsize-1)],bptr,amtcopy);
1016 res = (*softc->idecommon_writefunc)(softc,lba,1,sector);
1017 if (res < 0) goto out;
1018 bptr += amtcopy;
1019 offset += amtcopy;
1020 blen -= amtcopy;
1023 while (blen >= softc->idecommon_sectorsize) {
1024 amtcopy = softc->idecommon_sectorsize;
1025 lba = (offset >> sectorshift);
1026 res = (*softc->idecommon_writefunc)(softc,lba,1,bptr);
1027 if (res < 0) goto out;
1028 bptr += amtcopy;
1029 offset += amtcopy;
1030 blen -= amtcopy;
1033 if (blen) {
1034 lba = (offset >> sectorshift);
1035 res = (*softc->idecommon_readfunc)(softc,lba,1,sector);
1036 if (res < 0) goto out;
1037 amtcopy = blen;
1038 memcpy(sector,bptr,amtcopy);
1039 res = (*softc->idecommon_writefunc)(softc,lba,1,sector);
1040 if (res < 0) goto out;
1041 bptr += amtcopy;
1042 offset += amtcopy;
1043 blen -= amtcopy;
1046 out:
1047 buffer->buf_retlen = bptr - buffer->buf_ptr;
1049 return res;
1053 /* *********************************************************************
1054 * idecommon_ioctl(ctx,buffer)
1056 * Process device I/O control requests for the IDE device.
1058 * Input parameters:
1059 * ctx - device context
1060 * buffer - buffer descriptor
1062 * Return value:
1063 * 0 if ok
1064 * else error code
1065 ********************************************************************* */
1067 int idecommon_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
1069 idecommon_t *softc = ctx->dev_softc;
1070 unsigned int *info = (unsigned int *) buffer->buf_ptr;
1071 unsigned long long *linfo = (unsigned long long *) buffer->buf_ptr;
1072 blockdev_info_t *devinfo;
1074 switch ((int)buffer->buf_ioctlcmd) {
1075 case IOCTL_BLOCK_GETBLOCKSIZE:
1076 *info = softc->idecommon_sectorsize;
1077 break;
1078 case IOCTL_BLOCK_GETTOTALBLOCKS:
1079 *linfo = softc->idecommon_ttlsect;
1080 break;
1081 case IOCTL_BLOCK_GETDEVTYPE:
1082 devinfo = (blockdev_info_t *) buffer->buf_ptr;
1083 devinfo->blkdev_totalblocks = softc->idecommon_ttlsect;
1084 devinfo->blkdev_blocksize = softc->idecommon_sectorsize;
1085 devinfo->blkdev_devtype = (softc->idecommon_devtype == IDE_DEVTYPE_CDROM) ?
1086 BLOCK_DEVTYPE_CDROM : BLOCK_DEVTYPE_DISK;
1087 break;
1088 default:
1089 return -1;
1092 return 0;
1095 /* *********************************************************************
1096 * idecommon_close(ctx)
1098 * Close the I/O device.
1100 * Input parameters:
1101 * ctx - device context
1103 * Return value:
1104 * 0 if ok, else error code
1105 ********************************************************************* */
1107 int idecommon_close(cfe_devctx_t *ctx)
1109 /* idecommon_t *softc = ctx->dev_softc; */
1111 return 0;
1115 /* *********************************************************************
1116 * idecommon_init(ide,devtype)
1118 * Set up internal values based on the device type
1120 * Input parameters:
1121 * ide - IDE interface
1122 * devtype - device type
1124 * Return value:
1125 * nothing
1126 ********************************************************************* */
1128 void idecommon_init(idecommon_t *ide,int devtype)
1131 ide->idecommon_devtype = devtype;
1133 switch (ide->idecommon_devtype) {
1134 case IDE_DEVTYPE_DISK:
1135 ide->idecommon_atapi = FALSE;
1136 ide->idecommon_sectorsize = DISK_SECTORSIZE;
1137 break;
1138 case IDE_DEVTYPE_CDROM:
1139 ide->idecommon_atapi = TRUE;
1140 ide->idecommon_sectorsize = CDROM_SECTORSIZE;
1141 break;
1142 case IDE_DEVTYPE_ATAPIDISK:
1143 ide->idecommon_atapi = TRUE;
1144 ide->idecommon_sectorsize = DISK_SECTORSIZE;
1145 break;
1146 default:
1147 ide->idecommon_atapi = FALSE;
1148 ide->idecommon_sectorsize = DISK_SECTORSIZE;
1149 break;
1152 if (ide->idecommon_atapi) {
1153 ide->idecommon_readfunc = idecommon_read_atapi;
1154 ide->idecommon_writefunc = idecommon_write_atapi;
1156 else {
1157 ide->idecommon_readfunc = idecommon_read_lba;
1158 ide->idecommon_writefunc = idecommon_write_lba;
1162 /* *********************************************************************
1163 * idecommon_attach(devdisp)
1165 * Set up a cfe_devdisp structure that points at the idecommon
1166 * structures.
1168 * Input parameters:
1169 * devdisp - cfe_devdisp_t structure
1171 * Return value:
1172 * nothing
1173 ********************************************************************* */
1174 void idecommon_attach(cfe_devdisp_t *disp)
1176 disp->dev_open = idecommon_open;
1177 disp->dev_read = idecommon_read;
1178 disp->dev_inpstat = idecommon_inpstat;
1179 disp->dev_write = idecommon_write;
1180 disp->dev_ioctl = idecommon_ioctl;
1181 disp->dev_close = idecommon_close;
1182 disp->dev_poll = NULL;
1183 disp->dev_reset = NULL;