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; }
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; }
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); }