pcnet.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2016-2018 K. Lange
  5. */
  6. #include <kernel/module.h>
  7. #include <kernel/logging.h>
  8. #include <kernel/printf.h>
  9. #include <kernel/pci.h>
  10. #include <kernel/mem.h>
  11. #include <kernel/pipe.h>
  12. #include <kernel/ipv4.h>
  13. #include <kernel/mod/net.h>
  14. #include <toaru/list.h>
  15. static list_t * net_queue = NULL;
  16. static spin_lock_t net_queue_lock = { 0 };
  17. static list_t * rx_wait;
  18. static uint32_t pcnet_device_pci = 0x00000000;
  19. static uint32_t pcnet_io_base = 0;
  20. static uint32_t pcnet_mem_base = 0;
  21. static int pcnet_irq;
  22. static uint8_t mac[6];
  23. static uint32_t pcnet_buffer_phys;
  24. static uint8_t *pcnet_buffer_virt;
  25. static uint8_t * pcnet_rx_de_start;
  26. static uint8_t * pcnet_tx_de_start;
  27. static uint8_t * pcnet_rx_start;
  28. static uint8_t * pcnet_tx_start;
  29. static uint32_t pcnet_rx_de_phys;
  30. static uint32_t pcnet_tx_de_phys;
  31. static uint32_t pcnet_rx_phys;
  32. static uint32_t pcnet_tx_phys;
  33. static int pcnet_rx_buffer_id = 0;
  34. static int pcnet_tx_buffer_id = 0;
  35. #define PCNET_DE_SIZE 16
  36. #define PCNET_BUFFER_SIZE 1548
  37. #define PCNET_RX_COUNT 32
  38. #define PCNET_TX_COUNT 8
  39. static void find_pcnet(uint32_t device, uint16_t vendorid, uint16_t deviceid, void * extra) {
  40. if ((vendorid == 0x1022) && (deviceid == 0x2000)) {
  41. *((uint32_t *)extra) = device;
  42. }
  43. }
  44. static void write_rap32(uint32_t value) {
  45. outportl(pcnet_io_base + 0x14, value);
  46. }
  47. static void write_rap16(uint16_t value) {
  48. outports(pcnet_io_base + 0x12, value);
  49. }
  50. static uint32_t read_csr32(uint32_t csr_no) {
  51. write_rap32(csr_no);
  52. return inportl(pcnet_io_base + 0x10);
  53. }
  54. static uint16_t read_csr16(uint16_t csr_no) {
  55. write_rap32(csr_no);
  56. return inports(pcnet_io_base + 0x10);
  57. }
  58. static void write_csr32(uint32_t csr_no, uint32_t value) {
  59. write_rap32(csr_no);
  60. outportl(pcnet_io_base + 0x10, value);
  61. }
  62. static void write_csr16(uint32_t csr_no, uint16_t value) {
  63. write_rap16(csr_no);
  64. outports(pcnet_io_base + 0x10, value);
  65. }
  66. static uint32_t read_bcr32(uint32_t bcr_no) {
  67. write_rap32(bcr_no);
  68. return inportl(pcnet_io_base + 0x1c);
  69. }
  70. static void write_bcr32(uint32_t bcr_no, uint32_t value) {
  71. write_rap32(bcr_no);
  72. outportl(pcnet_io_base + 0x1c, value);
  73. }
  74. static uint32_t virt_to_phys(uint8_t * virt) {
  75. return ((uintptr_t)virt - (uintptr_t)pcnet_buffer_virt) + pcnet_buffer_phys;
  76. }
  77. static int driver_owns(uint8_t * de_table, int index) {
  78. return (de_table[PCNET_DE_SIZE * index + 7] & 0x80) == 0;
  79. }
  80. static int next_tx_index(int current_tx_index) {
  81. int out = current_tx_index + 1;
  82. if (out == PCNET_TX_COUNT) {
  83. return 0;
  84. }
  85. return out;
  86. }
  87. static int next_rx_index(int current_rx_index) {
  88. int out = current_rx_index + 1;
  89. if (out == PCNET_RX_COUNT) {
  90. return 0;
  91. }
  92. return out;
  93. }
  94. static void init_descriptor(int index, int is_tx) {
  95. uint8_t * de_table = is_tx ? pcnet_tx_de_start : pcnet_rx_de_start;
  96. memset(&de_table[index * PCNET_DE_SIZE], 0, PCNET_DE_SIZE);
  97. uint32_t buf_addr = is_tx ? pcnet_tx_phys : pcnet_rx_phys;
  98. *(uint32_t *)&de_table[index * PCNET_DE_SIZE] = buf_addr + index * PCNET_BUFFER_SIZE;
  99. uint16_t bcnt = (uint16_t)(-PCNET_BUFFER_SIZE);
  100. bcnt &= 0x0FFF;
  101. bcnt |= 0xF000;
  102. *(uint16_t *)&de_table[index * PCNET_DE_SIZE + 4] = bcnt;
  103. if (!is_tx) {
  104. de_table[index * PCNET_DE_SIZE + 7] = 0x80;
  105. }
  106. }
  107. static void enqueue_packet(void * buffer) {
  108. spin_lock(net_queue_lock);
  109. list_insert(net_queue, buffer);
  110. spin_unlock(net_queue_lock);
  111. }
  112. static struct ethernet_packet * dequeue_packet(void) {
  113. while (!net_queue->length) {
  114. sleep_on(rx_wait);
  115. }
  116. spin_lock(net_queue_lock);
  117. node_t * n = list_dequeue(net_queue);
  118. void* value = n->value;
  119. free(n);
  120. spin_unlock(net_queue_lock);
  121. return value;
  122. }
  123. static uint8_t* pcnet_get_mac() {
  124. return mac;
  125. }
  126. static void pcnet_send_packet(uint8_t* payload, size_t payload_size) {
  127. if (!driver_owns(pcnet_tx_de_start, pcnet_tx_buffer_id)) {
  128. /* sleep? */
  129. debug_print(ERROR, "No transmit descriptors available. Bailing.");
  130. return;
  131. }
  132. if (payload_size > PCNET_BUFFER_SIZE) {
  133. debug_print(ERROR, "Packet too big; max is %d, got %d", PCNET_BUFFER_SIZE, payload_size);
  134. return;
  135. }
  136. memcpy((void *)(pcnet_tx_start + pcnet_tx_buffer_id * PCNET_BUFFER_SIZE), payload, payload_size);
  137. pcnet_tx_de_start[pcnet_tx_buffer_id * PCNET_DE_SIZE + 7] |= 0x3;
  138. uint16_t bcnt = (uint16_t)(-payload_size);
  139. bcnt &= 0x0FFF;
  140. bcnt |= 0xF000;
  141. *(uint16_t *)&pcnet_tx_de_start[pcnet_tx_buffer_id * PCNET_DE_SIZE + 4] = bcnt;
  142. pcnet_tx_de_start[pcnet_tx_buffer_id * PCNET_DE_SIZE + 7] |= 0x80;
  143. write_csr32(0, read_csr32(0) | (1 << 3));
  144. pcnet_tx_buffer_id = next_tx_index(pcnet_tx_buffer_id);
  145. }
  146. static int pcnet_irq_handler(struct regs *r) {
  147. write_csr32(0, read_csr32(0) | 0x0400);
  148. irq_ack(pcnet_irq);
  149. while (driver_owns(pcnet_rx_de_start, pcnet_rx_buffer_id)) {
  150. uint16_t plen = *(uint16_t *)&pcnet_rx_de_start[pcnet_rx_buffer_id * PCNET_DE_SIZE + 8];
  151. void * pbuf = (void *)(pcnet_rx_start + pcnet_rx_buffer_id * PCNET_BUFFER_SIZE);
  152. void * packet = malloc(plen);
  153. memcpy(packet, pbuf, plen);
  154. pcnet_rx_de_start[pcnet_rx_buffer_id * PCNET_DE_SIZE + 7] = 0x80;
  155. enqueue_packet(packet);
  156. pcnet_rx_buffer_id = next_rx_index(pcnet_rx_buffer_id);
  157. }
  158. wakeup_queue(rx_wait);
  159. return 1;
  160. }
  161. static void pcnet_init(void * data, char * name) {
  162. uint16_t command_reg = pci_read_field(pcnet_device_pci, PCI_COMMAND, 4) & 0xFFFF0000;
  163. if (command_reg & (1 << 2)) {
  164. debug_print(NOTICE, "Bus mastering already enabled.\n");
  165. }
  166. command_reg |= (1 << 2);
  167. command_reg |= (1 << 0);
  168. pci_write_field(pcnet_device_pci, PCI_COMMAND, 4, command_reg);
  169. pcnet_io_base = pci_read_field(pcnet_device_pci, PCI_BAR0, 4) & 0xFFFFFFF0;
  170. pcnet_mem_base = pci_read_field(pcnet_device_pci, PCI_BAR1, 4) & 0xFFFFFFF0;
  171. pcnet_irq = pci_get_interrupt(pcnet_device_pci);
  172. irq_install_handler(pcnet_irq, pcnet_irq_handler, "pcnet");
  173. debug_print(NOTICE, "irq line: %d", pcnet_irq);
  174. debug_print(NOTICE, "io base: 0x%x", pcnet_io_base);
  175. /* Read MAC from EEPROM */
  176. mac[0] = inportb(pcnet_io_base + 0);
  177. mac[1] = inportb(pcnet_io_base + 1);
  178. mac[2] = inportb(pcnet_io_base + 2);
  179. mac[3] = inportb(pcnet_io_base + 3);
  180. mac[4] = inportb(pcnet_io_base + 4);
  181. mac[5] = inportb(pcnet_io_base + 5);
  182. /* Force reset */
  183. inportl(pcnet_io_base + 0x18);
  184. inports(pcnet_io_base + 0x14);
  185. unsigned long s, ss;
  186. relative_time(0, 10, &s, &ss);
  187. sleep_until((process_t *)current_process, s, ss);
  188. switch_task(0);
  189. debug_print(NOTICE, "pcnet return from sleep");
  190. /* set 32-bit mode */
  191. outportl(pcnet_io_base + 0x10, 0);
  192. /* SWSTYLE to 2 */
  193. uint32_t csr58 = read_csr32(58);
  194. csr58 &= 0xFFF0;
  195. csr58 |= 2;
  196. write_csr32(58, csr58);
  197. /* ASEL enable */
  198. uint32_t bcr2 = read_bcr32(2);
  199. bcr2 |= 0x2;
  200. write_bcr32(2, bcr2);
  201. debug_print(NOTICE, "device mac %2x:%2x:%2x:%2x:%2x:%2x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  202. if (!pcnet_buffer_virt) {
  203. debug_print(ERROR, "Failed.");
  204. return;
  205. }
  206. debug_print(WARNING, "phys: 0x%x, virt: 0x%x", pcnet_buffer_phys, pcnet_buffer_virt);
  207. pcnet_rx_de_start = pcnet_buffer_virt + 28;
  208. pcnet_tx_de_start = pcnet_rx_de_start + PCNET_RX_COUNT * PCNET_DE_SIZE;
  209. pcnet_rx_start = pcnet_tx_de_start + PCNET_TX_COUNT * PCNET_DE_SIZE;
  210. pcnet_tx_start = pcnet_rx_start + PCNET_RX_COUNT * PCNET_BUFFER_SIZE;
  211. pcnet_rx_de_phys = virt_to_phys(pcnet_rx_de_start);
  212. pcnet_tx_de_phys = virt_to_phys(pcnet_tx_de_start);
  213. pcnet_rx_phys = virt_to_phys(pcnet_rx_start);
  214. pcnet_tx_phys = virt_to_phys(pcnet_tx_start);
  215. /* set up descriptors */
  216. for (int i = 0; i < PCNET_RX_COUNT; i++) {
  217. init_descriptor(i, 0);
  218. }
  219. for (int i = 0; i < PCNET_TX_COUNT; i++) {
  220. init_descriptor(i, 1);
  221. }
  222. /* Set up device configuration structure */
  223. ((uint16_t *)&pcnet_buffer_virt[0])[0] = 0x0000;
  224. pcnet_buffer_virt[2] = 5 << 4; /* RLEN << 4 */
  225. pcnet_buffer_virt[3] = 3 << 4; /* TLEN << 4 */
  226. pcnet_buffer_virt[4] = mac[0];
  227. pcnet_buffer_virt[5] = mac[1];
  228. pcnet_buffer_virt[6] = mac[2];
  229. pcnet_buffer_virt[7] = mac[3];
  230. pcnet_buffer_virt[8] = mac[4];
  231. pcnet_buffer_virt[9] = mac[5];
  232. pcnet_buffer_virt[10] = 0; /* reserved */
  233. pcnet_buffer_virt[11] = 0; /* reserved */
  234. pcnet_buffer_virt[12] = 0;
  235. pcnet_buffer_virt[13] = 0;
  236. pcnet_buffer_virt[14] = 0;
  237. pcnet_buffer_virt[15] = 0;
  238. pcnet_buffer_virt[16] = 0;
  239. pcnet_buffer_virt[17] = 0;
  240. pcnet_buffer_virt[18] = 0;
  241. pcnet_buffer_virt[19] = 0;
  242. ((uint32_t *)&pcnet_buffer_virt[20])[0] = pcnet_rx_de_phys;
  243. ((uint32_t *)&pcnet_buffer_virt[24])[0] = pcnet_tx_de_phys;
  244. /* Configure network */
  245. net_queue = list_create();
  246. rx_wait = list_create();
  247. write_csr32(1, 0xFFFF & pcnet_buffer_phys);
  248. write_csr32(2, 0xFFFF & (pcnet_buffer_phys >> 16));
  249. uint32_t a = read_csr32(1);
  250. uint32_t b = read_csr32(2);
  251. debug_print(ERROR, "csr1 = 0x%4x csr2= 0x%4x", a, b);
  252. uint16_t csr3 = read_csr32(3);
  253. if (csr3 & (1 << 10)) csr3 ^= (1 << 10);
  254. if (csr3 & (1 << 2)) csr3 ^= (1 << 2);
  255. csr3 |= (1 << 9);
  256. csr3 |= (1 << 8);
  257. write_csr32(3, csr3); /* Disable interrupt on init */
  258. write_csr32(4, read_csr32(4) | (1 << 1) | (1 << 12) | (1 << 14)); /* pad */
  259. write_csr32(0, read_csr32(0) | (1 << 0) | (1 << 6)); /* do it */
  260. uint64_t start_time;
  261. asm volatile (".byte 0x0f, 0x31" : "=A" (start_time));
  262. uint32_t status;
  263. while (((status = read_csr32(0)) & (1 << 8)) == 0) {
  264. uint64_t now_time;
  265. asm volatile (".byte 0x0f, 0x31" : "=A" (now_time));
  266. if (now_time - start_time > 0x10000) {
  267. debug_print(ERROR, "Could not initialize PCNet card, status is 0x%4x", status);
  268. return;
  269. }
  270. }
  271. /* Start card */
  272. uint16_t csr0 = read_csr32(0);
  273. if (csr0 & (1 << 0)) csr0 ^= (1 << 0);
  274. if (csr0 & (1 << 2)) csr0 ^= (1 << 2);
  275. csr0 |= (1 << 1);
  276. write_csr32(0, csr0);
  277. debug_print(NOTICE, "Card start.");
  278. init_netif_funcs(pcnet_get_mac, dequeue_packet, pcnet_send_packet, "AMD PCnet FAST II/III");
  279. }
  280. static int init(void) {
  281. pci_scan(&find_pcnet, -1, &pcnet_device_pci);
  282. if (!pcnet_device_pci) {
  283. debug_print(WARNING, "No PCNET device found.");
  284. return 1;
  285. }
  286. /* Initialize ring buffers */
  287. debug_print(WARNING, "Request a large continuous chunk of memory.");
  288. /* This fits 32x1548 (rx) + 8x1548 (tx) + 32x16 (rx DE) + 8x16 (tx DE) */
  289. pcnet_buffer_virt = (void*)kvmalloc_p(0x10000, &pcnet_buffer_phys);
  290. create_kernel_tasklet(pcnet_init, "[pcnet]", NULL);
  291. return 0;
  292. }
  293. static int fini(void) {
  294. return 0;
  295. }
  296. MODULE_DEF(pcnet, init, fini);
  297. MODULE_DEPENDS(net);