Merge pull request #807 from parai/master

[BSP] x86: add floppy driver
This commit is contained in:
Bernard Xiong authored and GitHub committed 2017-08-18 10:55:22 +08:00
commit f975ef5146
6 files changed
+718 -79

No files matched your search

+55 -78
View File
@@ -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 <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)
#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;
}
/*@}*/
+187
View File
@@ -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
File diff suppressed because it is too large. Load diff
+71
View File
@@ -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
View File
@@ -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
View File
@@ -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