History

20060303

Charles.Forsyth committed 19 years ago

Commit 64418801 parent eea662d1386 files · +530669 −-6Browse files

Unified · Split

990 files
  1. os/NOTICE +31 −0
  2. os/README +32 −0
  3. os/boot/README +33 −0
  4. os/boot/arm1110/Mk +8 −0
  5. os/boot/arm1110/dat.h +1 −0
  6. os/boot/arm1110/donprint.c +332 −0
  7. os/boot/arm1110/fns.h +7 −0
  8. os/boot/arm1110/il.s +99 −0
  9. os/boot/arm1110/imain.c +48 −0
  10. os/boot/arm1110/inflate.c +208 −0
  11. os/boot/arm1110/io.h +261 −0
  12. os/boot/arm1110/l.s +454 −0
  13. os/boot/arm1110/lib.h +143 −0
  14. os/boot/arm1110/map +10 −0
  15. os/boot/arm1110/mem.h +215 −0
  16. os/boot/arm1110/mkfile +86 −0
  17. os/boot/arm1110/print.c +56 −0
  18. os/boot/arm1110/uart.c +69 −0
  19. os/boot/libflate/LICENCE +237 −0
  20. os/boot/libflate/NOTICE +8 −0
  21. os/boot/libflate/adler.c +71 −0
  22. os/boot/libflate/crc.c +39 −0
  23. os/boot/libflate/deflate.c +1358 −0
  24. os/boot/libflate/deflateblock.c +55 −0
  25. os/boot/libflate/deflatezlib.c +59 −0
  26. os/boot/libflate/deflatezlibblock.c +33 −0
  27. os/boot/libflate/flateerr.c +22 −0
  28. os/boot/libflate/inflate.c +692 −0
  29. os/boot/libflate/inflateblock.c +53 −0
  30. os/boot/libflate/inflatezlib.c +65 −0
  31. os/boot/libflate/inflatezlibblock.c +67 −0
  32. os/boot/libflate/mkfile +21 −0
  33. os/boot/libflate/zlib.h +11 −0
  34. os/boot/mpc/NOTICE +3 −0
  35. os/boot/mpc/alarm.c +123 −0
  36. os/boot/mpc/all.h +6 −0
  37. os/boot/mpc/archfads.c +355 −0
  38. os/boot/mpc/archfads.h +42 −0
  39. os/boot/mpc/archpaq.c +240 −0
  40. os/boot/mpc/archpaq.h +29 −0
  41. os/boot/mpc/boot.h +8 −0
  42. os/boot/mpc/bootp.c +507 −0
  43. os/boot/mpc/clock.c +71 −0
  44. os/boot/mpc/conf.c +173 −0
  45. os/boot/mpc/console.c +173 −0
  46. os/boot/mpc/cpm.c +162 −0
  47. os/boot/mpc/crc32.c +42 −0
  48. os/boot/mpc/dat.h +217 −0
  49. os/boot/mpc/defont0.c +216 −0
  50. os/boot/mpc/devether.c +157 −0
  51. os/boot/mpc/devuart.c +230 −0
  52. os/boot/mpc/dload.c +103 −0
  53. os/boot/mpc/donprint.c +332 −0
  54. os/boot/mpc/dosboot.c +614 −0
  55. os/boot/mpc/dosfs.h +110 −0
  56. os/boot/mpc/etherif.h +59 −0
  57. os/boot/mpc/etherscc.c +411 −0
  58. os/boot/mpc/fblt.c +531 −0
  59. os/boot/mpc/flash.c +212 −0
  60. os/boot/mpc/fns.h +117 −0
  61. os/boot/mpc/gbitbltclip.c +52 −0
  62. os/boot/mpc/gnot.h +71 −0
  63. os/boot/mpc/i2c.c +351 −0
  64. os/boot/mpc/initfads.c +187 −0
  65. os/boot/mpc/initpaq.c +101 −0
  66. os/boot/mpc/initrpcg.c +91 −0
  67. os/boot/mpc/io.h +463 −0
  68. os/boot/mpc/ip.h +98 −0
  69. os/boot/mpc/l.s +370 −0
  70. os/boot/mpc/lib.h +106 −0
  71. os/boot/mpc/main.c +524 −0
  72. os/boot/mpc/mem.c +0 −0
  73. os/boot/mpc/mem.h +95 −0
  74. os/boot/mpc/mkfile +116 −0
  75. os/boot/mpc/ms2.c +179 −0
  76. os/boot/mpc/plan9boot.c +96 −0
  77. os/boot/mpc/qio.c +128 −0
  78. os/boot/mpc/rmap.c +104 −0
  79. os/boot/mpc/screen.c +242 −0
  80. os/boot/mpc/sload.c +71 −0
  81. os/boot/mpc/squeeze.h +34 −0
  82. os/boot/mpc/trap.c +233 −0
  83. os/boot/mpc/uartboot.c +189 −0
  84. os/boot/mpc/ureg.h +43 −0
  85. os/boot/mpc/zqs.c +234 −0
  86. os/boot/pc/8250.c +308 −0
  87. os/boot/pc/LICENCE +237 −0
  88. os/boot/pc/NOTICE +4 −0
  89. os/boot/pc/alarm.c +123 −0
  90. os/boot/pc/apm.c +16 −0
  91. os/boot/pc/bcom.c +460 −0
  92. os/boot/pc/boot.c +451 −0
  93. os/boot/pc/bootld.c +108 −0
  94. os/boot/pc/bootp.c +652 −0
  95. os/boot/pc/cga.c +91 −0
  96. os/boot/pc/clock.c +305 −0
  97. os/boot/pc/conf.c +537 −0
  98. os/boot/pc/console.c +236 −0
  99. os/boot/pc/dat.h +212 −0
  100. os/boot/pc/devfloppy.c +853 −0
  101. os/boot/pc/devfloppy.h +196 −0
  102. os/boot/pc/devi82365.c +1205 −0
  103. os/boot/pc/devpccard.c +1957 −0
  104. os/boot/pc/devsd.c +617 −0
  105. os/boot/pc/dma.c +245 −0
  106. os/boot/pc/dosboot.c +582 −0
  107. os/boot/pc/dosfs.h +62 −0
  108. os/boot/pc/eipfmt.c +145 −0
  109. os/boot/pc/error.h +58 −0
  110. os/boot/pc/ether.c +282 −0
  111. os/boot/pc/ether2000.c +110 −0
  112. os/boot/pc/ether2114x.c +1652 −0
  113. os/boot/pc/ether589.c +211 −0
  114. os/boot/pc/ether79c970.c +539 −0
  115. os/boot/pc/ether8003.c +258 −0
  116. os/boot/pc/ether8139.c +614 −0
  117. os/boot/pc/ether8169.c +847 −0
  118. os/boot/pc/ether82557.c +881 −0
  119. os/boot/pc/ether83815.c +825 −0
  120. os/boot/pc/ether8390.c +715 −0
  121. os/boot/pc/ether8390.h +71 −0
  122. os/boot/pc/etherec2t.c +155 −0
  123. os/boot/pc/etherelnk3.c +1898 −0
  124. os/boot/pc/etherif.h +46 −0
  125. os/boot/pc/etherigbe.c +1706 −0
  126. os/boot/pc/ethermii.c +224 −0
  127. os/boot/pc/ethermii.h +116 −0
  128. os/boot/pc/etherrhine.c +676 −0
  129. os/boot/pc/fns.h +155 −0
  130. os/boot/pc/fs.c +94 −0
  131. os/boot/pc/fs.h +36 −0
  132. os/boot/pc/getcallerpc.c +8 −0
  133. os/boot/pc/ilock.c +24 −0
  134. os/boot/pc/inflate.c +199 −0
  135. os/boot/pc/io.h +201 −0
  136. os/boot/pc/ip.h +100 −0
  137. os/boot/pc/kbd.c +489 −0
  138. os/boot/pc/kfs.h +57 −0
  139. os/boot/pc/kfsboot.c +256 −0
  140. os/boot/pc/l.s +1079 −0
  141. os/boot/pc/lib.h +102 −0
  142. os/boot/pc/load.c +563 −0
  143. os/boot/pc/mbr.s +259 −0
  144. os/boot/pc/mem.h +114 −0
  145. os/boot/pc/memory.c +504 −0
  146. os/boot/pc/mkfile +241 −0
  147. os/boot/pc/noether.c +40 −0
  148. os/boot/pc/part.c +344 −0
  149. os/boot/pc/pbs.s +372 −0
  150. os/boot/pc/pbsdisk +0 −0
  151. os/boot/pc/pbsdisk.s +344 −0
  152. os/boot/pc/pbsdisklba +0 −0
  153. os/boot/pc/pbsdisklba.s +327 −0
  154. os/boot/pc/pbslba.s +362 −0
  155. os/boot/pc/pci.c +852 −0
  156. os/boot/pc/print.c +31 −0
  157. os/boot/pc/queue.c +44 −0
  158. os/boot/pc/sd.h +127 −0
  159. os/boot/pc/sd53c8xx.c +2120 −0
  160. os/boot/pc/sd53c8xx.i +769 −0
  161. os/boot/pc/sdata.c +1639 −0
  162. os/boot/pc/sdmylex.c +1294 −0
  163. os/boot/pc/sdscsi.c +376 −0
  164. os/boot/pc/trap.c +331 −0
  165. os/boot/pc/ureg.h +27 −0
  166. os/boot/pc/x16.h +159 −0
  167. os/boot/puma/8250.c +312 −0
  168. os/boot/puma/alarm.c +123 −0
  169. os/boot/puma/armv4.h +99 −0
  170. os/boot/puma/boot.h +12 −0
  171. os/boot/puma/bootp.c +502 −0
  172. os/boot/puma/cga.c +92 −0
  173. os/boot/puma/clock.c +154 −0
  174. os/boot/puma/conf.c +181 −0
  175. os/boot/puma/console.c +181 −0
  176. os/boot/puma/dat.h +205 −0
  177. os/boot/puma/div.s +122 −0
  178. os/boot/puma/donprint.c +332 −0
  179. os/boot/puma/dosboot.c +614 −0
  180. os/boot/puma/dosfs.h +110 −0
  181. os/boot/puma/ebsit.trap.c +206 −0
  182. os/boot/puma/ether.c +156 −0
  183. os/boot/puma/ether.h +82 −0
  184. os/boot/puma/ether8900.c +555 −0
  185. os/boot/puma/flash.c +226 −0
  186. os/boot/puma/fns.h +111 −0
  187. os/boot/puma/hard.c +773 −0
  188. os/boot/puma/io.h +3 −0
  189. os/boot/puma/ip.h +98 −0
  190. os/boot/puma/kbd.c +482 −0
  191. os/boot/puma/l.s +427 −0
  192. os/boot/puma/lib.h +107 −0
  193. os/boot/puma/main.c +552 −0
  194. os/boot/puma/mem.h +38 −0
  195. os/boot/puma/mkfile +71 −0
  196. os/boot/puma/outb.c +20 −0
  197. os/boot/puma/plan9boot.c +93 −0
  198. os/boot/puma/puma.c +123 −0
  199. os/boot/puma/puma.h +435 −0
  200. os/boot/puma/qio.c +128 −0
  201. os/boot/puma/rmap.c +104 −0
  202. os/boot/puma/squeeze.h +34 −0
  203. os/boot/puma/sum.c +13 −0
  204. os/boot/puma/trap.c +190 −0
  205. os/boot/puma/ureg.h +22 −0
  206. os/boot/puma/zqs.c +216 −0
  207. os/boot/rpcg/NOTICE +3 −0
  208. os/boot/rpcg/alarm.c +123 −0
  209. os/boot/rpcg/all.h +6 −0
  210. os/boot/rpcg/archrpcg.c +279 −0
  211. os/boot/rpcg/archrpcg.h +48 −0
  212. os/boot/rpcg/boot.h +8 −0
  213. os/boot/rpcg/bootp.c +509 −0
  214. os/boot/rpcg/clock.c +71 −0
  215. os/boot/rpcg/conf.c +173 −0
  216. os/boot/rpcg/console.c +173 −0
  217. os/boot/rpcg/cpm.c +162 −0
  218. os/boot/rpcg/crc32.c +42 −0
  219. os/boot/rpcg/dat.h +217 −0
  220. os/boot/rpcg/defont0.c +216 −0
  221. os/boot/rpcg/devether.c +157 −0
  222. os/boot/rpcg/devuart.c +230 −0
  223. os/boot/rpcg/dload.c +103 −0
  224. os/boot/rpcg/donprint.c +332 −0
  225. os/boot/rpcg/dosboot.c +614 −0
  226. os/boot/rpcg/dosfs.h +110 −0
  227. os/boot/rpcg/etherif.h +59 −0
  228. os/boot/rpcg/etherscc.c +411 −0
  229. os/boot/rpcg/fblt.c +531 −0
  230. os/boot/rpcg/flash.c +212 −0
  231. os/boot/rpcg/fns.h +118 −0
  232. os/boot/rpcg/g.mx +1987 −0
  233. os/boot/rpcg/gbitbltclip.c +52 −0
  234. os/boot/rpcg/gnot.h +71 −0
  235. os/boot/rpcg/i2c.c +360 −0
  236. os/boot/rpcg/initfads.c +187 −0
  237. os/boot/rpcg/initpaq.c +101 −0
  238. os/boot/rpcg/initrpcg.c +91 −0
  239. os/boot/rpcg/io.h +463 −0
  240. os/boot/rpcg/ip.h +98 −0
  241. os/boot/rpcg/l.s +388 −0
  242. os/boot/rpcg/lib.h +106 −0
  243. os/boot/rpcg/libg.h +418 −0
  244. os/boot/rpcg/main.c +527 −0
  245. os/boot/rpcg/mem.c +0 −0
  246. os/boot/rpcg/mem.h +94 −0
  247. os/boot/rpcg/mkfile +120 −0
  248. os/boot/rpcg/ms2.c +179 −0
  249. os/boot/rpcg/plan9boot.c +96 −0
  250. os/boot/rpcg/qbromrpcg +0 −0
  251. os/boot/rpcg/qio.c +128 −0
  252. os/boot/rpcg/rmap.c +104 −0
  253. os/boot/rpcg/screen.c +242 −0
  254. os/boot/rpcg/sload +0 −0
  255. os/boot/rpcg/sload.c +71 −0
  256. os/boot/rpcg/squeeze.h +34 −0
  257. os/boot/rpcg/trap.c +233 −0
  258. os/boot/rpcg/uartboot.c +189 −0
  259. os/boot/rpcg/ureg.h +43 −0
  260. os/boot/rpcg/zqs.c +234 −0
  261. os/cerf1110/Mk +8 −0
  262. os/cerf1110/NOTICE +2 −0
  263. os/cerf1110/README +22 −0
  264. os/cerf1110/archcerf.c +177 −0
  265. os/cerf1110/cerf +159 −0
  266. os/cerf1110/dat.h +135 −0
  267. os/cerf1110/devata.c +1200 −0
  268. os/cerf1110/devcerf.c +128 −0
  269. os/cerf1110/ether8900.c +702 −0
  270. os/cerf1110/fns.h +179 −0
  271. os/cerf1110/io.h +1 −0
  272. os/cerf1110/main.c +255 −0
  273. os/cerf1110/mem.h +200 −0
  274. os/cerf1110/mkfile +101 −0
  275. os/cerf250/NOTICE +2 −0
  276. os/cerf250/README +44 −0
  277. os/cerf250/archcerf.c +266 −0
  278. os/cerf250/cerf +163 −0
  279. os/cerf250/dat.h +135 −0
  280. os/cerf250/devpcf8563.c +371 −0
  281. os/cerf250/ether91c111.c +1056 −0
  282. os/cerf250/fns.h +168 −0
  283. os/cerf250/io.h +1 −0
  284. os/cerf250/main.c +351 −0
  285. os/cerf250/mem.h +174 −0
  286. os/cerf250/mkfile +102 −0
  287. os/cerf250/uart.h +118 −0
  288. os/cerf405/NOTICE +3 −0
  289. os/cerf405/README +45 −0
  290. os/cerf405/cerf +139 −0
  291. os/cerf405/clock.c +159 −0
  292. os/cerf405/compile.c +34 −0
  293. os/cerf405/dat.h +159 −0
  294. os/cerf405/devboot.c +132 −0
  295. os/cerf405/devether.c +617 −0
  296. os/cerf405/devrtc.c +369 −0
  297. os/cerf405/devuart.c +1064 −0
  298. os/cerf405/etheremac.c +829 −0
  299. os/cerf405/etherif.h +37 −0
  300. os/cerf405/fns.h +147 −0
  301. os/cerf405/fpi.h +61 −0
  302. os/cerf405/fpipower.c +970 −0
  303. os/cerf405/gpio.c +106 −0
  304. os/cerf405/iic.c +605 −0
  305. os/cerf405/inb.s +127 −0
  306. os/cerf405/io.h +301 −0
  307. os/cerf405/l.s +795 −0
  308. os/cerf405/main.c +719 −0
  309. os/cerf405/mal.c +334 −0
  310. os/cerf405/mem.h +147 −0
  311. os/cerf405/mkfile +104 −0
  312. os/cerf405/mmu.c +122 −0
  313. os/cerf405/nand.c +96 −0
  314. os/cerf405/nofp.s +31 −0
  315. os/cerf405/pci.c +981 −0
  316. os/cerf405/physmem.h +22 −0
  317. os/cerf405/powerbreak.c +123 −0
  318. os/cerf405/rmap.c +106 −0
  319. os/cerf405/tlb.s +30 −0
  320. os/cerf405/trap.c +581 −0
  321. os/cerf405/uart.c +139 −0
  322. os/cerf405/uart.h +101 −0
  323. os/fads/NOTICE +4 −0
  324. os/fads/archfads.c +619 −0
  325. os/fads/archfads.h +33 −0
  326. os/fads/dat.h +162 −0
  327. os/fads/fads +121 −0
  328. os/fads/fns.h +117 −0
  329. os/fads/io.h +1 −0
  330. os/fads/main.c +392 −0
  331. os/fads/mem.h +157 −0
  332. os/fads/mkfile +107 −0
  333. os/fads/mmu.c +20 −0
  334. os/fads/tlb.s +23 −0
  335. os/init/README +5 −0
  336. os/init/bootinit.b +628 −0
  337. os/init/cerf405.b +598 −0
  338. os/init/cerfinit.b +612 −0
  339. os/init/evalinit.b +119 −0
  340. os/init/geninit.b +93 −0
  341. os/init/i4e.b +210 −0
  342. os/init/init.b +613 −0
  343. os/init/ipaqinit.b +697 −0
  344. os/init/ipeinit.b +620 −0
  345. os/init/jsinit.b +213 −0
  346. os/init/mkfile +27 −0
  347. os/init/mpcinit.b +383 −0
  348. os/init/pcdemo.b +273 −0
  349. os/init/pcinit.b +405 −0
  350. os/init/reminit.b +239 −0
  351. os/init/rpcginit.b +610 −0
  352. os/init/shell.b +97 −0
  353. os/init/soeinit.b +613 −0
  354. os/init/srvinit.b +209 −0
  355. os/init/wminit.b +231 −0
  356. os/ip/arp.c +681 −0
  357. os/ip/bootp.c +231 −0
  358. os/ip/compress.c +520 −0
  359. os/ip/devip.c +1419 −0
  360. os/ip/dhcp.c +447 −0
  361. os/ip/eipconvtest.c +152 −0
  362. os/ip/esp.c +866 −0
  363. os/ip/ethermedium.c +792 −0
  364. os/ip/gre.c +282 −0
  365. os/ip/icmp.c +490 −0
  366. os/ip/icmp6.c +917 −0
  367. os/ip/igmp.c +291 −0
  368. os/ip/ihbootp.c +323 −0
  369. os/ip/il.c +1408 −0
  370. os/ip/ip.c +805 −0
  371. os/ip/ip.h +673 −0
  372. os/ip/ipaux.c +730 −0
  373. os/ip/ipifc.c +1721 −0
  374. os/ip/ipmux.c +857 −0
  375. os/ip/iproute.c +852 −0
  376. os/ip/iprouter.c +56 −0
  377. os/ip/ipv6.c +747 −0
  378. os/ip/ipv6.h +185 −0
  379. os/ip/kernel.h +10 −0
  380. os/ip/loopbackmedium.c +121 −0
  381. os/ip/netdevmedium.c +153 −0
  382. os/ip/netlog.c +263 −0
  383. os/ip/nullmedium.c +39 −0
  384. os/ip/pktmedium.c +79 −0
  385. os/ip/plan9.c +36 −0
  386. os/ip/ppp.c +1656 −0
  387. os/ip/ppp.h +258 −0
  388. os/ip/pppmedium.c +192 −0
  389. os/ip/ptclbsum.c +72 −0
  390. os/ip/rudp.c +1085 −0
  391. os/ip/tcp.c +3177 −0
  392. os/ip/udp.c +649 −0
  393. os/ipaq1110/Mk +8 −0
  394. os/ipaq1110/NOTICE +6 −0
  395. os/ipaq1110/README +65 −0
  396. os/ipaq1110/archipaq.c +376 −0
  397. os/ipaq1110/dat.h +135 −0
  398. os/ipaq1110/defont.c +290 −0
  399. os/ipaq1110/devaudio.c +1056 −0
  400. os/ipaq1110/devipaq.c +762 −0
  401. os/ipaq1110/etherwavelan.c +1307 −0
  402. os/ipaq1110/fns.h +179 −0
  403. os/ipaq1110/inflate +0 −0
  404. os/ipaq1110/io.h +60 −0
  405. os/ipaq1110/ipaq +172 −0
  406. os/ipaq1110/lcd.c +185 −0
  407. os/ipaq1110/main.c +255 −0
  408. os/ipaq1110/mem.h +200 −0
  409. os/ipaq1110/mkfile +103 −0
  410. os/ipaq1110/screen.c +917 −0
  411. os/ipaq1110/screen.h +64 −0
  412. os/ipaq1110/tstdraw.b +107 −0
  413. os/ipaq1110/upd +4 −0
  414. os/ipengine/NOTICE +4 −0
  415. os/ipengine/README +40 −0
  416. os/ipengine/archipe.c +488 −0
  417. os/ipengine/archipe.h +32 −0
  418. os/ipengine/dat.h +162 −0
  419. os/ipengine/devfpga.c +389 −0
  420. os/ipengine/flash28f320b3b.c +43 −0
  421. os/ipengine/fns.h +120 −0
  422. os/ipengine/io.h +1 −0
  423. os/ipengine/ipe +109 −0
  424. os/ipengine/main.c +348 −0
  425. os/ipengine/mem.h +156 −0
  426. os/ipengine/mkfile +105 −0
  427. os/ipengine/mmu.c +20 −0
  428. os/ipengine/tlb.s +21 −0
  429. os/js/README +10 −0
  430. os/js/audio.h +9 −0
  431. os/js/clock.c +104 −0
  432. os/js/cs4231.h +20 −0
  433. os/js/dat.h +163 −0
  434. os/js/devcs4231.c +1186 −0
  435. os/js/devrtc.c +413 −0
  436. os/js/fns.h +110 −0
  437. os/js/fsv.c +198 −0
  438. os/js/io.h +224 −0
  439. os/js/iob.c +13 −0
  440. os/js/js +104 −0
  441. os/js/kbd.c +482 −0
  442. os/js/l.s +560 −0
  443. os/js/main.c +564 −0
  444. os/js/mem.h +149 −0
  445. os/js/mkfile +77 −0
  446. os/js/mmu.c +252 −0
  447. os/js/ns16552.h +81 −0
  448. os/js/rom.c +103 −0
  449. os/js/rom.h +57 −0
  450. os/js/screen.c +483 −0
  451. os/js/screen.h +49 −0
  452. os/js/softcursor.h +13 −0
  453. os/js/superio.c +216 −0
  454. os/js/trap.c +472 −0
  455. os/js/ureg.h +45 −0
  456. os/ks32/Mk +7 −0
  457. os/ks32/NOTICE +2 −0
  458. os/ks32/archevaluator7t.c +161 −0
  459. os/ks32/armv7.h +19 −0
  460. os/ks32/clock.c +287 −0
  461. os/ks32/dat.h +218 −0
  462. os/ks32/devuart.c +719 −0
  463. os/ks32/download.ps +1040 −0
  464. os/ks32/evaluator7t +110 −0
  465. os/ks32/fns.h +145 −0
  466. os/ks32/fpi.h +61 −0
  467. os/ks32/fpiarm.c +483 −0
  468. os/ks32/io.h +168 −0
  469. os/ks32/l.s +205 −0
  470. os/ks32/main.c +289 −0
  471. os/ks32/mem.h +54 −0
  472. os/ks32/mkfile +115 −0
  473. os/ks32/not.c +3 −0
  474. os/ks32/squirt +2 −0
  475. os/ks32/trap.c +525 −0
  476. os/manga/Mk +8 −0
  477. os/manga/archmanga.c +164 −0
  478. os/manga/clock.c +166 −0
  479. os/manga/dat.h +128 −0
  480. os/manga/devether.c +765 −0
  481. os/manga/devusb.c +931 −0
  482. os/manga/eswnotes +41 −0
  483. os/manga/ether8139.c +744 −0
  484. os/manga/etherif.h +44 −0
  485. os/manga/etherks8695.c +1169 −0
  486. os/manga/flashif.h +82 −0
  487. os/manga/fns.h +163 −0
  488. os/manga/fpi.h +61 −0
  489. os/manga/fpiarm.c +483 −0
  490. os/manga/gpio.c +75 −0
  491. os/manga/inb.c +85 −0
  492. os/manga/io.h +320 −0
  493. os/manga/ioring.c +72 −0
  494. os/manga/l.s +404 −0
  495. os/manga/main.c +317 −0
  496. os/manga/manga +137 −0
  497. os/manga/mem.h +133 −0
  498. os/manga/mkfile +89 −0
  499. os/manga/mmu.c +244 −0
  500. os/manga/pci.c +1007 −0
  501. os/manga/pinflate +0 −0
  502. os/manga/trap.c +498 −0
  503. os/manga/uartks8695.c +629 −0
  504. os/manga/usb.h +160 −0
  505. os/manga/usbuhci.c +1556 −0
  506. os/mpc/800io.h +666 −0
  507. os/mpc/NOTICE +3 −0
  508. os/mpc/clock.c +145 −0
  509. os/mpc/cpm.c +695 −0
  510. os/mpc/cpmtimer.c +179 −0
  511. os/mpc/devata.c +1194 −0
  512. os/mpc/devbench.c +243 −0
  513. os/mpc/devboot.c +132 −0
  514. os/mpc/devether.c +617 −0
  515. os/mpc/devpcmcia.c +1076 −0
  516. os/mpc/devrtc.c +258 −0
  517. os/mpc/devtouch.c +497 −0
  518. os/mpc/devuart.c +1450 −0
  519. os/mpc/dsp.c +289 −0
  520. os/mpc/dsp.h +62 −0
  521. os/mpc/etherif.h +37 −0
  522. os/mpc/etherscc.c +528 −0
  523. os/mpc/faultpower.c +49 −0
  524. os/mpc/fp.s +205 −0
  525. os/mpc/fpi.h +61 −0
  526. os/mpc/fpipower.c +970 −0
  527. os/mpc/i2c.c +439 −0
  528. os/mpc/i2c_spi.srx +149 −0
  529. os/mpc/inb.s +120 −0
  530. os/mpc/kbd.c +20 −0
  531. os/mpc/l.s +685 −0
  532. os/mpc/nofp.s +31 −0
  533. os/mpc/pcmcia.h +19 −0
  534. os/mpc/pit.c +68 −0
  535. os/mpc/powerbreak.c +123 −0
  536. os/mpc/rmap.c +106 −0
  537. os/mpc/screen.c +832 −0
  538. os/mpc/screen.h +60 −0
  539. os/mpc/spi.c +243 −0
  540. os/mpc/trap.c +554 −0
  541. os/mpc/usb.h +62 −0
  542. os/omap/README +4 −0
  543. os/pc/NOTICE +8 −0
  544. os/pc/README +9 −0
  545. os/pc/apbootstrap.h +15 −0
  546. os/pc/apbootstrap.s +110 −0
  547. os/pc/apic.c +378 −0
  548. os/pc/apm.c +151 −0
  549. os/pc/apmjump.s +98 −0
  550. os/pc/archmp.c +138 −0
  551. os/pc/audio.h +15 −0
  552. os/pc/cga.c +127 −0
  553. os/pc/cgamemscr.c +203 −0
  554. os/pc/crystal.h +1118 −0
  555. os/pc/dat.h +258 −0
  556. os/pc/devarch.c +940 −0
  557. os/pc/devds1620.c +368 −0
  558. os/pc/devether.c +539 −0
  559. os/pc/devfloppy.c +1082 −0
  560. os/pc/devi82365.c +1044 −0
  561. os/pc/devlm78.c +346 −0
  562. os/pc/devlpt.c +245 −0
  563. os/pc/devmouse.c +672 −0
  564. os/pc/devmpeg.c +1063 −0
  565. os/pc/devpccard.c +1949 −0
  566. os/pc/devpnp.c +652 −0
  567. os/pc/devrtc.c +461 −0
  568. os/pc/devtv.c +1826 −0
  569. os/pc/devusb.c +951 −0
  570. os/pc/devvga.c +620 −0
  571. os/pc/devzt5512.c +308 −0
  572. os/pc/dma.c +237 −0
  573. os/pc/ether2000.c +230 −0
  574. os/pc/ether2114x.c +1828 −0
  575. os/pc/ether589.c +214 −0
  576. os/pc/ether79c960.c +523 −0
  577. os/pc/ether79c970.c +640 −0
  578. os/pc/ether8003.c +271 −0
  579. os/pc/ether8139.c +755 −0
  580. os/pc/ether82543gc.c +1367 −0
  581. os/pc/ether82557.c +1325 −0
  582. os/pc/ether83815.c +994 −0
  583. os/pc/ether8390.c +812 −0
  584. os/pc/ether8390.h +74 −0
  585. os/pc/etherec2t.c +173 −0
  586. os/pc/etherelnk3.c +2132 −0
  587. os/pc/etherga620.c +1224 −0
  588. os/pc/etherga620fw.h +4858 −0
  589. os/pc/etherif.h +39 −0
  590. os/pc/etherigbe.c +1968 −0
  591. os/pc/etherrhine.c +734 −0
  592. os/pc/ethersmc.c +780 −0
  593. os/pc/etherwavelan.c +196 −0
  594. os/pc/flashif.h +82 −0
  595. os/pc/flashzpc.c +371 −0
  596. os/pc/floppy.h +183 −0
  597. os/pc/fns.h +162 −0
  598. os/pc/fpi.h +61 −0
  599. os/pc/fpi387.c +743 −0
  600. os/pc/fpsave.s +9 −0
  601. os/pc/i8250.c +328 −0
  602. os/pc/i8253.c +314 −0
  603. os/pc/i8259.c +199 −0
  604. os/pc/io.h +323 −0
  605. os/pc/kbd.c +477 −0
  606. os/pc/l.s +953 −0
  607. os/pc/main.c +457 −0
  608. os/pc/mem.h +144 −0
  609. os/pc/memory.c +570 −0
  610. os/pc/mkfile +83 −0
  611. os/pc/mmu.c +321 −0
  612. os/pc/mouse.c +84 −0
  613. os/pc/mp.c +815 −0
  614. os/pc/mp.h +225 −0
  615. os/pc/pc +139 −0
  616. os/pc/pc4e +145 −0
  617. os/pc/pcdisk +154 −0
  618. os/pc/pci.acid +252 −0
  619. os/pc/pci.c +1341 −0
  620. os/pc/pcidb.acid +2848 −0
  621. os/pc/pcmciamodem.c +75 −0
  622. os/pc/piix4smbus.c +213 −0
  623. os/pc/pix +153 −0
  624. os/pc/ps2mouse.c +84 −0
  625. os/pc/ptclbsum386.s +126 −0
  626. os/pc/screen.c +410 −0
  627. os/pc/screen.h +173 −0
  628. os/pc/sd53c8xx.c +2138 −0
  629. os/pc/sd53c8xx.i +773 −0
  630. os/pc/sd53c8xx.n +448 −0
  631. os/pc/sdata.c +2206 −0
  632. os/pc/sdmylex.c +1249 −0
  633. os/pc/sdscsi.c +394 −0
  634. os/pc/trap.c +571 −0
  635. os/pc/tv.h +15 −0
  636. os/pc/uarti8250.c +740 −0
  637. os/pc/uartisa.c +98 −0
  638. os/pc/uartpci.c +137 −0
  639. os/pc/usb.h +160 −0
  640. os/pc/usbuhci.c +1538 −0
  641. os/pc/vga.c +241 −0
  642. os/pc/vga.h +75 −0
  643. os/pc/vga3dfx.c +258 −0
  644. os/pc/vgaark2000pv.c +190 −0
  645. os/pc/vgabt485.c +245 −0
  646. os/pc/vgaclgd542x.c +291 −0
  647. os/pc/vgaclgd546x.c +277 −0
  648. os/pc/vgact65545.c +149 −0
  649. os/pc/vgacyber938x.c +225 −0
  650. os/pc/vgaet4000.c +270 −0
  651. os/pc/vgahiqvideo.c +274 −0
  652. os/pc/vgai81x.c +282 −0
  653. os/pc/vgamach64xx.c +1250 −0
  654. os/pc/vgamga2164w.c +289 −0
  655. os/pc/vgamga4xx.c +603 −0
  656. os/pc/vganeomagic.c +541 −0
  657. os/pc/vganvidia.c +373 −0
  658. os/pc/vgargb524.c +236 −0
  659. os/pc/vgas3.c +620 −0
  660. os/pc/vgasavage.c +571 −0
  661. os/pc/vgat2r4.c +586 −0
  662. os/pc/vgatvp3020.c +216 −0
  663. os/pc/vgatvp3026.c +189 −0
  664. os/pc/vgavmware.c +386 −0
  665. os/pc/vgax.c +102 −0
  666. os/pc/wavelan.c +1268 −0
  667. os/pc/wavelan.h +327 −0
  668. os/pc/x86break.c +138 −0
  669. os/pc/zoran.h +907 −0
  670. os/port/NOTICE +18 −0
  671. os/port/alarm.c +41 −0
  672. os/port/alloc.c +963 −0
  673. os/port/allocb.c +159 −0
  674. os/port/chan.c +1431 −0
  675. os/port/cis.c +539 −0
  676. os/port/dev.c +434 −0
  677. os/port/devXXX.c +147 −0
  678. os/port/devaudio.c +947 −0
  679. os/port/devbench.c +1165 −0
  680. os/port/devboot.c +150 −0
  681. os/port/devbridge.c +1206 −0
  682. os/port/devcap.c +248 −0
  683. os/port/devcons.c +1274 −0
  684. os/port/devdbg.c +1000 −0
  685. os/port/devdraw.c +2088 −0
  686. os/port/devds.c +605 −0
  687. os/port/devdup.c +151 −0
  688. os/port/devdynld.c +365 −0
  689. os/port/devenv.c +338 −0
  690. os/port/devflash.c +641 −0
  691. os/port/devftl.c +1365 −0
  692. os/port/devi2c.c +227 −0
  693. os/port/devindir.c +40 −0
  694. os/port/devkprof.c +230 −0
  695. os/port/devlogfs.c +1531 −0
  696. os/port/devloopback.c +743 −0
  697. os/port/devmnt.c +1204 −0
  698. os/port/devns16552.c +1090 −0
  699. os/port/devpci.c +227 −0
  700. os/port/devpipe.c +464 −0
  701. os/port/devpointer.c +279 −0
  702. os/port/devprof.c +722 −0
  703. os/port/devprog.c +1510 −0
  704. os/port/devroot.c +153 −0
  705. os/port/devsd.c +1474 −0
  706. os/port/devsign.c +446 −0
  707. os/port/devsrv.c +726 −0
  708. os/port/devssl.c +1436 −0
  709. os/port/devtest.c +125 −0
  710. os/port/devtinyfs.c +915 −0
  711. os/port/devtk.c +180 −0
  712. os/port/devuart.c +748 −0
  713. os/port/dial.c +417 −0
  714. os/port/dis.c +1125 −0
  715. os/port/discall.c +185 −0
  716. os/port/dynld.c +75 −0
  717. os/port/edf.c +626 −0
  718. os/port/edf.h +53 −0
  719. os/port/error.h +64 −0
  720. os/port/ethermii.c +238 −0
  721. os/port/ethermii.h +116 −0
  722. os/port/ethersink.c +65 −0
  723. os/port/exception.c +216 −0
  724. os/port/exportfs.c +1325 −0
  725. os/port/flashamd29f0x0.c +167 −0
  726. os/port/flashcfi16.c +134 −0
  727. os/port/flashcfi8.c +143 −0
  728. os/port/flashif.h +147 −0
  729. os/port/flashintel +179 −0
  730. os/port/flashnand.c +337 −0
  731. os/port/fpi.c +304 −0
  732. os/port/fpimem.c +136 −0
  733. os/port/inferno.c +1030 −0
  734. os/port/latin1.c +76 −0
  735. os/port/latin1.h +100 −0
  736. os/port/lib.h +211 −0
  737. os/port/log.c +186 −0
  738. os/port/master +89 −0
  739. os/port/master.local +10 −0
  740. os/port/mkdevc +216 −0
  741. os/port/mkdevlist +86 −0
  742. os/port/mkroot +119 −0
  743. os/port/mul64fract.c +39 −0
  744. os/port/netaux.c +67 −0
  745. os/port/netif.c +671 −0
  746. os/port/netif.h +134 −0
  747. os/port/nocache.c +49 −0
  748. os/port/nodynld.c +48 −0
  749. os/port/noenv.c +33 −0
  750. os/port/noscreen.c +9 −0
  751. os/port/parse.c +114 −0
  752. os/port/pgrp.c +278 −0
  753. os/port/portbreak.c +161 −0
  754. os/port/portclock.c +277 −0
  755. os/port/portdat.h +673 −0
  756. os/port/portfns.h +319 −0
  757. os/port/portmkfile +152 −0
  758. os/port/print.c +31 −0
  759. os/port/proc.c +788 −0
  760. os/port/qio.c +1529 −0
  761. os/port/qlock.c +111 −0
  762. os/port/random.c +156 −0
  763. os/port/rdb.c +112 −0
  764. os/port/sd.h +132 −0
  765. os/port/swcursor.c +358 −0
  766. os/port/sysfile.c +1125 −0
  767. os/port/taslock.c +126 −0
  768. os/port/tod.c +283 −0
  769. os/port/uart.h +104 −0
  770. os/port/xalloc.c +246 −0
  771. os/pxa/NOTICE +2 −0
  772. os/pxa/clock.c +318 −0
  773. os/pxa/devether.c +617 −0
  774. os/pxa/devrtc.c +169 −0
  775. os/pxa/devuart.c +1070 −0
  776. os/pxa/dma.c +244 −0
  777. os/pxa/etherif.h +41 −0
  778. os/pxa/fpi.h +61 −0
  779. os/pxa/fpiarm.c +483 −0
  780. os/pxa/gpio.c +88 −0
  781. os/pxa/i2c.c +561 −0
  782. os/pxa/l.s +548 −0
  783. os/pxa/mmu.c +252 −0
  784. os/pxa/pxaio.h +383 −0
  785. os/pxa/sa1110break.c +360 −0
  786. os/pxa/trap.c +587 −0
  787. os/rpcg/NOTICE +4 −0
  788. os/rpcg/archrpcg.c +428 −0
  789. os/rpcg/archrpcg.h +48 −0
  790. os/rpcg/clock.c +145 −0
  791. os/rpcg/dat.h +162 −0
  792. os/rpcg/fns.h +119 −0
  793. os/rpcg/io.h +1 −0
  794. os/rpcg/main.c +392 −0
  795. os/rpcg/mem.h +157 −0
  796. os/rpcg/mkfile +108 −0
  797. os/rpcg/mmu.c +20 −0
  798. os/rpcg/rpcg +122 −0
  799. os/rpcg/tlb.s +24 −0
  800. os/sa1110/clock.c +317 −0
  801. os/sa1110/devether.c +617 −0
  802. os/sa1110/devgpio.c +165 −0
  803. os/sa1110/devpcmcia.c +761 −0
  804. os/sa1110/devpower.c +377 −0
  805. os/sa1110/devrtc.c +169 −0
  806. os/sa1110/devuart.c +781 −0
  807. os/sa1110/dma.c +233 −0
  808. os/sa1110/etherif.h +41 −0
  809. os/sa1110/fpi.h +61 −0
  810. os/sa1110/fpiarm.c +483 −0
  811. os/sa1110/gscreen.c +587 −0
  812. os/sa1110/gscreen.h +87 −0
  813. os/sa1110/i2c.h +16 −0
  814. os/sa1110/i2cgpio.c +274 −0
  815. os/sa1110/l.s +530 −0
  816. os/sa1110/l3gpio.c +246 −0
  817. os/sa1110/mmu.c +140 −0
  818. os/sa1110/sa1110break.c +360 −0
  819. os/sa1110/sa1110io.h +500 −0
  820. os/sa1110/softcursor.c +365 −0
  821. os/sa1110/suspend.c +161 −0
  822. os/sa1110/trap.c +601 −0
  823. utils/0a/a.h +183 −0
  824. utils/0a/a.y +588 −0
  825. utils/0a/l.s +703 −0
  826. utils/0a/lex.c +697 −0
  827. utils/0a/mkfile +30 −0
  828. utils/0c/cgen.c +1148 −0
  829. utils/0c/enam.c +118 −0
  830. utils/0c/gc.h +332 −0
  831. utils/0c/list.c +244 −0
  832. utils/0c/mkenam +15 −0
  833. utils/0c/mkfile +30 −0
  834. utils/0c/mul.c +608 −0
  835. utils/0c/peep.c +694 −0
  836. utils/0c/reg.c +1151 −0
  837. utils/0c/sgen.c +569 −0
  838. utils/0c/swt.c +727 −0
  839. utils/0c/txt.c +1483 −0
  840. utils/0c/v.out.h +201 −0
  841. utils/0l/Nt.c +77 −0
  842. utils/0l/Plan9.c +57 −0
  843. utils/0l/Posix.c +80 −0
  844. utils/0l/asm.c +1433 −0
  845. utils/0l/enam.c +122 −0
  846. utils/0l/l.h +329 −0
  847. utils/0l/list.c +277 −0
  848. utils/0l/mkfile +30 −0
  849. utils/0l/noop.c +420 −0
  850. utils/0l/obj.c +1384 −0
  851. utils/0l/optab.c +221 −0
  852. utils/0l/pass.c +498 −0
  853. utils/0l/sched.c +709 −0
  854. utils/0l/span.c +628 −0
  855. utils/1a/a.h +198 −0
  856. utils/1a/a.y +402 −0
  857. utils/1a/l.s +479 −0
  858. utils/1a/lex.c +925 −0
  859. utils/1a/mkfile +30 −0
  860. utils/1c/cgen.c +1396 −0
  861. utils/1c/enam.c +425 −0
  862. utils/1c/gc.h +339 −0
  863. utils/1c/list.c +319 −0
  864. utils/1c/mkfile +29 −0
  865. utils/1c/mul.c +174 −0
  866. utils/1c/peep.c +1060 −0
  867. utils/1c/reg.c +1221 −0
  868. utils/1c/sgen.c +694 −0
  869. utils/1c/swt.c +964 −0
  870. utils/1c/txt.c +903 −0
  871. utils/1l/Nt.c +77 −0
  872. utils/1l/Plan9.c +57 −0
  873. utils/1l/Posix.c +80 −0
  874. utils/1l/asm.c +1534 −0
  875. utils/1l/l.h +268 −0
  876. utils/1l/list.c +334 −0
  877. utils/1l/mkfile +32 −0
  878. utils/1l/obj.c +1380 −0
  879. utils/1l/optab.c +444 −0
  880. utils/1l/pass.c +673 −0
  881. utils/1l/span.c +515 −0
  882. utils/2a/a.h +200 −0
  883. utils/2a/a.y +540 −0
  884. utils/2a/l.s +479 −0
  885. utils/2a/lex.c +935 −0
  886. utils/2a/mkfile +30 −0
  887. utils/2c/2.out.h +523 −0
  888. utils/2c/Update +7 −0
  889. utils/2c/cgen.c +1404 −0
  890. utils/2c/enam.c +425 −0
  891. utils/2c/gc.h +357 −0
  892. utils/2c/list.c +384 −0
  893. utils/2c/mkfile +30 −0
  894. utils/2c/mul.c +174 −0
  895. utils/2c/peep.c +1076 −0
  896. utils/2c/reg.c +1275 −0
  897. utils/2c/sgen.c +819 −0
  898. utils/2c/swt.c +1046 −0
  899. utils/2c/txt.c +940 −0
  900. utils/2l/Nt.c +77 −0
  901. utils/2l/Plan9.c +57 −0
  902. utils/2l/Posix.c +80 −0
  903. utils/2l/asm.c +1569 −0
  904. utils/2l/l.h +263 −0
  905. utils/2l/list.c +395 −0
  906. utils/2l/mkfile +26 −0
  907. utils/2l/obj.c +1402 −0
  908. utils/2l/optab.c +444 −0
  909. utils/2l/pass.c +538 −0
  910. utils/2l/span.c +551 −0
  911. utils/5a/a.h +182 −0
  912. utils/5a/a.y +673 −0
  913. utils/5a/lex.c +689 −0
  914. utils/5a/mkfile +30 −0
  915. utils/5c/5.out.h +197 −0
  916. utils/5c/cgen.c +1156 −0
  917. utils/5c/enam.c +98 −0
  918. utils/5c/gc.h +349 −0
  919. utils/5c/list.c +304 −0
  920. utils/5c/mkenam +15 −0
  921. utils/5c/mkfile +30 −0
  922. utils/5c/mul.c +609 −0
  923. utils/5c/peep.c +1440 −0
  924. utils/5c/reg.c +1157 −0
  925. utils/5c/sgen.c +613 −0
  926. utils/5c/swt.c +757 −0
  927. utils/5c/txt.c +1249 −0
  928. utils/5coff/5coff.c +316 −0
  929. utils/5coff/NOTICE +27 −0
  930. utils/5coff/auxi.c +251 −0
  931. utils/5coff/auxi.h +46 −0
  932. utils/5coff/coff.c +642 −0
  933. utils/5coff/mkfile +23 −0
  934. utils/5coff/readcoff.c +298 −0
  935. utils/5cv/5cv.c +353 −0
  936. utils/5cv/mkfile +18 −0
  937. utils/5l/Nt.c +77 −0
  938. utils/5l/Plan9.c +57 −0
  939. utils/5l/Posix.c +80 −0
  940. utils/5l/asm.c +1793 −0
  941. utils/5l/l.h +444 −0
  942. utils/5l/list.c +360 −0
  943. utils/5l/mkfile +32 −0
  944. utils/5l/noop.c +894 −0
  945. utils/5l/obj.c +1557 −0
  946. utils/5l/optab.c +253 −0
  947. utils/5l/pass.c +942 −0
  948. utils/5l/span.c +1262 −0
  949. utils/5l/thumb.c +1637 −0
  950. utils/6c/6.out.h +820 −0
  951. utils/8a/a.h +194 −0
  952. utils/8a/a.y +520 −0
  953. utils/8a/l.s +704 −0
  954. utils/8a/lex.c +895 −0
  955. utils/8a/mkfile +30 −0
  956. utils/8c/8.out.h +445 −0
  957. utils/8c/cgen.c +1821 −0
  958. utils/8c/cgen64.c +2711 −0
  959. utils/8c/div.c +206 −0
  960. utils/8c/enam.c +337 −0
  961. utils/8c/gc.h +374 −0
  962. utils/8c/list.c +282 −0
  963. utils/8c/machcap.c +86 −0
  964. utils/8c/mkenam +15 −0
  965. utils/8c/mkfile +35 −0
  966. utils/8c/mul.c +428 −0
  967. utils/8c/peep.c +757 −0
  968. utils/8c/reg.c +1255 −0
  969. utils/8c/sgen.c +842 −0
  970. utils/8c/swt.c +647 −0
  971. utils/8c/txt.c +1410 −0
  972. utils/8l/Nt.c +77 −0
  973. utils/8l/Plan9.c +57 −0
  974. utils/8l/Posix.c +80 −0
  975. utils/8l/asm.c +502 −0
  976. utils/8l/l.h +349 −0
  977. utils/8l/list.c +292 −0
  978. utils/8l/mkfile +29 −0
  979. utils/8l/obj.c +1492 −0
  980. utils/8l/optab.c +654 −0
  981. utils/8l/pass.c +763 −0
  982. utils/8l/span.c +1387 −0
  983. utils/NOTICE +34 −0
  984. utils/acid/386 +146 −0
  985. utils/acid/B.sh +7 −0
  986. utils/acid/acid.h +317 −0
  987. utils/acid/arm +1 −0
  988. utils/acid/builtin.c +1285 −0
  989. utils/acid/dbg.y +402 −0
  990. utils/acid/dot.c +152 −0
os/NOTICE+31−0
@@ -0,0 +1,31 @@
1+This copyright NOTICE applies to all files in this directory and
2+subdirectories, unless another copyright notice appears in a given
3+file or subdirectory. If you take substantial code from this software to use in
4+other programs, you must somehow include with it an appropriate
5+copyright notice that includes the copyright notice and the other
6+notices below. It is fine (and often tidier) to do that in a separate
7+file such as NOTICE, LICENCE or COPYING.
8+
9+ Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
10+ Portions Copyright © 1997-1999 Vita Nuova Limited
11+ Portions Copyright © 2000-2006 Vita Nuova Holdings Limited (www.vitanuova.com)
12+ Revisions Copyright © 2000-2006 Lucent Technologies Inc. and others
13+
14+Permission is hereby granted, free of charge, to any person obtaining a copy
15+of this software and associated documentation files (the "Software"), to deal
16+in the Software without restriction, including without limitation the rights
17+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18+copies of the Software, and to permit persons to whom the Software is
19+furnished to do so, subject to the following conditions:
20+
21+The above copyright notice and this permission notice shall be included in
22+all copies or substantial portions of the Software.
23+
24+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30+THE SOFTWARE.
31+
os/README+32−0
@@ -0,0 +1,32 @@
1+# a few sample native ports for different architectures
2+
3+cerf1110 arm Intrinsyc SA-1110 Cerf Cube
4+ipaq1110 arm Strongarm SA1110 native kernel for Compaq iPAQ 36xx
5+sa1110 arm SA1110 code common to most/all SA1110 platforms (eg, ipaq, cerf)
6+
7+cerf250 arm Intrinsyc Cerfboard250 (PXA250)
8+gum arm Gumstix PXA255
9+pxa arm general PXA support
10+
11+js sparc original port to Javastation-1, not recently tested
12+
13+ks32 arm ARM Evaluator 7t demo
14+
15+manga arm Micrel KS8695P ARM922 core with 4-port switch and PCI support
16+
17+cerf405 power Cerfcube 405EP (based on IBM 405EP processor)
18+
19+ipengine power Bright Star Engineering (www.brightstareng.com) ipEngine-1 (MPC823)
20+rpcg power RPCG-Lite MPC823/850 board
21+fads power MPC8xx FADS development board
22+mpc power code common to ports to Motorola MPC8xx boards
23+
24+pc 386 basis for ports to various PC-based platforms
25+
26+# basic Inferno native kernel components
27+port common native operating system components
28+ip common Internet protocol stack, Ether and PPP media
29+init common Limbo initialisation program (run by native kernel on startup)
30+
31+# sample bootstraps
32+boot - directory of several bootstrap programs; see README there
os/boot/README+33−0
@@ -0,0 +1,33 @@
1+Often the devices we use now come with some
2+form of bootstrap (often annoyingly complicated,
3+which gets in the way). Older boards were sometimes
4+bare, and we had to provide something (often annoyingly
5+complicated...). On the PC it's currently helpful to
6+have something that can boot from disc or ether;
7+since it's a thankless task to write such a thing, we
8+use Plan 9's, and thank its authors.
9+
10+The current scheme on newer devices is to have a simple
11+program that can put a stripped-down Inferno kernel into
12+flash, and use that to boot from other devices (including over the net)
13+as required during development.
14+
15+There are two distinct models for bootstrap in this directory.
16+
17+ Model I
18+
19+Each member of the first model is represented by a self-contained directory.
20+They are derived from various ages of Plan 9's /sys/src/boot/pc.
21+
22+arm1110 arm a prefix to a gzip'd kernel to decompress it (runs after basic bootloader)
23+pc 386 pc-specific bootstrap essentially identical to current Plan 9
24+ and covered by the Lucent Public License; it uses
25+libflate - zlib-style inflate/deflate library
26+mpc power PowerPC bootstrap for FADS board derived from an older version
27+ of Plan 9 but covered by our Inferno licence (because it came with Inferno)
28+puma arm SA110 bootstrap for Teralogics Puma, also covered by the Inferno licence
29+
30+ Model II
31+omap purpose-built bootstrap for the OMAP processor
32+
33+Not all of these are being distributed.
os/boot/arm1110/Mk+8−0
@@ -0,0 +1,8 @@
1+#!/bin/rc
2+rfork ne
3+ROOT=/usr/inferno
4+fn cd
5+NPROC=3
6+path=(/usr/inferno/Plan9/$cputype/bin $path)
7+#bind /usr/inferno/mkconfig.dist /usr/inferno/mkconfig
8+exec mk $*
os/boot/arm1110/dat.h+1−0
@@ -0,0 +1 @@
1+/* deliberately empty */
os/boot/arm1110/donprint.c+332−0
@@ -0,0 +1,332 @@
1+#include "u.h"
2+#include "lib.h"
3+
4+#define PTR sizeof(char*)
5+#define SHORT sizeof(int)
6+#define INT sizeof(int)
7+#define LONG sizeof(long)
8+#define IDIGIT 30
9+#define MAXCON 30
10+
11+#define FLONG (1<<0)
12+#define FSHORT (1<<1)
13+#define FUNSIGN (1<<2)
14+
15+typedef struct Op Op;
16+struct Op
17+{
18+ char *p;
19+ char *ep;
20+ void *argp;
21+ int f1;
22+ int f2;
23+ int f3;
24+};
25+
26+static int noconv(Op*);
27+static int cconv(Op*);
28+static int dconv(Op*);
29+static int hconv(Op*);
30+static int lconv(Op*);
31+static int oconv(Op*);
32+static int sconv(Op*);
33+static int uconv(Op*);
34+static int xconv(Op*);
35+static int Xconv(Op*);
36+static int percent(Op*);
37+
38+static
39+int (*fmtconv[MAXCON])(Op*) =
40+{
41+ noconv,
42+ cconv, dconv, hconv, lconv,
43+ oconv, sconv, uconv, xconv,
44+ Xconv, percent,
45+};
46+static
47+char fmtindex[128] =
48+{
49+ ['c'] 1,
50+ ['d'] 2,
51+ ['h'] 3,
52+ ['l'] 4,
53+ ['o'] 5,
54+ ['s'] 6,
55+ ['u'] 7,
56+ ['x'] 8,
57+ ['X'] 9,
58+ ['%'] 10,
59+};
60+
61+static int convcount = { 11 };
62+static int ucase;
63+
64+static void
65+PUT(Op *o, int c)
66+{
67+ static int pos;
68+ int opos;
69+
70+ if(c == '\t'){
71+ opos = pos;
72+ pos = (opos+8) & ~7;
73+ while(opos++ < pos && o->p < o->ep)
74+ *o->p++ = ' ';
75+ return;
76+ }
77+ if(o->p < o->ep){
78+ *o->p++ = c;
79+ pos++;
80+ }
81+ if(c == '\n')
82+ pos = 0;
83+}
84+
85+int
86+fmtinstall(char c, int (*f)(Op*))
87+{
88+
89+ c &= 0177;
90+ if(fmtindex[c] == 0) {
91+ if(convcount >= MAXCON)
92+ return 1;
93+ fmtindex[c] = convcount++;
94+ }
95+ fmtconv[fmtindex[c]] = f;
96+ return 0;
97+}
98+
99+char*
100+donprint(char *p, char *ep, char *fmt, void *argp)
101+{
102+ int sf1, c;
103+ Op o;
104+
105+ o.p = p;
106+ o.ep = ep;
107+ o.argp = argp;
108+
109+loop:
110+ c = *fmt++;
111+ if(c != '%') {
112+ if(c == 0) {
113+ if(o.p < o.ep)
114+ *o.p = 0;
115+ return o.p;
116+ }
117+ PUT(&o, c);
118+ goto loop;
119+ }
120+ o.f1 = 0;
121+ o.f2 = -1;
122+ o.f3 = 0;
123+ c = *fmt++;
124+ sf1 = 0;
125+ if(c == '-') {
126+ sf1 = 1;
127+ c = *fmt++;
128+ }
129+ while(c >= '0' && c <= '9') {
130+ o.f1 = o.f1*10 + c-'0';
131+ c = *fmt++;
132+ }
133+ if(sf1)
134+ o.f1 = -o.f1;
135+ if(c != '.')
136+ goto l1;
137+ c = *fmt++;
138+ while(c >= '0' && c <= '9') {
139+ if(o.f2 < 0)
140+ o.f2 = 0;
141+ o.f2 = o.f2*10 + c-'0';
142+ c = *fmt++;
143+ }
144+l1:
145+ if(c == 0)
146+ fmt--;
147+ c = (*fmtconv[fmtindex[c&0177]])(&o);
148+ if(c < 0) {
149+ o.f3 |= -c;
150+ c = *fmt++;
151+ goto l1;
152+ }
153+ o.argp = (char*)o.argp + c;
154+ goto loop;
155+}
156+
157+void
158+strconv(char *o, Op *op, int f1, int f2)
159+{
160+ int n, c;
161+ char *p;
162+
163+ n = strlen(o);
164+ if(f1 >= 0)
165+ while(n < f1) {
166+ PUT(op, ' ');
167+ n++;
168+ }
169+ for(p=o; c = *p++;)
170+ if(f2 != 0) {
171+ PUT(op, c);
172+ f2--;
173+ }
174+ if(f1 < 0) {
175+ f1 = -f1;
176+ while(n < f1) {
177+ PUT(op, ' ');
178+ n++;
179+ }
180+ }
181+}
182+
183+int
184+numbconv(Op *op, int base)
185+{
186+ char b[IDIGIT];
187+ int i, f, n, r;
188+ long v;
189+ short h;
190+
191+ f = 0;
192+ switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
193+ case FLONG:
194+ v = *(long*)op->argp;
195+ r = LONG;
196+ break;
197+
198+ case FUNSIGN|FLONG:
199+ v = *(ulong*)op->argp;
200+ r = LONG;
201+ break;
202+
203+ case FSHORT:
204+ h = *(int*)op->argp;
205+ v = h;
206+ r = SHORT;
207+ break;
208+
209+ case FUNSIGN|FSHORT:
210+ h = *(int*)op->argp;
211+ v = (ushort)h;
212+ r = SHORT;
213+ break;
214+
215+ default:
216+ v = *(int*)op->argp;
217+ r = INT;
218+ break;
219+
220+ case FUNSIGN:
221+ v = *(unsigned*)op->argp;
222+ r = INT;
223+ break;
224+ }
225+ if(!(op->f3 & FUNSIGN) && v < 0) {
226+ v = -v;
227+ f = 1;
228+ }
229+ b[IDIGIT-1] = 0;
230+ for(i = IDIGIT-2;; i--) {
231+ n = (ulong)v % base;
232+ n += '0';
233+ if(n > '9'){
234+ n += 'a' - ('9'+1);
235+ if(ucase)
236+ n += 'A'-'a';
237+ }
238+ b[i] = n;
239+ if(i < 2)
240+ break;
241+ v = (ulong)v / base;
242+ if(op->f2 >= 0 && i >= IDIGIT-op->f2)
243+ continue;
244+ if(v <= 0)
245+ break;
246+ }
247+ if(f)
248+ b[--i] = '-';
249+ strconv(b+i, op, op->f1, -1);
250+ return r;
251+}
252+
253+static int
254+noconv(Op *op)
255+{
256+
257+ strconv("***", op, 0, -1);
258+ return 0;
259+}
260+
261+static int
262+cconv(Op *op)
263+{
264+ char b[2];
265+
266+ b[0] = *(int*)op->argp;
267+ b[1] = 0;
268+ strconv(b, op, op->f1, -1);
269+ return INT;
270+}
271+
272+static int
273+dconv(Op *op)
274+{
275+ return numbconv(op, 10);
276+}
277+
278+static int
279+hconv(Op*)
280+{
281+ return -FSHORT;
282+}
283+
284+static int
285+lconv(Op*)
286+{
287+ return -FLONG;
288+}
289+
290+static int
291+oconv(Op *op)
292+{
293+ return numbconv(op, 8);
294+}
295+
296+static int
297+sconv(Op *op)
298+{
299+ strconv(*(char**)op->argp, op, op->f1, op->f2);
300+ return PTR;
301+}
302+
303+static int
304+uconv(Op*)
305+{
306+ return -FUNSIGN;
307+}
308+
309+static int
310+xconv(Op *op)
311+{
312+ return numbconv(op, 16);
313+}
314+
315+static int
316+Xconv(Op *op)
317+{
318+ int r;
319+
320+ ucase = 1;
321+ r = numbconv(op, 16);
322+ ucase = 0;
323+ return r;
324+}
325+
326+static int
327+percent(Op *op)
328+{
329+
330+ PUT(op, '%');
331+ return 0;
332+}
os/boot/arm1110/fns.h+7−0
@@ -0,0 +1,7 @@
1+/*
2+ * functions defined locally
3+ */
4+extern int gunzip(uchar *out, int outn, uchar *in, int inn);
5+extern void delay(int ms);
6+extern void serialputs(char *str, int n);
7+extern void draincache(void);
os/boot/arm1110/il.s+99−0
@@ -0,0 +1,99 @@
1+#include "mem.h"
2+/*
3+ * Entered here from Compaq's bootldr. First relocate to
4+ * the location we're linked for and then copy back the
5+ * decompressed kernel.
6+ *
7+ * All
8+ */
9+TEXT _start(SB), $-4
10+ MOVW $setR12(SB), R12 /* load the SB */
11+ MOVW $1, R0 /* dance to make 5l think that the magic */
12+ MOVW $1, R1 /* numbers in WORDs below are being used */
13+ CMP.S R0, R1 /* and to align them to where bootldr wants */
14+ BEQ _start2
15+ WORD $0x016f2818 /* magic number to say we are a kernel */
16+ WORD $0xc0008000 /* entry point address */
17+ WORD $0 /* size?, or end of data? */
18+
19+_start2:
20+
21+ /* SVC mode, interrupts disabled */
22+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
23+ MOVW R1, CPSR
24+
25+ /* disable the MMU */
26+ MOVW $0x130, R1
27+ MCR CpMMU, 0, R1, C(CpControl), C(0x0)
28+
29+ /* enable caches */
30+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
31+ ORR $(CpCdcache|CpCicache|CpCwb), R0
32+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
33+
34+ /* flush caches */
35+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
36+ /* drain prefetch */
37+ MOVW R0,R0
38+ MOVW R0,R0
39+ MOVW R0,R0
40+ MOVW R0,R0
41+
42+ /* drain write buffer */
43+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
44+
45+ /* relocate to where we expect to be */
46+ MOVW $(FLATESIZE),R3
47+ MOVW $0xC0008000,R1
48+ MOVW $0xC0200000,R2
49+ ADD R1,R3
50+_relloop:
51+ MOVW (R1),R0
52+ MOVW R0,(R2)
53+ ADD $4,R1
54+ ADD $4,R2
55+ CMP.S R1,R3
56+ BNE _relloop
57+
58+ MOVW $(MACHADDR+BY2PG), R13 /* stack */
59+ SUB $4, R13 /* link */
60+
61+ /* jump to where we've been relocated */
62+ MOVW $_relocated(SB),R15
63+
64+TEXT _relocated(SB),$-4
65+ BL main(SB)
66+ BL exit(SB)
67+ /* we shouldn't get here */
68+_mainloop:
69+ B _mainloop
70+ BL _div(SB) /* hack to get _div etc loaded */
71+
72+TEXT mypc(SB),$-4
73+ MOVW R14,R0
74+ RET
75+
76+TEXT draincache(SB),$-4
77+ /* write back any dirty data */
78+ MOVW $0xe0000000,R0
79+ ADD $(8*1024),R0,R1
80+_cfloop:
81+ MOVW.P 32(R0),R2
82+ CMP.S R0,R1
83+ BNE _cfloop
84+
85+ /* drain write buffer and invalidate i&d cache contents */
86+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
87+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
88+
89+ /* drain prefetch */
90+ MOVW R0,R0
91+ MOVW R0,R0
92+ MOVW R0,R0
93+ MOVW R0,R0
94+
95+ /* disable caches */
96+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
97+ BIC $(CpCdcache|CpCicache|CpCwb), R0
98+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
99+ RET
os/boot/arm1110/imain.c+48−0
@@ -0,0 +1,48 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "fns.h"
4+#include "dat.h"
5+#include "mem.h"
6+
7+void
8+main(void)
9+{
10+ void (*f)(void);
11+ ulong *kernel;
12+
13+ print("inflating kernel\n");
14+
15+ kernel = (ulong*)(0xc0200000+20*1024);
16+ if(gunzip((uchar*)0xc0008000, 2*1024*1024, (uchar*)kernel, FLATESIZE) > 0){
17+ f = (void (*)(void))0xc0008010;
18+ draincache();
19+ } else {
20+ print("inflation failed\n");
21+ f = nil;
22+ }
23+ (*f)();
24+}
25+
26+void
27+exit(void)
28+{
29+
30+ void (*f)(void);
31+
32+ delay(1000);
33+
34+ print("it's a wonderful day to die\n");
35+ f = nil;
36+ (*f)();
37+}
38+
39+void
40+delay(int ms)
41+{
42+ int i;
43+
44+ while(ms-- > 0){
45+ for(i = 0; i < 1000; i++)
46+ ;
47+ }
48+}
os/boot/arm1110/inflate.c+208−0
@@ -0,0 +1,208 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+#include <flate.h>
8+
9+typedef struct Biobuf Biobuf;
10+
11+struct Biobuf
12+{
13+ uchar *bp;
14+ uchar *p;
15+ uchar *ep;
16+};
17+
18+static int header(Biobuf*);
19+static int trailer(Biobuf*, Biobuf*);
20+static int getc(void*);
21+static ulong offset(Biobuf*);
22+static int crcwrite(void *out, void *buf, int n);
23+static ulong get4(Biobuf *b);
24+static ulong Boffset(Biobuf *bp);
25+
26+/* GZIP flags */
27+enum {
28+ Ftext= (1<<0),
29+ Fhcrc= (1<<1),
30+ Fextra= (1<<2),
31+ Fname= (1<<3),
32+ Fcomment= (1<<4),
33+
34+ GZCRCPOLY = 0xedb88320UL,
35+};
36+
37+static ulong *crctab;
38+static ulong crc;
39+
40+int
41+gunzip(uchar *out, int outn, uchar *in, int inn)
42+{
43+ Biobuf bin, bout;
44+ int err;
45+
46+ crc = 0;
47+ crctab = mkcrctab(GZCRCPOLY);
48+ err = inflateinit();
49+ if(err != FlateOk)
50+ print("inflateinit failed: %s\n", flateerr(err));
51+
52+ bin.bp = bin.p = in;
53+ bin.ep = in+inn;
54+ bout.bp = bout.p = out;
55+ bout.ep = out+outn;
56+
57+ err = header(&bin);
58+ if(err != FlateOk)
59+ return err;
60+
61+ err = inflate(&bout, crcwrite, &bin, getc);
62+ if(err != FlateOk)
63+ print("inflate failed: %s\n", flateerr(err));
64+
65+ err = trailer(&bout, &bin);
66+ if(err != FlateOk)
67+ return err;
68+
69+ return Boffset(&bout);
70+}
71+
72+static int
73+header(Biobuf *bin)
74+{
75+ int i, flag;
76+
77+ if(getc(bin) != 0x1f || getc(bin) != 0x8b){
78+ print("bad magic\n");
79+ return FlateCorrupted;
80+ }
81+ if(getc(bin) != 8){
82+ print("unknown compression type\n");
83+ return FlateCorrupted;
84+ }
85+
86+ flag = getc(bin);
87+
88+ /* mod time */
89+ get4(bin);
90+
91+ /* extra flags */
92+ getc(bin);
93+
94+ /* OS type */
95+ getc(bin);
96+
97+ if(flag & Fextra)
98+ for(i=getc(bin); i>0; i--)
99+ getc(bin);
100+
101+ /* name */
102+ if(flag&Fname)
103+ while(getc(bin) != 0)
104+ ;
105+
106+ /* comment */
107+ if(flag&Fcomment)
108+ while(getc(bin) != 0)
109+ ;
110+
111+ /* crc16 */
112+ if(flag&Fhcrc) {
113+ getc(bin);
114+ getc(bin);
115+ }
116+
117+ return FlateOk;
118+}
119+
120+static int
121+trailer(Biobuf *bout, Biobuf *bin)
122+{
123+ /* crc32 */
124+ ulong x;
125+
126+ x = get4(bin);
127+ if(crc != x){
128+ print("crc mismatch %lux %lux\n", crc, x);
129+ return FlateCorrupted;
130+ }
131+
132+ /* length */
133+ if(get4(bin) != Boffset(bout)){
134+ print("bad output len\n");
135+ return FlateCorrupted;
136+ }
137+ return FlateOk;
138+}
139+
140+static ulong
141+get4(Biobuf *b)
142+{
143+ ulong v;
144+ int i, c;
145+
146+ v = 0;
147+ for(i = 0; i < 4; i++){
148+ c = getc(b);
149+ v |= c << (i * 8);
150+ }
151+ return v;
152+}
153+
154+static int
155+getc(void *in)
156+{
157+ Biobuf *bp = in;
158+
159+ if((bp->p - bp->bp) % 10000 == 0)
160+ print(".");
161+ if(bp->p >= bp->ep)
162+ return -1;
163+ return *bp->p++;
164+}
165+
166+static ulong
167+Boffset(Biobuf *bp)
168+{
169+ return bp->p - bp->bp;
170+}
171+
172+static int
173+crcwrite(void *out, void *buf, int n)
174+{
175+ Biobuf *bp;
176+
177+ crc = blockcrc(crctab, crc, buf, n);
178+ bp = out;
179+ if(n > bp->ep-bp->p)
180+ n = bp->ep-bp->p;
181+ memmove(bp->p, buf, n);
182+ bp->p += n;
183+ return n;
184+}
185+
186+#undef malloc
187+#undef free
188+
189+static ulong ibrkp = ~0;
190+
191+void *
192+malloc(ulong n)
193+{
194+ ulong rv;
195+
196+ if(ibrkp == ~0)
197+ ibrkp = ((ulong)end)+1024*1024;
198+ n = (n+3)>>2;
199+ n <<= 2;
200+ rv = ibrkp;
201+ ibrkp += n;
202+ return (void*)rv;
203+}
204+
205+void
206+free(void *)
207+{
208+}
os/boot/arm1110/io.h+261−0
@@ -0,0 +1,261 @@
1+/*
2+ * Definitions for IO devices. Used only in C.
3+ */
4+
5+enum
6+{
7+ /* hardware counter frequency */
8+ ClockFreq= 3686400,
9+};
10+
11+/*
12+ * IRQ's defined by SA1100
13+ */
14+enum
15+{
16+ IRQgpio0= 0,
17+ IRQgpio1= 1,
18+ IRQgpio2= 2,
19+ IRQgpio3= 3,
20+ IRQgpio4= 4,
21+ IRQgpio5= 5,
22+ IRQgpio6= 6,
23+ IRQgpio7= 7,
24+ IRQgpio8= 8,
25+ IRQgpio9= 9,
26+ IRQgpio10= 10,
27+ IRQgpiohi= 11,
28+ IRQlcd= 12,
29+ IRQudc= 13,
30+ IRQuart1b= 15,
31+ IRQuart2= 16,
32+ IRQuart3= 17,
33+ IRQmcp= 18,
34+ IRQssp= 19,
35+ IRQdma0= 20,
36+ IRQdma1= 21,
37+ IRQdma2= 22,
38+ IRQdma3= 23,
39+ IRQdma4= 24,
40+ IRQdma5= 25,
41+ IRQtimer0= 26,
42+ IRQtimer1= 27,
43+ IRQtimer2= 28,
44+ IRQtimer3= 29,
45+ IRQsecond= 30,
46+ IRQrtc= 31,
47+};
48+
49+/*
50+ * GPIO lines (signal names from compaq document). _i indicates input
51+ * and _o output.
52+ */
53+enum
54+{
55+ GPIO_PWR_ON_i= 1<<0, /* power button */
56+ GPIO_UP_IRQ_i= 1<<1, /* microcontroller interrupts */
57+ GPIO_LDD8_o= 1<<2, /* LCD data 8-15 */
58+ GPIO_LDD9_o= 1<<3,
59+ GPIO_LDD10_o= 1<<4,
60+ GPIO_LDD11_o= 1<<5,
61+ GPIO_LDD12_o= 1<<6,
62+ GPIO_LDD13_o= 1<<7,
63+ GPIO_LDD14_o= 1<<8,
64+ GPIO_LDD15_o= 1<<9,
65+ GPIO_CARD_IND1_i= 1<<10, /* card inserted in PCMCIA socket 1 */
66+ GPIO_CARD_IRQ1_i= 1<<11, /* PCMCIA socket 1 interrupt */
67+ GPIO_CLK_SET0_o= 1<<12, /* clock selects for audio codec */
68+ GPIO_CLK_SET1_o= 1<<13,
69+ GPIO_L3_SDA_io= 1<<14, /* UDA1341 interface */
70+ GPIO_L3_MODE_o= 1<<15,
71+ GPIO_L3_SCLK_o= 1<<16,
72+ GPIO_CARD_IND0_i= 1<<17, /* card inserted in PCMCIA socket 0 */
73+ GPIO_KEY_ACT_i= 1<<18, /* hot key from cradle */
74+ GPIO_SYS_CLK_i= 1<<19, /* clock from codec */
75+ GPIO_BAT_FAULT_i= 1<<20, /* battery fault */
76+ GPIO_CARD_IRQ0_i= 1<<21, /* PCMCIA socket 0 interrupt */
77+ GPIO_LOCK_i= 1<<22, /* expansion pack lock/unlock */
78+ GPIO_COM_DCD_i= 1<<23, /* DCD from UART3 */
79+ GPIO_OPT_IRQ_i= 1<<24, /* expansion pack IRQ */
80+ GPIO_COM_CTS_i= 1<<25, /* CTS from UART3 */
81+ GPIO_COM_RTS_o= 1<<26, /* RTS to UART3 */
82+ GPIO_OPT_IND_i= 1<<27, /* expansion pack inserted */
83+
84+/* Peripheral Unit GPIO pin assignments: alternate functions */
85+ GPIO_SSP_TXD_o= 1<<10, /* SSP Transmit Data */
86+ GPIO_SSP_RXD_i= 1<<11, /* SSP Receive Data */
87+ GPIO_SSP_SCLK_o= 1<<12, /* SSP Sample CLocK */
88+ GPIO_SSP_SFRM_o= 1<<13, /* SSP Sample FRaMe */
89+ /* ser. port 1: */
90+ GPIO_UART_TXD_o= 1<<14, /* UART Transmit Data */
91+ GPIO_UART_RXD_i= 1<<15, /* UART Receive Data */
92+ GPIO_SDLC_SCLK_io= 1<<16, /* SDLC Sample CLocK (I/O) */
93+ GPIO_SDLC_AAF_o= 1<<17, /* SDLC Abort After Frame */
94+ GPIO_UART_SCLK1_i= 1<<18, /* UART Sample CLocK 1 */
95+ /* ser. port 4: */
96+ GPIO_SSP_CLK_i= 1<<19, /* SSP external CLocK */
97+ /* ser. port 3: */
98+ GPIO_UART_SCLK3_i= 1<<20, /* UART Sample CLocK 3 */
99+ /* ser. port 4: */
100+ GPIO_MCP_CLK_i= 1<<21, /* MCP CLocK */
101+ /* test controller: */
102+ GPIO_TIC_ACK_o= 1<<21, /* TIC ACKnowledge */
103+ GPIO_MBGNT_o= 1<<21, /* Memory Bus GraNT */
104+ GPIO_TREQA_i= 1<<22, /* TIC REQuest A */
105+ GPIO_MBREQ_i= 1<<22, /* Memory Bus REQuest */
106+ GPIO_TREQB_i= 1<<23, /* TIC REQuest B */
107+ GPIO_1Hz_o= 1<<25, /* 1 Hz clock */
108+ GPIO_RCLK_o= 1<<26, /* internal (R) CLocK (O, fcpu/2) */
109+ GPIO_32_768kHz_o= 1<<27, /* 32.768 kHz clock (O, RTC) */
110+};
111+
112+/*
113+ * types of interrupts
114+ */
115+enum
116+{
117+ GPIOrising,
118+ GPIOfalling,
119+ GPIOboth,
120+ IRQ,
121+};
122+
123+/* hardware registers */
124+typedef struct Uartregs Uartregs;
125+struct Uartregs
126+{
127+ ulong ctl[4];
128+ ulong dummya;
129+ ulong data;
130+ ulong dummyb;
131+ ulong status[2];
132+};
133+Uartregs *uart3regs;
134+
135+/* general purpose I/O lines control registers */
136+typedef struct GPIOregs GPIOregs;
137+struct GPIOregs
138+{
139+ ulong level; /* 1 == high */
140+ ulong direction; /* 1 == output */
141+ ulong set; /* a 1 sets the bit, 0 leaves it alone */
142+ ulong clear; /* a 1 clears the bit, 0 leaves it alone */
143+ ulong rising; /* rising edge detect enable */
144+ ulong falling; /* falling edge detect enable */
145+ ulong edgestatus; /* writing a 1 bit clears */
146+ ulong altfunc; /* turn on alternate function for any set bits */
147+};
148+
149+extern GPIOregs *gpioregs;
150+
151+/* extra general purpose I/O bits, output only */
152+enum
153+{
154+ EGPIO_prog_flash= 1<<0,
155+ EGPIO_pcmcia_reset= 1<<1,
156+ EGPIO_exppack_reset= 1<<2,
157+ EGPIO_codec_reset= 1<<3,
158+ EGPIO_exp_nvram_power= 1<<4,
159+ EGPIO_exp_full_power= 1<<5,
160+ EGPIO_lcd_3v= 1<<6,
161+ EGPIO_rs232_power= 1<<7,
162+ EGPIO_lcd_ic_power= 1<<8,
163+ EGPIO_ir_power= 1<<9,
164+ EGPIO_audio_power= 1<<10,
165+ EGPIO_audio_ic_power= 1<<11,
166+ EGPIO_audio_mute= 1<<12,
167+ EGPIO_fir= 1<<13, /* not set is sir */
168+ EGPIO_lcd_5v= 1<<14,
169+ EGPIO_lcd_9v= 1<<15,
170+};
171+extern ulong *egpioreg;
172+
173+/* Peripheral pin controller registers */
174+typedef struct PPCregs PPCregs;
175+struct PPCregs {
176+ ulong direction;
177+ ulong state;
178+ ulong assignment;
179+ ulong sleepdir;
180+ ulong flags;
181+};
182+extern PPCregs *ppcregs;
183+
184+/* Synchronous Serial Port controller registers */
185+typedef struct SSPregs SSPregs;
186+struct SSPregs {
187+ ulong control0;
188+ ulong control1;
189+ ulong dummy0;
190+ ulong data;
191+ ulong dummy1;
192+ ulong status;
193+};
194+extern SSPregs *sspregs;
195+
196+/* Multimedia Communications Port controller registers */
197+typedef struct MCPregs MCPregs;
198+struct MCPregs {
199+ ulong control0;
200+ ulong reserved0;
201+ ulong data0;
202+ ulong data1;
203+ ulong data2;
204+ ulong reserved1;
205+ ulong status;
206+ ulong reserved[11];
207+ ulong control1;
208+};
209+extern MCPregs *mcpregs;
210+
211+/*
212+ * memory configuration
213+ */
214+enum
215+{
216+ /* bit shifts for pcmcia access time counters */
217+ MECR_io0= 0,
218+ MECR_attr0= 5,
219+ MECR_mem0= 10,
220+ MECR_fast0= 11,
221+ MECR_io1= MECR_io0+16,
222+ MECR_attr1= MECR_attr0+16,
223+ MECR_mem1= MECR_mem0+16,
224+ MECR_fast1= MECR_fast0+16,
225+};
226+
227+typedef struct MemConfRegs MemConfRegs;
228+struct MemConfRegs
229+{
230+ ulong mdcnfg; /* dram */
231+ ulong mdcas00; /* dram banks 0/1 */
232+ ulong mdcas01;
233+ ulong mdcas02;
234+ ulong msc0; /* static */
235+ ulong msc1;
236+ ulong mecr; /* pcmcia */
237+ ulong mdrefr; /* dram refresh */
238+ ulong mdcas20; /* dram banks 2/3 */
239+ ulong mdcas21;
240+ ulong mdcas22;
241+ ulong msc2; /* static */
242+ ulong smcnfg; /* SMROM config */
243+};
244+extern MemConfRegs *memconfregs;
245+
246+/*
247+ * power management
248+ */
249+typedef struct PowerRegs PowerRegs;
250+struct PowerRegs
251+{
252+ ulong pmcr; /* Power manager control register */
253+ ulong pssr; /* Power manager sleep status register */
254+ ulong pspr; /* Power manager scratch pad register */
255+ ulong pwer; /* Power manager wakeup enable register */
256+ ulong pcfr; /* Power manager general configuration register */
257+ ulong ppcr; /* Power manager PPL configuration register */
258+ ulong pgsr; /* Power manager GPIO sleep state register */
259+ ulong posr; /* Power manager oscillator status register */
260+};
261+extern PowerRegs *powerregs;
os/boot/arm1110/l.s+454−0
@@ -0,0 +1,454 @@
1+#include "mem.h"
2+
3+/*
4+ * Entered here from Compaq's bootldr with MMU disabled.
5+ */
6+TEXT _start(SB), $-4
7+ MOVW $setR12(SB), R12 /* load the SB */
8+_main:
9+ /* SVC mode, interrupts disabled */
10+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
11+ MOVW R1, CPSR
12+
13+ /* disable the MMU */
14+ MOVW $0x130, R1
15+ MCR CpMMU, 0, R1, C(CpControl), C(0x0)
16+
17+ /* flush caches */
18+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
19+ /* drain prefetch */
20+ MOVW R0,R0
21+ MOVW R0,R0
22+ MOVW R0,R0
23+ MOVW R0,R0
24+
25+ /* drain write buffer */
26+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
27+
28+ MOVW $(MACHADDR+BY2PG), R13 /* stack */
29+ SUB $4, R13 /* link */
30+ BL main(SB)
31+ BL exit(SB)
32+ /* we shouldn't get here */
33+_mainloop:
34+ B _mainloop
35+ BL _div(SB) /* hack to get _div etc loaded */
36+
37+/* flush tlb's */
38+TEXT mmuinvalidate(SB), $-4
39+ MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
40+ RET
41+
42+/* flush tlb's */
43+TEXT mmuinvalidateaddr(SB), $-4
44+ MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1
45+ RET
46+
47+/* write back and invalidate i and d caches */
48+TEXT cacheflush(SB), $-4
49+ /* write back any dirty data */
50+ MOVW $0xe0000000,R0
51+ ADD $(8*1024),R0,R1
52+_cfloop:
53+ MOVW.P 32(R0),R2
54+ CMP.S R0,R1
55+ BNE _cfloop
56+
57+ /* drain write buffer and invalidate i&d cache contents */
58+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
59+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
60+
61+ /* drain prefetch */
62+ MOVW R0,R0
63+ MOVW R0,R0
64+ MOVW R0,R0
65+ MOVW R0,R0
66+ RET
67+
68+/* write back d cache */
69+TEXT cachewb(SB), $-4
70+ /* write back any dirty data */
71+_cachewb:
72+ MOVW $0xe0000000,R0
73+ ADD $(8*1024),R0,R1
74+_cwbloop:
75+ MOVW.P 32(R0),R2
76+ CMP.S R0,R1
77+ BNE _cwbloop
78+
79+ /* drain write buffer */
80+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
81+ RET
82+
83+/* write back a single cache line */
84+TEXT cachewbaddr(SB), $-4
85+ BIC $31,R0
86+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
87+ B _wbflush
88+
89+/* write back a region of cache lines */
90+TEXT cachewbregion(SB), $-4
91+ MOVW 4(FP),R1
92+ CMP.S $(4*1024),R1
93+ BGT _cachewb
94+ ADD R0,R1
95+ BIC $31,R0
96+_cwbrloop:
97+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
98+ ADD $32,R0
99+ CMP.S R0,R1
100+ BGT _cwbrloop
101+ B _wbflush
102+
103+/* invalidate the dcache */
104+TEXT dcacheinvalidate(SB), $-4
105+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x6)
106+ RET
107+
108+/* invalidate the icache */
109+TEXT icacheinvalidate(SB), $-4
110+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x9)
111+ RET
112+
113+/* drain write buffer */
114+TEXT wbflush(SB), $-4
115+_wbflush:
116+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
117+ RET
118+
119+/* return cpu id */
120+TEXT getcpuid(SB), $-4
121+ MRC CpMMU, 0, R0, C(CpCPUID), C(0x0)
122+ RET
123+
124+/* return fault status */
125+TEXT getfsr(SB), $-4
126+ MRC CpMMU, 0, R0, C(CpFSR), C(0x0)
127+ RET
128+
129+/* return fault address */
130+TEXT getfar(SB), $-4
131+ MRC CpMMU, 0, R0, C(CpFAR), C(0x0)
132+ RET
133+
134+/* return fault address */
135+TEXT putfar(SB), $-4
136+ MRC CpMMU, 0, R0, C(CpFAR), C(0x0)
137+ RET
138+
139+/* set the translation table base */
140+TEXT putttb(SB), $-4
141+ MCR CpMMU, 0, R0, C(CpTTB), C(0x0)
142+ RET
143+
144+/*
145+ * enable mmu, i and d caches
146+ */
147+TEXT mmuenable(SB), $-4
148+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
149+ ORR $(CpCmmuena|CpCdcache|CpCicache|CpCwb), R0
150+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
151+ RET
152+
153+TEXT mmudisable(SB), $-4
154+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
155+ BIC $(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCvivec), R0
156+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
157+ RET
158+
159+/*
160+ * use exception vectors at 0xffff0000
161+ */
162+TEXT mappedIvecEnable(SB), $-4
163+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
164+ ORR $(CpCvivec), R0
165+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
166+ RET
167+TEXT mappedIvecDisable(SB), $-4
168+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
169+ BIC $(CpCvivec), R0
170+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
171+ RET
172+
173+/* set the translation table base */
174+TEXT putdac(SB), $-4
175+ MCR CpMMU, 0, R0, C(CpDAC), C(0x0)
176+ RET
177+
178+/* set address translation pid */
179+TEXT putpid(SB), $-4
180+ MCR CpMMU, 0, R0, C(CpPID), C(0x0)
181+ RET
182+
183+/*
184+ * set the stack value for the mode passed in R0
185+ */
186+TEXT setr13(SB), $-4
187+ MOVW 4(FP), R1
188+
189+ MOVW CPSR, R2
190+ BIC $PsrMask, R2, R3
191+ ORR R0, R3
192+ MOVW R3, CPSR
193+
194+ MOVW R13, R0
195+ MOVW R1, R13
196+
197+ MOVW R2, CPSR
198+ RET
199+
200+/*
201+ * exception vectors, copied by trapinit() to somewhere useful
202+ */
203+
204+TEXT vectors(SB), $-4
205+ MOVW 0x18(R15), R15 /* reset */
206+ MOVW 0x18(R15), R15 /* undefined */
207+ MOVW 0x18(R15), R15 /* SWI */
208+ MOVW 0x18(R15), R15 /* prefetch abort */
209+ MOVW 0x18(R15), R15 /* data abort */
210+ MOVW 0x18(R15), R15 /* reserved */
211+ MOVW 0x18(R15), R15 /* IRQ */
212+ MOVW 0x18(R15), R15 /* FIQ */
213+
214+TEXT vtable(SB), $-4
215+ WORD $_vsvc(SB) /* reset, in svc mode already */
216+ WORD $_vund(SB) /* undefined, switch to svc mode */
217+ WORD $_vsvc(SB) /* swi, in svc mode already */
218+ WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */
219+ WORD $_vdabt(SB) /* data abort, switch to svc mode */
220+ WORD $_vsvc(SB) /* reserved */
221+ WORD $_virq(SB) /* IRQ, switch to svc mode */
222+ WORD $_vfiq(SB) /* FIQ, switch to svc mode */
223+
224+TEXT _vrst(SB), $-4
225+ BL resettrap(SB)
226+
227+TEXT _vsvc(SB), $-4 /* SWI */
228+ MOVW.W R14, -4(R13) /* ureg->pc = interupted PC */
229+ MOVW SPSR, R14 /* ureg->psr = SPSR */
230+ MOVW.W R14, -4(R13) /* ... */
231+ MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */
232+ MOVW.W R14, -4(R13) /* ... */
233+ MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */
234+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
235+ MOVW R13, R0 /* first arg is pointer to ureg */
236+ SUB $8, R13 /* space for argument+link */
237+
238+ BL syscall(SB)
239+
240+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
241+ MOVW 8(R13), R14 /* restore link */
242+ MOVW 4(R13), R0 /* restore SPSR */
243+ MOVW R0, SPSR /* ... */
244+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
245+ ADD $8, R13 /* pop past ureg->{type+psr} */
246+ RFE /* MOVM.IA.S.W (R13), [R15] */
247+
248+TEXT _vund(SB), $-4 /* undefined */
249+ MOVM.IA [R0-R4], (R13) /* free some working space */
250+ MOVW $PsrMund, R0
251+ B _vswitch
252+
253+TEXT _vpabt(SB), $-4 /* prefetch abort */
254+ MOVM.IA [R0-R4], (R13) /* free some working space */
255+ MOVW $PsrMabt, R0 /* r0 = type */
256+ B _vswitch
257+
258+TEXT _vdabt(SB), $-4 /* prefetch abort */
259+ MOVM.IA [R0-R4], (R13) /* free some working space */
260+ MOVW $(PsrMabt+1), R0 /* r0 = type */
261+ B _vswitch
262+
263+TEXT _virq(SB), $-4 /* IRQ */
264+ MOVM.IA [R0-R4], (R13) /* free some working space */
265+ MOVW $PsrMirq, R0 /* r0 = type */
266+ B _vswitch
267+
268+ /*
269+ * come here with type in R0 and R13 pointing above saved [r0-r4]
270+ * and type in r0. we'll switch to SVC mode and then call trap.
271+ */
272+_vswitch:
273+ MOVW SPSR, R1 /* save SPSR for ureg */
274+ MOVW R14, R2 /* save interrupted pc for ureg */
275+ MOVW R13, R3 /* save pointer to where the original [R0-R3] are */
276+
277+ /* switch to svc mode */
278+ MOVW CPSR, R14
279+ BIC $PsrMask, R14
280+ ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
281+ MOVW R14, CPSR
282+
283+ /* interupted code kernel or user? */
284+ AND.S $0xf, R1, R4
285+ BEQ _userexcep
286+
287+ /* here for trap from SVC mode */
288+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
289+ MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
290+ MOVM.DB.W [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
291+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
292+ MOVW R13, R0 /* first arg is pointer to ureg */
293+ SUB $8, R13 /* space for argument+link (for debugger) */
294+ MOVW $0xdeaddead,R11 /* marker */
295+
296+ BL trap(SB)
297+
298+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
299+ MOVW 8(R13), R14 /* restore link */
300+ MOVW 4(R13), R0 /* restore SPSR */
301+ MOVW R0, SPSR /* ... */
302+ MOVM.DB (R13), [R0-R14] /* restore registers */
303+ ADD $8, R13 /* pop past ureg->{type+psr} */
304+ RFE /* MOVM.IA.S.W (R13), [R15] */
305+
306+ /* here for trap from USER mode */
307+_userexcep:
308+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
309+ MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
310+ MOVM.DB.W.S [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
311+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
312+ MOVW R13, R0 /* first arg is pointer to ureg */
313+ SUB $8, R13 /* space for argument+link (for debugger) */
314+
315+ BL trap(SB)
316+
317+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
318+ MOVW 8(R13), R14 /* restore link */
319+ MOVW 4(R13), R0 /* restore SPSR */
320+ MOVW R0, SPSR /* ... */
321+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
322+ ADD $8, R13 /* pop past ureg->{type+psr} */
323+ RFE /* MOVM.IA.S.W (R13), [R15] */
324+
325+TEXT _vfiq(SB), $-4 /* FIQ */
326+ RFE /* FIQ is special, ignore it for now */
327+
328+/*
329+ * This is the first jump from kernel to user mode.
330+ * Fake a return from interrupt.
331+ *
332+ * Enter with R0 containing the user stack pointer.
333+ * UTZERO + 0x20 is always the entry point.
334+ *
335+ */
336+TEXT touser(SB),$-4
337+ /* store the user stack pointer into the USR_r13 */
338+ MOVM.DB.W [R0], (R13)
339+ MOVM.S.IA.W (R13),[R13]
340+
341+ /* set up a PSR for user level */
342+ MOVW $(PsrMusr), R0
343+ MOVW R0,SPSR
344+
345+ /* save the PC on the stack */
346+ MOVW $(UTZERO+0x20), R0
347+ MOVM.DB.W [R0],(R13)
348+
349+ /* return from interrupt */
350+ RFE /* MOVM.IA.S.W (R13), [R15] */
351+
352+/*
353+ * here to jump to a newly forked process
354+ */
355+TEXT forkret(SB),$-4
356+ ADD $(4*15), R13 /* make r13 point to ureg->type */
357+ MOVW 8(R13), R14 /* restore link */
358+ MOVW 4(R13), R0 /* restore SPSR */
359+ MOVW R0, SPSR /* ... */
360+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
361+ ADD $8, R13 /* pop past ureg->{type+psr} */
362+ RFE /* MOVM.IA.S.W (R13), [R15] */
363+
364+TEXT splhi(SB), $-4
365+ /* save caller pc in Mach */
366+ MOVW $(MACHADDR+0x04),R2
367+ MOVW R14,0(R2)
368+ /* turn off interrupts */
369+ MOVW CPSR, R0
370+ ORR $(PsrDfiq|PsrDirq), R0, R1
371+ MOVW R1, CPSR
372+ RET
373+
374+TEXT spllo(SB), $-4
375+ MOVW CPSR, R0
376+ BIC $(PsrDfiq|PsrDirq), R0, R1
377+ MOVW R1, CPSR
378+ RET
379+
380+TEXT splx(SB), $-4
381+ /* save caller pc in Mach */
382+ MOVW $(MACHADDR+0x04),R2
383+ MOVW R14,0(R2)
384+ /* reset interrupt level */
385+ MOVW R0, R1
386+ MOVW CPSR, R0
387+ MOVW R1, CPSR
388+ RET
389+
390+TEXT splxpc(SB), $-4 /* for iunlock */
391+ MOVW R0, R1
392+ MOVW CPSR, R0
393+ MOVW R1, CPSR
394+ RET
395+
396+TEXT spldone(SB), $0
397+ RET
398+
399+TEXT islo(SB), $-4
400+ MOVW CPSR, R0
401+ AND $(PsrDfiq|PsrDirq), R0
402+ EOR $(PsrDfiq|PsrDirq), R0
403+ RET
404+
405+TEXT cpsrr(SB), $-4
406+ MOVW CPSR, R0
407+ RET
408+
409+TEXT spsrr(SB), $-4
410+ MOVW SPSR, R0
411+ RET
412+
413+TEXT getcallerpc(SB), $-4
414+ MOVW 0(R13), R0
415+ RET
416+
417+TEXT tas(SB), $-4
418+ MOVW R0, R1
419+ MOVW $0xDEADDEAD, R2
420+ SWPW R2, (R1), R0
421+ RET
422+
423+TEXT setlabel(SB), $-4
424+ MOVW R13, 0(R0) /* sp */
425+ MOVW R14, 4(R0) /* pc */
426+ MOVW $0, R0
427+ RET
428+
429+TEXT gotolabel(SB), $-4
430+ MOVW 0(R0), R13 /* sp */
431+ MOVW 4(R0), R14 /* pc */
432+ MOVW $1, R0
433+ RET
434+
435+
436+/* The first MCR instruction of this function needs to be on a cache-line
437+ * boundary; to make this happen, it will be copied (in trap.c).
438+ *
439+ * Doze puts the machine into idle mode. Any interrupt will get it out
440+ * at the next instruction (the RET, to be precise).
441+ */
442+TEXT _doze(SB), $-4
443+ MOVW $UCDRAMZERO, R1
444+ MOVW R0,R0
445+ MOVW R0,R0
446+ MOVW R0,R0
447+ MOVW R0,R0
448+ MOVW R0,R0
449+ MOVW R0,R0
450+ MOVW R0,R0
451+ MCR CpPWR, 0, R0, C(CpTest), C(0x2), 2
452+ MOVW (R1), R0
453+ MCR CpPWR, 0, R0, C(CpTest), C(0x8), 2
454+ RET
os/boot/arm1110/lib.h+143−0
@@ -0,0 +1,143 @@
1+/*
2+ * functions (possibly) linked in, complete, from libc.
3+ */
4+
5+/*
6+ * mem routines
7+ */
8+extern void *memccpy(void*, void*, int, long);
9+extern void *memset(void*, int, long);
10+extern int memcmp(void*, void*, long);
11+extern void *memmove(void*, void*, long);
12+extern void *memchr(void*, int, long);
13+
14+/*
15+ * string routines
16+ */
17+extern char *strcat(char*, char*);
18+extern char *strchr(char*, char);
19+extern char *strrchr(char*, char);
20+extern int strcmp(char*, char*);
21+extern char *strcpy(char*, char*);
22+extern char *strncat(char*, char*, long);
23+extern char *strncpy(char*, char*, long);
24+extern int strncmp(char*, char*, long);
25+extern long strlen(char*);
26+extern char* strstr(char*, char*);
27+extern int atoi(char*);
28+
29+enum
30+{
31+ UTFmax = 3, /* maximum bytes per rune */
32+ Runesync = 0x80, /* cannot represent part of a UTF sequence */
33+ Runeself = 0x80, /* rune and UTF sequences are the same (<) */
34+ Runeerror = 0x80, /* decoding error in UTF */
35+};
36+
37+/*
38+ * rune routines
39+ */
40+extern int runetochar(char*, Rune*);
41+extern int chartorune(Rune*, char*);
42+extern char* utfrune(char*, long);
43+extern int utflen(char*);
44+extern int runelen(long);
45+
46+extern int abs(int);
47+
48+/*
49+ * print routines
50+ */
51+typedef struct Cconv Fconv;
52+extern char* donprint(char*, char*, char*, void*);
53+extern int sprint(char*, char*, ...);
54+extern char* seprint(char*, char*, char*, ...);
55+extern int snprint(char*, int, char*, ...);
56+extern int print(char*, ...);
57+
58+/*
59+ * one-of-a-kind
60+ */
61+extern char* cleanname(char*);
62+extern ulong getcallerpc(void*);
63+extern long strtol(char*, char**, int);
64+extern ulong strtoul(char*, char**, int);
65+extern vlong strtoll(char*, char**, int);
66+extern uvlong strtoull(char*, char**, int);
67+extern char etext[];
68+extern char edata[];
69+extern char end[];
70+extern int getfields(char*, char**, int, int, char*);
71+
72+/*
73+ * Syscall data structures
74+ */
75+#define MORDER 0x0003 /* mask for bits defining order of mounting */
76+#define MREPL 0x0000 /* mount replaces object */
77+#define MBEFORE 0x0001 /* mount goes before others in union directory */
78+#define MAFTER 0x0002 /* mount goes after others in union directory */
79+#define MCREATE 0x0004 /* permit creation in mounted directory */
80+#define MCACHE 0x0010 /* cache some data */
81+#define MMASK 0x001F /* all bits on */
82+
83+#define OREAD 0 /* open for read */
84+#define OWRITE 1 /* write */
85+#define ORDWR 2 /* read and write */
86+#define OEXEC 3 /* execute, == read but check execute permission */
87+#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
88+#define OCEXEC 32 /* or'ed in, close on exec */
89+#define ORCLOSE 64 /* or'ed in, remove on close */
90+
91+#define NCONT 0 /* continue after note */
92+#define NDFLT 1 /* terminate after note */
93+#define NSAVE 2 /* clear note but hold state */
94+#define NRSTR 3 /* restore saved state */
95+
96+typedef struct Qid Qid;
97+typedef struct Dir Dir;
98+typedef struct Waitmsg Waitmsg;
99+
100+#define ERRLEN 64
101+#define DIRLEN 116
102+#define NAMELEN 28
103+
104+struct Qid
105+{
106+ ulong path;
107+ ulong vers;
108+};
109+
110+struct Dir
111+{
112+ char name[NAMELEN];
113+ char uid[NAMELEN];
114+ char gid[NAMELEN];
115+ Qid qid;
116+ ulong mode;
117+ long atime;
118+ long mtime;
119+ vlong length;
120+ short type;
121+ short dev;
122+};
123+
124+struct Waitmsg
125+{
126+ char pid[12]; /* of loved one */
127+ char time[3*12]; /* of loved one and descendants */
128+ char msg[ERRLEN];
129+};
130+
131+/*
132+ * locks
133+ */
134+typedef
135+struct Lock {
136+ int val;
137+} Lock;
138+
139+extern int _tas(int*);
140+
141+extern void lock(Lock*);
142+extern void unlock(Lock*);
143+extern int canlock(Lock*);
os/boot/arm1110/map+10−0
@@ -0,0 +1,10 @@
1+defn acidmap()
2+{
3+ local dfoffset;
4+
5+ dfoffset = map()[1][3];
6+ map({"text", _start, etext, 0x20});
7+ map({"data", etext+1, edata, dfoffset});
8+ print("Set map for plan 9 kernel image\n");
9+ print("btext ", _start, " etext ", etext, "\n");
10+}
os/boot/arm1110/mem.h+215−0
@@ -0,0 +1,215 @@
1+/*
2+ * Memory and machine-specific definitions. Used in C and assembler.
3+ */
4+
5+/*
6+ * Sizes
7+ */
8+#define BI2BY 8 /* bits per byte */
9+#define BI2WD 32 /* bits per word */
10+#define BY2WD 4 /* bytes per word */
11+#define BY2V 8 /* bytes per double word */
12+#define BY2PG 4096 /* bytes per page */
13+#define WD2PG (BY2PG/BY2WD) /* words per page */
14+#define PGSHIFT 12 /* log(BY2PG) */
15+#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
16+#define PGROUND(s) ROUND(s, BY2PG)
17+#define BLOCKALIGN 8
18+
19+#define MAXMACH 1 /* max # cpus system can run */
20+
21+/*
22+ * Time
23+ */
24+#define HZ (20) /* clock frequency */
25+#define MS2HZ (1000/HZ) /* millisec per clock tick */
26+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
27+#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
28+#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
29+
30+/*
31+ * Virtual addresses:
32+ *
33+ * We direct map all discovered DRAM and the area twixt 0xe0000000 and
34+ * 0xe8000000 used to provide zeros for cache flushing.
35+ *
36+ * Flash is mapped to 0xb0000000 and special registers are mapped
37+ * on demand to areas starting at 0xa0000000.
38+ *
39+ * The direct mapping is convenient but not necessary. It means
40+ * that we don't have to turn on the MMU till well into the
41+ * kernel. This can be changed by providing a mapping in l.s
42+ * before calling main.
43+ */
44+#define UZERO 0 /* base of user address space */
45+#define UTZERO (UZERO+BY2PG) /* first address in user text */
46+#define KZERO 0xC0000000 /* base of kernel address space */
47+#define KTZERO 0xC0008000 /* first address in kernel text */
48+#define EMEMZERO 0x90000000 /* 256 meg for add on memory */
49+#define EMEMTOP 0xA0000000 /* ... */
50+#define REGZERO 0xA0000000 /* 128 meg for mapspecial regs */
51+#define REGTOP 0xA8000000 /* ... */
52+#define FLASHZERO 0xB0000000 /* 128 meg for flash */
53+#define FLASHTOP 0xB8000000 /* ... */
54+#define DRAMZERO 0xC0000000 /* 128 meg for dram */
55+#define DRAMTOP 0xC8000000 /* ... */
56+#define UCDRAMZERO 0xC8000000 /* 128 meg for dram (uncached/unbuffered) */
57+#define UCDRAMTOP 0xD0000000 /* ... */
58+#define NULLZERO 0xE0000000 /* 128 meg for cache flush zeroes */
59+#define NULLTOP 0xE8000000 /* ... */
60+#define USTKTOP 0x2000000 /* byte just beyond user stack */
61+#define USTKSIZE (8*1024*1024) /* size of user stack */
62+#define TSTKTOP (USTKTOP-USTKSIZE) /* end of new stack in sysexec */
63+#define TSTKSIZ 100
64+#define MACHADDR (KZERO+0x00001000)
65+#define EVECTORS 0xFFFF0000 /* virt base of exception vectors */
66+
67+#define KSTACK (16*1024) /* Size of kernel stack */
68+
69+#define FLATESIZE (700*1024) /* maximum size of compressed image */
70+
71+/*
72+ * Offsets into flash
73+ */
74+#define Flash_bootldr (FLASHZERO+0x0) /* boot loader */
75+#define Flash_kernel (FLASHZERO+0x10000) /* boot kernel */
76+#define Flash_tar (FLASHZERO+0x100000) /* tar file containing fs.sac */
77+
78+/*
79+ * virtual MMU
80+ */
81+#define PTEMAPMEM (1024*1024)
82+#define PTEPERTAB (PTEMAPMEM/BY2PG)
83+#define SEGMAPSIZE 1984
84+#define SSEGMAPSIZE 16
85+#define PPN(x) ((x)&~(BY2PG-1))
86+
87+/*
88+ * SA1110 definitions
89+ */
90+
91+/*
92+ * memory physical addresses
93+ */
94+#define PHYSFLASH0 0x00000000
95+#define PHYSDRAM0 0xC0000000
96+#define PHYSNULL0 0xE0000000
97+
98+/*
99+ * peripheral control module physical addresses
100+ */
101+#define USBREGS 0x80000000 /* serial port 0 - USB */
102+#define UART1REGS 0x80010000 /* serial port 1 - UART */
103+#define GPCLKREGS 0x80020060 /* serial port 1 - general purpose clock */
104+#define UART2REGS 0x80030000 /* serial port 2 - low speed IR */
105+#define HSSPREGS 0x80040060 /* serial port 2 - high speed IR */
106+#define UART3REGS 0x80050000 /* serial port 3 - RS232 UART */
107+#define MCPREGS 0x80060000 /* serial port 4 - multimedia comm port */
108+#define SSPREGS 0x80070060 /* serial port 4 - synchronous serial port */
109+#define OSTIMERREGS 0x90000000 /* operating system timer registers */
110+#define POWERREGS 0x90020000 /* power management */
111+#define GPIOREGS 0x90040000 /* 28 general purpose IO pins */
112+#define INTRREGS 0x90050000 /* interrupt registers */
113+#define PPCREGS 0x90060000 /* peripheral pin controller */
114+#define MEMCONFREGS 0xA0000000 /* memory configuration */
115+#define LCDREGS 0xB0100000 /* display */
116+
117+/*
118+ * PCMCIA addresses
119+ */
120+#define PHYSPCM0REGS 0x20000000
121+#define PYHSPCM0ATTR 0x28000000
122+#define PYHSPCM0MEM 0x2C000000
123+#define PHYSPCM1REGS 0x30000000
124+#define PYHSPCM1ATTR 0x38000000
125+#define PYHSPCM1MEM 0x3C000000
126+
127+/*
128+ * Program Status Registers
129+ */
130+#define PsrMusr 0x00000010 /* mode */
131+#define PsrMfiq 0x00000011
132+#define PsrMirq 0x00000012
133+#define PsrMsvc 0x00000013
134+#define PsrMabt 0x00000017
135+#define PsrMund 0x0000001B
136+#define PsrMask 0x0000001F
137+
138+#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
139+#define PsrDirq 0x00000080 /* disable IRQ interrupts */
140+
141+#define PsrV 0x10000000 /* overflow */
142+#define PsrC 0x20000000 /* carry/borrow/extend */
143+#define PsrZ 0x40000000 /* zero */
144+#define PsrN 0x80000000 /* negative/less than */
145+
146+/*
147+ * Coprocessors
148+ */
149+#define CpMMU 15
150+#define CpPWR 15
151+
152+/*
153+ * Internal MMU coprocessor registers
154+ */
155+#define CpCPUID 0 /* R: */
156+#define CpControl 1 /* R: */
157+#define CpTTB 2 /* RW: translation table base */
158+#define CpDAC 3 /* RW: domain access control */
159+#define CpFSR 5 /* RW: fault status */
160+#define CpFAR 6 /* RW: fault address */
161+#define CpCacheFlush 7 /* W: cache flushing, wb draining*/
162+#define CpTLBFlush 8 /* W: TLB flushing */
163+#define CpRBFlush 9 /* W: Read Buffer ops */
164+#define CpPID 13 /* RW: PID for virtual mapping */
165+#define CpBpt 14 /* W: Breakpoint register */
166+#define CpTest 15 /* W: Test, Clock and Idle Control */
167+
168+/*
169+ * CpControl
170+ */
171+#define CpCmmuena 0x00000001 /* M: MMU enable */
172+#define CpCalign 0x00000002 /* A: alignment fault enable */
173+#define CpCdcache 0x00000004 /* C: data cache on */
174+#define CpCwb 0x00000008 /* W: write buffer turned on */
175+#define CpCi32 0x00000010 /* P: 32-bit program space */
176+#define CpCd32 0x00000020 /* D: 32-bit data space */
177+#define CpCbe 0x00000080 /* B: big-endian operation */
178+#define CpCsystem 0x00000100 /* S: system permission */
179+#define CpCrom 0x00000200 /* R: ROM permission */
180+#define CpCicache 0x00001000 /* I: instruction cache on */
181+#define CpCvivec 0x00002000 /* X: virtual interrupt vector adjust */
182+
183+/*
184+ * fault codes
185+ */
186+#define FCterm 0x2 /* terminal */
187+#define FCvec 0x0 /* vector */
188+#define FCalignf 0x1 /* unaligned full word data access */
189+#define FCalignh 0x3 /* unaligned half word data access */
190+#define FCl1abort 0xc /* level 1 external abort on translation */
191+#define FCl2abort 0xe /* level 2 external abort on translation */
192+#define FCtransSec 0x5 /* section translation */
193+#define FCtransPage 0x7 /* page translation */
194+#define FCdomainSec 0x9 /* section domain */
195+#define FCdomainPage 0x11 /* page domain */
196+#define FCpermSec 0x9 /* section permissions */
197+#define FCpermPage 0x11 /* page permissions */
198+#define FCabortLFSec 0x4 /* external abort on linefetch for section */
199+#define FCabortLFPage 0x6 /* external abort on linefetch for page */
200+#define FCabortNLFSec 0x8 /* external abort on non-linefetch for section */
201+#define FCabortNLFPage 0xa /* external abort on non-linefetch for page */
202+
203+/*
204+ * PTE bits used by fault.h. mmu.c translates them to real values.
205+ */
206+#define PTEVALID (1<<0)
207+#define PTERONLY 0 /* this is implied by the absence of PTEWRITE */
208+#define PTEWRITE (1<<1)
209+#define PTEUNCACHED (1<<2)
210+#define PTEKERNEL (1<<3) /* no user access */
211+
212+/*
213+ * H3650 specific definitions
214+ */
215+#define EGPIOREGS 0x49000000 /* Additional GPIO register */
os/boot/arm1110/mkfile+86−0
@@ -0,0 +1,86 @@
1+<../../../mkconfig
2+objtype=arm
3+SYSTARG=$OSTARG
4+OBJTYPE=arm
5+BIN=$ROOT/Inferno/$OBJTYPE
6+LIBDIR=$ROOT/Inferno/$OBJTYPE/lib
7+LIBDIRS=../libflate $ROOT/libkern
8+LIBS=\
9+ libflate\
10+ libkern\
11+
12+LIBFILES=${LIBS:%=$LIBDIR/%.a}
13+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
14+
15+BIN=$ROOT/Inferno/$OBJTYPE
16+
17+TARG=\
18+ inflate\
19+
20+INFLATE=\
21+ il.$O\
22+ imain.$O\
23+
24+CORE=\
25+ uart.$O\
26+ inflate.$O\
27+ donprint.$O\
28+ print.$O\
29+
30+HFILES=\
31+ mem.h\
32+
33+CFLAGS=-FVw -I. -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include
34+
35+all:V: $TARG
36+
37+install:V: $BIN/$TARG
38+
39+$BIN/%: %
40+ cp $stem $BIN/$stem
41+
42+inflate: $INFLATE $CORE $LIBFILES
43+ $LD -o s$target -R4 -T0xC0200010 -l $prereq
44+ $LD -o _$target -H5 -R4 -T0xC0200010 -l $prereq
45+ dd -conv sync -ibs 20k -if _$target -of $target
46+
47+%.$O: %.s
48+ $AS $stem.s
49+
50+%.$O: %.c
51+ $CC $CFLAGS $stem.c
52+
53+%.$O: $HFILES
54+
55+clean:
56+ rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG _$TARG s$TARG
57+
58+
59+# added to cause libflate to be made automatically:
60+
61+$ROOT/Inferno/$OBJTYPE/lib/lib%.a:Q: all-$SHELLTYPE
62+ #
63+
64+rc-lib%.a nt-lib%.a:VQ:
65+ echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
66+ @{builtin cd $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
67+
68+sh-lib%.a:VQ:
69+ echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
70+ (cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
71+
72+%-sh:QV:
73+ for i in $LIBDIRS
74+ do
75+ echo "(cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem)"
76+ (cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem)
77+ done
78+
79+%-rc %-nt:QV:
80+ for (i in $LIBDIRS)
81+ {
82+ echo '@{cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem}'
83+ @{cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem}
84+ }
85+
86+nuke:V: clean nuke-$SHELLTYPE
os/boot/arm1110/print.c+56−0
@@ -0,0 +1,56 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "fns.h"
4+#include "dat.h"
5+
6+
7+#define SIZE 1024
8+
9+int
10+print(char *fmt, ...)
11+{
12+ char buf[SIZE], *out;
13+ va_list arg;
14+
15+ va_start(arg, fmt);
16+ out = donprint(buf, buf+SIZE, fmt, arg);
17+ va_end(arg);
18+ serialputs(buf, out-buf);
19+ return out-buf;
20+}
21+
22+int
23+sprint(char *buf, char *fmt, ...)
24+{
25+ char *out;
26+ va_list arg;
27+
28+ va_start(arg, fmt);
29+ out = donprint(buf, buf+SIZE, fmt, arg);
30+ va_end(arg);
31+ return out-buf;
32+}
33+
34+int
35+snprint(char *buf, int len, char *fmt, ...)
36+{
37+ char *out;
38+ va_list arg;
39+
40+ va_start(arg, fmt);
41+ out = donprint(buf, buf+len, fmt, arg);
42+ va_end(arg);
43+ return out-buf;
44+}
45+
46+char*
47+seprint(char *buf, char *e, char *fmt, ...)
48+{
49+ char *out;
50+ va_list arg;
51+
52+ va_start(arg, fmt);
53+ out = donprint(buf, e, fmt, arg);
54+ va_end(arg);
55+ return out;
56+}
os/boot/arm1110/uart.c+69−0
@@ -0,0 +1,69 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+enum
9+{
10+ /* ctl[0] bits */
11+ Parity= 1<<0,
12+ Even= 1<<1,
13+ Stop2= 1<<2,
14+ Bits8= 1<<3,
15+ SCE= 1<<4, /* synchronous clock enable */
16+ RCE= 1<<5, /* rx on falling edge of clock */
17+ TCE= 1<<6, /* tx on falling edge of clock */
18+
19+ /* ctl[3] bits */
20+ Rena= 1<<0, /* receiver enable */
21+ Tena= 1<<1, /* transmitter enable */
22+ Break= 1<<2, /* force TXD3 low */
23+ Rintena= 1<<3, /* enable receive interrupt */
24+ Tintena= 1<<4, /* enable transmitter interrupt */
25+ Loopback= 1<<5, /* loop back data */
26+
27+ /* data bits */
28+ DEparity= 1<<8, /* parity error */
29+ DEframe= 1<<9, /* framing error */
30+ DEoverrun= 1<<10, /* overrun error */
31+
32+ /* status[0] bits */
33+ Tint= 1<<0, /* transmit fifo half full interrupt */
34+ Rint0= 1<<1, /* receiver fifo 1/3-2/3 full */
35+ Rint1= 1<<2, /* receiver fifo not empty and receiver idle */
36+ Breakstart= 1<<3,
37+ Breakend= 1<<4,
38+ Fifoerror= 1<<5, /* fifo error */
39+
40+ /* status[1] bits */
41+ Tbusy= 1<<0, /* transmitting */
42+ Rnotempty= 1<<1, /* receive fifo not empty */
43+ Tnotfull= 1<<2, /* transmit fifo not full */
44+ ParityError= 1<<3,
45+ FrameError= 1<<4,
46+ Overrun= 1<<5,
47+};
48+
49+Uartregs *uart3regs = UART3REGS;
50+
51+
52+/*
53+ * for iprint, just write it
54+ */
55+void
56+serialputs(char *str, int n)
57+{
58+ Uartregs *ur;
59+
60+ ur = uart3regs;
61+ while(n-- > 0){
62+ /* wait for output ready */
63+ while((ur->status[1] & Tnotfull) == 0)
64+ ;
65+ ur->data = *str++;
66+ }
67+ while((ur->status[1] & Tbusy))
68+ ;
69+}
os/boot/libflate/LICENCE+237−0
@@ -0,0 +1,237 @@
1+Lucent Public License Version 1.02
2+
3+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
4+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
5+PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
6+
7+1. DEFINITIONS
8+
9+"Contribution" means:
10+
11+ a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
12+ Program, and
13+ b. in the case of each Contributor,
14+
15+ i. changes to the Program, and
16+ ii. additions to the Program;
17+
18+ where such changes and/or additions to the Program were added to the
19+ Program by such Contributor itself or anyone acting on such
20+ Contributor's behalf, and the Contributor explicitly consents, in
21+ accordance with Section 3C, to characterization of the changes and/or
22+ additions as Contributions.
23+
24+"Contributor" means LUCENT and any other entity that has Contributed a
25+Contribution to the Program.
26+
27+"Distributor" means a Recipient that distributes the Program,
28+modifications to the Program, or any part thereof.
29+
30+"Licensed Patents" mean patent claims licensable by a Contributor
31+which are necessarily infringed by the use or sale of its Contribution
32+alone or when combined with the Program.
33+
34+"Original Program" means the original version of the software
35+accompanying this Agreement as released by LUCENT, including source
36+code, object code and documentation, if any.
37+
38+"Program" means the Original Program and Contributions or any part
39+thereof
40+
41+"Recipient" means anyone who receives the Program under this
42+Agreement, including all Contributors.
43+
44+2. GRANT OF RIGHTS
45+
46+ a. Subject to the terms of this Agreement, each Contributor hereby
47+ grants Recipient a non-exclusive, worldwide, royalty-free copyright
48+ license to reproduce, prepare derivative works of, publicly display,
49+ publicly perform, distribute and sublicense the Contribution of such
50+ Contributor, if any, and such derivative works, in source code and
51+ object code form.
52+
53+ b. Subject to the terms of this Agreement, each Contributor hereby
54+ grants Recipient a non-exclusive, worldwide, royalty-free patent
55+ license under Licensed Patents to make, use, sell, offer to sell,
56+ import and otherwise transfer the Contribution of such Contributor, if
57+ any, in source code and object code form. The patent license granted
58+ by a Contributor shall also apply to the combination of the
59+ Contribution of that Contributor and the Program if, at the time the
60+ Contribution is added by the Contributor, such addition of the
61+ Contribution causes such combination to be covered by the Licensed
62+ Patents. The patent license granted by a Contributor shall not apply
63+ to (i) any other combinations which include the Contribution, nor to
64+ (ii) Contributions of other Contributors. No hardware per se is
65+ licensed hereunder.
66+
67+ c. Recipient understands that although each Contributor grants the
68+ licenses to its Contributions set forth herein, no assurances are
69+ provided by any Contributor that the Program does not infringe the
70+ patent or other intellectual property rights of any other entity. Each
71+ Contributor disclaims any liability to Recipient for claims brought by
72+ any other entity based on infringement of intellectual property rights
73+ or otherwise. As a condition to exercising the rights and licenses
74+ granted hereunder, each Recipient hereby assumes sole responsibility
75+ to secure any other intellectual property rights needed, if any. For
76+ example, if a third party patent license is required to allow
77+ Recipient to distribute the Program, it is Recipient's responsibility
78+ to acquire that license before distributing the Program.
79+
80+ d. Each Contributor represents that to its knowledge it has sufficient
81+ copyright rights in its Contribution, if any, to grant the copyright
82+ license set forth in this Agreement.
83+
84+3. REQUIREMENTS
85+
86+A. Distributor may choose to distribute the Program in any form under
87+this Agreement or under its own license agreement, provided that:
88+
89+ a. it complies with the terms and conditions of this Agreement;
90+
91+ b. if the Program is distributed in source code or other tangible
92+ form, a copy of this Agreement or Distributor's own license agreement
93+ is included with each copy of the Program; and
94+
95+ c. if distributed under Distributor's own license agreement, such
96+ license agreement:
97+
98+ i. effectively disclaims on behalf of all Contributors all warranties
99+ and conditions, express and implied, including warranties or
100+ conditions of title and non-infringement, and implied warranties or
101+ conditions of merchantability and fitness for a particular purpose;
102+ ii. effectively excludes on behalf of all Contributors all liability
103+ for damages, including direct, indirect, special, incidental and
104+ consequential damages, such as lost profits; and
105+ iii. states that any provisions which differ from this Agreement are
106+ offered by that Contributor alone and not by any other party.
107+
108+B. Each Distributor must include the following in a conspicuous
109+ location in the Program:
110+
111+ Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
112+ Reserved.
113+
114+C. In addition, each Contributor must identify itself as the
115+originator of its Contribution in a manner that reasonably allows
116+subsequent Recipients to identify the originator of the Contribution.
117+Also, each Contributor must agree that the additions and/or changes
118+are intended to be a Contribution. Once a Contribution is contributed,
119+it may not thereafter be revoked.
120+
121+4. COMMERCIAL DISTRIBUTION
122+
123+Commercial distributors of software may accept certain
124+responsibilities with respect to end users, business partners and the
125+like. While this license is intended to facilitate the commercial use
126+of the Program, the Distributor who includes the Program in a
127+commercial product offering should do so in a manner which does not
128+create potential liability for Contributors. Therefore, if a
129+Distributor includes the Program in a commercial product offering,
130+such Distributor ("Commercial Distributor") hereby agrees to defend
131+and indemnify every Contributor ("Indemnified Contributor") against
132+any losses, damages and costs (collectively"Losses") arising from
133+claims, lawsuits and other legal actions brought by a third party
134+against the Indemnified Contributor to the extent caused by the acts
135+or omissions of such Commercial Distributor in connection with its
136+distribution of the Program in a commercial product offering. The
137+obligations in this section do not apply to any claims or Losses
138+relating to any actual or alleged intellectual property infringement.
139+In order to qualify, an Indemnified Contributor must: a) promptly
140+notify the Commercial Distributor in writing of such claim, and b)
141+allow the Commercial Distributor to control, and cooperate with the
142+Commercial Distributor in, the defense and any related settlement
143+negotiations. The Indemnified Contributor may participate in any such
144+claim at its own expense.
145+
146+For example, a Distributor might include the Program in a commercial
147+product offering, Product X. That Distributor is then a Commercial
148+Distributor. If that Commercial Distributor then makes performance
149+claims, or offers warranties related to Product X, those performance
150+claims and warranties are such Commercial Distributor's responsibility
151+alone. Under this section, the Commercial Distributor would have to
152+defend claims against the Contributors related to those performance
153+claims and warranties, and if a court requires any Contributor to pay
154+any damages as a result, the Commercial Distributor must pay those
155+damages.
156+
157+5. NO WARRANTY
158+
159+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
160+PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
161+KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
162+WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
163+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
164+responsible for determining the appropriateness of using and
165+distributing the Program and assumes all risks associated with its
166+exercise of rights under this Agreement, including but not limited to
167+the risks and costs of program errors, compliance with applicable
168+laws, damage to or loss of data, programs or equipment, and
169+unavailability or interruption of operations.
170+
171+6. DISCLAIMER OF LIABILITY
172+
173+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
174+ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
175+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
176+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
177+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
178+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
179+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
180+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
181+
182+7. EXPORT CONTROL
183+
184+Recipient agrees that Recipient alone is responsible for compliance
185+with the United States export administration regulations (and the
186+export control laws and regulation of any other countries).
187+
188+8. GENERAL
189+
190+If any provision of this Agreement is invalid or unenforceable under
191+applicable law, it shall not affect the validity or enforceability of
192+the remainder of the terms of this Agreement, and without further
193+action by the parties hereto, such provision shall be reformed to the
194+minimum extent necessary to make such provision valid and enforceable.
195+
196+If Recipient institutes patent litigation against a Contributor with
197+respect to a patent applicable to software (including a cross-claim or
198+counterclaim in a lawsuit), then any patent licenses granted by that
199+Contributor to such Recipient under this Agreement shall terminate as
200+of the date such litigation is filed. In addition, if Recipient
201+institutes patent litigation against any entity (including a
202+cross-claim or counterclaim in a lawsuit) alleging that the Program
203+itself (excluding combinations of the Program with other software or
204+hardware) infringes such Recipient's patent(s), then such Recipient's
205+rights granted under Section 2(b) shall terminate as of the date such
206+litigation is filed.
207+
208+All Recipient's rights under this Agreement shall terminate if it
209+fails to comply with any of the material terms or conditions of this
210+Agreement and does not cure such failure in a reasonable period of
211+time after becoming aware of such noncompliance. If all Recipient's
212+rights under this Agreement terminate, Recipient agrees to cease use
213+and distribution of the Program as soon as reasonably practicable.
214+However, Recipient's obligations under this Agreement and any licenses
215+granted by Recipient relating to the Program shall continue and
216+survive.
217+
218+LUCENT may publish new versions (including revisions) of this
219+Agreement from time to time. Each new version of the Agreement will be
220+given a distinguishing version number. The Program (including
221+Contributions) may always be distributed subject to the version of the
222+Agreement under which it was received. In addition, after a new
223+version of the Agreement is published, Contributor may elect to
224+distribute the Program (including its Contributions) under the new
225+version. No one other than LUCENT has the right to modify this
226+Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
227+Recipient receives no rights or licenses to the intellectual property
228+of any Contributor under this Agreement, whether expressly, by
229+implication, estoppel or otherwise. All rights in the Program not
230+expressly granted under this Agreement are reserved.
231+
232+This Agreement is governed by the laws of the State of New York and
233+the intellectual property laws of the United States of America. No
234+party to this Agreement will bring a legal action under this Agreement
235+more than one year after the cause of action arose. Each party waives
236+its rights to a jury trial in any resulting litigation.
237+
os/boot/libflate/NOTICE+8−0
@@ -0,0 +1,8 @@
1+Copyright © 2002 Lucent Technologies Inc.
2+All Rights Reserved
3+
4+This software was originally developed for Plan 9.
5+It is provided under the terms of the Lucent Public License, Version 1.02.
6+
7+Trivial modifications have been made to make it compile for Inferno.
8+ Vita Nuova Holdings Limited.
os/boot/libflate/adler.c+71−0
@@ -0,0 +1,71 @@
1+#include "lib9.h"
2+#include <flate.h>
3+
4+enum
5+{
6+ ADLERITERS = 5552, /* max iters before can overflow 32 bits */
7+ ADLERBASE = 65521 /* largest prime smaller than 65536 */
8+};
9+
10+ulong
11+adler32(ulong adler, void *vbuf, int n)
12+{
13+ ulong s1, s2;
14+ uchar *buf, *ebuf;
15+ int m;
16+
17+ buf = vbuf;
18+ s1 = adler & 0xffff;
19+ s2 = (adler >> 16) & 0xffff;
20+ for(; n >= 16; n -= m){
21+ m = n;
22+ if(m > ADLERITERS)
23+ m = ADLERITERS;
24+ m &= ~15;
25+ for(ebuf = buf + m; buf < ebuf; buf += 16){
26+ s1 += buf[0];
27+ s2 += s1;
28+ s1 += buf[1];
29+ s2 += s1;
30+ s1 += buf[2];
31+ s2 += s1;
32+ s1 += buf[3];
33+ s2 += s1;
34+ s1 += buf[4];
35+ s2 += s1;
36+ s1 += buf[5];
37+ s2 += s1;
38+ s1 += buf[6];
39+ s2 += s1;
40+ s1 += buf[7];
41+ s2 += s1;
42+ s1 += buf[8];
43+ s2 += s1;
44+ s1 += buf[9];
45+ s2 += s1;
46+ s1 += buf[10];
47+ s2 += s1;
48+ s1 += buf[11];
49+ s2 += s1;
50+ s1 += buf[12];
51+ s2 += s1;
52+ s1 += buf[13];
53+ s2 += s1;
54+ s1 += buf[14];
55+ s2 += s1;
56+ s1 += buf[15];
57+ s2 += s1;
58+ }
59+ s1 %= ADLERBASE;
60+ s2 %= ADLERBASE;
61+ }
62+ if(n){
63+ for(ebuf = buf + n; buf < ebuf; buf++){
64+ s1 += buf[0];
65+ s2 += s1;
66+ }
67+ s1 %= ADLERBASE;
68+ s2 %= ADLERBASE;
69+ }
70+ return (s2 << 16) + s1;
71+}
os/boot/libflate/crc.c+39−0
@@ -0,0 +1,39 @@
1+#include "lib9.h"
2+#include <flate.h>
3+
4+ulong*
5+mkcrctab(ulong poly)
6+{
7+ ulong *crctab;
8+ ulong crc;
9+ int i, j;
10+
11+ crctab = malloc(256 * sizeof(ulong));
12+ if(crctab == nil)
13+ return nil;
14+
15+ for(i = 0; i < 256; i++){
16+ crc = i;
17+ for(j = 0; j < 8; j++){
18+ if(crc & 1)
19+ crc = (crc >> 1) ^ poly;
20+ else
21+ crc >>= 1;
22+ }
23+ crctab[i] = crc;
24+ }
25+ return crctab;
26+}
27+
28+ulong
29+blockcrc(ulong *crctab, ulong crc, void *vbuf, int n)
30+{
31+ uchar *buf, *ebuf;
32+
33+ crc ^= 0xffffffff;
34+ buf = vbuf;
35+ ebuf = buf + n;
36+ while(buf < ebuf)
37+ crc = crctab[(crc & 0xff) ^ *buf++] ^ (crc >> 8);
38+ return crc ^ 0xffffffff;
39+}
os/boot/libflate/deflate.c+1358−0
@@ -0,0 +1,1358 @@
1+#include "lib9.h"
2+#include <flate.h>
3+
4+typedef struct Chain Chain;
5+typedef struct Chains Chains;
6+typedef struct Dyncode Dyncode;
7+typedef struct Huff Huff;
8+typedef struct LZblock LZblock;
9+typedef struct LZstate LZstate;
10+
11+enum
12+{
13+ /*
14+ * deflate format paramaters
15+ */
16+ DeflateUnc = 0, /* uncompressed block */
17+ DeflateFix = 1, /* fixed huffman codes */
18+ DeflateDyn = 2, /* dynamic huffman codes */
19+
20+ DeflateEob = 256, /* end of block code in lit/len book */
21+ DeflateMaxBlock = 64*1024-1, /* maximum size of uncompressed block */
22+
23+ DeflateMaxExp = 10, /* maximum expansion for a block */
24+
25+ LenStart = 257, /* start of length codes in litlen */
26+ Nlitlen = 288, /* number of litlen codes */
27+ Noff = 30, /* number of offset codes */
28+ Nclen = 19, /* number of codelen codes */
29+
30+ MaxOff = 32*1024,
31+ MinMatch = 3, /* shortest match possible */
32+ MaxMatch = 258, /* longest match possible */
33+
34+ /*
35+ * huffman code paramaters
36+ */
37+ MaxLeaf = Nlitlen,
38+ MaxHuffBits = 16, /* max bits in a huffman code */
39+ ChainMem = 2 * (MaxHuffBits - 1) * MaxHuffBits,
40+
41+ /*
42+ * coding of the lz parse
43+ */
44+ LenFlag = 1 << 3,
45+ LenShift = 4, /* leaves enough space for MinMatchMaxOff */
46+ MaxLitRun = LenFlag - 1,
47+
48+ /*
49+ * internal lz paramaters
50+ */
51+ DeflateOut = 4096, /* output buffer size */
52+ BlockSize = 8192, /* attempted input read quanta */
53+ DeflateBlock = DeflateMaxBlock & ~(BlockSize - 1),
54+ MinMatchMaxOff = 4096, /* max profitable offset for small match;
55+ * assumes 8 bits for len, 5+10 for offset
56+ * DONT CHANGE WITHOUT CHANGING LZPARSE CONSTANTS
57+ */
58+ HistSlop = 512, /* must be at lead MaxMatch */
59+ HistBlock = 64*1024,
60+ HistSize = HistBlock + HistSlop,
61+
62+ HashLog = 13,
63+ HashSize = 1<<HashLog,
64+
65+ MaxOffCode = 256, /* biggest offset looked up in direct table */
66+
67+ EstLitBits = 8,
68+ EstLenBits = 4,
69+ EstOffBits = 5,
70+};
71+
72+/*
73+ * knuth vol. 3 multiplicative hashing
74+ * each byte x chosen according to rules
75+ * 1/4 < x < 3/10, 1/3 x < < 3/7, 4/7 < x < 2/3, 7/10 < x < 3/4
76+ * with reasonable spread between the bytes & their complements
77+ *
78+ * the 3 byte value appears to be as almost good as the 4 byte value,
79+ * and might be faster on some machines
80+ */
81+/*
82+#define hashit(c) (((ulong)(c) * 0x6b43a9) >> (24 - HashLog))
83+*/
84+#define hashit(c) ((((ulong)(c) & 0xffffff) * 0x6b43a9b5) >> (32 - HashLog))
85+
86+/*
87+ * lempel-ziv style compression state
88+ */
89+struct LZstate
90+{
91+ uchar hist[HistSize];
92+ ulong pos; /* current location in history buffer */
93+ ulong avail; /* data available after pos */
94+ int eof;
95+ ushort hash[HashSize]; /* hash chains */
96+ ushort nexts[MaxOff];
97+ int now; /* pos in hash chains */
98+ int dot; /* dawn of time in history */
99+ int prevlen; /* lazy matching state */
100+ int prevoff;
101+ int maxcheck; /* compressor tuning */
102+
103+ uchar obuf[DeflateOut];
104+ uchar *out; /* current position in the output buffer */
105+ uchar *eout;
106+ ulong bits; /* bit shift register */
107+ int nbits;
108+ int rbad; /* got an error reading the buffer */
109+ int wbad; /* got an error writing the buffer */
110+ int (*w)(void*, void*, int);
111+ void *wr;
112+
113+ ulong totr; /* total input size */
114+ ulong totw; /* total output size */
115+ int debug;
116+};
117+
118+struct LZblock
119+{
120+ ushort parse[DeflateMaxBlock / 2 + 1];
121+ int lastv; /* value being constucted for parse */
122+ ulong litlencount[Nlitlen];
123+ ulong offcount[Noff];
124+ ushort *eparse; /* limit for parse table */
125+ int bytes; /* consumed from the input */
126+ int excost; /* cost of encoding extra len & off bits */
127+};
128+
129+/*
130+ * huffman code table
131+ */
132+struct Huff
133+{
134+ short bits; /* length of the code */
135+ ushort encode; /* the code */
136+};
137+
138+/*
139+ * encoding of dynamic huffman trees
140+ */
141+struct Dyncode
142+{
143+ int nlit;
144+ int noff;
145+ int nclen;
146+ int ncode;
147+ Huff codetab[Nclen];
148+ uchar codes[Nlitlen+Noff];
149+ uchar codeaux[Nlitlen+Noff];
150+};
151+
152+static int deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int));
153+static int lzcomp(LZstate*, LZblock*, uchar*, ushort*, int finish);
154+static void wrblock(LZstate*, int, ushort*, ushort*, Huff*, Huff*);
155+static int bitcost(Huff*, ulong*, int);
156+static int huffcodes(Dyncode*, Huff*, Huff*);
157+static void wrdyncode(LZstate*, Dyncode*);
158+static void lzput(LZstate*, ulong bits, int nbits);
159+static void lzflushbits(LZstate*);
160+static void lzflush(LZstate *lz);
161+static void lzwrite(LZstate *lz, void *buf, int n);
162+
163+static int hufftabinit(Huff*, int, ulong*, int);
164+static int mkgzprecode(Huff*, ulong *, int, int);
165+
166+static int mkprecode(Huff*, ulong *, int, int, ulong*);
167+static void nextchain(Chains*, int);
168+static void leafsort(ulong*, ushort*, int, int);
169+
170+/* conversion from len to code word */
171+static int lencode[MaxMatch];
172+
173+/*
174+ * conversion from off to code word
175+ * off <= MaxOffCode ? offcode[off] : bigoffcode[off >> 7]
176+*/
177+static int offcode[MaxOffCode];
178+static int bigoffcode[256];
179+
180+/* litlen code words LenStart-285 extra bits */
181+static int litlenbase[Nlitlen-LenStart];
182+static int litlenextra[Nlitlen-LenStart] =
183+{
184+/* 257 */ 0, 0, 0,
185+/* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
186+/* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
187+/* 280 */ 4, 5, 5, 5, 5, 0, 0, 0
188+};
189+
190+/* offset code word extra bits */
191+static int offbase[Noff];
192+static int offextra[] =
193+{
194+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
195+ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
196+ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
197+ 0, 0,
198+};
199+
200+/* order code lengths */
201+static int clenorder[Nclen] =
202+{
203+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
204+};
205+
206+/* static huffman tables */
207+static Huff litlentab[Nlitlen];
208+static Huff offtab[Noff];
209+static Huff hofftab[Noff];
210+
211+/* bit reversal for brain dead endian swap in huffman codes */
212+static uchar revtab[256];
213+static ulong nlits;
214+static ulong nmatches;
215+
216+int
217+deflateinit(void)
218+{
219+ ulong bitcount[MaxHuffBits];
220+ int i, j, ci, n;
221+
222+ /* byte reverse table */
223+ for(i=0; i<256; i++)
224+ for(j=0; j<8; j++)
225+ if(i & (1<<j))
226+ revtab[i] |= 0x80 >> j;
227+
228+ /* static Litlen bit lengths */
229+ for(i=0; i<144; i++)
230+ litlentab[i].bits = 8;
231+ for(i=144; i<256; i++)
232+ litlentab[i].bits = 9;
233+ for(i=256; i<280; i++)
234+ litlentab[i].bits = 7;
235+ for(i=280; i<Nlitlen; i++)
236+ litlentab[i].bits = 8;
237+
238+ memset(bitcount, 0, sizeof(bitcount));
239+ bitcount[8] += 144 - 0;
240+ bitcount[9] += 256 - 144;
241+ bitcount[7] += 280 - 256;
242+ bitcount[8] += Nlitlen - 280;
243+
244+ if(!hufftabinit(litlentab, Nlitlen, bitcount, 9))
245+ return FlateInternal;
246+
247+ /* static offset bit lengths */
248+ for(i = 0; i < Noff; i++)
249+ offtab[i].bits = 5;
250+
251+ memset(bitcount, 0, sizeof(bitcount));
252+ bitcount[5] = Noff;
253+
254+ if(!hufftabinit(offtab, Noff, bitcount, 5))
255+ return FlateInternal;
256+
257+ bitcount[0] = 0;
258+ bitcount[1] = 0;
259+ if(!mkgzprecode(hofftab, bitcount, 2, MaxHuffBits))
260+ return FlateInternal;
261+
262+ /* conversion tables for lens & offs to codes */
263+ ci = 0;
264+ for(i = LenStart; i < 286; i++){
265+ n = ci + (1 << litlenextra[i - LenStart]);
266+ litlenbase[i - LenStart] = ci;
267+ for(; ci < n; ci++)
268+ lencode[ci] = i;
269+ }
270+ /* patch up special case for len MaxMatch */
271+ lencode[MaxMatch-MinMatch] = 285;
272+ litlenbase[285-LenStart] = MaxMatch-MinMatch;
273+
274+ ci = 0;
275+ for(i = 0; i < 16; i++){
276+ n = ci + (1 << offextra[i]);
277+ offbase[i] = ci;
278+ for(; ci < n; ci++)
279+ offcode[ci] = i;
280+ }
281+
282+ ci = ci >> 7;
283+ for(; i < 30; i++){
284+ n = ci + (1 << (offextra[i] - 7));
285+ offbase[i] = ci << 7;
286+ for(; ci < n; ci++)
287+ bigoffcode[ci] = i;
288+ }
289+ return FlateOk;
290+}
291+
292+static void
293+deflatereset(LZstate *lz, int level, int debug)
294+{
295+ memset(lz->nexts, 0, sizeof lz->nexts);
296+ memset(lz->hash, 0, sizeof lz->hash);
297+ lz->totr = 0;
298+ lz->totw = 0;
299+ lz->pos = 0;
300+ lz->avail = 0;
301+ lz->out = lz->obuf;
302+ lz->eout = &lz->obuf[DeflateOut];
303+ lz->prevlen = MinMatch - 1;
304+ lz->prevoff = 0;
305+ lz->now = MaxOff + 1;
306+ lz->dot = lz->now;
307+ lz->bits = 0;
308+ lz->nbits = 0;
309+ lz->maxcheck = (1 << level);
310+ lz->maxcheck -= lz->maxcheck >> 2;
311+ if(lz->maxcheck < 2)
312+ lz->maxcheck = 2;
313+ else if(lz->maxcheck > 1024)
314+ lz->maxcheck = 1024;
315+
316+ lz->debug = debug;
317+}
318+
319+int
320+deflate(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
321+{
322+ LZstate *lz;
323+ LZblock *lzb;
324+ int ok;
325+
326+ lz = malloc(sizeof *lz + sizeof *lzb);
327+ if(lz == nil)
328+ return FlateNoMem;
329+ lzb = (LZblock*)&lz[1];
330+
331+ deflatereset(lz, level, debug);
332+ lz->w = w;
333+ lz->wr = wr;
334+ lz->wbad = 0;
335+ lz->rbad = 0;
336+ lz->eof = 0;
337+ ok = FlateOk;
338+ while(!lz->eof || lz->avail){
339+ ok = deflateb(lz, lzb, rr, r);
340+ if(ok != FlateOk)
341+ break;
342+ }
343+ if(ok == FlateOk && lz->rbad)
344+ ok = FlateInputFail;
345+ if(ok == FlateOk && lz->wbad)
346+ ok = FlateOutputFail;
347+ free(lz);
348+ return ok;
349+}
350+
351+static int
352+deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int))
353+{
354+ Dyncode dyncode, hdyncode;
355+ Huff dlitlentab[Nlitlen], dofftab[Noff], hlitlentab[Nlitlen];
356+ ulong litcount[Nlitlen];
357+ long nunc, ndyn, nfix, nhuff;
358+ uchar *slop, *hslop;
359+ ulong ep;
360+ int i, n, m, mm, nslop;
361+
362+ memset(lzb->litlencount, 0, sizeof lzb->litlencount);
363+ memset(lzb->offcount, 0, sizeof lzb->offcount);
364+ lzb->litlencount[DeflateEob]++;
365+
366+ lzb->bytes = 0;
367+ lzb->eparse = lzb->parse;
368+ lzb->lastv = 0;
369+ lzb->excost = 0;
370+
371+ slop = &lz->hist[lz->pos];
372+ n = lz->avail;
373+ while(n < DeflateBlock && (!lz->eof || lz->avail)){
374+ /*
375+ * fill the buffer as much as possible,
376+ * while leaving room for MaxOff history behind lz->pos,
377+ * and not reading more than we can handle.
378+ *
379+ * make sure we read at least HistSlop bytes.
380+ */
381+ if(!lz->eof){
382+ ep = lz->pos + lz->avail;
383+ if(ep >= HistBlock)
384+ ep -= HistBlock;
385+ m = HistBlock - MaxOff - lz->avail;
386+ if(m > HistBlock - n)
387+ m = HistBlock - n;
388+ if(m > (HistBlock + HistSlop) - ep)
389+ m = (HistBlock + HistSlop) - ep;
390+ if(m & ~(BlockSize - 1))
391+ m &= ~(BlockSize - 1);
392+
393+ /*
394+ * be nice to the caller: stop reads that are too small.
395+ * can only get here when we've already filled the buffer some
396+ */
397+ if(m < HistSlop){
398+ if(!m || !lzb->bytes)
399+ return FlateInternal;
400+ break;
401+ }
402+
403+ mm = (*r)(rr, &lz->hist[ep], m);
404+ if(mm > 0){
405+ /*
406+ * wrap data to end if we're read it from the beginning
407+ * this way, we don't have to wrap searches.
408+ *
409+ * wrap reads past the end to the beginning.
410+ * this way, we can guarantee minimum size reads.
411+ */
412+ if(ep < HistSlop)
413+ memmove(&lz->hist[ep + HistBlock], &lz->hist[ep], HistSlop - ep);
414+ else if(ep + mm > HistBlock)
415+ memmove(&lz->hist[0], &lz->hist[HistBlock], ep + mm - HistBlock);
416+
417+ lz->totr += mm;
418+ n += mm;
419+ lz->avail += mm;
420+ }else{
421+ if(mm < 0)
422+ lz->rbad = 1;
423+ lz->eof = 1;
424+ }
425+ }
426+ ep = lz->pos + lz->avail;
427+ if(ep > HistSize)
428+ ep = HistSize;
429+ if(lzb->bytes + ep - lz->pos > DeflateMaxBlock)
430+ ep = lz->pos + DeflateMaxBlock - lzb->bytes;
431+ m = lzcomp(lz, lzb, &lz->hist[ep], lzb->eparse, lz->eof);
432+ lzb->bytes += m;
433+ lz->pos = (lz->pos + m) & (HistBlock - 1);
434+ lz->avail -= m;
435+ }
436+ if(lzb->lastv)
437+ *lzb->eparse++ = lzb->lastv;
438+ if(lzb->eparse > lzb->parse + nelem(lzb->parse))
439+ return FlateInternal;
440+ nunc = lzb->bytes;
441+
442+ if(!mkgzprecode(dlitlentab, lzb->litlencount, Nlitlen, MaxHuffBits)
443+ || !mkgzprecode(dofftab, lzb->offcount, Noff, MaxHuffBits))
444+ return FlateInternal;
445+
446+ ndyn = huffcodes(&dyncode, dlitlentab, dofftab);
447+ if(ndyn < 0)
448+ return FlateInternal;
449+ ndyn += bitcost(dlitlentab, lzb->litlencount, Nlitlen)
450+ + bitcost(dofftab, lzb->offcount, Noff)
451+ + lzb->excost;
452+
453+ memset(litcount, 0, sizeof litcount);
454+
455+ nslop = nunc;
456+ if(nslop > &lz->hist[HistSize] - slop)
457+ nslop = &lz->hist[HistSize] - slop;
458+
459+ for(i = 0; i < nslop; i++)
460+ litcount[slop[i]]++;
461+ hslop = &lz->hist[HistSlop - nslop];
462+ for(; i < nunc; i++)
463+ litcount[hslop[i]]++;
464+ litcount[DeflateEob]++;
465+
466+ if(!mkgzprecode(hlitlentab, litcount, Nlitlen, MaxHuffBits))
467+ return FlateInternal;
468+ nhuff = huffcodes(&hdyncode, hlitlentab, hofftab);
469+ if(nhuff < 0)
470+ return FlateInternal;
471+ nhuff += bitcost(hlitlentab, litcount, Nlitlen);
472+
473+ nfix = bitcost(litlentab, lzb->litlencount, Nlitlen)
474+ + bitcost(offtab, lzb->offcount, Noff)
475+ + lzb->excost;
476+
477+ lzput(lz, lz->eof && !lz->avail, 1);
478+
479+ if(lz->debug){
480+ fprint(2, "block: bytes=%lud entries=%ld extra bits=%d\n\tuncompressed=%lud fixed=%lud dynamic=%lud huffman=%lud\n",
481+ nunc, lzb->eparse - lzb->parse, lzb->excost, (nunc + 4) * 8, nfix, ndyn, nhuff);
482+ fprint(2, "\tnlit=%lud matches=%lud eof=%d\n", nlits, nmatches, lz->eof && !lz->avail);
483+ }
484+
485+ if((nunc + 4) * 8 < ndyn && (nunc + 4) * 8 < nfix && (nunc + 4) * 8 < nhuff){
486+ lzput(lz, DeflateUnc, 2);
487+ lzflushbits(lz);
488+
489+ lzput(lz, nunc & 0xff, 8);
490+ lzput(lz, (nunc >> 8) & 0xff, 8);
491+ lzput(lz, ~nunc & 0xff, 8);
492+ lzput(lz, (~nunc >> 8) & 0xff, 8);
493+ lzflush(lz);
494+
495+ lzwrite(lz, slop, nslop);
496+ lzwrite(lz, &lz->hist[HistSlop], nunc - nslop);
497+ }else if(ndyn < nfix && ndyn < nhuff){
498+ lzput(lz, DeflateDyn, 2);
499+
500+ wrdyncode(lz, &dyncode);
501+ wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, dlitlentab, dofftab);
502+ lzput(lz, dlitlentab[DeflateEob].encode, dlitlentab[DeflateEob].bits);
503+ }else if(nhuff < nfix){
504+ lzput(lz, DeflateDyn, 2);
505+
506+ wrdyncode(lz, &hdyncode);
507+
508+ m = 0;
509+ for(i = nunc; i > MaxLitRun; i -= MaxLitRun)
510+ lzb->parse[m++] = MaxLitRun;
511+ lzb->parse[m++] = i;
512+
513+ wrblock(lz, slop - lz->hist, lzb->parse, lzb->parse + m, hlitlentab, hofftab);
514+ lzput(lz, hlitlentab[DeflateEob].encode, hlitlentab[DeflateEob].bits);
515+ }else{
516+ lzput(lz, DeflateFix, 2);
517+
518+ wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, litlentab, offtab);
519+ lzput(lz, litlentab[DeflateEob].encode, litlentab[DeflateEob].bits);
520+ }
521+
522+ if(lz->eof && !lz->avail){
523+ lzflushbits(lz);
524+ lzflush(lz);
525+ }
526+ return FlateOk;
527+}
528+
529+static void
530+lzwrite(LZstate *lz, void *buf, int n)
531+{
532+ int nw;
533+
534+ if(n && lz->w){
535+ nw = (*lz->w)(lz->wr, buf, n);
536+ if(nw != n){
537+ lz->w = nil;
538+ lz->wbad = 1;
539+ }else
540+ lz->totw += n;
541+ }
542+}
543+
544+static void
545+lzflush(LZstate *lz)
546+{
547+ lzwrite(lz, lz->obuf, lz->out - lz->obuf);
548+ lz->out = lz->obuf;
549+}
550+
551+static void
552+lzput(LZstate *lz, ulong bits, int nbits)
553+{
554+ bits = (bits << lz->nbits) | lz->bits;
555+ for(nbits += lz->nbits; nbits >= 8; nbits -= 8){
556+ *lz->out++ = bits;
557+ if(lz->out == lz->eout)
558+ lzflush(lz);
559+ bits >>= 8;
560+ }
561+ lz->bits = bits;
562+ lz->nbits = nbits;
563+}
564+
565+static void
566+lzflushbits(LZstate *lz)
567+{
568+ if(lz->nbits)
569+ lzput(lz, 0, 8 - (lz->nbits & 7));
570+}
571+
572+/*
573+ * write out a block of n samples,
574+ * given lz encoding and counts for huffman tables
575+ */
576+static void
577+wrblock(LZstate *out, int litoff, ushort *soff, ushort *eoff, Huff *litlentab, Huff *offtab)
578+{
579+ ushort *off;
580+ int i, run, offset, lit, len, c;
581+
582+ if(out->debug > 2){
583+ for(off = soff; off < eoff; ){
584+ offset = *off++;
585+ run = offset & MaxLitRun;
586+ if(run){
587+ for(i = 0; i < run; i++){
588+ lit = out->hist[litoff & (HistBlock - 1)];
589+ litoff++;
590+ fprint(2, "\tlit %.2ux %c\n", lit, lit);
591+ }
592+ if(!(offset & LenFlag))
593+ continue;
594+ len = offset >> LenShift;
595+ offset = *off++;
596+ }else if(offset & LenFlag){
597+ len = offset >> LenShift;
598+ offset = *off++;
599+ }else{
600+ len = 0;
601+ offset >>= LenShift;
602+ }
603+ litoff += len + MinMatch;
604+ fprint(2, "\t<%d, %d>\n", offset + 1, len + MinMatch);
605+ }
606+ }
607+
608+ for(off = soff; off < eoff; ){
609+ offset = *off++;
610+ run = offset & MaxLitRun;
611+ if(run){
612+ for(i = 0; i < run; i++){
613+ lit = out->hist[litoff & (HistBlock - 1)];
614+ litoff++;
615+ lzput(out, litlentab[lit].encode, litlentab[lit].bits);
616+ }
617+ if(!(offset & LenFlag))
618+ continue;
619+ len = offset >> LenShift;
620+ offset = *off++;
621+ }else if(offset & LenFlag){
622+ len = offset >> LenShift;
623+ offset = *off++;
624+ }else{
625+ len = 0;
626+ offset >>= LenShift;
627+ }
628+ litoff += len + MinMatch;
629+ c = lencode[len];
630+ lzput(out, litlentab[c].encode, litlentab[c].bits);
631+ c -= LenStart;
632+ if(litlenextra[c])
633+ lzput(out, len - litlenbase[c], litlenextra[c]);
634+
635+ if(offset < MaxOffCode)
636+ c = offcode[offset];
637+ else
638+ c = bigoffcode[offset >> 7];
639+ lzput(out, offtab[c].encode, offtab[c].bits);
640+ if(offextra[c])
641+ lzput(out, offset - offbase[c], offextra[c]);
642+ }
643+}
644+
645+/*
646+ * look for the longest, closest string which matches
647+ * the next prefix. the clever part here is looking for
648+ * a string 1 longer than the previous best match.
649+ *
650+ * follows the recommendation of limiting number of chains
651+ * which are checked. this appears to be the best heuristic.
652+ */
653+static int
654+lzmatch(int now, int then, uchar *p, uchar *es, ushort *nexts, uchar *hist, int runlen, int check, int *m)
655+{
656+ uchar *s, *t;
657+ int ml, off, last;
658+
659+ ml = check;
660+ if(runlen >= 8)
661+ check >>= 2;
662+ *m = 0;
663+ if(p + runlen >= es)
664+ return runlen;
665+ last = 0;
666+ for(; check-- > 0; then = nexts[then & (MaxOff-1)]){
667+ off = (ushort)(now - then);
668+ if(off <= last || off > MaxOff)
669+ break;
670+ s = p + runlen;
671+ t = hist + (((p - hist) - off) & (HistBlock-1));
672+ t += runlen;
673+ for(; s >= p; s--){
674+ if(*s != *t)
675+ goto matchloop;
676+ t--;
677+ }
678+
679+ /*
680+ * we have a new best match.
681+ * extend it to it's maximum length
682+ */
683+ t += runlen + 2;
684+ s += runlen + 2;
685+ for(; s < es; s++){
686+ if(*s != *t)
687+ break;
688+ t++;
689+ }
690+ runlen = s - p;
691+ *m = off - 1;
692+ if(s == es || runlen > ml)
693+ break;
694+matchloop:;
695+ last = off;
696+ }
697+ return runlen;
698+}
699+
700+static int
701+lzcomp(LZstate *lz, LZblock *lzb, uchar *ep, ushort *parse, int finish)
702+{
703+ ulong cont, excost, *litlencount, *offcount;
704+ uchar *p, *q, *s, *es;
705+ ushort *nexts, *hash;
706+ int v, i, h, runlen, n, now, then, m, prevlen, prevoff, maxdefer;
707+
708+ litlencount = lzb->litlencount;
709+ offcount = lzb->offcount;
710+ nexts = lz->nexts;
711+ hash = lz->hash;
712+ now = lz->now;
713+
714+ p = &lz->hist[lz->pos];
715+ if(lz->prevlen != MinMatch - 1)
716+ p++;
717+
718+ /*
719+ * hash in the links for any hanging link positions,
720+ * and calculate the hash for the current position.
721+ */
722+ n = MinMatch;
723+ if(n > ep - p)
724+ n = ep - p;
725+ cont = 0;
726+ for(i = 0; i < n - 1; i++){
727+ m = now - ((MinMatch-1) - i);
728+ if(m < lz->dot)
729+ continue;
730+ s = lz->hist + (((p - lz->hist) - (now - m)) & (HistBlock-1));
731+
732+ cont = (s[0] << 16) | (s[1] << 8) | s[2];
733+ h = hashit(cont);
734+ prevoff = 0;
735+ for(then = hash[h]; ; then = nexts[then & (MaxOff-1)]){
736+ v = (ushort)(now - then);
737+ if(v <= prevoff || v >= (MinMatch-1) - i)
738+ break;
739+ prevoff = v;
740+ }
741+ if(then == (ushort)m)
742+ continue;
743+ nexts[m & (MaxOff-1)] = hash[h];
744+ hash[h] = m;
745+ }
746+ for(i = 0; i < n; i++)
747+ cont = (cont << 8) | p[i];
748+
749+ /*
750+ * now must point to the index in the nexts array
751+ * corresponding to p's position in the history
752+ */
753+ prevlen = lz->prevlen;
754+ prevoff = lz->prevoff;
755+ maxdefer = lz->maxcheck >> 2;
756+ excost = 0;
757+ v = lzb->lastv;
758+ for(;;){
759+ es = p + MaxMatch;
760+ if(es > ep){
761+ if(!finish || p >= ep)
762+ break;
763+ es = ep;
764+ }
765+
766+ h = hashit(cont);
767+ runlen = lzmatch(now, hash[h], p, es, nexts, lz->hist, prevlen, lz->maxcheck, &m);
768+
769+ /*
770+ * back out of small matches too far in the past
771+ */
772+ if(runlen == MinMatch && m >= MinMatchMaxOff){
773+ runlen = MinMatch - 1;
774+ m = 0;
775+ }
776+
777+ /*
778+ * record the encoding and increment counts for huffman trees
779+ * if we get a match, defer selecting it until we check for
780+ * a longer match at the next position.
781+ */
782+ if(prevlen >= runlen && prevlen != MinMatch - 1){
783+ /*
784+ * old match at least as good; use that one
785+ */
786+ n = prevlen - MinMatch;
787+ if(v || n){
788+ *parse++ = v | LenFlag | (n << LenShift);
789+ *parse++ = prevoff;
790+ }else
791+ *parse++ = prevoff << LenShift;
792+ v = 0;
793+
794+ n = lencode[n];
795+ litlencount[n]++;
796+ excost += litlenextra[n - LenStart];
797+
798+ if(prevoff < MaxOffCode)
799+ n = offcode[prevoff];
800+ else
801+ n = bigoffcode[prevoff >> 7];
802+ offcount[n]++;
803+ excost += offextra[n];
804+
805+ runlen = prevlen - 1;
806+ prevlen = MinMatch - 1;
807+ nmatches++;
808+ }else if(runlen == MinMatch - 1){
809+ /*
810+ * no match; just put out the literal
811+ */
812+ if(++v == MaxLitRun){
813+ *parse++ = v;
814+ v = 0;
815+ }
816+ litlencount[*p]++;
817+ nlits++;
818+ runlen = 1;
819+ }else{
820+ if(prevlen != MinMatch - 1){
821+ /*
822+ * longer match now. output previous literal,
823+ * update current match, and try again
824+ */
825+ if(++v == MaxLitRun){
826+ *parse++ = v;
827+ v = 0;
828+ }
829+ litlencount[p[-1]]++;
830+ nlits++;
831+ }
832+
833+ prevoff = m;
834+
835+ if(runlen < maxdefer){
836+ prevlen = runlen;
837+ runlen = 1;
838+ }else{
839+ n = runlen - MinMatch;
840+ if(v || n){
841+ *parse++ = v | LenFlag | (n << LenShift);
842+ *parse++ = prevoff;
843+ }else
844+ *parse++ = prevoff << LenShift;
845+ v = 0;
846+
847+ n = lencode[n];
848+ litlencount[n]++;
849+ excost += litlenextra[n - LenStart];
850+
851+ if(prevoff < MaxOffCode)
852+ n = offcode[prevoff];
853+ else
854+ n = bigoffcode[prevoff >> 7];
855+ offcount[n]++;
856+ excost += offextra[n];
857+
858+ prevlen = MinMatch - 1;
859+ nmatches++;
860+ }
861+ }
862+
863+ /*
864+ * update the hash for the newly matched data
865+ * this is constructed so the link for the old
866+ * match in this position must be at the end of a chain,
867+ * and will expire when this match is added, ie it will
868+ * never be examined by the match loop.
869+ * add to the hash chain only if we have the real hash data.
870+ */
871+ for(q = p + runlen; p != q; p++){
872+ if(p + MinMatch <= ep){
873+ h = hashit(cont);
874+ nexts[now & (MaxOff-1)] = hash[h];
875+ hash[h] = now;
876+ if(p + MinMatch < ep)
877+ cont = (cont << 8) | p[MinMatch];
878+ }
879+ now++;
880+ }
881+ }
882+
883+ /*
884+ * we can just store away the lazy state and
885+ * pick it up next time. the last block will have finish set
886+ * so we won't have any pending matches
887+ * however, we need to correct for how much we've encoded
888+ */
889+ if(prevlen != MinMatch - 1)
890+ p--;
891+
892+ lzb->excost += excost;
893+ lzb->eparse = parse;
894+ lzb->lastv = v;
895+
896+ lz->now = now;
897+ lz->prevlen = prevlen;
898+ lz->prevoff = prevoff;
899+
900+ return p - &lz->hist[lz->pos];
901+}
902+
903+/*
904+ * make up the dynamic code tables, and return the number of bits
905+ * needed to transmit them.
906+ */
907+static int
908+huffcodes(Dyncode *dc, Huff *littab, Huff *offtab)
909+{
910+ Huff *codetab;
911+ uchar *codes, *codeaux;
912+ ulong codecount[Nclen], excost;
913+ int i, n, m, v, c, nlit, noff, ncode, nclen;
914+
915+ codetab = dc->codetab;
916+ codes = dc->codes;
917+ codeaux = dc->codeaux;
918+
919+ /*
920+ * trim the sizes of the tables
921+ */
922+ for(nlit = Nlitlen; nlit > 257 && littab[nlit-1].bits == 0; nlit--)
923+ ;
924+ for(noff = Noff; noff > 1 && offtab[noff-1].bits == 0; noff--)
925+ ;
926+
927+ /*
928+ * make the code-length code
929+ */
930+ for(i = 0; i < nlit; i++)
931+ codes[i] = littab[i].bits;
932+ for(i = 0; i < noff; i++)
933+ codes[i + nlit] = offtab[i].bits;
934+
935+ /*
936+ * run-length compress the code-length code
937+ */
938+ excost = 0;
939+ c = 0;
940+ ncode = nlit+noff;
941+ for(i = 0; i < ncode; ){
942+ n = i + 1;
943+ v = codes[i];
944+ while(n < ncode && v == codes[n])
945+ n++;
946+ n -= i;
947+ i += n;
948+ if(v == 0){
949+ while(n >= 11){
950+ m = n;
951+ if(m > 138)
952+ m = 138;
953+ codes[c] = 18;
954+ codeaux[c++] = m - 11;
955+ n -= m;
956+ excost += 7;
957+ }
958+ if(n >= 3){
959+ codes[c] = 17;
960+ codeaux[c++] = n - 3;
961+ n = 0;
962+ excost += 3;
963+ }
964+ }
965+ while(n--){
966+ codes[c++] = v;
967+ while(n >= 3){
968+ m = n;
969+ if(m > 6)
970+ m = 6;
971+ codes[c] = 16;
972+ codeaux[c++] = m - 3;
973+ n -= m;
974+ excost += 3;
975+ }
976+ }
977+ }
978+
979+ memset(codecount, 0, sizeof codecount);
980+ for(i = 0; i < c; i++)
981+ codecount[codes[i]]++;
982+ if(!mkgzprecode(codetab, codecount, Nclen, 8))
983+ return -1;
984+
985+ for(nclen = Nclen; nclen > 4 && codetab[clenorder[nclen-1]].bits == 0; nclen--)
986+ ;
987+
988+ dc->nlit = nlit;
989+ dc->noff = noff;
990+ dc->nclen = nclen;
991+ dc->ncode = c;
992+
993+ return 5 + 5 + 4 + nclen * 3 + bitcost(codetab, codecount, Nclen) + excost;
994+}
995+
996+static void
997+wrdyncode(LZstate *out, Dyncode *dc)
998+{
999+ Huff *codetab;
1000+ uchar *codes, *codeaux;
1001+ int i, v, c;
1002+
1003+ /*
1004+ * write out header, then code length code lengths,
1005+ * and code lengths
1006+ */
1007+ lzput(out, dc->nlit-257, 5);
1008+ lzput(out, dc->noff-1, 5);
1009+ lzput(out, dc->nclen-4, 4);
1010+
1011+ codetab = dc->codetab;
1012+ for(i = 0; i < dc->nclen; i++)
1013+ lzput(out, codetab[clenorder[i]].bits, 3);
1014+
1015+ codes = dc->codes;
1016+ codeaux = dc->codeaux;
1017+ c = dc->ncode;
1018+ for(i = 0; i < c; i++){
1019+ v = codes[i];
1020+ lzput(out, codetab[v].encode, codetab[v].bits);
1021+ if(v >= 16){
1022+ if(v == 16)
1023+ lzput(out, codeaux[i], 2);
1024+ else if(v == 17)
1025+ lzput(out, codeaux[i], 3);
1026+ else /* v == 18 */
1027+ lzput(out, codeaux[i], 7);
1028+ }
1029+ }
1030+}
1031+
1032+static int
1033+bitcost(Huff *tab, ulong *count, int n)
1034+{
1035+ ulong tot;
1036+ int i;
1037+
1038+ tot = 0;
1039+ for(i = 0; i < n; i++)
1040+ tot += count[i] * tab[i].bits;
1041+ return tot;
1042+}
1043+
1044+static int
1045+mkgzprecode(Huff *tab, ulong *count, int n, int maxbits)
1046+{
1047+ ulong bitcount[MaxHuffBits];
1048+ int i, nbits;
1049+
1050+ nbits = mkprecode(tab, count, n, maxbits, bitcount);
1051+ for(i = 0; i < n; i++){
1052+ if(tab[i].bits == -1)
1053+ tab[i].bits = 0;
1054+ else if(tab[i].bits == 0){
1055+ if(nbits != 0 || bitcount[0] != 1)
1056+ return 0;
1057+ bitcount[1] = 1;
1058+ bitcount[0] = 0;
1059+ nbits = 1;
1060+ tab[i].bits = 1;
1061+ }
1062+ }
1063+ if(bitcount[0] != 0)
1064+ return 0;
1065+ return hufftabinit(tab, n, bitcount, nbits);
1066+}
1067+
1068+static int
1069+hufftabinit(Huff *tab, int n, ulong *bitcount, int nbits)
1070+{
1071+ ulong code, nc[MaxHuffBits];
1072+ int i, bits;
1073+
1074+ code = 0;
1075+ for(bits = 1; bits <= nbits; bits++){
1076+ code = (code + bitcount[bits-1]) << 1;
1077+ nc[bits] = code;
1078+ }
1079+
1080+ for(i = 0; i < n; i++){
1081+ bits = tab[i].bits;
1082+ if(bits){
1083+ code = nc[bits]++ << (16 - bits);
1084+ if(code & ~0xffff)
1085+ return 0;
1086+ tab[i].encode = revtab[code >> 8] | (revtab[code & 0xff] << 8);
1087+ }
1088+ }
1089+ return 1;
1090+}
1091+
1092+
1093+/*
1094+ * this should be in a library
1095+ */
1096+struct Chain
1097+{
1098+ ulong count; /* occurances of everything in the chain */
1099+ ushort leaf; /* leaves to the left of chain, or leaf value */
1100+ char col; /* ref count for collecting unused chains */
1101+ char gen; /* need to generate chains for next lower level */
1102+ Chain *up; /* Chain up in the lists */
1103+};
1104+
1105+struct Chains
1106+{
1107+ Chain *lists[(MaxHuffBits - 1) * 2];
1108+ ulong leafcount[MaxLeaf]; /* sorted list of leaf counts */
1109+ ushort leafmap[MaxLeaf]; /* map to actual leaf number */
1110+ int nleaf; /* number of leaves */
1111+ Chain chains[ChainMem];
1112+ Chain *echains;
1113+ Chain *free;
1114+ char col;
1115+ int nlists;
1116+};
1117+
1118+/*
1119+ * fast, low space overhead algorithm for max depth huffman type codes
1120+ *
1121+ * J. Katajainen, A. Moffat and A. Turpin, "A fast and space-economical
1122+ * algorithm for length-limited coding," Proc. Intl. Symp. on Algorithms
1123+ * and Computation, Cairns, Australia, Dec. 1995, Lecture Notes in Computer
1124+ * Science, Vol 1004, J. Staples, P. Eades, N. Katoh, and A. Moffat, eds.,
1125+ * pp 12-21, Springer Verlag, New York, 1995.
1126+ */
1127+static int
1128+mkprecode(Huff *tab, ulong *count, int n, int maxbits, ulong *bitcount)
1129+{
1130+ Chains cs;
1131+ Chain *c;
1132+ int i, m, em, bits;
1133+
1134+ /*
1135+ * set up the sorted list of leaves
1136+ */
1137+ m = 0;
1138+ for(i = 0; i < n; i++){
1139+ tab[i].bits = -1;
1140+ tab[i].encode = 0;
1141+ if(count[i] != 0){
1142+ cs.leafcount[m] = count[i];
1143+ cs.leafmap[m] = i;
1144+ m++;
1145+ }
1146+ }
1147+ if(m < 2){
1148+ if(m != 0){
1149+ tab[cs.leafmap[0]].bits = 0;
1150+ bitcount[0] = 1;
1151+ }else
1152+ bitcount[0] = 0;
1153+ return 0;
1154+ }
1155+ cs.nleaf = m;
1156+ leafsort(cs.leafcount, cs.leafmap, 0, m);
1157+
1158+ for(i = 0; i < m; i++)
1159+ cs.leafcount[i] = count[cs.leafmap[i]];
1160+
1161+ /*
1162+ * set up free list
1163+ */
1164+ cs.free = &cs.chains[2];
1165+ cs.echains = &cs.chains[ChainMem];
1166+ cs.col = 1;
1167+
1168+ /*
1169+ * initialize chains for each list
1170+ */
1171+ c = &cs.chains[0];
1172+ c->count = cs.leafcount[0];
1173+ c->leaf = 1;
1174+ c->col = cs.col;
1175+ c->up = nil;
1176+ c->gen = 0;
1177+ cs.chains[1] = cs.chains[0];
1178+ cs.chains[1].leaf = 2;
1179+ cs.chains[1].count = cs.leafcount[1];
1180+ for(i = 0; i < maxbits-1; i++){
1181+ cs.lists[i * 2] = &cs.chains[0];
1182+ cs.lists[i * 2 + 1] = &cs.chains[1];
1183+ }
1184+
1185+ cs.nlists = 2 * (maxbits - 1);
1186+ m = 2 * m - 2;
1187+ for(i = 2; i < m; i++)
1188+ nextchain(&cs, cs.nlists - 2);
1189+
1190+ bits = 0;
1191+ bitcount[0] = cs.nleaf;
1192+ for(c = cs.lists[cs.nlists - 1]; c != nil; c = c->up){
1193+ m = c->leaf;
1194+ bitcount[bits++] -= m;
1195+ bitcount[bits] = m;
1196+ }
1197+ m = 0;
1198+ for(i = bits; i >= 0; i--)
1199+ for(em = m + bitcount[i]; m < em; m++)
1200+ tab[cs.leafmap[m]].bits = i;
1201+
1202+ return bits;
1203+}
1204+
1205+/*
1206+ * calculate the next chain on the list
1207+ * we can always toss out the old chain
1208+ */
1209+static void
1210+nextchain(Chains *cs, int list)
1211+{
1212+ Chain *c, *oc;
1213+ int i, nleaf, sumc;
1214+
1215+ oc = cs->lists[list + 1];
1216+ cs->lists[list] = oc;
1217+ if(oc == nil)
1218+ return;
1219+
1220+ /*
1221+ * make sure we have all chains needed to make sumc
1222+ * note it is possible to generate only one of these,
1223+ * use twice that value for sumc, and then generate
1224+ * the second if that preliminary sumc would be chosen.
1225+ * however, this appears to be slower on current tests
1226+ */
1227+ if(oc->gen){
1228+ nextchain(cs, list - 2);
1229+ nextchain(cs, list - 2);
1230+ oc->gen = 0;
1231+ }
1232+
1233+ /*
1234+ * pick up the chain we're going to add;
1235+ * collect unused chains no free ones are left
1236+ */
1237+ for(c = cs->free; ; c++){
1238+ if(c >= cs->echains){
1239+ cs->col++;
1240+ for(i = 0; i < cs->nlists; i++)
1241+ for(c = cs->lists[i]; c != nil; c = c->up)
1242+ c->col = cs->col;
1243+ c = cs->chains;
1244+ }
1245+ if(c->col != cs->col)
1246+ break;
1247+ }
1248+
1249+ /*
1250+ * pick the cheapest of
1251+ * 1) the next package from the previous list
1252+ * 2) the next leaf
1253+ */
1254+ nleaf = oc->leaf;
1255+ sumc = 0;
1256+ if(list > 0 && cs->lists[list-1] != nil)
1257+ sumc = cs->lists[list-2]->count + cs->lists[list-1]->count;
1258+ if(sumc != 0 && (nleaf >= cs->nleaf || cs->leafcount[nleaf] > sumc)){
1259+ c->count = sumc;
1260+ c->leaf = oc->leaf;
1261+ c->up = cs->lists[list-1];
1262+ c->gen = 1;
1263+ }else if(nleaf >= cs->nleaf){
1264+ cs->lists[list + 1] = nil;
1265+ return;
1266+ }else{
1267+ c->leaf = nleaf + 1;
1268+ c->count = cs->leafcount[nleaf];
1269+ c->up = oc->up;
1270+ c->gen = 0;
1271+ }
1272+ cs->free = c + 1;
1273+
1274+ cs->lists[list + 1] = c;
1275+ c->col = cs->col;
1276+}
1277+
1278+static int
1279+pivot(ulong *c, int a, int n)
1280+{
1281+ int j, pi, pj, pk;
1282+
1283+ j = n/6;
1284+ pi = a + j; /* 1/6 */
1285+ j += j;
1286+ pj = pi + j; /* 1/2 */
1287+ pk = pj + j; /* 5/6 */
1288+ if(c[pi] < c[pj]){
1289+ if(c[pi] < c[pk]){
1290+ if(c[pj] < c[pk])
1291+ return pj;
1292+ return pk;
1293+ }
1294+ return pi;
1295+ }
1296+ if(c[pj] < c[pk]){
1297+ if(c[pi] < c[pk])
1298+ return pi;
1299+ return pk;
1300+ }
1301+ return pj;
1302+}
1303+
1304+static void
1305+leafsort(ulong *leafcount, ushort *leafmap, int a, int n)
1306+{
1307+ ulong t;
1308+ int j, pi, pj, pn;
1309+
1310+ while(n > 1){
1311+ if(n > 10){
1312+ pi = pivot(leafcount, a, n);
1313+ }else
1314+ pi = a + (n>>1);
1315+
1316+ t = leafcount[pi];
1317+ leafcount[pi] = leafcount[a];
1318+ leafcount[a] = t;
1319+ t = leafmap[pi];
1320+ leafmap[pi] = leafmap[a];
1321+ leafmap[a] = t;
1322+ pi = a;
1323+ pn = a + n;
1324+ pj = pn;
1325+ for(;;){
1326+ do
1327+ pi++;
1328+ while(pi < pn && (leafcount[pi] < leafcount[a] || leafcount[pi] == leafcount[a] && leafmap[pi] > leafmap[a]));
1329+ do
1330+ pj--;
1331+ while(pj > a && (leafcount[pj] > leafcount[a] || leafcount[pj] == leafcount[a] && leafmap[pj] < leafmap[a]));
1332+ if(pj < pi)
1333+ break;
1334+ t = leafcount[pi];
1335+ leafcount[pi] = leafcount[pj];
1336+ leafcount[pj] = t;
1337+ t = leafmap[pi];
1338+ leafmap[pi] = leafmap[pj];
1339+ leafmap[pj] = t;
1340+ }
1341+ t = leafcount[a];
1342+ leafcount[a] = leafcount[pj];
1343+ leafcount[pj] = t;
1344+ t = leafmap[a];
1345+ leafmap[a] = leafmap[pj];
1346+ leafmap[pj] = t;
1347+ j = pj - a;
1348+
1349+ n = n-j-1;
1350+ if(j >= n){
1351+ leafsort(leafcount, leafmap, a, j);
1352+ a += j+1;
1353+ }else{
1354+ leafsort(leafcount, leafmap, a + (j+1), n);
1355+ n = j;
1356+ }
1357+ }
1358+}
os/boot/libflate/deflateblock.c+55−0
@@ -0,0 +1,55 @@
1+#include "lib9.h"
2+#include <flate.h>
3+
4+typedef struct Block Block;
5+
6+struct Block
7+{
8+ uchar *pos;
9+ uchar *limit;
10+};
11+
12+static int
13+blread(void *vb, void *buf, int n)
14+{
15+ Block *b;
16+
17+ b = vb;
18+ if(n > b->limit - b->pos)
19+ n = b->limit - b->pos;
20+ memmove(buf, b->pos, n);
21+ b->pos += n;
22+ return n;
23+}
24+
25+static int
26+blwrite(void *vb, void *buf, int n)
27+{
28+ Block *b;
29+
30+ b = vb;
31+
32+ if(n > b->limit - b->pos)
33+ n = b->limit - b->pos;
34+ memmove(b->pos, buf, n);
35+ b->pos += n;
36+ return n;
37+}
38+
39+int
40+deflateblock(uchar *dst, int dsize, uchar *src, int ssize, int level, int debug)
41+{
42+ Block bd, bs;
43+ int ok;
44+
45+ bs.pos = src;
46+ bs.limit = src + ssize;
47+
48+ bd.pos = dst;
49+ bd.limit = dst + dsize;
50+
51+ ok = deflate(&bd, blwrite, &bs, blread, level, debug);
52+ if(ok != FlateOk)
53+ return ok;
54+ return bd.pos - dst;
55+}
os/boot/libflate/deflatezlib.c+59−0
@@ -0,0 +1,59 @@
1+#include "lib9.h"
2+#include <flate.h>
3+#include "zlib.h"
4+
5+typedef struct ZRead ZRead;
6+
7+struct ZRead
8+{
9+ ulong adler;
10+ void *rr;
11+ int (*r)(void*, void*, int);
12+};
13+
14+static int
15+zlread(void *vzr, void *buf, int n)
16+{
17+ ZRead *zr;
18+
19+ zr = vzr;
20+ n = (*zr->r)(zr->rr, buf, n);
21+ if(n <= 0)
22+ return n;
23+ zr->adler = adler32(zr->adler, buf, n);
24+ return n;
25+}
26+
27+int
28+deflatezlib(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
29+{
30+ ZRead zr;
31+ uchar buf[4];
32+ int ok;
33+
34+ buf[0] = ZlibDeflate | ZlibWin32k;
35+
36+ /* bogus zlib encoding of compression level */
37+ buf[1] = ((level > 2) + (level > 5) + (level > 8)) << 6;
38+
39+ /* header check field */
40+ buf[1] |= 31 - ((buf[0] << 8) | buf[1]) % 31;
41+ if((*w)(wr, buf, 2) != 2)
42+ return FlateOutputFail;
43+
44+ zr.rr = rr;
45+ zr.r = r;
46+ zr.adler = 1;
47+ ok = deflate(wr, w, &zr, zlread, level, debug);
48+ if(ok != FlateOk)
49+ return ok;
50+
51+ buf[0] = zr.adler >> 24;
52+ buf[1] = zr.adler >> 16;
53+ buf[2] = zr.adler >> 8;
54+ buf[3] = zr.adler;
55+ if((*w)(wr, buf, 4) != 4)
56+ return FlateOutputFail;
57+
58+ return FlateOk;
59+}
os/boot/libflate/deflatezlibblock.c+33−0
@@ -0,0 +1,33 @@
1+#include "lib9.h"
2+#include <flate.h>
3+#include "zlib.h"
4+
5+int
6+deflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize, int level, int debug)
7+{
8+ ulong adler;
9+ int n;
10+
11+ if(dsize < 6)
12+ return FlateOutputFail;
13+
14+ n = deflateblock(dst + 2, dsize - 6, src, ssize, level, debug);
15+ if(n < 0)
16+ return n;
17+
18+ dst[0] = ZlibDeflate | ZlibWin32k;
19+
20+ /* bogus zlib encoding of compression level */
21+ dst[1] = ((level > 2) + (level > 5) + (level > 8)) << 6;
22+
23+ /* header check field */
24+ dst[1] |= 31 - ((dst[0] << 8) | dst[1]) % 31;
25+
26+ adler = adler32(1, src, ssize);
27+ dst[n + 2] = adler >> 24;
28+ dst[n + 3] = adler >> 16;
29+ dst[n + 4] = adler >> 8;
30+ dst[n + 5] = adler;
31+
32+ return n + 6;
33+}
os/boot/libflate/flateerr.c+22−0
@@ -0,0 +1,22 @@
1+#include "lib9.h"
2+#include <flate.h>
3+
4+char *
5+flateerr(int err)
6+{
7+ switch(err){
8+ case FlateOk:
9+ return "no error";
10+ case FlateNoMem:
11+ return "out of memory";
12+ case FlateInputFail:
13+ return "input error";
14+ case FlateOutputFail:
15+ return "output error";
16+ case FlateCorrupted:
17+ return "corrupted data";
18+ case FlateInternal:
19+ return "internal error";
20+ }
21+ return "unknown error";
22+}
os/boot/libflate/inflate.c+692−0
@@ -0,0 +1,692 @@
1+#include "lib9.h"
2+#include <flate.h>
3+
4+enum {
5+ HistorySize= 32*1024,
6+ BufSize= 4*1024,
7+ MaxHuffBits= 17, /* maximum bits in a encoded code */
8+ Nlitlen= 288, /* number of litlen codes */
9+ Noff= 32, /* number of offset codes */
10+ Nclen= 19, /* number of codelen codes */
11+ LenShift= 10, /* code = len<<LenShift|code */
12+ LitlenBits= 7, /* number of bits in litlen decode table */
13+ OffBits= 6, /* number of bits in offset decode table */
14+ ClenBits= 6, /* number of bits in code len decode table */
15+ MaxFlatBits= LitlenBits,
16+ MaxLeaf= Nlitlen
17+};
18+
19+typedef struct Input Input;
20+typedef struct History History;
21+typedef struct Huff Huff;
22+
23+struct Input
24+{
25+ int error; /* first error encountered, or FlateOk */
26+ void *wr;
27+ int (*w)(void*, void*, int);
28+ void *getr;
29+ int (*get)(void*);
30+ ulong sreg;
31+ int nbits;
32+};
33+
34+struct History
35+{
36+ uchar his[HistorySize];
37+ uchar *cp; /* current pointer in history */
38+ int full; /* his has been filled up at least once */
39+};
40+
41+struct Huff
42+{
43+ int maxbits; /* max bits for any code */
44+ int minbits; /* min bits to get before looking in flat */
45+ int flatmask; /* bits used in "flat" fast decoding table */
46+ ulong flat[1<<MaxFlatBits];
47+ ulong maxcode[MaxHuffBits];
48+ ulong last[MaxHuffBits];
49+ ulong decode[MaxLeaf];
50+};
51+
52+/* litlen code words 257-285 extra bits */
53+static int litlenextra[Nlitlen-257] =
54+{
55+/* 257 */ 0, 0, 0,
56+/* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
57+/* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
58+/* 280 */ 4, 5, 5, 5, 5, 0, 0, 0
59+};
60+
61+static int litlenbase[Nlitlen-257];
62+
63+/* offset code word extra bits */
64+static int offextra[Noff] =
65+{
66+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
67+ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
68+ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
69+ 0, 0,
70+};
71+static int offbase[Noff];
72+
73+/* order code lengths */
74+static int clenorder[Nclen] =
75+{
76+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
77+};
78+
79+/* for static huffman tables */
80+static Huff litlentab;
81+static Huff offtab;
82+static uchar revtab[256];
83+
84+static int uncblock(Input *in, History*);
85+static int fixedblock(Input *in, History*);
86+static int dynamicblock(Input *in, History*);
87+static int sregfill(Input *in, int n);
88+static int sregunget(Input *in);
89+static int decode(Input*, History*, Huff*, Huff*);
90+static int hufftab(Huff*, char*, int, int);
91+static int hdecsym(Input *in, Huff *h, int b);
92+
93+int
94+inflateinit(void)
95+{
96+ char *len;
97+ int i, j, base;
98+
99+ /* byte reverse table */
100+ for(i=0; i<256; i++)
101+ for(j=0; j<8; j++)
102+ if(i & (1<<j))
103+ revtab[i] |= 0x80 >> j;
104+
105+ for(i=257,base=3; i<Nlitlen; i++) {
106+ litlenbase[i-257] = base;
107+ base += 1<<litlenextra[i-257];
108+ }
109+ /* strange table entry in spec... */
110+ litlenbase[285-257]--;
111+
112+ for(i=0,base=1; i<Noff; i++) {
113+ offbase[i] = base;
114+ base += 1<<offextra[i];
115+ }
116+
117+ len = malloc(MaxLeaf);
118+ if(len == nil)
119+ return FlateNoMem;
120+
121+ /* static Litlen bit lengths */
122+ for(i=0; i<144; i++)
123+ len[i] = 8;
124+ for(i=144; i<256; i++)
125+ len[i] = 9;
126+ for(i=256; i<280; i++)
127+ len[i] = 7;
128+ for(i=280; i<Nlitlen; i++)
129+ len[i] = 8;
130+
131+ if(!hufftab(&litlentab, len, Nlitlen, MaxFlatBits))
132+ return FlateInternal;
133+
134+ /* static Offset bit lengths */
135+ for(i=0; i<Noff; i++)
136+ len[i] = 5;
137+
138+ if(!hufftab(&offtab, len, Noff, MaxFlatBits))
139+ return FlateInternal;
140+ free(len);
141+
142+ return FlateOk;
143+}
144+
145+int
146+inflate(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
147+{
148+ History *his;
149+ Input in;
150+ int final, type;
151+
152+ his = malloc(sizeof(History));
153+ if(his == nil)
154+ return FlateNoMem;
155+ his->cp = his->his;
156+ his->full = 0;
157+ in.getr = getr;
158+ in.get = get;
159+ in.wr = wr;
160+ in.w = w;
161+ in.nbits = 0;
162+ in.sreg = 0;
163+ in.error = FlateOk;
164+
165+ do {
166+ if(!sregfill(&in, 3))
167+ goto bad;
168+ final = in.sreg & 0x1;
169+ type = (in.sreg>>1) & 0x3;
170+ in.sreg >>= 3;
171+ in.nbits -= 3;
172+ switch(type) {
173+ default:
174+ in.error = FlateCorrupted;
175+ goto bad;
176+ case 0:
177+ /* uncompressed */
178+ if(!uncblock(&in, his))
179+ goto bad;
180+ break;
181+ case 1:
182+ /* fixed huffman */
183+ if(!fixedblock(&in, his))
184+ goto bad;
185+ break;
186+ case 2:
187+ /* dynamic huffman */
188+ if(!dynamicblock(&in, his))
189+ goto bad;
190+ break;
191+ }
192+ } while(!final);
193+
194+ if(his->cp != his->his && (*w)(wr, his->his, his->cp - his->his) != his->cp - his->his) {
195+ in.error = FlateOutputFail;
196+ goto bad;
197+ }
198+
199+ if(!sregunget(&in))
200+ goto bad;
201+
202+ free(his);
203+ if(in.error != FlateOk)
204+ return FlateInternal;
205+ return FlateOk;
206+
207+bad:
208+ free(his);
209+ if(in.error == FlateOk)
210+ return FlateInternal;
211+ return in.error;
212+}
213+
214+static int
215+uncblock(Input *in, History *his)
216+{
217+ int len, nlen, c;
218+ uchar *hs, *hp, *he;
219+
220+ if(!sregunget(in))
221+ return 0;
222+ len = (*in->get)(in->getr);
223+ len |= (*in->get)(in->getr)<<8;
224+ nlen = (*in->get)(in->getr);
225+ nlen |= (*in->get)(in->getr)<<8;
226+ if(len != (~nlen&0xffff)) {
227+ in->error = FlateCorrupted;
228+ return 0;
229+ }
230+
231+ hp = his->cp;
232+ hs = his->his;
233+ he = hs + HistorySize;
234+
235+ while(len > 0) {
236+ c = (*in->get)(in->getr);
237+ if(c < 0)
238+ return 0;
239+ *hp++ = c;
240+ if(hp == he) {
241+ his->full = 1;
242+ if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
243+ in->error = FlateOutputFail;
244+ return 0;
245+ }
246+ hp = hs;
247+ }
248+ len--;
249+ }
250+
251+ his->cp = hp;
252+
253+ return 1;
254+}
255+
256+static int
257+fixedblock(Input *in, History *his)
258+{
259+ return decode(in, his, &litlentab, &offtab);
260+}
261+
262+static int
263+dynamicblock(Input *in, History *his)
264+{
265+ Huff *lentab, *offtab;
266+ char *len;
267+ int i, j, n, c, nlit, ndist, nclen, res, nb;
268+
269+ if(!sregfill(in, 14))
270+ return 0;
271+ nlit = (in->sreg&0x1f) + 257;
272+ ndist = ((in->sreg>>5) & 0x1f) + 1;
273+ nclen = ((in->sreg>>10) & 0xf) + 4;
274+ in->sreg >>= 14;
275+ in->nbits -= 14;
276+
277+ if(nlit > Nlitlen || ndist > Noff || nlit < 257) {
278+ in->error = FlateCorrupted;
279+ return 0;
280+ }
281+
282+ /* huff table header */
283+ len = malloc(Nlitlen+Noff);
284+ lentab = malloc(sizeof(Huff));
285+ offtab = malloc(sizeof(Huff));
286+ if(len == nil || lentab == nil || offtab == nil){
287+ in->error = FlateNoMem;
288+ goto bad;
289+ }
290+ for(i=0; i < Nclen; i++)
291+ len[i] = 0;
292+ for(i=0; i<nclen; i++) {
293+ if(!sregfill(in, 3))
294+ goto bad;
295+ len[clenorder[i]] = in->sreg & 0x7;
296+ in->sreg >>= 3;
297+ in->nbits -= 3;
298+ }
299+
300+ if(!hufftab(lentab, len, Nclen, ClenBits)){
301+ in->error = FlateCorrupted;
302+ goto bad;
303+ }
304+
305+ n = nlit+ndist;
306+ for(i=0; i<n;) {
307+ nb = lentab->minbits;
308+ for(;;){
309+ if(in->nbits<nb && !sregfill(in, nb))
310+ goto bad;
311+ c = lentab->flat[in->sreg & lentab->flatmask];
312+ nb = c & 0xff;
313+ if(nb > in->nbits){
314+ if(nb != 0xff)
315+ continue;
316+ c = hdecsym(in, lentab, c);
317+ if(c < 0)
318+ goto bad;
319+ }else{
320+ c >>= 8;
321+ in->sreg >>= nb;
322+ in->nbits -= nb;
323+ }
324+ break;
325+ }
326+
327+ if(c < 16) {
328+ j = 1;
329+ } else if(c == 16) {
330+ if(in->nbits<2 && !sregfill(in, 2))
331+ goto bad;
332+ j = (in->sreg&0x3)+3;
333+ in->sreg >>= 2;
334+ in->nbits -= 2;
335+ if(i == 0) {
336+ in->error = FlateCorrupted;
337+ goto bad;
338+ }
339+ c = len[i-1];
340+ } else if(c == 17) {
341+ if(in->nbits<3 && !sregfill(in, 3))
342+ goto bad;
343+ j = (in->sreg&0x7)+3;
344+ in->sreg >>= 3;
345+ in->nbits -= 3;
346+ c = 0;
347+ } else if(c == 18) {
348+ if(in->nbits<7 && !sregfill(in, 7))
349+ goto bad;
350+ j = (in->sreg&0x7f)+11;
351+ in->sreg >>= 7;
352+ in->nbits -= 7;
353+ c = 0;
354+ } else {
355+ in->error = FlateCorrupted;
356+ goto bad;
357+ }
358+
359+ if(i+j > n) {
360+ in->error = FlateCorrupted;
361+ goto bad;
362+ }
363+
364+ while(j) {
365+ len[i] = c;
366+ i++;
367+ j--;
368+ }
369+ }
370+
371+ if(!hufftab(lentab, len, nlit, LitlenBits)
372+ || !hufftab(offtab, &len[nlit], ndist, OffBits)){
373+ in->error = FlateCorrupted;
374+ goto bad;
375+ }
376+
377+ res = decode(in, his, lentab, offtab);
378+
379+ free(len);
380+ free(lentab);
381+ free(offtab);
382+
383+ return res;
384+
385+bad:
386+ free(len);
387+ free(lentab);
388+ free(offtab);
389+ return 0;
390+}
391+
392+static int
393+decode(Input *in, History *his, Huff *litlentab, Huff *offtab)
394+{
395+ int len, off;
396+ uchar *hs, *hp, *hq, *he;
397+ int c;
398+ int nb;
399+
400+ hs = his->his;
401+ he = hs + HistorySize;
402+ hp = his->cp;
403+
404+ for(;;) {
405+ nb = litlentab->minbits;
406+ for(;;){
407+ if(in->nbits<nb && !sregfill(in, nb))
408+ return 0;
409+ c = litlentab->flat[in->sreg & litlentab->flatmask];
410+ nb = c & 0xff;
411+ if(nb > in->nbits){
412+ if(nb != 0xff)
413+ continue;
414+ c = hdecsym(in, litlentab, c);
415+ if(c < 0)
416+ return 0;
417+ }else{
418+ c >>= 8;
419+ in->sreg >>= nb;
420+ in->nbits -= nb;
421+ }
422+ break;
423+ }
424+
425+ if(c < 256) {
426+ /* literal */
427+ *hp++ = c;
428+ if(hp == he) {
429+ his->full = 1;
430+ if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
431+ in->error = FlateOutputFail;
432+ return 0;
433+ }
434+ hp = hs;
435+ }
436+ continue;
437+ }
438+
439+ if(c == 256)
440+ break;
441+
442+ if(c > 285) {
443+ in->error = FlateCorrupted;
444+ return 0;
445+ }
446+
447+ c -= 257;
448+ nb = litlenextra[c];
449+ if(in->nbits < nb && !sregfill(in, nb))
450+ return 0;
451+ len = litlenbase[c] + (in->sreg & ((1<<nb)-1));
452+ in->sreg >>= nb;
453+ in->nbits -= nb;
454+
455+ /* get offset */
456+ nb = offtab->minbits;
457+ for(;;){
458+ if(in->nbits<nb && !sregfill(in, nb))
459+ return 0;
460+ c = offtab->flat[in->sreg & offtab->flatmask];
461+ nb = c & 0xff;
462+ if(nb > in->nbits){
463+ if(nb != 0xff)
464+ continue;
465+ c = hdecsym(in, offtab, c);
466+ if(c < 0)
467+ return 0;
468+ }else{
469+ c >>= 8;
470+ in->sreg >>= nb;
471+ in->nbits -= nb;
472+ }
473+ break;
474+ }
475+
476+ if(c > 29) {
477+ in->error = FlateCorrupted;
478+ return 0;
479+ }
480+
481+ nb = offextra[c];
482+ if(in->nbits < nb && !sregfill(in, nb))
483+ return 0;
484+
485+ off = offbase[c] + (in->sreg & ((1<<nb)-1));
486+ in->sreg >>= nb;
487+ in->nbits -= nb;
488+
489+ hq = hp - off;
490+ if(hq < hs) {
491+ if(!his->full) {
492+ in->error = FlateCorrupted;
493+ return 0;
494+ }
495+ hq += HistorySize;
496+ }
497+
498+ /* slow but correct */
499+ while(len) {
500+ *hp = *hq;
501+ hq++;
502+ hp++;
503+ if(hq >= he)
504+ hq = hs;
505+ if(hp == he) {
506+ his->full = 1;
507+ if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
508+ in->error = FlateOutputFail;
509+ return 0;
510+ }
511+ hp = hs;
512+ }
513+ len--;
514+ }
515+
516+ }
517+
518+ his->cp = hp;
519+
520+ return 1;
521+}
522+
523+static int
524+revcode(int c, int b)
525+{
526+ /* shift encode up so it starts on bit 15 then reverse */
527+ c <<= (16-b);
528+ c = revtab[c>>8] | (revtab[c&0xff]<<8);
529+ return c;
530+}
531+
532+/*
533+ * construct the huffman decoding arrays and a fast lookup table.
534+ * the fast lookup is a table indexed by the next flatbits bits,
535+ * which returns the symbol matched and the number of bits consumed,
536+ * or the minimum number of bits needed and 0xff if more than flatbits
537+ * bits are needed.
538+ *
539+ * flatbits can be longer than the smallest huffman code,
540+ * because shorter codes are assigned smaller lexical prefixes.
541+ * this means assuming zeros for the next few bits will give a
542+ * conservative answer, in the sense that it will either give the
543+ * correct answer, or return the minimum number of bits which
544+ * are needed for an answer.
545+ */
546+static int
547+hufftab(Huff *h, char *hb, int maxleaf, int flatbits)
548+{
549+ ulong bitcount[MaxHuffBits];
550+ ulong c, fc, ec, mincode, code, nc[MaxHuffBits];
551+ int i, b, minbits, maxbits;
552+
553+ for(i = 0; i < MaxHuffBits; i++)
554+ bitcount[i] = 0;
555+ maxbits = -1;
556+ minbits = MaxHuffBits + 1;
557+ for(i=0; i < maxleaf; i++){
558+ b = hb[i];
559+ if(b){
560+ bitcount[b]++;
561+ if(b < minbits)
562+ minbits = b;
563+ if(b > maxbits)
564+ maxbits = b;
565+ }
566+ }
567+
568+ h->maxbits = maxbits;
569+ if(maxbits <= 0){
570+ h->maxbits = 0;
571+ h->minbits = 0;
572+ h->flatmask = 0;
573+ return 1;
574+ }
575+ code = 0;
576+ c = 0;
577+ for(b = 0; b <= maxbits; b++){
578+ h->last[b] = c;
579+ c += bitcount[b];
580+ mincode = code << 1;
581+ nc[b] = mincode;
582+ code = mincode + bitcount[b];
583+ if(code > (1 << b))
584+ return 0;
585+ h->maxcode[b] = code - 1;
586+ h->last[b] += code - 1;
587+ }
588+
589+ if(flatbits > maxbits)
590+ flatbits = maxbits;
591+ h->flatmask = (1 << flatbits) - 1;
592+ if(minbits > flatbits)
593+ minbits = flatbits;
594+ h->minbits = minbits;
595+
596+ b = 1 << flatbits;
597+ for(i = 0; i < b; i++)
598+ h->flat[i] = ~0;
599+
600+ /*
601+ * initialize the flat table to include the minimum possible
602+ * bit length for each code prefix
603+ */
604+ for(b = maxbits; b > flatbits; b--){
605+ code = h->maxcode[b];
606+ if(code == -1)
607+ break;
608+ mincode = code + 1 - bitcount[b];
609+ mincode >>= b - flatbits;
610+ code >>= b - flatbits;
611+ for(; mincode <= code; mincode++)
612+ h->flat[revcode(mincode, flatbits)] = (b << 8) | 0xff;
613+ }
614+
615+ for(i = 0; i < maxleaf; i++){
616+ b = hb[i];
617+ if(b <= 0)
618+ continue;
619+ c = nc[b]++;
620+ if(b <= flatbits){
621+ code = (i << 8) | b;
622+ ec = (c + 1) << (flatbits - b);
623+ if(ec > (1<<flatbits))
624+ return 0; /* this is actually an internal error */
625+ for(fc = c << (flatbits - b); fc < ec; fc++)
626+ h->flat[revcode(fc, flatbits)] = code;
627+ }
628+ if(b > minbits){
629+ c = h->last[b] - c;
630+ if(c >= maxleaf)
631+ return 0;
632+ h->decode[c] = i;
633+ }
634+ }
635+ return 1;
636+}
637+
638+static int
639+hdecsym(Input *in, Huff *h, int nb)
640+{
641+ long c;
642+
643+ if((nb & 0xff) == 0xff)
644+ nb = nb >> 8;
645+ else
646+ nb = nb & 0xff;
647+ for(; nb <= h->maxbits; nb++){
648+ if(in->nbits<nb && !sregfill(in, nb))
649+ return -1;
650+ c = revtab[in->sreg&0xff]<<8;
651+ c |= revtab[(in->sreg>>8)&0xff];
652+ c >>= (16-nb);
653+ if(c <= h->maxcode[nb]){
654+ in->sreg >>= nb;
655+ in->nbits -= nb;
656+ return h->decode[h->last[nb] - c];
657+ }
658+ }
659+ in->error = FlateCorrupted;
660+ return -1;
661+}
662+
663+static int
664+sregfill(Input *in, int n)
665+{
666+ int c;
667+
668+ while(n > in->nbits) {
669+ c = (*in->get)(in->getr);
670+ if(c < 0){
671+ in->error = FlateInputFail;
672+ return 0;
673+ }
674+ in->sreg |= c<<in->nbits;
675+ in->nbits += 8;
676+ }
677+ return 1;
678+}
679+
680+static int
681+sregunget(Input *in)
682+{
683+ if(in->nbits >= 8) {
684+ in->error = FlateInternal;
685+ return 0;
686+ }
687+
688+ /* throw other bits on the floor */
689+ in->nbits = 0;
690+ in->sreg = 0;
691+ return 1;
692+}
os/boot/libflate/inflateblock.c+53−0
@@ -0,0 +1,53 @@
1+#include "lib9.h"
2+#include <flate.h>
3+
4+typedef struct Block Block;
5+
6+struct Block
7+{
8+ uchar *pos;
9+ uchar *limit;
10+};
11+
12+static int
13+blgetc(void *vb)
14+{
15+ Block *b;
16+
17+ b = vb;
18+ if(b->pos >= b->limit)
19+ return -1;
20+ return *b->pos++;
21+}
22+
23+static int
24+blwrite(void *vb, void *buf, int n)
25+{
26+ Block *b;
27+
28+ b = vb;
29+
30+ if(n > b->limit - b->pos)
31+ n = b->limit - b->pos;
32+ memmove(b->pos, buf, n);
33+ b->pos += n;
34+ return n;
35+}
36+
37+int
38+inflateblock(uchar *dst, int dsize, uchar *src, int ssize)
39+{
40+ Block bd, bs;
41+ int ok;
42+
43+ bs.pos = src;
44+ bs.limit = src + ssize;
45+
46+ bd.pos = dst;
47+ bd.limit = dst + dsize;
48+
49+ ok = inflate(&bd, blwrite, &bs, blgetc);
50+ if(ok != FlateOk)
51+ return ok;
52+ return bd.pos - dst;
53+}
os/boot/libflate/inflatezlib.c+65−0
@@ -0,0 +1,65 @@
1+#include "lib9.h"
2+#include <flate.h>
3+#include "zlib.h"
4+
5+typedef struct ZWrite ZWrite;
6+
7+struct ZWrite
8+{
9+ ulong adler;
10+ void *wr;
11+ int (*w)(void*, void*, int);
12+};
13+
14+static int
15+zlwrite(void *vzw, void *buf, int n)
16+{
17+ ZWrite *zw;
18+
19+ zw = vzw;
20+ zw->adler = adler32(zw->adler, buf, n);
21+ n = (*zw->w)(zw->wr, buf, n);
22+ if(n <= 0)
23+ return n;
24+ return n;
25+}
26+
27+int
28+inflatezlib(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
29+{
30+ ZWrite zw;
31+ ulong v;
32+ int c, i;
33+
34+ c = (*get)(getr);
35+ if(c < 0)
36+ return FlateInputFail;
37+ i = (*get)(getr);
38+ if(i < 0)
39+ return FlateInputFail;
40+
41+ if(((c << 8) | i) % 31)
42+ return FlateCorrupted;
43+ if((c & ZlibMeth) != ZlibDeflate
44+ || (c & ZlibCInfo) > ZlibWin32k)
45+ return FlateCorrupted;
46+
47+ zw.wr = wr;
48+ zw.w = w;
49+ zw.adler = 1;
50+ i = inflate(&zw, zlwrite, getr, get);
51+ if(i != FlateOk)
52+ return i;
53+
54+ v = 0;
55+ for(i = 0; i < 4; i++){
56+ c = (*get)(getr);
57+ if(c < 0)
58+ return FlateInputFail;
59+ v = (v << 8) | c;
60+ }
61+ if(zw.adler != v)
62+ return FlateCorrupted;
63+
64+ return FlateOk;
65+}
os/boot/libflate/inflatezlibblock.c+67−0
@@ -0,0 +1,67 @@
1+#include "lib9.h"
2+#include <flate.h>
3+#include "zlib.h"
4+
5+typedef struct Block Block;
6+
7+struct Block
8+{
9+ uchar *pos;
10+ uchar *limit;
11+};
12+
13+static int
14+blgetc(void *vb)
15+{
16+ Block *b;
17+
18+ b = vb;
19+ if(b->pos >= b->limit)
20+ return -1;
21+ return *b->pos++;
22+}
23+
24+static int
25+blwrite(void *vb, void *buf, int n)
26+{
27+ Block *b;
28+
29+ b = vb;
30+
31+ if(n > b->limit - b->pos)
32+ n = b->limit - b->pos;
33+ memmove(b->pos, buf, n);
34+ b->pos += n;
35+ return n;
36+}
37+
38+int
39+inflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize)
40+{
41+ Block bd, bs;
42+ int ok;
43+
44+ if(ssize < 6)
45+ return FlateInputFail;
46+
47+ if(((src[0] << 8) | src[1]) % 31)
48+ return FlateCorrupted;
49+ if((src[0] & ZlibMeth) != ZlibDeflate
50+ || (src[0] & ZlibCInfo) > ZlibWin32k)
51+ return FlateCorrupted;
52+
53+ bs.pos = src + 2;
54+ bs.limit = src + ssize - 6;
55+
56+ bd.pos = dst;
57+ bd.limit = dst + dsize;
58+
59+ ok = inflate(&bd, blwrite, &bs, blgetc);
60+ if(ok != FlateOk)
61+ return ok;
62+
63+ if(adler32(1, dst, bs.pos - dst) != ((bs.pos[0] << 24) | (bs.pos[1] << 16) | (bs.pos[2] << 8) | bs.pos[3]))
64+ return FlateCorrupted;
65+
66+ return bd.pos - dst;
67+}
os/boot/libflate/mkfile+21−0
@@ -0,0 +1,21 @@
1+<../../../mkconfig
2+
3+LIB=libflate.a
4+OFILES=\
5+ deflate.$O\
6+ deflatezlib.$O\
7+ deflateblock.$O\
8+ deflatezlibblock.$O\
9+ inflate.$O\
10+ inflatezlib.$O\
11+ inflateblock.$O\
12+ inflatezlibblock.$O\
13+ flateerr.$O\
14+ crc.$O\
15+ adler.$O\
16+
17+HFILES=\
18+ $ROOT/include/flate.h\
19+ zlib.h\
20+
21+<$ROOT/mkfiles/mksyslib-$SHELLTYPE
os/boot/libflate/zlib.h+11−0
@@ -0,0 +1,11 @@
1+/*
2+ * zlib header fields
3+ */
4+enum
5+{
6+ ZlibMeth = 0x0f, /* mask of compression methods */
7+ ZlibDeflate = 0x08,
8+
9+ ZlibCInfo = 0xf0, /* mask of compression aux. info */
10+ ZlibWin32k = 0x70, /* 32k history window */
11+};
os/boot/mpc/NOTICE+3−0
@@ -0,0 +1,3 @@
1+Inferno® Copyright © 1996-1999 Lucent Technologies Inc. All rights reserved.
2+PowerPC support Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk). All rights reserved.
3+MPC8xx Inferno PowerPC port Copyright © 1998-2003 Vita Nuova Holdings Limited. All rights reserved.
os/boot/mpc/alarm.c+123−0
@@ -0,0 +1,123 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+#define MAXALARM 10
8+
9+Alarm alarmtab[MAXALARM];
10+
11+/*
12+ * Insert new into list after where
13+ */
14+void
15+insert(List **head, List *where, List *new)
16+{
17+ if(where == 0){
18+ new->next = *head;
19+ *head = new;
20+ }else{
21+ new->next = where->next;
22+ where->next = new;
23+ }
24+
25+}
26+
27+/*
28+ * Delete old from list. where->next is known to be old.
29+ */
30+void
31+delete(List **head, List *where, List *old)
32+{
33+ if(where == 0){
34+ *head = old->next;
35+ return;
36+ }
37+ where->next = old->next;
38+}
39+
40+Alarm*
41+newalarm(void)
42+{
43+ int i;
44+ Alarm *a;
45+
46+ for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
47+ if(a->busy==0 && a->f==0){
48+ a->f = 0;
49+ a->arg = 0;
50+ a->busy = 1;
51+ return a;
52+ }
53+ panic("newalarm");
54+ return 0; /* not reached */
55+}
56+
57+Alarm*
58+alarm(int ms, void (*f)(Alarm*), void *arg)
59+{
60+ Alarm *a, *w, *pw;
61+ ulong s;
62+
63+ if(ms < 0)
64+ ms = 0;
65+ s = splhi();
66+ a = newalarm();
67+ a->dt = MS2TK(ms);
68+ a->f = f;
69+ a->arg = arg;
70+ pw = 0;
71+ for(w=m->alarm; w; pw=w, w=w->next){
72+ if(w->dt <= a->dt){
73+ a->dt -= w->dt;
74+ continue;
75+ }
76+ w->dt -= a->dt;
77+ break;
78+ }
79+ insert(&m->alarm, pw, a);
80+ splx(s);
81+ return a;
82+}
83+
84+void
85+cancel(Alarm *a)
86+{
87+ a->f = 0;
88+}
89+
90+void
91+alarminit(void)
92+{
93+}
94+
95+#define NA 10 /* alarms per clock tick */
96+void
97+checkalarms(void)
98+{
99+ int i, n, s;
100+ Alarm *a;
101+ void (*f)(Alarm*);
102+ Alarm *alist[NA];
103+
104+ s = splhi();
105+ a = m->alarm;
106+ if(a){
107+ for(n=0; a && a->dt<=0 && n<NA; n++){
108+ alist[n] = a;
109+ delete(&m->alarm, 0, a);
110+ a = m->alarm;
111+ }
112+ if(a)
113+ a->dt--;
114+
115+ for(i = 0; i < n; i++){
116+ f = alist[i]->f; /* avoid race with cancel */
117+ if(f)
118+ (*f)(alist[i]);
119+ alist[i]->busy = 0;
120+ }
121+ }
122+ splx(s);
123+}
os/boot/mpc/all.h+6−0
@@ -0,0 +1,6 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "dat.h"
4+#include "fns.h"
5+#include "mem.h"
6+#include "io.h"
os/boot/mpc/archfads.c+355−0
@@ -0,0 +1,355 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+#include "archfads.h"
8+
9+/*
10+ * board-specific support for the 8xxFADS (including 860/21 development system)
11+ */
12+
13+enum {
14+ USESDRAM = 0, /* set to 1 if kernel is to use SDRAM as well as DRAM */
15+
16+ /* sccr */
17+ RTSEL = IBIT(8), /* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
18+ RTDIV = IBIT(7), /* =0, divide by 4; =1, divide by 512 */
19+ CRQEN = IBIT(9), /* =1, switch to high frequency when CPM active */
20+ PRQEN = IBIT(10), /* =1, switch to high frequency when interrupt pending */
21+
22+ /* plprcr */
23+ CSRC = IBIT(21), /* =0, clock is DFNH; =1, clock is DFNL */
24+};
25+
26+/*
27+ * called early in main.c, after machinit:
28+ * using board and architecture specific registers, initialise
29+ * 8xx registers that need it and complete initialisation of the Mach structure.
30+ */
31+void
32+archinit(void)
33+{
34+ IMM *io;
35+ int mf, isfads, sysmhz, t;
36+ ulong v;
37+
38+ v = getimmr() & 0xFFFF;
39+ isfads = 0; /* assume it's the 860/821 board */
40+ sysmhz = 40;
41+ switch(v>>8){
42+ case 0x00: t = 0x86000; break;
43+ case 0x20: t = 0x82300; isfads = 1; break;
44+ case 0x21: t = 0x823a0; isfads = 1; break;
45+ default: t = 0; break;
46+ }
47+ m->cputype = t;
48+ m->bcsr = KADDR(BCSRMEM);
49+ m->bcsr[1] |= DisableRS232a | DisableIR | DisableEther | DisablePCMCIA | DisableRS232b;
50+ m->bcsr[1] &= ~(DisableDRAM|DisableFlash);
51+ if(isfads){
52+ sysmhz = 50;
53+ m->bcsr[1] &= ~EnableSDRAM;
54+ m->bcsr[4] &= ~(EnableVideoClock|EnableVideoPort);
55+ m->bcsr[4] |= DisableVideoLamp;
56+ }
57+ io = m->iomem;
58+ if(1 || io->sccr & IBIT(7)){ /* RTDIV=1 */
59+ /* oscillator frequency can't be determined independently: check a switch */
60+ if((m->bcsr[2]>>19)&(1<<2))
61+ m->clockgen = 5*MHz;
62+ else
63+ m->clockgen = 4*MHz;
64+ } else
65+ m->clockgen = 32768;
66+ mf = (sysmhz*MHz)/m->clockgen;
67+ m->cpuhz = m->clockgen*mf;
68+ io->plprcrk = KEEP_ALIVE_KEY;
69+ io->plprcr &= ~IBIT(21); /* general system clock is DFNH */
70+ io->plprcr = (io->plprcr & ((1<<20)-1)) | ((mf-1)<<20);
71+ io->mptpr = 0x0400; /* memory prescaler = 16 for refresh */
72+ io->plprcrk = ~KEEP_ALIVE_KEY;
73+ if(isfads){
74+ m->bcsr[1] |= EnableSDRAM;
75+ sdraminit(SDRAMMEM);
76+ if(!USESDRAM)
77+ m->bcsr[1] &= ~EnableSDRAM; /* tells kernel not to map it */
78+ }
79+}
80+
81+static void
82+archidprint(void)
83+{
84+ int f, i;
85+ ulong v;
86+
87+ /* 8xx and FADS specific */
88+ print("IMMR: ");
89+ v = getimmr() & 0xFFFF;
90+ switch(v>>8){
91+ case 0x00: print("MPC860/821"); break;
92+ case 0x20: print("MPC823"); break;
93+ case 0x21: print("MPC823A"); break;
94+ default: print("Type #%lux", v>>8); break;
95+ }
96+ print(", mask #%lux\n", v&0xFF);
97+ v = m->bcsr[3]>>16;
98+ print("MPC8xxFADS rev %lud, DB: ", ((v>>4)&8)|((v>>1)&4)|(v&3));
99+ f = (v>>8)&0x3F;
100+ switch(f){
101+ default: print("ID#%x", f); break;
102+ case 0x00: print("MPC860/821"); break;
103+ case 0x01: print("MPC813"); break;
104+ case 0x02: print("MPC821"); break;
105+ case 0x03: print("MPC823"); break;
106+ case 0x20: print("MPC801"); break;
107+ case 0x21: print("MPC850"); break;
108+ case 0x22: print("MPC860"); break;
109+ case 0x23: print("MPC860SAR"); break;
110+ case 0x24: print("MPC860T"); break;
111+ }
112+ print("ADS, rev #%lux\n", (m->bcsr[2]>>16)&7);
113+ for(i=0; i<=4; i++)
114+ print("BCSR%d: %8.8lux\n", i, m->bcsr[i]);
115+ v = m->bcsr[2];
116+ f = (v>>28)&0xF;
117+ switch(f){
118+ default: print("Unknown"); break;
119+ case 4: print("SM732A2000/SM73228 - 8M SIMM"); break;
120+ case 5: print("SM732A1000A/SM73218 - 4M SIMM"); break;
121+ case 6: print("MCM29080 - 8M SIMM"); break;
122+ case 7: print("MCM29040 - 4M SIMM"); break;
123+ case 8: print("MCM29020 - 2M SIMM"); break;
124+ }
125+ switch((m->bcsr[3]>>20)&7){
126+ default: i = 0; break;
127+ case 1: i = 150; break;
128+ case 2: i = 120; break;
129+ case 3: i = 90; break;
130+ }
131+ print(" flash, %dns\n", i);
132+ f = (v>>23)&0xF;
133+ switch(f&3){
134+ case 0: i = 4; break;
135+ case 1: i = 32; break;
136+ case 2: i = 16; break;
137+ case 3: i = 8; break;
138+ }
139+ print("%dM SIMM, ", i);
140+ switch(f>>2){
141+ default: i = 0; break;
142+ case 2: i = 70; break;
143+ case 3: i = 60; break;
144+ }
145+ print("%dns\n", i);
146+ print("options: #%lux\n", (m->bcsr[2]>>19)&0xF);
147+ print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
148+}
149+
150+void
151+cpuidprint(void)
152+{
153+ int t;
154+
155+ print("PVR: ");
156+ t = getpvr()>>16;
157+ switch(t){
158+ case 0x01: print("MPC601"); break;
159+ case 0x03: print("MPC603"); break;
160+ case 0x04: print("MPC604"); break;
161+ case 0x06: print("MPC603e"); break;
162+ case 0x07: print("MPC603e-v7"); break;
163+ case 0x50: print("MPC8xx"); break;
164+ default: print("PowerPC version #%x", t); break;
165+ }
166+ print(", revision #%lux\n", getpvr()&0xffff);
167+ archidprint();
168+ print("%lud MHz system\n", m->cpuhz/MHz);
169+ print("\n");
170+}
171+
172+static char* defplan9ini[2] = {
173+ /* 860/821 */
174+ "ether0=type=SCC port=1 ea=00108bf12900\r\n"
175+ "vgasize=640x480x8\r\n"
176+ "kernelpercent=40\r\n"
177+ "console=0 lcd\r\nbaud=9600\r\n",
178+
179+ /* 823 */
180+ "ether0=type=SCC port=2 ea=00108bf12900\r\n"
181+ "vgasize=640x480x8\r\n"
182+ "kernelpercent=40\r\n"
183+ "console=0 lcd\r\nbaud=9600\r\n",
184+};
185+
186+char *
187+archconfig(void)
188+{
189+ print("Using default configuration\n");
190+ return defplan9ini[MPCMODEL(m->cputype) == 0x823];
191+}
192+
193+/*
194+ * provide value for #r/switch (devrtc.c)
195+ */
196+int
197+archoptionsw(void)
198+{
199+ return (m->bcsr[2]>>19)&0xF; /* value of switch DS1 */
200+}
201+
202+/*
203+ * invoked by clock.c:/^clockintr
204+ */
205+static void
206+twinkle(void)
207+{
208+ if(m->ticks%MS2TK(1000) == 0)
209+ m->bcsr[4] ^= DisableLamp;
210+}
211+
212+void (*archclocktick)(void) = twinkle;
213+
214+/*
215+ * for flash.c:/^flashreset
216+ * retrieve flash type, virtual base and length and return 0;
217+ * return -1 on error (no flash)
218+ */
219+int
220+archflashreset(char *type, void **addr, long *length)
221+{
222+ char *t;
223+ int mbyte;
224+
225+ if((m->iomem->memc[0].base & 1) == 0)
226+ return -1; /* shouldn't happen */
227+ switch((m->bcsr[2]>>28)&0xF){
228+ default: return -1; /* unknown or not there */
229+ case 4: mbyte=8; t = "SM732x8"; break;
230+ case 5: mbyte=4; t = "SM732x8"; break;
231+ case 6: mbyte=8; t = "AMD29F0x0"; break;
232+ case 7: mbyte=4; t = "AMD29F0x0"; break;
233+ case 8: mbyte=2; t = "AMD29F0x0"; break;
234+ }
235+ strcpy(type, t);
236+ *addr = KADDR(FLASHMEM);
237+ *length = mbyte*1024*1024;
238+ return 0;
239+}
240+
241+/*
242+ * enable the clocks for the given SCC ether and reveal them to the caller.
243+ * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
244+ */
245+int
246+archetherenable(int cpmid, int *rcs, int *tcs)
247+{
248+ IMM *io;
249+
250+ switch(cpmid){
251+ default:
252+ /* no other SCCs are wired on the FADS board */
253+ return -1;
254+
255+ case SCC2ID: /* assume 8xxFADS board with 823DABS */
256+ io = ioplock();
257+ m->bcsr[1] |= DisableIR|DisableRS232b;
258+ m->bcsr[1] &= ~DisableEther;
259+ io->papar |= SIBIT(6)|SIBIT(5); /* enable CLK2 and CLK3 */
260+ io->padir &= ~(SIBIT(6)|SIBIT(5));
261+
262+ /* ETHLOOP etc set in BCSR elsewhere */
263+ *rcs = CLK2;
264+ *tcs = CLK3;
265+ iopunlock();
266+ break;
267+
268+ case SCC1ID: /* assume 860/21 development board */
269+ io = ioplock();
270+ m->bcsr[1] |= DisableIR|DisableRS232b; /* TO DO: might not be shared with RS232b */
271+ m->bcsr[1] &= ~DisableEther;
272+ io->papar |= SIBIT(6)|SIBIT(7); /* enable CLK2 and CLK1 */
273+ io->padir &= ~(SIBIT(6)|SIBIT(7));
274+
275+ /* settings peculiar to 860/821 development board */
276+ io->pcpar &= ~(SIBIT(4)|SIBIT(5)|SIBIT(6)); /* ETHLOOP, TPFULDL~, TPSQEL~ */
277+ io->pcdir |= SIBIT(4)|SIBIT(5)|SIBIT(6);
278+ io->pcdat &= ~SIBIT(4);
279+ io->pcdat |= SIBIT(5)|SIBIT(6);
280+ *rcs = CLK2;
281+ *tcs = CLK1;
282+ iopunlock();
283+ break;
284+ }
285+ return 0;
286+}
287+
288+void
289+archetherdisable(int id)
290+{
291+ USED(id);
292+ m->bcsr[1] |= DisableEther|DisableIR|DisableRS232b;
293+}
294+
295+/*
296+ * do anything extra required to enable the UART on the given CPM port
297+ */
298+void
299+archenableuart(int id, int irda)
300+{
301+ switch(id){
302+ case SMC1ID:
303+ m->bcsr[1] &= ~DisableRS232a;
304+ break;
305+ case SCC2ID:
306+ m->bcsr[1] |= DisableEther|DisableIR|DisableRS232b;
307+ if(irda)
308+ m->bcsr[1] &= ~DisableIR;
309+ else
310+ m->bcsr[1] &= ~DisableRS232b;
311+ break;
312+ default:
313+ /* nothing special */
314+ break;
315+ }
316+}
317+
318+/*
319+ * do anything extra required to disable the UART on the given CPM port
320+ */
321+void
322+archdisableuart(int id)
323+{
324+ switch(id){
325+ case SMC1ID:
326+ m->bcsr[1] |= DisableRS232a;
327+ break;
328+ case SCC2ID:
329+ m->bcsr[1] |= DisableIR|DisableRS232b;
330+ break;
331+ default:
332+ /* nothing special */
333+ break;
334+ }
335+}
336+
337+/*
338+ * enable/disable the LCD panel's backlight via
339+ * York touch panel interface (does no harm without it)
340+ */
341+void
342+archbacklight(int on)
343+{
344+ IMM *io;
345+
346+ delay(2);
347+ io = ioplock();
348+ io->papar &= ~SIBIT(4);
349+ io->padir |= SIBIT(4);
350+ if(on)
351+ io->padat |= SIBIT(4);
352+ else
353+ io->padat &= ~SIBIT(4);
354+ iopunlock();
355+}
os/boot/mpc/archfads.h+42−0
@@ -0,0 +1,42 @@
1+
2+enum {
3+ /* BCSR1 bits */
4+ DisableFlash= IBIT(0),
5+ DisableDRAM= IBIT(1),
6+ DisableEther= IBIT(2),
7+ DisableIR= IBIT(3),
8+ DisableRS232a= IBIT(7),
9+ DisablePCMCIA= IBIT(8),
10+ PCCVCCMask= IBIT(9)|IBIT(15),
11+ PCCVPPMask= IBIT(10)|IBIT(11),
12+ DisableRS232b= IBIT(13),
13+ EnableSDRAM= IBIT(14),
14+
15+ PCCVCC0V= IBIT(15)|IBIT(9),
16+ PCCVCC5V= IBIT(9), /* active low */
17+ PCCVCC3V= IBIT(15), /* active low */
18+ PCCVPP0V= IBIT(10)|IBIT(11), /* active low */
19+ PCCVPP5V= IBIT(10), /* active low */
20+ PCCVPP12V= IBIT(11), /* active low */
21+ PCCVPPHiZ= IBIT(10)|IBIT(11),
22+
23+ /* BCSR4 bits */
24+ DisableTPDuplex= IBIT(1),
25+ DisableLamp= IBIT(3),
26+ DisableUSB= IBIT(4),
27+ USBFullSpeed= IBIT(5),
28+ DisableUSBVcc= IBIT(6),
29+ DisableVideoLamp= IBIT(8),
30+ EnableVideoClock= IBIT(9),
31+ EnableVideoPort= IBIT(10),
32+ DisableModem= IBIT(11),
33+};
34+
35+enum {
36+ /* memory controller CS assignment on FADS boards */
37+ BOOTCS = 0,
38+ BCSRCS = 1,
39+ DRAM1 = 2,
40+ DRAM2 = 3,
41+ SDRAM = 4,
42+};
os/boot/mpc/archpaq.c+240−0
@@ -0,0 +1,240 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+#include "archpaq.h"
9+
10+/*
11+ * board-specific support for the 82x PowerPAQ
12+ */
13+
14+enum {
15+ SYSMHZ = 50, /* desired system clock in MHz */
16+
17+ /* sccr */
18+ RTSEL = IBIT(8), /* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
19+ RTDIV = IBIT(7), /* =0, divide by 4; =1, divide by 512 */
20+ CRQEN = IBIT(9), /* =1, switch to high frequency when CPM active */
21+ PRQEN = IBIT(10), /* =1, switch to high frequency when interrupt pending */
22+
23+ /* plprcr */
24+ CSRC = IBIT(21), /* =0, clock is DFNH; =1, clock is DFNL */
25+};
26+
27+/*
28+ * called early in main.c, after machinit:
29+ * using board and architecture specific registers, initialise
30+ * 8xx registers that need it and complete initialisation of the Mach structure.
31+ */
32+void
33+archinit(void)
34+{
35+ IMM *io;
36+ int mf, t;
37+
38+ switch((getimmr()>>8)&0xFF){
39+ case 0x00: t = 0x86000; break; /* also 821 */
40+ case 0x20: t = 0x82300; break;
41+ case 0x21: t = 0x823a0; break;
42+ default: t = 0; break;
43+ }
44+ m->cputype = t;
45+ m->bcsr = nil; /* there isn't one */
46+ m->clockgen = 32*1024; /* crystal frequency */
47+ io = m->iomem;
48+ io->sccrk = KEEP_ALIVE_KEY;
49+ io->sccr &= ~RTDIV; /* divide 32k by 4 */
50+ io->sccr |= RTSEL;
51+ io->sccrk = ~KEEP_ALIVE_KEY;
52+ mf = (SYSMHZ*MHz)/m->clockgen;
53+ m->cpuhz = m->clockgen*mf;
54+ io->plprcrk = KEEP_ALIVE_KEY;
55+ io->plprcr &= ~IBIT(21); /* general system clock is DFNH */
56+ io->plprcr = (io->plprcr & ((1<<20)-1)) | ((mf-1)<<20);
57+ io->mptpr = 0x0400; /* memory prescaler = 16 for refresh */
58+ io->plprcrk = ~KEEP_ALIVE_KEY;
59+}
60+
61+void
62+cpuidprint(void)
63+{
64+ int t, v;
65+
66+ print("PVR: ");
67+ t = getpvr()>>16;
68+ switch(t){
69+ case 0x01: print("MPC601"); break;
70+ case 0x03: print("MPC603"); break;
71+ case 0x04: print("MPC604"); break;
72+ case 0x06: print("MPC603e"); break;
73+ case 0x07: print("MPC603e-v7"); break;
74+ case 0x50: print("MPC8xx"); break;
75+ default: print("PowerPC version #%x", t); break;
76+ }
77+ print(", revision #%lux\n", getpvr()&0xffff);
78+ print("IMMR: ");
79+ v = getimmr() & 0xFFFF;
80+ switch(v>>8){
81+ case 0x00: print("MPC860/821"); break;
82+ case 0x20: print("MPC823"); break;
83+ case 0x21: print("MPC823A"); break;
84+ default: print("Type #%lux", v>>8); break;
85+ }
86+ print(", mask #%lux\n", v&0xFF);
87+ print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
88+ print("%lud MHz system\n", m->cpuhz/MHz);
89+ print("\n");
90+}
91+
92+static char* defplan9ini[2] = {
93+ /* 860/821 */
94+ "ether0=type=SCC port=1 ea=00108bf12900\r\n"
95+ "vgasize=640x480x8\r\n"
96+ "kernelpercent=40\r\n"
97+ "console=0 lcd\r\nbaud=19200\r\n",
98+
99+ /* 823 */
100+ "ether0=type=SCC port=2 ea=00108bf12900\r\n"
101+ "vgasize=640x480x8\r\n"
102+ "kernelpercent=40\r\n"
103+ "console=0 lcd\r\nbaud=19200\r\n",
104+};
105+
106+char *
107+archconfig(void)
108+{
109+ print("Using default configuration\n");
110+ return defplan9ini[MPCMODEL(m->cputype) == 0x823];
111+}
112+
113+/*
114+ * provide value for #r/switch (devrtc.c)
115+ */
116+int
117+archoptionsw(void)
118+{
119+ return 0;
120+}
121+
122+/*
123+ * invoked by clock.c:/^clockintr
124+ */
125+static void
126+twinkle(void)
127+{
128+ /* no easy-to-use LED on PAQ (they use i2c) */
129+}
130+
131+void (*archclocktick)(void) = twinkle;
132+
133+/*
134+ * for flash.c:/^flashinit
135+ * retrieve flash type, virtual base and length and return 0;
136+ * return -1 on error (no flash)
137+ */
138+int
139+archflashreset(char *type, void **addr, long *length)
140+{
141+ strcpy(type, "AMD29F0x0");
142+ *addr = KADDR(FLASHMEM);
143+ *length = 8*1024*1024; /* 8mbytes on some models */
144+ return 0;
145+}
146+
147+/*
148+ * enable the clocks for the given SCC ether and reveal them to the caller.
149+ * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
150+ */
151+int
152+archetherenable(int cpmid, int *rcs, int *tcs)
153+{
154+ USED(cpmid, rcs, tcs);
155+ return -1; /* there isn't an ether on the PAQs */
156+}
157+
158+void
159+archetherdisable(int id)
160+{
161+ USED(id);
162+}
163+
164+/*
165+ * do anything extra required to enable the UART on the given CPM port
166+ */
167+void
168+archenableuart(int id, int irda)
169+{
170+ IMM *io;
171+
172+ USED(irda);
173+ switch(id){
174+ case SMC1ID:
175+ io = ioplock();
176+ io->pbodr &= ~0xc0;
177+ io->pbdat |= 0xc0;
178+ io->pcdat |= 0x400;
179+ io->pcpar &= ~0x400;
180+ io->pcdir |= 0x400;
181+ io->pcdat &= ~0x400; /* enable SMC RS232 buffer */
182+ iopunlock();
183+ break;
184+ case SCC2ID:
185+ /* TO DO */
186+ break;
187+ default:
188+ /* nothing special */
189+ break;
190+ }
191+}
192+
193+/*
194+ * do anything extra required to disable the UART on the given CPM port
195+ */
196+void
197+archdisableuart(int id)
198+{
199+ switch(id){
200+ case SMC1ID:
201+ /* TO DO */
202+ break;
203+ case SCC2ID:
204+ /* TO DO */
205+ break;
206+ default:
207+ /* nothing special */
208+ break;
209+ }
210+}
211+
212+/*
213+ * enable/disable the LCD panel's backlight via i2c
214+ */
215+void
216+archbacklight(int on)
217+{
218+ uchar msg;
219+ IMM *io;
220+
221+ i2csetup();
222+ msg = ~7;
223+ i2csend(LEDRegI2C, &msg, 1);
224+ io = ioplock();
225+ io->pbpar &= ~EnableLCD;
226+ io->pbodr &= ~EnableLCD;
227+ io->pbdir |= EnableLCD;
228+ if(on)
229+ io->pbdat |= EnableLCD;
230+ else
231+ io->pbdat &= ~EnableLCD;
232+ iopunlock();
233+ if(on){
234+ msg = ~(DisablePanelVCC5|DisableTFT);
235+ i2csend(PanelI2C, &msg, 1);
236+ }else{
237+ msg = ~0;
238+ i2csend(PanelI2C, &msg, 1);
239+ }
240+}
os/boot/mpc/archpaq.h+29−0
@@ -0,0 +1,29 @@
1+enum {
2+ /* memory controller CS assignment on PowerPAQ */
3+ BOOTCS = 0,
4+ DRAM1 = 1, /* UPMB */
5+ DRAM2 = 2, /* UPMB */
6+ /* CS3 also connected to DRAM */
7+ /* CS4 128mbyte 8-bit gpcm, trlx, 15 wait; it's DAC */
8+ /* CS5 is external*/
9+};
10+
11+enum {
12+ /* I2C addresses */
13+ PanelI2C = 0x21<<1,
14+ /* the control bits are active low enables, or high disables */
15+ DisableVGA = ~0xFD, /* disable VGA signals */
16+ DisableTFT = ~0xFB, /* disable TFT panel signals */
17+ DisableSPIBus = ~0xF7, /* disable SPI/I2C to panel */
18+ DisablePanelVCC5 = ~0xEF, /* disable +5V to panel(s) */
19+ DisablePanelVCC3 = ~0xDF, /* disable +3.3V to panel(s) */
20+ DisableMonoPanel = ~0xBF, /* disable mono panel signals */
21+ DisableSPISelect = ~0x7F, /* disable SPI chip select to LVDS panel */
22+ ContrastI2C = 0x2E<<1,
23+ LEDRegI2C = 0x20<<1,
24+ DisableGreenLED = ~0xFE,
25+ DisableYellowLED = ~0xFD,
26+ DisableRedLED = ~0xFB,
27+
28+ EnableLCD = IBIT(23), /* LCD enable bit in i/o port B */
29+};
os/boot/mpc/boot.h+8−0
@@ -0,0 +1,8 @@
1+#include <u.h>
2+#include "lib.h"
3+
4+#include "mem.h"
5+#include "dat.h"
6+#include "fns.h"
7+#include "io.h"
8+#include "ureg.h"
os/boot/mpc/bootp.c+507−0
@@ -0,0 +1,507 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+#include "ip.h"
9+
10+enum {
11+ CHECKSUM = 1, /* set zero if trouble booting from Linux */
12+};
13+
14+uchar broadcast[Eaddrlen] = {
15+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
16+};
17+
18+static ushort tftpport = 5000;
19+static int Id = 1;
20+static Netaddr myaddr;
21+static Netaddr server;
22+
23+typedef struct {
24+ uchar header[4];
25+ uchar data[Segsize];
26+} Tftp;
27+static Tftp tftpb;
28+
29+static void
30+hnputs(uchar *ptr, ushort val)
31+{
32+ ptr[0] = val>>8;
33+ ptr[1] = val;
34+}
35+
36+static void
37+hnputl(uchar *ptr, ulong val)
38+{
39+ ptr[0] = val>>24;
40+ ptr[1] = val>>16;
41+ ptr[2] = val>>8;
42+ ptr[3] = val;
43+}
44+
45+static ulong
46+nhgetl(uchar *ptr)
47+{
48+ return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
49+}
50+
51+static ushort
52+nhgets(uchar *ptr)
53+{
54+ return ((ptr[0]<<8) | ptr[1]);
55+}
56+
57+static short endian = 1;
58+static char* aendian = (char*)&endian;
59+#define LITTLE *aendian
60+
61+static ushort
62+ptcl_csum(void *a, int len)
63+{
64+ uchar *addr;
65+ ulong t1, t2;
66+ ulong losum, hisum, mdsum, x;
67+
68+ addr = a;
69+ losum = 0;
70+ hisum = 0;
71+ mdsum = 0;
72+
73+ x = 0;
74+ if((ulong)addr & 1) {
75+ if(len) {
76+ hisum += addr[0];
77+ len--;
78+ addr++;
79+ }
80+ x = 1;
81+ }
82+ while(len >= 16) {
83+ t1 = *(ushort*)(addr+0);
84+ t2 = *(ushort*)(addr+2); mdsum += t1;
85+ t1 = *(ushort*)(addr+4); mdsum += t2;
86+ t2 = *(ushort*)(addr+6); mdsum += t1;
87+ t1 = *(ushort*)(addr+8); mdsum += t2;
88+ t2 = *(ushort*)(addr+10); mdsum += t1;
89+ t1 = *(ushort*)(addr+12); mdsum += t2;
90+ t2 = *(ushort*)(addr+14); mdsum += t1;
91+ mdsum += t2;
92+ len -= 16;
93+ addr += 16;
94+ }
95+ while(len >= 2) {
96+ mdsum += *(ushort*)addr;
97+ len -= 2;
98+ addr += 2;
99+ }
100+ if(x) {
101+ if(len)
102+ losum += addr[0];
103+ if(LITTLE)
104+ losum += mdsum;
105+ else
106+ hisum += mdsum;
107+ } else {
108+ if(len)
109+ hisum += addr[0];
110+ if(LITTLE)
111+ hisum += mdsum;
112+ else
113+ losum += mdsum;
114+ }
115+
116+ losum += hisum >> 8;
117+ losum += (hisum & 0xff) << 8;
118+ while(hisum = losum>>16)
119+ losum = hisum + (losum & 0xffff);
120+
121+ return ~losum;
122+}
123+
124+static ushort
125+ip_csum(uchar *addr)
126+{
127+ int len;
128+ ulong sum = 0;
129+
130+ len = (addr[0]&0xf)<<2;
131+
132+ while(len > 0) {
133+ sum += addr[0]<<8 | addr[1] ;
134+ len -= 2;
135+ addr += 2;
136+ }
137+
138+ sum = (sum & 0xffff) + (sum >> 16);
139+ sum = (sum & 0xffff) + (sum >> 16);
140+ return (sum^0xffff);
141+}
142+
143+static void
144+udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
145+{
146+ Udphdr *uh;
147+ Etherhdr *ip;
148+ static Etherpkt pkt;
149+ int len, ptcllen;
150+
151+
152+ uh = (Udphdr*)&pkt;
153+
154+ memset(uh, 0, sizeof(Etherpkt));
155+ memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
156+
157+ /*
158+ * UDP portion
159+ */
160+ ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
161+ uh->ttl = 0;
162+ uh->udpproto = IP_UDPPROTO;
163+ uh->frag[0] = 0;
164+ uh->frag[1] = 0;
165+ hnputs(uh->udpplen, ptcllen);
166+ hnputl(uh->udpsrc, myaddr.ip);
167+ hnputs(uh->udpsport, myaddr.port);
168+ hnputl(uh->udpdst, a->ip);
169+ hnputs(uh->udpdport, a->port);
170+ hnputs(uh->udplen, ptcllen);
171+ uh->udpcksum[0] = 0;
172+ uh->udpcksum[1] = 0;
173+ /*dlen = (dlen+1)&~1; */
174+ hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
175+
176+ /*
177+ * IP portion
178+ */
179+ ip = (Etherhdr*)&pkt;
180+ len = sizeof(Udphdr)+dlen;
181+ ip->vihl = IP_VER|IP_HLEN;
182+ ip->tos = 0;
183+ ip->ttl = 255;
184+ hnputs(ip->length, len-ETHER_HDR);
185+ hnputs(ip->id, Id++);
186+ ip->frag[0] = 0;
187+ ip->frag[1] = 0;
188+ ip->cksum[0] = 0;
189+ ip->cksum[1] = 0;
190+ hnputs(ip->cksum, ip_csum(&ip->vihl));
191+
192+ /*
193+ * Ethernet MAC portion
194+ */
195+ hnputs(ip->type, ET_IP);
196+ memmove(ip->d, a->ea, sizeof(ip->d));
197+
198+ ethertxpkt(ctlrno, &pkt, len, Timeout);
199+}
200+
201+static void
202+nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
203+{
204+ int n;
205+ char buf[128];
206+
207+ buf[0] = 0;
208+ buf[1] = Tftp_ERROR;
209+ buf[2] = 0;
210+ buf[3] = code;
211+ strcpy(buf+4, msg);
212+ n = strlen(msg) + 4 + 1;
213+ udpsend(ctlrno, a, buf, n);
214+ if(report)
215+ print("\ntftp: error(%d): %s\n", code, msg);
216+}
217+
218+static int
219+udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
220+{
221+ int n, len;
222+ ushort csm;
223+ Udphdr *h;
224+ ulong addr, timo;
225+ static Etherpkt pkt;
226+ static int rxactive;
227+
228+ if(rxactive == 0)
229+ timo = 1000;
230+ else
231+ timo = Timeout;
232+ timo += TK2MS(m->ticks);
233+ while(timo > TK2MS(m->ticks)){
234+ n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
235+ if(n <= 0)
236+ continue;
237+
238+ h = (Udphdr*)&pkt;
239+ if(nhgets(h->type) != ET_IP)
240+ continue;
241+
242+ if(ip_csum(&h->vihl)) {
243+ print("ip chksum error\n");
244+ continue;
245+ }
246+ if(h->vihl != (IP_VER|IP_HLEN)) {
247+ print("ip bad vers/hlen\n");
248+ continue;
249+ }
250+
251+ if(h->udpproto != IP_UDPPROTO)
252+ continue;
253+
254+ h->ttl = 0;
255+ len = nhgets(h->udplen);
256+ hnputs(h->udpplen, len);
257+
258+ if(CHECKSUM && nhgets(h->udpcksum)) {
259+ csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
260+ if(csm != 0) {
261+ print("udp chksum error csum #%4lux len %d\n", csm, n);
262+ break;
263+ }
264+ }
265+
266+ if(a->port != 0 && nhgets(h->udpsport) != a->port)
267+ continue;
268+
269+ addr = nhgetl(h->udpsrc);
270+ if(a->ip != Bcastip && addr != a->ip)
271+ continue;
272+
273+ len -= UDP_HDRSIZE-UDP_PHDRSIZE;
274+ if(len > dlen) {
275+ print("udp: packet too big\n");
276+ continue;
277+ }
278+
279+ memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
280+ a->ip = addr;
281+ a->port = nhgets(h->udpsport);
282+ memmove(a->ea, pkt.s, sizeof(a->ea));
283+
284+ rxactive = 1;
285+ return len;
286+ }
287+
288+ return 0;
289+}
290+
291+static int tftpblockno;
292+
293+static int
294+tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
295+{
296+ int i, len, rlen, oport;
297+ char buf[Segsize+2];
298+
299+ buf[0] = 0;
300+ buf[1] = Tftp_READ;
301+ len = sprint(buf+2, "%s", name) + 2;
302+ len += sprint(buf+len+1, "octet") + 2;
303+
304+ oport = a->port;
305+ for(i = 0; i < 5; i++){
306+ a->port = oport;
307+ udpsend(ctlrno, a, buf, len);
308+ a->port = 0;
309+ if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
310+ continue;
311+
312+ switch((tftp->header[0]<<8)|tftp->header[1]){
313+
314+ case Tftp_ERROR:
315+ print("tftpopen: error (%d): %s\n",
316+ (tftp->header[2]<<8)|tftp->header[3], tftp->data);
317+ return -1;
318+
319+ case Tftp_DATA:
320+ tftpblockno = 1;
321+ len = (tftp->header[2]<<8)|tftp->header[3];
322+ if(len != tftpblockno){
323+ print("tftpopen: block error: %d\n", len);
324+ nak(ctlrno, a, 1, "block error", 0);
325+ return -1;
326+ }
327+ return rlen-sizeof(tftp->header);
328+ }
329+ }
330+
331+ print("tftpopen: failed to connect to server\n");
332+ return -1;
333+}
334+
335+static int
336+tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
337+{
338+ int blockno, len, retry;
339+ uchar buf[4];
340+
341+ buf[0] = 0;
342+ buf[1] = Tftp_ACK;
343+ buf[2] = tftpblockno>>8;
344+ buf[3] = tftpblockno;
345+ tftpblockno++;
346+
347+ dlen += sizeof(tftp->header);
348+
349+ retry = 0;
350+buggery:
351+ udpsend(ctlrno, a, buf, sizeof(buf));
352+
353+ if((len = udprecv(ctlrno, a, tftp, dlen)) < dlen){
354+ print("tftpread: %d != %d\n", len, dlen);
355+ nak(ctlrno, a, 2, "short read", 0);
356+ if(retry++ < 5)
357+ goto buggery;
358+ return -1;
359+ }
360+
361+ blockno = (tftp->header[2]<<8)|tftp->header[3];
362+ if(blockno != tftpblockno){
363+ print("?");
364+
365+ if(blockno == tftpblockno-1 && retry++ < 8)
366+ goto buggery;
367+ print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
368+ nak(ctlrno, a, 1, "block error", 0);
369+
370+ return -1;
371+ }
372+
373+ return len-sizeof(tftp->header);
374+}
375+
376+int
377+bootp(int ctlrno, char *file)
378+{
379+ Bootp req, rep;
380+ int i, dlen, segsize, text, data, bss, total;
381+ uchar *ea, *addr, *p;
382+ ulong entry;
383+ Exec *exec;
384+ char name[128], *filename, *sysname;
385+
386+ if((ea = etheraddr(ctlrno)) == 0){
387+ print("invalid ctlrno %d\n", ctlrno);
388+ return -1;
389+ }
390+
391+ filename = 0;
392+ sysname = 0;
393+ if(file && *file){
394+ strcpy(name, file);
395+ if(filename = strchr(name, ':')){
396+ if(filename != name && *(filename-1) != '\\'){
397+ sysname = name;
398+ *filename++ = 0;
399+ }
400+ }
401+ else
402+ filename = name;
403+ }
404+
405+
406+ memset(&req, 0, sizeof(req));
407+ req.op = Bootrequest;
408+ req.htype = 1; /* ethernet */
409+ req.hlen = Eaddrlen; /* ethernet */
410+ memmove(req.chaddr, ea, Eaddrlen);
411+
412+ myaddr.ip = 0;
413+ myaddr.port = BPportsrc;
414+ memmove(myaddr.ea, ea, Eaddrlen);
415+
416+ for(i = 0; i < 10; i++) {
417+ server.ip = Bcastip;
418+ server.port = BPportdst;
419+ memmove(server.ea, broadcast, sizeof(server.ea));
420+ udpsend(ctlrno, &server, &req, sizeof(req));
421+ if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
422+ continue;
423+ if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
424+ continue;
425+ if(rep.htype != 1 || rep.hlen != Eaddrlen)
426+ continue;
427+ if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
428+ break;
429+ }
430+ if(i >= 10) {
431+ print("bootp timed out\n");
432+ return -1;
433+ }
434+
435+ if(filename == 0 || *filename == 0)
436+ filename = rep.file;
437+
438+ if(rep.sname[0] != '\0')
439+ print("%s ", rep.sname);
440+ print("(%d.%d.%d.%d!%d): %s\n",
441+ rep.siaddr[0],
442+ rep.siaddr[1],
443+ rep.siaddr[2],
444+ rep.siaddr[3],
445+ server.port,
446+ filename);uartwait();
447+
448+ myaddr.ip = nhgetl(rep.yiaddr);
449+ myaddr.port = tftpport++;
450+ server.ip = nhgetl(rep.siaddr);
451+ server.port = TFTPport;
452+
453+ if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
454+ return -1;
455+ exec = (Exec*)(tftpb.data);
456+ if(dlen < sizeof(Exec) || GLLONG(exec->magic) != Q_MAGIC){
457+ nak(ctlrno, &server, 0, "bad magic number", 1);
458+ return -1;
459+ }
460+ text = GLLONG(exec->text);
461+ data = GLLONG(exec->data);
462+ bss = GLLONG(exec->bss);
463+ total = text+data+bss;
464+ entry = GLLONG(exec->entry);
465+print("load@%8.8lux: ", PADDR(entry));uartwait();
466+ print("%d", text);
467+
468+ addr = (uchar*)PADDR(entry);
469+ p = tftpb.data+sizeof(Exec);
470+ dlen -= sizeof(Exec);
471+ segsize = text;
472+ for(;;){
473+ if(dlen == 0){
474+ if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
475+ return -1;
476+ p = tftpb.data;
477+ }
478+ if(segsize <= dlen)
479+ i = segsize;
480+ else
481+ i = dlen;
482+ memmove(addr, p, i);
483+
484+ addr += i;
485+ p += i;
486+ segsize -= i;
487+ dlen -= i;
488+
489+ if(segsize <= 0){
490+ if(data == 0)
491+ break;
492+ print("+%d", data);
493+ segsize = data;
494+ data = 0;
495+ addr = (uchar*)PGROUND((ulong)addr);
496+ }
497+ }
498+ nak(ctlrno, &server, 3, "ok", 0); /* tftpclose */
499+ print("+%d=%d\n", bss, total);
500+ print("entry: 0x%lux\n", entry);
501+ uartwait();
502+ scc2stop();
503+ splhi();
504+ (*(void(*)(void))(PADDR(entry)))();
505+
506+ return 0;
507+}
os/boot/mpc/clock.c+71−0
@@ -0,0 +1,71 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+#include "ureg.h"
8+
9+enum {
10+ Timebase = 4, /* system clock cycles per time base cycle */
11+};
12+
13+void (*archclocktick)(void); /* set by arch*.c when desired */
14+
15+static ulong clkreload;
16+
17+void
18+delay(int l)
19+{
20+ ulong i, j;
21+
22+ j = m->delayloop;
23+ while(l-- > 0)
24+ for(i=0; i < j; i++)
25+ ;
26+}
27+
28+void
29+microdelay(int l)
30+{
31+ ulong i;
32+
33+ l *= m->delayloop;
34+ l /= 1000;
35+ if(l <= 0)
36+ l = 1;
37+ for(i = 0; i < l; i++)
38+ ;
39+}
40+
41+void
42+clockintr(Ureg*, void*)
43+{
44+ putdec(clkreload);
45+ m->ticks++;
46+ checkalarms();
47+ if(archclocktick != nil)
48+ archclocktick();
49+}
50+
51+void
52+clockinit(void)
53+{
54+ long x;
55+
56+ m->delayloop = m->cpuhz/1000; /* initial estimate */
57+ do {
58+ x = gettbl();
59+ delay(10);
60+ x = gettbl() - x;
61+ } while(x < 0);
62+
63+ /*
64+ * fix count
65+ */
66+ m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase);
67+ if(m->delayloop == 0)
68+ m->delayloop = 1;
69+ clkreload = (m->clockgen/Timebase)/HZ-1;
70+ putdec(clkreload);
71+}
os/boot/mpc/conf.c+173−0
@@ -0,0 +1,173 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+#include "dosfs.h"
9+
10+static char *confname[MAXCONF];
11+static char *confval[MAXCONF];
12+static int nconf;
13+
14+extern char **ini;
15+
16+char*
17+getconf(char *name)
18+{
19+ int i;
20+
21+ for(i = 0; i < nconf; i++)
22+ if(strcmp(confname[i], name) == 0)
23+ return confval[i];
24+ return 0;
25+}
26+
27+/*
28+ * read configuration file
29+ */
30+int
31+plan9ini(Dos *dos, char *val)
32+{
33+ Dosfile rc;
34+ int i, n;
35+ char *cp, *p, *q, *line[MAXCONF];
36+
37+ cp = BOOTARGS;
38+ if(dos) {
39+ if(dosstat(dos, *ini, &rc) <= 0)
40+ return -1;
41+
42+ *cp = 0;
43+ n = dosread(&rc, cp, BOOTARGSLEN-1);
44+ if(n <= 0)
45+ return -1;
46+ cp[n] = 0;
47+ } else if(val != nil){
48+ if(memchr(val, 0, BOOTARGSLEN-1) == nil)
49+ return -1;
50+ print("Using flash configuration\n");
51+ strcpy(cp, val);
52+ n = strlen(cp);
53+ }else{
54+ strcpy(cp, archconfig());
55+ n = strlen(cp);
56+ }
57+
58+ /*
59+ * Make a working copy.
60+ * We could change this to pass the parsed strings
61+ * to the booted programme instead of the raw
62+ * string, then it only gets done once.
63+ */
64+ memmove(cp+BOOTARGSLEN, cp, n+1);
65+ cp += BOOTARGSLEN;
66+
67+ /*
68+ * Strip out '\r', change '\t' -> ' '.
69+ */
70+ p = cp;
71+ for(q = cp; *q; q++){
72+ if(*q == '\r')
73+ continue;
74+ if(*q == '\t')
75+ *q = ' ';
76+ *p++ = *q;
77+ }
78+ *p = 0;
79+ n = getcfields(cp, line, MAXCONF, "\n");
80+ for(i = 0; i < n; i++){
81+ cp = strchr(line[i], '=');
82+ if(cp == 0)
83+ continue;
84+ *cp++ = 0;
85+ if(cp - line[i] >= NAMELEN+1)
86+ *(line[i]+NAMELEN-1) = 0;
87+ confname[nconf] = line[i];
88+ confval[nconf] = cp;
89+ nconf++;
90+ }
91+ return 0;
92+}
93+
94+int
95+parseether(uchar *to, char *from)
96+{
97+ char nip[4];
98+ char *p;
99+ int i;
100+
101+ p = from;
102+ while(*p == ' ')
103+ ++p;
104+ for(i = 0; i < 6; i++){
105+ if(*p == 0)
106+ return -1;
107+ nip[0] = *p++;
108+ if(*p == 0)
109+ return -1;
110+ nip[1] = *p++;
111+ nip[2] = 0;
112+ to[i] = strtoul(nip, 0, 16);
113+ if(*p == ':')
114+ p++;
115+ }
116+ return 0;
117+}
118+
119+int
120+isaconfig(char *class, int ctlrno, ISAConf *isa)
121+{
122+ char cc[NAMELEN], *p, *q, *r;
123+ int n;
124+
125+ sprint(cc, "%s%d", class, ctlrno);
126+ for(n = 0; n < nconf; n++){
127+ if(strncmp(confname[n], cc, NAMELEN))
128+ continue;
129+ isa->nopt = 0;
130+ p = confval[n];
131+ while(*p){
132+ while(*p == ' ' || *p == '\t')
133+ p++;
134+ if(*p == '\0')
135+ break;
136+ if(strncmp(p, "type=", 5) == 0){
137+ p += 5;
138+ for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
139+ if(*p == '\0' || *p == ' ' || *p == '\t')
140+ break;
141+ *q = *p++;
142+ }
143+ *q = '\0';
144+ }
145+ else if(strncmp(p, "port=", 5) == 0)
146+ isa->port = strtoul(p+5, &p, 0);
147+ else if(strncmp(p, "irq=", 4) == 0)
148+ isa->irq = strtoul(p+4, &p, 0);
149+ else if(strncmp(p, "mem=", 4) == 0)
150+ isa->mem = strtoul(p+4, &p, 0);
151+ else if(strncmp(p, "size=", 5) == 0)
152+ isa->size = strtoul(p+5, &p, 0);
153+ else if(strncmp(p, "ea=", 3) == 0){
154+ if(parseether(isa->ea, p+3) == -1)
155+ memset(isa->ea, 0, 6);
156+ }
157+ else if(isa->nopt < NISAOPT){
158+ r = isa->opt[isa->nopt];
159+ while(*p && *p != ' ' && *p != '\t'){
160+ *r++ = *p++;
161+ if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
162+ break;
163+ }
164+ *r = '\0';
165+ isa->nopt++;
166+ }
167+ while(*p && *p != ' ' && *p != '\t')
168+ p++;
169+ }
170+ return 1;
171+ }
172+ return 0;
173+}
os/boot/mpc/console.c+173−0
@@ -0,0 +1,173 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+static Queue* consiq;
9+static Queue* consoq;
10+
11+void
12+bothputs(char *s, int n)
13+{
14+ uartputs(s, n);
15+ screenputs(s, n);
16+}
17+
18+static void (*consputs)(char*, int) = bothputs; /* or screenputs */
19+
20+void
21+consinit(void)
22+{
23+ char *p;
24+ int baud, port;
25+ static int cgadone;
26+
27+ p = getconf("console");
28+ if(0)
29+ if(p == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
30+ consiq = qopen(4*1024, 0, 0, 0);
31+ consoq = qopen(8*1024, 0, 0, 0);
32+ consputs = screenputs;
33+ return;
34+ }
35+ if(p!=0 && strstr(p, "lcd") == 0)
36+ consputs = bothputs;
37+ else
38+ consputs = uartputs;
39+//consputs = screenputs;
40+ port = 0;
41+ if(p)
42+ port = strtoul(p, 0, 0);
43+ baud = 0;
44+ if(p = getconf("baud"))
45+ baud = strtoul(p, 0, 0);
46+ if(baud == 0)
47+ baud = 9600;
48+ uartspecial(port, baud, &consiq, &consoq, kbdchar);
49+}
50+
51+void
52+kbdchar(Queue *q, int c)
53+{
54+ c &= 0x7F;
55+ if(c == 0x10)
56+ panic("^p");
57+ qbputc(q, c);
58+}
59+
60+static int
61+getline(char *buf, int size, int dotimeout)
62+{
63+ int c, i=0;
64+ ulong start;
65+ char echo;
66+
67+ for (;;) {
68+ start = m->ticks;
69+ do{
70+ if(dotimeout && ((m->ticks - start) > 5*HZ))
71+ return -2;
72+ c = qbgetc(consiq);
73+ }while(c == -1);
74+ if(c == '\r')
75+ c = '\n'; /* turn carriage return into newline */
76+ if(c == '\177')
77+ c = '\010'; /* turn delete into backspace */
78+ if(c == '\025')
79+ echo = '\n'; /* echo ^U as a newline */
80+ else
81+ echo = c;
82+ (*consputs)(&echo, 1);
83+
84+ if(c == '\010'){
85+ if(i > 0)
86+ i--; /* bs deletes last character */
87+ continue;
88+ }
89+ /* a newline ends a line */
90+ if (c == '\n')
91+ break;
92+ /* ^U wipes out the line */
93+ if (c =='\025')
94+ return -1;
95+ if(i == size)
96+ return size;
97+ buf[i++] = c;
98+ }
99+ buf[i] = 0;
100+ return i;
101+}
102+
103+int
104+getstr(char *prompt, char *buf, int size, char *def)
105+{
106+ int len, isdefault;
107+
108+ buf[0] = 0;
109+ isdefault = (def && *def);
110+ for (;;) {
111+ if(isdefault)
112+ print("%s[default==%s]: ", prompt, def);
113+ else
114+ print("%s: ", prompt);
115+ len = getline(buf, size, isdefault);
116+ switch(len){
117+ case -1:
118+ /* ^U typed */
119+ continue;
120+ case -2:
121+ /* timeout, use default */
122+ (*consputs)("\n", 1);
123+ len = 0;
124+ break;
125+ default:
126+ break;
127+ }
128+ if(len >= size){
129+ print("line too long\n");
130+ continue;
131+ }
132+ break;
133+ }
134+ if(len == 0 && isdefault)
135+ strcpy(buf, def);
136+ return 0;
137+}
138+
139+int
140+sprint(char *s, char *fmt, ...)
141+{
142+ return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
143+}
144+
145+int
146+print(char *fmt, ...)
147+{
148+ char buf[PRINTSIZE];
149+ int n;
150+
151+ if(consputs == 0)
152+ return 0;
153+ n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
154+ (*consputs)(buf, n);
155+ return n;
156+}
157+
158+void
159+panic(char *fmt, ...)
160+{
161+ char buf[PRINTSIZE];
162+ int n;
163+
164+ if(consputs){
165+ (*consputs)("panic: ", 7);
166+ n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
167+ (*consputs)(buf, n);
168+ (*consputs)("\n", 1);
169+ }
170+ spllo();
171+ for(;;)
172+ idle();
173+}
os/boot/mpc/cpm.c+162−0
@@ -0,0 +1,162 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+enum {
9+ BDSIZE= 1024, /* TO DO: check this */
10+};
11+
12+static Map bdmapv[BDSIZE/sizeof(BD)];
13+static RMap bdmap = {"buffer descriptors"};
14+
15+void
16+cpminit(void)
17+{
18+ IMM *io;
19+
20+ io = m->iomem;
21+ io->sdcr = 1;
22+ io->lccr &= ~1; /* disable LCD */
23+ io->pcint = 0; /* disable all port C interrupts */
24+ io->pcso = 0;
25+ io->pcdir =0;
26+ io->pcpar = 0;
27+ io->pcdat = 0;
28+ io->papar = 0;
29+ io->padir = 0;
30+ io->paodr = 0;
31+ io->padat = 0;
32+ io->pbpar = 0;
33+ io->pbdir = 0;
34+ io->pbodr = 0;
35+ io->pbdat = 0;
36+ eieio();
37+
38+ for(io->cpcr = 0x8001; io->cpcr & 1;) /* reset all CPM channels */
39+ eieio();
40+
41+ mapinit(&bdmap, bdmapv, sizeof(bdmapv));
42+ mapfree(&bdmap, DPBASE, BDSIZE);
43+}
44+
45+void
46+cpmop(int op, int cno, int param)
47+{
48+ IMM *io;
49+ int s;
50+
51+ s = splhi();
52+ io = m->iomem;
53+ eieio();
54+ while(io->cpcr & 1)
55+ eieio();
56+ io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1;
57+ eieio();
58+ while(io->cpcr & 1)
59+ eieio();
60+ splx(s);
61+}
62+
63+/*
64+ * connect SCCx clocks in NSMI mode (x=1 for USB)
65+ */
66+void
67+sccnmsi(int x, int rcs, int tcs)
68+{
69+ IMM *io;
70+ ulong v;
71+ int sh;
72+
73+ sh = (x-1)*8; /* each SCCx field in sicr is 8 bits */
74+ v = (((rcs&7)<<3) | (tcs&7)) << sh;
75+ io = ioplock();
76+ io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
77+ iopunlock();
78+}
79+
80+void
81+scc2stop(void)
82+{
83+ SCC *scc;
84+
85+ scc = IOREGS(0xA20, SCC);
86+ if(scc->gsmrl & (3<<4)){
87+ cpmop(GracefulStopTx, SCC2ID, 0);
88+ cpmop(CloseRxBD, SCC2ID, 0);
89+ delay(1);
90+ scc->gsmrl &= ~(3<<4); /* disable current use */
91+ archetherdisable(SCC2ID);
92+ }
93+}
94+
95+BD *
96+bdalloc(int n)
97+{
98+ ulong a;
99+
100+ a = mapalloc(&bdmap, 0, n*sizeof(BD), 0);
101+ if(a == 0)
102+ panic("bdalloc");
103+ return KADDR(a);
104+}
105+
106+void
107+bdfree(BD *b, int n)
108+{
109+ if(b){
110+ eieio();
111+ mapfree(&bdmap, PADDR(b), n*sizeof(BD));
112+ }
113+}
114+
115+/*
116+ * initialise receive and transmit buffer rings.
117+ */
118+int
119+ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
120+{
121+ int i, x;
122+
123+ /* the ring entries must be aligned on sizeof(BD) boundaries */
124+ r->nrdre = nrdre;
125+ if(r->rdr == nil)
126+ r->rdr = bdalloc(nrdre);
127+ /* the buffer size must align with cache lines since the cache doesn't snoop */
128+ bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1);
129+ if(r->rrb == nil)
130+ r->rrb = malloc(nrdre*bufsize);
131+ if(r->rdr == nil || r->rrb == nil)
132+ return -1;
133+ dcflush(r->rrb, nrdre*bufsize);
134+ x = PADDR(r->rrb);
135+ for(i = 0; i < nrdre; i++){
136+ r->rdr[i].length = 0;
137+ r->rdr[i].addr = x;
138+ r->rdr[i].status = BDEmpty|BDInt;
139+ x += bufsize;
140+ }
141+ r->rdr[i-1].status |= BDWrap;
142+ r->rdrx = 0;
143+
144+ r->ntdre = ntdre;
145+ if(r->tdr == nil)
146+ r->tdr = bdalloc(ntdre);
147+ if(r->txb == nil)
148+ r->txb = malloc(ntdre*sizeof(Block*));
149+ if(r->tdr == nil || r->txb == nil)
150+ return -1;
151+ for(i = 0; i < ntdre; i++){
152+ r->txb[i] = nil;
153+ r->tdr[i].addr = 0;
154+ r->tdr[i].length = 0;
155+ r->tdr[i].status = 0;
156+ }
157+ r->tdr[i-1].status |= BDWrap;
158+ r->tdrh = 0;
159+ r->tdri = 0;
160+ r->ntq = 0;
161+ return 0;
162+}
os/boot/mpc/crc32.c+42−0
@@ -0,0 +1,42 @@
1+#include "boot.h"
2+
3+/*
4+ * from Rob Warnock
5+ */
6+static ulong crc32tab[256]; /* initialised on first call to crc32 */
7+
8+enum {
9+ CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
10+};
11+
12+/*
13+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
14+ */
15+static void
16+initcrc32(void)
17+{
18+ int i, j;
19+ ulong c;
20+
21+ for(i = 0; i < 256; i++) {
22+ for(c = i << 24, j = 8; j > 0; j--)
23+ if(c & (1<<31))
24+ c = (c<<1) ^ CRC32POLY;
25+ else
26+ c <<= 1;
27+ crc32tab[i] = c;
28+ }
29+}
30+
31+ulong
32+crc32(void *buf, int n, ulong crc)
33+{
34+ uchar *p;
35+
36+ if(crc32tab[1] == 0)
37+ initcrc32();
38+ crc = ~crc;
39+ for(p = buf; --n >= 0;)
40+ crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
41+ return ~crc;
42+}
os/boot/mpc/dat.h+217−0
@@ -0,0 +1,217 @@
1+typedef struct Alarm Alarm;
2+typedef struct Block Block;
3+typedef struct IMM IMM;
4+typedef struct Queue Queue;
5+
6+typedef struct List {
7+ void *next;
8+} List;
9+
10+typedef struct {
11+ int fake;
12+ int pri;
13+} Lock;
14+#define lock(x)
15+#define unlock(x)
16+
17+struct Alarm {
18+ List;
19+ int busy;
20+ long dt;
21+ void (*f)(Alarm*);
22+ void *arg;
23+};
24+
25+enum {
26+ Eaddrlen = 6,
27+ ETHERMINTU = 60, /* minimum transmit size */
28+ ETHERMAXTU = 1514, /* maximum transmit size */
29+ ETHERHDRSIZE = 14, /* size of an ethernet header */
30+
31+ MaxEther = 4,
32+};
33+
34+typedef struct {
35+ uchar d[Eaddrlen];
36+ uchar s[Eaddrlen];
37+ uchar type[2];
38+ uchar data[1500];
39+ uchar crc[4];
40+} Etherpkt;
41+
42+extern uchar broadcast[Eaddrlen];
43+
44+enum {
45+ Npart = 20+2, /* 8 sub partitions, disk, and partition */
46+ Maxxfer = 16*1024, /* maximum transfer size/cmd */
47+};
48+
49+typedef struct {
50+ ulong start;
51+ ulong end;
52+ char name[NAMELEN+1];
53+} Partition;
54+
55+typedef struct {
56+ int online;
57+ int npart; /* number of real partitions */
58+ Partition p[Npart];
59+ ulong offset;
60+ Partition *current; /* current partition */
61+
62+ ulong cap; /* total bytes */
63+ int bytes; /* bytes/sector */
64+ int sectors; /* sectors/track */
65+ int heads; /* heads/cyl */
66+ long cyl; /* cylinders/drive */
67+
68+ char lba; /* true if drive has logical block addressing */
69+ char multi; /* non-zero if drive does multiple block xfers */
70+} Disc;
71+
72+enum {
73+ ScsiTestunit = 0x00,
74+ ScsiExtsens = 0x03,
75+ ScsiInquiry = 0x12,
76+ ScsiModesense = 0x1a,
77+ ScsiStartunit = 0x1B,
78+ ScsiStopunit = 0x1B,
79+ ScsiGetcap = 0x25,
80+ ScsiRead = 0x08,
81+ ScsiWrite = 0x0a,
82+ ScsiExtread = 0x28,
83+ ScsiExtwrite = 0x2a,
84+
85+ /* data direction */
86+ ScsiIn = 1,
87+ ScsiOut = 0,
88+};
89+
90+typedef struct Scsibuf Scsibuf;
91+typedef struct Scsibuf {
92+ void* virt;
93+ void* phys;
94+ Scsibuf* next;
95+};
96+
97+typedef struct Scsidata {
98+ uchar* base;
99+ uchar* lim;
100+ uchar* ptr;
101+} Scsidata;
102+
103+typedef struct Ureg Ureg;
104+
105+typedef struct Scsi {
106+ ulong pid;
107+ ushort target;
108+ ushort lun;
109+ ushort rflag;
110+ ushort status;
111+ Scsidata cmd;
112+ Scsidata data;
113+ Scsibuf* b;
114+ uchar* save;
115+ uchar cmdblk[16];
116+} Scsi;
117+
118+typedef struct Segdesc {
119+ ulong d0;
120+ ulong d1;
121+} Segdesc;
122+
123+typedef struct Mach {
124+ ulong ticks; /* of the clock since boot time */
125+ ulong delayloop;
126+ long cpuhz; /* general system clock (cycles) */
127+ long clockgen; /* clock generator frequency (cycles) */
128+ ulong cpupvr; /* cpu type in processor version register */
129+ ulong cputype; /* cpu variant in BCD (eg, 0x823xx) */
130+ void* alarm; /* alarms bound to this clock */
131+ ulong* bcsr;
132+ IMM* iomem;
133+} Mach;
134+
135+/* Mach.cputype */
136+#define MPCREV(x) ((x) & 0xFF)
137+#define MPCMODEL(x) (((x)>>8) & 0xFFF)
138+#define MPCFAMILY(x) (((x)>>24) & 0x0F)
139+
140+
141+extern Mach *m;
142+
143+#define Q_MAGIC ((((4*21)+0)*21)+7)
144+
145+typedef struct Exec Exec;
146+struct Exec
147+{
148+ uchar magic[4]; /* magic number */
149+ uchar text[4]; /* size of text segment */
150+ uchar data[4]; /* size of initialized data */
151+ uchar bss[4]; /* size of uninitialized data */
152+ uchar syms[4]; /* size of symbol table */
153+ uchar entry[4]; /* entry point */
154+ uchar spsz[4]; /* size of sp/pc offset table */
155+ uchar pcsz[4]; /* size of pc/line number table */
156+};
157+
158+/*
159+ * bootline passed by boot program
160+ */
161+#define BOOTLINE ((char *)0x200000-150)
162+
163+/*
164+ * Where we leave configuration info.
165+ */
166+#define BOOTARGS ((char*)(0x200000))
167+#define BOOTARGSLEN 1024
168+#define MAXCONF 32
169+
170+/*
171+ * a parsed plan9.ini line
172+ */
173+#define ISAOPTLEN 16
174+#define NISAOPT 8
175+
176+typedef struct ISAConf {
177+ char type[NAMELEN];
178+ ulong port;
179+ ulong irq;
180+ ulong mem;
181+ ulong size;
182+ uchar ea[6];
183+
184+ int nopt;
185+ char opt[NISAOPT][ISAOPTLEN];
186+} ISAConf;
187+
188+typedef struct {
189+ int size;
190+ ulong addr;
191+} Map;
192+
193+typedef struct {
194+ char* name;
195+ Map* map;
196+ Map* mapend;
197+
198+ Lock;
199+} RMap;
200+
201+typedef struct PCIcfg PCIcfg;
202+
203+extern uchar* vgamem;
204+
205+struct Block {
206+ uchar *rp;
207+ uchar *wp;
208+ uchar *lim;
209+ uchar *data;
210+ Block* next;
211+ ulong magic;
212+};
213+#define BLEN(b) ((b)->wp-(b)->rp)
214+
215+typedef struct QLock {
216+ int dummy;
217+} QLock;
os/boot/mpc/defont0.c+216−0
@@ -0,0 +1,216 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <libg.h>
4+#include <gnot.h>
5+
6+
7+
8+static ulong bits0[] = {
9+ 0x907070f0, 0xf0f07000, 0xf0888888, 0xf8707070, 0xe0e0e0e0, 0xe09070f0, 0x70f870f0, 0xf870f088,
10+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
11+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000e0,
13+ 0xd0808080, 0x80808800, 0x8888c888, 0x80888888, 0x90909090, 0x90d08080, 0x80808080, 0x80888888,
14+ 0x00000000, 0x08000000, 0x0c300000, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
15+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000003c, 0xc03c0000,
16+ 0x00006000, 0x06001e00, 0x60181860, 0x78000000, 0x00000000, 0x00000000, 0x0000001c, 0x18380090,
17+ 0xb06060e0, 0xe0e0f800, 0xf088a888, 0x80808080, 0x90909090, 0x90b060e0, 0x808060e0, 0x80808888,
18+ 0x00182428, 0x3e707018, 0x18180000, 0x00000006, 0x3c183c3c, 0x1c3e3c7e, 0x3c3c0000, 0x0200403c,
19+ 0x3c187c1e, 0x787e7e1e, 0x663c7c66, 0x6066623c, 0x7c3c7c3c, 0x7e6266c2, 0x66667e30, 0xc00c1000,
20+ 0x08006000, 0x06003000, 0x60181860, 0x18000000, 0x00000000, 0x10000000, 0x00000030, 0x180c0090,
21+ 0x90101080, 0x80808818, 0x88f8a888, 0xe0807070, 0xe0e0e0e0, 0xe0901080, 0x70e01080, 0xe098f088,
22+ 0x00182428, 0x6adad818, 0x18181000, 0x0000000c, 0x66386666, 0x2c3e667e, 0x66660000, 0x06006066,
23+ 0x42186632, 0x6c606032, 0x66181864, 0x60667224, 0x66246666, 0x186262da, 0x62620630, 0x600c3800,
24+ 0x10006000, 0x06003000, 0x60000060, 0x18000000, 0x00000000, 0x30000000, 0x00000030, 0x180c00e0,
25+ 0x00e0e0f0, 0xf0f00018, 0x88889850, 0x80880808, 0x201c1c1c, 0x1c00e0f0, 0x0080e0f0, 0x80888888,
26+ 0x00182428, 0x68dad808, 0x300c5418, 0x0000000c, 0x66580606, 0x2c206002, 0x66661818, 0x0cfe3006,
27+ 0x9e2c6660, 0x66606060, 0x6618186c, 0x60667266, 0x66666660, 0x186262da, 0x36660c30, 0x600c2800,
28+ 0x103c6c3c, 0x3e3c7e3e, 0x6c787866, 0x18d46c3c, 0x6c3e763c, 0x7e6666c2, 0x66667e18, 0x18180000,
29+ 0x44180000, 0x18241c24, 0xf0888820, 0x8070f0f0, 0x20202020, 0x201c243e, 0x1cf8241c, 0x80708870,
30+ 0x0018247c, 0x78745008, 0x300c3818, 0x00000018, 0x66180606, 0x4c206006, 0x76661818, 0x18fe180c,
31+ 0xb62c6660, 0x66606060, 0x66181868, 0x607e5a66, 0x66666470, 0x186266da, 0x34340c30, 0x300c6c00,
32+ 0x18667666, 0x66663066, 0x76181864, 0x18fe7666, 0x76663666, 0x306662da, 0x62620608, 0x1810323c,
33+ 0x44247c7c, 0x24342042, 0x00000000, 0x00000000, 0x20202020, 0x20222408, 0x22002420, 0x00000000,
34+ 0x00180028, 0x3c287610, 0x300cee7e, 0x00fe0018, 0x66180c18, 0x4c3c7c0c, 0x3c3e0000, 0x30000c18,
35+ 0xb62c7c60, 0x667c7c6e, 0x7e181878, 0x605a5a66, 0x6466783c, 0x186234da, 0x18341830, 0x300c4400,
36+ 0x18066660, 0x66663066, 0x66181868, 0x18d66666, 0x66663860, 0x306662da, 0x34620c30, 0x180c5a20,
37+ 0x44241010, 0x242c2042, 0x0e3e103e, 0x3e3c1c3e, 0x3c1c1c1c, 0x1c3e1c08, 0x3e222418, 0x0e0e0e0e,
38+ 0x0008007c, 0x1e5cdc00, 0x300c387e, 0x00fe0030, 0x66181806, 0x7e066618, 0x6e060000, 0x18001818,
39+ 0xb67e6660, 0x66606066, 0x6618186c, 0x605a4e66, 0x78666c0e, 0x1862346c, 0x2c183030, 0x180c4400,
40+ 0x003e6660, 0x667e3066, 0x66181878, 0x18d66666, 0x6666303c, 0x306634da, 0x18341808, 0x18104c38,
41+ 0x3c181010, 0x18241c42, 0x11081008, 0x20222208, 0x00000000, 0x00220408, 0x22361804, 0x11111111,
42+ 0x00000028, 0x16b6cc00, 0x300c5418, 0x00000030, 0x66183006, 0x7e066618, 0x66060000, 0x0cfe3000,
43+ 0x9a466660, 0x66606066, 0x6618186c, 0x605a4e66, 0x60666606, 0x1862346c, 0x6c183030, 0x180c0000,
44+ 0x00666660, 0x66603066, 0x6618186c, 0x18d66666, 0x66663006, 0x3066346c, 0x2c343018, 0x18180020,
45+ 0x00091010, 0x000e0942, 0x10081008, 0x20222208, 0x0f06060f, 0x0a09041e, 0x002a0e38, 0x10101010,
46+ 0x00180028, 0x56b6cc00, 0x300c1018, 0x18001860, 0x66187e66, 0x0c666630, 0x66661818, 0x06fe6018,
47+ 0x40466632, 0x6c606036, 0x66181866, 0x605a4624, 0x60246666, 0x1834186c, 0x46186030, 0x0c0c0000,
48+ 0x006e6666, 0x6e66306e, 0x66181866, 0x18d66666, 0x666e3066, 0x306e186c, 0x46186030, 0x180c003c,
49+ 0x08090909, 0x1f110aff, 0x0e081008, 0x382c2208, 0x08020901, 0x0a0a0911, 0x09220907, 0x0e0e0e0e,
50+ 0x00180028, 0x7c1c7600, 0x18180000, 0x18001860, 0x3c7e7e3c, 0x0c3c3c30, 0x3c3c1818, 0x02004018,
51+ 0x3e467c1e, 0x787e601e, 0x663c1866, 0x7e42463c, 0x603c663c, 0x1818186c, 0x66187e30, 0x0c0c0000,
52+ 0x00367c3c, 0x363c7c36, 0x667e1866, 0x7ed6663c, 0x7c367c3c, 0x1e36186c, 0x66187e30, 0x180c0008,
53+ 0x080f0606, 0x04110c18, 0x01081008, 0x20222208, 0x0e020203, 0x0a0c0d1e, 0x0d220e08, 0x01010101,
54+ 0x00000000, 0x10000000, 0x18180000, 0x080000c0, 0x00000000, 0x00000000, 0x00000008, 0x00000000,
55+ 0x00000000, 0x00000000, 0x00001800, 0x00000000, 0x000c0000, 0x00000000, 0x00000030, 0x060c00fe,
56+ 0x00000000, 0x00000006, 0x00001800, 0x00000000, 0x60060000, 0x00000000, 0x0010001c, 0x18380008,
57+ 0x08090606, 0x040e0a18, 0x11081f08, 0x20221c3e, 0x08020401, 0x0f0a0b11, 0x0b220908, 0x11111111,
58+ 0x00000000, 0x00000000, 0x0c300000, 0x080000c0, 0x00000000, 0x00000000, 0x00000008, 0x00000000,
59+ 0x00000000, 0x00000000, 0x00007000, 0x00000000, 0x00060000, 0x00000000, 0x0000003c, 0x063c0000,
60+ 0x00000000, 0x00000066, 0x00001800, 0x00000000, 0x60060000, 0x00000000, 0x00300000, 0x00000008,
61+ 0x0f090909, 0x04030900, 0x0e000000, 0x00000000, 0x0f0f0f0f, 0x0209091e, 0x09000f07, 0x0e0e0e0e,
62+ 0x00000000, 0x00000000, 0x00000000, 0x10000000, 0x00000000, 0x00000000, 0x00000010, 0x00000000,
63+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
64+ 0x00000000, 0x0000003c, 0x00007000, 0x00000000, 0x60060000, 0x00000000, 0x00600000, 0x0000000f,
65+
66+};
67+
68+static GBitmap strike0 = {
69+ bits0,
70+ 0,
71+ 32,
72+ 0,
73+ {0, 0, 1024, 14},
74+ {0, 0, 1024, 14},
75+};
76+
77+static Fontchar info0[] = {
78+ { 0, 0, 14, 0, 8 },
79+ { 8, 0, 14, 0, 8 },
80+ { 16, 0, 14, 0, 8 },
81+ { 24, 0, 14, 0, 8 },
82+ { 32, 0, 14, 0, 8 },
83+ { 40, 0, 14, 0, 8 },
84+ { 48, 0, 14, 0, 8 },
85+ { 56, 0, 14, 0, 8 },
86+ { 64, 0, 14, 0, 8 },
87+ { 72, 0, 14, 0, 8 },
88+ { 80, 0, 14, 0, 8 },
89+ { 88, 0, 14, 0, 8 },
90+ { 96, 0, 14, 0, 8 },
91+ { 104, 0, 14, 0, 8 },
92+ { 112, 0, 14, 0, 8 },
93+ { 120, 0, 14, 0, 8 },
94+ { 128, 0, 14, 0, 8 },
95+ { 136, 0, 14, 0, 8 },
96+ { 144, 0, 14, 0, 8 },
97+ { 152, 0, 14, 0, 8 },
98+ { 160, 0, 14, 0, 8 },
99+ { 168, 0, 14, 0, 8 },
100+ { 176, 0, 14, 0, 8 },
101+ { 184, 0, 14, 0, 8 },
102+ { 192, 0, 14, 0, 8 },
103+ { 200, 0, 14, 0, 8 },
104+ { 208, 0, 14, 0, 8 },
105+ { 216, 0, 14, 0, 8 },
106+ { 224, 0, 14, 0, 8 },
107+ { 232, 0, 14, 0, 8 },
108+ { 240, 0, 14, 0, 8 },
109+ { 248, 0, 14, 0, 8 },
110+ { 256, 0, 0, 0, 8 },
111+ { 264, 2, 11, 0, 8 },
112+ { 272, 2, 6, 0, 8 },
113+ { 280, 2, 11, 0, 8 },
114+ { 288, 1, 12, 0, 8 },
115+ { 296, 2, 11, 0, 8 },
116+ { 304, 2, 11, 0, 8 },
117+ { 312, 2, 7, 0, 8 },
118+ { 320, 1, 13, 0, 8 },
119+ { 328, 1, 13, 0, 8 },
120+ { 336, 3, 10, 0, 8 },
121+ { 344, 4, 10, 0, 8 },
122+ { 352, 9, 14, 0, 8 },
123+ { 360, 6, 8, 0, 8 },
124+ { 368, 9, 11, 0, 8 },
125+ { 376, 1, 13, 0, 8 },
126+ { 384, 2, 11, 0, 8 },
127+ { 392, 2, 11, 0, 8 },
128+ { 400, 2, 11, 0, 8 },
129+ { 408, 2, 11, 0, 8 },
130+ { 416, 2, 11, 0, 8 },
131+ { 424, 2, 11, 0, 8 },
132+ { 432, 2, 11, 0, 8 },
133+ { 440, 2, 11, 0, 8 },
134+ { 448, 2, 11, 0, 8 },
135+ { 456, 2, 11, 0, 8 },
136+ { 464, 4, 11, 0, 8 },
137+ { 472, 4, 14, 0, 8 },
138+ { 480, 2, 11, 0, 8 },
139+ { 488, 4, 10, 0, 8 },
140+ { 496, 2, 11, 0, 8 },
141+ { 504, 2, 11, 0, 8 },
142+ { 512, 2, 11, 0, 8 },
143+ { 520, 2, 11, 0, 8 },
144+ { 528, 2, 11, 0, 8 },
145+ { 536, 2, 11, 0, 8 },
146+ { 544, 2, 11, 0, 8 },
147+ { 552, 2, 11, 0, 8 },
148+ { 560, 2, 11, 0, 8 },
149+ { 568, 2, 11, 0, 8 },
150+ { 576, 2, 11, 0, 8 },
151+ { 584, 2, 11, 0, 8 },
152+ { 592, 2, 13, 0, 8 },
153+ { 600, 2, 11, 0, 8 },
154+ { 608, 2, 11, 0, 8 },
155+ { 616, 2, 11, 0, 8 },
156+ { 624, 2, 11, 0, 8 },
157+ { 632, 2, 11, 0, 8 },
158+ { 640, 2, 11, 0, 8 },
159+ { 648, 2, 13, 0, 8 },
160+ { 656, 2, 11, 0, 8 },
161+ { 664, 2, 11, 0, 8 },
162+ { 672, 2, 11, 0, 8 },
163+ { 680, 2, 11, 0, 8 },
164+ { 688, 2, 11, 0, 8 },
165+ { 696, 2, 11, 0, 8 },
166+ { 704, 2, 11, 0, 8 },
167+ { 712, 2, 11, 0, 8 },
168+ { 720, 2, 11, 0, 8 },
169+ { 728, 1, 13, 0, 8 },
170+ { 736, 1, 13, 0, 8 },
171+ { 744, 1, 13, 0, 8 },
172+ { 752, 2, 8, 0, 8 },
173+ { 760, 11, 12, 0, 8 },
174+ { 768, 2, 7, 0, 8 },
175+ { 776, 4, 11, 0, 8 },
176+ { 784, 1, 11, 0, 8 },
177+ { 792, 4, 11, 0, 8 },
178+ { 800, 1, 11, 0, 8 },
179+ { 808, 4, 11, 0, 8 },
180+ { 816, 1, 11, 0, 8 },
181+ { 824, 4, 14, 0, 8 },
182+ { 832, 1, 11, 0, 8 },
183+ { 840, 1, 11, 0, 8 },
184+ { 848, 1, 14, 0, 8 },
185+ { 856, 1, 11, 0, 8 },
186+ { 864, 1, 11, 0, 8 },
187+ { 872, 4, 11, 0, 8 },
188+ { 880, 4, 11, 0, 8 },
189+ { 888, 4, 11, 0, 8 },
190+ { 896, 4, 14, 0, 8 },
191+ { 904, 4, 14, 0, 8 },
192+ { 912, 4, 11, 0, 8 },
193+ { 920, 4, 11, 0, 8 },
194+ { 928, 2, 11, 0, 8 },
195+ { 936, 4, 11, 0, 8 },
196+ { 944, 4, 11, 0, 8 },
197+ { 952, 4, 11, 0, 8 },
198+ { 960, 4, 11, 0, 8 },
199+ { 968, 4, 14, 0, 8 },
200+ { 976, 4, 11, 0, 8 },
201+ { 984, 1, 12, 0, 8 },
202+ { 992, 1, 12, 0, 8 },
203+ { 1000, 1, 12, 0, 8 },
204+ { 1008, 5, 8, 0, 8 },
205+ { 1016, 0, 14, 0, 8 },
206+ { 1024, 0, 14, 0, 8 },
207+ { 0, 0, 0, 0, 0 }
208+};
209+
210+GSubfont defont0 = {
211+ 129,
212+ 14,
213+ 2,
214+ info0,
215+ &strike0,
216+};
os/boot/mpc/devether.c+157−0
@@ -0,0 +1,157 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+#include "etherif.h"
9+
10+static Ctlr ether[MaxEther];
11+
12+static struct {
13+ char *type;
14+ int (*reset)(Ctlr*);
15+} cards[] = {
16+ { "SCC", sccethreset, },
17+ { "SCC2", sccethreset, },
18+ { 0, }
19+};
20+
21+int
22+etherinit(void)
23+{
24+ Ctlr *ctlr;
25+ int ctlrno, i, mask, n;
26+
27+ mask = 0;
28+ for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
29+ ctlr = &ether[ctlrno];
30+ memset(ctlr, 0, sizeof(Ctlr));
31+ if(isaconfig("ether", ctlrno, &ctlr->card) == 0)
32+ continue;
33+ for(n = 0; cards[n].type; n++){
34+ if(strcmp(cards[n].type, ctlr->card.type))
35+ continue;
36+ ctlr->ctlrno = ctlrno;
37+ if((*cards[n].reset)(ctlr))
38+ break;
39+
40+ ctlr->iq = qopen(16*1024, 1, 0, 0);
41+ ctlr->oq = qopen(16*1024, 1, 0, 0);
42+
43+ ctlr->present = 1;
44+ mask |= 1<<ctlrno;
45+
46+ print("ether%d: %s: port 0x%luX irq %d",
47+ ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
48+ if(ctlr->card.mem)
49+ print(" addr 0x%luX", PADDR(ctlr->card.mem));
50+ if(ctlr->card.size)
51+ print(" size 0x%luX", ctlr->card.size);
52+ print(":");
53+ for(i = 0; i < sizeof(ctlr->card.ea); i++)
54+ print(" %2.2uX", ctlr->card.ea[i]);
55+ print("\n"); uartwait();
56+ setvec(VectorPIC + ctlr->card.irq, ctlr->card.intr, ctlr);
57+ break;
58+ }
59+ }
60+
61+ return mask;
62+}
63+
64+static Ctlr*
65+attach(int ctlrno)
66+{
67+ Ctlr *ctlr;
68+
69+ if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
70+ return 0;
71+
72+ ctlr = &ether[ctlrno];
73+ if(ctlr->present == 1){
74+ ctlr->present = 2;
75+ (*ctlr->card.attach)(ctlr);
76+ }
77+
78+ return ctlr;
79+}
80+
81+uchar*
82+etheraddr(int ctlrno)
83+{
84+ Ctlr *ctlr;
85+
86+ if((ctlr = attach(ctlrno)) == 0)
87+ return 0;
88+
89+ return ctlr->card.ea;
90+}
91+
92+int
93+etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
94+{
95+ int n;
96+ Ctlr *ctlr;
97+ Block *b;
98+ ulong start;
99+
100+ if((ctlr = attach(ctlrno)) == 0)
101+ return 0;
102+
103+ start = m->ticks;
104+ while((b = qget(ctlr->iq)) == 0){
105+ if(TK2MS(m->ticks - start) >= timo){
106+ /*
107+ print("ether%d: rx timeout\n", ctlrno);
108+ */
109+ return 0;
110+ }
111+ }
112+
113+ n = BLEN(b);
114+ memmove(pkt, b->rp, n);
115+ freeb(b);
116+
117+ return n;
118+}
119+
120+int
121+etheriq(Ctlr *ctlr, Block *b, int freebp)
122+{
123+ if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0 &&
124+ memcmp(((Etherpkt*)b->rp)->d, broadcast, Eaddrlen) != 0){
125+ if(freebp)
126+ freeb(b);
127+ return 0;
128+ }
129+ qbwrite(ctlr->iq, b);
130+ return 1;
131+}
132+
133+int
134+ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
135+{
136+ Ctlr *ctlr;
137+ Block *b;
138+ int s;
139+
140+ if((ctlr = attach(ctlrno)) == 0)
141+ return 0;
142+
143+ if(qlen(ctlr->oq) > 16*1024){
144+ print("ether%d: tx queue full\n", ctlrno);
145+ return 0;
146+ }
147+ b = iallocb(sizeof(Etherpkt));
148+ memmove(b->wp, pkt, len);
149+ memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
150+ b->wp += len;
151+ qbwrite(ctlr->oq, b);
152+ s = splhi();
153+ (*ctlr->card.transmit)(ctlr);
154+ splx(s);
155+
156+ return 1;
157+}
os/boot/mpc/devuart.c+230−0
@@ -0,0 +1,230 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+/*
9+ * SMC1 in UART mode
10+ */
11+
12+typedef struct Uartsmc Uartsmc;
13+struct Uartsmc {
14+ IOCparam;
15+ ushort maxidl;
16+ ushort idlc;
17+ ushort brkln;
18+ ushort brkec;
19+ ushort brkcr;
20+ ushort rmask;
21+};
22+
23+typedef struct Uart Uart;
24+struct Uart
25+{
26+ int port;
27+ int setup;
28+ uchar txbusy;
29+
30+ Queue* iq;
31+ Queue* oq;
32+ void (*rx)(Queue*, int);
33+ void (*boot)(uchar*, int);
34+
35+ ulong frame;
36+ ulong overrun;
37+ uchar rxbuf[128];
38+ char txbuf[16];
39+ BD* rxb;
40+ BD* txb;
41+};
42+
43+Uart uart[1];
44+int predawn = 1;
45+
46+static void uartintr(Ureg*, void*);
47+static void uartkick(void*);
48+
49+static int
50+baudgen(int baud)
51+{
52+ int d;
53+
54+ d = ((m->cpuhz/baud)+8)>>4;
55+ if(d >= (1<<12))
56+ return ((d+15)>>3)|1;
57+ return d<<1;
58+}
59+
60+static void
61+smcsetup(Uart *up, int baud)
62+{
63+ IMM *io;
64+ Uartsmc *p;
65+ BD *bd;
66+ SMC *smc;
67+
68+ archenableuart(SMC1ID, 0);
69+ io = m->iomem;
70+ io->pbpar |= IBIT(24)|IBIT(25); /* enable SMC1 TX/RX */
71+ io->pbdir &= ~(IBIT(24)|IBIT(25));
72+ io->brgc1 = baudgen(baud) | BaudEnable;
73+ io->simode &= ~0xF000; /* SMC1 to NMSI mode, Tx/Rx clocks are BRG1 */
74+
75+ bd = bdalloc(1);
76+ p = (Uartsmc*)KADDR(SMC1P);
77+ p->rbase = (ushort)bd;
78+ up->rxb = bd;
79+ bd->status = BDEmpty|BDWrap|BDInt;
80+ bd->length = 0;
81+ bd->addr = PADDR(up->rxbuf);
82+ bd = bdalloc(1);
83+ p->tbase = (ushort)bd;
84+ up->txb = bd;
85+ bd->status = BDWrap|BDInt;
86+ bd->length = 0;
87+ bd->addr = PADDR(up->txbuf);
88+
89+ cpmop(InitRxTx, SMC1ID, 0);
90+
91+ /* protocol parameters */
92+ p->rfcr = 0x18;
93+ p->tfcr = 0x18;
94+ p->mrblr = 1;
95+ p->maxidl = 1;
96+ p->brkln = 0;
97+ p->brkec = 0;
98+ p->brkcr = 1;
99+ smc = IOREGS(0xA80, SMC);
100+ smc->smce = 0xff; /* clear events */
101+ smc->smcm = 0x17; /* enable all possible interrupts */
102+ setvec(VectorCPIC+4, uartintr, up);
103+ smc->smcmr = 0x4820; /* 8-bit mode, no parity, 1 stop bit, UART mode, ... */
104+ smc->smcmr |= 3; /* enable rx/tx */
105+}
106+
107+static void
108+uartintr(Ureg*, void *arg)
109+{
110+ Uart *up;
111+ int ch, i;
112+ BD *bd;
113+ SMC *smc;
114+ Block *b;
115+
116+ up = arg;
117+ smc = IOREGS(0xA80, SMC);
118+ smc->smce = 0xff; /* clear all events */
119+ if((bd = up->rxb) != nil && (bd->status & BDEmpty) == 0){
120+ if(up->iq != nil && bd->length > 0){
121+ if(up->boot != nil){
122+ up->boot(up->rxbuf, bd->length);
123+ }else if(up->rx != nil){
124+ for(i=0; i<bd->length; i++){
125+ ch = up->rxbuf[i];
126+ up->rx(up->iq, ch);
127+ }
128+ }else{
129+ b = iallocb(bd->length);
130+ memmove(b->wp, up->rxbuf, bd->length);
131+ b->wp += bd->length;
132+ qbwrite(up->iq, b);
133+ }
134+ }
135+ bd->status |= BDEmpty|BDInt;
136+ } else if((bd = up->txb) != nil && (bd->status & BDReady) == 0){
137+ ch = -1;
138+ if(up->oq)
139+ ch = qbgetc(up->oq);
140+ if(ch != -1){
141+ up->txbuf[0] = ch;
142+ bd->length = 1;
143+ bd->status |= BDReady;
144+ }else
145+ up->txbusy = 0;
146+ }
147+ /* TO DO: modem status, errors, etc */
148+}
149+
150+static void
151+uartkick(void *arg)
152+{
153+ Uart *up = arg;
154+ int s, c, i;
155+
156+ s = splhi();
157+ while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1){
158+ if(predawn){
159+ while(up->txb->status & BDReady)
160+ ;
161+ } else {
162+ for(i = 0; i < 100; i++){
163+ if((up->txb->status & BDReady) == 0)
164+ break;
165+ delay(1);
166+ }
167+ }
168+ up->txbuf[0] = c;
169+ up->txb->length = 1;
170+ up->txb->status |= BDReady;
171+ up->txbusy = !predawn;
172+ }
173+ splx(s);
174+}
175+
176+void
177+uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue*,int))
178+{
179+ Uart *up = &uart[0];
180+
181+ if(up->setup)
182+ return;
183+ up->setup = 1;
184+
185+ *iq = up->iq = qopen(4*1024, 0, 0, 0);
186+ *oq = up->oq = qopen(16*1024, 0, uartkick, up);
187+ up->rx = rx;
188+ USED(port);
189+ up->port = SMC1ID;
190+ if(baud == 0)
191+ baud = 9600;
192+ smcsetup(up, baud);
193+ /* if using SCCn's UART, would also set DTR and RTS, but SMC doesn't use them */
194+}
195+
196+void
197+uartsetboot(void (*f)(uchar*, int))
198+{
199+ uart[0].boot = f;
200+}
201+
202+void
203+uartputs(char *s, int n)
204+{
205+ Uart *up = &uart[0];
206+ Block *b;
207+ int nl;
208+ char *p;
209+
210+ nl = 0;
211+ for(p = s; p < s+n; p++)
212+ if(*p == '\n')
213+ nl++;
214+ b = iallocb(n+nl);
215+ while(n--){
216+ if(*s == '\n')
217+ *b->wp++ = '\r';
218+ *b->wp++ = *s++;
219+ }
220+ qbwrite(up->oq, b);
221+}
222+
223+void
224+uartwait(void)
225+{
226+ Uart *up = &uart[0];
227+
228+ while(up->txbusy)
229+ ;
230+}
os/boot/mpc/dload.c+103−0
@@ -0,0 +1,103 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <mach.h>
5+
6+static char *kernelfile = "/power/ipaq";
7+ulong crc32(void *buf, int n, ulong crc);
8+
9+void
10+main(int argc, char **argv)
11+{
12+ int ifd, n;
13+ char buf[64], reply[1];
14+ int i, execsize;
15+ Fhdr f;
16+ ulong csum;
17+
18+ ARGBEGIN{
19+ }ARGEND
20+ ifd = open(kernelfile, OREAD);
21+ if(ifd < 0){
22+ fprint(2, "dload: can't open %s: %r\n", kernelfile);
23+ exits("open");
24+ }
25+ i = 0;
26+ if(crackhdr(ifd, &f) == 0){
27+ fprint(2, "dload: not an executable file: %r\n");
28+ exits("format");
29+ }
30+ if(f.magic != Q_MAGIC){
31+ fprint(2, "dload: not a powerpc executable\n");
32+ exits("format");
33+ }
34+ execsize = f.txtsz + f.datsz + f.txtoff;
35+ seek(ifd, 0, 0);
36+ csum = ~0;
37+ while(execsize > 0 && (n = read(ifd, buf, sizeof(buf))) > 0){
38+ if(n > execsize)
39+ n = execsize;
40+ for(;;){
41+ if(write(1, buf, sizeof(buf)) != sizeof(buf)){ /* always writes full buffer */
42+ fprint(2, "dload: write error: %r\n");
43+ exits("write");
44+ }
45+ if(read(0, reply, 1) != 1){
46+ fprint(2, "dload: bad reply\n");
47+ exits("read");
48+ }
49+ if(reply[0] != 'n')
50+ break;
51+ fprint(2, "!");
52+ }
53+ if(reply[0] != 'y'){
54+ fprint(2, "dload: bad ack: %c\n", reply[0]);
55+ exits("reply");
56+ }
57+ if(++i%10 == 0)
58+ fprint(2, ".");
59+ execsize -= n;
60+ }
61+ exits(0);
62+}
63+
64+/*
65+ * from Rob Warnock
66+ */
67+static ulong crc32tab[256]; /* initialised on first call to crc32 */
68+
69+enum {
70+ CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
71+};
72+
73+/*
74+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
75+ */
76+static void
77+initcrc32(void)
78+{
79+ int i, j;
80+ ulong c;
81+
82+ for(i = 0; i < 256; i++) {
83+ for(c = i << 24, j = 8; j > 0; j--)
84+ if(c & (1<<31))
85+ c = (c<<1) ^ CRC32POLY;
86+ else
87+ c <<= 1;
88+ crc32tab[i] = c;
89+ }
90+}
91+
92+ulong
93+crc32(void *buf, int n, ulong crc)
94+{
95+ uchar *p;
96+
97+ if(crc32tab[1] == 0)
98+ initcrc32();
99+ crc = ~crc;
100+ for(p = buf; --n >= 0;)
101+ crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
102+ return ~crc;
103+}
os/boot/mpc/donprint.c+332−0
@@ -0,0 +1,332 @@
1+#include "u.h"
2+#include "lib.h"
3+
4+#define PTR sizeof(char*)
5+#define SHORT sizeof(int)
6+#define INT sizeof(int)
7+#define LONG sizeof(long)
8+#define IDIGIT 30
9+#define MAXCON 30
10+
11+#define FLONG (1<<0)
12+#define FSHORT (1<<1)
13+#define FUNSIGN (1<<2)
14+
15+typedef struct Op Op;
16+struct Op
17+{
18+ char *p;
19+ char *ep;
20+ void *argp;
21+ int f1;
22+ int f2;
23+ int f3;
24+};
25+
26+static int noconv(Op*);
27+static int cconv(Op*);
28+static int dconv(Op*);
29+static int hconv(Op*);
30+static int lconv(Op*);
31+static int oconv(Op*);
32+static int sconv(Op*);
33+static int uconv(Op*);
34+static int xconv(Op*);
35+static int Xconv(Op*);
36+static int percent(Op*);
37+
38+static
39+int (*fmtconv[MAXCON])(Op*) =
40+{
41+ noconv,
42+ cconv, dconv, hconv, lconv,
43+ oconv, sconv, uconv, xconv,
44+ Xconv, percent,
45+};
46+static
47+char fmtindex[128] =
48+{
49+ ['c'] 1,
50+ ['d'] 2,
51+ ['h'] 3,
52+ ['l'] 4,
53+ ['o'] 5,
54+ ['s'] 6,
55+ ['u'] 7,
56+ ['x'] 8,
57+ ['X'] 9,
58+ ['%'] 10,
59+};
60+
61+static int convcount = { 11 };
62+static int ucase;
63+
64+static void
65+PUT(Op *o, int c)
66+{
67+ static int pos;
68+ int opos;
69+
70+ if(c == '\t'){
71+ opos = pos;
72+ pos = (opos+8) & ~7;
73+ while(opos++ < pos && o->p < o->ep)
74+ *o->p++ = ' ';
75+ return;
76+ }
77+ if(o->p < o->ep){
78+ *o->p++ = c;
79+ pos++;
80+ }
81+ if(c == '\n')
82+ pos = 0;
83+}
84+
85+int
86+fmtinstall(char c, int (*f)(Op*))
87+{
88+
89+ c &= 0177;
90+ if(fmtindex[c] == 0) {
91+ if(convcount >= MAXCON)
92+ return 1;
93+ fmtindex[c] = convcount++;
94+ }
95+ fmtconv[fmtindex[c]] = f;
96+ return 0;
97+}
98+
99+char*
100+donprint(char *p, char *ep, char *fmt, void *argp)
101+{
102+ int sf1, c;
103+ Op o;
104+
105+ o.p = p;
106+ o.ep = ep;
107+ o.argp = argp;
108+
109+loop:
110+ c = *fmt++;
111+ if(c != '%') {
112+ if(c == 0) {
113+ if(o.p < o.ep)
114+ *o.p = 0;
115+ return o.p;
116+ }
117+ PUT(&o, c);
118+ goto loop;
119+ }
120+ o.f1 = 0;
121+ o.f2 = -1;
122+ o.f3 = 0;
123+ c = *fmt++;
124+ sf1 = 0;
125+ if(c == '-') {
126+ sf1 = 1;
127+ c = *fmt++;
128+ }
129+ while(c >= '0' && c <= '9') {
130+ o.f1 = o.f1*10 + c-'0';
131+ c = *fmt++;
132+ }
133+ if(sf1)
134+ o.f1 = -o.f1;
135+ if(c != '.')
136+ goto l1;
137+ c = *fmt++;
138+ while(c >= '0' && c <= '9') {
139+ if(o.f2 < 0)
140+ o.f2 = 0;
141+ o.f2 = o.f2*10 + c-'0';
142+ c = *fmt++;
143+ }
144+l1:
145+ if(c == 0)
146+ fmt--;
147+ c = (*fmtconv[fmtindex[c&0177]])(&o);
148+ if(c < 0) {
149+ o.f3 |= -c;
150+ c = *fmt++;
151+ goto l1;
152+ }
153+ o.argp = (char*)o.argp + c;
154+ goto loop;
155+}
156+
157+void
158+strconv(char *o, Op *op, int f1, int f2)
159+{
160+ int n, c;
161+ char *p;
162+
163+ n = strlen(o);
164+ if(f1 >= 0)
165+ while(n < f1) {
166+ PUT(op, ' ');
167+ n++;
168+ }
169+ for(p=o; c = *p++;)
170+ if(f2 != 0) {
171+ PUT(op, c);
172+ f2--;
173+ }
174+ if(f1 < 0) {
175+ f1 = -f1;
176+ while(n < f1) {
177+ PUT(op, ' ');
178+ n++;
179+ }
180+ }
181+}
182+
183+int
184+numbconv(Op *op, int base)
185+{
186+ char b[IDIGIT];
187+ int i, f, n, r;
188+ long v;
189+ short h;
190+
191+ f = 0;
192+ switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
193+ case FLONG:
194+ v = *(long*)op->argp;
195+ r = LONG;
196+ break;
197+
198+ case FUNSIGN|FLONG:
199+ v = *(ulong*)op->argp;
200+ r = LONG;
201+ break;
202+
203+ case FSHORT:
204+ h = *(int*)op->argp;
205+ v = h;
206+ r = SHORT;
207+ break;
208+
209+ case FUNSIGN|FSHORT:
210+ h = *(int*)op->argp;
211+ v = (ushort)h;
212+ r = SHORT;
213+ break;
214+
215+ default:
216+ v = *(int*)op->argp;
217+ r = INT;
218+ break;
219+
220+ case FUNSIGN:
221+ v = *(unsigned*)op->argp;
222+ r = INT;
223+ break;
224+ }
225+ if(!(op->f3 & FUNSIGN) && v < 0) {
226+ v = -v;
227+ f = 1;
228+ }
229+ b[IDIGIT-1] = 0;
230+ for(i = IDIGIT-2;; i--) {
231+ n = (ulong)v % base;
232+ n += '0';
233+ if(n > '9'){
234+ n += 'a' - ('9'+1);
235+ if(ucase)
236+ n += 'A'-'a';
237+ }
238+ b[i] = n;
239+ if(i < 2)
240+ break;
241+ v = (ulong)v / base;
242+ if(op->f2 >= 0 && i >= IDIGIT-op->f2)
243+ continue;
244+ if(v <= 0)
245+ break;
246+ }
247+ if(f)
248+ b[--i] = '-';
249+ strconv(b+i, op, op->f1, -1);
250+ return r;
251+}
252+
253+static int
254+noconv(Op *op)
255+{
256+
257+ strconv("***", op, 0, -1);
258+ return 0;
259+}
260+
261+static int
262+cconv(Op *op)
263+{
264+ char b[2];
265+
266+ b[0] = *(int*)op->argp;
267+ b[1] = 0;
268+ strconv(b, op, op->f1, -1);
269+ return INT;
270+}
271+
272+static int
273+dconv(Op *op)
274+{
275+ return numbconv(op, 10);
276+}
277+
278+static int
279+hconv(Op*)
280+{
281+ return -FSHORT;
282+}
283+
284+static int
285+lconv(Op*)
286+{
287+ return -FLONG;
288+}
289+
290+static int
291+oconv(Op *op)
292+{
293+ return numbconv(op, 8);
294+}
295+
296+static int
297+sconv(Op *op)
298+{
299+ strconv(*(char**)op->argp, op, op->f1, op->f2);
300+ return PTR;
301+}
302+
303+static int
304+uconv(Op*)
305+{
306+ return -FUNSIGN;
307+}
308+
309+static int
310+xconv(Op *op)
311+{
312+ return numbconv(op, 16);
313+}
314+
315+static int
316+Xconv(Op *op)
317+{
318+ int r;
319+
320+ ucase = 1;
321+ r = numbconv(op, 16);
322+ ucase = 0;
323+ return r;
324+}
325+
326+static int
327+percent(Op *op)
328+{
329+
330+ PUT(op, '%');
331+ return 0;
332+}
os/boot/mpc/dosboot.c+614−0
@@ -0,0 +1,614 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "dosfs.h"
7+
8+extern char *premature;
9+
10+/*
11+ * predeclared
12+ */
13+static void bootdump(Dosboot*);
14+static void setname(Dosfile*, char*);
15+long dosreadseg(Dosfile*, long, long);
16+
17+/*
18+ * debugging
19+ */
20+#define chatty 1
21+#define chat if(chatty)print
22+
23+/*
24+ * block io buffers
25+ */
26+enum
27+{
28+ Nbio= 16,
29+};
30+typedef struct Clustbuf Clustbuf;
31+struct Clustbuf
32+{
33+ int age;
34+ long sector;
35+ uchar *iobuf;
36+ Dos *dos;
37+ int size;
38+};
39+Clustbuf bio[Nbio];
40+
41+/*
42+ * get an io block from an io buffer
43+ */
44+Clustbuf*
45+getclust(Dos *dos, long sector)
46+{
47+ Clustbuf *p, *oldest;
48+ int size;
49+
50+ chat("getclust @ %d\n", sector);
51+
52+ /*
53+ * if we have it, just return it
54+ */
55+ for(p = bio; p < &bio[Nbio]; p++){
56+ if(sector == p->sector && dos == p->dos){
57+ p->age = m->ticks;
58+ chat("getclust %d in cache\n", sector);
59+ return p;
60+ }
61+ }
62+
63+ /*
64+ * otherwise, reuse the oldest entry
65+ */
66+ oldest = bio;
67+ for(p = &bio[1]; p < &bio[Nbio]; p++){
68+ if(p->age <= oldest->age)
69+ oldest = p;
70+ }
71+ p = oldest;
72+
73+ /*
74+ * make sure the buffer is big enough
75+ */
76+ size = dos->clustsize*dos->sectsize;
77+ if(p->iobuf==0 || p->size < size)
78+ p->iobuf = ialloc(size, 0);
79+ p->size = size;
80+
81+ /*
82+ * read in the cluster
83+ */
84+ chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
85+ if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
86+ chat("can't seek block\n");
87+ return 0;
88+ }
89+ if((*dos->read)(dos->dev, p->iobuf, size) != size){
90+ chat("can't read block\n");
91+ return 0;
92+ }
93+
94+ p->age = m->ticks;
95+ p->dos = dos;
96+ p->sector = sector;
97+ chat("getclust %d read\n", sector);
98+ return p;
99+}
100+
101+/*
102+ * walk the fat one level ( n is a current cluster number ).
103+ * return the new cluster number or -1 if no more.
104+ */
105+static long
106+fatwalk(Dos *dos, int n)
107+{
108+ ulong k, sect;
109+ Clustbuf *p;
110+ int o;
111+
112+ chat("fatwalk %d\n", n);
113+
114+ if(n < 2 || n >= dos->fatclusters)
115+ return -1;
116+
117+ switch(dos->fatbits){
118+ case 12:
119+ k = (3*n)/2; break;
120+ case 16:
121+ k = 2*n; break;
122+ default:
123+ return -1;
124+ }
125+ if(k >= dos->fatsize*dos->sectsize)
126+ panic("getfat");
127+
128+ sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
129+ o = k%(dos->sectsize*dos->clustsize);
130+ p = getclust(dos, sect);
131+ k = p->iobuf[o++];
132+ if(o >= dos->sectsize*dos->clustsize){
133+ p = getclust(dos, sect+dos->clustsize);
134+ o = 0;
135+ }
136+ k |= p->iobuf[o]<<8;
137+ if(dos->fatbits == 12){
138+ if(n&1)
139+ k >>= 4;
140+ else
141+ k &= 0xfff;
142+ if(k >= 0xff8)
143+ k |= 0xf000;
144+ }
145+ k = k < 0xfff8 ? k : -1;
146+ chat("fatwalk %d -> %d\n", n, k);
147+ return k;
148+}
149+
150+/*
151+ * map a file's logical cluster address to a physical sector address
152+ */
153+static long
154+fileaddr(Dosfile *fp, long ltarget)
155+{
156+ Dos *dos = fp->dos;
157+ long l;
158+ long p;
159+
160+ chat("fileaddr %8.8s %d\n", fp->name, ltarget);
161+ /*
162+ * root directory is contiguous and easy
163+ */
164+ if(fp->pstart == 0){
165+ if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
166+ return -1;
167+ l = dos->rootaddr + ltarget*dos->clustsize;
168+ chat("fileaddr %d -> %d\n", ltarget, l);
169+ return l;
170+ }
171+
172+ /*
173+ * anything else requires a walk through the fat
174+ */
175+ if(ltarget >= fp->lcurrent && fp->pcurrent){
176+ /* start at the currrent point */
177+ l = fp->lcurrent;
178+ p = fp->pcurrent;
179+ } else {
180+ /* go back to the beginning */
181+ l = 0;
182+ p = fp->pstart;
183+ }
184+ while(l != ltarget){
185+ /* walk the fat */
186+ p = fatwalk(dos, p);
187+ if(p < 0)
188+ return -1;
189+ l++;
190+ }
191+ fp->lcurrent = l;
192+ fp->pcurrent = p;
193+
194+ /*
195+ * clusters start at 2 instead of 0 (why? - presotto)
196+ */
197+ l = dos->dataaddr + (p-2)*dos->clustsize;
198+ chat("fileaddr %d -> %d\n", ltarget, l);
199+ return l;
200+}
201+
202+/*
203+ * read from a dos file
204+ */
205+long
206+dosread(Dosfile *fp, void *a, long n)
207+{
208+ long addr;
209+ long rv;
210+ int i;
211+ int off;
212+ Clustbuf *p;
213+ uchar *from, *to;
214+
215+ if((fp->attr & DDIR) == 0){
216+ if(fp->offset >= fp->length)
217+ return 0;
218+ if(fp->offset+n > fp->length)
219+ n = fp->length - fp->offset;
220+ }
221+
222+ to = a;
223+ for(rv = 0; rv < n; rv+=i){
224+ /*
225+ * read the cluster
226+ */
227+ addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
228+ if(addr < 0)
229+ return -1;
230+ p = getclust(fp->dos, addr);
231+ if(p == 0)
232+ return -1;
233+
234+ /*
235+ * copy the bytes we need
236+ */
237+ off = fp->offset % fp->dos->clustbytes;
238+ from = &p->iobuf[off];
239+ i = n - rv;
240+ if(i > fp->dos->clustbytes - off)
241+ i = fp->dos->clustbytes - off;
242+ memmove(to, from, i);
243+ to += i;
244+ fp->offset += i;
245+ }
246+
247+ return rv;
248+}
249+
250+/*
251+ * walk a directory returns
252+ * -1 if something went wrong
253+ * 0 if not found
254+ * 1 if found
255+ */
256+int
257+doswalk(Dosfile *file, char *name)
258+{
259+ Dosdir d;
260+ long n;
261+
262+ if((file->attr & DDIR) == 0){
263+ chat("walking non-directory!\n");
264+ return -1;
265+ }
266+
267+ setname(file, name);
268+
269+ file->offset = 0; /* start at the beginning */
270+ while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
271+ chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
272+ if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
273+ continue;
274+ if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
275+ continue;
276+ if(d.attr & DVLABEL){
277+ chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
278+ continue;
279+ }
280+ file->attr = d.attr;
281+ file->pstart = GSHORT(d.start);
282+ file->length = GLONG(d.length);
283+ file->pcurrent = 0;
284+ file->lcurrent = 0;
285+ file->offset = 0;
286+ return 1;
287+ }
288+ return n >= 0 ? 0 : -1;
289+}
290+
291+
292+/*
293+ * instructions that boot blocks can start with
294+ */
295+#define JMPSHORT 0xeb
296+#define JMPNEAR 0xe9
297+
298+/*
299+ * read dos file system properties
300+ */
301+int
302+dosinit(Dos *dos, int start, int ishard)
303+{
304+ Dosboot *b;
305+ int i;
306+ Clustbuf *p;
307+ Dospart *dp;
308+ ulong mbroffset, offset;
309+
310+ /* defaults till we know better */
311+ dos->start = start;
312+ dos->sectsize = 512;
313+ dos->clustsize = 1;
314+ mbroffset = 0;
315+
316+dmddo:
317+ /* get first sector */
318+ p = getclust(dos, mbroffset);
319+ if(p == 0){
320+ chat("can't read boot block\n");
321+ return -1;
322+ }
323+
324+ /*
325+ * If it's a hard disc then look for an MBR and pick either an
326+ * active partition or the FAT with the lowest starting LBA.
327+ * Things are tricky because we could be pointing to, amongst others:
328+ * 1) a floppy BPB;
329+ * 2) a hard disc MBR;
330+ * 3) a hard disc extended partition table;
331+ * 4) a logical drive on a hard disc;
332+ * 5) a disc-manager boot block.
333+ * They all have the same magic at the end of the block.
334+ */
335+ if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
336+ chat("not DOS\n");
337+ return -1;
338+ }
339+ p->dos = 0;
340+ b = (Dosboot *)p->iobuf;
341+ if(ishard && b->mediadesc != 0xF8){
342+ dp = (Dospart*)&p->iobuf[0x1BE];
343+ offset = 0xFFFFFFFF;
344+ for(i = 0; i < 4; i++, dp++){
345+ if(dp->type == DMDDO){
346+ mbroffset = 63;
347+ goto dmddo;
348+ }
349+ if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
350+ continue;
351+ if(dp->flag & 0x80){
352+ offset = GLONG(dp->start);
353+ break;
354+ }
355+ if(GLONG(dp->start) < offset)
356+ offset = GLONG(dp->start);
357+ }
358+ if(i != 4 || offset != 0xFFFFFFFF){
359+ dos->start = mbroffset+offset;
360+ p = getclust(dos, 0);
361+ if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
362+ return -1;
363+ }
364+ p->dos = 0;
365+ }
366+
367+ b = (Dosboot *)p->iobuf;
368+ if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
369+ chat("no dos file system\n");
370+ return -1;
371+ }
372+
373+ if(chatty)
374+ bootdump(b);
375+
376+ /*
377+ * determine the systems' wondersous properties
378+ */
379+ dos->sectsize = GSHORT(b->sectsize);
380+ dos->clustsize = b->clustsize;
381+ dos->clustbytes = dos->sectsize*dos->clustsize;
382+ dos->nresrv = GSHORT(b->nresrv);
383+ dos->nfats = b->nfats;
384+ dos->rootsize = GSHORT(b->rootsize);
385+ dos->volsize = GSHORT(b->volsize);
386+ if(dos->volsize == 0)
387+ dos->volsize = GLONG(b->bigvolsize);
388+ dos->mediadesc = b->mediadesc;
389+ dos->fatsize = GSHORT(b->fatsize);
390+ dos->fataddr = dos->nresrv;
391+ dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
392+ i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
393+ i = i/dos->sectsize;
394+ dos->dataaddr = dos->rootaddr + i;
395+ dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
396+ if(dos->fatclusters < 4087)
397+ dos->fatbits = 12;
398+ else
399+ dos->fatbits = 16;
400+ dos->freeptr = 2;
401+
402+ /*
403+ * set up the root
404+ */
405+ dos->root.dos = dos;
406+ dos->root.pstart = 0;
407+ dos->root.pcurrent = dos->root.lcurrent = 0;
408+ dos->root.offset = 0;
409+ dos->root.attr = DDIR;
410+ dos->root.length = dos->rootsize*sizeof(Dosdir);
411+
412+ return 0;
413+}
414+
415+static void
416+bootdump(Dosboot *b)
417+{
418+ if(chatty == 0)
419+ return;
420+ print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
421+ b->magic[0], b->magic[1], b->magic[2]);
422+ print("version: \"%8.8s\"\n", b->version);
423+ print("sectsize: %d\n", GSHORT(b->sectsize));
424+ print("allocsize: %d\n", b->clustsize);
425+ print("nresrv: %d\n", GSHORT(b->nresrv));
426+ print("nfats: %d\n", b->nfats);
427+ print("rootsize: %d\n", GSHORT(b->rootsize));
428+ print("volsize: %d\n", GSHORT(b->volsize));
429+ print("mediadesc: 0x%2.2x\n", b->mediadesc);
430+ print("fatsize: %d\n", GSHORT(b->fatsize));
431+ print("trksize: %d\n", GSHORT(b->trksize));
432+ print("nheads: %d\n", GSHORT(b->nheads));
433+ print("nhidden: %d\n", GLONG(b->nhidden));
434+ print("bigvolsize: %d\n", GLONG(b->bigvolsize));
435+ print("driveno: %d\n", b->driveno);
436+ print("reserved0: 0x%2.2x\n", b->reserved0);
437+ print("bootsig: 0x%2.2x\n", b->bootsig);
438+ print("volid: 0x%8.8x\n", GLONG(b->volid));
439+ print("label: \"%11.11s\"\n", b->label);
440+}
441+
442+/*
443+ * grab next element from a path, return the pointer to unprocessed portion of
444+ * path.
445+ */
446+static char *
447+nextelem(char *path, char *elem)
448+{
449+ int i;
450+
451+ while(*path == '/')
452+ path++;
453+ if(*path==0 || *path==' ')
454+ return 0;
455+ for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
456+ if(i==28){
457+ print("name component too long\n");
458+ return 0;
459+ }
460+ *elem++ = *path++;
461+ }
462+ *elem = '\0';
463+ return path;
464+}
465+
466+int
467+dosstat(Dos *dos, char *path, Dosfile *f)
468+{
469+ char element[NAMELEN];
470+
471+ *f = dos->root;
472+ while(path = nextelem(path, element)){
473+ switch(doswalk(f, element)){
474+ case -1:
475+ return -1;
476+ case 0:
477+ return 0;
478+ }
479+ }
480+ return 1;
481+}
482+
483+/*
484+ * boot
485+ */
486+int
487+dosboot(Dos *dos, char *path)
488+{
489+ Dosfile file;
490+ long n;
491+ long addr;
492+ Exec *ep;
493+ void (*b)(void);
494+
495+ switch(dosstat(dos, path, &file)){
496+
497+ case -1:
498+ print("error walking to %s\n", path);
499+ return -1;
500+ case 0:
501+ print("%s not found\n", path);
502+ return -1;
503+ case 1:
504+ print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
505+ file.ext, file.attr, file.pstart, file.length);
506+ break;
507+ }
508+
509+ /*
510+ * read header
511+ */
512+ ep = (Exec*)ialloc(sizeof(Exec), 0);
513+ n = sizeof(Exec);
514+ if(dosreadseg(&file, n, (ulong) ep) != n){
515+ print(premature);
516+ return -1;
517+ }
518+ if(GLLONG(ep->magic) != Q_MAGIC){
519+ print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
520+ return -1;
521+ }
522+
523+ /*
524+ * read text
525+ */
526+ addr = PADDR(GLLONG(ep->entry));
527+ n = GLLONG(ep->text);
528+ print("+%d", n);
529+ if(dosreadseg(&file, n, addr) != n){
530+ print(premature);
531+ return -1;
532+ }
533+
534+ /*
535+ * read data (starts at first page after kernel)
536+ */
537+ addr = PGROUND(addr+n);
538+ n = GLLONG(ep->data);
539+ print("+%d", n);
540+ if(dosreadseg(&file, n, addr) != n){
541+ print(premature);
542+ return -1;
543+ }
544+
545+ /*
546+ * bss and entry point
547+ */
548+ print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
549+
550+ /*
551+ * Go to new code. It's up to the program to get its PC relocated to
552+ * the right place.
553+ */
554+ b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
555+ (*b)();
556+ return 0;
557+}
558+
559+/*
560+ * read in a segment
561+ */
562+long
563+dosreadseg(Dosfile *fp, long len, long addr)
564+{
565+ char *a;
566+ long n, sofar;
567+
568+ a = (char *)addr;
569+ for(sofar = 0; sofar < len; sofar += n){
570+ n = 8*1024;
571+ if(len - sofar < n)
572+ n = len - sofar;
573+ n = dosread(fp, a + sofar, n);
574+ if(n <= 0)
575+ break;
576+ print(".");
577+ }
578+ return sofar;
579+}
580+
581+/*
582+ * set up a dos file name
583+ */
584+static void
585+setname(Dosfile *fp, char *from)
586+{
587+ char *to;
588+
589+ to = fp->name;
590+ for(; *from && to-fp->name < 8; from++, to++){
591+ if(*from == '.'){
592+ from++;
593+ break;
594+ }
595+ if(*from >= 'a' && *from <= 'z')
596+ *to = *from + 'A' - 'a';
597+ else
598+ *to = *from;
599+ }
600+ while(to - fp->name < 8)
601+ *to++ = ' ';
602+
603+ to = fp->ext;
604+ for(; *from && to-fp->ext < 3; from++, to++){
605+ if(*from >= 'a' && *from <= 'z')
606+ *to = *from + 'A' - 'a';
607+ else
608+ *to = *from;
609+ }
610+ while(to-fp->ext < 3)
611+ *to++ = ' ';
612+
613+ chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
614+}
os/boot/mpc/dosfs.h+110−0
@@ -0,0 +1,110 @@
1+typedef struct Dosboot Dosboot;
2+typedef struct Dos Dos;
3+typedef struct Dosdir Dosdir;
4+typedef struct Dosfile Dosfile;
5+typedef struct Dospart Dospart;
6+
7+struct Dospart
8+{
9+ uchar flag; /* active flag */
10+ uchar shead; /* starting head */
11+ uchar scs[2]; /* starting cylinder/sector */
12+ uchar type; /* partition type */
13+ uchar ehead; /* ending head */
14+ uchar ecs[2]; /* ending cylinder/sector */
15+ uchar start[4]; /* starting sector */
16+ uchar len[4]; /* length in sectors */
17+};
18+
19+#define FAT12 0x01
20+#define FAT16 0x04
21+#define FATHUGE 0x06
22+#define DMDDO 0x54
23+
24+struct Dosboot{
25+ uchar magic[3];
26+ uchar version[8];
27+ uchar sectsize[2];
28+ uchar clustsize;
29+ uchar nresrv[2];
30+ uchar nfats;
31+ uchar rootsize[2];
32+ uchar volsize[2];
33+ uchar mediadesc;
34+ uchar fatsize[2];
35+ uchar trksize[2];
36+ uchar nheads[2];
37+ uchar nhidden[4];
38+ uchar bigvolsize[4];
39+ uchar driveno;
40+ uchar reserved0;
41+ uchar bootsig;
42+ uchar volid[4];
43+ uchar label[11];
44+ uchar reserved1[8];
45+};
46+
47+struct Dosfile{
48+ Dos *dos; /* owning dos file system */
49+ char name[8];
50+ char ext[3];
51+ uchar attr;
52+ long length;
53+ long pstart; /* physical start cluster address */
54+ long pcurrent; /* physical current cluster address */
55+ long lcurrent; /* logical current cluster address */
56+ long offset;
57+};
58+
59+struct Dos{
60+ int dev; /* device id */
61+ long (*read)(int, void*, long); /* read routine */
62+ long (*seek)(int, long); /* seek routine */
63+
64+ int start; /* start of file system */
65+ int sectsize; /* in bytes */
66+ int clustsize; /* in sectors */
67+ int clustbytes; /* in bytes */
68+ int nresrv; /* sectors */
69+ int nfats; /* usually 2 */
70+ int rootsize; /* number of entries */
71+ int volsize; /* in sectors */
72+ int mediadesc;
73+ int fatsize; /* in sectors */
74+ int fatclusters;
75+ int fatbits; /* 12 or 16 */
76+ long fataddr; /* sector number */
77+ long rootaddr;
78+ long dataaddr;
79+ long freeptr;
80+
81+ Dosfile root;
82+};
83+
84+struct Dosdir{
85+ uchar name[8];
86+ uchar ext[3];
87+ uchar attr;
88+ uchar reserved[10];
89+ uchar time[2];
90+ uchar date[2];
91+ uchar start[2];
92+ uchar length[4];
93+};
94+
95+#define DRONLY 0x01
96+#define DHIDDEN 0x02
97+#define DSYSTEM 0x04
98+#define DVLABEL 0x08
99+#define DDIR 0x10
100+#define DARCH 0x20
101+
102+extern int chatty;
103+
104+extern int dosboot(Dos*, char*);
105+extern int dosinit(Dos*, int, int);
106+extern long dosread(Dosfile*, void*, long);
107+extern int dosstat(Dos*, char*, Dosfile*);
108+extern int doswalk(Dosfile*, char*);
109+
110+extern int plan9ini(Dos*, char*);
os/boot/mpc/etherif.h+59−0
@@ -0,0 +1,59 @@
1+/*
2+ * All the goo for PC ethernet cards.
3+ */
4+typedef struct Card Card;
5+typedef struct Type Type;
6+typedef struct Ctlr Ctlr;
7+
8+/*
9+ * Hardware interface.
10+ */
11+struct Card {
12+ ISAConf;
13+
14+ int (*reset)(Ctlr*);
15+ void (*attach)(Ctlr*);
16+
17+ void *(*read)(Ctlr*, void*, ulong, ulong);
18+ void *(*write)(Ctlr*, ulong, void*, ulong);
19+
20+ void (*receive)(Ctlr*);
21+ void (*transmit)(Ctlr*);
22+ void (*intr)(Ureg*, void*);
23+ void (*overflow)(Ctlr*);
24+
25+ uchar bit16; /* true if a 16 bit interface */
26+ uchar ram; /* true if card has shared memory */
27+
28+ ulong dp8390; /* I/O address of 8390 (if any) */
29+ ulong data; /* I/O data port if no shared memory */
30+ uchar nxtpkt; /* software bndry */
31+ uchar tstart; /* 8390 ring addresses */
32+ uchar pstart;
33+ uchar pstop;
34+
35+ uchar dummyrr; /* do dummy remote read */
36+};
37+
38+/*
39+ * Software controller.
40+ */
41+struct Ctlr {
42+ Card card; /* hardware info */
43+ int ctlrno;
44+ int present;
45+
46+ Queue* iq;
47+ Queue* oq;
48+
49+ int inpackets;
50+ int outpackets;
51+ int crcs; /* input crc errors */
52+ int oerrs; /* output errors */
53+ int frames; /* framing errors */
54+ int overflows; /* packet overflows */
55+ int buffs; /* buffering errors */
56+};
57+
58+extern int sccethreset(Ctlr*);
59+extern int etheriq(Ctlr*, Block*, int);
os/boot/mpc/etherscc.c+411−0
@@ -0,0 +1,411 @@
1+/*
2+ * SCCn ethernet
3+ */
4+
5+#include "u.h"
6+#include "lib.h"
7+#include "mem.h"
8+#include "dat.h"
9+#include "fns.h"
10+#include "io.h"
11+
12+#include "etherif.h"
13+
14+enum {
15+ Nrdre = 32, /* receive descriptor ring entries */
16+ Ntdre = 4, /* transmit descriptor ring entries */
17+
18+ Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
19+ Bufsize = (Rbsize+7)&~7, /* aligned */
20+};
21+
22+enum {
23+ /* ether-specific Rx BD bits */
24+ RxMiss= 1<<8,
25+ RxeLG= 1<<5,
26+ RxeNO= 1<<4,
27+ RxeSH= 1<<3,
28+ RxeCR= 1<<2,
29+ RxeOV= 1<<1,
30+ RxeCL= 1<<0,
31+ RxError= (RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL), /* various error flags */
32+
33+ /* ether-specific Tx BD bits */
34+ TxPad= 1<<14, /* pad short frames */
35+ TxTC= 1<<10, /* transmit CRC */
36+ TxeDEF= 1<<9,
37+ TxeHB= 1<<8,
38+ TxeLC= 1<<7,
39+ TxeRL= 1<<6,
40+ TxeUN= 1<<1,
41+ TxeCSL= 1<<0,
42+
43+ /* scce */
44+ RXB= 1<<0,
45+ TXB= 1<<1,
46+ BSY= 1<<2,
47+ RXF= 1<<3,
48+ TXE= 1<<4,
49+
50+ /* gsmrl */
51+ ENR= 1<<5,
52+ ENT= 1<<4,
53+
54+ /* port A */
55+ RXD1= SIBIT(15),
56+ TXD1= SIBIT(14),
57+
58+ /* port B */
59+ RTS1= IBIT(19),
60+
61+ /* port C */
62+ CTS1= SIBIT(11),
63+ CD1= SIBIT(10),
64+};
65+
66+typedef struct Etherparam Etherparam;
67+struct Etherparam {
68+ SCCparam;
69+ ulong c_pres; /* preset CRC */
70+ ulong c_mask; /* constant mask for CRC */
71+ ulong crcec; /* CRC error counter */
72+ ulong alec; /* alighnment error counter */
73+ ulong disfc; /* discard frame counter */
74+ ushort pads; /* short frame PAD characters */
75+ ushort ret_lim; /* retry limit threshold */
76+ ushort ret_cnt; /* retry limit counter */
77+ ushort mflr; /* maximum frame length reg */
78+ ushort minflr; /* minimum frame length reg */
79+ ushort maxd1; /* maximum DMA1 length reg */
80+ ushort maxd2; /* maximum DMA2 length reg */
81+ ushort maxd; /* rx max DMA */
82+ ushort dma_cnt; /* rx dma counter */
83+ ushort max_b; /* max bd byte count */
84+ ushort gaddr[4]; /* group address filter */
85+ ulong tbuf0_data0; /* save area 0 - current frm */
86+ ulong tbuf0_data1; /* save area 1 - current frm */
87+ ulong tbuf0_rba0;
88+ ulong tbuf0_crc;
89+ ushort tbuf0_bcnt;
90+ ushort paddr[3]; /* physical address LSB to MSB increasing */
91+ ushort p_per; /* persistence */
92+ ushort rfbd_ptr; /* rx first bd pointer */
93+ ushort tfbd_ptr; /* tx first bd pointer */
94+ ushort tlbd_ptr; /* tx last bd pointer */
95+ ulong tbuf1_data0; /* save area 0 - next frame */
96+ ulong tbuf1_data1; /* save area 1 - next frame */
97+ ulong tbuf1_rba0;
98+ ulong tbuf1_crc;
99+ ushort tbuf1_bcnt;
100+ ushort tx_len; /* tx frame length counter */
101+ ushort iaddr[4]; /* individual address filter*/
102+ ushort boff_cnt; /* back-off counter */
103+ ushort taddr[3]; /* temp address */
104+};
105+
106+typedef struct {
107+ SCC* scc;
108+ int port;
109+ int cpm;
110+
111+ BD* rdr; /* receive descriptor ring */
112+ void* rrb; /* receive ring buffers */
113+ int rdrx; /* index into rdr */
114+
115+ BD* tdr; /* transmit descriptor ring */
116+ void* trb; /* transmit ring buffers */
117+ int tdrx; /* index into tdr */
118+} Mot;
119+static Mot mot[MaxEther];
120+
121+static int sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID};
122+static int sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P};
123+static int sccreg[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60};
124+static int sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B};
125+
126+static void
127+attach(Ctlr *ctlr)
128+{
129+ mot[ctlr->ctlrno].scc->gsmrl |= ENR|ENT;
130+ eieio();
131+}
132+
133+static void
134+transmit(Ctlr *ctlr)
135+{
136+ int len;
137+ Mot *motp;
138+ Block *b;
139+ BD *tdre;
140+
141+ motp = &mot[ctlr->ctlrno];
142+ while(((tdre = &motp->tdr[motp->tdrx])->status & BDReady) == 0){
143+ b = qget(ctlr->oq);
144+ if(b == 0)
145+ break;
146+
147+ /*
148+ * Copy the packet to the transmit buffer.
149+ */
150+ len = BLEN(b);
151+ memmove(KADDR(tdre->addr), b->rp, len);
152+
153+ /*
154+ * Give ownership of the descriptor to the chip, increment the
155+ * software ring descriptor pointer and tell the chip to poll.
156+ */
157+ tdre->length = len;
158+ eieio();
159+ tdre->status = (tdre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
160+ eieio();
161+ motp->scc->todr = 1<<15; /* transmit now */
162+ eieio();
163+ motp->tdrx = NEXT(motp->tdrx, Ntdre);
164+
165+ freeb(b);
166+
167+ }
168+}
169+
170+static void
171+interrupt(Ureg*, void *ap)
172+{
173+ int len, events, status;
174+ Mot *motp;
175+ BD *rdre;
176+ Block *b;
177+ Ctlr *ctlr;
178+
179+ ctlr = ap;
180+ motp = &mot[ctlr->ctlrno];
181+
182+ /*
183+ * Acknowledge all interrupts and whine about those that shouldn't
184+ * happen.
185+ */
186+ events = motp->scc->scce;
187+ eieio();
188+ motp->scc->scce = events;
189+ eieio();
190+ if(events & (TXE|BSY|RXB))
191+ print("ETHER.SCC#%d: scce = 0x%uX\n", ctlr->ctlrno, events);
192+ //print(" %ux|", events);
193+ /*
194+ * Receiver interrupt: run round the descriptor ring logging
195+ * errors and passing valid receive data up to the higher levels
196+ * until we encounter a descriptor still owned by the chip.
197+ */
198+ if(events & (RXF|RXB) || 1){
199+ rdre = &motp->rdr[motp->rdrx];
200+ while(((status = rdre->status) & BDEmpty) == 0){
201+ if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
202+ //if(status & RxBuff)
203+ // ctlr->buffs++;
204+ if(status & (1<<2))
205+ ctlr->crcs++;
206+ if(status & (1<<1))
207+ ctlr->overflows++;
208+ //print("eth rx: %ux\n", status);
209+ if(status & RxError)
210+ print("~");
211+ else if((status & BDLast) == 0)
212+ print("@");
213+ }
214+ else{
215+ /*
216+ * We have a packet. Read it into the next
217+ * free ring buffer, if any.
218+ */
219+ len = rdre->length-4;
220+ if((b = iallocb(len)) != 0){
221+ memmove(b->wp, KADDR(rdre->addr), len);
222+ b->wp += len;
223+ etheriq(ctlr, b, 1);
224+ }
225+ }
226+
227+ /*
228+ * Finished with this descriptor, reinitialise it,
229+ * give it back to the chip, then on to the next...
230+ */
231+ rdre->length = 0;
232+ rdre->status = (rdre->status & BDWrap) | BDEmpty | BDInt;
233+ eieio();
234+
235+ motp->rdrx = NEXT(motp->rdrx, Nrdre);
236+ rdre = &motp->rdr[motp->rdrx];
237+ }
238+ }
239+
240+ /*
241+ * Transmitter interrupt: handle anything queued for a free descriptor.
242+ */
243+ if(events & TXB)
244+ transmit(ctlr);
245+ if(events & TXE)
246+ cpmop(RestartTx, motp->cpm, 0);
247+}
248+
249+static void
250+ringinit(Mot* motp)
251+{
252+ int i, x;
253+
254+ /*
255+ * Initialise the receive and transmit buffer rings. The ring
256+ * entries must be aligned on 16-byte boundaries.
257+ */
258+ if(motp->rdr == 0)
259+ motp->rdr = bdalloc(Nrdre);
260+ if(motp->rrb == 0)
261+ motp->rrb = ialloc(Nrdre*Bufsize, 0);
262+ x = PADDR(motp->rrb);
263+ for(i = 0; i < Nrdre; i++){
264+ motp->rdr[i].length = 0;
265+ motp->rdr[i].addr = x;
266+ motp->rdr[i].status = BDEmpty|BDInt;
267+ x += Bufsize;
268+ }
269+ motp->rdr[i-1].status |= BDWrap;
270+ motp->rdrx = 0;
271+
272+ if(motp->tdr == 0)
273+ motp->tdr = bdalloc(Ntdre);
274+ if(motp->trb == 0)
275+ motp->trb = ialloc(Ntdre*Bufsize, 0);
276+ x = PADDR(motp->trb);
277+ for(i = 0; i < Ntdre; i++){
278+ motp->tdr[i].addr = x;
279+ motp->tdr[i].length = 0;
280+ motp->tdr[i].status = TxPad|BDInt|BDLast|TxTC;
281+ x += Bufsize;
282+ }
283+ motp->tdr[i-1].status |= BDWrap;
284+ motp->tdrx = 0;
285+}
286+
287+/*
288+ * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence,
289+ * except that it sets the right bits for the MPC823ADS board when SCC2 is used,
290+ * and those for the 860/821 development board for SCC1.
291+ */
292+static void
293+sccsetup(Mot *ctlr, SCC *scc, uchar *ea)
294+{
295+ int i, rcs, tcs, w;
296+ Etherparam *p;
297+ IMM *io;
298+
299+
300+ i = 2*(ctlr->port-1);
301+ io = ioplock();
302+ w = (TXD1|RXD1)<<i; /* TXDn and RXDn in port A */
303+ io->papar |= w; /* enable TXDn and RXDn pins */
304+ io->padir &= ~w;
305+ io->paodr &= ~w; /* not open drain */
306+
307+ w = (CD1|CTS1)<<i; /* CLSN and RENA: CDn and CTSn in port C */
308+ io->pcpar &= ~w; /* enable CLSN (CTSn) and RENA (CDn) */
309+ io->pcdir &= ~w;
310+ io->pcso |= w;
311+ iopunlock();
312+
313+ /* clocks and transceiver control: details depend on the board's wiring */
314+ archetherenable(ctlr->cpm, &rcs, &tcs);
315+
316+ sccnmsi(ctlr->port, rcs, tcs); /* connect the clocks */
317+
318+ p = (Etherparam*)KADDR(sccparam[ctlr->port]);
319+ memset(p, 0, sizeof(*p));
320+ p->rfcr = 0x18;
321+ p->tfcr = 0x18;
322+ p->mrblr = Bufsize;
323+ p->rbase = PADDR(ctlr->rdr);
324+ p->tbase = PADDR(ctlr->tdr);
325+
326+ cpmop(InitRxTx, ctlr->cpm, 0);
327+
328+ p->c_pres = ~0;
329+ p->c_mask = 0xDEBB20E3;
330+ p->crcec = 0;
331+ p->alec = 0;
332+ p->disfc = 0;
333+ p->pads = 0x8888;
334+ p->ret_lim = 0xF;
335+ p->mflr = Rbsize;
336+ p->minflr = ETHERMINTU+4;
337+ p->maxd1 = Bufsize;
338+ p->maxd2 = Bufsize;
339+ p->p_per = 0; /* only moderate aggression */
340+
341+ for(i=0; i<Eaddrlen; i+=2)
342+ p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i]; /* it's not the obvious byte order */
343+
344+ scc->psmr = (2<<10)|(5<<1); /* 32-bit CRC, ignore 22 bits before SFD */
345+ scc->dsr = 0xd555;
346+ scc->gsmrh = 0; /* normal operation */
347+ scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC; /* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */
348+ eieio();
349+ scc->scce = ~0; /* clear all events */
350+ eieio();
351+ scc->sccm = TXE | RXF | TXB; /* enable interrupts */
352+ eieio();
353+
354+ io = ioplock();
355+ w = RTS1<<(ctlr->port-1); /* enable TENA pin (RTSn) */
356+ io->pbpar |= w;
357+ io->pbdir |= w;
358+ iopunlock();
359+
360+ /* gsmrl enable is deferred until attach */
361+}
362+
363+/*
364+ * Prepare the SCCx ethernet for booting.
365+ */
366+int
367+sccethreset(Ctlr* ctlr)
368+{
369+ uchar ea[Eaddrlen];
370+ Mot *motp;
371+ SCC *scc;
372+ char line[50], def[50];
373+
374+ /*
375+ * Since there's no EPROM, insist that the configuration entry
376+ * (see conf.c and flash.c) holds the Ethernet address.
377+ */
378+ memset(ea, 0, Eaddrlen);
379+ if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0){
380+ print("no preset Ether address\n");
381+ for(;;){
382+ strcpy(def, "00108bf12900"); /* valid MAC address to be used only for initial configuration */
383+ if(getstr("ether MAC address", line, sizeof(line), def) < 0)
384+ return -1;
385+ if(parseether(ctlr->card.ea, line) >= 0 || ctlr->card.ea[0] == 0xFF)
386+ break;
387+ print("invalid MAC address\n");
388+ }
389+ }
390+
391+ scc = IOREGS(sccreg[ctlr->card.port], SCC);
392+ ctlr->card.irq = VectorCPIC+sccirq[ctlr->card.port];
393+
394+ motp = &mot[ctlr->ctlrno];
395+ motp->scc = scc;
396+ motp->port = ctlr->card.port;
397+ motp->cpm = sccid[ctlr->card.port];
398+
399+ ringinit(motp);
400+
401+ sccsetup(motp, scc, ctlr->card.ea);
402+
403+ /* enable is deferred until attach */
404+
405+ ctlr->card.reset = sccethreset;
406+ ctlr->card.attach = attach;
407+ ctlr->card.transmit = transmit;
408+ ctlr->card.intr = interrupt;
409+
410+ return 0;
411+}
os/boot/mpc/fblt.c+531−0
@@ -0,0 +1,531 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <libg.h>
4+#include <gnot.h>
5+
6+/*
7+ * bitblt operates a 'word' at a time.
8+ * WBITS is the number of bits in a word
9+ * LWBITS=log2(WBITS),
10+ * W2L is the number of words in a long
11+ * WMASK has bits set for the low order word of a long
12+ * WType is a pointer to a word
13+ */
14+#ifndef WBITS
15+#define WBITS 32
16+#define LWBITS 5
17+#define W2L 1
18+#define WMASK ~0UL
19+typedef ulong *WType;
20+#endif
21+
22+#define DEBUG
23+
24+#ifdef TEST
25+/*
26+ * globals used for testing
27+ */
28+int FORCEFORW;
29+int FORCEBAKW;
30+GBitmap *curdm, *cursm;
31+Point curpt;
32+Rectangle curr;
33+Fcode curf;
34+void *mem;
35+#endif
36+
37+static void
38+gbitexplode(ulong sw, ulong *buf, int sdep, int x)
39+{
40+ int j, o, q, n, nw, inc, qinc;
41+ ulong s, dw, pix;
42+
43+ inc = 1 << sdep;
44+ pix = (1 << inc) - 1;
45+ nw = 1 << x;
46+ n = 32 >> x;
47+ qinc = (nw << sdep) - inc;
48+ for(o = 32 - n; o >= 0; o -= n){
49+ dw = 0;
50+ s = sw >> o;
51+ q = 0;
52+ for(j = 0; j < n; j += inc){
53+ dw |= (s & (pix << j)) << q;
54+ q += qinc;
55+ }
56+ for(j = 0; j < x; j++)
57+ dw |= dw << (inc << j);
58+ *buf++ = dw;
59+ }
60+}
61+
62+/*
63+void
64+main(void)
65+{
66+ ulong buf[128];
67+
68+ gbitexplode(0x7777, buf, 0, 3);
69+ exits(0);
70+}
71+*/
72+
73+void
74+gbitblt(GBitmap *dm, Point pt, GBitmap *sm, Rectangle r, Fcode fcode)
75+{
76+ int width; /* width in bits of dst */
77+ int wwidth; /* floor width in words */
78+ int height; /* height in pixels minus 1 */
79+ int sdep; /* src ldepth */
80+ int ddep; /* dst ldepth */
81+ int deltadep; /* diff between ldepths */
82+ int sspan; /* words between scanlines in src */
83+ int dspan; /* words between scanlines in dst */
84+ int soff; /* bit offset of src start point */
85+ int sdest; /* bit offset of src start point that matches doff when expanded */
86+ int doff; /* bit offset of dst start point */
87+ int delta; /* amount to shift src by */
88+ int sign; /* of delta */
89+ ulong *saddr;
90+ ulong *daddr;
91+ ulong *s;
92+ ulong *d;
93+ ulong mask;
94+ ulong tmp; /* temp storage source word */
95+ ulong sw; /* source word constructed */
96+ ulong dw; /* dest word fetched */
97+ ulong lmask; /* affected pixels in leftmost dst word */
98+ ulong rmask; /* affected pixels in rightmost dst word */
99+ int i;
100+ int j;
101+ ulong buf[32]; /* for expanding a source */
102+ ulong *p; /* pointer into buf */
103+ int spare; /* number of words already converted */
104+
105+
106+#ifdef TEST
107+ curdm = dm;
108+ cursm = sm;
109+ curpt = pt;
110+ curr = r;
111+ curf = fcode;
112+#endif
113+
114+ gbitbltclip(&dm);
115+
116+ width = r.max.x - r.min.x;
117+ if(width <= 0)
118+ return;
119+ height = r.max.y - r.min.y - 1;
120+ if(height < 0)
121+ return;
122+
123+ ddep = dm->ldepth;
124+ pt.x <<= ddep;
125+ width <<= ddep;
126+
127+ sdep = sm->ldepth;
128+ r.min.x <<= sdep;
129+ r.max.x <<= sdep;
130+
131+ dspan = dm->width * W2L;
132+ sspan = sm->width * W2L;
133+
134+ daddr = (ulong*)((WType)dm->base
135+ + dm->zero*W2L + pt.y*dspan
136+ + (pt.x >> LWBITS));
137+ saddr = (ulong*)((WType)sm->base
138+ + sm->zero*W2L + r.min.y*sspan
139+ + (r.min.x >> LWBITS));
140+
141+ doff = pt.x & (WBITS - 1);
142+ lmask = WMASK >> doff;
143+ rmask = (WMASK << (WBITS - ((doff+width) & (WBITS-1))))&WMASK;
144+ if(!rmask)
145+ rmask = WMASK;
146+ soff = r.min.x & (WBITS-1);
147+ wwidth = ((pt.x+width-1)>>LWBITS) - (pt.x>>LWBITS);
148+
149+ if(sm == dm){
150+#ifdef TEST
151+ if(!FORCEBAKW &&
152+ (FORCEFORW || sm != dm || saddr > daddr ||
153+ (saddr == daddr && soff > doff)))
154+ ;
155+ else{
156+ daddr += height * dspan;
157+ saddr += height * sspan;
158+ sspan -= 2 * W2L * sm->width;
159+ dspan -= 2 * W2L * dm->width;
160+ }
161+#else
162+ if(r.min.y < pt.y){ /* bottom to top */
163+ daddr += height * dspan;
164+ saddr += height * sspan;
165+ sspan -= 2 * W2L * sm->width;
166+ dspan -= 2 * W2L * dm->width;
167+ }else if(r.min.y == pt.y && r.min.x < pt.x)
168+ abort()/*goto right*/;
169+#endif
170+ }
171+ if(wwidth == 0) /* collapse masks for narrow cases */
172+ lmask &= rmask;
173+ fcode &= F;
174+
175+ deltadep = ddep - sdep;
176+ sdest = doff >> deltadep;
177+ delta = soff - sdest;
178+ sign = 0;
179+ if(delta < 0){
180+ sign = 1;
181+ delta = -delta;
182+ }
183+
184+ p = 0;
185+ for(j = 0; j <= height; j++){
186+ d = daddr;
187+ s = saddr;
188+ mask = lmask;
189+ tmp = 0;
190+ if(!sign)
191+ tmp = *s++;
192+ spare = 0;
193+ for(i = wwidth; i >= 0; i--){
194+ if(spare)
195+ sw = *p++;
196+ else{
197+ if(sign){
198+ sw = tmp << (WBITS-delta);
199+ tmp = *s++;
200+ sw |= tmp >> delta;
201+ }else{
202+ sw = tmp << delta;
203+ tmp = *s++;
204+ if(delta)
205+ sw |= tmp >> (WBITS-delta);
206+ }
207+ spare = 1 << deltadep;
208+ if(deltadep >= 1){
209+ gbitexplode(sw, buf, sdep, deltadep);
210+ p = buf;
211+ sw = *p++;
212+ }
213+ }
214+
215+ dw = *d;
216+ switch(fcode){ /* ltor bit aligned */
217+ case Zero: *d = dw & ~mask; break;
218+ case DnorS: *d = dw ^ ((~sw | dw) & mask); break;
219+ case DandnotS: *d = dw ^ ((sw & dw) & mask); break;
220+ case notS: *d = dw ^ ((~sw ^ dw) & mask); break;
221+ case notDandS: *d = dw ^ ((sw | dw) & mask); break;
222+ case notD: *d = dw ^ mask; break;
223+ case DxorS: *d = dw ^ (sw & mask); break;
224+ case DnandS: *d = dw ^ ((sw | ~dw) & mask); break;
225+ case DandS: *d = dw ^ ((~sw & dw) & mask); break;
226+ case DxnorS: *d = dw ^ (~sw & mask); break;
227+ case D: break;
228+ case DornotS: *d = dw | (~sw & mask); break;
229+ case S: *d = dw ^ ((sw ^ dw) & mask); break;
230+ case notDorS: *d = dw ^ (~(sw & dw) & mask); break;
231+ case DorS: *d = dw | (sw & mask); break;
232+ case F: *d = dw | mask; break;
233+ }
234+ d++;
235+
236+ mask = WMASK;
237+ if(i == 1)
238+ mask = rmask;
239+ spare--;
240+ }
241+ saddr += sspan;
242+ daddr += dspan;
243+ }
244+}
245+
246+#ifdef TEST
247+void prprog(void);
248+GBitmap *bb1, *bb2;
249+ulong *src, *dst, *xdst, *xans;
250+int swds, dwds;
251+long ticks;
252+int timeit;
253+
254+long
255+func(int f, long s, int sld, long d, int dld)
256+{
257+ long a;
258+ int sh, i, db, sb;
259+
260+ db = 1 << dld;
261+ sb = 1 << sld;
262+ sh = db - sb;
263+ if(sh > 0) {
264+ a = s;
265+ for(i = sb; i<db; i += sb){
266+ a <<= sb;
267+ s |= a;
268+ }
269+ } else if(sh < 0)
270+ s >>= -sh;
271+
272+ switch(f){
273+ case Zero: d = 0; break;
274+ case DnorS: d = ~(d|s); break;
275+ case DandnotS: d = d & ~s; break;
276+ case notS: d = ~s; break;
277+ case notDandS: d = ~d & s; break;
278+ case notD: d = ~d; break;
279+ case DxorS: d = d ^ s; break;
280+ case DnandS: d = ~(d&s); break;
281+ case DandS: d = d & s; break;
282+ case DxnorS: d = ~(d^s); break;
283+ case S: d = s; break;
284+ case DornotS: d = d | ~s; break;
285+ case D: d = d; break;
286+ case notDorS: d = ~d | s; break;
287+ case DorS: d = d | s; break;
288+ case F: d = ~0; break;
289+ }
290+
291+ d &= ((1<<db)-1);
292+ return d;
293+}
294+
295+void
296+run(int fr, int to, int w, int op)
297+{
298+ int i, j, f, t, fy, ty;
299+ extern long *_clock;
300+
301+ fr += bb2->r.min.x;
302+ to += bb1->r.min.x;
303+ fy = bb2->r.min.y + 1;
304+ ty = bb1->r.min.y + 1;
305+ if(timeit) {
306+ memcpy(dst, xdst, dwds * sizeof(long));
307+ ticks -= *_clock;
308+ gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
309+ ticks += *_clock;
310+ return;
311+ }
312+ f = fr;
313+ t = to;
314+ memcpy(dst, xdst, dwds * sizeof(long));
315+ for(i=0; i<w; i++) {
316+ gbitblt(bb1, Pt(t,ty), bb2, Rect(f,fy,f+1,fy+1), op);
317+ gbitblt(bb1, Pt(t,ty+1), bb2, Rect(f,fy+1,f+1,fy+2), op);
318+ f++;
319+ t++;
320+ }
321+ memcpy(xans, dst, dwds * sizeof(long));
322+
323+ memcpy(dst, xdst, dwds * sizeof(long));
324+ gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
325+
326+ if(memcmp(xans, dst, dwds * sizeof(long))) {
327+ /*
328+ * print src and dst row offset, width in bits, and forw/back
329+ * then print for each of the four rows: the source (s),
330+ * the dest (d), the good value of the answer (g),
331+ * and the actual bad value of the answer (b)
332+ */
333+ print("fr=%d to=%d w=%d fb=%d%d\n",
334+ fr, to, w, FORCEFORW, FORCEBAKW);
335+ print("dst bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
336+ bb1->base, bb1->zero, bb1->width, bb1->ldepth,
337+ bb1->r.min.x, bb1->r.min.y, bb1->r.max.x, bb1->r.max.y);
338+ print("src bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
339+ bb2->base, bb2->zero, bb2->width, bb2->ldepth,
340+ bb2->r.min.x, bb2->r.min.y, bb2->r.max.x, bb2->r.max.y);
341+ for(j=0; 7*j < dwds; j++) {
342+ print("\ns");
343+ for(i=0; i<7 && 7*j+i < dwds; i++)
344+ print(" %.8lux", src[7*j + i]);
345+ print("\nd");
346+ for(i=0; i<7 && 7*j+i < dwds; i++)
347+ print(" %.8lux", xdst[7*j + i]);
348+ print("\ng");
349+ for(i=0; i<7 && 7*j+i < dwds; i++)
350+ print(" %.8lux", xans[7*j + i]);
351+ print("\nb");
352+ for(i=0; i<7 && 7*j+i < dwds; i++)
353+ print(" %.8lux", dst[7*j + i]);
354+ print("\n");
355+ }
356+ prprog();
357+ }
358+}
359+
360+void
361+prprog(void)
362+{
363+ exits(0);
364+}
365+
366+int
367+main(int argc, char *argv[])
368+{
369+ int f, t, w, i, sld, dld, op, iters, simple;
370+ ulong s, d, spix, dpix, apix, fpix, m, *ps, *pd;
371+ Point sorg, dorg;
372+ GBitmap *bs, *bd;
373+ long seed;
374+ char *ct;
375+
376+ sld = 0;
377+ dld = 0;
378+ timeit = 0;
379+ iters = 200;
380+ simple = 0;
381+ ARGBEGIN {
382+ case 'i':
383+ iters = atoi(ARGF());
384+ break;
385+ case 's':
386+ simple = 1;
387+ break;
388+ case 't':
389+ timeit = 1;
390+ ct = ARGF();
391+ if(ct)
392+ iters = atoi(ct);
393+ break;
394+ } ARGEND
395+ if(argc > 0)
396+ sld = atoi(argv[0]);
397+ if(argc > 1)
398+ dld = atoi(argv[1]);
399+ if(!timeit && !simple) {
400+ seed = time(0);
401+ print("seed %lux\n", seed); srand(seed); /**/
402+ }
403+
404+ print("sld %d dld %d\n", sld, dld);
405+ op = 1;
406+
407+ /* bitmaps for 1-bit tests */
408+ bd = gballoc(Rect(0,0,32,1), dld);
409+ bs = gballoc(Rect(0,0,32,1), sld);
410+ for(i=0; i<bs->width; i++)
411+ bs->base[i] = lrand();
412+
413+ /* bitmaps for rect tests */
414+ if(simple) {
415+ dorg = Pt(0,0);
416+ sorg = Pt(0,0);
417+ } else {
418+ dorg = Pt(nrand(63)-31,nrand(63)-31);
419+ sorg = Pt(nrand(63)-31,nrand(63)-31);
420+ }
421+ bb1 = gballoc(Rpt(dorg,add(dorg,Pt(200,4))), dld);
422+ bb2 = gballoc(Rpt(sorg,add(sorg,Pt(200,4))), sld);
423+ dwds = bb1->width * Dy(bb1->r);
424+ swds = bb2->width * Dy(bb2->r);
425+ dst = bb1->base;
426+ src = bb2->base;
427+ xdst = malloc(dwds * sizeof(long));
428+ xans = malloc(dwds * sizeof(long));
429+ for(i=0; i<swds; i++)
430+ src[i] = lrand();
431+ for(i=0; i<dwds; i++)
432+ xdst[i] = lrand();
433+
434+loop:
435+ print("Op %d\n", op);
436+ if(!timeit) {
437+ print("one pixel\n");
438+ ps = bs->base;
439+ pd = bd->base;
440+ FORCEFORW = 1;
441+ FORCEBAKW = 0;
442+ for(i=0; i<1000; i++, FORCEFORW = !FORCEFORW, FORCEBAKW = !FORCEBAKW) {
443+ f = nrand(32 >> sld);
444+ t = nrand(32 >> dld);
445+ s = lrand();
446+ d = lrand();
447+ ps[0] = s;
448+ pd[0] = d;
449+#ifdef T386
450+ spix = (byterev(s) >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
451+ dpix = (byterev(d) >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
452+#else
453+ spix = (s >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
454+ dpix = (d >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
455+#endif
456+#ifdef T386
457+ apix = byterev(func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld)));
458+#else
459+ apix = func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld));
460+#endif
461+ gbitblt(bd, Pt(t,0), bs, Rect(f,0,f+1,1), op);
462+ if(ps[0] != s) {
463+ print("bb src %.8lux %.8lux %d %d\n", ps[0], s, f, t);
464+ exits("error");
465+ }
466+ m = ((1 << (1<<dld)) - 1) << (32 - ((t+1)<<dld));
467+#ifdef T386
468+ m = byterev(m);
469+#endif
470+ if((pd[0] & ~m) != (d & ~m)) {
471+ print("bb dst1 %.8lux %.8lux\n",
472+ s, d);
473+ print("bb %.8lux %.8lux %d %d\n",
474+ ps[0], pd[0], f, t);
475+ prprog();
476+ exits("error");
477+ }
478+ if((pd[0] & m) != apix) {
479+ spix <<= 32 - ((f+1)<<sld);
480+ dpix <<= 32 - ((t+1)<<dld);
481+#ifdef T386
482+ spix = byterev(spix);
483+ dpix = byterev(dpix);
484+#endif
485+ print("bb dst2 %.8lux %.8lux\n",
486+ s, d);
487+ print("bb %.8lux %.8lux %d %d\n",
488+ ps[0], pd[0], f, t);
489+ print("bb %.8lux %.8lux %.8lux %.8lux\n",
490+ spix, dpix, apix, pd[0] & m);
491+ prprog();
492+ exits("error");
493+ }
494+ }
495+ }
496+
497+ print("for\n");
498+ FORCEFORW = 1;
499+ FORCEBAKW = 0;
500+
501+ for(i=0; i<iters; i++) {
502+ f = nrand(64);
503+ t = nrand(64);
504+ w = nrand(130);
505+ run(f, t, w, op);
506+ }
507+
508+ if(sld == dld) {
509+ print("bak\n");
510+ FORCEFORW = 0;
511+ FORCEBAKW = 1;
512+
513+ for(i=0; i<iters; i++) {
514+ f = nrand(64);
515+ t = nrand(64);
516+ w = nrand(130);
517+ run(f, t, w, op);
518+ }
519+ }
520+
521+ if(op < F) {
522+ op++;
523+ goto loop;
524+ }
525+ if(timeit)
526+ print("time: %d ticks\n", ticks);
527+ exits(0);
528+}
529+
530+
531+#endif
os/boot/mpc/flash.c+212−0
@@ -0,0 +1,212 @@
1+#include "boot.h"
2+
3+typedef struct Flashdev Flashdev;
4+struct Flashdev {
5+ uchar* base;
6+ int size;
7+ uchar* exec;
8+ char* config;
9+ int conflen;
10+};
11+
12+enum {
13+ FLASHSEG = 256*1024,
14+ CONFIGLIM = FLASHSEG,
15+ BOOTOFF = FLASHSEG,
16+ BOOTLEN = 3*FLASHSEG, /* third segment might be filsys */
17+ /* rest of flash is free */
18+};
19+
20+static Flashdev flash;
21+
22+/*
23+ * configuration data is written between the bootstrap and
24+ * the end of region 0. the region ends with allocation descriptors
25+ * of the following form:
26+ *
27+ * byte order is big endian
28+ *
29+ * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
30+ */
31+typedef struct Flalloc Flalloc;
32+struct Flalloc {
33+ ulong check; /* checksum of data, or ~0 */
34+ ulong base; /* base of region; ~0 if unallocated, 0 if deleted */
35+ uchar len[3];
36+ uchar tag; /* see below */
37+ uchar sig[4];
38+};
39+
40+enum {
41+ /* tags */
42+ Tdead= 0,
43+ Tboot= 0x01, /* space reserved for boot */
44+ Tconf= 0x02, /* configuration data */
45+ Tnone= 0xFF,
46+
47+ Noval= ~0,
48+};
49+
50+static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
51+static char conftag[] = "#plan9.ini\n";
52+
53+static ulong
54+checksum(uchar* p, int n)
55+{
56+ ulong s;
57+
58+ for(s=0; --n >= 0;)
59+ s += *p++;
60+ return s;
61+}
62+
63+static int
64+validptr(Flalloc *ap, uchar *p)
65+{
66+ return p > (uchar*)&end && p < (uchar*)ap;
67+}
68+
69+static int
70+flashcheck(Flalloc *ap, char **val, int *len)
71+{
72+ uchar *base;
73+ int n;
74+
75+ if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
76+ return 0;
77+ base = flash.base+ap->base;
78+ if(!validptr(ap, base))
79+ return 0;
80+ n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
81+ if(n == 0xFFFFFF)
82+ n = 0;
83+ if(n < 0)
84+ return 0;
85+ if(n > 0 && !validptr(ap, base+n-1))
86+ return 0;
87+ if(ap->check != Noval && checksum(base, n) != ap->check){
88+ print("flash: bad checksum\n");
89+ return 0;
90+ }
91+ *val = (char*)base;
92+ *len = n;
93+ return 1;
94+}
95+
96+int
97+flashinit(void)
98+{
99+ int len;
100+ char *val;
101+ Flalloc *ap;
102+ void *addr;
103+ long mbytes;
104+ char type[20];
105+
106+ flash.base = 0;
107+ flash.exec = 0;
108+ flash.size = 0;
109+ if(archflashreset(type, &addr, &mbytes) < 0){
110+ print("flash: flash not present or not enabled\n"); /* shouldn't happen */
111+ return 0;
112+ }
113+ flash.size = mbytes;
114+ flash.base = addr;
115+ flash.exec = flash.base + BOOTOFF;
116+ flash.config = nil;
117+ flash.conflen = 0;
118+
119+ for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
120+ if(0)
121+ print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
122+ if(ap->tag == Tconf &&
123+ flashcheck(ap, &val, &len) &&
124+ len >= sizeof(conftag)-1 &&
125+ memcmp(val, conftag, sizeof(conftag)-1) == 0){
126+ flash.config = val;
127+ flash.conflen = len;
128+ if(0)
129+ print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
130+ }
131+ }
132+ if(flash.config == nil)
133+ print("flash: no config\n");
134+ else
135+ print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
136+ if(issqueezed(flash.exec) == Q_MAGIC){
137+ print("flash: squeezed powerpc kernel installed\n");
138+ return 1<<0;
139+ }
140+ if(GLLONG(flash.exec) == Q_MAGIC){
141+ print("flash: unsqueezed powerpc kernel installed\n");
142+ return 1<<0;
143+ }
144+ flash.exec = 0;
145+ print("flash: no powerpc kernel in Flash\n");
146+ return 0;
147+}
148+
149+char*
150+flashconfig(int)
151+{
152+ return flash.config;
153+}
154+
155+int
156+flashbootable(int)
157+{
158+ return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == Q_MAGIC);
159+}
160+
161+int
162+flashboot(int)
163+{
164+ ulong entry, addr;
165+ void (*b)(void);
166+ Exec *ep;
167+ Block in;
168+ long n;
169+ uchar *p;
170+
171+ if(flash.exec == 0)
172+ return -1;
173+ p = flash.exec;
174+ if(GLLONG(p) == Q_MAGIC){
175+ /* unsqueezed: copy data and perhaps text, then jump to it */
176+ ep = (Exec*)p;
177+ entry = PADDR(GLLONG(ep->entry));
178+ p += sizeof(Exec);
179+ addr = entry;
180+ n = GLLONG(ep->text);
181+ if(addr != (ulong)p){
182+ memmove((void*)addr, p, n);
183+ print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
184+ }
185+ p += n;
186+ if(entry >= FLASHMEM)
187+ addr = 3*BY2PG; /* kernel text is in Flash, data in RAM */
188+ else
189+ addr = PGROUND(addr+n);
190+ n = GLLONG(ep->data);
191+ memmove((void*)addr, p, n);
192+ print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
193+ }else{
194+ in.data = p;
195+ in.rp = in.data;
196+ in.lim = p+BOOTLEN;
197+ in.wp = in.lim;
198+ n = unsqueezef(&in, &entry);
199+ if(n < 0)
200+ return -1;
201+ }
202+ print("entry=0x%lux\n", entry);
203+ uartwait();
204+ scc2stop();
205+ /*
206+ * Go to new code. It's up to the program to get its PC relocated to
207+ * the right place.
208+ */
209+ b = (void (*)(void))KADDR(PADDR(entry));
210+ (*b)();
211+ return -1;
212+}
os/boot/mpc/fns.h+117−0
@@ -0,0 +1,117 @@
1+Alarm* alarm(int, void (*)(Alarm*), void*);
2+void alarminit(void);
3+void archbacklight(int);
4+char* archconfig(void);
5+void archdisableuart(int);
6+void archenableuart(int, int);
7+void archenableusb(int);
8+void archetherdisable(int);
9+int archetherenable(int, int*, int*);
10+int archflashreset(char*, void**, long*);
11+void archinit(void);
12+int archoptionsw(void);
13+int bootp(int, char*);
14+void cancel(Alarm*);
15+void checkalarms(void);
16+void clockinit(void);
17+void clockintr(Ureg*, void*);
18+void consinit(void);
19+void cpminit(void);
20+void cpuidprint(void);
21+#define dcflush(a,b)
22+void delay(int);
23+void eieio(void);
24+uchar* etheraddr(int);
25+int etherinit(void);
26+int etherrxpkt(int, Etherpkt*, int);
27+int ethertxpkt(int, Etherpkt*, int, int);
28+void exception(void);
29+int flashboot(int);
30+int flashbootable(int);
31+char* flashconfig(int);
32+int flashinit(void);
33+void free(void*);
34+void freeb(Block*);
35+int getcfields(char*, char**, int, char*);
36+char* getconf(char*);
37+ulong getdec(void);
38+ulong gethid0(void);
39+ulong getimmr(void);
40+ulong getmsr(void);
41+ulong getpvr(void);
42+int getstr(char*, char*, int, char*);
43+ulong gettbl(void);
44+ulong gettbu(void);
45+int hardinit(void);
46+long hardread(int, void*, long);
47+long hardseek(int, long);
48+long hardwrite(int, void*, long);
49+long i2csend(int, void*, long);
50+void i2csetup(void);
51+void* ialloc(ulong, int);
52+Block* iallocb(int);
53+void idle(void);
54+int isaconfig(char*, int, ISAConf*);
55+int issqueezed(uchar*);
56+void kbdchar(Queue*, int);
57+void kbdinit(void);
58+void kbdreset(void);
59+void machinit(void);
60+void* malloc(ulong);
61+ulong mapalloc(RMap*, ulong, int, int);
62+void mapfree(RMap*, ulong, int);
63+void mapinit(RMap*, Map*, int);
64+void meminit(void);
65+void microdelay(int);
66+void mmuinit(void);
67+int optionsw(void);
68+void panic(char*, ...);
69+int parseether(uchar*, char*);
70+int plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
71+void putdec(ulong);
72+void puthid0(ulong);
73+void putmsr(ulong);
74+int qbgetc(Queue*);
75+void qbputc(Queue*, int);
76+void qbwrite(Queue*, Block*);
77+Block* qget(Queue*);
78+long qlen(Queue*);
79+Queue* qopen(int, int, void (*)(void*), void*);
80+#define qpass qbwrite
81+void scc2stop(void);
82+void sccnmsi(int, int, int);
83+void sched(void);
84+void screeninit(void);
85+void screenputs(char*, int);
86+void sdraminit(ulong);
87+Partition* sethardpart(int, char*);
88+Partition* setscsipart(int, char*);
89+void setvec(int, void (*)(Ureg*, void*), void*);
90+int splhi(void);
91+int spllo(void);
92+void splx(int);
93+void trapinit(void);
94+void uartputs(char*, int);
95+void uartsetboot(void (*f)(uchar*, int));
96+void uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
97+void uartwait(void);
98+long unsqueezef(Block*, ulong*);
99+
100+#define GSHORT(p) (((p)[1]<<8)|(p)[0])
101+#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))
102+#define GLSHORT(p) (((p)[0]<<8)|(p)[1])
103+#define GLLONG(p) ((GLSHORT(p)<<16)|GLSHORT(p+2))
104+
105+#define KADDR(a) ((void*)((ulong)(a)|KZERO))
106+#define PADDR(a) ((ulong)(a)&~KSEGM)
107+
108+/* IBM bit field order */
109+#define IBIT(b) ((ulong)1<<(31-(b)))
110+#define SIBIT(n) ((ushort)1<<(15-(n)))
111+
112+#define IOREGS(x, T) ((T*)((char*)m->iomem+(x)))
113+
114+int uartinit(void);
115+Partition* setuartpart(int, char*);
116+long uartread(int, void*, long);
117+long uartseek(int, long);
os/boot/mpc/gbitbltclip.c+52−0
@@ -0,0 +1,52 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <libg.h>
4+#include <gnot.h>
5+
6+void
7+gbitbltclip(void *vp)
8+{
9+ int dx, dy;
10+ int i;
11+ struct{
12+ GBitmap *dm;
13+ Point p;
14+ GBitmap *sm;
15+ Rectangle r;
16+ Fcode f;
17+ }*bp;
18+
19+ bp = vp;
20+ dx = Dx(bp->r);
21+ dy = Dy(bp->r);
22+ if(bp->p.x < bp->dm->clipr.min.x){
23+ i = bp->dm->clipr.min.x-bp->p.x;
24+ bp->r.min.x += i;
25+ bp->p.x += i;
26+ dx -= i;
27+ }
28+ if(bp->p.y < bp->dm->clipr.min.y){
29+ i = bp->dm->clipr.min.y-bp->p.y;
30+ bp->r.min.y += i;
31+ bp->p.y += i;
32+ dy -= i;
33+ }
34+ if(bp->p.x+dx > bp->dm->clipr.max.x)
35+ bp->r.max.x -= bp->p.x+dx-bp->dm->clipr.max.x;
36+ if(bp->p.y+dy > bp->dm->clipr.max.y)
37+ bp->r.max.y -= bp->p.y+dy-bp->dm->clipr.max.y;
38+ if(bp->r.min.x < bp->sm->clipr.min.x){
39+ i = bp->sm->clipr.min.x-bp->r.min.x;
40+ bp->p.x += i;
41+ bp->r.min.x += i;
42+ }
43+ if(bp->r.min.y < bp->sm->clipr.min.y){
44+ i = bp->sm->clipr.min.y-bp->r.min.y;
45+ bp->p.y += i;
46+ bp->r.min.y += i;
47+ }
48+ if(bp->r.max.x > bp->sm->clipr.max.x)
49+ bp->r.max.x = bp->sm->clipr.max.x;
50+ if(bp->r.max.y > bp->sm->clipr.max.y)
51+ bp->r.max.y = bp->sm->clipr.max.y;
52+}
os/boot/mpc/gnot.h+71−0
@@ -0,0 +1,71 @@
1+
2+extern void *bbmalloc(int);
3+extern void bbfree(void *, int);
4+extern int bbonstack(void);
5+extern void bbexec(void(*)(void), int, int);
6+
7+/*
8+ * Graphics types
9+ */
10+
11+typedef struct GBitmap GBitmap;
12+typedef struct GFont GFont;
13+typedef struct GSubfont GSubfont;
14+typedef struct GCacheinfo GCacheinfo;
15+
16+struct GBitmap
17+{
18+ ulong *base; /* pointer to start of data */
19+ long zero; /* base+zero=&word containing (0,0) */
20+ ulong width; /* width in 32 bit words of total data area */
21+ int ldepth; /* log base 2 of number of bits per pixel */
22+ Rectangle r; /* rectangle in data area, local coords */
23+ Rectangle clipr; /* clipping region */
24+ GBitmap *cache; /* zero; distinguishes bitmap from layer */
25+};
26+
27+
28+/*
29+ * GFont etc. are not used in the library, only in devbit.c.
30+ * GSubfont is only barely used.
31+ */
32+struct GSubfont
33+{
34+ short n; /* number of chars in font */
35+ char height; /* height of bitmap */
36+ char ascent; /* top of bitmap to baseline */
37+ Fontchar *info; /* n+1 character descriptors */
38+ GBitmap *bits; /* where the characters are */
39+};
40+struct GCacheinfo
41+{
42+ ulong xright; /* right edge of bits */
43+ Fontchar;
44+};
45+
46+struct GFont
47+{
48+ uchar height; /* max height of bitmap, interline spacing */
49+ char ascent; /* top of bitmap to baseline */
50+ char width; /* widest so far; used in caching only */
51+ char ldepth; /* of images */
52+ short id; /* of font */
53+ int ncache; /* number of entries in cache */
54+ GCacheinfo *cache; /* cached characters */
55+ GBitmap *b; /* cached images */
56+};
57+
58+extern ulong *gaddr(GBitmap*, Point);
59+extern uchar *gbaddr(GBitmap*, Point);
60+extern void gbitblt(GBitmap*, Point, GBitmap*, Rectangle, Fcode);
61+extern void gbitbltclip(void*);
62+extern void gtexture(GBitmap*, Rectangle, GBitmap*, Fcode);
63+extern Point gsubfstrsize(GSubfont*, char*);
64+extern int gsubfstrwidth(GSubfont*, char*);
65+extern Point gsubfstring(GBitmap*, Point, GSubfont*, char*, Fcode);
66+extern Point gbitbltstring(GBitmap*, Point, GSubfont*, char*, Fcode);
67+extern void gsegment(GBitmap*, Point, Point, int, Fcode);
68+extern void gpoint(GBitmap*, Point, int, Fcode);
69+extern void gflushcpucache(void);
70+extern GBitmap* gballoc(Rectangle, int);
71+extern void gbfree(GBitmap*);
os/boot/mpc/i2c.c+351−0
@@ -0,0 +1,351 @@
1+#include "boot.h"
2+
3+/*
4+ * basic read/write interface to mpc8xx I2C bus (master mode)
5+ */
6+
7+typedef struct I2C I2C;
8+
9+struct I2C {
10+ uchar i2mod;
11+ uchar rsv12a[3];
12+ uchar i2add;
13+ uchar rsv12b[3];
14+ uchar i2brg;
15+ uchar rsv12c[3];
16+ uchar i2com;
17+ uchar rsv12d[3];
18+ uchar i2cer;
19+ uchar rsv12e[3];
20+ uchar i2cmr;
21+};
22+
23+enum {
24+ /* i2c-specific BD flags */
25+ RxeOV= 1<<1, /* overrun */
26+ TxS= 1<<10, /* transmit start condition */
27+ TxeNAK= 1<<2, /* last transmitted byte not acknowledged */
28+ TxeUN= 1<<1, /* underflow */
29+ TxeCL= 1<<0, /* collision */
30+ TxERR= (TxeNAK|TxeUN|TxeCL),
31+
32+ /* i2cmod */
33+ REVD= 1<<5, /* =1, LSB first */
34+ GCD= 1<<4, /* =1, general call address disabled */
35+ FLT= 1<<3, /* =0, not filtered; =1, filtered */
36+ PDIV= 3<<1, /* predivisor field */
37+ EN= 1<<0, /* enable */
38+
39+ /* i2com */
40+ STR= 1<<7, /* start transmit */
41+ I2CM= 1<<0, /* master */
42+ I2CS= 0<<0, /* slave */
43+
44+ /* i2cer */
45+ TXE = 1<<4,
46+ BSY = 1<<2,
47+ TXB = 1<<1,
48+ RXB = 1<<0,
49+
50+ /* port B bits */
51+ I2CSDA = IBIT(27),
52+ I2CSCL = IBIT(26),
53+
54+ Rbit = 1<<0, /* bit in address byte denoting read */
55+
56+ /* maximum I2C I/O (can change) */
57+ Bufsize = 64,
58+ Tbuflen= Bufsize+4, /* extra address bytes and alignment */
59+ Freq = 100000,
60+ I2CTimeout = 250, /* msec */
61+};
62+
63+/* data cache needn't be flushed if buffers allocated in uncached INTMEM */
64+#define DCFLUSH(a,n)
65+
66+/*
67+ * I2C software structures
68+ */
69+
70+struct Ctlr {
71+ Lock;
72+ QLock io;
73+ int init;
74+ I2C* i2c;
75+ IOCparam* sp;
76+
77+ BD* rd;
78+ BD* td;
79+ int phase;
80+ char* addr;
81+ char* txbuf;
82+ char* rxbuf;
83+};
84+typedef struct Ctlr Ctlr;
85+
86+static Ctlr i2ctlr[1];
87+extern int predawn;
88+
89+static void interrupt(Ureg*, void*);
90+
91+static void
92+enable(void)
93+{
94+ I2C *i2c;
95+
96+ i2c = i2ctlr->i2c;
97+ i2c->i2cer = ~0; /* clear events */
98+ eieio();
99+ i2c->i2mod |= EN;
100+ eieio();
101+ i2c->i2cmr = TXE|BSY|TXB|RXB; /* enable all interrupts */
102+ eieio();
103+}
104+
105+static void
106+disable(void)
107+{
108+ I2C *i2c;
109+
110+ i2c = i2ctlr->i2c;
111+ i2c->i2cmr = 0; /* mask all interrupts */
112+ i2c->i2mod &= ~EN;
113+}
114+
115+/*
116+ * called by the reset routine of any driver using the I2C
117+ */
118+void
119+i2csetup(void)
120+{
121+ IMM *io;
122+ I2C *i2c;
123+ IOCparam *sp;
124+ Ctlr *ctlr;
125+ long f, e, emin;
126+ int p, d, dmax;
127+
128+ ctlr = i2ctlr;
129+ if(ctlr->init)
130+ return;
131+ print("i2c setup...\n");
132+ ctlr->init = 1;
133+ i2c = KADDR(INTMEM+0x860);
134+ ctlr->i2c = i2c;
135+ sp = KADDR(INTMEM+0x3c80);
136+ ctlr->sp = sp;
137+ disable();
138+
139+ if(ctlr->txbuf == nil){
140+ ctlr->txbuf = ialloc(Tbuflen, 2);
141+ ctlr->addr = ctlr->txbuf+Bufsize;
142+ }
143+ if(ctlr->rxbuf == nil)
144+ ctlr->rxbuf = ialloc(Bufsize, 2);
145+ if(ctlr->rd == nil){
146+ ctlr->rd = bdalloc(1);
147+ ctlr->rd->addr = PADDR(ctlr->rxbuf);
148+ ctlr->rd->length = 0;
149+ ctlr->rd->status = BDWrap;
150+ }
151+ if(ctlr->td == nil){
152+ ctlr->td = bdalloc(2);
153+ ctlr->td->addr = PADDR(ctlr->txbuf);
154+ ctlr->td->length = 0;
155+ ctlr->td->status = BDWrap|BDLast;
156+ }
157+
158+ /* select port pins */
159+ io = ioplock();
160+ io->pbdir |= I2CSDA | I2CSCL;
161+ io->pbodr |= I2CSDA | I2CSCL;
162+ io->pbpar |= I2CSDA | I2CSCL;
163+ iopunlock();
164+
165+ /* explicitly initialise parameters, because InitRxTx can't be used (see i2c/spi relocation errata) */
166+ sp = ctlr->sp;
167+ sp->rbase = PADDR(ctlr->rd);
168+ sp->tbase = PADDR(ctlr->td);
169+ sp->rfcr = 0x18;
170+ sp->tfcr = 0x18;
171+ sp->mrblr = Bufsize;
172+ sp->rstate = 0;
173+ sp->rptr = 0;
174+ sp->rbptr = sp->rbase;
175+ sp->rcnt = 0;
176+ sp->tstate = 0;
177+ sp->tbptr = sp->tbase;
178+ sp->tptr = 0;
179+ sp->tcnt = 0;
180+ eieio();
181+
182+ i2c->i2com = I2CM;
183+ i2c->i2mod = 0; /* normal mode */
184+ i2c->i2add = 0;
185+
186+ emin = Freq;
187+ dmax = (m->cpuhz/Freq)/2-3;
188+ for(d=0; d < dmax; d++){
189+ for(p=3; p>=0; p--){
190+ f = (m->cpuhz>>(p+2))/(2*(d+3));
191+ e = Freq - f;
192+ if(e < 0)
193+ e = -e;
194+ if(e < emin){
195+ emin = e;
196+ i2c->i2brg = d;
197+ i2c->i2mod = (i2c->i2mod&~PDIV)|((3-p)<<1); /* set PDIV */
198+ }
199+ }
200+ }
201+ //print("i2brg=%d i2mod=#%2.2ux\n", i2c->i2brg, i2c->i2mod);
202+ setvec(VectorCPIC+0x10, interrupt, i2ctlr);
203+}
204+
205+enum {
206+ Idling,
207+ Done,
208+ Busy,
209+ Sending,
210+ Recving,
211+};
212+
213+static void
214+interrupt(Ureg*, void *arg)
215+{
216+ int events;
217+ Ctlr *ctlr;
218+ I2C *i2c;
219+
220+ ctlr = arg;
221+ i2c = ctlr->i2c;
222+ events = i2c->i2cer;
223+ eieio();
224+ i2c->i2cer = events;
225+ if(events & (BSY|TXE)){
226+ //print("I2C#%x\n", events);
227+ if(ctlr->phase != Idling){
228+ ctlr->phase = Idling;
229+ }
230+ }else{
231+ if(events & TXB){
232+ //print("i2c: xmt %d %4.4ux %4.4ux\n", ctlr->phase, ctlr->td->status, ctlr->td[1].status);
233+ if(ctlr->phase == Sending){
234+ ctlr->phase = Done;
235+ }
236+ }
237+ if(events & RXB){
238+ //print("i2c: rcv %d %4.4ux %d\n", ctlr->phase, ctlr->rd->status, ctlr->rd->length);
239+ if(ctlr->phase == Recving){
240+ ctlr->phase = Done;
241+ }
242+ }
243+ }
244+}
245+
246+static int
247+done(void *a)
248+{
249+ return ((Ctlr*)a)->phase < Busy;
250+}
251+
252+static void
253+i2cwait(Ctlr *ctlr)
254+{
255+ /* TO DO: timeout */
256+ while(!done(ctlr)){
257+ if(predawn)
258+ interrupt(nil, ctlr);
259+ }
260+}
261+
262+long
263+i2csend(int addr, void *buf, long n)
264+{
265+ Ctlr *ctlr;
266+ int i, p, s;
267+
268+ ctlr = i2ctlr;
269+ if(n > Bufsize)
270+ return -1;
271+ i = 1;
272+ ctlr->txbuf[0] = addr & ~1;
273+ if(addr & 1){
274+ ctlr->txbuf[1] = addr>>8;
275+ i++;
276+ }
277+ memmove(ctlr->txbuf+i, buf, n);
278+ DCFLUSH(ctlr->txbuf, Tbuflen);
279+ ctlr->phase = Sending;
280+ ctlr->rd->status = BDEmpty|BDWrap|BDInt;
281+ ctlr->td->addr = PADDR(ctlr->txbuf);
282+ ctlr->td->length = n+i;
283+ ctlr->td->status = BDReady|BDWrap|BDLast|BDInt;
284+ enable();
285+ ctlr->i2c->i2com = STR|I2CM;
286+ eieio();
287+ i2cwait(ctlr);
288+ disable();
289+ p = ctlr->phase;
290+ s = ctlr->td->status;
291+ if(s & BDReady || s & TxERR || p != Done)
292+ return -1;
293+ return n;
294+}
295+
296+long
297+i2crecv(int addr, void *buf, long n)
298+{
299+ Ctlr *ctlr;
300+ int p, s, flag;
301+ BD *td;
302+ long nr;
303+
304+ ctlr = i2ctlr;
305+ if(n > Bufsize)
306+ return -1;
307+ ctlr->txbuf[0] = addr|Rbit;
308+ if(addr & 1){ /* special select sequence */
309+ ctlr->addr[0] = addr &~ 1;
310+ ctlr->addr[1] = addr>>8;
311+ }
312+ DCFLUSH(ctlr->txbuf, Tbuflen);
313+ DCFLUSH(ctlr->rxbuf, Bufsize);
314+ ctlr->phase = Recving;
315+ ctlr->rd->addr = PADDR(ctlr->rxbuf);
316+ ctlr->rd->status = BDEmpty|BDWrap|BDInt;
317+ flag = 0;
318+ td = ctlr->td;
319+ td[1].status = 0;
320+ if(addr & 1){
321+ /* special select sequence */
322+ td->addr = PADDR(ctlr->addr);
323+ td->length = 2;
324+ /* td->status made BDReady below */
325+ td++;
326+ flag = TxS;
327+ }
328+ td->addr = PADDR(ctlr->txbuf);
329+ td->length = n+1;
330+ td->status = BDReady|BDWrap|BDLast | flag; /* not BDInt: leave that to receive */
331+ if(flag)
332+ ctlr->td->status = BDReady;
333+ enable();
334+ ctlr->i2c->i2com = STR|I2CM;
335+ eieio();
336+ i2cwait(ctlr);
337+ disable();
338+ p = ctlr->phase;
339+ s = ctlr->td->status;
340+ if(flag)
341+ s |= ctlr->td[1].status;
342+ nr = ctlr->rd->length;
343+ if(nr > n)
344+ nr = n; /* shouldn't happen */
345+ if(s & TxERR || s & BDReady || ctlr->rd->status & BDEmpty)
346+ return -1;
347+ if(p != Done)
348+ return -1;
349+ memmove(buf, ctlr->rxbuf, nr);
350+ return nr;
351+}
os/boot/mpc/initfads.c+187−0
@@ -0,0 +1,187 @@
1+/*
2+ * Called from l.s in EPROM to set up a minimal working environment.
3+ * Since there is no DRAM yet, and therefore no stack, no function
4+ * calls may be made from sysinit0, and values can't be stored,
5+ * except to INTMEM. Global values are accessed by offset from SB,
6+ * which has been set by l.s to point into EPROM.
7+ *
8+ * This is FADS-specific in CS assignment and access of the FADS BCSR
9+ * to discover memory size and speed.
10+ */
11+
12+#include "u.h"
13+#include "lib.h"
14+#include "mem.h"
15+#include "dat.h"
16+#include "fns.h"
17+#include "io.h"
18+
19+#include "archfads.h"
20+
21+#define MB (1024*1024)
22+
23+enum {
24+ UPMSIZE = 64, /* memory controller instruction RAM */
25+ SPEED = 50, /* maximum memory clock in MHz */
26+ SDRAMSIZE = 4*MB,
27+
28+ /* mcr */
29+ WriteRAM = 0<<30,
30+ ReadRAM = 1<<30,
31+ ExecRAM = 2<<30,
32+
33+ SelUPMA = 0<<23,
34+ SelUPMB = 1<<23,
35+
36+ Once = 1<<8,
37+};
38+
39+/*
40+ * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
41+ */
42+static ulong upma50[UPMSIZE] = {
43+ 0x8FFFEC24, 0xFFFEC04, 0xCFFEC04, 0xFFEC04,
44+ 0xFFEC00, 0x37FFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
45+ 0x8FFFEC24, 0xFFFEC04, 0x8FFEC04, 0xFFEC0C,
46+ 0x3FFEC00, 0xFFEC44, 0xFFCC08, 0xCFFCC44,
47+ 0xFFEC0C, 0x3FFEC00, 0xFFEC44, 0xFFCC00,
48+ 0x3FFFC847, 0x3FFFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
49+ 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x11BFCC47,
50+ 0xC0FFCC84, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
51+ 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x3AFCC4C,
52+ 0xCAFCC00, 0x3AFCC4C, 0xCAFCC00, 0x3AFCC4C,
53+ 0xCAFCC00, 0x33BFCC4F, 0xFFFFFFFF, 0xFFFFFFFF,
54+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
55+ 0xC0FFCC84, 0xFFCC04, 0x7FFCC04, 0x3FFFCC06,
56+ 0xFFFFCC85, 0xFFFFCC05, 0xFFFFCC05, 0xFFFFFFFF,
57+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
58+ 0x33FFCC07, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
59+};
60+
61+/*
62+ * the FADS manual table 3-7 suggests the following for 60ns EDO DRAMs at 20MHz
63+ */
64+static ulong upma20[UPMSIZE] = {
65+ 0x8FFFCC04, 0x08FFCC00, 0x33FFCC47, ~0, ~0, ~0, ~0, ~0,
66+ [0x08] 0x8FFFCC04, 0x08FFCC08, 0x08FFCC08, 0x08FFCC08, 0x08FFCC00, 0x3FFFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
67+ [0x18] 0x8FEFCC00, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0,
68+ [0x20] 0x8FEFCC00, 0x09AFCC48, 0x09AFCC48, 0x08AFCC48, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
69+ [0x30] 0x80FFCC84, 0x17FFCC04, 0xFFFFCC86, 0xFFFFCC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
70+ [0x3C] 0x33FFCC07, ~0, ~0, ~0,
71+};
72+
73+void
74+sysinit0(int inrom)
75+{
76+ ulong *upm, *bcsr;
77+ IMM *io;
78+ int i, mb;
79+
80+ io = (IMM*)INTMEM; /* running before maps, no KADDR */
81+
82+ /* system interface unit initialisation, FADS manual table 3-2, except as noted */
83+ io->siumcr = 0x01012440;
84+ io->sypcr = 0xFFFFFF88;
85+ io->tbscrk = KEEP_ALIVE_KEY;
86+ io->tbscr = 0xC3; /* time base enabled */
87+ io->rtcsck = KEEP_ALIVE_KEY;
88+ io->rtcsc = 0xC1; /* don't FRZ, real-time clock enabled */
89+ io->rtcsck = ~KEEP_ALIVE_KEY;
90+ io->piscrk = KEEP_ALIVE_KEY;
91+ io->piscr = 0x82;
92+
93+ io->memc[BCSRCS].option = 0xFFFF8110; /* 32k block, all types access, CS early negate, 1 ws */
94+ io->memc[BCSRCS].base = BCSRMEM | 1; /* base, 32-bit port, no parity, GPCM */
95+
96+ io->memc[BOOTCS].base = FLASHMEM | 1;
97+ io->memc[BOOTCS].option = 0xFF800D54;
98+
99+ if(!inrom)
100+ return; /* can't initialise DRAM controller from DRAM */
101+
102+ bcsr = (ulong*)BCSRMEM;
103+// bcsr[1] &= ~DisableDRAM;
104+ /* could check DRAM speed here; assume 60ns */
105+ switch((bcsr[2]>>23)&3){
106+ default: return; /* can't happen; for the compiler */
107+ case 0: mb = 4; break;
108+ case 1: mb = 32; break;
109+ case 2: mb = 16; break;
110+ case 3: mb = 8; break;
111+ }
112+
113+ upm = upma50;
114+ for(i=0; i<UPMSIZE; i++){
115+ io->mdr = upm[i];
116+ io->mcr = WriteRAM | SelUPMA | i;
117+ }
118+ io->mptpr = 0x0400;
119+ if(SPEED >= 32)
120+ io->mamr = (0x9C<<24) | 0xA21114; /* 50MHz BRGCLK; FADS manual says 0xC0, mpc8bug sets 0x9C */
121+ else if(SPEED >= 20)
122+ io->mamr = (0x60<<24) | 0xA21114; /* 25MHz BRGCLK */
123+ else
124+ io->mamr = (0x40<<24) | 0xA21114; /* 16.67MHz BRGCLK */
125+ io->memc[DRAM1].option = ~((mb<<20)-1)|0x0800; /* address mask, SAM=1 */
126+ io->memc[DRAM1].base = 0 | 0x81; /* base at 0, 32-bit port size, no parity, UPMA */
127+}
128+
129+/*
130+ * the FADS manual table 3-9's suggestion for MB811171622A-100 32+MHz-50MHz
131+ */
132+static ulong upmb50[UPMSIZE] = {
133+ [0x00] 0x1F07FC04, 0xEEAEFC04, 0x11ADFC04, 0xEFBBBC00, 0x1FF77C47,
134+ [0x05] 0x1FF77C34, 0xEFEABC34, 0x1FB57C35,
135+ [0x08] 0x1F07FC04, 0xEEAEFC04, 0x10ADFC04, 0xF0AFFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
136+ [0x18] 0x1F27FC04, 0xEEAEBC00, 0x01B93C04, 0x1FF77C47, ~0, ~0, ~0, ~0,
137+ [0x20] 0x1F07FC04, 0xEEAEBC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
138+ [0x30] 0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC07, ~0, ~0, ~0, ~0, ~0, ~0,
139+ [0x3C] 0x7FFFFC07, ~0, ~0, ~0,
140+};
141+
142+/*
143+ * the FADS manual table 3-8's suggestion for MB811171622A-100 up to 32MHz
144+ */
145+static ulong upmb32[UPMSIZE] = {
146+ [0x00] 0x126CC04, 0xFB98C00, 0x1FF74C45, ~0, ~0,
147+ [0x05] 0x1FE77C34, 0xEFAABC34, 0x1FA57C35,
148+ [0x08] 0x0026FC04, 0x10ADFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
149+ [0x18] 0x0E26BC04, 0x01B93C00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0,
150+ [0x20] 0x0E26BC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
151+ [0x30] 0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
152+ [0x3C] 0x7FFFFC07, ~0, ~0, ~0,
153+};
154+
155+/*
156+ * optionally called by archfads.c:/^archinit to initialise access to SDRAM
157+ */
158+void
159+sdraminit(ulong base)
160+{
161+ ulong *upm;
162+ IMM *io;
163+ int i;
164+
165+ io = (IMM*)INTMEM; /* running before maps, no KADDR */
166+ if(SPEED > 32)
167+ upm = upmb50;
168+ else
169+ upm = upmb32;
170+ for(i=0; i<UPMSIZE; i++){
171+ io->mdr = upm[i];
172+ io->mcr = WriteRAM | SelUPMB | i;
173+ }
174+ io->memc[SDRAM].option = ~(SDRAMSIZE-1)|0x0A00; /* address mask, SAM=1, G5LS=1 */
175+ io->memc[SDRAM].base = base | 0xC1;
176+ if(SPEED > 32){
177+ io->mbmr = 0xD0802114; /* 50MHz BRGCLK */
178+ io->mar = 0x88;
179+ }else{
180+ io->mbmr = 0x80802114; /* 32MHz BRGCLK */
181+ io->mar = 0x48;
182+ }
183+ io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 5; /* run MRS command in locations 5-8 of UPMB */
184+ io->mbmr = (io->mbmr & ~0xF) | 8;
185+ io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 0x30; /* run refresh sequence */
186+ io->mbmr = (io->mbmr & ~0xF) | 4; /* 4-beat refresh bursts */
187+}
os/boot/mpc/initpaq.c+101−0
@@ -0,0 +1,101 @@
1+/*
2+ * Called from l.s in EPROM to set up a minimal working environment.
3+ * Since there is no DRAM yet, and therefore no stack, no function
4+ * calls may be made from sysinit0, and values can't be stored,
5+ * except to INTMEM. Global values are accessed by offset from SB,
6+ * which has been set by l.s to point into EPROM.
7+ *
8+ * This is PowerPAQ-specific:
9+ * - assumes 8mbytes
10+ * - powerpaq CS assignment
11+ */
12+
13+#include "u.h"
14+#include "lib.h"
15+#include "mem.h"
16+#include "dat.h"
17+#include "fns.h"
18+#include "io.h"
19+
20+#include "archpaq.h"
21+
22+#define MB (1024*1024)
23+
24+enum {
25+ DRAMSIZE = 8*MB,
26+ FLASHSIZE = 8*MB,
27+
28+ UPMSIZE = 64, /* memory controller instruction RAM */
29+ SPEED = 50, /* maximum memory clock in MHz */
30+
31+ /* mcr */
32+ WriteRAM = 0<<30,
33+ ReadRAM = 1<<30,
34+ ExecRAM = 2<<30,
35+
36+ SelUPMA = 0<<23,
37+ SelUPMB = 1<<23,
38+
39+ Once = 1<<8,
40+};
41+
42+/*
43+ * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
44+ */
45+static ulong upmb50[UPMSIZE] = {
46+ 0x8FFFEC24, 0xFFFEC04, 0xCFFEC04, 0xFFEC04,
47+ 0xFFEC00, 0x37FFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
48+ 0x8FFFEC24, 0xFFFEC04, 0x8FFEC04, 0xFFEC0C,
49+ 0x3FFEC00, 0xFFEC44, 0xFFCC08, 0xCFFCC44,
50+ 0xFFEC0C, 0x3FFEC00, 0xFFEC44, 0xFFCC00,
51+ 0x3FFFC847, 0x3FFFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
52+ 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x11BFCC47,
53+ 0xC0FFCC84, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
54+ 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x3AFCC4C,
55+ 0xCAFCC00, 0x3AFCC4C, 0xCAFCC00, 0x3AFCC4C,
56+ 0xCAFCC00, 0x33BFCC4F, 0xFFFFFFFF, 0xFFFFFFFF,
57+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
58+ 0xC0FFCC84, 0xFFCC04, 0x7FFCC04, 0x3FFFCC06,
59+ 0xFFFFCC85, 0xFFFFCC05, 0xFFFFCC05, 0xFFFFFFFF,
60+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
61+ 0x33FFCC07, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
62+};
63+
64+void
65+sysinit0(int inrom)
66+{
67+ ulong *upm;
68+ IMM *io;
69+ int i;
70+
71+ io = (IMM*)INTMEM; /* running before maps, no KADDR */
72+
73+ /* system interface unit initialisation, FADS manual table 3-2, except as noted */
74+ io->siumcr = 0x01012440;
75+ io->sypcr = 0xFFFFFF88;
76+ io->tbscrk = KEEP_ALIVE_KEY;
77+ io->tbscr = 0xC3; /* time base enabled */
78+ io->rtcsck = KEEP_ALIVE_KEY;
79+ io->rtcsc = 0xC1; /* don't FRZ, real-time clock enabled */
80+ io->rtcsck = ~KEEP_ALIVE_KEY;
81+ io->piscrk = KEEP_ALIVE_KEY;
82+ io->piscr = 0x82;
83+
84+ io->memc[BOOTCS].base = FLASHMEM | 1;
85+ io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(2<<4); /* mask, BIH, 2 wait states */
86+
87+ if(!inrom)
88+ return; /* can't initialise DRAM controller from DRAM */
89+
90+ /* could check DRAM speed here; assume 60ns */
91+ /* could probe DRAM for size here; assume DRAMSIZE */
92+ io->mptpr = 0x400; /* powerpaq flash has 0x1000 */
93+ io->mbmr = (0xC0<<24) | 0xA21114; /* 50MHz BRGCLK */
94+ upm = upmb50;
95+ for(i=0; i<UPMSIZE; i++){
96+ io->mdr = upm[i];
97+ io->mcr = WriteRAM | SelUPMB | i;
98+ }
99+ io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0800; /* address mask, SAM=1 */
100+ io->memc[DRAM1].base = 0 | 0xC1; /* base at 0, 32-bit port size, no parity, UPMB */
101+}
os/boot/mpc/initrpcg.c+91−0
@@ -0,0 +1,91 @@
1+
2+/*
3+ * Called from l.s in EPROM to set up a minimal working environment.
4+ * Since there is no DRAM yet, and therefore no stack, no function
5+ * calls may be made from sysinit, and values can't be stored,
6+ * except to INTMEM. Global values are accessed by offset from SB,
7+ * which has been set by l.s to point into EPROM.
8+ */
9+
10+#include "u.h"
11+#include "lib.h"
12+#include "mem.h"
13+#include "dat.h"
14+#include "fns.h"
15+#include "io.h"
16+
17+#include "archrpcg.h"
18+
19+#define MB (1024*1024)
20+
21+enum {
22+ UPMSIZE = 64, /* memory controller instruction RAM */
23+ DRAMSIZE = 16*MB,
24+ FLASHSIZE = 4*MB,
25+
26+ WriteRAM = 0<<30,
27+ ReadRAM = 1<<30,
28+ ExecRAM = 2<<30,
29+
30+ SelUPMA = 0<<23,
31+ SelUPMB = 1<<23,
32+};
33+/* RPCG values for RPXLite AW */
34+static ulong upma50[UPMSIZE] = {
35+ 0xCFFFCC24, 0x0FFFCC04, 0x0CAFCC04, 0x03AFCC08,
36+ 0x3FBFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
37+ 0xCFFFCC24, 0x0FFFCC04, 0x0CAFCC84, 0x03AFCC88,
38+ 0x3FBFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
39+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
40+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
41+ 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC04, 0x03FFCC00,
42+ 0x3FFFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
43+ 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC84, 0x03FFCC84,
44+ 0x0CFFCC00, 0x33FFCC27, 0xFFFFCC25, 0xFFFFCC25,
45+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
46+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
47+ 0xC0FFCC24, 0x03FFCC24, 0x0FFFCC24, 0x0FFFCC24,
48+ 0x3FFFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
49+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
50+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
51+};
52+
53+void
54+sysinit0(int inrom)
55+{
56+ ulong *upm;
57+ IMM *io;
58+ int i;
59+
60+ io = (IMM*)INTMEM; /* running before maps, no KADDR */
61+ io->siumcr = 0x01012440;
62+ io->sypcr = 0xFFFFFF88;
63+ io->tbscrk = KEEP_ALIVE_KEY;
64+ io->tbscr = 0xC3;
65+ io->rtcsck = KEEP_ALIVE_KEY;
66+ io->rtcsc = 0xC1;
67+ io->rtcsck = ~KEEP_ALIVE_KEY;
68+ io->piscrk = KEEP_ALIVE_KEY;
69+ io->piscr = 0x82;
70+return;
71+ io->memc[BCSRCS].option = 0xFFFF8910; /* 32k block, all types access, CSNT, CS early negate, burst inhibit, 1 ws */
72+ io->memc[BCSRCS].base = BCSRMEM | 1; /* base, 32-bit port, no parity, GPCM */
73+
74+ io->memc[BOOTCS].base = FLASHMEM | 0x801; /* base, 16 bit port */
75+ io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(4<<4); /* mask, BIH, 4 wait states */
76+
77+ if(1||!inrom)
78+ return; /* can't initialise DRAM controller from DRAM */
79+
80+ /* TO DO: could check DRAM size and speed now */
81+
82+ upm = upma50;
83+ for(i=0; i<nelem(upma50); i++){
84+ io->mdr = upm[i];
85+ io->mcr = WriteRAM | SelUPMA | i;
86+ }
87+ io->mptpr = 0x0800; /* divide by 8 */
88+ io->mamr = (0x58<<24) | 0xA01430; /* 40MHz BRGCLK */
89+ io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0E00; /* address mask, SAM=1, G5LA/S=3 */
90+ io->memc[DRAM1].base = 0 | 0x81; /* base at 0, 32-bit port size, no parity, UPMA */
91+}
os/boot/mpc/io.h+463−0
@@ -0,0 +1,463 @@
1+enum
2+{
3+ /* software interrupt vectors (SIU and CPM) */
4+ VectorPIC= 0, /* level 0 to level 7, assigned by software */
5+ CPIClevel= 4,
6+ VectorIRQ= VectorPIC+8, /* IRQ0 to IRQ7 */
7+ VectorCPIC= VectorIRQ+8, /* 32 CPM interrupts: 0 (error) to 0x1F (PC15) */
8+};
9+
10+enum
11+{
12+ BUSUNKNOWN = 0,
13+};
14+
15+/*
16+ * Buffer Descriptors and IO Rings
17+ */
18+
19+typedef struct BD BD;
20+struct BD {
21+ ushort status;
22+ ushort length;
23+ ulong addr;
24+};
25+
26+BD* bdalloc(int);
27+void bdfree(BD*, int);
28+
29+enum {
30+ /* Rx BDs, bits common to all protocols */
31+ BDEmpty= 1<<15,
32+ BDWrap= 1<<13,
33+ BDInt= 1<<12,
34+ BDLast= 1<<11,
35+ BDFirst= 1<<10,
36+
37+ /* Tx BDs */
38+ BDReady= 1<<15,
39+ /* BDWrap, BDInt, BDLast */
40+};
41+
42+typedef struct Ring Ring;
43+struct Ring {
44+ BD* rdr; /* receive descriptor ring */
45+ void* rrb; /* receive ring buffers */
46+ int rdrx; /* index into rdr */
47+ int nrdre; /* length of rdr */
48+
49+ BD* tdr; /* transmit descriptor ring */
50+ Block** txb; /* corresponding transmit ring buffers */
51+ int tdrh; /* host index into tdr */
52+ int tdri; /* interface index into tdr */
53+ int ntdre; /* length of tdr */
54+ int ntq; /* pending transmit requests */
55+};
56+
57+#define NEXT(x, l) (((x)+1)%(l))
58+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
59+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
60+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
61+
62+int ioringinit(Ring*, int, int, int);
63+
64+/*
65+ * CPM
66+ */
67+enum {
68+ /* commands */
69+ InitRxTx = 0,
70+ InitRx = 1,
71+ InitTx = 2,
72+ EnterHunt= 3,
73+ StopTx= 4,
74+ GracefulStopTx = 5,
75+ InitIDMA = 5,
76+ RestartTx = 6,
77+ CloseRxBD = 7,
78+ SetGroupAddr = 8,
79+ SetTimer = 8,
80+ GCITimeout = 9,
81+ GCIAbort = 10,
82+ StopIDMA = 11,
83+ StartDSP = 12,
84+ ArmIDMA = 13,
85+ InitDSP = 13,
86+ USBCmd = 15,
87+
88+ /* channel IDs */
89+ SCC1ID= 0,
90+ USBID= 0,
91+ I2CID= 1,
92+ IDMA1ID= 1,
93+ SCC2ID= 4,
94+ SPIID= 5,
95+ IDMA2ID= 5,
96+ TIMERID= 5,
97+ SCC3ID= 8,
98+ SMC1ID= 9,
99+ DSP1ID=9,
100+ SCC4ID= 12,
101+ SMC2ID= 13,
102+ DSP2ID= 13,
103+
104+ BaudEnable = 1<<16,
105+
106+ /* sicr */
107+ CLK1 = 4, /* SCC1,2 */
108+ CLK2 = 5,
109+ CLK3 = 6,
110+ CLK4 = 7,
111+ CLK5 = CLK1, /* SCC3,4 */
112+ CLK6 = CLK2,
113+ CLK7 = CLK3,
114+ CLK8 = CLK4,
115+};
116+
117+void cpmop(int, int, int);
118+#define ioplock() (m->iomem)
119+#define iopunlock()
120+
121+/*
122+ * the structures below follow hardware/firmware layouts in the 8xx manuals:
123+ * mind the data types, offsets and alignment
124+ */
125+
126+/*
127+ * basic IO controller parameters (SMC and SCC)
128+ */
129+typedef struct IOCparam IOCparam;
130+struct IOCparam {
131+ ushort rbase;
132+ ushort tbase;
133+ uchar rfcr;
134+ uchar tfcr;
135+ ushort mrblr;
136+ ulong rstate;
137+ ulong rptr;
138+ ushort rbptr;
139+ ushort rcnt;
140+ ulong rtmp;
141+ ulong tstate;
142+ ulong tptr;
143+ ushort tbptr;
144+ ushort tcnt;
145+ ulong ttmp;
146+};
147+
148+typedef struct SCCparam SCCparam;
149+struct SCCparam {
150+ IOCparam;
151+ ulong rcrc;
152+ ulong tcrc;
153+};
154+
155+typedef struct SCC SCC;
156+struct SCC {
157+ ulong gsmrl;
158+ ulong gsmrh;
159+ ushort psmr;
160+ uchar rsvscc0[2];
161+ ushort todr;
162+ ushort dsr;
163+ ushort scce;
164+ uchar rsvscc1[2];
165+ ushort sccm;
166+ uchar rsvscc3;
167+ uchar sccs;
168+ ushort irmode;
169+ ushort irsip;
170+};
171+
172+typedef struct SMC SMC;
173+struct SMC {
174+ uchar pad1[2];
175+ ushort smcmr;
176+ uchar pad2[2];
177+ uchar smce;
178+ uchar pad3[3];
179+ uchar smcm;
180+ uchar pad4[5];
181+};
182+
183+typedef struct SPI SPI;
184+struct SPI {
185+ ushort spmode;
186+ uchar res1[4];
187+ uchar spie;
188+ uchar res2[3];
189+ uchar spim;
190+ uchar res3[2];
191+ uchar spcom;
192+ uchar res4[10];
193+};
194+
195+typedef struct USB USB;
196+struct USB { /* 823 only */
197+ uchar usmod;
198+ uchar usadr;
199+ uchar uscom;
200+ uchar rsvu1;
201+ ushort usep[4];
202+ uchar rsvu2[4];
203+ ushort usber;
204+ uchar rsvu3[2];
205+ ushort usbmr;
206+ uchar rsvu4;
207+ uchar usbs;
208+ uchar rsvu5[8];
209+};
210+
211+typedef struct IMM IMM;
212+struct IMM {
213+ struct { /* general SIU */
214+ ulong siumcr;
215+ ulong sypcr;
216+ uchar rsv0[0xE-0x8];
217+ ushort swsr;
218+ ulong sipend;
219+ ulong simask;
220+ ulong siel;
221+ uchar sivec;
222+ uchar padv[3];
223+ ulong tesr;
224+ uchar rsv1[0x30-0x24];
225+ ulong sdcr;
226+ uchar rsv2[0x80-0x34];
227+ };
228+ struct { /* PCMCIA */
229+ struct {
230+ ulong base;
231+ ulong option;
232+ } pcmr[8];
233+ uchar rsv3[0xe0-0xc0];
234+ ulong pgcra;
235+ ulong pgcrb;
236+ ulong pscr;
237+ uchar rsv4[0xf0-0xec];
238+ ulong pipr;
239+ uchar rsv5[4];
240+ ulong per;
241+ uchar rsv6[4];
242+ };
243+ struct { /* MEMC */
244+ struct {
245+ ulong base;
246+ ulong option;
247+ } memc[8];
248+ uchar rsv7a[0x24];
249+ ulong mar;
250+ ulong mcr;
251+ uchar rsv7b[4];
252+ ulong mamr;
253+ ulong mbmr;
254+ ushort mstat;
255+ ushort mptpr;
256+ ulong mdr;
257+ uchar rsv7c[0x80];
258+ };
259+ struct { /* system integration timers */
260+ ushort tbscr;
261+ uchar rsv8a[2];
262+ ulong tbrefu;
263+ ulong tbrefl;
264+ uchar rsv8b[0x14];
265+ ushort rtcsc;
266+ uchar rsv8c[2];
267+ ulong rtc;
268+ ulong rtsec;
269+ ulong rtcal;
270+ uchar rsv8d[0x10];
271+ ushort piscr;
272+ ushort rsv8e;
273+ ulong pitc;
274+ ulong pitr;
275+ uchar rsv8f[0x34];
276+ };
277+ struct { /* 280: clocks and resets */
278+ ulong sccr;
279+ ulong plprcr;
280+ ulong rsr;
281+ uchar rsv9[0x300-0x28c];
282+ };
283+ struct { /* 300: system integration timers keys */
284+ ulong tbscrk;
285+ ulong tbrefuk;
286+ ulong tbreflk;
287+ ulong tbk;
288+ uchar rsv10a[0x10];
289+ ulong rtcsck;
290+ ulong rtck;
291+ ulong rtseck;
292+ ulong rtcalk;
293+ uchar rsv10b[0x10];
294+ ulong piscrk;
295+ ulong pitck;
296+ uchar rsv10c[0x38];
297+ };
298+ struct { /* 380: clocks and resets keys */
299+ ulong sccrk;
300+ ulong plprcrk;
301+ ulong rsrk;
302+ uchar rsv11[0x800-0x38C];
303+ };
304+ struct { /* 800: video controller */
305+ ushort vccr;
306+ ushort pad11a;
307+ uchar vsr;
308+ uchar pad11b;
309+ uchar vcmr;
310+ uchar pad11c;
311+ ulong vbcb;
312+ ulong pad11d;
313+ ulong vfcr0;
314+ ulong vfaa0;
315+ ulong vfba0;
316+ ulong vfcr1;
317+ ulong vfaa1;
318+ ulong vfba1;
319+ uchar rsv11a[0x840-0x828];
320+ };
321+ struct { /* 840: LCD */
322+ ulong lccr;
323+ ulong lchcr;
324+ ulong lcvcr;
325+ ulong rsv11b;
326+ ulong lcfaa;
327+ ulong lcfba;
328+ uchar lcsr;
329+ uchar rsv11c[0x860-0x859];
330+ };
331+ struct { /* 860: I2C */
332+ uchar i2mod;
333+ uchar rsv12a[3];
334+ uchar i2add;
335+ uchar rsv12b[3];
336+ uchar i2brg;
337+ uchar rsv12c[3];
338+ uchar i2com;
339+ uchar rsv12d[3];
340+ uchar i2cer;
341+ uchar rsv12e[3];
342+ uchar i2cmr;
343+ uchar rsv12[0x900-0x875];
344+ };
345+ struct { /* 900: DMA */
346+ uchar rsv13[4];
347+ ulong sdar;
348+ uchar sdsr;
349+ uchar pad1[3];
350+ uchar sdmr;
351+ uchar pad2[3];
352+ uchar idsr1;
353+ uchar pad3[3];
354+ uchar idmr1;
355+ uchar pad4[3];
356+ uchar idsr2;
357+ uchar pad5[3];
358+ uchar idmr2;
359+ uchar pad6[0x930-0x91D];
360+ };
361+ struct { /* CPM interrupt control */
362+ ushort civr;
363+ uchar pad7[0x940-0x932];
364+ ulong cicr;
365+ ulong cipr;
366+ ulong cimr;
367+ ulong cisr;
368+ };
369+ struct { /* input/output port */
370+ ushort padir;
371+ ushort papar;
372+ ushort paodr;
373+ ushort padat;
374+ uchar pad8[8];
375+ ushort pcdir;
376+ ushort pcpar;
377+ ushort pcso;
378+ ushort pcdat;
379+ ushort pcint;
380+ uchar pad9[6];
381+ ushort pddir;
382+ ushort pdpar;
383+ ushort rsv14a;
384+ ushort pddat;
385+ uchar rsv14[0x980-0x978];
386+ };
387+ struct { /* CPM timers */
388+ ushort tgcr;
389+ uchar rsv15a[0x990-0x982];
390+ ushort tmr1;
391+ ushort tmr2;
392+ ushort trr1;
393+ ushort trr2;
394+ ushort tcr1;
395+ ushort tcr2;
396+ ushort tcn1;
397+ ushort tcn2;
398+ ushort tmr3;
399+ ushort tmr4;
400+ ushort trr3;
401+ ushort trr4;
402+ ushort tcr3;
403+ ushort tcr4;
404+ ushort tcn3;
405+ ushort tcn4;
406+ ushort ter1;
407+ ushort ter2;
408+ ushort ter3;
409+ ushort ter4;
410+ uchar rsv15[0x9C0-0x9B8];
411+ };
412+ struct { /* CPM */
413+ ushort cpcr;
414+ uchar res0[2];
415+ ushort rccr;
416+ uchar res1;
417+ uchar rmds;
418+ uchar res2a[4];
419+ ushort rctr1;
420+ ushort rctr2;
421+ ushort rctr3;
422+ ushort rctr4;
423+ uchar res2[2];
424+ ushort rter;
425+ uchar res3[2];
426+ ushort rtmr;
427+ uchar rsv16[0x9F0-0x9DC];
428+ };
429+ union { /* BRG */
430+ struct {
431+ ulong brgc1;
432+ ulong brgc2;
433+ ulong brgc3;
434+ ulong brgc4;
435+ };
436+ ulong brgc[4];
437+ };
438+ uchar skip0[0xAB2-0xA00]; /* USB, SCC, SMC, SPI: address using cpmdev(CP...)->regs */
439+ struct { /* PIP */
440+ ushort pipc; /* not 823 */
441+ ushort ptpr; /* not 823 */
442+ ulong pbdir;
443+ ulong pbpar;
444+ uchar pad10[2];
445+ ushort pbodr;
446+ ulong pbdat;
447+ uchar pad11[0xAE0-0xAC8];
448+ };
449+ struct { /* SI */
450+ ulong simode;
451+ uchar sigmr;
452+ uchar pad12;
453+ uchar sistr;
454+ uchar sicmr;
455+ uchar pad13[4];
456+ ulong sicr;
457+ ulong sirp;
458+ uchar pad14[0xB00-0xAF4];
459+ };
460+ ulong vcram[64];
461+ ushort siram[256];
462+ ushort lcdmap[256];
463+};
os/boot/mpc/ip.h+98−0
@@ -0,0 +1,98 @@
1+typedef struct Udphdr Udphdr;
2+struct Udphdr
3+{
4+ uchar d[6]; /* Ethernet destination */
5+ uchar s[6]; /* Ethernet source */
6+ uchar type[2]; /* Ethernet packet type */
7+
8+ uchar vihl; /* Version and header length */
9+ uchar tos; /* Type of service */
10+ uchar length[2]; /* packet length */
11+ uchar id[2]; /* Identification */
12+ uchar frag[2]; /* Fragment information */
13+
14+ /* Udp pseudo ip really starts here */
15+ uchar ttl;
16+ uchar udpproto; /* Protocol */
17+ uchar udpplen[2]; /* Header plus data length */
18+ uchar udpsrc[4]; /* Ip source */
19+ uchar udpdst[4]; /* Ip destination */
20+ uchar udpsport[2]; /* Source port */
21+ uchar udpdport[2]; /* Destination port */
22+ uchar udplen[2]; /* data length */
23+ uchar udpcksum[2]; /* Checksum */
24+};
25+
26+typedef struct Etherhdr Etherhdr;
27+struct Etherhdr
28+{
29+ uchar d[6];
30+ uchar s[6];
31+ uchar type[2];
32+
33+ /* Now we have the ip fields */
34+ uchar vihl; /* Version and header length */
35+ uchar tos; /* Type of service */
36+ uchar length[2]; /* packet length */
37+ uchar id[2]; /* Identification */
38+ uchar frag[2]; /* Fragment information */
39+ uchar ttl; /* Time to live */
40+ uchar proto; /* Protocol */
41+ uchar cksum[2]; /* Header checksum */
42+ uchar src[4]; /* Ip source */
43+ uchar dst[4]; /* Ip destination */
44+};
45+
46+enum
47+{
48+ IP_VER = 0x40,
49+ IP_HLEN = 0x05,
50+ UDP_EHSIZE = 22,
51+ UDP_PHDRSIZE = 12,
52+ UDP_HDRSIZE = 20,
53+ ETHER_HDR = 14,
54+ IP_UDPPROTO = 17,
55+ ET_IP = 0x800,
56+ Bcastip = 0xffffffff,
57+ BPportsrc = 68,
58+ BPportdst = 67,
59+ TFTPport = 69,
60+ Timeout = 5000, /* milliseconds */
61+ Bootrequest = 1,
62+ Bootreply = 2,
63+ Tftp_READ = 1,
64+ Tftp_WRITE = 2,
65+ Tftp_DATA = 3,
66+ Tftp_ACK = 4,
67+ Tftp_ERROR = 5,
68+ Segsize = 512,
69+ TFTPSZ = Segsize+10,
70+};
71+
72+typedef struct Bootp Bootp;
73+struct Bootp
74+{
75+ uchar op; /* opcode */
76+ uchar htype; /* hardware type */
77+ uchar hlen; /* hardware address len */
78+ uchar hops; /* hops */
79+ uchar xid[4]; /* a random number */
80+ uchar secs[2]; /* elapsed snce client started booting */
81+ uchar pad[2];
82+ uchar ciaddr[4]; /* client IP address (client tells server) */
83+ uchar yiaddr[4]; /* client IP address (server tells client) */
84+ uchar siaddr[4]; /* server IP address */
85+ uchar giaddr[4]; /* gateway IP address */
86+ uchar chaddr[16]; /* client hardware address */
87+ char sname[64]; /* server host name (optional) */
88+ char file[128]; /* boot file name */
89+ char vend[128]; /* vendor-specific goo */
90+};
91+
92+typedef struct Netaddr Netaddr;
93+struct Netaddr
94+{
95+ ulong ip;
96+ ushort port;
97+ char ea[Eaddrlen];
98+};
os/boot/mpc/l.s+370−0
@@ -0,0 +1,370 @@
1+#include "mem.h"
2+
3+/* special instruction definitions */
4+#define BDNE BC 0,2,
5+#define BDNZ BC 16,0,
6+#define NOOP OR R0,R0,R0
7+
8+/*
9+ * common ppc special purpose registers
10+ */
11+#define DSISR 18
12+#define DAR 19 /* Data Address Register */
13+#define DEC 22 /* Decrementer */
14+#define SRR0 26 /* Saved Registers (exception) */
15+#define SRR1 27
16+#define SPRG0 272 /* Supervisor Private Registers */
17+#define SPRG1 273
18+#define SPRG2 274
19+#define SPRG3 275
20+#define TBRU 269 /* Time base Upper/Lower (Reading) */
21+#define TBRL 268
22+#define TBWU 285 /* Time base Upper/Lower (Writing) */
23+#define TBWL 284
24+#define PVR 287 /* Processor Version */
25+
26+/*
27+ * mpc82x-specific special purpose registers of interest here
28+ */
29+#define EIE 80
30+#define EID 81
31+#define NRI 82
32+#define IMMR 638
33+#define IC_CST 560
34+#define IC_ADR 561
35+#define IC_DAT 562
36+#define DC_CST 568
37+#define DC_ADR 569
38+#define DC_DAT 570
39+#define MI_CTR 784
40+#define MI_AP 786
41+#define MI_EPN 787
42+#define MI_TWC 789
43+#define MI_RPN 790
44+#define MI_DBCAM 816
45+#define MI_DBRAM0 817
46+#define MI_DBRAM1 818
47+#define MD_CTR 792
48+#define M_CASID 793
49+#define MD_AP 794
50+#define MD_EPN 795
51+#define M_TWB 796
52+#define MD_TWC 797
53+#define MD_RPN 798
54+#define M_TW 799
55+#define MD_DBCAM 824
56+#define MD_DBRAM0 825
57+#define MD_DBRAM1 826
58+
59+/* as on 603e, apparently mtmsr needs help in some chip revisions */
60+#define WAITMSR SYNC; ISYNC
61+
62+/* use of SPRG registers in save/restore */
63+#define SAVER0 SPRG0
64+#define SAVER1 SPRG1
65+#define SAVELR SPRG2
66+#define SAVECR SPRG3
67+
68+#define UREGSIZE ((8+32)*4)
69+#define UREGSPACE (UREGSIZE+8) /* allow for arg to trap, and align */
70+
71+/*
72+ * This code is loaded by the ROM loader at location 0x3000,
73+ * or lives in flash memory at 0x2800100.
74+ * Move it to high memory so that it can load the kernel at 0x0000.
75+ */
76+
77+#define LOADCODEBASE 0x3000 /* when downloaded in S records */
78+#define FLASHCODEBASE (FLASHMEM+0x100) /* when in flash */
79+
80+ TEXT start(SB), $-4
81+ MOVW MSR, R3
82+ MOVW $(EE|IP|RI), R4
83+ ANDN R4, R3
84+ OR $ME, R3
85+ SYNC
86+ MOVW R3, MSR /* turn off interrupts but enable traps */
87+ WAITMSR
88+
89+/*
90+ * reset the caches and disable them for now
91+ */
92+ MOVW SPR(IC_CST), R4 /* read and clear */
93+ MOVW $(5<<25), R4
94+ MOVW R4, SPR(IC_CST) /* unlock all */
95+ ISYNC
96+ MOVW $(6<<25), R4
97+ MOVW R4, SPR(IC_CST) /* invalidate all */
98+ ISYNC
99+ MOVW $(2<<25), R4
100+ MOVW R4, SPR(IC_CST) /* disable i-cache */
101+ ISYNC
102+
103+ SYNC
104+ MOVW SPR(DC_CST), R4 /* read and clear */
105+ MOVW $(10<<24), R4
106+ MOVW R4, SPR(DC_CST) /* unlock all */
107+ ISYNC
108+ MOVW $(12<<24), R4
109+ MOVW R4, SPR(DC_CST) /* invalidate all */
110+ ISYNC
111+ MOVW $(4<<24), R4
112+ MOVW R4, SPR(DC_CST) /* disable i-cache */
113+ ISYNC
114+
115+ MOVW $7, R4
116+ANDN R4, R4, R4
117+ MOVW R4, SPR(158) /* cancel `show cycle' for normal instruction execution */
118+
119+/*
120+ * set other system configuration values
121+ */
122+ MOVW SPR(IMMR), R5 /* save initial space pointer */
123+ MOVW $INTMEM, R4
124+ MOVW R4, SPR(IMMR) /* set internal memory base */
125+ MOVW $0xFFFFFF88, R3
126+ MOVW R3, 4(R4) /* disable watchdog in sypcr */
127+ MOVW $0x01012440, R3
128+ MOVW R3, 0(R4) /* siumcr */
129+
130+/*
131+ * system initialisation (init and map DRAM)
132+ */
133+ MOVW $0, R0
134+ MOVW $setSB(SB), R2
135+ MOVW $(0xF000<<16), R3
136+/*MOVW R0, R3*/
137+ ANDCC R5, R3 /* initial space is high? */
138+ BEQ notrom
139+ MOVW $FLASHCODEBASE, R5 /* where $start(SB) actually is now */
140+ MOVW $start(SB), R4 /* logical start address */
141+ SUB R4, R5, R6 /* text relocation value */
142+ MOVW $etext(SB), R7
143+ SUB R4, R7
144+ ADD R5, R7 /* data address in ROM */
145+ MOVW $bdata(SB), R8
146+ SUB R8, R2
147+ ADD R7, R2 /* relocate SB: SB' = romdata+(SB-bdata) */
148+ MOVW $sysinit0(SB), R4
149+ ADD R6, R4 /* relocate sysinit0's address */
150+ MOVW R4, CTR
151+ MOVW $inmem(SB), R4
152+ ADD R6, R4
153+ MOVW R4, LR /* and the return address */
154+ BR (CTR) /* call sysinit0 */
155+ TEXT inmem(SB), $-4
156+ MOVW $FLASHCODEBASE, R3
157+ BR cpu0
158+notrom:
159+ MOVW $start(SB), R6
160+ SUB R6, R2
161+ ADD $LOADCODEBASE, R2
162+ BL sysinit0(SB)
163+ MOVW $LOADCODEBASE, R3
164+
165+/*
166+ * cpu 0
167+ * relocate bootstrap to our link addresses for text and data
168+ * set new PC
169+ */
170+cpu0:
171+ MOVW $setSB(SB), R2 /* set correct static base register */
172+ MOVW $start(SB), R4
173+ MOVW $etext(SB), R5
174+ SUB R4, R5
175+ CMP R4, R3 /* already there? */
176+ BNE copytext
177+ ADD R5, R3 /* start of data image */
178+ BR copydata
179+
180+copytext:
181+ ADD $3, R5
182+ SRAW $2, R5
183+ MOVW R5, CTR
184+ SUB $4, R4
185+ SUB $4, R3
186+copyt: /* copy text */
187+ MOVWU 4(R3), R5
188+ MOVWU R5, 4(R4)
189+ BDNZ copyt
190+ ADD $4, R3
191+
192+copydata:
193+ /* copy data */
194+ MOVW $bdata(SB), R4
195+ CMP R4, R3 /* already there? */
196+ BEQ loadkpc
197+ MOVW $edata(SB), R5
198+ SUB R4, R5
199+ ADD $3, R5
200+ SRAW $2, R5
201+ MOVW R5, CTR
202+ SUB $4, R4
203+ SUB $4, R3
204+copyd:
205+ MOVWU 4(R3), R5
206+ MOVWU R5, 4(R4)
207+ BDNZ copyd
208+
209+ /* load correct PC */
210+loadkpc:
211+ MOVW $start1(SB), R3
212+ MOVW R3, LR
213+ BR (LR)
214+TEXT start1(SB), $-4
215+ MOVW $edata(SB), R3
216+ MOVW $end(SB), R4
217+ SUBCC R3, R4
218+ BLE skipz
219+ SRAW $2, R4
220+ MOVW R4, CTR
221+ SUB $4, R3
222+ MOVW $0, R0
223+zero:
224+ MOVWU R0, 4(R3)
225+ BDNZ zero
226+skipz:
227+ MOVW $mach0(SB), R1
228+ MOVW R1, m(SB)
229+ ADD $(MACHSIZE-8), R1
230+ MOVW $0, R0
231+ BL main(SB)
232+ BR 0(PC)
233+
234+TEXT getmsr(SB), $0
235+ MOVW MSR, R3
236+ RETURN
237+
238+TEXT putmsr(SB), $0
239+ SYNC
240+ MOVW R3, MSR
241+ WAITMSR
242+ RETURN
243+
244+TEXT eieio(SB), $0
245+ EIEIO
246+ RETURN
247+
248+TEXT idle(SB), $0
249+ RETURN
250+
251+TEXT spllo(SB), $0
252+ MOVW MSR, R3
253+ OR $EE, R3, R4
254+ SYNC
255+ MOVW R4, MSR
256+ WAITMSR
257+ RETURN
258+
259+TEXT splhi(SB), $0
260+ MOVW MSR, R3
261+ RLWNM $0, R3, $~EE, R4
262+ SYNC
263+ MOVW R4, MSR
264+ WAITMSR
265+ RETURN
266+
267+TEXT splx(SB), $0
268+ MOVW MSR, R4
269+ RLWMI $0, R3, $EE, R4
270+ SYNC
271+ MOVW R4, MSR
272+ WAITMSR
273+ RETURN
274+
275+TEXT gettbl(SB), $0
276+/* MOVW SPR(TBRL), R3 */
277+ WORD $0x7c6c42e6 /* mftbl on 8xx series */
278+ RETURN
279+
280+TEXT getpvr(SB), $0
281+ MOVW SPR(PVR), R3
282+ RETURN
283+
284+TEXT getimmr(SB), $0
285+ MOVW SPR(IMMR), R3
286+ RETURN
287+
288+TEXT getdec(SB), $0
289+ MOVW SPR(DEC), R3
290+ RETURN
291+
292+TEXT putdec(SB), $0
293+ MOVW R3, SPR(DEC)
294+ RETURN
295+
296+/*
297+ * save state in Ureg on kernel stack.
298+ * enter with R0 giving the PC from the call to `exception' from the vector.
299+ * on return, SB (R2) has been set, and R3 has the Ureg*
300+ */
301+TEXT saveureg(SB), $-4
302+ SUB $UREGSPACE, R1
303+ MOVMW R2, 48(R1) /* r2:r31 */
304+ MOVW $setSB(SB), R2
305+ MOVW SPR(SAVER1), R4
306+ MOVW R4, 44(R1)
307+ MOVW SPR(SAVER0), R5
308+ MOVW R5, 40(R1)
309+ MOVW CTR, R6
310+ MOVW R6, 36(R1)
311+ MOVW XER, R4
312+ MOVW R4, 32(R1)
313+ MOVW SPR(SAVECR), R5 /* CR */
314+ MOVW R5, 28(R1)
315+ MOVW SPR(SAVELR), R6 /* LR */
316+ MOVW R6, 24(R1)
317+ /* pad at 20(R1) */
318+ MOVW SPR(SRR0), R4
319+ MOVW R4, 16(R1) /* old PC */
320+ MOVW SPR(SRR1), R5
321+ MOVW R5, 12(R1)
322+ MOVW R0, 8(R1) /* cause/vector, encoded in LR from vector */
323+ ADD $8, R1, R3 /* Ureg* */
324+ STWCCC R3, (R1) /* break any pending reservations */
325+ MOVW $0, R0 /* R0ISZERO */
326+ BR (LR)
327+
328+/*
329+ * restore state from Ureg
330+ * SB (R2) is unusable on return
331+ */
332+TEXT restoreureg(SB), $-4
333+ MOVMW 48(R1), R2 /* r2:r31 */
334+ /* defer R1 */
335+ MOVW 40(R1), R0
336+ MOVW R0, SPR(SAVER0)
337+ MOVW 36(R1), R0
338+ MOVW R0, CTR
339+ MOVW 32(R1), R0
340+ MOVW R0, XER
341+ MOVW 28(R1), R0
342+ MOVW R0, CR /* CR */
343+ MOVW 24(R1), R0
344+ MOVW R0, SPR(SAVELR) /* LR */
345+ /* pad, skip */
346+ MOVW 16(R1), R0
347+ MOVW R0, SPR(SRR0) /* old PC */
348+ MOVW 12(R1), R0
349+ MOVW R0, SPR(SRR1) /* old MSR */
350+ /* cause, skip */
351+ MOVW 44(R1), R1 /* old SP */
352+ BR (LR)
353+
354+TEXT exception(SB), $-4
355+ MOVW R1, SPR(SAVER1)
356+ MOVW CR, R0
357+ MOVW R0, SPR(SAVECR)
358+ MOVW LR, R0
359+ BL saveureg(SB)
360+ MOVW $0, R0
361+ BL trap(SB)
362+ BL restoreureg(SB)
363+ MOVW SPR(SAVELR), R0
364+ MOVW R0, LR
365+ MOVW SPR(SAVER0), R0
366+ ISYNC
367+ RFI
368+
369+GLOBL mach0+0(SB), $MACHSIZE
370+GLOBL m(SB), $4
os/boot/mpc/lib.h+106−0
@@ -0,0 +1,106 @@
1+/*
2+ * functions (possibly) linked in, complete, from libc.
3+ */
4+
5+/*
6+ * mem routines
7+ */
8+extern void* memccpy(void*, void*, int, long);
9+extern void* memset(void*, int, long);
10+extern int memcmp(void*, void*, long);
11+extern void* memmove(void*, void*, long);
12+extern void* memchr(void*, int, long);
13+
14+/*
15+ * string routines
16+ */
17+extern char* strcat(char*, char*);
18+extern char* strchr(char*, char);
19+extern int strcmp(char*, char*);
20+extern char* strcpy(char*, char*);
21+extern char* strncat(char*, char*, long);
22+extern char* strncpy(char*, char*, long);
23+extern int strncmp(char*, char*, long);
24+extern long strlen(char*);
25+extern char* strrchr(char*, char);
26+extern char* strstr(char*, char*);
27+
28+/*
29+ * print routines
30+ * Fconv isn't used but is defined to satisfy prototypes in libg.h
31+ * that are never called.
32+ */
33+typedef struct Fconv Fconv;
34+
35+extern char* donprint(char*, char*, char*, void*);
36+extern int sprint(char*, char*, ...);
37+extern int print(char*, ...);
38+
39+#define PRINTSIZE 256
40+
41+/*
42+ * one-of-a-kind
43+ */
44+extern int atoi(char*);
45+extern long strtol(char*, char**, int);
46+extern ulong strtoul(char*, char**, int);
47+extern long end;
48+
49+/*
50+ * Syscall data structures
51+ */
52+
53+#define MORDER 0x0003 /* mask for bits defining order of mounting */
54+#define MREPL 0x0000 /* mount replaces object */
55+#define MBEFORE 0x0001 /* mount goes before others in union directory */
56+#define MAFTER 0x0002 /* mount goes after others in union directory */
57+#define MCREATE 0x0004 /* permit creation in mounted directory */
58+#define MMASK 0x0007 /* all bits on */
59+
60+#define OREAD 0 /* open for read */
61+#define OWRITE 1 /* write */
62+#define ORDWR 2 /* read and write */
63+#define OEXEC 3 /* execute, == read but check execute permission */
64+#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
65+#define OCEXEC 32 /* or'ed in, close on exec */
66+#define ORCLOSE 64 /* or'ed in, remove on close */
67+
68+#define NCONT 0 /* continue after note */
69+#define NDFLT 1 /* terminate after note */
70+
71+typedef struct Qid Qid;
72+typedef struct Dir Dir;
73+typedef struct Waitmsg Waitmsg;
74+
75+#define ERRLEN 64
76+#define DIRLEN 116
77+#define NAMELEN 28
78+
79+struct Qid
80+{
81+ ulong path;
82+ ulong vers;
83+};
84+
85+struct Dir
86+{
87+ char name[NAMELEN];
88+ char uid[NAMELEN];
89+ char gid[NAMELEN];
90+ Qid qid;
91+ ulong mode;
92+ long atime;
93+ long mtime;
94+ vlong length;
95+ short type;
96+ short dev;
97+};
98+
99+struct Waitmsg
100+{
101+ int pid; /* of loved one */
102+ int status; /* unused; a placeholder */
103+ ulong time[3]; /* of loved one */
104+ char msg[ERRLEN];
105+};
106+#define nelem(x) (sizeof(x)/sizeof((x)[0]))
os/boot/mpc/main.c+524−0
@@ -0,0 +1,524 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+#include "dosfs.h"
9+
10+typedef struct Type Type;
11+typedef struct Medium Medium;
12+typedef struct Mode Mode;
13+
14+enum {
15+ Dany = -1,
16+ Nmedia = 16,
17+
18+ /* DS1 switch options */
19+ Sflashfs = 1<<0, /* take local fs from flash */
20+ Snotflash = 1<<1, /* don't boot from flash */
21+};
22+
23+enum { /* type */
24+ Tflash,
25+ Tuart,
26+ Tether,
27+ Thard,
28+
29+ Tany = -1,
30+};
31+
32+enum { /* flag and name */
33+ Fnone = 0x00,
34+
35+ Fdos = 0x01,
36+ Ndos = 0x00,
37+ Fboot = 0x02,
38+ Nboot = 0x01,
39+ Fbootp = 0x04,
40+ Nbootp = 0x02,
41+ Fflash = 0x08,
42+ Fuart = 0x10,
43+ NName = 0x03,
44+
45+ Fany = Fbootp|Fboot|Fdos|Fflash|Fuart,
46+
47+ Fini = 0x10,
48+ Fprobe = 0x80,
49+};
50+
51+enum { /* mode */
52+ Mauto = 0x00,
53+ Mlocal = 0x01,
54+ Manual = 0x02,
55+ NMode = 0x03,
56+};
57+
58+typedef struct Type {
59+ int type;
60+ char *cname;
61+ int flag;
62+ int (*init)(void);
63+ long (*read)(int, void*, long);
64+ long (*seek)(int, long);
65+ Partition* (*setpart)(int, char*);
66+ char* name[NName];
67+
68+ int mask;
69+ Medium* media;
70+} Type;
71+
72+typedef struct Medium {
73+ Type* type;
74+ int flag;
75+ Partition* partition;
76+ Dos;
77+
78+ Medium* next;
79+} Medium;
80+
81+typedef struct Mode {
82+ char* name;
83+ int mode;
84+} Mode;
85+
86+static Type types[] = {
87+ { Tflash, "flash",
88+ Fflash,
89+ flashinit, 0, 0, 0,
90+ { 0, "F", 0, }
91+ },
92+/*
93+ { Tuart, "uart",
94+ Fuart|Fboot,
95+ uartinit, uartread, uartseek, setuartpart,
96+ { 0, "u", 0, }
97+ },
98+*/
99+ { Tether, "ether",
100+ Fbootp,
101+ etherinit, 0, 0, 0,
102+ { 0, 0, "e", },
103+ },
104+ { Thard, "ata",
105+ Fini|Fboot|Fdos,
106+ 0, 0, 0, 0, /* not used now, will be later with PCMCIA */
107+ { "hd", "h", 0, },
108+ },
109+ {-1},
110+};
111+
112+static Medium media[Nmedia];
113+static Medium *curmedium = media;
114+
115+static Mode modes[NMode+1] = {
116+ [Mauto] { "auto", Mauto, },
117+ [Mlocal] { "local", Mlocal, },
118+ [Manual] { "manual", Manual, },
119+};
120+
121+static char *inis[] = {
122+ "inferno/inferno.ini",
123+ "inferno.ini",
124+ "plan9/plan9.ini",
125+ "plan9.ini",
126+ 0,
127+};
128+char **ini;
129+int predawn;
130+
131+static int
132+parse(char *line, int *type, int *flag, int *dev, char *file)
133+{
134+ Type *tp;
135+ char buf[2*NAMELEN], *v[4], *p;
136+ int i;
137+
138+ strcpy(buf, line);
139+ switch(getcfields(buf, v, 4, "!")){
140+
141+ case 3:
142+ break;
143+
144+ case 2:
145+ v[2] = "";
146+ break;
147+
148+ default:
149+ return 0;
150+ }
151+
152+ *flag = 0;
153+ for(tp = types; tp->cname; tp++){
154+ for(i = 0; i < NName; i++){
155+
156+ if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
157+ continue;
158+ *type = tp->type;
159+ *flag |= 1<<i;
160+
161+ if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
162+ return 0;
163+
164+ strcpy(file, v[2]);
165+
166+ return 1;
167+ }
168+ }
169+
170+ return 0;
171+
172+}
173+
174+static int
175+boot(Medium *mp, int flag, char *file)
176+{
177+ Dosfile df;
178+ char ixdos[128], *p;
179+ int r;
180+
181+ uartsetboot(0);
182+ if(flag & Fbootp){
183+ sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
184+ return bootp(mp->dev, file);
185+ }
186+
187+ if(flag & Fflash){
188+ if(mp->flag & Fflash && flashbootable(0))
189+ flashboot(mp->dev);
190+ }
191+
192+ if(flag & Fboot){
193+
194+ if(mp->flag & Fini){
195+ (*mp->type->setpart)(mp->dev, "disk");
196+ plan9ini(mp, nil);
197+ }
198+ if(file == 0 || *file == 0)
199+ file = mp->partition->name;
200+ (*mp->type->setpart)(mp->dev, file);
201+ sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
202+ r = plan9boot(mp->dev, mp->seek, mp->read);
203+ uartsetboot(0);
204+ return r;
205+ }
206+
207+ if(flag & Fdos){
208+ if(mp->type->setpart)
209+ (*mp->type->setpart)(mp->dev, "disk");
210+ if(mp->flag & Fini)
211+ plan9ini(mp, nil);
212+ if(file == 0 || *file == 0){
213+ strcpy(ixdos, *ini);
214+ if(p = strrchr(ixdos, '/'))
215+ p++;
216+ else
217+ p = ixdos;
218+ strcpy(p, "impc");
219+ if(dosstat(mp, ixdos, &df) <= 0)
220+ return -1;
221+ }
222+ else
223+ strcpy(ixdos, file);
224+ sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
225+ return dosboot(mp, ixdos);
226+ }
227+
228+ return -1;
229+}
230+
231+static Medium*
232+allocm(Type *tp)
233+{
234+ Medium **l;
235+
236+ if(curmedium >= &media[Nmedia])
237+ return 0;
238+
239+ for(l = &tp->media; *l; l = &(*l)->next)
240+ ;
241+ *l = curmedium++;
242+ return *l;
243+}
244+
245+Medium*
246+probe(int type, int flag, int dev)
247+{
248+ Type *tp;
249+ int dombr, i, start;
250+ Medium *mp;
251+ Dosfile df;
252+ Partition *pp;
253+
254+ for(tp = types; tp->cname; tp++){
255+ if(type != Tany && type != tp->type || tp->init == 0)
256+ continue;
257+
258+ if(flag != Fnone){
259+ for(mp = tp->media; mp; mp = mp->next){
260+ if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
261+ return mp;
262+ }
263+ }
264+ if((tp->flag & Fprobe) == 0){
265+ tp->flag |= Fprobe;
266+ tp->mask = (*tp->init)();
267+ }
268+
269+ for(i = 0; tp->mask; i++){
270+ if((tp->mask & (1<<i)) == 0)
271+ continue;
272+ tp->mask &= ~(1<<i);
273+
274+ if((mp = allocm(tp)) == 0)
275+ continue;
276+
277+ mp->dev = i;
278+ mp->flag = tp->flag;
279+ mp->seek = tp->seek;
280+ mp->read = tp->read;
281+ mp->type = tp;
282+
283+ if(mp->flag & Fboot){
284+ if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
285+ mp->flag &= ~Fboot;
286+ if((mp->flag & (Fflash|Fuart)) == 0)
287+ (*tp->setpart)(i, "disk");
288+ }
289+
290+ if(mp->flag & Fdos){
291+ start = 0;
292+ dombr = 1;
293+ if(mp->type->setpart){
294+ if(pp = (*mp->type->setpart)(i, "dos")){
295+ if(start = pp->start)
296+ dombr = 0;
297+ }
298+ (*tp->setpart)(i, "disk");
299+ }
300+ if(dosinit(mp, start, dombr) < 0)
301+ mp->flag &= ~(Fini|Fdos);
302+ else
303+ print("dos init failed\n");
304+ }
305+
306+ if(mp->flag & Fini){
307+ mp->flag &= ~Fini;
308+ for(ini = inis; *ini; ini++){
309+ if(dosstat(mp, *ini, &df) <= 0)
310+ continue;
311+ mp->flag |= Fini;
312+ break;
313+ }
314+ }
315+
316+ if((flag & mp->flag) && (dev == Dany || dev == i))
317+ return mp;
318+ }
319+ }
320+
321+ return 0;
322+}
323+
324+void
325+main(void)
326+{
327+ Medium *mp;
328+ int dev, flag, i, mode, tried, type, options;
329+ char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
330+ Type *tp;
331+
332+ machinit();
333+ archinit();
334+ meminit();
335+ cpminit();
336+ trapinit();
337+ consinit(); /* screen and keyboard initially */
338+ screeninit();
339+ cpuidprint();
340+ alarminit();
341+ clockinit();
342+ predawn = 0;
343+ spllo();
344+ options = archoptionsw();
345+
346+ mp = 0;
347+ for(tp = types; tp->cname; tp++){
348+ if(tp->type == Tether)
349+ continue;
350+ if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
351+ plan9ini(mp, nil);
352+ break;
353+ }
354+ }
355+
356+ if(mp == 0 || (mp->flag & Fini) == 0)
357+ plan9ini(nil, flashconfig(0));
358+
359+ //consinit(); /* establish new console location */
360+
361+ if((options & Snotflash) == 0 && flashbootable(0)){
362+ print("Flash boot\n");
363+ flashboot(0);
364+ }
365+
366+ tried = 0;
367+ mode = Mauto;
368+ p = getconf("bootfile");
369+ flag = 0;
370+
371+ if(p != 0) {
372+ mode = Manual;
373+ for(i = 0; i < NMode; i++){
374+ if(strcmp(p, modes[i].name) == 0){
375+ mode = modes[i].mode;
376+ goto done;
377+ }
378+ }
379+ if(parse(p, &type, &flag, &dev, file) == 0) {
380+ print("Bad bootfile syntax: %s\n", p);
381+ goto done;
382+ }
383+ mp = probe(type, flag, dev);
384+ if(mp == 0) {
385+ print("Cannot access device: %s\n", p);
386+ goto done;
387+ }
388+ tried = boot(mp, flag, file);
389+ }
390+done:
391+ if(tried == 0 && mode != Manual){
392+ flag = Fany;
393+ if(mode == Mlocal)
394+ flag &= ~Fbootp;
395+ if(options & Snotflash)
396+ flag &= ~Fflash;
397+ if((mp = probe(Tany, flag, Dany)) != 0)
398+ boot(mp, flag & mp->flag, 0);
399+ }
400+
401+ def[0] = 0;
402+ probe(Tany, Fnone, Dany);
403+
404+ flag = 0;
405+ for(tp = types; tp->cname; tp++){
406+ for(mp = tp->media; mp; mp = mp->next){
407+ if(flag == 0){
408+ flag = 1;
409+ print("Boot devices:");
410+ }
411+
412+ if(mp->flag & Fbootp)
413+ print(" %s!%d", mp->type->name[Nbootp], mp->dev);
414+ if(mp->flag & Fdos)
415+ print(" %s!%d", mp->type->name[Ndos], mp->dev);
416+ if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot)
417+ print(" %s!%d", mp->type->name[Nboot], mp->dev);
418+ }
419+ }
420+ if(flag)
421+ print("\n");
422+
423+ for(;;){
424+ if(getstr("boot from", line, sizeof(line), def) >= 0){
425+ if(parse(line, &type, &flag, &dev, file)){
426+ if(mp = probe(type, flag, dev))
427+ boot(mp, flag, file);
428+ }
429+ }
430+ def[0] = 0;
431+ }
432+}
433+
434+void
435+machinit(void)
436+{
437+ memset(m, 0, sizeof(*m));
438+ m->delayloop = 20000;
439+ m->cpupvr = getpvr();
440+ m->iomem = KADDR(INTMEM);
441+}
442+
443+int
444+getcfields(char* lp, char** fields, int n, char* sep)
445+{
446+ int i;
447+
448+ for(i = 0; lp && *lp && i < n; i++){
449+ while(*lp && strchr(sep, *lp) != 0)
450+ *lp++ = 0;
451+ if(*lp == 0)
452+ break;
453+ fields[i] = lp;
454+ while(*lp && strchr(sep, *lp) == 0){
455+ if(*lp == '\\' && *(lp+1) == '\n')
456+ *lp++ = ' ';
457+ lp++;
458+ }
459+ }
460+
461+ return i;
462+}
463+
464+static Map memv[512];
465+static RMap rammap = {"physical memory"};
466+
467+void
468+meminit(void)
469+{
470+ ulong e;
471+
472+ mapinit(&rammap, memv, sizeof(memv));
473+ e = PADDR(&end);
474+ mapfree(&rammap, e, 4*1024*1024-e); /* fixed 4Mbytes is plenty for bootstrap */
475+}
476+
477+void*
478+ialloc(ulong n, int align)
479+{
480+ ulong a;
481+ int s;
482+
483+ if(align <= 0)
484+ align = 4;
485+ s = splhi();
486+ a = mapalloc(&rammap, 0, n, align);
487+ splx(s);
488+ if(a == 0)
489+ panic("ialloc");
490+ return memset(KADDR(a), 0, n);
491+}
492+
493+void*
494+malloc(ulong n)
495+{
496+ ulong *p;
497+
498+ n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
499+ p = ialloc(n, sizeof(int));
500+ *p++ = 0xcafebeef;
501+ *p++ = n;
502+ return p;
503+}
504+
505+void
506+free(void *ap)
507+{
508+ int s;
509+ ulong *p;
510+
511+ p = ap;
512+ if(p){
513+ if(*(p -= 2) != 0xcafebeef)
514+ panic("free");
515+ s = splhi();
516+ mapfree(&rammap, (ulong)p, p[1]);
517+ splx(s);
518+ }
519+}
520+
521+void
522+sched(void)
523+{
524+}
os/boot/mpc/mem.c+0−0

Empty file added.

os/boot/mpc/mem.h+95−0
@@ -0,0 +1,95 @@
1+/*
2+ * Memory and machine-specific definitions. Used in C and assembler.
3+ */
4+
5+/*
6+ * Sizes
7+ */
8+#define BI2BY 8 /* bits per byte */
9+#define BI2WD 32 /* bits per word */
10+#define BY2WD 4 /* bytes per word */
11+#define BY2PG 4096 /* bytes per page */
12+#define WD2PG (BY2PG/BY2WD) /* words per page */
13+#define PGSHIFT 12 /* log(BY2PG) */
14+#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
15+
16+#define MAXMACH 1 /* max # cpus system can run */
17+#define CACHELINELOG 4
18+#define CACHELINESZ (1<<CACHELINELOG)
19+
20+/*
21+ * Time
22+ */
23+#define HZ (50) /* clock frequency */
24+#define MS2HZ (1000/HZ) /* millisec per clock tick */
25+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
26+#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
27+#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
28+#define MHz 1000000
29+
30+/*
31+ * Fundamental values
32+ */
33+
34+#define KZERO 0 /* bootstrap runs in real mode */
35+#define MACHSIZE 4096
36+
37+/*
38+ * physical MMU
39+ */
40+#define KSEG0 0x20000000
41+#define KSEGM 0xE0000000 /* mask to check which seg */
42+
43+/*
44+ * MSR bits
45+ */
46+
47+#define POW 0x40000 /* enable power mgmt */
48+#define TGPR 0x20000 /* GPR0-3 remapped; 603/603e specific */
49+#define ILE 0x10000 /* interrupts little endian */
50+#define EE 0x08000 /* enable external/decrementer interrupts */
51+#define PR 0x04000 /* =1, user mode */
52+#define FPE 0x02000 /* enable floating point */
53+#define ME 0x01000 /* enable machine check exceptions */
54+#define FE0 0x00800
55+#define SE 0x00400 /* single-step trace */
56+#define BE 0x00200 /* branch trace */
57+#define FE1 0x00100
58+#define IP 0x00040 /* =0, vector to nnnnn; =1, vector to FFFnnnnn */
59+#define IR 0x00020 /* enable instruction address translation */
60+#define DR 0x00010 /* enable data address translation */
61+#define RI 0x00002 /* exception is recoverable */
62+#define LE 0x00001 /* little endian mode */
63+
64+#define KMSR (ME|FE0|FE1|FPE)
65+#define UMSR (KMSR|PR|EE|IR|DR)
66+
67+/*
68+ * MPC82x addresses; mpc8bug is happy with these
69+ */
70+#define BCSRMEM 0x02100000
71+#define INTMEM 0x02200000
72+#define FLASHMEM 0x02800000
73+#define SDRAMMEM 0x03000000
74+
75+#define DPRAM (INTMEM+0x2000)
76+#define DPLEN1 0x400
77+#define DPLEN2 0x200
78+#define DPLEN3 0x100
79+#define DPBASE (DPRAM+DPLEN1)
80+
81+#define SCC1P (INTMEM+0x3C00)
82+#define I2CP (INTMEM+0x3C80)
83+#define MISCP (INTMEM+0x3CB0)
84+#define IDMA1P (INTMEM+0x3CC0)
85+#define SCC2P (INTMEM+0x3D00)
86+#define SCC3P (INTMEM+0x3E00)
87+#define SCC4P (INTMEM+0x3F00)
88+#define SPIP (INTMEM+0x3D80)
89+#define TIMERP (INTMEM+0x3DB0)
90+#define SMC1P (INTMEM+0x3E80)
91+#define DSP1P (INTMEM+0x3EC0)
92+#define SMC2P (INTMEM+0x3F80)
93+#define DSP2P (INTMEM+0x3FC0)
94+
95+#define KEEP_ALIVE_KEY 0x55ccaa33 /* clock and rtc register key */
os/boot/mpc/mkfile+116−0
@@ -0,0 +1,116 @@
1+objtype=power
2+OBJTYPE=power # always
3+<../../../mkconfig
4+SYSTARG=$OSTARG # always
5+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
6+INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin #path of directory where kernel is installed
7+ARCH=fads # selects board dependent code
8+TARG=qb$ARCH
9+OFILES=\
10+ l.$O\
11+ arch$ARCH.$O\
12+ devuart.$O\
13+ uartboot.$O\
14+ alarm.$O\
15+ bootp.$O\
16+ clock.$O\
17+ conf.$O\
18+ console.$O\
19+ cpm.$O\
20+ defont0.$O\
21+ donprint.$O\
22+ dosboot.$O\
23+ devether.$O\
24+ etherscc.$O\
25+ fblt.$O\
26+ gbitbltclip.$O\
27+ flash.$O\
28+ main.$O\
29+ plan9boot.$O\
30+ qio.$O\
31+ rmap.$O\
32+ screen.$O\
33+ init$ARCH.$O\
34+ trap.$O\
35+ zqs.$O\
36+
37+HFILES=\
38+ boot.h\
39+ dat.h\
40+ fns.h\
41+ io.h\
42+ lib.h\
43+ mem.h\
44+ squeeze.h\
45+ gnot.h\
46+ arch$ARCH.h\
47+
48+LIBS=\
49+ kern\
50+
51+LIBDIRS=$LIBS
52+LIBNAMES=${LIBS:%=lib%.a}
53+LIBFILES=${LIBS:%=$ROOT/$TARGMODEL/$OBJTYPE/lib/lib%.a}
54+
55+#all:NV: $TARG k.mx f.mx
56+all:NV: $TARG
57+install:V: $INSTALLDIR/$TARG
58+installall:V: $INSTALLDIR/$TARG
59+
60+$INSTALLDIR/%: %
61+ rm -f $INSTALLDIR/$stem && cp $stem $INSTALLDIR/$stem
62+
63+$TARG: $OFILES $LIBNAMES
64+ $LD -o $target -l -T0x140000 -R4 $OFILES $LIBFILES
65+ ls -l $target
66+
67+qbrom$ARCH: $OFILES $LIBNAMES
68+ $LD -o $target -l -T0x02800100 -R0 -D0x140000 $OFILES $LIBFILES
69+
70+k.mx: $TARG
71+ ms2 -S 0x100 -a 0x100 -p 4 $TARG >k.mx
72+
73+f.mx: qbrom$ARCH
74+ ms2 -S 0x100 -a 0x2800100 -p 4 $prereq >f.mx
75+
76+%.$O: %.s
77+ $AS $stem.s
78+
79+%.$O: %.c
80+ $CC $CFLAGS $stem.c
81+
82+%.$O: $HFILES
83+
84+lib%.a:V: $SHELLTYPE-lib%.a
85+
86+rc-lib%.a nt-lib%.a:VQ:
87+ echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
88+ @{builtin cd $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
89+
90+sh-lib%.a:VQ:
91+ echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
92+ (cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
93+
94+clock.$O floppy.$O trap.$O: ureg.h
95+conf.$O dosboot.$O main.$O: dosfs.h
96+ether.$O etherscc.$O: etherif.h
97+bootp.$O: ip.h
98+
99+clean:V:
100+ rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG qboot k.mx f.mx romboot
101+
102+nuke-sh:QV:
103+ for i in $LIBDIRS
104+ do
105+ echo "(cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke)"
106+ (cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke)
107+ done
108+
109+nuke-rc nuke-nt:QV:
110+ for (i in $LIBDIRS)
111+ {
112+ echo '@{cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke}'
113+ @{cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke}
114+ }
115+
116+nuke:V: clean nuke-$SHELLTYPE
os/boot/mpc/ms2.c+179−0
@@ -0,0 +1,179 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <mach.h>
5+
6+void record(uchar*, int);
7+void usage(void);
8+void dosegment(long, int);
9+void trailer(ulong);
10+
11+enum
12+{
13+ Recordsize = 32,
14+};
15+
16+int dsegonly;
17+int supressend;
18+int binary;
19+int addr4;
20+ulong addr;
21+ulong psize = 4096;
22+ulong startaddr = 0x030000;
23+Biobuf stdout;
24+Biobuf bio;
25+
26+void
27+main(int argc, char **argv)
28+{
29+ Dir dir;
30+ Fhdr f;
31+ int fd;
32+
33+ ARGBEGIN{
34+ case 'd':
35+ dsegonly++;
36+ break;
37+ case 's':
38+ supressend++;
39+ break;
40+ case 'a':
41+ addr = strtoul(ARGF(), 0, 0);
42+ break;
43+ case 'p':
44+ psize = strtoul(ARGF(), 0, 0);
45+ break;
46+ case 'b':
47+ binary++;
48+ break;
49+ case 'S':
50+ startaddr = strtoul(ARGF(), 0, 0);
51+ break;
52+ case '4':
53+ addr4++;
54+ break;
55+ default:
56+ usage();
57+ }ARGEND
58+
59+ if(argc != 1)
60+ usage();
61+
62+ Binit(&stdout, 1, OWRITE);
63+
64+ fd = open(argv[0], OREAD);
65+ if(fd < 0) {
66+ fprint(2, "ms2: open %s: %r\n", argv[0]);
67+ exits("open");
68+ }
69+
70+ if(binary) {
71+ if(dirfstat(fd, &dir) < 0) {
72+ fprint(2, "ms2: stat failed %r");
73+ exits("dirfstat");
74+ }
75+ Binit(&bio, fd, OREAD);
76+ dosegment(0, dir.length);
77+ if(supressend == 0)
78+ trailer(startaddr);
79+ Bterm(&stdout);
80+ Bterm(&bio);
81+ exits(0);
82+ }
83+
84+ if(crackhdr(fd, &f) == 0){
85+ fprint(2, "ms2: bad magic: %r\n");
86+ exits("magic");
87+ }
88+ seek(fd, 0, 0);
89+
90+ Binit(&bio, fd, OREAD);
91+
92+ if(dsegonly)
93+ dosegment(f.datoff, f.datsz);
94+ else {
95+ dosegment(f.txtoff, f.txtsz);
96+ addr = (addr+(psize-1))&~(psize-1);
97+ dosegment(f.datoff, f.datsz);
98+ }
99+
100+ if(supressend == 0)
101+ trailer(startaddr);
102+
103+ Bterm(&stdout);
104+ Bterm(&bio);
105+ exits(0);
106+}
107+
108+void
109+dosegment(long foff, int len)
110+{
111+ int l, n;
112+ uchar buf[2*Recordsize];
113+
114+ Bseek(&bio, foff, 0);
115+ for(;;) {
116+ l = len;
117+ if(l > Recordsize)
118+ l = Recordsize;
119+ n = Bread(&bio, buf, l);
120+ if(n == 0)
121+ break;
122+ if(n < 0) {
123+ fprint(2, "ms2: read error: %r\n");
124+ exits("read");
125+ }
126+ record(buf, l);
127+ len -= l;
128+ }
129+}
130+
131+void
132+record(uchar *s, int l)
133+{
134+ int i;
135+ ulong cksum;
136+
137+ if(addr4 || addr & (0xFF<<24)){
138+ Bprint(&stdout, "S3%.2X%.8luX", l+5, addr);
139+ cksum = l+5;
140+ cksum += (addr>>24)&0xff;
141+ }else{
142+ Bprint(&stdout, "S2%.2X%.6X", l+4, addr);
143+ cksum = l+4;
144+ }
145+ cksum += addr&0xff;
146+ cksum += (addr>>8)&0xff;
147+ cksum += (addr>>16)&0xff;
148+
149+ for(i = 0; i < l; i++) {
150+ cksum += *s;
151+ Bprint(&stdout, "%.2X", *s++);
152+ }
153+ Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
154+ addr += l;
155+}
156+
157+void
158+trailer(ulong a)
159+{
160+ ulong cksum;
161+
162+ cksum = 0;
163+ if(addr4 || a & (0xFF<<24)){
164+ Bprint(&stdout, "S7%.8luX", a);
165+ cksum += (a>>24)&0xff;
166+ }else
167+ Bprint(&stdout, "S9%.6X", a);
168+ cksum += a&0xff;
169+ cksum += (a>>8)&0xff;
170+ cksum += (a>>16)&0xff;
171+ Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
172+}
173+
174+void
175+usage(void)
176+{
177+ fprint(2, "usage: ms2 [-ds] [-a address] [-p pagesize] ?.out\n");
178+ exits("usage");
179+}
os/boot/mpc/plan9boot.c+96−0
@@ -0,0 +1,96 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+
7+char *premature = "premature EOF\n";
8+
9+/*
10+ * read in a segment
11+ */
12+static long
13+readseg(int dev, long (*read)(int, void*, long), long len, long addr)
14+{
15+ char *a;
16+ long n, sofar;
17+
18+ a = (char *)addr;
19+ for(sofar = 0; sofar < len; sofar += n){
20+ n = 8*1024;
21+ if(len - sofar < n)
22+ n = len - sofar;
23+ n = (*read)(dev, a + sofar, n);
24+ if(n <= 0)
25+ break;
26+ print(".");
27+ }
28+ return sofar;
29+}
30+
31+/*
32+ * boot
33+ */
34+int
35+plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
36+{
37+ long n;
38+ long addr;
39+ void (*b)(void);
40+ Exec *ep;
41+
42+ if((*seek)(dev, 0) < 0)
43+ return -1;
44+
45+ /*
46+ * read header
47+ */
48+ ep = (Exec *) ialloc(sizeof(Exec), 0);
49+ n = sizeof(Exec);
50+ if(readseg(dev, read, n, (long) ep) != n){
51+ print(premature);
52+ return -1;
53+ }
54+ if(GLLONG(ep->magic) != Q_MAGIC){
55+ print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
56+ return -1;
57+ }
58+
59+ /*
60+ * read text
61+ */
62+ addr = PADDR(GLLONG(ep->entry));
63+ n = GLLONG(ep->text);
64+ print("%d", n);
65+ if(readseg(dev, read, n, addr) != n){
66+ print(premature);
67+ return -1;
68+ }
69+
70+ /*
71+ * read data (starts at first page after kernel)
72+ */
73+ addr = PGROUND(addr+n);
74+ n = GLLONG(ep->data);
75+ print("+%d@%8.8lux", n, addr);
76+ if(readseg(dev, read, n, addr) != n){
77+ print(premature);
78+ return -1;
79+ }
80+
81+ /*
82+ * bss and entry point
83+ */
84+ print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
85+ uartwait();
86+ scc2stop();
87+ splhi();
88+
89+ /*
90+ * Go to new code. It's up to the program to get its PC relocated to
91+ * the right place.
92+ */
93+ b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
94+ (*b)();
95+ return 0;
96+}
os/boot/mpc/qio.c+128−0
@@ -0,0 +1,128 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+struct Queue {
9+ Block* first;
10+ Block* last;
11+ void (*kick)(void*);
12+ void* arg;
13+ long len;
14+};
15+
16+Block *
17+iallocb(int n)
18+{
19+ Block *b;
20+
21+ b = (Block*)malloc(sizeof(Block)+n);
22+ b->data = (uchar*)b + sizeof(Block);
23+ b->rp = b->wp = b->data;
24+ b->lim = b->data + n;
25+ b->next = 0;
26+ b->magic = 0xcafebee0;
27+ return b;
28+}
29+
30+void
31+freeb(Block *b)
32+{
33+ if(b){
34+ if(b->magic != 0xcafebee0)
35+ panic("freeb");
36+ b->magic = 0;
37+ b->next = (Block*)0xdeadbabe;
38+ free(b);
39+ }
40+}
41+
42+Queue *
43+qopen(int limit, int msg, void (*kick)(void*), void *arg)
44+{
45+ Queue *q;
46+
47+ USED(limit, msg);
48+ q = (Queue*)malloc(sizeof(Queue));
49+ q->first = q->last = 0;
50+ q->kick = kick;
51+ q->arg = arg;
52+ q->len = 0;
53+ return q;
54+}
55+
56+Block *
57+qget(Queue *q)
58+{
59+ int s;
60+ Block *b;
61+
62+ s = splhi();
63+ if((b = q->first) != 0){
64+ q->first = b->next;
65+ b->next = 0;
66+ q->len -= BLEN(b);
67+ if(q->len < 0)
68+ panic("qget");
69+ }
70+ splx(s);
71+ return b;
72+}
73+
74+void
75+qbwrite(Queue *q, Block *b)
76+{
77+ int s;
78+
79+ s = splhi();
80+ b->next = 0;
81+ if(q->first == 0)
82+ q->first = b;
83+ else
84+ q->last->next = b;
85+ q->last = b;
86+ q->len += BLEN(b);
87+ splx(s);
88+ if(q->kick)
89+ q->kick(q->arg);
90+}
91+
92+long
93+qlen(Queue *q)
94+{
95+ return q->len;
96+}
97+
98+int
99+qbgetc(Queue *q)
100+{
101+ Block *b;
102+ int s, c;
103+
104+ c = -1;
105+ s = splhi();
106+ while(c < 0 && (b = q->first) != nil){
107+ if(b->rp < b->wp){
108+ c = *b->rp++;
109+ q->len--;
110+ }
111+ if(b->rp >= b->wp){
112+ q->first = b->next;
113+ b->next = nil;
114+ }
115+ }
116+ splx(s);
117+ return c;
118+}
119+
120+void
121+qbputc(Queue *q, int c)
122+{
123+ Block *b;
124+
125+ b = iallocb(1);
126+ *b->wp++ = c;
127+ qbwrite(q, b);
128+}
os/boot/mpc/rmap.c+104−0
@@ -0,0 +1,104 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+
7+void
8+mapinit(RMap *rmap, Map *map, int size)
9+{
10+ lock(rmap);
11+ rmap->map = map;
12+ rmap->mapend = map+(size/sizeof(Map));
13+ unlock(rmap);
14+}
15+
16+void
17+mapfree(RMap* rmap, ulong addr, int size)
18+{
19+ Map *mp;
20+ ulong t;
21+
22+ if(size <= 0)
23+ return;
24+
25+ lock(rmap);
26+ for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
27+ ;
28+
29+ if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
30+ (mp-1)->size += size;
31+ if(addr+size == mp->addr){
32+ (mp-1)->size += mp->size;
33+ while(mp->size){
34+ mp++;
35+ (mp-1)->addr = mp->addr;
36+ (mp-1)->size = mp->size;
37+ }
38+ }
39+ }
40+ else{
41+ if(addr+size == mp->addr && mp->size){
42+ mp->addr -= size;
43+ mp->size += size;
44+ }
45+ else do{
46+ if(mp >= rmap->mapend){
47+ print("mapfree: %s: losing 0x%uX, %d\n",
48+ rmap->name, addr, size);
49+ break;
50+ }
51+ t = mp->addr;
52+ mp->addr = addr;
53+ addr = t;
54+ t = mp->size;
55+ mp->size = size;
56+ mp++;
57+ }while(size = t);
58+ }
59+ unlock(rmap);
60+}
61+
62+ulong
63+mapalloc(RMap* rmap, ulong addr, int size, int align)
64+{
65+ Map *mp;
66+ ulong maddr, oaddr;
67+
68+ lock(rmap);
69+ for(mp = rmap->map; mp->size; mp++){
70+ maddr = mp->addr;
71+
72+ if(addr){
73+ if(maddr > addr)
74+ continue;
75+ if(addr+size > maddr+mp->size)
76+ break;
77+ maddr = addr;
78+ }
79+
80+ if(align > 0)
81+ maddr = ((maddr+align-1)/align)*align;
82+ if(mp->addr+mp->size-maddr < size)
83+ continue;
84+
85+ oaddr = mp->addr;
86+ mp->addr = maddr+size;
87+ mp->size -= maddr-oaddr+size;
88+ if(mp->size == 0){
89+ do{
90+ mp++;
91+ (mp-1)->addr = mp->addr;
92+ }while((mp-1)->size = mp->size);
93+ }
94+
95+ unlock(rmap);
96+ if(oaddr != maddr)
97+ mapfree(rmap, oaddr, maddr-oaddr);
98+
99+ return maddr;
100+ }
101+ unlock(rmap);
102+
103+ return 0;
104+}
os/boot/mpc/screen.c+242−0
@@ -0,0 +1,242 @@
1+#include "all.h"
2+#include <libg.h>
3+#include <gnot.h>
4+
5+enum {
6+ Colldepth = 3,
7+ Colmaxx = 640,
8+ Colmaxxvis = 640,
9+ Colmaxy = 480,
10+};
11+
12+#define MINX 8
13+
14+extern GSubfont defont0;
15+
16+struct{
17+ Point pos;
18+ int bwid;
19+}out;
20+
21+typedef struct Mode Mode;
22+struct Mode {
23+ int x;
24+ int y;
25+ int d;
26+ char* aperture;
27+ int apsize;
28+};
29+
30+GBitmap gscreen;
31+Point gchar(GBitmap*, Point, GFont*, int, Fcode);
32+int setcolor(ulong, ulong, ulong, ulong);
33+static void lcdinit(Mode*);
34+
35+void
36+screeninit(void)
37+{
38+ Mode m;
39+
40+ m.x = Colmaxx;
41+ m.y = Colmaxy;
42+ m.d = Colldepth;
43+ m.aperture = 0;
44+ lcdinit(&m);
45+ if(m.aperture == 0)
46+ return;
47+ gscreen.ldepth = 3;
48+ gscreen.base = (ulong*)m.aperture;
49+ gscreen.width = Colmaxx/BY2WD;
50+ gscreen.r = Rect(0, 0, Colmaxxvis, Colmaxy);
51+ gscreen.clipr = gscreen.r;
52+ /*
53+ * For now, just use a fixed colormap:
54+ * 0 == white and 255 == black
55+ */
56+ setcolor(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
57+ setcolor(255, 0x00000000, 0x00000000, 0x00000000);
58+
59+ gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, Zero);
60+ out.pos.x = MINX;
61+ out.pos.y = 0;
62+ out.bwid = defont0.info[' '].width;
63+}
64+
65+void
66+screenputc(int c)
67+{
68+ Fontchar *i;
69+ Point p;
70+
71+ if(gscreen.base == nil)
72+ return;
73+ switch(c){
74+ case '\n':
75+ out.pos.x = MINX;
76+ out.pos.y += defont0.height;
77+ if(out.pos.y > gscreen.r.max.y-defont0.height)
78+ out.pos.y = gscreen.r.min.y;
79+ gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
80+ Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height),
81+ Zero);
82+ break;
83+ case '\t':
84+ out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
85+ if(out.pos.x >= gscreen.r.max.x)
86+ screenputc('\n');
87+ break;
88+ case '\b':
89+ if(out.pos.x >= out.bwid+MINX){
90+ out.pos.x -= out.bwid;
91+ screenputc(' ');
92+ out.pos.x -= out.bwid;
93+ }
94+ break;
95+ default:
96+ if(out.pos.x >= gscreen.r.max.x-out.bwid)
97+ screenputc('\n');
98+ c &= 0x7f;
99+ if(c <= 0 || c >= defont0.n)
100+ break;
101+ i = defont0.info + c;
102+ p = out.pos;
103+ gbitblt(&gscreen, Pt(p.x+i->left, p.y), defont0.bits,
104+ Rect(i[0].x, 0, i[1].x, defont0.height),
105+ S);
106+ out.pos.x = p.x + i->width;
107+ break;
108+ }
109+}
110+
111+void
112+screenputs(char *s, int n)
113+{
114+ while(n-- > 0)
115+ screenputc(*s++);
116+}
117+
118+/*
119+ * See section 5.2.1 (page 5-6) of the MPC823 manual
120+ */
121+static uchar lcdclock[17] = { /* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */
122+ 0, 0, (1<<2), 1,
123+ (2<<2), 2, (1<<2)|1, 3,
124+ (3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1,
125+ (2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2),
126+ (4<<2)
127+};
128+
129+/*
130+ * support for the Sharp LQ64D341 TFT colour display
131+ */
132+
133+enum {
134+ COLS = 640,
135+ ROWS = 480,
136+ LDEPTH = 3, /* screen depth */
137+ LCDFREQ = 25000000,
138+
139+ /* lccr */
140+ ClockLow = 1<<11,
141+ OELow = 1<<10,
142+ HsyncLow = 1<<9,
143+ VsyncLow = 1<<8,
144+ DataLow = 1<<7,
145+ Passive8 = 1<<4,
146+ DualScan = 1<<3,
147+ IsColour = 1<<2,
148+ IsTFT = 1<<1,
149+ Enable = 1<<0,
150+
151+ /* lchcr */
152+ BigEndian = 1<<24,
153+ AT7 = 7<<21, /* access type */
154+
155+ /* sdcr */
156+ LAM = 1<<6, /* ``LCD aggressive mode'' */
157+};
158+
159+/*
160+ * TO DO: most of the data could come from a table
161+ */
162+static void
163+lcdinit(Mode *mode)
164+{
165+ IMM *io;
166+ int i, d;
167+ long hz;
168+
169+ io = m->iomem;
170+ mode->y = ROWS;
171+ mode->x = COLS;
172+ mode->d = LDEPTH;
173+ mode->aperture = ialloc(mode->x*mode->y, 16);
174+ mode->apsize = mode->x*mode->y;
175+
176+ io->sdcr &= ~LAM; /* MPC823 errata: turn off LAM before disabling controller */
177+ io->lcfaa = PADDR(mode->aperture);
178+ io->lccr = (((mode->x*mode->y*(1<<LDEPTH)+127)/128) << 17) | (LDEPTH << 5) | IsColour | IsTFT | OELow | VsyncLow | ClockLow;
179+
180+ switch(LDEPTH){
181+ default:
182+ case 0:
183+ /* monochrome/greyscale identity map */
184+ for(i=0; i<16; i++)
185+ io->lcdmap[i] = i;
186+ break;
187+ case 2:
188+ /* 4-bit grey scale map */
189+ for(i=0; i<16; i++)
190+ io->lcdmap[0] = (i<<8)|(i<<4)|i;
191+ break;
192+ case 3:
193+ /* 8-bit linear map */
194+ for(i=0; i<256; i++)
195+ io->lcdmap[i] = (i<<8)|(i<<4)|i;
196+ break;
197+ }
198+
199+ io->lcvcr = (mode->y << 11) | (1<<28) | 33; /* 2 line vsync pulse, 34 line wait between frames */
200+ io->lchcr = (mode->x<<10) | BigEndian | 228; /* clock cycles between lines */
201+
202+ hz = m->cpuhz;
203+ d = hz/LCDFREQ;
204+ if(hz/d > LCDFREQ)
205+ d++;
206+ if(d >= 16)
207+ d = 16;
208+
209+ /*
210+ * enable LCD outputs
211+ */
212+ io->pddat = 0;
213+ io->pdpar = 0x1fff;
214+io->pdpar &= ~SIBIT(6); /* 823 bug fix? */
215+ io->pddir = 0x1fff;
216+ io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17);
217+ io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17);
218+ io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17));
219+
220+ eieio();
221+ io->sccrk = KEEP_ALIVE_KEY;
222+ eieio();
223+ io->sccr = (io->sccr & ~0x1F) | lcdclock[d];
224+ eieio();
225+ io->sccrk = ~KEEP_ALIVE_KEY;
226+ eieio();
227+ gscreen.width = gscreen.width; /* access external memory before enabling (mpc823 errata) */
228+ io->lcsr = 7; /* clear status */
229+ eieio();
230+ io->lccr |= Enable;
231+ archbacklight(1);
232+}
233+
234+int
235+setcolor(ulong p, ulong r, ulong g, ulong b)
236+{
237+ r >>= 28;
238+ g >>= 28;
239+ b >>= 28;
240+ m->iomem->lcdmap[~p&0xFF] = (r<<8) | (g<<4) | b; /* TO DO: it's a function of the ldepth */
241+ return 1;
242+}
os/boot/mpc/sload.c+71−0
@@ -0,0 +1,71 @@
1+/*
2+ * send S records to rpcg
3+ */
4+
5+#include <u.h>
6+#include <libc.h>
7+#include <bio.h>
8+
9+static int dbg;
10+static char buf[2048];
11+static int run=1;
12+static void stuffbym(char*, int, int);
13+static void getdot(void);
14+
15+void
16+main(int argc, char **argv)
17+{
18+ int n;
19+ char *l;
20+ Biobuf *f;
21+ static int p;
22+
23+ ARGBEGIN{
24+ case 'd': dbg++; break;
25+ case 'n': run=0; break;
26+ }ARGEND
27+
28+ f = Bopen(*argv? *argv: "k.mx", OREAD);
29+ if(f == 0) {
30+ fprint(2, "sload: cannot open k.mx: %r\n");
31+ exits("sload");
32+ }
33+ getdot();
34+ while((l = Brdline(f, '\n')) != 0) {
35+ l[Blinelen(f)-1] = '\r';
36+ stuffbym(l, Blinelen(f), 16);
37+ getdot();
38+ if(++p % 25 == 0)
39+ write(2, ".", 1);
40+ }
41+ exits(0);
42+}
43+
44+static void
45+stuffbym(char *l, int n, int m)
46+{
47+ int nr, ns;
48+
49+ while(n > 0) {
50+ ns = n;
51+ if(ns > m)
52+ ns = m;
53+ write(1, l, ns);
54+ l += ns;
55+ n -= ns;
56+ }
57+}
58+
59+static void
60+getdot(void)
61+{
62+ char c;
63+
64+ for(;;){
65+ if(read(0, &c, 1) != 1)
66+ exits("bang");
67+ write(2, &c, 1);
68+ if(c == '.')
69+ break;
70+ }
71+}
os/boot/mpc/squeeze.h+34−0
@@ -0,0 +1,34 @@
1+
2+/*
3+ * squeezed file format:
4+ * Sqhdr
5+ * original Exec header
6+ * two Squeeze tables
7+ * squeezed segment
8+ * unsqueezed segment, if any
9+ */
10+#define SQMAGIC (ulong)0xFEEF0F1E
11+
12+typedef struct Sqhdr Sqhdr;
13+struct Sqhdr {
14+ uchar magic[4]; /* SQMAGIC */
15+ uchar text[4]; /* squeezed length of text (excluding tables) */
16+ uchar data[4]; /* squeezed length of data (excluding tables) */
17+ uchar asis[4]; /* length of unsqueezed segment */
18+ uchar toptxt[4]; /* value for 0 encoding in text */
19+ uchar topdat[4]; /* value for 0 encoding in data */
20+ uchar sum[4]; /* simple checksum of unsqueezed data */
21+ uchar flags[4];
22+};
23+#define SQHDRLEN (8*4)
24+
25+/*
26+ * certain power instruction types are rearranged by sqz
27+ * so as to move the variable part of the instruction word to the
28+ * low order bits. note that the mapping is its own inverse.
29+ */
30+#define QREMAP(X)\
31+ switch((X)>>26){\
32+ case 19: case 31: case 59: case 63:\
33+ (X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
34+ }
os/boot/mpc/trap.c+233−0
@@ -0,0 +1,233 @@
1+#include "boot.h"
2+
3+enum
4+{
5+ Maxhandler= 32+16, /* max number of interrupt handlers */
6+};
7+
8+typedef struct Handler Handler;
9+struct Handler
10+{
11+ void (*r)(Ureg*, void*);
12+ void *arg;
13+ Handler *next;
14+ int edge;
15+};
16+
17+struct
18+{
19+ Handler *ivec[128];
20+ Handler h[Maxhandler];
21+ int free;
22+} halloc;
23+
24+char *excname[] = {
25+ "reserved 0",
26+ "system reset",
27+ "machine check",
28+ "data access",
29+ "instruction access",
30+ "external interrupt",
31+ "alignment",
32+ "program exception",
33+ "floating-point unavailable",
34+ "decrementer",
35+ "reserved A",
36+ "reserved B",
37+ "system call",
38+ "trace trap",
39+ "floating point assist",
40+ "reserved F",
41+ "software emulation",
42+ "ITLB miss",
43+ "DTLB miss",
44+ "ITLB error",
45+ "DTLB error",
46+};
47+
48+char *regname[]={
49+ "CAUSE", "SRR1",
50+ "PC", "GOK",
51+ "LR", "CR",
52+ "XER", "CTR",
53+ "R0", "R1",
54+ "R2", "R3",
55+ "R4", "R5",
56+ "R6", "R7",
57+ "R8", "R9",
58+ "R10", "R11",
59+ "R12", "R13",
60+ "R14", "R15",
61+ "R16", "R17",
62+ "R18", "R19",
63+ "R20", "R21",
64+ "R22", "R23",
65+ "R24", "R25",
66+ "R26", "R27",
67+ "R28", "R29",
68+ "R30", "R31",
69+};
70+
71+static void intr(Ureg*);
72+
73+void
74+sethvec(int v, void (*r)(void))
75+{
76+ ulong *vp, pa, o;
77+
78+ if((ulong)r & 3)
79+ panic("sethvec");
80+ vp = (ulong*)KADDR(v);
81+ vp[0] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */
82+ vp[1] = 0x7c0802a6; /* MOVW LR, R0 */
83+ vp[2] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */
84+ pa = PADDR(r);
85+ o = pa >> 25;
86+ if(o != 0 && o != 0x7F){
87+ /* a branch too far: running from ROM */
88+ vp[3] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
89+ vp[4] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
90+ vp[5] = 0x7c0803a6; /* MOVW R0, LR */
91+ vp[6] = 0x4e800021; /* BL (LR) */
92+ }else
93+ vp[3] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
94+}
95+
96+#define LEV(n) (((n)<<1)|1)
97+#define IRQ(n) (((n)<<1)|0)
98+
99+void
100+setvec(int v, void (*r)(Ureg*, void*), void *arg)
101+{
102+ Handler *h;
103+ IMM *io;
104+
105+ if(halloc.free >= Maxhandler)
106+ panic("out of interrupt handlers");
107+ v -= VectorPIC;
108+ h = &halloc.h[halloc.free++];
109+ h->next = halloc.ivec[v];
110+ h->r = r;
111+ h->arg = arg;
112+ halloc.ivec[v] = h;
113+
114+ /*
115+ * enable corresponding interrupt in SIU/CPM
116+ */
117+
118+ io = m->iomem;
119+ if(v >= VectorCPIC){
120+ v -= VectorCPIC;
121+ io->cimr |= 1<<(v&0x1F);
122+ }
123+ else if(v >= VectorIRQ)
124+ io->simask |= 1<<(31-IRQ(v&7));
125+ else
126+ io->simask |= 1<<(31-LEV(v));
127+}
128+
129+void
130+trapinit(void)
131+{
132+ int i;
133+ IMM *io;
134+
135+ io = m->iomem;
136+ io->sypcr &= ~(3<<2); /* disable watchdog (821/823) */
137+ io->simask = 0; /* mask all */
138+ io->siel = ~0; /* edge sensitive, wake on all */
139+ io->cicr = 0; /* disable CPM interrupts */
140+ io->cipr = ~0; /* clear all interrupts */
141+ io->cimr = 0; /* mask all events */
142+ io->cicr = (0xE1<<16)|(CPIClevel<<13)|(0x1F<<8);
143+ io->cicr |= 1 << 7; /* enable */
144+ io->tbscrk = KEEP_ALIVE_KEY;
145+ io->tbscr = 1; /* TBE */
146+ io->simask |= 1<<(31-LEV(CPIClevel)); /* CPM's level */
147+ io->tbk = KEEP_ALIVE_KEY;
148+ eieio();
149+ putdec(~0);
150+
151+ /*
152+ * set all exceptions to trap
153+ */
154+ for(i = 0x0; i < 0x3000; i += 0x100)
155+ sethvec(i, exception);
156+}
157+
158+void
159+dumpregs(Ureg *ur)
160+{
161+ int i;
162+ ulong *l;
163+ l = &ur->cause;
164+ for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
165+ print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
166+}
167+
168+void
169+trap(Ureg *ur)
170+{
171+ int c;
172+
173+ c = ur->cause >> 8;
174+ switch(c){
175+ default:
176+ {extern int predawn; predawn = 1;}
177+ if(c < 0 || c >= nelem(excname))
178+ print("exception/interrupt #%x\n", c);
179+ else
180+ print("exception %s\n", excname[c]);
181+ dumpregs(ur);
182+ /* spllo(); */
183+ print("^P to reset\n");
184+ for(;;)
185+ ;
186+
187+ case 0x09: /* decrementer */
188+ clockintr(ur, 0);
189+ return;
190+
191+ case 0x05: /* external interrupt */
192+ intr(ur);
193+ break;
194+ }
195+}
196+
197+static void
198+intr(Ureg *ur)
199+{
200+ int b, v;
201+ Handler *h;
202+ IMM *io;
203+
204+ io = m->iomem;
205+ b = io->sivec>>2;
206+ v = b>>1;
207+ if(b & 1) {
208+ if(v == CPIClevel){
209+ io->civr = 1;
210+ eieio();
211+ v = VectorCPIC+(io->civr>>11);
212+ }
213+ }else
214+ v += VectorIRQ;
215+ h = halloc.ivec[v];
216+ if(h == nil){
217+ for(;;)
218+ ;
219+ //print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
220+ return;
221+ }
222+ if(h->edge)
223+ io->sipend |= 1<<(31-b);
224+ /*
225+ * call the interrupt handlers
226+ */
227+ do {
228+ (*h->r)(ur, h->arg);
229+ h = h->next;
230+ } while(h != nil);
231+ if(v >= VectorCPIC)
232+ io->cisr |= 1<<(v-VectorCPIC);
233+}
os/boot/mpc/uartboot.c+189−0
@@ -0,0 +1,189 @@
1+#include "boot.h"
2+
3+/*
4+ * this doesn't yet use the crc
5+ */
6+
7+typedef struct Uboot Uboot;
8+struct Uboot {
9+ Queue* iq;
10+ Block* partial;
11+ ulong csum;
12+ long bno;
13+ uchar buf[64];
14+ int nleft;
15+ int ntimeout;
16+};
17+
18+static Uboot uboot;
19+ulong crc32(void *buf, int n, ulong crc);
20+
21+static void
22+uartbrecv(uchar *p, int n)
23+{
24+ Uboot *ub;
25+ Block *b;
26+
27+ ub = &uboot;
28+ if(n > 0 && ub->iq != nil){
29+ b = iallocb(n);
30+ memmove(b->wp, p, n);
31+ b->wp += n;
32+ qbwrite(ub->iq, b);
33+ }
34+}
35+
36+int
37+uartinit(void)
38+{
39+ return 1<<0;
40+}
41+
42+Partition*
43+setuartpart(int, char *s)
44+{
45+ static Partition pp[1];
46+
47+ if(strcmp(s, "boot") != 0 && strcmp(s, "disk") != 0)
48+ return 0;
49+ pp[0].start = 0;
50+ pp[0].end = 2*1024*1024;
51+ strcpy(pp[0].name, "boot");
52+ return pp;
53+}
54+
55+long
56+uartseek(int, long)
57+{
58+ /* start the boot */
59+ if(uboot.iq == nil)
60+ uboot.iq = qopen(64*1024, 0, 0, 0);
61+ if(uboot.partial){
62+ freeb(uboot.partial);
63+ uboot.partial = 0;
64+ }
65+ print("uart: start transmission\n");
66+ uartsetboot(uartbrecv);
67+ uboot.csum = ~0;
68+ uboot.bno = 0;
69+ uboot.nleft = 0;
70+ uboot.ntimeout = 0;
71+ return 0;
72+}
73+
74+static long
75+uartreadn(void *buf, int nb)
76+{
77+ ulong start;
78+ Uboot *ub;
79+ int l;
80+ Block *b;
81+ uchar *p;
82+
83+ p = buf;
84+ ub = &uboot;
85+ start = m->ticks;
86+ while(nb > 0){
87+ b = ub->partial;
88+ ub->partial = nil;
89+ if(b == nil){
90+ ub->ntimeout = 0;
91+ while((b = qget(ub->iq)) == 0){
92+ if(TK2MS(m->ticks - start) >= 15*1000){
93+ if(++ub->ntimeout >= 3){
94+ print("uart: timeout\n");
95+ return 0;
96+ }
97+ uartputs("n", 1);
98+ }
99+ }
100+ }
101+ l = BLEN(b);
102+ if(l > nb)
103+ l = nb;
104+ memmove(p, b->rp, l);
105+ b->rp += l;
106+ if(b->rp >= b->wp)
107+ freeb(b);
108+ else
109+ ub->partial = b;
110+ nb -= l;
111+ p += l;
112+ }
113+ return p-(uchar*)buf;
114+}
115+
116+long
117+uartread(int, void *buf, long n)
118+{
119+ uchar *p;
120+ int l;
121+ static uchar lbuf[64];
122+
123+ p = buf;
124+ if((l = uboot.nleft) > 0){
125+ if(l > n)
126+ l = n;
127+ uboot.nleft -= l;
128+ memmove(p, uboot.buf, l);
129+ p += l;
130+ n -= l;
131+ }
132+ while(n > 0){
133+ l = uartreadn(lbuf, sizeof(lbuf));
134+ if(l < sizeof(lbuf))
135+ return 0;
136+ if(l > n){
137+ uboot.nleft = l-n;
138+ memmove(uboot.buf, lbuf+n, uboot.nleft);
139+ l = n;
140+ }
141+ memmove(p, lbuf, l);
142+ n -= l;
143+ p += l;
144+ uboot.bno++;
145+ uartputs("y", 1);
146+ }
147+ return p-(uchar*)buf;
148+}
149+
150+/*
151+ * from Rob Warnock
152+ */
153+static ulong crc32tab[256]; /* initialised on first call to crc32 */
154+
155+enum {
156+ CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
157+};
158+
159+/*
160+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
161+ */
162+static void
163+initcrc32(void)
164+{
165+ int i, j;
166+ ulong c;
167+
168+ for(i = 0; i < 256; i++) {
169+ for(c = i << 24, j = 8; j > 0; j--)
170+ if(c & (1<<31))
171+ c = (c<<1) ^ CRC32POLY;
172+ else
173+ c <<= 1;
174+ crc32tab[i] = c;
175+ }
176+}
177+
178+ulong
179+crc32(void *buf, int n, ulong crc)
180+{
181+ uchar *p;
182+
183+ if(crc32tab[1] == 0)
184+ initcrc32();
185+ crc = ~crc;
186+ for(p = buf; --n >= 0;)
187+ crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
188+ return ~crc;
189+}
os/boot/mpc/ureg.h+43−0
@@ -0,0 +1,43 @@
1+struct Ureg
2+{
3+ ulong cause;
4+ union { ulong srr1; ulong status;};
5+ ulong pc; /* SRR0 */
6+ ulong pad;
7+ ulong lr;
8+ ulong cr;
9+ ulong xer;
10+ ulong ctr;
11+ ulong r0;
12+ union{ ulong r1; ulong sp; ulong usp; };
13+ ulong r2;
14+ ulong r3;
15+ ulong r4;
16+ ulong r5;
17+ ulong r6;
18+ ulong r7;
19+ ulong r8;
20+ ulong r9;
21+ ulong r10;
22+ ulong r11;
23+ ulong r12;
24+ ulong r13;
25+ ulong r14;
26+ ulong r15;
27+ ulong r16;
28+ ulong r17;
29+ ulong r18;
30+ ulong r19;
31+ ulong r20;
32+ ulong r21;
33+ ulong r22;
34+ ulong r23;
35+ ulong r24;
36+ ulong r25;
37+ ulong r26;
38+ ulong r27;
39+ ulong r28;
40+ ulong r29;
41+ ulong r30;
42+ ulong r31;
43+};
os/boot/mpc/zqs.c+234−0
@@ -0,0 +1,234 @@
1+#include "boot.h"
2+#include "squeeze.h"
3+
4+/*
5+ * for details of `unsqueeze' see:
6+ *
7+ * %A Mark Taunton
8+ * %T Compressed Executables: An Exercise in Thinking Small
9+ * %P 385-404
10+ * %I USENIX
11+ * %B USENIX Conference Proceedings
12+ * %D Summer 1991
13+ * %C Nashville, TN
14+ *
15+ * several of the unimplemented improvements described in the paper
16+ * have been implemented here
17+ *
18+ * there is a further transformation on the powerpc (QFLAG!=0) to shuffle bits
19+ * in certain instructions so as to push the fixed bits to the top of the word.
20+ */
21+
22+#define EXECHDRLEN (8*4)
23+
24+typedef struct Squeeze Squeeze;
25+struct Squeeze {
26+ int n;
27+ ulong tab[7*256];
28+};
29+
30+#define GET4(p) (((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
31+
32+/*
33+ * for speed of unsqueezing from Flash, certain checks are
34+ * not done inside the loop (as they would be in the unsqueeze program zqs),
35+ * but instead the checksum is expected to catch corrupted files.
36+ * in fact the Squeeze array bounds can't be exceeded in practice
37+ * because the tables are always full for a squeezed kernel.
38+ */
39+enum {
40+ QFLAG = 1, /* invert powerpc-specific code transformation */
41+ CHECK = 0, /* check precise bounds in Squeeze array (otherwise checksum detects error) */
42+};
43+
44+static ulong chksum;
45+static int rdtab(Block*, Squeeze*, int);
46+static ulong* unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
47+static uchar* unsqzseg(uchar*, Block*, long, long, char*);
48+static Alarm* unsqzal;
49+
50+int
51+issqueezed(uchar *b)
52+{
53+ return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
54+}
55+
56+static void
57+unsqzdot(Alarm*)
58+{
59+ unsqzal = alarm(500, unsqzdot, nil);
60+ print(".");
61+}
62+
63+long
64+unsqueezef(Block *b, ulong *entryp)
65+{
66+ uchar *loada, *wp;
67+ ulong toptxt, topdat, oldsum;
68+ long asis, nst, nsd;
69+ Sqhdr *sqh;
70+ Exec *ex;
71+
72+ if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
73+ return -1;
74+ sqh = (Sqhdr*)b->rp;
75+ if(GET4(sqh->magic) != SQMAGIC)
76+ return -1;
77+ chksum = 0;
78+ toptxt = GET4(sqh->toptxt);
79+ topdat = GET4(sqh->topdat);
80+ oldsum = GET4(sqh->sum);
81+ asis = GET4(sqh->asis);
82+ nst = GET4(sqh->text);
83+ nsd = GET4(sqh->data);
84+ b->rp += SQHDRLEN;
85+ ex = (Exec*)b->rp;
86+ if(GET4(ex->magic) != Q_MAGIC){
87+ print("zqs: not powerPC executable\n");
88+ return -1;
89+ }
90+ *entryp = GET4(ex->entry);
91+ b->rp += EXECHDRLEN;
92+ loada = KADDR(PADDR(*entryp));
93+ wp = unsqzseg(loada, b, nst, toptxt, "text");
94+ if(wp == nil){
95+ print("zqs: format error\n");
96+ return -1;
97+ }
98+ if(nsd){
99+ wp = (uchar*)PGROUND((ulong)wp);
100+ wp = unsqzseg(wp, b, nsd, topdat, "data");
101+ if(wp == nil){
102+ print("zqs: format error\n");
103+ return -1;
104+ }
105+ }
106+ if(asis){
107+ memmove(wp, b->rp, asis);
108+ wp += asis;
109+ b->rp += asis;
110+ }
111+ if(chksum != oldsum){
112+ print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
113+ return -1;
114+ }
115+ return wp-loada;
116+}
117+
118+static uchar *
119+unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
120+{
121+ static Squeeze sq3, sq4;
122+
123+ print("unpack %s %8.8lux %lud:", what, wp, ns);
124+ if(ns == 0)
125+ return wp;
126+ if(rdtab(b, &sq3, 0) < 0)
127+ return nil;
128+ if(rdtab(b, &sq4, 8) < 0)
129+ return nil;
130+ if(BLEN(b) < ns){
131+ print(" **size error\n");
132+ return nil;
133+ }
134+ unsqzal = alarm(500, unsqzdot, nil);
135+ wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
136+ cancel(unsqzal);
137+ unsqzal = nil;
138+ print("\n");
139+ if(wp == nil){
140+ print("zqs: corrupt squeezed data stream\n");
141+ return nil;
142+ }
143+ b->rp += ns;
144+ return wp;
145+}
146+
147+static ulong*
148+unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
149+{
150+ ulong nx, csum;
151+ int code, n;
152+
153+ if(QFLAG){
154+ QREMAP(top); /* adjust top just once, outside the loop */
155+ }
156+ csum = chksum;
157+ while(rp < ep){
158+ /* no function calls within this loop for speed */
159+ code = *rp;
160+ rp++;
161+ n = 0;
162+ nx = code>>4;
163+ do{
164+ if(nx == 0){
165+ nx = top;
166+ }else{
167+ if(nx==1){
168+ nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
169+ rp += 4;
170+ }else if(nx <= 8){ /* 2 to 8 */
171+ nx = ((nx-2)<<8) | rp[0];
172+ if(CHECK && nx >= sq4->n)
173+ return nil; /* corrupted file */
174+ nx = sq4->tab[nx] | rp[1];
175+ rp += 2;
176+ }else{ /* 9 to 15 */
177+ nx = ((nx-9)<<8) | rp[0];
178+ if(CHECK && nx >= sq3->n)
179+ return nil; /* corrupted file */
180+ nx = sq3->tab[nx];
181+ rp++;
182+ }
183+ if(rp > ep)
184+ return nil; /* corrupted file */
185+ if(QFLAG){
186+ QREMAP(nx);
187+ }
188+ }
189+ *wp = nx;
190+ wp++;
191+ csum += nx;
192+ nx = code & 0xF;
193+ }while(++n == 1);
194+ }
195+ chksum = csum;
196+ return wp;
197+}
198+
199+static int
200+rdtab(Block *b, Squeeze *sq, int shift)
201+{
202+ uchar *p, *ep;
203+ ulong v, w;
204+ int i;
205+
206+ if(BLEN(b) < 2)
207+ return -1;
208+ i = (b->rp[0]<<8) | b->rp[1];
209+ if(1)
210+ print(" T%d", i);
211+ b->rp += 2;
212+ if((i -= 2) > 0){
213+ if(BLEN(b) < i)
214+ return -1;
215+ }
216+ sq->n = 0;
217+ p = b->rp;
218+ ep = b->rp+i;
219+ b->rp += i;
220+ v = 0;
221+ while(p < ep){
222+ w = 0;
223+ do{
224+ if(p >= ep)
225+ return -1;
226+ w = (w<<7) | (*p & 0x7F);
227+ }while(*p++ & 0x80);
228+ v += w;
229+ if(0)
230+ print("%d %8.8lux %8.8lux\n", sq->n, v, w);
231+ sq->tab[sq->n++] = v<<shift;
232+ }
233+ return 0;
234+}
os/boot/pc/8250.c+308−0
@@ -0,0 +1,308 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+/*
9+ * INS8250 uart
10+ */
11+enum
12+{
13+ /*
14+ * register numbers
15+ */
16+ Data= 0, /* xmit/rcv buffer */
17+ Iena= 1, /* interrupt enable */
18+ Ircv= (1<<0), /* for char rcv'd */
19+ Ixmt= (1<<1), /* for xmit buffer empty */
20+ Irstat=(1<<2), /* for change in rcv'er status */
21+ Imstat=(1<<3), /* for change in modem status */
22+ Istat= 2, /* interrupt flag (read) */
23+ Tctl= 2, /* test control (write) */
24+ Format= 3, /* byte format */
25+ Bits8= (3<<0), /* 8 bits/byte */
26+ Stop2= (1<<2), /* 2 stop bits */
27+ Pena= (1<<3), /* generate parity */
28+ Peven= (1<<4), /* even parity */
29+ Pforce=(1<<5), /* force parity */
30+ Break= (1<<6), /* generate a break */
31+ Dra= (1<<7), /* address the divisor */
32+ Mctl= 4, /* modem control */
33+ Dtr= (1<<0), /* data terminal ready */
34+ Rts= (1<<1), /* request to send */
35+ Ri= (1<<2), /* ring */
36+ Inton= (1<<3), /* turn on interrupts */
37+ Loop= (1<<4), /* loop back */
38+ Lstat= 5, /* line status */
39+ Inready=(1<<0), /* receive buffer full */
40+ Oerror=(1<<1), /* receiver overrun */
41+ Perror=(1<<2), /* receiver parity error */
42+ Ferror=(1<<3), /* rcv framing error */
43+ Outready=(1<<5), /* output buffer empty */
44+ Mstat= 6, /* modem status */
45+ Ctsc= (1<<0), /* clear to send changed */
46+ Dsrc= (1<<1), /* data set ready changed */
47+ Rire= (1<<2), /* rising edge of ring indicator */
48+ Dcdc= (1<<3), /* data carrier detect changed */
49+ Cts= (1<<4), /* complement of clear to send line */
50+ Dsr= (1<<5), /* complement of data set ready line */
51+ Ring= (1<<6), /* complement of ring indicator line */
52+ Dcd= (1<<7), /* complement of data carrier detect line */
53+ Scratch=7, /* scratchpad */
54+ Dlsb= 0, /* divisor lsb */
55+ Dmsb= 1, /* divisor msb */
56+
57+ Serial= 0,
58+ Modem= 1,
59+};
60+
61+typedef struct Uart Uart;
62+struct Uart
63+{
64+ int port;
65+ uchar sticky[8]; /* sticky write register values */
66+ uchar txbusy;
67+
68+ void (*rx)(int); /* routine to take a received character */
69+ int (*tx)(void); /* routine to get a character to transmit */
70+
71+ ulong frame;
72+ ulong overrun;
73+};
74+
75+static Uart com[2];
76+static Uart* uart;
77+
78+#define UartFREQ 1843200
79+
80+#define uartwrreg(u,r,v) outb((u)->port + r, (u)->sticky[r] | (v))
81+#define uartrdreg(u,r) inb((u)->port + r)
82+
83+/*
84+ * set the baud rate by calculating and setting the baudrate
85+ * generator constant. This will work with fairly non-standard
86+ * baud rates.
87+ */
88+static void
89+uartsetbaud(Uart *up, int rate)
90+{
91+ ulong brconst;
92+
93+ brconst = (UartFREQ+8*rate-1)/(16*rate);
94+
95+ uartwrreg(up, Format, Dra);
96+ outb(up->port+Dmsb, (brconst>>8) & 0xff);
97+ outb(up->port+Dlsb, brconst & 0xff);
98+ uartwrreg(up, Format, 0);
99+}
100+
101+/*
102+ * toggle DTR
103+ */
104+static void
105+uartdtr(Uart *up, int n)
106+{
107+ if(n)
108+ up->sticky[Mctl] |= Dtr;
109+ else
110+ up->sticky[Mctl] &= ~Dtr;
111+ uartwrreg(up, Mctl, 0);
112+}
113+
114+/*
115+ * toggle RTS
116+ */
117+static void
118+uartrts(Uart *up, int n)
119+{
120+ if(n)
121+ up->sticky[Mctl] |= Rts;
122+ else
123+ up->sticky[Mctl] &= ~Rts;
124+ uartwrreg(up, Mctl, 0);
125+}
126+
127+static void
128+uartintr(Ureg*, void *arg)
129+{
130+ Uart *up;
131+ int ch;
132+ int s, l, loops;
133+
134+ up = arg;
135+ for(loops = 0; loops < 1024; loops++){
136+ s = uartrdreg(up, Istat);
137+ switch(s & 0x3F){
138+ case 6: /* receiver line status */
139+ l = uartrdreg(up, Lstat);
140+ if(l & Ferror)
141+ up->frame++;
142+ if(l & Oerror)
143+ up->overrun++;
144+ break;
145+
146+ case 4: /* received data available */
147+ case 12:
148+ ch = inb(up->port+Data);
149+ if(up->rx)
150+ (*up->rx)(ch);
151+ break;
152+
153+ case 2: /* transmitter empty */
154+ ch = -1;
155+ if(up->tx)
156+ ch = (*up->tx)();
157+ if(ch != -1)
158+ outb(up->port+Data, ch);
159+ else
160+ up->txbusy = 0;
161+ break;
162+
163+ case 0: /* modem status */
164+ uartrdreg(up, Mstat);
165+ break;
166+
167+ default:
168+ if(s&1)
169+ return;
170+ print("weird modem interrupt #%2.2ux\n", s);
171+ break;
172+ }
173+ }
174+ panic("uartintr: 0x%2.2ux\n", uartrdreg(up, Istat));
175+}
176+
177+/*
178+ * turn on a port's interrupts. set DTR and RTS
179+ */
180+static void
181+uartenable(Uart *up)
182+{
183+ /*
184+ * turn on interrupts
185+ */
186+ up->sticky[Iena] = 0;
187+ if(up->tx)
188+ up->sticky[Iena] |= Ixmt;
189+ if(up->rx)
190+ up->sticky[Iena] |= Ircv|Irstat;
191+ uartwrreg(up, Iena, 0);
192+
193+ /*
194+ * turn on DTR and RTS
195+ */
196+ uartdtr(up, 1);
197+ uartrts(up, 1);
198+}
199+
200+static void
201+uartdisable(Uart* up)
202+{
203+ /*
204+ * Disable interrupts.
205+ */
206+ up->sticky[Iena] = 0;
207+ uartwrreg(up, Iena, 0);
208+ uartdtr(up, 0);
209+ uartrts(up, 0);
210+}
211+
212+void
213+uartspecial(int port, void (*rx)(int), int (*tx)(void), int baud)
214+{
215+ Uart *up;
216+ int vector;
217+
218+ switch(port){
219+ case 0:
220+ port = 0x3F8;
221+ vector = VectorUART0;
222+ up = &com[0];
223+ break;
224+ case 1:
225+ port = 0x2F8;
226+ vector = VectorUART1;
227+ up = &com[1];
228+ break;
229+ default:
230+ return;
231+ }
232+
233+ if(uart != nil && uart != up)
234+ uartdisable(uart);
235+ uart = up;
236+
237+ if(up->port == 0){
238+ up->port = port;
239+ setvec(vector, uartintr, up);
240+ }
241+
242+ /*
243+ * set rate to 9600 baud.
244+ * 8 bits/character.
245+ * 1 stop bit.
246+ * interrupts enabled.
247+ */
248+ uartsetbaud(up, 9600);
249+ up->sticky[Format] = Bits8;
250+ uartwrreg(up, Format, 0);
251+ up->sticky[Mctl] |= Inton;
252+ uartwrreg(up, Mctl, 0x0);
253+
254+ up->rx = rx;
255+ up->tx = tx;
256+ uartenable(up);
257+ if(baud)
258+ uartsetbaud(up, baud);
259+}
260+
261+void
262+uartputc(int c)
263+{
264+ int i;
265+ Uart *up;
266+
267+ if((up = uart) == nil)
268+ return;
269+ for(i = 0; i < 100; i++){
270+ if(uartrdreg(up, Lstat) & Outready)
271+ break;
272+ delay(1);
273+ }
274+ outb(up->port+Data, c);
275+}
276+
277+void
278+uartputs(IOQ *q, char *s, int n)
279+{
280+ Uart *up;
281+ int c, x;
282+
283+ if((up = uart) == nil)
284+ return;
285+ while(n--){
286+ if(*s == '\n')
287+ q->putc(q, '\r');
288+ q->putc(q, *s++);
289+ }
290+ x = splhi();
291+ if(up->txbusy == 0 && (c = q->getc(q)) != -1){
292+ uartputc(c & 0xFF);
293+ up->txbusy = 1;
294+ }
295+ splx(x);
296+}
297+
298+void
299+uartdrain(void)
300+{
301+ Uart *up;
302+ int timeo;
303+
304+ if((up = uart) == nil)
305+ return;
306+ for(timeo = 0; timeo < 10000 && up->txbusy; timeo++)
307+ delay(1);
308+}
os/boot/pc/LICENCE+237−0
@@ -0,0 +1,237 @@
1+Lucent Public License Version 1.02
2+
3+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
4+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
5+PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
6+
7+1. DEFINITIONS
8+
9+"Contribution" means:
10+
11+ a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
12+ Program, and
13+ b. in the case of each Contributor,
14+
15+ i. changes to the Program, and
16+ ii. additions to the Program;
17+
18+ where such changes and/or additions to the Program were added to the
19+ Program by such Contributor itself or anyone acting on such
20+ Contributor's behalf, and the Contributor explicitly consents, in
21+ accordance with Section 3C, to characterization of the changes and/or
22+ additions as Contributions.
23+
24+"Contributor" means LUCENT and any other entity that has Contributed a
25+Contribution to the Program.
26+
27+"Distributor" means a Recipient that distributes the Program,
28+modifications to the Program, or any part thereof.
29+
30+"Licensed Patents" mean patent claims licensable by a Contributor
31+which are necessarily infringed by the use or sale of its Contribution
32+alone or when combined with the Program.
33+
34+"Original Program" means the original version of the software
35+accompanying this Agreement as released by LUCENT, including source
36+code, object code and documentation, if any.
37+
38+"Program" means the Original Program and Contributions or any part
39+thereof
40+
41+"Recipient" means anyone who receives the Program under this
42+Agreement, including all Contributors.
43+
44+2. GRANT OF RIGHTS
45+
46+ a. Subject to the terms of this Agreement, each Contributor hereby
47+ grants Recipient a non-exclusive, worldwide, royalty-free copyright
48+ license to reproduce, prepare derivative works of, publicly display,
49+ publicly perform, distribute and sublicense the Contribution of such
50+ Contributor, if any, and such derivative works, in source code and
51+ object code form.
52+
53+ b. Subject to the terms of this Agreement, each Contributor hereby
54+ grants Recipient a non-exclusive, worldwide, royalty-free patent
55+ license under Licensed Patents to make, use, sell, offer to sell,
56+ import and otherwise transfer the Contribution of such Contributor, if
57+ any, in source code and object code form. The patent license granted
58+ by a Contributor shall also apply to the combination of the
59+ Contribution of that Contributor and the Program if, at the time the
60+ Contribution is added by the Contributor, such addition of the
61+ Contribution causes such combination to be covered by the Licensed
62+ Patents. The patent license granted by a Contributor shall not apply
63+ to (i) any other combinations which include the Contribution, nor to
64+ (ii) Contributions of other Contributors. No hardware per se is
65+ licensed hereunder.
66+
67+ c. Recipient understands that although each Contributor grants the
68+ licenses to its Contributions set forth herein, no assurances are
69+ provided by any Contributor that the Program does not infringe the
70+ patent or other intellectual property rights of any other entity. Each
71+ Contributor disclaims any liability to Recipient for claims brought by
72+ any other entity based on infringement of intellectual property rights
73+ or otherwise. As a condition to exercising the rights and licenses
74+ granted hereunder, each Recipient hereby assumes sole responsibility
75+ to secure any other intellectual property rights needed, if any. For
76+ example, if a third party patent license is required to allow
77+ Recipient to distribute the Program, it is Recipient's responsibility
78+ to acquire that license before distributing the Program.
79+
80+ d. Each Contributor represents that to its knowledge it has sufficient
81+ copyright rights in its Contribution, if any, to grant the copyright
82+ license set forth in this Agreement.
83+
84+3. REQUIREMENTS
85+
86+A. Distributor may choose to distribute the Program in any form under
87+this Agreement or under its own license agreement, provided that:
88+
89+ a. it complies with the terms and conditions of this Agreement;
90+
91+ b. if the Program is distributed in source code or other tangible
92+ form, a copy of this Agreement or Distributor's own license agreement
93+ is included with each copy of the Program; and
94+
95+ c. if distributed under Distributor's own license agreement, such
96+ license agreement:
97+
98+ i. effectively disclaims on behalf of all Contributors all warranties
99+ and conditions, express and implied, including warranties or
100+ conditions of title and non-infringement, and implied warranties or
101+ conditions of merchantability and fitness for a particular purpose;
102+ ii. effectively excludes on behalf of all Contributors all liability
103+ for damages, including direct, indirect, special, incidental and
104+ consequential damages, such as lost profits; and
105+ iii. states that any provisions which differ from this Agreement are
106+ offered by that Contributor alone and not by any other party.
107+
108+B. Each Distributor must include the following in a conspicuous
109+ location in the Program:
110+
111+ Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
112+ Reserved.
113+
114+C. In addition, each Contributor must identify itself as the
115+originator of its Contribution in a manner that reasonably allows
116+subsequent Recipients to identify the originator of the Contribution.
117+Also, each Contributor must agree that the additions and/or changes
118+are intended to be a Contribution. Once a Contribution is contributed,
119+it may not thereafter be revoked.
120+
121+4. COMMERCIAL DISTRIBUTION
122+
123+Commercial distributors of software may accept certain
124+responsibilities with respect to end users, business partners and the
125+like. While this license is intended to facilitate the commercial use
126+of the Program, the Distributor who includes the Program in a
127+commercial product offering should do so in a manner which does not
128+create potential liability for Contributors. Therefore, if a
129+Distributor includes the Program in a commercial product offering,
130+such Distributor ("Commercial Distributor") hereby agrees to defend
131+and indemnify every Contributor ("Indemnified Contributor") against
132+any losses, damages and costs (collectively"Losses") arising from
133+claims, lawsuits and other legal actions brought by a third party
134+against the Indemnified Contributor to the extent caused by the acts
135+or omissions of such Commercial Distributor in connection with its
136+distribution of the Program in a commercial product offering. The
137+obligations in this section do not apply to any claims or Losses
138+relating to any actual or alleged intellectual property infringement.
139+In order to qualify, an Indemnified Contributor must: a) promptly
140+notify the Commercial Distributor in writing of such claim, and b)
141+allow the Commercial Distributor to control, and cooperate with the
142+Commercial Distributor in, the defense and any related settlement
143+negotiations. The Indemnified Contributor may participate in any such
144+claim at its own expense.
145+
146+For example, a Distributor might include the Program in a commercial
147+product offering, Product X. That Distributor is then a Commercial
148+Distributor. If that Commercial Distributor then makes performance
149+claims, or offers warranties related to Product X, those performance
150+claims and warranties are such Commercial Distributor's responsibility
151+alone. Under this section, the Commercial Distributor would have to
152+defend claims against the Contributors related to those performance
153+claims and warranties, and if a court requires any Contributor to pay
154+any damages as a result, the Commercial Distributor must pay those
155+damages.
156+
157+5. NO WARRANTY
158+
159+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
160+PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
161+KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
162+WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
163+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
164+responsible for determining the appropriateness of using and
165+distributing the Program and assumes all risks associated with its
166+exercise of rights under this Agreement, including but not limited to
167+the risks and costs of program errors, compliance with applicable
168+laws, damage to or loss of data, programs or equipment, and
169+unavailability or interruption of operations.
170+
171+6. DISCLAIMER OF LIABILITY
172+
173+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
174+ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
175+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
176+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
177+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
178+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
179+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
180+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
181+
182+7. EXPORT CONTROL
183+
184+Recipient agrees that Recipient alone is responsible for compliance
185+with the United States export administration regulations (and the
186+export control laws and regulation of any other countries).
187+
188+8. GENERAL
189+
190+If any provision of this Agreement is invalid or unenforceable under
191+applicable law, it shall not affect the validity or enforceability of
192+the remainder of the terms of this Agreement, and without further
193+action by the parties hereto, such provision shall be reformed to the
194+minimum extent necessary to make such provision valid and enforceable.
195+
196+If Recipient institutes patent litigation against a Contributor with
197+respect to a patent applicable to software (including a cross-claim or
198+counterclaim in a lawsuit), then any patent licenses granted by that
199+Contributor to such Recipient under this Agreement shall terminate as
200+of the date such litigation is filed. In addition, if Recipient
201+institutes patent litigation against any entity (including a
202+cross-claim or counterclaim in a lawsuit) alleging that the Program
203+itself (excluding combinations of the Program with other software or
204+hardware) infringes such Recipient's patent(s), then such Recipient's
205+rights granted under Section 2(b) shall terminate as of the date such
206+litigation is filed.
207+
208+All Recipient's rights under this Agreement shall terminate if it
209+fails to comply with any of the material terms or conditions of this
210+Agreement and does not cure such failure in a reasonable period of
211+time after becoming aware of such noncompliance. If all Recipient's
212+rights under this Agreement terminate, Recipient agrees to cease use
213+and distribution of the Program as soon as reasonably practicable.
214+However, Recipient's obligations under this Agreement and any licenses
215+granted by Recipient relating to the Program shall continue and
216+survive.
217+
218+LUCENT may publish new versions (including revisions) of this
219+Agreement from time to time. Each new version of the Agreement will be
220+given a distinguishing version number. The Program (including
221+Contributions) may always be distributed subject to the version of the
222+Agreement under which it was received. In addition, after a new
223+version of the Agreement is published, Contributor may elect to
224+distribute the Program (including its Contributions) under the new
225+version. No one other than LUCENT has the right to modify this
226+Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
227+Recipient receives no rights or licenses to the intellectual property
228+of any Contributor under this Agreement, whether expressly, by
229+implication, estoppel or otherwise. All rights in the Program not
230+expressly granted under this Agreement are reserved.
231+
232+This Agreement is governed by the laws of the State of New York and
233+the intellectual property laws of the United States of America. No
234+party to this Agreement will bring a legal action under this Agreement
235+more than one year after the cause of action arose. Each party waives
236+its rights to a jury trial in any resulting litigation.
237+
os/boot/pc/NOTICE+4−0
@@ -0,0 +1,4 @@
1+Copyright © 1995-2006 Lucent Technologies Inc. and others. All rights reserved.
2+Revisions for use with Inferno © 2003-2006 Vita Nuova Holdings Limited.
3+
4+This software is provided under the terms of the Lucent Public License, Version 1.02.
os/boot/pc/alarm.c+123−0
@@ -0,0 +1,123 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+#define MAXALARM 10
8+
9+Alarm alarmtab[MAXALARM];
10+
11+/*
12+ * Insert new into list after where
13+ */
14+void
15+insert(List **head, List *where, List *new)
16+{
17+ if(where == 0){
18+ new->next = *head;
19+ *head = new;
20+ }else{
21+ new->next = where->next;
22+ where->next = new;
23+ }
24+
25+}
26+
27+/*
28+ * Delete old from list. where->next is known to be old.
29+ */
30+void
31+delete(List **head, List *where, List *old)
32+{
33+ if(where == 0){
34+ *head = old->next;
35+ return;
36+ }
37+ where->next = old->next;
38+}
39+
40+Alarm*
41+newalarm(void)
42+{
43+ int i;
44+ Alarm *a;
45+
46+ for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
47+ if(a->busy==0 && a->f==0){
48+ a->f = 0;
49+ a->arg = 0;
50+ a->busy = 1;
51+ return a;
52+ }
53+ panic("newalarm");
54+ return 0; /* not reached */
55+}
56+
57+Alarm*
58+alarm(int ms, void (*f)(Alarm*), void *arg)
59+{
60+ Alarm *a, *w, *pw;
61+ ulong s;
62+
63+ if(ms < 0)
64+ ms = 0;
65+ s = splhi();
66+ a = newalarm();
67+ a->dt = MS2TK(ms);
68+ a->f = f;
69+ a->arg = arg;
70+ pw = 0;
71+ for(w=m->alarm; w; pw=w, w=w->next){
72+ if(w->dt <= a->dt){
73+ a->dt -= w->dt;
74+ continue;
75+ }
76+ w->dt -= a->dt;
77+ break;
78+ }
79+ insert(&m->alarm, pw, a);
80+ splx(s);
81+ return a;
82+}
83+
84+void
85+cancel(Alarm *a)
86+{
87+ a->f = 0;
88+}
89+
90+void
91+alarminit(void)
92+{
93+}
94+
95+#define NA 10 /* alarms per clock tick */
96+void
97+checkalarms(void)
98+{
99+ int i, n, s;
100+ Alarm *a;
101+ void (*f)(Alarm*);
102+ Alarm *alist[NA];
103+
104+ s = splhi();
105+ a = m->alarm;
106+ if(a){
107+ for(n=0; a && a->dt<=0 && n<NA; n++){
108+ alist[n] = a;
109+ delete(&m->alarm, 0, a);
110+ a = m->alarm;
111+ }
112+ if(a)
113+ a->dt--;
114+
115+ for(i = 0; i < n; i++){
116+ f = alist[i]->f; /* avoid race with cancel */
117+ if(f)
118+ (*f)(alist[i]);
119+ alist[i]->busy = 0;
120+ }
121+ }
122+ splx(s);
123+}
os/boot/pc/apm.c+16−0
@@ -0,0 +1,16 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+Apminfo apm;
9+
10+void
11+apminit(void)
12+{
13+ if(getconf("apm0") && apm.haveinfo)
14+ changeconf("apm0=ax=%x ebx=%x cx=%x dx=%x di=%x esi=%x\n",
15+ apm.ax, apm.ebx, apm.cx, apm.dx, apm.di, apm.esi);
16+}
os/boot/pc/bcom.c+460−0
@@ -0,0 +1,460 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+#include "fs.h"
9+
10+Type types[] = {
11+ { Tfloppy,
12+ Fini|Ffs,
13+ floppyinit, floppyinitdev,
14+ floppygetfspart, 0, floppyboot,
15+ },
16+ { Tsd,
17+ Fini|Ffs,
18+ sdinit, sdinitdev,
19+ sdgetfspart, sdaddconf, sdboot,
20+ },
21+ { Tnil,
22+ 0,
23+ 0, 0,
24+ 0, 0, 0,
25+ },
26+};
27+
28+#include "sd.h"
29+
30+extern SDifc sdataifc;
31+extern SDifc sdmylexifc;
32+extern SDifc sd53c8xxifc;
33+SDifc* sdifc[] = {
34+ &sdataifc,
35+// &sdmylexifc,
36+// &sd53c8xxifc,
37+ nil,
38+};
39+
40+typedef struct Mode Mode;
41+
42+enum {
43+ Maxdev = 7,
44+ Dany = -1,
45+ Nmedia = 16,
46+ Nini = 10,
47+};
48+
49+enum { /* mode */
50+ Mauto = 0x00,
51+ Mlocal = 0x01,
52+ Manual = 0x02,
53+ NMode = 0x03,
54+};
55+
56+typedef struct Medium Medium;
57+struct Medium {
58+ Type* type;
59+ int flag;
60+ int dev;
61+ char name[NAMELEN];
62+ Fs* inifs;
63+
64+ Medium* next;
65+};
66+
67+typedef struct Mode {
68+ char* name;
69+ int mode;
70+} Mode;
71+
72+static Medium media[Nmedia];
73+static Medium *curmedium = media;
74+
75+static Mode modes[NMode+1] = {
76+ [Mauto] { "auto", Mauto, },
77+ [Mlocal] { "local", Mlocal, },
78+ [Manual] { "manual", Manual, },
79+};
80+
81+char *defaultpartition = "new";
82+
83+static Medium*
84+parse(char *line, char **file)
85+{
86+ char *p;
87+ Type *tp;
88+ Medium *mp;
89+
90+ if(p = strchr(line, '!')) {
91+ *p++ = 0;
92+ *file = p;
93+ } else
94+ *file = "";
95+
96+ for(tp = types; tp->type != Tnil; tp++)
97+ for(mp = tp->media; mp; mp = mp->next)
98+ if(strcmp(mp->name, line) == 0)
99+ return mp;
100+ return nil;
101+}
102+
103+static int
104+boot(Medium *mp, char *file)
105+{
106+ static Boot b;
107+
108+ memset(&b, 0, sizeof b);
109+ b.state = INIT9LOAD;
110+
111+// sprint(BOOTLINE, "%s!%s", mp->name, file);
112+ return (*mp->type->boot)(mp->dev, file, &b);
113+}
114+
115+static Medium*
116+allocm(Type *tp)
117+{
118+ Medium **l;
119+
120+ if(curmedium >= &media[Nmedia])
121+ return 0;
122+
123+ for(l = &tp->media; *l; l = &(*l)->next)
124+ ;
125+ *l = curmedium++;
126+ return *l;
127+}
128+
129+char *parts[] = { "dos", "9fat", "fs", 0 };
130+
131+Medium*
132+probe(int type, int flag, int dev)
133+{
134+ Type *tp;
135+ int i;
136+ Medium *mp;
137+
138+ for(tp = types; tp->type != Tnil; tp++){
139+ if(type != Tany && type != tp->type)
140+ continue;
141+
142+ if(flag != Fnone){
143+ for(mp = tp->media; mp; mp = mp->next){
144+ if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
145+ return mp;
146+ }
147+ }
148+
149+ if((tp->flag & Fprobe) == 0){
150+ tp->flag |= Fprobe;
151+ tp->mask = (*tp->init)();
152+ }
153+
154+ for(i = 0; tp->mask; i++){
155+ if((tp->mask & (1<<i)) == 0)
156+ continue;
157+ tp->mask &= ~(1<<i);
158+
159+ if((mp = allocm(tp)) == 0)
160+ continue;
161+
162+ mp->dev = i;
163+ mp->flag = tp->flag;
164+ mp->type = tp;
165+ (*tp->initdev)(i, mp->name);
166+
167+ if((flag & mp->flag) && (dev == Dany || dev == i))
168+ return mp;
169+ }
170+ }
171+
172+ return 0;
173+}
174+
175+extern int loopconst;
176+void
177+main(void)
178+{
179+ Medium *mp;
180+ int flag;
181+ char def[2*NAMELEN], line[80], *p, *file;
182+ Type *tp;
183+
184+ i8042a20();
185+ memset(m, 0, sizeof(Mach));
186+ trapinit();
187+ clockinit();
188+ alarminit();
189+ spllo();
190+
191+ kbdinit();
192+
193+ if((ulong)&end > (KZERO|(640*1024)))
194+ panic("i'm too big");
195+
196+ /*
197+ * If there were any arguments, MS-DOS leaves a character
198+ * count followed by the arguments in the runtime header.
199+ * Step over the leading space.
200+ */
201+ p = (char*)0x80080080;
202+ if(p[0]){
203+ p[p[0]+1] = 0;
204+ p += 2;
205+ }
206+ else
207+ p = 0;
208+
209+ /*
210+ * Advance command line to first option, if any
211+ */
212+ if(p) {
213+ while(*p==' ' || *p=='\t')
214+ p++;
215+ if(*p == 0)
216+ p = nil;
217+ }
218+
219+ /*
220+ * Probe everything, to collect device names.
221+ */
222+ probe(Tany, Fnone, Dany);
223+
224+ if(p != 0) {
225+ if((mp = parse(p, &file)) == nil) {
226+ print("bad loadfile syntax: %s\n", p);
227+ goto done;
228+ }
229+ boot(mp, file);
230+ }
231+
232+done:
233+ flag = 0;
234+ for(tp = types; tp->type != Tnil; tp++){
235+ for(mp = tp->media; mp; mp = mp->next){
236+ if(flag == 0){
237+ flag = 1;
238+ print("Load devices:");
239+ }
240+ print(" %s", mp->name);
241+ }
242+ }
243+ if(flag)
244+ print("\n");
245+
246+ for(;;){
247+ if(getstr("load from", line, sizeof(line), nil, 0) >= 0)
248+ if(mp = parse(line, &file))
249+ boot(mp, file);
250+ def[0] = 0;
251+ }
252+}
253+
254+int
255+getfields(char *lp, char **fields, int n, char sep)
256+{
257+ int i;
258+
259+ for(i = 0; lp && *lp && i < n; i++){
260+ while(*lp == sep)
261+ *lp++ = 0;
262+ if(*lp == 0)
263+ break;
264+ fields[i] = lp;
265+ while(*lp && *lp != sep){
266+ if(*lp == '\\' && *(lp+1) == '\n')
267+ *lp++ = ' ';
268+ lp++;
269+ }
270+ }
271+ return i;
272+}
273+
274+int
275+cistrcmp(char *a, char *b)
276+{
277+ int ac, bc;
278+
279+ for(;;){
280+ ac = *a++;
281+ bc = *b++;
282+
283+ if(ac >= 'A' && ac <= 'Z')
284+ ac = 'a' + (ac - 'A');
285+ if(bc >= 'A' && bc <= 'Z')
286+ bc = 'a' + (bc - 'A');
287+ ac -= bc;
288+ if(ac)
289+ return ac;
290+ if(bc == 0)
291+ break;
292+ }
293+ return 0;
294+}
295+
296+int
297+cistrncmp(char *a, char *b, int n)
298+{
299+ unsigned ac, bc;
300+
301+ while(n > 0){
302+ ac = *a++;
303+ bc = *b++;
304+ n--;
305+
306+ if(ac >= 'A' && ac <= 'Z')
307+ ac = 'a' + (ac - 'A');
308+ if(bc >= 'A' && bc <= 'Z')
309+ bc = 'a' + (bc - 'A');
310+
311+ ac -= bc;
312+ if(ac)
313+ return ac;
314+ if(bc == 0)
315+ break;
316+ }
317+
318+ return 0;
319+}
320+
321+void*
322+ialloc(ulong n, int align)
323+{
324+
325+ static ulong palloc;
326+ ulong p;
327+ int a;
328+
329+ if(palloc == 0)
330+ palloc = 3*1024*1024;
331+
332+ p = palloc;
333+ if(align <= 0)
334+ align = 4;
335+ if(a = n % align)
336+ n += align - a;
337+ if(a = p % align)
338+ p += align - a;
339+
340+ palloc = p+n;
341+
342+ return memset((void*)(p|KZERO), 0, n);
343+}
344+
345+void*
346+xspanalloc(ulong size, int align, ulong span)
347+{
348+ ulong a, v;
349+
350+ a = (ulong)ialloc(size+align+span, 0);
351+
352+ if(span > 2)
353+ v = (a + span) & ~(span-1);
354+ else
355+ v = a;
356+
357+ if(align > 1)
358+ v = (v + align) & ~(align-1);
359+
360+ return (void*)v;
361+}
362+
363+static Block *allocbp;
364+
365+Block*
366+allocb(int size)
367+{
368+ Block *bp, **lbp;
369+ ulong addr;
370+
371+ lbp = &allocbp;
372+ for(bp = *lbp; bp; bp = bp->next){
373+ if((bp->lim - bp->base) >= size){
374+ *lbp = bp->next;
375+ break;
376+ }
377+ lbp = &bp->next;
378+ }
379+ if(bp == 0){
380+ bp = ialloc(sizeof(Block)+size+64, 0);
381+ addr = (ulong)bp;
382+ addr = ROUNDUP(addr + sizeof(Block), 8);
383+ bp->base = (uchar*)addr;
384+ bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
385+ }
386+
387+ if(bp->flag)
388+ panic("allocb reuse\n");
389+
390+ bp->rp = bp->base;
391+ bp->wp = bp->rp;
392+ bp->next = 0;
393+ bp->flag = 1;
394+
395+ return bp;
396+}
397+
398+void
399+freeb(Block* bp)
400+{
401+ bp->next = allocbp;
402+ allocbp = bp;
403+
404+ bp->flag = 0;
405+}
406+
407+enum {
408+ Paddr= 0x70, /* address port */
409+ Pdata= 0x71, /* data port */
410+};
411+
412+uchar
413+nvramread(int offset)
414+{
415+ outb(Paddr, offset);
416+ return inb(Pdata);
417+}
418+
419+void (*etherdetach)(void);
420+void (*floppydetach)(void);
421+void (*sddetach)(void);
422+
423+void
424+warp9(ulong entry)
425+{
426+ if(etherdetach)
427+ etherdetach();
428+ consdrain();
429+ (*(void(*)(void))(PADDR(entry)))();
430+}
431+
432+char*
433+getconf(char*)
434+{
435+ return nil;
436+}
437+
438+void
439+addconf(char*, ...)
440+{
441+}
442+
443+void
444+uartspecial(int, void(*)(int), int(*)(void), int)
445+{
446+}
447+
448+void
449+uartputs(IOQ*, char*, int)
450+{
451+}
452+
453+void
454+uartputc(int)
455+{}
456+
457+void
458+uartdrain(void)
459+{
460+}
os/boot/pc/boot.c+451−0
@@ -0,0 +1,451 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+#include "../../../utils/libmach/elf.h"
9+
10+static uchar elfident[7] = {
11+ '\177', 'E', 'L', 'F', '\1', '\1', '\1'
12+};
13+static Ehdr ehdr, rehdr;
14+static Phdr *phdr;
15+static int curphdr;
16+static ulong curoff;
17+static ulong elftotal;
18+static long (*swal)(long);
19+static ushort (*swab)(ushort);
20+
21+/*
22+ * big-endian short
23+ */
24+ushort
25+beswab(ushort s)
26+{
27+ uchar *p;
28+
29+ p = (uchar*)&s;
30+ return (p[0]<<8) | p[1];
31+}
32+
33+/*
34+ * big-endian long
35+ */
36+long
37+beswal(long l)
38+{
39+ uchar *p;
40+
41+ p = (uchar*)&l;
42+ return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
43+}
44+
45+/*
46+ * little-endian short
47+ */
48+ushort
49+leswab(ushort s)
50+{
51+ uchar *p;
52+
53+ p = (uchar*)&s;
54+ return (p[1]<<8) | p[0];
55+}
56+
57+/*
58+ * little-endian long
59+ */
60+long
61+leswal(long l)
62+{
63+ uchar *p;
64+
65+ p = (uchar*)&l;
66+ return (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
67+}
68+
69+/*
70+ * Convert header to canonical form
71+ */
72+static void
73+hswal(long *lp, int n, long (*swap) (long))
74+{
75+ while (n--) {
76+ *lp = (*swap) (*lp);
77+ lp++;
78+ }
79+}
80+
81+static int
82+readehdr(Boot *b)
83+{
84+ int i;
85+
86+ /* bitswap the header according to the DATA format */
87+ if(ehdr.ident[CLASS] != ELFCLASS32) {
88+ print("bad ELF class - not 32 bit\n");
89+ return 0;
90+ }
91+ if(ehdr.ident[DATA] == ELFDATA2LSB) {
92+ swab = leswab;
93+ swal = leswal;
94+ } else if(ehdr.ident[DATA] == ELFDATA2MSB) {
95+ swab = beswab;
96+ swal = beswal;
97+ } else {
98+ print("bad ELF encoding - not big or little endian\n");
99+ return 0;
100+ }
101+ memmove(&rehdr, &ehdr, sizeof(Ehdr));
102+
103+ ehdr.type = swab(ehdr.type);
104+ ehdr.machine = swab(ehdr.machine);
105+ ehdr.version = swal(ehdr.version);
106+ ehdr.elfentry = swal(ehdr.elfentry);
107+ ehdr.phoff = swal(ehdr.phoff);
108+ ehdr.shoff = swal(ehdr.shoff);
109+ ehdr.flags = swal(ehdr.flags);
110+ ehdr.ehsize = swab(ehdr.ehsize);
111+ ehdr.phentsize = swab(ehdr.phentsize);
112+ ehdr.phnum = swab(ehdr.phnum);
113+ ehdr.shentsize = swab(ehdr.shentsize);
114+ ehdr.shnum = swab(ehdr.shnum);
115+ ehdr.shstrndx = swab(ehdr.shstrndx);
116+ if(ehdr.type != EXEC || ehdr.version != CURRENT)
117+ return 0;
118+ if(ehdr.phentsize != sizeof(Phdr))
119+ return 0;
120+
121+ if(debug)
122+ print("readehdr OK entry 0x%lux\n", ehdr.elfentry);
123+
124+ curoff = sizeof(Ehdr);
125+ i = ehdr.phoff+ehdr.phentsize*ehdr.phnum - curoff;
126+ b->state = READPHDR;
127+ b->bp = (char*)malloc(i);
128+ b->wp = b->bp;
129+ b->ep = b->wp + i;
130+ phdr = (Phdr*)(b->bp + ehdr.phoff-sizeof(Ehdr));
131+ if(debug)
132+ print("phdr...");
133+
134+ return 1;
135+}
136+
137+static int
138+nextphdr(Boot *b)
139+{
140+ Phdr *php;
141+ ulong entry, offset;
142+ char *paddr;
143+
144+ if(debug)
145+ print("readedata %d\n", curphdr);
146+
147+ for(; curphdr < ehdr.phnum; curphdr++){
148+ php = phdr+curphdr;
149+ if(php->type != LOAD)
150+ continue;
151+ offset = php->offset;
152+ paddr = (char*)PADDR(php->paddr);
153+ if(offset < curoff){
154+ /*
155+ * Can't (be bothered to) rewind the
156+ * input, it might be from tftp. If we
157+ * did then we could boot FreeBSD kernels
158+ * too maybe.
159+ */
160+ return 0;
161+ }
162+ if(php->offset > curoff){
163+ b->state = READEPAD;
164+ b->bp = (char*)malloc(offset - curoff);
165+ b->wp = b->bp;
166+ b->ep = b->wp + offset - curoff;
167+ if(debug)
168+ print("nextphdr %lud...\n", offset - curoff);
169+ return 1;
170+ }
171+ b->state = READEDATA;
172+ b->bp = paddr;
173+ b->wp = b->bp;
174+ b->ep = b->wp+php->filesz;
175+ print("%ud+", php->filesz);
176+ elftotal += php->filesz;
177+ if(debug)
178+ print("nextphdr %ud@0x%p\n", php->filesz, paddr);
179+
180+ return 1;
181+ }
182+
183+ if(curphdr != 0){
184+ print("=%lud\n", elftotal);
185+ b->state = TRYBOOT;
186+ entry = ehdr.elfentry & ~0xF0000000;
187+ PLLONG(b->exec.entry, entry);
188+ return 1;
189+ }
190+
191+ return 0;
192+}
193+
194+static int
195+readepad(Boot *b)
196+{
197+ Phdr *php;
198+
199+ php = phdr+curphdr;
200+ if(debug)
201+ print("readepad %d\n", curphdr);
202+ curoff = php->offset;
203+
204+ return nextphdr(b);
205+}
206+
207+static int
208+readedata(Boot *b)
209+{
210+ Phdr *php;
211+
212+ php = phdr+curphdr;
213+ if(debug)
214+ print("readedata %d\n", curphdr);
215+ if(php->filesz < php->memsz){
216+ print("%lud", php->memsz-php->filesz);
217+ elftotal += php->memsz-php->filesz;
218+ memset((char*)(PADDR(php->paddr)+php->filesz), 0, php->memsz-php->filesz);
219+ }
220+ curoff = php->offset+php->filesz;
221+ curphdr++;
222+
223+ return nextphdr(b);
224+}
225+
226+static int
227+readphdr(Boot *b)
228+{
229+ Phdr *php;
230+
231+ php = phdr;
232+ hswal((long*)php, ehdr.phentsize*ehdr.phnum/sizeof(long), swal);
233+ if(debug)
234+ print("phdr curoff %lud vaddr 0x%lux paddr 0x%lux\n",
235+ curoff, php->vaddr, php->paddr);
236+
237+ curoff = ehdr.phoff+ehdr.phentsize*ehdr.phnum;
238+ curphdr = 0;
239+
240+ return nextphdr(b);
241+}
242+
243+static int
244+addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
245+{
246+ int n;
247+
248+ n = edbuf - *dbuf;
249+ if(n <= 0)
250+ return 0;
251+ if(n > esbuf - *sbuf)
252+ n = esbuf - *sbuf;
253+ if(n <= 0)
254+ return -1;
255+
256+ memmove(*dbuf, *sbuf, n);
257+ *sbuf += n;
258+ *dbuf += n;
259+ return edbuf - *dbuf;
260+}
261+
262+int
263+bootpass(Boot *b, void *vbuf, int nbuf)
264+{
265+ char *buf, *ebuf;
266+ Exec *ep;
267+ ulong entry, data, text, bss;
268+
269+ if(b->state == FAILED)
270+ return FAIL;
271+
272+ if(nbuf == 0)
273+ goto Endofinput;
274+
275+ buf = vbuf;
276+ ebuf = buf+nbuf;
277+ while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
278+ switch(b->state) {
279+ case INITKERNEL:
280+ b->state = READEXEC;
281+ b->bp = (char*)&b->exec;
282+ b->wp = b->bp;
283+ b->ep = b->bp+sizeof(Exec);
284+ break;
285+ case READEXEC:
286+ ep = &b->exec;
287+ if(GLLONG(ep->magic) == I_MAGIC) {
288+ b->state = READ9TEXT;
289+ b->bp = (char*)PADDR(GLLONG(ep->entry));
290+ b->wp = b->bp;
291+ b->ep = b->wp+GLLONG(ep->text);
292+ print("%lud", GLLONG(ep->text));
293+ break;
294+ }
295+
296+ /* check for gzipped kernel */
297+ if(b->bp[0] == 0x1F && (uchar)b->bp[1] == 0x8B && b->bp[2] == 0x08) {
298+ b->state = READGZIP;
299+ b->bp = (char*)malloc(1440*1024);
300+ b->wp = b->bp;
301+ b->ep = b->wp + 1440*1024;
302+ memmove(b->bp, &b->exec, sizeof(Exec));
303+ b->wp += sizeof(Exec);
304+ print("gz...");
305+ break;
306+ }
307+
308+ /*
309+ * Check for ELF.
310+ */
311+ if(memcmp(b->bp, elfident, 4) == 0){
312+ b->state = READEHDR;
313+ b->bp = (char*)&ehdr;
314+ b->wp = b->bp;
315+ b->ep = b->wp + sizeof(Ehdr);
316+ memmove(b->bp, &b->exec, sizeof(Exec));
317+ b->wp += sizeof(Exec);
318+ print("elf...");
319+ break;
320+ }
321+
322+ print("bad kernel format\n");
323+ b->state = FAILED;
324+ return FAIL;
325+
326+ case READ9TEXT:
327+ ep = &b->exec;
328+ b->state = READ9DATA;
329+ b->bp = (char*)PGROUND(PADDR(GLLONG(ep->entry))+GLLONG(ep->text));
330+ b->wp = b->bp;
331+ b->ep = b->wp + GLLONG(ep->data);
332+ print("+%ld", GLLONG(ep->data));
333+ break;
334+
335+ case READ9DATA:
336+ ep = &b->exec;
337+ bss = GLLONG(ep->bss);
338+ print("+%ld=%ld\n",
339+ bss, GLLONG(ep->text)+GLLONG(ep->data)+bss);
340+ b->state = TRYBOOT;
341+ return ENOUGH;
342+
343+ case READEHDR:
344+ if(!readehdr(b)){
345+ print("readehdr failed\n");
346+ b->state = FAILED;
347+ return FAIL;
348+ }
349+ break;
350+
351+ case READPHDR:
352+ if(!readphdr(b)){
353+ b->state = FAILED;
354+ return FAIL;
355+ }
356+ break;
357+
358+ case READEPAD:
359+ if(!readepad(b)){
360+ b->state = FAILED;
361+ return FAIL;
362+ }
363+ break;
364+
365+ case READEDATA:
366+ if(!readedata(b)){
367+ b->state = FAILED;
368+ return FAIL;
369+ }
370+ if(b->state == TRYBOOT)
371+ return ENOUGH;
372+ break;
373+
374+ case TRYBOOT:
375+ case READGZIP:
376+ return ENOUGH;
377+
378+ case READ9LOAD:
379+ case INIT9LOAD:
380+ panic("9load");
381+
382+ default:
383+ panic("bootstate");
384+ }
385+ }
386+ return MORE;
387+
388+
389+Endofinput:
390+ /* end of input */
391+ switch(b->state) {
392+ case INITKERNEL:
393+ case READEXEC:
394+ case READ9TEXT:
395+ case READ9DATA:
396+ case READEHDR:
397+ case READPHDR:
398+ case READEPAD:
399+ case READEDATA:
400+ print("premature EOF\n");
401+ b->state = FAILED;
402+ return FAIL;
403+
404+ case TRYBOOT:
405+ entry = GLLONG(b->exec.entry);
406+ print("entry: 0x%lux\n", entry);
407+ warp9(PADDR(entry));
408+ b->state = FAILED;
409+ return FAIL;
410+
411+ case READGZIP:
412+ ep = &b->exec;
413+ if(b->bp[0] != 0x1F || (uchar)b->bp[1] != 0x8B || b->bp[2] != 0x08)
414+ print("lost magic\n");
415+
416+ print("%ld => ", b->wp - b->bp);
417+ if(gunzip((uchar*)ep, sizeof(*ep), (uchar*)b->bp, b->wp - b->bp) < sizeof(*ep)) {
418+ print("badly compressed kernel\n");
419+ return FAIL;
420+ }
421+
422+ entry = GLLONG(ep->entry);
423+ text = GLLONG(ep->text);
424+ data = GLLONG(ep->data);
425+ bss = GLLONG(ep->bss);
426+ print("%lud+%lud+%lud=%lud\n", text, data, bss, text+data+bss);
427+
428+ if(gunzip((uchar*)PADDR(entry)-sizeof(Exec), sizeof(Exec)+text+data,
429+ (uchar*)b->bp, b->wp-b->bp) < sizeof(Exec)+text+data) {
430+ print("error uncompressing kernel\n");
431+ return FAIL;
432+ }
433+
434+ /* relocate data to start at page boundary */
435+ memmove((void*)PGROUND(PADDR(entry+text)), (void*)(PADDR(entry+text)), data);
436+
437+ print("entry: %lux\n", entry);
438+ warp9(PADDR(entry));
439+ b->state = FAILED;
440+ return FAIL;
441+
442+ case INIT9LOAD:
443+ case READ9LOAD:
444+ panic("end 9load");
445+
446+ default:
447+ panic("bootdone");
448+ }
449+ b->state = FAILED;
450+ return FAIL;
451+}
os/boot/pc/bootld.c+108−0
@@ -0,0 +1,108 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+static int
9+addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
10+{
11+ int n;
12+
13+ n = edbuf - *dbuf;
14+ if(n <= 0)
15+ return 0;
16+ if(n > esbuf - *sbuf)
17+ n = esbuf - *sbuf;
18+ if(n <= 0)
19+ return -1;
20+
21+ memmove(*dbuf, *sbuf, n);
22+ *sbuf += n;
23+ *dbuf += n;
24+ return edbuf - *dbuf;
25+}
26+
27+extern void origin(void);
28+
29+int
30+bootpass(Boot *b, void *vbuf, int nbuf)
31+{
32+ char *buf, *ebuf, *p, *q;
33+ ulong size;
34+
35+ if(b->state == FAILED)
36+ return FAIL;
37+
38+ if(nbuf == 0)
39+ goto Endofinput;
40+
41+ buf = vbuf;
42+ ebuf = buf+nbuf;
43+ while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
44+ switch(b->state) {
45+ case INIT9LOAD:
46+ b->state = READ9LOAD;
47+ b->bp = (char*)0x10000;
48+ b->wp = b->bp;
49+ b->ep = b->bp + 256*1024;
50+ break;
51+
52+ case READ9LOAD:
53+ return ENOUGH;
54+
55+ default:
56+ panic("bootstate");
57+ }
58+ }
59+ return MORE;
60+
61+
62+Endofinput:
63+ /* end of input */
64+ print("\n");
65+ switch(b->state) {
66+ case INIT9LOAD:
67+ print("premature EOF\n");
68+ b->state = FAILED;
69+ return FAIL;
70+
71+ case READ9LOAD:
72+ size = b->wp - b->bp;
73+ if(memcmp(b->bp, origin, 16) != 0) {
74+ print("beginning of file does not look right\n");
75+ b->state = FAILED;
76+ return FAIL;
77+ }
78+ if(size < 32*1024 || size > 256*1024) {
79+ print("got %lud byte loader; not likely\n", size);
80+ b->state = FAILED;
81+ return FAIL;
82+ }
83+
84+ p = b->bp;
85+ q = b->wp;
86+ if(q - p > 10000) /* don't search much past l.s */
87+ q = p+10000;
88+
89+ /*
90+ * The string `JUMP' appears right before
91+ * tokzero, which is where we want to jump.
92+ */
93+ for(; p<q; p++) {
94+ if(strncmp(p, "JUMP", 4) == 0) {
95+ p += 4;
96+ warp9((ulong)p);
97+ }
98+ }
99+ print("could not find jump destination\n");
100+ b->state = FAILED;
101+ return FAIL;
102+
103+ default:
104+ panic("bootdone");
105+ }
106+ b->state = FAILED;
107+ return FAIL;
108+}
os/boot/pc/bootp.c+652−0
@@ -0,0 +1,652 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+#include "ip.h"
9+
10+uchar broadcast[Eaddrlen] = {
11+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
12+};
13+
14+static ushort tftpport = 5000;
15+static int Id = 1;
16+static Netaddr myaddr;
17+static Netaddr server;
18+
19+typedef struct {
20+ uchar header[4];
21+ uchar data[Segsize];
22+} Tftp;
23+static Tftp tftpb;
24+
25+static void
26+hnputs(uchar *ptr, ushort val)
27+{
28+ ptr[0] = val>>8;
29+ ptr[1] = val;
30+}
31+
32+static void
33+hnputl(uchar *ptr, ulong val)
34+{
35+ ptr[0] = val>>24;
36+ ptr[1] = val>>16;
37+ ptr[2] = val>>8;
38+ ptr[3] = val;
39+}
40+
41+static ulong
42+nhgetl(uchar *ptr)
43+{
44+ return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
45+}
46+
47+static ushort
48+nhgets(uchar *ptr)
49+{
50+ return ((ptr[0]<<8) | ptr[1]);
51+}
52+
53+static short endian = 1;
54+static char* aendian = (char*)&endian;
55+#define LITTLE *aendian
56+
57+static ushort
58+ptcl_csum(void *a, int len)
59+{
60+ uchar *addr;
61+ ulong t1, t2;
62+ ulong losum, hisum, mdsum, x;
63+
64+ addr = a;
65+ losum = 0;
66+ hisum = 0;
67+ mdsum = 0;
68+
69+ x = 0;
70+ if((ulong)addr & 1) {
71+ if(len) {
72+ hisum += addr[0];
73+ len--;
74+ addr++;
75+ }
76+ x = 1;
77+ }
78+ while(len >= 16) {
79+ t1 = *(ushort*)(addr+0);
80+ t2 = *(ushort*)(addr+2); mdsum += t1;
81+ t1 = *(ushort*)(addr+4); mdsum += t2;
82+ t2 = *(ushort*)(addr+6); mdsum += t1;
83+ t1 = *(ushort*)(addr+8); mdsum += t2;
84+ t2 = *(ushort*)(addr+10); mdsum += t1;
85+ t1 = *(ushort*)(addr+12); mdsum += t2;
86+ t2 = *(ushort*)(addr+14); mdsum += t1;
87+ mdsum += t2;
88+ len -= 16;
89+ addr += 16;
90+ }
91+ while(len >= 2) {
92+ mdsum += *(ushort*)addr;
93+ len -= 2;
94+ addr += 2;
95+ }
96+ if(x) {
97+ if(len)
98+ losum += addr[0];
99+ if(LITTLE)
100+ losum += mdsum;
101+ else
102+ hisum += mdsum;
103+ } else {
104+ if(len)
105+ hisum += addr[0];
106+ if(LITTLE)
107+ hisum += mdsum;
108+ else
109+ losum += mdsum;
110+ }
111+
112+ losum += hisum >> 8;
113+ losum += (hisum & 0xff) << 8;
114+ while(hisum = losum>>16)
115+ losum = hisum + (losum & 0xffff);
116+
117+ return ~losum;
118+}
119+
120+static ushort
121+ip_csum(uchar *addr)
122+{
123+ int len;
124+ ulong sum = 0;
125+
126+ len = (addr[0]&0xf)<<2;
127+
128+ while(len > 0) {
129+ sum += addr[0]<<8 | addr[1] ;
130+ len -= 2;
131+ addr += 2;
132+ }
133+
134+ sum = (sum & 0xffff) + (sum >> 16);
135+ sum = (sum & 0xffff) + (sum >> 16);
136+ return (sum^0xffff);
137+}
138+
139+enum {
140+ /* this is only true of IPv4, but we're not doing v6 yet */
141+ Min_udp_payload = ETHERMINTU - ETHERHDRSIZE - UDP_HDRSIZE,
142+};
143+
144+static void
145+udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
146+{
147+ char payload[ETHERMAXTU];
148+ Udphdr *uh;
149+ Etherhdr *ip;
150+ Etherpkt pkt;
151+ int len, ptcllen;
152+
153+ /*
154+ * if packet is too short, make it longer rather than relying
155+ * on ethernet interface or lower layers to pad it.
156+ */
157+ if (dlen < Min_udp_payload) {
158+ memmove(payload, data, dlen);
159+ data = payload;
160+ dlen = Min_udp_payload;
161+ }
162+
163+ uh = (Udphdr*)&pkt;
164+
165+ memset(uh, 0, sizeof(Etherpkt));
166+ memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
167+
168+ /*
169+ * UDP portion
170+ */
171+ ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
172+ uh->ttl = 0;
173+ uh->udpproto = IP_UDPPROTO;
174+ uh->frag[0] = 0;
175+ uh->frag[1] = 0;
176+ hnputs(uh->udpplen, ptcllen);
177+ hnputl(uh->udpsrc, myaddr.ip);
178+ hnputs(uh->udpsport, myaddr.port);
179+ hnputl(uh->udpdst, a->ip);
180+ hnputs(uh->udpdport, a->port);
181+ hnputs(uh->udplen, ptcllen);
182+ uh->udpcksum[0] = 0;
183+ uh->udpcksum[1] = 0;
184+ dlen = (dlen+1)&~1;
185+ hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
186+
187+ /*
188+ * IP portion
189+ */
190+ ip = (Etherhdr*)&pkt;
191+ len = UDP_EHSIZE+UDP_HDRSIZE+dlen; /* non-descriptive names */
192+ ip->vihl = IP_VER|IP_HLEN;
193+ ip->tos = 0;
194+ ip->ttl = 255;
195+ hnputs(ip->length, len-ETHER_HDR);
196+ hnputs(ip->id, Id++);
197+ ip->frag[0] = 0;
198+ ip->frag[1] = 0;
199+ ip->cksum[0] = 0;
200+ ip->cksum[1] = 0;
201+ hnputs(ip->cksum, ip_csum(&ip->vihl));
202+
203+ /*
204+ * Ethernet MAC portion
205+ */
206+ hnputs(ip->type, ET_IP);
207+ memmove(ip->d, a->ea, sizeof(ip->d));
208+
209+if(debug) {
210+ print("udpsend ");
211+}
212+ ethertxpkt(ctlrno, &pkt, len, Timeout);
213+}
214+
215+static void
216+nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
217+{
218+ int n;
219+ char buf[128];
220+
221+ buf[0] = 0;
222+ buf[1] = Tftp_ERROR;
223+ buf[2] = 0;
224+ buf[3] = code;
225+ strcpy(buf+4, msg);
226+ n = strlen(msg) + 4 + 1;
227+ udpsend(ctlrno, a, buf, n);
228+ if(report)
229+ print("\ntftp: error(%d): %s\n", code, msg);
230+}
231+
232+static int
233+udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
234+{
235+ int n, len;
236+ ushort csm;
237+ Udphdr *h;
238+ ulong addr, timo;
239+ Etherpkt pkt;
240+ static int rxactive;
241+
242+ if(rxactive == 0)
243+ timo = 1000;
244+ else
245+ timo = Timeout;
246+ timo += TK2MS(m->ticks);
247+ while(timo > TK2MS(m->ticks)){
248+ n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
249+ if(n <= 0)
250+ continue;
251+
252+ h = (Udphdr*)&pkt;
253+ if(debug)
254+ print("udprecv %E to %E...\n", h->s, h->d);
255+
256+ if(nhgets(h->type) != ET_IP) {
257+ if(debug)
258+ print("not ip...");
259+ continue;
260+ }
261+
262+ if(ip_csum(&h->vihl)) {
263+ print("ip chksum error\n");
264+ continue;
265+ }
266+ if(h->vihl != (IP_VER|IP_HLEN)) {
267+ print("ip bad vers/hlen\n");
268+ continue;
269+ }
270+
271+ if(h->udpproto != IP_UDPPROTO) {
272+ if(debug)
273+ print("not udp (%d)...", h->udpproto);
274+ continue;
275+ }
276+
277+ if(debug)
278+ print("okay udp...");
279+
280+ h->ttl = 0;
281+ len = nhgets(h->udplen);
282+ hnputs(h->udpplen, len);
283+
284+ if(nhgets(h->udpcksum)) {
285+ csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
286+ if(csm != 0) {
287+ print("udp chksum error csum #%4ux len %d\n",
288+ csm, n);
289+ break;
290+ }
291+ }
292+
293+ if(a->port != 0 && nhgets(h->udpsport) != a->port) {
294+ if(debug)
295+ print("udpport %ux %ux\n",
296+ nhgets(h->udpsport), a->port);
297+ continue;
298+ }
299+
300+ addr = nhgetl(h->udpsrc);
301+ if(a->ip != Bcastip && addr != a->ip) {
302+ if(debug)
303+ print("bad ip\n");
304+ continue;
305+ }
306+
307+ len -= UDP_HDRSIZE-UDP_PHDRSIZE;
308+ if(len > dlen) {
309+ print("udp: packet too big: %d > %d; from addr %E\n",
310+ len, dlen, h->udpsrc);
311+ continue;
312+ }
313+
314+ memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
315+ a->ip = addr;
316+ a->port = nhgets(h->udpsport);
317+ memmove(a->ea, pkt.s, sizeof(a->ea));
318+
319+ rxactive = 1;
320+ return len;
321+ }
322+
323+ return 0;
324+}
325+
326+static int tftpblockno;
327+
328+/*
329+ * format of a request packet, from the RFC:
330+ *
331+ 2 bytes string 1 byte string 1 byte
332+ ------------------------------------------------
333+ | Opcode | Filename | 0 | Mode | 0 |
334+ ------------------------------------------------
335+ */
336+static int
337+tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
338+{
339+ int i, len, rlen, oport;
340+ char buf[Segsize+2];
341+
342+ buf[0] = 0;
343+ buf[1] = Tftp_READ;
344+ len = 2 + sprint(buf+2, "%s", name) + 1;
345+ len += sprint(buf+len, "octet") + 1;
346+
347+ oport = a->port;
348+ for(i = 0; i < 5; i++){
349+ a->port = oport;
350+ udpsend(ctlrno, a, buf, len);
351+ a->port = 0;
352+ if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
353+ continue;
354+
355+ switch((tftp->header[0]<<8)|tftp->header[1]){
356+
357+ case Tftp_ERROR:
358+ print("tftpopen: error (%d): %s\n",
359+ (tftp->header[2]<<8)|tftp->header[3], (char*)tftp->data);
360+ return -1;
361+
362+ case Tftp_DATA:
363+ tftpblockno = 1;
364+ len = (tftp->header[2]<<8)|tftp->header[3];
365+ if(len != tftpblockno){
366+ print("tftpopen: block error: %d\n", len);
367+ nak(ctlrno, a, 1, "block error", 0);
368+ return -1;
369+ }
370+ rlen -= sizeof(tftp->header);
371+ if(rlen < Segsize){
372+ /* ACK now, in case we don't later */
373+ buf[0] = 0;
374+ buf[1] = Tftp_ACK;
375+ buf[2] = tftpblockno>>8;
376+ buf[3] = tftpblockno;
377+ udpsend(ctlrno, a, buf, sizeof(tftp->header));
378+ }
379+ return rlen;
380+ }
381+ }
382+
383+ print("tftpopen: failed to connect to server\n");
384+ return -1;
385+}
386+
387+static int
388+tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
389+{
390+ uchar buf[4];
391+ int try, blockno, len;
392+
393+ dlen += sizeof(tftp->header);
394+
395+ for(try = 0; try < 10; try++) {
396+ buf[0] = 0;
397+ buf[1] = Tftp_ACK;
398+ buf[2] = tftpblockno>>8;
399+ buf[3] = tftpblockno;
400+
401+ udpsend(ctlrno, a, buf, sizeof(buf));
402+ len = udprecv(ctlrno, a, tftp, dlen);
403+ if(len <= sizeof(tftp->header)){
404+ if(debug)
405+ print("tftpread: too short %d <= %d\n",
406+ len, sizeof(tftp->header));
407+ continue;
408+ }
409+ blockno = (tftp->header[2]<<8)|tftp->header[3];
410+ if(blockno <= tftpblockno){
411+ if(debug)
412+ print("tftpread: blkno %d <= %d\n",
413+ blockno, tftpblockno);
414+ continue;
415+ }
416+
417+ if(blockno == tftpblockno+1) {
418+ tftpblockno++;
419+ if(len < dlen) { /* last packet; send final ack */
420+ tftpblockno++;
421+ buf[0] = 0;
422+ buf[1] = Tftp_ACK;
423+ buf[2] = tftpblockno>>8;
424+ buf[3] = tftpblockno;
425+ udpsend(ctlrno, a, buf, sizeof(buf));
426+ }
427+ return len-sizeof(tftp->header);
428+ }
429+ print("tftpread: block error: %d, expected %d\n",
430+ blockno, tftpblockno+1);
431+ }
432+
433+ return -1;
434+}
435+
436+static int
437+bootpopen(int ctlrno, char *file, Bootp *rep, int dotftpopen)
438+{
439+ Bootp req;
440+ int i, n;
441+ uchar *ea;
442+ char name[128], *filename, *sysname;
443+
444+ if((ea = etheraddr(ctlrno)) == 0){
445+ print("invalid ctlrno %d\n", ctlrno);
446+ return -1;
447+ }
448+
449+ filename = 0;
450+ sysname = 0;
451+ if(file && *file){
452+ strcpy(name, file);
453+ if(filename = strchr(name, '!')){
454+ sysname = name;
455+ *filename++ = 0;
456+ }
457+ else
458+ filename = name;
459+ }
460+
461+ memset(&req, 0, sizeof(req));
462+ req.op = Bootrequest;
463+ req.htype = 1; /* ethernet */
464+ req.hlen = Eaddrlen; /* ethernet */
465+ memmove(req.chaddr, ea, Eaddrlen);
466+ if(filename != nil)
467+ strncpy(req.file, filename, sizeof(req.file));
468+ if(sysname != nil)
469+ strncpy(req.sname, sysname, sizeof(req.sname));
470+
471+ myaddr.ip = 0;
472+ myaddr.port = BPportsrc;
473+ memmove(myaddr.ea, ea, Eaddrlen);
474+
475+ etherrxflush(ctlrno);
476+ for(i = 0; i < 10; i++) {
477+ server.ip = Bcastip;
478+ server.port = BPportdst;
479+ memmove(server.ea, broadcast, sizeof(server.ea));
480+ udpsend(ctlrno, &server, &req, sizeof(req));
481+ if(udprecv(ctlrno, &server, rep, sizeof(*rep)) <= 0)
482+ continue;
483+ if(memcmp(req.chaddr, rep->chaddr, Eaddrlen))
484+ continue;
485+ if(rep->htype != 1 || rep->hlen != Eaddrlen)
486+ continue;
487+ if(sysname == 0 || strcmp(sysname, rep->sname) == 0)
488+ break;
489+ }
490+ if(i >= 10) {
491+ print("bootp timed out\n");
492+ return -1;
493+ }
494+
495+ if(!dotftpopen)
496+ return 0;
497+
498+ if(filename == 0 || *filename == 0){
499+ if(strcmp(rep->file, "/386/9pxeload") == 0)
500+ return -1;
501+ filename = rep->file;
502+ }
503+
504+ if(rep->sname[0] != '\0')
505+ print("%s ", rep->sname);
506+ print("(%d.%d.%d.%d!%d): %s\n",
507+ rep->siaddr[0],
508+ rep->siaddr[1],
509+ rep->siaddr[2],
510+ rep->siaddr[3],
511+ server.port,
512+ filename);
513+
514+ myaddr.ip = nhgetl(rep->yiaddr);
515+ myaddr.port = tftpport++;
516+ server.ip = nhgetl(rep->siaddr);
517+ server.port = TFTPport;
518+
519+ if((n = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
520+ return -1;
521+
522+ return n;
523+}
524+
525+int
526+bootpboot(int ctlrno, char *file, Boot *b)
527+{
528+ int n;
529+ Bootp rep;
530+
531+ if((n = bootpopen(ctlrno, file, &rep, 1)) < 0)
532+ return -1;
533+
534+ while(bootpass(b, tftpb.data, n) == MORE){
535+ n = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data));
536+ if(n < sizeof(tftpb.data))
537+ break;
538+ }
539+
540+ if(0 < n && n < sizeof(tftpb.data)) /* got to end of file */
541+ bootpass(b, tftpb.data, n);
542+ else
543+ nak(ctlrno, &server, 3, "ok", 0); /* tftpclose to abort transfer */
544+ bootpass(b, nil, 0); /* boot if possible */
545+ return -1;
546+}
547+
548+#include "fs.h"
549+
550+#define INIPATHLEN 64
551+
552+static struct {
553+ Fs fs;
554+ char ini[INIPATHLEN];
555+} pxether[MaxEther];
556+
557+static vlong
558+pxediskseek(Fs*, vlong)
559+{
560+ return -1LL;
561+}
562+
563+static long
564+pxediskread(Fs*, void*, long)
565+{
566+ return -1;
567+}
568+
569+static long
570+pxeread(File* f, void* va, long len)
571+{
572+ int n;
573+ Bootp rep;
574+ char *p, *v;
575+
576+ if((n = bootpopen(f->fs->dev, pxether[f->fs->dev].ini, &rep, 1)) < 0)
577+ return -1;
578+
579+ p = v = va;
580+ while(n > 0) {
581+ if((p-v)+n > len)
582+ n = len - (p-v);
583+ memmove(p, tftpb.data, n);
584+ p += n;
585+ if(n != Segsize)
586+ break;
587+ if((n = tftpread(f->fs->dev, &server, &tftpb, sizeof(tftpb.data))) < 0)
588+ return -1;
589+ }
590+ return p-v;
591+}
592+
593+static int
594+pxewalk(File* f, char* name)
595+{
596+ Bootp rep;
597+ char *ini;
598+
599+ switch(f->walked){
600+ default:
601+ return -1;
602+ case 0:
603+ if(strcmp(name, "cfg") == 0){
604+ f->walked = 1;
605+ return 1;
606+ }
607+ break;
608+ case 1:
609+ if(strcmp(name, "pxe") == 0){
610+ f->walked = 2;
611+ return 1;
612+ }
613+ break;
614+ case 2:
615+ if(strcmp(name, "%E") != 0)
616+ break;
617+ f->walked = 3;
618+
619+ if(bootpopen(f->fs->dev, nil, &rep, 0) < 0)
620+ return 0;
621+
622+ ini = pxether[f->fs->dev].ini;
623+ snprint(ini, INIPATHLEN, "/cfg/pxe/%E", rep.chaddr);
624+ f->path = ini;
625+
626+ return 1;
627+ }
628+ return 0;
629+}
630+
631+void*
632+pxegetfspart(int ctlrno, char* part, int)
633+{
634+ if(!pxe)
635+ return nil;
636+ if(strcmp(part, "*") != 0)
637+ return nil;
638+ if(ctlrno >= MaxEther)
639+ return nil;
640+
641+ pxether[ctlrno].fs.dev = ctlrno;
642+ pxether[ctlrno].fs.diskread = pxediskread;
643+ pxether[ctlrno].fs.diskseek = pxediskseek;
644+
645+ pxether[ctlrno].fs.read = pxeread;
646+ pxether[ctlrno].fs.walk = pxewalk;
647+
648+ pxether[ctlrno].fs.root.fs = &pxether[ctlrno].fs;
649+ pxether[ctlrno].fs.root.walked = 0;
650+
651+ return &pxether[ctlrno].fs;
652+}
os/boot/pc/cga.c+91−0
@@ -0,0 +1,91 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+
7+enum {
8+ Width = 160,
9+ Height = 25,
10+
11+ Attr = 7, /* white on black */
12+};
13+
14+#define CGASCREENBASE ((uchar*)KADDR(0xB8000))
15+
16+static int pos;
17+static int screeninitdone;
18+
19+static uchar
20+cgaregr(int index)
21+{
22+ outb(0x3D4, index);
23+ return inb(0x3D4+1) & 0xFF;
24+}
25+
26+static void
27+cgaregw(int index, int data)
28+{
29+ outb(0x3D4, index);
30+ outb(0x3D4+1, data);
31+}
32+
33+static void
34+movecursor(void)
35+{
36+ cgaregw(0x0E, (pos/2>>8) & 0xFF);
37+ cgaregw(0x0F, pos/2 & 0xFF);
38+ CGASCREENBASE[pos+1] = Attr;
39+}
40+
41+static void
42+cgascreenputc(int c)
43+{
44+ int i;
45+
46+ if(c == '\n'){
47+ pos = pos/Width;
48+ pos = (pos+1)*Width;
49+ }
50+ else if(c == '\t'){
51+ i = 8 - ((pos/2)&7);
52+ while(i-->0)
53+ cgascreenputc(' ');
54+ }
55+ else if(c == '\b'){
56+ if(pos >= 2)
57+ pos -= 2;
58+ cgascreenputc(' ');
59+ pos -= 2;
60+ }
61+ else{
62+ CGASCREENBASE[pos++] = c;
63+ CGASCREENBASE[pos++] = Attr;
64+ }
65+ if(pos >= Width*Height){
66+ memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
67+ memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
68+ pos = Width*(Height-1);
69+ }
70+ movecursor();
71+}
72+
73+static void
74+screeninit(void)
75+{
76+ if(screeninitdone == 0){
77+ pos = cgaregr(0x0E)<<8;
78+ pos |= cgaregr(0x0F);
79+ pos *= 2;
80+ screeninitdone = 1;
81+ }
82+}
83+
84+void
85+cgascreenputs(char* s, int n)
86+{
87+ if(screeninitdone == 0)
88+ screeninit();
89+ while(n-- > 0)
90+ cgascreenputc(*s++);
91+}
os/boot/pc/clock.c+305−0
@@ -0,0 +1,305 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+#include "ureg.h"
8+
9+/*
10+ * 8253 timer
11+ */
12+enum
13+{
14+ T0cntr= 0x40, /* counter ports */
15+ T1cntr= 0x41, /* ... */
16+ T2cntr= 0x42, /* ... */
17+ Tmode= 0x43, /* mode port */
18+
19+ /* commands */
20+ Latch0= 0x00, /* latch counter 0's value */
21+ Load0= 0x30, /* load counter 0 with 2 bytes */
22+
23+ /* modes */
24+ Square= 0x36, /* perioic square wave */
25+
26+ Freq= 1193182, /* Real clock frequency */
27+};
28+
29+static uvlong cpuhz = 66000000;
30+static int cpumhz = 66;
31+static int loopconst = 100;
32+int cpuidax, cpuiddx;
33+int havetsc;
34+
35+extern void _cycles(uvlong*); /* in l.s */
36+extern void wrmsr(int, vlong);
37+
38+static void
39+clockintr(Ureg*, void*)
40+{
41+ m->ticks++;
42+ checkalarms();
43+}
44+
45+#define STEPPING(x) ((x)&0xf)
46+#define X86MODEL(x) (((x)>>4)&0xf)
47+#define X86FAMILY(x) (((x)>>8)&0xf)
48+
49+enum
50+{
51+ /* flags */
52+ CpuidFPU = 0x001, /* on-chip floating point unit */
53+ CpuidMCE = 0x080, /* machine check exception */
54+ CpuidCX8 = 0x100, /* CMPXCHG8B instruction */
55+};
56+
57+typedef struct
58+{
59+ int family;
60+ int model;
61+ int aalcycles;
62+ char *name;
63+} X86type;
64+
65+X86type x86intel[] =
66+{
67+ { 4, 0, 22, "486DX", }, /* known chips */
68+ { 4, 1, 22, "486DX50", },
69+ { 4, 2, 22, "486SX", },
70+ { 4, 3, 22, "486DX2", },
71+ { 4, 4, 22, "486SL", },
72+ { 4, 5, 22, "486SX2", },
73+ { 4, 7, 22, "DX2WB", }, /* P24D */
74+ { 4, 8, 22, "DX4", }, /* P24C */
75+ { 4, 9, 22, "DX4WB", }, /* P24CT */
76+ { 5, 0, 23, "P5", },
77+ { 5, 1, 23, "P5", },
78+ { 5, 2, 23, "P54C", },
79+ { 5, 3, 23, "P24T", },
80+ { 5, 4, 23, "P55C MMX", },
81+ { 5, 7, 23, "P54C VRT", },
82+ { 6, 1, 16, "PentiumPro", },/* trial and error */
83+ { 6, 3, 16, "PentiumII", },
84+ { 6, 5, 16, "PentiumII/Xeon", },
85+ { 6, 6, 16, "Celeron", },
86+ { 6, 7, 16, "PentiumIII/Xeon", },
87+ { 6, 8, 16, "PentiumIII/Xeon", },
88+ { 6, 0xB, 16, "PentiumIII/Xeon", },
89+ { 0xF, 1, 16, "P4", }, /* P4 */
90+ { 0xF, 2, 16, "PentiumIV/Xeon", },
91+
92+ { 3, -1, 32, "386", }, /* family defaults */
93+ { 4, -1, 22, "486", },
94+ { 5, -1, 23, "P5", },
95+ { 6, -1, 16, "P6", },
96+ { 0xF, -1, 16, "P4", }, /* P4 */
97+
98+ { -1, -1, 16, "unknown", }, /* total default */
99+};
100+
101+
102+/*
103+ * The AMD processors all implement the CPUID instruction.
104+ * The later ones also return the processor name via functions
105+ * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX
106+ * and DX:
107+ * K5 "AMD-K5(tm) Processor"
108+ * K6 "AMD-K6tm w/ multimedia extensions"
109+ * K6 3D "AMD-K6(tm) 3D processor"
110+ * K6 3D+ ?
111+ */
112+static X86type x86amd[] =
113+{
114+ { 5, 0, 23, "AMD-K5", }, /* guesswork */
115+ { 5, 1, 23, "AMD-K5", }, /* guesswork */
116+ { 5, 2, 23, "AMD-K5", }, /* guesswork */
117+ { 5, 3, 23, "AMD-K5", }, /* guesswork */
118+ { 5, 6, 11, "AMD-K6", }, /* trial and error */
119+ { 5, 7, 11, "AMD-K6", }, /* trial and error */
120+ { 5, 8, 11, "AMD-K6-2", }, /* trial and error */
121+ { 5, 9, 11, "AMD-K6-III", },/* trial and error */
122+
123+ { 6, 1, 11, "AMD-Athlon", },/* trial and error */
124+ { 6, 2, 11, "AMD-Athlon", },/* trial and error */
125+
126+ { 4, -1, 22, "Am486", }, /* guesswork */
127+ { 5, -1, 23, "AMD-K5/K6", }, /* guesswork */
128+ { 6, -1, 11, "AMD-Athlon", },/* guesswork */
129+ { 0xF, -1, 11, "AMD64", }, /* guesswork */
130+
131+ { -1, -1, 11, "unknown", }, /* total default */
132+};
133+
134+static X86type *cputype;
135+
136+
137+void
138+delay(int millisecs)
139+{
140+ millisecs *= loopconst;
141+ if(millisecs <= 0)
142+ millisecs = 1;
143+ aamloop(millisecs);
144+}
145+
146+void
147+microdelay(int microsecs)
148+{
149+ microsecs *= loopconst;
150+ microsecs /= 1000;
151+ if(microsecs <= 0)
152+ microsecs = 1;
153+ aamloop(microsecs);
154+}
155+
156+extern void cpuid(char*, int*, int*);
157+
158+X86type*
159+cpuidentify(void)
160+{
161+ int family, model;
162+ X86type *t;
163+ char cpuidid[16];
164+ int cpuidax, cpuiddx;
165+
166+ cpuid(cpuidid, &cpuidax, &cpuiddx);
167+ if(strncmp(cpuidid, "AuthenticAMD", 12) == 0)
168+ t = x86amd;
169+ else
170+ t = x86intel;
171+ family = X86FAMILY(cpuidax);
172+ model = X86MODEL(cpuidax);
173+ if (0)
174+ print("cpuidentify: cpuidax 0x%ux cpuiddx 0x%ux\n",
175+ cpuidax, cpuiddx);
176+ while(t->name){
177+ if((t->family == family && t->model == model)
178+ || (t->family == family && t->model == -1)
179+ || (t->family == -1))
180+ break;
181+ t++;
182+ }
183+ if(t->name == nil)
184+ panic("cpuidentify");
185+
186+ if(cpuiddx & 0x10){
187+ havetsc = 1;
188+ if(cpuiddx & 0x20)
189+ wrmsr(0x10, 0);
190+ }
191+
192+ return t;
193+}
194+
195+void
196+clockinit(void)
197+{
198+ uvlong a, b, cpufreq;
199+ int loops, incr, x, y;
200+ X86type *t;
201+
202+ /*
203+ * set vector for clock interrupts
204+ */
205+ setvec(VectorCLOCK, clockintr, 0);
206+
207+ t = cpuidentify();
208+
209+ /*
210+ * set clock for 1/HZ seconds
211+ */
212+ outb(Tmode, Load0|Square);
213+ outb(T0cntr, (Freq/HZ)); /* low byte */
214+ outb(T0cntr, (Freq/HZ)>>8); /* high byte */
215+
216+ /*
217+ * Introduce a little delay to make sure the count is
218+ * latched and the timer is counting down; with a fast
219+ * enough processor this may not be the case.
220+ * The i8254 (which this probably is) has a read-back
221+ * command which can be used to make sure the counting
222+ * register has been written into the counting element.
223+ */
224+ x = (Freq/HZ);
225+ for(loops = 0; loops < 100000 && x >= (Freq/HZ); loops++){
226+ outb(Tmode, Latch0);
227+ x = inb(T0cntr);
228+ x |= inb(T0cntr)<<8;
229+ }
230+
231+ /* find biggest loop that doesn't wrap */
232+ incr = 16000000/(t->aalcycles*HZ*2);
233+ x = 2000;
234+ for(loops = incr; loops < 64*1024; loops += incr) {
235+
236+ /*
237+ * measure time for the loop
238+ *
239+ * MOVL loops,CX
240+ * aaml1: AAM
241+ * LOOP aaml1
242+ *
243+ * the time for the loop should be independent of external
244+ * cache and memory system since it fits in the execution
245+ * prefetch buffer.
246+ *
247+ */
248+ outb(Tmode, Latch0);
249+ if(havetsc)
250+ _cycles(&a);
251+ x = inb(T0cntr);
252+ x |= inb(T0cntr)<<8;
253+ aamloop(loops);
254+ outb(Tmode, Latch0);
255+ if(havetsc)
256+ _cycles(&b);
257+ y = inb(T0cntr);
258+ y |= inb(T0cntr)<<8;
259+ x -= y;
260+
261+ if(x < 0)
262+ x += Freq/HZ;
263+
264+ if(x > Freq/(3*HZ))
265+ break;
266+ }
267+
268+ /*
269+ * figure out clock frequency and a loop multiplier for delay().
270+ * counter goes at twice the frequency, once per transition,
271+ * i.e., twice per square wave
272+ */
273+ cpufreq = (vlong)loops*((t->aalcycles*2*Freq)/x);
274+ loopconst = (cpufreq/1000)/t->aalcycles; /* AAM+LOOP's for 1 ms */
275+
276+ if(havetsc){
277+ /* counter goes up by 2*Freq */
278+ b = (b-a)<<1;
279+ b *= Freq;
280+ b /= x;
281+
282+ /*
283+ * round to the nearest megahz
284+ */
285+ cpumhz = (b+500000)/1000000L;
286+ cpuhz = b;
287+ }
288+ else{
289+ /*
290+ * add in possible .5% error and convert to MHz
291+ */
292+ cpumhz = (cpufreq + cpufreq/200)/1000000;
293+ cpuhz = cpufreq;
294+ }
295+
296+ if(debug){
297+ int timeo;
298+
299+ print("%dMHz %s loop %d\n", cpumhz, t->name, loopconst);
300+ print("tick...");
301+ for(timeo = 0; timeo < 10; timeo++)
302+ delay(1000);
303+ print("tock...\n");
304+ }
305+}
os/boot/pc/conf.c+537−0
@@ -0,0 +1,537 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+#include "fs.h"
9+
10+/*
11+ * Where configuration info is left for the loaded programme.
12+ * This will turn into a structure as more is done by the boot loader
13+ * (e.g. why parse the .ini file twice?).
14+ * There are 3584 bytes available at CONFADDR.
15+ *
16+ * The low-level boot routines in l.s leave data for us at CONFADDR,
17+ * which we pick up before reading the plan9.ini file.
18+ */
19+#define BOOTLINELEN 64
20+#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
21+#define BOOTARGSLEN (3584-0x200-BOOTLINELEN)
22+#define MAXCONF 100
23+
24+static char *confname[MAXCONF];
25+static char *confval[MAXCONF];
26+static int nconf;
27+
28+extern char **ini;
29+
30+typedef struct {
31+ char* name;
32+ int start;
33+ int end;
34+} Mblock;
35+
36+typedef struct {
37+ char* tag;
38+ Mblock* mb;
39+} Mitem;
40+
41+static Mblock mblock[MAXCONF];
42+static int nmblock;
43+static Mitem mitem[MAXCONF];
44+static int nmitem;
45+static char* mdefault;
46+static char mdefaultbuf[10];
47+static int mtimeout;
48+
49+static char*
50+comma(char* line, char** residue)
51+{
52+ char *q, *r;
53+
54+ if((q = strchr(line, ',')) != nil){
55+ *q++ = 0;
56+ if(*q == ' ')
57+ q++;
58+ }
59+ *residue = q;
60+
61+ if((r = strchr(line, ' ')) != nil)
62+ *r = 0;
63+
64+ if(*line == ' ')
65+ line++;
66+ return line;
67+}
68+
69+static Mblock*
70+findblock(char* name, char** residue)
71+{
72+ int i;
73+ char *p;
74+
75+ p = comma(name, residue);
76+ for(i = 0; i < nmblock; i++){
77+ if(strcmp(p, mblock[i].name) == 0)
78+ return &mblock[i];
79+ }
80+ return nil;
81+}
82+
83+static Mitem*
84+finditem(char* name, char** residue)
85+{
86+ int i;
87+ char *p;
88+
89+ p = comma(name, residue);
90+ for(i = 0; i < nmitem; i++){
91+ if(strcmp(p, mitem[i].mb->name) == 0)
92+ return &mitem[i];
93+ }
94+ return nil;
95+}
96+
97+static void
98+parsemenu(char* str, char* scratch, int len)
99+{
100+ Mitem *mi;
101+ Mblock *mb, *menu;
102+ char buf[20], *p, *q, *line[MAXCONF];
103+ int i, inblock, n, show;
104+
105+ inblock = 0;
106+ menu = nil;
107+ memmove(scratch, str, len);
108+ n = getfields(scratch, line, MAXCONF, '\n');
109+ if(n >= MAXCONF)
110+ print("warning: possibly too many lines in plan9.ini\n");
111+ for(i = 0; i < n; i++){
112+ p = line[i];
113+ if(inblock && *p == '['){
114+ mblock[nmblock].end = i;
115+ if(strcmp(mblock[nmblock].name, "menu") == 0)
116+ menu = &mblock[nmblock];
117+ nmblock++;
118+ inblock = 0;
119+ }
120+ if(*p == '['){
121+ if(nmblock == 0 && i != 0){
122+ mblock[nmblock].name = "common";
123+ mblock[nmblock].start = 0;
124+ mblock[nmblock].end = i;
125+ nmblock++;
126+ }
127+ q = strchr(p+1, ']');
128+ if(q == nil || *(q+1) != 0){
129+ print("malformed menu block header - %s\n", p);
130+ return;
131+ }
132+ *q = 0;
133+ mblock[nmblock].name = p+1;
134+ mblock[nmblock].start = i+1;
135+ inblock = 1;
136+ }
137+ }
138+
139+ if(inblock){
140+ mblock[nmblock].end = i;
141+ nmblock++;
142+ }
143+ if(menu == nil)
144+ return;
145+ if(nmblock < 2){
146+ print("incomplete menu specification\n");
147+ return;
148+ }
149+
150+ for(i = menu->start; i < menu->end; i++){
151+ p = line[i];
152+ if(cistrncmp(p, "menuitem=", 9) == 0){
153+ p += 9;
154+ if((mb = findblock(p, &q)) == nil){
155+ print("no block for menuitem %s\n", p);
156+ return;
157+ }
158+ if(q != nil)
159+ mitem[nmitem].tag = q;
160+ else
161+ mitem[nmitem].tag = mb->name;
162+ mitem[nmitem].mb = mb;
163+ nmitem++;
164+ }
165+ else if(cistrncmp(p, "menudefault=", 12) == 0){
166+ p += 12;
167+ if((mi = finditem(p, &q)) == nil){
168+ print("no item for menudefault %s\n", p);
169+ return;
170+ }
171+ if(q != nil)
172+ mtimeout = strtol(q, 0, 0);
173+ sprint(mdefaultbuf, "%ld", mi-mitem+1);
174+ mdefault = mdefaultbuf;
175+ }
176+ else if(cistrncmp(p, "menuconsole=", 12) == 0){
177+ p += 12;
178+ p = comma(p, &q);
179+ consinit(p, q);
180+ }
181+ else{
182+ print("invalid line in [menu] block - %s\n", p);
183+ return;
184+ }
185+ }
186+
187+again:
188+ print("\nPlan 9 Startup Menu:\n====================\n");
189+ for(i = 0; i < nmitem; i++)
190+ print(" %d. %s\n", i+1, mitem[i].tag);
191+ for(;;){
192+ getstr("Selection", buf, sizeof(buf), mdefault, mtimeout);
193+ mtimeout = 0;
194+ i = strtol(buf, &p, 0)-1;
195+ if(i < 0 || i >= nmitem)
196+ goto again;
197+ switch(*p){
198+ case 'p':
199+ case 'P':
200+ show = 1;
201+ print("\n");
202+ break;
203+ case 0:
204+ show = 0;
205+ break;
206+ default:
207+ continue;
208+
209+ }
210+ mi = &mitem[i];
211+
212+ p = str;
213+ p += sprint(p, "menuitem=%s\n", mi->mb->name);
214+ for(i = 0; i < nmblock; i++){
215+ mb = &mblock[i];
216+ if(mi->mb != mb && cistrcmp(mb->name, "common") != 0)
217+ continue;
218+ for(n = mb->start; n < mb->end; n++)
219+ p += sprint(p, "%s\n", line[n]);
220+ }
221+
222+ if(show){
223+ for(q = str; q < p; q += i){
224+ if((i = print(q)) <= 0)
225+ break;
226+ }
227+ goto again;
228+ }
229+ break;
230+ }
231+ print("\n");
232+}
233+
234+/*
235+static void
236+msleep(int msec)
237+{
238+ ulong start;
239+
240+ for(start = m->ticks; TK2MS(m->ticks - start) < msec; )
241+ ;
242+}
243+*/
244+
245+void
246+readlsconf(void)
247+{
248+ uchar *p;
249+
250+ p = (uchar*)CONFADDR;
251+ for(;;) {
252+ if(strcmp((char*)p, "APM") == 0){
253+ apm.haveinfo = 1;
254+ apm.ax = *(ushort*)(p+4);
255+ apm.cx = *(ushort*)(p+6);
256+ apm.dx = *(ushort*)(p+8);
257+ apm.di = *(ushort*)(p+10);
258+ apm.ebx = *(ulong*)(p+12);
259+ apm.esi = *(ulong*)(p+16);
260+ print("apm ax=%x cx=%x dx=%x di=%x ebx=%x esi=%x\n",
261+ apm.ax, apm.cx, apm.dx, apm.di, apm.ebx, apm.esi);
262+ p += 20;
263+ continue;
264+ }
265+ break;
266+ }
267+}
268+
269+char*
270+getconf(char *name)
271+{
272+ int i, n, nmatch;
273+ char buf[20];
274+
275+ nmatch = 0;
276+ for(i = 0; i < nconf; i++)
277+ if(cistrcmp(confname[i], name) == 0)
278+ nmatch++;
279+
280+ switch(nmatch) {
281+ default:
282+ print("\n");
283+ nmatch = 0;
284+ for(i = 0; i < nconf; i++)
285+ if(cistrcmp(confname[i], name) == 0)
286+ print("%d. %s\n", ++nmatch, confval[i]);
287+ print("%d. none of the above\n", ++nmatch);
288+ do {
289+ getstr(name, buf, sizeof(buf), nil, 0);
290+ n = atoi(buf);
291+ } while(n < 1 || n > nmatch);
292+
293+ for(i = 0; i < nconf; i++)
294+ if(cistrcmp(confname[i], name) == 0)
295+ if(--n == 0)
296+ return confval[i];
297+ break;
298+
299+ case 1:
300+ for(i = 0; i < nconf; i++)
301+ if(cistrcmp(confname[i], name) == 0)
302+ return confval[i];
303+ break;
304+
305+ case 0:
306+ break;
307+ }
308+ return nil;
309+}
310+
311+void
312+addconf(char *fmt, ...)
313+{
314+ va_list arg;
315+
316+ va_start(arg, fmt);
317+ vseprint(BOOTARGS+strlen(BOOTARGS), BOOTARGS+BOOTARGSLEN, fmt, arg);
318+ va_end(arg);
319+}
320+
321+void
322+changeconf(char *fmt, ...)
323+{
324+ va_list arg;
325+ char *p, *q, pref[20], buf[128];
326+
327+ va_start(arg, fmt);
328+ vseprint(buf, buf+sizeof buf, fmt, arg);
329+ va_end(arg);
330+ strncpy(pref+1, buf, 19);
331+ pref[19] = '\0';
332+ if(p = strchr(pref, '='))
333+ *(p+1) = '\0';
334+ else
335+ print("warning: did not change %s in plan9.ini\n", buf);
336+
337+ /* find old line by looking for \nwhat= */
338+ pref[0] = '\n';
339+ if(strncmp(BOOTARGS, pref+1, strlen(pref+1)) == 0)
340+ p = BOOTARGS;
341+ else if(p = strstr(BOOTARGS, pref))
342+ p++;
343+ else
344+ p = nil;
345+
346+ /* move rest of args up, deleting what= line. */
347+ if(p != nil && (q = strchr(p, '\n')) != nil)
348+ memmove(p, q+1, strlen(q+1)+1);
349+
350+ /* add replacement to end */
351+ addconf("%s", buf);
352+}
353+
354+/*
355+ * read configuration file
356+ */
357+static char inibuf[BOOTARGSLEN];
358+static char id[8] = "ZORT 0\r\n";
359+
360+int
361+dotini(Fs *fs)
362+{
363+ File rc;
364+ int blankline, i, incomment, inspace, n;
365+ char *cp, *p, *q, *line[MAXCONF];
366+
367+ if(fswalk(fs, *ini, &rc) <= 0)
368+ return -1;
369+
370+ cp = inibuf;
371+ *cp = 0;
372+ n = fsread(&rc, cp, BOOTARGSLEN-1);
373+ if(n <= 0)
374+ return -1;
375+
376+ cp[n] = 0;
377+
378+ /*
379+ * Strip out '\r', change '\t' -> ' '.
380+ * Change runs of spaces into single spaces.
381+ * Strip out trailing spaces, blank lines.
382+ *
383+ * We do this before we make the copy so that if we
384+ * need to change the copy, it is already fairly clean.
385+ * The main need is in the case when plan9.ini has been
386+ * padded with lots of trailing spaces, as is the case
387+ * for those created during a distribution install.
388+ */
389+ p = cp;
390+ blankline = 1;
391+ incomment = inspace = 0;
392+ for(q = cp; *q; q++){
393+ if(*q == '\r')
394+ continue;
395+ if(*q == '\t')
396+ *q = ' ';
397+ if(*q == ' '){
398+ inspace = 1;
399+ continue;
400+ }
401+ if(*q == '\n'){
402+ if(!blankline){
403+ if(!incomment)
404+ *p++ = '\n';
405+ blankline = 1;
406+ }
407+ incomment = inspace = 0;
408+ continue;
409+ }
410+ if(inspace){
411+ if(!blankline && !incomment)
412+ *p++ = ' ';
413+ inspace = 0;
414+ }
415+ if(blankline && *q == '#')
416+ incomment = 1;
417+ blankline = 0;
418+ if(!incomment)
419+ *p++ = *q;
420+ }
421+ if(p > cp && p[-1] != '\n')
422+ *p++ = '\n';
423+ *p++ = 0;
424+ n = p-cp;
425+
426+ parsemenu(cp, BOOTARGS, n);
427+
428+ /*
429+ * Keep a copy.
430+ * We could change this to pass the parsed strings
431+ * to the booted programme instead of the raw
432+ * string, then it only gets done once.
433+ */
434+ if(strncmp(cp, id, sizeof(id))){
435+ memmove(BOOTARGS, id, sizeof(id));
436+ if(n+1+sizeof(id) >= BOOTARGSLEN)
437+ n -= sizeof(id);
438+ memmove(BOOTARGS+sizeof(id), cp, n+1);
439+ }
440+ else
441+ memmove(BOOTARGS, cp, n+1);
442+
443+ n = getfields(cp, line, MAXCONF, '\n');
444+ for(i = 0; i < n; i++){
445+ cp = strchr(line[i], '=');
446+ if(cp == 0)
447+ continue;
448+ *cp++ = 0;
449+ if(cp - line[i] >= NAMELEN+1)
450+ *(line[i]+NAMELEN-1) = 0;
451+ confname[nconf] = line[i];
452+ confval[nconf] = cp;
453+ nconf++;
454+ }
455+ return 0;
456+}
457+
458+static int
459+parseether(uchar *to, char *from)
460+{
461+ char nip[4];
462+ char *p;
463+ int i;
464+
465+ p = from;
466+ while(*p == ' ')
467+ ++p;
468+ for(i = 0; i < 6; i++){
469+ if(*p == 0)
470+ return -1;
471+ nip[0] = *p++;
472+ if(*p == 0)
473+ return -1;
474+ nip[1] = *p++;
475+ nip[2] = 0;
476+ to[i] = strtoul(nip, 0, 16);
477+ if(*p == ':')
478+ p++;
479+ }
480+ return 0;
481+}
482+
483+int
484+isaconfig(char *class, int ctlrno, ISAConf *isa)
485+{
486+ char cc[NAMELEN], *p, *q, *r;
487+ int n;
488+
489+ sprint(cc, "%s%d", class, ctlrno);
490+ for(n = 0; n < nconf; n++){
491+ if(cistrncmp(confname[n], cc, NAMELEN))
492+ continue;
493+ isa->nopt = 0;
494+ p = confval[n];
495+ while(*p){
496+ while(*p == ' ' || *p == '\t')
497+ p++;
498+ if(*p == '\0')
499+ break;
500+ if(cistrncmp(p, "type=", 5) == 0){
501+ p += 5;
502+ for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
503+ if(*p == '\0' || *p == ' ' || *p == '\t')
504+ break;
505+ *q = *p++;
506+ }
507+ *q = '\0';
508+ }
509+ else if(cistrncmp(p, "port=", 5) == 0)
510+ isa->port = strtoul(p+5, &p, 0);
511+ else if(cistrncmp(p, "irq=", 4) == 0)
512+ isa->irq = strtoul(p+4, &p, 0);
513+ else if(cistrncmp(p, "mem=", 4) == 0)
514+ isa->mem = strtoul(p+4, &p, 0);
515+ else if(cistrncmp(p, "size=", 5) == 0)
516+ isa->size = strtoul(p+5, &p, 0);
517+ else if(cistrncmp(p, "ea=", 3) == 0){
518+ if(parseether(isa->ea, p+3) == -1)
519+ memset(isa->ea, 0, 6);
520+ }
521+ else if(isa->nopt < NISAOPT){
522+ r = isa->opt[isa->nopt];
523+ while(*p && *p != ' ' && *p != '\t'){
524+ *r++ = *p++;
525+ if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
526+ break;
527+ }
528+ *r = '\0';
529+ isa->nopt++;
530+ }
531+ while(*p && *p != ' ' && *p != '\t')
532+ p++;
533+ }
534+ return 1;
535+ }
536+ return 0;
537+}
os/boot/pc/console.c+236−0
@@ -0,0 +1,236 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "io.h"
7+
8+IOQ consiq;
9+IOQ consoq;
10+
11+static int useuart;
12+
13+int debug = 0;
14+
15+void
16+kbdchar(int c)
17+{
18+ c &= 0x7F;
19+ if(c == 0x10)
20+ warp86("\n^P\n", 0);
21+ if(c == 0x12)
22+ debug = !debug;
23+ consiq.putc(&consiq, c);
24+}
25+
26+static int
27+consputc(void)
28+{
29+ return consoq.getc(&consoq);
30+}
31+
32+void
33+kbdinit(void)
34+{
35+ i8042init();
36+ qinit(&consiq);
37+}
38+
39+void
40+consinit(char* name, char* speed)
41+{
42+ int baud, port;
43+
44+ if(name == nil || cistrcmp(name, "cga") == 0)
45+ return;
46+ port = strtoul(name, 0, 0);
47+ if(port < 0 || port > 1)
48+ return;
49+ if(speed == nil || (baud = strtoul(speed, 0, 0)) == 0)
50+ baud = 9600;
51+
52+ qinit(&consoq);
53+
54+ uartspecial(port, kbdchar, consputc, baud);
55+ useuart = 1;
56+ uartputs(&consoq, "\n", 1);
57+}
58+
59+void
60+consdrain(void)
61+{
62+ if(useuart)
63+ uartdrain();
64+}
65+
66+void
67+consputs(char* s, int n)
68+{
69+ cgascreenputs(s, n);
70+ if(useuart)
71+ uartputs(&consoq, s, n);
72+}
73+
74+void
75+warp86(char* s, ulong)
76+{
77+ if(s != nil)
78+ print(s);
79+ spllo();
80+ consdrain();
81+
82+ i8042reset();
83+ print("Takes a licking and keeps on ticking...\n");
84+ for(;;)
85+ idle();
86+}
87+
88+static int
89+getline(char *buf, int size, int timeout)
90+{
91+ int c, i=0;
92+ ulong start;
93+ char echo;
94+
95+ for (;;) {
96+ start = m->ticks;
97+ do{
98+ /* timeout seconds to first char */
99+ if(timeout && ((m->ticks - start) > timeout*HZ))
100+ return -2;
101+ c = consiq.getc(&consiq);
102+ }while(c == -1);
103+ timeout = 0;
104+
105+ if(c == '\r')
106+ c = '\n'; /* turn carriage return into newline */
107+ if(c == '\177')
108+ c = '\010'; /* turn delete into backspace */
109+ if(c == '\025')
110+ echo = '\n'; /* echo ^U as a newline */
111+ else
112+ echo = c;
113+ consputs(&echo, 1);
114+
115+ if(c == '\010'){
116+ if(i > 0)
117+ i--; /* bs deletes last character */
118+ continue;
119+ }
120+ /* a newline ends a line */
121+ if (c == '\n')
122+ break;
123+ /* ^U wipes out the line */
124+ if (c =='\025')
125+ return -1;
126+ if(i == size)
127+ return size;
128+ buf[i++] = c;
129+ }
130+ buf[i] = 0;
131+ return i;
132+}
133+
134+int
135+getstr(char *prompt, char *buf, int size, char *def, int timeout)
136+{
137+ int len, isdefault;
138+ char pbuf[PRINTSIZE];
139+
140+ buf[0] = 0;
141+ isdefault = (def && *def);
142+ if(isdefault == 0){
143+ timeout = 0;
144+ sprint(pbuf, "%s: ", prompt);
145+ }
146+ else if(timeout)
147+ sprint(pbuf, "%s[default==%s (%ds timeout)]: ", prompt, def, timeout);
148+ else
149+ sprint(pbuf, "%s[default==%s]: ", prompt, def);
150+ for (;;) {
151+ print(pbuf);
152+ len = getline(buf, size, timeout);
153+ switch(len){
154+ case 0:
155+ /* RETURN */
156+ if(isdefault)
157+ break;
158+ continue;
159+ case -1:
160+ /* ^U typed */
161+ continue;
162+ case -2:
163+ /* timeout, use default */
164+ consputs("\n", 1);
165+ len = 0;
166+ break;
167+ default:
168+ break;
169+ }
170+ if(len >= size){
171+ print("line too long\n");
172+ continue;
173+ }
174+ break;
175+ }
176+ if(len == 0 && isdefault)
177+ strcpy(buf, def);
178+ return 0;
179+}
180+
181+int
182+print(char *fmt, ...)
183+{
184+ int n;
185+ va_list arg;
186+ char buf[PRINTSIZE];
187+
188+ va_start(arg, fmt);
189+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
190+ va_end(arg);
191+ consputs(buf, n);
192+
193+ return n;
194+}
195+
196+int
197+sprint(char *s, char *fmt, ...)
198+{
199+ int n;
200+ va_list arg;
201+
202+ va_start(arg, fmt);
203+ n = vseprint(s, s+PRINTSIZE, fmt, arg) - s;
204+ va_end(arg);
205+
206+ return n;
207+}
208+
209+void
210+panic(char *fmt, ...)
211+{
212+ int n;
213+ va_list arg;
214+ char buf[PRINTSIZE];
215+
216+ strcpy(buf, "panic: ");
217+ va_start(arg, fmt);
218+ n = vseprint(buf+7, buf+sizeof(buf), fmt, arg) - buf;
219+ va_end(arg);
220+ buf[n] = '\n';
221+ consputs(buf, n+1);
222+
223+//floppymemwrite();
224+//splhi(); for(;;);
225+ if(etherdetach)
226+ etherdetach();
227+ if(sddetach)
228+ sddetach();
229+
230+ consputs("\nPress almost any key to reset...", 32);
231+ spllo();
232+ while(consiq.getc(&consiq) == -1)
233+ ;
234+
235+ warp86(nil, 0);
236+}
os/boot/pc/dat.h+212−0
@@ -0,0 +1,212 @@
1+typedef struct List {
2+ void *next;
3+} List;
4+
5+typedef struct Alarm Alarm;
6+typedef struct Alarm {
7+ List;
8+ int busy;
9+ long dt;
10+ void (*f)(Alarm*);
11+ void *arg;
12+} Alarm;
13+
14+typedef struct Apminfo {
15+ int haveinfo;
16+ int ax;
17+ int cx;
18+ int dx;
19+ int di;
20+ int ebx;
21+ int esi;
22+} Apminfo;
23+
24+typedef struct Block Block;
25+struct Block {
26+ Block* next;
27+ uchar* rp; /* first unconsumed byte */
28+ uchar* wp; /* first empty byte */
29+ uchar* lim; /* 1 past the end of the buffer */
30+ uchar* base; /* start of the buffer */
31+ ulong flag;
32+};
33+#define BLEN(s) ((s)->wp - (s)->rp)
34+
35+typedef struct IOQ IOQ;
36+typedef struct IOQ {
37+ uchar buf[4096];
38+ uchar *in;
39+ uchar *out;
40+ int state;
41+ int (*getc)(IOQ*);
42+ int (*putc)(IOQ*, int);
43+ void *ptr;
44+};
45+
46+enum {
47+ Eaddrlen = 6,
48+ /* next two exclude 4-byte ether CRC */
49+ ETHERMINTU = 60, /* minimum transmit size */
50+ ETHERMAXTU = 1514, /* maximum transmit size */
51+ ETHERHDRSIZE = 14, /* size of an ethernet header */
52+
53+ MaxEther = 6,
54+};
55+
56+typedef struct {
57+ uchar d[Eaddrlen];
58+ uchar s[Eaddrlen];
59+ uchar type[2];
60+ uchar data[1500];
61+ uchar crc[4];
62+} Etherpkt;
63+
64+extern uchar broadcast[Eaddrlen];
65+
66+typedef struct Ureg Ureg;
67+
68+typedef struct Segdesc {
69+ ulong d0;
70+ ulong d1;
71+} Segdesc;
72+
73+typedef struct Mach {
74+ ulong ticks; /* of the clock since boot time */
75+ void *alarm; /* alarms bound to this clock */
76+} Mach;
77+
78+extern Mach *m;
79+
80+#define I_MAGIC ((((4*11)+0)*11)+7)
81+
82+typedef struct Exec Exec;
83+struct Exec
84+{
85+ uchar magic[4]; /* magic number */
86+ uchar text[4]; /* size of text segment */
87+ uchar data[4]; /* size of initialized data */
88+ uchar bss[4]; /* size of uninitialized data */
89+ uchar syms[4]; /* size of symbol table */
90+ uchar entry[4]; /* entry point */
91+ uchar spsz[4]; /* size of sp/pc offset table */
92+ uchar pcsz[4]; /* size of pc/line number table */
93+};
94+
95+/*
96+ * a parsed .ini line
97+ */
98+#define ISAOPTLEN 32
99+#define NISAOPT 8
100+
101+typedef struct ISAConf {
102+ char type[NAMELEN];
103+ ulong port;
104+ ulong irq;
105+ ulong mem;
106+ ulong size;
107+ uchar ea[6];
108+
109+ int nopt;
110+ char opt[NISAOPT][ISAOPTLEN];
111+} ISAConf;
112+
113+typedef struct Pcidev Pcidev;
114+typedef struct PCMmap PCMmap;
115+
116+#define BOOTLINE ((char*)CONFADDR)
117+
118+enum {
119+ MB = (1024*1024),
120+};
121+#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1))
122+
123+
124+typedef struct Type Type;
125+typedef struct Medium Medium;
126+typedef struct Boot Boot;
127+
128+enum { /* type */
129+ Tnil = 0x00,
130+
131+ Tfloppy = 0x01,
132+ Tsd = 0x02,
133+ Tether = 0x03,
134+ Tcd = 0x04,
135+
136+ Tany = -1,
137+};
138+
139+enum { /* name and flag */
140+ Fnone = 0x00,
141+
142+ Nfs = 0x00,
143+ Ffs = (1<<Nfs),
144+ Nboot = 0x01,
145+ Fboot = (1<<Nboot),
146+ Nbootp = 0x02,
147+ Fbootp = (1<<Nbootp),
148+ NName = 3,
149+
150+ Fany = Fbootp|Fboot|Ffs,
151+
152+ Fini = 0x10,
153+ Fprobe = 0x80,
154+};
155+
156+typedef struct Type {
157+ int type;
158+ int flag;
159+ int (*init)(void);
160+ void (*initdev)(int, char*);
161+ void* (*getfspart)(int, char*, int); /* actually returns Dos* */
162+ void (*addconf)(int);
163+ int (*boot)(int, char*, Boot*);
164+ void (*printdevs)(int);
165+ char** parts;
166+ char** inis;
167+ int mask;
168+ Medium* media;
169+} Type;
170+
171+extern void (*etherdetach)(void);
172+extern void (*floppydetach)(void);
173+extern void (*sddetach)(void);
174+
175+typedef struct Lock { /* for ilock, iunlock */
176+ int locked;
177+ int spl;
178+} Lock;
179+
180+enum { /* returned by bootpass */
181+ MORE, ENOUGH, FAIL
182+};
183+enum {
184+ INITKERNEL,
185+ READEXEC,
186+ READ9TEXT,
187+ READ9DATA,
188+ READGZIP,
189+ READEHDR,
190+ READPHDR,
191+ READEPAD,
192+ READEDATA,
193+ TRYBOOT,
194+ INIT9LOAD,
195+ READ9LOAD,
196+ FAILED
197+};
198+
199+struct Boot {
200+ int state;
201+
202+ Exec exec;
203+ char *bp; /* base ptr */
204+ char *wp; /* write ptr */
205+ char *ep; /* end ptr */
206+};
207+
208+extern int debug;
209+extern Apminfo apm;
210+extern char *defaultpartition;
211+extern int iniread;
212+extern int pxe;
os/boot/pc/devfloppy.c+853−0
@@ -0,0 +1,853 @@
1+#include <u.h>
2+
3+#include "lib.h"
4+#include "mem.h"
5+#include "dat.h"
6+#include "fns.h"
7+#include "io.h"
8+#include "ureg.h"
9+
10+#include "fs.h"
11+#include "devfloppy.h"
12+
13+
14+/* Intel 82077A (8272A compatible) floppy controller */
15+
16+/* This module expects the following functions to be defined
17+ * elsewhere:
18+ *
19+ * inb()
20+ * outb()
21+ * floppyexec()
22+ * floppyeject()
23+ * floppysetup0()
24+ * floppysetup1()
25+ * dmainit()
26+ * dmasetup()
27+ * dmaend()
28+ *
29+ * On DMA systems, floppyexec() should be an empty function;
30+ * on non-DMA systems, dmaend() should be an empty function;
31+ * dmasetup() may enforce maximum transfer sizes.
32+ */
33+
34+enum {
35+ /* file types */
36+ Qdir= 0,
37+ Qdata= (1<<2),
38+ Qctl= (2<<2),
39+ Qmask= (3<<2),
40+
41+ DMAchan= 2, /* floppy dma channel */
42+};
43+
44+#define DPRINT if(0)print
45+
46+FType floppytype[] =
47+{
48+ { "3½HD", T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54, 0, },
49+ { "3½DD", T1440kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
50+ { "3½DD", T720kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
51+ { "5¼HD", T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, },
52+ { "5¼DD", T1200kb, 512, 9, 2, 2, 40, 0x2A, 0x50, 1, },
53+ { "ATT3B1", T1200kb, 512, 8, 2, 2, 48, 0x2A, 0x50, 1, },
54+ { "5¼DD", T360kb, 512, 9, 2, 1, 40, 0x2A, 0x50, 2, },
55+};
56+
57+/*
58+ * bytes per sector encoding for the controller.
59+ * - index for b2c is is (bytes per sector/128).
60+ * - index for c2b is code from b2c
61+ */
62+static int b2c[] =
63+{
64+[1] 0,
65+[2] 1,
66+[4] 2,
67+[8] 3,
68+};
69+static int c2b[] =
70+{
71+ 128,
72+ 256,
73+ 512,
74+ 1024,
75+};
76+
77+FController fl;
78+
79+#define MOTORBIT(i) (1<<((i)+4))
80+
81+/*
82+ * predeclared
83+ */
84+static int cmddone(void*);
85+static void floppyformat(FDrive*, char*);
86+static void floppykproc(void*);
87+static void floppypos(FDrive*,long);
88+static int floppyrecal(FDrive*);
89+static int floppyresult(void);
90+static void floppyrevive(void);
91+static vlong pcfloppyseek(FDrive*, vlong);
92+static int floppysense(void);
93+static void floppywait(int);
94+static long floppyxfer(FDrive*, int, void*, long, long);
95+
96+static void
97+fldump(void)
98+{
99+ DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb),
100+ inb(Pdor), inb(Pmsr), inb(Pdir));
101+}
102+
103+static void
104+floppyalarm(Alarm* a)
105+{
106+ FDrive *dp;
107+
108+ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
109+ if((fl.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5)
110+ floppyoff(dp);
111+ }
112+
113+ alarm(5*1000, floppyalarm, 0);
114+ cancel(a);
115+}
116+
117+/*
118+ * set floppy drive to its default type
119+ */
120+static void
121+floppysetdef(FDrive *dp)
122+{
123+ FType *t;
124+
125+ for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++)
126+ if(dp->dt == t->dt){
127+ dp->t = t;
128+ break;
129+ }
130+}
131+
132+static void
133+_floppydetach(void)
134+{
135+ /*
136+ * stop the motors
137+ */
138+ fl.motor = 0;
139+ delay(10);
140+ outb(Pdor, fl.motor | Fintena | Fena);
141+ delay(10);
142+}
143+
144+int
145+floppyinit(void)
146+{
147+ FDrive *dp;
148+ FType *t;
149+ ulong maxtsize;
150+ int mask;
151+
152+ dmainit(DMAchan);
153+
154+ floppysetup0(&fl);
155+
156+ /*
157+ * init dependent parameters
158+ */
159+ maxtsize = 0;
160+ for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
161+ t->cap = t->bytes * t->heads * t->sectors * t->tracks;
162+ t->bcode = b2c[t->bytes/128];
163+ t->tsize = t->bytes * t->sectors;
164+ if(maxtsize < t->tsize)
165+ maxtsize = t->tsize;
166+ }
167+
168+ fl.selected = fl.d;
169+
170+ floppydetach = _floppydetach;
171+ floppydetach();
172+
173+ /*
174+ * init drives
175+ */
176+ mask = 0;
177+ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
178+ dp->dev = dp - fl.d;
179+ if(dp->dt == Tnone)
180+ continue;
181+ mask |= 1<<dp->dev;
182+ floppysetdef(dp);
183+ dp->cyl = -1; /* because we don't know */
184+ dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024);
185+ dp->ccyl = -1;
186+ dp->vers = 0;
187+ dp->maxtries = 5;
188+ }
189+
190+ /*
191+ * first operation will recalibrate
192+ */
193+ fl.confused = 1;
194+
195+ floppysetup1(&fl);
196+
197+ /* to turn the motor off when inactive */
198+ alarm(5*1000, floppyalarm, 0);
199+
200+ return mask;
201+}
202+
203+void
204+floppyinitdev(int i, char *name)
205+{
206+ if(i >= fl.ndrive)
207+ panic("floppyinitdev");
208+ sprint(name, "fd%d", i);
209+}
210+
211+void
212+floppyprintdevs(int i)
213+{
214+ if(i >= fl.ndrive)
215+ panic("floppyprintdevs");
216+ print(" fd%d", i);
217+}
218+
219+int
220+floppyboot(int dev, char *file, Boot *b)
221+{
222+ Fs *fs;
223+
224+ if(strncmp(file, "dos!", 4) == 0)
225+ file += 4;
226+ else if(strchr(file, '!') || strcmp(file, "")==0) {
227+ print("syntax is fd0!file\n");
228+ return -1;
229+ }
230+
231+ fs = floppygetfspart(dev, "dos", 1);
232+ if(fs == nil)
233+ return -1;
234+
235+ return fsboot(fs, file, b);
236+}
237+
238+void
239+floppyprintbootdevs(int dev)
240+{
241+ print(" fd%d", dev);
242+}
243+
244+/*
245+ * check if the floppy has been replaced under foot. cause
246+ * an error if it has.
247+ *
248+ * a seek and a read clears the condition. this was determined
249+ * experimentally, there has to be a better way.
250+ *
251+ * if the read fails, cycle through the possible floppy
252+ * density till one works or we've cycled through all
253+ * possibilities for this drive.
254+ */
255+static int
256+changed(FDrive *dp)
257+{
258+ FType *start;
259+
260+ /*
261+ * if floppy has changed or first time through
262+ */
263+ if((inb(Pdir)&Fchange) || dp->vers == 0){
264+ DPRINT("changed\n");
265+ fldump();
266+ dp->vers++;
267+ floppysetdef(dp);
268+ dp->maxtries = 3;
269+ start = dp->t;
270+
271+ /* flopppyon fails if there's no drive */
272+ dp->confused = 1; /* make floppyon recal */
273+ if(floppyon(dp) < 0)
274+ return -1;
275+
276+ pcfloppyseek(dp, dp->t->heads*dp->t->tsize);
277+
278+ while(floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize) <= 0){
279+
280+ /*
281+ * if the xfer attempt doesn't clear the changed bit,
282+ * there's no floppy in the drive
283+ */
284+ if(inb(Pdir)&Fchange)
285+ return -1;
286+
287+ while(++dp->t){
288+ if(dp->t == &floppytype[nelem(floppytype)])
289+ dp->t = floppytype;
290+ if(dp->dt == dp->t->dt)
291+ break;
292+ }
293+
294+ /* flopppyon fails if there's no drive */
295+ if(floppyon(dp) < 0)
296+ return -1;
297+
298+ DPRINT("changed: trying %s\n", dp->t->name);
299+ fldump();
300+ if(dp->t == start)
301+ return -1;
302+ }
303+ }
304+
305+ return 0;
306+}
307+
308+static int
309+readtrack(FDrive *dp, int cyl, int head)
310+{
311+ int i, nn, sofar;
312+ ulong pos;
313+
314+ nn = dp->t->tsize;
315+ if(dp->ccyl==cyl && dp->chead==head)
316+ return nn;
317+ pos = (cyl*dp->t->heads+head) * nn;
318+ for(sofar = 0; sofar < nn; sofar += i){
319+ dp->ccyl = -1;
320+ i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar);
321+ if(i <= 0)
322+ return -1;
323+ }
324+ dp->ccyl = cyl;
325+ dp->chead = head;
326+ return nn;
327+}
328+
329+long
330+floppyread(Fs *fs, void *a, long n)
331+{
332+ FDrive *dp;
333+ long rv, offset;
334+ int sec, head, cyl;
335+ long len;
336+ uchar *aa;
337+
338+ aa = a;
339+ dp = &fl.d[fs->dev];
340+
341+ offset = dp->offset;
342+ floppyon(dp);
343+ if(changed(dp))
344+ return -1;
345+
346+ for(rv = 0; rv < n; rv += len){
347+ /*
348+ * all xfers come out of the track cache
349+ */
350+ dp->len = n - rv;
351+ floppypos(dp, offset+rv);
352+ cyl = dp->tcyl;
353+ head = dp->thead;
354+ len = dp->len;
355+ sec = dp->tsec;
356+ if(readtrack(dp, cyl, head) < 0)
357+ break;
358+ memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);
359+ }
360+ dp->offset = offset+rv;
361+
362+ return rv;
363+}
364+
365+void*
366+floppygetfspart(int i, char *name, int chatty)
367+{
368+ static Fs fs;
369+
370+ if(strcmp(name, "dos") != 0){
371+ if(chatty)
372+ print("unknown partition fd%d!%s (use fd%d!dos)\n", i, name, i);
373+ return nil;
374+ }
375+
376+ fs.dev = i;
377+ fs.diskread = floppyread;
378+ fs.diskseek = floppyseek;
379+
380+ /* sometimes we get spurious errors and doing it again works */
381+ if(dosinit(&fs) < 0 && dosinit(&fs) < 0){
382+ if(chatty)
383+ print("fd%d!%s does not contain a FAT file system\n", i, name);
384+ return nil;
385+ }
386+ return &fs;
387+}
388+
389+static int
390+return0(void*)
391+{
392+ return 0;
393+}
394+
395+static void
396+timedsleep(int (*f)(void*), void* arg, int ms)
397+{
398+ int s;
399+ ulong end;
400+
401+ end = m->ticks + 1 + MS2TK(ms);
402+ while(m->ticks < end && !(*f)(arg)){
403+ s = spllo();
404+ delay(10);
405+ splx(s);
406+ }
407+}
408+
409+/*
410+ * start a floppy drive's motor.
411+ */
412+static int
413+floppyon(FDrive *dp)
414+{
415+ int alreadyon;
416+ int tries;
417+
418+ if(fl.confused)
419+ floppyrevive();
420+
421+ /* start motor and select drive */
422+ dp->lasttouched = m->ticks;
423+ alreadyon = fl.motor & MOTORBIT(dp->dev);
424+ if(!alreadyon){
425+ fl.motor |= MOTORBIT(dp->dev);
426+ outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
427+ /* wait for drive to spin up */
428+ timedsleep(return0, 0, 750);
429+
430+ /* clear any pending interrupts */
431+ floppysense();
432+ }
433+
434+ /* set transfer rate */
435+ if(fl.rate != dp->t->rate){
436+ fl.rate = dp->t->rate;
437+ outb(Pdsr, fl.rate);
438+ }
439+
440+ /* get drive to a known cylinder */
441+ if(dp->confused)
442+ for(tries = 0; tries < 4; tries++)
443+ if(floppyrecal(dp) >= 0)
444+ break;
445+ dp->lasttouched = m->ticks;
446+ fl.selected = dp;
447+ if(dp->confused)
448+ return -1;
449+ return 0;
450+}
451+
452+/*
453+ * stop the floppy if it hasn't been used in 5 seconds
454+ */
455+static void
456+floppyoff(FDrive *dp)
457+{
458+ fl.motor &= ~MOTORBIT(dp->dev);
459+ outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
460+}
461+
462+/*
463+ * send a command to the floppy
464+ */
465+static int
466+floppycmd(void)
467+{
468+ int i;
469+ int tries;
470+
471+ fl.nstat = 0;
472+ for(i = 0; i < fl.ncmd; i++){
473+ for(tries = 0; ; tries++){
474+ if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
475+ break;
476+ if(tries > 1000){
477+ DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
478+ fldump();
479+
480+ /* empty fifo, might have been a bad command */
481+ floppyresult();
482+ return -1;
483+ }
484+ microdelay(1);
485+ }
486+ outb(Pfdata, fl.cmd[i]);
487+ }
488+ return 0;
489+}
490+
491+/*
492+ * get a command result from the floppy
493+ *
494+ * when the controller goes ready waiting for a command
495+ * (instead of sending results), we're done
496+ *
497+ */
498+static int
499+floppyresult(void)
500+{
501+ int i, s;
502+ int tries;
503+
504+ /* get the result of the operation */
505+ for(i = 0; i < sizeof(fl.stat); i++){
506+ /* wait for status byte */
507+ for(tries = 0; ; tries++){
508+ s = inb(Pmsr)&(Ffrom|Fready);
509+ if(s == Fready){
510+ fl.nstat = i;
511+ return fl.nstat;
512+ }
513+ if(s == (Ffrom|Fready))
514+ break;
515+ if(tries > 1000){
516+ DPRINT("floppyresult: %d stats\n", i);
517+ fldump();
518+ fl.confused = 1;
519+ return -1;
520+ }
521+ microdelay(1);
522+ }
523+ fl.stat[i] = inb(Pfdata);
524+ }
525+ fl.nstat = sizeof(fl.stat);
526+ return fl.nstat;
527+}
528+
529+/*
530+ * calculate physical address of a logical byte offset into the disk
531+ *
532+ * truncate dp->length if it crosses a track boundary
533+ */
534+static void
535+floppypos(FDrive *dp, long off)
536+{
537+ int lsec;
538+ int ltrack;
539+ int end;
540+
541+ lsec = off/dp->t->bytes;
542+ ltrack = lsec/dp->t->sectors;
543+ dp->tcyl = ltrack/dp->t->heads;
544+ dp->tsec = (lsec % dp->t->sectors) + 1;
545+ dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
546+
547+ /*
548+ * can't read across track boundaries.
549+ * if so, decrement the bytes to be read.
550+ */
551+ end = (ltrack+1)*dp->t->sectors*dp->t->bytes;
552+ if(off+dp->len > end)
553+ dp->len = end - off;
554+}
555+
556+/*
557+ * get the interrupt cause from the floppy.
558+ */
559+static int
560+floppysense(void)
561+{
562+ fl.ncmd = 0;
563+ fl.cmd[fl.ncmd++] = Fsense;
564+ if(floppycmd() < 0)
565+ return -1;
566+ if(floppyresult() < 2){
567+ DPRINT("can't read sense response\n");
568+ fldump();
569+ fl.confused = 1;
570+ return -1;
571+ }
572+ return 0;
573+}
574+
575+static int
576+cmddone(void *a)
577+{
578+ USED(a);
579+ return fl.ncmd == 0;
580+}
581+
582+/*
583+ * Wait for a floppy interrupt. If none occurs in 5 seconds, we
584+ * may have missed one. This only happens on some portables which
585+ * do power management behind our backs. Call the interrupt
586+ * routine to try to clear any conditions.
587+ */
588+static void
589+floppywait(int slow)
590+{
591+ timedsleep(cmddone, 0, slow ? 5000 : 1000);
592+ if(!cmddone(0)){
593+ floppyintr(0);
594+ fl.confused = 1;
595+ }
596+}
597+
598+/*
599+ * we've lost the floppy position, go to cylinder 0.
600+ */
601+static int
602+floppyrecal(FDrive *dp)
603+{
604+ dp->ccyl = -1;
605+ dp->cyl = -1;
606+
607+ fl.ncmd = 0;
608+ fl.cmd[fl.ncmd++] = Frecal;
609+ fl.cmd[fl.ncmd++] = dp->dev;
610+ if(floppycmd() < 0)
611+ return -1;
612+ floppywait(1);
613+ if(fl.nstat < 2){
614+ DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
615+ fl.confused = 1;
616+ return -1;
617+ }
618+ if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
619+ DPRINT("recalibrate: failed\n");
620+ dp->confused = 1;
621+ return -1;
622+ }
623+ dp->cyl = fl.stat[1];
624+ if(dp->cyl != 0){
625+ DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl);
626+ dp->cyl = -1;
627+ dp->confused = 1;
628+ return -1;
629+ }
630+
631+ dp->confused = 0;
632+ return 0;
633+}
634+
635+/*
636+ * if the controller or a specific drive is in a confused state,
637+ * reset it and get back to a kown state
638+ */
639+static void
640+floppyrevive(void)
641+{
642+ FDrive *dp;
643+
644+ /*
645+ * reset the controller if it's confused
646+ */
647+ if(fl.confused){
648+ DPRINT("floppyrevive in\n");
649+ fldump();
650+
651+ /* reset controller and turn all motors off */
652+ splhi();
653+ fl.ncmd = 1;
654+ fl.cmd[0] = 0;
655+ outb(Pdor, 0);
656+ delay(10);
657+ outb(Pdor, Fintena|Fena);
658+ delay(10);
659+ spllo();
660+ fl.motor = 0;
661+ fl.confused = 0;
662+ floppywait(0);
663+
664+ /* mark all drives in an unknown state */
665+ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)
666+ dp->confused = 1;
667+
668+ /* set rate to a known value */
669+ outb(Pdsr, 0);
670+ fl.rate = 0;
671+
672+ DPRINT("floppyrevive out\n");
673+ fldump();
674+ }
675+}
676+
677+/*
678+ * seek to the target cylinder
679+ *
680+ * interrupt, no results
681+ */
682+static vlong
683+pcfloppyseek(FDrive *dp, vlong off)
684+{
685+ floppypos(dp, off);
686+ if(dp->cyl == dp->tcyl){
687+ dp->offset = off;
688+ return off;
689+ }
690+ dp->cyl = -1;
691+
692+ fl.ncmd = 0;
693+ fl.cmd[fl.ncmd++] = Fseek;
694+ fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
695+ fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
696+ if(floppycmd() < 0)
697+ return -1;
698+ floppywait(1);
699+ if(fl.nstat < 2){
700+ DPRINT("seek: confused\n");
701+ fl.confused = 1;
702+ return -1;
703+ }
704+ if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
705+ DPRINT("seek: failed\n");
706+ dp->confused = 1;
707+ return -1;
708+ }
709+
710+ dp->cyl = dp->tcyl;
711+ dp->offset = off;
712+ DPRINT("seek to %d succeeded\n", dp->offset);
713+
714+ return dp->offset;
715+}
716+
717+/*
718+ * read or write to floppy. try up to three times.
719+ */
720+static long
721+floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
722+{
723+ long offset;
724+ int tries;
725+
726+ if(off >= dp->t->cap)
727+ return 0;
728+ if(off + n > dp->t->cap)
729+ n = dp->t->cap - off;
730+
731+ /* retry on error (until it gets ridiculous) */
732+ for(tries = 0; tries < dp->maxtries; tries++){
733+
734+ dp->len = n;
735+ if(pcfloppyseek(dp, off) < 0){
736+ DPRINT("xfer: seek failed\n");
737+ dp->confused = 1;
738+ continue;
739+ }
740+
741+ /*
742+ * set up the dma (dp->len may be trimmed)
743+ */
744+ dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
745+ if(dp->len < 0){
746+ buggery:
747+ dmaend(DMAchan);
748+ continue;
749+ }
750+
751+ /*
752+ * start operation
753+ */
754+ fl.ncmd = 0;
755+ fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);
756+ fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
757+ fl.cmd[fl.ncmd++] = dp->tcyl;
758+ fl.cmd[fl.ncmd++] = dp->thead;
759+ fl.cmd[fl.ncmd++] = dp->tsec;
760+ fl.cmd[fl.ncmd++] = dp->t->bcode;
761+ fl.cmd[fl.ncmd++] = dp->t->sectors;
762+ fl.cmd[fl.ncmd++] = dp->t->gpl;
763+ fl.cmd[fl.ncmd++] = 0xFF;
764+ if(floppycmd() < 0)
765+ goto buggery;
766+
767+ /*
768+ * give bus to DMA, floppyintr() will read result
769+ */
770+ floppywait(0);
771+ dmaend(DMAchan);
772+
773+ /*
774+ * check for errors
775+ */
776+ if(fl.nstat < 7){
777+ DPRINT("xfer: confused\n");
778+ fl.confused = 1;
779+ continue;
780+ }
781+ if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
782+ DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],
783+ fl.stat[1], fl.stat[2]);
784+ DPRINT("offset %lud len %ld\n", off, dp->len);
785+ if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){
786+ DPRINT("DMA overrun: retry\n");
787+ } else
788+ dp->confused = 1;
789+ continue;
790+ }
791+
792+ /*
793+ * check for correct cylinder
794+ */
795+ offset = fl.stat[3] * dp->t->heads + fl.stat[4];
796+ offset = offset*dp->t->sectors + fl.stat[5] - 1;
797+ offset = offset * c2b[fl.stat[6]];
798+ if(offset != off+dp->len){
799+ DPRINT("xfer: ends on wrong cyl\n");
800+ dp->confused = 1;
801+ continue;
802+ }
803+
804+ dp->lasttouched = m->ticks;
805+ dp->maxtries = 20;
806+ return dp->len;
807+ }
808+
809+ return -1;
810+}
811+
812+/*
813+void
814+floppymemwrite(void)
815+{
816+ int i;
817+ int n;
818+ uchar *a;
819+ FDrive *dp;
820+
821+ dp = &fl.d[0];
822+ a = (uchar*)0x80000000;
823+ n = 0;
824+ while(n < 1440*1024){
825+ i = floppyxfer(dp, Fwrite, a+n, n, 1440*1024-n);
826+ if(i <= 0)
827+ break;
828+ n += i;
829+ }
830+ print("floppymemwrite wrote %d bytes\n", n);
831+splhi(); for(;;);
832+}
833+*/
834+
835+static void
836+floppyintr(Ureg *ur)
837+{
838+ USED(ur);
839+ switch(fl.cmd[0]&~Fmulti){
840+ case Fread:
841+ case Fwrite:
842+ case Fformat:
843+ case Fdumpreg:
844+ floppyresult();
845+ break;
846+ case Fseek:
847+ case Frecal:
848+ default:
849+ floppysense(); /* to clear interrupt */
850+ break;
851+ }
852+ fl.ncmd = 0;
853+}
os/boot/pc/devfloppy.h+196−0
@@ -0,0 +1,196 @@
1+typedef struct FController FController;
2+typedef struct FDrive FDrive;
3+typedef struct FType FType;
4+
5+static void floppyintr(Ureg*);
6+static int floppyon(FDrive*);
7+static void floppyoff(FDrive*);
8+static void floppysetdef(FDrive*);
9+
10+/*
11+ * a floppy drive
12+ */
13+struct FDrive
14+{
15+ FType *t; /* floppy type */
16+ int dt; /* drive type */
17+ int dev;
18+
19+ ulong lasttouched; /* time last touched */
20+ int cyl; /* current arm position */
21+ int confused; /* needs to be recalibrated */
22+ int offset; /* current offset */
23+ int vers;
24+ int maxtries;
25+
26+ int tcyl; /* target cylinder */
27+ int thead; /* target head */
28+ int tsec; /* target sector */
29+ long len; /* size of xfer */
30+
31+ uchar *cache; /* track cache */
32+ int ccyl;
33+ int chead;
34+
35+// Rendez r; /* waiting here for motor to spin up */
36+ void *aux;
37+};
38+
39+/*
40+ * controller for 4 floppys
41+ */
42+struct FController
43+{
44+// QLock; /* exclusive access to the contoller */
45+
46+ int ndrive;
47+ FDrive *d; /* the floppy drives */
48+ FDrive *selected;
49+ int rate; /* current rate selected */
50+ uchar cmd[14]; /* command */
51+ int ncmd; /* # command bytes */
52+ uchar stat[14]; /* command status */
53+ int nstat; /* # status bytes */
54+ int confused; /* controler needs to be reset */
55+// Rendez r; /* wait here for command termination */
56+ int motor; /* bit mask of spinning disks */
57+// Rendez kr; /* for motor watcher */
58+};
59+
60+/*
61+ * floppy types (all MFM encoding)
62+ */
63+struct FType
64+{
65+ char *name;
66+ int dt; /* compatible drive type */
67+ int bytes; /* bytes/sector */
68+ int sectors; /* sectors/track */
69+ int heads; /* number of heads */
70+ int steps; /* steps per cylinder */
71+ int tracks; /* tracks/disk */
72+ int gpl; /* intersector gap length for read/write */
73+ int fgpl; /* intersector gap length for format */
74+ int rate; /* rate code */
75+
76+ /*
77+ * these depend on previous entries and are set filled in
78+ * by floppyinit
79+ */
80+ int bcode; /* coded version of bytes for the controller */
81+ long cap; /* drive capacity in bytes */
82+ long tsize; /* track size in bytes */
83+};
84+/* bits in the registers */
85+enum
86+{
87+ /* status registers a & b */
88+ Psra= 0x3f0,
89+ Psrb= 0x3f1,
90+
91+ /* digital output register */
92+ Pdor= 0x3f2,
93+ Fintena= 0x8, /* enable floppy interrupt */
94+ Fena= 0x4, /* 0 == reset controller */
95+
96+ /* main status register */
97+ Pmsr= 0x3f4,
98+ Fready= 0x80, /* ready to be touched */
99+ Ffrom= 0x40, /* data from controller */
100+ Ffloppybusy= 0x10, /* operation not over */
101+
102+ /* data register */
103+ Pfdata= 0x3f5,
104+ Frecal= 0x07, /* recalibrate cmd */
105+ Fseek= 0x0f, /* seek cmd */
106+ Fsense= 0x08, /* sense cmd */
107+ Fread= 0x66, /* read cmd */
108+ Freadid= 0x4a, /* read track id */
109+ Fspec= 0x03, /* set hold times */
110+ Fwrite= 0x45, /* write cmd */
111+ Fformat= 0x4d, /* format cmd */
112+ Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */
113+ Fdumpreg= 0x0e, /* dump internal registers */
114+
115+ /* digital input register */
116+ Pdir= 0x3F7, /* disk changed port (read only) */
117+ Pdsr= 0x3F7, /* data rate select port (write only) */
118+ Fchange= 0x80, /* disk has changed */
119+
120+ /* status 0 byte */
121+ Drivemask= 3<<0,
122+ Seekend= 1<<5,
123+ Codemask= (3<<6)|(3<<3),
124+ Cmdexec= 1<<6,
125+
126+ /* status 1 byte */
127+ Overrun= 0x10,
128+};
129+
130+/*
131+ * types of drive (from PC equipment byte)
132+ */
133+enum
134+{
135+ Tnone= 0,
136+ T360kb= 1,
137+ T1200kb= 2,
138+ T720kb= 3,
139+ T1440kb= 4,
140+};
141+
142+static void
143+pcfloppyintr(Ureg *ur, void *a)
144+{
145+ USED(a);
146+
147+ floppyintr(ur);
148+}
149+
150+void
151+floppysetup0(FController *fl)
152+{
153+ uchar equip;
154+
155+ /*
156+ * Read nvram for types of floppies 0 & 1.
157+ * Always try floppy 0.
158+ */
159+ equip = nvramread(0x10);
160+ fl->ndrive = 1;
161+
162+ if(equip & 0xf)
163+ fl->ndrive++;
164+
165+ /*
166+ * Allocate the drive storage.
167+ * There's always one.
168+ */
169+ fl->d = xalloc(fl->ndrive*sizeof(FDrive));
170+ fl->d[0].dt = (equip >> 4) & 0xf;
171+ if(fl->d[0].dt == Tnone)
172+ fl->d[0].dt = T1440kb;
173+
174+ if(fl->ndrive == 2)
175+ fl->d[1].dt = equip & 0xf;
176+}
177+
178+void
179+floppysetup1(FController*)
180+{
181+// intrenable(VectorFLOPPY, pcfloppyintr, fl, BUSUNKNOWN);
182+ setvec(VectorFLOPPY, pcfloppyintr, 0);
183+}
184+
185+
186+static vlong pcfloppyseek(FDrive*, vlong);
187+FController fl;
188+
189+vlong
190+floppyseek(Fs *fs, vlong off)
191+{
192+ FDrive *dp;
193+
194+ dp = &fl.d[fs->dev];
195+ return pcfloppyseek(dp, off);
196+}
os/boot/pc/devi82365.c+1205−0
@@ -0,0 +1,1205 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "mem.h"
4+#include "dat.h"
5+#include "fns.h"
6+#include "error.h"
7+#include "io.h"
8+
9+/*
10+ * Support for up to 4 Slot card slots. Generalizing above that is hard
11+ * since addressing is not obvious. - presotto
12+ *
13+ * WARNING: This has never been tried with more than one card slot.
14+ */
15+
16+/*
17+ * Intel 82365SL PCIC controller for the PCMCIA or
18+ * Cirrus Logic PD6710/PD6720 which is mostly register compatible
19+ */
20+enum
21+{
22+ /*
23+ * registers indices
24+ */
25+ Rid= 0x0, /* identification and revision */
26+ Ris= 0x1, /* interface status */
27+ Rpc= 0x2, /* power control */
28+ Foutena= (1<<7), /* output enable */
29+ Fautopower= (1<<5), /* automatic power switching */
30+ Fcardena= (1<<4), /* PC card enable */
31+ Rigc= 0x3, /* interrupt and general control */
32+ Fiocard= (1<<5), /* I/O card (vs memory) */
33+ Fnotreset= (1<<6), /* reset if not set */
34+ FSMIena= (1<<4), /* enable change interrupt on SMI */
35+ Rcsc= 0x4, /* card status change */
36+ Rcscic= 0x5, /* card status change interrupt config */
37+ Fchangeena= (1<<3), /* card changed */
38+ Fbwarnena= (1<<1), /* card battery warning */
39+ Fbdeadena= (1<<0), /* card battery dead */
40+ Rwe= 0x6, /* address window enable */
41+ Fmem16= (1<<5), /* use A23-A12 to decode address */
42+ Rio= 0x7, /* I/O control */
43+ Fwidth16= (1<<0), /* 16 bit data width */
44+ Fiocs16= (1<<1), /* IOCS16 determines data width */
45+ Fzerows= (1<<2), /* zero wait state */
46+ Ftiming= (1<<3), /* timing register to use */
47+ Riobtm0lo= 0x8, /* I/O address 0 start low byte */
48+ Riobtm0hi= 0x9, /* I/O address 0 start high byte */
49+ Riotop0lo= 0xa, /* I/O address 0 stop low byte */
50+ Riotop0hi= 0xb, /* I/O address 0 stop high byte */
51+ Riobtm1lo= 0xc, /* I/O address 1 start low byte */
52+ Riobtm1hi= 0xd, /* I/O address 1 start high byte */
53+ Riotop1lo= 0xe, /* I/O address 1 stop low byte */
54+ Riotop1hi= 0xf, /* I/O address 1 stop high byte */
55+ Rmap= 0x10, /* map 0 */
56+
57+ /*
58+ * CL-PD67xx extension registers
59+ */
60+ Rmisc1= 0x16, /* misc control 1 */
61+ F5Vdetect= (1<<0),
62+ Fvcc3V= (1<<1),
63+ Fpmint= (1<<2),
64+ Fpsirq= (1<<3),
65+ Fspeaker= (1<<4),
66+ Finpack= (1<<7),
67+ Rfifo= 0x17, /* fifo control */
68+ Fflush= (1<<7), /* flush fifo */
69+ Rmisc2= 0x1E, /* misc control 2 */
70+ Flowpow= (1<<1), /* low power mode */
71+ Rchipinfo= 0x1F, /* chip information */
72+ Ratactl= 0x26, /* ATA control */
73+
74+ /*
75+ * offsets into the system memory address maps
76+ */
77+ Mbtmlo= 0x0, /* System mem addr mapping start low byte */
78+ Mbtmhi= 0x1, /* System mem addr mapping start high byte */
79+ F16bit= (1<<7), /* 16-bit wide data path */
80+ Mtoplo= 0x2, /* System mem addr mapping stop low byte */
81+ Mtophi= 0x3, /* System mem addr mapping stop high byte */
82+ Ftimer1= (1<<6), /* timer set 1 */
83+ Mofflo= 0x4, /* Card memory offset address low byte */
84+ Moffhi= 0x5, /* Card memory offset address high byte */
85+ Fregactive= (1<<6), /* attribute memory */
86+
87+ Mbits= 13, /* msb of Mchunk */
88+ Mchunk= 1<<Mbits, /* logical mapping granularity */
89+ Nmap= 4, /* max number of maps to use */
90+
91+ /*
92+ * configuration registers - they start at an offset in attribute
93+ * memory found in the CIS.
94+ */
95+ Rconfig= 0,
96+ Creset= (1<<7), /* reset device */
97+ Clevel= (1<<6), /* level sensitive interrupt line */
98+
99+ Maxctab= 8, /* maximum configuration table entries */
100+};
101+
102+static int pcmcia_pcmspecial(char *, ISAConf *);
103+static void pcmcia_pcmspecialclose(int);
104+
105+#define MAP(x,o) (Rmap + (x)*0x8 + o)
106+
107+typedef struct I82365 I82365;
108+typedef struct Slot Slot;
109+typedef struct Conftab Conftab;
110+typedef struct Cisdat Cisdat;
111+/* a controller */
112+enum
113+{
114+ Ti82365,
115+ Tpd6710,
116+ Tpd6720,
117+ Tvg46x,
118+};
119+struct I82365
120+{
121+ int type;
122+ int dev;
123+ int nslot;
124+ int xreg; /* index register address */
125+ int dreg; /* data register address */
126+ int irq;
127+};
128+static I82365 *controller[4];
129+static int ncontroller;
130+
131+/* configuration table entry */
132+struct Conftab
133+{
134+ int index;
135+ ushort irqs; /* legal irqs */
136+ uchar irqtype;
137+ uchar bit16; /* true for 16 bit access */
138+ struct {
139+ ulong start;
140+ ulong len;
141+ } io[16];
142+ int nio;
143+ uchar vpp1;
144+ uchar vpp2;
145+ uchar memwait;
146+ ulong maxwait;
147+ ulong readywait;
148+ ulong otherwait;
149+};
150+
151+/* cis memory walking */
152+struct Cisdat
153+{
154+ uchar *cisbase;
155+ int cispos;
156+ int cisskip;
157+ int cislen;
158+};
159+
160+/* a card slot */
161+struct Slot
162+{
163+ Lock;
164+ int ref;
165+
166+ I82365 *cp; /* controller for this slot */
167+ long memlen; /* memory length */
168+ uchar base; /* index register base */
169+ uchar slotno; /* slot number */
170+
171+ /* status */
172+ uchar special; /* in use for a special device */
173+ uchar already; /* already inited */
174+ uchar occupied;
175+ uchar battery;
176+ uchar wrprot;
177+ uchar powered;
178+ uchar configed;
179+ uchar enabled;
180+ uchar busy;
181+
182+ /* cis info */
183+ char verstr[512]; /* version string */
184+ uchar cpresent; /* config registers present */
185+ ulong caddr; /* relative address of config registers */
186+ int nctab; /* number of config table entries */
187+ Conftab ctab[Maxctab];
188+ Conftab *def; /* default conftab */
189+
190+ /* for walking through cis */
191+ Cisdat;
192+
193+ /* memory maps */
194+ Lock mlock; /* lock down the maps */
195+ int time;
196+ PCMmap mmap[Nmap]; /* maps, last is always for the kernel */
197+};
198+static Slot *slot;
199+static Slot *lastslot;
200+static nslot;
201+
202+static void cisread(Slot*);
203+static void i82365intr(Ureg*, void*);
204+static void i82365reset(void);
205+static int pcmio(int, ISAConf*);
206+static long pcmread(int, int, void*, long, vlong);
207+static long pcmwrite(int, int, void*, long, vlong);
208+
209+static void i82365dump(Slot*);
210+
211+void
212+devi82365link(void)
213+{
214+ static int already;
215+
216+ if(already)
217+ return;
218+ already = 1;
219+
220+ if (_pcmspecial)
221+ return;
222+
223+ _pcmspecial = pcmcia_pcmspecial;
224+ _pcmspecialclose = pcmcia_pcmspecialclose;
225+}
226+
227+/*
228+ * reading and writing card registers
229+ */
230+static uchar
231+rdreg(Slot *pp, int index)
232+{
233+ outb(pp->cp->xreg, pp->base + index);
234+ return inb(pp->cp->dreg);
235+}
236+static void
237+wrreg(Slot *pp, int index, uchar val)
238+{
239+ outb(pp->cp->xreg, pp->base + index);
240+ outb(pp->cp->dreg, val);
241+}
242+
243+/*
244+ * get info about card
245+ */
246+static void
247+slotinfo(Slot *pp)
248+{
249+ uchar isr;
250+
251+ isr = rdreg(pp, Ris);
252+ pp->occupied = (isr & (3<<2)) == (3<<2);
253+ pp->powered = isr & (1<<6);
254+ pp->battery = (isr & 3) == 3;
255+ pp->wrprot = isr & (1<<4);
256+ pp->busy = isr & (1<<5);
257+}
258+
259+static int
260+vcode(int volt)
261+{
262+ switch(volt){
263+ case 5:
264+ return 1;
265+ case 12:
266+ return 2;
267+ default:
268+ return 0;
269+ }
270+}
271+
272+/*
273+ * enable the slot card
274+ */
275+static void
276+slotena(Slot *pp)
277+{
278+ if(pp->enabled)
279+ return;
280+
281+ /* power up and unreset, wait's are empirical (???) */
282+ wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
283+ delay(300);
284+ wrreg(pp, Rigc, 0);
285+ delay(100);
286+ wrreg(pp, Rigc, Fnotreset);
287+ delay(500);
288+
289+ /* get configuration */
290+ slotinfo(pp);
291+ if(pp->occupied){
292+ cisread(pp);
293+ pp->enabled = 1;
294+ } else
295+ wrreg(pp, Rpc, Fautopower);
296+}
297+
298+/*
299+ * disable the slot card
300+ */
301+static void
302+slotdis(Slot *pp)
303+{
304+ wrreg(pp, Rpc, 0); /* turn off card power */
305+ wrreg(pp, Rwe, 0); /* no windows */
306+ pp->enabled = 0;
307+}
308+
309+/*
310+ * status change interrupt
311+ */
312+static void
313+i82365intr(Ureg *, void *)
314+{
315+ uchar csc, was;
316+ Slot *pp;
317+
318+ if(slot == 0)
319+ return;
320+
321+ for(pp = slot; pp < lastslot; pp++){
322+ csc = rdreg(pp, Rcsc);
323+ was = pp->occupied;
324+ slotinfo(pp);
325+ if(csc & (1<<3) && was != pp->occupied){
326+ if(!pp->occupied)
327+ slotdis(pp);
328+ }
329+ }
330+}
331+
332+enum
333+{
334+ Mshift= 12,
335+ Mgran= (1<<Mshift), /* granularity of maps */
336+ Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
337+};
338+
339+/*
340+ * get a map for pc card region, return corrected len
341+ */
342+PCMmap*
343+pcmmap(int slotno, ulong offset, int len, int attr)
344+{
345+ Slot *pp;
346+ uchar we, bit;
347+ PCMmap *m, *nm;
348+ int i;
349+ ulong e;
350+
351+ pp = slot + slotno;
352+ lock(&pp->mlock);
353+
354+ /* convert offset to granularity */
355+ if(len <= 0)
356+ len = 1;
357+ e = ROUND(offset+len, Mgran);
358+ offset &= Mmask;
359+ len = e - offset;
360+
361+ /* look for a map that covers the right area */
362+ we = rdreg(pp, Rwe);
363+ bit = 1;
364+ nm = 0;
365+ for(m = pp->mmap; m < &pp->mmap[Nmap]; m++){
366+ if((we & bit))
367+ if(m->attr == attr)
368+ if(offset >= m->ca && e <= m->cea){
369+
370+ m->ref++;
371+ unlock(&pp->mlock);
372+ return m;
373+ }
374+ bit <<= 1;
375+ if(nm == 0 && m->ref == 0)
376+ nm = m;
377+ }
378+ m = nm;
379+ if(m == 0){
380+ unlock(&pp->mlock);
381+ return 0;
382+ }
383+
384+ /* if isa space isn't big enough, free it and get more */
385+ if(m->len < len){
386+ if(m->isa){
387+ umbfree(m->isa, m->len);
388+ m->len = 0;
389+ }
390+ m->isa = PADDR(umbmalloc(0, len, Mgran));
391+ if(m->isa == 0){
392+ print("pcmmap %d: out of isa space\n", len);
393+ unlock(&pp->mlock);
394+ return 0;
395+ }
396+ m->len = len;
397+ }
398+
399+ /* set up new map */
400+ m->ca = offset;
401+ m->cea = m->ca + m->len;
402+ m->attr = attr;
403+ i = m-pp->mmap;
404+ bit = 1<<i;
405+ wrreg(pp, Rwe, we & ~bit); /* disable map before changing it */
406+ wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift);
407+ wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
408+ wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
409+ wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
410+ offset -= m->isa;
411+ offset &= (1<<25)-1;
412+ offset >>= Mshift;
413+ wrreg(pp, MAP(i, Mofflo), offset);
414+ wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
415+ wrreg(pp, Rwe, we | bit); /* enable map */
416+ m->ref = 1;
417+
418+ unlock(&pp->mlock);
419+ return m;
420+}
421+
422+void
423+pcmunmap(int slotno, PCMmap* m)
424+{
425+ Slot *pp;
426+
427+ pp = slot + slotno;
428+ lock(&pp->mlock);
429+ m->ref--;
430+ unlock(&pp->mlock);
431+}
432+
433+static void
434+increfp(Slot *pp)
435+{
436+ lock(pp);
437+ if(pp->ref++ == 0)
438+ slotena(pp);
439+ unlock(pp);
440+}
441+
442+static void
443+decrefp(Slot *pp)
444+{
445+ lock(pp);
446+ if(pp->ref-- == 1)
447+ slotdis(pp);
448+ unlock(pp);
449+}
450+
451+/*
452+ * look for a card whose version contains 'idstr'
453+ */
454+static int
455+pcmcia_pcmspecial(char *idstr, ISAConf *isa)
456+{
457+ Slot *pp;
458+ extern char *strstr(char*, char*);
459+ int enabled;
460+
461+ i82365reset();
462+ for(pp = slot; pp < lastslot; pp++){
463+ if(pp->special)
464+ continue; /* already taken */
465+ enabled = 0;
466+ /* make sure we don't power on cards when we already know what's
467+ * in them. We'll reread every two minutes if necessary
468+ */
469+ if (pp->verstr[0] == '\0') {
470+ increfp(pp);
471+ enabled++;
472+ }
473+
474+ if(pp->occupied) {
475+ if(strstr(pp->verstr, idstr)) {
476+ if (!enabled)
477+ increfp(pp);
478+ if(isa == 0 || pcmio(pp->slotno, isa) == 0){
479+ pp->special = 1;
480+ return pp->slotno;
481+ }
482+ }
483+ } else
484+ pp->special = 1;
485+ if (enabled)
486+ decrefp(pp);
487+ }
488+ return -1;
489+}
490+
491+static void
492+pcmcia_pcmspecialclose(int slotno)
493+{
494+ Slot *pp;
495+
496+ print("pcmspecialclose called\n");
497+ if(slotno >= nslot)
498+ panic("pcmspecialclose");
499+ pp = slot + slotno;
500+ pp->special = 0;
501+ decrefp(pp);
502+}
503+
504+static char *chipname[] =
505+{
506+[Ti82365] "Intel 82365SL",
507+[Tpd6710] "Cirrus Logic PD6710",
508+[Tpd6720] "Cirrus Logic PD6720",
509+[Tvg46x] "Vadem VG-46x",
510+};
511+
512+static I82365*
513+i82365probe(int x, int d, int dev)
514+{
515+ uchar c, id;
516+ I82365 *cp;
517+ ISAConf isa;
518+ int i, nslot;
519+
520+ outb(x, Rid + (dev<<7));
521+ id = inb(d);
522+ if((id & 0xf0) != 0x80)
523+ return 0; /* not this family */
524+
525+ cp = xalloc(sizeof(I82365));
526+ cp->xreg = x;
527+ cp->dreg = d;
528+ cp->dev = dev;
529+ cp->type = Ti82365;
530+ cp->nslot = 2;
531+
532+ switch(id){
533+ case 0x82:
534+ case 0x83:
535+ case 0x84:
536+ /* could be a cirrus */
537+ outb(x, Rchipinfo + (dev<<7));
538+ outb(d, 0);
539+ c = inb(d);
540+ if((c & 0xc0) != 0xc0)
541+ break;
542+ c = inb(d);
543+ if((c & 0xc0) != 0x00)
544+ break;
545+ if(c & 0x20){
546+ cp->type = Tpd6720;
547+ } else {
548+ cp->type = Tpd6710;
549+ cp->nslot = 1;
550+ }
551+
552+ /* low power mode */
553+ outb(x, Rmisc2 + (dev<<7));
554+ c = inb(d);
555+ outb(d, c & ~Flowpow);
556+ break;
557+ }
558+
559+ if(cp->type == Ti82365){
560+ outb(x, 0x0E + (dev<<7));
561+ outb(x, 0x37 + (dev<<7));
562+ outb(x, 0x3A + (dev<<7));
563+ c = inb(d);
564+ outb(d, c|0xC0);
565+ outb(x, Rid + (dev<<7));
566+ c = inb(d);
567+ if(c != id && !(c & 0x08))
568+ print("#y%d: id %uX changed to %uX\n", ncontroller, id, c);
569+ if(c & 0x08)
570+ cp->type = Tvg46x;
571+ outb(x, 0x3A + (dev<<7));
572+ c = inb(d);
573+ outb(d, c & ~0xC0);
574+ }
575+
576+ memset(&isa, 0, sizeof(ISAConf));
577+ if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq)
578+ cp->irq = isa.irq;
579+ else
580+ cp->irq = VectorPCMCIA - VectorPIC;
581+
582+ for(i = 0; i < isa.nopt; i++){
583+ if(cistrncmp(isa.opt[i], "nslot=", 6))
584+ continue;
585+ nslot = strtol(&isa.opt[i][6], nil, 0);
586+ if(nslot > 0 && nslot <= 2)
587+ cp->nslot = nslot;
588+ }
589+
590+ controller[ncontroller++] = cp;
591+ return cp;
592+}
593+
594+static void
595+i82365dump(Slot *pp)
596+{
597+ int i;
598+
599+ for(i = 0; i < 0x40; i++){
600+ if((i&0x0F) == 0)
601+ print("\n%2.2uX: ", i);
602+ if(((i+1) & 0x0F) == 0x08)
603+ print(" - ");
604+ print("%2.2uX ", rdreg(pp, i));
605+ }
606+ print("\n");
607+}
608+
609+/*
610+ * set up for slot cards
611+ */
612+static void
613+i82365reset(void)
614+{
615+ static int already;
616+ int i, j;
617+ I82365 *cp;
618+ Slot *pp;
619+
620+ if(already)
621+ return;
622+ already = 1;
623+
624+
625+ /* look for controllers */
626+ i82365probe(0x3E0, 0x3E1, 0);
627+ i82365probe(0x3E0, 0x3E1, 1);
628+ i82365probe(0x3E2, 0x3E3, 0);
629+ i82365probe(0x3E2, 0x3E3, 1);
630+
631+ for(i = 0; i < ncontroller; i++)
632+ nslot += controller[i]->nslot;
633+ slot = xalloc(nslot * sizeof(Slot));
634+
635+ /* if the card is there turn on 5V power to keep its battery alive */
636+ lastslot = slot;
637+ for(i = 0; i < ncontroller; i++){
638+ cp = controller[i];
639+ print("#y%d: %d slot %s: port 0x%uX irq %d\n",
640+ i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq);
641+ for(j = 0; j < cp->nslot; j++){
642+ pp = lastslot++;
643+ pp->slotno = pp - slot;
644+ pp->memlen = 64*MB;
645+ pp->base = (cp->dev<<7) | (j<<6);
646+ pp->cp = cp;
647+ slotdis(pp);
648+
649+ /* interrupt on status change */
650+ wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena);
651+ rdreg(pp, Rcsc);
652+ }
653+
654+ /* for card management interrupts */
655+ setvec(cp->irq+VectorPIC, i82365intr, 0);
656+ }
657+}
658+
659+/*
660+ * configure the Slot for IO. We assume very heavily that we can read
661+ * configuration info from the CIS. If not, we won't set up correctly.
662+ */
663+static int
664+pcmio(int slotno, ISAConf *isa)
665+{
666+ uchar we, x, *p;
667+ Slot *pp;
668+ Conftab *ct, *et, *t;
669+ PCMmap *m;
670+ int i, index, irq;
671+ char *cp;
672+
673+ irq = isa->irq;
674+ if(irq == 2)
675+ irq = 9;
676+
677+ if(slotno > nslot)
678+ return -1;
679+ pp = slot + slotno;
680+
681+ if(!pp->occupied)
682+ return -1;
683+
684+ et = &pp->ctab[pp->nctab];
685+
686+ ct = 0;
687+ for(i = 0; i < isa->nopt; i++){
688+ if(strncmp(isa->opt[i], "index=", 6))
689+ continue;
690+ index = strtol(&isa->opt[i][6], &cp, 0);
691+ if(cp == &isa->opt[i][6] || index >= pp->nctab)
692+ return -1;
693+ ct = &pp->ctab[index];
694+ }
695+ if(ct == 0){
696+
697+ /* assume default is right */
698+ if(pp->def)
699+ ct = pp->def;
700+ else
701+ ct = pp->ctab;
702+
703+ /* try for best match */
704+ if(ct->nio == 0
705+ || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
706+ for(t = pp->ctab; t < et; t++)
707+ if(t->nio
708+ && t->io[0].start == isa->port
709+ && ((1<<irq) & t->irqs)){
710+ ct = t;
711+ break;
712+ }
713+ }
714+ if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
715+ for(t = pp->ctab; t < et; t++)
716+ if(t->nio && ((1<<irq) & t->irqs)){
717+ ct = t;
718+ break;
719+ }
720+ }
721+ if(ct->nio == 0){
722+ for(t = pp->ctab; t < et; t++)
723+ if(t->nio){
724+ ct = t;
725+ break;
726+ }
727+ }
728+ }
729+
730+ if(ct == et || ct->nio == 0)
731+ return -1;
732+ if(isa->port == 0 && ct->io[0].start == 0)
733+ return -1;
734+
735+ /* route interrupts */
736+ isa->irq = irq;
737+ wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
738+
739+ /* set power and enable device */
740+ x = vcode(ct->vpp1);
741+ wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
742+
743+ /* 16-bit data path */
744+ if(ct->bit16)
745+ x = Ftiming|Fiocs16|Fwidth16;
746+ else
747+ x = Ftiming;
748+ if(ct->nio == 2 && ct->io[1].start)
749+ x |= x<<4;
750+ wrreg(pp, Rio, x);
751+
752+ /* enable io port map 0 */
753+ if(isa->port == 0)
754+ isa->port = ct->io[0].start;
755+ we = rdreg(pp, Rwe);
756+ wrreg(pp, Riobtm0lo, isa->port);
757+ wrreg(pp, Riobtm0hi, isa->port>>8);
758+ i = isa->port+ct->io[0].len-1;
759+ wrreg(pp, Riotop0lo, i);
760+ wrreg(pp, Riotop0hi, i>>8);
761+ we |= 1<<6;
762+ if(ct->nio == 2 && ct->io[1].start){
763+ wrreg(pp, Riobtm1lo, ct->io[1].start);
764+ wrreg(pp, Riobtm1hi, ct->io[1].start>>8);
765+ i = ct->io[1].start+ct->io[1].len-1;
766+ wrreg(pp, Riotop1lo, i);
767+ wrreg(pp, Riotop1hi, i>>8);
768+ we |= 1<<7;
769+ }
770+ wrreg(pp, Rwe, we);
771+
772+ /* only touch Rconfig if it is present */
773+ if(pp->cpresent & (1<<Rconfig)){
774+ /* Reset adapter */
775+ m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1);
776+ p = KADDR(m->isa + pp->caddr + Rconfig - m->ca);
777+
778+ /* set configuration and interrupt type */
779+ x = ct->index;
780+ if((ct->irqtype & 0x20) && ((ct->irqtype & 0x40)==0 || isa->irq>7))
781+ x |= Clevel;
782+ *p = x;
783+ delay(5);
784+
785+ pcmunmap(slotno, m);
786+ }
787+ return 0;
788+}
789+
790+/*
791+ * read and crack the card information structure enough to set
792+ * important parameters like power
793+ */
794+static void tcfig(Slot*, Cisdat*, int);
795+static void tentry(Slot*, Cisdat*, int);
796+static void tvers1(Slot*, Cisdat*, int);
797+
798+struct {
799+ int n;
800+ void (*parse)(Slot*, Cisdat*, int);
801+} cistab[] = {
802+ 0x15, tvers1,
803+ 0x1A, tcfig,
804+ 0x1B, tentry,
805+};

400 more lines aren’t shown here.

os/boot/pc/devpccard.c+1957−0

This diff is large: its 1958 lines aren’t shown here.

os/boot/pc/devsd.c+617−0

This diff is large: its 618 lines aren’t shown here.

os/boot/pc/dma.c+245−0

This diff is large: its 246 lines aren’t shown here.

os/boot/pc/dosboot.c+582−0

This diff is large: its 583 lines aren’t shown here.

os/boot/pc/dosfs.h+62−0

This diff is large: its 63 lines aren’t shown here.

os/boot/pc/eipfmt.c+145−0

This diff is large: its 146 lines aren’t shown here.

os/boot/pc/error.h+58−0

This diff is large: its 59 lines aren’t shown here.

os/boot/pc/ether.c+282−0

This diff is large: its 283 lines aren’t shown here.

os/boot/pc/ether2000.c+110−0

This diff is large: its 111 lines aren’t shown here.

os/boot/pc/ether2114x.c+1652−0

This diff is large: its 1653 lines aren’t shown here.

os/boot/pc/ether589.c+211−0

This diff is large: its 212 lines aren’t shown here.

os/boot/pc/ether79c970.c+539−0

This diff is large: its 540 lines aren’t shown here.

os/boot/pc/ether8003.c+258−0

This diff is large: its 259 lines aren’t shown here.

os/boot/pc/ether8139.c+614−0

This diff is large: its 615 lines aren’t shown here.

os/boot/pc/ether8169.c+847−0

This diff is large: its 848 lines aren’t shown here.

os/boot/pc/ether82557.c+881−0

This diff is large: its 882 lines aren’t shown here.

os/boot/pc/ether83815.c+825−0

This diff is large: its 826 lines aren’t shown here.

os/boot/pc/ether8390.c+715−0

This diff is large: its 716 lines aren’t shown here.

os/boot/pc/ether8390.h+71−0

This diff is large: its 72 lines aren’t shown here.

os/boot/pc/etherec2t.c+155−0

This diff is large: its 156 lines aren’t shown here.

os/boot/pc/etherelnk3.c+1898−0

This diff is large: its 1899 lines aren’t shown here.

os/boot/pc/etherif.h+46−0

This diff is large: its 47 lines aren’t shown here.

os/boot/pc/etherigbe.c+1706−0

This diff is large: its 1707 lines aren’t shown here.

os/boot/pc/ethermii.c+224−0

This diff is large: its 225 lines aren’t shown here.

os/boot/pc/ethermii.h+116−0

This diff is large: its 117 lines aren’t shown here.

os/boot/pc/etherrhine.c+676−0

This diff is large: its 677 lines aren’t shown here.

os/boot/pc/fns.h+155−0

This diff is large: its 156 lines aren’t shown here.

os/boot/pc/fs.c+94−0

This diff is large: its 95 lines aren’t shown here.

os/boot/pc/fs.h+36−0

This diff is large: its 37 lines aren’t shown here.

os/boot/pc/getcallerpc.c+8−0

This diff is large: its 9 lines aren’t shown here.

os/boot/pc/ilock.c+24−0

This diff is large: its 25 lines aren’t shown here.

os/boot/pc/inflate.c+199−0

This diff is large: its 200 lines aren’t shown here.

os/boot/pc/io.h+201−0

This diff is large: its 202 lines aren’t shown here.

os/boot/pc/ip.h+100−0

This diff is large: its 101 lines aren’t shown here.

os/boot/pc/kbd.c+489−0

This diff is large: its 490 lines aren’t shown here.

os/boot/pc/kfs.h+57−0

This diff is large: its 58 lines aren’t shown here.

os/boot/pc/kfsboot.c+256−0

This diff is large: its 257 lines aren’t shown here.

os/boot/pc/l.s+1079−0

This diff is large: its 1080 lines aren’t shown here.

os/boot/pc/lib.h+102−0

This diff is large: its 103 lines aren’t shown here.

os/boot/pc/load.c+563−0

This diff is large: its 564 lines aren’t shown here.

os/boot/pc/mbr.s+259−0

This diff is large: its 260 lines aren’t shown here.

os/boot/pc/mem.h+114−0

This diff is large: its 115 lines aren’t shown here.

os/boot/pc/memory.c+504−0

This diff is large: its 505 lines aren’t shown here.

os/boot/pc/mkfile+241−0

This diff is large: its 242 lines aren’t shown here.

os/boot/pc/noether.c+40−0

This diff is large: its 41 lines aren’t shown here.

os/boot/pc/part.c+344−0

This diff is large: its 345 lines aren’t shown here.

os/boot/pc/pbs.s+372−0

This diff is large: its 373 lines aren’t shown here.

os/boot/pc/pbsdisk+0−0

Binary file not shown.

os/boot/pc/pbsdisk.s+344−0

This diff is large: its 345 lines aren’t shown here.

os/boot/pc/pbsdisklba+0−0

Binary file not shown.

os/boot/pc/pbsdisklba.s+327−0

This diff is large: its 328 lines aren’t shown here.

os/boot/pc/pbslba.s+362−0

This diff is large: its 363 lines aren’t shown here.

os/boot/pc/pci.c+852−0

This diff is large: its 853 lines aren’t shown here.

os/boot/pc/print.c+31−0

This diff is large: its 32 lines aren’t shown here.

os/boot/pc/queue.c+44−0

This diff is large: its 45 lines aren’t shown here.

os/boot/pc/sd.h+127−0

This diff is large: its 128 lines aren’t shown here.

os/boot/pc/sd53c8xx.c+2120−0

This diff is large: its 2121 lines aren’t shown here.

os/boot/pc/sd53c8xx.i+769−0

This diff is large: its 770 lines aren’t shown here.

os/boot/pc/sdata.c+1639−0

This diff is large: its 1640 lines aren’t shown here.

os/boot/pc/sdmylex.c+1294−0

This diff is large: its 1295 lines aren’t shown here.

os/boot/pc/sdscsi.c+376−0

This diff is large: its 377 lines aren’t shown here.

os/boot/pc/trap.c+331−0

This diff is large: its 332 lines aren’t shown here.

os/boot/pc/ureg.h+27−0

This diff is large: its 28 lines aren’t shown here.

os/boot/pc/x16.h+159−0

This diff is large: its 160 lines aren’t shown here.

os/boot/puma/8250.c+312−0

This diff is large: its 313 lines aren’t shown here.

os/boot/puma/alarm.c+123−0

This diff is large: its 124 lines aren’t shown here.

os/boot/puma/armv4.h+99−0

This diff is large: its 100 lines aren’t shown here.

os/boot/puma/boot.h+12−0

This diff is large: its 13 lines aren’t shown here.

os/boot/puma/bootp.c+502−0

This diff is large: its 503 lines aren’t shown here.

os/boot/puma/cga.c+92−0

This diff is large: its 93 lines aren’t shown here.

os/boot/puma/clock.c+154−0

This diff is large: its 155 lines aren’t shown here.

os/boot/puma/conf.c+181−0

This diff is large: its 182 lines aren’t shown here.

os/boot/puma/console.c+181−0

This diff is large: its 182 lines aren’t shown here.

os/boot/puma/dat.h+205−0

This diff is large: its 206 lines aren’t shown here.

os/boot/puma/div.s+122−0

This diff is large: its 123 lines aren’t shown here.

os/boot/puma/donprint.c+332−0

This diff is large: its 333 lines aren’t shown here.

os/boot/puma/dosboot.c+614−0

This diff is large: its 615 lines aren’t shown here.

os/boot/puma/dosfs.h+110−0

This diff is large: its 111 lines aren’t shown here.

os/boot/puma/ebsit.trap.c+206−0

This diff is large: its 207 lines aren’t shown here.

os/boot/puma/ether.c+156−0

This diff is large: its 157 lines aren’t shown here.

os/boot/puma/ether.h+82−0

This diff is large: its 83 lines aren’t shown here.

os/boot/puma/ether8900.c+555−0

This diff is large: its 556 lines aren’t shown here.

os/boot/puma/flash.c+226−0

This diff is large: its 227 lines aren’t shown here.

os/boot/puma/fns.h+111−0

This diff is large: its 112 lines aren’t shown here.

os/boot/puma/hard.c+773−0

This diff is large: its 774 lines aren’t shown here.

os/boot/puma/io.h+3−0

This diff is large: its 4 lines aren’t shown here.

os/boot/puma/ip.h+98−0

This diff is large: its 99 lines aren’t shown here.

os/boot/puma/kbd.c+482−0

This diff is large: its 483 lines aren’t shown here.

os/boot/puma/l.s+427−0

This diff is large: its 428 lines aren’t shown here.

os/boot/puma/lib.h+107−0

This diff is large: its 108 lines aren’t shown here.

os/boot/puma/main.c+552−0

This diff is large: its 553 lines aren’t shown here.

os/boot/puma/mem.h+38−0

This diff is large: its 39 lines aren’t shown here.

os/boot/puma/mkfile+71−0

This diff is large: its 72 lines aren’t shown here.

os/boot/puma/outb.c+20−0

This diff is large: its 21 lines aren’t shown here.

os/boot/puma/plan9boot.c+93−0

This diff is large: its 94 lines aren’t shown here.

os/boot/puma/puma.c+123−0

This diff is large: its 124 lines aren’t shown here.

os/boot/puma/puma.h+435−0

This diff is large: its 436 lines aren’t shown here.

os/boot/puma/qio.c+128−0

This diff is large: its 129 lines aren’t shown here.

os/boot/puma/rmap.c+104−0

This diff is large: its 105 lines aren’t shown here.

os/boot/puma/squeeze.h+34−0

This diff is large: its 35 lines aren’t shown here.

os/boot/puma/sum.c+13−0

This diff is large: its 14 lines aren’t shown here.

os/boot/puma/trap.c+190−0

This diff is large: its 191 lines aren’t shown here.

os/boot/puma/ureg.h+22−0

This diff is large: its 23 lines aren’t shown here.

os/boot/puma/zqs.c+216−0

This diff is large: its 217 lines aren’t shown here.

os/boot/rpcg/NOTICE+3−0

This diff is large: its 4 lines aren’t shown here.

os/boot/rpcg/alarm.c+123−0

This diff is large: its 124 lines aren’t shown here.

os/boot/rpcg/all.h+6−0

This diff is large: its 7 lines aren’t shown here.

os/boot/rpcg/archrpcg.c+279−0

This diff is large: its 280 lines aren’t shown here.

os/boot/rpcg/archrpcg.h+48−0

This diff is large: its 49 lines aren’t shown here.

os/boot/rpcg/boot.h+8−0

This diff is large: its 9 lines aren’t shown here.

os/boot/rpcg/bootp.c+509−0

This diff is large: its 510 lines aren’t shown here.

os/boot/rpcg/clock.c+71−0

This diff is large: its 72 lines aren’t shown here.

os/boot/rpcg/conf.c+173−0

This diff is large: its 174 lines aren’t shown here.

os/boot/rpcg/console.c+173−0

This diff is large: its 174 lines aren’t shown here.

os/boot/rpcg/cpm.c+162−0

This diff is large: its 163 lines aren’t shown here.

os/boot/rpcg/crc32.c+42−0

This diff is large: its 43 lines aren’t shown here.

os/boot/rpcg/dat.h+217−0

This diff is large: its 218 lines aren’t shown here.

os/boot/rpcg/defont0.c+216−0

This diff is large: its 217 lines aren’t shown here.

os/boot/rpcg/devether.c+157−0

This diff is large: its 158 lines aren’t shown here.

os/boot/rpcg/devuart.c+230−0

This diff is large: its 231 lines aren’t shown here.

os/boot/rpcg/dload.c+103−0

This diff is large: its 104 lines aren’t shown here.

os/boot/rpcg/donprint.c+332−0

This diff is large: its 333 lines aren’t shown here.

os/boot/rpcg/dosboot.c+614−0

This diff is large: its 615 lines aren’t shown here.

os/boot/rpcg/dosfs.h+110−0

This diff is large: its 111 lines aren’t shown here.

os/boot/rpcg/etherif.h+59−0

This diff is large: its 60 lines aren’t shown here.

os/boot/rpcg/etherscc.c+411−0

This diff is large: its 412 lines aren’t shown here.

os/boot/rpcg/fblt.c+531−0

This diff is large: its 532 lines aren’t shown here.

os/boot/rpcg/flash.c+212−0

This diff is large: its 213 lines aren’t shown here.

os/boot/rpcg/fns.h+118−0

This diff is large: its 119 lines aren’t shown here.

os/boot/rpcg/g.mx+1987−0

This diff is large: its 1988 lines aren’t shown here.

os/boot/rpcg/gbitbltclip.c+52−0

This diff is large: its 53 lines aren’t shown here.

os/boot/rpcg/gnot.h+71−0

This diff is large: its 72 lines aren’t shown here.

os/boot/rpcg/i2c.c+360−0

This diff is large: its 361 lines aren’t shown here.

os/boot/rpcg/initfads.c+187−0

This diff is large: its 188 lines aren’t shown here.

os/boot/rpcg/initpaq.c+101−0

This diff is large: its 102 lines aren’t shown here.

os/boot/rpcg/initrpcg.c+91−0

This diff is large: its 92 lines aren’t shown here.

os/boot/rpcg/io.h+463−0

This diff is large: its 464 lines aren’t shown here.

os/boot/rpcg/ip.h+98−0

This diff is large: its 99 lines aren’t shown here.

os/boot/rpcg/l.s+388−0

This diff is large: its 389 lines aren’t shown here.

os/boot/rpcg/lib.h+106−0

This diff is large: its 107 lines aren’t shown here.

os/boot/rpcg/libg.h+418−0

This diff is large: its 419 lines aren’t shown here.

os/boot/rpcg/main.c+527−0

This diff is large: its 528 lines aren’t shown here.

os/boot/rpcg/mem.c+0−0

Empty file added.

os/boot/rpcg/mem.h+94−0

This diff is large: its 95 lines aren’t shown here.

os/boot/rpcg/mkfile+120−0

This diff is large: its 121 lines aren’t shown here.

os/boot/rpcg/ms2.c+179−0

This diff is large: its 180 lines aren’t shown here.

os/boot/rpcg/plan9boot.c+96−0

This diff is large: its 97 lines aren’t shown here.

os/boot/rpcg/qbromrpcg+0−0

Binary file not shown.

os/boot/rpcg/qio.c+128−0

This diff is large: its 129 lines aren’t shown here.

os/boot/rpcg/rmap.c+104−0

This diff is large: its 105 lines aren’t shown here.

os/boot/rpcg/screen.c+242−0

This diff is large: its 243 lines aren’t shown here.

os/boot/rpcg/sload+0−0

Binary file not shown.

os/boot/rpcg/sload.c+71−0

This diff is large: its 72 lines aren’t shown here.

os/boot/rpcg/squeeze.h+34−0

This diff is large: its 35 lines aren’t shown here.

os/boot/rpcg/trap.c+233−0

This diff is large: its 234 lines aren’t shown here.

os/boot/rpcg/uartboot.c+189−0

This diff is large: its 190 lines aren’t shown here.

os/boot/rpcg/ureg.h+43−0

This diff is large: its 44 lines aren’t shown here.

os/boot/rpcg/zqs.c+234−0

This diff is large: its 235 lines aren’t shown here.

os/cerf1110/Mk+8−0

This diff is large: its 9 lines aren’t shown here.

os/cerf1110/NOTICE+2−0

This diff is large: its 3 lines aren’t shown here.

os/cerf1110/README+22−0

This diff is large: its 23 lines aren’t shown here.

os/cerf1110/archcerf.c+177−0

This diff is large: its 178 lines aren’t shown here.

os/cerf1110/cerf+159−0

This diff is large: its 160 lines aren’t shown here.

os/cerf1110/dat.h+135−0

This diff is large: its 136 lines aren’t shown here.

os/cerf1110/devata.c+1200−0

This diff is large: its 1201 lines aren’t shown here.

os/cerf1110/devcerf.c+128−0

This diff is large: its 129 lines aren’t shown here.

os/cerf1110/ether8900.c+702−0

This diff is large: its 703 lines aren’t shown here.

os/cerf1110/fns.h+179−0

This diff is large: its 180 lines aren’t shown here.

os/cerf1110/io.h+1−0

This diff is large: its 2 lines aren’t shown here.

os/cerf1110/main.c+255−0

This diff is large: its 256 lines aren’t shown here.

os/cerf1110/mem.h+200−0

This diff is large: its 201 lines aren’t shown here.

os/cerf1110/mkfile+101−0

This diff is large: its 102 lines aren’t shown here.

os/cerf250/NOTICE+2−0

This diff is large: its 3 lines aren’t shown here.

os/cerf250/README+44−0

This diff is large: its 45 lines aren’t shown here.

os/cerf250/archcerf.c+266−0

This diff is large: its 267 lines aren’t shown here.

os/cerf250/cerf+163−0

This diff is large: its 164 lines aren’t shown here.

os/cerf250/dat.h+135−0

This diff is large: its 136 lines aren’t shown here.

os/cerf250/devpcf8563.c+371−0

This diff is large: its 372 lines aren’t shown here.

os/cerf250/ether91c111.c+1056−0

This diff is large: its 1057 lines aren’t shown here.

os/cerf250/fns.h+168−0

This diff is large: its 169 lines aren’t shown here.

os/cerf250/io.h+1−0

This diff is large: its 2 lines aren’t shown here.

os/cerf250/main.c+351−0

This diff is large: its 352 lines aren’t shown here.

os/cerf250/mem.h+174−0

This diff is large: its 175 lines aren’t shown here.

os/cerf250/mkfile+102−0

This diff is large: its 103 lines aren’t shown here.

os/cerf250/uart.h+118−0

This diff is large: its 119 lines aren’t shown here.

os/cerf405/NOTICE+3−0

This diff is large: its 4 lines aren’t shown here.

os/cerf405/README+45−0

This diff is large: its 46 lines aren’t shown here.

os/cerf405/cerf+139−0

This diff is large: its 140 lines aren’t shown here.

os/cerf405/clock.c+159−0

This diff is large: its 160 lines aren’t shown here.

os/cerf405/compile.c+34−0

This diff is large: its 35 lines aren’t shown here.

os/cerf405/dat.h+159−0

This diff is large: its 160 lines aren’t shown here.

os/cerf405/devboot.c+132−0

This diff is large: its 133 lines aren’t shown here.

os/cerf405/devether.c+617−0

This diff is large: its 618 lines aren’t shown here.

os/cerf405/devrtc.c+369−0

This diff is large: its 370 lines aren’t shown here.

os/cerf405/devuart.c+1064−0

This diff is large: its 1065 lines aren’t shown here.

os/cerf405/etheremac.c+829−0

This diff is large: its 830 lines aren’t shown here.

os/cerf405/etherif.h+37−0

This diff is large: its 38 lines aren’t shown here.

os/cerf405/fns.h+147−0

This diff is large: its 148 lines aren’t shown here.

os/cerf405/fpi.h+61−0

This diff is large: its 62 lines aren’t shown here.

os/cerf405/fpipower.c+970−0

This diff is large: its 971 lines aren’t shown here.

os/cerf405/gpio.c+106−0

This diff is large: its 107 lines aren’t shown here.

os/cerf405/iic.c+605−0

This diff is large: its 606 lines aren’t shown here.

os/cerf405/inb.s+127−0

This diff is large: its 128 lines aren’t shown here.

os/cerf405/io.h+301−0

This diff is large: its 302 lines aren’t shown here.

os/cerf405/l.s+795−0

This diff is large: its 796 lines aren’t shown here.

os/cerf405/main.c+719−0

This diff is large: its 720 lines aren’t shown here.

os/cerf405/mal.c+334−0

This diff is large: its 335 lines aren’t shown here.

os/cerf405/mem.h+147−0

This diff is large: its 148 lines aren’t shown here.

os/cerf405/mkfile+104−0

This diff is large: its 105 lines aren’t shown here.

os/cerf405/mmu.c+122−0

This diff is large: its 123 lines aren’t shown here.

os/cerf405/nand.c+96−0

This diff is large: its 97 lines aren’t shown here.

os/cerf405/nofp.s+31−0

This diff is large: its 32 lines aren’t shown here.

os/cerf405/pci.c+981−0

This diff is large: its 982 lines aren’t shown here.

os/cerf405/physmem.h+22−0

This diff is large: its 23 lines aren’t shown here.

os/cerf405/powerbreak.c+123−0

This diff is large: its 124 lines aren’t shown here.

os/cerf405/rmap.c+106−0

This diff is large: its 107 lines aren’t shown here.

os/cerf405/tlb.s+30−0

This diff is large: its 31 lines aren’t shown here.

os/cerf405/trap.c+581−0

This diff is large: its 582 lines aren’t shown here.

os/cerf405/uart.c+139−0

This diff is large: its 140 lines aren’t shown here.

os/cerf405/uart.h+101−0

This diff is large: its 102 lines aren’t shown here.

os/fads/NOTICE+4−0

This diff is large: its 5 lines aren’t shown here.

os/fads/archfads.c+619−0

This diff is large: its 620 lines aren’t shown here.

os/fads/archfads.h+33−0

This diff is large: its 34 lines aren’t shown here.

os/fads/dat.h+162−0

This diff is large: its 163 lines aren’t shown here.

os/fads/fads+121−0

This diff is large: its 122 lines aren’t shown here.

os/fads/fns.h+117−0

This diff is large: its 118 lines aren’t shown here.

os/fads/io.h+1−0

This diff is large: its 2 lines aren’t shown here.

os/fads/main.c+392−0

This diff is large: its 393 lines aren’t shown here.

os/fads/mem.h+157−0

This diff is large: its 158 lines aren’t shown here.

os/fads/mkfile+107−0

This diff is large: its 108 lines aren’t shown here.

os/fads/mmu.c+20−0

This diff is large: its 21 lines aren’t shown here.

os/fads/tlb.s+23−0

This diff is large: its 24 lines aren’t shown here.

os/init/README+5−0

This diff is large: its 6 lines aren’t shown here.

os/init/bootinit.b+628−0

This diff is large: its 629 lines aren’t shown here.

os/init/cerf405.b+598−0

This diff is large: its 599 lines aren’t shown here.

os/init/cerfinit.b+612−0

This diff is large: its 613 lines aren’t shown here.

os/init/evalinit.b+119−0

This diff is large: its 120 lines aren’t shown here.

os/init/geninit.b+93−0

This diff is large: its 94 lines aren’t shown here.

os/init/i4e.b+210−0

This diff is large: its 211 lines aren’t shown here.

os/init/init.b+613−0

This diff is large: its 614 lines aren’t shown here.

os/init/ipaqinit.b+697−0

This diff is large: its 698 lines aren’t shown here.

os/init/ipeinit.b+620−0

This diff is large: its 621 lines aren’t shown here.

os/init/jsinit.b+213−0

This diff is large: its 214 lines aren’t shown here.

os/init/mkfile+27−0

This diff is large: its 28 lines aren’t shown here.

os/init/mpcinit.b+383−0

This diff is large: its 384 lines aren’t shown here.

os/init/pcdemo.b+273−0

This diff is large: its 274 lines aren’t shown here.

os/init/pcinit.b+405−0

This diff is large: its 406 lines aren’t shown here.

os/init/reminit.b+239−0

This diff is large: its 240 lines aren’t shown here.

os/init/rpcginit.b+610−0

This diff is large: its 611 lines aren’t shown here.

os/init/shell.b+97−0

This diff is large: its 98 lines aren’t shown here.

os/init/soeinit.b+613−0

This diff is large: its 614 lines aren’t shown here.

os/init/srvinit.b+209−0

This diff is large: its 210 lines aren’t shown here.

os/init/wminit.b+231−0

This diff is large: its 232 lines aren’t shown here.

os/ip/arp.c+681−0

This diff is large: its 682 lines aren’t shown here.

os/ip/bootp.c+231−0

This diff is large: its 232 lines aren’t shown here.

os/ip/compress.c+520−0

This diff is large: its 521 lines aren’t shown here.

os/ip/devip.c+1419−0

This diff is large: its 1420 lines aren’t shown here.

os/ip/dhcp.c+447−0

This diff is large: its 448 lines aren’t shown here.

os/ip/eipconvtest.c+152−0

This diff is large: its 153 lines aren’t shown here.

os/ip/esp.c+866−0

This diff is large: its 867 lines aren’t shown here.

os/ip/ethermedium.c+792−0

This diff is large: its 793 lines aren’t shown here.

os/ip/gre.c+282−0

This diff is large: its 283 lines aren’t shown here.

os/ip/icmp.c+490−0

This diff is large: its 491 lines aren’t shown here.

os/ip/icmp6.c+917−0

This diff is large: its 918 lines aren’t shown here.

os/ip/igmp.c+291−0

This diff is large: its 292 lines aren’t shown here.

os/ip/ihbootp.c+323−0

This diff is large: its 324 lines aren’t shown here.

os/ip/il.c+1408−0

This diff is large: its 1409 lines aren’t shown here.

os/ip/ip.c+805−0

This diff is large: its 806 lines aren’t shown here.

os/ip/ip.h+673−0

This diff is large: its 674 lines aren’t shown here.

os/ip/ipaux.c+730−0

This diff is large: its 731 lines aren’t shown here.

os/ip/ipifc.c+1721−0

This diff is large: its 1722 lines aren’t shown here.

os/ip/ipmux.c+857−0

This diff is large: its 858 lines aren’t shown here.

os/ip/iproute.c+852−0

This diff is large: its 853 lines aren’t shown here.

os/ip/iprouter.c+56−0

This diff is large: its 57 lines aren’t shown here.

os/ip/ipv6.c+747−0

This diff is large: its 748 lines aren’t shown here.

os/ip/ipv6.h+185−0

This diff is large: its 186 lines aren’t shown here.

os/ip/kernel.h+10−0

This diff is large: its 11 lines aren’t shown here.

os/ip/loopbackmedium.c+121−0

This diff is large: its 122 lines aren’t shown here.

os/ip/netdevmedium.c+153−0

This diff is large: its 154 lines aren’t shown here.

os/ip/netlog.c+263−0

This diff is large: its 264 lines aren’t shown here.

os/ip/nullmedium.c+39−0

This diff is large: its 40 lines aren’t shown here.

os/ip/pktmedium.c+79−0

This diff is large: its 80 lines aren’t shown here.

os/ip/plan9.c+36−0

This diff is large: its 37 lines aren’t shown here.

os/ip/ppp.c+1656−0

This diff is large: its 1657 lines aren’t shown here.

os/ip/ppp.h+258−0

This diff is large: its 259 lines aren’t shown here.

os/ip/pppmedium.c+192−0

This diff is large: its 193 lines aren’t shown here.

os/ip/ptclbsum.c+72−0

This diff is large: its 73 lines aren’t shown here.

os/ip/rudp.c+1085−0

This diff is large: its 1086 lines aren’t shown here.

os/ip/tcp.c+3177−0

This diff is large: its 3178 lines aren’t shown here.

os/ip/udp.c+649−0

This diff is large: its 650 lines aren’t shown here.

os/ipaq1110/Mk+8−0

This diff is large: its 9 lines aren’t shown here.

os/ipaq1110/NOTICE+6−0

This diff is large: its 7 lines aren’t shown here.

os/ipaq1110/README+65−0

This diff is large: its 66 lines aren’t shown here.

os/ipaq1110/archipaq.c+376−0

This diff is large: its 377 lines aren’t shown here.

os/ipaq1110/dat.h+135−0

This diff is large: its 136 lines aren’t shown here.

os/ipaq1110/defont.c+290−0

This diff is large: its 291 lines aren’t shown here.

os/ipaq1110/devaudio.c+1056−0

This diff is large: its 1057 lines aren’t shown here.

os/ipaq1110/devipaq.c+762−0

This diff is large: its 763 lines aren’t shown here.

os/ipaq1110/etherwavelan.c+1307−0

This diff is large: its 1308 lines aren’t shown here.

os/ipaq1110/fns.h+179−0

This diff is large: its 180 lines aren’t shown here.

os/ipaq1110/inflate+0−0

Binary file not shown.

os/ipaq1110/io.h+60−0

This diff is large: its 61 lines aren’t shown here.

os/ipaq1110/ipaq+172−0

This diff is large: its 173 lines aren’t shown here.

os/ipaq1110/lcd.c+185−0

This diff is large: its 186 lines aren’t shown here.

os/ipaq1110/main.c+255−0

This diff is large: its 256 lines aren’t shown here.

os/ipaq1110/mem.h+200−0

This diff is large: its 201 lines aren’t shown here.

os/ipaq1110/mkfile+103−0

This diff is large: its 104 lines aren’t shown here.

os/ipaq1110/screen.c+917−0

This diff is large: its 918 lines aren’t shown here.

os/ipaq1110/screen.h+64−0

This diff is large: its 65 lines aren’t shown here.

os/ipaq1110/tstdraw.b+107−0

This diff is large: its 108 lines aren’t shown here.

os/ipaq1110/upd+4−0

This diff is large: its 5 lines aren’t shown here.

os/ipengine/NOTICE+4−0

This diff is large: its 5 lines aren’t shown here.

os/ipengine/README+40−0

This diff is large: its 41 lines aren’t shown here.

os/ipengine/archipe.c+488−0

This diff is large: its 489 lines aren’t shown here.

os/ipengine/archipe.h+32−0

This diff is large: its 33 lines aren’t shown here.

os/ipengine/dat.h+162−0

This diff is large: its 163 lines aren’t shown here.

os/ipengine/devfpga.c+389−0

This diff is large: its 390 lines aren’t shown here.

os/ipengine/flash28f320b3b.c+43−0

This diff is large: its 44 lines aren’t shown here.

os/ipengine/fns.h+120−0

This diff is large: its 121 lines aren’t shown here.

os/ipengine/io.h+1−0

This diff is large: its 2 lines aren’t shown here.

os/ipengine/ipe+109−0

This diff is large: its 110 lines aren’t shown here.

os/ipengine/main.c+348−0

This diff is large: its 349 lines aren’t shown here.

os/ipengine/mem.h+156−0

This diff is large: its 157 lines aren’t shown here.

os/ipengine/mkfile+105−0

This diff is large: its 106 lines aren’t shown here.

os/ipengine/mmu.c+20−0

This diff is large: its 21 lines aren’t shown here.

os/ipengine/tlb.s+21−0

This diff is large: its 22 lines aren’t shown here.

os/js/README+10−0

This diff is large: its 11 lines aren’t shown here.

os/js/audio.h+9−0

This diff is large: its 10 lines aren’t shown here.

os/js/clock.c+104−0

This diff is large: its 105 lines aren’t shown here.

os/js/cs4231.h+20−0

This diff is large: its 21 lines aren’t shown here.

os/js/dat.h+163−0

This diff is large: its 164 lines aren’t shown here.

os/js/devcs4231.c+1186−0

This diff is large: its 1187 lines aren’t shown here.

os/js/devrtc.c+413−0

This diff is large: its 414 lines aren’t shown here.

os/js/fns.h+110−0

This diff is large: its 111 lines aren’t shown here.

os/js/fsv.c+198−0

This diff is large: its 199 lines aren’t shown here.

os/js/io.h+224−0

This diff is large: its 225 lines aren’t shown here.

os/js/iob.c+13−0

This diff is large: its 14 lines aren’t shown here.

os/js/js+104−0

This diff is large: its 105 lines aren’t shown here.

os/js/kbd.c+482−0

This diff is large: its 483 lines aren’t shown here.

os/js/l.s+560−0

This diff is large: its 561 lines aren’t shown here.

os/js/main.c+564−0

This diff is large: its 565 lines aren’t shown here.

os/js/mem.h+149−0

This diff is large: its 150 lines aren’t shown here.

os/js/mkfile+77−0

This diff is large: its 78 lines aren’t shown here.

os/js/mmu.c+252−0

This diff is large: its 253 lines aren’t shown here.

os/js/ns16552.h+81−0

This diff is large: its 82 lines aren’t shown here.

os/js/rom.c+103−0

This diff is large: its 104 lines aren’t shown here.

os/js/rom.h+57−0

This diff is large: its 58 lines aren’t shown here.

os/js/screen.c+483−0

This diff is large: its 484 lines aren’t shown here.

os/js/screen.h+49−0

This diff is large: its 50 lines aren’t shown here.

os/js/softcursor.h+13−0

This diff is large: its 14 lines aren’t shown here.

os/js/superio.c+216−0

This diff is large: its 217 lines aren’t shown here.

os/js/trap.c+472−0

This diff is large: its 473 lines aren’t shown here.

os/js/ureg.h+45−0

This diff is large: its 46 lines aren’t shown here.

os/ks32/Mk+7−0

This diff is large: its 8 lines aren’t shown here.

os/ks32/NOTICE+2−0

This diff is large: its 3 lines aren’t shown here.

os/ks32/archevaluator7t.c+161−0

This diff is large: its 162 lines aren’t shown here.

os/ks32/armv7.h+19−0

This diff is large: its 20 lines aren’t shown here.

os/ks32/clock.c+287−0

This diff is large: its 288 lines aren’t shown here.

os/ks32/dat.h+218−0

This diff is large: its 219 lines aren’t shown here.

os/ks32/devuart.c+719−0

This diff is large: its 720 lines aren’t shown here.

os/ks32/download.ps+1040−0

This diff is large: its 1041 lines aren’t shown here.

os/ks32/evaluator7t+110−0

This diff is large: its 111 lines aren’t shown here.

os/ks32/fns.h+145−0

This diff is large: its 146 lines aren’t shown here.

os/ks32/fpi.h+61−0

This diff is large: its 62 lines aren’t shown here.

os/ks32/fpiarm.c+483−0

This diff is large: its 484 lines aren’t shown here.

os/ks32/io.h+168−0

This diff is large: its 169 lines aren’t shown here.

os/ks32/l.s+205−0

This diff is large: its 206 lines aren’t shown here.

os/ks32/main.c+289−0

This diff is large: its 290 lines aren’t shown here.

os/ks32/mem.h+54−0

This diff is large: its 55 lines aren’t shown here.

os/ks32/mkfile+115−0

This diff is large: its 116 lines aren’t shown here.

os/ks32/not.c+3−0

This diff is large: its 4 lines aren’t shown here.

os/ks32/squirt+2−0

This diff is large: its 3 lines aren’t shown here.

os/ks32/trap.c+525−0

This diff is large: its 526 lines aren’t shown here.

os/manga/Mk+8−0

This diff is large: its 9 lines aren’t shown here.

os/manga/archmanga.c+164−0

This diff is large: its 165 lines aren’t shown here.

os/manga/clock.c+166−0

This diff is large: its 167 lines aren’t shown here.

os/manga/dat.h+128−0

This diff is large: its 129 lines aren’t shown here.

os/manga/devether.c+765−0

This diff is large: its 766 lines aren’t shown here.

os/manga/devusb.c+931−0

This diff is large: its 932 lines aren’t shown here.

os/manga/eswnotes+41−0

This diff is large: its 42 lines aren’t shown here.

os/manga/ether8139.c+744−0

This diff is large: its 745 lines aren’t shown here.

os/manga/etherif.h+44−0

This diff is large: its 45 lines aren’t shown here.

os/manga/etherks8695.c+1169−0

This diff is large: its 1170 lines aren’t shown here.

os/manga/flashif.h+82−0

This diff is large: its 83 lines aren’t shown here.

os/manga/fns.h+163−0

This diff is large: its 164 lines aren’t shown here.

os/manga/fpi.h+61−0

This diff is large: its 62 lines aren’t shown here.

os/manga/fpiarm.c+483−0

This diff is large: its 484 lines aren’t shown here.

os/manga/gpio.c+75−0

This diff is large: its 76 lines aren’t shown here.

os/manga/inb.c+85−0

This diff is large: its 86 lines aren’t shown here.

os/manga/io.h+320−0

This diff is large: its 321 lines aren’t shown here.

os/manga/ioring.c+72−0

This diff is large: its 73 lines aren’t shown here.

os/manga/l.s+404−0

This diff is large: its 405 lines aren’t shown here.

os/manga/main.c+317−0

This diff is large: its 318 lines aren’t shown here.

os/manga/manga+137−0

This diff is large: its 138 lines aren’t shown here.

os/manga/mem.h+133−0

This diff is large: its 134 lines aren’t shown here.

os/manga/mkfile+89−0

This diff is large: its 90 lines aren’t shown here.

os/manga/mmu.c+244−0

This diff is large: its 245 lines aren’t shown here.

os/manga/pci.c+1007−0

This diff is large: its 1008 lines aren’t shown here.

os/manga/pinflate+0−0

Binary file not shown.

os/manga/trap.c+498−0

This diff is large: its 499 lines aren’t shown here.

os/manga/uartks8695.c+629−0

This diff is large: its 630 lines aren’t shown here.

os/manga/usb.h+160−0

This diff is large: its 161 lines aren’t shown here.

os/manga/usbuhci.c+1556−0

This diff is large: its 1557 lines aren’t shown here.

os/mpc/800io.h+666−0

This diff is large: its 667 lines aren’t shown here.

os/mpc/NOTICE+3−0

This diff is large: its 4 lines aren’t shown here.

os/mpc/clock.c+145−0

This diff is large: its 146 lines aren’t shown here.

os/mpc/cpm.c+695−0

This diff is large: its 696 lines aren’t shown here.

os/mpc/cpmtimer.c+179−0

This diff is large: its 180 lines aren’t shown here.

os/mpc/devata.c+1194−0

This diff is large: its 1195 lines aren’t shown here.

os/mpc/devbench.c+243−0

This diff is large: its 244 lines aren’t shown here.

os/mpc/devboot.c+132−0

This diff is large: its 133 lines aren’t shown here.

os/mpc/devether.c+617−0

This diff is large: its 618 lines aren’t shown here.

os/mpc/devpcmcia.c+1076−0

This diff is large: its 1077 lines aren’t shown here.

os/mpc/devrtc.c+258−0

This diff is large: its 259 lines aren’t shown here.

os/mpc/devtouch.c+497−0

This diff is large: its 498 lines aren’t shown here.

os/mpc/devuart.c+1450−0

This diff is large: its 1451 lines aren’t shown here.

os/mpc/dsp.c+289−0

This diff is large: its 290 lines aren’t shown here.

os/mpc/dsp.h+62−0

This diff is large: its 63 lines aren’t shown here.

os/mpc/etherif.h+37−0

This diff is large: its 38 lines aren’t shown here.

os/mpc/etherscc.c+528−0

This diff is large: its 529 lines aren’t shown here.

os/mpc/faultpower.c+49−0

This diff is large: its 50 lines aren’t shown here.

os/mpc/fp.s+205−0

This diff is large: its 206 lines aren’t shown here.

os/mpc/fpi.h+61−0

This diff is large: its 62 lines aren’t shown here.

os/mpc/fpipower.c+970−0

This diff is large: its 971 lines aren’t shown here.

os/mpc/i2c.c+439−0

This diff is large: its 440 lines aren’t shown here.

os/mpc/i2c_spi.srx+149−0

This diff is large: its 150 lines aren’t shown here.

os/mpc/inb.s+120−0

This diff is large: its 121 lines aren’t shown here.

os/mpc/kbd.c+20−0

This diff is large: its 21 lines aren’t shown here.

os/mpc/l.s+685−0

This diff is large: its 686 lines aren’t shown here.

os/mpc/nofp.s+31−0

This diff is large: its 32 lines aren’t shown here.

os/mpc/pcmcia.h+19−0

This diff is large: its 20 lines aren’t shown here.

os/mpc/pit.c+68−0

This diff is large: its 69 lines aren’t shown here.

os/mpc/powerbreak.c+123−0

This diff is large: its 124 lines aren’t shown here.

os/mpc/rmap.c+106−0

This diff is large: its 107 lines aren’t shown here.

os/mpc/screen.c+832−0

This diff is large: its 833 lines aren’t shown here.

os/mpc/screen.h+60−0

This diff is large: its 61 lines aren’t shown here.

os/mpc/spi.c+243−0

This diff is large: its 244 lines aren’t shown here.

os/mpc/trap.c+554−0

This diff is large: its 555 lines aren’t shown here.

os/mpc/usb.h+62−0

This diff is large: its 63 lines aren’t shown here.

os/omap/README+4−0

This diff is large: its 5 lines aren’t shown here.

os/pc/NOTICE+8−0

This diff is large: its 9 lines aren’t shown here.

os/pc/README+9−0

This diff is large: its 10 lines aren’t shown here.

os/pc/apbootstrap.h+15−0

This diff is large: its 16 lines aren’t shown here.

os/pc/apbootstrap.s+110−0

This diff is large: its 111 lines aren’t shown here.

os/pc/apic.c+378−0

This diff is large: its 379 lines aren’t shown here.

os/pc/apm.c+151−0

This diff is large: its 152 lines aren’t shown here.

os/pc/apmjump.s+98−0

This diff is large: its 99 lines aren’t shown here.

os/pc/archmp.c+138−0

This diff is large: its 139 lines aren’t shown here.

os/pc/audio.h+15−0

This diff is large: its 16 lines aren’t shown here.

os/pc/cga.c+127−0

This diff is large: its 128 lines aren’t shown here.

os/pc/cgamemscr.c+203−0

This diff is large: its 204 lines aren’t shown here.

os/pc/crystal.h+1118−0

This diff is large: its 1119 lines aren’t shown here.

os/pc/dat.h+258−0

This diff is large: its 259 lines aren’t shown here.

os/pc/devarch.c+940−0

This diff is large: its 941 lines aren’t shown here.

os/pc/devds1620.c+368−0

This diff is large: its 369 lines aren’t shown here.

os/pc/devether.c+539−0

This diff is large: its 540 lines aren’t shown here.

os/pc/devfloppy.c+1082−0

This diff is large: its 1083 lines aren’t shown here.

os/pc/devi82365.c+1044−0

This diff is large: its 1045 lines aren’t shown here.

os/pc/devlm78.c+346−0

This diff is large: its 347 lines aren’t shown here.

os/pc/devlpt.c+245−0

This diff is large: its 246 lines aren’t shown here.

os/pc/devmouse.c+672−0

This diff is large: its 673 lines aren’t shown here.

os/pc/devmpeg.c+1063−0

This diff is large: its 1064 lines aren’t shown here.

os/pc/devpccard.c+1949−0

This diff is large: its 1950 lines aren’t shown here.

os/pc/devpnp.c+652−0

This diff is large: its 653 lines aren’t shown here.

os/pc/devrtc.c+461−0

This diff is large: its 462 lines aren’t shown here.

os/pc/devtv.c+1826−0

This diff is large: its 1827 lines aren’t shown here.

os/pc/devusb.c+951−0

This diff is large: its 952 lines aren’t shown here.

os/pc/devvga.c+620−0

This diff is large: its 621 lines aren’t shown here.

os/pc/devzt5512.c+308−0

This diff is large: its 309 lines aren’t shown here.

os/pc/dma.c+237−0

This diff is large: its 238 lines aren’t shown here.

os/pc/ether2000.c+230−0

This diff is large: its 231 lines aren’t shown here.

os/pc/ether2114x.c+1828−0

This diff is large: its 1829 lines aren’t shown here.

os/pc/ether589.c+214−0

This diff is large: its 215 lines aren’t shown here.

os/pc/ether79c960.c+523−0

This diff is large: its 524 lines aren’t shown here.

os/pc/ether79c970.c+640−0

This diff is large: its 641 lines aren’t shown here.

os/pc/ether8003.c+271−0

This diff is large: its 272 lines aren’t shown here.

os/pc/ether8139.c+755−0

This diff is large: its 756 lines aren’t shown here.

os/pc/ether82543gc.c+1367−0

This diff is large: its 1368 lines aren’t shown here.

os/pc/ether82557.c+1325−0

This diff is large: its 1326 lines aren’t shown here.

os/pc/ether83815.c+994−0

This diff is large: its 995 lines aren’t shown here.

os/pc/ether8390.c+812−0

This diff is large: its 813 lines aren’t shown here.

os/pc/ether8390.h+74−0

This diff is large: its 75 lines aren’t shown here.

os/pc/etherec2t.c+173−0

This diff is large: its 174 lines aren’t shown here.

os/pc/etherelnk3.c+2132−0

This diff is large: its 2133 lines aren’t shown here.

os/pc/etherga620.c+1224−0

This diff is large: its 1225 lines aren’t shown here.

os/pc/etherga620fw.h+4858−0

This diff is large: its 4859 lines aren’t shown here.

os/pc/etherif.h+39−0

This diff is large: its 40 lines aren’t shown here.

os/pc/etherigbe.c+1968−0

This diff is large: its 1969 lines aren’t shown here.

os/pc/etherrhine.c+734−0

This diff is large: its 735 lines aren’t shown here.

os/pc/ethersmc.c+780−0

This diff is large: its 781 lines aren’t shown here.

os/pc/etherwavelan.c+196−0

This diff is large: its 197 lines aren’t shown here.

os/pc/flashif.h+82−0

This diff is large: its 83 lines aren’t shown here.

os/pc/flashzpc.c+371−0

This diff is large: its 372 lines aren’t shown here.

os/pc/floppy.h+183−0

This diff is large: its 184 lines aren’t shown here.

os/pc/fns.h+162−0

This diff is large: its 163 lines aren’t shown here.

os/pc/fpi.h+61−0

This diff is large: its 62 lines aren’t shown here.

os/pc/fpi387.c+743−0

This diff is large: its 744 lines aren’t shown here.

os/pc/fpsave.s+9−0

This diff is large: its 10 lines aren’t shown here.

os/pc/i8250.c+328−0

This diff is large: its 329 lines aren’t shown here.

os/pc/i8253.c+314−0

This diff is large: its 315 lines aren’t shown here.

os/pc/i8259.c+199−0

This diff is large: its 200 lines aren’t shown here.

os/pc/io.h+323−0

This diff is large: its 324 lines aren’t shown here.

os/pc/kbd.c+477−0

This diff is large: its 478 lines aren’t shown here.

os/pc/l.s+953−0

This diff is large: its 954 lines aren’t shown here.

os/pc/main.c+457−0

This diff is large: its 458 lines aren’t shown here.

os/pc/mem.h+144−0

This diff is large: its 145 lines aren’t shown here.

os/pc/memory.c+570−0

This diff is large: its 571 lines aren’t shown here.

os/pc/mkfile+83−0

This diff is large: its 84 lines aren’t shown here.

os/pc/mmu.c+321−0

This diff is large: its 322 lines aren’t shown here.

os/pc/mouse.c+84−0

This diff is large: its 85 lines aren’t shown here.

os/pc/mp.c+815−0

This diff is large: its 816 lines aren’t shown here.

os/pc/mp.h+225−0

This diff is large: its 226 lines aren’t shown here.

os/pc/pc+139−0

This diff is large: its 140 lines aren’t shown here.

os/pc/pc4e+145−0

This diff is large: its 146 lines aren’t shown here.

os/pc/pcdisk+154−0

This diff is large: its 155 lines aren’t shown here.

os/pc/pci.acid+252−0

This diff is large: its 253 lines aren’t shown here.

os/pc/pci.c+1341−0

This diff is large: its 1342 lines aren’t shown here.

os/pc/pcidb.acid+2848−0

This diff is large: its 2849 lines aren’t shown here.

os/pc/pcmciamodem.c+75−0

This diff is large: its 76 lines aren’t shown here.

os/pc/piix4smbus.c+213−0

This diff is large: its 214 lines aren’t shown here.

os/pc/pix+153−0

This diff is large: its 154 lines aren’t shown here.

os/pc/ps2mouse.c+84−0

This diff is large: its 85 lines aren’t shown here.

os/pc/ptclbsum386.s+126−0

This diff is large: its 127 lines aren’t shown here.

os/pc/screen.c+410−0

This diff is large: its 411 lines aren’t shown here.

os/pc/screen.h+173−0

This diff is large: its 174 lines aren’t shown here.

os/pc/sd53c8xx.c+2138−0

This diff is large: its 2139 lines aren’t shown here.

os/pc/sd53c8xx.i+773−0

This diff is large: its 774 lines aren’t shown here.

os/pc/sd53c8xx.n+448−0

This diff is large: its 449 lines aren’t shown here.

os/pc/sdata.c+2206−0

This diff is large: its 2207 lines aren’t shown here.

os/pc/sdmylex.c+1249−0

This diff is large: its 1250 lines aren’t shown here.

os/pc/sdscsi.c+394−0

This diff is large: its 395 lines aren’t shown here.

os/pc/trap.c+571−0

This diff is large: its 572 lines aren’t shown here.

os/pc/tv.h+15−0

This diff is large: its 16 lines aren’t shown here.

os/pc/uarti8250.c+740−0

This diff is large: its 741 lines aren’t shown here.

os/pc/uartisa.c+98−0

This diff is large: its 99 lines aren’t shown here.

os/pc/uartpci.c+137−0

This diff is large: its 138 lines aren’t shown here.

os/pc/usb.h+160−0

This diff is large: its 161 lines aren’t shown here.

os/pc/usbuhci.c+1538−0

This diff is large: its 1539 lines aren’t shown here.

os/pc/vga.c+241−0

This diff is large: its 242 lines aren’t shown here.

os/pc/vga.h+75−0

This diff is large: its 76 lines aren’t shown here.

os/pc/vga3dfx.c+258−0

This diff is large: its 259 lines aren’t shown here.

os/pc/vgaark2000pv.c+190−0

This diff is large: its 191 lines aren’t shown here.

os/pc/vgabt485.c+245−0

This diff is large: its 246 lines aren’t shown here.

os/pc/vgaclgd542x.c+291−0

This diff is large: its 292 lines aren’t shown here.

os/pc/vgaclgd546x.c+277−0

This diff is large: its 278 lines aren’t shown here.

os/pc/vgact65545.c+149−0

This diff is large: its 150 lines aren’t shown here.

os/pc/vgacyber938x.c+225−0

This diff is large: its 226 lines aren’t shown here.

os/pc/vgaet4000.c+270−0

This diff is large: its 271 lines aren’t shown here.

os/pc/vgahiqvideo.c+274−0

This diff is large: its 275 lines aren’t shown here.

os/pc/vgai81x.c+282−0

This diff is large: its 283 lines aren’t shown here.

os/pc/vgamach64xx.c+1250−0

This diff is large: its 1251 lines aren’t shown here.

os/pc/vgamga2164w.c+289−0

This diff is large: its 290 lines aren’t shown here.

os/pc/vgamga4xx.c+603−0

This diff is large: its 604 lines aren’t shown here.

os/pc/vganeomagic.c+541−0

This diff is large: its 542 lines aren’t shown here.

os/pc/vganvidia.c+373−0

This diff is large: its 374 lines aren’t shown here.

os/pc/vgargb524.c+236−0

This diff is large: its 237 lines aren’t shown here.

os/pc/vgas3.c+620−0

This diff is large: its 621 lines aren’t shown here.

os/pc/vgasavage.c+571−0

This diff is large: its 572 lines aren’t shown here.

os/pc/vgat2r4.c+586−0

This diff is large: its 587 lines aren’t shown here.

os/pc/vgatvp3020.c+216−0

This diff is large: its 217 lines aren’t shown here.

os/pc/vgatvp3026.c+189−0

This diff is large: its 190 lines aren’t shown here.

os/pc/vgavmware.c+386−0

This diff is large: its 387 lines aren’t shown here.

os/pc/vgax.c+102−0

This diff is large: its 103 lines aren’t shown here.

os/pc/wavelan.c+1268−0

This diff is large: its 1269 lines aren’t shown here.

os/pc/wavelan.h+327−0

This diff is large: its 328 lines aren’t shown here.

os/pc/x86break.c+138−0

This diff is large: its 139 lines aren’t shown here.

os/pc/zoran.h+907−0

This diff is large: its 908 lines aren’t shown here.

os/port/NOTICE+18−0

This diff is large: its 19 lines aren’t shown here.

os/port/alarm.c+41−0

This diff is large: its 42 lines aren’t shown here.

os/port/alloc.c+963−0

This diff is large: its 964 lines aren’t shown here.

os/port/allocb.c+159−0

This diff is large: its 160 lines aren’t shown here.

os/port/chan.c+1431−0

This diff is large: its 1432 lines aren’t shown here.

os/port/cis.c+539−0

This diff is large: its 540 lines aren’t shown here.

os/port/dev.c+434−0

This diff is large: its 435 lines aren’t shown here.

os/port/devXXX.c+147−0

This diff is large: its 148 lines aren’t shown here.

os/port/devaudio.c+947−0

This diff is large: its 948 lines aren’t shown here.

os/port/devbench.c+1165−0

This diff is large: its 1166 lines aren’t shown here.

os/port/devboot.c+150−0

This diff is large: its 151 lines aren’t shown here.

os/port/devbridge.c+1206−0

This diff is large: its 1207 lines aren’t shown here.

os/port/devcap.c+248−0

This diff is large: its 249 lines aren’t shown here.

os/port/devcons.c+1274−0

This diff is large: its 1275 lines aren’t shown here.

os/port/devdbg.c+1000−0

This diff is large: its 1001 lines aren’t shown here.

os/port/devdraw.c+2088−0

This diff is large: its 2089 lines aren’t shown here.

os/port/devds.c+605−0

This diff is large: its 606 lines aren’t shown here.

os/port/devdup.c+151−0

This diff is large: its 152 lines aren’t shown here.

os/port/devdynld.c+365−0

This diff is large: its 366 lines aren’t shown here.

os/port/devenv.c+338−0

This diff is large: its 339 lines aren’t shown here.

os/port/devflash.c+641−0

This diff is large: its 642 lines aren’t shown here.

os/port/devftl.c+1365−0

This diff is large: its 1366 lines aren’t shown here.

os/port/devi2c.c+227−0

This diff is large: its 228 lines aren’t shown here.

os/port/devindir.c+40−0

This diff is large: its 41 lines aren’t shown here.

os/port/devkprof.c+230−0

This diff is large: its 231 lines aren’t shown here.

os/port/devlogfs.c+1531−0

This diff is large: its 1532 lines aren’t shown here.

os/port/devloopback.c+743−0

This diff is large: its 744 lines aren’t shown here.

os/port/devmnt.c+1204−0

This diff is large: its 1205 lines aren’t shown here.

os/port/devns16552.c+1090−0

This diff is large: its 1091 lines aren’t shown here.

os/port/devpci.c+227−0

This diff is large: its 228 lines aren’t shown here.

os/port/devpipe.c+464−0

This diff is large: its 465 lines aren’t shown here.

os/port/devpointer.c+279−0

This diff is large: its 280 lines aren’t shown here.

os/port/devprof.c+722−0

This diff is large: its 723 lines aren’t shown here.

os/port/devprog.c+1510−0

This diff is large: its 1511 lines aren’t shown here.

os/port/devroot.c+153−0

This diff is large: its 154 lines aren’t shown here.

os/port/devsd.c+1474−0

This diff is large: its 1475 lines aren’t shown here.

os/port/devsign.c+446−0

This diff is large: its 447 lines aren’t shown here.

os/port/devsrv.c+726−0

This diff is large: its 727 lines aren’t shown here.

os/port/devssl.c+1436−0

This diff is large: its 1437 lines aren’t shown here.

os/port/devtest.c+125−0

This diff is large: its 126 lines aren’t shown here.

os/port/devtinyfs.c+915−0

This diff is large: its 916 lines aren’t shown here.

os/port/devtk.c+180−0

This diff is large: its 181 lines aren’t shown here.

os/port/devuart.c+748−0

This diff is large: its 749 lines aren’t shown here.

os/port/dial.c+417−0

This diff is large: its 418 lines aren’t shown here.

os/port/dis.c+1125−0

This diff is large: its 1126 lines aren’t shown here.

os/port/discall.c+185−0

This diff is large: its 186 lines aren’t shown here.

os/port/dynld.c+75−0

This diff is large: its 76 lines aren’t shown here.

os/port/edf.c+626−0

This diff is large: its 627 lines aren’t shown here.

os/port/edf.h+53−0

This diff is large: its 54 lines aren’t shown here.

os/port/error.h+64−0

This diff is large: its 65 lines aren’t shown here.

os/port/ethermii.c+238−0

This diff is large: its 239 lines aren’t shown here.

os/port/ethermii.h+116−0

This diff is large: its 117 lines aren’t shown here.

os/port/ethersink.c+65−0

This diff is large: its 66 lines aren’t shown here.

os/port/exception.c+216−0

This diff is large: its 217 lines aren’t shown here.

os/port/exportfs.c+1325−0

This diff is large: its 1326 lines aren’t shown here.

os/port/flashamd29f0x0.c+167−0

This diff is large: its 168 lines aren’t shown here.

os/port/flashcfi16.c+134−0

This diff is large: its 135 lines aren’t shown here.

os/port/flashcfi8.c+143−0

This diff is large: its 144 lines aren’t shown here.

os/port/flashif.h+147−0

This diff is large: its 148 lines aren’t shown here.

os/port/flashintel+179−0

This diff is large: its 180 lines aren’t shown here.

os/port/flashnand.c+337−0

This diff is large: its 338 lines aren’t shown here.

os/port/fpi.c+304−0

This diff is large: its 305 lines aren’t shown here.

os/port/fpimem.c+136−0

This diff is large: its 137 lines aren’t shown here.

os/port/inferno.c+1030−0

This diff is large: its 1031 lines aren’t shown here.

os/port/latin1.c+76−0

This diff is large: its 77 lines aren’t shown here.

os/port/latin1.h+100−0

This diff is large: its 101 lines aren’t shown here.

os/port/lib.h+211−0

This diff is large: its 212 lines aren’t shown here.

os/port/log.c+186−0

This diff is large: its 187 lines aren’t shown here.

os/port/master+89−0

This diff is large: its 90 lines aren’t shown here.

os/port/master.local+10−0

This diff is large: its 11 lines aren’t shown here.

os/port/mkdevc+216−0

This diff is large: its 217 lines aren’t shown here.

os/port/mkdevlist+86−0

This diff is large: its 87 lines aren’t shown here.

os/port/mkroot+119−0

This diff is large: its 120 lines aren’t shown here.

os/port/mul64fract.c+39−0

This diff is large: its 40 lines aren’t shown here.

os/port/netaux.c+67−0

This diff is large: its 68 lines aren’t shown here.

os/port/netif.c+671−0

This diff is large: its 672 lines aren’t shown here.

os/port/netif.h+134−0

This diff is large: its 135 lines aren’t shown here.

os/port/nocache.c+49−0

This diff is large: its 50 lines aren’t shown here.

os/port/nodynld.c+48−0

This diff is large: its 49 lines aren’t shown here.

os/port/noenv.c+33−0

This diff is large: its 34 lines aren’t shown here.

os/port/noscreen.c+9−0

This diff is large: its 10 lines aren’t shown here.

os/port/parse.c+114−0

This diff is large: its 115 lines aren’t shown here.

os/port/pgrp.c+278−0

This diff is large: its 279 lines aren’t shown here.

os/port/portbreak.c+161−0

This diff is large: its 162 lines aren’t shown here.

os/port/portclock.c+277−0

This diff is large: its 278 lines aren’t shown here.

os/port/portdat.h+673−0

This diff is large: its 674 lines aren’t shown here.

os/port/portfns.h+319−0

This diff is large: its 320 lines aren’t shown here.

os/port/portmkfile+152−0

This diff is large: its 153 lines aren’t shown here.

os/port/print.c+31−0

This diff is large: its 32 lines aren’t shown here.

os/port/proc.c+788−0

This diff is large: its 789 lines aren’t shown here.

os/port/qio.c+1529−0

This diff is large: its 1530 lines aren’t shown here.

os/port/qlock.c+111−0

This diff is large: its 112 lines aren’t shown here.

os/port/random.c+156−0

This diff is large: its 157 lines aren’t shown here.

os/port/rdb.c+112−0

This diff is large: its 113 lines aren’t shown here.

os/port/sd.h+132−0

This diff is large: its 133 lines aren’t shown here.

os/port/swcursor.c+358−0

This diff is large: its 359 lines aren’t shown here.

os/port/sysfile.c+1125−0

This diff is large: its 1126 lines aren’t shown here.

os/port/taslock.c+126−0

This diff is large: its 127 lines aren’t shown here.

os/port/tod.c+283−0

This diff is large: its 284 lines aren’t shown here.

os/port/uart.h+104−0

This diff is large: its 105 lines aren’t shown here.

os/port/xalloc.c+246−0

This diff is large: its 247 lines aren’t shown here.

os/pxa/NOTICE+2−0

This diff is large: its 3 lines aren’t shown here.

os/pxa/clock.c+318−0

This diff is large: its 319 lines aren’t shown here.

os/pxa/devether.c+617−0

This diff is large: its 618 lines aren’t shown here.

os/pxa/devrtc.c+169−0

This diff is large: its 170 lines aren’t shown here.

os/pxa/devuart.c+1070−0

This diff is large: its 1071 lines aren’t shown here.

os/pxa/dma.c+244−0

This diff is large: its 245 lines aren’t shown here.

os/pxa/etherif.h+41−0

This diff is large: its 42 lines aren’t shown here.

os/pxa/fpi.h+61−0

This diff is large: its 62 lines aren’t shown here.

os/pxa/fpiarm.c+483−0

This diff is large: its 484 lines aren’t shown here.

os/pxa/gpio.c+88−0

This diff is large: its 89 lines aren’t shown here.

os/pxa/i2c.c+561−0

This diff is large: its 562 lines aren’t shown here.

os/pxa/l.s+548−0

This diff is large: its 549 lines aren’t shown here.

os/pxa/mmu.c+252−0

This diff is large: its 253 lines aren’t shown here.

os/pxa/pxaio.h+383−0

This diff is large: its 384 lines aren’t shown here.

os/pxa/sa1110break.c+360−0

This diff is large: its 361 lines aren’t shown here.

os/pxa/trap.c+587−0

This diff is large: its 588 lines aren’t shown here.

os/rpcg/NOTICE+4−0

This diff is large: its 5 lines aren’t shown here.

os/rpcg/archrpcg.c+428−0

This diff is large: its 429 lines aren’t shown here.

os/rpcg/archrpcg.h+48−0

This diff is large: its 49 lines aren’t shown here.

os/rpcg/clock.c+145−0

This diff is large: its 146 lines aren’t shown here.

os/rpcg/dat.h+162−0

This diff is large: its 163 lines aren’t shown here.

os/rpcg/fns.h+119−0

This diff is large: its 120 lines aren’t shown here.

os/rpcg/io.h+1−0

This diff is large: its 2 lines aren’t shown here.

os/rpcg/main.c+392−0

This diff is large: its 393 lines aren’t shown here.

os/rpcg/mem.h+157−0

This diff is large: its 158 lines aren’t shown here.

os/rpcg/mkfile+108−0

This diff is large: its 109 lines aren’t shown here.

os/rpcg/mmu.c+20−0

This diff is large: its 21 lines aren’t shown here.

os/rpcg/rpcg+122−0

This diff is large: its 123 lines aren’t shown here.

os/rpcg/tlb.s+24−0

This diff is large: its 25 lines aren’t shown here.

os/sa1110/clock.c+317−0

This diff is large: its 318 lines aren’t shown here.

os/sa1110/devether.c+617−0

This diff is large: its 618 lines aren’t shown here.

os/sa1110/devgpio.c+165−0

This diff is large: its 166 lines aren’t shown here.

os/sa1110/devpcmcia.c+761−0

This diff is large: its 762 lines aren’t shown here.

os/sa1110/devpower.c+377−0

This diff is large: its 378 lines aren’t shown here.

os/sa1110/devrtc.c+169−0

This diff is large: its 170 lines aren’t shown here.

os/sa1110/devuart.c+781−0

This diff is large: its 782 lines aren’t shown here.

os/sa1110/dma.c+233−0

This diff is large: its 234 lines aren’t shown here.

os/sa1110/etherif.h+41−0

This diff is large: its 42 lines aren’t shown here.

os/sa1110/fpi.h+61−0

This diff is large: its 62 lines aren’t shown here.

os/sa1110/fpiarm.c+483−0

This diff is large: its 484 lines aren’t shown here.

os/sa1110/gscreen.c+587−0

This diff is large: its 588 lines aren’t shown here.

os/sa1110/gscreen.h+87−0

This diff is large: its 88 lines aren’t shown here.

os/sa1110/i2c.h+16−0

This diff is large: its 17 lines aren’t shown here.

os/sa1110/i2cgpio.c+274−0

This diff is large: its 275 lines aren’t shown here.

os/sa1110/l.s+530−0

This diff is large: its 531 lines aren’t shown here.

os/sa1110/l3gpio.c+246−0

This diff is large: its 247 lines aren’t shown here.

os/sa1110/mmu.c+140−0

This diff is large: its 141 lines aren’t shown here.

os/sa1110/sa1110break.c+360−0

This diff is large: its 361 lines aren’t shown here.

os/sa1110/sa1110io.h+500−0

This diff is large: its 501 lines aren’t shown here.

os/sa1110/softcursor.c+365−0

This diff is large: its 366 lines aren’t shown here.

os/sa1110/suspend.c+161−0

This diff is large: its 162 lines aren’t shown here.

os/sa1110/trap.c+601−0

This diff is large: its 602 lines aren’t shown here.

utils/0a/a.h+183−0

This diff is large: its 184 lines aren’t shown here.

utils/0a/a.y+588−0

This diff is large: its 589 lines aren’t shown here.

utils/0a/l.s+703−0

This diff is large: its 704 lines aren’t shown here.

utils/0a/lex.c+697−0

This diff is large: its 698 lines aren’t shown here.

utils/0a/mkfile+30−0

This diff is large: its 31 lines aren’t shown here.

utils/0c/cgen.c+1148−0

This diff is large: its 1149 lines aren’t shown here.

utils/0c/enam.c+118−0

This diff is large: its 119 lines aren’t shown here.

utils/0c/gc.h+332−0

This diff is large: its 333 lines aren’t shown here.

utils/0c/list.c+244−0

This diff is large: its 245 lines aren’t shown here.

utils/0c/mkenam+15−0

This diff is large: its 16 lines aren’t shown here.

utils/0c/mkfile+30−0

This diff is large: its 31 lines aren’t shown here.

utils/0c/mul.c+608−0

This diff is large: its 609 lines aren’t shown here.

utils/0c/peep.c+694−0

This diff is large: its 695 lines aren’t shown here.

utils/0c/reg.c+1151−0

This diff is large: its 1152 lines aren’t shown here.

utils/0c/sgen.c+569−0

This diff is large: its 570 lines aren’t shown here.

utils/0c/swt.c+727−0

This diff is large: its 728 lines aren’t shown here.

utils/0c/txt.c+1483−0

This diff is large: its 1484 lines aren’t shown here.

utils/0c/v.out.h+201−0

This diff is large: its 202 lines aren’t shown here.

utils/0l/Nt.c+77−0

This diff is large: its 78 lines aren’t shown here.

utils/0l/Plan9.c+57−0

This diff is large: its 58 lines aren’t shown here.

utils/0l/Posix.c+80−0

This diff is large: its 81 lines aren’t shown here.

utils/0l/asm.c+1433−0

This diff is large: its 1434 lines aren’t shown here.

utils/0l/enam.c+122−0

This diff is large: its 123 lines aren’t shown here.

utils/0l/l.h+329−0

This diff is large: its 330 lines aren’t shown here.

utils/0l/list.c+277−0

This diff is large: its 278 lines aren’t shown here.

utils/0l/mkfile+30−0

This diff is large: its 31 lines aren’t shown here.

utils/0l/noop.c+420−0

This diff is large: its 421 lines aren’t shown here.

utils/0l/obj.c+1384−0

This diff is large: its 1385 lines aren’t shown here.

utils/0l/optab.c+221−0

This diff is large: its 222 lines aren’t shown here.

utils/0l/pass.c+498−0

This diff is large: its 499 lines aren’t shown here.

utils/0l/sched.c+709−0

This diff is large: its 710 lines aren’t shown here.

utils/0l/span.c+628−0

This diff is large: its 629 lines aren’t shown here.

utils/1a/a.h+198−0

This diff is large: its 199 lines aren’t shown here.

utils/1a/a.y+402−0

This diff is large: its 403 lines aren’t shown here.

utils/1a/l.s+479−0

This diff is large: its 480 lines aren’t shown here.

utils/1a/lex.c+925−0

This diff is large: its 926 lines aren’t shown here.

utils/1a/mkfile+30−0

This diff is large: its 31 lines aren’t shown here.

utils/1c/cgen.c+1396−0

This diff is large: its 1397 lines aren’t shown here.

utils/1c/enam.c+425−0

This diff is large: its 426 lines aren’t shown here.

utils/1c/gc.h+339−0

This diff is large: its 340 lines aren’t shown here.

utils/1c/list.c+319−0

This diff is large: its 320 lines aren’t shown here.

utils/1c/mkfile+29−0

This diff is large: its 30 lines aren’t shown here.

utils/1c/mul.c+174−0

This diff is large: its 175 lines aren’t shown here.

utils/1c/peep.c+1060−0

This diff is large: its 1061 lines aren’t shown here.

utils/1c/reg.c+1221−0

This diff is large: its 1222 lines aren’t shown here.

utils/1c/sgen.c+694−0

This diff is large: its 695 lines aren’t shown here.

utils/1c/swt.c+964−0

This diff is large: its 965 lines aren’t shown here.

utils/1c/txt.c+903−0

This diff is large: its 904 lines aren’t shown here.

utils/1l/Nt.c+77−0

This diff is large: its 78 lines aren’t shown here.

utils/1l/Plan9.c+57−0

This diff is large: its 58 lines aren’t shown here.

utils/1l/Posix.c+80−0

This diff is large: its 81 lines aren’t shown here.

utils/1l/asm.c+1534−0

This diff is large: its 1535 lines aren’t shown here.

utils/1l/l.h+268−0

This diff is large: its 269 lines aren’t shown here.

utils/1l/list.c+334−0

This diff is large: its 335 lines aren’t shown here.

utils/1l/mkfile+32−0

This diff is large: its 33 lines aren’t shown here.

utils/1l/obj.c+1380−0

This diff is large: its 1381 lines aren’t shown here.

utils/1l/optab.c+444−0

This diff is large: its 445 lines aren’t shown here.

utils/1l/pass.c+673−0

This diff is large: its 674 lines aren’t shown here.

utils/1l/span.c+515−0

This diff is large: its 516 lines aren’t shown here.

utils/2a/a.h+200−0

This diff is large: its 201 lines aren’t shown here.

utils/2a/a.y+540−0

This diff is large: its 541 lines aren’t shown here.

utils/2a/l.s+479−0

This diff is large: its 480 lines aren’t shown here.

utils/2a/lex.c+935−0

This diff is large: its 936 lines aren’t shown here.

utils/2a/mkfile+30−0

This diff is large: its 31 lines aren’t shown here.

utils/2c/2.out.h+523−0

This diff is large: its 524 lines aren’t shown here.

utils/2c/Update+7−0

This diff is large: its 8 lines aren’t shown here.

utils/2c/cgen.c+1404−0

This diff is large: its 1405 lines aren’t shown here.

utils/2c/enam.c+425−0

This diff is large: its 426 lines aren’t shown here.

utils/2c/gc.h+357−0

This diff is large: its 358 lines aren’t shown here.

utils/2c/list.c+384−0

This diff is large: its 385 lines aren’t shown here.

utils/2c/mkfile+30−0

This diff is large: its 31 lines aren’t shown here.

utils/2c/mul.c+174−0

This diff is large: its 175 lines aren’t shown here.

utils/2c/peep.c+1076−0

This diff is large: its 1077 lines aren’t shown here.

utils/2c/reg.c+1275−0

This diff is large: its 1276 lines aren’t shown here.

utils/2c/sgen.c+819−0

This diff is large: its 820 lines aren’t shown here.

utils/2c/swt.c+1046−0

This diff is large: its 1047 lines aren’t shown here.

utils/2c/txt.c+940−0

This diff is large: its 941 lines aren’t shown here.

utils/2l/Nt.c+77−0

This diff is large: its 78 lines aren’t shown here.

utils/2l/Plan9.c+57−0

This diff is large: its 58 lines aren’t shown here.

utils/2l/Posix.c+80−0

This diff is large: its 81 lines aren’t shown here.

utils/2l/asm.c+1569−0

This diff is large: its 1570 lines aren’t shown here.

utils/2l/l.h+263−0

This diff is large: its 264 lines aren’t shown here.

utils/2l/list.c+395−0

This diff is large: its 396 lines aren’t shown here.

utils/2l/mkfile+26−0

This diff is large: its 27 lines aren’t shown here.

utils/2l/obj.c+1402−0

This diff is large: its 1403 lines aren’t shown here.

utils/2l/optab.c+444−0

This diff is large: its 445 lines aren’t shown here.

utils/2l/pass.c+538−0

This diff is large: its 539 lines aren’t shown here.

utils/2l/span.c+551−0

This diff is large: its 552 lines aren’t shown here.

utils/5a/a.h+182−0

This diff is large: its 183 lines aren’t shown here.

utils/5a/a.y+673−0

This diff is large: its 674 lines aren’t shown here.

utils/5a/lex.c+689−0

This diff is large: its 690 lines aren’t shown here.

utils/5a/mkfile+30−0

This diff is large: its 31 lines aren’t shown here.

utils/5c/5.out.h+197−0

This diff is large: its 198 lines aren’t shown here.

utils/5c/cgen.c+1156−0

This diff is large: its 1157 lines aren’t shown here.

utils/5c/enam.c+98−0

This diff is large: its 99 lines aren’t shown here.

utils/5c/gc.h+349−0

This diff is large: its 350 lines aren’t shown here.

utils/5c/list.c+304−0

This diff is large: its 305 lines aren’t shown here.

utils/5c/mkenam+15−0

This diff is large: its 16 lines aren’t shown here.

utils/5c/mkfile+30−0

This diff is large: its 31 lines aren’t shown here.

utils/5c/mul.c+609−0

This diff is large: its 610 lines aren’t shown here.

utils/5c/peep.c+1440−0

This diff is large: its 1441 lines aren’t shown here.

utils/5c/reg.c+1157−0

This diff is large: its 1158 lines aren’t shown here.

utils/5c/sgen.c+613−0

This diff is large: its 614 lines aren’t shown here.

utils/5c/swt.c+757−0

This diff is large: its 758 lines aren’t shown here.

utils/5c/txt.c+1249−0

This diff is large: its 1250 lines aren’t shown here.

utils/5coff/5coff.c+316−0

This diff is large: its 317 lines aren’t shown here.

utils/5coff/NOTICE+27−0

This diff is large: its 28 lines aren’t shown here.

utils/5coff/auxi.c+251−0

This diff is large: its 252 lines aren’t shown here.

utils/5coff/auxi.h+46−0

This diff is large: its 47 lines aren’t shown here.

utils/5coff/coff.c+642−0

This diff is large: its 643 lines aren’t shown here.

utils/5coff/mkfile+23−0

This diff is large: its 24 lines aren’t shown here.

utils/5coff/readcoff.c+298−0

This diff is large: its 299 lines aren’t shown here.

utils/5cv/5cv.c+353−0

This diff is large: its 354 lines aren’t shown here.

utils/5cv/mkfile+18−0

This diff is large: its 19 lines aren’t shown here.

utils/5l/Nt.c+77−0

This diff is large: its 78 lines aren’t shown here.

utils/5l/Plan9.c+57−0

This diff is large: its 58 lines aren’t shown here.

utils/5l/Posix.c+80−0

This diff is large: its 81 lines aren’t shown here.

utils/5l/asm.c+1793−0

This diff is large: its 1794 lines aren’t shown here.

utils/5l/l.h+444−0

This diff is large: its 445 lines aren’t shown here.

utils/5l/list.c+360−0

This diff is large: its 361 lines aren’t shown here.

utils/5l/mkfile+32−0

This diff is large: its 33 lines aren’t shown here.

utils/5l/noop.c+894−0

This diff is large: its 895 lines aren’t shown here.

utils/5l/obj.c+1557−0

This diff is large: its 1558 lines aren’t shown here.

utils/5l/optab.c+253−0

This diff is large: its 254 lines aren’t shown here.

utils/5l/pass.c+942−0

This diff is large: its 943 lines aren’t shown here.

utils/5l/span.c+1262−0

This diff is large: its 1263 lines aren’t shown here.

utils/5l/thumb.c+1637−0

This diff is large: its 1638 lines aren’t shown here.

utils/6c/6.out.h+820−0

This diff is large: its 821 lines aren’t shown here.

utils/8a/a.h+194−0

This diff is large: its 195 lines aren’t shown here.

utils/8a/a.y+520−0

This diff is large: its 521 lines aren’t shown here.

utils/8a/l.s+704−0

This diff is large: its 705 lines aren’t shown here.

utils/8a/lex.c+895−0

This diff is large: its 896 lines aren’t shown here.

utils/8a/mkfile+30−0

This diff is large: its 31 lines aren’t shown here.

utils/8c/8.out.h+445−0

This diff is large: its 446 lines aren’t shown here.

utils/8c/cgen.c+1821−0

This diff is large: its 1822 lines aren’t shown here.

utils/8c/cgen64.c+2711−0

This diff is large: its 2712 lines aren’t shown here.

utils/8c/div.c+206−0

This diff is large: its 207 lines aren’t shown here.

utils/8c/enam.c+337−0

This diff is large: its 338 lines aren’t shown here.

utils/8c/gc.h+374−0

This diff is large: its 375 lines aren’t shown here.

utils/8c/list.c+282−0

This diff is large: its 283 lines aren’t shown here.

utils/8c/machcap.c+86−0

This diff is large: its 87 lines aren’t shown here.

utils/8c/mkenam+15−0

This diff is large: its 16 lines aren’t shown here.

utils/8c/mkfile+35−0

This diff is large: its 36 lines aren’t shown here.

utils/8c/mul.c+428−0

This diff is large: its 429 lines aren’t shown here.

utils/8c/peep.c+757−0

This diff is large: its 758 lines aren’t shown here.

utils/8c/reg.c+1255−0

This diff is large: its 1256 lines aren’t shown here.

utils/8c/sgen.c+842−0

This diff is large: its 843 lines aren’t shown here.

utils/8c/swt.c+647−0

This diff is large: its 648 lines aren’t shown here.

utils/8c/txt.c+1410−0

This diff is large: its 1411 lines aren’t shown here.

utils/8l/Nt.c+77−0

This diff is large: its 78 lines aren’t shown here.

utils/8l/Plan9.c+57−0

This diff is large: its 58 lines aren’t shown here.

utils/8l/Posix.c+80−0

This diff is large: its 81 lines aren’t shown here.

utils/8l/asm.c+502−0

This diff is large: its 503 lines aren’t shown here.

utils/8l/l.h+349−0

This diff is large: its 350 lines aren’t shown here.

utils/8l/list.c+292−0

This diff is large: its 293 lines aren’t shown here.

utils/8l/mkfile+29−0

This diff is large: its 30 lines aren’t shown here.

utils/8l/obj.c+1492−0

This diff is large: its 1493 lines aren’t shown here.

utils/8l/optab.c+654−0

This diff is large: its 655 lines aren’t shown here.

utils/8l/pass.c+763−0

This diff is large: its 764 lines aren’t shown here.

utils/8l/span.c+1387−0

This diff is large: its 1388 lines aren’t shown here.

utils/NOTICE+34−0

This diff is large: its 35 lines aren’t shown here.

utils/acid/386+146−0

This diff is large: its 147 lines aren’t shown here.

utils/acid/B.sh+7−0

This diff is large: its 8 lines aren’t shown here.

utils/acid/acid.h+317−0

This diff is large: its 318 lines aren’t shown here.

utils/acid/arm+1−0

This diff is large: its 2 lines aren’t shown here.

utils/acid/builtin.c+1285−0

This diff is large: its 1286 lines aren’t shown here.

utils/acid/dbg.y+402−0

This diff is large: its 403 lines aren’t shown here.

utils/acid/dot.c+152−0

This diff is large: its 153 lines aren’t shown here.

This diff is larger than a page shows: the files after these aren’t listed. Clone the repository to see all of it.