3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/dev/hfa/fore_load.c,v 1.13 1999/09/25 18:23:49 phk Exp $
27 * @(#) $DragonFly: src/sys/dev/atm/hfa/fore_load.c,v 1.8 2004/05/13 23:49:14 dillon Exp $
31 * FORE Systems 200-Series Adapter Support
32 * ---------------------------------------
34 * Loadable kernel module and device identification support
38 #include "fore_include.h"
43 static int fore_start (void);
45 static int fore_stop (void);
46 static int fore_doload (void);
47 static int fore_dounload (void);
48 static int fore_identify (char *);
49 static int fore_attach (struct devinfo *);
51 #if defined(__DragonFly__) || defined(__FreeBSD__)
52 static const char * fore_pci_probe (pcici_t, pcidi_t);
53 static void fore_pci_attach (pcici_t, int);
55 static int fore_pci_shutdown (struct kern_devconf *, int);
57 static void fore_pci_shutdown (void *, int);
60 static void fore_unattach (Fore_unit *);
61 static void fore_reset (Fore_unit *);
67 static int fore_inited = 0;
73 static struct dev_ops fore_ops = {
75 fore_identify, /* identify */
76 fore_attach, /* attach */
90 #if defined(__DragonFly__) || defined(__FreeBSD__)
91 static u_long fore_pci_count = 0;
93 static struct pci_device fore_pci_device = {
105 COMPAT_PCI_DRIVER(fore_pci, fore_pci_device);
110 * Initialize driver processing
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.
120 * 0 startup was successful
121 * errno startup failed - reason indicated
129 * Verify software version
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));
139 * Initialize DMA mapping
144 * Start up watchdog timer
146 atm_timeout(&fore_timer, ATM_HZ * FORE_TIME_TICK, fore_timeout);
157 * Halt driver processing
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.
166 * 0 shutdown was successful
167 * errno shutdown failed - reason indicated
178 * Stop the watchdog timer
180 (void) atm_untimeout(&fore_timer);
183 * Clean up each device (if any)
185 for ( i = 0; i < fore_nunits; i++ ) {
186 Fore_unit *fup = fore_units[i];
192 * Deregister device from kernel services
194 if (err = atm_physif_deregister((Cmn_unit *)fup)) {
200 * Unattach the device from the system
205 * Free any Fore-specific device resources
207 fore_interface_free(fup);
210 * Free the unit structure
213 fore_units[i] = NULL;
219 * Now free our global resources
223 * Release our storage pools
225 atm_release_pool(&fore_vcc_pool);
226 atm_release_pool(&fore_nif_pool);
229 * Release all DMA mappings
241 * Device identify routine
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
248 * name pointer to identifier string from device
251 * 1 driver claims support for this device
252 * 0 device not claimed by this driver
263 * Initialize driver stuff
265 if (fore_inited == 0) {
270 while (fore_devices[i].fd_name) {
271 if (strcmp(fore_devices[i].fd_name, name) == 0) {
274 * We support this device!!
276 if (fore_nunits < FORE_MAX_UNITS) {
281 "fore_identify: Too many devices\n");
292 * Device attach routine
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.
301 * devinfo_p pointer to device information structure
304 * 0 attach was successful
309 fore_attach(devinfo_p)
310 struct dev_info *devinfo_p;
312 struct dev_reg *dev_reg_p;
313 struct dev_intr *dev_intr_p;
319 int err_count = BOOT_LOOPS;
325 if (devinfo_p == NULL)
329 * Make sure this isn't a duplicate unit
331 if (fore_units[unit] != NULL)
335 * Allocate a new unit structure
337 fup = (Fore_unit *) atm_dev_alloc(sizeof(Fore_unit), sizeof(int), 0);
342 * Start initializing it
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;
356 * Consider this unit assigned
358 fore_units[unit] = fup;
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",
376 * Tell kernel our unit number
378 devinfo_p->devi_unit = fup->fu_unit;
381 * Figure out what type of device we've got. This should always
382 * work since we've already done this at identify time!
385 while (fore_devices[i].fd_name) {
386 if (strcmp(fore_devices[i].fd_name, devinfo_p->devi_name) == 0)
390 if (fore_devices[i].fd_name == NULL)
393 fup->fu_config.ac_device = fore_devices[i].fd_devtyp;
396 * Walk through the OPENPROM register information
397 * mapping register banks as they are found.
399 for ( dev_reg_p = devinfo_p->devi_reg, i = 1;
400 i <= devinfo_p->devi_nreg; i++, ++dev_reg_p )
402 if ( dev_reg_p == NULL )
411 * Each device type has different register sets
413 switch (fup->fu_config.ac_device) {
416 case DEV_FORE_SBA200E:
421 * Host Control Register (HCR)
424 if ( sizeof(Fore_reg) != dev_reg_p->reg_size )
428 fup->fu_ctlreg = (Fore_reg *)
429 map_regs ( dev_reg_p->reg_addr,
431 dev_reg_p->reg_bustype );
432 if ( fup->fu_ctlreg == NULL )
439 * SBus Burst Transfer Configuration Register
448 * SBus Interrupt Level Select Register
451 if ( sizeof (Fore_reg) != dev_reg_p->reg_size )
455 fup->fu_intlvl = (Fore_reg *)
456 map_regs ( dev_reg_p->reg_addr,
458 dev_reg_p->reg_bustype );
459 if ( fup->fu_intlvl == NULL )
469 fup->fu_ram = (Fore_mem *)
470 map_regs ( dev_reg_p->reg_addr,
472 dev_reg_p->reg_bustype );
473 if ( fup->fu_ram == NULL )
477 fup->fu_ramsize = dev_reg_p->reg_size;
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
486 val = getprop(devinfo_p->devi_nodeid,
491 fup->fu_config.ac_ram = val;
492 fup->fu_config.ac_ramsize = fup->fu_ramsize;
495 * Set monitor interface for initializing
497 fup->fu_mon = (Mon960 *)
498 (fup->fu_ram + MON960_BASE);
503 "fore_attach: Too many registers\n");
508 case DEV_FORE_SBA200:
513 * Board Control Register (BCR)
516 if ( sizeof(Fore_reg) != dev_reg_p->reg_size )
520 fup->fu_ctlreg = (Fore_reg *)
521 map_regs ( dev_reg_p->reg_addr,
523 dev_reg_p->reg_bustype );
524 if ( fup->fu_ctlreg == NULL )
534 fup->fu_ram = (Fore_mem *)
535 map_regs ( dev_reg_p->reg_addr,
537 dev_reg_p->reg_bustype );
538 if ( fup->fu_ram == NULL )
542 fup->fu_ramsize = dev_reg_p->reg_size;
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
551 val = getprop(devinfo_p->devi_nodeid,
556 fup->fu_config.ac_ram = val;
557 fup->fu_config.ac_ramsize = fup->fu_ramsize;
560 * Set monitor interface for initializing
562 fup->fu_mon = (Mon960 *)
563 (fup->fu_ram + MON960_BASE);
568 "fore_attach: Too many registers\n");
572 #endif /* FORE_SBUS */
576 "fore_attach: Unsupported device type %d\n",
577 fup->fu_config.ac_device);
583 * Install the device in the interrupt chain.
585 * dev_intr_p may be null IFF devi_nintr is zero.
587 dev_intr_p = devinfo_p->devi_intr;
588 for ( i = devinfo_p->devi_nintr; i > 0; --i, ++dev_intr_p )
591 if ( dev_intr_p == NULL )
600 * Convert hardware ipl (0-15) into spl level.
602 if ( ipltospl ( dev_intr_p->int_pri ) > fup->fu_intrpri )
604 fup->fu_intrpri = ipltospl ( dev_intr_p->int_pri );
607 * If SBA-200E card, set SBus interrupt level
608 * into board register
610 if ( fup->fu_intlvl ) {
612 *(fup->fu_intlvl) = dev_intr_p->int_pri;
617 svimap[dev_intr_p->int_pri & 0xf];
624 DEVICE_LOCK((Cmn_unit *)fup);
627 * Register our interrupt routine.
629 (void) addintr ( dev_intr_p->int_pri, fore_poll,
630 devinfo_p->devi_name, devinfo_p->devi_unit );
633 * If we can do DMA (we can), then DVMA routines need
634 * to know the highest IPL level we will interrupt at.
636 adddma ( dev_intr_p->int_pri );
638 DEVICE_UNLOCK((Cmn_unit *)fup);
642 * Poke the hardware...boot the CP and prepare it for downloading
646 switch (fup->fu_config.ac_device) {
649 case DEV_FORE_SBA200E:
653 SBA200E_HCR_SET(*fup->fu_ctlreg, SBA200E_SBUS_ENA);
655 #endif /* FORE_SBUS */
659 * Wait for monitor to perform self-test
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",
667 } else if ( --err_count == 0 ) {
668 log(LOG_ERR, "fore_attach: Unit %d unable to boot\n",
672 DELAY ( BOOT_DELAY );
676 * Write a one line message to the console informing
677 * that we've attached the device.
679 report_dev ( devinfo_p );
682 * Get the mac address from the card PROM
684 val = getprop ( devinfo_p->devi_nodeid, "macaddress1", -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;
699 * Newer PROM - mac addresses have been combined. Also,
700 * macaddrlo2 reflects the board serial number.
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],
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,
713 * Setup the adapter config info
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 );
721 val = getprop ( devinfo_p->devi_nodeid, "hw-version", -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);
728 snprintf(fcp->ac_hard_vers,
729 sizeof(fcp->ac_hard_vers), "Unknown");
731 val = getprop ( devinfo_p->devi_nodeid, "serialnumber", -1 );
733 fcp->ac_serial = val;
735 valp = (addr_t)getlongprop ( devinfo_p->devi_nodeid, "model" );
741 switch (fcp->ac_device) {
744 case DEV_FORE_SBA200E:
745 fcp->ac_media = MEDIA_OC3C;
746 fup->fu_pif.pif_pcr = ATM_PCR_OC3C;
749 case DEV_FORE_SBA200:
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.
755 while (*valp && *valp != '/')
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;
764 fcp->ac_media = MEDIA_TAXI_140;
765 fup->fu_pif.pif_pcr = ATM_PCR_TAXI140;
768 #endif /* FORE_SBUS */
772 * Free property space
774 KM_FREE(valp, getproplen(devinfo_p->devi_nodeid, "model"), 0);
782 (long)(devinfo_p->devi_reg->reg_addr - SBUS_BASE) / SBUS_SIZE;
784 sbusslot((u_long)devinfo_p->devi_reg->reg_addr);
787 val = getprop(devinfo_p->devi_parent->devi_nodeid, "burst-sizes", 0);
788 if (val & SBUS_BURST32)
789 fcp->ac_bustype = BUS_SBUS_B32;
791 fcp->ac_bustype = BUS_SBUS_B16;
794 * Set device capabilities
796 fup->fu_pif.pif_maxvpi = FORE_MAX_VPI;
797 fup->fu_pif.pif_maxvci = FORE_MAX_VCI;
800 * Register this interface with ATM core services
802 if ( atm_physif_register
803 ((Cmn_unit *)fup, FORE_DEV_NAME, fore_services) != 0 )
806 * Registration failed - back everything out
809 * Modload calls UNLOAD if it get's a failure - don't
810 * call fore_unload() here.
816 * Initialize the CP microcode program.
818 fore_initialize(fup);
825 #if defined(__DragonFly__) || defined(__FreeBSD__)
827 * Device probe routine
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
834 * config_id device's PCI configuration ID
835 * device_id device's PCI Vendor/Device ID
838 * name device identification string
839 * NULL device not claimed by this driver
843 fore_pci_probe(config_id, device_id)
849 * Initialize driver stuff
851 if (fore_inited == 0) {
856 if ((device_id & 0xffff) != FORE_VENDOR_ID)
859 if (((device_id >> 16) & 0xffff) == FORE_PCA200E_ID)
860 return ("FORE Systems PCA-200E ATM");
867 * Device attach routine
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.
876 * config_id device's PCI configuration ID
877 * unit device unit number
884 fore_pci_attach(config_id, unit)
893 int err_count = BOOT_LOOPS;
898 if (unit >= FORE_MAX_UNITS) {
899 log(LOG_ERR, "%s%d: too many devices\n",
900 FORE_DEV_NAME, unit);
905 * Make sure this isn't a duplicate unit
907 if (fore_units[unit] != NULL)
911 * Allocate a new unit structure
913 fup = (Fore_unit *) atm_dev_alloc(sizeof(Fore_unit), sizeof(int), 0);
918 * Start initializing it
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;
930 callout_handle_init(&fup->fu_thandle);
933 * Get our device type
935 device_id = pci_conf_read ( config_id, PCI_ID_REG );
936 switch ((device_id >> 16) & 0xffff) {
938 case FORE_PCA200E_ID:
939 fup->fu_config.ac_device = DEV_FORE_PCA200E;
943 fup->fu_config.ac_device = DEV_UNKNOWN;
947 * Enable Memory Mapping / Bus Mastering
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);
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);
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);
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);
975 * Convert Endianess of Slave RAM accesses
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);
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);
991 * Poke the hardware - boot the CP and prepare it for downloading
996 * Wait for the monitor to perform self-test
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);
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));
1009 DELAY ( BOOT_DELAY );
1013 * Setup the adapter config info - at least as much as we can
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;
1023 * Save device ram info for user-level programs
1025 fup->fu_config.ac_ram = (long)fup->fu_ram;
1026 fup->fu_config.ac_ramsize = fup->fu_ramsize;
1029 * Set device capabilities
1031 fup->fu_pif.pif_maxvpi = FORE_MAX_VPI;
1032 fup->fu_pif.pif_maxvci = FORE_MAX_VCI;
1035 * Register this interface with ATM core services
1037 if ( atm_physif_register
1038 ((Cmn_unit *)fup, FORE_DEV_NAME, fore_services) != 0 )
1041 * Registration failed - back everything out
1046 fore_units[unit] = fup;
1051 * Add hook to our shutdown function
1053 EVENTHANDLER_REGISTER(shutdown_post_sync, fore_pci_shutdown, fup,
1054 SHUTDOWN_PRI_DEFAULT);
1058 * Initialize the CP microcode program.
1060 fore_initialize(fup);
1066 * Unattach the device from the system
1071 * Free any Fore-specific device resources
1073 fore_interface_free(fup);
1083 * Device shutdown routine
1086 * kdc pointer to device's configuration table
1087 * force forced shutdown flag
1094 fore_pci_shutdown(kdc, force)
1095 struct kern_devconf *kdc;
1100 if (kdc->kdc_unit < fore_nunits) {
1102 fup = fore_units[kdc->kdc_unit];
1108 (void) dev_detach(kdc);
1113 * Device shutdown routine
1116 * howto type of shutdown
1117 * fup pointer to device unit structure
1124 fore_pci_shutdown(fup, howto)
1129 fore_reset((Fore_unit *) fup);
1133 #endif /* BSD < 199506 */
1134 #endif /* __FreeBSD__ */
1138 * Device unattach routine
1140 * Reset the physical device, remove any pending timeouts,
1141 * unmap any register sets, and unregister any interrupts.
1144 * fup pointer to device unit structure
1154 struct dev_info *devinfo_p = fup->fu_devinfo;
1155 struct dev_reg *dev_reg_p;
1156 struct dev_intr *dev_intr_p;
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.
1169 * Lock out all device interrupts
1171 DEVICE_LOCK((Cmn_unit *)fup);
1174 * Remove any pending timeout()'s
1176 (void)untimeout((KTimeout_ret(*) (void *))fore_initialize,
1177 (void *)fup, fup->fu_thandle);
1181 * Remove any mappings of the device
1183 for ( dev_reg_p = devinfo_p->devi_reg, i = 1;
1184 i <= devinfo_p->devi_nreg; i++, ++dev_reg_p )
1186 if ( dev_reg_p == NULL )
1195 * Each device type has different register sets
1197 switch (fup->fu_config.ac_device) {
1200 case DEV_FORE_SBA200E:
1205 * Host Control Register (HCR)
1208 unmap_regs((addr_t)fup->fu_ctlreg,
1213 * SBus Burst Transfer Configuration Register
1222 * SBus Interrupt Level Select Register
1225 unmap_regs((addr_t)fup->fu_intlvl,
1233 unmap_regs((addr_t)fup->fu_ram,
1239 case DEV_FORE_SBA200:
1244 * Board Control Register (BCR)
1247 unmap_regs((addr_t)fup->fu_ctlreg,
1255 unmap_regs((addr_t)fup->fu_ram,
1260 #endif /* FORE_SBUS */
1265 * Remove the interrupt vector(s)
1267 dev_intr_p = devinfo_p->devi_intr;
1268 for ( i = devinfo_p->devi_nintr; i > 0; --i, ++dev_intr_p )
1270 if ( dev_intr_p == NULL )
1277 (void) remintr ( dev_intr_p->int_pri, fore_poll );
1281 #if defined(__DragonFly__) || defined(__FreeBSD__)
1283 * Unmap the device interrupt
1285 (void) pci_unmap_int(fup->fu_pcitag);
1291 (void) pci_unmap_mem(fup->fu_pcitag, PCA200E_PCI_MEMBASE);
1293 #endif /* __FreeBSD__ */
1295 DEVICE_UNLOCK((Cmn_unit *)fup);
1300 * Device reset routine
1302 * Reset the physical device
1305 * fup pointer to device unit structure
1317 * Reset the board and return it to cold_start state
1320 fup->fu_mon->mon_bstat = CP_WRITE(BOOT_COLDSTART);
1322 if (fup->fu_ctlreg) {
1324 switch (fup->fu_config.ac_device) {
1327 case DEV_FORE_SBA200E:
1329 * Reset i960 by setting and clearing RESET
1331 SBA200E_HCR_INIT(*fup->fu_ctlreg, SBA200E_RESET);
1332 SBA200E_HCR_CLR(*fup->fu_ctlreg, SBA200E_RESET);
1335 case DEV_FORE_SBA200:
1337 * Reset i960 by setting and clearing RESET
1339 * SBA200 will NOT reset if bit is OR'd in!
1341 *fup->fu_ctlreg = SBA200_RESET;
1342 *fup->fu_ctlreg = SBA200_RESET_CLR;
1344 #endif /* FORE_SBUS */
1346 case DEV_FORE_PCA200E:
1348 * Reset i960 by setting and clearing RESET
1350 PCA200E_HCR_INIT(*fup->fu_ctlreg, PCA200E_RESET);
1352 PCA200E_HCR_CLR(*fup->fu_ctlreg, PCA200E_RESET);
1357 panic("fore_reset: unknown device type");
1369 *******************************************************************
1371 * Loadable Module Support
1373 *******************************************************************
1378 * Generic module load processing
1380 * This function is called by an OS-specific function when this
1381 * module is being loaded.
1387 * 0 load was successful
1388 * errno load failed - reason indicated
1401 /* Problems, clean up */
1409 * Generic module unload processing
1411 * This function is called by an OS-specific function when this
1412 * module is being unloaded.
1418 * 0 unload was successful
1419 * errno unload failed - reason indicated
1428 * OK, try to clean up our mess
1437 * Loadable driver description
1439 static struct vdldrv fore_drv = {
1440 VDMAGIC_DRV, /* Device Driver */
1441 "fore_mod", /* name */
1442 &fore_ops, /* dev_ops */
1451 * Loadable module support entry point
1453 * This is the routine called by the vd driver for all loadable module
1454 * functions for this pseudo driver. This routine name must be specified
1455 * on the modload(1) command. This routine will be called whenever the
1456 * modload(1), modunload(1) or modstat(1) commands are issued for this
1460 * cmd vd command code
1461 * vdp pointer to vd driver's structure
1462 * vdi pointer to command-specific vdioctl_* structure
1463 * vds pointer to status structure (VDSTAT only)
1466 * 0 command was successful
1467 * errno command failed - reason indicated
1471 fore_mod(cmd, vdp, vdi, vds)
1485 * We dont support any user configuration
1487 err = fore_doload();
1489 /* Let vd driver know about us */
1490 vdp->vdd_vdtab = (struct vdlinkage *)&fore_drv;
1497 err = fore_dounload();
1505 /* Not much to say at the moment */
1510 log(LOG_ERR, "fore_mod: Unknown vd command 0x%x\n", cmd);
1518 #if defined(__DragonFly__) || defined(__FreeBSD__)
1522 * Driver entry points
1524 static struct cdevsw fore_cdev = {
1532 /* close */ noclose,
1534 /* write */ nowrite,
1535 /* ioctl */ noioctl,
1538 /* strategy */ nostrategy,
1545 * Loadable device driver module description
1548 MOD_DEV("fore_mod", LM_DT_CHAR, -1, (void *)&fore_cdev);
1550 MOD_DEV(fore, LM_DT_CHAR, -1, (void *)&fore_cdev);
1555 * Loadable module support "load" entry point
1557 * This is the routine called by the lkm driver whenever the
1558 * modload(1) command is issued for this module.
1561 * lkmtp pointer to lkm drivers's structure
1562 * cmd lkm command code
1565 * 0 command was successful
1566 * errno command failed - reason indicated
1570 fore_load(lkmtp, cmd)
1571 struct lkm_table *lkmtp;
1574 return(fore_doload());
1579 * Loadable module support "unload" entry point
1581 * This is the routine called by the lkm driver whenever the
1582 * modunload(1) command is issued for this module.
1585 * lkmtp pointer to lkm drivers's structure
1586 * cmd lkm command code
1589 * 0 command was successful
1590 * errno command failed - reason indicated
1594 fore_unload(lkmtp, cmd)
1595 struct lkm_table *lkmtp;
1598 return(fore_dounload());
1603 * Loadable module support entry point
1605 * This is the routine called by the lkm driver for all loadable module
1606 * functions for this driver. This routine name must be specified
1607 * on the modload(1) command. This routine will be called whenever the
1608 * modload(1), modunload(1) or modstat(1) commands are issued for this
1612 * lkmtp pointer to lkm drivers's structure
1613 * cmd lkm command code
1617 * 0 command was successful
1618 * errno command failed - reason indicated
1622 fore_mod(lkmtp, cmd, ver)
1623 struct lkm_table *lkmtp;
1628 DISPATCH(lkmtp, cmd, ver, fore_load, fore_unload, nosys);
1630 DISPATCH(lkmtp, cmd, ver, fore_load, fore_unload, lkm_nullcmd);
1634 #endif /* __FreeBSD__ */
1636 #endif /* ATM_LINKED */