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

📄 ata.c

📁 编译后直接运行的MP3播放器全部C语言源代码 一个包含FAT文件系统、系统引导 Boot、FLASH Driver等内容的
💻 C
📖 第 1 页 / 共 2 页
字号:
        DEBUGF("ata_flush()\n");        delayed_write = false;        ata_write_sectors(delayed_sector_num, 1, delayed_sector);    }}static int check_registers(void){    if ( ATA_STATUS & STATUS_BSY )            return -1;    ATA_NSECTOR = 0xa5;    ATA_SECTOR  = 0x5a;    ATA_LCYL    = 0xaa;    ATA_HCYL    = 0x55;    if ((ATA_NSECTOR == 0xa5) &&        (ATA_SECTOR  == 0x5a) &&        (ATA_LCYL    == 0xaa) &&        (ATA_HCYL    == 0x55))        return 0;    return -2;}static int freeze_lock(void){    ATA_SELECT = ata_device;    if (!wait_for_rdy())        return -1;    ATA_COMMAND = CMD_SECURITY_FREEZE_LOCK;    if (!wait_for_rdy())        return -2;    return 0;}void ata_spindown(int seconds){    sleep_timeout = seconds * HZ;}#ifdef HAVE_ATA_POWER_OFFvoid ata_poweroff(bool enable){    if (enable)        poweroff_timeout = 2*HZ;    else        poweroff_timeout = 0;}#endifbool ata_disk_is_active(void){    return !sleeping;}static int ata_perform_sleep(void){    int ret = 0;    mutex_lock(&ata_mtx);    ATA_SELECT = ata_device;    if(!wait_for_rdy()) {        DEBUGF("ata_perform_sleep() - not RDY\n");        mutex_unlock(&ata_mtx);        return -1;    }    ATA_COMMAND = CMD_SLEEP;    if (!wait_for_rdy())    {        DEBUGF("ata_perform_sleep() - CMD failed\n");        ret = -2;    }    sleeping = true;    mutex_unlock(&ata_mtx);    return ret;}int ata_standby(int time){    int ret = 0;    mutex_lock(&ata_mtx);    ATA_SELECT = ata_device;    if(!wait_for_rdy()) {        DEBUGF("ata_standby() - not RDY\n");        mutex_unlock(&ata_mtx);        return -1;    }    if(time)        ATA_NSECTOR = ((time + 5) / 5) & 0xff; /* Round up to nearest 5 secs */    else        ATA_NSECTOR = 0; /* Disable standby */            ATA_COMMAND = CMD_STANDBY;    if (!wait_for_rdy())    {        DEBUGF("ata_standby() - CMD failed\n");        ret = -2;    }    mutex_unlock(&ata_mtx);    return ret;}int ata_sleep(void){    queue_post(&ata_queue, Q_SLEEP, NULL);    return 0;}void ata_spin(void){    last_user_activity = current_tick;}static void ata_thread(void){    static long last_sleep = 0;    struct event ev;        while (1) {        while ( queue_empty( &ata_queue ) ) {            if ( !spinup && sleep_timeout && !sleeping &&                 TIME_AFTER( current_tick,                              last_user_activity + sleep_timeout ) &&                 TIME_AFTER( current_tick,                              last_disk_activity + sleep_timeout ) )            {                ata_perform_sleep();                last_sleep = current_tick;            }#ifdef HAVE_ATA_POWER_OFF            if ( !spinup && sleeping && poweroff_timeout && !poweroff &&                 TIME_AFTER( current_tick, last_sleep + poweroff_timeout ))            {                mutex_lock(&ata_mtx);                ide_power_enable(false);                mutex_unlock(&ata_mtx);                poweroff = true;            }#endif            sleep(HZ/4);        }        queue_wait(&ata_queue, &ev);        switch ( ev.id ) {#ifndef USB_NONE            case SYS_USB_CONNECTED:                if (poweroff) {                    mutex_lock(&ata_mtx);                    led(true);                    ata_power_on();                    led(false);                    mutex_unlock(&ata_mtx);                }                /* Tell the USB thread that we are safe */                DEBUGF("ata_thread got SYS_USB_CONNECTED\n");                usb_acknowledge(SYS_USB_CONNECTED_ACK);                /* Wait until the USB cable is extracted again */                usb_wait_for_disconnect(&ata_queue);                break;#endif            case Q_SLEEP:                last_disk_activity = current_tick - sleep_timeout + (HZ/2);                break;        }    }}/* Hardware reset protocol as specified in chapter 9.1, ATA spec draft v5 */int ata_hard_reset(void){    int ret;        /* state HRR0 */    and_b(~0x02, &PADRH); /* assert _RESET */    sleep(1); /* > 25us */    /* state HRR1 */    or_b(0x02, &PADRH); /* negate _RESET */    sleep(1); /* > 2ms */    /* state HRR2 */    ATA_SELECT = ata_device; /* select the right device */    ret = wait_for_bsy();    /* Massage the return code so it is 0 on success and -1 on failure */    ret = ret?0:-1;    return ret;}static int perform_soft_reset(void){    int ret;    int retry_count;        ATA_SELECT = SELECT_LBA | ata_device;    ATA_CONTROL = CONTROL_nIEN|CONTROL_SRST;    sleep(1); /* >= 5us */    ATA_CONTROL = CONTROL_nIEN;    sleep(1); /* >2ms */    /* This little sucker can take up to 30 seconds */    retry_count = 8;    do    {        ret = wait_for_rdy();    } while(!ret && retry_count--);    /* Massage the return code so it is 0 on success and -1 on failure */    ret = ret?0:-1;    return ret;}int ata_soft_reset(void){    int ret;        mutex_lock(&ata_mtx);    ret = perform_soft_reset();    mutex_unlock(&ata_mtx);    return ret;}static int ata_power_on(void){    int rc;        ide_power_enable(true);    if( ata_hard_reset() )        return -1;    rc = set_features();    if (rc)        return rc * 10 - 2;    if (set_multiple_mode(multisectors))        return -3;    if (freeze_lock())        return -4;    return 0;}static int master_slave_detect(void){    /* master? */    ATA_SELECT = 0;    if ( ATA_STATUS & (STATUS_RDY|STATUS_BSY) ) {        ata_device = 0;        DEBUGF("Found master harddisk\n");    }    else {        /* slave? */        ATA_SELECT = SELECT_DEVICE1;        if ( ATA_STATUS & (STATUS_RDY|STATUS_BSY) ) {            ata_device = SELECT_DEVICE1;            DEBUGF("Found slave harddisk\n");        }        else            return -1;    }    return 0;}static int io_address_detect(void){   /* now, use the HW mask instead of probing */    if (read_hw_mask() & ATA_ADDRESS_200)    {        ata_io_address = 0x200; /* For debug purposes only */        old_recorder = false;        ata_control = ATA_CONTROL1;    }    else    {        ata_io_address = 0x300; /* For debug purposes only */        old_recorder = true;        ata_control = ATA_CONTROL2;    }    return 0;}void ata_enable(bool on){    if(on)        and_b(~0x80, &PADRL); /* enable ATA */    else        or_b(0x80, &PADRL); /* disable ATA */    or_b(0x80, &PAIORL);}static int identify(void){    int i;    ATA_SELECT = ata_device;    if(!wait_for_rdy()) {        DEBUGF("identify() - not RDY\n");        return -1;    }    ATA_COMMAND = CMD_IDENTIFY;    if (!wait_for_start_of_transfer())    {        DEBUGF("identify() - CMD failed\n");        return -2;    }    for (i=0; i<SECTOR_SIZE/2; i++)        /* the IDENTIFY words are already swapped */        identify_info[i] = ATA_DATA;        return 0;}static int set_multiple_mode(int sectors){    ATA_SELECT = ata_device;    if(!wait_for_rdy()) {        DEBUGF("set_multiple_mode() - not RDY\n");        return -1;    }    ATA_NSECTOR = sectors;    ATA_COMMAND = CMD_SET_MULTIPLE_MODE;    if (!wait_for_rdy())    {        DEBUGF("set_multiple_mode() - CMD failed\n");        return -2;    }    return 0;}static int set_features(void){    struct {        unsigned char id_word;        unsigned char id_bit;        unsigned char subcommand;        unsigned char parameter;    } features[] = {        { 83, 3, 0x05, 1 },    /* power management: lowest power */        { 83, 9, 0x42, 0x80 }, /* acoustic management: lowest noise */        { 82, 6, 0xaa, 0 },    /* enable read look-ahead */        { 83, 14, 0x03, 0 },   /* force PIO mode */        { 0, 0, 0, 0 }         /* <end of list> */    };    int i;    int pio_mode = 2;    /* Find out the highest supported PIO mode */    if(identify_info[64] & 2)        pio_mode = 4;    else        if(identify_info[64] & 1)            pio_mode = 3;    /* Update the table */    features[3].parameter = 8 + pio_mode;        ATA_SELECT = ata_device;    if (!wait_for_rdy()) {        DEBUGF("set_features() - not RDY\n");        return -1;    }    for (i=0; features[i].id_word; i++) {        if (identify_info[features[i].id_word] & (1 << features[i].id_bit)) {            ATA_FEATURE = features[i].subcommand;            ATA_NSECTOR = features[i].parameter;            ATA_COMMAND = CMD_SET_FEATURES;            if (!wait_for_rdy()) {                DEBUGF("set_features() - CMD failed\n");                return -10 - i;            }            if(ATA_ALT_STATUS & STATUS_ERR) {                if(ATA_ERROR & ERROR_ABRT) {                    return -20 - i;                }            }        }    }    return 0;}unsigned short* ata_get_identify(void){    return identify_info;}int ata_init(void){    int rc;    bool coldstart = (PACR2 & 0x4000) != 0;     mutex_init(&ata_mtx);    led(false);    /* Port A setup */    or_b(0x02, &PAIORH); /* output for ATA reset */    or_b(0x02, &PADRH); /* release ATA reset */    PACR2 &= 0xBFFF; /* GPIO function for PA7 (IDE enable) */    sleeping = false;    ata_enable(true);    if ( !initialized ) {        if (!ide_powered()) /* somebody has switched it off */        {            ide_power_enable(true);            sleep(HZ); /* allow voltage to build up */        }        if (coldstart)        {            /* Reset both master and slave, we don't yet know what's in */            /* this is safe because non-present devices don't report busy */            ata_device = 0;            if (ata_hard_reset())                return -1;            ata_device = SELECT_DEVICE1;            if (ata_hard_reset())                return -2;        }        rc = master_slave_detect();        if (rc)            return -10 + rc;        rc = io_address_detect();        if (rc)            return -20 + rc;        /* symptom fix: else check_registers() below may fail */        if (coldstart && !wait_for_bsy())        {               return -29;        }        rc = check_registers();        if (rc)            return -30 + rc;        rc = freeze_lock();        if (rc)            return -40 + rc;        rc = identify();        if (rc)            return -50 + rc;        multisectors = identify_info[47] & 0xff;        DEBUGF("ata: %d sectors per ata request\n",multisectors);                rc = set_features();        if (rc)            return -60 + rc;        queue_init(&ata_queue);        last_disk_activity = current_tick;        create_thread(ata_thread, ata_stack,                      sizeof(ata_stack), ata_thread_name);        initialized = true;    }    rc = set_multiple_mode(multisectors);    if (rc)        return -70 + rc;    return 0;}

⌨️ 快捷键说明

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