diff -purN u-boot/common/cmd_sata.c u-boot_chg/common/cmd_sata.c --- u-boot/common/cmd_sata.c 1970-01-01 05:30:00.000000000 +0530 +++ u-boot_chg/common/cmd_sata.c 2007-03-14 17:15:50.000000000 +0530 @@ -0,0 +1,740 @@ +/* + * Copyright (C) Processor Systems. All rights reserved. + * Author: Mushtaq Khan + + * + * + * 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 + * + * with the reference to libata in kernel 2.4.32 + * +*/ + + +/*File contains SATA read-write and other utility functions.*/ +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_SATA_SUPPORTED + +#define DEBUG_SATA 0 /*For debug prints set macro DEBUG_SATA to 1*/ + +#define SATA_DECL /*Macro for SATA library specific declarations*/ +#include +#undef SATA_DECL + +/*ALL Static definitions are on top to avoid declarations*/ + +static u8 __inline__ +sata_inb(unsigned long ioaddr) +{ + return inb(ioaddr); +} + +static void __inline__ +sata_outb(unsigned char val, unsigned long ioaddr) +{ + outb(val, ioaddr); +} + +static void +output_data(struct sata_ioports *ioaddr, ulong *sect_buf, int words) +{ + outsw(ioaddr->data_addr, sect_buf, words<<1); +} + +static int +input_data(struct sata_ioports *ioaddr, ulong *sect_buf, int words) +{ + insw(ioaddr->data_addr,sect_buf, words << 1); + return 0; +} + +static void +sata_cpy (unsigned char *dst, unsigned char *src, unsigned int len) +{ + unsigned char *end, *last; + + last = dst; + end = src + len - 1; + + /* reserve space for '\0' */ + if (len < 2) + goto OUT; + + /* skip leading white space */ + while ((*src) && (src= 2ms" before checking status. + * We wait 150ms, because that was the magic delay used for + * ATAPI devices in Hale Landis's ATADRVR, for the period of time + * between when the ATA command register is written, and then + * status is checked. Because waiting for "a while" before + * checking status is fine, post SRST, we perform this magic + * delay here as well. + */ + msleep(150); + status = Sata_busy_wait(&port[num].ioaddr,ATA_BUSY, 300); + while ((status & ATA_BUSY)){ + msleep(100); + status = Sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 3); + } + + if (status & ATA_BUSY) + printf("ata%u is slow to respond,please be patient\n",port); + + while ((status & ATA_BUSY)){ + msleep(100); + status = Sata_chk_status(&port[num].ioaddr); + } + + if (status & ATA_BUSY){ + printf("ata%u failed to respond : ",port); + printf("bus reset failed\n"); + return 1; + } + return 0; +} + +void Sata_identify(int num,int dev) +{ + u8 cmd=0,status=0,devno=num*CFG_SATA_DEV_PER_BUS+dev; + u16 iobuf[ATA_SECT_SIZE]; + u64 n_sectors=0; + u8 mask=0; + + memset(iobuf,0,sizeof(iobuf)); + hd_driveid_t *iop = (hd_driveid_t *)iobuf; + + if(dev == 0) + mask = 0x01; + else + mask = 0x02; + + if(!(port[num].dev_mask & mask)){ + printf("dev%d is not present on port#%d\n",dev,num); + return; + } + + printf("port=%d dev=%d\n",num,dev); + + dev_select(&port[num].ioaddr,dev); + + status = 0; + cmd = ATA_CMD_IDENT; /*Device Identify Command*/ + sata_outb(cmd,port[num].ioaddr.command_addr); + sata_inb(port[num].ioaddr.altstatus_addr); + udelay(10); + + status = Sata_busy_wait(&port[num].ioaddr,ATA_BUSY, 1000); + udelay(5000); + if(status & ATA_ERR){ + printf("\ndevice not responding\n"); + port[num].dev_mask &= ~mask; + return; + } + + input_data(&port[num].ioaddr,(ulong *)iobuf,ATA_SECTORWORDS); + + PRINTF("\nata%u: dev %u cfg " + "49:%04x 82:%04x 83:%04x 84:%04x 85:%04x 86:%04x" + "87:%04x 88:%04x\n",num,dev,iobuf[49], + iobuf[82], iobuf[83], iobuf[84], + iobuf[85], iobuf[86], iobuf[87], + iobuf[88]); + + /* we require LBA and DMA support (bits 8 & 9 of word 49) */ + if (!ata_id_has_dma(iobuf) || !ata_id_has_lba(iobuf)) { + PRINTF("ata%u: no dma/lba\n", num); + } + ata_dump_id(iobuf); + + if (ata_id_has_lba48(iobuf)) { + n_sectors = ata_id_u64(iobuf, 100); + }else{ + n_sectors = ata_id_u32(iobuf, 60); + } + PRINTF("no. of sectors %u\n", ata_id_u64(iobuf, 100)); + PRINTF("no. of sectors %u\n", ata_id_u32(iobuf, 60)); + + if(n_sectors == 0){ + PRINTF("No. of Sectors is Zero\n"); + port[num].dev_mask &= ~mask; + return ; + } + + sata_cpy (sata_dev_desc[devno].revision, iop->fw_rev, + sizeof(sata_dev_desc[devno].revision)); + sata_cpy (sata_dev_desc[devno].vendor, iop->model, + sizeof(sata_dev_desc[devno].vendor)); + sata_cpy (sata_dev_desc[devno].product, iop->serial_no, + sizeof(sata_dev_desc[devno].product)); + strswab (sata_dev_desc[devno].revision); + strswab (sata_dev_desc[devno].vendor); + + if ((iop->config & 0x0080)==0x0080){ + sata_dev_desc[devno].removable = 1; + }else{ + sata_dev_desc[devno].removable = 0; + } + + sata_dev_desc[devno].lba = iop->lba_capacity; + PRINTF("lba=0x%x",sata_dev_desc[devno].lba); + +#ifdef CONFIG_LBA48 + if (iop->command_set_2 & 0x0400) { /* LBA 48 support */ + sata_dev_desc[devno].lba48 = 1; + 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); + } else { + sata_dev_desc[devno].lba48 = 0; + } +#endif + + /* assuming HD */ + sata_dev_desc[devno].type=DEV_TYPE_HARDDISK; + sata_dev_desc[devno].blksz=ATA_BLOCKSIZE; + sata_dev_desc[devno].lun=0; /* just to fill something in... */ +} + +void Set_Feature_cmd(int num, int dev) +{ + u8 mask = 0x00,status=0; + + if(dev == 0) + mask = 0x01; + else + mask = 0x02; + + if(!(port[num].dev_mask & mask)){ + printf("dev%d is not present on port#%d\n",dev,num); + return; + } + + dev_select(&port[num].ioaddr,dev); + + sata_outb (SETFEATURES_XFER,port[num].ioaddr.feature_addr); + sata_outb (XFER_PIO_4,port[num].ioaddr.nsect_addr); + sata_outb (0, port[num].ioaddr.lbal_addr); + sata_outb (0, port[num].ioaddr.lbam_addr); + sata_outb (0, port[num].ioaddr.lbah_addr); + + sata_outb (ATA_DEVICE_OBS , port[num].ioaddr.device_addr); + sata_outb (ATA_CMD_SETF, port[num].ioaddr.command_addr); + + udelay (50); + msleep(150); + + status = Sata_busy_wait(&port[num].ioaddr,ATA_BUSY, 5000); + if ((status &(ATA_STAT_BUSY|ATA_STAT_ERR))) { + printf ("Error : status 0x%02x\n",status); + port[num].dev_mask &= ~mask; + } +} + +void Sata_port(struct sata_ioports *ioport) +{ + ioport->data_addr = ioport->cmd_addr + ATA_REG_DATA; + ioport->error_addr =ioport->cmd_addr + ATA_REG_ERR; + ioport->feature_addr = ioport->cmd_addr + ATA_REG_FEATURE; + ioport->nsect_addr = ioport->cmd_addr + ATA_REG_NSECT; + ioport->lbal_addr = ioport->cmd_addr + ATA_REG_LBAL; + ioport->lbam_addr = ioport->cmd_addr + ATA_REG_LBAM; + ioport->lbah_addr = ioport->cmd_addr + ATA_REG_LBAH; + ioport->device_addr = ioport->cmd_addr + ATA_REG_DEVICE; + ioport->status_addr = ioport->cmd_addr + ATA_REG_STATUS; + ioport->command_addr = ioport->cmd_addr + ATA_REG_CMD; +} + +int Sata_devchk(struct sata_ioports *ioaddr,int dev) +{ + u8 nsect, lbal; + + dev_select(ioaddr,dev); + + sata_outb(0x55, ioaddr->nsect_addr); + sata_outb(0xaa, ioaddr->lbal_addr); + + sata_outb(0xaa, ioaddr->nsect_addr); + sata_outb(0x55, ioaddr->lbal_addr); + + sata_outb(0x55, ioaddr->nsect_addr); + sata_outb(0xaa, ioaddr->lbal_addr); + + nsect = sata_inb(ioaddr->nsect_addr); + lbal = sata_inb(ioaddr->lbal_addr); + + if ((nsect == 0x55) && (lbal == 0xaa)) + return 1; /* we found a device */ + else + return 0; /* nothing found */ + return 0; +} + +void dev_select(struct sata_ioports *ioaddr,int dev) +{ + u8 tmp=0; + if (dev == 0) + tmp = ATA_DEVICE_OBS; + else + tmp = ATA_DEVICE_OBS | ATA_DEV1; + + sata_outb(tmp, ioaddr->device_addr); + sata_inb(ioaddr->altstatus_addr); + udelay(5); +} + + +u8 Sata_busy_wait(struct sata_ioports *ioaddr, int bits, + unsigned int max) +{ + u8 status; + + do { + udelay(1000); + status = Sata_chk_status(ioaddr); + max--; + } while ((status & bits) && (max > 0)); + + return status; +} + + + +u8 Sata_chk_status(struct sata_ioports *ioaddr) +{ + return sata_inb(ioaddr->status_addr); +} + +void msleep(int count) +{ + int i; + for(i=0;i= CFG_SATA_DEV_PER_BUS) + dev = device - CFG_SATA_DEV_PER_BUS; /*dev on the port*/ + else + dev = device; /*dev on the port*/ + + if(dev == 0) + mask = 0x01; + else + mask = 0x02; + + if(!(port[num].dev_mask & mask)){ + printf("dev%d is not present on port#%d\n",dev,num); + return 0; + } + + dev_select(&port[num].ioaddr,dev); + + status = Sata_busy_wait(&port[num].ioaddr,ATA_BUSY, 500); + if (status & ATA_BUSY) { + printf("ata%u failed to respond\n",port[num].port_no); + return n; + } + + sata_outb(ATA_CMD_CHK_PWR,port[num].ioaddr.command_addr); + udelay (50); + status = Sata_busy_wait(&port[num].ioaddr,ATA_BUSY, 500); + + if (status & ATA_BUSY) { + printf("ata%u failed to respond\n",port[num].port_no); + return 0; + } + + if ((status & ATA_STAT_ERR) == ATA_STAT_ERR) { + printf("No Powersaving mode %X\n", status); + } else { + status = sata_inb(port[num].ioaddr.altstatus_addr); + if(status==0) + pwrsave=1; + } + + while (blkcnt-- > 0) { + status = Sata_busy_wait(&port[num].ioaddr,ATA_BUSY, 500); + if (status & ATA_BUSY) { + printf("ata%u failed to respond\n",0); + return n; + } + +#ifdef CONFIG_LBA48 + if(lba48){ + /* write high bits */ + sata_outb (0,port[num].ioaddr.nsect_addr); + sata_outb ((blknr >> 24) & 0xFF, + port[num].ioaddr.lbal_addr); + sata_outb ((blknr >> 32) & 0xFF, + port[num].ioaddr.lbam_addr); + sata_outb ((blknr >> 40) & 0xFF, + port[num].ioaddr.lbah_addr); + } +#endif + sata_outb (1,port[num].ioaddr.nsect_addr); + sata_outb (((blknr) >> 0) & 0xFF, + port[num].ioaddr.lbal_addr); + sata_outb ((blknr >> 8) & 0xFF, + port[num].ioaddr.lbam_addr); + sata_outb ((blknr >> 16) & 0xFF, + port[num].ioaddr.lbah_addr); + +#ifdef CONFIG_LBA48 + if (lba48) { + sata_outb (ATA_LBA, + port[num].ioaddr.device_addr ); + sata_outb (ATA_CMD_READ_EXT, + port[num].ioaddr.command_addr); + }else +#endif + { + sata_outb ( ATA_LBA |((blknr >> 24) & 0xF), + port[num].ioaddr.device_addr); + sata_outb (ATA_CMD_READ , + port[num].ioaddr.command_addr); + } + + udelay (50); + msleep(50); + + if(pwrsave){ + pwrsave=0; + /* may take up to 4 sec */ + status = Sata_busy_wait(&port[num].ioaddr, + ATA_BUSY, 4000); + }else{ + status = Sata_busy_wait(&port[num].ioaddr, + ATA_BUSY, 500); + } + + if ((status &(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) + != ATA_STAT_DRQ) { + u8 err=0; + printf ("Error no DRQ dev %d blk %ld: status 0x%02x\n", + device, (ulong)blknr, status); + err=sata_inb(port[num].ioaddr.error_addr); + printf("error reg = 0x%x\n",err); + return (n); + } + PRINTF("sts=0x%x\n",status); + input_data (&port[num].ioaddr, buffer, ATA_SECTORWORDS); + sata_inb(port[num].ioaddr.altstatus_addr); + udelay(50); + + ++n; + ++blknr; + buffer += ATA_SECTORWORDS; + } + return n; +} + + +ulong +sata_write(int device, lbaint_t blknr, ulong blkcnt, ulong *buffer) +{ + ulong n = 0; + unsigned char status=0,num=0,dev=0,mask=0; +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0; + if (blknr & 0x0000fffff0000000) { + if(!sata_dev_desc[devno].lba48){ + printf("\nDrive doesn't support 48-bit addressing\n"); + return 0; + } + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; + } +#endif + + num = device/CFG_SATA_DEV_PER_BUS; /*Port number*/ + + if(device >= CFG_SATA_DEV_PER_BUS) + dev = device - CFG_SATA_DEV_PER_BUS; + else + dev = device; + + if(dev == 0) + mask = 0x01; + else + mask = 0x02; + + /* Select device*/ + dev_select(&port[num].ioaddr,dev); + + status = Sata_busy_wait(&port[num].ioaddr,ATA_BUSY, 500); + if (status & ATA_BUSY) { + printf("ata%u failed to respond\n",port[num].port_no); + return n; + } + + while (blkcnt-- > 0) { + status = Sata_busy_wait(&port[num].ioaddr,ATA_BUSY, 500); + if (status & ATA_BUSY) { + printf("ata%u failed to respond\n",port[num].port_no); + return n; + } +#ifdef CONFIG_LBA48 + if(lba48){ + /* write high bits */ + sata_outb (0,port[num].ioaddr.nsect_addr); + sata_outb ((blknr >> 24) & 0xFF, + port[num].ioaddr.lbal_addr); + sata_outb ((blknr >> 32) & 0xFF, + port[num].ioaddr.lbam_addr); + sata_outb ((blknr >> 40) & 0xFF, + port[num].ioaddr.lbah_addr); + } +#endif + sata_outb (1,port[num].ioaddr.nsect_addr); + sata_outb ((blknr >> 0) & 0xFF, + port[num].ioaddr.lbal_addr); + sata_outb ((blknr >> 8) & 0xFF, + port[num].ioaddr.lbam_addr); + sata_outb ((blknr >> 16) & 0xFF, + port[num].ioaddr.lbah_addr); +#ifdef CONFIG_LBA48 + if (lba48) { + sata_outb (ATA_LBA, + port[num].ioaddr.device_addr ); + sata_outb (ATA_CMD_WRITE_EXT, + port[num].ioaddr.command_addr); + } else +#endif + { + sata_outb (ATA_LBA | ((blknr >> 24) & 0xF), port[num].ioaddr.device_addr); + sata_outb (ATA_CMD_WRITE , port[num].ioaddr.command_addr); + } + + udelay (50); + msleep(50); + status = Sata_busy_wait(&port[num].ioaddr, + ATA_BUSY, 4000); + if ((status &(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) + != ATA_STAT_DRQ) { + printf("Error (no IRQ) dev %d blk %ld:" + "status 0x%02x\n", + device, (ulong)blknr, status); + return (n); + } + + output_data (&port[num].ioaddr, buffer, ATA_SECTORWORDS); + sata_inb(port[num].ioaddr.altstatus_addr); + udelay(50); + + ++n; + ++blknr; + buffer += ATA_SECTORWORDS; + } + return n; +} + + +block_dev_desc_t * sata_get_dev(int dev); +block_dev_desc_t * sata_get_dev(int dev) +{ + return ((block_dev_desc_t *)&sata_dev_desc[dev]); +} + + + + +int do_sata (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + + switch (argc) { + case 0: + case 1: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + case 2: + if (strncmp(argv[1],"init",4) == 0) { + int rcode = 0; + rcode = init_sata(); + if(rcode) + printf("\nSata initialization Failed"); + return rcode; + }else if (strncmp(argv[1],"inf",3) == 0) { + int i; + putc ('\n'); + for (i=0; iusage); + return 1; + case 3: + if(strcmp(argv[1],"dev") == 0){ + int dev = (int)simple_strtoul(argv[2], NULL, 10); + if(dev >= CFG_SATA_MAXDEVICES){ + printf("\nSata device %d not available\n", dev); + return 1; + } + printf ("\nSATA device %d: ", dev); + dev_print(&sata_dev_desc[dev]); + if (sata_dev_desc[dev].type==DEV_TYPE_UNKNOWN){ + return 1; + } + curr_dev = dev; + return 0; + }else if(strcmp(argv[1],"part") == 0){ + int dev = (int)simple_strtoul(argv[2], NULL, 10); + if(dev >= CFG_SATA_MAXDEVICES){ + printf("\nSata device %d not available\n", dev); + return 1; + } + PRINTF("\nSATA device %d: ", dev); + if (sata_dev_desc[dev].part_type!=PART_TYPE_UNKNOWN) { + print_part(&sata_dev_desc[dev]); + } else { + printf("\nSata device %d partition type unknown\n", dev); + return 1; + } + return 0; + } + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + default: + if(argc < 5){ + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + if (strcmp(argv[1],"read") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + lbaint_t blk = simple_strtoul(argv[3], NULL, 16); + memset((int *)addr,0,cnt*512); + printf("\nSATA read: device %d block # %ld, count %ld ... ", + curr_dev, blk, cnt); + n = sata_read(curr_dev,blk, cnt,(ulong *)addr); + /* flush cache after read */ + flush_cache (addr, cnt*512); + printf("%ld blocks read: %s\n",n, (n==cnt) ? + "OK" : "ERROR"); + if (n==cnt) + return 1; + else + return 0; + }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; + lbaint_t blk = simple_strtoul(argv[3], NULL, 16); + printf ("\nSata write: device %d block # %ld," + "count %ld ... ", + curr_dev, blk, cnt); + n = sata_write (curr_dev, blk, cnt, (ulong *)addr); + printf ("%ld blocks written: %s\n", + n, (n==cnt) ? "OK" : "ERROR"); + if (n==cnt) + return 1; + else + return 0; + } else { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + } /*End OF SWITCH*/ +} + + +U_BOOT_CMD( + Sata, 5, 1, do_sata, + "Sata init\n" + "Sata info\n" + "Sata part device\n" + "Sata dev device\n" + "Sata read addr blk# cnt\n" + "Sata write addr blk# cnt\n", + "Sata cmd for init,rw and dev-info\n" +); +#endif diff -purN u-boot/common/Makefile u-boot_chg/common/Makefile --- u-boot/common/Makefile 2007-02-21 11:00:24.000000000 +0530 +++ u-boot_chg/common/Makefile 2007-03-14 17:17:36.000000000 +0530 @@ -40,7 +40,7 @@ COBJS = main.o ACEX1K.o altera.o bedbug. cmd_nand.o cmd_net.o cmd_nvedit.o \ cmd_pci.o cmd_pcmcia.o cmd_portio.o \ cmd_reginfo.o cmd_reiser.o cmd_scsi.o cmd_spi.o cmd_universe.o \ - cmd_usb.o cmd_vfd.o \ + cmd_usb.o cmd_vfd.o cmd_sata.o\ command.o console.o cyclon2.o devices.o dlmalloc.o docecc.o \ environment.o env_common.o \ env_nand.o env_dataflash.o env_flash.o env_eeprom.o \ diff -purN u-boot/drivers/ata_piix.c u-boot_chg/drivers/ata_piix.c --- u-boot/drivers/ata_piix.c 1970-01-01 05:30:00.000000000 +0530 +++ u-boot_chg/drivers/ata_piix.c 2007-03-14 17:15:36.000000000 +0530 @@ -0,0 +1,210 @@ +/* + * Copyright (C) Processor Systems. All rights reserved. + * Author: Mushtaq Khan + + * + * 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 + * + * with the reference to ata_piix driver in kernel 2.4.32 +*/ + +/* +This file contains SATA controller and SATA drive initialization functions +*/ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_ATA_PIIX /*ata_piix driver*/ + +#define DEBUG_SATA 0 /*For debug prints set DEBUG_SATA to 1*/ + +#define DRV_DECL /*For file specific declarations*/ +#include +#undef DRV_DECL + +/*Macros realted to PCI*/ +#define PCI_SATA_BUS 0x00 +#define PCI_SATA_DEV 0x1f +#define PCI_SATA_FUNC 0x02 + +#define PCI_SATA_BASE1 0x10 +#define PCI_SATA_BASE2 0x14 +#define PCI_SATA_BASE3 0x18 +#define PCI_SATA_BASE4 0x1c +#define PCI_SATA_BASE5 0x20 +#define PCI_PMR 0x90 +#define PCI_PI 0x09 +#define PCI_PCS 0x92 +#define PCI_DMA_CTL 0x48 + +#define PORT_PRESENT (1<<0) +#define PORT_ENABLED (1<<4) + +u32 bdf; +u32 iobase1 = 0; /*Primary cmd block*/ +u32 iobase2 = 0; /*Primary ctl block*/ +u32 iobase3 = 0; /*Sec cmd block*/ +u32 iobase4 = 0; /*sec ctl block*/ +u32 iobase5 = 0; /*BMDMA*/ + +int pci_sata_init(void) +{ + u32 bus = PCI_SATA_BUS; + u32 dev = PCI_SATA_DEV; + u32 fun = PCI_SATA_FUNC; + u16 cmd = 0; + u8 lat = 0,pcibios_max_latency = 0xff; + u8 pmr; /*Port mapping reg*/ + u8 pi; /*Prgming Interface reg*/ + + bdf = PCI_BDF(bus,dev,fun); + pci_read_config_dword (bdf, PCI_SATA_BASE1, &iobase1); + pci_read_config_dword (bdf, PCI_SATA_BASE2, &iobase2); + pci_read_config_dword (bdf, PCI_SATA_BASE3, &iobase3); + pci_read_config_dword (bdf, PCI_SATA_BASE4, &iobase4); + pci_read_config_dword (bdf, PCI_SATA_BASE5, &iobase5); + + iobase1 &= 0xFFFFFFFE; + iobase2 &= 0xFFFFFFFE; + iobase3 &= 0xFFFFFFFE; + iobase4 &= 0xFFFFFFFE; + iobase5 &= 0xFFFFFFFE; + + if((iobase1 == 0xFFFFFFFE) || (iobase2 == 0xFFFFFFFE) || + (iobase3 == 0xFFFFFFFE) || (iobase4 ==0xFFFFFFFE) + || (iobase5==0xFFFFFFFE)) { + printf("error no base addr for SATA controller\n"); + return 1; /*ERROR*/ + } + + /*check for mode */ + pci_read_config_byte (bdf, PCI_PMR , &pmr); + if(pmr > 1){ + printf("combined mode not supported\n"); + return 1; + } + + pci_read_config_byte (bdf, PCI_PI , &pi); + if((pi & 0x05) != 0x05){ + printf("Sata is in Legacy mode\n"); + return 1; + }else{ + printf("sata is in Native mode\n"); + } + + /*MASTER CFG AND IO CFG*/ + pci_read_config_word(bdf, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word(bdf, PCI_COMMAND, cmd); + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + + if (lat < 16) + lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; + else if (lat > pcibios_max_latency) + lat = pcibios_max_latency; + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); + + return 0; +} + +int Sata_bus_probe(int port_no) +{ + int orig_mask, mask; + u16 pcs; + + mask = (PORT_PRESENT << port_no); + pci_read_config_word(bdf, PCI_PCS, &pcs); + orig_mask = (int) pcs & 0xff; + if((orig_mask & mask) != mask) + return 0; + else + return 1; +} + + +int init_sata(void) +{ + u8 i,rv=0; + rv = pci_sata_init(); + if(rv == 1){ + printf("pci initialization failed\n"); + return 1; + } + port[0].port_no = 0; + port[0].ioaddr.cmd_addr = iobase1; + port[0].ioaddr.altstatus_addr = port[0].ioaddr.ctl_addr = + iobase2 |ATA_PCI_CTL_OFS; + port[0].ioaddr.bmdma_addr = iobase5; + + port[1].port_no = 1; + port[1].ioaddr.cmd_addr = iobase3; + port[1].ioaddr.altstatus_addr = port[1].ioaddr.ctl_addr = + iobase4 |ATA_PCI_CTL_OFS; + port[1].ioaddr.bmdma_addr = iobase5 + 0x8; + + for(i=0;i 0) && + (sata_dev_desc[devno].blksz > 0)){ + dev_print(&sata_dev_desc[devno]); + /* initialize partition type */ + init_part (&sata_dev_desc[devno]); + if (curr_dev < 0) + curr_dev = i*CFG_SATA_DEV_PER_BUS+j; + } + } + } + return 0; +} +#endif diff -purN u-boot/drivers/Makefile u-boot_chg/drivers/Makefile --- u-boot/drivers/Makefile 2007-02-21 10:59:19.000000000 +0530 +++ u-boot_chg/drivers/Makefile 2007-03-14 17:16:17.000000000 +0530 @@ -51,7 +51,7 @@ COBJS = 3c589.o 5701rls.o ali512x.o atme ks8695eth.o \ pxa_pcmcia.o mpc8xx_pcmcia.o tqm8xx_pcmcia.o \ rpx_pcmcia.o \ - fsl_i2c.o + fsl_i2c.o ata_piix.o SRCS := $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff -purN u-boot/include/ata.h u-boot_chg/include/ata.h --- u-boot/include/ata.h 2007-02-21 11:00:39.000000000 +0530 +++ u-boot_chg/include/ata.h 2007-03-14 17:44:37.000000000 +0530 @@ -83,6 +83,70 @@ #define ATA_DEVICE(x) ((x & 1)<<4) #define ATA_LBA 0xE0 +/*******************************MK_CHG Constants related to ATA*************************************/ +enum{ + ATA_MAX_DEVICES = 1, /* per bus/port */ + ATA_MAX_PRD = 256, /* we could make these 256/256 */ + ATA_SECT_SIZE = 256, /*256 words per sector*/ + + /* bits in ATA command block registers */ + ATA_HOB = (1 << 7), /* LBA48 selector */ + ATA_NIEN = (1 << 1), /* disable-irq flag */ + /*ATA_LBA = (1 << 6),*/ /* LBA28 selector */ + ATA_DEV1 = (1 << 4), /* Select Device 1 (slave) */ + ATA_DEVICE_OBS = (1 << 7) | (1 << 5), /* obs bits in dev reg */ + ATA_DEVCTL_OBS = (1 << 3), /* obsolete bit in devctl reg */ + ATA_BUSY = (1 << 7), /* BSY status bit */ + ATA_DRDY = (1 << 6), /* device ready */ + ATA_DF = (1 << 5), /* device fault */ + ATA_DRQ = (1 << 3), /* data request i/o */ + ATA_ERR = (1 << 0), /* have an error */ + ATA_SRST = (1 << 2), /* software reset */ + ATA_ABORTED = (1 << 2), /* command aborted */ + /* ATA command block registers */ + ATA_REG_DATA = 0x00, + ATA_REG_ERR = 0x01, + ATA_REG_NSECT = 0x02, + ATA_REG_LBAL = 0x03, + ATA_REG_LBAM = 0x04, + ATA_REG_LBAH = 0x05, + ATA_REG_DEVICE = 0x06, + ATA_REG_STATUS = 0x07, + ATA_PCI_CTL_OFS = 0x02, + /* and their aliases */ + ATA_REG_FEATURE = ATA_REG_ERR, + ATA_REG_CMD = ATA_REG_STATUS, + ATA_REG_BYTEL = ATA_REG_LBAM, + ATA_REG_BYTEH = ATA_REG_LBAH, + ATA_REG_DEVSEL = ATA_REG_DEVICE, + ATA_REG_IRQ = ATA_REG_NSECT, + + /* SETFEATURES stuff */ + SETFEATURES_XFER = 0x03, + XFER_UDMA_7 = 0x47, + XFER_UDMA_6 = 0x46, + XFER_UDMA_5 = 0x45, + XFER_UDMA_4 = 0x44, + XFER_UDMA_3 = 0x43, + XFER_UDMA_2 = 0x42, + XFER_UDMA_1 = 0x41, + XFER_UDMA_0 = 0x40, + XFER_MW_DMA_2 = 0x22, + XFER_MW_DMA_1 = 0x21, + XFER_MW_DMA_0 = 0x20, + XFER_PIO_4 = 0x0C, + XFER_PIO_3 = 0x0B, + XFER_PIO_2 = 0x0A, + XFER_PIO_1 = 0x09, + XFER_PIO_0 = 0x08, + XFER_SW_DMA_2 = 0x12, + XFER_SW_DMA_1 = 0x11, + XFER_SW_DMA_0 = 0x10, + XFER_PIO_SLOW = 0x00 +}; + + + /* * ATA Commands (only mandatory commands listed here) */ diff -purN u-boot/include/configs/sc520_cdp.h u-boot_chg/include/configs/sc520_cdp.h --- u-boot/include/configs/sc520_cdp.h 2007-02-21 11:00:32.000000000 +0530 +++ u-boot_chg/include/configs/sc520_cdp.h 2007-03-14 17:29:14.000000000 +0530 @@ -180,6 +180,15 @@ #undef CONFIG_IDE_LED /* no led for ide supported */ #undef CONFIG_IDE_RESET /* reset for ide unsupported... */ #undef CONFIG_IDE_RESET_ROUTINE /* no special reset function */ + +/************************************************************ +*SATA/Native Stuff +************************************************************/ +#define CFG_SATA_SUPPORTED 1 /*Conditional compilation of SATA libarary*/ +#define CFG_SATA_MAXBUS 2 /*Max Sata buses supported*/ +#define CFG_SATA_DEV_PER_BUS 2 /*Max no. of devices per bus/port*/ +#define CFG_SATA_MAXDEVICES (CFG_SATA_MAXBUS* CFG_SATA_DEV_PER_BUS) +#define CFG_ATA_PIIX 1 /*Supports ata_piix driver*/ /************************************************************ * ATAPI support (experimental) diff -purN u-boot/include/sata.h u-boot_chg/include/sata.h --- u-boot/include/sata.h 1970-01-01 05:30:00.000000000 +0530 +++ u-boot_chg/include/sata.h 2007-03-14 17:15:18.000000000 +0530 @@ -0,0 +1,130 @@ + + +#if (DEBUG_SATA) +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +struct sata_ioports { + unsigned long cmd_addr; + unsigned long data_addr; + unsigned long error_addr; + unsigned long feature_addr; + unsigned long nsect_addr; + unsigned long lbal_addr; + unsigned long lbam_addr; + unsigned long lbah_addr; + unsigned long device_addr; + unsigned long status_addr; + unsigned long command_addr; + unsigned long altstatus_addr; + unsigned long ctl_addr; + unsigned long bmdma_addr; + unsigned long scr_addr; +}; + + +struct sata_port{ + unsigned char port_no; /*primary-0, secondary=1*/ + struct sata_ioports ioaddr; /*ATA cmd/ctl/dma reg blks*/ + unsigned char ctl_reg; + unsigned char last_ctl; + unsigned char port_state; /*1-port is present and + 0-port is not available*/ + unsigned char dev_mask; + }; + + + +/***********SATA LIBRARY SPECIFIC DEFINITIONS AND DECLARATIONS**************/ +#ifdef SATA_DECL /*SATA library specific declarations*/ + #define ata_id_has_lba48(id) ((id)[83] & (1 << 10)) + #define ata_id_has_lba(id) ((id)[49] & (1 << 9)) + #define ata_id_has_dma(id) ((id)[49] & (1 << 8)) + #define ata_id_u32(id,n) \ + (((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)])) + #define ata_id_u64(id,n) \ + (((u64) (id)[(n) + 3] << 48) | \ + ((u64) (id)[(n) + 2] << 32) | \ + ((u64) (id)[(n) + 1] << 16) | \ + ((u64) (id)[(n) + 0]) ) +#endif + + +#ifdef SATA_DECL /*SATA library specific declarations*/ +static inline void ata_dump_id(u16 *id) +{ + PRINTF("49==0x%04x " + "53==0x%04x " + "63==0x%04x " + "64==0x%04x " + "75==0x%04x \n", + id[49], + id[53], + id[63], + id[64], + id[75]); + PRINTF("80==0x%04x " + "81==0x%04x " + "82==0x%04x " + "83==0x%04x " + "84==0x%04x \n", + id[80], + id[81], + id[82], + id[83], + id[84]); + PRINTF("88==0x%04x " + "93==0x%04x\n", + id[88], + id[93]); +} +#endif + +#ifdef SATA_DECL /*SATA library specific declarations*/ + int Sata_bus_softreset(int num); + void Sata_identify(int num,int dev); + void Sata_port(struct sata_ioports *ioport); + void Set_Feature_cmd(int num, int dev); + int Sata_devchk(struct sata_ioports *ioaddr,int dev); + void dev_select(struct sata_ioports *ioaddr,int dev); + u8 Sata_busy_wait(struct sata_ioports *ioaddr, int bits, + unsigned int max); + u8 Sata_chk_status(struct sata_ioports *ioaddr); + ulong sata_read (int device, lbaint_t blknr, + ulong blkcnt, ulong *buffer); + ulong sata_write(int device, lbaint_t blknr, + ulong blkcnt, ulong *buffer); + void msleep(int count); +#else + extern int Sata_bus_softreset(int num); + extern void Sata_identify(int num,int dev); + extern void Sata_port(struct sata_ioports *ioport); + extern void Set_Feature_cmd(int num, int dev); + extern ulong sata_read (int device, lbaint_t blknr, + ulong blkcnt, ulong *buffer); + extern ulong sata_write(int device, lbaint_t blknr, + ulong blkcnt, ulong *buffer); + extern void msleep(int count); +#endif + + +/************DRIVER SPECIFIC DEFINITIONS AND DECLARATIONS**************/ + +#ifdef DRV_DECL /*Driver specific declaration*/ + int init_sata(void); +#else + extern int init_sata(void); +#endif + + +#ifdef DRV_DECL /*Defines Driver Specific variables*/ + struct sata_port port[CFG_SATA_MAXBUS]; + block_dev_desc_t sata_dev_desc[CFG_SATA_MAXDEVICES]; + int curr_dev = -1; +#else + extern struct sata_port port[CFG_SATA_MAXBUS]; + extern block_dev_desc_t sata_dev_desc[CFG_SATA_MAXDEVICES]; + extern int curr_dev ; +#endif