uartsaturn.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "../port/error.h"
  8. #include "msaturn.h"
  9. enum{
  10. UartAoffs = Saturn + 0x0a00,
  11. UartBoffs = Saturn + 0x0b00,
  12. Nuart = 2,
  13. Baudfreq = 14745600 / 16,
  14. Lcr_div = RBIT(1, uchar),
  15. Lcr_peven = RBIT(3, uchar),
  16. Lcr_pen = RBIT(4, uchar),
  17. Lcr_stop = RBIT(5, uchar),
  18. Lcr_wrdlenmask = RBIT(6, uchar) | RBIT(7, uchar),
  19. Lcr_wrdlenshift = 0,
  20. Lsr_tbre = RBIT(2, uchar),
  21. Fcr_txreset = RBIT(5, uchar),
  22. Fcr_rxreset = RBIT(6, uchar),
  23. Iir_txempty = RBIT(5, uchar),
  24. Iir_rxfull = RBIT(6, uchar),
  25. Iir_rxerr = RBIT(7, uchar),
  26. Ier_rxerr = RBIT(5, uchar),
  27. Ier_txempty = RBIT(6, uchar),
  28. Ier_rxfull = RBIT(7, uchar),
  29. Lsr_rxavail = RBIT(7, uchar),
  30. Txsize = 16,
  31. Rxsize = 16,
  32. };
  33. typedef struct Saturnuart Saturnuart;
  34. struct Saturnuart {
  35. uchar rxb;
  36. #define txb rxb
  37. #define dll rxb
  38. uchar ier; // Interrupt enable, divisor latch
  39. #define dlm ier
  40. uchar iir; // Interrupt identification, fifo control
  41. #define fcr iir
  42. uchar lcr; // Line control register
  43. uchar f1;
  44. uchar lsr; // Line status register
  45. ushort f2;
  46. };
  47. typedef struct UartData UartData;
  48. struct UartData {
  49. int suno; /* saturn uart number: 0 or 1 */
  50. Saturnuart *su;
  51. char *rxbuf;
  52. char *txbuf;
  53. int initialized;
  54. int enabled;
  55. } uartdata[Nuart];
  56. extern PhysUart saturnphysuart;
  57. Uart suart[Nuart] = {
  58. {
  59. .name = "SaturnUart1",
  60. .baud = 19200,
  61. .bits = 8,
  62. .stop = 1,
  63. .parity = 'n',
  64. .phys = &saturnphysuart,
  65. .special = 0,
  66. },
  67. {
  68. .name = "SaturnUart2",
  69. .baud = 115200,
  70. .bits = 8,
  71. .stop = 1,
  72. .parity = 'n',
  73. .phys = &saturnphysuart,
  74. .special = 0,
  75. },
  76. };
  77. static void suinterrupt(Ureg*, void*);
  78. static Uart*
  79. supnp(void)
  80. {
  81. int i;
  82. for (i = 0; i < nelem(suart)-1; i++)
  83. suart[i].next = &suart[i + 1];
  84. suart[nelem(suart)-1].next=nil;
  85. return suart;
  86. }
  87. static void
  88. suinit(Uart*uart)
  89. {
  90. UartData *ud;
  91. Saturnuart *su;
  92. ud = uart->regs;
  93. su = ud->su;
  94. su->fcr=Fcr_txreset|Fcr_rxreset;
  95. ud->initialized=1;
  96. }
  97. static void
  98. suenable(Uart*uart, int ie)
  99. {
  100. Saturnuart *su;
  101. UartData *ud;
  102. int nr;
  103. nr = uart - suart;
  104. if (nr < 0 || nr > Nuart)
  105. panic("No uart %d", nr);
  106. ud = uartdata + nr;
  107. ud->suno = nr;
  108. su=ud->su = (Saturnuart*)((nr == 0)? UartAoffs: UartBoffs);
  109. uart->regs = ud;
  110. if(ud->initialized==0)
  111. suinit(uart);
  112. if(!ud->enabled && ie){
  113. intrenable(Vecuart0+nr , suinterrupt, uart, uart->name);
  114. su->ier=Ier_txempty|Ier_rxfull;
  115. ud->enabled=1;
  116. }
  117. }
  118. static long
  119. sustatus(Uart* uart, void* buf, long n, long offset)
  120. {
  121. Saturnuart *su;
  122. char p[128];
  123. su = ((UartData*)uart->regs)->su;
  124. snprint(p, sizeof p, "b%d c%d e%d l%d m0 p%c s%d i1\n"
  125. "dev(%d) type(%d) framing(%d) overruns(%d)\n",
  126. uart->baud,
  127. uart->hup_dcd,
  128. uart->hup_dsr,
  129. Txsize,
  130. (su->lcr & Lcr_pen)? ((su->lcr & Lcr_peven) ? 'e': 'o'): 'n',
  131. (su->lcr & Lcr_stop)? 2: 1,
  132. uart->dev,
  133. uart->type,
  134. uart->ferr,
  135. uart->oerr);
  136. n = readstr(offset, buf, n, p);
  137. free(p);
  138. return n;
  139. }
  140. static void
  141. sufifo(Uart*, int)
  142. {}
  143. static void
  144. sudtr(Uart*, int)
  145. {}
  146. static void
  147. surts(Uart*, int)
  148. {}
  149. static void
  150. sumodemctl(Uart*, int)
  151. {}
  152. static int
  153. suparity(Uart*uart, int parity)
  154. {
  155. int lcr;
  156. Saturnuart *su;
  157. su = ((UartData*)uart->regs)->su;
  158. lcr = su->lcr & ~(Lcr_pen|Lcr_peven);
  159. switch(parity){
  160. case 'e':
  161. lcr |= (Lcr_pen|Lcr_peven);
  162. break;
  163. case 'o':
  164. lcr |= Lcr_pen;
  165. break;
  166. case 'n':
  167. default:
  168. break;
  169. }
  170. su->lcr = lcr;
  171. uart->parity = parity;
  172. return 0;
  173. }
  174. static int
  175. sustop(Uart* uart, int stop)
  176. {
  177. int lcr;
  178. Saturnuart *su;
  179. su = ((UartData*)uart->regs)->su;
  180. lcr = su->lcr & ~Lcr_stop;
  181. switch(stop){
  182. case 1:
  183. break;
  184. case 2:
  185. lcr |= Lcr_stop;
  186. break;
  187. default:
  188. return -1;
  189. }
  190. /* Set new value and reenable if device was previously enabled */
  191. su->lcr = lcr;
  192. uart->stop = stop;
  193. return 0;
  194. }
  195. static int
  196. subits(Uart*uart, int n)
  197. {
  198. Saturnuart *su;
  199. uchar lcr;
  200. su = ((UartData*)uart->regs)->su;
  201. if(n<5||n>8)
  202. return -1;
  203. lcr = su->lcr & ~Lcr_wrdlenmask;
  204. lcr |= (n-5) << Lcr_wrdlenshift;
  205. su->lcr = lcr;
  206. return 0;
  207. }
  208. static int
  209. subaud(Uart* uart, int baud)
  210. {
  211. ushort v;
  212. Saturnuart *su;
  213. if (uart->enabled){
  214. su = ((UartData*)uart->regs)->su;
  215. if(baud <= 0)
  216. return -1;
  217. v = Baudfreq / baud;
  218. su->lcr |= Lcr_div;
  219. su->dll = v;
  220. su->dlm = v >> 8;
  221. su->lcr &= ~Lcr_div;
  222. }
  223. uart->baud = baud;
  224. return 0;
  225. }
  226. static void
  227. subreak(Uart*, int)
  228. {}
  229. static void
  230. sukick(Uart *uart)
  231. {
  232. Saturnuart *su;
  233. int i;
  234. if(uart->blocked)
  235. return;
  236. su = ((UartData*)uart->regs)->su;
  237. if((su->iir & Iir_txempty) == 0)
  238. return;
  239. for(i = 0; i < Txsize; i++){
  240. if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
  241. break;
  242. su->txb = *(uart->op++);
  243. su->ier |= Ier_txempty;
  244. break;
  245. }
  246. }
  247. static void
  248. suputc(Uart *uart, int c)
  249. {
  250. Saturnuart *su;
  251. su = ((UartData*)uart->regs)->su;
  252. while((su->lsr&Lsr_tbre) == 0)
  253. ;
  254. su->txb=c;
  255. while((su->lsr&Lsr_tbre) == 0)
  256. ;
  257. }
  258. static int
  259. getchars(Uart *uart, uchar *cbuf)
  260. {
  261. int nc;
  262. UartData *ud;
  263. Saturnuart *su;
  264. ud = uart->regs;
  265. su = ud->su;
  266. while((su->lsr&Lsr_rxavail) == 0)
  267. ;
  268. *cbuf++ = su->rxb;
  269. nc = 1;
  270. while(su->lsr&Lsr_rxavail){
  271. *cbuf++ = su->rxb;
  272. nc++;
  273. }
  274. return nc;
  275. }
  276. static int
  277. sugetc(Uart *uart)
  278. {
  279. static uchar buf[128], *p;
  280. static int cnt;
  281. char c;
  282. if (cnt <= 0) {
  283. cnt = getchars(uart, buf);
  284. p = buf;
  285. }
  286. c = *p++;
  287. cnt--;
  288. return c;
  289. }
  290. static void
  291. suinterrupt(Ureg*, void*u)
  292. {
  293. Saturnuart *su;
  294. Uart *uart;
  295. uchar iir;
  296. uart = u;
  297. if (uart == nil)
  298. panic("uart is nil");
  299. su = ((UartData*)uart->regs)->su;
  300. iir = su->iir;
  301. if(iir&Iir_rxfull)
  302. while(su->lsr&Lsr_rxavail)
  303. uartrecv(uart, su->rxb);
  304. if(iir & Iir_txempty){
  305. su->ier&=~Ier_txempty;
  306. uartkick(uart);
  307. }
  308. if (iir & Iir_rxerr)
  309. uart->oerr++;
  310. intack();
  311. }
  312. static void
  313. sudisable(Uart* uart)
  314. {
  315. Saturnuart *su;
  316. su = ((UartData*)uart->regs)->su;
  317. su->ier&=~(Ier_txempty|Ier_rxfull);
  318. }
  319. PhysUart saturnphysuart = {
  320. .name = "su",
  321. .pnp = supnp,
  322. .enable = suenable,
  323. .disable = sudisable,
  324. .kick = sukick,
  325. .dobreak = subreak,
  326. .baud = subaud,
  327. .bits = subits,
  328. .stop = sustop,
  329. .parity = suparity,
  330. .modemctl = sumodemctl,
  331. .rts = surts,
  332. .dtr = sudtr,
  333. .status = sustatus,
  334. .fifo = sufifo,
  335. .getc = sugetc,
  336. .putc = suputc,
  337. };
  338. void
  339. console(void)
  340. {
  341. Uart *uart;
  342. int n;
  343. char *cmd, *p;
  344. if((p = getconf("console")) == nil)
  345. return;
  346. n = strtoul(p, &cmd, 0);
  347. if(p == cmd)
  348. return;
  349. if(n < 0 || n >= nelem(suart))
  350. return;
  351. uart = suart + n;
  352. /* uartctl(uart, "b115200 l8 pn s1"); */
  353. if(*cmd != '\0')
  354. uartctl(uart, cmd);
  355. (*uart->phys->enable)(uart, 0);
  356. consuart = uart;
  357. uart->console = 1;
  358. }
  359. Saturnuart*uart = (Saturnuart*)UartAoffs;
  360. void
  361. dbgputc(int c)
  362. {
  363. while((uart->lsr&Lsr_tbre) == 0)
  364. ;
  365. uart->txb=c;
  366. while((uart->lsr&Lsr_tbre) == 0)
  367. ;
  368. }
  369. void
  370. dbgputs(char*s)
  371. {
  372. while(*s)
  373. dbgputc(*s++);
  374. }
  375. void
  376. dbgputx(ulong x)
  377. {
  378. int i;
  379. char c;
  380. for(i=0; i < sizeof(ulong) * 2; i++){
  381. c = ((x >> (28 - i * 4))) & 0xf;
  382. if(c >= 0 && c <= 9)
  383. c += '0';
  384. else
  385. c += 'a' - 10;
  386. while((uart->lsr&Lsr_tbre) == 0)
  387. ;
  388. uart->txb=c;
  389. }
  390. while((uart->lsr&Lsr_tbre) == 0)
  391. ;
  392. uart->txb='\n';
  393. while((uart->lsr&Lsr_tbre) == 0)
  394. ;
  395. }