⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ide.c

📁 em86xx 完整启动程序,支持网络下载与串通下载
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************** Copyright (c) 2003-2004 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the EM86XX boot loader *//* * ide.c * * IDE controller * * by Ho Lee 03/12/2003 */#include "config.h"#include "uart.h"#include "io.h"#include "util.h"#include "hardware.h"#include "em86xxapi.h"#include "irqs.h"#include "timer.h"#include "ide.h"#include "atapi.h"#ifdef CONFIG_ENABLE_FIP#include "fip.h"extern const char *fiptext;#endif#define IDE_VERBOSE         0/* CDROM try status, only for drive 0 */int cdrom0_tray_state = 0;int ide_init(void){    // Peripheral Bus interface    // 0x00080000 is optimal for both of PIO and DMA for recent HDDs#if 0    // use timing 1 : normal transfer    __raw_writel(DEFAULT_PB_TIMING1, REG_BASE_HOST + PB_timing1);    __raw_writel(DEFAULT_PB_USE_TIMING1, REG_BASE_HOST + PB_use_timing1);    // use timing 2 : DMA transfer    __raw_writel(DEFAULT_PB_TIMING2, REG_BASE_HOST + PB_timing2);    __raw_writel(DEFAULT_PB_USE_TIMING2, REG_BASE_HOST + PB_use_timing2);#endif#if 0    // use timing 1, 2 : normal transfer R/W    __raw_writel(0x00080000, REG_BASE_HOST + PB_timing1);    __raw_writel(0x000001e3, REG_BASE_HOST + PB_use_timing1);    __raw_writel(0x00030000, REG_BASE_HOST + PB_timing2);    __raw_writel(0x000001d3, REG_BASE_HOST + PB_use_timing2);    // use timing 3, 4 : DMA transfer R/W    __raw_writel(0x00080000, REG_BASE_HOST + PB_timing3);    __raw_writel(0x000002e3, REG_BASE_HOST + PB_use_timing3);    __raw_writel(0x00050000, REG_BASE_HOST + PB_timing4);    __raw_writel(0x000002d3, REG_BASE_HOST + PB_use_timing4);#endif    return 0;}#ifdef CONFIG_ENABLE_IDEunsigned long g_ide_reg_base = #ifdef CONFIG_ENABLE_IDE_ISA    REG_BASE_HOST_ISAIDE;#else    REG_BASE_HOST_BMIDE;#endif//// IDE Initialize//static int g_ide_dsinited = 0;static ide_info_t g_ideinfo[MAX_DRIVES];int ide_dsinit(void){    int i;    for (i = 0; i < MAX_DRIVES; ++i)        g_ideinfo[i].select.all = ((i << 4) | 0xa0);    g_ide_dsinited = 1;    return 0;}int ide_found(int mask){    int drive, found = 0;    ide_info_t *pideinfo;    if (!g_ide_dsinited)        ide_dsinit();    for (drive = 0; drive < MAX_DRIVES; ++drive) {        pideinfo = g_ideinfo + drive;        if (pideinfo->type & mask)             found |= (1 << drive);    }    return found;}#ifdef CONFIG_ENABLE_IDE_BMstatic void em86xx_ide_config_drive(int drive, ide_info_t *pideinfo){	ide_id_t *id = &pideinfo->id;	int speed=0;	int mode=0;	int set_mode;	if ((__raw_readl(REG_BASE_host_interface + IDECTRL_idestatus) & 0x02) == 0x02)        mode = 1;   // 40 donductor cable (UDMA33) : Mode 0/1/2	else 		mode = 4;   // 80 conductor cable : Mode 0/1/2/3/4/5/6	switch(mode) {		case 0x04:			if (id->dma_ultra & 0x0040) 				{ speed = XFER_UDMA_6; break; }		case 0x03:			if (id->dma_ultra & 0x0020) 				{ speed = XFER_UDMA_5; break; }		case 0x02:			if (id->dma_ultra & 0x0010) 				{ speed = XFER_UDMA_4; break; }			if (id->dma_ultra & 0x0008) 				{ speed = XFER_UDMA_3; break; }		case 0x01:			if (id->dma_ultra & 0x0004) 				{ speed = XFER_UDMA_2; break; }			if (id->dma_ultra & 0x0002) 				{ speed = XFER_UDMA_1; break; }			if (id->dma_ultra & 0x0001) 				{ speed = XFER_UDMA_0; break; }		case 0x00:			if (id->dma_mword & 0x0004) 				{ speed = XFER_MW_DMA_2; break; }			if (id->dma_mword & 0x0002) 				{ speed = XFER_MW_DMA_1; break; }			if (id->dma_mword & 0x0001) 				{ speed = XFER_MW_DMA_0; break; }			if (id->dma_1word & 0x0004) 				{ speed = XFER_SW_DMA_2; break; }			if (id->dma_1word & 0x0002) 				{ speed = XFER_SW_DMA_1; break; }			if (id->dma_1word & 0x0001) 				{ speed = XFER_SW_DMA_0; break; }	}	/* For CDROM, we do the max. MDMA mode 2 */	if ((speed > XFER_MW_DMA_2)  && (pideinfo->type == IDE_ATAPI)) 		speed = XFER_MW_DMA_2;	if (speed == 0) //PIO mode		speed = id->pio_modes; 	set_mode = speed & 0x0f;		if (pideinfo->cap_udma && (speed >= XFER_UDMA_0 && speed <= XFER_UDMA_7)) {	// setup UDMA mode		// setup timing for Ultra DMA		static unsigned int s_udma_tim1[] = {#if 0			0x33331f17, 0x3333180f, 0x3333130b, 0x33331308,			0x33331305, 0x33331003, 0x11110202,#endif			0x33332016, 0x3333190e, 0x3333140a, 0x33331407,			0x33331404, 0x33331103, 0x33331102, 0x11110202		};		static unsigned int s_udma_tim2[] = {#if 0			0x0000020d, 0x00000209, 0x00000206, 0x00000203, 			0x00000201, 0x00000201, 0x00000201,#endif			0x0000010d, 0x00000109, 0x00000106, 0x00000103,			0x00000101, 0x00000101, 0x00000101, 0x00000101		};		uart_printf("  Set drive %d to Ultra DMA set_mode %d\n", drive, set_mode);        // set drive speed        ide_set_drive_speed(drive, XFER_UDMA_0 | set_mode);		pideinfo->use_udma = 1;		// enable Ultra DMA		__raw_writel(__raw_readl(REG_BASE_host_interface + IDECTRL_udmactl) | ((drive == 0) ? 0x01 : 0x02),			REG_BASE_host_interface + IDECTRL_udmactl);				// set timing register		__raw_writel(s_udma_tim1[set_mode], REG_BASE_host_interface + ((drive == 0) ? IDECTRL_pri_drv0udmatim1 : IDECTRL_pri_drv1udmatim1));		__raw_writel(s_udma_tim2[set_mode], REG_BASE_host_interface + ((drive == 0) ? IDECTRL_pri_drv0udmatim2 : IDECTRL_pri_drv1udmatim2));	} else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {     // setup DMA mode		uart_printf("  Set drive %d to Multi-word DMA set_mode %d\n", drive, set_mode);        // set drive speed        ide_set_drive_speed(drive, XFER_MW_DMA_0 | set_mode);        pideinfo->use_dma = 1;		{			// setup timing for Multi-word DMA			static unsigned int s_dma_tim[] = {#if 0				0xdf2a2a93, 0x9d0f0952, 0x970d0441, 0x82020211 #endif				0xdf2a2a93, 0x9d0f0952, 0x970d0441			};			static unsigned int s_udma_tim1[] = {#if 0				0x35440b08, 0x35440a06, 0x35440804, 0x11110202#endif				0x35440b08, 0x35440a06, 0x35440804			};			static unsigned int s_udma_tim2[] = {#if 0				0x00000208, 0x00000206, 0x00000204, 0x00000202#endif				0x00000208, 0x00000206, 0x00000204			};			__raw_writel(s_dma_tim[set_mode], REG_BASE_host_interface + ((drive == 0) ? IDECTRL_pri_drv0tim : IDECTRL_pri_drv1tim));			__raw_writel(s_udma_tim1[set_mode], REG_BASE_host_interface + ((drive == 0) ? IDECTRL_pri_drv0udmatim1 : IDECTRL_pri_drv1udmatim1));			__raw_writel(s_udma_tim2[set_mode], REG_BASE_host_interface + ((drive == 0) ? IDECTRL_pri_drv0udmatim2 : IDECTRL_pri_drv1udmatim2));		}	} else if (speed >= XFER_PIO_0 && speed <= XFER_PIO_4) {		// setup timing for PIO set_mode		static unsigned int s_pio_tim[] = {#if 0			0xf73900d5, 0xcb2f0093, 0xaf280052, 0xa30f0d51, 0x970d0441#endif			0xf7200dd5, 0xcc180d93, 0xaf130d52, 0xa30f0d51, 0x970d0441		};		set_mode -= 8;		uart_printf("  Set drive %d to PIO set_mode %d\n", drive, set_mode);		__raw_writel(s_pio_tim[set_mode], REG_BASE_host_interface + ((drive == 0) ? IDECTRL_pri_drv0tim : IDECTRL_pri_drv1tim));	} 	return;}#endifint ide_probe(int drivemask, int verbose){    int i, drive, nfound;    ide_info_t *pideinfo;    if (!g_ide_dsinited)        ide_dsinit();    for (drive = 0, nfound = 0; drive < MAX_DRIVES; ++drive) {        if (drivemask & (1 << drive)) {            if (verbose)                uart_printf("Probing drive %d :\n", drive);                        pideinfo = ide_identify(drive);                        if (pideinfo->type != IDE_NONE) {                if (verbose)                     uart_printf("  Found %s device : ", (pideinfo->type == IDE_ATA) ? "ATA" : "ATAPI");                else                    uart_printf("IDE %d (%s) : ", drive, (pideinfo->type == IDE_ATA) ? "ATA" : "ATAPI");            }                        if (pideinfo->type != IDE_NONE) {                ++nfound;                pideinfo->use_dma = 0;                pideinfo->use_udma = 0;                uart_printf("%s, %dMB, %s, %s\n", pideinfo->id.model_num, pideinfo->size,                     pideinfo->lba ? "LBA" : "CHS",                    pideinfo->cap_udma ? "UDMA" : (pideinfo->cap_dma ? "DMA" : "No DMA"));                if (!pideinfo->lba && verbose)                    uart_printf("  cylinders = %d, heads = %d, sectors = %d\n",                        pideinfo->cyls, pideinfo->heads, pideinfo->sectors);                 if (verbose) {                    uart_puts("  ");                    if (pideinfo->cap_udma)                        uart_printf("UDMA = 0x%04x, ", pideinfo->id.dma_ultra);                    uart_printf("MDMA = 0x%04x, PIO = 0x%04x\n",                        pideinfo->id.dma_mword, pideinfo->id.pio_modes);                    uart_printf("  PIO mode support :");                    if (pideinfo->id.pio_modes & 0x01)                        uart_puts(" 3");                    if (pideinfo->id.pio_modes & 0x02)                        uart_puts(" 4");                    uart_puts("\n");                    uart_printf("  Major Rev = 0x%04x, Minor Rev = 0x%04x\n",                        pideinfo->id.major_ver, pideinfo->id.minor_ver);                }#ifdef CONFIG_ENABLE_IDE_BM				em86xx_ide_config_drive(drive, pideinfo);#else                // setup DMA mode                if (!pideinfo->use_udma && pideinfo->id.dma_mword & 0x0f) {					ide_id_t *id = &pideinfo->id;					int speed=0, set_mode;					if (id->dma_mword & 0x0004) 						speed = XFER_MW_DMA_2;					else if (id->dma_mword & 0x0002) 						speed = XFER_MW_DMA_1; 					else if (id->dma_mword & 0x0001) 						speed = XFER_MW_DMA_0;  					if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {					 // setup DMA mode						set_mode = speed & 0x0f;						uart_printf("  Set drive %d to Multi-word DMA set_mode %d\n", drive, set_mode);						// set drive speed						ide_set_drive_speed(drive, XFER_MW_DMA_0 | set_mode);						pideinfo->use_dma = 1;					}				}#endif                // read partition table                if (pideinfo->type == IDE_ATA) {                    pideinfo->npart = ide_read_partition(drive, pideinfo->part, 0);                    if (verbose) {                        uart_puts("  Partitions : ");                        for (i = 0; i < pideinfo->npart; ++i)                            if (pideinfo->part[i].valid)                                uart_printf("p%d ", i);                        uart_puts("\n");                    }                } else                    pideinfo->npart = 0;            }        }    }    return nfound;}//// IDE command//static int ide_command(int cmd, int drive, int feature, int cyl, int head, int sector, int nsector, void *buf, int buflen);static void ide_fixstring(unsigned char *s, const int bytecount, const int byteswap);// ide_command : sends command to ATA/ATAPI device and then read or write data//   cmd : ATACMD_//   drive : 0/1 (master/slave)//   feature, cyl, head, sector, nsector : IDE registers//   buf : buffer for read or write//   buflen : buffer length in bytesint ide_command(int cmd, int drive, int feature, int cyl, int head, int sector, int nsector, void *buf, int buflen){#if IDE_VERBOSE    static struct {        int cmd;        char *name;    } s_cmdnamelist[] = {        { ATACMD_NOP, "NOP" },        { ATACMD_DEVICERESET, "Device Reset" },        { ATACMD_READ, "Read Sector" },        { ATACMD_WRITE, "Write Sector" },        { ATACMD_FORMAT, "Format Sector" },        { ATACMD_SEEK, "Seek" },        { ATACMD_DIAGNOSE, "Diagnose" },        { ATACMD_PIDENTIFY, "ATAPI Identify" },        { ATACMD_READDMA, "Read Sector by DMA" },        { ATACMD_WRITEDMA, "Write Sector by DMA" },        { ATACMD_IDENTIFY, "ATA Identify" },        { -1, NULL },    };    int i;#endif        int status;        // Selecting drive#if IDE_VERBOSE    uart_puts("  Select, ");#endif    if (ide_select_drive(drive, (cmd == ATACMD_IDENTIFY || cmd == ATACMD_PIDENTIFY) ? 0 : 1)) {#if IDE_VERBOSE        uart_puts("No device\n");#endif        return 1;    }         // Sending command    ide_outb(feature, IDE_FEATURE_REG);    ide_outb(nsector, IDE_NSECTOR_REG);    ide_outb(sector, IDE_SECTOR_REG);    ide_outb((cyl & 0xff), IDE_LCYL_REG);    ide_outb((cyl >> 8) & 0xff, IDE_HCYL_REG);    ide_outb(head | g_ideinfo[drive].select.all, IDE_SELECT_REG);    #if IDE_VERBOSE    for (i = 0; s_cmdnamelist[i].cmd >= 0; ++i) {        if (cmd == s_cmdnamelist[i].cmd) {            uart_printf("%s, ", s_cmdnamelist[i].name);            break;        }    }    if (s_cmdnamelist[i].cmd < 0)        uart_printf("Command 0x%02x, ", cmd);#endif    ide_outb(cmd, IDE_COMMAND_REG);    // Reading or Writing data    if (buf && buflen > 0) {        if (cmd == ATACMD_WRITE) {            while (buflen > 0) {#if IDE_VERBOSE                uart_puts("Writing\n");                if (buflen > SECTOR_SIZE)                    uart_puts(", ");                else                    uart_puts("\n");#endif                ide_wait_stat(IDESTAT_DRQ, IDESTAT_DRQ, 0);                ide_output_data((unsigned short *) buf, SECTOR_SIZE / 2);                buf = (unsigned char *) buf + SECTOR_SIZE;                buflen -= SECTOR_SIZE;                ide_wait_stat(IDESTAT_BUSY, 0, 0);            }        } else {            memset(buf, 0xbe, buflen);            while (buflen > 0) {                ide_wait_stat(IDESTAT_BUSY, 0, 0);                status = ide_inb(IDE_STATUS_REG);                if (status & IDESTAT_DRQ) {#if IDE_VERBOSE                    uart_puts("Reading");                    if (buflen > SECTOR_SIZE)                        uart_puts(", ");                    else                        uart_puts("\n");#endif                    ide_input_data((unsigned short *) buf, SECTOR_SIZE / 2);                    buf = (unsigned char *) buf + SECTOR_SIZE;                    buflen -= SECTOR_SIZE;                } else {#if IDE_VERBOSE                    uart_puts("No Data\n"); #endif                    return 2;                }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -