* ------------------------------------------------------------------------
*/
#include <ata.h>
+#include <disk.h>
#include <ide.h>
#include <io.h>
#include <irq.h>
#include <sched.h>
#include <string.h>
#include <system.h>
-#include <types.h>
-#include <wait.h>
extern ide_pci_controller_t ide_pci_controller;
// 3. 等到status的DRQ位或ERR位设置
u16 identify[256];
void ata_send_read_identify_cmd(int dev) {}
-void ata_read_identify(int dev) { // 这里所用的dev是逻辑编号 ATA0、ATA1下的Master、Salve的dev分别为0,1,2,3
+void ata_read_data(int dev, int sect_cnt, void *dst) { insl(REG_DATA(dev), dst, (512 * sect_cnt) / sizeof(uint32_t)); }
+
+void ata_read_identify(int dev) {
+ outb(0x00, REG_CTL(dev));
+ outb(0x00 | ((dev & 0x01) << 4), REG_DEVICE(dev)); // 根据文档P113,这里不用指定bit5, bit7,直接指示DRIVE就行
+
+ unsigned long flags;
+ irq_save(flags);
+
+ outb(ATA_CMD_IDENTIFY, REG_CMD(dev));
+ wait_on_ide();
+
+ irq_restore(flags);
+}
+
+void ata_init() {
+ disk_request_t r;
+ r.buf = (void *)identify;
+ r.count = 1;
+ r.pos = 0;
+ r.command = DISK_REQ_IDENTIFY;
+
+ send_disk_request(&r);
+
+ // 第49个word的第8个bit位表示是否支持DMA
+ // 第83个word的第10个bit位表示是否支持LBA48,为1表示支持。
+ // 第100~103个word的八个字节表示user的LBA最大值
+ printk("%04x %04x %d %d\n", identify[49], 1 << 8, identify[49] & (1 << 8), (identify[49] & (1 << 8)) != 0);
+ if ((identify[49] & (1 << 8)) != 0) {
+ printk("support DMA\n");
+ }
+
+ if ((identify[83] & (1 << 10)) != 0) {
+ printk("support LBA48\n");
+
+ u64 lba = *(u64 *)(identify + 100);
+ printk("hard disk size: %u MB\n", (lba * 512) >> 20);
+ }
+}
+
+void ata_read_identify_old(int dev) { // 这里所用的dev是逻辑编号 ATA0、ATA1下的Master、Salve的dev分别为0,1,2,3
+ // void send_disk_request();
+ // send_disk_request();
// DECLARE_WAIT_QUEUE_HEAD(wq_head);
// DECLARE_WAIT_QUEUE(wait, current);
// add_wait_queue(&wq_head, &wait);
if (r) {
buf[cnt++] = ch;
- task->state = TASK_RUNNING;
+ task->state = TASK_READY;
del_wait_queue(&rdwq, &wait);
if (ch == '\n') goto end;
// }
// // printd("%s pid %d is really running\n", __func__, sysc_getpid());
-// task->state = TASK_RUNNING;
+// task->state = TASK_READY;
// del_wait_queue(&r->wait, &wait);
// }
DECLARE_WAIT_QUEUE_HEAD(ide_wait_queue_head);
void sleep_on_ide() { sleep_on(&ide_wait_queue_head); }
+
+void prepare_to_wait_on_ide() { ide_pci_controller.done = 0; }
void wait_on_ide() { wait_event(&ide_wait_queue_head, ide_pci_controller.done); }
extern void *mbr_buf;
printk("ide pci status after interrupt: %x\n", ata_pci_bus_status());
-#if 0
- unsigned int v = pci_read_config_word(pci_cmd(ide_pci_controller.pci, PCI_COMMAND));
- pci_write_config_word(v & (~PCI_COMMAND_MASTER), pci_cmd(ide_pci_controller.pci, PCI_COMMAND));
-
- uint16_t *p = (uint16_t *)mbr_buf;
- for (int i = 0; i < 256; i++) {
- if (i % 12 == 0) {
- printk("\n%03d ", i);
- }
- printk("%04x ", p[i]);
- }
-#endif
-
ide_pci_controller.done = 1;
wake_up(&ide_wait_queue_head);
-
- // ide_pci_controller.task->state = TASK_RUNNING;
}
void ide_init() {
// init_pci_controller(0x0106);
init_pci_controller(0x0101);
-
- // ide_detect();
- // return;
- // ide_read_identify();
- ata_read_identify(0);
- return;
-
- // // 还没开启中断
- // ide_read_partition();
-
- // ide_printl();
}
--- /dev/null
+/*
+ * ------------------------------------------------------------------------
+ * File Name: disk.h
+ * Author: Zhao Yanbai
+ * 2021-11-21 22:08:16 Sunday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#pragma once
+
+#include <list.h>
+#include <semaphore.h>
+#include <types.h>
+#include <wait.h>
+
+typedef enum {
+ DISK_REQ_IDENTIFY,
+ DISK_REQ_READ,
+} disk_request_cmd_t;
+
+typedef struct disk_request {
+ uint64_t pos; // 扇区号
+ uint16_t count; // 扇区数
+ void *buf; // 到的缓冲区
+ disk_request_cmd_t command; // 命令
+ list_head_t list;
+ wait_queue_head_t wait; // 等待队列
+ // 驱动器完全有可能在进程在进程睡眠到等待队列前返回数据并执行唤醒操作
+ // 这时等待队列上无进程,就相当于不执行任何操作
+ // 然后进程再睡眠到等待队列上,就会造成永远无法唤醒该进程
+ // 因此要添加一个字段,标志驱动器已经对该请求做过唤醒操作
+ // 进程在睡眠前需要检查该字段
+ int done;
+} disk_request_t;
+
+typedef struct {
+ uint32_t count;
+ semaphore_t sem;
+ list_head_t list;
+} disk_request_queue_t;
+
+void send_disk_request(disk_request_t *r);
\ No newline at end of file
struct list_head *prev, *next;
} list_head_t;
-// TODO Remove
-typedef list_head_t ListHead, *pListHead;
-
#define LIST_HEAD_INIT(name) \
{ &(name), &(name) }
#define LIST_HEAD(name) list_head_t name = LIST_HEAD_INIT(name)
enum {
TASK_UNUSED,
- TASK_RUNNING,
+ TASK_READY,
TASK_WAIT,
TASK_INITING,
TASK_EXITING,
typedef unsigned long long u64_t;
typedef unsigned char uint8_t;
+typedef char int8_t;
typedef unsigned short uint16_t;
+typedef short int16_t;
typedef unsigned long uint32_t;
+typedef long int32_t;
typedef unsigned long long uint64_t;
+typedef long long int64_t;
typedef unsigned long pid_t;
typedef unsigned long mode_t;
p->delay_cnt -= p->delay_cnt == 0 ? 0 : 1;
if (0 == p->delay_cnt) {
- p->state = TASK_RUNNING;
+ p->state = TASK_READY;
list_del(&p->pend);
}
}
list_add(&tsk->list, &all_tasks);
irq_restore(iflags);
- tsk->state = TASK_RUNNING;
+ tsk->state = TASK_READY;
return (int)tsk->pid;
}
root_task.pid = get_next_pid();
root_task.ppid = 0;
- root_task.state = TASK_RUNNING;
+ root_task.state = TASK_READY;
root_task.weight = TASK_INIT_WEIGHT;
root_task.priority = 100;
strcpy(root_task.name, "root");
static const char *task_state(unsigned int state) {
static const char s[][16] = {
- " ERROR", "RUNNING", " WAIT", "INITING", "EXITING",
+ " ERROR", "READY", " WAIT", " INIT", " EXIT",
};
if (state >= TASK_END) {
bool need_reset_weight = true;
list_for_each_safe(pos, t, &all_tasks) {
p = list_entry(pos, task_union, list);
- if (p->state != TASK_RUNNING) {
+ if (p->state != TASK_READY) {
continue;
}
if (p->weight < p->priority) {
if (need_reset_weight) {
list_for_each_safe(pos, t, &all_tasks) {
p = list_entry(pos, task_union, list);
- if (p->state != TASK_RUNNING) {
+ if (p->state != TASK_READY) {
continue;
}
p->weight = 0;
list_for_each_safe(pos, t, &all_tasks) {
p = list_entry(pos, task_union, list);
- if (p->state != TASK_RUNNING) {
+ if (p->state != TASK_READY) {
continue;
}
void debug_sched() {
task_union *p = list_entry(current->list.next, task_union, list);
- p->state = (p->state == TASK_RUNNING) ? TASK_WAIT : TASK_RUNNING;
+ p->state = (p->state == TASK_READY) ? TASK_WAIT : TASK_READY;
}
void down(semaphore_t *s) {
unsigned long iflags;
irq_save(iflags);
-
if (likely(s->cnt > 0)) {
s->cnt--;
} else {
list_del(&waiter->list);
waiter->up = 1;
- waiter->task->state = TASK_RUNNING;
+ waiter->task->state = TASK_READY;
}
void up(semaphore_t *s) {
unsigned long iflags;
irq_save(iflags);
- if (likely(list_empty(&s->wait_list))) {
+ // if (likely(list_empty(&s->wait_list))) {
+ if (list_empty(&s->wait_list)) {
+ printk("++++++\n");
s->cnt++;
} else {
+ printk("upupupuppupupup\n");
__up(s);
}
extern tty_t monitor_tty;
tty_switch(&monitor_tty);
+
+ void ide_init();
+ ide_init();
}
// 在开中断的情况下继续初始化的内容
void setup_under_irq() {
- void ide_init();
- ide_init();
+ void ata_init();
+ ata_init();
return;
setup_fs();
}
\ No newline at end of file
// 下一次系统调用还可能走到这里
// 所以这里就直接判断不是RUNNING就返回
// 不再操作delay_tasks链表
- if (current->state != TASK_RUNNING) {
+ if (current->state != TASK_READY) {
return 0;
}
* ------------------------------------------------------------------------
*/
+#include <disk.h>
#include <sched.h>
-#include <semaphore.h>
-#include <wait.h>
-
-#if 0
-typedef enum {
- DISK_REQ_IDENTIFY,
- DISK_REQ_READ,
-} disk_request_cmd_t;
-
-typedef struct disk_request {
- uint64_t pos; // 扇区号
- uint16_t count; // 扇区数
- void *buf; // 到的缓冲区
- disk_request_cmd_t command; // 命令
- wait_queue_head_t wait; // 等待队列
- // 驱动器完全有可能在进程在进程睡眠到等待队列前返回数据并执行唤醒操作
- // 这时等待队列上无进程,就相当于不执行任何操作
- // 然后进程再睡眠到等待队列上,就会造成永远无法唤醒该进程
- // 因此要添加一个字段,标志驱动器已经对该请求做过唤醒操作
- // 进程在睡眠前需要检查该字段
- int done;
-} disk_request_t;
-
-void send_disk_request() {
- disk_request_t r;
- r.pos = 0;
- r.count = 1;
- r.buf = kmalloc(512, 0);
- r.command = DISK_REQ_IDENTIFY;
- INIT_LIST_HEAD(&r.wait.task_list);
- r.done = 0;
-
- list_add_tail(&wq->task_list, &head->task_list);
- // 发送命令
- //....
+disk_request_queue_t disk_request_queue; // = {.count = 0,
+ // .sem = SEMAPHORE_INITIALIZER(disk_request_queue.sem, 0),
+ // .list = LIST_HEAD_INIT(disk_request_queue.list)};
+
+void disk_init() {
+ disk_request_queue.count = 0;
+ disk_request_queue.sem.cnt = 0;
+ INIT_LIST_HEAD(&disk_request_queue.sem.wait_list);
+ INIT_LIST_HEAD(&disk_request_queue.list);
+}
+
+#if 1
+void send_disk_request(disk_request_t *r) {
+ if (NULL == r) {
+ panic("null disk request");
+ }
+
+ // 校验pos,和pos+count是否大于硬盘返回的最大LBA48
+ // ...
+
+ // 校验buffer是否跨64K
+ // 先不处理
+ if (((uint32_t)r->buf & 0xFFFF0000) != (((uint32_t)(r->buf + r->count * 512)) & 0xFFFF0000)) {
+ panic("disk DMA read cross 64K");
+ }
+ INIT_LIST_HEAD(&r->wait.task_list);
+ r->done = 0;
+ // r.pos = pos;
+ // r.count = count;
+ // r.buf = kmalloc(512, 0);
+ // r.command = DISK_REQ_IDENTIFY;
+ // INIT_LIST_HEAD(&r.wait.task_list);
+ // r.done = 0;
+
+ // printk("do send disk request: %d %x %x %x\n", list_empty(&disk_request_queue.sem.wait_list),
+ // &disk_request_queue.sem.wait_list, disk_request_queue.sem.wait_list.next,
+ // disk_request_queue.sem.wait_list.prev);
+
+ // 发送命令
unsigned long flags;
irq_save(flags);
- if (0 == r.done) { // 驱动器还没完成
- set_current_state(TASK_WAIT);
- irq_restore(flags);
- // 就算在schedule前驱动器触发中断也没有问题
- // 因为该进程已经加到等待队列上了
- // 所以它一定以唤醒该进程
- schedule();
- } else { // 驱动器已经完成
- irq_restore(flags);
- }
-}
-#endif
+ list_add_tail(&r->list, &disk_request_queue.list);
+ irq_restore(flags);
-typedef struct {
- semaphore_t sem;
- list_head_t list;
-} disk_request_queue_t;
+ // 唤醒task_disk
+ printk("up sem\n");
+ up(&disk_request_queue.sem);
-disk_request_queue_t disk_request_queue = {.sem = SEMAPHORE_INITIALIZER(disk_request_queue.sem, 0),
- .list = LIST_HEAD_INIT(disk_request_queue.list)};
+ // 等待task_dist结束
+ printk("wait event\n");
+ wait_event(&r->wait, r->done != 0);
+
+ printk("wait finished\n");
+}
+#endif
-int cnt = 0;
void disk_task_entry() {
while (1) {
- printk("fuck you: %d\n", cnt);
+ void prepare_to_wait_on_ide();
+ prepare_to_wait_on_ide();
+
+ printk("wait for new hard disk request\n");
down(&disk_request_queue.sem);
- printk("fuck me: %d\n", cnt);
- cnt++;
+ printk("hard disk request: %d\n", disk_request_queue.count++);
+
+ unsigned long flags;
+ irq_save(flags);
+
+ disk_request_t *r;
+ if (list_empty(&disk_request_queue.list)) {
+ } else {
+ r = list_first_entry(&disk_request_queue.list, disk_request_t, list);
+ if (NULL == r) {
+ panic("no disk request");
+ }
+
+ printk("disk request: pos %ld count %d cmd %d\n", r->pos, r->count, r->command);
+ }
+
+ irq_restore(flags);
+
+ if (NULL == r) {
+ continue;
+ }
+
+ int dev = 0;
+ switch (r->command) {
+ case DISK_REQ_IDENTIFY:
+ assert(r->count == 1);
+ void ata_read_identify(int dev);
+ ata_read_identify(dev);
+ break;
+
+ default:
+ break;
+ }
+
+ // 等待硬盘中断
+ void wait_on_ide();
+ wait_on_ide();
+
+ // 读数据
+ if (DISK_REQ_IDENTIFY == r->command) {
+ void ata_read_data(int dev, int sect_cnt, void *dst);
+ ata_read_data(dev, 1, r->buf);
+ }
+
+ // 唤醒等待该请求的进程
+ r->done = 1;
+ wake_up(&r->wait);
}
}
// 所以得先清空一下键盘
inb(0x60);
+ //
+ void disk_init();
+ disk_init();
+
kernel_task("init", init_task_entry);
kernel_task("disk", disk_task_entry);
kernel_task("user", user_task_entry);
}
void __end_wait(wait_queue_head_t *head, wait_queue_t *wq) {
- set_current_state(TASK_RUNNING);
+ set_current_state(TASK_READY);
unsigned long flags;
irq_save(flags);
list_del_init(&wq->task_list);
irq_save(flags);
list_for_each_entry_safe(p, tmp, &head->task_list, task_list) {
list_del(&p->task_list);
- printk("wakeup: %s\nread sector 0 with LBA48 and DMA", p->task->name);
- p->task->state = TASK_RUNNING;
+ printk("wakeup: %s\n", p->task->name);
+ p->task->state = TASK_READY;
--nr;
if (nr == 0) {
}
printd("pid %d is really running\n", sysc_getpid());
- task->state = TASK_RUNNING;
+ task->state = TASK_READY;
del_wait_queue(&debug_wq, &wait);
return v;
schedule();
}
- task->state = TASK_RUNNING;
+ task->state = TASK_READY;
del_wait_queue(&p->wait, &wait);
return 0;
// Add %012d %012x %12d %12x Support Mon, 20 Jul 2009 19:30:34
// Add %u Support Sun, 06 Jul 2014 12:07:54
// ========================================================================
+#include <types.h>
+
#include "string.h"
char *itoa(char *s, int n);
char *itou(char *s, unsigned int n);
char *itox(char *s, unsigned int n);
+char *i64tou(char *s, int64_t n);
enum { ALIGN_RIGHT, ALIGN_LEFT };
itoa(tmp, *((int *)args));
p += write_buf(p, tmp, char_fill, char_cnt, align);
break;
+ case 'l':
+ fmt++;
+ if (*fmt == 'u' || *fmt == 'd') { // d u都当成u来处理
+ i64tou(tmp, *((int64_t *)args));
+ p += write_buf(p, tmp, char_fill, char_cnt, align);
+ args += 4;
+ }
+ break;
case 's':
p += write_buf(p, (const char *)*((unsigned int *)args), char_fill, char_cnt, align);
break;
}
}
+char *i64tou(char *s, int64_t n) {
+ itou(s, n >> 32);
+ int i = 0;
+ if ((n >> 32) > 0) {
+ i = strlen(s);
+ }
+ itou(s + i, n & 0xFFFFFFFF);
+}
+
char *itou(char *s, unsigned int n) {
char c;
char *p = s;
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Allmost Copy From Linux */
+typedef struct list_head {
+ struct list_head *prev, *next;
+} list_head_t;
+
+#define LIST_HEAD_INIT(name) \
+ { &(name), &(name) }
+#define LIST_HEAD(name) list_head_t name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) \
+ do { \
+ (ptr)->next = (ptr); \
+ (ptr)->prev = (ptr); \
+ } while (0)
+
+#define list_entry(ptr, type, member) ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
+
+#define list_first_entry(ptr, type, member) list_entry((ptr)->next, type, member)
+
+#define list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define list_for_each_safe(pos, tmp, head) \
+ for (pos = (head)->next, tmp = pos->next; pos != (head); pos = tmp, tmp = pos->next)
+
+#define list_for_each_entry_safe(pos, tmp, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ tmp = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); pos = tmp, tmp = list_entry(tmp->member.next, typeof(*tmp), member))
+
+static inline void _list_add(list_head_t *pnew, list_head_t *prev, list_head_t *next) {
+ next->prev = pnew;
+ pnew->next = next;
+ pnew->prev = prev;
+ prev->next = pnew;
+}
+
+static inline void list_add(list_head_t *pnew, list_head_t *head) { _list_add(pnew, head, head->next); }
+
+static inline void list_add_tail(list_head_t *pnew, list_head_t *head) { _list_add(pnew, head->prev, head); }
+
+static inline void _list_del(list_head_t *prev, list_head_t *next) {
+ next->prev = prev;
+ prev->next = next;
+}
+
+static inline void list_del(list_head_t *entry) {
+ _list_del(entry->prev, entry->next);
+ entry->prev = NULL;
+ entry->next = NULL;
+}
+
+static inline void list_del_init(list_head_t *entry) {
+ _list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+static inline int list_empty(list_head_t *head) { return head->next == head; }
+
+typedef struct node {
+ int id;
+ list_head_t list;
+ list_head_t pend;
+} node_t;
+
+LIST_HEAD(allH);
+LIST_HEAD(pendH);
+
+int main() {
+ INIT_LIST_HEAD(&allH);
+ INIT_LIST_HEAD(&pendH);
+
+ for (int i = 0; i < 10; i++) {
+ node_t *n = (node_t *)malloc(sizeof(node_t));
+ n->id = i;
+ list_add(&n->list, &allH);
+ if (n->id % 3 == 0) {
+ list_add(&n->pend, &pendH);
+ }
+ }
+
+ list_head_t *pos;
+ list_head_t *tmp;
+ node_t *p, *p1;
+ list_for_each_safe(pos, tmp, &allH) {
+ p = list_entry(pos, node_t, list);
+ printf("allH: %d\n", p->id);
+ }
+
+ printf("-----\n");
+ list_for_each_safe(pos, tmp, &pendH) {
+ p = list_entry(pos, node_t, pend);
+ printf("pendH: %d\n", p->id);
+ }
+
+ // list_for_each_safe(pos, tmp, &allH) {
+
+ // p = list_entry(pos, node_t, list);
+ list_for_each_entry_safe(p, p1, &pendH, pend) {
+ // printf("%d\n", p->id);
+ if (p->id == 3) {
+ list_del(&p->pend);
+ }
+ }
+
+ printf("-----\n");
+
+ list_for_each_safe(pos, tmp, &allH) {
+ p = list_entry(pos, node_t, list);
+ printf("allH: %d\n", p->id);
+ }
+
+ printf("-----\n");
+ list_for_each_safe(pos, tmp, &pendH) {
+ p = list_entry(pos, node_t, pend);
+ printf("pendH: %d\n", p->id);
+ }
+}
\ No newline at end of file