Annotation of sys/dev/pci/if_art.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_art.c,v 1.13 2006/01/26 16:51:00 claudio Exp $ */
2:
3: /*
4: * Copyright (c) 2004,2005 Internet Business Solutions AG, Zurich, Switzerland
5: * Written by: Claudio Jeker <jeker@accoom.net>
6: *
7: * Permission to use, copy, modify, and distribute this software for any
8: * purpose with or without fee is hereby granted, provided that the above
9: * copyright notice and this permission notice appear in all copies.
10: *
11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19:
20: #include <sys/param.h>
21: #include <sys/types.h>
22:
23: #include <sys/device.h>
24: #include <sys/proc.h>
25: #include <sys/socket.h>
26: #include <sys/sockio.h>
27: #include <sys/syslog.h>
28: #include <sys/systm.h>
29:
30: #include <machine/bus.h>
31:
32: #include <net/if.h>
33: #include <net/if_media.h>
34: #include <net/if_sppp.h>
35:
36: #include <dev/pci/musyccvar.h>
37: #include <dev/pci/if_art.h>
38:
39: #define ART_E1_MASK 0xffffffff
40: #define ART_T1_MASK 0x01fffffe
41:
42: int art_match(struct device *, void *, void *);
43: void art_softc_attach(struct device *, struct device *, void *);
44:
45: int art_ioctl(struct ifnet *, u_long, caddr_t);
46: int art_ifm_change(struct ifnet *);
47: void art_ifm_status(struct ifnet *, struct ifmediareq *);
48: int art_ifm_options(struct ifnet *, struct channel_softc *, u_int);
49: void art_onesec(void *);
50: void art_linkstate(void *);
51: u_int32_t art_mask_tsmap(u_int, u_int32_t);
52:
53: struct cfattach art_ca = {
54: sizeof(struct art_softc), art_match, art_softc_attach
55: };
56:
57: struct cfdriver art_cd = {
58: NULL, "art", DV_DULL
59: };
60:
61: int
62: art_match(struct device *parent, void *match, void *aux)
63: {
64: struct musycc_attach_args *ma = aux;
65:
66: if (ma->ma_type == MUSYCC_FRAMER_BT8370)
67: return (1);
68: return (0);
69: }
70:
71: /*
72: * used for the one second timer
73: */
74: extern int hz;
75:
76: void
77: art_softc_attach(struct device *parent, struct device *self, void *aux)
78: {
79: struct art_softc *sc = (struct art_softc *)self;
80: struct musycc_softc *psc = (struct musycc_softc *)parent;
81: struct musycc_attach_args *ma = aux;
82:
83: printf(" \"%s\"", ma->ma_product);
84:
85: if (ebus_attach_device(&sc->art_ebus, psc, ma->ma_base,
86: ma->ma_size) != 0) {
87: printf(": could not map framer\n");
88: return;
89: }
90:
91: /* set basic values */
92: sc->art_port = ma->ma_port;
93: sc->art_slot = ma->ma_slot;
94: sc->art_gnum = ma->ma_gnum;
95: sc->art_type = ma->ma_flags & 0x03;
96:
97: sc->art_channel = musycc_channel_create(self->dv_xname, 1);
98: if (sc->art_channel == NULL) {
99: printf(": could not alloc channel descriptor\n");
100: return;
101: }
102:
103: if (musycc_channel_attach(psc, sc->art_channel, self, sc->art_gnum) ==
104: -1) {
105: printf(": unable to attach to hdlc controller\n");
106: return;
107: }
108:
109: ifmedia_init(&sc->art_ifm, 0, art_ifm_change, art_ifm_status);
110: ifmedia_add(&sc->art_ifm,
111: IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1, 0, 0), 0, NULL);
112: ifmedia_add(&sc->art_ifm,
113: IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1_AMI, 0, 0), 0, NULL);
114: ifmedia_add(&sc->art_ifm,
115: IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1, 0, 0), 0, NULL);
116: ifmedia_add(&sc->art_ifm,
117: IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704, 0, 0), 0, NULL);
118: ifmedia_add(&sc->art_ifm,
119: IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704_CRC4, 0, 0), 0, NULL);
120:
121: ifmedia_add(&sc->art_ifm,
122: IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1, IFM_TDM_MASTER, 0), 0, NULL);
123: ifmedia_add(&sc->art_ifm,
124: IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1_AMI, IFM_TDM_MASTER, 0), 0, NULL);
125: ifmedia_add(&sc->art_ifm,
126: IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1, IFM_TDM_MASTER, 0), 0, NULL);
127: ifmedia_add(&sc->art_ifm,
128: IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704, IFM_TDM_MASTER, 0), 0, NULL);
129: ifmedia_add(&sc->art_ifm,
130: IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704_CRC4, IFM_TDM_MASTER, 0),
131: 0, NULL);
132:
133: ifmedia_add(&sc->art_ifm,
134: IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1, IFM_TDM_PPP, 0), 0, NULL);
135: ifmedia_add(&sc->art_ifm,
136: IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1, IFM_TDM_PPP, 0), 0, NULL);
137: ifmedia_add(&sc->art_ifm,
138: IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1_AMI, IFM_TDM_PPP, 0), 0, NULL);
139: ifmedia_add(&sc->art_ifm,
140: IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704, IFM_TDM_PPP, 0), 0, NULL);
141: ifmedia_add(&sc->art_ifm,
142: IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704_CRC4, IFM_TDM_PPP, 0), 0,
143: NULL);
144:
145: ifmedia_add(&sc->art_ifm,
146: IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1, IFM_TDM_PPP | IFM_TDM_MASTER, 0),
147: 0, NULL);
148: ifmedia_add(&sc->art_ifm,
149: IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1, IFM_TDM_PPP | IFM_TDM_MASTER, 0),
150: 0, NULL);
151: ifmedia_add(&sc->art_ifm,
152: IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1_AMI, IFM_TDM_PPP | IFM_TDM_MASTER,
153: 0), 0, NULL);
154: ifmedia_add(&sc->art_ifm,
155: IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704, IFM_TDM_PPP |
156: IFM_TDM_MASTER, 0), 0, NULL);
157: ifmedia_add(&sc->art_ifm,
158: IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704_CRC4, IFM_TDM_PPP |
159: IFM_TDM_MASTER, 0), 0, NULL);
160:
161: printf("\n");
162:
163: if (bt8370_reset(sc) != 0)
164: return;
165:
166: /* Initialize timeout for statistics update. */
167: timeout_set(&sc->art_onesec, art_onesec, sc);
168:
169: ifmedia_set(&sc->art_ifm, IFM_TDM|IFM_TDM_E1_G704_CRC4);
170: sc->art_media = sc->art_ifm.ifm_media;
171:
172: bt8370_set_frame_mode(sc, sc->art_type, IFM_TDM_E1_G704_CRC4, 0);
173: musycc_attach_sppp(sc->art_channel, art_ioctl);
174:
175: /* Set linkstate hook to track link state changes done by sppp. */
176: sc->art_linkstatehook = hook_establish(
177: sc->art_channel->cc_ifp->if_linkstatehooks, 0, art_linkstate, sc);
178:
179: /* Schedule the timeout one second from now. */
180: timeout_add(&sc->art_onesec, hz);
181: }
182:
183: /* interface ioctl */
184: int
185: art_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
186: {
187: struct ifreq *ifr = (struct ifreq*) data;
188: struct channel_softc *cc = ifp->if_softc;
189: struct art_softc *ac = (struct art_softc *)cc->cc_parent;
190: u_int32_t tsmap;
191: int s, rv = 0;
192:
193: s = splnet();
194: switch (command) {
195: case SIOCSIFADDR:
196: if ((rv = musycc_init_channel(cc, ac->art_slot)))
197: break;
198: rv = sppp_ioctl(ifp, command, data);
199: break;
200: case SIOCSIFTIMESLOT:
201: if ((rv = suser(curproc, 0)) != 0)
202: break;
203: rv = copyin(ifr->ifr_data, &tsmap, sizeof(tsmap));
204: if (rv)
205: break;
206: if (art_mask_tsmap(IFM_SUBTYPE(ac->art_media), tsmap) !=
207: tsmap) {
208: rv = EINVAL;
209: break;
210: }
211: if (ac->art_type == ART_SBI_SINGLE &&
212: (IFM_SUBTYPE(ac->art_media) == IFM_TDM_T1 ||
213: IFM_SUBTYPE(ac->art_media) == IFM_TDM_T1_AMI))
214: /*
215: * need to adjust timeslot mask for T1 on single port
216: * cards. There timeslot 0-23 are usable not 1-24
217: */
218: tsmap >>= 1;
219:
220: cc->cc_tslots = tsmap;
221: rv = musycc_init_channel(cc, ac->art_slot);
222: break;
223: case SIOCGIFTIMESLOT:
224: tsmap = cc->cc_tslots;
225: if (ac->art_type == ART_SBI_SINGLE &&
226: (IFM_SUBTYPE(ac->art_media) == IFM_TDM_T1 ||
227: IFM_SUBTYPE(ac->art_media) == IFM_TDM_T1_AMI))
228: tsmap <<= 1;
229: rv = copyout(&tsmap, ifr->ifr_data, sizeof(tsmap));
230: break;
231: case SIOCSIFFLAGS:
232: /*
233: * If interface is marked up and not running, then start it.
234: * If it is marked down and running, stop it.
235: */
236: if (ifr->ifr_flags & IFF_UP && cc->cc_state != CHAN_RUNNING) {
237: if ((rv = musycc_init_channel(cc, ac->art_slot)))
238: break;
239: } else if ((ifr->ifr_flags & IFF_UP) == 0 &&
240: cc->cc_state == CHAN_RUNNING)
241: musycc_stop_channel(cc);
242: rv = sppp_ioctl(ifp, command, data);
243: break;
244: case SIOCSIFMEDIA:
245: case SIOCGIFMEDIA:
246: if (ac != NULL)
247: rv = ifmedia_ioctl(ifp, ifr, &ac->art_ifm, command);
248: else
249: rv = EINVAL;
250: break;
251: default:
252: rv = sppp_ioctl(ifp, command, data);
253: break;
254: }
255: splx(s);
256: return (rv);
257: }
258:
259: int
260: art_ifm_change(struct ifnet *ifp)
261: {
262: struct channel_softc *cc = ifp->if_softc;
263: struct art_softc *ac = (struct art_softc *)cc->cc_parent;
264: struct ifmedia *ifm = &ac->art_ifm;
265: int rv, s, baudrate;
266:
267: ACCOOM_PRINTF(2, ("%s: art_ifm_change %08x\n", ifp->if_xname,
268: ifm->ifm_media));
269:
270: if (IFM_TYPE(ifm->ifm_media) != IFM_TDM)
271: return (EINVAL);
272:
273: /* OPTIONS (controller mode hdlc, ppp, eoe) */
274: if ((rv = art_ifm_options(ifp, cc, IFM_OPTIONS(ifm->ifm_media))) != 0)
275: return (rv);
276:
277: /* SUBTYPE (framing mode T1/E1) + MODE (clocking master/slave) */
278: if (IFM_SUBTYPE(ifm->ifm_media) != IFM_SUBTYPE(ac->art_media) ||
279: IFM_MODE(ifm->ifm_media) != IFM_MODE(ac->art_media)) {
280: ACCOOM_PRINTF(0, ("%s: art_ifm_change type %d mode %x\n",
281: ifp->if_xname, IFM_SUBTYPE(ifm->ifm_media),
282: IFM_MODE(ifm->ifm_media)));
283:
284: bt8370_set_frame_mode(ac, ac->art_type,
285: IFM_SUBTYPE(ifm->ifm_media), IFM_MODE(ifm->ifm_media));
286:
287: if (IFM_SUBTYPE(ifm->ifm_media) != IFM_SUBTYPE(ac->art_media)) {
288: /* adjust timeslot map on media change */
289: cc->cc_tslots = art_mask_tsmap(
290: IFM_SUBTYPE(ifm->ifm_media), cc->cc_tslots);
291:
292: if (ac->art_type == ART_SBI_SINGLE &&
293: (IFM_SUBTYPE(ifm->ifm_media) == IFM_TDM_T1 ||
294: IFM_SUBTYPE(ifm->ifm_media) == IFM_TDM_T1_AMI) &&
295: (IFM_SUBTYPE(ac->art_media) != IFM_TDM_T1 &&
296: IFM_SUBTYPE(ac->art_media) != IFM_TDM_T1_AMI))
297: /*
298: * need to adjust timeslot mask for T1 on
299: * single port cards. There timeslot 0-23 are
300: * usable not 1-24
301: */
302: cc->cc_tslots >>= 1;
303: else if (ac->art_type == ART_SBI_SINGLE &&
304: (IFM_SUBTYPE(ifm->ifm_media) != IFM_TDM_T1 &&
305: IFM_SUBTYPE(ifm->ifm_media) != IFM_TDM_T1_AMI) &&
306: (IFM_SUBTYPE(ac->art_media) == IFM_TDM_T1 ||
307: IFM_SUBTYPE(ac->art_media) == IFM_TDM_T1_AMI))
308: /* undo the last adjustment */
309: cc->cc_tslots <<= 1;
310: }
311:
312: /* re-init the card */
313: if ((rv = musycc_init_channel(cc, ac->art_slot)))
314: return (rv);
315: }
316:
317: baudrate = ifmedia_baudrate(ac->art_media);
318: if (baudrate != ifp->if_baudrate) {
319: ifp->if_baudrate = baudrate;
320: s = splsoftnet();
321: if_link_state_change(ifp), baudrate;
322: splx(s);
323: }
324:
325: ac->art_media = ifm->ifm_media;
326:
327: return (0);
328: }
329:
330: void
331: art_ifm_status(struct ifnet *ifp, struct ifmediareq *ifmreq)
332: {
333: struct art_softc *ac;
334:
335: ac = (struct art_softc *)
336: ((struct channel_softc *)ifp->if_softc)->cc_parent;
337: ifmreq->ifm_status = IFM_AVALID;
338: if (ifp->if_link_state == LINK_STATE_UP)
339: ifmreq->ifm_status |= IFM_ACTIVE;
340: ifmreq->ifm_active = ac->art_media;
341:
342: return;
343: }
344:
345: int
346: art_ifm_options(struct ifnet *ifp, struct channel_softc *cc, u_int options)
347: {
348: struct art_softc *ac = (struct art_softc *)cc->cc_parent;
349: u_int flags = cc->cc_ppp.pp_flags;
350: int rv;
351:
352: if (options == IFM_TDM_PPP) {
353: flags &= ~PP_CISCO;
354: flags |= PP_KEEPALIVE;
355: } else if (options == 0) {
356: flags |= PP_CISCO;
357: flags |= PP_KEEPALIVE;
358: } else {
359: ACCOOM_PRINTF(0, ("%s: Unsupported ifmedia options\n",
360: ifp->if_xname));
361: return (EINVAL);
362: }
363: if (flags != cc->cc_ppp.pp_flags) {
364: musycc_stop_channel(cc);
365: cc->cc_ppp.pp_flags = flags;
366: if ((rv = musycc_init_channel(cc, ac->art_slot)))
367: return (rv);
368: return (sppp_ioctl(ifp, SIOCSIFFLAGS, NULL));
369: }
370: return (0);
371: }
372:
373: void
374: art_onesec(void *arg)
375: {
376: struct art_softc *ac = arg;
377: struct ifnet *ifp = ac->art_channel->cc_ifp;
378: struct sppp *ppp = &ac->art_channel->cc_ppp;
379: int s, rv, link_state;
380:
381: rv = bt8370_link_status(ac);
382: switch (rv) {
383: case 1:
384: link_state = LINK_STATE_UP;
385: /* set green led */
386: ebus_set_led(ac->art_channel, 1, MUSYCC_LED_GREEN);
387: break;
388: case 0:
389: link_state = LINK_STATE_DOWN;
390: /* set green led and red led as well */
391: ebus_set_led(ac->art_channel, 1,
392: MUSYCC_LED_GREEN | MUSYCC_LED_RED);
393: break;
394: default:
395: link_state = LINK_STATE_DOWN;
396: /* turn green led off */
397: ebus_set_led(ac->art_channel, 0, MUSYCC_LED_GREEN);
398: break;
399: }
400:
401: if (link_state != ifp->if_link_state) {
402: s = splsoftnet();
403: if (link_state == LINK_STATE_UP)
404: ppp->pp_up(ppp);
405: else
406: ppp->pp_down(ppp);
407: splx(s);
408: }
409:
410: /*
411: * run musycc onesec job
412: */
413: musycc_tick(ac->art_channel);
414:
415: /*
416: * Schedule another timeout one second from now.
417: */
418: timeout_add(&ac->art_onesec, hz);
419: }
420:
421: void
422: art_linkstate(void *arg)
423: {
424: struct art_softc *ac = arg;
425: struct ifnet *ifp = ac->art_channel->cc_ifp;
426:
427: if (ifp->if_link_state == LINK_STATE_UP)
428: /* turn red led off */
429: ebus_set_led(ac->art_channel, 0, MUSYCC_LED_RED);
430: else
431: /* turn red led on */
432: ebus_set_led(ac->art_channel, 1, MUSYCC_LED_RED);
433: }
434:
435: u_int32_t
436: art_mask_tsmap(u_int mode, u_int32_t tsmap)
437: {
438: switch (mode) {
439: case IFM_TDM_E1:
440: case IFM_TDM_E1_G704:
441: case IFM_TDM_E1_G704_CRC4:
442: return (tsmap & ART_E1_MASK);
443: case IFM_TDM_T1_AMI:
444: case IFM_TDM_T1:
445: return (tsmap & ART_T1_MASK);
446: default:
447: return (tsmap);
448: }
449: }
CVSweb