timeout/untimeout ==> callout_*
[dragonfly.git] / sys / dev / atm / hfa / fore_load.c
CommitLineData
984263bc
MD
1/*
2 *
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
6 *
7 *
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
12 *
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
20 *
21 * Copyright 1994-1998 Network Computing Services, Inc.
22 *
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
25 *
26 * @(#) $FreeBSD: src/sys/dev/hfa/fore_load.c,v 1.13 1999/09/25 18:23:49 phk Exp $
7a651277 27 * @(#) $DragonFly: src/sys/dev/atm/hfa/fore_load.c,v 1.9 2004/09/15 01:51:55 joerg Exp $
984263bc
MD
28 */
29
30/*
31 * FORE Systems 200-Series Adapter Support
32 * ---------------------------------------
33 *
34 * Loadable kernel module and device identification support
35 *
36 */
37
1f2de5d4 38#include "fore_include.h"
984263bc 39
984263bc
MD
40/*
41 * Local functions
42 */
38e94a25 43static int fore_start (void);
984263bc 44#ifdef sun
38e94a25
RG
45static int fore_stop (void);
46static int fore_doload (void);
47static int fore_dounload (void);
48static int fore_identify (char *);
49static int fore_attach (struct devinfo *);
984263bc 50#endif
8021d602 51#if defined(__DragonFly__) || defined(__FreeBSD__)
38e94a25
RG
52static const char * fore_pci_probe (pcici_t, pcidi_t);
53static void fore_pci_attach (pcici_t, int);
984263bc 54#if BSD < 199506
38e94a25 55static int fore_pci_shutdown (struct kern_devconf *, int);
984263bc 56#else
38e94a25 57static void fore_pci_shutdown (void *, int);
984263bc
MD
58#endif
59#endif
38e94a25
RG
60static void fore_unattach (Fore_unit *);
61static void fore_reset (Fore_unit *);
984263bc
MD
62
63
64/*
65 * Local variables
66 */
67static int fore_inited = 0;
68
69/*
70 * Driver entry points
71 */
72#ifdef sun
73static struct dev_ops fore_ops = {
74 1, /* revision */
75 fore_identify, /* identify */
76 fore_attach, /* attach */
77 NULL, /* open */
78 NULL, /* close */
79 NULL, /* read */
80 NULL, /* write */
81 NULL, /* strategy */
82 NULL, /* dump */
83 NULL, /* psize */
84 NULL, /* ioctl */
85 NULL, /* reset */
86 NULL /* mmap */
87};
88#endif
89
8021d602 90#if defined(__DragonFly__) || defined(__FreeBSD__)
984263bc
MD
91static u_long fore_pci_count = 0;
92
93static struct pci_device fore_pci_device = {
94 FORE_DEV_NAME,
95 fore_pci_probe,
96 fore_pci_attach,
97 &fore_pci_count,
98#if BSD < 199506
99 fore_pci_shutdown
100#else
101 NULL
102#endif
103};
104
105COMPAT_PCI_DRIVER(fore_pci, fore_pci_device);
106#endif
107
108
109/*
110 * Initialize driver processing
111 *
112 * This will be called during module loading. Not much to do here, as
113 * we must wait for our identify/attach routines to get called before
114 * we know what we're in for.
115 *
116 * Arguments:
117 * none
118 *
119 * Returns:
120 * 0 startup was successful
121 * errno startup failed - reason indicated
122 *
123 */
124static int
125fore_start()
126{
127
128 /*
129 * Verify software version
130 */
131 if (atm_version != ATM_VERSION) {
132 log(LOG_ERR, "version mismatch: fore=%d.%d kernel=%d.%d\n",
133 ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION),
134 ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version));
135 return (EINVAL);
136 }
137
138 /*
139 * Initialize DMA mapping
140 */
141 DMA_INIT();
142
143 /*
144 * Start up watchdog timer
145 */
146 atm_timeout(&fore_timer, ATM_HZ * FORE_TIME_TICK, fore_timeout);
147
148 fore_inited = 1;
149
150 return (0);
151}
152
153
154#ifdef sun
155
156/*
157 * Halt driver processing
158 *
159 * This will be called just prior to unloading the module from memory.
160 * Everything we've setup since we've been loaded must be undone here.
161 *
162 * Arguments:
163 * none
164 *
165 * Returns:
166 * 0 shutdown was successful
167 * errno shutdown failed - reason indicated
168 *
169 */
170static int
171fore_stop()
172{
173 int err = 0;
174 int s = splimp();
175 int i;
176
177 /*
178 * Stop the watchdog timer
179 */
180 (void) atm_untimeout(&fore_timer);
181
182 /*
183 * Clean up each device (if any)
184 */
185 for ( i = 0; i < fore_nunits; i++ ) {
186 Fore_unit *fup = fore_units[i];
187
188 if (fup == NULL)
189 continue;
190
191 /*
192 * Deregister device from kernel services
193 */
194 if (err = atm_physif_deregister((Cmn_unit *)fup)) {
195 (void) splx(s);
196 return (err);
197 }
198
199 /*
200 * Unattach the device from the system
201 */
202 fore_unattach(fup);
203
204 /*
205 * Free any Fore-specific device resources
206 */
207 fore_interface_free(fup);
208
209 /*
210 * Free the unit structure
211 */
212 atm_dev_free(fup);
213 fore_units[i] = NULL;
214 }
215
216 fore_nunits = 0;
217
218 /*
219 * Now free our global resources
220 */
221
222 /*
223 * Release our storage pools
224 */
225 atm_release_pool(&fore_vcc_pool);
226 atm_release_pool(&fore_nif_pool);
227
228 /*
229 * Release all DMA mappings
230 */
231 DMA_RELEASE();
232
233 fore_inited = 0;
234
235 (void) splx(s);
236
237 return (0);
238}
239
240/*
241 * Device identify routine
242 *
243 * Determine if this driver will support the named device. If we claim to
244 * support the device, our attach routine will (later) be called for the
245 * device.
246 *
247 * Arguments:
248 * name pointer to identifier string from device
249 *
250 * Returns:
251 * 1 driver claims support for this device
252 * 0 device not claimed by this driver
253 *
254 */
255static int
256fore_identify(name)
257 char *name;
258{
259 int ret = 0;
260 int i = 0;
261
262 /*
263 * Initialize driver stuff
264 */
265 if (fore_inited == 0) {
266 if (fore_start())
267 return (0);
268 }
269
270 while (fore_devices[i].fd_name) {
271 if (strcmp(fore_devices[i].fd_name, name) == 0) {
272
273 /*
274 * We support this device!!
275 */
276 if (fore_nunits < FORE_MAX_UNITS) {
277 fore_nunits++;
278 ret = 1;
279 } else {
280 log(LOG_ERR,
281 "fore_identify: Too many devices\n");
282 }
283 break;
284 }
285 i++;
286 }
287 return (ret);
288}
289
290
291/*
292 * Device attach routine
293 *
294 * Attach a device we've previously claimed to support. Walk through its
295 * register set and map, as required. Determine what level the device will
296 * be interrupting at and then register an interrupt handler for it. If we
297 * succeed, then reset the adapter and read useful info from its PROM.
298 * Last, register the interface with the kernel ATM services.
299 *
300 * Arguments:
301 * devinfo_p pointer to device information structure
302 *
303 * Returns:
304 * 0 attach was successful
305 * -1 attach failed
306 *
307 */
308static int
309fore_attach(devinfo_p)
310 struct dev_info *devinfo_p;
311{
312 struct dev_reg *dev_reg_p;
313 struct dev_intr *dev_intr_p;
314 Fore_unit *fup;
315 Atm_config *fcp;
316 addr_t valp;
317 int val;
318 int i;
319 int err_count = BOOT_LOOPS;
320 static int unit = 0;
321
322 /*
323 * Sanity check
324 */
325 if (devinfo_p == NULL)
326 return (-1);
327
328 /*
329 * Make sure this isn't a duplicate unit
330 */
331 if (fore_units[unit] != NULL)
332 return (-1);
333
334 /*
335 * Allocate a new unit structure
336 */
337 fup = (Fore_unit *) atm_dev_alloc(sizeof(Fore_unit), sizeof(int), 0);
338 if (fup == NULL)
339 return (-1);
340
341 /*
342 * Start initializing it
343 */
344 fup->fu_unit = unit;
345 fup->fu_mtu = FORE_IFF_MTU;
346 fup->fu_devinfo = devinfo_p;
347 fup->fu_vcc_pool = &fore_vcc_pool;
348 fup->fu_nif_pool = &fore_nif_pool;
349 fup->fu_ioctl = fore_atm_ioctl;
350 fup->fu_instvcc = fore_instvcc;
351 fup->fu_openvcc = fore_openvcc;
352 fup->fu_closevcc = fore_closevcc;
353 fup->fu_output = fore_output;
354
355 /*
356 * Consider this unit assigned
357 */
358 fore_units[unit] = fup;
359 unit++;
360
361 ATM_DEBUG1("fore_attach: fup=%p\n", fup);
362 ATM_DEBUG2("\tfu_xmit_q=%p fu_xmit_head=%p\n",
363 fup->fu_xmit_q, &fup->fu_xmit_head);
364 ATM_DEBUG2("\tfu_recv_q=%p fu_recv_head=%p\n",
365 fup->fu_recv_q, &fup->fu_recv_head);
366 ATM_DEBUG2("\tfu_buf1s_q=%p fu_buf1s_head=%p\n",
367 fup->fu_buf1s_q, &fup->fu_buf1s_head);
368 ATM_DEBUG2("\tfu_buf1l_q=%p fu_buf1l_head=%p\n",
369 fup->fu_buf1l_q, &fup->fu_buf1l_head);
370 ATM_DEBUG2("\tfu_cmd_q=%p fu_cmd_head=%p\n",
371 fup->fu_cmd_q, &fup->fu_cmd_head);
372 ATM_DEBUG1("\tfu_stats=%p\n",
373 &fup->fu_stats);
374
375 /*
376 * Tell kernel our unit number
377 */
378 devinfo_p->devi_unit = fup->fu_unit;
379
380 /*
381 * Figure out what type of device we've got. This should always
382 * work since we've already done this at identify time!
383 */
384 i = 0;
385 while (fore_devices[i].fd_name) {
386 if (strcmp(fore_devices[i].fd_name, devinfo_p->devi_name) == 0)
387 break;
388 i++;
389 }
390 if (fore_devices[i].fd_name == NULL)
391 return (-1);
392
393 fup->fu_config.ac_device = fore_devices[i].fd_devtyp;
394
395 /*
396 * Walk through the OPENPROM register information
397 * mapping register banks as they are found.
398 */
399 for ( dev_reg_p = devinfo_p->devi_reg, i = 1;
400 i <= devinfo_p->devi_nreg; i++, ++dev_reg_p )
401 {
402 if ( dev_reg_p == NULL )
403 {
404 /*
405 * Can't happen...
406 */
407 return ( -1 );
408 }
409
410 /*
411 * Each device type has different register sets
412 */
413 switch (fup->fu_config.ac_device) {
414
415#ifdef FORE_SBUS
416 case DEV_FORE_SBA200E:
417
418 switch ( i )
419 {
420 /*
421 * Host Control Register (HCR)
422 */
423 case 1:
424 if ( sizeof(Fore_reg) != dev_reg_p->reg_size )
425 {
426 return ( -1 );
427 }
428 fup->fu_ctlreg = (Fore_reg *)
429 map_regs ( dev_reg_p->reg_addr,
430 sizeof(Fore_reg),
431 dev_reg_p->reg_bustype );
432 if ( fup->fu_ctlreg == NULL )
433 {
434 return ( -1 );
435 }
436 break;
437
438 /*
439 * SBus Burst Transfer Configuration Register
440 */
441 case 2:
442 /*
443 * Not used
444 */
445 break;
446
447 /*
448 * SBus Interrupt Level Select Register
449 */
450 case 3:
451 if ( sizeof (Fore_reg) != dev_reg_p->reg_size )
452 {
453 return ( -1 );
454 }
455 fup->fu_intlvl = (Fore_reg *)
456 map_regs ( dev_reg_p->reg_addr,
457 sizeof(Fore_reg),
458 dev_reg_p->reg_bustype );
459 if ( fup->fu_intlvl == NULL )
460 {
461 return ( -1 );
462 }
463 break;
464
465 /*
466 * i960 RAM
467 */
468 case 4:
469 fup->fu_ram = (Fore_mem *)
470 map_regs ( dev_reg_p->reg_addr,
471 dev_reg_p->reg_size,
472 dev_reg_p->reg_bustype );
473 if ( fup->fu_ram == NULL )
474 {
475 return ( -1 );
476 }
477 fup->fu_ramsize = dev_reg_p->reg_size;
478
479 /*
480 * Various versions of the Sun PROM mess with
481 * the reg_addr value in unpredictable (to me,
482 * at least) ways, so just use the "memoffset"
483 * property, which should give us the RAM
484 * offset directly.
485 */
486 val = getprop(devinfo_p->devi_nodeid,
487 "memoffset", -1);
488 if (val == -1) {
489 return (-1);
490 }
491 fup->fu_config.ac_ram = val;
492 fup->fu_config.ac_ramsize = fup->fu_ramsize;
493
494 /*
495 * Set monitor interface for initializing
496 */
497 fup->fu_mon = (Mon960 *)
498 (fup->fu_ram + MON960_BASE);
499 break;
500
501 default:
502 log(LOG_ERR,
503 "fore_attach: Too many registers\n");
504 return ( -1 );
505 }
506 break;
507
508 case DEV_FORE_SBA200:
509
510 switch ( i )
511 {
512 /*
513 * Board Control Register (BCR)
514 */
515 case 1:
516 if ( sizeof(Fore_reg) != dev_reg_p->reg_size )
517 {
518 return ( -1 );
519 }
520 fup->fu_ctlreg = (Fore_reg *)
521 map_regs ( dev_reg_p->reg_addr,
522 sizeof(Fore_reg),
523 dev_reg_p->reg_bustype );
524 if ( fup->fu_ctlreg == NULL )
525 {
526 return ( -1 );
527 }
528 break;
529
530 /*
531 * i960 RAM
532 */
533 case 2:
534 fup->fu_ram = (Fore_mem *)
535 map_regs ( dev_reg_p->reg_addr,
536 dev_reg_p->reg_size,
537 dev_reg_p->reg_bustype );
538 if ( fup->fu_ram == NULL )
539 {
540 return ( -1 );
541 }
542 fup->fu_ramsize = dev_reg_p->reg_size;
543
544 /*
545 * Various versions of the Sun PROM mess with
546 * the reg_addr value in unpredictable (to me,
547 * at least) ways, so just use the "memoffset"
548 * property, which should give us the RAM
549 * offset directly.
550 */
551 val = getprop(devinfo_p->devi_nodeid,
552 "memoffset", -1);
553 if (val == -1) {
554 return (-1);
555 }
556 fup->fu_config.ac_ram = val;
557 fup->fu_config.ac_ramsize = fup->fu_ramsize;
558
559 /*
560 * Set monitor interface for initializing
561 */
562 fup->fu_mon = (Mon960 *)
563 (fup->fu_ram + MON960_BASE);
564 break;
565
566 default:
567 log(LOG_ERR,
568 "fore_attach: Too many registers\n");
569 return ( -1 );
570 }
571 break;
572#endif /* FORE_SBUS */
573
574 default:
575 log(LOG_ERR,
576 "fore_attach: Unsupported device type %d\n",
577 fup->fu_config.ac_device);
578 return (-1);
579 }
580 }
581
582 /*
583 * Install the device in the interrupt chain.
584 *
585 * dev_intr_p may be null IFF devi_nintr is zero.
586 */
587 dev_intr_p = devinfo_p->devi_intr;
588 for ( i = devinfo_p->devi_nintr; i > 0; --i, ++dev_intr_p )
589 {
590
591 if ( dev_intr_p == NULL )
592 {
593 /*
594 * Can't happen.
595 */
596 return ( -1 );
597 }
598
599 /*
600 * Convert hardware ipl (0-15) into spl level.
601 */
602 if ( ipltospl ( dev_intr_p->int_pri ) > fup->fu_intrpri )
603 {
604 fup->fu_intrpri = ipltospl ( dev_intr_p->int_pri );
605
606 /*
607 * If SBA-200E card, set SBus interrupt level
608 * into board register
609 */
610 if ( fup->fu_intlvl ) {
611#if defined(sun4c)
612 *(fup->fu_intlvl) = dev_intr_p->int_pri;
613#elif defined(sun4m)
614 extern int svimap[];
615
616 *(fup->fu_intlvl) =
617 svimap[dev_intr_p->int_pri & 0xf];
618#else
619 #error PORT ME;
620#endif
621 }
622 }
623
624 DEVICE_LOCK((Cmn_unit *)fup);
625
626 /*
627 * Register our interrupt routine.
628 */
629 (void) addintr ( dev_intr_p->int_pri, fore_poll,
630 devinfo_p->devi_name, devinfo_p->devi_unit );
631
632 /*
633 * If we can do DMA (we can), then DVMA routines need
634 * to know the highest IPL level we will interrupt at.
635 */
636 adddma ( dev_intr_p->int_pri );
637
638 DEVICE_UNLOCK((Cmn_unit *)fup);
639 }
640
641 /*
642 * Poke the hardware...boot the CP and prepare it for downloading
643 */
644 fore_reset(fup);
645
646 switch (fup->fu_config.ac_device) {
647
648#ifdef FORE_SBUS
649 case DEV_FORE_SBA200E:
650 /*
651 * Enable interrupts
652 */
653 SBA200E_HCR_SET(*fup->fu_ctlreg, SBA200E_SBUS_ENA);
654 break;
655#endif /* FORE_SBUS */
656 }
657
658 /*
659 * Wait for monitor to perform self-test
660 */
661 while (CP_READ(fup->fu_mon->mon_bstat) != BOOT_MONREADY) {
662 if (CP_READ(fup->fu_mon->mon_bstat) == BOOT_FAILTEST) {
663 log(LOG_ERR, "fore_attach: Unit %d failed self-test\n",
664 fup->fu_unit);
665 return (-1);
666
667 } else if ( --err_count == 0 ) {
668 log(LOG_ERR, "fore_attach: Unit %d unable to boot\n",
669 fup->fu_unit);
670 return (-1);
671 }
672 DELAY ( BOOT_DELAY );
673 }
674
675 /*
676 * Write a one line message to the console informing
677 * that we've attached the device.
678 */
679 report_dev ( devinfo_p );
680
681 /*
682 * Get the mac address from the card PROM
683 */
684 val = getprop ( devinfo_p->devi_nodeid, "macaddress1", -1 );
685 if ( val != -1 ) {
686 fup->fu_pif.pif_macaddr.ma_data[0] = val & 0xff;
687 val = getprop ( devinfo_p->devi_nodeid, "macaddress2", -1 );
688 fup->fu_pif.pif_macaddr.ma_data[1] = val & 0xff;
689 val = getprop ( devinfo_p->devi_nodeid, "macaddress3", -1 );
690 fup->fu_pif.pif_macaddr.ma_data[2] = val & 0xff;
691 val = getprop ( devinfo_p->devi_nodeid, "macaddress4", -1 );
692 fup->fu_pif.pif_macaddr.ma_data[3] = val & 0xff;
693 val = getprop ( devinfo_p->devi_nodeid, "macaddress5", -1 );
694 fup->fu_pif.pif_macaddr.ma_data[4] = val & 0xff;
695 val = getprop ( devinfo_p->devi_nodeid, "macaddress6", -1 );
696 fup->fu_pif.pif_macaddr.ma_data[5] = val & 0xff;
697 } else {
698 /*
699 * Newer PROM - mac addresses have been combined. Also,
700 * macaddrlo2 reflects the board serial number.
701 */
702 val = htonl(getprop(devinfo_p->devi_nodeid, "macaddrlo2", -1));
703 KM_COPY ( (caddr_t)&val,
704 (caddr_t)&fup->fu_pif.pif_macaddr.ma_data[2],
705 sizeof(val) );
706 val = htonl(getprop(devinfo_p->devi_nodeid, "macaddrhi4", -1));
707 KM_COPY ( (caddr_t)&val,
708 (caddr_t)fup->fu_pif.pif_macaddr.ma_data,
709 sizeof(val) );
710 }
711
712 /*
713 * Setup the adapter config info
714 */
715 fcp = &fup->fu_config;
716 fcp->ac_vendor = VENDOR_FORE;
717 fcp->ac_vendapi = VENDAPI_FORE_1;
718 fcp->ac_macaddr = fup->fu_pif.pif_macaddr;
719 val = getprop ( devinfo_p->devi_nodeid, "promversion", -1 );
720 if ( val == -1 ) {
721 val = getprop ( devinfo_p->devi_nodeid, "hw-version", -1 );
722 }
723 if (val != -1) {
724 snprintf(fcp->ac_hard_vers,
725 sizeof(fcp->ac_hard_vers), "%d.%d.%d",
726 (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff);
727 } else
728 snprintf(fcp->ac_hard_vers,
729 sizeof(fcp->ac_hard_vers), "Unknown");
730
731 val = getprop ( devinfo_p->devi_nodeid, "serialnumber", -1 );
732 if ( val != -1 )
733 fcp->ac_serial = val;
734
735 valp = (addr_t)getlongprop ( devinfo_p->devi_nodeid, "model" );
736 if ( valp )
737 {
738 /*
739 * Media Type
740 */
741 switch (fcp->ac_device) {
742
743#ifdef FORE_SBUS
744 case DEV_FORE_SBA200E:
745 fcp->ac_media = MEDIA_OC3C;
746 fup->fu_pif.pif_pcr = ATM_PCR_OC3C;
747 break;
748
749 case DEV_FORE_SBA200:
750 /*
751 * Look at the /SSS trailer to determine 4B5B speed
752 * TAXI-100 = 125; TAXI-140 = 175
753 * Assume that OC3 has no /SSS speed identifier.
754 */
755 while (*valp && *valp != '/')
756 valp++;
757 if (*valp == NULL) {
758 fcp->ac_media = MEDIA_OC3C;
759 fup->fu_pif.pif_pcr = ATM_PCR_OC3C;
760 } else if (strcmp(valp, "/125") == 0) {
761 fcp->ac_media = MEDIA_TAXI_100;
762 fup->fu_pif.pif_pcr = ATM_PCR_TAXI100;
763 } else {
764 fcp->ac_media = MEDIA_TAXI_140;
765 fup->fu_pif.pif_pcr = ATM_PCR_TAXI140;
766 }
767 break;
768#endif /* FORE_SBUS */
769 }
770
771 /*
772 * Free property space
773 */
774 KM_FREE(valp, getproplen(devinfo_p->devi_nodeid, "model"), 0);
775 }
776
777 /*
778 * Bus information
779 */
780 fcp->ac_busslot =
781#ifdef SBUS_SIZE
782 (long)(devinfo_p->devi_reg->reg_addr - SBUS_BASE) / SBUS_SIZE;
783#else
784 sbusslot((u_long)devinfo_p->devi_reg->reg_addr);
785#endif
786
787 val = getprop(devinfo_p->devi_parent->devi_nodeid, "burst-sizes", 0);
788 if (val & SBUS_BURST32)
789 fcp->ac_bustype = BUS_SBUS_B32;
790 else
791 fcp->ac_bustype = BUS_SBUS_B16;
792
793 /*
794 * Set device capabilities
795 */
796 fup->fu_pif.pif_maxvpi = FORE_MAX_VPI;
797 fup->fu_pif.pif_maxvci = FORE_MAX_VCI;
798
799 /*
800 * Register this interface with ATM core services
801 */
802 if ( atm_physif_register
803 ((Cmn_unit *)fup, FORE_DEV_NAME, fore_services) != 0 )
804 {
805 /*
806 * Registration failed - back everything out
807 */
808 /*
809 * Modload calls UNLOAD if it get's a failure - don't
810 * call fore_unload() here.
811 */
812 return ( -1 );
813 }
814
815 /*
816 * Initialize the CP microcode program.
817 */
818 fore_initialize(fup);
819
820 return (0);
821}
822#endif /* sun */
823
824
8021d602 825#if defined(__DragonFly__) || defined(__FreeBSD__)
984263bc
MD
826/*
827 * Device probe routine
828 *
829 * Determine if this driver will support the identified device. If we claim
830 * to support the device, our attach routine will (later) be called for the
831 * device.
832 *
833 * Arguments:
834 * config_id device's PCI configuration ID
835 * device_id device's PCI Vendor/Device ID
836 *
837 * Returns:
838 * name device identification string
839 * NULL device not claimed by this driver
840 *
841 */
842static const char *
843fore_pci_probe(config_id, device_id)
844 pcici_t config_id;
845 pcidi_t device_id;
846{
847
848 /*
849 * Initialize driver stuff
850 */
851 if (fore_inited == 0) {
852 if (fore_start())
853 return (NULL);
854 }
855
856 if ((device_id & 0xffff) != FORE_VENDOR_ID)
857 return (NULL);
858
859 if (((device_id >> 16) & 0xffff) == FORE_PCA200E_ID)
860 return ("FORE Systems PCA-200E ATM");
861
862 return (NULL);
863}
864
865
866/*
867 * Device attach routine
868 *
869 * Attach a device we've previously claimed to support. Walk through its
870 * register set and map, as required. Determine what level the device will
871 * be interrupting at and then register an interrupt handler for it. If we
872 * succeed, then reset the adapter and initialize the microcode.
873 * Last, register the interface with the kernel ATM services.
874 *
875 * Arguments:
876 * config_id device's PCI configuration ID
877 * unit device unit number
878 *
879 * Returns:
880 * none
881 *
882 */
883static void
884fore_pci_attach(config_id, unit)
885 pcici_t config_id;
886 int unit;
887{
888 Fore_unit *fup;
889 vm_offset_t va;
890 vm_offset_t pa;
891 pcidi_t device_id;
892 long val;
893 int err_count = BOOT_LOOPS;
894
895 /*
896 * Just checking...
897 */
898 if (unit >= FORE_MAX_UNITS) {
899 log(LOG_ERR, "%s%d: too many devices\n",
900 FORE_DEV_NAME, unit);
901 return;
902 }
903
904 /*
905 * Make sure this isn't a duplicate unit
906 */
907 if (fore_units[unit] != NULL)
908 return;
909
910 /*
911 * Allocate a new unit structure
912 */
913 fup = (Fore_unit *) atm_dev_alloc(sizeof(Fore_unit), sizeof(int), 0);
914 if (fup == NULL)
915 return;
916
917 /*
918 * Start initializing it
919 */
920 fup->fu_unit = unit;
921 fup->fu_mtu = FORE_IFF_MTU;
922 fup->fu_pcitag = config_id;
923 fup->fu_vcc_pool = &fore_vcc_pool;
924 fup->fu_nif_pool = &fore_nif_pool;
925 fup->fu_ioctl = fore_atm_ioctl;
926 fup->fu_instvcc = fore_instvcc;
927 fup->fu_openvcc = fore_openvcc;
928 fup->fu_closevcc = fore_closevcc;
929 fup->fu_output = fore_output;
7a651277 930 callout_init(&fup->fu_init_timer);
984263bc
MD
931
932 /*
933 * Get our device type
934 */
935 device_id = pci_conf_read ( config_id, PCI_ID_REG );
936 switch ((device_id >> 16) & 0xffff) {
937
938 case FORE_PCA200E_ID:
939 fup->fu_config.ac_device = DEV_FORE_PCA200E;
940 break;
941
942 default:
943 fup->fu_config.ac_device = DEV_UNKNOWN;
944 }
945
946 /*
947 * Enable Memory Mapping / Bus Mastering
948 */
949 val = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
950 val |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
951 pci_conf_write(config_id, PCI_COMMAND_STATUS_REG, val);
952
953 /*
954 * Map RAM
955 */
956 val = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
957 if ((val & PCIM_CMD_MEMEN) == 0) {
958 log(LOG_ERR, "%s%d: memory mapping not enabled\n",
959 FORE_DEV_NAME, unit);
960 goto failed;
961 }
962 if ((pci_map_mem(config_id, PCA200E_PCI_MEMBASE, &va, &pa)) == 0) {
963 log(LOG_ERR, "%s%d: unable to map memory\n",
964 FORE_DEV_NAME, unit);
965 goto failed;
966 }
967 fup->fu_ram = (Fore_mem *)va;
968 fup->fu_ramsize = PCA200E_RAM_SIZE;
969 fup->fu_mon = (Mon960 *)(fup->fu_ram + MON960_BASE);
970 fup->fu_ctlreg = (Fore_reg *)(va + PCA200E_HCR_OFFSET);
971 fup->fu_imask = (Fore_reg *)(va + PCA200E_IMASK_OFFSET);
972 fup->fu_psr = (Fore_reg *)(va + PCA200E_PSR_OFFSET);
973
974 /*
975 * Convert Endianess of Slave RAM accesses
976 */
977 val = pci_conf_read(config_id, PCA200E_PCI_MCTL);
978 val |= PCA200E_MCTL_SWAP;
979 pci_conf_write(config_id, PCA200E_PCI_MCTL, val);
980
981 /*
982 * Map interrupt in
983 */
984 if ( !pci_map_int( config_id, fore_intr, fup, &net_imask ) ) {
985 log(LOG_ERR, "%s%d: unable to map interrupt\n",
986 FORE_DEV_NAME, unit);
987 goto failed;
988 }
989
990 /*
991 * Poke the hardware - boot the CP and prepare it for downloading
992 */
993 fore_reset(fup);
994
995 /*
996 * Wait for the monitor to perform self-test
997 */
998 while (CP_READ(fup->fu_mon->mon_bstat) != BOOT_MONREADY) {
999 if (CP_READ(fup->fu_mon->mon_bstat) == BOOT_FAILTEST) {
1000 log(LOG_ERR, "%s%d: failed self-test\n",
1001 FORE_DEV_NAME, unit);
1002 goto failed;
1003 } else if ( --err_count == 0 ) {
1004 log(LOG_ERR, "%s%d: unable to boot - status=0x%lx\n",
1005 FORE_DEV_NAME, unit,
1006 (u_long)CP_READ(fup->fu_mon->mon_bstat));
1007 goto failed;
1008 }
1009 DELAY ( BOOT_DELAY );
1010 }
1011
1012 /*
1013 * Setup the adapter config info - at least as much as we can
1014 */
1015 fup->fu_config.ac_vendor = VENDOR_FORE;
1016 fup->fu_config.ac_vendapi = VENDAPI_FORE_1;
1017 fup->fu_config.ac_media = MEDIA_OC3C;
1018 fup->fu_pif.pif_pcr = ATM_PCR_OC3C;
1019 fup->fu_config.ac_bustype = BUS_PCI;
1020 fup->fu_config.ac_busslot = config_id->bus << 8 | config_id->slot;
1021
1022 /*
1023 * Save device ram info for user-level programs
1024 */
1025 fup->fu_config.ac_ram = (long)fup->fu_ram;
1026 fup->fu_config.ac_ramsize = fup->fu_ramsize;
1027
1028 /*
1029 * Set device capabilities
1030 */
1031 fup->fu_pif.pif_maxvpi = FORE_MAX_VPI;
1032 fup->fu_pif.pif_maxvci = FORE_MAX_VCI;
1033
1034 /*
1035 * Register this interface with ATM core services
1036 */
1037 if ( atm_physif_register
1038 ((Cmn_unit *)fup, FORE_DEV_NAME, fore_services) != 0 )
1039 {
1040 /*
1041 * Registration failed - back everything out
1042 */
1043 goto failed;
1044 }
1045
1046 fore_units[unit] = fup;
1047 fore_nunits++;
1048
1049#if BSD >= 199506
1050 /*
1051 * Add hook to our shutdown function
1052 */
1053 EVENTHANDLER_REGISTER(shutdown_post_sync, fore_pci_shutdown, fup,
1054 SHUTDOWN_PRI_DEFAULT);
1055#endif
1056
1057 /*
1058 * Initialize the CP microcode program.
1059 */
1060 fore_initialize(fup);
1061
1062 return;
1063
1064failed:
1065 /*
1066 * Unattach the device from the system
1067 */
1068 fore_unattach(fup);
1069
1070 /*
1071 * Free any Fore-specific device resources
1072 */
1073 fore_interface_free(fup);
1074
1075 atm_dev_free(fup);
1076
1077 return;
1078}
1079
1080
1081#if BSD < 199506
1082/*
1083 * Device shutdown routine
1084 *
1085 * Arguments:
1086 * kdc pointer to device's configuration table
1087 * force forced shutdown flag
1088 *
1089 * Returns:
1090 * none
1091 *
1092 */
1093static int
1094fore_pci_shutdown(kdc, force)
1095 struct kern_devconf *kdc;
1096 int force;
1097{
1098 Fore_unit *fup;
1099
1100 if (kdc->kdc_unit < fore_nunits) {
1101
1102 fup = fore_units[kdc->kdc_unit];
1103 if (fup != NULL) {
1104 fore_reset(fup);
1105 }
1106 }
1107
1108 (void) dev_detach(kdc);
1109 return (0);
1110}
1111#else
1112/*
1113 * Device shutdown routine
1114 *
1115 * Arguments:
1116 * howto type of shutdown
1117 * fup pointer to device unit structure
1118 *
1119 * Returns:
1120 * none
1121 *
1122 */
1123static void
1124fore_pci_shutdown(fup, howto)
1125 void *fup;
1126 int howto;
1127{
1128
1129 fore_reset((Fore_unit *) fup);
1130
1131 return;
1132}
1133#endif /* BSD < 199506 */
1134#endif /* __FreeBSD__ */
1135
1136
1137/*
1138 * Device unattach routine
1139 *
1140 * Reset the physical device, remove any pending timeouts,
1141 * unmap any register sets, and unregister any interrupts.
1142 *
1143 * Arguments:
1144 * fup pointer to device unit structure
1145 *
1146 * Returns:
1147 * none
1148 */
1149static void
1150fore_unattach(fup)
1151 Fore_unit *fup;
1152{
1153#ifdef sun
1154 struct dev_info *devinfo_p = fup->fu_devinfo;
1155 struct dev_reg *dev_reg_p;
1156 struct dev_intr *dev_intr_p;
1157 int i;
1158#endif
1159
1160
1161 /*
1162 * Reset the board and return it to cold_start state.
1163 * Hopefully, this will prevent use of resources as
1164 * we're trying to free things up.
1165 */
1166 fore_reset(fup);
1167
1168 /*
1169 * Lock out all device interrupts
1170 */
1171 DEVICE_LOCK((Cmn_unit *)fup);
1172
1173 /*
1174 * Remove any pending timeout()'s
1175 */
7a651277 1176 callout_stop(&fup->fu_init_timer);
984263bc
MD
1177
1178#ifdef sun
1179 /*
1180 * Remove any mappings of the device
1181 */
1182 for ( dev_reg_p = devinfo_p->devi_reg, i = 1;
1183 i <= devinfo_p->devi_nreg; i++, ++dev_reg_p )
1184 {
1185 if ( dev_reg_p == NULL )
1186 {
1187 /*
1188 * Can't happen...
1189 */
1190 break;
1191 }
1192
1193 /*
1194 * Each device type has different register sets
1195 */
1196 switch (fup->fu_config.ac_device) {
1197
1198#ifdef FORE_SBUS
1199 case DEV_FORE_SBA200E:
1200
1201 switch ( i )
1202 {
1203 /*
1204 * Host Control Register (HCR)
1205 */
1206 case 1:
1207 unmap_regs((addr_t)fup->fu_ctlreg,
1208 sizeof(Fore_reg));
1209 break;
1210
1211 /*
1212 * SBus Burst Transfer Configuration Register
1213 */
1214 case 2:
1215 /*
1216 * Not used
1217 */
1218 break;
1219
1220 /*
1221 * SBus Interrupt Level Select Register
1222 */
1223 case 3:
1224 unmap_regs((addr_t)fup->fu_intlvl,
1225 sizeof(Fore_reg));
1226 break;
1227
1228 /*
1229 * i960 RAM
1230 */
1231 case 4:
1232 unmap_regs((addr_t)fup->fu_ram,
1233 fup->fu_ramsize);
1234 break;
1235 }
1236 break;
1237
1238 case DEV_FORE_SBA200:
1239
1240 switch ( i )
1241 {
1242 /*
1243 * Board Control Register (BCR)
1244 */
1245 case 1:
1246 unmap_regs((addr_t)fup->fu_ctlreg,
1247 sizeof(Fore_reg));
1248 break;
1249
1250 /*
1251 * i960 RAM
1252 */
1253 case 2:
1254 unmap_regs((addr_t)fup->fu_ram,
1255 fup->fu_ramsize);
1256 break;
1257 }
1258 break;
1259#endif /* FORE_SBUS */
1260 }
1261 }
1262
1263 /*
1264 * Remove the interrupt vector(s)
1265 */
1266 dev_intr_p = devinfo_p->devi_intr;
1267 for ( i = devinfo_p->devi_nintr; i > 0; --i, ++dev_intr_p )
1268 {
1269 if ( dev_intr_p == NULL )
1270 {
1271 /*
1272 * Can't happen...
1273 */
1274 break;
1275 }
1276 (void) remintr ( dev_intr_p->int_pri, fore_poll );
1277 }
1278#endif /* sun */
1279
8021d602 1280#if defined(__DragonFly__) || defined(__FreeBSD__)
984263bc
MD
1281 /*
1282 * Unmap the device interrupt
1283 */
1284 (void) pci_unmap_int(fup->fu_pcitag);
1285
1286 /*
1287 * Unmap memory
1288 */
1289#ifdef notdef
1290 (void) pci_unmap_mem(fup->fu_pcitag, PCA200E_PCI_MEMBASE);
1291#endif
1292#endif /* __FreeBSD__ */
1293
1294 DEVICE_UNLOCK((Cmn_unit *)fup);
1295}
1296
1297
1298/*
1299 * Device reset routine
1300 *
1301 * Reset the physical device
1302 *
1303 * Arguments:
1304 * fup pointer to device unit structure
1305 *
1306 * Returns:
1307 * none
1308 */
1309static void
1310fore_reset(fup)
1311 Fore_unit *fup;
1312{
1313 int s = splimp();
1314
1315 /*
1316 * Reset the board and return it to cold_start state
1317 */
1318 if (fup->fu_mon)
1319 fup->fu_mon->mon_bstat = CP_WRITE(BOOT_COLDSTART);
1320
1321 if (fup->fu_ctlreg) {
1322
1323 switch (fup->fu_config.ac_device) {
1324
1325#ifdef FORE_SBUS
1326 case DEV_FORE_SBA200E:
1327 /*
1328 * Reset i960 by setting and clearing RESET
1329 */
1330 SBA200E_HCR_INIT(*fup->fu_ctlreg, SBA200E_RESET);
1331 SBA200E_HCR_CLR(*fup->fu_ctlreg, SBA200E_RESET);
1332 break;
1333
1334 case DEV_FORE_SBA200:
1335 /*
1336 * Reset i960 by setting and clearing RESET
1337 *
1338 * SBA200 will NOT reset if bit is OR'd in!
1339 */
1340 *fup->fu_ctlreg = SBA200_RESET;
1341 *fup->fu_ctlreg = SBA200_RESET_CLR;
1342 break;
1343#endif /* FORE_SBUS */
1344#ifdef FORE_PCI
1345 case DEV_FORE_PCA200E:
1346 /*
1347 * Reset i960 by setting and clearing RESET
1348 */
1349 PCA200E_HCR_INIT(*fup->fu_ctlreg, PCA200E_RESET);
1350 DELAY(10000);
1351 PCA200E_HCR_CLR(*fup->fu_ctlreg, PCA200E_RESET);
1352 break;
1353
1354#endif
f15db79e
MD
1355 default:
1356 panic("fore_reset: unknown device type");
1357 break;
984263bc
MD
1358 }
1359 }
1360
1361 (void) splx(s);
1362 return;
1363}
1364
1365
1366#ifndef ATM_LINKED
1367/*
1368 *******************************************************************
1369 *
1370 * Loadable Module Support
1371 *
1372 *******************************************************************
1373 */
1374
1375#ifdef sun
1376/*
1377 * Generic module load processing
1378 *
1379 * This function is called by an OS-specific function when this
1380 * module is being loaded.
1381 *
1382 * Arguments:
1383 * none
1384 *
1385 * Returns:
1386 * 0 load was successful
1387 * errno load failed - reason indicated
1388 *
1389 */
1390static int
1391fore_doload()
1392{
1393 int err = 0;
1394
1395 /*
1396 * Start us up
1397 */
1398 err = fore_start();
1399 if (err)
1400 /* Problems, clean up */
1401 (void)fore_stop();
1402
1403 return (err);
1404}
1405
1406
1407/*
1408 * Generic module unload processing
1409 *
1410 * This function is called by an OS-specific function when this
1411 * module is being unloaded.
1412 *
1413 * Arguments:
1414 * none
1415 *
1416 * Returns:
1417 * 0 unload was successful
1418 * errno unload failed - reason indicated
1419 *
1420 */
1421static int
1422fore_dounload()
1423{
1424 int err = 0;
1425
1426 /*
1427 * OK, try to clean up our mess
1428 */
1429 err = fore_stop();
1430
1431 return (err);
1432}
1433
1434
1435/*
1436 * Loadable driver description
1437 */
1438static struct vdldrv fore_drv = {
1439 VDMAGIC_DRV, /* Device Driver */
1440 "fore_mod", /* name */
1441 &fore_ops, /* dev_ops */
1442 NULL, /* bdevsw */
1443 NULL, /* cdevsw */
1444 0, /* blockmajor */
1445 0 /* charmajor */
1446};
1447
1448
1449/*
1450 * Loadable module support entry point
1451 *
1452 * This is the routine called by the vd driver for all loadable module
1453 * functions for this pseudo driver. This routine name must be specified
1454 * on the modload(1) command. This routine will be called whenever the
1455 * modload(1), modunload(1) or modstat(1) commands are issued for this
1456 * module.
1457 *
1458 * Arguments:
1459 * cmd vd command code
1460 * vdp pointer to vd driver's structure
1461 * vdi pointer to command-specific vdioctl_* structure
1462 * vds pointer to status structure (VDSTAT only)
1463 *
1464 * Returns:
1465 * 0 command was successful
1466 * errno command failed - reason indicated
1467 *
1468 */
1469int
1470fore_mod(cmd, vdp, vdi, vds)
1471 int cmd;
1472 struct vddrv *vdp;
1473 caddr_t vdi;
1474 struct vdstat *vds;
1475{
1476 int err = 0;
1477
1478 switch (cmd) {
1479
1480 case VDLOAD:
1481 /*
1482 * Module Load
1483 *
1484 * We dont support any user configuration
1485 */
1486 err = fore_doload();
1487 if (err == 0)
1488 /* Let vd driver know about us */
1489 vdp->vdd_vdtab = (struct vdlinkage *)&fore_drv;
1490 break;
1491
1492 case VDUNLOAD:
1493 /*
1494 * Module Unload
1495 */
1496 err = fore_dounload();
1497 break;
1498
1499 case VDSTAT:
1500 /*
1501 * Module Status
1502 */
1503
1504 /* Not much to say at the moment */
1505
1506 break;
1507
1508 default:
1509 log(LOG_ERR, "fore_mod: Unknown vd command 0x%x\n", cmd);
1510 err = EINVAL;
1511 }
1512
1513 return (err);
1514}
1515#endif /* sun */
1516
8021d602 1517#if defined(__DragonFly__) || defined(__FreeBSD__)
984263bc
MD
1518#ifdef notdef
1519
1520/*
1521 * Driver entry points
1522 */
1523static struct cdevsw fore_cdev = {
fabb8ceb
MD
1524 /* name */ noname,
1525 /* maj */ -1,
1526 /* flags */ 0,
1527 /* port */ NULL,
455fcd7e 1528 /* clone */ NULL,
fabb8ceb 1529
984263bc
MD
1530 /* open */ noopen,
1531 /* close */ noclose,
1532 /* read */ noread,
1533 /* write */ nowrite,
1534 /* ioctl */ noioctl,
1535 /* poll */ nopoll,
1536 /* mmap */ nommap,
1537 /* strategy */ nostrategy,
984263bc 1538 /* dump */ nodump,
fabb8ceb 1539 /* psize */ nopsize
984263bc
MD
1540};
1541
1542
1543/*
1544 * Loadable device driver module description
1545 */
1546#if BSD < 199506
1547MOD_DEV("fore_mod", LM_DT_CHAR, -1, (void *)&fore_cdev);
1548#else
1549MOD_DEV(fore, LM_DT_CHAR, -1, (void *)&fore_cdev);
1550#endif
1551
1552
1553/*
1554 * Loadable module support "load" entry point
1555 *
1556 * This is the routine called by the lkm driver whenever the
1557 * modload(1) command is issued for this module.
1558 *
1559 * Arguments:
1560 * lkmtp pointer to lkm drivers's structure
1561 * cmd lkm command code
1562 *
1563 * Returns:
1564 * 0 command was successful
1565 * errno command failed - reason indicated
1566 *
1567 */
1568static int
1569fore_load(lkmtp, cmd)
1570 struct lkm_table *lkmtp;
1571 int cmd;
1572{
1573 return(fore_doload());
1574}
1575
1576
1577/*
1578 * Loadable module support "unload" entry point
1579 *
1580 * This is the routine called by the lkm driver whenever the
1581 * modunload(1) command is issued for this module.
1582 *
1583 * Arguments:
1584 * lkmtp pointer to lkm drivers's structure
1585 * cmd lkm command code
1586 *
1587 * Returns:
1588 * 0 command was successful
1589 * errno command failed - reason indicated
1590 *
1591 */
1592static int
1593fore_unload(lkmtp, cmd)
1594 struct lkm_table *lkmtp;
1595 int cmd;
1596{
1597 return(fore_dounload());
1598}
1599
1600
1601/*
1602 * Loadable module support entry point
1603 *
1604 * This is the routine called by the lkm driver for all loadable module
1605 * functions for this driver. This routine name must be specified
1606 * on the modload(1) command. This routine will be called whenever the
1607 * modload(1), modunload(1) or modstat(1) commands are issued for this
1608 * module.
1609 *
1610 * Arguments:
1611 * lkmtp pointer to lkm drivers's structure
1612 * cmd lkm command code
1613 * ver lkm version
1614 *
1615 * Returns:
1616 * 0 command was successful
1617 * errno command failed - reason indicated
1618 *
1619 */
1620int
1621fore_mod(lkmtp, cmd, ver)
1622 struct lkm_table *lkmtp;
1623 int cmd;
1624 int ver;
1625{
1626#if BSD < 199506
1627 DISPATCH(lkmtp, cmd, ver, fore_load, fore_unload, nosys);
1628#else
1629 DISPATCH(lkmtp, cmd, ver, fore_load, fore_unload, lkm_nullcmd);
1630#endif
1631}
1632#endif /* notdef */
1633#endif /* __FreeBSD__ */
1634
1635#endif /* ATM_LINKED */
1636