BoolU4 RAMRBlks(LTPartition *p,U1 *buf,U8 blk,U8 cnt) { LTBlkDev *bdev=p->bdev; CheckLTBlkDev(bdev); MemCpy(buf,bdev->RAM_disk+blk*BLK_SIZE,cnt*BLK_SIZE); return TRUE; } BoolU4 RAMWBlks(LTPartition *p,U1 *buf,U8 blk,U8 cnt) { LTBlkDev *bdev=p->bdev; CheckLTBlkDev(bdev); MemCpy(bdev->RAM_disk+blk*BLK_SIZE,buf,cnt*BLK_SIZE); return TRUE; } BoolU4 FileRBlks(LTPartition *p,U1 *buf,U8 blk,U8 cnt) { LTBlkDev *bdev=p->bdev; CheckLTBlkDev(bdev); if (!bdev->f) throw(EXCEPT_PARTITION,5); if (!FRBlks(bdev->f,buf,blk,cnt)) throw(EXCEPT_PARTITION,6); FSync(bdev->f); return TRUE; } BoolU4 FileWBlks(LTPartition *p,U1 *buf,U8 blk,U8 cnt) { LTBlkDev *bdev=p->bdev; CheckLTBlkDev(bdev); if (!bdev->f) throw(EXCEPT_PARTITION,7); if (!FWBlks(bdev->f,buf,blk,cnt)) throw(EXCEPT_PARTITION,8); FSync(bdev->f); return TRUE; } #define FDC_p0 0 #define FDC_p1 1 #define FDC_DOR 2 #define FDC_p3 3 #define FDC_STATUS 4 #define FDC_DATA 5 #define FDC_DIR 7 #define FDC_DCR 7 void Irq06Handler() { Bts(&sys_irq_flags,6); } void FDCFlushStatus(LTBlkDev *bdev) { U1 b; I8 i; MemSet(bdev->status,0,32); i=0; while (i<32) { b=InP(bdev->base0+FDC_STATUS); if (b & 0x80) { if (b & 0x40) bdev->status[i++]=InP(bdev->base0+FDC_DATA); else break; } SwapInNext; } if (i==32) throw(EXCEPT_FDC,2); bdev->status[0]=bdev->status[0] & 0xC8; //clear non-error bits bdev->last_jiffy=jiffies; } void FDCWaitIrq(LTBlkDev *bdev) { BoolU4 old_flags=GetFlags; Sti; while (!Btr(&sys_irq_flags,bdev->irq)) { /* if (!(InP(bdev->base0+FDC_p0) & 0x80)) //Pending IRQ? throw(EXCEPT_FDC,1); */ SwapInNext; } SetFlags(old_flags); FDCFlushStatus(bdev); } void FDCSendCmdU1(LTBlkDev *bdev,U1 v) { FDCFlushStatus(bdev); OutP(bdev->base0+FDC_DATA,v); } void FDCSeek(LTBlkDev *bdev,U1 cyl, U1 head) { FDCSendCmdU1(bdev,0x0F); FDCSendCmdU1(bdev,head<<2); FDCSendCmdU1(bdev,cyl); FDCWaitIrq(bdev); } void FDCFree(LTBlkDev *bdev) { Btr(&sys_irq_busy_flags,bdev->irq); } void MonitorFDCTsk() { LTBlkDev *bdev; Preempt(OFF); bdev=Fs->user_aux0; CheckLTBlkDev(bdev); while (TRUE) { if (!Bts(&sys_irq_busy_flags,bdev->irq)) { if (bdev->last_jiffy) { if (jiffies > bdev->last_jiffy+JIFFY_FREQ<<1) { FDCSeek(bdev,0,0); FDCSeek(bdev,0,1); OutP(bdev->base0+FDC_DOR,0x00); bdev->last_jiffy=0; } } FDCFree(bdev); } SwapInNext; } } void FDCGet(LTBlkDev *bdev) { CheckLTBlkDev(bdev); while (Bts(&sys_irq_busy_flags,bdev->irq)) SwapInNext; Btr(&sys_irq_flags,bdev->irq); if (!bdev->last_jiffy) { bdev->last_jiffy=jiffies; OutP(bdev->base0+FDC_DOR,0x00); BusyWait(100); OutP(bdev->base0+FDC_DOR,0x1C); //Motor ON FDCWaitIrq(bdev); OutP(bdev->base0+FDC_DCR,0x00); //step,Load, Unload specs FDCSendCmdU1(bdev,0x03); FDCSendCmdU1(bdev,0xCF); FDCSendCmdU1(bdev,0x10); FDCWaitIrq(bdev); FDCSendCmdU1(bdev,0x07); //Recalibrate FDCSendCmdU1(bdev,0x00); FDCWaitIrq(bdev); } } void FDCReset(LTBlkDev *bdev) { CheckLTBlkDev(bdev); OutP(0x0A,0x42); //Shut down old DMA OutP(0x09,0x02); bdev->last_jiffy=0; Btr(&sys_irq_busy_flags,bdev->irq); FDCGet(bdev); } BoolU4 FDCReadTrack(LTBlkDev *bdev,U1 cyl, U1 head,U8 blk) { I8 i; U8 size=BLK_SIZE*FDC_DISK_SECTORS-1; BoolU4 old_preempt=Preempt(OFF); CheckLTBlkDev(bdev); for (i=0;i>8) & 0xFF); OutP(0x81,FDC_DMA_BUF>>16); //set page OutP(0x0C,0); OutP(0x05,size.u1[0]); //cnt OutP(0x05,size.u1[1]); OutP(0x0A,0x02); //Start new DMA OutP(0x09,0x06); FDCSendCmdU1(bdev,0x62); FDCSendCmdU1(bdev,head<<2); FDCSendCmdU1(bdev,cyl); FDCSendCmdU1(bdev,head); FDCSendCmdU1(bdev,1); //sector FDCSendCmdU1(bdev,BLK_SIZE>>8); FDCSendCmdU1(bdev,FDC_DISK_SECTORS); //last sec FDCSendCmdU1(bdev,0x1B); //gap FDCSendCmdU1(bdev,0xFF); FDCWaitIrq(bdev); if (bdev->status[0] || bdev->status[1] || bdev->status[2]) { coutln "FDC Read Error:",bdev->status[2],bdev->status[1],bdev->status[0]; FDCReset(bdev); } else { Preempt(old_preempt); return TRUE; } } coutln "FDC Read Failed!!! Blk:",blk; Preempt(old_preempt); return FALSE; } BoolU4 FDCRBlks(LTPartition *p,U1 *buf, U8 blk, U8 cnt) { LTCacheBlk *tempc; BoolU4 okay=TRUE; U8 l,blk2; U1 cyl,head,sec; LTBlkDev *bdev=p->bdev; CheckLTBlkDev(bdev); while (cnt>0) { if (bdev->flags & LTBDF_READ_CACHE) { while (cnt) { tempc=LTDCFindBlk(p,blk); //TODO preempt if (tempc) { MemCpy(buf,&tempc->body,BLK_SIZE); cnt--; buf+=BLK_SIZE; blk++; } else break; } } if (cnt) { l=cnt; if (l>bdev->max_reads) l=bdev->max_reads; blk2=blk; sec=blk2%FDC_DISK_SECTORS+1;blk2=blk2/FDC_DISK_SECTORS; head=blk2%FDC_DRIVE_HEADS; cyl=blk2/FDC_DRIVE_HEADS; if (!FDCReadTrack(bdev,cyl,head,blk-(sec-1))) okay=FALSE; MemCpy(buf,FDC_DMA_BUF+BLK_SIZE*(sec-1),l*BLK_SIZE); if (bdev->flags & LTBDF_READ_CACHE) LTDCAdd(DriveToPartition(bdev->partition_base), FDC_DMA_BUF,blk-(sec-1),FDC_DISK_SECTORS); buf+=l*BLK_SIZE; blk+=l; cnt-=l; disk_status_display.u2[0]=disk_status_display.u2[0]-l; } } return okay; } BoolU4 FDCWriteBlk2(LTBlkDev *bdev,U1 *buf, U1 cyl, U1 head,U1 sec,U8 blk) { I8 i; U8 size=BLK_SIZE*bdev->max_writes-1; BoolU4 old_preempt; old_preempt=Preempt(OFF); for (i=0;i>8) & 0xFF); OutP(0x81,FDC_DMA_BUF>>16); //set page OutP(0x0C,0); OutP(0x05,size.u1[0]); //cnt OutP(0x05,size.u1[1]); OutP(0x0A,0x02); //Start new DMA OutP(0x09,0x06); FDCSendCmdU1(bdev,0xC5); FDCSendCmdU1(bdev,head<<2); FDCSendCmdU1(bdev,cyl); FDCSendCmdU1(bdev,head); FDCSendCmdU1(bdev,sec); FDCSendCmdU1(bdev,BLK_SIZE>>8); FDCSendCmdU1(bdev,FDC_DISK_SECTORS); //last sec FDCSendCmdU1(bdev,0x1B); //gap FDCSendCmdU1(bdev,0xFF); FDCWaitIrq(bdev); if (bdev->status[2] || bdev->status[1] || bdev->status[0]) { coutln "FDC Write Error:",bdev->status[0],bdev->status[1],bdev->status[2]; FDCReset(bdev); } else { Preempt(old_preempt); return TRUE; } } coutln "FDC Write Failed!!! Blk:",blk; Preempt(old_preempt); return FALSE; } BoolU4 FDCWBlks(LTPartition *p,U1 *buf, U8 blk, U8 cnt) { BoolU4 okay=TRUE; U8 l,blk2; U1 cyl,head,sec; LTBlkDev *bdev=p->bdev; CheckLTBlkDev(bdev); while (cnt>0) { l=cnt; if (l>bdev->max_writes) l=bdev->max_writes; blk2=blk; sec=blk2%FDC_DISK_SECTORS+1;blk2=blk2/FDC_DISK_SECTORS; head=blk2%FDC_DRIVE_HEADS; cyl=blk2/FDC_DRIVE_HEADS; if (!FDCWriteBlk2(bdev,buf,cyl,head,sec,blk)) okay=FALSE; buf+=l*BLK_SIZE; blk+=l; cnt-=l; disk_status_display.u2[0]=disk_status_display.u2[0]-l; } return okay; } //The following definitions were copied from Linux source code /* ATA/ATAPI Cmds pre T13 Spec */ #define WIN_NOP 0x00 #define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ #define WIN_SRST 0x08 /* ATAPI soft reset cmd */ #define WIN_DEV_RESET 0x08 #define WIN_RESTORE 0x10 #define WIN_READ 0x20 /* 28-Bit */ #define WIN_READ_EXT 0x24 /* 48-Bit */ #define WIN_READDMA_EXT 0x25 /* 48-Bit */ #define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */ #define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ #define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ #define WIN_WRITE 0x30 /* 28-Bit */ #define WIN_WRITE_EXT 0x34 /* 48-Bit */ #define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ #define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ #define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ #define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ #define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ #define WIN_WRITE_VERIFY 0x3C /* 28-Bit */ #define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ #define WIN_VERIFY_EXT 0x42 /* 48-Bit */ #define WIN_FORMAT 0x50 #define WIN_INIT 0x60 #define WIN_SEEK 0x70 #define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ #define WIN_DIAGNOSE 0x90 #define WIN_SPECIFY 0x91 /* set Drive geometry translation */ #define WIN_DOWNLOAD_MICROCODE 0x92 #define WIN_STANDBYNOW2 0x94 #define WIN_SETIDLE2 0x97 #define WIN_CHECKPOWERMODE2 0x98 #define WIN_SLEEPNOW2 0x99 #define WIN_PACKETCMD 0xA0 /* Send a packet cmd. */ #define WIN_PIDENTIFY 0xA1 /* IDEntify ATAPI dev */ #define WIN_QUEUED_SERVICE 0xA2 #define WIN_SMART 0xB0 /* self-monitoring and reporting */ #define CFA_ERASE_SECTORS 0xC0 #define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ #define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ #define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ #define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */ #define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ #define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ #define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */ #define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ #define WIN_GETMEDIASTATUS 0xDA #define WIN_DOORLOCK 0xDE /* lock door ON removable drives */ #define WIN_DOORUNLOCK 0xDF /* unlock door ON removable drives */ #define WIN_STANDBYNOW1 0xE0 #define WIN_IDLEIMMEDIATE 0xE1 /* force Drive to become "ready" */ #define WIN_STANDBY 0xE2 /* Set dev in Standby Mode */ #define WIN_SETIDLE1 0xE3 #define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ #define WIN_CHECKPOWERMODE1 0xE5 #define WIN_SLEEPNOW1 0xE6 #define WIN_FLUSH_CACHE 0xE7 #define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ #define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ #define WIN_IDENTIFY 0xEC /* ask Drive to IDEntify itself */ #define WIN_MEDIAELTECT 0xED #define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */ #define WIN_SETFEATURES 0xEF /* set special Drive features */ #define EXAU1_ENABLE_NEST 0xF0 #define WIN_SECURITY_SET_PASS 0xF1 #define WIN_SECURITY_UNLOCK 0xF2 #define WIN_SECURITY_ERASE_PREPARE 0xF3 #define WIN_SECURITY_ERASE_UNIT 0xF4 #define WIN_SECURITY_FREEZE_LOCK 0xF5 #define WIN_SECURITY_DISABLE 0xF6 #define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ #define WIN_SET_MAX 0xF9 #define DISABLE_SEAGATE 0xFB /* Bits of HD_STATUS */ #define ERR_STAT 0x01 #define INDEX_STAT 0x02 #define ECC_STAT 0x04 /* Corrected error */ #define DRQ_STAT 0x08 #define SEEK_STAT 0x10 #define WRERR_STAT 0x20 #define READY_STAT 0x40 #define BUSY_STAT 0x80 ; /*here for compiler bug*/ #define BAD_R_STAT (BUSY_STAT | ERR_STAT) #define BAD_W_STAT (BAD_R_STAT | WRERR_STAT) #define BAD_STAT (BAD_R_STAT | DRQ_STAT) #define DRIVE_READY (READY_STAT | SEEK_STAT) #define DATA_READY (DRQ_STAT) #define IDE_DATA_REG 0 #define IDE_FEATURE_REG 1 #define IDE_NSECTOR_REG 2 #define IDE_SECTOR_REG 3 #define IDE_LCYL_REG 4 #define IDE_HCYL_REG 5 #define IDE_SELECT_REG 6 #define IDE_STATUS 7 #define IDE_CMD 7 #define IDE_CONTROL_REG 0 void Irq0EHandler() { Bts(&sys_irq_flags,14); } void Irq0FHandler() { Bts(&sys_irq_flags,15); } void ATASelectBlk28(LTBlkDev *bdev,U8 blk,U8 cnt) { OutP(bdev->base1+IDE_CONTROL_REG,0x8); OutP(bdev->base0+IDE_SECTOR_REG,blk); OutP(bdev->base0+IDE_NSECTOR_REG,cnt); OutP(bdev->base0+IDE_LCYL_REG,blk.u1[1]); OutP(bdev->base0+IDE_HCYL_REG,blk.u1[2]); OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4|blk.u1[3]); } /************* void ATASelectBlk48(LTBlkDev *bdev,U8 blk,U8 cnt) {//Untested OutP(bdev->base1+IDE_CONTROL_REG,0x8); OutP(bdev->base0+IDE_NSECTOR_REG,cnt.u1[1]); OutP(bdev->base0+IDE_SECTOR_REG,blk_lo.u1[3]); OutP(bdev->base0+IDE_LCYL_REG,blk_hi); OutP(bdev->base0+IDE_HCYL_REG,blk_hi.u1[1]); OutP(bdev->base0+IDE_NSECTOR_REG,cnt); OutP(bdev->base0+IDE_SECTOR_REG,blk_lo); OutP(bdev->base0+IDE_LCYL_REG,blk_lo.u1[1]); OutP(bdev->base0+IDE_HCYL_REG,blk_lo.u1[2]); OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4); } ***************/ void IDEWaitNotBusy(LTBlkDev *bdev) { while (InP(bdev->base0+IDE_STATUS) & BUSY_STAT) SwapInNext; } void ATANop(LTBlkDev *bdev) { OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4); OutP(bdev->base0+IDE_FEATURE_REG,0); OutP(bdev->base0+IDE_CMD,WIN_NOP); IDEWaitNotBusy(bdev); } void ATACmd(LTBlkDev *bdev,U1 cmd) { OutP(bdev->base0+IDE_FEATURE_REG,0); OutP(bdev->base0+IDE_CMD,cmd); bdev->last_jiffy=jiffies; } /******* U8 ATAPIStat(LTBlkDev *bdev) { return InP(bdev->base0+IDE_STATUS)+ 256*(InP(bdev->base0+IDE_NSECTOR_REG)+ 256* InP(bdev->base0+IDE_FEATURE_REG) ); } **********/ void ATAPIWritePktWord(LTBlkDev *bdev,U2 w) { while (!(InP(bdev->base0+IDE_STATUS)&DATA_READY)) SwapInNext; OutPW(bdev->base0+IDE_DATA_REG,w.u1[1]+256*w.u1[0]); bdev->last_jiffy=jiffies; } void IDEWaitForDrive(LTBlkDev *bdev) { while (Bts(&sys_irq_busy_flags,bdev->irq)) SwapInNext; Btr(&sys_irq_flags,bdev->irq); } /******** void IDEWaitForIrq(LTBlkDev *bdev) { BoolU4 old_flags=GetFlags; Sti; while (!Btr(&sys_irq_flags,bdev->irq)) SwapInNext; SetFlags(old_flags); } *********/ void ATAPISeek(LTBlkDev *bdev,U8 blk) { OutP(bdev->base1+IDE_CONTROL_REG,0x8); OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4); OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size); OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]); ATACmd(bdev,WIN_PACKETCMD); ATAPIWritePktWord(bdev,0x2B00); //Seek ATAPIWritePktWord(bdev,blk>>16); ATAPIWritePktWord(bdev,blk); ATAPIWritePktWord(bdev,0); ATAPIWritePktWord(bdev,0); ATAPIWritePktWord(bdev,0x0000); IDEWaitNotBusy(bdev); } void ATAPIStartStop(LTBlkDev *bdev,BoolU4 start) { OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4); ATACmd(bdev,WIN_PACKETCMD); ATAPIWritePktWord(bdev,0x1B00); //Start/Stop ATAPIWritePktWord(bdev,0x0000); if (start) ATAPIWritePktWord(bdev,0x0100); else ATAPIWritePktWord(bdev,0x0000); ATAPIWritePktWord(bdev,0x0000); ATAPIWritePktWord(bdev,0x0000); ATAPIWritePktWord(bdev,0x0000); IDEWaitNotBusy(bdev); } void IDEInit(LTBlkDev *bdev,BoolU4 unlock) { U8 blk=0x0F000000; //TODO:fix this? BoolU4 old_preempt=Preempt(OFF); CheckLTBlkDev(bdev); if (unlock) { Btr(&sys_irq_busy_flags,bdev->irq); IDEWaitForDrive(bdev); } // not using irqs // Btr(&sys_irq_flags,bdev->irq); if (!(bdev->flags & LTBDF_HAS_BEEN_RESET)) { OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4); ATACmd(bdev,WIN_DEV_RESET); IDEWaitNotBusy(bdev); bdev->flags=bdev->flags | LTBDF_HAS_BEEN_RESET; } if (bdev->type==LTBDT_ATA) { OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4); ATACmd(bdev,WIN_READ_NATIVE_MAX); IDEWaitNotBusy(bdev); //TODO:do this right ATASelectBlk28(bdev,blk,0); ATACmd(bdev,WIN_SET_MAX); IDEWaitNotBusy(bdev); } else { ATAPIStartStop(bdev,TRUE); ATAPISeek(bdev,0); } Btr(&sys_irq_flags,bdev->irq); if (unlock) Btr(&sys_irq_busy_flags,bdev->irq); Preempt(old_preempt); } /********** void IDEWaitReady(LTBlkDev *bdev) { U8 i=0; while (!(InP(bdev->base0+IDE_STATUS) & READY_STAT)) { if (!(++i & 0xFFF)) IDEInit(bdev,FALSE); ATANop(bdev); SwapInNext; } } ***********/ void ATAPIWaitReady(LTBlkDev *bdev) { U8 pass=0; BoolU4 cont; do { IDEWaitNotBusy(bdev); if (pass) SwapInNext; ATANop(bdev); if (InP(bdev->base0+IDE_STATUS) & READY_STAT) { if (!bdev->last_jiffy || pass>16 || (jiffies>bdev->last_jiffy+JIFFY_FREQ<<1)) { ATAPIStartStop(bdev,TRUE); } cont=FALSE; } else { if (pass>16) IDEInit(bdev,FALSE); cont=TRUE; } pass++; } while (cont || InP(bdev->base0+IDE_FEATURE_REG)); } void ATAReadBlks2(LTBlkDev *bdev,U1 *buf, U8 cnt) { U8 U2s_avail,sectors_avail; while (cnt) { while (InP(bdev->base0+IDE_STATUS) & DATA_READY!=DATA_READY) SwapInNext; // while (!(sectors_avail=cnt-InP(bdev->base0+IDE_NSECTOR_REG))) // SwapInNext; sectors_avail=1; U2s_avail=sectors_avail*BLK_SIZE>>1; RepInSW(buf,U2s_avail,bdev->base0+IDE_DATA_REG); buf+=U2s_avail<<1; cnt-=sectors_avail; } IDEWaitNotBusy(bdev); Btr(&sys_irq_flags,bdev->irq); } /*********** void ATAReadBlksExt(LTBlkDev *bdev,U1 *buf, U8 blk, U8 cnt) {// Untested BoolU4 old_preempt=Preempt(OFF); IDEWaitForDrive(bdev); ATASelectBlk48(bdev,blk,0,cnt); ATACmd(bdev,WIN_MULTREAD_EXT); ATAReadBlks2(bdev,buf,cnt); Btr(&sys_irq_busy_flags,bdev->irq); Preempt(old_preempt); } *************/ void ATAReadBlks(LTBlkDev *bdev,U1 *buf, U8 blk, U8 cnt) { BoolU4 old_preempt=Preempt(OFF); IDEWaitForDrive(bdev); ATASelectBlk28(bdev,blk,cnt); ATACmd(bdev,WIN_MULTREAD); ATAReadBlks2(bdev,buf,cnt); Btr(&sys_irq_busy_flags,bdev->irq); Preempt(old_preempt); } void ATAPIReadBlks2(LTBlkDev *bdev,U1 *buf, U8 blk, U8 cnt) { U8 U2s_avail; U1 *done_add=buf+cnt*bdev->blk_size; BoolU4 old_preempt=Preempt(OFF); if (!cnt) return; IDEWaitForDrive(bdev); ATAPIWaitReady(bdev); OutP(bdev->base1+IDE_CONTROL_REG,0x8); OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4); OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size); OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]); ATACmd(bdev,WIN_PACKETCMD); ATAPIWritePktWord(bdev,0xA800); ATAPIWritePktWord(bdev,blk.u2[1]); ATAPIWritePktWord(bdev,blk); ATAPIWritePktWord(bdev,cnt.u2[1]); ATAPIWritePktWord(bdev,cnt); ATAPIWritePktWord(bdev,0x0000); while (bufbase0+IDE_STATUS) & DATA_READY)) SwapInNext; if (U2s_avail=(InP(bdev->base0+IDE_HCYL_REG)<<8+InP(bdev->base0+IDE_LCYL_REG))>>1) { if (buf+U2s_avail<<1>done_add) U2s_avail=(done_add-buf)>>1; RepInSW(buf,U2s_avail,bdev->base0+IDE_DATA_REG); buf+=U2s_avail<<1; } } IDEWaitNotBusy(bdev); // ATAPIStartStop(bdev,FALSE); Btr(&sys_irq_busy_flags,bdev->irq); Preempt(old_preempt); } void ATAPIReadBlks(LTBlkDev *bdev,U1 *buf, U8 blk, U8 cnt) { LTPartition *p=DriveToPartition(bdev->partition_base); U8 dv=bdev->blk_size/BLK_SIZE,l,blk2, l2=bdev->max_reads<<1+dv<<1; U1 *cd_buf=MAlloc(BLK_SIZE*l2); if (cnt) { if (blk<=bdev->max_reads) blk2=0; else blk2=((blk-bdev->max_reads)/dv)*dv; if (blk2+l2>p->size) l2=p->size-blk2; l=(l2+dv-1)/dv; ATAPIReadBlks2(bdev,cd_buf,blk2/dv,l); if (bdev->flags & LTBDF_READ_CACHE) LTDCAdd(p,cd_buf,blk2,l*dv); MemCpy(buf,cd_buf+(blk-blk2)*BLK_SIZE,cnt*BLK_SIZE); } Free(cd_buf); } void IDERBlks(LTPartition *p,U1 *buf, U8 blk, U8 cnt) { U8 l; LTBlkDev *bdev=p->bdev; CheckLTBlkDev(bdev); while (cnt>0) { l=cnt; if (l>bdev->max_reads) l=bdev->max_reads; if (bdev->type==LTBDT_ATAPI) ATAPIReadBlks(bdev,buf,blk,l); else ATAReadBlks(bdev,buf,blk,l); buf+=l*BLK_SIZE; blk+=l; cnt-=l; disk_status_display.u2[0]=disk_status_display.u2[0]-l; } } //This is for low level disk access //Call WBlks() instead void ATAWriteBlks(LTBlkDev *bdev,U1 *buf, U8 blk, U8 cnt) { U8 U2s_avail,sectors_avail; BoolU4 old_preempt=Preempt(OFF); IDEWaitForDrive(bdev); ATASelectBlk28(bdev,blk,cnt); ATACmd(bdev,WIN_MULTWRITE); while (cnt) { while (InP(bdev->base0+IDE_STATUS) & DRIVE_READY!=DRIVE_READY) SwapInNext; while (InP(bdev->base0+IDE_STATUS) & DATA_READY!=DATA_READY) SwapInNext; //TODO sectors_avail=1; U2s_avail=sectors_avail*BLK_SIZE>>1; RepOutSW(buf,U2s_avail,bdev->base0+IDE_DATA_REG); buf+=U2s_avail<<1; cnt-=sectors_avail; } IDEWaitNotBusy(bdev); Btr(&sys_irq_busy_flags,bdev->irq); Preempt(old_preempt); } void ATAPISync(LTBlkDev *bdev) { OutP(bdev->base1+IDE_CONTROL_REG,0x8); OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4); OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size); OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]); ATACmd(bdev,WIN_PACKETCMD); ATAPIWritePktWord(bdev,0x3500); //Sync ATAPIWritePktWord(bdev,0x0000); ATAPIWritePktWord(bdev,0x0000); ATAPIWritePktWord(bdev,0x0000); ATAPIWritePktWord(bdev,0x0000); ATAPIWritePktWord(bdev,0x0000); IDEWaitNotBusy(bdev); } void ATAPIClose(LTBlkDev *bdev) { OutP(bdev->base1+IDE_CONTROL_REG,0x8); OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4); OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size); OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]); ATACmd(bdev,WIN_PACKETCMD); ATAPIWritePktWord(bdev,0x5B00); //Close ATAPIWritePktWord(bdev,0x0200); ATAPIWritePktWord(bdev,0x0000); ATAPIWritePktWord(bdev,0x0000); ATAPIWritePktWord(bdev,0x0000); ATAPIWritePktWord(bdev,0x0000); IDEWaitNotBusy(bdev); } void ATAPIWriteBlks(LTBlkDev *bdev,U1 *buf, U8 blk, U8 cnt) { U8 U2s_avail; U1 *buf2; ATAPISeek(bdev,blk); OutP(bdev->base0+IDE_FEATURE_REG,0); OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size); OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]); OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4); OutP(bdev->base0+IDE_CMD,WIN_PACKETCMD); ATAPIWritePktWord(bdev,0x0400); //FMT ATAPIWritePktWord(bdev,blk.u2[1]); ATAPIWritePktWord(bdev,blk); ATAPIWritePktWord(bdev,cnt.u2[1]); ATAPIWritePktWord(bdev,cnt); ATAPIWritePktWord(bdev,0x0000); IDEWaitNotBusy(bdev); ATAPISeek(bdev,blk); OutP(bdev->base1+IDE_CONTROL_REG,0x8); OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4); OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size); OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]); ATACmd(bdev,WIN_PACKETCMD); ATAPIWritePktWord(bdev,0xAA00); //Write ATAPIWritePktWord(bdev,blk.u2[1]); ATAPIWritePktWord(bdev,blk); ATAPIWritePktWord(bdev,cnt.u2[1]); ATAPIWritePktWord(bdev,cnt); ATAPIWritePktWord(bdev,0x0000); buf2=buf+bdev->blk_size*cnt; while (bufbase0+IDE_STATUS) & DRIVE_READY!=DRIVE_READY) SwapInNext; while (InP(bdev->base0+IDE_STATUS) & DATA_READY!=DATA_READY) SwapInNext; U2s_avail=(InP(bdev->base0+IDE_HCYL_REG)<<8+InP(bdev->base0+IDE_LCYL_REG))>>1; if (buf+U2s_avail<<1>buf2) U2s_avail=(buf2-buf)>>1; if (U2s_avail) { RepOutSW(buf,U2s_avail,bdev->base0+IDE_DATA_REG); buf+=U2s_avail<<1; } } IDEWaitNotBusy(bdev); } //TODO: needs to be fixed so it does more than one blk at //a time when it calls ATAWriteBlks. void IDEWBlks(LTPartition *p,U1 *buf, U8 blk, U8 cnt) { U8 l,dv; LTBlkDev *bdev=p->bdev; CheckLTBlkDev(bdev); dv=bdev->blk_size/BLK_SIZE; if (bdev->type==LTBDT_ATAPI) { IDEWaitForDrive(bdev); ATAPIWaitReady(bdev); } while (cnt>0) { l=cnt; if (l>bdev->max_writes) l=bdev->max_writes; if (bdev->type==LTBDT_ATAPI) ATAPIWriteBlks(bdev,buf,blk/dv,(l+dv-1)/dv); else ATAWriteBlks(bdev,buf,blk,l); buf+=l*BLK_SIZE; blk+=l; cnt-=l; disk_status_display.u2[0]=disk_status_display.u2[0]-l; } if (bdev->type==LTBDT_ATAPI) { ATAPISync(bdev); // ATAPIStartStop(bdev,FALSE); Btr(&sys_irq_busy_flags,bdev->irq); } }