mailer.conf - Add missing send-mail for dma.
[dragonfly.git] / sys / dev / netif / iwl / if_iwl.c
1 /*
2  * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Sepherosa Ziehau <sepherosa@gmail.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  * 
34  */
35
36 #include <sys/param.h>
37 #include <sys/bus.h>
38 #include <sys/endian.h>
39 #include <sys/kernel.h>
40 #include <sys/mbuf.h>
41 #include <sys/module.h>
42 #include <sys/msgport2.h>
43 #include <sys/sysctl.h>
44 #include <sys/socket.h>
45 #include <sys/sockio.h>
46 #include <sys/rman.h>
47
48 #include <net/bpf.h>
49 #include <net/if.h>
50 #include <net/if_arp.h>
51 #include <net/ethernet.h>
52 #include <net/if_dl.h>
53 #include <net/if_media.h>
54 #include <net/netmsg2.h>
55
56 #include <netproto/802_11/ieee80211_var.h>
57 #include <netproto/802_11/ieee80211_radiotap.h>
58
59 #include "pcidevs.h"
60 #include <bus/pci/pcireg.h>
61 #include <bus/pci/pcivar.h>
62
63 #include "if_iwlreg.h"
64 #include "if_iwlvar.h"
65 #include "iwl2100var.h"
66
67 struct iwl_devinfo {
68         const char      *desc;
69         int             bar;
70         int             (*attach)(device_t);
71         void            (*detach)(device_t);
72         int             (*shutdown)(device_t);
73 };
74
75 struct iwl_softc {
76         union {
77                 struct iwlcom common;
78                 struct iwl2100_softc sc2100;
79         } u;
80         const struct iwl_devinfo *sc_info;
81 };
82
83 static int      iwl_probe(device_t);
84 static int      iwl_attach(device_t);
85 static int      iwl_detach(device_t);
86 static int      iwl_shutdown(device_t);
87
88 static void     iwl_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
89 static void     iwl_service_loop(void *);
90 static int      iwl_put_port(struct lwkt_port *, struct lwkt_msg *);
91 static void     iwl_destroy_thread_dispatch(struct netmsg *);
92
93 static const struct iwl_devinfo iwl2100_devinfo = {
94         .desc =         IWL2100_DESC,
95         .bar =          IWL2100_PCIR_BAR,
96         .attach =       iwl2100_attach,
97         .detach =       iwl2100_detach,
98         .shutdown =     iwl2100_shutdown
99 };
100
101 static const struct iwl_dev {
102         uint16_t        vid;
103         uint16_t        did;
104         const struct iwl_devinfo *info;
105 } iwl_devices[] = {
106         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_2100, &iwl2100_devinfo },
107         { 0, 0, NULL }
108 };
109
110 static device_method_t iwl_methods[] = {
111         /* Device interface */
112         DEVMETHOD(device_probe,         iwl_probe),
113         DEVMETHOD(device_attach,        iwl_attach),
114         DEVMETHOD(device_detach,        iwl_detach),
115         DEVMETHOD(device_shutdown,      iwl_shutdown),
116
117         DEVMETHOD_END
118 };
119
120 static driver_t iwl_driver = {
121         "iwl",
122         iwl_methods,
123         sizeof(struct iwl_softc)
124 };
125
126 static devclass_t iwl_devclass;
127
128 DRIVER_MODULE(iwl, pci, iwl_driver, iwl_devclass, NULL, NULL);
129
130 MODULE_DEPEND(iwl, wlan, 1, 1, 1);
131 MODULE_DEPEND(iwl, pci, 1, 1, 1);
132
133 const struct ieee80211_rateset iwl_rateset_11b = { 4, { 2, 4, 11, 22 } };
134
135 static int
136 iwl_probe(device_t dev)
137 {
138         const struct iwl_dev *d;
139         uint16_t did, vid;
140
141         vid = pci_get_vendor(dev);
142         did = pci_get_device(dev);
143
144         for (d = iwl_devices; d->info != NULL; ++d) {
145                 if (d->did == did && d->vid == vid) {
146                         struct iwl_softc *sc = device_get_softc(dev);
147
148                         device_set_desc(dev, d->info->desc);
149                         sc->sc_info = d->info;
150                         return 0;
151                 }
152         }
153         return ENXIO;
154 }
155
156 static int
157 iwl_attach(device_t dev)
158 {
159         struct iwl_softc *sc = device_get_softc(dev);
160         struct iwlcom *iwl = &sc->u.common;
161         struct ifnet *ifp = &iwl->iwl_ic.ic_if;
162         int error, bar;
163
164         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
165         bar = sc->sc_info->bar;
166
167 #ifndef BURN_BRIDGES
168         if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
169                 uint32_t irq, mem;
170
171                 irq = pci_read_config(dev, PCIR_INTLINE, 4);
172                 mem = pci_read_config(dev, bar, 4);
173
174                 device_printf(dev, "chip is in D%d power mode "
175                     "-- setting to D0\n", pci_get_powerstate(dev));
176
177                 pci_set_powerstate(dev, PCI_POWERSTATE_D0);
178
179                 pci_write_config(dev, PCIR_INTLINE, irq, 4);
180                 pci_write_config(dev, bar, mem, 4);
181         }
182 #endif  /* !BURN_BRIDGES */
183
184         /* Enable bus mastering */
185         pci_enable_busmaster(dev);
186
187         /*
188          * Allocate IO memory
189          */
190         iwl->iwl_mem_rid = bar;
191         iwl->iwl_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
192                                                   &iwl->iwl_mem_rid, RF_ACTIVE);
193         if (iwl->iwl_mem_res == NULL) {
194                 device_printf(dev, "can't allocate IO memory\n");
195                 return ENXIO;
196         }
197         iwl->iwl_mem_bt = rman_get_bustag(iwl->iwl_mem_res);
198         iwl->iwl_mem_bh = rman_get_bushandle(iwl->iwl_mem_res);
199
200         /*
201          * Allocate IRQ
202          */
203         iwl->iwl_irq_rid = 0;
204         iwl->iwl_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
205                                                   &iwl->iwl_irq_rid,
206                                                   RF_SHAREABLE | RF_ACTIVE);
207         if (iwl->iwl_irq_res == NULL) {
208                 device_printf(dev, "can't allocate irq\n");
209                 error = ENXIO;
210                 goto back;
211         }
212
213         /*
214          * Device specific attach
215          */
216         error = sc->sc_info->attach(dev);
217 back:
218         if (error)
219                 iwl_detach(dev);
220         return error;
221 }
222
223 static int
224 iwl_detach(device_t dev)
225 {
226         struct iwl_softc *sc = device_get_softc(dev);
227         struct iwlcom *iwl = &sc->u.common;
228
229         sc->sc_info->detach(dev);
230
231         if (iwl->iwl_irq_res != NULL) {
232                 bus_release_resource(dev, SYS_RES_IRQ, iwl->iwl_irq_rid,
233                                      iwl->iwl_irq_res);
234         }
235
236         if (iwl->iwl_mem_res != NULL) {
237                 bus_release_resource(dev, SYS_RES_MEMORY, iwl->iwl_mem_rid,
238                                      iwl->iwl_mem_res);
239         }
240         return 0;
241 }
242
243 static int
244 iwl_shutdown(device_t dev)
245 {
246         struct iwl_softc *sc = device_get_softc(dev);
247
248         return sc->sc_info->shutdown(dev);
249 }
250
251 void
252 iwl_ind_write_4(struct iwlcom *iwl, uint32_t addr, uint32_t data)
253 {
254         IWL_WRITE_4(iwl, IWL_IND_ADDR, addr);
255         IWL_WRITE_4(iwl, IWL_IND_DATA, data);
256 }
257
258 void
259 iwl_ind_write_2(struct iwlcom *iwl, uint32_t addr, uint16_t data)
260 {
261         IWL_WRITE_4(iwl, IWL_IND_ADDR, addr);
262         IWL_WRITE_2(iwl, IWL_IND_DATA, data);
263 }
264
265 void
266 iwl_ind_write_1(struct iwlcom *iwl, uint32_t addr, uint8_t data)
267 {
268         IWL_WRITE_4(iwl, IWL_IND_ADDR, addr);
269         IWL_WRITE_1(iwl, IWL_IND_DATA, data);
270 }
271
272 uint32_t
273 iwl_ind_read_4(struct iwlcom *iwl, uint32_t addr)
274 {
275         IWL_WRITE_4(iwl, IWL_IND_ADDR, addr);
276         return IWL_READ_4(iwl, IWL_IND_DATA);
277 }
278
279 uint16_t
280 iwl_ind_read_2(struct iwlcom *iwl, uint32_t addr)
281 {
282         IWL_WRITE_4(iwl, IWL_IND_ADDR, addr);
283         return IWL_READ_2(iwl, IWL_IND_DATA);
284 }
285
286 uint8_t
287 iwl_ind_read_1(struct iwlcom *iwl, uint32_t addr)
288 {
289         IWL_WRITE_4(iwl, IWL_IND_ADDR, addr);
290         return IWL_READ_1(iwl, IWL_IND_DATA);
291 }
292
293 #define EEPROM_WRITE(iwl, data) \
294 do { \
295         iwl_ind_write_4((iwl), IWL_EEPROM_IND_CSR, (data)); \
296         DELAY(1); \
297 } while (0)
298
299 #define EEPROM_SET_BIT(iwl) \
300 do { \
301         EEPROM_WRITE((iwl), IWL_EEBIT_CS | IWL_EEBIT_DI); \
302         EEPROM_WRITE((iwl), IWL_EEBIT_CS | IWL_EEBIT_DI | IWL_EEBIT_SK); \
303 } while (0)
304
305 #define EEPROM_CLR_BIT(iwl) \
306 do { \
307         EEPROM_WRITE((iwl), IWL_EEBIT_CS); \
308         EEPROM_WRITE((iwl), IWL_EEBIT_CS | IWL_EEBIT_SK); \
309 } while (0)
310
311 uint16_t
312 iwl_read_eeprom(struct iwlcom *iwl, uint8_t ofs)
313 {
314         uint16_t ret;
315         int i;
316
317         /* Chip select */
318         EEPROM_WRITE(iwl, 0);
319         EEPROM_WRITE(iwl, IWL_EEBIT_CS);
320         EEPROM_WRITE(iwl, IWL_EEBIT_CS | IWL_EEBIT_SK);
321         EEPROM_WRITE(iwl, IWL_EEBIT_CS);
322
323         /* Send READ opcode (0x2) */
324         EEPROM_SET_BIT(iwl);
325         EEPROM_SET_BIT(iwl); /* READ opcode */
326         EEPROM_CLR_BIT(iwl); /* READ opcode */
327
328         /* Send offset */
329         for (i = NBBY - 1; i >= 0; --i) {
330                 if (ofs & (1 << i))
331                         EEPROM_SET_BIT(iwl);
332                 else
333                         EEPROM_CLR_BIT(iwl);
334         }
335
336         /* Kick start */
337         EEPROM_WRITE(iwl, IWL_EEBIT_CS);
338
339         /* Read data */
340         ret = 0;
341         for (i = 0; i < (sizeof(ret) * NBBY); ++i) {
342                 EEPROM_WRITE(iwl, IWL_EEBIT_CS | IWL_EEBIT_SK);
343                 EEPROM_WRITE(iwl, IWL_EEBIT_CS);
344
345                 ret <<= 1;
346                 if (iwl_ind_read_4(iwl, IWL_EEPROM_IND_CSR) & IWL_EEBIT_DO)
347                         ret |= 1;
348         }
349
350         /* Stop */
351         EEPROM_WRITE(iwl, 0);
352
353         /* Chip de-select */
354         EEPROM_WRITE(iwl, IWL_EEBIT_CS);
355         EEPROM_WRITE(iwl, 0);
356         EEPROM_WRITE(iwl, IWL_EEBIT_SK);
357
358         return le16toh(ret);
359 }
360
361 static void
362 iwl_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
363 {
364         KASSERT(nseg == 1, ("too many segments"));
365         *((bus_addr_t *)arg) = seg->ds_addr;
366 }
367
368 int
369 iwl_dma_mem_create(device_t dev, bus_dma_tag_t parent, bus_size_t size,
370                    bus_dma_tag_t *dtag, void **addr, bus_addr_t *paddr,
371                    bus_dmamap_t *dmap)
372 {
373         int error;
374
375         error = bus_dma_tag_create(parent, IWL_ALIGN, 0,
376                                    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
377                                    NULL, NULL,
378                                    size, 1, BUS_SPACE_MAXSIZE_32BIT,
379                                    0, dtag);
380         if (error) {
381                 device_printf(dev, "can't create DMA tag\n");
382                 return error;
383         }
384
385         error = bus_dmamem_alloc(*dtag, addr, BUS_DMA_WAITOK | BUS_DMA_ZERO,
386                                  dmap);
387         if (error) {
388                 device_printf(dev, "can't allocate DMA mem\n");
389                 bus_dma_tag_destroy(*dtag);
390                 *dtag = NULL;
391                 return error;
392         }
393
394         error = bus_dmamap_load(*dtag, *dmap, *addr, size,
395                                 iwl_dma_ring_addr, paddr, BUS_DMA_WAITOK);
396         if (error) {
397                 device_printf(dev, "can't load DMA mem\n");
398                 bus_dmamem_free(*dtag, *addr, *dmap);
399                 bus_dma_tag_destroy(*dtag);
400                 *dtag = NULL;
401                 return error;
402         }
403         return 0;
404 }
405
406 void
407 iwl_dma_mem_destroy(bus_dma_tag_t dtag, void *addr, bus_dmamap_t dmap)
408 {
409         if (dtag != NULL) {
410                 bus_dmamap_unload(dtag, dmap);
411                 bus_dmamem_free(dtag, addr, dmap);
412                 bus_dma_tag_destroy(dtag);
413         }
414 }
415
416 void
417 iwl_dma_buf_addr(void *xctx, bus_dma_segment_t *segs, int nsegs,
418                  bus_size_t mapsz __unused, int error)
419 {
420         struct iwl_dmamap_ctx *ctx = xctx;
421         int i;
422
423         if (error)
424                 return;
425
426         if (nsegs > ctx->nsegs) {
427                 ctx->nsegs = 0;
428                 return;
429         }
430
431         ctx->nsegs = nsegs;
432         for (i = 0; i < nsegs; ++i)
433                 ctx->segs[i] = segs[i];
434 }
435
436 static int
437 iwl_put_port(struct lwkt_port *port, struct lwkt_msg *lmsg)
438 {
439         struct iwlmsg *msg = (struct iwlmsg *)lmsg;
440         struct iwlcom *iwl = msg->iwlm_softc;
441
442         ASSERT_SERIALIZED(port->mpu_serialize);
443
444         if ((lmsg->ms_flags & MSGF_SYNC) && curthread == &iwl->iwl_thread) {
445                 msg->iwlm_nmsg.nm_dispatch(&msg->iwlm_nmsg);
446                 if ((lmsg->ms_flags & MSGF_DONE) == 0) {
447                         panic("%s: self-referential deadlock on "
448                               "iwl thread port\n", __func__);
449                 }
450                 return EASYNC;
451         } else {
452                 return iwl->iwl_fwd_port(port, lmsg);
453         }
454 }
455
456 static void
457 iwl_service_loop(void *arg)
458 {
459         struct iwlcom *iwl = arg;
460         struct ifnet *ifp = &iwl->iwl_ic.ic_if;
461         struct netmsg *nmsg;
462
463         get_mplock();
464         lwkt_serialize_enter(ifp->if_serializer);
465         while ((nmsg = lwkt_waitport(&iwl->iwl_thread_port, 0))) {
466                 nmsg->nm_dispatch(nmsg);
467                 if (iwl->iwl_end)
468                         break;
469         }
470         lwkt_serialize_exit(ifp->if_serializer);
471         rel_mplock();
472 }
473
474 void
475 iwl_create_thread(struct iwlcom *iwl, int unit)
476 {
477         struct ifnet *ifp = &iwl->iwl_ic.ic_if;
478
479         lwkt_initport_serialize(&iwl->iwl_reply_port, ifp->if_serializer);
480         lwkt_initport_serialize(&iwl->iwl_thread_port, ifp->if_serializer);
481
482         /* NB: avoid self-reference domsg */
483         iwl->iwl_fwd_port = iwl->iwl_thread_port.mp_putport;
484         iwl->iwl_thread_port.mp_putport = iwl_put_port;
485
486         lwkt_create(iwl_service_loop, iwl, NULL, &iwl->iwl_thread,
487                     0, unit % ncpus, "iwl%d", unit);
488 }
489
490 static void
491 iwl_destroy_thread_dispatch(struct netmsg *nmsg)
492 {
493         struct iwlmsg *msg = (struct iwlmsg *)nmsg;
494         struct iwlcom *iwl = msg->iwlm_softc;
495
496         ASSERT_SERIALIZED(iwl->iwl_ic.ic_if.if_serializer);
497
498         iwl->iwl_end = 1;
499         lwkt_replymsg(&nmsg->nm_lmsg, 0);
500 }
501
502 void
503 iwl_destroy_thread(struct iwlcom *iwl)
504 {
505         struct iwlmsg msg;
506
507         ASSERT_SERIALIZED(iwl->iwl_ic.ic_if.if_serializer);
508
509         iwlmsg_init(&msg, &iwl->iwl_reply_port,
510                     iwl_destroy_thread_dispatch, iwl);
511         lwkt_domsg(&iwl->iwl_thread_port, &msg.iwlm_nmsg.nm_lmsg, 0);
512 }
513
514 void
515 iwlmsg_init(struct iwlmsg *msg, struct lwkt_port *rport, netisr_fn_t dispatch,
516             void *sc)
517 {
518         netmsg_init(&msg->iwlm_nmsg, NULL, rport, 0, dispatch);
519         msg->iwlm_softc = sc;
520 }
521
522 void
523 iwlmsg_send(struct iwlmsg *msg, struct lwkt_port *port)
524 {
525         struct lwkt_msg *lmsg;
526
527         lmsg = &msg->iwlm_nmsg.nm_lmsg;
528         if (lmsg->ms_flags & MSGF_DONE)
529                 lwkt_sendmsg(port, lmsg);
530 }