You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mt25218.c 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /**************************************************************************
  2. Etherboot - BOOTP/TFTP Bootstrap Program
  3. Skeleton NIC driver for Etherboot
  4. ***************************************************************************/
  5. /*
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2, or (at
  9. * your option) any later version.
  10. */
  11. #include <errno.h>
  12. #include <gpxe/pci.h>
  13. #include <gpxe/iobuf.h>
  14. #include <gpxe/netdevice.h>
  15. #include <gpxe/infiniband.h>
  16. struct mlx_nic {
  17. };
  18. /* to get some global routines like printf */
  19. #include "etherboot.h"
  20. /* to get the interface to the body of the program */
  21. #include "nic.h"
  22. #include "mt_version.c"
  23. #include "mt25218_imp.c"
  24. /* NIC specific static variables go here */
  25. int prompt_key(int secs, unsigned char *ch_p)
  26. {
  27. unsigned long tmo;
  28. unsigned char ch;
  29. for (tmo = currticks() + secs * TICKS_PER_SEC; currticks() < tmo;) {
  30. if (iskey()) {
  31. ch = getchar();
  32. /* toupper does not work ... */
  33. if (ch == 'v')
  34. ch = 'V';
  35. if (ch == 'i')
  36. ch = 'I';
  37. if ((ch=='V') || (ch=='I')) {
  38. *ch_p = ch;
  39. return 1;
  40. }
  41. }
  42. }
  43. return 0;
  44. }
  45. /**************************************************************************
  46. IRQ - handle interrupts
  47. ***************************************************************************/
  48. static void mt25218_irq(struct nic *nic, irq_action_t action)
  49. {
  50. /* This routine is somewhat optional. Etherboot itself
  51. * doesn't use interrupts, but they are required under some
  52. * circumstances when we're acting as a PXE stack.
  53. *
  54. * If you don't implement this routine, the only effect will
  55. * be that your driver cannot be used via Etherboot's UNDI
  56. * API. This won't affect programs that use only the UDP
  57. * portion of the PXE API, such as pxelinux.
  58. */
  59. if (0) {
  60. nic = NULL;
  61. }
  62. switch (action) {
  63. case DISABLE:
  64. case ENABLE:
  65. /* Set receive interrupt enabled/disabled state */
  66. /*
  67. outb ( action == ENABLE ? IntrMaskEnabled : IntrMaskDisabled,
  68. nic->ioaddr + IntrMaskRegister );
  69. */
  70. break;
  71. case FORCE:
  72. /* Force NIC to generate a receive interrupt */
  73. /*
  74. outb ( ForceInterrupt, nic->ioaddr + IntrForceRegister );
  75. */
  76. break;
  77. }
  78. }
  79. /**************************************************************************
  80. POLL - Wait for a frame
  81. ***************************************************************************/
  82. static int mt25218_poll(struct nic *nic, int retrieve)
  83. {
  84. /* Work out whether or not there's an ethernet packet ready to
  85. * read. Return 0 if not.
  86. */
  87. /*
  88. if ( ! <packet_ready> ) return 0;
  89. */
  90. /* retrieve==0 indicates that we are just checking for the
  91. * presence of a packet but don't want to read it just yet.
  92. */
  93. /*
  94. if ( ! retrieve ) return 1;
  95. */
  96. /* Copy data to nic->packet. Data should include the
  97. * link-layer header (dest MAC, source MAC, type).
  98. * Store length of data in nic->packetlen.
  99. * Return true to indicate a packet has been read.
  100. */
  101. /*
  102. nic->packetlen = <packet_length>;
  103. memcpy ( nic->packet, <packet_data>, <packet_length> );
  104. return 1;
  105. */
  106. unsigned int size;
  107. int rc;
  108. rc = poll_imp(nic, retrieve, &size);
  109. if (rc) {
  110. return 0;
  111. }
  112. if (size == 0) {
  113. return 0;
  114. }
  115. nic->packetlen = size;
  116. return 1;
  117. }
  118. /**************************************************************************
  119. TRANSMIT - Transmit a frame
  120. ***************************************************************************/
  121. static void mt25218_transmit(struct nic *nic, const char *dest, /* Destination */
  122. unsigned int type, /* Type */
  123. unsigned int size, /* size */
  124. const char *packet)
  125. { /* Packet */
  126. int rc;
  127. /* Transmit packet to dest MAC address. You will need to
  128. * construct the link-layer header (dest MAC, source MAC,
  129. * type).
  130. */
  131. if (nic) {
  132. rc = transmit_imp(dest, type, packet, size);
  133. if (rc)
  134. eprintf("tranmit error");
  135. }
  136. }
  137. /**
  138. * Open network device
  139. *
  140. * @v netdev Network device
  141. * @ret rc Return status code
  142. */
  143. static int mlx_open ( struct net_device *netdev ) {
  144. return 0;
  145. }
  146. /**
  147. * Close network device
  148. *
  149. * @v netdev Network device
  150. */
  151. static void mlx_close ( struct net_device *netdev ) {
  152. }
  153. #warning "Broadcast address?"
  154. static uint8_t ib_broadcast[IB_ALEN] = { 0xff, };
  155. /**
  156. * Transmit packet
  157. *
  158. * @v netdev Network device
  159. * @v iobuf I/O buffer
  160. * @ret rc Return status code
  161. */
  162. static int mlx_transmit ( struct net_device *netdev,
  163. struct io_buffer *iobuf ) {
  164. struct ibhdr *ibhdr = iobuf->data;
  165. iob_pull ( iobuf, sizeof ( *ibhdr ) );
  166. if ( memcmp ( ibhdr->peer, ib_broadcast, IB_ALEN ) == 0 ) {
  167. printf ( "Sending broadcast packet\n" );
  168. return send_bcast_packet ( ntohs ( ibhdr->proto ),
  169. iobuf->data, iob_len ( iobuf ) );
  170. } else {
  171. printf ( "Sending unicast packet\n" );
  172. return send_ucast_packet ( ibhdr->peer,
  173. ntohs ( ibhdr->proto ),
  174. iobuf->data, iob_len ( iobuf ) );
  175. }
  176. }
  177. /**
  178. * Poll for completed and received packets
  179. *
  180. * @v netdev Network device
  181. */
  182. static void mlx_poll ( struct net_device *netdev ) {
  183. struct ib_cqe_st ib_cqe;
  184. uint8_t num_cqes;
  185. unsigned int len;
  186. struct io_buffer *iobuf;
  187. void *buf;
  188. int rc;
  189. if ( ( rc = poll_error_buf() ) != 0 ) {
  190. DBG ( "poll_error_buf() failed: %s\n", strerror ( rc ) );
  191. return;
  192. }
  193. if ( ( rc = drain_eq() ) != 0 ) {
  194. DBG ( "drain_eq() failed: %s\n", strerror ( rc ) );
  195. return;
  196. }
  197. if ( ( rc = ib_poll_cq ( ipoib_data.rcv_cqh, &ib_cqe,
  198. &num_cqes ) ) != 0 ) {
  199. DBG ( "ib_poll_cq() failed: %s\n", strerror ( rc ) );
  200. return;
  201. }
  202. if ( ! num_cqes )
  203. return;
  204. if ( ib_cqe.is_error ) {
  205. DBG ( "cqe error\n" );
  206. free_wqe ( ib_cqe.wqe );
  207. return;
  208. }
  209. len = ib_cqe.count;
  210. iobuf = alloc_iob ( len );
  211. if ( ! iobuf ) {
  212. DBG ( "out of memory\n" );
  213. free_wqe ( ib_cqe.wqe );
  214. return;
  215. }
  216. memcpy ( iob_put ( iobuf, len ), buf, len );
  217. DBG ( "Received packet:\n" );
  218. DBG_HD ( iobuf->data, iob_len ( iobuf ) );
  219. netdev_rx ( netdev, iobuf );
  220. free_wqe ( ib_cqe.wqe );
  221. }
  222. /**
  223. * Enable or disable interrupts
  224. *
  225. * @v netdev Network device
  226. * @v enable Interrupts should be enabled
  227. */
  228. static void mlx_irq ( struct net_device *netdev, int enable ) {
  229. }
  230. static struct net_device_operations mlx_operations = {
  231. .open = mlx_open,
  232. .close = mlx_close,
  233. .transmit = mlx_transmit,
  234. .poll = mlx_poll,
  235. .irq = mlx_irq,
  236. };
  237. /**************************************************************************
  238. DISABLE - Turn off ethernet interface
  239. ***************************************************************************/
  240. static void mt25218_disable(struct nic *nic)
  241. {
  242. /* put the card in its initial state */
  243. /* This function serves 3 purposes.
  244. * This disables DMA and interrupts so we don't receive
  245. * unexpected packets or interrupts from the card after
  246. * etherboot has finished.
  247. * This frees resources so etherboot may use
  248. * this driver on another interface
  249. * This allows etherboot to reinitialize the interface
  250. * if something is something goes wrong.
  251. */
  252. if (nic || 1) { // ????
  253. disable_imp();
  254. }
  255. }
  256. /**
  257. * Remove PCI device
  258. *
  259. * @v pci PCI device
  260. */
  261. static void mlx_remove ( struct pci_device *pci ) {
  262. struct net_device *netdev = pci_get_drvdata ( pci );
  263. struct mlx_nic *mlx = netdev->priv;
  264. unregister_netdev ( netdev );
  265. ipoib_close(0);
  266. netdev_nullify ( netdev );
  267. netdev_put ( netdev );
  268. }
  269. static struct nic_operations mt25218_operations = {
  270. .connect = dummy_connect,
  271. .poll = mt25218_poll,
  272. .transmit = mt25218_transmit,
  273. .irq = mt25218_irq,
  274. };
  275. /**************************************************************************
  276. PROBE - Look for an adapter, this routine's visible to the outside
  277. ***************************************************************************/
  278. static int mt25218_probe(struct nic *nic, struct pci_device *pci)
  279. {
  280. int rc;
  281. unsigned char user_request;
  282. if (pci->vendor != MELLANOX_VENDOR_ID) {
  283. eprintf("");
  284. return 0;
  285. }
  286. printf("\n");
  287. printf("Mellanox Technologies LTD - Boot over IB implementaion\n");
  288. printf("Build version = %s\n\n", build_revision);
  289. verbose_messages = 0;
  290. print_info = 0;
  291. printf("Press within 3 seconds:\n");
  292. printf("V - to increase verbosity\n");
  293. printf("I - to print information\n");
  294. if (prompt_key(3, &user_request)) {
  295. if (user_request == 'V') {
  296. printf("User selected verbose messages\n");
  297. verbose_messages = 1;
  298. }
  299. else if (user_request == 'I') {
  300. printf("User selected to print information\n");
  301. print_info = 1;
  302. }
  303. }
  304. printf("\n");
  305. adjust_pci_device(pci);
  306. nic->priv_data = NULL;
  307. rc = probe_imp(pci, nic);
  308. /* give the user a chance to look at the info */
  309. if (print_info)
  310. sleep(5);
  311. if (!rc) {
  312. /* store NIC parameters */
  313. nic->ioaddr = pci->ioaddr & ~3;
  314. nic->irqno = pci->irq;
  315. /* point to NIC specific routines */
  316. nic->nic_op = &mt25218_operations;
  317. uint8_t fixed_node_addr[ETH_ALEN] = { 0x00, 0x02, 0xc9,
  318. 0x20, 0xf5, 0x95 };
  319. memcpy ( nic->node_addr, fixed_node_addr, ETH_ALEN );
  320. return 1;
  321. }
  322. /* else */
  323. return 0;
  324. }
  325. /**
  326. * Probe PCI device
  327. *
  328. * @v pci PCI device
  329. * @v id PCI ID
  330. * @ret rc Return status code
  331. */
  332. static int mlx_probe ( struct pci_device *pci,
  333. const struct pci_device_id *id __unused ) {
  334. struct net_device *netdev;
  335. struct mlx_nic *mlx;
  336. int rc;
  337. /* Allocate net device */
  338. netdev = alloc_ibdev ( sizeof ( *mlx ) );
  339. if ( ! netdev )
  340. return -ENOMEM;
  341. netdev_init ( netdev, &mlx_operations );
  342. mlx = netdev->priv;
  343. pci_set_drvdata ( pci, netdev );
  344. netdev->dev = &pci->dev;
  345. memset ( mlx, 0, sizeof ( *mlx ) );
  346. /* Fix up PCI device */
  347. adjust_pci_device ( pci );
  348. /* Initialise hardware */
  349. if ( ( rc = ipoib_init ( pci ) ) != 0 )
  350. goto err_ipoib_init;
  351. memcpy ( netdev->ll_addr, ipoib_data.port_gid_raw, IB_ALEN );
  352. /* Register network device */
  353. if ( ( rc = register_netdev ( netdev ) ) != 0 )
  354. goto err_register_netdev;
  355. return 0;
  356. err_register_netdev:
  357. err_ipoib_init:
  358. ipoib_close(0);
  359. netdev_nullify ( netdev );
  360. netdev_put ( netdev );
  361. return rc;
  362. }
  363. static struct pci_device_id mlx_nics[] = {
  364. PCI_ROM(0x15b3, 0x6282, "MT25218", "MT25218 HCA driver"),
  365. PCI_ROM(0x15b3, 0x6274, "MT25204", "MT25204 HCA driver"),
  366. };
  367. struct pci_driver mlx_driver __pci_driver = {
  368. .ids = mlx_nics,
  369. .id_count = ( sizeof ( mlx_nics ) / sizeof ( mlx_nics[0] ) ),
  370. .probe = mlx_probe,
  371. .remove = mlx_remove,
  372. };