sh_serial.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /*
  2. * QEMU SCI/SCIF serial port emulation
  3. *
  4. * Copyright (c) 2007 Magnus Damm
  5. *
  6. * Based on serial.c - QEMU 16450 UART emulation
  7. * Copyright (c) 2003-2004 Fabrice Bellard
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. */
  27. #include "hw.h"
  28. #include "sh.h"
  29. #include "qemu-char.h"
  30. //#define DEBUG_SERIAL
  31. #define SH_SERIAL_FLAG_TEND (1 << 0)
  32. #define SH_SERIAL_FLAG_TDE (1 << 1)
  33. #define SH_SERIAL_FLAG_RDF (1 << 2)
  34. #define SH_SERIAL_FLAG_BRK (1 << 3)
  35. #define SH_SERIAL_FLAG_DR (1 << 4)
  36. #define SH_RX_FIFO_LENGTH (16)
  37. typedef struct {
  38. uint8_t smr;
  39. uint8_t brr;
  40. uint8_t scr;
  41. uint8_t dr; /* ftdr / tdr */
  42. uint8_t sr; /* fsr / ssr */
  43. uint16_t fcr;
  44. uint8_t sptr;
  45. uint8_t rx_fifo[SH_RX_FIFO_LENGTH]; /* frdr / rdr */
  46. uint8_t rx_cnt;
  47. uint8_t rx_tail;
  48. uint8_t rx_head;
  49. int freq;
  50. int feat;
  51. int flags;
  52. int rtrg;
  53. CharDriverState *chr;
  54. qemu_irq eri;
  55. qemu_irq rxi;
  56. qemu_irq txi;
  57. qemu_irq tei;
  58. qemu_irq bri;
  59. } sh_serial_state;
  60. static void sh_serial_clear_fifo(sh_serial_state * s)
  61. {
  62. memset(s->rx_fifo, 0, SH_RX_FIFO_LENGTH);
  63. s->rx_cnt = 0;
  64. s->rx_head = 0;
  65. s->rx_tail = 0;
  66. }
  67. static void sh_serial_write(void *opaque, uint32_t offs, uint32_t val)
  68. {
  69. sh_serial_state *s = opaque;
  70. unsigned char ch;
  71. #ifdef DEBUG_SERIAL
  72. printf("sh_serial: write offs=0x%02x val=0x%02x\n",
  73. offs, val);
  74. #endif
  75. switch(offs) {
  76. case 0x00: /* SMR */
  77. s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff);
  78. return;
  79. case 0x04: /* BRR */
  80. s->brr = val;
  81. return;
  82. case 0x08: /* SCR */
  83. /* TODO : For SH7751, SCIF mask should be 0xfb. */
  84. s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff);
  85. if (!(val & (1 << 5)))
  86. s->flags |= SH_SERIAL_FLAG_TEND;
  87. if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) {
  88. qemu_set_irq(s->txi, val & (1 << 7));
  89. }
  90. if (!(val & (1 << 6))) {
  91. qemu_set_irq(s->rxi, 0);
  92. }
  93. return;
  94. case 0x0c: /* FTDR / TDR */
  95. if (s->chr) {
  96. ch = val;
  97. qemu_chr_write(s->chr, &ch, 1);
  98. }
  99. s->dr = val;
  100. s->flags &= ~SH_SERIAL_FLAG_TDE;
  101. return;
  102. #if 0
  103. case 0x14: /* FRDR / RDR */
  104. ret = 0;
  105. break;
  106. #endif
  107. }
  108. if (s->feat & SH_SERIAL_FEAT_SCIF) {
  109. switch(offs) {
  110. case 0x10: /* FSR */
  111. if (!(val & (1 << 6)))
  112. s->flags &= ~SH_SERIAL_FLAG_TEND;
  113. if (!(val & (1 << 5)))
  114. s->flags &= ~SH_SERIAL_FLAG_TDE;
  115. if (!(val & (1 << 4)))
  116. s->flags &= ~SH_SERIAL_FLAG_BRK;
  117. if (!(val & (1 << 1)))
  118. s->flags &= ~SH_SERIAL_FLAG_RDF;
  119. if (!(val & (1 << 0)))
  120. s->flags &= ~SH_SERIAL_FLAG_DR;
  121. if (!(val & (1 << 1)) || !(val & (1 << 0))) {
  122. if (s->rxi) {
  123. qemu_set_irq(s->rxi, 0);
  124. }
  125. }
  126. return;
  127. case 0x18: /* FCR */
  128. s->fcr = val;
  129. switch ((val >> 6) & 3) {
  130. case 0:
  131. s->rtrg = 1;
  132. break;
  133. case 1:
  134. s->rtrg = 4;
  135. break;
  136. case 2:
  137. s->rtrg = 8;
  138. break;
  139. case 3:
  140. s->rtrg = 14;
  141. break;
  142. }
  143. if (val & (1 << 1)) {
  144. sh_serial_clear_fifo(s);
  145. s->sr &= ~(1 << 1);
  146. }
  147. return;
  148. case 0x20: /* SPTR */
  149. s->sptr = val & 0xf3;
  150. return;
  151. case 0x24: /* LSR */
  152. return;
  153. }
  154. }
  155. else {
  156. switch(offs) {
  157. #if 0
  158. case 0x0c:
  159. ret = s->dr;
  160. break;
  161. case 0x10:
  162. ret = 0;
  163. break;
  164. #endif
  165. case 0x1c:
  166. s->sptr = val & 0x8f;
  167. return;
  168. }
  169. }
  170. fprintf(stderr, "sh_serial: unsupported write to 0x%02x\n", offs);
  171. abort();
  172. }
  173. static uint32_t sh_serial_read(void *opaque, uint32_t offs)
  174. {
  175. sh_serial_state *s = opaque;
  176. uint32_t ret = ~0;
  177. #if 0
  178. switch(offs) {
  179. case 0x00:
  180. ret = s->smr;
  181. break;
  182. case 0x04:
  183. ret = s->brr;
  184. break;
  185. case 0x08:
  186. ret = s->scr;
  187. break;
  188. case 0x14:
  189. ret = 0;
  190. break;
  191. }
  192. #endif
  193. if (s->feat & SH_SERIAL_FEAT_SCIF) {
  194. switch(offs) {
  195. case 0x00: /* SMR */
  196. ret = s->smr;
  197. break;
  198. case 0x08: /* SCR */
  199. ret = s->scr;
  200. break;
  201. case 0x10: /* FSR */
  202. ret = 0;
  203. if (s->flags & SH_SERIAL_FLAG_TEND)
  204. ret |= (1 << 6);
  205. if (s->flags & SH_SERIAL_FLAG_TDE)
  206. ret |= (1 << 5);
  207. if (s->flags & SH_SERIAL_FLAG_BRK)
  208. ret |= (1 << 4);
  209. if (s->flags & SH_SERIAL_FLAG_RDF)
  210. ret |= (1 << 1);
  211. if (s->flags & SH_SERIAL_FLAG_DR)
  212. ret |= (1 << 0);
  213. if (s->scr & (1 << 5))
  214. s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
  215. break;
  216. case 0x14:
  217. if (s->rx_cnt > 0) {
  218. ret = s->rx_fifo[s->rx_tail++];
  219. s->rx_cnt--;
  220. if (s->rx_tail == SH_RX_FIFO_LENGTH)
  221. s->rx_tail = 0;
  222. if (s->rx_cnt < s->rtrg)
  223. s->flags &= ~SH_SERIAL_FLAG_RDF;
  224. }
  225. break;
  226. #if 0
  227. case 0x18:
  228. ret = s->fcr;
  229. break;
  230. #endif
  231. case 0x1c:
  232. ret = s->rx_cnt;
  233. break;
  234. case 0x20:
  235. ret = s->sptr;
  236. break;
  237. case 0x24:
  238. ret = 0;
  239. break;
  240. }
  241. }
  242. else {
  243. switch(offs) {
  244. #if 0
  245. case 0x0c:
  246. ret = s->dr;
  247. break;
  248. case 0x10:
  249. ret = 0;
  250. break;
  251. case 0x14:
  252. ret = s->rx_fifo[0];
  253. break;
  254. #endif
  255. case 0x1c:
  256. ret = s->sptr;
  257. break;
  258. }
  259. }
  260. #ifdef DEBUG_SERIAL
  261. printf("sh_serial: read offs=0x%02x val=0x%x\n",
  262. offs, ret);
  263. #endif
  264. if (ret & ~((1 << 16) - 1)) {
  265. fprintf(stderr, "sh_serial: unsupported read from 0x%02x\n", offs);
  266. abort();
  267. }
  268. return ret;
  269. }
  270. static int sh_serial_can_receive(sh_serial_state *s)
  271. {
  272. return s->scr & (1 << 4);
  273. }
  274. static void sh_serial_receive_break(sh_serial_state *s)
  275. {
  276. if (s->feat & SH_SERIAL_FEAT_SCIF)
  277. s->sr |= (1 << 4);
  278. }
  279. static int sh_serial_can_receive1(void *opaque)
  280. {
  281. sh_serial_state *s = opaque;
  282. return sh_serial_can_receive(s);
  283. }
  284. static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
  285. {
  286. sh_serial_state *s = opaque;
  287. if (s->feat & SH_SERIAL_FEAT_SCIF) {
  288. int i;
  289. for (i = 0; i < size; i++) {
  290. if (s->rx_cnt < SH_RX_FIFO_LENGTH) {
  291. s->rx_fifo[s->rx_head++] = buf[i];
  292. if (s->rx_head == SH_RX_FIFO_LENGTH) {
  293. s->rx_head = 0;
  294. }
  295. s->rx_cnt++;
  296. if (s->rx_cnt >= s->rtrg) {
  297. s->flags |= SH_SERIAL_FLAG_RDF;
  298. if (s->scr & (1 << 6) && s->rxi) {
  299. qemu_set_irq(s->rxi, 1);
  300. }
  301. }
  302. }
  303. }
  304. } else {
  305. s->rx_fifo[0] = buf[0];
  306. }
  307. }
  308. static void sh_serial_event(void *opaque, int event)
  309. {
  310. sh_serial_state *s = opaque;
  311. if (event == CHR_EVENT_BREAK)
  312. sh_serial_receive_break(s);
  313. }
  314. static CPUReadMemoryFunc * const sh_serial_readfn[] = {
  315. &sh_serial_read,
  316. &sh_serial_read,
  317. &sh_serial_read,
  318. };
  319. static CPUWriteMemoryFunc * const sh_serial_writefn[] = {
  320. &sh_serial_write,
  321. &sh_serial_write,
  322. &sh_serial_write,
  323. };
  324. void sh_serial_init (target_phys_addr_t base, int feat,
  325. uint32_t freq, CharDriverState *chr,
  326. qemu_irq eri_source,
  327. qemu_irq rxi_source,
  328. qemu_irq txi_source,
  329. qemu_irq tei_source,
  330. qemu_irq bri_source)
  331. {
  332. sh_serial_state *s;
  333. int s_io_memory;
  334. s = qemu_mallocz(sizeof(sh_serial_state));
  335. s->feat = feat;
  336. s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
  337. s->rtrg = 1;
  338. s->smr = 0;
  339. s->brr = 0xff;
  340. s->scr = 1 << 5; /* pretend that TX is enabled so early printk works */
  341. s->sptr = 0;
  342. if (feat & SH_SERIAL_FEAT_SCIF) {
  343. s->fcr = 0;
  344. }
  345. else {
  346. s->dr = 0xff;
  347. }
  348. sh_serial_clear_fifo(s);
  349. s_io_memory = cpu_register_io_memory(sh_serial_readfn,
  350. sh_serial_writefn, s,
  351. DEVICE_NATIVE_ENDIAN);
  352. cpu_register_physical_memory(P4ADDR(base), 0x28, s_io_memory);
  353. cpu_register_physical_memory(A7ADDR(base), 0x28, s_io_memory);
  354. s->chr = chr;
  355. if (chr)
  356. qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
  357. sh_serial_event, s);
  358. s->eri = eri_source;
  359. s->rxi = rxi_source;
  360. s->txi = txi_source;
  361. s->tei = tei_source;
  362. s->bri = bri_source;
  363. }