sh_serial.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  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. #include <assert.h>
  31. //#define DEBUG_SERIAL
  32. #define SH_SERIAL_FLAG_TEND (1 << 0)
  33. #define SH_SERIAL_FLAG_TDE (1 << 1)
  34. #define SH_SERIAL_FLAG_RDF (1 << 2)
  35. #define SH_SERIAL_FLAG_BRK (1 << 3)
  36. #define SH_SERIAL_FLAG_DR (1 << 4)
  37. #define SH_RX_FIFO_LENGTH (16)
  38. typedef struct {
  39. uint8_t smr;
  40. uint8_t brr;
  41. uint8_t scr;
  42. uint8_t dr; /* ftdr / tdr */
  43. uint8_t sr; /* fsr / ssr */
  44. uint16_t fcr;
  45. uint8_t sptr;
  46. uint8_t rx_fifo[SH_RX_FIFO_LENGTH]; /* frdr / rdr */
  47. uint8_t rx_cnt;
  48. uint8_t rx_tail;
  49. uint8_t rx_head;
  50. int freq;
  51. int feat;
  52. int flags;
  53. int rtrg;
  54. CharDriverState *chr;
  55. qemu_irq eri;
  56. qemu_irq rxi;
  57. qemu_irq txi;
  58. qemu_irq tei;
  59. qemu_irq bri;
  60. } sh_serial_state;
  61. static void sh_serial_clear_fifo(sh_serial_state * s)
  62. {
  63. memset(s->rx_fifo, 0, SH_RX_FIFO_LENGTH);
  64. s->rx_cnt = 0;
  65. s->rx_head = 0;
  66. s->rx_tail = 0;
  67. }
  68. static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
  69. {
  70. sh_serial_state *s = opaque;
  71. unsigned char ch;
  72. #ifdef DEBUG_SERIAL
  73. printf("sh_serial: write offs=0x%02x val=0x%02x\n",
  74. offs, val);
  75. #endif
  76. switch(offs) {
  77. case 0x00: /* SMR */
  78. s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff);
  79. return;
  80. case 0x04: /* BRR */
  81. s->brr = val;
  82. return;
  83. case 0x08: /* SCR */
  84. /* TODO : For SH7751, SCIF mask should be 0xfb. */
  85. s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff);
  86. if (!(val & (1 << 5)))
  87. s->flags |= SH_SERIAL_FLAG_TEND;
  88. if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) {
  89. qemu_set_irq(s->txi, val & (1 << 7));
  90. }
  91. if (!(val & (1 << 6))) {
  92. qemu_set_irq(s->rxi, 0);
  93. }
  94. return;
  95. case 0x0c: /* FTDR / TDR */
  96. if (s->chr) {
  97. ch = val;
  98. qemu_chr_write(s->chr, &ch, 1);
  99. }
  100. s->dr = val;
  101. s->flags &= ~SH_SERIAL_FLAG_TDE;
  102. return;
  103. #if 0
  104. case 0x14: /* FRDR / RDR */
  105. ret = 0;
  106. break;
  107. #endif
  108. }
  109. if (s->feat & SH_SERIAL_FEAT_SCIF) {
  110. switch(offs) {
  111. case 0x10: /* FSR */
  112. if (!(val & (1 << 6)))
  113. s->flags &= ~SH_SERIAL_FLAG_TEND;
  114. if (!(val & (1 << 5)))
  115. s->flags &= ~SH_SERIAL_FLAG_TDE;
  116. if (!(val & (1 << 4)))
  117. s->flags &= ~SH_SERIAL_FLAG_BRK;
  118. if (!(val & (1 << 1)))
  119. s->flags &= ~SH_SERIAL_FLAG_RDF;
  120. if (!(val & (1 << 0)))
  121. s->flags &= ~SH_SERIAL_FLAG_DR;
  122. if (!(val & (1 << 1)) || !(val & (1 << 0))) {
  123. if (s->rxi) {
  124. qemu_set_irq(s->rxi, 0);
  125. }
  126. }
  127. return;
  128. case 0x18: /* FCR */
  129. s->fcr = val;
  130. switch ((val >> 6) & 3) {
  131. case 0:
  132. s->rtrg = 1;
  133. break;
  134. case 1:
  135. s->rtrg = 4;
  136. break;
  137. case 2:
  138. s->rtrg = 8;
  139. break;
  140. case 3:
  141. s->rtrg = 14;
  142. break;
  143. }
  144. if (val & (1 << 1)) {
  145. sh_serial_clear_fifo(s);
  146. s->sr &= ~(1 << 1);
  147. }
  148. return;
  149. case 0x20: /* SPTR */
  150. s->sptr = val & 0xf3;
  151. return;
  152. case 0x24: /* LSR */
  153. return;
  154. }
  155. }
  156. else {
  157. switch(offs) {
  158. #if 0
  159. case 0x0c:
  160. ret = s->dr;
  161. break;
  162. case 0x10:
  163. ret = 0;
  164. break;
  165. #endif
  166. case 0x1c:
  167. s->sptr = val & 0x8f;
  168. return;
  169. }
  170. }
  171. fprintf(stderr, "sh_serial: unsupported write to 0x%02x\n", offs);
  172. assert(0);
  173. }
  174. static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs)
  175. {
  176. sh_serial_state *s = opaque;
  177. uint32_t ret = ~0;
  178. #if 0
  179. switch(offs) {
  180. case 0x00:
  181. ret = s->smr;
  182. break;
  183. case 0x04:
  184. ret = s->brr;
  185. break;
  186. case 0x08:
  187. ret = s->scr;
  188. break;
  189. case 0x14:
  190. ret = 0;
  191. break;
  192. }
  193. #endif
  194. if (s->feat & SH_SERIAL_FEAT_SCIF) {
  195. switch(offs) {
  196. case 0x00: /* SMR */
  197. ret = s->smr;
  198. break;
  199. case 0x08: /* SCR */
  200. ret = s->scr;
  201. break;
  202. case 0x10: /* FSR */
  203. ret = 0;
  204. if (s->flags & SH_SERIAL_FLAG_TEND)
  205. ret |= (1 << 6);
  206. if (s->flags & SH_SERIAL_FLAG_TDE)
  207. ret |= (1 << 5);
  208. if (s->flags & SH_SERIAL_FLAG_BRK)
  209. ret |= (1 << 4);
  210. if (s->flags & SH_SERIAL_FLAG_RDF)
  211. ret |= (1 << 1);
  212. if (s->flags & SH_SERIAL_FLAG_DR)
  213. ret |= (1 << 0);
  214. if (s->scr & (1 << 5))
  215. s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
  216. break;
  217. case 0x14:
  218. if (s->rx_cnt > 0) {
  219. ret = s->rx_fifo[s->rx_tail++];
  220. s->rx_cnt--;
  221. if (s->rx_tail == SH_RX_FIFO_LENGTH)
  222. s->rx_tail = 0;
  223. if (s->rx_cnt < s->rtrg)
  224. s->flags &= ~SH_SERIAL_FLAG_RDF;
  225. }
  226. break;
  227. #if 0
  228. case 0x18:
  229. ret = s->fcr;
  230. break;
  231. #endif
  232. case 0x1c:
  233. ret = s->rx_cnt;
  234. break;
  235. case 0x20:
  236. ret = s->sptr;
  237. break;
  238. case 0x24:
  239. ret = 0;
  240. break;
  241. }
  242. }
  243. else {
  244. switch(offs) {
  245. #if 0
  246. case 0x0c:
  247. ret = s->dr;
  248. break;
  249. case 0x10:
  250. ret = 0;
  251. break;
  252. case 0x14:
  253. ret = s->rx_fifo[0];
  254. break;
  255. #endif
  256. case 0x1c:
  257. ret = s->sptr;
  258. break;
  259. }
  260. }
  261. #ifdef DEBUG_SERIAL
  262. printf("sh_serial: read offs=0x%02x val=0x%x\n",
  263. offs, ret);
  264. #endif
  265. if (ret & ~((1 << 16) - 1)) {
  266. fprintf(stderr, "sh_serial: unsupported read from 0x%02x\n", offs);
  267. assert(0);
  268. }
  269. return ret;
  270. }
  271. static int sh_serial_can_receive(sh_serial_state *s)
  272. {
  273. return s->scr & (1 << 4);
  274. }
  275. static void sh_serial_receive_byte(sh_serial_state *s, int ch)
  276. {
  277. if (s->feat & SH_SERIAL_FEAT_SCIF) {
  278. if (s->rx_cnt < SH_RX_FIFO_LENGTH) {
  279. s->rx_fifo[s->rx_head++] = ch;
  280. if (s->rx_head == SH_RX_FIFO_LENGTH)
  281. s->rx_head = 0;
  282. s->rx_cnt++;
  283. if (s->rx_cnt >= s->rtrg) {
  284. s->flags |= SH_SERIAL_FLAG_RDF;
  285. if (s->scr & (1 << 6) && s->rxi) {
  286. qemu_set_irq(s->rxi, 1);
  287. }
  288. }
  289. }
  290. } else {
  291. s->rx_fifo[0] = ch;
  292. }
  293. }
  294. static void sh_serial_receive_break(sh_serial_state *s)
  295. {
  296. if (s->feat & SH_SERIAL_FEAT_SCIF)
  297. s->sr |= (1 << 4);
  298. }
  299. static int sh_serial_can_receive1(void *opaque)
  300. {
  301. sh_serial_state *s = opaque;
  302. return sh_serial_can_receive(s);
  303. }
  304. static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
  305. {
  306. sh_serial_state *s = opaque;
  307. sh_serial_receive_byte(s, buf[0]);
  308. }
  309. static void sh_serial_event(void *opaque, int event)
  310. {
  311. sh_serial_state *s = opaque;
  312. if (event == CHR_EVENT_BREAK)
  313. sh_serial_receive_break(s);
  314. }
  315. static uint32_t sh_serial_read (void *opaque, target_phys_addr_t addr)
  316. {
  317. sh_serial_state *s = opaque;
  318. return sh_serial_ioport_read(s, addr);
  319. }
  320. static void sh_serial_write (void *opaque,
  321. target_phys_addr_t addr, uint32_t value)
  322. {
  323. sh_serial_state *s = opaque;
  324. sh_serial_ioport_write(s, addr, value);
  325. }
  326. static CPUReadMemoryFunc *sh_serial_readfn[] = {
  327. &sh_serial_read,
  328. &sh_serial_read,
  329. &sh_serial_read,
  330. };
  331. static CPUWriteMemoryFunc *sh_serial_writefn[] = {
  332. &sh_serial_write,
  333. &sh_serial_write,
  334. &sh_serial_write,
  335. };
  336. void sh_serial_init (target_phys_addr_t base, int feat,
  337. uint32_t freq, CharDriverState *chr,
  338. qemu_irq eri_source,
  339. qemu_irq rxi_source,
  340. qemu_irq txi_source,
  341. qemu_irq tei_source,
  342. qemu_irq bri_source)
  343. {
  344. sh_serial_state *s;
  345. int s_io_memory;
  346. s = qemu_mallocz(sizeof(sh_serial_state));
  347. s->feat = feat;
  348. s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
  349. s->rtrg = 1;
  350. s->smr = 0;
  351. s->brr = 0xff;
  352. s->scr = 1 << 5; /* pretend that TX is enabled so early printk works */
  353. s->sptr = 0;
  354. if (feat & SH_SERIAL_FEAT_SCIF) {
  355. s->fcr = 0;
  356. }
  357. else {
  358. s->dr = 0xff;
  359. }
  360. sh_serial_clear_fifo(s);
  361. s_io_memory = cpu_register_io_memory(0, sh_serial_readfn,
  362. sh_serial_writefn, s);
  363. cpu_register_physical_memory(P4ADDR(base), 0x28, s_io_memory);
  364. cpu_register_physical_memory(A7ADDR(base), 0x28, s_io_memory);
  365. s->chr = chr;
  366. if (chr)
  367. qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
  368. sh_serial_event, s);
  369. s->eri = eri_source;
  370. s->rxi = rxi_source;
  371. s->txi = txi_source;
  372. s->tei = tei_source;
  373. s->bri = bri_source;
  374. }