Sfoglia il codice sorgente

Merge pull request #807 from parai/master

[BSP] x86: add floppy driver
Bernard Xiong 7 anni fa
parent
commit
f975ef5146

+ 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