IDE驱动
This commit is contained in:
parent
7e471c20ba
commit
8da818145d
@ -1,60 +0,0 @@
|
|||||||
#include "../include/disk.h"
|
|
||||||
#include "../include/io.h"
|
|
||||||
|
|
||||||
void wait_disk_ready() {
|
|
||||||
while (1) {
|
|
||||||
int data = io_in8(0x1f7);
|
|
||||||
if ((data & 0x88) == 0x08) // 第3位为1表示硬盘控制器已准备好数据传输,第7位为1表示硬盘忙。
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void select_sector(int lba) {
|
|
||||||
io_out8(0x1f2, 1);
|
|
||||||
io_out8(0x1f3, lba);
|
|
||||||
io_out8(0x1f4, lba >> 8);
|
|
||||||
io_out8(0x1f5, lba >> 16);
|
|
||||||
io_out8(0x1f6, (((lba >> 24) & 0x0f) | 0xe0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_disk_one_sector(int lba, unsigned int memory_addrress) {
|
|
||||||
while (io_in8(0x1f7) & 0x80);
|
|
||||||
select_sector(lba);
|
|
||||||
io_out8(0x1f7, 0x20);
|
|
||||||
wait_disk_ready();
|
|
||||||
for (int i = 0; i < 256; i++) {
|
|
||||||
short data = (short) io_in16(0x1f0);
|
|
||||||
*((short *) memory_addrress) = data;
|
|
||||||
memory_addrress += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_disk_one_sertor(int lba, unsigned int memory_addrress) {
|
|
||||||
while (io_in8(0x1f7) & 0x80);
|
|
||||||
select_sector(lba);
|
|
||||||
io_out8(0x1f7, 0x30);
|
|
||||||
wait_disk_ready();
|
|
||||||
for (int i = 0; i < 256; i++) {
|
|
||||||
short data = *((short *) memory_addrress);
|
|
||||||
io_out16(0x1f0, data);
|
|
||||||
memory_addrress += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_disk(int lba, int sector_count, unsigned int memory_addrress) {
|
|
||||||
for (int i = 0; i < sector_count; i++) {
|
|
||||||
read_disk_one_sector(lba, memory_addrress);
|
|
||||||
lba++;
|
|
||||||
memory_addrress += 512;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_disk(int lba, int sector_count, unsigned int memory_addrress) {
|
|
||||||
for (int i = 0; i < sector_count; i++) {
|
|
||||||
write_disk_one_sertor(lba, memory_addrress);
|
|
||||||
lba++;
|
|
||||||
memory_addrress += 512;
|
|
||||||
}
|
|
||||||
}
|
|
399
driver/floppy.c
399
driver/floppy.c
@ -1,399 +0,0 @@
|
|||||||
#include "../include/floppy.h"
|
|
||||||
#include "../include/task.h"
|
|
||||||
#include "../include/printf.h"
|
|
||||||
#include "../include/vdisk.h"
|
|
||||||
#include "../include/io.h"
|
|
||||||
#include "../include/dma.h"
|
|
||||||
|
|
||||||
struct task_struct *floppy_use;
|
|
||||||
struct task_struct *waiter;
|
|
||||||
volatile int floppy_int_count = 0;
|
|
||||||
|
|
||||||
static volatile int done = 0;
|
|
||||||
static int dchange = 0;
|
|
||||||
static int motor = 0;
|
|
||||||
static int mtick = 0;
|
|
||||||
static volatile int tmout = 0;
|
|
||||||
static unsigned char status[7] = {0};
|
|
||||||
static unsigned char statsz = 0;
|
|
||||||
static unsigned char sr0 = 0;
|
|
||||||
static unsigned char fdc_track = 0xff;
|
|
||||||
static DrvGeom geometry = {DG144_HEADS, DG144_TRACKS, DG144_SPT};
|
|
||||||
unsigned long tbaddr = 0x80000L;
|
|
||||||
|
|
||||||
static void Read(char drive, unsigned char *buffer, unsigned int number,
|
|
||||||
unsigned int lba) {
|
|
||||||
floppy_use = get_current();
|
|
||||||
for (int i = 0; i < number; i += SECTORS_ONCE) {
|
|
||||||
int sectors = ((number - i) >= SECTORS_ONCE) ? SECTORS_ONCE : (number - i);
|
|
||||||
fdc_rw(lba + i, buffer + i * 512, 1, sectors);
|
|
||||||
}
|
|
||||||
floppy_use = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Write(char drive, unsigned char *buffer, unsigned int number,
|
|
||||||
unsigned int lba) {
|
|
||||||
floppy_use = get_current();
|
|
||||||
for (int i = 0; i < number; i += SECTORS_ONCE) {
|
|
||||||
int sectors = ((number - i) >= SECTORS_ONCE) ? SECTORS_ONCE : (number - i);
|
|
||||||
fdc_rw(lba + i, buffer + i * 512, 0, sectors);
|
|
||||||
}
|
|
||||||
floppy_use = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_floppy() {
|
|
||||||
sendbyte(CMD_VERSION); //发送命令(获取软盘版本),如果收到回应,说明软盘正在工作
|
|
||||||
if (getbyte() == -1) {
|
|
||||||
printf("floppy: no floppy drive found\n");
|
|
||||||
printf("No fount FDC\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
register_interrupt_handler(0x26,flint);
|
|
||||||
|
|
||||||
printf("[\035floppy\036]: FLOPPY DISK:RESETING\n");
|
|
||||||
reset(); //重置软盘驱动器
|
|
||||||
printf("[\035floppy\036]:FLOPPY DISK:reset over!\n");
|
|
||||||
sendbyte(CMD_VERSION); //获取软盘版本
|
|
||||||
printf("[\035floppy\036]:FDC_VER:0x%x\n", getbyte()); //并且输出到屏幕上
|
|
||||||
vdisk vd;
|
|
||||||
strcpy(vd.DriveName, "floppy");
|
|
||||||
vd.Read = Read;
|
|
||||||
vd.Write = Write;
|
|
||||||
vd.size = 1474560;
|
|
||||||
vd.flag = 1;
|
|
||||||
register_vdisk(vd);
|
|
||||||
}
|
|
||||||
|
|
||||||
int fdc_rw_ths(int track,
|
|
||||||
int head,
|
|
||||||
int sector,
|
|
||||||
unsigned char* blockbuff,
|
|
||||||
int read,
|
|
||||||
unsigned long nosectors) {
|
|
||||||
// 跟上面的大同小异
|
|
||||||
int tries, copycount = 0;
|
|
||||||
unsigned char* p_tbaddr = (char*)0x80000;
|
|
||||||
unsigned char* p_blockbuff = blockbuff;
|
|
||||||
|
|
||||||
motoron();
|
|
||||||
|
|
||||||
if (!read && blockbuff) {
|
|
||||||
for (copycount = 0; copycount < (nosectors * 512); copycount++) {
|
|
||||||
*p_tbaddr = *p_blockbuff;
|
|
||||||
p_blockbuff++;
|
|
||||||
p_tbaddr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (tries = 0; tries < 3; tries++) {
|
|
||||||
if (io_in8(FDC_DIR) & 0x80) {
|
|
||||||
dchange = 1;
|
|
||||||
seek(1);
|
|
||||||
recalibrate();
|
|
||||||
motoroff();
|
|
||||||
|
|
||||||
return fdc_rw_ths(track, head, sector, blockbuff, read, nosectors);
|
|
||||||
}
|
|
||||||
if (!seek(track)) {
|
|
||||||
motoroff();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
io_out8(FDC_CCR, 0);
|
|
||||||
|
|
||||||
if (read) {
|
|
||||||
dma_xfer(2, tbaddr, nosectors * 512, 0);
|
|
||||||
sendbyte(CMD_READ);
|
|
||||||
} else {
|
|
||||||
dma_xfer(2, tbaddr, nosectors * 512, 1);
|
|
||||||
sendbyte(CMD_WRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
sendbyte(head << 2);
|
|
||||||
sendbyte(track);
|
|
||||||
sendbyte(head);
|
|
||||||
sendbyte(sector);
|
|
||||||
sendbyte(2);
|
|
||||||
sendbyte(geometry.spt);
|
|
||||||
|
|
||||||
if (geometry.spt == DG144_SPT)
|
|
||||||
sendbyte(DG144_GAP3RW);
|
|
||||||
else
|
|
||||||
sendbyte(DG168_GAP3RW);
|
|
||||||
sendbyte(0xff);
|
|
||||||
|
|
||||||
wait_floppy_interrupt();
|
|
||||||
|
|
||||||
if ((status[0] & 0xc0) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
recalibrate();
|
|
||||||
}
|
|
||||||
|
|
||||||
motoroff();
|
|
||||||
|
|
||||||
if (read && blockbuff) {
|
|
||||||
p_blockbuff = blockbuff;
|
|
||||||
p_tbaddr = (char*)0x80000;
|
|
||||||
for (copycount = 0; copycount < (nosectors * 512); copycount++) {
|
|
||||||
*p_blockbuff = *p_tbaddr;
|
|
||||||
p_blockbuff++;
|
|
||||||
p_tbaddr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (tries != 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
int write_floppy_for_ths(int track,
|
|
||||||
int head,
|
|
||||||
int sec,
|
|
||||||
unsigned char* blockbuff,
|
|
||||||
unsigned long nosec) {
|
|
||||||
int res = fdc_rw_ths(track, head, sec, blockbuff, 0, nosec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void flint(registers_t *reg) {
|
|
||||||
floppy_int_count =
|
|
||||||
1; // 设置中断计数器为1,代表中断已经发生(或者是系统已经收到了中断)
|
|
||||||
io_out8(0x20, 0x20); // 发送EOI信号,告诉PIC,我们已经处理完了这个中断
|
|
||||||
//task_run(waiter);
|
|
||||||
// task_next();
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendbyte(int byte) {
|
|
||||||
volatile int msr;
|
|
||||||
int tmo; // 超时计数器
|
|
||||||
|
|
||||||
for (tmo = 0; tmo < 128; tmo++) // 这里我们只给128次尝试的机会
|
|
||||||
{
|
|
||||||
msr = io_in8(FDC_MSR);
|
|
||||||
if ((msr & 0xc0) ==
|
|
||||||
0x80) {
|
|
||||||
io_out8(FDC_DATA, byte);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
io_in8(0x80); /* 等待 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int getbyte() {
|
|
||||||
int msr; // 软盘驱动器状态寄存器
|
|
||||||
int tmo; // 软盘驱动器状态寄存器的超时计数器
|
|
||||||
|
|
||||||
for (tmo = 0; tmo < 128; tmo++){
|
|
||||||
msr = io_in8(FDC_MSR);
|
|
||||||
if ((msr & 0xd0) == 0xd0){
|
|
||||||
return io_in8(FDC_DATA);
|
|
||||||
}
|
|
||||||
io_in8(0x80); /* 延时 */
|
|
||||||
}
|
|
||||||
return -1; /* 没读取到 */
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_waiter(struct task_struct *t) {
|
|
||||||
while(waiter); // wait
|
|
||||||
waiter = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset(void) {
|
|
||||||
set_waiter(get_current());
|
|
||||||
io_out8(FDC_DOR, 0);
|
|
||||||
|
|
||||||
mtick = 0;
|
|
||||||
motor = 0;
|
|
||||||
|
|
||||||
io_out8(FDC_DRS, 0);
|
|
||||||
|
|
||||||
io_out8(FDC_DOR, 0x0c);
|
|
||||||
|
|
||||||
wait_floppy_interrupt();
|
|
||||||
sendbyte(CMD_SPECIFY);
|
|
||||||
sendbyte(0xdf); /* SRT = 3ms, HUT = 240ms */
|
|
||||||
sendbyte(0x02); /* HLT = 16ms, ND = 0 */
|
|
||||||
|
|
||||||
recalibrate();
|
|
||||||
|
|
||||||
dchange =
|
|
||||||
0; //清除“磁盘更改”状态(将dchange设置为false,让别的函数知道磁盘更改状态已经被清楚了)
|
|
||||||
}
|
|
||||||
void motoron(void) {
|
|
||||||
if (!motor) {
|
|
||||||
mtick = -1; /* 停止电机计时 */
|
|
||||||
io_out8(FDC_DOR, 0x1c);
|
|
||||||
for (int i = 0; i < 80000; i++)
|
|
||||||
;
|
|
||||||
motor = 1; //设置电机状态为true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 关闭电机 */
|
|
||||||
void motoroff(void) {
|
|
||||||
if (motor) {
|
|
||||||
mtick = 13500; /* 重新初始化电机计时器 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 重新校准驱动器 */
|
|
||||||
void recalibrate() {
|
|
||||||
set_waiter(get_current());
|
|
||||||
/* 先启用电机 */
|
|
||||||
motoron();
|
|
||||||
|
|
||||||
/* 然后重新校准电机 */
|
|
||||||
sendbyte(CMD_RECAL);
|
|
||||||
sendbyte(0);
|
|
||||||
|
|
||||||
/* 等待软盘中断(也就是电机校准成功) */
|
|
||||||
wait_floppy_interrupt();
|
|
||||||
/* 关闭电机 */
|
|
||||||
motoroff();
|
|
||||||
}
|
|
||||||
|
|
||||||
void wait_floppy_interrupt() {
|
|
||||||
io_sti();
|
|
||||||
while(!floppy_int_count);
|
|
||||||
statsz = 0; // 清空状态
|
|
||||||
while ((statsz < 7) &&(io_in8(FDC_MSR) &(1<< 4))) {
|
|
||||||
status[statsz++] = getbyte(); // 获取数据
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 获取中断状态 */
|
|
||||||
sendbyte(CMD_SENSEI);
|
|
||||||
sr0 = getbyte();
|
|
||||||
fdc_track = getbyte();
|
|
||||||
|
|
||||||
floppy_int_count = 0;
|
|
||||||
floppy_use = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int seek(int track) {
|
|
||||||
if (fdc_track == track) /* 目前的磁道和需要seek的磁道一样吗 */
|
|
||||||
{
|
|
||||||
// 一样的话就不用seek了
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
set_waiter(get_current());
|
|
||||||
/* 向软盘控制器发送SEEK命令 */
|
|
||||||
sendbyte(CMD_SEEK);
|
|
||||||
sendbyte(0);
|
|
||||||
sendbyte(track); /* 要seek到的磁道号 */
|
|
||||||
|
|
||||||
/* 发送完之后,软盘理应会送来一个中断 */
|
|
||||||
wait_floppy_interrupt(); // 所以我们需要等待软盘中断
|
|
||||||
|
|
||||||
for (int i = 0; i < 500; i++)
|
|
||||||
;
|
|
||||||
/* 检查一下成功了没有 */
|
|
||||||
if ((sr0 != 0x20) || (fdc_track != track))
|
|
||||||
return 0; // 没成功
|
|
||||||
else
|
|
||||||
return 1; // 成功了
|
|
||||||
}
|
|
||||||
|
|
||||||
void block2hts(int block, int* track, int* head, int* sector) {
|
|
||||||
*track = (block / 18) / 2;
|
|
||||||
*head = (block / 18) % 2;
|
|
||||||
*sector = block % 18 + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hts2block(int track, int head, int sector, int* block) {
|
|
||||||
*block = track * 18 * 2 + head * 18 + sector;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fdc_rw(int block,
|
|
||||||
unsigned char* blockbuff,
|
|
||||||
int read,
|
|
||||||
unsigned long nosectors) {
|
|
||||||
set_waiter(get_current());
|
|
||||||
int head, track, sector, tries, copycount = 0;
|
|
||||||
unsigned char* p_tbaddr =
|
|
||||||
(char*)0x80000; // 512byte
|
|
||||||
// 缓冲区(大家可以放心,我们再page.c已经把这里设置为占用了)
|
|
||||||
unsigned char* p_blockbuff = blockbuff; // r/w的数据缓冲区
|
|
||||||
|
|
||||||
/* 获取block对应的ths */
|
|
||||||
block2hts(block, &track, &head, §or);
|
|
||||||
|
|
||||||
motoron();
|
|
||||||
|
|
||||||
if (!read && blockbuff) {
|
|
||||||
/* 从数据缓冲区复制数据到轨道缓冲区 */
|
|
||||||
for (copycount = 0; copycount < (nosectors * 512); copycount++) {
|
|
||||||
*p_tbaddr = *p_blockbuff;
|
|
||||||
p_blockbuff++;
|
|
||||||
p_tbaddr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (tries = 0; tries < 3; tries++) {
|
|
||||||
/* 检查 */
|
|
||||||
if (io_in8(FDC_DIR) & 0x80) {
|
|
||||||
waiter = NULL;
|
|
||||||
dchange = 1;
|
|
||||||
seek(1); /* 清除磁盘更改 */
|
|
||||||
recalibrate();
|
|
||||||
motoroff();
|
|
||||||
return fdc_rw(block, blockbuff, read, nosectors);
|
|
||||||
}
|
|
||||||
waiter = NULL;
|
|
||||||
/* seek到track的位置*/
|
|
||||||
if (!seek(track)) {
|
|
||||||
motoroff();
|
|
||||||
waiter = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
set_waiter(get_current());
|
|
||||||
/* 传输速度(500K/s) */
|
|
||||||
io_out8(FDC_CCR, 0);
|
|
||||||
|
|
||||||
/* 发送命令 */
|
|
||||||
if (read) {
|
|
||||||
dma_xfer(2, tbaddr, nosectors * 512, 0);
|
|
||||||
sendbyte(CMD_READ);
|
|
||||||
} else {
|
|
||||||
dma_xfer(2, tbaddr, nosectors * 512, 1);
|
|
||||||
sendbyte(CMD_WRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
sendbyte(head << 2);
|
|
||||||
sendbyte(track);
|
|
||||||
sendbyte(head);
|
|
||||||
sendbyte(sector);
|
|
||||||
sendbyte(2); /* 每个扇区是512字节 */
|
|
||||||
sendbyte(geometry.spt);
|
|
||||||
|
|
||||||
if (geometry.spt == DG144_SPT)
|
|
||||||
sendbyte(DG144_GAP3RW);
|
|
||||||
else
|
|
||||||
sendbyte(DG168_GAP3RW);
|
|
||||||
sendbyte(0xff);
|
|
||||||
|
|
||||||
/* 等待中断...... */
|
|
||||||
/* 读写数据不需要中断状态 */
|
|
||||||
wait_floppy_interrupt();
|
|
||||||
|
|
||||||
if ((status[0] & 0xc0) == 0)
|
|
||||||
break; /* worked! outta here! */
|
|
||||||
waiter = NULL;
|
|
||||||
recalibrate(); /* az,报错了,再试一遍 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 关闭电动机 */
|
|
||||||
motoroff();
|
|
||||||
|
|
||||||
if (read && blockbuff) {
|
|
||||||
/* 复制数据 */
|
|
||||||
p_blockbuff = blockbuff;
|
|
||||||
p_tbaddr = (char*)0x80000;
|
|
||||||
for (copycount = 0; copycount < (nosectors * 512); copycount++) {
|
|
||||||
*p_blockbuff = *p_tbaddr;
|
|
||||||
p_blockbuff++;
|
|
||||||
p_tbaddr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (tries != 3);
|
|
||||||
}
|
|
735
driver/ide.c
Normal file
735
driver/ide.c
Normal file
@ -0,0 +1,735 @@
|
|||||||
|
#include "../include/ide.h"
|
||||||
|
#include "../include/printf.h"
|
||||||
|
#include "../include/common.h"
|
||||||
|
#include "../include/vdisk.h"
|
||||||
|
#include "../include/timer.h"
|
||||||
|
#include "../include/pci.h"
|
||||||
|
|
||||||
|
static inline nul(char *f, ...) {}
|
||||||
|
|
||||||
|
#define logk nul
|
||||||
|
|
||||||
|
#define inb io_in8
|
||||||
|
#define outb io_out8
|
||||||
|
|
||||||
|
struct IDEChannelRegisters {
|
||||||
|
unsigned short base; // I/O Base.
|
||||||
|
unsigned short ctrl; // Control Base
|
||||||
|
unsigned short bmide; // Bus Master IDE
|
||||||
|
unsigned char nIEN; // nIEN (No Interrupt);
|
||||||
|
} channels[2];
|
||||||
|
|
||||||
|
struct ide_device {
|
||||||
|
unsigned char Reserved; // 0 (Empty) or 1 (This Drive really exists).
|
||||||
|
unsigned char Channel; // 0 (Primary Channel) or 1 (Secondary Channel).
|
||||||
|
unsigned char Drive; // 0 (Master Drive) or 1 (Slave Drive).
|
||||||
|
unsigned short Type; // 0: ATA, 1:ATAPI.
|
||||||
|
unsigned short Signature; // Drive Signature
|
||||||
|
unsigned short Capabilities; // Features.
|
||||||
|
unsigned int CommandSets; // Command Sets Supported.
|
||||||
|
unsigned int Size; // Size in Sectors.
|
||||||
|
unsigned char Model[41]; // Model in string.
|
||||||
|
} ide_devices[4];
|
||||||
|
|
||||||
|
unsigned char ide_buf[2048] = {0};
|
||||||
|
volatile unsigned static char ide_irq_invoked = 0;
|
||||||
|
unsigned static char atapi_packet[12] = {0xA8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
static int package[2];
|
||||||
|
|
||||||
|
static inline void insl(uint32_t port, uint32_t *addr, int cnt) {
|
||||||
|
asm volatile("cld;"
|
||||||
|
"repne; insl;"
|
||||||
|
: "=D"(addr), "=c"(cnt)
|
||||||
|
: "d"(port), "0"(addr), "1"(cnt)
|
||||||
|
: "memory", "cc");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Read(char drive, unsigned char *buffer, unsigned int number,
|
||||||
|
unsigned int lba) {
|
||||||
|
ide_read_sectors(drive - 'C', number, lba, 1 * 8, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Write(char drive, unsigned char *buffer, unsigned int number,
|
||||||
|
unsigned int lba) {
|
||||||
|
ide_write_sectors(drive - 'C', number, lba, 1 * 8, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char ide_read(unsigned char channel, unsigned char reg) {
|
||||||
|
unsigned char result;
|
||||||
|
if (reg > 0x07 && reg < 0x0C)
|
||||||
|
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
||||||
|
if (reg < 0x08)
|
||||||
|
result = inb(channels[channel].base + reg - 0x00);
|
||||||
|
else if (reg < 0x0C)
|
||||||
|
result = inb(channels[channel].base + reg - 0x06);
|
||||||
|
else if (reg < 0x0E)
|
||||||
|
result = inb(channels[channel].ctrl + reg - 0x0A);
|
||||||
|
else if (reg < 0x16)
|
||||||
|
result = inb(channels[channel].bmide + reg - 0x0E);
|
||||||
|
if (reg > 0x07 && reg < 0x0C)
|
||||||
|
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void ide_write(unsigned char channel, unsigned char reg, unsigned char data) {
|
||||||
|
if (reg > 0x07 && reg < 0x0C)
|
||||||
|
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
||||||
|
if (reg < 0x08)
|
||||||
|
outb(channels[channel].base + reg - 0x00, data);
|
||||||
|
else if (reg < 0x0C)
|
||||||
|
outb(channels[channel].base + reg - 0x06, data);
|
||||||
|
else if (reg < 0x0E)
|
||||||
|
outb(channels[channel].ctrl + reg - 0x0A, data);
|
||||||
|
else if (reg < 0x16)
|
||||||
|
outb(channels[channel].bmide + reg - 0x0E, data);
|
||||||
|
if (reg > 0x07 && reg < 0x0C)
|
||||||
|
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
||||||
|
}
|
||||||
|
void ide_read_buffer(unsigned char channel, unsigned char reg,
|
||||||
|
unsigned int buffer, unsigned int quads) {
|
||||||
|
/* WARNING: This code contains a serious bug. The inline assembly trashes ES
|
||||||
|
* and ESP for all of the code the compiler generates between the inline
|
||||||
|
* assembly blocks.
|
||||||
|
*/
|
||||||
|
if (reg > 0x07 && reg < 0x0C)
|
||||||
|
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
||||||
|
// asm("pushw %es; movw %ds, %ax; movw %ax, %es");
|
||||||
|
if (reg < 0x08)
|
||||||
|
insl(channels[channel].base + reg - 0x00, buffer, quads);
|
||||||
|
else if (reg < 0x0C)
|
||||||
|
insl(channels[channel].base + reg - 0x06, buffer, quads);
|
||||||
|
else if (reg < 0x0E)
|
||||||
|
insl(channels[channel].ctrl + reg - 0x0A, buffer, quads);
|
||||||
|
else if (reg < 0x16)
|
||||||
|
insl(channels[channel].bmide + reg - 0x0E, buffer, quads);
|
||||||
|
// asm("popw %es;");
|
||||||
|
if (reg > 0x07 && reg < 0x0C)
|
||||||
|
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
||||||
|
}
|
||||||
|
unsigned char ide_polling(unsigned char channel, unsigned int advanced_check) {
|
||||||
|
// (I) Delay 400 nanosecond for BSY to be set:
|
||||||
|
// -------------------------------------------------
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port
|
||||||
|
// wastes 100ns; loop four times.
|
||||||
|
|
||||||
|
// (II) Wait for BSY to be cleared:
|
||||||
|
// -------------------------------------------------
|
||||||
|
logk("II\n");
|
||||||
|
int a = ide_read(channel, ATA_REG_STATUS);
|
||||||
|
while (a & ATA_SR_BSY) {
|
||||||
|
logk("a=%d\n", a & ATA_SR_BSY); // Wait for BSY to be zero.
|
||||||
|
a = ide_read(channel, ATA_REG_STATUS);
|
||||||
|
clock_sleep(1);
|
||||||
|
}
|
||||||
|
logk("II OK\n");
|
||||||
|
if (advanced_check) {
|
||||||
|
unsigned char state =
|
||||||
|
ide_read(channel, ATA_REG_STATUS); // Read Status Register.
|
||||||
|
|
||||||
|
// (III) Check For Errors:
|
||||||
|
// -------------------------------------------------
|
||||||
|
logk("III\n");
|
||||||
|
if (state & ATA_SR_ERR)
|
||||||
|
return 2; // Error.
|
||||||
|
|
||||||
|
// (IV) Check If Device fault:
|
||||||
|
// -------------------------------------------------
|
||||||
|
if (state & ATA_SR_DF)
|
||||||
|
return 1; // Device Fault.
|
||||||
|
|
||||||
|
// (V) Check DRQ:
|
||||||
|
// -------------------------------------------------
|
||||||
|
// BSY = 0; DF = 0; ERR = 0 so we should check for DRQ now.
|
||||||
|
if ((state & ATA_SR_DRQ) == 0)
|
||||||
|
return 3; // DRQ should be set
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; // No Error.
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char ide_print_error(unsigned int drive, unsigned char err) {
|
||||||
|
if (err == 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
printk("IDE:");
|
||||||
|
if (err == 1) {
|
||||||
|
printk("- Device Fault\n ");
|
||||||
|
err = 19;
|
||||||
|
} else if (err == 2) {
|
||||||
|
unsigned char st = ide_read(ide_devices[drive].Channel, ATA_REG_ERROR);
|
||||||
|
if (st & ATA_ER_AMNF) {
|
||||||
|
printk("- No Address Mark Found\n ");
|
||||||
|
err = 7;
|
||||||
|
}
|
||||||
|
if (st & ATA_ER_TK0NF) {
|
||||||
|
printk("- No Media or Media Error\n ");
|
||||||
|
err = 3;
|
||||||
|
}
|
||||||
|
if (st & ATA_ER_ABRT) {
|
||||||
|
printk("- Command Aborted\n ");
|
||||||
|
err = 20;
|
||||||
|
}
|
||||||
|
if (st & ATA_ER_MCR) {
|
||||||
|
printk("- No Media or Media Error\n ");
|
||||||
|
err = 3;
|
||||||
|
}
|
||||||
|
if (st & ATA_ER_IDNF) {
|
||||||
|
printk("- ID mark not Found\n ");
|
||||||
|
err = 21;
|
||||||
|
}
|
||||||
|
if (st & ATA_ER_MC) {
|
||||||
|
printk("- No Media or Media Error\n ");
|
||||||
|
err = 3;
|
||||||
|
}
|
||||||
|
if (st & ATA_ER_UNC) {
|
||||||
|
printk("- Uncorrectable Data Error\n ");
|
||||||
|
err = 22;
|
||||||
|
}
|
||||||
|
if (st & ATA_ER_BBK) {
|
||||||
|
printk("- Bad Sectors\n ");
|
||||||
|
err = 13;
|
||||||
|
}
|
||||||
|
} else if (err == 3) {
|
||||||
|
printk("- Reads Nothing\n ");
|
||||||
|
err = 23;
|
||||||
|
} else if (err == 4) {
|
||||||
|
printk("- Write Protected\n ");
|
||||||
|
err = 8;
|
||||||
|
}
|
||||||
|
printk(
|
||||||
|
"- [%s %s] %s\n",
|
||||||
|
(const char *[]){
|
||||||
|
"Primary",
|
||||||
|
"Secondary"}[ide_devices[drive].Channel], // Use the channel as an
|
||||||
|
// index into the array
|
||||||
|
(const char *[]){
|
||||||
|
"Master",
|
||||||
|
"Slave"}[ide_devices[drive].Drive], // Same as above, using the drive
|
||||||
|
ide_devices[drive].Model);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char ide_ata_access(unsigned char direction, unsigned char drive,
|
||||||
|
unsigned int lba, unsigned char numsects,
|
||||||
|
unsigned short selector, unsigned int edi) {
|
||||||
|
unsigned char lba_mode /* 0: CHS, 1:LBA28, 2: LBA48 */,
|
||||||
|
dma /* 0: No DMA, 1: DMA */, cmd;
|
||||||
|
unsigned char lba_io[6];
|
||||||
|
unsigned int channel = ide_devices[drive].Channel; // Read the Channel.
|
||||||
|
unsigned int slavebit =
|
||||||
|
ide_devices[drive].Drive; // Read the Drive [Master/Slave]
|
||||||
|
unsigned int bus =
|
||||||
|
channels[channel].base; // Bus Base, like 0x1F0 which is also data port.
|
||||||
|
unsigned int words =
|
||||||
|
256; // Almost every ATA drive has a sector-size of 512-byte.
|
||||||
|
unsigned short cyl, i;
|
||||||
|
unsigned char head, sect, err;
|
||||||
|
ide_write(channel, ATA_REG_CONTROL,
|
||||||
|
channels[channel].nIEN = (ide_irq_invoked = 0x0) + 0x02);
|
||||||
|
// (I) Select one from LBA28, LBA48 or CHS;
|
||||||
|
logk("I %02x\n", channels[channel].nIEN);
|
||||||
|
if (lba >= 0x10000000) { // Sure Drive should support LBA in this case, or
|
||||||
|
// you are giving a wrong LBA.
|
||||||
|
// LBA48:
|
||||||
|
lba_mode = 2;
|
||||||
|
lba_io[0] = (lba & 0x000000FF) >> 0;
|
||||||
|
lba_io[1] = (lba & 0x0000FF00) >> 8;
|
||||||
|
lba_io[2] = (lba & 0x00FF0000) >> 16;
|
||||||
|
lba_io[3] = (lba & 0xFF000000) >> 24;
|
||||||
|
lba_io[4] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.
|
||||||
|
lba_io[5] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.
|
||||||
|
head = 0; // Lower 4-bits of HDDEVSEL are not used here.
|
||||||
|
} else if (ide_devices[drive].Capabilities & 0x200) { // Drive supports LBA?
|
||||||
|
// LBA28:
|
||||||
|
lba_mode = 1;
|
||||||
|
lba_io[0] = (lba & 0x00000FF) >> 0;
|
||||||
|
lba_io[1] = (lba & 0x000FF00) >> 8;
|
||||||
|
lba_io[2] = (lba & 0x0FF0000) >> 16;
|
||||||
|
lba_io[3] = 0; // These Registers are not used here.
|
||||||
|
lba_io[4] = 0; // These Registers are not used here.
|
||||||
|
lba_io[5] = 0; // These Registers are not used here.
|
||||||
|
head = (lba & 0xF000000) >> 24;
|
||||||
|
} else {
|
||||||
|
// CHS:
|
||||||
|
lba_mode = 0;
|
||||||
|
sect = (lba % 63) + 1;
|
||||||
|
cyl = (lba + 1 - sect) / (16 * 63);
|
||||||
|
lba_io[0] = sect;
|
||||||
|
lba_io[1] = (cyl >> 0) & 0xFF;
|
||||||
|
lba_io[2] = (cyl >> 8) & 0xFF;
|
||||||
|
lba_io[3] = 0;
|
||||||
|
lba_io[4] = 0;
|
||||||
|
lba_io[5] = 0;
|
||||||
|
head = (lba + 1 - sect) % (16 * 63) /
|
||||||
|
(63); // Head number is written to HDDEVSEL lower 4-bits.
|
||||||
|
}
|
||||||
|
// (II) See if drive supports DMA or not;
|
||||||
|
logk("II\n");
|
||||||
|
dma = 0; // We don't support DMA
|
||||||
|
// (III) Wait if the drive is busy;
|
||||||
|
logk("III\n");
|
||||||
|
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY) {
|
||||||
|
} // Wait if busy.
|
||||||
|
// (IV) Select Drive from the controller;
|
||||||
|
logk("IV\n");
|
||||||
|
if (lba_mode == 0)
|
||||||
|
ide_write(channel, ATA_REG_HDDEVSEL,
|
||||||
|
0xA0 | (slavebit << 4) | head); // Drive & CHS.
|
||||||
|
else
|
||||||
|
ide_write(channel, ATA_REG_HDDEVSEL,
|
||||||
|
0xE0 | (slavebit << 4) | head); // Drive & LBA
|
||||||
|
// (V) Write Parameters;
|
||||||
|
if (lba_mode == 2) {
|
||||||
|
ide_write(channel, ATA_REG_SECCOUNT1, 0);
|
||||||
|
ide_write(channel, ATA_REG_LBA3, lba_io[3]);
|
||||||
|
ide_write(channel, ATA_REG_LBA4, lba_io[4]);
|
||||||
|
ide_write(channel, ATA_REG_LBA5, lba_io[5]);
|
||||||
|
}
|
||||||
|
ide_write(channel, ATA_REG_SECCOUNT0, numsects);
|
||||||
|
ide_write(channel, ATA_REG_LBA0, lba_io[0]);
|
||||||
|
ide_write(channel, ATA_REG_LBA1, lba_io[1]);
|
||||||
|
ide_write(channel, ATA_REG_LBA2, lba_io[2]);
|
||||||
|
if (lba_mode == 0 && dma == 0 && direction == 0)
|
||||||
|
cmd = ATA_CMD_READ_PIO;
|
||||||
|
if (lba_mode == 1 && dma == 0 && direction == 0)
|
||||||
|
cmd = ATA_CMD_READ_PIO;
|
||||||
|
if (lba_mode == 2 && dma == 0 && direction == 0)
|
||||||
|
cmd = ATA_CMD_READ_PIO_EXT;
|
||||||
|
if (lba_mode == 0 && dma == 1 && direction == 0)
|
||||||
|
cmd = ATA_CMD_READ_DMA;
|
||||||
|
if (lba_mode == 1 && dma == 1 && direction == 0)
|
||||||
|
cmd = ATA_CMD_READ_DMA;
|
||||||
|
if (lba_mode == 2 && dma == 1 && direction == 0)
|
||||||
|
cmd = ATA_CMD_READ_DMA_EXT;
|
||||||
|
if (lba_mode == 0 && dma == 0 && direction == 1)
|
||||||
|
cmd = ATA_CMD_WRITE_PIO;
|
||||||
|
if (lba_mode == 1 && dma == 0 && direction == 1)
|
||||||
|
cmd = ATA_CMD_WRITE_PIO;
|
||||||
|
if (lba_mode == 2 && dma == 0 && direction == 1)
|
||||||
|
cmd = ATA_CMD_WRITE_PIO_EXT;
|
||||||
|
if (lba_mode == 0 && dma == 1 && direction == 1)
|
||||||
|
cmd = ATA_CMD_WRITE_DMA;
|
||||||
|
if (lba_mode == 1 && dma == 1 && direction == 1)
|
||||||
|
cmd = ATA_CMD_WRITE_DMA;
|
||||||
|
if (lba_mode == 2 && dma == 1 && direction == 1)
|
||||||
|
cmd = ATA_CMD_WRITE_DMA_EXT;
|
||||||
|
ide_write(channel, ATA_REG_COMMAND, cmd); // Send the Command.
|
||||||
|
logk("IV1\n");
|
||||||
|
if (dma)
|
||||||
|
if (direction == 0)
|
||||||
|
;
|
||||||
|
// DMA Read.
|
||||||
|
else
|
||||||
|
;
|
||||||
|
// DMA Write.
|
||||||
|
else if (direction == 0) {
|
||||||
|
// PIO Read.
|
||||||
|
uint16_t *word_ = edi;
|
||||||
|
for (i = 0; i < numsects; i++) {
|
||||||
|
logk("read %d\n", i);
|
||||||
|
if (err = ide_polling(channel, 1))
|
||||||
|
return err; // Polling, set error and exit if there is.
|
||||||
|
|
||||||
|
logk("words=%d bus=%d\n", words, bus);
|
||||||
|
// for (int h = 0; h < words; h++) {
|
||||||
|
// unsigned short a = io_in16(bus);
|
||||||
|
// word_[i * words + h] = a;
|
||||||
|
// }
|
||||||
|
insl(bus, word_ + i * words, words / 2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// PIO Write.
|
||||||
|
uint16_t *word_ = edi;
|
||||||
|
for (i = 0; i < numsects; i++) {
|
||||||
|
logk("write %d\n", i);
|
||||||
|
ide_polling(channel, 0); // Polling.
|
||||||
|
// asm("pushw %ds");
|
||||||
|
// asm("mov %%ax, %%ds" ::"a"(selector));
|
||||||
|
// asm("rep outsw" ::"c"(words), "d"(bus), "S"(edi)); // Send Data
|
||||||
|
// asm("popw %ds");
|
||||||
|
for (int h = 0; h < words; h++) {
|
||||||
|
io_out16(bus, word_[i * words + h]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ide_write(channel, ATA_REG_COMMAND,
|
||||||
|
(char[]){ATA_CMD_CACHE_FLUSH, ATA_CMD_CACHE_FLUSH,
|
||||||
|
ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);
|
||||||
|
ide_polling(channel, 0); // Polling.
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; // Easy, isn't it?
|
||||||
|
}
|
||||||
|
void ide_wait_irq() {
|
||||||
|
while (!ide_irq_invoked)
|
||||||
|
;
|
||||||
|
ide_irq_invoked = 0;
|
||||||
|
}
|
||||||
|
void ide_irq() {
|
||||||
|
logk("ide irq.\n");
|
||||||
|
ide_irq_invoked = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char ide_atapi_read(unsigned char drive, unsigned int lba,
|
||||||
|
unsigned char numsects, unsigned short selector,
|
||||||
|
unsigned int edi) {
|
||||||
|
logk("cdrom read.\n");
|
||||||
|
unsigned int channel = ide_devices[drive].Channel;
|
||||||
|
unsigned int slavebit = ide_devices[drive].Drive;
|
||||||
|
unsigned int bus = channels[channel].base;
|
||||||
|
unsigned int words =
|
||||||
|
1024; // Sector Size. ATAPI drives have a sector size of 2048 bytes.
|
||||||
|
unsigned char err;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ide_write(channel, ATA_REG_CONTROL,
|
||||||
|
channels[channel].nIEN = ide_irq_invoked = 0x0);
|
||||||
|
// (I): Setup SCSI Packet:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
logk("I\n");
|
||||||
|
atapi_packet[0] = ATAPI_CMD_READ;
|
||||||
|
atapi_packet[1] = 0x0;
|
||||||
|
atapi_packet[2] = (lba >> 24) & 0xFF;
|
||||||
|
atapi_packet[3] = (lba >> 16) & 0xFF;
|
||||||
|
atapi_packet[4] = (lba >> 8) & 0xFF;
|
||||||
|
atapi_packet[5] = (lba >> 0) & 0xFF;
|
||||||
|
atapi_packet[6] = 0x0;
|
||||||
|
atapi_packet[7] = 0x0;
|
||||||
|
atapi_packet[8] = 0x0;
|
||||||
|
atapi_packet[9] = numsects;
|
||||||
|
atapi_packet[10] = 0x0;
|
||||||
|
atapi_packet[11] = 0x0; // (II): Select the drive:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
ide_write(channel, ATA_REG_HDDEVSEL, slavebit << 4);
|
||||||
|
logk("II\n");
|
||||||
|
// (III): Delay 400 nanoseconds for select to complete:
|
||||||
|
for (int i = 0; i < 4000; i++)
|
||||||
|
;
|
||||||
|
logk("III\n");
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
logk("IV\n");
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
ide_read(channel,
|
||||||
|
ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes
|
||||||
|
// 100ns. (IV): Inform the Controller that we
|
||||||
|
// use PIO mode:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
ide_write(channel, ATA_REG_FEATURES,
|
||||||
|
0); // PIO mode.
|
||||||
|
// (V): Tell the Controller the size of buffer:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
logk("V\n");
|
||||||
|
ide_write(channel, ATA_REG_LBA1,
|
||||||
|
(words * 2) & 0xFF); // Lower Byte of Sector Size.
|
||||||
|
ide_write(channel, ATA_REG_LBA2,
|
||||||
|
(words * 2) >> 8); // Upper Byte of Sector Size.
|
||||||
|
// (VI): Send the Packet Command:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
ide_write(channel, ATA_REG_COMMAND, ATA_CMD_PACKET); // Send the Command.
|
||||||
|
|
||||||
|
// (VII): Waiting for the driver to finish or return an error code:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
if (err = ide_polling(channel, 1))
|
||||||
|
return err; // Polling and return if error.
|
||||||
|
|
||||||
|
// (VIII): Sending the packet data:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
logk("VIII\n");
|
||||||
|
uint16_t *_atapi_packet = atapi_packet;
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
io_out16(bus, _atapi_packet[i]);
|
||||||
|
}
|
||||||
|
// (IX): Receiving Data:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
logk("IX\n");
|
||||||
|
uint16_t *_word = edi;
|
||||||
|
for (i = 0; i < numsects; i++) {
|
||||||
|
ide_wait_irq(); // Wait for an IRQ.
|
||||||
|
if (err = ide_polling(channel, 1))
|
||||||
|
return err; // Polling and return if error.
|
||||||
|
logk("words = %d\n", words);
|
||||||
|
for (int h = 0; h < words; h++) {
|
||||||
|
uint16_t a = io_in16(bus);
|
||||||
|
_word[i * words + h] = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// (X): Waiting for an IRQ:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
ide_wait_irq();
|
||||||
|
|
||||||
|
// (XI): Waiting for BSY & DRQ to clear:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
while (ide_read(channel, ATA_REG_STATUS) & (ATA_SR_BSY | ATA_SR_DRQ))
|
||||||
|
;
|
||||||
|
|
||||||
|
return 0; // Easy, ... Isn't it?
|
||||||
|
}
|
||||||
|
void ide_read_sectors(unsigned char drive, unsigned char numsects,
|
||||||
|
unsigned int lba, unsigned short es, unsigned int edi) {
|
||||||
|
// 1: Check if the drive presents:
|
||||||
|
// ==================================
|
||||||
|
if (drive > 3 || ide_devices[drive].Reserved == 0)
|
||||||
|
package[0] = 0x1; // Drive Not Found!
|
||||||
|
|
||||||
|
// 2: Check if inputs are valid:
|
||||||
|
// ==================================
|
||||||
|
else if (((lba + numsects) > ide_devices[drive].Size) &&
|
||||||
|
(ide_devices[drive].Type == IDE_ATA))
|
||||||
|
package[0] = 0x2; // Seeking to invalid position.
|
||||||
|
|
||||||
|
// 3: Read in PIO Mode through Polling & IRQs:
|
||||||
|
// ============================================
|
||||||
|
else {
|
||||||
|
unsigned char err;
|
||||||
|
if (ide_devices[drive].Type == IDE_ATA) {
|
||||||
|
logk("Will Read.\n");
|
||||||
|
err = ide_ata_access(ATA_READ, drive, lba, numsects, es, edi);
|
||||||
|
|
||||||
|
} else if (ide_devices[drive].Type == IDE_ATAPI)
|
||||||
|
for (int i = 0; i < numsects; i++)
|
||||||
|
err = ide_atapi_read(drive, lba + i, 1, es, edi + (i * 2048));
|
||||||
|
package[0] = ide_print_error(drive, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// package[0] is an entry of an array. It contains the Error Code.
|
||||||
|
void ide_write_sectors(unsigned char drive, unsigned char numsects,
|
||||||
|
unsigned int lba, unsigned short es, unsigned int edi) {
|
||||||
|
// 1: Check if the drive presents:
|
||||||
|
// ==================================
|
||||||
|
if (drive > 3 || ide_devices[drive].Reserved == 0)
|
||||||
|
package[0] = 0x1; // Drive Not Found!
|
||||||
|
// 2: Check if inputs are valid:
|
||||||
|
// ==================================
|
||||||
|
else if (((lba + numsects) > ide_devices[drive].Size) &&
|
||||||
|
(ide_devices[drive].Type == IDE_ATA))
|
||||||
|
package[0] = 0x2; // Seeking to invalid position.
|
||||||
|
// 3: Read in PIO Mode through Polling & IRQs:
|
||||||
|
// ============================================
|
||||||
|
else {
|
||||||
|
unsigned char err;
|
||||||
|
if (ide_devices[drive].Type == IDE_ATA)
|
||||||
|
err = ide_ata_access(ATA_WRITE, drive, lba, numsects, es, edi);
|
||||||
|
else if (ide_devices[drive].Type == IDE_ATAPI)
|
||||||
|
err = 4; // Write-Protected.
|
||||||
|
package[0] = ide_print_error(drive, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ide_atapi_eject(unsigned char drive) {
|
||||||
|
unsigned int channel = ide_devices[drive].Channel;
|
||||||
|
unsigned int slavebit = ide_devices[drive].Drive;
|
||||||
|
unsigned int bus = channels[channel].base;
|
||||||
|
unsigned int words = 2048 / 2; // Sector Size in Words.
|
||||||
|
unsigned char err = 0;
|
||||||
|
ide_irq_invoked = 0;
|
||||||
|
|
||||||
|
// 1: Check if the drive presents:
|
||||||
|
// ==================================
|
||||||
|
if (drive > 3 || ide_devices[drive].Reserved == 0)
|
||||||
|
package[0] = 0x1; // Drive Not Found!
|
||||||
|
// 2: Check if drive isn't ATAPI:
|
||||||
|
// ==================================
|
||||||
|
else if (ide_devices[drive].Type == IDE_ATA)
|
||||||
|
package[0] = 20; // Command Aborted.
|
||||||
|
// 3: Eject ATAPI Driver:
|
||||||
|
// ============================================
|
||||||
|
else {
|
||||||
|
// Enable IRQs:
|
||||||
|
ide_write(channel, ATA_REG_CONTROL,
|
||||||
|
channels[channel].nIEN = ide_irq_invoked = 0x0);
|
||||||
|
|
||||||
|
// (I): Setup SCSI Packet:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
atapi_packet[0] = ATAPI_CMD_EJECT;
|
||||||
|
atapi_packet[1] = 0x00;
|
||||||
|
atapi_packet[2] = 0x00;
|
||||||
|
atapi_packet[3] = 0x00;
|
||||||
|
atapi_packet[4] = 0x02;
|
||||||
|
atapi_packet[5] = 0x00;
|
||||||
|
atapi_packet[6] = 0x00;
|
||||||
|
atapi_packet[7] = 0x00;
|
||||||
|
atapi_packet[8] = 0x00;
|
||||||
|
atapi_packet[9] = 0x00;
|
||||||
|
atapi_packet[10] = 0x00;
|
||||||
|
atapi_packet[11] = 0x00;
|
||||||
|
|
||||||
|
// (II): Select the Drive:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
ide_write(channel, ATA_REG_HDDEVSEL, slavebit << 4);
|
||||||
|
|
||||||
|
// (III): Delay 400 nanosecond for select to complete:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
ide_read(
|
||||||
|
channel,
|
||||||
|
ATA_REG_ALTSTATUS); // Reading Alternate Status Port wastes 100ns.
|
||||||
|
|
||||||
|
// (IV): Send the Packet Command:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
ide_write(channel, ATA_REG_COMMAND, ATA_CMD_PACKET); // Send the Command.
|
||||||
|
|
||||||
|
// (V): Waiting for the driver to finish or invoke an error:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
err = ide_polling(channel, 1); // Polling and stop if error.
|
||||||
|
|
||||||
|
// (VI): Sending the packet data:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
asm("rep outsw" ::"c"(6), "d"(bus),
|
||||||
|
"S"(atapi_packet)); // Send Packet Data
|
||||||
|
ide_wait_irq(); // Wait for an IRQ.
|
||||||
|
err = ide_polling(channel, 1); // Polling and get error code.
|
||||||
|
if (err == 3)
|
||||||
|
err = 0; // DRQ is not needed here.
|
||||||
|
|
||||||
|
package[0] = ide_print_error(drive, err); // Return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
|
||||||
|
unsigned int BAR3, unsigned int BAR4) {
|
||||||
|
int i1, j1, k1;
|
||||||
|
int flag = 0;
|
||||||
|
for (i1 = 0; i1 < 255; i1++) {
|
||||||
|
for (j1 = 0; j1 < 32; j1++) {
|
||||||
|
for (k1 = 0; k1 < 8; k1++) {
|
||||||
|
uint32_t p = read_pci(i1, j1, k1, 0x8);
|
||||||
|
uint16_t *reg =
|
||||||
|
&p; // reg[0] ---> P & R, reg[1] ---> Sub Class Class Code
|
||||||
|
uint8_t *codes =
|
||||||
|
&(reg[1]); // codes[0] --> Sub Class Code codes[1] Class Code
|
||||||
|
if (codes[1] == 0x1 && codes[0] == 0x1) {
|
||||||
|
flag = 1;
|
||||||
|
goto OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OK:
|
||||||
|
if (flag == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BAR0 = read_bar_n(i1, j1, k1, 0);
|
||||||
|
BAR1 = read_bar_n(i1, j1, k1, 1);
|
||||||
|
BAR2 = read_bar_n(i1, j1, k1, 2);
|
||||||
|
BAR3 = read_bar_n(i1, j1, k1, 3);
|
||||||
|
BAR4 = read_bar_n(i1, j1, k1, 4);
|
||||||
|
int j, k, count = 0;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
ide_devices[i].Reserved = 0;
|
||||||
|
}
|
||||||
|
// 1- Detect I/O Ports which interface IDE Controller:
|
||||||
|
channels[ATA_PRIMARY].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0);
|
||||||
|
channels[ATA_PRIMARY].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1);
|
||||||
|
channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2);
|
||||||
|
channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x376 * (!BAR3);
|
||||||
|
channels[ATA_PRIMARY].bmide = (BAR4 & 0xFFFFFFFC) + 0; // Bus Master IDE
|
||||||
|
channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; // Bus Master IDE
|
||||||
|
// 2- Disable IRQs:
|
||||||
|
ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2);
|
||||||
|
ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2);
|
||||||
|
logk("w1\n");
|
||||||
|
// 3- Detect ATA-ATAPI Devices:
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
for (j = 0; j < 2; j++) {
|
||||||
|
unsigned char err = 0, type = IDE_ATA, status;
|
||||||
|
ide_devices[count].Reserved = 0; // Assuming that no drive here.
|
||||||
|
|
||||||
|
// (I) Select Drive:
|
||||||
|
ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive.
|
||||||
|
clock_sleep(1); // Wait 1ms for drive select to work.
|
||||||
|
logk("I\n");
|
||||||
|
// (II) Send ATA Identify Command:
|
||||||
|
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
|
||||||
|
clock_sleep(1); // This function should be implemented in your OS. which waits
|
||||||
|
// for 1 ms. it is based on System Timer Device Driver.
|
||||||
|
logk("II\n");
|
||||||
|
// (III) Polling:
|
||||||
|
if (ide_read(i, ATA_REG_STATUS) == 0)
|
||||||
|
continue; // If Status = 0, No Device.
|
||||||
|
logk("III\n");
|
||||||
|
while (1) {
|
||||||
|
logk("read ide....\n");
|
||||||
|
status = ide_read(i, ATA_REG_STATUS);
|
||||||
|
logk("read ok\n");
|
||||||
|
if ((status & ATA_SR_ERR)) {
|
||||||
|
err = 1;
|
||||||
|
break;
|
||||||
|
} // If Err, Device is not ATA.
|
||||||
|
if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ))
|
||||||
|
break; // Everything is right.
|
||||||
|
}
|
||||||
|
|
||||||
|
// (IV) Probe for ATAPI Devices:
|
||||||
|
logk("IV\n");
|
||||||
|
if (err != 0) {
|
||||||
|
unsigned char cl = ide_read(i, ATA_REG_LBA1);
|
||||||
|
unsigned char ch = ide_read(i, ATA_REG_LBA2);
|
||||||
|
|
||||||
|
if (cl == 0x14 && ch == 0xEB)
|
||||||
|
type = IDE_ATAPI;
|
||||||
|
else if (cl == 0x69 && ch == 0x96)
|
||||||
|
type = IDE_ATAPI;
|
||||||
|
else
|
||||||
|
continue; // Unknown Type (may not be a device).
|
||||||
|
|
||||||
|
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);
|
||||||
|
clock_sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (V) Read Identification Space of the Device:
|
||||||
|
logk("V\n");
|
||||||
|
ide_read_buffer(i, ATA_REG_DATA, (unsigned int)ide_buf, 128);
|
||||||
|
|
||||||
|
// (VI) Read Device Parameters:
|
||||||
|
logk("VI\n");
|
||||||
|
ide_devices[count].Reserved = 1;
|
||||||
|
ide_devices[count].Type = type;
|
||||||
|
ide_devices[count].Channel = i;
|
||||||
|
ide_devices[count].Drive = j;
|
||||||
|
ide_devices[count].Signature =
|
||||||
|
*((unsigned short *)(ide_buf + ATA_IDENT_DEVICETYPE));
|
||||||
|
ide_devices[count].Capabilities =
|
||||||
|
*((unsigned short *)(ide_buf + ATA_IDENT_CAPABILITIES));
|
||||||
|
ide_devices[count].CommandSets =
|
||||||
|
*((unsigned int *)(ide_buf + ATA_IDENT_COMMANDSETS));
|
||||||
|
|
||||||
|
// (VII) Get Size:
|
||||||
|
logk("VII\n");
|
||||||
|
if (ide_devices[count].CommandSets & (1 << 26))
|
||||||
|
// Device uses 48-Bit Addressing:
|
||||||
|
ide_devices[count].Size =
|
||||||
|
*((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA_EXT));
|
||||||
|
else
|
||||||
|
// Device uses CHS or 28-bit Addressing:
|
||||||
|
ide_devices[count].Size =
|
||||||
|
*((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA));
|
||||||
|
|
||||||
|
// (VIII) String indicates model of device (like Western Digital HDD and
|
||||||
|
// SONY DVD-RW...):
|
||||||
|
logk("VIII\n");
|
||||||
|
for (k = 0; k < 40; k += 2) {
|
||||||
|
ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1];
|
||||||
|
ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k];
|
||||||
|
}
|
||||||
|
ide_devices[count].Model[40] = 0; // Terminate String.
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4- Print Summary:
|
||||||
|
vdisk vd;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
if (ide_devices[i].Reserved == 1) {
|
||||||
|
logk(" %d Found %s Drive %dMB - %s\n", i,
|
||||||
|
(const char *[]){"ATA", "ATAPI"}[ide_devices[i].Type], /* Type */
|
||||||
|
ide_devices[i].Size / 1024 / 2, /* Size */
|
||||||
|
ide_devices[i].Model);
|
||||||
|
strcpy(vd.DriveName, ide_devices[i].Model);
|
||||||
|
vd.flag = 1;
|
||||||
|
vd.Read = Read;
|
||||||
|
vd.Write = Write;
|
||||||
|
vd.size = ide_devices[i].Size;
|
||||||
|
printf("[Disk (%c)]: Size: %dMB Name: %s\n",register_vdisk(vd),vd.size,vd.DriveName);
|
||||||
|
}
|
||||||
|
}
|
327
fs/fat16.c
327
fs/fat16.c
@ -1,327 +0,0 @@
|
|||||||
#include "../include/fat16.h"
|
|
||||||
#include "../include/memory.h"
|
|
||||||
#include "../include/disk.h"
|
|
||||||
|
|
||||||
void read_root_dir_sector1(struct File *root_entries) {
|
|
||||||
read_disk(SECTOR_NUM_OF_ROOT_DIR_START, 1, (unsigned int) root_entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
void save_root_dir_sector1(struct File *root_entries) {
|
|
||||||
write_disk(SECTOR_NUM_OF_ROOT_DIR_START, 1, (unsigned int) root_entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_one_cluster(unsigned short clustno, unsigned int memory_addrress) {
|
|
||||||
read_disk(clustno + SECTOR_CLUSTER_BALANCE, 1, memory_addrress);
|
|
||||||
}
|
|
||||||
|
|
||||||
int read_root_dir(struct File *file_infos) {
|
|
||||||
struct File *root_entries = (struct File *) kmalloc(SECTOR_SIZE);
|
|
||||||
read_root_dir_sector1(root_entries);
|
|
||||||
int n = 0; // 记录文件数
|
|
||||||
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
|
||||||
if (root_entries[i].name[0] == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (root_entries[i].name[0] != 0xe5) {
|
|
||||||
file_infos[n] = root_entries[i];
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kfree(root_entries);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_fat1(unsigned short *fat1) {
|
|
||||||
read_disk(SECTOR_NUM_OF_FAT1_START, FAT1_SECTORS, (unsigned int) fat1); // 将FAT1全部读取到内存中。
|
|
||||||
}
|
|
||||||
|
|
||||||
void save_fat1(unsigned short *fat1) {
|
|
||||||
write_disk(SECTOR_NUM_OF_FAT1_START, FAT1_SECTORS, (unsigned int) fat1); // 将FAT1全部写回到内存中。
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_file_all_clustnos(unsigned short first_clustno, unsigned short *clustnos) {
|
|
||||||
unsigned short *fat1 = kmalloc(FAT1_SECTORS * SECTOR_SIZE);
|
|
||||||
get_fat1(fat1);
|
|
||||||
*clustnos = first_clustno;
|
|
||||||
while (1) {
|
|
||||||
unsigned short clustno = *(fat1 + *clustnos);
|
|
||||||
clustnos++;
|
|
||||||
*clustnos = clustno;
|
|
||||||
if (clustno >= 0xfff8) // 大于等于0xfff8表示文件的最后一个簇
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kfree(fat1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_file(struct File *file, void *file_addr) {
|
|
||||||
if (file->size == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int cluster_count = (file->size + 511) / 512;
|
|
||||||
unsigned short *clustnos = kmalloc(cluster_count * 2);
|
|
||||||
get_file_all_clustnos(file->clustno, clustnos);
|
|
||||||
for (int i = 0; i < cluster_count; i++) {
|
|
||||||
read_one_cluster(clustnos[i], (unsigned int) file_addr);
|
|
||||||
file_addr += 512;
|
|
||||||
}
|
|
||||||
kfree(clustnos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_name_or_ext(char *str, int len) {
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
if (str[i] == 0) {
|
|
||||||
str[i] = ' ';
|
|
||||||
} else if ('a' <= str[i] && str[i] <= 'z') {
|
|
||||||
str[i] -= 0x20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_name_and_ext(char *name, char *ext) {
|
|
||||||
check_name_or_ext(name, 8);
|
|
||||||
check_name_or_ext(ext, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void analyse_fullname(char *fullname, char *name, char *ext) {
|
|
||||||
int ext_dot_index = -1;
|
|
||||||
for (int i = 11; i >= 0; i--) {
|
|
||||||
if (fullname[i] == '.') {
|
|
||||||
ext_dot_index = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ext_dot_index == -1) // 没有后缀名的情况
|
|
||||||
{
|
|
||||||
memcpy(name, fullname, 8);
|
|
||||||
memset(ext, ' ', 3);
|
|
||||||
} else if (ext_dot_index == 0) // 没有文件名的情况
|
|
||||||
{
|
|
||||||
memset(name, ' ', 8);
|
|
||||||
memcpy(ext, fullname + 1, 3);
|
|
||||||
} else {
|
|
||||||
memcpy(name, fullname, ext_dot_index);
|
|
||||||
memcpy(ext, fullname + ext_dot_index + 1, 3);
|
|
||||||
}
|
|
||||||
check_name_and_ext(name, ext);
|
|
||||||
}
|
|
||||||
|
|
||||||
int find_file(char *name, char *ext, struct File *const file) {
|
|
||||||
struct File *root_entries = kmalloc(SECTOR_SIZE);
|
|
||||||
read_root_dir_sector1(root_entries);
|
|
||||||
int isfind = 0;
|
|
||||||
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
|
||||||
if (memcmp(root_entries[i].name, name, 8) == 0 && memcmp(root_entries[i].ext, ext, 3) == 0) {
|
|
||||||
if (file != 0) {
|
|
||||||
*file = root_entries[i];
|
|
||||||
}
|
|
||||||
isfind = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kfree(root_entries);
|
|
||||||
return isfind;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct File *create_dir(char *fullname) {
|
|
||||||
char name[8] = {0};
|
|
||||||
char ext[3] = {0};
|
|
||||||
analyse_fullname(fullname, name, ext);
|
|
||||||
int isfind = find_file(name, ext, 0);
|
|
||||||
if (isfind) {
|
|
||||||
return 0; //文件已存在。
|
|
||||||
}
|
|
||||||
|
|
||||||
struct File *file = (struct File *) kmalloc(32);
|
|
||||||
memcpy(file->name, name, 8);
|
|
||||||
memcpy(file->ext, " ", 3);
|
|
||||||
file->type = 0x10;
|
|
||||||
file->time = 0;
|
|
||||||
file->date = 0;
|
|
||||||
file->clustno = 0;
|
|
||||||
file->size = 0;
|
|
||||||
|
|
||||||
struct File *root_entries = kmalloc(SECTOR_SIZE);
|
|
||||||
read_root_dir_sector1(root_entries);
|
|
||||||
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
|
||||||
if (root_entries[i].name[0] == 0 || root_entries[i].name[0] == 0xe5) { //找一个空闲的文件项存放。
|
|
||||||
root_entries[i] = *file;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
save_root_dir_sector1(root_entries);
|
|
||||||
kfree(root_entries);
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct File *create_file(char *fullname) {
|
|
||||||
char name[8] = {0};
|
|
||||||
char ext[3] = {0};
|
|
||||||
analyse_fullname(fullname, name, ext);
|
|
||||||
int isfind = find_file(name, ext, 0);
|
|
||||||
if (isfind) {
|
|
||||||
return 0; //文件已存在。
|
|
||||||
}
|
|
||||||
|
|
||||||
struct File *file = (struct File *) kmalloc(32);
|
|
||||||
memcpy(file->name, name, 8);
|
|
||||||
memcpy(file->ext, ext, 3);
|
|
||||||
file->type = 0x20;
|
|
||||||
file->time = 0;
|
|
||||||
file->date = 0;
|
|
||||||
file->clustno = 0;
|
|
||||||
file->size = 0;
|
|
||||||
|
|
||||||
struct File *root_entries = kmalloc(SECTOR_SIZE);
|
|
||||||
read_root_dir_sector1(root_entries);
|
|
||||||
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
|
||||||
if (root_entries[i].name[0] == 0 || root_entries[i].name[0] == 0xe5) { //找一个空闲的文件项存放。
|
|
||||||
root_entries[i] = *file;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
save_root_dir_sector1(root_entries);
|
|
||||||
|
|
||||||
kfree(root_entries);
|
|
||||||
//open_file_task(file);
|
|
||||||
kfree(name);
|
|
||||||
kfree(ext);
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct File *open_file(char *fullname) {
|
|
||||||
char name[8] = {0};
|
|
||||||
char ext[3] = {0};
|
|
||||||
analyse_fullname(fullname, name, ext);
|
|
||||||
struct File *file = (struct File *) kmalloc(32);
|
|
||||||
int isfind = find_file(name, ext, file);
|
|
||||||
if (!isfind) {
|
|
||||||
kfree(file);
|
|
||||||
file = 0;
|
|
||||||
} else {
|
|
||||||
//set_opened_file(file);
|
|
||||||
}
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
void alter_file_name(struct File *file, char *new_fullname) {
|
|
||||||
char new_name[8] = {0};
|
|
||||||
char new_ext[3] = {0};
|
|
||||||
analyse_fullname(new_fullname, new_name, new_ext);
|
|
||||||
struct File *root_entries = kmalloc(SECTOR_SIZE);
|
|
||||||
read_root_dir_sector1(root_entries);
|
|
||||||
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
|
||||||
if (memcmp(root_entries[i].name, file->name, 8) == 0 && memcmp(root_entries[i].ext, file->ext, 3) == 0) {
|
|
||||||
memcpy(root_entries[i].name, new_name, 8);
|
|
||||||
memcpy(root_entries[i].ext, new_ext, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
save_root_dir_sector1(root_entries);
|
|
||||||
kfree(root_entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
void alter_dir_entry(struct File *file) {
|
|
||||||
struct File *root_entries = kmalloc(SECTOR_SIZE);
|
|
||||||
read_root_dir_sector1(root_entries);
|
|
||||||
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
|
||||||
if (memcmp(root_entries[i].name, file->name, 8) == 0 && memcmp(root_entries[i].ext, file->ext, 3) == 0) {
|
|
||||||
root_entries[i] = *file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
save_root_dir_sector1(root_entries);
|
|
||||||
kfree(root_entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
void save_file(struct File *file, char *content) {
|
|
||||||
unsigned int file_size = strlen(content); //内容大小
|
|
||||||
if (file_size == 0 && file->size == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
file->size = file_size;
|
|
||||||
int sector_num = (file_size + 511) / 512; //将要占用的扇区数
|
|
||||||
unsigned short *fat1 = kmalloc(FAT1_SECTORS * SECTOR_SIZE);
|
|
||||||
get_fat1(fat1);
|
|
||||||
unsigned short clustno = file->clustno;
|
|
||||||
unsigned short next_clustno;
|
|
||||||
if (file->clustno == 0) //第一次写入
|
|
||||||
{
|
|
||||||
clustno = 2; //可用簇号从2开始
|
|
||||||
while (1) {
|
|
||||||
if (*(fat1 + clustno) == 0) //空闲簇号
|
|
||||||
{
|
|
||||||
file->clustno = clustno; //分配起始簇号
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
clustno++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int i = 0;
|
|
||||||
while (1) {
|
|
||||||
write_disk(SECTOR_CLUSTER_BALANCE + clustno, 1, (unsigned int) content);
|
|
||||||
if (i == sector_num - 1) { //已写完最后一扇区。
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
content += 512;
|
|
||||||
next_clustno = *(fat1 + clustno);
|
|
||||||
if (next_clustno == 0 || next_clustno >= 0xfff8) { //寻找下一个可用簇号
|
|
||||||
next_clustno = clustno + 1;
|
|
||||||
while (1) {
|
|
||||||
if (*(fat1 + next_clustno) == 0) {
|
|
||||||
*(fat1 + clustno) = next_clustno;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
next_clustno++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clustno = next_clustno;
|
|
||||||
}
|
|
||||||
next_clustno = *(fat1 + clustno);
|
|
||||||
*(fat1 + clustno) = 0xffff; //0xfff8~0xffff表示文件结束,没有下一个簇了。
|
|
||||||
//如果本次写入的内容比上次的少,上次用过的簇号本次用不完,以下将剩下的簇号清零处理。
|
|
||||||
if (1 < next_clustno && next_clustno < 0xfff0) {
|
|
||||||
while (1) {
|
|
||||||
clustno = next_clustno;
|
|
||||||
next_clustno = *(fat1 + clustno);
|
|
||||||
*(fat1 + clustno) = 0;
|
|
||||||
if (next_clustno >= 0xfff8) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
alter_dir_entry(file);
|
|
||||||
save_fat1(fat1);
|
|
||||||
kfree(fat1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete_file(struct File *file) {
|
|
||||||
//1.标记目录项为已删除。
|
|
||||||
struct File *root_entries = kmalloc(SECTOR_SIZE);
|
|
||||||
read_root_dir_sector1(root_entries);
|
|
||||||
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
|
||||||
if (memcmp(root_entries[i].name, file->name, 8) == 0 && memcmp(root_entries[i].ext, file->ext, 3) == 0) {
|
|
||||||
root_entries[i].name[0] = 0xe5;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
save_root_dir_sector1(root_entries);
|
|
||||||
kfree(root_entries);
|
|
||||||
if (file->clustno == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
unsigned short *fat1 = kmalloc(FAT1_SECTORS * SECTOR_SIZE);
|
|
||||||
get_fat1(fat1);
|
|
||||||
unsigned short clustno = file->clustno;
|
|
||||||
unsigned short next_clustno = 0;
|
|
||||||
while (1) {
|
|
||||||
next_clustno = *(fat1 + clustno);
|
|
||||||
*(fat1 + clustno) = 0;
|
|
||||||
if (next_clustno >= 0xfff8) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
clustno = next_clustno;
|
|
||||||
}
|
|
||||||
save_fat1(fat1);
|
|
||||||
kfree(fat1);
|
|
||||||
}
|
|
236
fs/file.c
236
fs/file.c
@ -1,236 +0,0 @@
|
|||||||
#include "../include/file.h"
|
|
||||||
#include "../include/memory.h"
|
|
||||||
#include "../include/common.h"
|
|
||||||
|
|
||||||
int fseek(FILE *fp, int offset, int whence) {
|
|
||||||
if (whence == 0) {
|
|
||||||
fp->p = offset;
|
|
||||||
} else if (whence == 1) {
|
|
||||||
fp->p += offset;
|
|
||||||
} else if (whence == 2) {
|
|
||||||
fp->p = fp->fileSize + offset;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
long ftell(FILE *stream) { return stream->p; }
|
|
||||||
|
|
||||||
FILE *fopen(char *filename, char *mode) {
|
|
||||||
unsigned int flag = 0;
|
|
||||||
FILE *fp = (FILE *)kmalloc(sizeof(FILE));
|
|
||||||
while (*mode != '\0') {
|
|
||||||
switch (*mode) {
|
|
||||||
case 'a':
|
|
||||||
flag |= APPEND;
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
flag |= READ;
|
|
||||||
break;
|
|
||||||
case 'w':
|
|
||||||
flag |= WRITE;
|
|
||||||
break;
|
|
||||||
case '+':
|
|
||||||
flag |= PLUS;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mode++;
|
|
||||||
}
|
|
||||||
if (vfs_filesize(filename) == -1) {
|
|
||||||
kfree(fp);
|
|
||||||
return NULL; // 找不到
|
|
||||||
} else if (flag & WRITE) {
|
|
||||||
char buffe2[100];
|
|
||||||
// vfs_delfile(filename);
|
|
||||||
// vfs_createfile(filename);
|
|
||||||
}
|
|
||||||
if (flag & WRITE) {
|
|
||||||
fp->fileSize = 0;
|
|
||||||
} else {
|
|
||||||
fp->fileSize = vfs_filesize(filename);
|
|
||||||
}
|
|
||||||
fp->bufferSize = 0;
|
|
||||||
if (flag & READ || flag & PLUS || flag & APPEND) {
|
|
||||||
fp->bufferSize = vfs_filesize(filename);
|
|
||||||
// printk("[Set]BufferSize=%d\n",fp->bufferSize);
|
|
||||||
}
|
|
||||||
if (flag & WRITE || flag & PLUS || flag & APPEND) {
|
|
||||||
fp->bufferSize += 100;
|
|
||||||
}
|
|
||||||
if (fp->bufferSize == 0) {
|
|
||||||
fp->bufferSize = 1;
|
|
||||||
}
|
|
||||||
fp->buffer = kmalloc(fp->bufferSize);
|
|
||||||
if (flag & PLUS || flag & APPEND || flag & READ) {
|
|
||||||
// printk("ReadFile........\n");
|
|
||||||
vfs_readfile(filename, fp->buffer);
|
|
||||||
}
|
|
||||||
fp->p = 0;
|
|
||||||
if (flag & APPEND) {
|
|
||||||
fp->p = fp->fileSize;
|
|
||||||
}
|
|
||||||
fp->name = kmalloc(strlen(filename) + 1);
|
|
||||||
strcpy(fp->name, filename);
|
|
||||||
fp->mode = flag;
|
|
||||||
// printk("[fopen]BufferSize=%d\n",fp->bufferSize);
|
|
||||||
return fp;
|
|
||||||
}
|
|
||||||
int fgetc(FILE *stream) {
|
|
||||||
if (CANREAD(stream->mode)) {
|
|
||||||
if (stream->p >= stream->fileSize) {
|
|
||||||
return EOF;
|
|
||||||
} else {
|
|
||||||
return stream->buffer[stream->p++];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int fputc(int ch, FILE *stream) {
|
|
||||||
if (CANWRITE(stream->mode)) {
|
|
||||||
// printk("Current Buffer=%s\n",stream->buffer);
|
|
||||||
if (stream->p >= stream->bufferSize) {
|
|
||||||
// printk("Realloc....(%d,%d)\n",stream->p,stream->bufferSize);
|
|
||||||
stream->buffer = realloc(stream->buffer, stream->bufferSize + 100);
|
|
||||||
stream->bufferSize += 100;
|
|
||||||
}
|
|
||||||
if (stream->p >= stream->fileSize) {
|
|
||||||
stream->fileSize++;
|
|
||||||
}
|
|
||||||
// printk("Current Buffer=%s(A)\n",stream->buffer);
|
|
||||||
stream->buffer[stream->p++] = ch;
|
|
||||||
// printk("Current Buffer=%s(B)\n",stream->buffer);
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
unsigned int fwrite(const void *ptr, unsigned int size, unsigned int nmemb,
|
|
||||||
FILE *stream) {
|
|
||||||
if (CANWRITE(stream->mode)) {
|
|
||||||
unsigned char *c_ptr = (unsigned char *)ptr;
|
|
||||||
for (int i = 0; i < size * nmemb; i++) {
|
|
||||||
fputc(c_ptr[i], stream);
|
|
||||||
}
|
|
||||||
return nmemb;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unsigned int fread(void *buffer, unsigned int size, unsigned int count,
|
|
||||||
FILE *stream) {
|
|
||||||
if (CANREAD(stream->mode)) {
|
|
||||||
unsigned char *c_ptr = (unsigned char *)buffer;
|
|
||||||
for (int i = 0; i < size * count; i++) {
|
|
||||||
unsigned int ch = fgetc(stream);
|
|
||||||
if (ch == EOF) {
|
|
||||||
return i;
|
|
||||||
} else {
|
|
||||||
c_ptr[i] = ch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int fclose(FILE *fp) {
|
|
||||||
if (fp == NULL) {
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
if (CANWRITE(fp->mode)) {
|
|
||||||
// printk("Save file.....(%s) Size =
|
|
||||||
//%d\n",fp->buffer,fp->fileSize);
|
|
||||||
// Edit_File(fp->name, fp->buffer, fp->fileSize, 0);
|
|
||||||
vfs_writefile(fp->name, fp->buffer, fp->fileSize);
|
|
||||||
}
|
|
||||||
kfree(fp->buffer);
|
|
||||||
kfree(fp->name);
|
|
||||||
kfree(fp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
char *fgets(char *str, int n, FILE *stream) {
|
|
||||||
if (CANREAD(stream->mode)) {
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
unsigned int ch = fgetc(stream);
|
|
||||||
if (ch == EOF) {
|
|
||||||
if (i == 0) {
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ch == '\n') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
str[i] = ch;
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
int fputs(const char *str, FILE *stream) {
|
|
||||||
if (CANWRITE(stream->mode)) {
|
|
||||||
for (int i = 0; i < strlen(str); i++) {
|
|
||||||
fputc(str[i], stream);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
int fprintf(FILE *stream, const char *format, ...) {
|
|
||||||
if (CANWRITE(stream->mode)) {
|
|
||||||
int len;
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, format);
|
|
||||||
char *buf = kmalloc(1024);
|
|
||||||
len = vsprintf(buf, format, ap);
|
|
||||||
fputs(buf, stream);
|
|
||||||
kfree(buf);
|
|
||||||
va_end(ap);
|
|
||||||
return len;
|
|
||||||
} else {
|
|
||||||
// printk("CAN NOT WRITE\n");
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int feof(FILE *stream) {
|
|
||||||
if (stream->p >= stream->fileSize) {
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int ferror(FILE *stream) { return 0; }
|
|
||||||
int fsz(char *filename) { return vfs_filesize(filename); }
|
|
||||||
|
|
||||||
void EDIT_FILE(char *name, char *dest, int length, int offset) {
|
|
||||||
if (vfs_filesize(name) == -1) {
|
|
||||||
//没有找到文件,创建一个,然后再编辑
|
|
||||||
vfs_createfile(name);
|
|
||||||
EDIT_FILE(name, dest, length, offset);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vfs_writefile(name, dest, length);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int Copy(char *path, char *path1) {
|
|
||||||
unsigned char *path1_file_buffer;
|
|
||||||
if (fsz(path) == -1) {
|
|
||||||
// printk("file not found\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// printk("-----------------------------\n");
|
|
||||||
vfs_createfile(path1);
|
|
||||||
|
|
||||||
path1_file_buffer = kmalloc(fsz(path) + 1);
|
|
||||||
int sz = fsz(path);
|
|
||||||
vfs_readfile(path, path1_file_buffer);
|
|
||||||
vfs_writefile(path1, path1_file_buffer, sz);
|
|
||||||
kfree(path1_file_buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
#ifndef CPOS_DISK_H
|
|
||||||
#define CPOS_DISK_H
|
|
||||||
|
|
||||||
void wait_disk_ready(); //不适用于SATA硬盘
|
|
||||||
void select_sector(int lba);
|
|
||||||
void read_disk_one_sector(int lba, unsigned int memory_addrress);
|
|
||||||
void write_disk_one_sertor(int lba, unsigned int memory_addrress);
|
|
||||||
void read_disk(int lba, int sector_count, unsigned int memory_addrress);
|
|
||||||
void write_disk(int lba, int sector_count, unsigned int memory_addrress);
|
|
||||||
|
|
||||||
#endif
|
|
115
include/fat.h
115
include/fat.h
@ -1,115 +0,0 @@
|
|||||||
#ifndef CRASHPOWEROS_FAT_H
|
|
||||||
#define CRASHPOWEROS_FAT_H
|
|
||||||
|
|
||||||
#define BS_jmpBoot 0
|
|
||||||
#define BS_OEMName 3
|
|
||||||
#define BPB_BytsPerSec 11
|
|
||||||
#define BPB_SecPerClus 13
|
|
||||||
#define BPB_RsvdSecCnt 14
|
|
||||||
#define BPB_NumFATs 16
|
|
||||||
#define BPB_RootEntCnt 17
|
|
||||||
#define BPB_TotSec16 19
|
|
||||||
#define BPB_Media 21
|
|
||||||
#define BPB_FATSz16 22
|
|
||||||
#define BPB_SecPerTrk 24
|
|
||||||
#define BPB_NumHeads 26
|
|
||||||
#define BPB_HiddSec 28
|
|
||||||
#define BPB_TotSec32 32
|
|
||||||
#define BPB_FATSz32 36
|
|
||||||
#define BPB_ExtFlags 40
|
|
||||||
#define BPB_FSVer 42
|
|
||||||
#define BPB_RootClus 44
|
|
||||||
#define BPB_FSInfo 48
|
|
||||||
#define BPB_BkBootSec 50
|
|
||||||
#define BPB_Reserved 52
|
|
||||||
#define BPB_Fat32ExtByts 28
|
|
||||||
#define BS_DrvNum 36
|
|
||||||
#define BS_Reserved1 37
|
|
||||||
#define BS_BootSig 38
|
|
||||||
#define BS_VolD 39
|
|
||||||
#define BS_VolLab 43
|
|
||||||
#define BS_FileSysType 54
|
|
||||||
#define EOF -1
|
|
||||||
#define SEEK_SET 0
|
|
||||||
#define SEEK_CUR 1
|
|
||||||
#define SEEK_END 2
|
|
||||||
|
|
||||||
#define get_dm(vfs) ((fat_cache *)(vfs->cache))->dm
|
|
||||||
#define get_now_dir(vfs) ((fat_cache *)(vfs->cache))->dir
|
|
||||||
#define get_clustno(high, low) (high << 16) | (low & 0xffff)
|
|
||||||
#define clustno_end(type) 0xfffffff & ((((1 << (type - 1)) - 1) << 1) + 1)
|
|
||||||
#define rmfarptr2ptr(x) ((x).seg * 0x10 + (x).offset)
|
|
||||||
|
|
||||||
#include "../include/common.h"
|
|
||||||
#include "vfs.h"
|
|
||||||
|
|
||||||
struct FAT_CACHE {
|
|
||||||
unsigned int ADR_DISKIMG;
|
|
||||||
struct FAT_FILEINFO *root_directory;
|
|
||||||
struct LIST *directory_list;
|
|
||||||
struct LIST *directory_max_list;
|
|
||||||
struct LIST *directory_clustno_list;
|
|
||||||
int *fat;
|
|
||||||
int FatMaxTerms;
|
|
||||||
unsigned int ClustnoBytes;
|
|
||||||
unsigned short RootMaxFiles;
|
|
||||||
unsigned int RootDictAddress;
|
|
||||||
unsigned int FileDataAddress;
|
|
||||||
unsigned int imgTotalSize;
|
|
||||||
unsigned short SectorBytes;
|
|
||||||
unsigned int Fat1Address, Fat2Address;
|
|
||||||
unsigned char *FatClustnoFlags;
|
|
||||||
int type;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
struct FAT_CACHE dm;
|
|
||||||
struct FAT_FILEINFO *dir;
|
|
||||||
} fat_cache;
|
|
||||||
|
|
||||||
struct FAT_FILEINFO {
|
|
||||||
unsigned char name[8], ext[3], type;
|
|
||||||
char reserve;
|
|
||||||
unsigned char create_time_tenth;
|
|
||||||
unsigned short create_time, create_date, access_date, clustno_high;
|
|
||||||
unsigned short update_time, update_date, clustno_low;
|
|
||||||
unsigned int size;
|
|
||||||
};
|
|
||||||
|
|
||||||
void read_fat(unsigned char *img, int *fat, unsigned char *ff, int max,int type);
|
|
||||||
int get_directory_max(struct FAT_FILEINFO *directory, vfs_t *vfs);
|
|
||||||
void file_loadfile(int clustno, int size, char *buf, int *fat, vfs_t *vfs);
|
|
||||||
void file_savefile(int clustno, int size, char *buf, int *fat,
|
|
||||||
unsigned char *ff, vfs_t *vfs);
|
|
||||||
void file_saveinfo(struct FAT_FILEINFO *directory, vfs_t *vfs);
|
|
||||||
void file_savefat(int *fat, int clustno, int length, vfs_t *vfs);
|
|
||||||
int mkfile(char *name, vfs_t *vfs);
|
|
||||||
int del(char *cmdline, vfs_t *vfs);
|
|
||||||
int deldir(char *path, vfs_t *vfs);
|
|
||||||
int format(char drive);
|
|
||||||
int attrib(char *filename, ftype type, struct vfs_t *vfs);
|
|
||||||
void Register_fat_fileSys();
|
|
||||||
struct FAT_FILEINFO *Get_dictaddr(char *path1, vfs_t *vfs);
|
|
||||||
void Fat_CopyCache(struct vfs_t *dest, struct vfs_t *src);
|
|
||||||
bool Fat_cd(struct vfs_t *vfs, char *dictName);
|
|
||||||
bool Fat_ReadFile(struct vfs_t *vfs, char *path, char *buffer);
|
|
||||||
bool Fat_WriteFile(struct vfs_t *vfs, char *path, char *buffer, int size);
|
|
||||||
List *Fat_ListFile(struct vfs_t *vfs, char *dictpath);
|
|
||||||
bool Fat_RenameFile(struct vfs_t *vfs, char *filename, char *filename_of_new);
|
|
||||||
bool Fat_CreateFile(struct vfs_t *vfs, char *filename);
|
|
||||||
bool Fat_DelFile(struct vfs_t *vfs, char *path);
|
|
||||||
bool Fat_DelDict(struct vfs_t *vfs, char *path);
|
|
||||||
void Fat_DeleteFs(struct vfs_t *vfs);
|
|
||||||
bool Fat_Check(uint8_t disk_number);
|
|
||||||
int Fat_FileSize(struct vfs_t *vfs, char *filename);
|
|
||||||
bool Fat_Format(uint8_t disk_number);
|
|
||||||
bool Fat_CreateDict(struct vfs_t *vfs, char *filename);
|
|
||||||
bool Fat_Attrib(struct vfs_t *vfs, char *filename, ftype type);
|
|
||||||
vfs_file *Fat_FileInfo(struct vfs_t *vfs, char *filename);
|
|
||||||
void fat_InitFS(struct vfs_t *vfs, uint8_t disk_number);
|
|
||||||
int get_directory_max(struct FAT_FILEINFO *directory, vfs_t *vfs);
|
|
||||||
int mkdir(char *dictname, int last_clust, vfs_t *vfs);
|
|
||||||
int rename(char *src_name, char *dst_name, vfs_t *vfs);
|
|
||||||
int changedict(char *dictname, vfs_t *vfs);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,48 +0,0 @@
|
|||||||
#ifndef CPOS_FAT16_H
|
|
||||||
#define CPOS_FAT16_H
|
|
||||||
|
|
||||||
#define SECTOR_SIZE 512
|
|
||||||
#define FAT1_SECTORS 32 //FAT1占用扇区数
|
|
||||||
#define ROOT_DIR_SECTORS 32 //根目录占用扇区数
|
|
||||||
#define SECTOR_NUM_OF_FAT1_START 1 //FAT1起始扇区号
|
|
||||||
#define SECTOR_NUM_OF_ROOT_DIR_START 33 //根目录起始扇区号
|
|
||||||
#define SECTOR_NUM_OF_DATA_START 65 //数据区起始扇区号,对应簇号为2。
|
|
||||||
#define SECTOR_CLUSTER_BALANCE SECTOR_NUM_OF_DATA_START - 2 //簇号加上该值正好对应扇区号。
|
|
||||||
#define MAX_FILE_NUM 16 //最大文件数
|
|
||||||
|
|
||||||
// FAT16目录项结构(32B);
|
|
||||||
struct File {
|
|
||||||
// 文件名 如果第一个字节为0xe5,代表这个文件已经被删除;如果第一个字节为0x00,代表这一段不包含任何文件名信息。
|
|
||||||
unsigned char name[8];
|
|
||||||
unsigned char ext[3]; // 扩展名
|
|
||||||
// 属性:bit0只读文件,bit1隐藏文件,bit2系统文件,bit3非文件信息(比如磁盘名称),bit4目录,bit5文件。
|
|
||||||
unsigned char type; // 0x20 文件 | 0x10 目录
|
|
||||||
unsigned char reserve[10]; // 保留
|
|
||||||
unsigned short time; // 最后一次写入时间
|
|
||||||
unsigned short date; // 最后一次写入日期
|
|
||||||
unsigned short clustno; // 起始簇号
|
|
||||||
unsigned int size; // 文件大小
|
|
||||||
};
|
|
||||||
|
|
||||||
void read_root_dir_sector1(struct File *root_entries);
|
|
||||||
void save_root_dir_sector1(struct File *root_entries);
|
|
||||||
void read_one_cluster(unsigned short clustno, unsigned int memory_addrress);
|
|
||||||
int read_root_dir(struct File *file_infos);
|
|
||||||
void get_fat1(unsigned short *fat1);
|
|
||||||
void save_fat1(unsigned short *fat1);
|
|
||||||
void get_file_all_clustnos(unsigned short first_clustno, unsigned short *clustnos);
|
|
||||||
void get_file_all_clustnos(unsigned short first_clustno, unsigned short *clustnos);
|
|
||||||
void read_file(struct File *file, void *file_addr);
|
|
||||||
void check_name_or_ext(char *str, int len);
|
|
||||||
void check_name_and_ext(char *name, char *ext);
|
|
||||||
void analyse_fullname(char *fullname, char *name, char *ext);
|
|
||||||
int find_file(char *name, char *ext, struct File *const file);
|
|
||||||
struct File *create_file(char *fullname);
|
|
||||||
struct File *create_dir(char *fullname);
|
|
||||||
struct File *open_file(char *fullname);
|
|
||||||
void alter_file_name(struct File *file, char *new_fullname);
|
|
||||||
void alter_dir_entry(struct File *file);
|
|
||||||
void save_file(struct File *file, char *content);
|
|
||||||
void delete_file(struct File *file);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,33 +0,0 @@
|
|||||||
#ifndef CRASHPOWEROS_FILE_H
|
|
||||||
#define CRASHPOWEROS_FILE_H
|
|
||||||
|
|
||||||
#define READ 0x2
|
|
||||||
#define WRITE 0x4
|
|
||||||
#define APPEND 0x8
|
|
||||||
#define BIN 0x0
|
|
||||||
#define PLUS 0x10
|
|
||||||
#define CANREAD(flag) ((flag)&READ || (flag)&PLUS)
|
|
||||||
#define CANWRITE(flag) ((flag)&WRITE || (flag)&PLUS || (flag)&APPEND)
|
|
||||||
|
|
||||||
#include "../include/vfs.h"
|
|
||||||
|
|
||||||
int fseek(FILE *fp, int offset, int whence);
|
|
||||||
long ftell(FILE *stream);
|
|
||||||
FILE *fopen(char *filename, char *mode);
|
|
||||||
int fgetc(FILE *stream);
|
|
||||||
int fputc(int ch, FILE *stream);
|
|
||||||
unsigned int fwrite(const void *ptr, unsigned int size, unsigned int nmemb,
|
|
||||||
FILE *stream);
|
|
||||||
unsigned int fread(void *buffer, unsigned int size, unsigned int count,
|
|
||||||
FILE *stream);
|
|
||||||
int fclose(FILE *fp);
|
|
||||||
char *fgets(char *str, int n, FILE *stream);
|
|
||||||
int fputs(const char *str, FILE *stream);
|
|
||||||
int fprintf(FILE *stream, const char *format, ...);
|
|
||||||
int feof(FILE *stream);
|
|
||||||
int ferror(FILE *stream);
|
|
||||||
int fsz(char *filename);
|
|
||||||
void EDIT_FILE(char *name, char *dest, int length, int offset);
|
|
||||||
int Copy(char *path, char *path1);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,71 +0,0 @@
|
|||||||
#ifndef CRASHPOWEROS_FLOPPY_H
|
|
||||||
#define CRASHPOWEROS_FLOPPY_H
|
|
||||||
|
|
||||||
#define DG144_HEADS 2 /* 每个磁道中的磁头数 (1.44M) */
|
|
||||||
#define DG144_TRACKS 80 /* 每个驱动器的磁道数 (1.44M) */
|
|
||||||
#define DG144_SPT 18 /* 每个磁头中的的扇区数 (1.44M) */
|
|
||||||
#define DG144_GAP3FMT 0x54 /* GAP3格式化 (1.44M) */
|
|
||||||
#define DG144_GAP3RW 0x1b /* GAP3(读/写) (1.44M) */
|
|
||||||
|
|
||||||
#define DG168_HEADS 2 /* 每个磁道中的磁头数 (1.68M) */
|
|
||||||
#define DG168_TRACKS 80 /* 每个驱动器的磁道数 (1.68M) */
|
|
||||||
#define DG168_SPT 21 /* 每个磁头中的的扇区数 (1.68M) */
|
|
||||||
#define DG168_GAP3FMT 0x0c /* GAP3格式化 (1.68M) */
|
|
||||||
#define DG168_GAP3RW 0x1c /* GAP3(读/写) (1.68M) */
|
|
||||||
|
|
||||||
/* i/o端口定义 */
|
|
||||||
#define FDC_DOR (0x3f2) /* 数字输出寄存器 */
|
|
||||||
#define FDC_MSR (0x3f4) /* 主要状态寄存器(输入) */
|
|
||||||
#define FDC_DRS (0x3f4) /* DRS寄存器 */
|
|
||||||
#define FDC_DATA (0x3f5) /* 数据寄存器 */
|
|
||||||
#define FDC_DIR (0x3f7) /* 数字输入寄存器(输入) */
|
|
||||||
#define FDC_CCR (0x3f7) /* CCR寄存器 */
|
|
||||||
|
|
||||||
/* 软盘命令 */
|
|
||||||
#define CMD_SPECIFY (0x03) /* 指定驱动器计时 */
|
|
||||||
#define CMD_WRITE (0xc5) /* 写(写入数据的最小单位是扇区) */
|
|
||||||
#define CMD_READ (0xe6) /* 读(读取扇区的最小单位是扇区) */
|
|
||||||
#define CMD_RECAL (0x07) /* 重新校准软盘 */
|
|
||||||
#define CMD_SENSEI (0x08) /* 中断状态 */
|
|
||||||
#define CMD_FORMAT (0x4d) /* 格式化磁道 */
|
|
||||||
#define CMD_SEEK (0x0f) /* 寻找磁道 */
|
|
||||||
#define CMD_VERSION (0x10) /* 获取软盘驱动器的版本 */
|
|
||||||
#define SECTORS_ONCE 4
|
|
||||||
|
|
||||||
#include "isr.h"
|
|
||||||
|
|
||||||
typedef struct DrvGeom {
|
|
||||||
unsigned char heads;
|
|
||||||
unsigned char tracks;
|
|
||||||
unsigned char spt; /* 每轨扇区数 */
|
|
||||||
} DrvGeom;
|
|
||||||
|
|
||||||
int getbyte();
|
|
||||||
void sendbyte(int byte);
|
|
||||||
void motoron(void);
|
|
||||||
void motoroff(void);
|
|
||||||
void recalibrate(void);
|
|
||||||
void init_floppy();
|
|
||||||
void hts2block(int track, int head, int sector, int* block);
|
|
||||||
void block2hts(int block, int* track, int* head, int* sector);
|
|
||||||
int seek(int track);
|
|
||||||
void wait_floppy_interrupt();
|
|
||||||
void reset(void);
|
|
||||||
int fdc_rw(int block,
|
|
||||||
unsigned char* blockbuff,
|
|
||||||
int read,
|
|
||||||
unsigned long nosectors);
|
|
||||||
void flint(registers_t *reg);
|
|
||||||
int write_floppy_for_ths(int track,
|
|
||||||
int head,
|
|
||||||
int sec,
|
|
||||||
unsigned char* blockbuff,
|
|
||||||
unsigned long nosec);
|
|
||||||
int fdc_rw_ths(int track,
|
|
||||||
int head,
|
|
||||||
int sector,
|
|
||||||
unsigned char* blockbuff,
|
|
||||||
int read,
|
|
||||||
unsigned long nosectors);
|
|
||||||
|
|
||||||
#endif
|
|
98
include/ide.h
Normal file
98
include/ide.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#ifndef CRASHPOWEROS_IDE_H
|
||||||
|
#define CRASHPOWEROS_IDE_H
|
||||||
|
|
||||||
|
#define ATA_SR_BSY 0x80 // Busy
|
||||||
|
#define ATA_SR_DRDY 0x40 // Drive ready
|
||||||
|
#define ATA_SR_DF 0x20 // Drive write fault
|
||||||
|
#define ATA_SR_DSC 0x10 // Drive seek complete
|
||||||
|
#define ATA_SR_DRQ 0x08 // Data request ready
|
||||||
|
#define ATA_SR_CORR 0x04 // Corrected data
|
||||||
|
#define ATA_SR_IDX 0x02 // Index
|
||||||
|
#define ATA_SR_ERR 0x01 // Error
|
||||||
|
#define ATA_ER_BBK 0x80 // Bad block
|
||||||
|
#define ATA_ER_UNC 0x40 // Uncorrectable data
|
||||||
|
#define ATA_ER_MC 0x20 // Media changed
|
||||||
|
#define ATA_ER_IDNF 0x10 // ID mark not found
|
||||||
|
#define ATA_ER_MCR 0x08 // Media change request
|
||||||
|
#define ATA_ER_ABRT 0x04 // Command aborted
|
||||||
|
#define ATA_ER_TK0NF 0x02 // Track 0 not found
|
||||||
|
#define ATA_ER_AMNF 0x01 // No address mark
|
||||||
|
#define ATA_CMD_READ_PIO 0x20
|
||||||
|
#define ATA_CMD_READ_PIO_EXT 0x24
|
||||||
|
#define ATA_CMD_READ_DMA 0xC8
|
||||||
|
#define ATA_CMD_READ_DMA_EXT 0x25
|
||||||
|
#define ATA_CMD_WRITE_PIO 0x30
|
||||||
|
#define ATA_CMD_WRITE_PIO_EXT 0x34
|
||||||
|
#define ATA_CMD_WRITE_DMA 0xCA
|
||||||
|
#define ATA_CMD_WRITE_DMA_EXT 0x35
|
||||||
|
#define ATA_CMD_CACHE_FLUSH 0xE7
|
||||||
|
#define ATA_CMD_CACHE_FLUSH_EXT 0xEA
|
||||||
|
#define ATA_CMD_PACKET 0xA0
|
||||||
|
#define ATA_CMD_IDENTIFY_PACKET 0xA1
|
||||||
|
#define ATA_CMD_IDENTIFY 0xEC
|
||||||
|
#define ATAPI_CMD_READ 0xA8
|
||||||
|
#define ATAPI_CMD_EJECT 0x1B
|
||||||
|
#define ATA_IDENT_DEVICETYPE 0
|
||||||
|
#define ATA_IDENT_CYLINDERS 2
|
||||||
|
#define ATA_IDENT_HEADS 6
|
||||||
|
#define ATA_IDENT_SECTORS 12
|
||||||
|
#define ATA_IDENT_SERIAL 20
|
||||||
|
#define ATA_IDENT_MODEL 54
|
||||||
|
#define ATA_IDENT_CAPABILITIES 98
|
||||||
|
#define ATA_IDENT_FIELDVALID 106
|
||||||
|
#define ATA_IDENT_MAX_LBA 120
|
||||||
|
#define ATA_IDENT_COMMANDSETS 164
|
||||||
|
#define ATA_IDENT_MAX_LBA_EXT 200
|
||||||
|
#define IDE_ATA 0x00
|
||||||
|
#define IDE_ATAPI 0x01
|
||||||
|
|
||||||
|
#define ATA_MASTER 0x00
|
||||||
|
#define ATA_SLAVE 0x01
|
||||||
|
#define ATA_REG_DATA 0x00
|
||||||
|
#define ATA_REG_ERROR 0x01
|
||||||
|
#define ATA_REG_FEATURES 0x01
|
||||||
|
#define ATA_REG_SECCOUNT0 0x02
|
||||||
|
#define ATA_REG_LBA0 0x03
|
||||||
|
#define ATA_REG_LBA1 0x04
|
||||||
|
#define ATA_REG_LBA2 0x05
|
||||||
|
#define ATA_REG_HDDEVSEL 0x06
|
||||||
|
#define ATA_REG_COMMAND 0x07
|
||||||
|
#define ATA_REG_STATUS 0x07
|
||||||
|
#define ATA_REG_SECCOUNT1 0x08
|
||||||
|
#define ATA_REG_LBA3 0x09
|
||||||
|
#define ATA_REG_LBA4 0x0A
|
||||||
|
#define ATA_REG_LBA5 0x0B
|
||||||
|
#define ATA_REG_CONTROL 0x0C
|
||||||
|
#define ATA_REG_ALTSTATUS 0x0C
|
||||||
|
#define ATA_REG_DEVADDRESS 0x0D
|
||||||
|
// Channels:
|
||||||
|
#define ATA_PRIMARY 0x00
|
||||||
|
#define ATA_SECONDARY 0x01
|
||||||
|
|
||||||
|
// Directions:
|
||||||
|
#define ATA_READ 0x00
|
||||||
|
#define ATA_WRITE 0x01
|
||||||
|
|
||||||
|
unsigned char ide_read(unsigned char channel, unsigned char reg);
|
||||||
|
void ide_write(unsigned char channel, unsigned char reg, unsigned char data);
|
||||||
|
void ide_read_buffer(unsigned char channel, unsigned char reg,
|
||||||
|
unsigned int buffer, unsigned int quads);
|
||||||
|
unsigned char ide_polling(unsigned char channel, unsigned int advanced_check);
|
||||||
|
unsigned char ide_print_error(unsigned int drive, unsigned char err);
|
||||||
|
void ide_wait_irq();
|
||||||
|
void ide_irq();
|
||||||
|
unsigned char ide_ata_access(unsigned char direction, unsigned char drive,
|
||||||
|
unsigned int lba, unsigned char numsects,
|
||||||
|
unsigned short selector, unsigned int edi);
|
||||||
|
void ide_write_sectors(unsigned char drive, unsigned char numsects,
|
||||||
|
unsigned int lba, unsigned short es, unsigned int edi);
|
||||||
|
void ide_read_sectors(unsigned char drive, unsigned char numsects,
|
||||||
|
unsigned int lba, unsigned short es, unsigned int edi);
|
||||||
|
unsigned char ide_atapi_read(unsigned char drive, unsigned int lba,
|
||||||
|
unsigned char numsects, unsigned short selector,
|
||||||
|
unsigned int edi);
|
||||||
|
void ide_atapi_eject(unsigned char drive);
|
||||||
|
void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
|
||||||
|
unsigned int BAR3, unsigned int BAR4);
|
||||||
|
|
||||||
|
#endif
|
@ -2,7 +2,6 @@
|
|||||||
#define CRASHPOWEROS_PCAT_H
|
#define CRASHPOWEROS_PCAT_H
|
||||||
|
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "fat16.h"
|
|
||||||
|
|
||||||
struct pcat_process{
|
struct pcat_process{
|
||||||
uint32_t line;
|
uint32_t line;
|
||||||
|
@ -9,5 +9,6 @@ int vsprintf(char *buf, const char *fmt, va_list args);
|
|||||||
int sprintf(char *buf, const char *fmt, ...);
|
int sprintf(char *buf, const char *fmt, ...);
|
||||||
void printf(const char *formet, ...);
|
void printf(const char *formet, ...);
|
||||||
void print(char *message);
|
void print(char *message);
|
||||||
|
void printk(const char *formet, ...);
|
||||||
|
|
||||||
#endif //CRASHPOWEROS_PRINTF_H
|
#endif //CRASHPOWEROS_PRINTF_H
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
#include "../include/vdisk.h"
|
#include "../include/vdisk.h"
|
||||||
#include "../include/pci.h"
|
#include "../include/pci.h"
|
||||||
#include "../include/pcnet.h"
|
#include "../include/pcnet.h"
|
||||||
#include "../include/fat.h"
|
#include "../include/ide.h"
|
||||||
#include "../include/floppy.h"
|
#include "../include/vfs.h"
|
||||||
|
|
||||||
extern uint32_t end;
|
extern uint32_t end;
|
||||||
extern int status;
|
extern int status;
|
||||||
@ -71,8 +71,7 @@ void kernel_main(multiboot_t *multiboot) {
|
|||||||
init_vdisk();
|
init_vdisk();
|
||||||
init_pci();
|
init_pci();
|
||||||
init_vfs();
|
init_vfs();
|
||||||
//init_floppy();
|
ide_initialize(0x1F0, 0x3F6, 0x170, 0x376, 0x000);
|
||||||
Register_fat_fileSys();
|
|
||||||
syscall_install();
|
syscall_install();
|
||||||
|
|
||||||
if(pcnet_find_card()){
|
if(pcnet_find_card()){
|
||||||
@ -85,7 +84,7 @@ void kernel_main(multiboot_t *multiboot) {
|
|||||||
|
|
||||||
clock_sleep(25);
|
clock_sleep(25);
|
||||||
|
|
||||||
kernel_thread(setup_shell, NULL, "CPOS-Shell");
|
//kernel_thread(setup_shell, NULL, "CPOS-Shell");
|
||||||
launch_date();
|
launch_date();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include "../include/common.h"
|
#include "../include/common.h"
|
||||||
#include "../include/task.h"
|
#include "../include/task.h"
|
||||||
#include "../include/cmos.h"
|
#include "../include/cmos.h"
|
||||||
#include "../include/fat16.h"
|
|
||||||
#include "../include/pcat.h"
|
#include "../include/pcat.h"
|
||||||
|
|
||||||
extern Queue *key_char_queue;
|
extern Queue *key_char_queue;
|
||||||
@ -95,60 +94,7 @@ void cmd_date(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cmd_ls() {
|
void cmd_ls() {
|
||||||
struct File *root = (struct File *) kmalloc(sizeof(struct File) * MAX_FILE_NUM);
|
|
||||||
int files = read_root_dir(root);
|
|
||||||
int index = 0, size = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < files; ++i) {
|
|
||||||
struct File file = root[i];
|
|
||||||
if (!strcmp(file.name, "\0")) continue;
|
|
||||||
printf("%s %s %d\n", file.name, file.type == 0x20 ? "<FILE>" : " <DIR> ", file.size);
|
|
||||||
index++;
|
|
||||||
size += file.size;
|
|
||||||
}
|
|
||||||
printf(" All File: %d | All Size: %dByte\n", index, size);
|
|
||||||
kfree(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmd_cat(int argc, char **argv) {
|
|
||||||
if (argc <= 2) {
|
|
||||||
printf("\033[Shell-CAT]: If there are too few parameters, please specify the filename and util.\036\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct File *file = open_file(argv[1]);
|
|
||||||
if (file == NULL) {
|
|
||||||
printf("\033[Shell-CAT]: Not found [%s]\036 \n", argv[1]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *buffer[1024] = {0};
|
|
||||||
|
|
||||||
for (int i = 2; i < argc; i++) {
|
|
||||||
if (i == 2) strcat(buffer, "");
|
|
||||||
else strcat(buffer, " ");
|
|
||||||
strcat(buffer, argv[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
save_file(file, buffer);
|
|
||||||
kfree(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmd_read(int argc, char **argv) {
|
|
||||||
if (argc == 1) {
|
|
||||||
printf("\033[Shell-READ]: If there are too few parameters, please specify the filename.\036\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct File *file = open_file(argv[1]);
|
|
||||||
char *buffer = (char *) kmalloc(sizeof(char) * 4096);
|
|
||||||
if (file == NULL) {
|
|
||||||
printf("\033[Shell-READ]: Not found [%s]\036 \n", argv[1]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
read_file(file, buffer);
|
|
||||||
printf("%s\n", buffer);
|
|
||||||
kfree(buffer);
|
|
||||||
kfree(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_mkdir(int argc, char **argv) {
|
void cmd_mkdir(int argc, char **argv) {
|
||||||
@ -157,12 +103,7 @@ void cmd_mkdir(int argc, char **argv) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf("Create directory: %s\n",argv[1]);
|
printf("Create directory: %s\n",argv[1]);
|
||||||
struct File *dir = create_dir(argv[1]);
|
|
||||||
if (dir == NULL) {
|
|
||||||
printf("\033[Shell-MKDIR]: Cannot create directory '%s'.\036\n", argv[1]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
kfree(dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_del(int argc, char **argv) {
|
void cmd_del(int argc, char **argv) {
|
||||||
@ -170,13 +111,7 @@ void cmd_del(int argc, char **argv) {
|
|||||||
vga_writestring("\033[Shell-DEL]: If there are too few parameters, please specify the folder name.\036\n");
|
vga_writestring("\033[Shell-DEL]: If there are too few parameters, please specify the folder name.\036\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct File *info = open_file(argv[1]);
|
|
||||||
if (info == NULL) {
|
|
||||||
printf("\033[Shell-DEL]: Not found [%s]\036 \n", argv[1]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
delete_file(info);
|
|
||||||
kfree(info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_reset(){
|
void cmd_reset(){
|
||||||
@ -215,16 +150,7 @@ void cmd_pcat(int argc,char **argv){
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char name[8] = {0};
|
|
||||||
char ext[3] = {0};
|
|
||||||
analyse_fullname(argv[1], name, ext);
|
|
||||||
int isfind = find_file(name, ext, 0);
|
|
||||||
struct File* file;
|
|
||||||
if(isfind){
|
|
||||||
file = open_file(argv[1]);
|
|
||||||
} else file = create_file(argv[1]);
|
|
||||||
|
|
||||||
pcat_launch(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_shell(){
|
void setup_shell(){
|
||||||
@ -258,10 +184,6 @@ void setup_shell(){
|
|||||||
cmd_date();
|
cmd_date();
|
||||||
else if (!strcmp("ls", argv[0]))
|
else if (!strcmp("ls", argv[0]))
|
||||||
cmd_ls();
|
cmd_ls();
|
||||||
else if (!strcmp("cat", argv[0]))
|
|
||||||
cmd_cat(argc, argv);
|
|
||||||
else if (!strcmp("read", argv[0]))
|
|
||||||
cmd_read(argc, argv);
|
|
||||||
else if (!strcmp("mkdir", argv[0]))
|
else if (!strcmp("mkdir", argv[0]))
|
||||||
cmd_mkdir(argc, argv);
|
cmd_mkdir(argc, argv);
|
||||||
else if (!strcmp("del", argv[0]) || !strcmp("rm", argv[0]))
|
else if (!strcmp("del", argv[0]) || !strcmp("rm", argv[0]))
|
||||||
@ -280,8 +202,6 @@ void setup_shell(){
|
|||||||
vga_writestring("version \032Print os version.\036\n");
|
vga_writestring("version \032Print os version.\036\n");
|
||||||
vga_writestring("echo <msg> \032Print message.\036\n");
|
vga_writestring("echo <msg> \032Print message.\036\n");
|
||||||
vga_writestring("ls \032List all files.\036\n");
|
vga_writestring("ls \032List all files.\036\n");
|
||||||
vga_writestring("cat <name> <util> \032Edit a file.\036\n");
|
|
||||||
vga_writestring("read <name> \032Read a file.\036\n");
|
|
||||||
vga_writestring("mkdir <name> \032Make a directory.\036\n");
|
vga_writestring("mkdir <name> \032Make a directory.\036\n");
|
||||||
vga_writestring("del rm <name> \032Delete a file.\036\n");
|
vga_writestring("del rm <name> \032Delete a file.\036\n");
|
||||||
vga_writestring("sysinfo \032Print system info.\036\n");
|
vga_writestring("sysinfo \032Print system info.\036\n");
|
||||||
|
@ -281,6 +281,15 @@ int sprintf(char *buf, const char *fmt, ...) {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printk(const char *formet, ...) {
|
||||||
|
int len;
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, formet);
|
||||||
|
char *buf[1024] = {0};
|
||||||
|
len = vsprintf(buf, formet, ap);
|
||||||
|
print(buf);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
void printf(const char *formet, ...) {
|
void printf(const char *formet, ...) {
|
||||||
int len;
|
int len;
|
||||||
|
Loading…
Reference in New Issue
Block a user