1: __init()函数的解释:
Pmon中有三类constructor函数,他们都是静态函数,此类函数都有一个共性就是受__attribute__((constructor))属性修饰,例如
Static void init_fs __P((void)) __attribute__((constructor))
下面说明三类函数:
a:命令处理函数,位于pmon/cmds目录,其名称都叫init_cmd(),该目录下几乎每个函数都有。
b:文件系统初始化函数,位于pmon/fs目录,其名称叫init_fs()或init_xxxfs()。例如init_diskfs、init_fs、init_netfs等。
c:可执行文件类型初始化函数,位于pmon/loaders目录中exec_*.c文件中,函数叫init_exec()。
2:利用uart实现printf()函数功能:
1:涉及结构体
ConfigEntry ConfigTable[]数组实现设备和操作函数的关联。如下:
315 ConfigEntry ConfigTable[] =
316 {
{ (char *)COMMON_COM_BASE_ADDR, 0, ns16550, 256, CONS_BAUD, NS16550HZ },
333 #if NMOD_VGACON >0
334 #if NMOD_FRAMEBUFFER >0
335 { (char *)1, 0, fbterm, 256, CONS_BAUD, NS16550HZ },
336 #else
337 { (char *)1, 0, vgaterm, 256, CONS_BAUD, NS16550HZ },
338 #endif
339 #endif
340 #ifdef DEVBD2F_FIREWALL
341 { (char *)LS2F_COMB_ADDR, 0, ns16550, 256, CONS_BAUD, NS16550HZ/2 ,1},
342 #endif
343 { 0 }
344 };
以上面红色为例说明:
COMMON_COM_BASE_ADDR :串口的地址
0 : chan在程序中用到<用途现在还不清楚>
Ns16550 :和串口相关的操作函数
256 :缓冲区大小
COMS_BAUD :波特率
NS16550HZ :频率
Flag :标志<为实现此处>
FILE结构体,对打开文件的描述
22 typedef struct FILE {
23 int fd;
24 int valid;
25 int ungetcflag;
26 int ungetchar;
27 } FILE;
FILE _iob[OPEN_MAX]数组实现
52 FILE _iob[OPEN_MAX] =
53 {
54 {0, 1},
55 {1, 1},
56 {2, 1},
57 {3, 1},
58 {4, 1},
59 };
具体printf实现过程:
1:__init()函数调用init_fs()函数:实现对ns16550串口设备的初始化;插入基于终端的文件系统;FILE结构体初始化<实现标准I/O的适当方法>、open 0-5 6个tty设备分别对应:stdin、stdout、stderr、kbdin、vgain、vgaout。
pmon中实现的文件系统:
51 #define FS_NULL 0 /* Null FileSystem */
52 #define FS_TTY 1 /* tty:// TTY */
53 #define FS_NET 2 /* tftp:// Network */
54 #define FS_SOCK 3 /* socket:// Socket */
55 #define FS_DEV 4 /* dev:// Raw device */
56 #define FS_MEM 5 /* mem:// Memory */
57 #define FS_FILE 6 /* file:// Structured File */
终端文件系统处理函数结构体:
552 static FileSystem termfs =
553 {
554 "tty", FS_TTY,
555 term_open,
556 term_read,
557 term_write,
558 NULL,
559 term_close,
560 term_ioctl
561 };
Init_fs()函数实现:
563 static void init_fs __P((void)) __attribute__ ((constructor));
564
565 static void
566 init_fs()
567 {
568 SBD_DISPLAY ("DEVI", CHKPNT_DEVI);
569 devinit (); /* initial ns16550 */
570
571 /*
572 * Install terminal based file system.
573 */
574 filefs_init(&termfs);
575
576 /*
577 * Create the standard i/o files the proper way
578 */
579 _file[0].valid = 1;
580 _file[0].fs = &termfs;
581 _file[1].valid = 1;
582 _file[1].fs = &termfs;
583 _file[2].valid = 1;
584 _file[2].fs = &termfs;
585 _file[3].valid = 1;
586 _file[3].fs = &termfs;
587 _file[4].valid = 1;
588 _file[4].fs = &termfs;
589 _file[5].valid = 1;
590 _file[5].fs = &termfs;
_file[]数组的0-5的初始化,实现了文件系统和操作方法的关联
591 term_open(0, "/dev/tty0", 0, 0); /* stdin */
592 term_open(1, "/dev/tty0", 0, 0); /* stdout */
593 term_open(2, "/dev/tty0", 0, 0); /* stderr */
594 term_open(3, "/dev/tty1", 0, 0); /* kbdin */
595 term_open(4, "/dev/tty1", 0, 0); /* vgaout */
596 term_open(5, "/dev/tty2", 0, 0); /* vgaout */
将5个基本的输入输出文件都打开,以便下面printf和vga输出调用。
597 }
2:printf()实现:
38 int
39 printf (const char *fmt, ...)
40 {
41 int len;
42 va_list ap;
43
44 va_start(ap, fmt);
45 len = vfprintf (stdout, fmt, ap);
46 va_end(ap);
47 return (len);
48 }
Stdout的定义:
#define stdout (vga_available?(&_iob[4]):(&_iob[1]));stdout为输出文件描述符,用来确定输出到那个tty设备,在此可选的值符合__iob数组每个元素的第一个值。
3:vfprintf()实现:
49 int
50 vfprintf (FILE *fp, const char *fmt, va_list ap)
51 {
52 int n;
53 char buf[1024];
54 #ifdef FASTBOOT
55 static int inited=0;
56 if(!inited)
57 {
58 if(getenv("novga"))
59 novga=1;
60 inited=1;
61 }
62 if((fp==&_iob[1])&&!novga)
63 return n;
64 #endif
65 n = vsprintf (buf, fmt, ap);
66 fputs (buf, fp);
67 return (n);
68 }
此函数仅仅将输入参数按格式存入到buf中,并调用fputs来真正实现输出。
4:fputs()实现:
39 int
40 fputs(const char *p, FILE *fp)
41 {
42 write (fp->fd, p, strlen (p));
43 return(0);
44 }
通过write将p中的数据输出到pf->fd所描述的文件描述符中,这里对应的是uart的输出。
5:write()函数的实现:
在此处,write调用的是term_write()函数,这一步的关联在init_fs()中实现。
119 int
120 term_write (int fd, const void *buf, size_t nchar)
121 {
122 DevEntry *p;
123 struct TermDev *devp;
124 char *buf2 = (char *)buf;
125 int i, n;
126 int dsel;
127 int count;
128
129 devp = (struct TermDev *)_file[fd].data;
130 p = &DevTable[devp->dev];
131 n = nchar;
132 dsel=devp->dev;
133
134 do
135 {
136 p = &DevTable[dsel];
137 buf2 = (char *)buf;
138 n = nchar;
139
140 while (n > 0) {
141 /* << LOCK >> */
142 while(!tgt_smplock());
143
144 i = Qspace (p->txq);
145 while (i > 2 && n > 0) {
146 if ((p->t.c_oflag & ONLCR) && *buf2 == '\n') {
147 Qput(p->txq, '\r');
148 i--;
149 }
150 Qput(p->txq, *buf2++);
151 n--;
152 i--;
153 }
154 tgt_smpunlock();
155 /* << UNLOCK >> */
156
157 while (Qused(p->txq)) {
158 scandevs();
159 }
160 }
161 dsel=DevTable[dsel+1].handler?dsel+1:0;
162 }while(dsel!=devp->dev && output_to_both);
163
164 return (nchar);
165 }
在scandevs()中,通过ns16550()函数实现了对串口的读写。
6:scandevs()函数的实现:
179 void
180 scandevs ()
181 {
182 int s, c, n;
183 DevEntry *p;
184
185
186 for (p = DevTable; p->rxq; p++) {
187 /* << LOCK >> */
188 while(!tgt_smplock());
189
190 /* Read queue */
191 while ((*p->handler) (OP_RXRDY, p, NULL, NULL)) {
192 c = (*p->handler) (OP_RX, p, NULL, NULL); //ns16550调用
193 if (p->t.c_iflag & ISTRIP)
194 c &= 0x7f;
195
196 if (p->t.c_lflag & ISIG) {
197 if (c == p->t.c_cc[VINTR]) {
198 gsignal (p->intr/*XXX*/, 2 /*SIGINT*/);
199 continue;
200 }
201 }
202 if (p->t.c_iflag & IXON) {
203 if (p->t.c_iflag & IXANY && p->txoff) {
204 p->txoff = 0;
205 continue;
206 }
207 if (c == p->t.c_cc[V_STOP]) {
208 p->txoff = 1;
209 continue;
210 }
211 if (c == p->t.c_cc[V_START]) {
212 p->txoff = 0;
213 continue;
214 }
215 }
216
217 n = Qspace (p->rxq);
218 if (n > 0) {
219 Qput (p->rxq, c);
220 if (n < 20 && !p->rxoff) {
221 (*p->handler) (OP_RXSTOP, p, NULL, p->rxoff = 1);
222 if (p->t.c_iflag & IXOFF)
223 chwrite (p, CNTRL ('S'));
224 }
225 }
226 else break;
227 }
228
229 /* Write queue */
230 n = Qused (p->txq);
231 while (n > 0 && !p->txoff &&
232 (*p->handler)(OP_TXRDY, p, NULL, NULL)) {
233 char c = Qget(p->txq);
234 (*p->handler) (OP_TX, p, NULL, c);
235 n--;
236 }
237
238 tgt_smpunlock();
239 /* << UNLOCK >> */
240 }
241
242 #if defined(SMP)
243 if (tgt_smpwhoami() != 0)
244 return; /* Only CPU 1 is allowed to run kernel */
245 #endif
246 #if 1 //delay 10 micro seconds
247 {
248 int i;
249 for(dummy=1,i=0; i<200; i++){
250 dummy*=i;
251 }
252 }
253 #endif
254 s = splhigh(); /* Trigg the polled interrupt system */
255 splx(s);
256
257 #ifdef NETIO
258 tgt_netpoll (); /* XXX this one should die! */
259 #endif
260 #if NMOD_VGACON >0
261 #if NMOD_USB_KBD >0
262 if (usb_kbd_available)
263 usb_kbd_poll();
264 #endif
265 if (kbd_available)
266 kbd_poll();
267 #endif
268 }
阅读(2191) | 评论(0) | 转发(0) |