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