I started to write FDC driver for x86 using bochs and intel documents, some tutorials (from this forum)
but I couldn't make it works. I spent few weeks to solve this problem...
would you let me know what I've missed?
I can't understand why it doesn't work. I followed the instruction of manual....
in the fdc_read function, go into the loop until the interrupt occurs, but the interrupt does not generated...
thank you.
Code: Select all
#if !defined(_ARCH_BOOT_X86_FDC)
#define _ARCH_BOOT_X86_FDC
enum {
FD_SECTOR_PER_TRACK = 18,
};
#define LBA_TO_CHS(lba, h, t, s) do { \
(h) = ((lba) % (FD_SECTOR_PER_TRACK << 1)) / FD_SECTOR_PER_TRACK;\
(t) = (lba) / (FD_SECTOR_PER_TRACK << 1); \
(s) = (lba) % FD_SECTOR_PER_TRACK + 1; \
} while(0)
// 0x3F0 ~ 0x3F7
enum base_address
{
FDC_PRIMARY = 0x3F0,
FDC_SECONDARY = 0x370,
};
enum bytes_per_sector
{
SECTOR_128 = 0,
SECTOR_256 = 1,
SECTOR_512 = 2,
SECTOR_1024 = 3,
SECTOR_16K = 7,
};
// IDX:0, R - SRA
#define REG_SRA(base) (base)
#define SRA(reg) ((SRA_t*)(reg))
typedef struct status_register_a SRA_t;
struct status_register_a
{
#if defined(MODE_PS2)
unsigned long dir:1;
unsigned long b_wp:1;
unsigned long b_idx:1;
unsigned long hdsel:1;
unsigned long b_trk0:1;
unsigned long step:1;
unsigned long b_drv2:1;
unsigned long interrupted:1;
#define SRA_RESET_DONE(reg) (!SRA(reg)->interrupted && !SRA(reg)->step && !SRA(reg)->hdsel && !SRA(reg)->dir)
#define SRA_INTERRUPTED(reg) SRA(reg)->interrupted)
#elif defined(MODE_MODEL30)
unsigned long b_dir:1;
unsigned long wp:1;
unsigned long index:1;
unsigned long b_hdsel:1;
unsigned long trk0:1;
unsigned long step_ff:1;
unsigned long drq:1; // DMA Request
unsigned long interrupted:1;
#define SRA_RESET_DONE(reg) (!SRA(reg)->step_ff)
#define SRA_INTERRUPTED(reg) (((SRA_t*)(reg))->interrupted)
#elif defined(MODE_PCAT)
unsigned char none;
#define SRA_RESET_DONE(reg) 1
#define SRA_INTERRUPTED(reg) 0
#endif
};
// IDX:1, R - SRB
#define REG_SRB(base) ((base) + 0x01)
#define SRB(reg) ((SRB_t*)(reg))
typedef struct status_register_b SRB_t;
struct status_register_b
{
#if defined(MODE_PS2)
unsigned long motor:2;
unsigned long we:1;
unsigned long rddata_toggle:1;
unsigned long wrdata_toggle:1;
unsigned long drive_sel0:1;
unsigned long reserved:2; //! 11
#define SRB_RESET_DONE(reg) (!SRB(reg)->rddata_toggle && !SRB(reg)->wrdata_toggle)
#elif defined(MODE_MODEL30)
unsigned long b_ds_high:2;
unsigned long we_ff:1;
unsigned long rddata_ff:1;
unsigned long wrdata_ff:1;
unsigned long b_ds_low:2;
unsigned long b_drv2:1;
#define SRB_RESET_DONE(reg) (!SRB(reg)->we_ff && !SRB(reg)->rddata_ff && !SRB(reg)->wrdata_ff)
#elif defined(MODE_PCAT)
unsigned char none;
#define SRB_RESET_DONE(reg) 1
#endif
};
// IDX:2, RW - DOR
#define REG_DOR(base) ((base) + 0x02)
enum drive_activation_values
{
DRIVE0 = 0x1C,
DRIVE1 = 0x2D,
DRIVE2 = 0x4E,
DRIVE3 = 0x8F,
};
typedef struct digital_output_register DOR_t;
struct digital_output_register
{
unsigned long drive:2;
unsigned long b_reset:1;
unsigned long b_dma_gate:1;
unsigned long motor:4;
};
enum dma_state {
DMA = 0x01,
NONDMA = 0x00,
};
#define DOR_RESET(reg) do { \
DOR_t *dor = (DOR_t*)(reg); \
dor->b_reset = 0; \
dor->drive = 0; \
dor->b_dma_gate = 1; \
dor->motor = 0; \
} while (0)
#define DOR_ENABLE(reg, drv, dma) do { \
DOR_t *dor = (DOR_t*)(reg); \
dor->b_reset = 1; \
dor->drive = (drv); \
dor->b_dma_gate = dma; \
dor->motor = 0x01 << (drv); \
} while (0)
// IDX:3, RW - TDR
#define REG_TDR(base) ((base) + 0x03)
typedef struct tape_drive_register TDR_t;
struct tape_drive_register
{
unsigned long tape_sel:2;
unsigned long none:6;
};
// IDX:4, W - DSR
#define REG_DSR(base) ((base) + 0x04)
enum precompensation_delays
{
DELAY_DISABLED = 0x07,
DELAY_41_67ns = 0x01, // -> 1Mbps
DELAY_83_34ns = 0x02,
DELAY_125ns = 0x03, // -> 500Kbps, 300Kbps, 250Kbps
DELAY_166_67ns = 0x04,
DELAY_208_33ns = 0x05,
DELAY_250ns = 0x06,
DELAY_DEFAULT = 0x0,
};
enum data_rates
{
DRATE_1Mbps = 0x03, // -> 41.67ns
DRATE_500Kbps = 0x00, // -> 125ns
DRATE_300Kbps = 0x01, // -> 125ns
DRATE_250Kbps = 0x02, // -> 125ns
};
typedef struct datarate_select_register DSR_t;
struct datarate_select_register
{
unsigned long dratesel:2;
unsigned long precomp:3;
unsigned long zeroed:1;
unsigned long power_down:1;
unsigned long sw_reset:1;
};
#define SELECT_DRATE(reg, rate) do { \
DSR_t *dsr = (DSR_t*)(reg); \
dsr->dratesel = rate; \
switch (dsr->dratesel) { \
case DRATE_1Mbps: \
dsr->precomp = DELAY_41_67ns; \
break; \
case DRATE_500Kbps: \
dsr->precomp = DELAY_125ns; \
break; \
case DRATE_300Kbps: \
dsr->precomp = DELAY_125ns; \
break; \
case DRATE_250Kbps: \
dsr->precomp = DELAY_125ns; \
break; \
default: \
break; \
} \
} while (0)
// Auto-toggle reset_pin
#define DSR_RESET(reg) do { \
DSR_t *dsr = (DSR_t*)(reg); \
dsr->sw_reset = 1; \
dsr->power_down = 1; \
} while (0)
// IDX:4, R - MSR
#define REG_MSR(base) ((base) + 0x04)
enum drive_letter
{
DRIVE_A = 0x00,
DRIVE_B = 0x01,
DRIVE_C = 0x02,
DRIVE_D = 0x03,
};
enum dir_of_data
{
UNDEFINED = 0x00,
READ_REQUIRED = 0x01,
WRITE_REQUIRED = 0x02,
};
typedef struct main_status_register MSR_t;
struct main_status_register
{
unsigned long drive_busy:4;
unsigned long cmd_busy:1;
unsigned long non_dma:1;// 1 == durring execution phase
unsigned long DIO:1; // 1 == read is required, otherwise(0) write is required
unsigned long RQM:1; // 1 == host can transfer data, otherwise 0
};
#define MSR(reg) ((MSR_t*)(reg))
#define DIR_OF_DATA(reg) (MSR(reg)->RQM ? (MSR(reg)->DIO ? READ_REQUIRED : WRITE_REQUIRED) : UNDEFINED)
#define IN_RESULT_PHASE(reg) (MSR(reg)->cmd_busy)
#define IN_SEEK_PORTION(reg) (MSR(reg)->drive_busy)
#define REG_FIFO(base) ((base) + 0x05)
// IDX:5, RW - FIFO
// NO DATA STRUCTURE
// IDX:6, RESERVED
// IDX:7, R - DIR
#define REG_DIR(base) ((base) + 0x07)
typedef struct digital_input_register DIR_t;
struct digital_input_register
{
#if defined(MODE_PCAT)
unsigned long none:7;
unsigned long disk_change:1;
#define DISK_CHANGED(reg) (((DIR_t*)(reg))->disk_change)
#elif defined(MODE_PS2)
unsigned long b_high_dens:1; // 500 Kbps, 1 Mbps --> set 1
unsigned long drate_sel:2;
unsigned long reserved:4; // set 1
unsigned long disk_change:1;
#define DISK_CHANGED(reg) (((DIR_t*)(reg))->disk_change)
#elif defined(MODE_MODEL30)
unsigned long drate_sel:2;
unsigned long no_prec:1;
unsigned long b_dma_gate:1;
unsigned long reserved:3; // set 0
unsigned long b_disk_change:1;
#define DISK_CHANGED(reg) (!((DIR_t*)(reg))->disk_change)
#else
unsigned char none;
#endif
};
// IDX:7, W - CCR
#define REG_CCR(base) ((base) + 0x07)
typedef struct configuration_control_register CCR_t;
struct configuration_control_register
{
#if defined(MODE_PCAT) || defined(MODE_PS2)
unsigned long drate_sel:2;
unsigned long none:6;
#elif defined(MODE_MODEL30)
unsigned long drate_sel:2;
unsigned long no_prec:1;
unsigned long none:5;
#endif
};
#define SET_DRATE(reg, drate) (((CCR_t*)(reg))->drate_sel = (drate))
enum fdc_dma_dir_t
{
FDC_DMA_READ = 1,
FDC_DMA_WRITE = 2,
};
enum command_set
{
CMD_READ_DATA = 0x06,
CMD_READ_DELETED_DATA = 0x0C,
CMD_WRITE_DATA = 0x05,
CMD_WRITE_DELETED_DATA = 0x09,
CMD_READ_TRACK = 0x02,
CMD_VERIFY = 0x16,
CMD_VERSION = 0x10,
CMD_FORMAT_TRACK = 0x0D,
CMD_SCAN_EQUAL = 0x11,
CMD_SCAN_LOW_OR_EQUAL = 0x19,
CMD_SCAN_HIGH_OR_EQUAL = 0x1D,
CMD_RECALIBRATE = 0x07,
CMD_SENSE_INTERRUPT = 0x08,
CMD_SPECIFY = 0x03,
CMD_SEND_DRIVE_STATUS = 0x04,
CMD_SEEK = 0x0F,
CMD_CONFIGURE = 0x13,
CMD_RELATIVE_SEEK = 0x8F,
CMD_DUMPREG = 0x0E,
CMD_READ_ID = 0x0A,
CMD_PERPENDICULAR_MODE = 0x12,
CMD_LOCK = 0x24,
CMD_EXT_MULTITRACK = 0x80,
CMD_EXT_DENSITY = 0x40,
CMD_EXT_SKIP = 0x20,
};
extern void fdc_select_ctrl(enum base_address bsr);
extern void fdc_select_drive(enum drive_letter drv);
extern enum base_address fdc_ctrl(void);
extern enum drive_letter fdc_drive(void);
extern void fdc_reset(void);
extern int fdc_read_deleted_sector(int c, int h, int r);
extern int fdc_read_sector(int c, int h, int r);
extern int fdc_sense_interrupt(unsigned char *st0, unsigned char *cyl);
extern int fdc_write_sector(int c, int h, int r);
extern int fdc_write_deleted_sector(int c, int h, int r);
extern int fdc_read_track(int c, int h, int r);
extern int fdc_verify(int c, int h, int r);
extern int fdc_version(unsigned char *ver);
extern int fdc_read(unsigned long block, void *buf, int size);
extern int fdc_write(unsigned long block, void *buf, int size);
extern int fdc_seek(unsigned long block);
#endif
//! End of a file
Code: Select all
#include <ncloader.h>
#include <port.h>
#include <fdc.h>
#include <libc.h>
#include <resource_str.h>
#include <dma.h>
#include <isr.h>
#include <list.h>
#include <lock.h>
#include <kthread.h>
static enum base_address g_ctrl = FDC_PRIMARY;
static enum drive_letter g_drv = DRIVE_A;
//static void send_cmd_read_data(unsigned char cyl, int head, int sec);
inline static void
fdc_dma_init(enum fdc_dma_dir_t dir, unsigned long address, int count)
{
unsigned long mode;
switch (dir) {
case FDC_DMA_READ:
mode = DMA_MODE_SINGLE|DMA_CH2|DMA_MODE_TX_WRITE;
break;
case FDC_DMA_WRITE:
mode = DMA_MODE_SINGLE|DMA_CH2|DMA_MODE_TX_READ;
break;
default:
PANIC("Invalid dir");
return;
}
DbgPrint("dma_init %p %d\n", address, count);
dma_init(DMA_CH2, mode, address, count);
}
void fdc_select_ctrl(enum base_address bsr)
{
g_ctrl = bsr;
}
void fdc_select_drive(enum drive_letter drv)
{
g_drv = drv;
}
enum base_address fdc_ctrl(void)
{
return g_ctrl;
}
enum drive_letter fdc_drive(void)
{
return g_drv;
}
inline static int send_byte(unsigned char byte)
{
unsigned char reg;
reg = inb(REG_MSR(g_ctrl));
if (DIR_OF_DATA(®) != WRITE_REQUIRED) {
DbgPrint("Impossible to send a command\n");
return -1;
}
outb(REG_FIFO(g_ctrl), byte);
return 0;
}
inline static int read_byte(unsigned char *byte)
{
unsigned char reg;
reg = inb(REG_MSR(g_ctrl));
if (DIR_OF_DATA(®) != READ_REQUIRED) {
DbgPrint("Not read states\n");
return -1;
}
*byte = inb(REG_FIFO(g_ctrl));
return 0;
}
inline static int calibrate(void)
{
unsigned char st0;
unsigned char cyl;
if (send_byte(CMD_RECALIBRATE) < 0) {
int ret;
unsigned char byte;
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(g_drv) < 0) {
int ret;
unsigned char byte;
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
wait_irq(WAIT_IRQ_FLOPPY);
if (fdc_sense_interrupt(&st0, &cyl) < 0) {
DbgPrint("Failed to sense the interrupt\n");
return -1;
}
return cyl ? -1 : 0;
}
inline static int fdc_specify(void)
{
int srt = 3; // 3 ms
int hut = 240; // 240 ms
int hlt = 16; // 16 ms
if (send_byte(CMD_SPECIFY) < 0) {
int ret;
unsigned char byte;
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
// TODO: set srt/hut/hlt
if (send_byte(((srt & 0x0f) << 4) | (hut & 0xf)) < 0) {
int ret;
unsigned char byte;
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte((hlt << 1) | DMA) < 0) {
int ret;
unsigned char byte;
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
return 0;
}
int fdc_read_deleted_sector(int c, int h, int r)
{
unsigned char byte;
int ret;
if (send_byte(CMD_READ_DELETED_DATA | CMD_EXT_MULTITRACK | CMD_EXT_DENSITY | CMD_EXT_SKIP) < 0)
{
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte((h << 2) | g_drv) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(c) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(h) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(r) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(SECTOR_512) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(80) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(27) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(0xFF) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
wait_irq(WAIT_IRQ_FLOPPY);
if (read_byte(&byte) < 0) {
return -1;
}; // ST0
if (read_byte(&byte) < 0) {
return -1;
}; // ST1
if (read_byte(&byte) < 0) {
return -1;
}; // ST2
if (read_byte(&byte) < 0) {
return -1;
}; // C
if (read_byte(&byte) < 0) {
return -1;
}; // H
if (read_byte(&byte) < 0) {
return -1;
}; // R
if (read_byte(&byte) < 0) {
return -1;
}; // N
return 0;
}
int fdc_read_sector(int c, int h, int r)
{
unsigned char byte;
int ret;
if (send_byte(CMD_READ_DATA | CMD_EXT_MULTITRACK | CMD_EXT_DENSITY | CMD_EXT_SKIP) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte((h << 2) | g_drv) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(c) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(h) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(r) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(SECTOR_512) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(80) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(27) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(0xFF) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
wait_irq(WAIT_IRQ_FLOPPY);
if (read_byte(&byte) < 0) {
return -1;
}; // ST0
if (read_byte(&byte) < 0) {
return -1;
}; // ST1
if (read_byte(&byte) < 0) {
return -1;
}; // ST2
if (read_byte(&byte) < 0) {
return -1;
}; // C
if (read_byte(&byte) < 0) {
return -1;
}; // H
if (read_byte(&byte) < 0) {
return -1;
}; // R
if (read_byte(&byte) < 0) {
return -1;
}; // N
return 0;
}
int fdc_sense_interrupt(unsigned char *st0, unsigned char *cyl)
{
if (send_byte(CMD_SENSE_INTERRUPT) < 0) {
int ret;
unsigned char byte;
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (read_byte(st0) < 0) {
return -1;
}
if (*st0 == 0x80) {
DbgPrint("Invalid command\n");
return -1;
}
if (read_byte(cyl) < 0) {
return -1;
}
return 0;
}
int fdc_write_sector(int c, int h, int r)
{
int ret;
unsigned char byte;
if (send_byte(CMD_WRITE_DATA | CMD_EXT_MULTITRACK | CMD_EXT_DENSITY) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte((h<<2) | g_drv) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(c) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(h) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(r) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(SECTOR_512) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(80) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(27) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(0xFF) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
wait_irq(WAIT_IRQ_FLOPPY);
if (read_byte(&byte) < 0) {
return -1;
}; // ST0
if (read_byte(&byte) < 0) {
return -1;
}; // ST1
if (read_byte(&byte) < 0) {
return -1;
}; // ST2
if (read_byte(&byte) < 0) {
return -1;
}; // C
if (read_byte(&byte) < 0) {
return -1;
}; // H
if (read_byte(&byte) < 0) {
return -1;
}; // R
if (read_byte(&byte) < 0) {
return -1;
}; // N
return 0;
}
int fdc_write_deleted_sector(int c, int h, int r)
{
int ret;
unsigned char byte;
if (send_byte(CMD_WRITE_DELETED_DATA | CMD_EXT_MULTITRACK | CMD_EXT_DENSITY) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte((h<<2) | g_drv) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(c) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(h) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(r) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(SECTOR_512) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(80) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(27) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(0xFF) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
wait_irq(WAIT_IRQ_FLOPPY);
if (read_byte(&byte) < 0) {
return -1;
}; // ST0
if (read_byte(&byte) < 0) {
return -1;
}; // ST1
if (read_byte(&byte) < 0) {
return -1;
}; // ST2
if (read_byte(&byte) < 0) {
return -1;
}; // C
if (read_byte(&byte) < 0) {
return -1;
}; // H
if (read_byte(&byte) < 0) {
return -1;
}; // R
if (read_byte(&byte) < 0) {
return -1;
}; // N
return 0;
}
int fdc_read_track(int c, int h, int r)
{
int ret;
unsigned char byte;
if (send_byte(CMD_READ_TRACK | CMD_EXT_DENSITY) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte((h<<2) | g_drv) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(c) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(h) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(r) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(SECTOR_512) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(80) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(27) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(0xFF) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
wait_irq(WAIT_IRQ_FLOPPY);
if (read_byte(&byte) < 0) {
return -1;
}; // ST0
if (read_byte(&byte) < 0) {
return -1;
}; // ST1
if (read_byte(&byte) < 0) {
return -1;
}; // ST2
if (read_byte(&byte) < 0) {
return -1;
}; // C
if (read_byte(&byte) < 0) {
return -1;
}; // H
if (read_byte(&byte) < 0) {
return -1;
}; // R
if (read_byte(&byte) < 0) {
return -1;
}; // N
return 0;
}
int fdc_verify(int c, int h, int r)
{
int ret;
unsigned char byte;
if (send_byte(CMD_VERIFY | CMD_EXT_DENSITY | CMD_EXT_MULTITRACK | CMD_EXT_SKIP) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte((h<<2) | g_drv) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(c) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(h) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(r) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(SECTOR_512) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(80) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(27) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(0xFF) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
wait_irq(WAIT_IRQ_FLOPPY);
if (read_byte(&byte) < 0) {
return -1;
}; // ST0
if (read_byte(&byte) < 0) {
return -1;
}; // ST1
if (read_byte(&byte) < 0) {
return -1;
}; // ST2
if (read_byte(&byte) < 0) {
return -1;
}; // C
if (read_byte(&byte) < 0) {
return -1;
}; // H
if (read_byte(&byte) < 0) {
return -1;
}; // R
if (read_byte(&byte) < 0) {
return -1;
}; // N
return 0;
}
int fdc_version(unsigned char *ver)
{
int ret;
unsigned char byte;
if (send_byte(CMD_VERSION) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (read_byte(&byte) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
return 0;
}
void fdc_reset(void)
{
unsigned char reg;
unsigned char st0;
unsigned char cyl;
int i;
DOR_RESET(®);
outb(REG_DOR(g_ctrl), reg);
DOR_ENABLE(®, g_drv, DMA);
outb(REG_DOR(g_ctrl), reg);
outb(REG_CCR(g_ctrl), DRATE_500Kbps);
wait_irq(WAIT_IRQ_FLOPPY);
// for DRIVE_A, DRIVE_B, DRIVE_C, DRIVE_D
for (i = 0; i < 4; i ++) {
if (fdc_sense_interrupt(&st0, &cyl) < 0) {
PANIC("Faield to sense the interrupt\n");
return;
}
}
// NOTE:
// IF PARAMTERS DIFFERENT FROM DEFALT
// - CONFIGURE COMMAND
// ELSE ..
if (fdc_specify() < 0) {
PANIC("Failed to specify");
return;
}
if (calibrate() < 0) {
PANIC("Failed to do calibration\n");
return;
}
/*
unsigned char sra;
unsigned char srb;
do {
sra = inb(REG_SRA(g_ctrl));
srb = inb(REG_SRB(g_ctrl));
DbgPrint("SRA = %d, SRB = %d\f", sra, srb);
} while (!SRA_RESET_DONE(&sra) || !SRB_RESET_DONE(&srb));
*/
}
static inline int seek(int cyl, int head)
{
int ret;
unsigned char byte;
if (send_byte(CMD_SEEK) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte((head << 2) | g_drv) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
if (send_byte(cyl) < 0) {
ret = read_byte(&byte);
if (ret < 0 || byte == 0x80) {
DbgPrint("Failed to read\n");
}
return -1;
}
wait_irq(WAIT_IRQ_FLOPPY);
return 0;
}
int fdc_read(unsigned long block, void *buf, int size)
{
int c;
int h;
int s;
LBA_TO_CHS(block, c, h, s);
seek(c, h);
fdc_dma_init(FDC_DMA_READ, (unsigned long)buf, size);
fdc_read_sector(c, h, s);
return 0;
}
int fdc_write(unsigned long block, void *buf, int size)
{
int c;
int h;
int s;
LBA_TO_CHS(block, c, h, s);
seek(c, h);
fdc_dma_init(FDC_DMA_WRITE, (unsigned long)buf, size);
fdc_write_sector(c, h, s);
return 0;
}
int fdc_seek(unsigned long block)
{
int c;
int h;
int s;
LBA_TO_CHS(block, c, h, s);
seek(c, h);
return 0;
}
//! End of a file