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

📄 ata-ops.c

📁 freedos32的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
        {            res = pio_data_out(max_wait, 0, start, (void*)buff, d, command, use_48bit);            count -= max_per_irq;            buff += max_per_irq;        }        else        {            res = pio_data_out(max_wait, (BYTE)count, start, (void*)buff, d, command, use_48bit);            count = 0;        }        if(res)        {            return -1;        }    }    d->flags &= ~DEV_FLG_STANDBY;    return 0;}/* Here follows the non-data stuff */int command_ackn(struct ata_device* dev){    int res;    BYTE status;    if(dev->polled_mode)    {        delay(400);        fd32_inb(dev->interface->control_port);        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);    }    else    {        status = ata_cmd_irq(MAX_WAIT_1, 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;    }    return 0;}#if 0int non_data( struct ata_device* dev, BYTE command, BYTE* res_count_reg){    int res;    res = device_select( dev );    if(res)        return res;    /*    if(command != ATA_CMD_IDENTIFY)        {            write_reg_start_sect(start, dev);            fd32_outb(dev->interface->command_port + CMD_CNT, count);        }*/    fd32_outb(dev->interface->command_port + CMD_COMMAND, command);    res = command_ackn(dev);    if(res)        return res;    if(res_count_reg != NULL)        *res_count_reg = fd32_inb(dev->interface->command_port + CMD_CNT);    return 0;}#endifint ata_set_multiple( struct ata_device* dev, BYTE sectors){    int res;    if(sectors > dev->max_multiple_rw)        return ATA_EINVPARAM;    res = device_select( MAX_WAIT_1, dev);    if(res)        return res;    fd32_outb(dev->interface->command_port + CMD_CNT, sectors);    fd32_outb(dev->interface->command_port + CMD_COMMAND, ATA_CMD_SET_MULTIPLE_MODE);    return command_ackn(dev);}int ata_standby( struct ata_device* dev, BYTE timer){    int res;    res = device_select( MAX_WAIT_1, dev);    if(res)        return res;    fd32_outb(dev->interface->command_port + CMD_CNT, timer);    fd32_outb(dev->interface->command_port + CMD_COMMAND, ATA_CMD_STANDBY);    return command_ackn(dev);}int ata_idle( struct ata_device* dev, BYTE timer){    int res;    res = device_select( MAX_WAIT_1, dev);    if(res)        return res;    fd32_outb(dev->interface->command_port + CMD_CNT, timer);    fd32_outb(dev->interface->command_port + CMD_COMMAND, ATA_CMD_IDLE);    return command_ackn(dev);}int ata_standby_imm( struct ata_device* dev){    int res;    res = device_select( MAX_WAIT_1, dev);    if(res)        return res;    fd32_outb(dev->interface->command_port + CMD_COMMAND, ATA_CMD_STANDBY_IMMEDIATE);    return command_ackn(dev);}int ata_sleep( struct ata_device* dev){    int res;    res = device_select( MAX_WAIT_1, dev);    if(res)        return res;    fd32_outb(dev->interface->command_port + CMD_COMMAND, ATA_CMD_SLEEP);    return command_ackn(dev);}int ata_sreset( struct ata_device* dev){    BYTE b;    int res;    b = fd32_inb(dev->interface->control_port);    fd32_outb(dev->interface->control_port, b | ATA_SRST);    delay(8000);    fd32_outb(dev->interface->control_port, b & ~ATA_SRST);    ata_wait(2500);    /* What about the DEV bit? */    res = ata_poll(31*1000*1000, &dev_is_busy, dev->interface);    if(res<0)        return res;    /* FIXME: This is a hack! What PIO modes does the host support? */    /* On what type of bus does the controller reside? */    if(!(ata_global_flags & ATA_GFLAG_PIO_MODE))    {        ata_global_flags |= ATA_GFLAG_PIO_MODE;        max_pio_mode = 2;    }    if(dev->interface->dev0 != 0)        ata_detect_single(0, dev->interface, &(dev->interface->dev0), NULL);    if(dev->interface->dev1 != 0)        ata_detect_single(1, dev->interface, &(dev->interface->dev1), NULL);    return 0;}int ata_dev_reset( struct ata_device* dev){    int res;    BYTE status;    if(dev->interface->current_dev_bit != dev->dev_bit)    {        /* Is this correct? Should we wait for the other device? */        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;            }        }        fd32_outb(dev->interface->command_port + CMD_DEVHEAD, dev->dev_bit);        dev->interface->current_dev_bit = dev->dev_bit;    }    fd32_outb(dev->interface->command_port + CMD_COMMAND, ATA_CMD_DEVICE_RESET);    /* The device is not supposed to revert to defaults after this command, so we just return */    /* without reinitializing */    /* FIXME: proper timeout */    /* TODO: check (return?) diagnostics results */    return command_ackn(dev);}int ata_check_standby( struct ata_device* dev){    int res;    res = device_select( MAX_WAIT_1, dev);    if(res)        return res;    fd32_outb(dev->interface->command_port + CMD_COMMAND, ATA_CMD_CHECK_POW_MODE);    res = command_ackn(dev);    if(res)        return res;    res = fd32_inb(dev->interface->command_port + CMD_CNT);    if(res != 255)        return 1;    return 0;}int ata_set_pio_mode( struct ata_device* dev, int mode){    int res;    res = device_select( MAX_WAIT_1, dev);    if(res)        return res;    fd32_outb(dev->interface->command_port + CMD_FEATURES, 3);    fd32_outb(dev->interface->command_port + CMD_CNT, (BYTE)(mode | 0x08));    fd32_outb(dev->interface->command_port + CMD_COMMAND, ATA_CMD_SET_FEATURES);    return command_ackn(dev);}/* TODO: implement overlapped commands */int ata_packet_pio( unsigned long max_wait, /* how long to wait, in us */                    struct ata_device* dev,                    WORD* packet,        /* the command packet, also used for returning error info */                    int packet_size,    /* length of packet in bytes (minimum 12 bytes) */                    WORD* buffer,                    int max_count,        /* max number of bytes per transfer */                    unsigned long* total_bytes, /* return actual number of bytes transfered */                    unsigned long buffer_size) /* for safety, bytes */{    int res;    BYTE status;    int i;    BYTE ir;    BYTE* ebuff = (BYTE*)packet;    int count;    int buffer_overflow = FALSE;    *total_bytes = 0;    res = device_select( MAX_WAIT_1, dev);    if(res)    {        ebuff[0] = 0;        *(int*)&ebuff[4] = res;        return res;    }    fd32_outb(dev->interface->command_port + CMD_FEATURES, 0);     /* no overlap or DMA */    fd32_outb(dev->interface->command_port + CMD_CNT, 0);    fd32_outb(dev->interface->command_port + CMD_PI_COUNT_L, 0xFF & max_count);    fd32_outb(dev->interface->command_port + CMD_PI_COUNT_H, 0xFF & (max_count >> 8));    fd32_outb(dev->interface->command_port + CMD_COMMAND, ATA_CMD_PACKET);    delay(400);    if((dev->polled_mode == 0) && (dev->flags & DEV_FLG_IRQ_ON_PCMD))    {        /* Only old and odd devices arrive here */        status = ata_cmd_irq(MAX_WAIT_1, dev->interface);        if(status == 0xFF)        {            ebuff[0] = 0;            *(int*)&ebuff[4] = ATA_ETOIRQ;            return ATA_ETOIRQ;        }    }    else    {        if(dev_is_busy(dev->interface))        {            res = ata_poll(MAX_WAIT_1, &dev_is_busy, dev->interface);            if(res)            {                ebuff[0] = 0;                *(int*)&ebuff[4] = ATA_ETOBUSY;                return ATA_ETOBUSY;            }        }        status = fd32_inb(dev->interface->command_port + CMD_STATUS);    }    ir = fd32_inb(dev->interface->command_port + CMD_PI_INTERRUPT_REASON);    if(((ir & 0x07) != ATAPI_CD) /*|| (status & ATA_STATUS_ERR)*/ || !(status & ATA_STATUS_DRQ))    {        /* return error info in the command packet buffer */        ebuff[0] = 1;        ebuff[1] = dev->status_reg = status;        ebuff[2] = dev->error_reg = fd32_inb(dev->interface->command_port + CMD_ERROR);        ebuff[3] = ir;        *(int*)&ebuff[4] = ATA_EPIPRECMD;        return ATA_EPIPRECMD;    }    /* sending command packet */    for(i=0; i<packet_size; i+=2)    {        fd32_outw(dev->interface->command_port + CMD_DATA, *packet++ );    }    while(1)    {        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)                {                    ebuff[0] = 0;                    *(int*)&ebuff[4] = ATA_ETOBUSY;                    return ATA_ETOBUSY;                }            }            status = fd32_inb(dev->interface->command_port + CMD_STATUS);        }        else        {            status = ata_cmd_irq(max_wait, dev->interface);            if(status == 0xFF)            {                ebuff[0] = 0;                *(int*)&ebuff[4] = ATA_ETOIRQ;                return ATA_ETOIRQ;            }        }        ir = fd32_inb(dev->interface->command_port + CMD_PI_INTERRUPT_REASON);        if(!(status & ATA_STATUS_DRQ))        {            /* If we arrive here, then there is no more data or there is an error*/            if(status & ATAPI_CHECK)            {                /* return error info in the command packet buffer */                ebuff[0] = 1;                ebuff[1] = dev->status_reg = status;                ebuff[2] = dev->error_reg = fd32_inb(dev->interface->command_port + CMD_ERROR);                ebuff[3] = ir;                *(int*)&ebuff[4] = ATA_EPIPOSTCMD;                return ATA_EPIPOSTCMD;            }            if(buffer_overflow == TRUE)            {                ebuff[0] = 0;                *(int*)&ebuff[4] = ATA_EOWRFL;                return ATA_EOWRFL;            }            /* Success! */            return 0;        }        count = fd32_inb(dev->interface->command_port + CMD_PI_COUNT_H);        count <<= 8;        count |= fd32_inb(dev->interface->command_port + CMD_PI_COUNT_L);        *total_bytes += count;        /* round up and divide */        count++;        count >>= 1;        if(*total_bytes > buffer_size)        {            buffer_overflow = TRUE;            if(ir & ATAPI_IO)            {                /* We have run out of space to store data. We choose to paly along with the device */                /* to avoid device reset, but we will loose the extra data */                if(*total_bytes > buffer_size + 1024*1024*16)                {                    /* No, this has gone too far! Abort! */                    ebuff[0] = 0;                    *(int*)&ebuff[4] = ATA_EPIFATAL;                    return ATA_EPIFATAL;                }                for(i=0; i<count; i++)                {                    if(*total_bytes - (count-i)*2 < buffer_size)                        *buffer++ = fd32_inw(dev->interface->command_port + CMD_DATA);                    else                        fd32_inw(dev->interface->command_port + CMD_DATA);                }            }            else            {                /* The device wants more data than we have */                /* We choose abort, but we write what we have first */                /* TODO */                ebuff[0] = 0;                *(int*)&ebuff[4] = ATA_EPIFATAL;                return ATA_EPIFATAL;            }        }        else        {            if(ir & ATAPI_IO)            {                for(i=0; i<count; i++)                {                    *buffer++ = fd32_inw(dev->interface->command_port + CMD_DATA);                }            }            else            {                for(i=0; i<count; i++)                {                    fd32_outw(dev->interface->command_port + CMD_DATA, *buffer++ );                }            }        }    }}

⌨️ 快捷键说明

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