// LAB 6: Your code here: // - read a packet from the device driver // - send it to the network server // Hint: When you IPC a page to the network server, it will be // reading from it for a while, so don't immediately receive // another packet in to the same physical page. int r;
while(1) { if (r = sys_page_alloc(0, &nsipcbuf, PTE_P | PTE_U | PTE_W), r < 0) panic("in input, sys_page_alloc: %e", r); while (r = sys_dl_receive(nsipcbuf.pkt.jp_data, PGSIZE - sizeof(int)), r < 0) sys_yield(); nsipcbuf.pkt.jp_len = r; ipc_send(ns_envid, NSREQ_INPUT, &nsipcbuf, PTE_P | PTE_U); if (r = sys_page_unmap(0, &nsipcbuf), r < 0) panic("in input, sys_page_unmap: %e", r); } }
Q: How did you structure your receive implementation? In particular, what do you do if the receive queue is empty and a user environment requests the next incoming packet?
staticint send_file(struct http_request *req) { int r; off_t file_size = -1; int fd;
// open the requested url for reading // if the file does not exist, send a 404 error using send_error // if the file is a directory, send a 404 error using send_error // set file_size to the size of the file
// LAB 6: Your code here. // panic("send_file not implemented"); if (fd = open(req->url, O_RDONLY), fd < 0) { send_error(req, 404); return fd; }
structStatst; if (r = stat(req->url, &st), r < 0 || st.st_isdir) { r = send_error(req, 404); goto end; }
file_size = st.st_size;
if ((r = send_header(req, 200)) < 0) goto end;
if ((r = send_size(req, file_size)) < 0) goto end;
staticint send_data(struct http_request *req, int fd) { // LAB 6: Your code here. // panic("send_data not implemented"); int r; int rd, wt, tot; char buf[256];
tot = 0; while (rd = read(fd, buf, sizeof(buf)), rd > 0) { for (wt = 0; wt < rd; ) { if (r = write(req->sock, buf + wt, rd - wt), r < 0) return r; wt += r; } tot += rd; } return rd < 0 ? rd : tot; }
Q: What does the web page served by JOS’s web server say?
A: This file came from JOS. Cheesy web page!
Q: How long approximately did it take you to do this lab?
A:
This complete this lab
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
testtime: OK (7.9s) pci attach: OK (0.8s) testoutput [5 packets]: OK (2.0s) testoutput [100 packets]: OK (2.2s) Part A score: 35/35
testinput [5 packets]: OK (1.9s) testinput [100 packets]: OK (1.2s) tcp echo server [echosrv]: OK (1.6s) web server [httpd]: http://localhost:26002/: OK (2.2s) http://localhost:26002/index.html: OK (0.9s) http://localhost:26002/random_file.txt: OK (1.7s) Part B score: 70/70
Score: 105/105
Challenge: Get MAC Address from EEPROM
原理
查阅手册可知,可以通过EERD寄存器来访问EEPROM:
Software can use the EEPROM Read register (EERD) to cause the Ethernet controller to read a word from the EEPROM that the software can then use. To do this, software writes the address to read the Read Address (EERD.ADDR) field and then simultaneously writes a 1b to the Start Read bit (EERD.START). The Ethernet controller then reads the word from the EEPROM, sets the Read Done bit (EERD.DONE), and puts the data in the Read Data field (EERD.DATA). Software can poll the EEPROM Read register until it sees the EERD.DONE bit set, then use the data from the EERD.DATA field. Any words read this way are not written to hardware’s internal registers.