/* The printf is similar to printk.printk can be subsituted for printf in the below code. The code works upto some extent. When using the code while booting i can see the harddisk light blinking (red light) . So the controller is moving . But it is unable to read sectors somehow. Is the sequence correct for ide. It works correctly in vmware under linux(checked with hexdump /dev/hda in linux).But when tried to boot independently it causes error (atleast doesn't match with the correct data. It produces d0 1 d0 1 d0 1 d0 1 d0 1 d0 ...d9 1 d9 ...) which doesn't tally with hexdump /dev/hda. My guess is that sequence is not correct or i have made some error.So if someone experienced can tell me where the error is and make it work it would be very helpful in moving forward. */ static inline void insw(unsigned short port, void *addr, unsigned long count) { __asm__ __volatile__(" rep ; ins" "w":"=D"(addr), "=c"(count):"d"(port), "0"(addr), "1"(count)); } static int drive_busy(void) { unsigned int i; unsigned char c; for (i = 0; i < 10000; i++) if (0x40 == (inb(0x1f7) & (0x80 | 0x40))) break; i = inb(0x1f7); i &= 0x80 | 0x40 | 0x10; if (i == 0x40 | 0x10) return 0; printf("Hd controller times out\n"); } void reset_controller(void) { unsigned int i; outb(4, 0x3f6); for (i = 0; i < 1000; i++) __asm__ __volatile__("nop"); outb(0, 0x3f6); for (i = 0; i < 10000 && drive_busy(); i++); if (drive_busy()) printf("HD controller still busy\n"); if (i = inb(0x1f1) != 1) printf("HD controller reset failed \n"); if (!controller_ready()) printf("HD controller not ready\n"); } void hd_out(unsigned int drive, unsigned char nsect, unsigned char sect, unsigned char head, unsigned char cyl, unsigned char cmd) { unsigned short port; port = 0x1f0; ++port; outb(nsect, ++port); /*1f2 */ outb(sect, ++port); /*1f3 */ outb(cyl, ++port); /*1f4 */ outb(cyl >> 8, ++port); /*1f5 */ outb(0xA0 | (drive << 4), 0x1f6); outb(cmd, ++port); } void hd_init(void) { unsigned char *s; unsigned int i = 0; hd_out(0, 2, 0, 0, 0, 0x10); hd_out(0, 2, 0, 0, 0, 0x20); insw(0x1f0, s, 10); for (i = 0; i < 10; i++) printf("%x\n", *(s + i)); }