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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  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. DBG ( "Sending packet:\n" );
  166. // DBG_HD ( iobuf->data, iob_len ( iobuf ) );
  167. DBG ( "Peer:\n" );
  168. DBG_HD ( &ibhdr->peer[0], IB_ALEN );
  169. DBG ( "Bcast:\n" );
  170. DBG_HD ( &ib_broadcast[0], IB_ALEN );
  171. iob_pull ( iobuf, sizeof ( *ibhdr ) );
  172. if ( memcmp ( ibhdr->peer, ib_broadcast, IB_ALEN ) == 0 ) {
  173. printf ( "Sending broadcast packet\n" );
  174. return send_bcast_packet ( ibhdr->proto, iobuf->data,
  175. iob_len ( iobuf ) );
  176. } else {
  177. printf ( "Sending unicast packet\n" );
  178. return send_ucast_packet ( ibhdr->peer, ibhdr->proto,
  179. iobuf->data, iob_len ( iobuf ) );
  180. }
  181. }
  182. /**
  183. * Poll for completed and received packets
  184. *
  185. * @v netdev Network device
  186. */
  187. static void mlx_poll ( struct net_device *netdev ) {
  188. struct ib_cqe_st ib_cqe;
  189. uint8_t num_cqes;
  190. unsigned int len;
  191. struct io_buffer *iobuf;
  192. void *buf;
  193. int rc;
  194. if ( ( rc = poll_error_buf() ) != 0 ) {
  195. DBG ( "poll_error_buf() failed: %s\n", strerror ( rc ) );
  196. return;
  197. }
  198. if ( ( rc = drain_eq() ) != 0 ) {
  199. DBG ( "drain_eq() failed: %s\n", strerror ( rc ) );
  200. return;
  201. }
  202. if ( ( rc = ib_poll_cq ( ipoib_data.rcv_cqh, &ib_cqe,
  203. &num_cqes ) ) != 0 ) {
  204. DBG ( "ib_poll_cq() failed: %s\n", strerror ( rc ) );
  205. return;
  206. }
  207. if ( ! num_cqes )
  208. return;
  209. if ( ib_cqe.is_error ) {
  210. DBG ( "cqe error\n" );
  211. free_wqe ( ib_cqe.wqe );
  212. return;
  213. }
  214. len = ib_cqe.count;
  215. iobuf = alloc_iob ( len );
  216. if ( ! iobuf ) {
  217. DBG ( "out of memory\n" );
  218. free_wqe ( ib_cqe.wqe );
  219. return;
  220. }
  221. memcpy ( iob_put ( iobuf, len ), buf, len );
  222. DBG ( "Received packet:\n" );
  223. DBG_HD ( iobuf->data, iob_len ( iobuf ) );
  224. netdev_rx ( netdev, iobuf );
  225. free_wqe ( ib_cqe.wqe );
  226. }
  227. /**
  228. * Enable or disable interrupts
  229. *
  230. * @v netdev Network device
  231. * @v enable Interrupts should be enabled
  232. */
  233. static void mlx_irq ( struct net_device *netdev, int enable ) {
  234. }
  235. static struct net_device_operations mlx_operations = {
  236. .open = mlx_open,
  237. .close = mlx_close,
  238. .transmit = mlx_transmit,
  239. .poll = mlx_poll,
  240. .irq = mlx_irq,
  241. };
  242. /**************************************************************************
  243. DISABLE - Turn off ethernet interface
  244. ***************************************************************************/
  245. static void mt25218_disable(struct nic *nic)
  246. {
  247. /* put the card in its initial state */
  248. /* This function serves 3 purposes.
  249. * This disables DMA and interrupts so we don't receive
  250. * unexpected packets or interrupts from the card after
  251. * etherboot has finished.
  252. * This frees resources so etherboot may use
  253. * this driver on another interface
  254. * This allows etherboot to reinitialize the interface
  255. * if something is something goes wrong.
  256. */
  257. if (nic || 1) { // ????
  258. disable_imp();
  259. }
  260. }
  261. /**
  262. * Remove PCI device
  263. *
  264. * @v pci PCI device
  265. */
  266. static void mlx_remove ( struct pci_device *pci ) {
  267. struct net_device *netdev = pci_get_drvdata ( pci );
  268. struct mlx_nic *mlx = netdev->priv;
  269. unregister_netdev ( netdev );
  270. ipoib_close(0);
  271. netdev_nullify ( netdev );
  272. netdev_put ( netdev );
  273. }
  274. static struct nic_operations mt25218_operations = {
  275. .connect = dummy_connect,
  276. .poll = mt25218_poll,
  277. .transmit = mt25218_transmit,
  278. .irq = mt25218_irq,
  279. };
  280. /**************************************************************************
  281. PROBE - Look for an adapter, this routine's visible to the outside
  282. ***************************************************************************/
  283. static int mt25218_probe(struct nic *nic, struct pci_device *pci)
  284. {
  285. int rc;
  286. unsigned char user_request;
  287. if (pci->vendor != MELLANOX_VENDOR_ID) {
  288. eprintf("");
  289. return 0;
  290. }
  291. printf("\n");
  292. printf("Mellanox Technologies LTD - Boot over IB implementaion\n");
  293. printf("Build version = %s\n\n", build_revision);
  294. verbose_messages = 0;
  295. print_info = 0;
  296. printf("Press within 3 seconds:\n");
  297. printf("V - to increase verbosity\n");
  298. printf("I - to print information\n");
  299. if (prompt_key(3, &user_request)) {
  300. if (user_request == 'V') {
  301. printf("User selected verbose messages\n");
  302. verbose_messages = 1;
  303. }
  304. else if (user_request == 'I') {
  305. printf("User selected to print information\n");
  306. print_info = 1;
  307. }
  308. }
  309. printf("\n");
  310. adjust_pci_device(pci);
  311. nic->priv_data = NULL;
  312. rc = probe_imp(pci, nic);
  313. /* give the user a chance to look at the info */
  314. if (print_info)
  315. sleep(5);
  316. if (!rc) {
  317. /* store NIC parameters */
  318. nic->ioaddr = pci->ioaddr & ~3;
  319. nic->irqno = pci->irq;
  320. /* point to NIC specific routines */
  321. nic->nic_op = &mt25218_operations;
  322. uint8_t fixed_node_addr[ETH_ALEN] = { 0x00, 0x02, 0xc9,
  323. 0x20, 0xf5, 0x95 };
  324. memcpy ( nic->node_addr, fixed_node_addr, ETH_ALEN );
  325. return 1;
  326. }
  327. /* else */
  328. return 0;
  329. }
  330. /**
  331. * Probe PCI device
  332. *
  333. * @v pci PCI device
  334. * @v id PCI ID
  335. * @ret rc Return status code
  336. */
  337. static int mlx_probe ( struct pci_device *pci,
  338. const struct pci_device_id *id __unused ) {
  339. struct net_device *netdev;
  340. struct mlx_nic *mlx;
  341. int rc;
  342. /* Allocate net device */
  343. netdev = alloc_ibdev ( sizeof ( *mlx ) );
  344. if ( ! netdev )
  345. return -ENOMEM;
  346. netdev_init ( netdev, &mlx_operations );
  347. mlx = netdev->priv;
  348. pci_set_drvdata ( pci, netdev );
  349. netdev->dev = &pci->dev;
  350. memset ( mlx, 0, sizeof ( *mlx ) );
  351. /* Fix up PCI device */
  352. adjust_pci_device ( pci );
  353. /* Initialise hardware */
  354. if ( ( rc = ipoib_init ( pci ) ) != 0 )
  355. goto err_ipoib_init;
  356. memcpy ( netdev->ll_addr, ipoib_data.port_gid_raw, IB_ALEN );
  357. /* Register network device */
  358. if ( ( rc = register_netdev ( netdev ) ) != 0 )
  359. goto err_register_netdev;
  360. return 0;
  361. err_register_netdev:
  362. err_ipoib_init:
  363. ipoib_close(0);
  364. netdev_nullify ( netdev );
  365. netdev_put ( netdev );
  366. return rc;
  367. }
  368. static struct pci_device_id mlx_nics[] = {
  369. PCI_ROM(0x15b3, 0x6282, "MT25218", "MT25218 HCA driver"),
  370. PCI_ROM(0x15b3, 0x6274, "MT25204", "MT25204 HCA driver"),
  371. };
  372. struct pci_driver mlx_driver __pci_driver = {
  373. .ids = mlx_nics,
  374. .id_count = ( sizeof ( mlx_nics ) / sizeof ( mlx_nics[0] ) ),
  375. .probe = mlx_probe,
  376. .remove = mlx_remove,
  377. };