Ejemplo n.º 1
0
int devide_flush_cache(void)
{
    uint8_t drive;

    drive = blk_op.blkdev->driver_data & DRIVE_NR_MASK;

    ide_select(drive);

    /* check drive has a cache and was written to since the last flush */
    if((blk_op.blkdev->driver_data & (FLAG_WRITE_CACHE | FLAG_CACHE_DIRTY))
		                 == (FLAG_WRITE_CACHE | FLAG_CACHE_DIRTY)){
	devide_writeb(ide_reg_lba_3, (((drive & 1) == 0) ? 0xE0 : 0xF0)); // select drive

	if (!devide_wait(IDE_STATUS_READY))
	    goto fail;

	devide_writeb(ide_reg_command, IDE_CMD_FLUSH_CACHE);

	if (!devide_wait(IDE_STATUS_READY))
	    goto fail;

        /* drive cache is now clean */
	blk_op.blkdev->driver_data &= ~FLAG_CACHE_DIRTY;
    }
    ide_deselect();
    return 0;

fail:
    udata.u_error = EIO;
    ide_deselect();
    return -1;
}
Ejemplo n.º 2
0
/* Reset depends upon the presence of alt control, which is optional */
void devide_reset(void)
{
    kputs("IDE reset\n");

    /* reset both drives */
    devide_writeb(ide_reg_devhead, 0xE0); /* select master */
    devide_writeb(ide_reg_control, 0x06); /* assert reset, no interrupts */
    devide_delay();

    devide_writeb(ide_reg_control, 0x02); /* release reset, no interrupts */
    devide_delay();
}
Ejemplo n.º 3
0
uint8_t devide_transfer_sector(void)
{
    uint8_t drive;
#if defined(__SDCC_z80) || defined(__SDCC_z180) || defined(__SDCC_gbz80) || defined(__SDCC_r2k) || defined(__SDCC_r3k)
    uint8_t *p;
#endif


    drive = blk_op.blkdev->driver_data & DRIVE_NR_MASK;

    ide_select(drive);

#if defined(__SDCC_z80) || defined(__SDCC_z180) || defined(__SDCC_gbz80) || defined(__SDCC_r2k) || defined(__SDCC_r3k)
    /* sdcc sadly unable to figure this out for itself yet */
    p = ((uint8_t *)&blk_op.lba)+3;
    devide_writeb(ide_reg_lba_3, (*(p--) & 0x0F) | ((drive == 0) ? 0xE0 : 0xF0)); // select drive, start loading LBA
    devide_writeb(ide_reg_lba_2, *(p--));
    devide_writeb(ide_reg_lba_1, *(p--));
    devide_writeb(ide_reg_lba_0, *p);
#else
    devide_writeb(ide_reg_lba_3, ((blk_op.lba >> 24) & 0xF) | ((drive == 0) ? 0xE0 : 0xF0)); // select drive, start loading LBA
    devide_writeb(ide_reg_lba_2, (blk_op.lba >> 16));
    devide_writeb(ide_reg_lba_1, (blk_op.lba >> 8));
    devide_writeb(ide_reg_lba_0, blk_op.lba);
#endif

    if (!devide_wait(IDE_STATUS_READY))
	goto fail;

    devide_writeb(ide_reg_sec_count, 1);
    devide_writeb(ide_reg_command, blk_op.is_read ? IDE_CMD_READ_SECTOR : IDE_CMD_WRITE_SECTOR);

    if(!devide_wait(IDE_STATUS_DATAREQUEST))
        goto fail;

    if (blk_op.is_read)
	devide_read_data();
    else {
	devide_write_data();
	if(!devide_wait(IDE_STATUS_READY))
	    goto fail;
	blk_op.blkdev->driver_data |= FLAG_CACHE_DIRTY;
    }

    ide_deselect();

    return 1;
fail:
    ide_deselect();
    return 0;
}
Ejemplo n.º 4
0
void devide_init_drive(uint8_t drive)
{
    blkdev_t *blk;
    uint8_t *buffer, select;

    switch(drive){
	case 0: select = 0xE0; break;
	case 1: select = 0xF0; break;
        default: return;
    }

    kprintf("IDE drive %d: ", drive);

#ifdef IDE_8BIT_ONLY
    /* set 8-bit mode -- mostly only supported by CF cards */
    devide_writeb(ide_reg_devhead, select);
    if(!devide_wait(IDE_STATUS_READY))
        return;

    devide_writeb(ide_reg_features, 0x01); /* Enable 8-bit PIO transfer mode (CFA feature set only) */
    devide_writeb(ide_reg_command, IDE_CMD_SET_FEATURES);
#endif

    /* confirm drive has LBA support */
    if(!devide_wait(IDE_STATUS_READY))
        return;

    /* send identify command */
    devide_writeb(ide_reg_devhead, select);
    devide_writeb(ide_reg_command, IDE_CMD_IDENTIFY);

    /* allocate temporary sector buffer memory */
    buffer = (uint8_t *)tmpbuf();

    if(!devide_wait(IDE_STATUS_DATAREQUEST))
	goto failout;

    blk_op.is_user = false;
    blk_op.addr = buffer;
    blk_op.nblock = 1;
    devide_read_data();

    if(!(buffer[99] & 0x02)){
        kputs("LBA unsupported.\n");
        goto failout;
    }

    blk = blkdev_alloc();
    if(!blk)
	goto failout;

    blk->transfer = devide_transfer_sector;
    blk->flush = devide_flush_cache;
    blk->driver_data = drive & DRIVE_NR_MASK;

    if( !(((uint16_t*)buffer)[82] == 0x0000 && ((uint16_t*)buffer)[83] == 0x0000) ||
         (((uint16_t*)buffer)[82] == 0xFFFF && ((uint16_t*)buffer)[83] == 0xFFFF) ){
	/* command set notification is supported */
	if(buffer[164] & 0x20){
	    /* write cache is supported */
            blk->driver_data |= FLAG_WRITE_CACHE;
	}
    }

    /* read out the drive's sector count */
    blk->drive_lba_count = le32_to_cpu(*((uint32_t*)&buffer[120]));

    /* done with our temporary memory */
    brelse((bufptr)buffer);

    /* scan partitions */
    blkdev_scan(blk, SWAPSCAN);

    return;
failout:
    brelse((bufptr)buffer);
    return;
}
Ejemplo n.º 5
0
void devide_init_drive(uint_fast8_t drive)
{
    blkdev_t *blk;
    uint8_t *buffer;
    uint_fast8_t select;

    select = (drive & 1) ? 0xF0 : 0xE0;

    ide_select(drive);

    devide_writeb(ide_reg_devhead, select);
    kprintf("IDE drive %d: ", drive);

#ifdef IDE_8BIT_ONLY
    if (IDE_IS_8BIT(drive)) {
    /* set 8-bit mode -- mostly only supported by CF cards */
        if (!devide_wait(IDE_STATUS_READY))
            goto out;

        devide_writeb(ide_reg_devhead, select);
        if (!devide_wait(IDE_STATUS_READY))
            goto out;

        devide_writeb(ide_reg_features, 0x01); /* Enable 8-bit PIO transfer mode (CFA feature set only) */
        devide_writeb(ide_reg_command, IDE_CMD_SET_FEATURES);
    }
#endif

    /* confirm drive has LBA support */
    if (!devide_wait(IDE_STATUS_READY))
        goto out;

    /* send identify command */
    devide_writeb(ide_reg_devhead, select);
    devide_writeb(ide_reg_command, IDE_CMD_IDENTIFY);

    /* allocate temporary sector buffer memory */
    buffer = (uint8_t *)tmpbuf();

    if (!devide_wait(IDE_STATUS_DATAREQUEST))
	goto failout;

    blk_op.is_user = false;
    blk_op.addr = buffer;
    blk_op.nblock = 1;
    devide_read_data();

#ifdef CONFIG_IDE_BSWAP
    if(!(buffer[98] & 0x02)) {
#else
    if(!(buffer[99] & 0x02)) {
#endif    
        kputs("LBA unsupported.\n");
        goto failout;
    }

    blk = blkdev_alloc();
    if(!blk)
	goto failout;

    blk->transfer = devide_transfer_sector;
    blk->flush = devide_flush_cache;
    blk->driver_data = drive & IDE_DRIVE_NR_MASK;

    if( !(((uint16_t*)buffer)[82] == 0x0000 && ((uint16_t*)buffer)[83] == 0x0000) ||
         (((uint16_t*)buffer)[82] == 0xFFFF && ((uint16_t*)buffer)[83] == 0xFFFF) ){
	/* command set notification is supported */
	if(buffer[164] & 0x20){
	    /* write cache is supported */
            blk->driver_data |= FLAG_WRITE_CACHE;
	}
    }

    /* read out the drive's sector count */
    blk->drive_lba_count = le32_to_cpu(*((uint32_t*)&buffer[120]));

    /* done with our temporary memory */
    tmpfree(buffer);

    /* Deselect the IDE, as we will re-select it in the partition scan and
       it may not recursively stack de-selections */
    ide_deselect();

    /* scan partitions */
    blkdev_scan(blk, SWAPSCAN);

    return;
failout:
    tmpfree(buffer);
out:
    ide_deselect();
    return;
}

void devide_init(void)
{
    uint_fast8_t d;

#ifdef IDE_HAS_RESET
    devide_reset();
#endif

    for(d=0; d < IDE_DRIVE_COUNT; d++)
        devide_init_drive(d);
}