From bafa3a8eb39e04b36e5c4eb3e8eac6340b0ec94f Mon Sep 17 00:00:00 2001 From: parai Date: Thu, 17 Aug 2017 23:31:52 +0800 Subject: [PATCH] x86: add floppy driver currently only read okay, write is not supported, this is enough for me to study ELF, but the floppy is really small, now only about 400kb space free showed by df("/"). Signed-off-by: parai --- bsp/x86/applications/application.c | 133 +++++------ bsp/x86/drivers/dma.h | 187 +++++++++++++++ bsp/x86/drivers/floppy.c | 360 +++++++++++++++++++++++++++++ bsp/x86/drivers/floppy.h | 71 ++++++ bsp/x86/drivers/include/bsp.h | 11 +- bsp/x86/drivers/include/i386.h | 35 +++ 6 files changed, 718 insertions(+), 79 deletions(-) create mode 100644 bsp/x86/drivers/dma.h create mode 100644 bsp/x86/drivers/floppy.c create mode 100644 bsp/x86/drivers/floppy.h diff --git a/bsp/x86/applications/application.c b/bsp/x86/applications/application.c index 0883216976..3a2f6c9b82 100644 --- a/bsp/x86/applications/application.c +++ b/bsp/x86/applications/application.c @@ -1,100 +1,77 @@ -/** File : application.c +/* + * File : application.c * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2012, RT-Thread Develop Team + * COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://openlab.rt-thread.com/license/LICENSE + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - -* Change Logs: + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: * Date Author Notes - * 2006-09-15 QiuYi the first version + * 2009-01-05 Bernard the first version */ -/** - * @addtogroup QEMU - */ - -/*@{*/ - #include -ALIGN(RT_ALIGN_SIZE) -static char thread_led1_stack[1024]; -struct rt_thread thread_led1; -static void rt_thread_entry_led1(void *parameter) +#ifdef RT_USING_DFS +#include +#include "floppy.h" +#endif + +/* components initialization for simulator */ +void components_init(void) { - unsigned int count=0; +#ifdef RT_USING_DFS + rt_floppy_init(); + /* initialize the device file system */ + dfs_init(); - while (1) +#ifdef RT_USING_DFS_ELMFAT + /* initialize the elm chan FatFS file system*/ + elm_init(); +#endif +#endif +} +void rt_init_thread_entry(void *parameter) +{ + components_init(); + + /* File system Initialization */ +#ifdef RT_USING_DFS { - /* led1 on */ -#ifndef RT_USING_FINSH - rt_kprintf("led1 on,count : %d\r\n",count); -#endif - count ++; - /* sleep 0.5 second and switch to other thread */ - rt_thread_delay(RT_TICK_PER_SECOND / 2); - /* led1 off */ -#ifndef RT_USING_FINSH - rt_kprintf("led1 off\r\n"); +#ifdef RT_USING_DFS_ELMFAT + /* mount sd card fatfs as root directory */ + if (dfs_mount("floppy", "/", "elm", 0, 0) == 0) + rt_kprintf("fatfs initialized!\n"); + else + rt_kprintf("fatfs initialization failed!\n"); #endif - rt_thread_delay(RT_TICK_PER_SECOND / 2); } +#endif } -ALIGN(RT_ALIGN_SIZE) -static char thread_led2_stack[1024]; -struct rt_thread thread_led2; -void rt_thread_entry_led2(void *parameter) +int rt_application_init() { - unsigned int count=0; + rt_thread_t tid; - while (1) - { - /* led2 on */ -#ifndef RT_USING_FINSH - rt_kprintf("led2 on,count : %d\r\n",count); -#endif - count ++; - rt_thread_delay(RT_TICK_PER_SECOND); + tid = rt_thread_create("init", + rt_init_thread_entry, RT_NULL, + 2048, RT_THREAD_PRIORITY_MAX / 3, 20); - /* led2 off */ -#ifndef RT_USING_FINSH - rt_kprintf("led2 off\r\n"); -#endif - rt_thread_delay(RT_TICK_PER_SECOND); - } -} - -/** - * This function will be invoked to initalize user application when system - * startup. - */ - -int rt_application_init(void) -{ - // init led1 thread - rt_thread_init(&thread_led1, - "led1", - rt_thread_entry_led1, - RT_NULL, - &thread_led1_stack[0], - sizeof(thread_led1_stack),11,5); - rt_thread_startup(&thread_led1); - - // init led2 thread - rt_thread_init(&thread_led2, - "led2", - rt_thread_entry_led2, - RT_NULL, - &thread_led2_stack[0], - sizeof(thread_led2_stack),12,5); - rt_thread_startup(&thread_led2); + if (tid != RT_NULL) + rt_thread_startup(tid); return 0; } - -/*@}*/ diff --git a/bsp/x86/drivers/dma.h b/bsp/x86/drivers/dma.h new file mode 100644 index 0000000000..f1a8563cb1 --- /dev/null +++ b/bsp/x86/drivers/dma.h @@ -0,0 +1,187 @@ +#ifndef _DMA_H +#define _DMA_H + + +#define MAX_DMA_CHANNELS 8 + +/* 8237 DMA controllers */ +#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ +#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ + +/* DMA controller registers */ +#define DMA1_CMD_REG 0x08 /* command register (w) */ +#define DMA1_STAT_REG 0x08 /* status register (r) */ +#define DMA1_REQ_REG 0x09 /* request register (w) */ +#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */ +#define DMA1_MODE_REG 0x0B /* mode register (w) */ +#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */ +#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */ +#define DMA1_RESET_REG 0x0D /* Master Clear (w) */ +#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ +#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ + +#define DMA2_CMD_REG 0xD0 /* command register (w) */ +#define DMA2_STAT_REG 0xD0 /* status register (r) */ +#define DMA2_REQ_REG 0xD2 /* request register (w) */ +#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */ +#define DMA2_MODE_REG 0xD6 /* mode register (w) */ +#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */ +#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */ +#define DMA2_RESET_REG 0xDA /* Master Clear (w) */ +#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ +#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ + +#define DMA_ADDR_0 0x00 /* DMA address registers */ +#define DMA_ADDR_1 0x02 +#define DMA_ADDR_2 0x04 +#define DMA_ADDR_3 0x06 +#define DMA_ADDR_4 0xC0 +#define DMA_ADDR_5 0xC4 +#define DMA_ADDR_6 0xC8 +#define DMA_ADDR_7 0xCC + +#define DMA_CNT_0 0x01 /* DMA count registers */ +#define DMA_CNT_1 0x03 +#define DMA_CNT_2 0x05 +#define DMA_CNT_3 0x07 +#define DMA_CNT_4 0xC2 +#define DMA_CNT_5 0xC6 +#define DMA_CNT_6 0xCA +#define DMA_CNT_7 0xCE + +#define DMA_PAGE_0 0x87 /* DMA page registers */ +#define DMA_PAGE_1 0x83 +#define DMA_PAGE_2 0x81 +#define DMA_PAGE_3 0x82 +#define DMA_PAGE_5 0x8B +#define DMA_PAGE_6 0x89 +#define DMA_PAGE_7 0x8A + +#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ +#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ +#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ + +/* + * 启用指定的DMA通道 + */ +static __inline__ void EnableDma(unsigned int dmanr) +{ + if (dmanr<=3) + OUTB(dmanr, DMA1_MASK_REG); + else + OUTB(dmanr & 3, DMA2_MASK_REG); +} + +/* + * 禁用指定的DMA通道 + */ +static __inline__ void DisableDma(unsigned int dmanr) +{ + if (dmanr<=3) + OUTB(dmanr | 4, DMA1_MASK_REG); + else + OUTB((dmanr & 3) | 4, DMA2_MASK_REG); +} + +/* + * 清空DMA 晶体计数器 + */ +static __inline__ void ClearDmaFF(unsigned int dmanr) +{ + if (dmanr<=3) + OUTB(0, DMA1_CLEAR_FF_REG); + else + OUTB(0, DMA2_CLEAR_FF_REG); +} + +/* + * 清空DMA 晶体计数器 + */ +static __inline__ void SetDmaMode(unsigned int dmanr, char mode) +{ + if (dmanr<=3) + OUTB(mode | dmanr, DMA1_MODE_REG); + else + OUTB(mode | (dmanr&3), DMA2_MODE_REG); +} + +/* + * 设定DMA 页面寄存器 + */ +static __inline__ void SetDmaPage(unsigned int dmanr, char pagenr) +{ + switch(dmanr) { + case 0: + OUTB(pagenr, DMA_PAGE_0); + break; + case 1: + OUTB(pagenr, DMA_PAGE_1); + break; + case 2: + OUTB(pagenr, DMA_PAGE_2); + break; + case 3: + OUTB(pagenr, DMA_PAGE_3); + break; + case 5: + OUTB(pagenr & 0xfe, DMA_PAGE_5); + break; + case 6: + OUTB(pagenr & 0xfe, DMA_PAGE_6); + break; + case 7: + OUTB(pagenr & 0xfe, DMA_PAGE_7); + break; + } +} + + +/* + * 设定DMA 传输高速缓冲区地址 + */ +static __inline__ void SetDmaAddr(unsigned int dmanr, unsigned int a) +{ + SetDmaPage(dmanr, a>>16); + if (dmanr <= 3) { + OUTB( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); + OUTB( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); + } else { + OUTB( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + OUTB( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + } +} + + +/* + * 设定DMA 传输块数 + */ +static __inline__ void SetDmaCount(unsigned int dmanr, unsigned int count) +{ + count--; + if (dmanr <= 3) { + OUTB( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + OUTB( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + } else { + OUTB( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + OUTB( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + } +} + + +/* + * 获得DMA 传输剩余块数 + */ +static __inline__ int GetDmaResidue(unsigned int dmanr) +{ + unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE + : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE; + + /* using short to get 16-bit wrap around */ + unsigned short count; + count = 1 + inb(io_port); + count += inb(io_port) << 8; + return (dmanr<=3)? count : (count<<1); +} + +#endif + diff --git a/bsp/x86/drivers/floppy.c b/bsp/x86/drivers/floppy.c new file mode 100644 index 0000000000..058bf1b941 --- /dev/null +++ b/bsp/x86/drivers/floppy.c @@ -0,0 +1,360 @@ + +#include +#include + +#include + +typedef rt_uint8_t u8; +typedef rt_uint16_t u16; +typedef rt_uint32_t u32; + +typedef rt_int8_t s8; +typedef rt_int16_t s16; +typedef rt_int32_t s32; + +#define OUTB(v,p) outb(p,v) + +#include "floppy.h" +#include "dma.h" + +#define NULL RT_NULL +#define SECTOR_SIZE 512 +#define panic(str,...) do { rt_kprintf("panic::" str,##__VA_ARGS__); while(1); } while(0) + +#define _local_irq_save(level) level = rt_hw_interrupt_disable() +#define _local_irq_restore(level) rt_hw_interrupt_enable(level) + +static u8 floppy_buffer[512]; /* 软盘高速缓冲区地址指针 */ + +#define MAX_REPLIES 7 +static u8 floppy_reply_buffer[MAX_REPLIES]; /* 软驱回应缓冲区 */ +#define ST0 (floppy_reply_buffer[0]) /* 软驱回应0号字节 */ +#define ST1 (floppy_reply_buffer[1]) /* 软驱回应1号字节 */ +#define ST2 (floppy_reply_buffer[2]) /* 软驱回应2号字节 */ +#define ST3 (floppy_reply_buffer[3]) /* 软驱回应3号字节 */ + + +static char *floppy_inc_name; /* 软驱型号名 */ +static char *floppy_type; +static u32 floppy_motor=0; /* 软驱马达状态字节 */ +static u32 floppy_size =0; +/**********************功能函数***************************/ +static void floppy_result(void); /* 获得软驱响应状态 */ +static u32 floppy_sendbyte(u32); /* 向软驱控制寄存器发送一个控制字节 */ +static u32 floppy_getbyte(void); /* 从软驱数据寄存器得到一个数据字节 */ +static u32 floppy_get_info(void); /* 得到软驱信息 */ +static void floppy_motorOn(void); /* 打开软驱马达 */ +static void floppy_motorOff(void); /* 关闭软驱马达 */ +static void floppy_setmode(void); /* 软驱模式设置 */ +static void block_to_hts(u32, u32*, u32*, u32*); /* 逻辑块转为磁盘头、磁道号和扇区号 */ +static void floppy_setupDMA(void); /* 设置软驱DMA通道 */ +static void floppy_read_cmd(u32 blk); /* 从软盘上读取指定的逻辑块到缓冲区 */ + + +void floppy_result(void) +{ + u8 stat, i,count; + i=0; + for(count=0; count<0xFF; count++) + { + stat = inb( FD_STATUS ) & (STATUS_READY|STATUS_DIR|STATUS_BUSY); //读取状态寄存器 + if (stat == STATUS_READY) + return; + if (stat == (STATUS_READY|STATUS_DIR|STATUS_BUSY)) + { + if(i>7) break; + floppy_reply_buffer[i++]=inb_p(FD_DATA); + } + } + + panic("Get floppy status times out !\n"); +} + +u32 floppy_sendbyte( u32 value ) +{ + u8 stat, i; + + for ( i = 0; i < 128; i++ ) { + stat = inb( FD_STATUS ) & (STATUS_READY|STATUS_DIR); //读取状态寄存器 + if ( stat == STATUS_READY ) + { + OUTB( value ,FD_DATA); //将参数写入数据寄存器 + return 1; + } + io_delay(); // 作一些延迟 + } + return 0; +} + + +u32 floppy_getbyte(void) +{ + u8 stat, i; + + for ( i = 0; i < 128; i++ ) { + stat = inb( FD_STATUS ) & (STATUS_READY|STATUS_DIR|STATUS_BUSY); //读取状态寄存器 + if (stat == STATUS_READY) + return -1; + if ( stat == 0xD0 ) + return inb(FD_DATA); + io_delay(); + } + return 0; +} + + +u32 floppy_get_info(void) +{ + u32 i; + u8 CmType, FdType; + + floppy_sendbyte(0x10); + i = floppy_getbyte(); + + switch (i) + { + case 0x80: floppy_inc_name = "NEC765A controller"; break; + case 0x90: floppy_inc_name = "NEC765B controller"; break; + default: floppy_inc_name = "Enhanced controller"; break; + } + + CmType = readcmos(0x10); //read floppy type from cmos + FdType = (CmType>>4) & 0x07; + + if ( FdType == 0 ) + panic("Floppy driver not found!"); + + switch( FdType ) + { + case 0x02: // 1.2MB + floppy_type = "1.2MB"; + floppy_size = 2458*512; + break; + + case 0x04: // 1.44MB 标准软盘 + floppy_type = "1.44MB"; + floppy_size = 2880*512; + break; + + case 0x05: // 2.88MB + floppy_type = "2.88MB"; + floppy_size = 2*2880*512; + break; + } + return 1; +} + + +void floppy_motorOn( void ) +{ + u32 eflags; + if (!floppy_motor) + { + _local_irq_save(eflags); + OUTB(28,FD_DOR); + floppy_motor = 1; + _local_irq_restore(eflags); + } + return; +} + + +void floppy_motorOff( void ) +{ + u32 eflags; + if (floppy_motor) + { + _local_irq_save(eflags); + OUTB(12,FD_DOR); + floppy_motor = 0; + _local_irq_restore(eflags); + + } + return; +} + + +void floppy_setmode(void) +{ + floppy_sendbyte (FD_SPECIFY); + floppy_sendbyte (0xcf); + floppy_sendbyte (0x06); + OUTB (0,FD_DCR); +} + + +void block_to_hts(u32 block, u32 *head, u32 *track, u32 *sector ) +{ + *head = ( block % ( 18 * 2 ) ) /18; + *track = block / ( 18 * 2 ); + *sector = block % 18 + 1; +} + + +void floppy_setupDMA(void) +{ + u32 eflags; + _local_irq_save(eflags); + DisableDma(2); + ClearDmaFF(2); + SetDmaMode(2,DMA_MODE_READ); + SetDmaAddr(2,(unsigned long)floppy_buffer); + SetDmaCount(2,512); + EnableDma(2); + _local_irq_restore(eflags); +} + + +void floppy_read_cmd(u32 blk) +{ + u32 head; + u32 track; + u32 sector; + + block_to_hts(blk,&head,&track,§or); + + floppy_motorOn(); + io_delay(); + + floppy_setupDMA(); + io_delay(); + + floppy_setmode(); + io_delay(); + floppy_sendbyte (FD_READ); //send read command + floppy_sendbyte (head*4 + 0); + floppy_sendbyte (track); /* Cylinder */ + floppy_sendbyte (head); /* Head */ + floppy_sendbyte (sector); /* Sector */ + floppy_sendbyte (2); /* 0=128, 1=256, 2=512, 3=1024, ... */ + floppy_sendbyte (18); + //floppy_sendbyte (sector+secs-1); /* Last sector in track:here are sectors count */ + floppy_sendbyte (0x1B); + floppy_sendbyte (0xff); + return; +} + +static struct rt_device devF; +static struct rt_mutex lock; +static struct rt_semaphore sem; + +/* RT-Thread device interface */ + +static rt_err_t rt_floppy_init_internal(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_err_t rt_floppy_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t rt_floppy_close(rt_device_t dev) +{ + return RT_EOK; +} + +/* position: block page address, not bytes address + * buffer: + * size : how many blocks + */ +static rt_size_t rt_floppy_read(rt_device_t device, rt_off_t position, void *buffer, rt_size_t size) +{ + rt_size_t doSize = size; + + rt_mutex_take(&lock, RT_WAITING_FOREVER); + while(size>0) + { + floppy_read_cmd(position); + + rt_sem_take(&sem, RT_WAITING_FOREVER); /* waiting isr sem forever */ + + floppy_result(); + io_delay(); + + if(ST1 != 0 || ST2 != 0) + { + panic("ST0 %d ST1 %d ST2 %d\n",ST0,ST1,ST2); + } + + rt_memcpy(buffer, floppy_buffer, 512); + + floppy_motorOff(); + io_delay(); + + position += 1; + size -= 1; + } + rt_mutex_release(&lock); + + return doSize; +} + +/* position: block page address, not bytes address + * buffer: + * size : how many blocks + */ +static rt_size_t rt_floppy_write(rt_device_t device, rt_off_t position, const void *buffer, rt_size_t size) +{ + rt_mutex_take(&lock, RT_WAITING_FOREVER); + panic("FIXME:I don't know how!\n"); + rt_mutex_release(&lock); + return size; +} + +static rt_err_t rt_floppy_control(rt_device_t dev, rt_uint8_t cmd, void *args) +{ + RT_ASSERT(dev != RT_NULL); + + if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) + { + struct rt_device_blk_geometry *geometry; + + geometry = (struct rt_device_blk_geometry *)args; + if (geometry == RT_NULL) return -RT_ERROR; + + geometry->bytes_per_sector = SECTOR_SIZE; + geometry->block_size = SECTOR_SIZE; + + geometry->sector_count = floppy_size / SECTOR_SIZE; + } + + return RT_EOK; +} + +static void rt_floppy_isr(int vector, void* param) +{ + (void)vector; + (void)param; + rt_sem_release(&sem); +} + +void rt_floppy_init(void) +{ + struct rt_device *device; + + rt_mutex_init(&lock,"fdlock", RT_IPC_FLAG_FIFO); + rt_sem_init(&sem, "fdsem", 0, RT_IPC_FLAG_FIFO); + + rt_hw_interrupt_install(FLOPPY_IRQ, rt_floppy_isr, RT_NULL, "floppy"); + rt_hw_interrupt_umask(FLOPPY_IRQ); + + floppy_get_info(); + rt_kprintf("Floppy Inc : %s Floppy Type : %s\n",floppy_inc_name,floppy_type); + + device = &(devF); + + device->type = RT_Device_Class_Block; + device->init = rt_floppy_init_internal; + device->open = rt_floppy_open; + device->close = rt_floppy_close; + device->read = rt_floppy_read; + device->write = rt_floppy_write; + device->control = rt_floppy_control; + device->user_data = NULL; + + rt_device_register(device, "floppy", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); + +} diff --git a/bsp/x86/drivers/floppy.h b/bsp/x86/drivers/floppy.h new file mode 100644 index 0000000000..f619508c43 --- /dev/null +++ b/bsp/x86/drivers/floppy.h @@ -0,0 +1,71 @@ +#ifndef _FLOPPY_H +#define _FLOPPY_H + +#define FD_STATUS 0x3f4 // 主状态寄存器端口。 +#define FD_DATA 0x3f5 // 数据端口。 +#define FD_DOR 0x3f2 // 数字输出寄存器(也称为数字控制寄存器)。 +#define FD_DIR 0x3f7 // 数字输入寄存器。 +#define FD_DCR 0x3f7 // 数据传输率控制寄存器。 + +/* 主状态寄存器各比特位的含义 */ + +#define STATUS_BUSYMASK 0x0F // 驱动器忙位(每位对应一个驱动器)。 +#define STATUS_BUSY 0x10 // 软盘控制器忙。 +#define STATUS_DMA 0x20 // 0 - 为DMA 数据传输模式,1 - 为非DMA 模式。 +#define STATUS_DIR 0x40 // 传输方向:0 - CPU .. fdc,1 - 相反。 +#define STATUS_READY 0x80 // 数据寄存器就绪位。 + + +/*状态字节0(ST0)各比特位的含义 */ + +#define ST0_DS 0x03 // 驱动器选择号(发生中断时驱动器号)。 +#define ST0_HA 0x04 // 磁头号。 +#define ST0_NR 0x08 // 磁盘驱动器未准备好。 +#define ST0_ECE 0x10 // 设备检测出错(零磁道校准出错)。 +#define ST0_SE 0x20 // 寻道或重新校正操作执行结束。 +#define ST0_INTR 0xC0 // 中断代码位(中断原因),00 - 命令正常结束; + // 01 - 命令异常结束;10 - 命令无效;11 - FDD 就绪状态改变。 + +/*状态字节1(ST1)各比特位的含义 */ + +#define ST1_MAM 0x01 // 未找到地址标志(ID AM)。 +#define ST1_WP 0x02 // 写保护。 +#define ST1_ND 0x04 // 未找到指定的扇区。 +#define ST1_OR 0x10 // 数据传输超时(DMA 控制器故障)。 +#define ST1_CRC 0x20 // CRC 检验出错。 +#define ST1_EOC 0x80 // 访问超过一个磁道上的最大扇区号。 + +/*状态字节2(ST2)各比特位的含义 */ + +#define ST2_MAM 0x01 // 未找到数据地址标志。 +#define ST2_BC 0x02 // 磁道坏。 +#define ST2_SNS 0x04 // 检索(扫描)条件不满足。 +#define ST2_SEH 0x08 // 检索条件满足。 +#define ST2_WC 0x10 // 磁道(柱面)号不符。 +#define ST2_CRC 0x20 // 数据场CRC 校验错。 +#define ST2_CM 0x40 // 读数据遇到删除标志。 + +/*状态字节3(ST3)各比特位的含义 */ + +#define ST3_HA 0x04 // 磁头号。 +#define ST3_TZ 0x10 // 零磁道信号。 +#define ST3_WP 0x40 // 写保护。 + + +/* 软盘命令码 */ + +#define FD_RECALIBRATE 0x07 // 重新校正(磁头退到零磁道)。 +#define FD_SEEK 0x0F // 磁头寻道。 +#define FD_READ 0xE6 // 读数据(MT 多磁道操作,MFM 格式,跳过删除数据)。 +#define FD_WRITE 0xC5 // 写数据(MT,MFM)。 +#define FD_SENSEI 0x08 // 检测中断状态。 +#define FD_SPECIFY 0x03 // 设定驱动器参数(步进速率、磁头卸载时间等)。 + + +/* DMA 命令 */ +#define DMA_READ 0x46 // DMA 读盘,DMA 方式字(送DMA 端口12,11)。 +#define DMA_WRITE 0x4A + +extern void rt_floppy_init(void); + +#endif diff --git a/bsp/x86/drivers/include/bsp.h b/bsp/x86/drivers/include/bsp.h index 908c721661..724f518c6e 100644 --- a/bsp/x86/drivers/include/bsp.h +++ b/bsp/x86/drivers/include/bsp.h @@ -74,7 +74,16 @@ extern "C" { #define INTTIMER0 0 #define INTKEYBOARD 1 #define INTUART0_RX 4 - +#define CLOCK_IRQ 0 +#define KEYBOARD_IRQ 1 +#define CASCADE_IRQ 2 /* cascade enable for 2nd AT controller */ +#define ETHER_IRQ 3 /* default ethernet interrupt vector */ +#define SECONDARY_IRQ 3 /* RS232 interrupt vector for port 2 */ +#define RS232_IRQ 4 /* RS232 interrupt vector for port 1 */ +#define XT_WINI_IRQ 5 /* xt winchester */ +#define FLOPPY_IRQ 6 /* floppy disk */ +#define PRINTER_IRQ 7 +#define AT_WINI_IRQ 14 /* at winchester */ /* I/O Addresses of the two 8259A programmable interrupt controllers */ #define IO_PIC1 0x20 /* Master(IRQs 0-7) */ #define IO_PIC2 0xa0 /* Slave(IRQs 8-15) */ diff --git a/bsp/x86/drivers/include/i386.h b/bsp/x86/drivers/include/i386.h index fe023d754a..68c854932b 100644 --- a/bsp/x86/drivers/include/i386.h +++ b/bsp/x86/drivers/include/i386.h @@ -11,6 +11,18 @@ static __inline unsigned char inb(int port) __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port)); return data; } +static __inline unsigned char inb_p(unsigned short port) +{ + unsigned char _v; + __asm__ __volatile__ ("inb %1, %0\n\t" + // "outb %0,$0x80\n\t" + // "outb %0,$0x80\n\t" + // "outb %0,$0x80\n\t" + "outb %0,$0x80" + :"=a" (_v) + :"d" ((unsigned short) port)); + return _v; +} static __inline unsigned short inw(int port) { @@ -39,11 +51,34 @@ static __inline void outb(int port, unsigned char data) __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port)); } + +static __inline void outb_p(char value, unsigned short port) +{ + __asm__ __volatile__ ("outb %0,%1\n\t" + "outb %0,$0x80" + ::"a" ((char) value),"d" ((unsigned short) port)); +} + static __inline void outw(int port, unsigned short data) { __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port)); } +static __inline unsigned char readcmos(int reg) +{ + outb(0x70,reg); + return (unsigned char) inb(0x71); +} + +#define io_delay() \ + __asm__ __volatile__ ("pushal \n\t"\ + "mov $0x3F6, %dx \n\t" \ + "inb %dx, %al \n\t" \ + "inb %dx, %al \n\t" \ + "inb %dx, %al \n\t" \ + "inb %dx, %al \n\t" \ + "popal") + /* Gate descriptors are slightly different*/ struct Gatedesc { unsigned gd_off_15_0 : 16; // low 16 bits of offset in segment