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

📄 bddrv.c

📁 Linux0.01设备驱动程序 最精简的linux代码 适合操作系统入门
💻 C
📖 第 1 页 / 共 5 页
字号:
        printf("floppy_await_interrupt: timeout\n");
        return -1;
    }
    /* read in command result bytes */
    for(temp = 0; temp < 7; temp++)
    {
        if((inportb(ioadr + FDC_MSR) & 0x10) == 0)
            break;
        status[temp] = floppy_get_byte(ioadr);
    }
    /* perform "sense interrupt" */
    floppy_send_byte(ioadr, 0x08); /* CMD_SENSEI */
    fdev->sr0 = floppy_get_byte(ioadr);
    fdev->curr_track = floppy_get_byte(ioadr);

    /* */
#if 1
    DEBUG(printf("status byte returned by floppy controller: 0x%X\n",
                 status[0]);)
#else
    DEBUG(
        printf("status returned by floppy controller:\n");
        printf("drive %u, head %u\n", status[0] & 3,
               (status[0] >> 2) & 1);
        printf("not ready on R/W or SS access to head 1: %u\n",
               (status[0] >> 3) & 1);
        printf("equipment check: %u\n",
               (status[0] >> 4) & 1);
        printf("seek complete: %u\n",
               (status[0] >> 5) & 1);
        printf("last command status: ");
        switch(status[0] >> 6)
    {
    case 0:	printf("success\n");	break;
        case 1: printf("started OK but abnormal termination\n"); break;
        case 2: printf("invalid command issued\n"); break;
        case 3: printf("abnormal termination because READY changed state\n"); break;
        }
    )
#endif
    return status[0];
}
/*****************************************************************************
*****************************************************************************/
static int floppy_seek(floppy_t *dev, unsigned char track)
{
    unsigned short ioadr;

    DEBUG(printf("floppy_seek: seeking track %u\n", track);)
    /* already there? */
    if(dev->curr_track == track)
        return 0;
    /* turn on the motor */
    floppy_motor_on(dev);
    /* send the actual command bytes */
    ioadr = dev->blkdev.io.adr[0];
    floppy_send_byte(ioadr, 0x0F);	/* CMD_SEEK */
    floppy_send_byte(ioadr, 0);
    floppy_send_byte(ioadr, track);
    /* wait until seek finished */
    if(floppy_await_interrupt(dev) < 0)
        return -1;
    /* now let head settle for 15ms
    xxx - use interrupt */
    msleep(15);
    DEBUG(printf("floppy_seek: sr0=0x%X (should be 0x20), curr_track=%u "
                 "(should be %u)\n", dev->sr0, dev->curr_track, track);)
    floppy_motor_off(dev);
    /* check that seek worked */
    if(dev->sr0 != 0x20 || dev->curr_track != track)
        return -1;
    return 0;
}
/*****************************************************************************
*****************************************************************************/
static int floppy_recalibrate(floppy_t *fdev)
{
    unsigned short ioadr;

    DEBUG(printf("floppy_recalibrate:\n");)
    ioadr = fdev->blkdev.io.adr[0];
    floppy_send_byte(ioadr, 0x07);
    floppy_send_byte(ioadr, 0);
    return floppy_await_interrupt(fdev) < 0;
}
/*****************************************************************************
*****************************************************************************/
static int floppy_error(request_t *req)
{
    floppy_t *fdev;
    unsigned short ioadr;

    DEBUG(printf("*** floppy_error: ***\n");)
    /* increment req->errors */
    (req->errors)++;
    if(req->errors >= 3)
        return -1;
    /* */
    fdev = (floppy_t *)req->dev;
    ioadr = fdev->blkdev.io.adr[0];
    /* if disk change, seek track 1 (xxx - one? not zero?) */
    if(inportb(ioadr + FDC_DIR) & 0x80)
    {
        DEBUG(printf("floppy_error: disk change\n");)
        if(floppy_seek(fdev, 1) != 0)
        {
            /* if that fails, we're screwed... */
            floppy_motor_off(fdev);
            return -1;
        }
    }
    return floppy_recalibrate(fdev);
}
/*****************************************************************************
*****************************************************************************/
static int floppy_rw(request_t *req)
{
    unsigned short ioadr, sector, head, num_bytes, num_blks;
    unsigned long blk, adr;
    blkdev_t *blkdev;
    floppy_t *fdev;
    int temp;

    DEBUG(printf("floppy_rw:\n");)
    fdev = (floppy_t *)req->dev;
    /* if floppy_t struct had a magic value in it, we could validate it here */
    blkdev = &fdev->blkdev;
    /* select drive and spin up the disk */
    floppy_motor_on(fdev);
    ioadr = blkdev->io.adr[0];
    do
    {
        blk = req->blk;
        sector = blk % blkdev->sectors + 1;
        blk /= blkdev->sectors;
        head = blk % blkdev->heads;
        blk /= blkdev->heads;
        DEBUG(printf("floppy_rw: CHS=%lu:%u:%u\n", blk, head,
                     sector);)
        /* do not cross a track boundary */
        num_blks = min(req->num_blks, blkdev->sectors -
                       req->blk % blkdev->sectors);
        num_bytes = num_blks * blkdev->bytes_per_blk;
        DEBUG(printf("floppy_rw: transferring %u blocks (%u bytes)\n",
                     num_blks, num_bytes);)
        /* disk change? */
        if(inportb(ioadr + FDC_DIR) & 0x80)
            goto ERR;
        /* seek to correct track */
        if(floppy_seek(fdev, blk) != 0)
            goto ERR;
        /* program data rate (500K/s) */
        outportb(ioadr + FDC_CCR, 0);
        /* copy data to 64K-aligned conventional memory buffer */
        if(req->cmd == BLK_CMD_WRITE)
            movedata(_DS, (unsigned)req->buf,
                     LMEM_SEG, LMEM_OFF,
                     num_bytes);
#if defined(__TURBOC__)
        adr = LMEM_SEG;
        adr <<= 4;
        adr += LMEM_OFF;
#elif defined(__DJGPP__)
        adr = LMEM_OFF;
#endif
        if(req->cmd == BLK_CMD_READ)
        {
            DEBUG(printf("floppy_rw: read\n");)
            floppy_send_byte(ioadr, 0xE6);//CMD_READ);
            /* xxx - 2 is DMA number. Can't use blkdev->io.dma; it is a mask
            Dammit, I forgot to subtract one here to convert length into terminal count.
            Made that error with my sound software, too. */
            if(dma_read(2, adr, num_bytes - 1) != 0)
            {
                printf("floppy_rw: error from dma_read()\n");
                goto ERR;
            }
        }
        else// if(req->cmd == BLK_CMD_WRITE)
        {
            DEBUG(printf("floppy_rw: write\n");)
            floppy_send_byte(ioadr, 0xC5);//CMD_WRITE);
            if(dma_write(2, adr, num_bytes - 1) != 0)
            {
                printf("floppy_rw: error from dma_write()\n");
                goto ERR;
            }
        }
        /* head and drive select */
        floppy_send_byte(ioadr, (head << 2) | blkdev->unit);
        /* C, H, S, N */
        floppy_send_byte(ioadr, blk);
        floppy_send_byte(ioadr, head);
        floppy_send_byte(ioadr, sector);
        floppy_send_byte(ioadr, 2);	/* 512 bytes/sector */
        /* EOT */
        floppy_send_byte(ioadr, blkdev->sectors);
        /* gap 3 length for 1.44M or 1.68M floppies */
        if(blkdev->sectors == 18)
            floppy_send_byte(ioadr, 0x1B);
        else //if(blkdev->sectors == 21)
            floppy_send_byte(ioadr, 0x1C);
        floppy_send_byte(ioadr, 0xFF);	/* DTL = unused */
        /* wait up to 1 second for IRQ 6 */
        temp = floppy_await_interrupt(fdev);
        if((temp < 0) || (temp & 0xC0))
        {
ERR:
            temp = floppy_error(req);
            /* if floppy_error() returns non-zero, then we are doomed... */
            if(temp != 0)
                return temp;
            /* ...else try again */
            else
                continue;
        }
        /* copy data from 64K-aligned conventional memory buffer */
        if(req->cmd == BLK_CMD_READ)
            movedata(LMEM_SEG, LMEM_OFF,
                     _DS, (unsigned)req->buf,
                     num_bytes);
        /* advance pointers */
        req->num_blks -= num_blks;
        req->blk += num_blks;
        req->buf += num_bytes;
    } while (req->num_blks != 0);
    floppy_motor_off(fdev);
    return 0;
}
//////////////////////////////////////////////////////////////////////////////
// MAIN/DEMO ROUTINES
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*****************************************************************************/
static void INTERRUPT irq6(void)
{
    _interrupt_occurred |= 0x0040;
    outportb(0x20, 0x20);
}
/*****************************************************************************
*****************************************************************************/
static void INTERRUPT irq14(void)
{
    _interrupt_occurred |= 0x4000;
    outportb(0xA0, 0x20);
    outportb(0x20, 0x20);
}
/*****************************************************************************
*****************************************************************************/
static void INTERRUPT irq15(void)
{
    _interrupt_occurred |= 0x8000;
    outportb(0xA0, 0x20);
    outportb(0x20, 0x20);
}
/*****************************************************************************
*****************************************************************************/
#define	_18K	18432
#define FLOPPY	1

#if defined(__TURBOC__)
#define	LEN	(32768u + 2048)
#elif defined(__DJGPP__)
#define	LEN	92160u
#endif


static unsigned char _big_buf[LEN];

int main(void)
{
    vector_t vector6, vector14, vector15;
    request_t freq, creq;
    floppy_t fdev;
    unsigned temp, foo;
    unsigned char buf[_18K];

    memset(&fdev, 0, sizeof(fdev));
    fdev.blkdev.io.dma = 0x04;
    fdev.blkdev.io.irq = 0x0040;
    fdev.blkdev.io.adr[0] = 0x3F0;
    /* 8 bytes at 0x3F0
    xxx - steer clear of 0x3F6? Win95 says 0x3F2-0x3F5, but we need 0x3F7 too */
    fdev.blkdev.io.span[0] = 8;

    //	fdev.blkdev.unit = ?;
    fdev.blkdev.num_blks = 2880;
    fdev.blkdev.bytes_per_blk = 512;
    fdev.blkdev.sectors = 18; /* xxx - probe this, somehow */
    fdev.blkdev.heads = 2;
    fdev.blkdev.cyls = 80;
    fdev.curr_track = -1;

    memset(&creq, 0, sizeof(creq));
    creq.cmd = BLK_CMD_READ;
    creq.dev = _drives + 1;

    memset(&freq, 0, sizeof(freq));
    freq.dev = &fdev;
    /* */
    SAVE_VECT(14, vector6);
    SAVE_VECT(118, vector14);
    SAVE_VECT(119, vector15);
    SET_VECT(14, irq6);
    SET_VECT(118, irq14);
    SET_VECT(119, irq15);
    /* */
    ide_probe();
    /* */
#if 0
    /******
    check if CD-ROM drive can rip audio
    look for "CD-DA commands: YES"
    xxx - not sure about this
    ******/
    (void)atapi_mode_sense(_drives + 1);
#elif 0
    /******
    this is both incomplete and untested, so don't use it
    1 block of CD-DA data = 2352 bytes = 1/75 sec of audio
    ******/
    creq.buf = buf;
    creq.num_blks = 1;
    (void)atapi_rip_audio(&creq);
#elif 0
    /******
    read from CD-ROM
    ******/
    creq.buf = buf;
    creq.num_blks = 9;
    creq.blk = 16;
    (void)atapi_read_sectors(&creq);
    dump(buf, 128);
#elif 0
    /******
    read from floppy
    ******/
    foo = fdev.blkdev.sectors *	/* =18 */
          fdev.blkdev.heads;	/* =2 */
    freq.cmd = BLK_CMD_READ;
    freq.buf = buf;
    freq.num_blks = foo;
    freq.blk = 0;
    (void)floppy_rw(&freq);
    dump(buf, 128);
#elif 0
    /******
    copy data from CD-ROM to disk file
    ******/
    creq.buf = _big_buf;
    creq.num_blks = LEN / 2048;
    creq.blk = 0;
    if(atapi_read_sectors(&creq) != 0)
    {
        printf("atapi_read_sectors failed\n");
        goto ERR;
    }
    RESTORE_VECT(14, vector6);
    RESTORE_VECT(118, vector14);
    RESTORE_VECT(119, vector15);
    {
        FILE *out;

        out = fopen("data.bin", "wb");
        if(out == NULL)
            exit(0);
        fwrite(_big_buf, 1, LEN, out);
        fclose(out);

⌨️ 快捷键说明

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