]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/contrib/dev/oltr/if_oltr.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / contrib / dev / oltr / if_oltr.c
1 /*
2  * Copyright (c) 1998, Larry Lile
3  * All rights reserved.
4  *
5  * For latest sources and information on this driver, please
6  * go to http://anarchy.stdio.com.
7  *
8  * Questions, comments or suggestions should be directed to
9  * Larry Lile <lile@stdio.com>.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice unmodified, this list of conditions, and the following
16  *    disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * $FreeBSD$
34  */
35
36 #include <sys/param.h>
37 #include <sys/sockio.h>
38 #include <sys/malloc.h>
39 #include <sys/kernel.h>
40 #include <sys/module.h>
41 #include <sys/socket.h>
42
43 #include <net/if.h>
44 #include <net/if_dl.h>
45 #include <net/iso88025.h>
46 #include <net/if_media.h>
47 #include <net/if_types.h>
48 #include <net/bpf.h>
49
50 #ifndef BPF_MTAP
51 #define BPF_MTAP(_ifp, _m) do {                         \
52         if ((_ifp)->if_bpf)                             \
53                 bpf_mtap((_ifp), (_m));                 \
54 } while (0)
55 #endif
56
57 #include <vm/vm.h>              /* for vtophys */
58 #include <vm/pmap.h>            /* for vtophys */
59
60 #include <machine/bus.h>
61 #include <machine/resource.h>
62
63 #include <sys/bus.h>
64 #include <sys/rman.h>
65
66 #include "contrib/dev/oltr/trlld.h"
67 #include "contrib/dev/oltr/if_oltrvar.h"
68
69 /*
70  * Glue function prototypes for PMW kit IO
71  */
72
73 #ifndef TRlldInlineIO
74 static void DriverOutByte       __P((unsigned short, unsigned char));
75 static void DriverOutWord       __P((unsigned short, unsigned short));
76 static void DriverOutDword      __P((unsigned short, unsigned long));
77 static void DriverRepOutByte    __P((unsigned short, unsigned char  *, int));
78 static void DriverRepOutWord    __P((unsigned short, unsigned short *, int));
79 static void DriverRepOutDword   __P((unsigned short, unsigned long  *, int));
80 static unsigned char  DriverInByte __P((unsigned short));
81 static unsigned short DriverInWord __P((unsigned short));
82 static unsigned long  DriverInDword __P((unsigned short));
83 static void DriverRepInByte     __P((unsigned short, unsigned char  *, int));
84 static void DriverRepInWord     __P((unsigned short, unsigned short *, int));
85 static void DriverRepInDword    __P((unsigned short, unsigned long  *, int));
86 #endif /*TRlldInlineIO*/
87 static void DriverSuspend       __P((unsigned short));
88 static void DriverStatus        __P((void *, TRlldStatus_t *));
89 static void DriverCloseCompleted __P((void *));
90 static void DriverStatistics    __P((void *, TRlldStatistics_t *));
91 static void DriverTransmitFrameCompleted __P((void *, void *, int));
92 static void DriverReceiveFrameCompleted __P((void *, int, int, void *, int));
93
94 TRlldDriver_t LldDriver = {
95         TRLLD_VERSION,
96 #ifndef TRlldInlineIO
97         DriverOutByte,
98         DriverOutWord,
99         DriverOutDword,
100         DriverRepOutByte,
101         DriverRepOutWord,
102         DriverRepOutDword,
103         DriverInByte,
104         DriverInWord,
105         DriverInDword,
106         DriverRepInByte,
107         DriverRepInWord,
108         DriverRepInDword,
109 #endif /*TRlldInlineIO*/
110         DriverSuspend,
111         DriverStatus,
112         DriverCloseCompleted,
113         DriverStatistics,
114         DriverTransmitFrameCompleted,
115         DriverReceiveFrameCompleted,
116 };
117
118
119 static void oltr_start          __P((struct ifnet *));
120 static void oltr_close          __P((struct oltr_softc *));
121 static void oltr_init           __P((void *));
122 static int oltr_ioctl           __P((struct ifnet *, u_long, caddr_t));
123 static void oltr_intr           __P((void *));
124 static int oltr_ifmedia_upd     __P((struct ifnet *));
125 static void oltr_ifmedia_sts    __P((struct ifnet *, struct ifmediareq *));
126
127
128
129 int
130 oltr_attach(device_t dev)
131 {
132
133         struct oltr_softc               *sc = device_get_softc(dev);
134         struct ifnet            *ifp;
135         int             rc = 0;
136         int             media = IFM_TOKEN|IFM_TOK_UTP16;
137
138         ifp = sc->ifp = if_alloc(IFT_ISO88025);
139         if (ifp == NULL) {
140                 device_printf(dev, "couldn't if_alloc()");
141                 return (-1);
142         }
143         
144         /*
145          * Allocate interrupt and DMA channel
146          */
147
148         sc->irq_rid = 0;
149         sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
150                 (sc->config.mode & TRLLD_MODE_SHARE_INTERRUPT) ?
151                 RF_ACTIVE | RF_SHAREABLE : RF_ACTIVE);
152         if (sc->irq_res == NULL) {
153                 device_printf(dev, "couldn't map interrupt\n");
154                 if_free(ifp);
155                 return (-1);
156         }
157         if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, NULL, oltr_intr,
158                         sc, &sc-> oltr_intrhand)) {
159                 device_printf(dev, "couldn't setup interrupt\n");
160                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
161                 if_free(ifp);
162                 return (-1);
163         }
164
165         /*
166          * Do the ifnet initialization
167          */
168         ifp->if_softc   = sc;
169         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
170         ifp->if_init    = oltr_init;
171         ifp->if_start   = oltr_start;
172         ifp->if_ioctl   = oltr_ioctl;
173         ifp->if_flags   = IFF_BROADCAST | IFF_NEEDSGIANT;
174         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
175
176         /*
177          * Do ifmedia setup.
178          */
179         ifmedia_init(&sc->ifmedia, 0, oltr_ifmedia_upd, oltr_ifmedia_sts);
180         rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
181         switch(sc->config.type) {
182         case TRLLD_ADAPTER_PCI7:        /* OC-3540 */
183                 ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP100, 0, NULL);
184                 /* FALL THROUGH */
185         case TRLLD_ADAPTER_PCI4:        /* OC-3139 */
186         case TRLLD_ADAPTER_PCI5:        /* OC-3140 */
187         case TRLLD_ADAPTER_PCI6:        /* OC-3141 */
188                 ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_AUTO, 0, NULL);
189                 media = IFM_TOKEN|IFM_AUTO;
190                 rc = TRlldSetSpeed(sc->TRlldAdapter, 0);
191                 /* FALL THROUGH */
192         default:
193                 ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP4, 0, NULL);
194                 ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16, 0, NULL);
195                 break;
196         }
197         sc->ifmedia.ifm_media = media;
198         ifmedia_set(&sc->ifmedia, media);
199
200         /*
201          * Attach the interface
202          */
203
204         iso88025_ifattach(ifp, sc->config.macaddress, ISO88025_BPF_SUPPORTED);
205
206         return(0);
207 }
208
209
210 static void
211 oltr_intr(void *xsc)
212 {
213         struct oltr_softc               *sc = (struct oltr_softc *)xsc;
214
215         if (DEBUG_MASK & DEBUG_INT)
216                 printf("I");
217
218         TRlldInterruptService(sc->TRlldAdapter);
219
220         return;
221 }
222
223 static void
224 oltr_start(struct ifnet *ifp)
225 {
226         struct oltr_softc       *sc = ifp->if_softc;
227         struct mbuf             *m0, *m;
228         int                     copy_len, buffer, frame, fragment, rc, s;
229         
230         /*
231          * Check to see if output is already active
232          */
233         if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
234                 return;
235
236 outloop:
237
238         /*
239          * Make sure we have buffers to transmit with
240          */
241         if (sc->tx_avail <= 0) {
242                 printf("oltr%d: tx queue full\n", sc->unit);
243                 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
244                 return;
245         }
246
247         if (sc->restart == NULL) {
248                 IF_DEQUEUE(&ifp->if_snd, m);
249                 if (m == NULL)
250                         return;
251         } else {
252                 m = sc->restart;
253                 sc->restart = NULL;
254         }
255
256         m0 = m;
257         frame = RING_BUFFER(sc->tx_frame);
258         buffer = RING_BUFFER(sc->tx_head);
259         fragment = 0;
260         copy_len = 0;
261         sc->frame_ring[frame].FragmentCount = 0;
262         
263         while (copy_len < m0->m_pkthdr.len) {
264                 sc->frame_ring[frame].FragmentCount++;
265                 if (sc->frame_ring[frame].FragmentCount > sc->tx_avail)
266                         goto nobuffers;
267                 sc->frame_ring[frame].TransmitFragment[fragment].VirtualAddress = sc->tx_ring[buffer].data;
268                 sc->frame_ring[frame].TransmitFragment[fragment].PhysicalAddress = sc->tx_ring[buffer].address;
269                 sc->frame_ring[frame].TransmitFragment[fragment].count = MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN);
270                 m_copydata(m0, copy_len, MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN), sc->tx_ring[buffer].data);
271                 copy_len += MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN);
272                 fragment++;
273                 buffer = RING_BUFFER((buffer + 1));
274         }
275
276         s = splimp();
277         rc = TRlldTransmitFrame(sc->TRlldAdapter, &sc->frame_ring[frame], (void *)&sc->frame_ring[frame]);
278         (void)splx(s);
279
280         if (rc != TRLLD_TRANSMIT_OK) {
281                 printf("oltr%d: TRlldTransmitFrame returned %d\n", sc->unit, rc);
282                 ifp->if_oerrors++;
283                 goto bad;
284         }
285
286         sc->tx_avail -= sc->frame_ring[frame].FragmentCount;
287         sc->tx_head = RING_BUFFER((sc->tx_head + sc->frame_ring[frame].FragmentCount));
288         sc->tx_frame++;
289
290         BPF_MTAP(ifp, m0);
291         /*ifp->if_opackets++;*/
292
293 bad:
294         m_freem(m0);
295
296         goto outloop;
297
298 nobuffers:
299
300         printf("oltr%d: queue full\n", sc->unit);
301         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
302         ifp->if_oerrors++;
303         /*m_freem(m0);*/
304         sc->restart = m0;
305
306         return;
307 }
308
309 static void
310 oltr_close(struct oltr_softc *sc)
311 {
312         /*printf("oltr%d: oltr_close\n", sc->unit);*/
313
314         oltr_stop(sc);
315
316         tsleep(sc, PWAIT, "oltrclose", 30*hz);
317 }
318
319 void
320 oltr_stop(struct oltr_softc *sc)
321 {
322         struct ifnet            *ifp = sc->ifp;
323
324         /*printf("oltr%d: oltr_stop\n", sc->unit);*/
325
326         ifp->if_flags &= ~IFF_UP;
327         ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
328         TRlldClose(sc->TRlldAdapter, 0);
329         sc->state = OL_CLOSING;
330 }
331
332 static void
333 oltr_init(void * xsc)
334 {
335         struct oltr_softc       *sc = (struct oltr_softc *)xsc;
336         struct ifnet            *ifp = sc->ifp;
337         struct ifmedia          *ifm = &sc->ifmedia;
338         int                     poll = 0, i, rc = 0, s;
339         int                     work_size;
340
341         /*
342          * Check adapter state, don't allow multiple inits
343          */
344         if (sc->state > OL_CLOSED) {
345                 printf("oltr%d: adapter not ready\n", sc->unit);
346                 return;
347         }
348
349         s = splimp();
350
351         /*
352          * Initialize Adapter
353          */
354         if ((rc = TRlldAdapterInit(&LldDriver, sc->TRlldAdapter, sc->TRlldAdapter_phys,
355             (void *)sc, &sc->config)) != TRLLD_INIT_OK) {
356                 switch(rc) {
357                 case TRLLD_INIT_NOT_FOUND:
358                         printf("oltr%d: adapter not found\n", sc->unit);
359                         break;
360                 case TRLLD_INIT_UNSUPPORTED:
361                         printf("oltr%d: adapter not supported by low level driver\n", sc->unit);
362                         break;
363                 case TRLLD_INIT_PHYS16:
364                         printf("oltr%d: adapter memory block above 16M cannot DMA\n", sc->unit);
365                         break;
366                 case TRLLD_INIT_VERSION:
367                         printf("oltr%d: low level driver version mismatch\n", sc->unit);
368                         break;
369                 default:
370                         printf("oltr%d: unknown init error %d\n", sc->unit, rc);
371                         break;
372                 }
373                 goto init_failed;
374         }
375         sc->state = OL_INIT;
376
377         switch(sc->config.type) {
378         case TRLLD_ADAPTER_PCI4:        /* OC-3139 */
379                 work_size = 32 * 1024;
380                 break;
381         case TRLLD_ADAPTER_PCI7:        /* OC-3540 */
382                 work_size = 256;
383                 break;
384         default:
385                 work_size = 0;
386         }
387
388         if (work_size) {
389                 if ((sc->work_memory = malloc(work_size, M_DEVBUF, M_NOWAIT)) == NULL) {
390                         printf("oltr%d: failed to allocate work memory (%d octets).\n", sc->unit, work_size);
391                 } else {
392                 TRlldAddMemory(sc->TRlldAdapter, sc->work_memory,
393                     vtophys(sc->work_memory), work_size);
394                 }
395         }
396
397         switch(IFM_SUBTYPE(ifm->ifm_media)) {
398         case IFM_AUTO:
399                 rc = TRlldSetSpeed(sc->TRlldAdapter, 0); /* TRLLD_SPEED_AUTO */
400                 break;
401         case IFM_TOK_UTP4:
402                 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_4MBPS);
403                 break;
404         case IFM_TOK_UTP16:
405                 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
406                 break;
407         case IFM_TOK_UTP100:
408                 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_100MBPS);
409                 break;
410         }
411
412         /*
413          * Download adapter micro-code
414          */
415         if (bootverbose)
416                 printf("oltr%d: Downloading adapter microcode: ", sc->unit);
417
418         switch(sc->config.mactype) {
419         case TRLLD_MAC_TMS:
420                 rc = TRlldDownload(sc->TRlldAdapter, TRlldMacCode);
421                 if (bootverbose)
422                         printf("TMS-380");
423                 break;
424         case TRLLD_MAC_HAWKEYE:
425                 rc = TRlldDownload(sc->TRlldAdapter, TRlldHawkeyeMac);
426                 if (bootverbose)
427                         printf("Hawkeye");
428                 break;
429         case TRLLD_MAC_BULLSEYE:
430                 rc = TRlldDownload(sc->TRlldAdapter, TRlldBullseyeMac);
431                 if (bootverbose)
432                         printf("Bullseye");
433                 break;
434         default:
435                 if (bootverbose)
436                         printf("unknown - failed!\n");
437                 goto init_failed;
438                 break;
439         }
440
441         /*
442          * Check download status
443          */
444         switch(rc) {
445         case TRLLD_DOWNLOAD_OK:
446                 if (bootverbose)
447                         printf(" - ok\n");
448                 break;
449         case TRLLD_DOWNLOAD_ERROR:
450                 if (bootverbose)
451                         printf(" - failed\n");
452                 else
453                         printf("oltr%d: adapter microcode download failed\n", sc->unit);
454                 goto init_failed;
455                 break;
456         case TRLLD_STATE:
457                 if (bootverbose)
458                         printf(" - not ready\n");
459                 goto init_failed;
460                 break;
461         }
462
463         /*
464          * Wait for self-test to complete
465          */
466         i = 0;
467         while ((poll++ < SELF_TEST_POLLS) && (sc->state < OL_READY)) {
468                 if (DEBUG_MASK & DEBUG_INIT)
469                         printf("p");
470                 DELAY(TRlldPoll(sc->TRlldAdapter) * 1000);
471                 if (TRlldInterruptService(sc->TRlldAdapter) != 0)
472                         if (DEBUG_MASK & DEBUG_INIT) printf("i");
473         }
474
475         if (sc->state != OL_CLOSED) {
476                 printf("oltr%d: self-test failed\n", sc->unit);
477                 goto init_failed;
478         }
479
480         /*
481          * Set up adapter poll
482          */
483         callout_handle_init(&sc->oltr_poll_ch);
484         sc->oltr_poll_ch = timeout(oltr_poll, (void *)sc, 1);
485
486         sc->state = OL_OPENING;
487
488         /*
489          * Open the adapter
490          */
491         rc = TRlldOpen(sc->TRlldAdapter, IF_LLADDR(sc->ifp), sc->GroupAddress,
492                 sc->FunctionalAddress, 1552, sc->AdapterMode);
493         switch(rc) {
494                 case TRLLD_OPEN_OK:
495                         break;
496                 case TRLLD_OPEN_STATE:
497                         printf("oltr%d: adapter not ready for open\n", sc->unit);
498                         (void)splx(s);
499                         return;
500                 case TRLLD_OPEN_ADDRESS_ERROR:
501                         printf("oltr%d: illegal MAC address\n", sc->unit);
502                         (void)splx(s);
503                         return;
504                 case TRLLD_OPEN_MODE_ERROR:
505                         printf("oltr%d: illegal open mode\n", sc->unit);
506                         (void)splx(s);
507                         return;
508                 default:
509                         printf("oltr%d: unknown open error (%d)\n", sc->unit, rc);
510                         (void)splx(s);
511                         return;
512         }
513
514         /*
515          * Set promiscious mode for now...
516          */
517         TRlldSetPromiscuousMode(sc->TRlldAdapter, TRLLD_PROM_LLC);
518         ifp->if_flags |= IFF_PROMISC;
519
520         /*
521          * Block on the ring insert and set a timeout
522          */
523         tsleep(sc, PWAIT, "oltropen", 30*hz);
524
525         /*
526          * Set up receive buffer ring
527          */
528         for (i = 0; i < RING_BUFFER_LEN; i++) {
529                 rc = TRlldReceiveFragment(sc->TRlldAdapter, (void *)sc->rx_ring[i].data,
530                         sc->rx_ring[i].address, RX_BUFFER_LEN, (void *)sc->rx_ring[i].index);
531                 if (rc != TRLLD_RECEIVE_OK) {
532                         printf("oltr%d: adapter refused receive fragment %d (rc = %d)\n", sc->unit, i, rc);
533                         break;
534                 }       
535         }
536
537         sc->tx_avail = RING_BUFFER_LEN;
538         sc->tx_head = 0;
539         sc->tx_frame = 0;
540
541         sc->restart = NULL;
542
543         ifp->if_drv_flags |= IFF_DRV_RUNNING;
544         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
545
546         /*
547          * Set up adapter statistics poll
548          */
549         /*callout_handle_init(&sc->oltr_stat_ch);*/
550         /*sc->oltr_stat_ch = timeout(oltr_stat, (void *)sc, 1*hz);*/
551
552         (void)splx(s);
553         return;
554
555 init_failed:
556         sc->state = OL_DEAD;
557         (void)splx(s);
558         return;
559 }
560
561 static int
562 oltr_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
563 {
564         struct oltr_softc       *sc = ifp->if_softc;
565         struct ifreq            *ifr = (struct ifreq *)data;
566         int                     error = 0, s;
567
568         s = splimp();
569
570         switch(command) {
571         case SIOCSIFADDR:
572         case SIOCGIFADDR:
573         case SIOCSIFMTU:
574                 error = iso88025_ioctl(ifp, command, data);
575                 break;
576
577         case SIOCSIFFLAGS:
578                 if (ifp->if_flags & IFF_UP) {
579                         oltr_init(sc);
580                 } else {
581                         if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
582                                 oltr_close(sc);
583                         }
584                 }
585                 break;
586         case SIOCGIFMEDIA:
587         case SIOCSIFMEDIA:
588                 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
589                 break;
590         default:
591                 error = EINVAL;
592                 break;
593         }
594
595         (void)splx(s);  
596
597         return(error);
598 }
599
600
601 void
602 oltr_poll(void *arg)
603 {
604         struct oltr_softc *sc = (struct oltr_softc *)arg;
605         int s;
606
607         s = splimp();
608
609         if (DEBUG_MASK & DEBUG_POLL) printf("P");
610
611         /* Set up next adapter poll */
612         sc->oltr_poll_ch = timeout(oltr_poll, (void *)sc, (TRlldPoll(sc->TRlldAdapter) * hz / 1000));
613
614         (void)splx(s);
615 }
616
617 #ifdef NOTYET
618 void
619 oltr_stat(void *arg)
620 {
621         struct oltr_softc       *sc = (struct oltr_softc *)arg;
622         int                     s;
623
624         s = splimp();
625
626         /* Set up next adapter poll */
627         sc->oltr_stat_ch = timeout(oltr_stat, (void *)sc, 1*hz);
628         if (TRlldGetStatistics(sc->TRlldAdapter, &sc->current, 0) != 0) {
629                 /*printf("oltr%d: statistics available immediately...\n", sc->unit);*/
630                 DriverStatistics((void *)sc, &sc->current);
631         }
632
633         (void)splx(s);
634 }
635 #endif
636 static int
637 oltr_ifmedia_upd(struct ifnet *ifp)
638 {
639         struct oltr_softc       *sc = ifp->if_softc;
640         struct ifmedia          *ifm = &sc->ifmedia;
641         int                     rc;
642
643         if (IFM_TYPE(ifm->ifm_media) != IFM_TOKEN)
644                 return(EINVAL);
645
646         switch(IFM_SUBTYPE(ifm->ifm_media)) {
647         case IFM_AUTO:
648                 rc = TRlldSetSpeed(sc->TRlldAdapter, 0); /* TRLLD_SPEED_AUTO */
649                 break;
650         case IFM_TOK_UTP4:
651                 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_4MBPS);
652                 break;
653         case IFM_TOK_UTP16:
654                 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
655                 break;
656         case IFM_TOK_UTP100:
657                 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_100MBPS);
658                 break;
659         default:
660                 return(EINVAL);
661                 break;
662         }
663
664         return(0);
665
666 }
667
668 static void
669 oltr_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
670 {
671         struct oltr_softc       *sc = ifp->if_softc;
672         struct ifmedia          *ifm = &sc->ifmedia;
673
674         /*printf("oltr%d: oltr_ifmedia_sts\n", sc->unit);*/
675
676         ifmr->ifm_active = IFM_TYPE(ifm->ifm_media)|IFM_SUBTYPE(ifm->ifm_media);
677
678 }
679
680 /*
681  * ---------------------- PMW Callback Functions -----------------------
682  */
683
684 void
685 DriverStatistics(void *DriverHandle, TRlldStatistics_t *statistics)
686 {
687 #ifdef NOTYET
688         struct oltr_softc               *sc = (struct oltr_softc *)DriverHandle;
689
690         if (sc->statistics.LineErrors != statistics->LineErrors)
691                 printf("oltr%d: Line Errors %lu\n", sc->unit,
692                     statistics->LineErrors);
693         if (sc->statistics.InternalErrors != statistics->InternalErrors)
694                 printf("oltr%d: Internal Errors %lu\n", sc->unit,
695                     statistics->InternalErrors);
696         if (sc->statistics.BurstErrors != statistics->BurstErrors)
697                 printf("oltr%d: Burst Errors %lu\n", sc->unit,
698                     statistics->BurstErrors);
699         if (sc->statistics.AbortDelimiters != statistics->AbortDelimiters)
700                 printf("oltr%d: Abort Delimiters %lu\n", sc->unit,
701                     statistics->AbortDelimiters);
702         if (sc->statistics.ARIFCIErrors != statistics->ARIFCIErrors)
703                 printf("oltr%d: ARIFCI Errors %lu\n", sc->unit,
704                     statistics->ARIFCIErrors);
705         if (sc->statistics.LostFrames != statistics->LostFrames)
706                 printf("oltr%d: Lost Frames %lu\n", sc->unit,
707                     statistics->LostFrames);
708         if (sc->statistics.CongestionErrors != statistics->CongestionErrors)
709                 printf("oltr%d: Congestion Errors %lu\n", sc->unit,
710                     statistics->CongestionErrors);
711         if (sc->statistics.FrequencyErrors != statistics->FrequencyErrors)
712                 printf("oltr%d: Frequency Errors %lu\n", sc->unit,
713                     statistics->FrequencyErrors);
714         if (sc->statistics.TokenErrors != statistics->TokenErrors)
715                 printf("oltr%d: Token Errors %lu\n", sc->unit,
716                     statistics->TokenErrors);
717         if (sc->statistics.DMABusErrors != statistics->DMABusErrors)
718                 printf("oltr%d: DMA Bus Errors %lu\n", sc->unit,
719                     statistics->DMABusErrors);
720         if (sc->statistics.DMAParityErrors != statistics->DMAParityErrors)
721                 printf("oltr%d: DMA Parity Errors %lu\n", sc->unit,
722                     statistics->DMAParityErrors);
723         if (sc->statistics.ReceiveLongFrame != statistics->ReceiveLongFrame)
724                 printf("oltr%d: Long frames received %lu\n", sc->unit,
725                     statistics->ReceiveLongFrame);
726         if (sc->statistics.ReceiveCRCErrors != statistics->ReceiveCRCErrors)
727                 printf("oltr%d: Receive CRC Errors %lu\n", sc->unit,
728                     statistics->ReceiveCRCErrors);
729         if (sc->statistics.ReceiveOverflow != statistics->ReceiveOverflow)
730                 printf("oltr%d: Recieve overflows %lu\n", sc->unit,
731                     statistics->ReceiveOverflow);
732         if (sc->statistics.TransmitUnderrun != statistics->TransmitUnderrun)
733                 printf("oltr%d: Frequency Errors %lu\n", sc->unit,
734                     statistics->TransmitUnderrun);
735         bcopy(statistics, &sc->statistics, sizeof(TRlldStatistics_t));
736 #endif
737 }
738
739 static void
740 DriverSuspend(unsigned short MicroSeconds)
741 {
742     DELAY(MicroSeconds);
743 }
744
745
746 static void
747 DriverStatus(void *DriverHandle, TRlldStatus_t *Status)
748 {
749         struct oltr_softc       *sc = (struct oltr_softc *)DriverHandle;
750         struct ifnet            *ifp = sc->ifp;
751
752         char *Protocol[] = { /* 0 */ "Unknown",
753                              /* 1 */ "TKP",
754                              /* 2 */ "TXI" };
755         char *Timeout[]  = { /* 0 */ "command",
756                              /* 1 */ "transmit",
757                              /* 2 */ "interrupt" };
758         
759         switch (Status->Type) {
760
761         case TRLLD_STS_ON_WIRE:
762                 printf("oltr%d: ring insert (%d Mbps - %s)\n", sc->unit,
763                     Status->Specification.OnWireInformation.Speed,
764                     Protocol[Status->Specification.OnWireInformation.AccessProtocol]);
765                 sc->state = OL_OPEN;
766                 wakeup(sc);
767                 break;
768         case TRLLD_STS_SELFTEST_STATUS:
769                 if (Status->Specification.SelftestStatus == TRLLD_ST_OK) {
770                         sc->state = OL_CLOSED;
771                         if (bootverbose)
772                                 printf("oltr%d: self test complete\n", sc->unit);
773                 }
774                 if (Status->Specification.SelftestStatus & TRLLD_ST_ERROR) {
775                         printf("oltr%d: Adapter self test error %d", sc->unit,
776                         Status->Specification.SelftestStatus & ~TRLLD_ST_ERROR);
777                         sc->state = OL_DEAD;
778                 }
779                 if (Status->Specification.SelftestStatus & TRLLD_ST_TIMEOUT) {
780                         printf("oltr%d: Adapter self test timed out.\n", sc->unit);
781                         sc->state = OL_DEAD;
782                 }
783                 break;
784         case TRLLD_STS_INIT_STATUS:
785                 if (Status->Specification.InitStatus == 0x800) {
786                         oltr_stop(sc);
787                         ifmedia_set(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16);
788                         TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
789                         oltr_init(sc);
790                         break;
791                 }
792                 printf("oltr%d: adapter init failure 0x%03x\n", sc->unit,
793                     Status->Specification.InitStatus);
794                 oltr_stop(sc);
795                 break;
796         case TRLLD_STS_RING_STATUS:
797                 if (Status->Specification.RingStatus) {
798                         printf("oltr%d: Ring status change: ", sc->unit);
799                         if (Status->Specification.RingStatus &
800                             TRLLD_RS_SIGNAL_LOSS)
801                                 printf(" [Signal Loss]");
802                         if (Status->Specification.RingStatus &
803                             TRLLD_RS_HARD_ERROR)
804                                 printf(" [Hard Error]");
805                         if (Status->Specification.RingStatus &
806                             TRLLD_RS_SOFT_ERROR)
807                                 printf(" [Soft Error]");
808                         if (Status->Specification.RingStatus &
809                             TRLLD_RS_TRANSMIT_BEACON)
810                                 printf(" [Beacon]");
811                         if (Status->Specification.RingStatus &
812                             TRLLD_RS_LOBE_WIRE_FAULT)
813                                 printf(" [Wire Fault]");
814                         if (Status->Specification.RingStatus &
815                             TRLLD_RS_AUTO_REMOVAL_ERROR)
816                                 printf(" [Auto Removal]");
817                         if (Status->Specification.RingStatus &
818                             TRLLD_RS_REMOVE_RECEIVED)
819                                 printf(" [Remove Received]");
820                         if (Status->Specification.RingStatus &
821                             TRLLD_RS_COUNTER_OVERFLOW)
822                                 printf(" [Counter Overflow]");
823                         if (Status->Specification.RingStatus &
824                             TRLLD_RS_SINGLE_STATION)
825                                 printf(" [Single Station]");
826                         if (Status->Specification.RingStatus &
827                                 TRLLD_RS_RING_RECOVERY)
828                                 printf(" [Ring Recovery]");
829                         printf("\n");   
830                 }
831                 break;
832         case TRLLD_STS_ADAPTER_CHECK:
833                 printf("oltr%d: adapter check (%04x %04x %04x %04x)\n", sc->unit,
834                     Status->Specification.AdapterCheck[0],
835                     Status->Specification.AdapterCheck[1],
836                     Status->Specification.AdapterCheck[2],
837                     Status->Specification.AdapterCheck[3]);
838                 sc->state = OL_DEAD;
839                 oltr_stop(sc);
840                 break;
841         case TRLLD_STS_PROMISCUOUS_STOPPED:
842                 printf("oltr%d: promiscuous mode ", sc->unit);
843                 if (Status->Specification.PromRemovedCause == 1)
844                         printf("remove received.");
845                 if (Status->Specification.PromRemovedCause == 2)
846                         printf("poll failure.");
847                 if (Status->Specification.PromRemovedCause == 2)
848                         printf("buffer size failure.");
849                 printf("\n");
850                 ifp->if_flags &= ~IFF_PROMISC;
851                 break;
852         case TRLLD_STS_LLD_ERROR:
853                 printf("oltr%d: low level driver internal error ", sc->unit);
854                 printf("(%04x %04x %04x %04x).\n",
855                     Status->Specification.InternalError[0],
856                     Status->Specification.InternalError[1],
857                     Status->Specification.InternalError[2],
858                     Status->Specification.InternalError[3]);
859                 sc->state = OL_DEAD;
860                 oltr_stop(sc);
861                 break;
862         case TRLLD_STS_ADAPTER_TIMEOUT:
863                 printf("oltr%d: adapter %s timeout.\n", sc->unit,
864                     Timeout[Status->Specification.AdapterTimeout]);
865                 break;
866         default:
867                 printf("oltr%d: driver status Type = %d\n", sc->unit, Status->Type);
868                 break;
869
870         }
871         if (Status->Closed) {
872                 sc->state = OL_CLOSING;
873                 oltr_stop(sc);
874         }
875
876 }
877
878 static void
879 DriverCloseCompleted(void *DriverHandle)
880 {
881         struct oltr_softc               *sc = (struct oltr_softc *)DriverHandle;
882         
883         printf("oltr%d: adapter closed\n", sc->unit);
884         wakeup(sc);
885         sc->state = OL_CLOSED;
886 }
887
888 static void
889 DriverTransmitFrameCompleted(void *DriverHandle, void *FrameHandle, int TransmitStatus)
890 {
891         struct oltr_softc       *sc = (struct oltr_softc *)DriverHandle;
892         struct ifnet            *ifp = sc->ifp;
893         TRlldTransmit_t         *frame = (TRlldTransmit_t *)FrameHandle;
894         
895         /*printf("oltr%d: DriverTransmitFrameCompleted\n", sc->unit);*/
896
897         if (TransmitStatus != TRLLD_TRANSMIT_OK) {
898                 ifp->if_oerrors++;
899                 printf("oltr%d: transmit error %d\n", sc->unit, TransmitStatus);
900         } else {
901                 ifp->if_opackets++;
902         }
903         
904         sc->tx_avail += frame->FragmentCount;
905
906         if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
907                 printf("oltr%d: queue restart\n", sc->unit);
908                 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
909                 oltr_start(ifp);
910         }
911
912
913 }
914
915 static void
916 DriverReceiveFrameCompleted(void *DriverHandle, int ByteCount, int FragmentCount, void *FragmentHandle, int ReceiveStatus)
917 {
918         struct oltr_softc       *sc = (struct oltr_softc *)DriverHandle;
919         struct ifnet            *ifp = sc->ifp;
920         struct mbuf             *m0, *m1, *m;
921         int                     frame_len = ByteCount, i = (int)FragmentHandle, rc, s;
922         int                     mbuf_offset, mbuf_size, frag_offset, copy_length;
923         char                    *fragment = sc->rx_ring[RING_BUFFER(i)].data;
924         
925         if (sc->state > OL_CLOSED) {
926                 if (ReceiveStatus == TRLLD_RCV_OK) {
927                         MGETHDR(m0, M_DONTWAIT, MT_DATA);
928                         mbuf_size = MHLEN - 2;
929                         if (!m0) {
930                                 ifp->if_ierrors++;
931                                 goto dropped;
932                         }
933                         if (ByteCount + 2 > MHLEN) {
934                                 MCLGET(m0, M_DONTWAIT);
935                                 mbuf_size = MCLBYTES - 2;
936                                 if (!(m0->m_flags & M_EXT)) {
937                                         m_freem(m0);
938                                         ifp->if_ierrors++;
939                                         goto dropped;
940                                 }
941                         }
942                         m0->m_pkthdr.rcvif = ifp;
943                         m0->m_pkthdr.len = ByteCount;
944                         m0->m_len = 0;
945                         m0->m_data += 2;
946
947                         m = m0;
948                         mbuf_offset = 0;
949                         frag_offset = 0;
950                         while (frame_len) {
951                                 copy_length = MIN3(frame_len,
952                                     (RX_BUFFER_LEN - frag_offset),
953                                     (mbuf_size - mbuf_offset));
954                                 bcopy(fragment + frag_offset, mtod(m, char *) +
955                                     mbuf_offset, copy_length);
956                                 m->m_len += copy_length;
957                                 mbuf_offset += copy_length;
958                                 frag_offset += copy_length;
959                                 frame_len -= copy_length;
960                         
961                                 if (frag_offset == RX_BUFFER_LEN) {
962                                         fragment =
963                                             sc->rx_ring[RING_BUFFER(++i)].data;
964                                         frag_offset = 0;
965                                 }
966                                 if ((mbuf_offset == mbuf_size) && (frame_len > 0)) {
967                                         MGET(m1, M_DONTWAIT, MT_DATA);
968                                         mbuf_size = MHLEN;
969                                         if (!m1) {
970                                                 ifp->if_ierrors++;
971                                                 m_freem(m0);
972                                                 goto dropped;
973                                         }
974                                         if (frame_len > MHLEN) {
975                                                 MCLGET(m1, M_DONTWAIT);
976                                                 mbuf_size = MCLBYTES;
977                                                 if (!(m1->m_flags & M_EXT)) {
978                                                         m_freem(m0);
979                                                         m_freem(m1);
980                                                         ifp->if_ierrors++;
981                                                         goto dropped;
982                                                 }
983                                         }
984                                         m->m_next = m1;
985                                         m = m1;
986                                         mbuf_offset = 0;
987                                         m->m_len = 0;
988                                 }
989                         }
990                         iso88025_input(ifp, m0);
991                 } else {        /* Receiver error */
992                         if (ReceiveStatus != TRLLD_RCV_NO_DATA) {
993                                 printf("oltr%d: receive error %d\n", sc->unit,
994                                     ReceiveStatus);
995                                 ifp->if_ierrors++;
996                         }
997                 }
998
999 dropped:
1000                 s = splimp();
1001                 i = (int)FragmentHandle;
1002                 while (FragmentCount--) {
1003                         rc = TRlldReceiveFragment(sc->TRlldAdapter,
1004                             (void *)sc->rx_ring[RING_BUFFER(i)].data,
1005                             sc->rx_ring[RING_BUFFER(i)].address,
1006                             RX_BUFFER_LEN, (void *)sc->rx_ring[RING_BUFFER(i)].index);
1007                         if (rc != TRLLD_RECEIVE_OK) {
1008                                 printf("oltr%d: adapter refused receive fragment %d (rc = %d)\n", sc->unit, i, rc);
1009                                 break;
1010                         }
1011                         i++;
1012                 }
1013                 (void)splx(s);
1014         }
1015 }
1016
1017
1018 /*
1019  * ---------------------------- PMW Glue -------------------------------
1020  */
1021
1022 #ifndef TRlldInlineIO
1023
1024 static void
1025 DriverOutByte(unsigned short IOAddress, unsigned char value)
1026 {
1027         outbv(IOAddress, value);
1028 }
1029
1030 static void
1031 DriverOutWord(unsigned short IOAddress, unsigned short value)
1032 {
1033         outw(IOAddress, value);
1034 }
1035
1036 static void
1037 DriverOutDword(unsigned short IOAddress, unsigned long value)
1038 {
1039         outl(IOAddress, value);
1040 }
1041
1042 static void
1043 DriverRepOutByte(unsigned short IOAddress, unsigned char *DataPointer, int ByteCount)
1044 {
1045         outsb(IOAddress, (void *)DataPointer, ByteCount);
1046 }
1047
1048 static void
1049 DriverRepOutWord(unsigned short IOAddress, unsigned short *DataPointer, int WordCount)
1050 {
1051         outsw(IOAddress, (void *)DataPointer, WordCount);
1052 }
1053
1054 static void
1055 DriverRepOutDword(unsigned short IOAddress, unsigned long *DataPointer, int DWordCount)
1056 {
1057         outsl(IOAddress, (void *)DataPointer, DWordCount);
1058 }
1059
1060 static unsigned char
1061 DriverInByte(unsigned short IOAddress)
1062 {
1063         return(inbv(IOAddress));
1064 }
1065
1066 static unsigned short
1067 DriverInWord(unsigned short IOAddress)
1068 {
1069         return(inw(IOAddress));
1070 }
1071
1072 static unsigned long
1073 DriverInDword(unsigned short IOAddress)
1074 {
1075         return(inl(IOAddress));
1076 }
1077
1078 static void
1079 DriverRepInByte(unsigned short IOAddress, unsigned char *DataPointer, int ByteCount)
1080 {
1081         insb(IOAddress, (void *)DataPointer, ByteCount);
1082 }
1083
1084 static void
1085 DriverRepInWord(unsigned short IOAddress, unsigned short *DataPointer, int WordCount)
1086 {
1087         insw(IOAddress, (void *)DataPointer, WordCount);
1088 }
1089 static void
1090 DriverRepInDword( unsigned short IOAddress, unsigned long *DataPointer, int DWordCount)
1091 {
1092         insl(IOAddress, (void *)DataPointer, DWordCount);
1093 }
1094 #endif /* TRlldInlineIO */