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

📄 ata-ops.c

📁 freedos32的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ATA Driver for FD32 * by Luca Abeni & Nils Labugt * * This is free software; see GPL.txt */#include <dr-env.h>#include "ata.h"#include "disk.h"#include "ata-ops.h"#include "ata-wait.h"#include "ata-detect.h"extern int ata_global_flags;extern int max_pio_mode;#ifdef _DEBUG_void reg_dump(const struct ata_device* dev){    BYTE b;    b = fd32_inb(dev->interface->command_port + CMD_ERROR);    fd32_message("ERR:0x%x ", (BYTE)b);    b = fd32_inb(dev->interface->command_port + CMD_STATUS);    fd32_message("ST:0x%x ", (BYTE)b);    b = fd32_inb(dev->interface->command_port + CMD_SECT);    fd32_message("SCT:%u ", (BYTE)b);    b = fd32_inb(dev->interface->command_port + CMD_CYL_L);    fd32_message("CL:%u ", (BYTE)b);    b = fd32_inb(dev->interface->command_port + CMD_CYL_H);    fd32_message("CH:%u ", (BYTE)b);    b = fd32_inb(dev->interface->command_port + CMD_DEVHEAD);    fd32_message("DH:0x%x\n", (BYTE)b);}#endifint dev_is_busy(const struct ide_interface* iface){    return ((fd32_inb(iface->control_port) & ATA_STATUS_BSY) != 0);}int dev_not_ready(const struct ide_interface* iface){    return ((fd32_inb(iface->control_port) & ATA_STATUS_DRDY) == 0);}int bsy_drq_is_set(const struct ide_interface* iface){    return (fd32_inb(iface->control_port) & (ATA_STATUS_BSY | ATA_STATUS_DRQ));}int device_select( unsigned long max_wait, const struct ata_device* dev){    int res;    BYTE status;    extern int irq_reset(int i);    if(dev->flags & DEV_FLG_SLEEP)    {#if 1        return ATA_ESLEEP;#else        if(ata_reset( dev ) < 0)            return ATA_ESLEEP;#endif    }    if(bsy_drq_is_set(dev->interface))    {        res = ata_poll(MAX_WAIT_1, &bsy_drq_is_set, dev->interface);        if(res)        {            status = fd32_inb(dev->interface->command_port + CMD_STATUS);            if(status & ATA_STATUS_DRQ)            {                return ATA_DRQ_SET;            }            return ATA_ETOBUSY;        }    }    /* Skip device selection if already selected */    if(dev->interface->current_dev_bit != dev->dev_bit)    {        fd32_outb(dev->interface->command_port + CMD_DEVHEAD, dev->dev_bit);        dev->interface->current_dev_bit = dev->dev_bit;        if(bsy_drq_is_set(dev->interface))        {            res = ata_poll(MAX_WAIT_1, &bsy_drq_is_set, dev->interface);            if(res)            {                status = fd32_inb(dev->interface->command_port + CMD_STATUS);                if(status & ATA_STATUS_DRQ)                {                    return ATA_DRQ_SET;                }                return ATA_ETOBUSY;            }        }    }    irq_reset(dev->interface->irq);    return 0;}static void write_reg_start_count(DWORD start, WORD count, int use_48bit, const struct ata_device* dev){    if(dev->capabilities & ATA_CAPAB_LBA)    {        if(use_48bit)        {            fd32_outb(dev->interface->command_port + CMD_SECT, (BYTE)(start>>24));            fd32_outb(dev->interface->command_port + CMD_CYL_L, (BYTE)((QWORD)start>>32));            fd32_outb(dev->interface->command_port + CMD_CYL_H, (BYTE)((QWORD)start>>40));            fd32_outb(dev->interface->command_port + CMD_CNT, (BYTE)(count>>8));        }        else            fd32_outb(dev->interface->command_port + CMD_DEVHEAD,                      (BYTE)( ((start>>24) & 0x0F) | dev->dev_bit | ATA_DEVHEAD_L | 0xA0));        fd32_outb(dev->interface->command_port + CMD_SECT, (BYTE)start);        fd32_outb(dev->interface->command_port + CMD_CYL_L, (BYTE)(start>>8));        fd32_outb(dev->interface->command_port + CMD_CYL_H, (BYTE)(start>>16));    }    else    {        fd32_outb(dev->interface->command_port + CMD_SECT, (start % dev->sectors) + 1);        start /= dev->sectors;        fd32_outb(dev->interface->command_port + CMD_DEVHEAD, (BYTE)( (start % dev->heads) | dev->dev_bit | 0xA0 ) );        start /= dev->heads;        fd32_outb(dev->interface->command_port + CMD_CYL_L, (BYTE) start );        fd32_outb(dev->interface->command_port + CMD_CYL_H, (BYTE)(start>>8));    }    fd32_outb(dev->interface->command_port + CMD_CNT, (BYTE)count);}int pio_data_in(unsigned long max_wait, BYTE count, DWORD start,                void* buffer, struct ata_device* dev, BYTE command, int use_48bit){    int res, i, j, k;    BYTE status;    WORD* b = (WORD*)buffer;    res = device_select( max_wait, dev);    if(res)        return res;    if(command != ATA_CMD_IDENTIFY)    {        write_reg_start_count(start, count, use_48bit, dev);    }    fd32_outb(dev->interface->command_port + CMD_COMMAND, command);    do    {        if(dev->polled_mode)        {            delay(400);            fd32_inb(dev->interface->control_port);            if(dev_is_busy(dev->interface))            {                res = ata_poll(max_wait, &dev_is_busy, dev->interface);                if(res)                    return ATA_ETOBUSY;            }            status = fd32_inb(dev->interface->command_port + CMD_STATUS);        }        else        {            status = ata_cmd_irq(max_wait, dev->interface);            if(status == 0xFF)                return ATA_ETOIRQ;        }        if((status & ATA_STATUS_DRQ) != ATA_STATUS_DRQ)            return ATA_EDRQ_CLEAR;        /* If sectors_per_block == 0, then block mode is not enabled */        if(dev->sectors_per_block == 0)        {            for (i = 0; i < 256; i++)            {                *b++ = fd32_inw(dev->interface->command_port + CMD_DATA);            }            count--;        }        else        {            k = dev->sectors_per_block;            for(j=0; j<k; j++)            {                for (i = 0; i < 256; i++)                {                    *b++ = fd32_inw(dev->interface->command_port + CMD_DATA);                }                count--;                if(count == 0)                    break;            }        }        if(status & ATA_STATUS_ERR)        {            dev->status_reg = status;            dev->error_reg = fd32_inb(dev->interface->command_port + CMD_ERROR);            return ATA_ESTATUS;        }        if(count == 0)            break;    }    while(count);    return 0;}int ata_read(struct ata_device *d, DWORD start, DWORD count, void *b){    int res;    BYTE command;    WORD* buff = (WORD*)b;    unsigned long max_wait;    int use_48bit = FALSE;    int max_per_irq;    if(b == NULL || d == NULL)    {        return -1;    }    if(d->flags & (DEV_FLG_ST_TIMER_ACTIVE | DEV_FLG_STANDBY))    {        /* TODO: check timer (and DRDY?) first */        max_wait = 30 * 1000 * 1000;    }    else        max_wait = MAX_WAIT_1;    if(start + count > d->total_blocks)        return ATA_ERANGE;    start += d->first_sector;    if((start + count - 1) & 0xF0000000)    {        if(d->flags & DEV_FLG_48BIT_LBA)            use_48bit = TRUE;        else            return ATA_ERANGE;        if(d->sectors_per_block != 0)            command = ATA_CMD_READ_MULTIPLE_EXT;        else            command = ATA_CMD_READ_SECTORS_EXT;        max_per_irq = 256 * 256;    }    else    {        if(d->sectors_per_block != 0)            command = ATA_CMD_READ_MULTIPLE;        else            command = ATA_CMD_READ_SECTORS;        max_per_irq = 256;    }    while(count)    {        if(count >= max_per_irq)        {            /* When we ask for 0 sectors, then we mean 256 sectors */            res = pio_data_in(max_wait, 0, start, (void*)buff, d, command, use_48bit);            count -= max_per_irq;            buff += max_per_irq;        }        else        {            res = pio_data_in(max_wait, (BYTE)count, start, (void*)buff, d, command, use_48bit);            count = 0;        }        if(res)        {            return -1;        }    }    d->flags &= ~DEV_FLG_STANDBY;    return 0;}int pio_data_out(unsigned long max_wait, WORD count, DWORD start,                 void* buffer, struct ata_device* dev, BYTE command, int use_48bit){    int res, i, j, k;    BYTE status;    WORD* b = (WORD*)buffer;    res = device_select( max_wait, dev );    if(res)        return res;    write_reg_start_count(start, count, use_48bit, dev);    fd32_outb(dev->interface->command_port + CMD_CNT, count);    fd32_outb(dev->interface->command_port + CMD_COMMAND, command);    delay(400);    if(dev_is_busy(dev->interface))    {        res = ata_poll(MAX_WAIT_1, &dev_is_busy, dev->interface);        if(res)            return ATA_ETOBUSY;    }    status = fd32_inb(dev->interface->command_port + CMD_STATUS);    if(status & ATA_STATUS_ERR)        return ATA_ESTATUS;    do    {        if((status & ATA_STATUS_DRQ) != ATA_STATUS_DRQ)            return ATA_EDRQ_CLEAR;        /* If sectors_per_block == 0, then block mode is not enabled */        if(dev->sectors_per_block == 0)        {            for (i = 0; i < 256; i++)            {                fd32_outw(dev->interface->command_port + CMD_DATA, *b++ );            }            count--;        }        else        {            k = dev->sectors_per_block;            for(j=0; j<k; j++)            {                for (i = 0; i < 256; i++)                {                    fd32_outw(dev->interface->command_port + CMD_DATA, *b++ );                }                count--;                if(count == 0)                    break;            }        }        if(dev->polled_mode)        {            delay(400);            fd32_inb(dev->interface->control_port);            if(dev_is_busy(dev->interface))            {                res = ata_poll(max_wait, &dev_is_busy, dev->interface);                if(res)                    return ATA_ETOBUSY;            }            status = fd32_inb(dev->interface->command_port + CMD_STATUS);        }        else        {            status = ata_cmd_irq(max_wait, dev->interface);            if(status == 0xFF)                return ATA_ETOIRQ;        }        if(status & ATA_STATUS_ERR)        {            dev->status_reg = status;            dev->error_reg = fd32_inb(dev->interface->command_port + CMD_ERROR);            return ATA_ESTATUS;        }        if(count == 0)            break;    }    while(count);    return 0;}int ata_write(struct ata_device *d, DWORD start, DWORD count, const void *b){    int res;    BYTE command;    WORD* buff = (WORD*)b;    unsigned long max_wait;    int use_48bit = FALSE;    int max_per_irq;    if(b == NULL || d == NULL)    {        return -1;    }    if(d->flags & (DEV_FLG_ST_TIMER_ACTIVE | DEV_FLG_STANDBY))    {        /* TODO: check timer (and DRDY?) first */        max_wait = 30 * 1000 * 1000;    }    else        max_wait = MAX_WAIT_1;    if(start + count > d->total_blocks)        return ATA_ERANGE;    start += d->first_sector;    if((start + count - 1) & 0xF0000000)    {        if(d->flags & DEV_FLG_48BIT_LBA)            use_48bit = TRUE;        else            return ATA_ERANGE;        if(d->sectors_per_block != 0)            command = ATA_CMD_WRITE_MULTIPLE_EXT;        else            command = ATA_CMD_WRITE_SECTORS_EXT;        max_per_irq = 256 * 256;    }    else    {        if(d->sectors_per_block != 0)            command = ATA_CMD_WRITE_MULTIPLE;        else            command = ATA_CMD_WRITE_SECTORS;        max_per_irq = 256;    }    while(count)    {        if(count >= max_per_irq)

⌨️ 快捷键说明

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