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>
This commit is contained in:
parai committed 2017-08-17 23:34:09 +08:00
1 parent 08d13e033c
commit bafa3a8eb3
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