|  |  |  | @ -5,267 +5,120 @@ | 
			
		
	
		
			
				
					|  |  |  |  | use spin::Mutex; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | lazy_static! { | 
			
		
	
		
			
				
					|  |  |  |  |     pub static ref DISK0: LockedIde = LockedIde(Mutex::new(DmaController::new(0))); | 
			
		
	
		
			
				
					|  |  |  |  |     pub static ref DISK1: LockedIde = LockedIde(Mutex::new(DmaController::new(1))); | 
			
		
	
		
			
				
					|  |  |  |  |     pub static ref DISK0: LockedIde = LockedIde(Mutex::new(IDE::new(0))); | 
			
		
	
		
			
				
					|  |  |  |  |     pub static ref DISK1: LockedIde = LockedIde(Mutex::new(IDE::new(1))); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | pub const BLOCK_SIZE: usize = 512; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub struct LockedIde(pub Mutex<DmaController>); | 
			
		
	
		
			
				
					|  |  |  |  | pub struct LockedIde(pub Mutex<IDE>); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub struct DmaController { | 
			
		
	
		
			
				
					|  |  |  |  | pub struct IDE { | 
			
		
	
		
			
				
					|  |  |  |  |     num: u8, | 
			
		
	
		
			
				
					|  |  |  |  |     /// I/O Base
 | 
			
		
	
		
			
				
					|  |  |  |  |     base: u16, | 
			
		
	
		
			
				
					|  |  |  |  |     /// Control Base
 | 
			
		
	
		
			
				
					|  |  |  |  |     ctrl: u16, | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | impl DmaController | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     /// Read ATA DMA. Block size = 512 bytes.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn read(&self, blockidx: u64, count: usize, dst: &mut [u32]) -> Result<usize, ()> { | 
			
		
	
		
			
				
					|  |  |  |  |         assert_eq!(dst.len(), count * SECTOR_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  |         let dst = if count > MAX_DMA_SECTORS { &mut dst[..MAX_DMA_SECTORS * SECTOR_SIZE] } else { dst }; | 
			
		
	
		
			
				
					|  |  |  |  |         //self.do_dma(blockidx, DMABuffer::new_mut(dst, 32), disk, false);
 | 
			
		
	
		
			
				
					|  |  |  |  |         self.ide_read_secs(self.num, blockidx, dst, count as u8) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     /// Write ATA DMA. Block size = 512 bytes.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn write(&self, blockidx: u64, count: usize, dst: &[u32]) -> Result<usize, ()> { | 
			
		
	
		
			
				
					|  |  |  |  |         assert_eq!(dst.len(), count * SECTOR_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  |         let dst = if count > MAX_DMA_SECTORS { &dst[..MAX_DMA_SECTORS * SECTOR_SIZE] } else { dst }; | 
			
		
	
		
			
				
					|  |  |  |  |         //println!("ide_write_secs: disk={},blockidx={},count={}",disk,blockidx,count);
 | 
			
		
	
		
			
				
					|  |  |  |  |         self.ide_write_secs(self.num, blockidx, dst, count as u8) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     /// Create structure and init
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn new(num: u8) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         assert!(num < MAX_IDE as u8); | 
			
		
	
		
			
				
					|  |  |  |  |         let ide = DmaController { num }; | 
			
		
	
		
			
				
					|  |  |  |  |         ide.ide_init(); | 
			
		
	
		
			
				
					|  |  |  |  | impl IDE { | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn new(num: u8) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         let ide = match num { | 
			
		
	
		
			
				
					|  |  |  |  |             0 => IDE { num: 0, base: 0x1f0, ctrl: 0x3f4 }, | 
			
		
	
		
			
				
					|  |  |  |  |             1 => IDE { num: 1, base: 0x1f0, ctrl: 0x3f4 }, | 
			
		
	
		
			
				
					|  |  |  |  |             2 => IDE { num: 2, base: 0x170, ctrl: 0x374 }, | 
			
		
	
		
			
				
					|  |  |  |  |             3 => IDE { num: 3, base: 0x170, ctrl: 0x374 }, | 
			
		
	
		
			
				
					|  |  |  |  |             _ => panic!("ide number should be 0,1,2,3"), | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         ide.init(); | 
			
		
	
		
			
				
					|  |  |  |  |         ide | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn ide_wait_ready(&self, iobase: u16, check_error: usize) -> usize { | 
			
		
	
		
			
				
					|  |  |  |  |     /// Read ATA DMA. Block size = 512 bytes.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn read(&self, sector: u64, count: usize, data: &mut [u32]) -> Result<(), ()> { | 
			
		
	
		
			
				
					|  |  |  |  |         assert_eq!(data.len(), count * SECTOR_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  |         self.wait(); | 
			
		
	
		
			
				
					|  |  |  |  |         unsafe { | 
			
		
	
		
			
				
					|  |  |  |  |             let mut r = port::inb(iobase + ISA_STATUS); | 
			
		
	
		
			
				
					|  |  |  |  |             //println!("iobase:{} ready:{}",iobase,r);
 | 
			
		
	
		
			
				
					|  |  |  |  |             while (r & IDE_BSY) > 0 { | 
			
		
	
		
			
				
					|  |  |  |  |                 r = port::inb(iobase + ISA_STATUS); | 
			
		
	
		
			
				
					|  |  |  |  |                 //println!("busy");
 | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             /* nothing */ | 
			
		
	
		
			
				
					|  |  |  |  |             if check_error == 1 && (r & (IDE_DF | IDE_ERR)) != 0 { | 
			
		
	
		
			
				
					|  |  |  |  |                 return 1; | 
			
		
	
		
			
				
					|  |  |  |  |             self.select(sector, count as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(self.base + ISA_COMMAND, IDE_CMD_READ); | 
			
		
	
		
			
				
					|  |  |  |  |             for i in 0..count { | 
			
		
	
		
			
				
					|  |  |  |  |                 let ptr = &data[(i as usize) * SECTOR_SIZE]; | 
			
		
	
		
			
				
					|  |  |  |  |                 if self.wait_error() { | 
			
		
	
		
			
				
					|  |  |  |  |                     return Err(()); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |                 asm!("rep insl" :: "{dx}"(self.base), "{rdi}"(ptr), "{cx}"(SECTOR_SIZE) : "rdi" : "volatile"); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         return 0; | 
			
		
	
		
			
				
					|  |  |  |  |         Ok(()) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn ide_init(&self) { | 
			
		
	
		
			
				
					|  |  |  |  |         //static_assert((SECTSIZE % 4) == 0);
 | 
			
		
	
		
			
				
					|  |  |  |  |         let ideno = self.num; | 
			
		
	
		
			
				
					|  |  |  |  |         //println!("ideno:{}",ideno);
 | 
			
		
	
		
			
				
					|  |  |  |  |         /* assume that no device here */ | 
			
		
	
		
			
				
					|  |  |  |  |         //ide_devices[ideno].valid = 0;
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         //let iobase = IO_BASE(ideno);
 | 
			
		
	
		
			
				
					|  |  |  |  |         let iobase = CHANNELS[if ideno > 2 { 1 } else { 0 }].0; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         /* wait device ready */ | 
			
		
	
		
			
				
					|  |  |  |  |         self.ide_wait_ready(iobase, 0); | 
			
		
	
		
			
				
					|  |  |  |  |         //println!("ide_wait_ready");
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Write ATA DMA. Block size = 512 bytes.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn write(&self, sector: u64, count: usize, data: &[u32]) -> Result<(), ()> { | 
			
		
	
		
			
				
					|  |  |  |  |         assert_eq!(data.len(), count * SECTOR_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  |         self.wait(); | 
			
		
	
		
			
				
					|  |  |  |  |         unsafe { | 
			
		
	
		
			
				
					|  |  |  |  |             /* step1: select drive */ | 
			
		
	
		
			
				
					|  |  |  |  |             //println!("outb");
 | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_SDH, (0xE0 | ((ideno & 1) << 4)) as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             self.ide_wait_ready(iobase, 0); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             /* step2: send ATA identify command */ | 
			
		
	
		
			
				
					|  |  |  |  |             //println!("outb");
 | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_COMMAND, IDE_CMD_IDENTIFY); | 
			
		
	
		
			
				
					|  |  |  |  |             self.ide_wait_ready(iobase, 0); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             /* step3: polling */ | 
			
		
	
		
			
				
					|  |  |  |  |             //println!("inb");
 | 
			
		
	
		
			
				
					|  |  |  |  |             if port::inb(iobase + ISA_STATUS) == 0 || self.ide_wait_ready(iobase, 1) != 0 { | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             //println!("insl");
 | 
			
		
	
		
			
				
					|  |  |  |  |             let mut buffer: [u32; 128] = [0; 128]; | 
			
		
	
		
			
				
					|  |  |  |  |             for i in 0..buffer.len() { | 
			
		
	
		
			
				
					|  |  |  |  |                 buffer[i] = i as u32; | 
			
		
	
		
			
				
					|  |  |  |  |                 if i == 1 { | 
			
		
	
		
			
				
					|  |  |  |  |                     //println!("{:#x}",&buffer[i] as *const u32 as usize - ::consts::KERNEL_OFFSET)
 | 
			
		
	
		
			
				
					|  |  |  |  |             self.select(sector, count as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(self.base + ISA_COMMAND, IDE_CMD_WRITE); | 
			
		
	
		
			
				
					|  |  |  |  |             for i in 0..count { | 
			
		
	
		
			
				
					|  |  |  |  |                 let ptr = &data[(i as usize) * SECTOR_SIZE]; | 
			
		
	
		
			
				
					|  |  |  |  |                 if self.wait_error() { | 
			
		
	
		
			
				
					|  |  |  |  |                     return Err(()); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             //println!("insl {:#x}",&buffer as *const u32 as usize - ::consts::KERNEL_OFFSET);
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             //println!("insl {:#x}",buffer.as_ptr() as usize - ::consts::KERNEL_OFFSET);
 | 
			
		
	
		
			
				
					|  |  |  |  |             //port::insl(iobase + ISA_DATA, &mut buffer);
 | 
			
		
	
		
			
				
					|  |  |  |  |             let port = iobase + ISA_DATA; | 
			
		
	
		
			
				
					|  |  |  |  |             //let buf=&mut buffer;
 | 
			
		
	
		
			
				
					|  |  |  |  |             for i in 0..buffer.len() { | 
			
		
	
		
			
				
					|  |  |  |  |                 asm!("insl %dx, (%rdi)" | 
			
		
	
		
			
				
					|  |  |  |  |                 :: "{dx}"(port), "{rdi}"(&buffer[i]) | 
			
		
	
		
			
				
					|  |  |  |  |                 : "rdi" : "volatile"); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             //println!("insl");
 | 
			
		
	
		
			
				
					|  |  |  |  |             for i in 0..4 { | 
			
		
	
		
			
				
					|  |  |  |  |                 info!("ide init: {}", buffer[i]); | 
			
		
	
		
			
				
					|  |  |  |  |                 asm!("rep outsl" :: "{dx}"(self.base), "{rsi}"(ptr), "{cx}"(SECTOR_SIZE) : "rsi" : "volatile"); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         /* device is ok */ | 
			
		
	
		
			
				
					|  |  |  |  |         //ide_devices[ideno].valid = 1;
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         /* read identification space of the device */ | 
			
		
	
		
			
				
					|  |  |  |  |         /*let buffer[128];
 | 
			
		
	
		
			
				
					|  |  |  |  |         insl(iobase + ISA_DATA, buffer, sizeof(buffer) / sizeof(unsigned int)); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         unsigned char *ident = (unsigned char *)buffer; | 
			
		
	
		
			
				
					|  |  |  |  |         unsigned int sectors; | 
			
		
	
		
			
				
					|  |  |  |  |         unsigned int cmdsets = *(unsigned int *)(ident + IDE_IDENT_CMDSETS); | 
			
		
	
		
			
				
					|  |  |  |  |         /* device use 48-bits or 28-bits addressing */ | 
			
		
	
		
			
				
					|  |  |  |  |         if (cmdsets & (1 << 26)) { | 
			
		
	
		
			
				
					|  |  |  |  |             sectors = *(unsigned int *)(ident + IDE_IDENT_MAX_LBA_EXT); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         else { | 
			
		
	
		
			
				
					|  |  |  |  |             sectors = *(unsigned int *)(ident + IDE_IDENT_MAX_LBA); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         ide_devices[ideno].sets = cmdsets; | 
			
		
	
		
			
				
					|  |  |  |  |         ide_devices[ideno].size = sectors; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         /* check if supports LBA */ | 
			
		
	
		
			
				
					|  |  |  |  |         assert((*(unsigned short *)(ident + IDE_IDENT_CAPABILITIES) & 0x200) != 0); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         unsigned char *model = ide_devices[ideno].model, *data = ident + IDE_IDENT_MODEL; | 
			
		
	
		
			
				
					|  |  |  |  |         unsigned int i, length = 40; | 
			
		
	
		
			
				
					|  |  |  |  |         for (i = 0; i < length; i += 2) { | 
			
		
	
		
			
				
					|  |  |  |  |             model[i] = data[i + 1], model[i + 1] = data[i]; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         do { | 
			
		
	
		
			
				
					|  |  |  |  |             model[i] = '\0'; | 
			
		
	
		
			
				
					|  |  |  |  |         } while (i -- > 0 && model[i] == ' '); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         cprintf("ide %d: %10u(sectors), '%s'.\n", ideno, ide_devices[ideno].size, ide_devices[ideno].model);*/ | 
			
		
	
		
			
				
					|  |  |  |  |         Ok(()) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // enable ide interrupt
 | 
			
		
	
		
			
				
					|  |  |  |  |         //pic_enable(IRQ_IDE1);
 | 
			
		
	
		
			
				
					|  |  |  |  |         //pic_enable(IRQ_IDE2);
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn wait(&self) { | 
			
		
	
		
			
				
					|  |  |  |  |         while unsafe { port::inb(self.base + ISA_STATUS) } & IDE_BUSY != 0 {} | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         info!("ide {} init end", self.num); | 
			
		
	
		
			
				
					|  |  |  |  |     fn wait_error(&self) -> bool { | 
			
		
	
		
			
				
					|  |  |  |  |         self.wait(); | 
			
		
	
		
			
				
					|  |  |  |  |         let status = unsafe { port::inb(self.base + ISA_STATUS) }; | 
			
		
	
		
			
				
					|  |  |  |  |         status & (IDE_DF | IDE_ERR) != 0 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     fn ide_read_secs<'a>(&'a self, ideno: u8, secno: u64, dst: &'a mut [u32], nsecs: u8) -> Result<usize, ()> { | 
			
		
	
		
			
				
					|  |  |  |  |         //assert(nsecs <= MAX_NSECS && VALID_IDE(ideno));
 | 
			
		
	
		
			
				
					|  |  |  |  |         //assert(secno < MAX_DISK_NSECS && secno + nsecs <= MAX_DISK_NSECS);
 | 
			
		
	
		
			
				
					|  |  |  |  |         let iobase = CHANNELS[if ideno > 2 { 1 } else { 0 }].0; | 
			
		
	
		
			
				
					|  |  |  |  |         let ioctrl = CHANNELS[if ideno > 2 { 1 } else { 0 }].1; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         //ide_wait_ready(iobase, 0);
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn init(&self) { | 
			
		
	
		
			
				
					|  |  |  |  |         self.wait(); | 
			
		
	
		
			
				
					|  |  |  |  |         unsafe { | 
			
		
	
		
			
				
					|  |  |  |  |             // step1: select drive
 | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(self.base + ISA_SDH, (0xE0 | ((self.num & 1) << 4)) as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             self.wait(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         self.ide_wait_ready(iobase, 0); | 
			
		
	
		
			
				
					|  |  |  |  |             // step2: send ATA identify command
 | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(self.base + ISA_COMMAND, IDE_CMD_IDENTIFY); | 
			
		
	
		
			
				
					|  |  |  |  |             self.wait(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let ret = 0; | 
			
		
	
		
			
				
					|  |  |  |  |         // generate interrupt
 | 
			
		
	
		
			
				
					|  |  |  |  |         unsafe { | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(ioctrl + ISA_CTRL, 0); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_SECCNT, nsecs); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_SECTOR, (secno & 0xFF) as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_CYL_LO, ((secno >> 8) & 0xFF) as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_CYL_HI, ((secno >> 16) & 0xFF) as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_SDH, 0xE0 | ((ideno & 1) << 4) | (((secno >> 24) & 0xF) as u8)); | 
			
		
	
		
			
				
					|  |  |  |  |             //port::outb(iobase + ISA_SDH, (0xE0 | ((ideno & 1) << 4)) as u8);
 | 
			
		
	
		
			
				
					|  |  |  |  |             //self.ide_wait_ready(iobase, 0);
 | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_COMMAND, IDE_CMD_READ); | 
			
		
	
		
			
				
					|  |  |  |  |             //self.ide_wait_ready(iobase, 0);
 | 
			
		
	
		
			
				
					|  |  |  |  |             // if port::inb(iobase + ISA_STATUS) == 0 || self.ide_wait_ready(iobase, 1) != 0 {
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 	println!("error?");
 | 
			
		
	
		
			
				
					|  |  |  |  |             // }
 | 
			
		
	
		
			
				
					|  |  |  |  |             for i in 0..nsecs { | 
			
		
	
		
			
				
					|  |  |  |  |                 //dst = dst + SECTSIZE;
 | 
			
		
	
		
			
				
					|  |  |  |  |                 let tmp = &mut dst[(i as usize) * SECTOR_SIZE..((i + 1) as usize) * SECTOR_SIZE]; | 
			
		
	
		
			
				
					|  |  |  |  |                 if self.ide_wait_ready(iobase, 1) != 0 { | 
			
		
	
		
			
				
					|  |  |  |  |                     println!("wait ready error"); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |                 //self.ide_wait_ready(iobase, 1);
 | 
			
		
	
		
			
				
					|  |  |  |  |                 //port::insl(iobase, tmp);
 | 
			
		
	
		
			
				
					|  |  |  |  |                 let port = iobase; | 
			
		
	
		
			
				
					|  |  |  |  |                 //let buf=&mut buffer;
 | 
			
		
	
		
			
				
					|  |  |  |  |                 for i in 0..tmp.len() { | 
			
		
	
		
			
				
					|  |  |  |  |                     asm!("insl %dx, (%rdi)" | 
			
		
	
		
			
				
					|  |  |  |  | 					:: "{dx}"(port), "{rdi}"(&tmp[i]) | 
			
		
	
		
			
				
					|  |  |  |  | 					: "rdi" : "volatile"); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |                 //println!("read :{}",i);
 | 
			
		
	
		
			
				
					|  |  |  |  |             // step3: polling
 | 
			
		
	
		
			
				
					|  |  |  |  |             if port::inb(self.base + ISA_STATUS) == 0 || self.wait_error() { | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // ???
 | 
			
		
	
		
			
				
					|  |  |  |  |             let mut data = [0; SECTOR_SIZE]; | 
			
		
	
		
			
				
					|  |  |  |  |             asm!("rep insl" :: "{dx}"(self.base + ISA_DATA), "{rdi}"(data.as_ptr()), "{cx}"(SECTOR_SIZE) : "rdi" : "volatile"); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Ok(ret) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn ide_write_secs<'a>(&'a self, ideno: u8, secno: u64, src: &'a [u32], nsecs: u8) -> Result<usize, ()> { | 
			
		
	
		
			
				
					|  |  |  |  |         //assert(nsecs <= MAX_NSECS && VALID_IDE(ideno));
 | 
			
		
	
		
			
				
					|  |  |  |  |         //assert(secno < MAX_DISK_NSECS && secno + nsecs <= MAX_DISK_NSECS);
 | 
			
		
	
		
			
				
					|  |  |  |  |         let iobase = CHANNELS[if ideno > 2 { 1 } else { 0 }].0; | 
			
		
	
		
			
				
					|  |  |  |  |         let ioctrl = CHANNELS[if ideno > 2 { 1 } else { 0 }].1; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         //ide_wait_ready(iobase, 0);
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         self.ide_wait_ready(iobase, 0); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let ret = 0; | 
			
		
	
		
			
				
					|  |  |  |  |         // generate interrupt
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn select(&self, sector: u64, count: u8) { | 
			
		
	
		
			
				
					|  |  |  |  |         assert_ne!(count, 0); | 
			
		
	
		
			
				
					|  |  |  |  |         self.wait(); | 
			
		
	
		
			
				
					|  |  |  |  |         unsafe { | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(ioctrl + ISA_CTRL, 0); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_SECCNT, nsecs); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_SECTOR, (secno & 0xFF) as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_CYL_LO, ((secno >> 8) & 0xFF) as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_CYL_HI, ((secno >> 16) & 0xFF) as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_SDH, 0xE0 | ((ideno & 1) << 4) | (((secno >> 24) & 0xF) as u8)); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(iobase + ISA_COMMAND, IDE_CMD_WRITE); | 
			
		
	
		
			
				
					|  |  |  |  |             //println!("{}",nsecs);
 | 
			
		
	
		
			
				
					|  |  |  |  |             for i in 0..nsecs { | 
			
		
	
		
			
				
					|  |  |  |  |                 //dst = dst + SECTSIZE;
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // if ((ret = ide_wait_ready(iobase, 1)) != 0) {
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // 	goto out;
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // }
 | 
			
		
	
		
			
				
					|  |  |  |  |                 //port::insb(iobase, dst);
 | 
			
		
	
		
			
				
					|  |  |  |  |                 //println!("i={}",i);
 | 
			
		
	
		
			
				
					|  |  |  |  |                 let tmp = &src[(i as usize) * SECTOR_SIZE..((i + 1) as usize) * SECTOR_SIZE]; | 
			
		
	
		
			
				
					|  |  |  |  |                 if self.ide_wait_ready(iobase, 1) != 0 { | 
			
		
	
		
			
				
					|  |  |  |  |                     println!("wait ready error"); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |                 //println!("write {}:{}",i,src[i as usize]);
 | 
			
		
	
		
			
				
					|  |  |  |  |                 //println!("outsl");
 | 
			
		
	
		
			
				
					|  |  |  |  |                 //port::outsl(iobase, tmp);
 | 
			
		
	
		
			
				
					|  |  |  |  |                 let port = iobase; | 
			
		
	
		
			
				
					|  |  |  |  |                 //let buf=&mut buffer;
 | 
			
		
	
		
			
				
					|  |  |  |  |                 for i in 0..tmp.len() { | 
			
		
	
		
			
				
					|  |  |  |  |                     asm!("outsl (%rsi), %dx" | 
			
		
	
		
			
				
					|  |  |  |  |         			:: "{dx}"(port), "{rsi}"(&tmp[i]) | 
			
		
	
		
			
				
					|  |  |  |  |         			: "rsi"); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |                 //println!("write :{}",i);
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // for i in 0..4 {
 | 
			
		
	
		
			
				
					|  |  |  |  |                 //  	println!("{}",src[i as usize]);
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // }
 | 
			
		
	
		
			
				
					|  |  |  |  |                 //port::outb(iobase, src[i as usize]);
 | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             // generate interrupt
 | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(self.ctrl + ISA_CTRL, 0); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(self.base + ISA_SECCNT, count); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(self.base + ISA_SECTOR, (sector & 0xFF) as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(self.base + ISA_CYL_LO, ((sector >> 8) & 0xFF) as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(self.base + ISA_CYL_HI, ((sector >> 16) & 0xFF) as u8); | 
			
		
	
		
			
				
					|  |  |  |  |             port::outb(self.base + ISA_SDH, 0xE0 | ((self.num & 1) << 4) | (((sector >> 24) & 0xF) as u8)); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Ok(ret) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | const SECTOR_SIZE: usize = 128; | 
			
		
	
		
			
				
					|  |  |  |  | //const MAX_DMA_SECTORS: usize = 0x2_0000 / SECTOR_SIZE;	// Limited by sector count (and PRDT entries)
 | 
			
		
	
		
			
				
					|  |  |  |  | const MAX_DMA_SECTORS: usize = 0x1F_F000 / SECTOR_SIZE;    // Limited by sector count (and PRDT entries)
 | 
			
		
	
		
			
				
					|  |  |  |  | // 512 PDRT entries, assume maximum fragmentation = 512 * 4K max = 2^21 = 2MB per transfer
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | const HDD_PIO_W28: u8 = 0x30; | 
			
		
	
		
			
				
					|  |  |  |  | const HDD_PIO_R28: u8 = 0x20; | 
			
		
	
		
			
				
					|  |  |  |  | const HDD_PIO_W48: u8 = 0x34; | 
			
		
	
		
			
				
					|  |  |  |  | const HDD_PIO_R48: u8 = 0x24; | 
			
		
	
		
			
				
					|  |  |  |  | const HDD_IDENTIFY: u8 = 0xEC; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | const HDD_DMA_R28: u8 = 0xC8; | 
			
		
	
		
			
				
					|  |  |  |  | const HDD_DMA_W28: u8 = 0xCA; | 
			
		
	
		
			
				
					|  |  |  |  | const HDD_DMA_R48: u8 = 0x25; | 
			
		
	
		
			
				
					|  |  |  |  | const HDD_DMA_W48: u8 = 0x35; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | const ISA_DATA: u16 = 0x00; | 
			
		
	
		
			
				
					|  |  |  |  | const ISA_ERROR: u16 = 0x01; | 
			
		
	
		
			
				
					|  |  |  |  | const ISA_PRECOMP: u16 = 0x01; | 
			
		
	
	
		
			
				
					|  |  |  | @ -278,7 +131,7 @@ const ISA_SDH: u16 = 0x06; | 
			
		
	
		
			
				
					|  |  |  |  | const ISA_COMMAND: u16 = 0x07; | 
			
		
	
		
			
				
					|  |  |  |  | const ISA_STATUS: u16 = 0x07; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_BSY: u8 = 0x80; | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_BUSY: u8 = 0x80; | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_DRDY: u8 = 0x40; | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_DF: u8 = 0x20; | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_DRQ: u8 = 0x08; | 
			
		
	
	
		
			
				
					|  |  |  | @ -288,33 +141,7 @@ const IDE_CMD_READ: u8 = 0x20; | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_CMD_WRITE: u8 = 0x30; | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_CMD_IDENTIFY: u8 = 0xEC; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_IDENT_SECTORS: usize = 20; | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_IDENT_MODEL: usize = 54; | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_IDENT_CAPABILITIES: usize = 98; | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_IDENT_CMDSETS: usize = 164; | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_IDENT_MAX_LBA: usize = 120; | 
			
		
	
		
			
				
					|  |  |  |  | const IDE_IDENT_MAX_LBA_EXT: usize = 200; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | const IO_BASE0: u16 = 0x1F0; | 
			
		
	
		
			
				
					|  |  |  |  | const IO_BASE1: u16 = 0x170; | 
			
		
	
		
			
				
					|  |  |  |  | const IO_CTRL0: u16 = 0x3F4; | 
			
		
	
		
			
				
					|  |  |  |  | const IO_CTRL1: u16 = 0x374; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | const MAX_IDE: usize = 4; | 
			
		
	
		
			
				
					|  |  |  |  | const MAX_NSECS: usize = 128; | 
			
		
	
		
			
				
					|  |  |  |  | //const MAX_DISK_NSECS          0x10000000U;
 | 
			
		
	
		
			
				
					|  |  |  |  | //const VALID_IDE(ideno)        (((ideno) >= 0) && ((ideno) < MAX_IDE) && (ide_devices[ideno].valid))
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | struct Channels { | 
			
		
	
		
			
				
					|  |  |  |  |     base: u16, | 
			
		
	
		
			
				
					|  |  |  |  |     // I/O Base
 | 
			
		
	
		
			
				
					|  |  |  |  |     ctrl: u16,        // Control Base
 | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | const CHANNELS: [(u16, u16); 2] = [(IO_BASE0, IO_CTRL0), (IO_BASE1, IO_CTRL1)]; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | //const IO_BASE(ideno)          (CHANNELS[(ideno) >> 1].base)
 | 
			
		
	
		
			
				
					|  |  |  |  | //const IO_CTRL(ideno)          (CHANNELS[(ideno) >> 1].ctrl)
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | mod port { | 
			
		
	
		
			
				
					|  |  |  |  |     use x86_64::instructions::port::Port; | 
			
		
	
	
		
			
				
					|  |  |  | 
 |