arch164.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /*
  2. * EB164 and similar
  3. * CPU: 21164
  4. * Core Logic: 21172 CIA or 21174 PYXIS
  5. */
  6. #include "u.h"
  7. #include "../port/lib.h"
  8. #include "mem.h"
  9. #include "dat.h"
  10. #include "fns.h"
  11. #include "io.h"
  12. #include "ureg.h"
  13. static ulong *core;
  14. static ulong *wind;
  15. static ulong windsave[16];
  16. static ulong coresave[1];
  17. ulong iobase0;
  18. ulong iobase1;
  19. #define iobase(p) (iobase0+(p))
  20. static int
  21. ident(void)
  22. {
  23. return 0; /* bug! */
  24. }
  25. static uvlong* sgmap;
  26. static void
  27. sginit(void)
  28. {
  29. ulong pa;
  30. uvlong *pte;
  31. sgmap = xspanalloc(BY2PG, BY2PG, 0);
  32. memset(sgmap, 0, BY2PG);
  33. /*
  34. * Prepare scatter-gather map for 0-8MB.
  35. */
  36. pte = sgmap;
  37. for(pa = 0; pa < 8*1024*1024; pa += BY2PG)
  38. *pte++ = ((pa>>PGSHIFT)<<1)|1;
  39. /*
  40. * Set up a map for ISA DMA accesses to physical memory.
  41. * Addresses presented by an ISA device between ISAWINDOW
  42. * and ISAWINDOW+8MB will be translated to between 0 and
  43. * 0+8MB of physical memory.
  44. */
  45. wind[0x400/4] = ISAWINDOW|2|1; /* window base */
  46. wind[0x440/4] = 0x00700000; /* window mask */
  47. wind[0x480/4] = PADDR(sgmap)>>2; /* <33:10> of sg map */
  48. wind[0x100/4] = 3; /* invalidate tlb cache */
  49. }
  50. static void *
  51. kmapio(ulong space, ulong offset, int size)
  52. {
  53. return kmapv(((uvlong)space<<32LL)|offset, size);
  54. }
  55. static void
  56. coreinit(void)
  57. {
  58. int i;
  59. core = kmapio(0x87, 0x40000000, 0x10000);
  60. wind = kmapio(0x87, 0x60000000, 0x1000);
  61. iobase0 = (ulong)kmapio(0x89, 0, 0x20000);
  62. /* hae_io = core[0x440/4];
  63. iobase1 = (ulong)kmapio(0x89, hae_io, 0x10000); */
  64. /* save critical parts of hardware memory mapping */
  65. for (i = 4; i < 8; i++) {
  66. windsave[4*(i-4)+0] = wind[(i*0x100+0x00)/4];
  67. windsave[4*(i-4)+1] = wind[(i*0x100+0x40)/4];
  68. windsave[4*(i-4)+2] = wind[(i*0x100+0x80)/4];
  69. }
  70. coresave[0] = core[0x140/4];
  71. /* disable windows */
  72. wind[0x400/4] = 0;
  73. wind[0x500/4] = 0;
  74. wind[0x600/4] = 0;
  75. wind[0x700/4] = 0;
  76. sginit();
  77. /*
  78. * Set up a map for PCI DMA accesses to physical memory.
  79. * Addresses presented by a PCI device between PCIWINDOW
  80. * and PCIWINDOW+1GB will be translated to between 0 and
  81. * 0+1GB of physical memory.
  82. */
  83. wind[0x500/4] = PCIWINDOW|1;
  84. wind[0x540/4] = 0x3ff00000;
  85. wind[0x580/4] = 0;
  86. /* clear error state */
  87. core[0x8200/4] = 0x7ff;
  88. /* set config: byte/word enable, no monster window, etc. */
  89. core[0x140/4] = 0x21;
  90. /* turn off mcheck on master abort. now we can probe PCI space. */
  91. core[0x8280/4] &= ~(1<<7);
  92. /* set up interrupts. */
  93. i8259init();
  94. cserve(52, 4); /* enable SIO interrupt */
  95. }
  96. void
  97. ciaerror(void)
  98. {
  99. print("cia error 0x%luX\n", core[0x8200/4]);
  100. }
  101. static void
  102. corehello(void)
  103. {
  104. print("cpu%d: CIA revision %ld; cnfg %lux cntrl %lux\n",
  105. 0, /* BUG */
  106. core[0x80/4] & 0x7f, core[0x140/4], core[0x100/4]);
  107. print("cpu%d: HAE_IO %lux\n", 0, core[0x440/4]);
  108. print("\n");
  109. }
  110. static void
  111. coredetach(void)
  112. {
  113. int i;
  114. for (i = 4; i < 8; i++) {
  115. wind[(i*0x100+0x00)/4] = windsave[4*(i-4)+0];
  116. wind[(i*0x100+0x40)/4] = windsave[4*(i-4)+1];
  117. wind[(i*0x100+0x80)/4] = windsave[4*(i-4)+2];
  118. }
  119. core[0x140/4] = coresave[0];
  120. /* for (i = 0; i < 4; i++)
  121. if (i != 4)
  122. cserve(53, i); /* disable interrupts */
  123. }
  124. static Lock pcicfgl;
  125. static ulong pcimap[256];
  126. static void*
  127. pcicfg2117x(int tbdf, int rno)
  128. {
  129. int space, bus;
  130. ulong base;
  131. bus = BUSBNO(tbdf);
  132. lock(&pcicfgl);
  133. base = pcimap[bus];
  134. if (base == 0) {
  135. if(bus)
  136. space = 0x8B;
  137. else
  138. space = 0x8A;
  139. pcimap[bus] = base = (ulong)kmapio(space, MKBUS(0, bus, 0, 0), (1<<16));
  140. }
  141. unlock(&pcicfgl);
  142. return (void*)(base + BUSDF(tbdf) + rno);
  143. }
  144. static void*
  145. pcimem2117x(int addr, int len)
  146. {
  147. return kmapio(0x88, addr, len);
  148. }
  149. static int
  150. intrenable164(Vctl *v)
  151. {
  152. int vec, irq;
  153. irq = v->irq;
  154. if(irq > MaxIrqPIC) {
  155. print("intrenable: irq %d out of range\n", v->irq);
  156. return -1;
  157. }
  158. if(BUSTYPE(v->tbdf) == BusPCI) {
  159. vec = irq+VectorPCI;
  160. cserve(52, irq);
  161. }
  162. else {
  163. vec = irq+VectorPIC;
  164. if(i8259enable(irq, v->tbdf, v) == -1)
  165. return -1;
  166. }
  167. return vec;
  168. }
  169. /*
  170. * I have a function pointer in PCArch for every one of these, because on
  171. * some Alphas we have to use sparse mode, but on others we can use
  172. * MOVB et al. Additionally, the PC164 documentation threatened us
  173. * with the lie that the SIO is in region B, but everything else in region A.
  174. * This turned out not to be the case. Given the cost of this solution, it
  175. * may be better just to use sparse mode for I/O space on all platforms.
  176. */
  177. int
  178. inb2117x(int port)
  179. {
  180. mb();
  181. return *(uchar*)(iobase(port));
  182. }
  183. ushort
  184. ins2117x(int port)
  185. {
  186. mb();
  187. return *(ushort*)(iobase(port));
  188. }
  189. ulong
  190. inl2117x(int port)
  191. {
  192. mb();
  193. return *(ulong*)(iobase(port));
  194. }
  195. void
  196. outb2117x(int port, int val)
  197. {
  198. mb();
  199. *(uchar*)(iobase(port)) = val;
  200. mb();
  201. }
  202. void
  203. outs2117x(int port, ushort val)
  204. {
  205. mb();
  206. *(ushort*)(iobase(port)) = val;
  207. mb();
  208. }
  209. void
  210. outl2117x(int port, ulong val)
  211. {
  212. mb();
  213. *(ulong*)(iobase(port)) = val;
  214. mb();
  215. }
  216. void
  217. insb2117x(int port, void *buf, int len)
  218. {
  219. int i;
  220. uchar *p, *q;
  221. p = (uchar*)iobase(port);
  222. q = buf;
  223. for(i = 0; i < len; i++){
  224. mb();
  225. *q++ = *p;
  226. }
  227. }
  228. void
  229. inss2117x(int port, void *buf, int len)
  230. {
  231. int i;
  232. ushort *p, *q;
  233. p = (ushort*)iobase(port);
  234. q = buf;
  235. for(i = 0; i < len; i++){
  236. mb();
  237. *q++ = *p;
  238. }
  239. }
  240. void
  241. insl2117x(int port, void *buf, int len)
  242. {
  243. int i;
  244. ulong *p, *q;
  245. p = (ulong*)iobase(port);
  246. q = buf;
  247. for(i = 0; i < len; i++){
  248. mb();
  249. *q++ = *p;
  250. }
  251. }
  252. void
  253. outsb2117x(int port, void *buf, int len)
  254. {
  255. int i;
  256. uchar *p, *q;
  257. p = (uchar*)iobase(port);
  258. q = buf;
  259. for(i = 0; i < len; i++){
  260. mb();
  261. *p = *q++;
  262. }
  263. }
  264. void
  265. outss2117x(int port, void *buf, int len)
  266. {
  267. int i;
  268. ushort *p, *q;
  269. p = (ushort*)iobase(port);
  270. q = buf;
  271. for(i = 0; i < len; i++){
  272. mb();
  273. *p = *q++;
  274. }
  275. }
  276. void
  277. outsl2117x(int port, void *buf, int len)
  278. {
  279. int i;
  280. ulong *p, *q;
  281. p = (ulong*)iobase(port);
  282. q = buf;
  283. for(i = 0; i < len; i++){
  284. mb();
  285. *p = *q++;
  286. }
  287. }
  288. PCArch arch164 = {
  289. "EB164",
  290. ident,
  291. coreinit,
  292. corehello,
  293. coredetach,
  294. pcicfg2117x,
  295. pcimem2117x,
  296. intrenable164,
  297. nil,
  298. nil,
  299. inb2117x,
  300. ins2117x,
  301. inl2117x,
  302. outb2117x,
  303. outs2117x,
  304. outl2117x,
  305. insb2117x,
  306. inss2117x,
  307. insl2117x,
  308. outsb2117x,
  309. outss2117x,
  310. outsl2117x,
  311. };