gelic_udbg.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * udbg debug output routine via GELIC UDP broadcasts
  3. *
  4. * Copyright (C) 2007 Sony Computer Entertainment Inc.
  5. * Copyright 2006, 2007 Sony Corporation
  6. * Copyright (C) 2010 Hector Martin <hector@marcansoft.com>
  7. * Copyright (C) 2011 Andre Heider <a.heider@gmail.com>
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or (at your option) any later version.
  13. *
  14. */
  15. #include <asm/io.h>
  16. #include <asm/udbg.h>
  17. #include <asm/lv1call.h>
  18. #define GELIC_BUS_ID 1
  19. #define GELIC_DEVICE_ID 0
  20. #define GELIC_DEBUG_PORT 18194
  21. #define GELIC_MAX_MESSAGE_SIZE 1000
  22. #define GELIC_LV1_GET_MAC_ADDRESS 1
  23. #define GELIC_LV1_GET_VLAN_ID 4
  24. #define GELIC_LV1_VLAN_TX_ETHERNET_0 2
  25. #define GELIC_DESCR_DMA_STAT_MASK 0xf0000000
  26. #define GELIC_DESCR_DMA_CARDOWNED 0xa0000000
  27. #define GELIC_DESCR_TX_DMA_IKE 0x00080000
  28. #define GELIC_DESCR_TX_DMA_NO_CHKSUM 0x00000000
  29. #define GELIC_DESCR_TX_DMA_FRAME_TAIL 0x00040000
  30. #define GELIC_DESCR_DMA_CMD_NO_CHKSUM (GELIC_DESCR_DMA_CARDOWNED | \
  31. GELIC_DESCR_TX_DMA_IKE | \
  32. GELIC_DESCR_TX_DMA_NO_CHKSUM)
  33. static u64 bus_addr;
  34. struct gelic_descr {
  35. /* as defined by the hardware */
  36. __be32 buf_addr;
  37. __be32 buf_size;
  38. __be32 next_descr_addr;
  39. __be32 dmac_cmd_status;
  40. __be32 result_size;
  41. __be32 valid_size; /* all zeroes for tx */
  42. __be32 data_status;
  43. __be32 data_error; /* all zeroes for tx */
  44. } __attribute__((aligned(32)));
  45. struct debug_block {
  46. struct gelic_descr descr;
  47. u8 pkt[1520];
  48. } __packed;
  49. struct ethhdr {
  50. u8 dest[6];
  51. u8 src[6];
  52. u16 type;
  53. } __packed;
  54. struct vlantag {
  55. u16 vlan;
  56. u16 subtype;
  57. } __packed;
  58. struct iphdr {
  59. u8 ver_len;
  60. u8 dscp_ecn;
  61. u16 total_length;
  62. u16 ident;
  63. u16 frag_off_flags;
  64. u8 ttl;
  65. u8 proto;
  66. u16 checksum;
  67. u32 src;
  68. u32 dest;
  69. } __packed;
  70. struct udphdr {
  71. u16 src;
  72. u16 dest;
  73. u16 len;
  74. u16 checksum;
  75. } __packed;
  76. static __iomem struct ethhdr *h_eth;
  77. static __iomem struct vlantag *h_vlan;
  78. static __iomem struct iphdr *h_ip;
  79. static __iomem struct udphdr *h_udp;
  80. static __iomem char *pmsg;
  81. static __iomem char *pmsgc;
  82. static __iomem struct debug_block dbg __attribute__((aligned(32)));
  83. static int header_size;
  84. static void map_dma_mem(int bus_id, int dev_id, void *start, size_t len,
  85. u64 *real_bus_addr)
  86. {
  87. s64 result;
  88. u64 real_addr = ((u64)start) & 0x0fffffffffffffffUL;
  89. u64 real_end = real_addr + len;
  90. u64 map_start = real_addr & ~0xfff;
  91. u64 map_end = (real_end + 0xfff) & ~0xfff;
  92. u64 bus_addr = 0;
  93. u64 flags = 0xf800000000000000UL;
  94. result = lv1_allocate_device_dma_region(bus_id, dev_id,
  95. map_end - map_start, 12, 0,
  96. &bus_addr);
  97. if (result)
  98. lv1_panic(0);
  99. result = lv1_map_device_dma_region(bus_id, dev_id, map_start,
  100. bus_addr, map_end - map_start,
  101. flags);
  102. if (result)
  103. lv1_panic(0);
  104. *real_bus_addr = bus_addr + real_addr - map_start;
  105. }
  106. static int unmap_dma_mem(int bus_id, int dev_id, u64 bus_addr, size_t len)
  107. {
  108. s64 result;
  109. u64 real_bus_addr;
  110. real_bus_addr = bus_addr & ~0xfff;
  111. len += bus_addr - real_bus_addr;
  112. len = (len + 0xfff) & ~0xfff;
  113. result = lv1_unmap_device_dma_region(bus_id, dev_id, real_bus_addr,
  114. len);
  115. if (result)
  116. return result;
  117. return lv1_free_device_dma_region(bus_id, dev_id, real_bus_addr);
  118. }
  119. static void gelic_debug_init(void)
  120. {
  121. s64 result;
  122. u64 v2;
  123. u64 mac;
  124. u64 vlan_id;
  125. result = lv1_open_device(GELIC_BUS_ID, GELIC_DEVICE_ID, 0);
  126. if (result)
  127. lv1_panic(0);
  128. map_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID, &dbg, sizeof(dbg),
  129. &bus_addr);
  130. memset(&dbg, 0, sizeof(dbg));
  131. dbg.descr.buf_addr = bus_addr + offsetof(struct debug_block, pkt);
  132. wmb();
  133. result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID,
  134. GELIC_LV1_GET_MAC_ADDRESS, 0, 0, 0,
  135. &mac, &v2);
  136. if (result)
  137. lv1_panic(0);
  138. mac <<= 16;
  139. h_eth = (struct ethhdr *)dbg.pkt;
  140. memset(&h_eth->dest, 0xff, 6);
  141. memcpy(&h_eth->src, &mac, 6);
  142. header_size = sizeof(struct ethhdr);
  143. result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID,
  144. GELIC_LV1_GET_VLAN_ID,
  145. GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0,
  146. &vlan_id, &v2);
  147. if (!result) {
  148. h_eth->type = 0x8100;
  149. header_size += sizeof(struct vlantag);
  150. h_vlan = (struct vlantag *)(h_eth + 1);
  151. h_vlan->vlan = vlan_id;
  152. h_vlan->subtype = 0x0800;
  153. h_ip = (struct iphdr *)(h_vlan + 1);
  154. } else {
  155. h_eth->type = 0x0800;
  156. h_ip = (struct iphdr *)(h_eth + 1);
  157. }
  158. header_size += sizeof(struct iphdr);
  159. h_ip->ver_len = 0x45;
  160. h_ip->ttl = 10;
  161. h_ip->proto = 0x11;
  162. h_ip->src = 0x00000000;
  163. h_ip->dest = 0xffffffff;
  164. header_size += sizeof(struct udphdr);
  165. h_udp = (struct udphdr *)(h_ip + 1);
  166. h_udp->src = GELIC_DEBUG_PORT;
  167. h_udp->dest = GELIC_DEBUG_PORT;
  168. pmsgc = pmsg = (char *)(h_udp + 1);
  169. }
  170. static void gelic_debug_shutdown(void)
  171. {
  172. if (bus_addr)
  173. unmap_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID,
  174. bus_addr, sizeof(dbg));
  175. lv1_close_device(GELIC_BUS_ID, GELIC_DEVICE_ID);
  176. }
  177. static void gelic_sendbuf(int msgsize)
  178. {
  179. u16 *p;
  180. u32 sum;
  181. int i;
  182. dbg.descr.buf_size = header_size + msgsize;
  183. h_ip->total_length = msgsize + sizeof(struct udphdr) +
  184. sizeof(struct iphdr);
  185. h_udp->len = msgsize + sizeof(struct udphdr);
  186. h_ip->checksum = 0;
  187. sum = 0;
  188. p = (u16 *)h_ip;
  189. for (i = 0; i < 5; i++)
  190. sum += *p++;
  191. h_ip->checksum = ~(sum + (sum >> 16));
  192. dbg.descr.dmac_cmd_status = GELIC_DESCR_DMA_CMD_NO_CHKSUM |
  193. GELIC_DESCR_TX_DMA_FRAME_TAIL;
  194. dbg.descr.result_size = 0;
  195. dbg.descr.data_status = 0;
  196. wmb();
  197. lv1_net_start_tx_dma(GELIC_BUS_ID, GELIC_DEVICE_ID, bus_addr, 0);
  198. while ((dbg.descr.dmac_cmd_status & GELIC_DESCR_DMA_STAT_MASK) ==
  199. GELIC_DESCR_DMA_CARDOWNED)
  200. cpu_relax();
  201. }
  202. static void ps3gelic_udbg_putc(char ch)
  203. {
  204. *pmsgc++ = ch;
  205. if (ch == '\n' || (pmsgc-pmsg) >= GELIC_MAX_MESSAGE_SIZE) {
  206. gelic_sendbuf(pmsgc-pmsg);
  207. pmsgc = pmsg;
  208. }
  209. }
  210. void __init udbg_init_ps3gelic(void)
  211. {
  212. gelic_debug_init();
  213. udbg_putc = ps3gelic_udbg_putc;
  214. }
  215. void udbg_shutdown_ps3gelic(void)
  216. {
  217. udbg_putc = NULL;
  218. gelic_debug_shutdown();
  219. }
  220. EXPORT_SYMBOL(udbg_shutdown_ps3gelic);