1 /*
2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <stdint.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <byteswap.h>
31 #include <ipxe/netdevice.h>
32 #include <ipxe/ethernet.h>
33 #include <ipxe/if_ether.h>
34 #include <ipxe/iobuf.h>
35 #include <ipxe/malloc.h>
36 #include <ipxe/pci.h>
37 #include "skeleton.h"
38
39 /** @file
40 *
41 * Skeleton network driver
42 *
43 */
44
45 /******************************************************************************
46 *
47 * Device reset
48 *
49 ******************************************************************************
50 */
51
52 /**
53 * Reset hardware
54 *
55 * @v skel Skeleton device
56 * @ret rc Return status code
57 */
skeleton_reset(struct skeleton_nic * skel)58 static int skeleton_reset ( struct skeleton_nic *skel ) {
59
60 DBGC ( skel, "SKELETON %p does not yet support reset\n", skel );
61 return -ENOTSUP;
62 }
63
64 /******************************************************************************
65 *
66 * Link state
67 *
68 ******************************************************************************
69 */
70
71 /**
72 * Check link state
73 *
74 * @v netdev Network device
75 */
skeleton_check_link(struct net_device * netdev)76 static void skeleton_check_link ( struct net_device *netdev ) {
77 struct skeleton_nic *skel = netdev->priv;
78
79 DBGC ( skel, "SKELETON %p does not yet support link state\n", skel );
80 netdev_link_err ( netdev, -ENOTSUP );
81 }
82
83 /******************************************************************************
84 *
85 * Network device interface
86 *
87 ******************************************************************************
88 */
89
90 /**
91 * Open network device
92 *
93 * @v netdev Network device
94 * @ret rc Return status code
95 */
skeleton_open(struct net_device * netdev)96 static int skeleton_open ( struct net_device *netdev ) {
97 struct skeleton_nic *skel = netdev->priv;
98
99 DBGC ( skel, "SKELETON %p does not yet support open\n", skel );
100 return -ENOTSUP;
101 }
102
103 /**
104 * Close network device
105 *
106 * @v netdev Network device
107 */
skeleton_close(struct net_device * netdev)108 static void skeleton_close ( struct net_device *netdev ) {
109 struct skeleton_nic *skel = netdev->priv;
110
111 DBGC ( skel, "SKELETON %p does not yet support close\n", skel );
112 }
113
114 /**
115 * Transmit packet
116 *
117 * @v netdev Network device
118 * @v iobuf I/O buffer
119 * @ret rc Return status code
120 */
skeleton_transmit(struct net_device * netdev,struct io_buffer * iobuf)121 static int skeleton_transmit ( struct net_device *netdev,
122 struct io_buffer *iobuf ) {
123 struct skeleton_nic *skel = netdev->priv;
124
125 DBGC ( skel, "SKELETON %p does not yet support transmit\n", skel );
126 ( void ) iobuf;
127 return -ENOTSUP;
128 }
129
130 /**
131 * Poll for completed and received packets
132 *
133 * @v netdev Network device
134 */
skeleton_poll(struct net_device * netdev)135 static void skeleton_poll ( struct net_device *netdev ) {
136 struct skeleton_nic *skel = netdev->priv;
137
138 /* Not yet implemented */
139 ( void ) skel;
140 }
141
142 /**
143 * Enable or disable interrupts
144 *
145 * @v netdev Network device
146 * @v enable Interrupts should be enabled
147 */
skeleton_irq(struct net_device * netdev,int enable)148 static void skeleton_irq ( struct net_device *netdev, int enable ) {
149 struct skeleton_nic *skel = netdev->priv;
150
151 DBGC ( skel, "SKELETON %p does not yet support interrupts\n", skel );
152 ( void ) enable;
153 }
154
155 /** Skeleton network device operations */
156 static struct net_device_operations skeleton_operations = {
157 .open = skeleton_open,
158 .close = skeleton_close,
159 .transmit = skeleton_transmit,
160 .poll = skeleton_poll,
161 .irq = skeleton_irq,
162 };
163
164 /******************************************************************************
165 *
166 * PCI interface
167 *
168 ******************************************************************************
169 */
170
171 /**
172 * Probe PCI device
173 *
174 * @v pci PCI device
175 * @ret rc Return status code
176 */
skeleton_probe(struct pci_device * pci)177 static int skeleton_probe ( struct pci_device *pci ) {
178 struct net_device *netdev;
179 struct skeleton_nic *skel;
180 int rc;
181
182 /* Allocate and initialise net device */
183 netdev = alloc_etherdev ( sizeof ( *skel ) );
184 if ( ! netdev ) {
185 rc = -ENOMEM;
186 goto err_alloc;
187 }
188 netdev_init ( netdev, &skeleton_operations );
189 skel = netdev->priv;
190 pci_set_drvdata ( pci, netdev );
191 netdev->dev = &pci->dev;
192 memset ( skel, 0, sizeof ( *skel ) );
193
194 /* Fix up PCI device */
195 adjust_pci_device ( pci );
196
197 /* Map registers */
198 skel->regs = ioremap ( pci->membase, SKELETON_BAR_SIZE );
199 if ( ! skel->regs ) {
200 rc = -ENODEV;
201 goto err_ioremap;
202 }
203
204 /* Reset the NIC */
205 if ( ( rc = skeleton_reset ( skel ) ) != 0 )
206 goto err_reset;
207
208 /* Register network device */
209 if ( ( rc = register_netdev ( netdev ) ) != 0 )
210 goto err_register_netdev;
211
212 /* Set initial link state */
213 skeleton_check_link ( netdev );
214
215 return 0;
216
217 unregister_netdev ( netdev );
218 err_register_netdev:
219 skeleton_reset ( skel );
220 err_reset:
221 iounmap ( skel->regs );
222 err_ioremap:
223 netdev_nullify ( netdev );
224 netdev_put ( netdev );
225 err_alloc:
226 return rc;
227 }
228
229 /**
230 * Remove PCI device
231 *
232 * @v pci PCI device
233 */
skeleton_remove(struct pci_device * pci)234 static void skeleton_remove ( struct pci_device *pci ) {
235 struct net_device *netdev = pci_get_drvdata ( pci );
236 struct skeleton_nic *skel = netdev->priv;
237
238 /* Unregister network device */
239 unregister_netdev ( netdev );
240
241 /* Reset card */
242 skeleton_reset ( skel );
243
244 /* Free network device */
245 iounmap ( skel->regs );
246 netdev_nullify ( netdev );
247 netdev_put ( netdev );
248 }
249
250 /** Skeleton PCI device IDs */
251 static struct pci_device_id skeleton_nics[] = {
252 PCI_ROM ( 0x5ce1, 0x5ce1, "skel", "Skeleton", 0 ),
253 };
254
255 /** Skeleton PCI driver */
256 struct pci_driver skeleton_driver __pci_driver = {
257 .ids = skeleton_nics,
258 .id_count = ( sizeof ( skeleton_nics ) / sizeof ( skeleton_nics[0] ) ),
259 .probe = skeleton_probe,
260 .remove = skeleton_remove,
261 };
262