11a35c2e590289a2ce9f1da3336299a0774d60c8
[people/sha0/gpxe.git] / src / drivers / net / mlx_ipoib / mt25218.c
1 /**************************************************************************
2 Etherboot -  BOOTP/TFTP Bootstrap Program
3 Skeleton NIC driver for Etherboot
4 ***************************************************************************/
5
6 /*
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2, or (at
10  * your option) any later version.
11  */
12
13 /* to get some global routines like printf */
14 #include "etherboot.h"
15 /* to get the interface to the body of the program */
16 #include "nic.h"
17
18 #include "mt_version.c"
19 #include "mt25218_imp.c"
20
21 /* NIC specific static variables go here */
22
23 int prompt_key(int secs, unsigned char *ch_p)
24 {
25         unsigned long tmo;
26         unsigned char ch;
27
28         for (tmo = currticks() + secs * TICKS_PER_SEC; currticks() < tmo;) {
29                 if (iskey()) {
30                         ch = getchar();
31                         /* toupper does not work ... */
32                         if (ch == 'v')
33                                 ch = 'V';
34                         if (ch == 'i')
35                                 ch = 'I';
36                         if ((ch=='V') || (ch=='I')) {
37                                 *ch_p = ch;
38                                 return 1;
39                         }
40                 }
41         }
42
43         return 0;
44 }
45
46 /**************************************************************************
47 IRQ - handle interrupts
48 ***************************************************************************/
49 static void mt25218_irq(struct nic *nic, irq_action_t action)
50 {
51         /* This routine is somewhat optional.  Etherboot itself
52          * doesn't use interrupts, but they are required under some
53          * circumstances when we're acting as a PXE stack.
54          *
55          * If you don't implement this routine, the only effect will
56          * be that your driver cannot be used via Etherboot's UNDI
57          * API.  This won't affect programs that use only the UDP
58          * portion of the PXE API, such as pxelinux.
59          */
60
61         if (0) {
62                 nic = NULL;
63         }
64         switch (action) {
65         case DISABLE:
66         case ENABLE:
67                 /* Set receive interrupt enabled/disabled state */
68                 /*
69                    outb ( action == ENABLE ? IntrMaskEnabled : IntrMaskDisabled,
70                    nic->ioaddr + IntrMaskRegister );
71                  */
72                 break;
73         case FORCE:
74                 /* Force NIC to generate a receive interrupt */
75                 /*
76                    outb ( ForceInterrupt, nic->ioaddr + IntrForceRegister );
77                  */
78                 break;
79         }
80 }
81
82 /**************************************************************************
83 POLL - Wait for a frame
84 ***************************************************************************/
85 static int mt25218_poll(struct nic *nic, int retrieve)
86 {
87         /* Work out whether or not there's an ethernet packet ready to
88          * read.  Return 0 if not.
89          */
90         /* 
91            if ( ! <packet_ready> ) return 0;
92          */
93
94         /* retrieve==0 indicates that we are just checking for the
95          * presence of a packet but don't want to read it just yet.
96          */
97         /*
98            if ( ! retrieve ) return 1;
99          */
100
101         /* Copy data to nic->packet.  Data should include the
102          * link-layer header (dest MAC, source MAC, type).
103          * Store length of data in nic->packetlen.
104          * Return true to indicate a packet has been read.
105          */
106         /* 
107            nic->packetlen = <packet_length>;
108            memcpy ( nic->packet, <packet_data>, <packet_length> );
109            return 1;
110          */
111         unsigned int size;
112         int rc;
113         rc = poll_imp(nic, retrieve, &size);
114         if (rc) {
115                 return 0;
116         }
117
118         if (size == 0) {
119                 return 0;
120         }
121
122         nic->packetlen = size;
123
124         return 1;
125 }
126
127 /**************************************************************************
128 TRANSMIT - Transmit a frame
129 ***************************************************************************/
130 static void mt25218_transmit(struct nic *nic, const char *dest, /* Destination */
131                              unsigned int type, /* Type */
132                              unsigned int size, /* size */
133                              const char *packet)
134 {                               /* Packet */
135         int rc;
136
137         /* Transmit packet to dest MAC address.  You will need to
138          * construct the link-layer header (dest MAC, source MAC,
139          * type).
140          */
141         if (nic) {
142                 rc = transmit_imp(dest, type, packet, size);
143                 if (rc)
144                         eprintf("tranmit error");
145         }
146 }
147
148 /**************************************************************************
149 DISABLE - Turn off ethernet interface
150 ***************************************************************************/
151 static void mt25218_disable(struct nic *nic)
152 {
153         /* put the card in its initial state */
154         /* This function serves 3 purposes.
155          * This disables DMA and interrupts so we don't receive
156          *  unexpected packets or interrupts from the card after
157          *  etherboot has finished. 
158          * This frees resources so etherboot may use
159          *  this driver on another interface
160          * This allows etherboot to reinitialize the interface
161          *  if something is something goes wrong.
162          */
163         if (nic || 1) {         // ????
164                 disable_imp();
165         }
166 }
167
168 static struct nic_operations mt25218_operations = {
169         .connect        = dummy_connect,
170         .poll           = mt25218_poll,
171         .transmit       = mt25218_transmit,
172         .irq            = mt25218_irq,
173 };
174
175 /**************************************************************************
176 PROBE - Look for an adapter, this routine's visible to the outside
177 ***************************************************************************/
178
179 static int mt25218_probe(struct nic *nic, struct pci_device *pci)
180 {
181         int rc;
182         unsigned char user_request;
183
184         if (pci->vendor != MELLANOX_VENDOR_ID) {
185                 eprintf("");
186                 return 0;
187         }
188
189         printf("\n");
190         printf("Mellanox Technologies LTD - Boot over IB implementaion\n");
191         printf("Build version = %s\n\n", build_revision);
192
193         verbose_messages = 0;
194         print_info = 0;
195         printf("Press within 3 seconds:\n");
196         printf("V - to increase verbosity\n");
197         printf("I - to print information\n");
198         if (prompt_key(3, &user_request)) {
199                 if (user_request == 'V') {
200                         printf("User selected verbose messages\n");
201                         verbose_messages = 1;
202                 }
203                 else if (user_request == 'I') {
204                         printf("User selected to print information\n");
205                         print_info = 1;
206                 }
207         }
208         printf("\n");
209
210         adjust_pci_device(pci);
211
212         nic->priv_data = NULL;
213         rc = probe_imp(pci, nic);
214
215         /* give the user a chance to look at the info */
216         if (print_info)
217                 sleep(5);
218
219         if (!rc) {
220                 /* store NIC parameters */
221                 nic->ioaddr = pci->ioaddr & ~3;
222                 nic->irqno = pci->irq;
223                 /* point to NIC specific routines */
224                 nic->nic_op = &mt25218_operations;
225
226                 uint8_t fixed_node_addr[ETH_ALEN] = { 0x00, 0x02, 0xc9,
227                                                       0x20, 0xf5, 0x95 };
228                 memcpy ( nic->node_addr, fixed_node_addr, ETH_ALEN );
229
230                 return 1;
231         }
232         /* else */
233         return 0;
234 }
235
236 static struct pci_device_id mt25218_nics[] = {
237         PCI_ROM(0x15b3, 0x6282, "MT25218", "MT25218 HCA driver"),
238         PCI_ROM(0x15b3, 0x6274, "MT25204", "MT25204 HCA driver"),
239 };
240
241 PCI_DRIVER ( mt25218_driver, mt25218_nics, PCI_NO_CLASS );
242
243 DRIVER ( "MT25218", nic_driver, pci_driver, mt25218_driver,
244          mt25218_probe, mt25218_disable );