Browse Source

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 <parai@foxmail.com>
parai 7 years ago
parent
commit
bafa3a8eb3

+ 51 - 74
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
- */
-
-/**
- * @addtogroup QEMU
+ * 2009-01-05     Bernard      the first version
  */
 
-/*@{*/
-
 #include <rtthread.h>
 
-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 <dfs_fs.h>
+#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)
-    {
-        /* led1 on */
-#ifndef RT_USING_FINSH
-        rt_kprintf("led1 on,count : %d\r\n",count);
+#ifdef RT_USING_DFS_ELMFAT
+	/* initialize the elm chan FatFS file system*/
+	elm_init();
 #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");
 #endif
-        rt_thread_delay(RT_TICK_PER_SECOND / 2);
-    }
 }
-
-ALIGN(RT_ALIGN_SIZE)
-static char thread_led2_stack[1024];
-struct rt_thread thread_led2;
-void rt_thread_entry_led2(void *parameter)
+void rt_init_thread_entry(void *parameter)
 {
-    unsigned int count=0;
+    components_init();
 
-    while (1)
+    /* File system Initialization */
+#ifdef RT_USING_DFS
     {
-        /* led2 on */
-#ifndef RT_USING_FINSH
-        rt_kprintf("led2 on,count : %d\r\n",count);
-#endif
-        count ++;
-        rt_thread_delay(RT_TICK_PER_SECOND);
 
-        /* led2 off */
-#ifndef RT_USING_FINSH
-        rt_kprintf("led2 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);
     }
+#endif
 }
 
-/**
- * This function will be invoked to initalize user application when system
- * startup.
- */
-
-int rt_application_init(void)
+int rt_application_init()
 {
-    // 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);
+    rt_thread_t tid;
 
-    // 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);
+    tid = rt_thread_create("init",
+                           rt_init_thread_entry, RT_NULL,
+                           2048, RT_THREAD_PRIORITY_MAX / 3, 20);
+
+    if (tid != RT_NULL)
+        rt_thread_startup(tid);
 
     return 0;
 }
-
-/*@}*/

+ 187 - 0
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
+

+ 360 - 0
bsp/x86/drivers/floppy.c

@@ -0,0 +1,360 @@
+
+#include <rtthread.h>
+#include <rthw.h>
+
+#include <bsp.h>
+
+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,&sector);
+
+    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);
+
+}

+ 71 - 0
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

+ 10 - 1
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) */

+ 35 - 0
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