mac.asm
[BITS 32]
[GLOBAL _netinitial] ;我们必须导出这个函数让C程序使用,注意此函数名不用出现在头文件里
[SECTION .data]
ns db 0xEC,0x17,0x2F,0xF4,0xC5,0xA2,0xB0,0xC4,0x20,0xA1,0x3C,0x00,0x08,0x00,0x45,0x00,0x00,0x54,0x00,0x10,0x00,0x00,0x40,0x01,0xE5,0x24,0xC0,0xA8,0x01,0x63,0x6F,0x0D,0x64,0x5C,0x08,0x00,0x96,0x98,0x2B,0x00,0x00,0x00,0x44,0x45,0xF3,0x55,0x0C,0xC9,0x07,0x00,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x48,0x65,0x6C,0x6C,0x6F,0x20,0x77,0x6F,0x72,0x6C, 0x64,0x21,
;;Hello world! -> 48 65 6C 6C 6F 20 77 6F 72 6C 64 21
[SECTION .text]
_netinitial: ;入口
pushad
ioNo equ 0xc040 ;一定要以数字开头,不能用ioNo dw 0c000h
mov edi, 0x4001c0 ;内存中存放节点的缓冲区首址0x4001c0 待改
mov dx,ioNo ;CR命令寄存器
mov al,0x21 ;选择页面0,总清网卡,看看里面是什么,一开始选择页面0是因为许多寄存器在页面0里
;强制DMA结束
out dx,al
mov dx,ioNo+0xa
xor al,0x6
out dx,al
mov dx,ioNo+0xb
xor al,1
out dx,al
mov dx,ioNo+0xc
mov al,0xe0 ;monitor mode (no packet receive)
out dx,al
mov dx,ioNo+0xd
mov al,0xe2 ;loop back mode
out dx,al
;;使用0x40-0x4B为网卡的发送缓冲区,共12页,刚好可以存储2个最大的以太网包。
;;使用0x4c-0x7f为网卡的接收缓冲区,共52页。
mov dx,ioNo+0x01
mov al,0x4c ;Pstart 接收缓冲区范围
out dx,al
mov dx,ioNo+0x02
mov al,0x80 ;Pstop
out dx,al
mov dx,ioNo+0x03
mov al,0x4c ;BNRY设置指针
out dx,al
mov dx,ioNo+0x07
mov al,0xff ;清除所有中断标志位
out dx,al
mov dx,ioNo+0x0f
mov al,0x00 ;IMR disable all interrupt
out dx,al
mov dx,ioNo+0x0e
;;mov al,0x49 ;DCR设置数据配置寄存器,规定远程传输方式使用PIO
mov al,0xc8 ;DCR设置数据配置寄存器,使用FIFO缓存,普通模式,8位数据DMA;
out dx,al
;;下面转到页面1
mov dx,ioNo
mov al,0x62 ;选择页面1,加电start,强制DMA结束
out dx,al
;;给页面1前PDR0~5写入mac值
mov cx,6 ;循环6次
mov ebx,6 ;从数组[6]开始
mov dx,ioNo+1 ;PAR0
next1:
mov al,[ns + ebx]
out dx,al ;写网卡
inc dx
inc bx
dec cx
jnz next1 ;cx不为0则继续
mov dx,ioNo+0x07
mov al,0x4d ;CURR是RTL8019AS写内存的指针,指向当前正在写的页的下一页,初始化时指向0x4c+1=0x4d;
out dx,al
;;再次选择页面0
;;将网卡设置成正常的模式,跟外部网络连接
mov dx,ioNo ;CR命令寄存器
mov al,0x22 ;选择页面0,start网卡,强制DMA结束
out dx,al
mov dx,ioNo+0xc
mov al,0xcc ;RCR设置接收配置寄存器,使用接收缓冲区,仅接收自己地址的数据包(以及广播地址数据包)和多点播送地址包,小于64字节的包丢弃,校验错的数据包不接收;
out dx,al
mov dx,ioNo+0xd
mov al,0xe0 ;TCR 设置发送配置寄存器,启用CRC自动生成和自动校验,工作在正常模式;
out dx,al
mov dx,ioNo+0x07
mov al,0xff ;清除所有中断标志位
out dx,al
;;之后启动远程DMA,数据写入RTL8019AS的RAM,再启动本地DMA,将数据发送网上。
mov dx,ioNo+0x08
mov al,0x00 ;RSAR0寄存器为远程开始地址低8位
out dx,al
mov dx,ioNo+0x09
mov al,0x40 ;RSAR1寄存器为远程开始地址高8位
out dx,al
mov dx,ioNo
mov al,0x12 ;远程DMA写页面0开始
out dx,al
mov cx,98 ;循环98次
mov ebx,0
mov dx,ioNo+0x10 ;远程DMA读写端口
next2:
mov al,[ns+ebx]
out dx,al ;依次写入到网卡rom 0x4000
inc ebx
dec cx
jnz next2 ;cx不为0则继续
;;之后启动远程DMA,数据写入RTL8019AS的RAM的0x4000,再启动本地DMA,将数据发送网上。
mov dx,ioNo+0x08
mov al,0x00 ;RSAR0寄存器为远程开始地址低8位
out dx,al
mov dx,ioNo+0x09
mov al,0x40 ;RSAR1寄存器为远程开始地址高8位
out dx,al
mov dx,ioNo+0x04
mov al,0x40 ;TPSR 发送页的起始页地址,初始化为指向第一个发送缓冲区的页即0x40
out dx,al
mov dx,ioNo+0x05
mov al,0x62 ;TBCR0 发送字节计数 98字节,低八位
out dx,al
mov dx,ioNo+0x06
mov al,0x00 ;TBCR1 发送字节计数器,高八位
out dx,al
mov dx,ioNo
mov al,0x16 ;禁远程DMA,页面0,网卡加电,发送
out dx,al
popad
ret
graph.h
#ifndef _GRAPH_H_
#define _GRAPH_H_
// 色调合成函数
unsigned short rgb_mix( unsigned char r , unsigned char g , unsigned char b ) ;
// 画点函数
void draw_dot( unsigned int x , unsigned int y , unsigned short color ) ;
// 显示英文
void ya_draw_english( unsigned int x , unsigned int y , unsigned int pos_in_font , unsigned short color ) ;
// 显示汉字
void ya_draw_chinese( unsigned int x , unsigned int y , unsigned int pos_in_font , unsigned short color ) ;
// 显示字符串
void ya_draw_chars( int x, int y, char *chars , unsigned short color) ;
// 显示四位bmp图片
void ya_draw_4bit_bmp( unsigned int x , unsigned int y ,unsigned int addr) ;
//画块,旋转
void draw_trunk(int addr_begin, int x, int y, int a, int b, unsigned short color) ;
#endif
port.h
#ifndef _PORT_H_
#define _PORT_H_
unsigned char readb( unsigned short p ) ;
unsigned short readw( unsigned short p ) ;
unsigned int readl( unsigned short p ) ;
void writeb( unsigned short p , unsigned char val ) ;
void writew( unsigned short p , unsigned short val ) ;
void writel( unsigned short p , unsigned int val ) ;
#endif
pciprobe.h
#ifndef _PCIPROBE_H_
#define _PCIPROBE_H_
#define CONFIG_ADDRESS 0xCF8 //Configure register used to read configure space. PCI的地址寄存器IO地址
#define CONFIG_DATA 0xCFC //Data register. PCI的数据寄存器IO地址
int PciBusProbe();
void PciProbe() ;
void netcardprobe() ;
#endif
makefile
######################
#声明要编译的所有组成,这里的ya是本工程名称,可以取任何名字,这里就用ya
######################
ya:out/boot.bin out/kernelloader.bin out/kernel.asmo out/kernel.o out/graph.o out/port.o out/pciprobe.o out/mac.asmo out/kernel.ld out/kernel.bin out/creat_img.exe out/write_in_img.exe A B C D E F G H
#开始对各部分编译,注意不是空格是Tab键
out/boot.bin:code/boot.asm
nasm code/boot.asm -o out/boot.bin
out/kernelloader.bin:code/kernelloader.asm
nasm code/kernelloader.asm -o out/kernelloader.bin
# 编译asm文件,生成中间文件
out/kernel.asmo:code/kernel.asm
nasm -f aout code/kernel.asm -o out/kernel.asmo
out/mac.asmo:code/mac.asm
nasm -f aout code/mac.asm -o out/mac.asmo
# 编译C文件,生成中间文件
out/kernel.o:code/kernel.c
gcc -fpack-struct -std=c99 -c code/kernel.c -o out/kernel.o
out/graph.o:code/graph.c
gcc -fpack-struct -std=c99 -Wno-packed-bitfield-compat -c code/graph.c -o out/graph.o
out/port.o:code/port.c
gcc -fpack-struct -std=c99 -Wno-packed-bitfield-compat -c code/port.c -o out/port.o
out/pciprobe.o:code/pciprobe.c
gcc -fpack-struct -std=c99 -Wno-packed-bitfield-compat -c code/pciprobe.c -o out/pciprobe.o
# 链接内核
out/kernel.ld:out/kernel.asmo out/kernel.o out/graph.o out/port.o out/pciprobe.o out/mac.asmo
ld -Ttext 0x80000 -e start -o out/kernel.ld out/kernel.asmo out/kernel.o out/graph.o out/port.o out/pciprobe.o out/mac.asmo
# 生成可执行代码文件
out/kernel.bin:out/kernel.ld
objcopy -R .note -R .comment -S -O binary out/kernel.ld out/kernel.bin
# 制作内核映象文件
out/creat_img.exe:code/creat_img.c
gpp code/creat_img.c -o out/creat_img.exe
# 执行dos命令,在final目录下生成a.img文件
A:
out/creat_img.exe final/a.img
# 写入文件,argv[1]=目标文件 argv[2]=源文件 argv[3]=写入偏移量
#在DOS下用法: write.exe a.img kernelloader.bin 512
out/write_in_img.exe:code/write_in_img.c
gpp code/write_in_img.c -o out/write_in_img.exe
# 执行dos命令,向a.img写入代码,内容是boot.bin
# 写入磁盘位置从0偏移量起始,占1个扇区512字节
B:
out/write_in_img.exe final/a.img out/boot.bin 0
# 执行dos命令,向a.img写入代码,内容是kernelloader.bin
# boot.bin已经占用了512字节,写入磁盘位置从512偏移量起始,占2个扇区1024字节
C:
out/write_in_img.exe final/a.img out/kernelloader.bin 512
# 执行dos命令,向a.img写入代码,内容是asc16
# boot.bin+kernelloader.bin已经占用了512+1024 = 1536字节,写入磁盘位置从1536偏移量起始
D:
out/write_in_img.exe final/a.img charpic/asc16 1536
E:
out/write_in_img.exe final/a.img charpic/hzk16f 5632
F:
out/write_in_img.exe final/a.img charpic/ya.bmp 267776
G:
out/write_in_img.exe final/a.img charpic/faya.bmp 361984
H:
out/write_in_img.exe final/a.img out/kernel.bin 479232
######################