2 * Granch SBNI16 G.SHDSL Modem driver
3 * Written by Denis I. Timofeev, 2002-2003.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/sys/dev/sbsh/if_sbsh.c,v 1.3.2.1 2003/04/15 18:15:07 fjoe Exp $
27 * $DragonFly: src/sys/dev/netif/sbsh/if_sbsh.c,v 1.28 2008/08/17 04:32:34 sephe Exp $
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/sockio.h>
34 #include <sys/malloc.h>
35 #include <sys/kernel.h>
38 #include <sys/socket.h>
39 #include <sys/random.h>
40 #include <sys/serialize.h>
43 #include <sys/thread2.h>
44 #include <sys/interrupt.h>
47 #include <net/ifq_var.h>
48 #include <net/if_arp.h>
49 #include <net/ethernet.h>
50 #include <net/if_media.h>
57 #include <bus/pci/pcireg.h>
58 #include <bus/pci/pcivar.h>
60 #include "if_sbshreg.h"
62 /* -------------------------------------------------------------------------- */
64 struct sbni16_hw_regs
{
65 u_int8_t CR
, CRB
, SR
, IMR
, CTDR
, LTDR
, CRDR
, LRDR
;
73 struct cx28975_cmdarea
{
91 u_int8_t out_data
[75];
99 struct arpcom arpcom
; /* ethernet common */
101 struct resource
*mem_res
;
102 struct resource
*irq_res
;
105 void *mem_base
; /* mapped memory address */
107 volatile struct sbni16_hw_regs
*regs
;
108 volatile struct hw_descr
*tbd
;
109 volatile struct hw_descr
*rbd
;
110 volatile struct cx28975_cmdarea
*cmdp
;
112 /* SBNI16 controller statistics */
113 struct sbni16_stats
{
114 u_int32_t sent_pkts
, rcvd_pkts
;
115 u_int32_t crc_errs
, ufl_errs
, ofl_errs
, attempts
, last_time
;
118 /* transmit and reception queues */
119 struct mbuf
*xq
[XQLEN
], *rq
[RQLEN
];
120 unsigned head_xq
, tail_xq
, head_rq
, tail_rq
;
122 /* the descriptors mapped onto the first buffers in xq and rq */
123 unsigned head_tdesc
, head_rdesc
;
128 u_int8_t
*firmw_image
;
134 u_int32_t fill_7e
: 1;
141 /* SHDSL transceiver statistics */
143 u_int8_t status_1
, status_3
;
144 u_int8_t attenuat
, nmr
, tpbo
, rpbo
;
145 u_int16_t losw
, segd
, crc
, sega
, losd
;
148 enum State
{ NOT_LOADED
, DOWN
, ACTIVATION
, ACTIVE
};
150 #define SIOCLOADFIRMW _IOWR('i', 67, struct ifreq)
151 #define SIOCGETSTATS _IOWR('i', 68, struct ifreq)
152 #define SIOCCLRSTATS _IOWR('i', 69, struct ifreq)
154 static int sbsh_probe(device_t
);
155 static int sbsh_attach(device_t
);
156 static int sbsh_detach(device_t
);
157 static int sbsh_ioctl(struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
158 static void sbsh_shutdown(device_t
);
159 static int sbsh_suspend(device_t
);
160 static int sbsh_resume(device_t
);
161 static void sbsh_watchdog(struct ifnet
*);
163 static void sbsh_start(struct ifnet
*);
164 static void sbsh_init(void *);
165 static void sbsh_stop(struct sbsh_softc
*);
166 static void init_card(struct sbsh_softc
*);
167 static void sbsh_intr(void *);
168 static void resume_tx(struct sbsh_softc
*);
169 static void start_xmit_frames(struct sbsh_softc
*);
170 static void encap_frame(struct sbsh_softc
*, struct mbuf
*);
171 static struct mbuf
* repack(struct sbsh_softc
*, struct mbuf
*);
172 static void free_sent_buffers(struct sbsh_softc
*);
173 static void alloc_rx_buffers(struct sbsh_softc
*);
174 static void indicate_frames(struct sbsh_softc
*);
175 static void drop_queues(struct sbsh_softc
*);
176 static void activate(struct sbsh_softc
*);
177 static void deactivate(struct sbsh_softc
*);
178 static void cx28975_interrupt(struct sbsh_softc
*);
179 static int start_cx28975(struct sbsh_softc
*, struct cx28975_cfg
);
180 static int download_firmware(struct sbsh_softc
*, u_int8_t
*, u_int32_t
);
181 static int issue_cx28975_cmd(struct sbsh_softc
*, u_int8_t
,
182 u_int8_t
*, u_int8_t
);
184 static device_method_t sbsh_methods
[] = {
185 /* Device interface */
186 DEVMETHOD(device_probe
, sbsh_probe
),
187 DEVMETHOD(device_attach
, sbsh_attach
),
188 DEVMETHOD(device_detach
, sbsh_detach
),
189 DEVMETHOD(device_shutdown
, sbsh_shutdown
),
190 DEVMETHOD(device_suspend
, sbsh_suspend
),
191 DEVMETHOD(device_resume
, sbsh_resume
),
196 static driver_t sbsh_driver
= {
199 sizeof(struct sbsh_softc
)
202 static devclass_t sbsh_devclass
;
204 DECLARE_DUMMY_MODULE(if_sbsh
);
205 DRIVER_MODULE(if_sbsh
, pci
, sbsh_driver
, sbsh_devclass
, 0, 0);
208 sbsh_probe(device_t dev
)
210 if (pci_get_vendor(dev
) != SBNI16_VENDOR
211 || pci_get_device(dev
) != SBNI16_DEVICE
212 || pci_get_subdevice(dev
) != SBNI16_SUBDEV
)
215 device_set_desc(dev
, "Granch SBNI16 G.SHDSL Modem");
220 sbsh_attach(device_t dev
)
222 struct sbsh_softc
*sc
;
224 int unit
, error
= 0, rid
;
226 sc
= device_get_softc(dev
);
227 unit
= device_get_unit(dev
);
230 sc
->mem_res
= bus_alloc_resource(dev
, SYS_RES_MEMORY
, &rid
,
231 0, ~0, 4096, RF_ACTIVE
);
233 if (sc
->mem_res
== NULL
) {
234 kprintf ("sbsh%d: couldn't map memory\n", unit
);
240 sc
->irq_res
= bus_alloc_resource_any(dev
, SYS_RES_IRQ
, &rid
,
241 RF_SHAREABLE
| RF_ACTIVE
);
243 if (sc
->irq_res
== NULL
) {
244 kprintf("sbsh%d: couldn't map interrupt\n", unit
);
249 sc
->mem_base
= rman_get_virtual(sc
->mem_res
);
251 /* generate ethernet MAC address */
252 *(u_int32_t
*)sc
->arpcom
.ac_enaddr
= htonl(0x00ff0192);
253 read_random_unlimited(sc
->arpcom
.ac_enaddr
+ 4, 2);
255 ifp
= &sc
->arpcom
.ac_if
;
257 if_initname(ifp
, "sbsh", unit
);
258 ifp
->if_mtu
= ETHERMTU
;
259 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
;
260 ifp
->if_ioctl
= sbsh_ioctl
;
261 ifp
->if_start
= sbsh_start
;
262 ifp
->if_watchdog
= sbsh_watchdog
;
263 ifp
->if_init
= sbsh_init
;
264 ifp
->if_baudrate
= 4600000;
265 ifq_set_maxlen(&ifp
->if_snd
, IFQ_MAXLEN
);
266 ifq_set_ready(&ifp
->if_snd
);
268 ether_ifattach(ifp
, sc
->arpcom
.ac_enaddr
, NULL
);
270 error
= bus_setup_intr(dev
, sc
->irq_res
, INTR_MPSAFE
,
271 sbsh_intr
, sc
, &sc
->intr_hand
,
275 kprintf("sbsh%d: couldn't set up irq\n", unit
);
279 ifp
->if_cpuid
= ithread_cpuid(rman_get_start(sc
->irq_res
));
280 KKASSERT(ifp
->if_cpuid
>= 0 && ifp
->if_cpuid
< ncpus
);
290 sbsh_detach(device_t dev
)
292 struct sbsh_softc
*sc
= device_get_softc(dev
);
293 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
295 if (device_is_attached(dev
)) {
296 lwkt_serialize_enter(ifp
->if_serializer
);
298 bus_teardown_intr(dev
, sc
->irq_res
, sc
->intr_hand
);
299 lwkt_serialize_exit(ifp
->if_serializer
);
305 bus_release_resource(dev
, SYS_RES_IRQ
, 0, sc
->irq_res
);
307 bus_release_resource(dev
, SYS_RES_MEMORY
, PCIR_MAPS
+ 4,
316 sbsh_start(struct ifnet
*ifp
)
318 struct sbsh_softc
*sc
= ifp
->if_softc
;
320 if (sc
->state
== ACTIVE
)
321 start_xmit_frames(ifp
->if_softc
);
328 struct sbsh_softc
*sc
= xsc
;
329 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
332 if ((ifp
->if_flags
& IFF_RUNNING
) || sc
->state
== NOT_LOADED
) {
336 bzero(&sc
->in_stats
, sizeof(struct sbni16_stats
));
337 sc
->head_xq
= sc
->tail_xq
= sc
->head_rq
= sc
->tail_rq
= 0;
338 sc
->head_tdesc
= sc
->head_rdesc
= 0;
342 issue_cx28975_cmd(sc
, _DSL_CLEAR_ERROR_CTRS
, &t
, 1);
343 if (issue_cx28975_cmd(sc
, _DSL_ACTIVATION
, &t
, 1) == 0) {
344 sc
->state
= ACTIVATION
;
346 ifp
->if_flags
|= IFF_RUNNING
;
347 ifp
->if_flags
&= ~IFF_OACTIVE
;
353 sbsh_stop(struct sbsh_softc
*sc
)
360 issue_cx28975_cmd(sc
, _DSL_ACTIVATION
, &t
, 1);
361 if (sc
->state
== ACTIVE
) {
363 issue_cx28975_cmd(sc
, _DSL_FORCE_DEACTIVATE
, &t
, 1);
364 /* FIX! activation manager state */
366 /* Is it really must be done here? It calls from intr handler */
376 init_card(struct sbsh_softc
*sc
)
378 sc
->state
= NOT_LOADED
;
379 sc
->tbd
= (struct hw_descr
*) sc
->mem_base
;
380 sc
->rbd
= (struct hw_descr
*) ((u_int8_t
*)sc
->mem_base
+ 0x400);
381 sc
->regs
= (struct sbni16_hw_regs
*) ((u_int8_t
*)sc
->mem_base
+ 0x800);
382 sc
->cmdp
= (struct cx28975_cmdarea
*) ((u_int8_t
*)sc
->mem_base
+ 0xc00);
391 sbsh_ioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*cr
)
393 struct sbsh_softc
*sc
= ifp
->if_softc
;
394 struct ifreq
*ifr
= (struct ifreq
*) data
;
395 struct cx28975_cfg cfg
;
402 if ((error
= priv_check_cred(cr
, PRIV_ROOT
, NULL_CRED_OKAY
)) != 0)
404 if (ifp
->if_flags
& IFF_UP
)
407 bcopy((caddr_t
)ifr
->ifr_data
, (caddr_t
)&cfg
, sizeof cfg
);
408 if (start_cx28975(sc
, cfg
) == 0) {
409 static char *modstr
[] = {
410 "TCPAM32", "TCPAM16", "TCPAM8", "TCPAM4" };
411 if_printf(&sc
->arpcom
.ac_if
, "%s, rate %d, %s\n",
412 cfg
.master
? "master" : "slave",
413 cfg
.lrate
<< 3, modstr
[cfg
.mod
]);
415 if_printf(&sc
->arpcom
.ac_if
,
416 "unable to load firmware\n");
422 if ((error
= priv_check_cred(cr
, PRIV_ROOT
, NULL_CRED_OKAY
)) != 0)
426 if (issue_cx28975_cmd(sc
, _DSL_FAR_END_ATTEN
, &t
, 1))
428 ds
.attenuat
= sc
->cmdp
->out_data
[0];
430 if (issue_cx28975_cmd(sc
, _DSL_NOISE_MARGIN
, &t
, 1))
432 ds
.nmr
= sc
->cmdp
->out_data
[0];
434 if (issue_cx28975_cmd(sc
, _DSL_POWER_BACK_OFF_RESULT
, &t
, 1))
436 ds
.tpbo
= sc
->cmdp
->out_data
[0];
437 ds
.rpbo
= sc
->cmdp
->out_data
[1];
439 if (!issue_cx28975_cmd(sc
, _DSL_HDSL_PERF_ERR_CTRS
, &t
, 1)) {
441 for (i
= 0; i
< 10; ++i
)
442 ((u_int8_t
*) &ds
.losw
)[i
] =
443 sc
->cmdp
->out_data
[i
];
447 ds
.status_1
= ((volatile u_int8_t
*)sc
->cmdp
)[0x3c0];
448 ds
.status_3
= ((volatile u_int8_t
*)sc
->cmdp
)[0x3c2];
450 bcopy(&sc
->in_stats
, ifr
->ifr_data
, sizeof(struct sbni16_stats
));
451 bcopy(&ds
, (char *)ifr
->ifr_data
+ sizeof(struct sbni16_stats
),
452 sizeof(struct dsl_stats
));
456 if (!(error
= priv_check_cred(cr
, PRIV_ROOT
, NULL_CRED_OKAY
))) {
457 bzero(&sc
->in_stats
, sizeof(struct sbni16_stats
));
459 if (issue_cx28975_cmd(sc
, _DSL_CLEAR_ERROR_CTRS
, &t
, 1))
464 if (ifp
->if_flags
& IFF_UP
) {
465 if (!(ifp
->if_flags
& IFF_RUNNING
)) {
466 if (sc
->state
== NOT_LOADED
) {
467 if_printf(ifp
, "firmware wasn't loaded\n");
473 if (ifp
->if_flags
& IFF_RUNNING
) {
475 ifp
->if_flags
&= ~IFF_RUNNING
;
485 error
= ether_ioctl(ifp
, cmd
, data
);
493 sbsh_shutdown(device_t dev
)
495 struct sbsh_softc
*sc
= device_get_softc(dev
);
497 lwkt_serialize_enter(sc
->arpcom
.ac_if
.if_serializer
);
499 lwkt_serialize_exit(sc
->arpcom
.ac_if
.if_serializer
);
503 sbsh_suspend(device_t dev
)
505 struct sbsh_softc
*sc
= device_get_softc(dev
);
507 lwkt_serialize_enter(sc
->arpcom
.ac_if
.if_serializer
);
509 lwkt_serialize_exit(sc
->arpcom
.ac_if
.if_serializer
);
515 sbsh_resume(device_t dev
)
517 struct sbsh_softc
*sc
= device_get_softc(dev
);
518 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
520 if (ifp
->if_flags
& IFF_UP
)
528 sbsh_watchdog(struct ifnet
*ifp
)
530 struct sbsh_softc
*sc
= ifp
->if_softc
;
532 if_printf(ifp
, "transmit timeout\n");
534 if (sc
->regs
->SR
& TXS
) {
536 if_printf(ifp
, "interrupt posted but not delivered\n");
538 free_sent_buffers(sc
);
541 /* -------------------------------------------------------------------------- */
546 struct sbsh_softc
*sc
= (struct sbsh_softc
*)arg
;
547 u_int8_t status
= sc
->regs
->SR
;
553 cx28975_interrupt(sc
);
560 ++sc
->in_stats
.ufl_errs
;
561 ++sc
->arpcom
.ac_if
.if_oerrors
;
567 alloc_rx_buffers(sc
);
572 free_sent_buffers(sc
);
576 ++sc
->in_stats
.crc_errs
;
577 ++sc
->arpcom
.ac_if
.if_ierrors
;
582 ++sc
->in_stats
.ofl_errs
;
583 ++sc
->arpcom
.ac_if
.if_ierrors
;
589 * Look for a first descriptor of a next packet, and write it's number
590 * into CTDR. Then enable the transmitter.
593 resume_tx(struct sbsh_softc
*sc
)
595 u_int32_t cur_tbd
= sc
->regs
->CTDR
;
597 while (cur_tbd
!= sc
->regs
->LTDR
598 && (sc
->tbd
[cur_tbd
++].length
& LAST_FRAG
) == 0)
600 sc
->regs
->CTDR
= cur_tbd
;
601 sc
->regs
->CR
|= TXEN
;
605 start_xmit_frames(struct sbsh_softc
*sc
)
607 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
611 * Check if we have any free descriptor(s) and free space in
612 * our transmit queue.
614 while (sc
->tail_xq
!= ((sc
->head_xq
- 1) & (XQLEN
- 1))
615 && sc
->regs
->LTDR
!= ((sc
->head_tdesc
- 1) & 0x7f)) {
617 m
= ifq_dequeue(&ifp
->if_snd
, NULL
);
620 if (m
->m_pkthdr
.len
) {
627 if (sc
->regs
->CTDR
!= sc
->regs
->LTDR
)
628 ifp
->if_flags
|= IFF_OACTIVE
;
630 ifp
->if_flags
&= ~IFF_OACTIVE
;
635 encap_frame(struct sbsh_softc
*sc
, struct mbuf
*m_head
)
642 for (m
= m_head
; !m
->m_len
; m
= m
->m_next
)
645 cur_tbd
= sc
->regs
->LTDR
& 0x7f;
648 if (m
->m_len
< 5 || cur_tbd
== ((sc
->head_tdesc
- 1) & 0x7f)) {
649 if ((m_head
= repack(sc
, m_head
)) != NULL
)
650 goto look_for_nonzero
;
655 sc
->tbd
[cur_tbd
].address
= vtophys(mtod(m
, vm_offset_t
));
656 sc
->tbd
[cur_tbd
].length
= m
->m_len
;
660 } while (m
&& !m
->m_len
);
662 if (!m
) { /* last fragment has been reached */
663 sc
->tbd
[cur_tbd
].length
|= LAST_FRAG
;
671 sc
->xq
[sc
->tail_xq
++] = m_head
;
672 sc
->tail_xq
&= (XQLEN
- 1);
674 sc
->regs
->LTDR
= cur_tbd
;
675 ++sc
->in_stats
.sent_pkts
;
676 ++sc
->arpcom
.ac_if
.if_opackets
;
680 repack(struct sbsh_softc
*sc
, struct mbuf
*m
)
684 MGETHDR(m_new
, MB_DONTWAIT
, MT_DATA
);
686 if_printf (&sc
->arpcom
.ac_if
,
687 "unable to get mbuf.\n");
691 if (m
->m_pkthdr
.len
> MHLEN
) {
692 MCLGET(m_new
, MB_DONTWAIT
);
693 if (!(m_new
->m_flags
& M_EXT
)) {
695 if_printf (&sc
->arpcom
.ac_if
,
696 "unable to get mbuf cluster.\n");
701 m_copydata(m
, 0, m
->m_pkthdr
.len
, mtod(m_new
, caddr_t
));
702 m_new
->m_pkthdr
.len
= m_new
->m_len
= m
->m_pkthdr
.len
;
708 free_sent_buffers(struct sbsh_softc
*sc
)
712 cur_tbd
= sc
->regs
->CTDR
;
714 while (sc
->head_tdesc
!= cur_tbd
) {
716 * Be careful! one element in xq may correspond to
717 * multiple descriptors.
719 if (sc
->tbd
[sc
->head_tdesc
].length
& LAST_FRAG
) {
720 m_freem(sc
->xq
[sc
->head_xq
++]);
721 sc
->head_xq
&= (XQLEN
- 1);
724 sc
->tbd
[sc
->head_tdesc
].length
= 0;
725 sc
->head_tdesc
= (sc
->head_tdesc
+ 1) & 0x7f;
728 start_xmit_frames(sc
);
732 * DON'T use free_sent_buffers to drop the queue!
735 alloc_rx_buffers(struct sbsh_softc
*sc
)
737 unsigned cur_rbd
= sc
->regs
->LRDR
& 0x7f;
740 while (sc
->tail_rq
!= ((sc
->head_rq
- 1) & (RQLEN
- 1))) {
741 MGETHDR(m
, MB_DONTWAIT
, MT_DATA
);
743 if_printf (&sc
->arpcom
.ac_if
,
744 "unable to get mbuf.\n");
748 if (SBNI16_MAX_FRAME
> MHLEN
) {
749 MCLGET(m
, MB_DONTWAIT
);
750 if (!(m
->m_flags
& M_EXT
)) {
752 if_printf (&sc
->arpcom
.ac_if
,
753 "unable to get mbuf cluster.\n");
756 m
->m_pkthdr
.len
= m
->m_len
= MCLBYTES
;
759 m_adj(m
, 2); /* align ip on longword boundaries */
761 sc
->rq
[sc
->tail_rq
++] = m
;
762 sc
->tail_rq
&= (RQLEN
- 1);
764 sc
->rbd
[cur_rbd
].address
= vtophys(mtod(m
, vm_offset_t
));
765 sc
->rbd
[cur_rbd
].length
= 0;
766 sc
->regs
->LRDR
= cur_rbd
= (cur_rbd
+ 1) & 0x7f;
771 indicate_frames(struct sbsh_softc
*sc
)
773 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
774 unsigned cur_rbd
= sc
->regs
->CRDR
& 0x7f;
776 while (sc
->head_rdesc
!= cur_rbd
) {
777 struct mbuf
*m
= sc
->rq
[sc
->head_rq
++];
778 sc
->head_rq
&= (RQLEN
- 1);
780 m
->m_pkthdr
.len
= m
->m_len
=
781 sc
->rbd
[sc
->head_rdesc
].length
& 0x7ff;
782 m
->m_pkthdr
.rcvif
= ifp
;
784 ifp
->if_input(ifp
, m
);
785 ++sc
->in_stats
.rcvd_pkts
;
788 sc
->head_rdesc
= (sc
->head_rdesc
+ 1) & 0x7f;
793 drop_queues(struct sbsh_softc
*sc
)
795 while (sc
->head_rq
!= sc
->tail_rq
) {
796 m_freem(sc
->rq
[sc
->head_rq
++]);
797 sc
->head_rq
&= (RQLEN
- 1);
800 while (sc
->head_xq
!= sc
->tail_xq
) {
801 m_freem(sc
->xq
[sc
->head_xq
++]);
802 sc
->head_xq
&= (XQLEN
- 1);
806 /* -------------------------------------------------------------------------- */
809 activate(struct sbsh_softc
*sc
)
813 sc
->regs
->SR
= 0xff; /* clear it! */
814 sc
->regs
->CTDR
= sc
->regs
->LTDR
= sc
->regs
->CRDR
= sc
->regs
->LRDR
= 0;
816 sc
->head_tdesc
= sc
->head_rdesc
= 0;
817 alloc_rx_buffers(sc
);
819 sc
->regs
->CRB
&= ~RXDE
;
820 sc
->regs
->IMR
= EXT
| RXS
| TXS
| CRC
| OFL
| UFL
;
821 sc
->regs
->CR
|= TXEN
| RXEN
;
824 ++sc
->in_stats
.attempts
;
826 sc
->in_stats
.last_time
= tv
.tv_sec
;
827 start_xmit_frames(sc
);
831 deactivate(struct sbsh_softc
*sc
)
833 sc
->regs
->CR
&= ~(RXEN
| TXEN
);
834 sc
->regs
->CRB
|= RXDE
;
836 sc
->regs
->CTDR
= sc
->regs
->LTDR
;
837 sc
->regs
->CRDR
= sc
->regs
->LRDR
;
838 sc
->state
= ACTIVATION
;
843 /* -------------------------------------------------------------------------- */
846 cx28975_interrupt(struct sbsh_softc
*sc
)
848 volatile struct cx28975_cmdarea
*p
= sc
->cmdp
;
851 if (p
->intr_host
!= 0xfe)
854 if (p
->out_ack
& 0x80) {
855 if (*((volatile u_int8_t
*)p
+ 0x3c7) & 2) {
856 if (sc
->state
!= ACTIVE
857 && (*((volatile u_int8_t
*)p
+ 0x3c0) & 0xc0) == 0x40) {
859 if_printf(&sc
->arpcom
.ac_if
, "connected to peer\n");
860 } else if (sc
->state
== ACTIVE
861 && (*((volatile u_int8_t
*)p
+ 0x3c0) & 0xc0) != 0x40) {
863 if_printf(&sc
->arpcom
.ac_if
, "carrier lost\n");
878 /* -------------------------------------------------------------------------- */
881 start_cx28975(struct sbsh_softc
*sc
, struct cx28975_cfg cfg
)
883 static char thresh
[] = { +8, -4, -16, -40 };
885 volatile struct cx28975_cmdarea
*p
= sc
->cmdp
;
886 u_int8_t t
, parm
[12];
898 sc
->regs
->CR
|= CMOD
;
900 sc
->regs
->CR
|= FMOD
;
902 sc
->regs
->CR
|= PMOD
;
904 sc
->regs
->CRB
|= RODD
| RXDE
;
906 sc
->regs
->CRB
|= RDBE
;
908 sc
->regs
->CRB
|= WTBE
;
910 tsleep(sc
, 0, "sbsh", 0);
911 if ((p
->out_ack
& 0x1f) != _ACK_BOOT_WAKE_UP
)
914 if (download_firmware(sc
, cfg
.firmw_image
, cfg
.firmw_len
))
917 tsleep(sc
, 0, "sbsh", 0);
918 if ((p
->out_ack
& 0x1f) != _ACK_OPER_WAKE_UP
)
921 t
= cfg
.master
? 1 : 9;
922 if (issue_cx28975_cmd(sc
, _DSL_SYSTEM_ENABLE
, &t
, 1))
926 if (issue_cx28975_cmd(sc
, _DSL_SYSTEM_CONFIG
, &t
, 1))
929 *(u_int16_t
*)parm
= cfg
.lrate
>> 3;
930 parm
[2] = parm
[3] = parm
[0];
931 parm
[5] = cfg
.lrate
& 7;
932 parm
[4] = parm
[7] = 1;
934 if (issue_cx28975_cmd(sc
, _DSL_MULTI_RATE_CONFIG
, parm
, 8))
937 parm
[0] = 0x02 | (cfg
.mod
<< 4);
939 if (issue_cx28975_cmd(sc
, _DSL_TRAINING_MODE
, parm
, 2))
943 parm
[0] = 0x04; /* pre-activation: G.hs */
944 parm
[4] = 0x04; /* no remote configuration */
945 parm
[7] = 0x01; /* annex A (default) */
946 parm
[8] = 0xff; /* i-bit mask (all bits) */
947 if (issue_cx28975_cmd(sc
, _DSL_PREACTIVATION_CFG
, parm
, 12))
950 parm
[0] = 0x03; /* dying gasp time - 3 frames */
951 parm
[1] = thresh
[cfg
.mod
];
952 parm
[2] = 0xff; /* attenuation */
953 parm
[3] = 0x04; /* line probe NMR (+2 dB) */
954 parm
[4] = 0x00; /* reserved */
956 if (issue_cx28975_cmd(sc
, _DSL_THRESHOLDS
, parm
, 6))
959 t
= cfg
.master
? 0x23 : 0x21;
960 if (issue_cx28975_cmd(sc
, _DSL_FR_PCM_CONFIG
, &t
, 1))
964 if (issue_cx28975_cmd(sc
, _DSL_INTR_HOST_MASK
, &t
, 1))
972 download_firmware(struct sbsh_softc
*sc
, u_int8_t
*img
, u_int32_t img_len
)
978 for (i
= 0; i
< img_len
; ++i
)
982 if (issue_cx28975_cmd(sc
, _DSL_DOWNLOAD_START
, (u_int8_t
*) &t
, 4))
985 for (i
= 0; img_len
>= 75; i
+= 75, img_len
-= 75) {
986 if (issue_cx28975_cmd(sc
, _DSL_DOWNLOAD_DATA
, img
+ i
, 75))
991 && issue_cx28975_cmd(sc
, _DSL_DOWNLOAD_DATA
, img
+ i
, img_len
))
994 t
= (cksum
^ 0xff) + 1;
995 if (issue_cx28975_cmd(sc
, _DSL_DOWNLOAD_END
, (u_int8_t
*) &t
, 1))
1002 issue_cx28975_cmd(struct sbsh_softc
*sc
, u_int8_t cmd
,
1003 u_int8_t
*data
, u_int8_t size
)
1005 volatile struct cx28975_cmdarea
*p
= sc
->cmdp
;
1006 volatile u_int8_t
*databuf
= p
->in_data
;
1014 p
->in_length
= --size
;
1015 p
->in_csum
= 0xf0 ^ cmd
^ size
^ 0xaa;
1017 for (i
= 0; i
<= size
; ++i
) {
1019 *databuf
++ = *data
++; /* only 1 byte per cycle! */
1022 p
->in_datasum
= cksum
^ 0xaa;
1023 p
->out_ack
= _ACK_NOT_COMPLETE
;
1024 p
->intr_8051
= 0xfe;
1026 if (tsleep(sc
, 0, "sbsh", hz
<< 3))
1029 while (p
->out_ack
== _ACK_NOT_COMPLETE
)
1032 if ((p
->out_ack
& 0x1f) == _ACK_PASS
) {