summaryrefslogtreecommitdiff
path: root/usr/src/uts/intel/io/dnet.c
diff options
context:
space:
mode:
authormrj <none@none>2007-01-19 08:10:06 -0800
committermrj <none@none>2007-01-19 08:10:06 -0800
commitae115bc77f6fcde83175c75b4206dc2e50747966 (patch)
tree4cbe67724fffb4374fdef9af1e188357a20aad1d /usr/src/uts/intel/io/dnet.c
parent4fceebdf03eeac0d7c58a4f70cc19b00a8c40a73 (diff)
downloadillumos-joyent-ae115bc77f6fcde83175c75b4206dc2e50747966.tar.gz
PSARC 2006/469 EOF and removal of eeprom -I
PSARC 2006/568 direct boot (dboot) for x86 6219282 interrupt service routine called twice 6223946 potential infinite loop in fbt.c 6228819 tsc_gethrtimeunscaled resets to 0 on suspend 6342201 hat_unload() and cross call usage are needlessly slow on x86, x64 6378723 ctfconvert can't handle GCC empty struct C extension 6379124 ctfconvert can't handle C99 flexible array members 6401187 merging ip's CTF data into genunix introduces a race 6437553 shmat(2) fails on platforms that don't support large pages 6449286 eeprom -I should be torched 6464072 need support for firmware properties 6465816 need a debug record page 6467491 64-bit processes must point %fs or %gs to null selector to utilize [fs|gs]base 6475880 vestiges of old boot code on i386/amd64 should be purged 6475956 Interrupt handling code on x86 platforms should be easier to understand 6477828 pcplusmp psm module should be rearranged to allow multiple platforms to share the same apic code 6477867 x86 KDI should belong in the kernel 6477871 fix for 6232859 also needed for kmdb 6477872 MDB MMU commands need improvements 6477873 cpr debugging can be improved 6477877 mstate accounting should be reset when gethrtimef() is changed 6477915 32-bit x86 kernel should use interrupt gates for all traps 6477963 _update_sregs should be written in C 6477976 no longer need to capture [fs,gs]base in struct regs on every exception 6478642 Solaris needs to support multiple x86 platforms 6478648 ON could use an new & unencumbered xsvc driver 6478734 kernel lint not in C99 mode 6478826 swrand should have framework to lock individual pages 6480763 if interrupts can't be disabled, re-onlining an offline cpu fails 6481824 /dev/fb is not created if installation is done over tty 6483747 clock-tick processing should re-include threads waiting for I/O 6485872 use PTOU macro to access user area instead of old "u" from user.h 6486263 need way to extend kernel core dumps with pages that don't have page_t's 6486435 eeprom, prtdiag should only be platform specific where necessary 6486436 genunix mdb module makefiles duplicate list of files 6486437 intr_common.c should be common 6486445 /dev/mem needs support for page_t-less pages 6486451 cpu_pause() routine should be mach-specific 6486456 SIMULATOR_SUPPORT should die 6486832 x86 platform will need memlist/memseg locking 6486911 amd64 port not finished 6486972 platform TOD setting code may not have real TOD hdw to set 6492647 Better trap trace support for x-calls 6493613 apic_disable_intr() needs round robin fix 6497633 ctfmerge could allow for no ctf sections 6500637 floating point context switching is needlessly slow 6500656 move floating point configuration to C 6500666 need a means to override the setting of uname -m in the kernel build 6500669 update x86 defines 6502790 Files in the boot archive should be individually compressed 6503792 live upgrade environment + bfu + alternate root == incorrect menu.lst file 6504373 kmdb promif shouldn't needlessly busy-wait 6504374 ::interrupts could show level/edge 6506305 opteron erratum 123 should be enabled 6507629 porting x86 platform code to Xen 6510847 kobj.c is unaware of sparc hole between nucleus text and data (from dtrace) --HG-- rename : usr/src/cmd/eeprom/common/Makefile => deleted_files/usr/src/cmd/eeprom/common/Makefile rename : usr/src/cmd/eeprom/eeprom.xml => deleted_files/usr/src/cmd/eeprom/eeprom.xml rename : usr/src/cmd/eeprom/i386/common/benv_sync.c => deleted_files/usr/src/cmd/eeprom/i386/common/benv_sync.c rename : usr/src/cmd/eeprom/i386/i86pc/Makefile => deleted_files/usr/src/cmd/eeprom/i386/i86pc/Makefile rename : usr/src/cmd/eeprom/sparc/sun4u/Makefile => deleted_files/usr/src/cmd/eeprom/sparc/sun4u/Makefile rename : usr/src/cmd/eeprom/sparc/sun4v/Makefile => deleted_files/usr/src/cmd/eeprom/sparc/sun4v/Makefile rename : usr/src/cmd/mdb/common/kmdb/kmdb_kdi_impl.h => deleted_files/usr/src/cmd/mdb/common/kmdb/kmdb_kdi_impl.h rename : usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.h => deleted_files/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.h rename : usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.s => deleted_files/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.s rename : usr/src/cmd/mdb/intel/amd64/kmdb/kaif_resume.s => deleted_files/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_resume.s rename : usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.h => deleted_files/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.h rename : usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.s => deleted_files/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.s rename : usr/src/cmd/mdb/intel/ia32/kmdb/kaif_resume.s => deleted_files/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_resume.s rename : usr/src/cmd/mdb/intel/kmdb/kaif_activate.c => deleted_files/usr/src/cmd/mdb/intel/kmdb/kaif_activate.c rename : usr/src/cmd/mdb/intel/kmdb/kaif_start_isadep.c => deleted_files/usr/src/cmd/mdb/intel/kmdb/kaif_start_isadep.c rename : usr/src/cmd/mdb/sparc/kmdb/kaif_enter.s => deleted_files/usr/src/cmd/mdb/sparc/kmdb/kaif_enter.s rename : usr/src/cmd/prtdiag/i386/i86pc/Makefile => deleted_files/usr/src/cmd/prtdiag/i386/i86pc/Makefile rename : usr/src/cmd/svc/profile/platform_i86pc.xml => deleted_files/usr/src/cmd/svc/profile/platform_i86pc.xml rename : usr/src/psm/stand/boot/amd64/alloc.c => deleted_files/usr/src/psm/stand/boot/amd64/alloc.c rename : usr/src/psm/stand/boot/amd64/amd64/alloc.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/alloc.h rename : usr/src/psm/stand/boot/amd64/amd64/amd64.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/amd64.h rename : usr/src/psm/stand/boot/amd64/amd64/amd64_page.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/amd64_page.h rename : usr/src/psm/stand/boot/amd64/amd64/auxv64.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/auxv64.h rename : usr/src/psm/stand/boot/amd64/amd64/boothooks.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/boothooks.h rename : usr/src/psm/stand/boot/amd64/amd64/bootops64.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/bootops64.h rename : usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h rename : usr/src/psm/stand/boot/amd64/amd64/cpu.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/cpu.h rename : usr/src/psm/stand/boot/amd64/amd64/debug.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/debug.h rename : usr/src/psm/stand/boot/amd64/amd64/machregs.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/machregs.h rename : usr/src/psm/stand/boot/amd64/amd64/memlist64.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/memlist64.h rename : usr/src/psm/stand/boot/amd64/amd64/msr.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/msr.h rename : usr/src/psm/stand/boot/amd64/amd64/print.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/print.h rename : usr/src/psm/stand/boot/amd64/amd64/segments.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/segments.h rename : usr/src/psm/stand/boot/amd64/amd64/tss.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/tss.h rename : usr/src/psm/stand/boot/amd64/amd64/types.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/types.h rename : usr/src/psm/stand/boot/amd64/context.c => deleted_files/usr/src/psm/stand/boot/amd64/context.c rename : usr/src/psm/stand/boot/amd64/cpu.c => deleted_files/usr/src/psm/stand/boot/amd64/cpu.c rename : usr/src/psm/stand/boot/amd64/exception.s => deleted_files/usr/src/psm/stand/boot/amd64/exception.s rename : usr/src/psm/stand/boot/amd64/genassym.c => deleted_files/usr/src/psm/stand/boot/amd64/genassym.c rename : usr/src/psm/stand/boot/amd64/handoff.c => deleted_files/usr/src/psm/stand/boot/amd64/handoff.c rename : usr/src/psm/stand/boot/amd64/i386_subr.s => deleted_files/usr/src/psm/stand/boot/amd64/i386_subr.s rename : usr/src/psm/stand/boot/amd64/locore.s => deleted_files/usr/src/psm/stand/boot/amd64/locore.s rename : usr/src/psm/stand/boot/amd64/memlist.c => deleted_files/usr/src/psm/stand/boot/amd64/memlist.c rename : usr/src/psm/stand/boot/amd64/offsets.in => deleted_files/usr/src/psm/stand/boot/amd64/offsets.in rename : usr/src/psm/stand/boot/amd64/print.c => deleted_files/usr/src/psm/stand/boot/amd64/print.c rename : usr/src/psm/stand/boot/amd64/ptops.c => deleted_files/usr/src/psm/stand/boot/amd64/ptops.c rename : usr/src/psm/stand/boot/amd64/ptxlate.c => deleted_files/usr/src/psm/stand/boot/amd64/ptxlate.c rename : usr/src/psm/stand/boot/amd64/segments.c => deleted_files/usr/src/psm/stand/boot/amd64/segments.c rename : usr/src/psm/stand/boot/amd64/vtrap.c => deleted_files/usr/src/psm/stand/boot/amd64/vtrap.c rename : usr/src/psm/stand/boot/i386/Makefile => deleted_files/usr/src/psm/stand/boot/i386/Makefile rename : usr/src/psm/stand/boot/i386/Makefile.com => deleted_files/usr/src/psm/stand/boot/i386/Makefile.com rename : usr/src/psm/stand/boot/i386/common/bios.c => deleted_files/usr/src/psm/stand/boot/i386/common/bios.c rename : usr/src/psm/stand/boot/i386/common/biosint.h => deleted_files/usr/src/psm/stand/boot/i386/common/biosint.h rename : usr/src/psm/stand/boot/i386/common/biosint.map => deleted_files/usr/src/psm/stand/boot/i386/common/biosint.map rename : usr/src/psm/stand/boot/i386/common/biosutil.c => deleted_files/usr/src/psm/stand/boot/i386/common/biosutil.c rename : usr/src/psm/stand/boot/i386/common/boot_plat.c => deleted_files/usr/src/psm/stand/boot/i386/common/boot_plat.c rename : usr/src/psm/stand/boot/i386/common/boot_ramdisk.c => deleted_files/usr/src/psm/stand/boot/i386/common/boot_ramdisk.c rename : usr/src/psm/stand/boot/i386/common/bootenv.c => deleted_files/usr/src/psm/stand/boot/i386/common/bootenv.c rename : usr/src/psm/stand/boot/i386/common/bootflags.c => deleted_files/usr/src/psm/stand/boot/i386/common/bootflags.c rename : usr/src/psm/stand/boot/i386/common/bootops.c => deleted_files/usr/src/psm/stand/boot/i386/common/bootops.c rename : usr/src/psm/stand/boot/i386/common/bootprop.c => deleted_files/usr/src/psm/stand/boot/i386/common/bootprop.c rename : usr/src/psm/stand/boot/i386/common/bootprop.h => deleted_files/usr/src/psm/stand/boot/i386/common/bootprop.h rename : usr/src/psm/stand/boot/i386/common/chario.h => deleted_files/usr/src/psm/stand/boot/i386/common/chario.h rename : usr/src/psm/stand/boot/i386/common/check_iopath.c => deleted_files/usr/src/psm/stand/boot/i386/common/check_iopath.c rename : usr/src/psm/stand/boot/i386/common/cpu_id.h => deleted_files/usr/src/psm/stand/boot/i386/common/cpu_id.h rename : usr/src/psm/stand/boot/i386/common/debug.h => deleted_files/usr/src/psm/stand/boot/i386/common/debug.h rename : usr/src/psm/stand/boot/i386/common/i86.il => deleted_files/usr/src/psm/stand/boot/i386/common/i86.il rename : usr/src/psm/stand/boot/i386/common/machine.h => deleted_files/usr/src/psm/stand/boot/i386/common/machine.h rename : usr/src/psm/stand/boot/i386/common/mapfile => deleted_files/usr/src/psm/stand/boot/i386/common/mapfile rename : usr/src/psm/stand/boot/i386/common/memory.c => deleted_files/usr/src/psm/stand/boot/i386/common/memory.c rename : usr/src/psm/stand/boot/i386/common/mkbin.c => deleted_files/usr/src/psm/stand/boot/i386/common/mkbin.c rename : usr/src/psm/stand/boot/i386/common/multiboot.c => deleted_files/usr/src/psm/stand/boot/i386/common/multiboot.c rename : usr/src/psm/stand/boot/i386/common/multiboot.h => deleted_files/usr/src/psm/stand/boot/i386/common/multiboot.h rename : usr/src/psm/stand/boot/i386/common/standalloc.c => deleted_files/usr/src/psm/stand/boot/i386/common/standalloc.c rename : usr/src/psm/stand/boot/i386/common/standalloc.h => deleted_files/usr/src/psm/stand/boot/i386/common/standalloc.h rename : usr/src/psm/stand/boot/i386/common/util.h => deleted_files/usr/src/psm/stand/boot/i386/common/util.h rename : usr/src/psm/stand/boot/i386/common/vgaprobe.c => deleted_files/usr/src/psm/stand/boot/i386/common/vgaprobe.c rename : usr/src/psm/stand/boot/i386/i86pc/Makefile => deleted_files/usr/src/psm/stand/boot/i386/i86pc/Makefile rename : usr/src/psm/stand/boot/i386/i86pc/asm.s => deleted_files/usr/src/psm/stand/boot/i386/i86pc/asm.s rename : usr/src/psm/stand/boot/i386/i86pc/biosint.s => deleted_files/usr/src/psm/stand/boot/i386/i86pc/biosint.s rename : usr/src/psm/stand/boot/i386/i86pc/cpu_id.s => deleted_files/usr/src/psm/stand/boot/i386/i86pc/cpu_id.s rename : usr/src/psm/stand/boot/i386/i86pc/idttab.s => deleted_files/usr/src/psm/stand/boot/i386/i86pc/idttab.s rename : usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s => deleted_files/usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s rename : usr/src/uts/common/zmod/mapfile => deleted_files/usr/src/uts/common/zmod/mapfile rename : usr/src/uts/intel/amd64/Makefile.rules => deleted_files/usr/src/uts/intel/amd64/Makefile.rules rename : usr/src/uts/intel/ia32/Makefile.rules => deleted_files/usr/src/uts/intel/ia32/Makefile.rules rename : usr/src/uts/intel/ia32/os/arch_kdi.c => deleted_files/usr/src/uts/intel/ia32/os/arch_kdi.c rename : usr/src/uts/intel/ia32/sys/mmu.h => deleted_files/usr/src/uts/intel/ia32/sys/mmu.h rename : usr/src/uts/intel/krtld/Makefile => deleted_files/usr/src/uts/intel/krtld/Makefile rename : usr/src/uts/intel/sys/immu.h => deleted_files/usr/src/uts/intel/sys/immu.h rename : usr/src/uts/intel/sys/mmu.h => deleted_files/usr/src/uts/intel/sys/mmu.h rename : usr/src/uts/intel/zmod/Makefile => deleted_files/usr/src/uts/intel/zmod/Makefile rename : usr/src/uts/sparc/zmod/Makefile => deleted_files/usr/src/uts/sparc/zmod/Makefile rename : usr/src/cmd/eeprom/i386/common/benv.c => usr/src/cmd/eeprom/i386/benv.c rename : usr/src/cmd/eeprom/i386/common/benv.h => usr/src/cmd/eeprom/i386/benv.h rename : usr/src/cmd/eeprom/i386/common/benv_kvm.c => usr/src/cmd/eeprom/i386/benv_kvm.c rename : usr/src/cmd/eeprom/common/loadlogo.c => usr/src/cmd/eeprom/sparc/loadlogo.c rename : usr/src/cmd/eeprom/common/openprom.c => usr/src/cmd/eeprom/sparc/openprom.c rename : usr/src/cmd/mdb/i86pc/modules/uppc/intr_common.c => usr/src/cmd/mdb/i86pc/modules/common/intr_common.c rename : usr/src/cmd/mdb/i86pc/modules/uppc/intr_common.h => usr/src/cmd/mdb/i86pc/modules/common/intr_common.h rename : usr/src/cmd/prtdiag/i386/i86pc/smbios.c => usr/src/cmd/prtdiag/i386/smbios.c rename : usr/src/cmd/prtdiag/Makefile.targ => usr/src/cmd/prtdiag/sparc/Makefile.targ rename : usr/src/psm/stand/boot/i386/common/console.c => usr/src/uts/i86pc/boot/boot_console.c rename : usr/src/psm/stand/boot/i386/common/keyboard.c => usr/src/uts/i86pc/boot/boot_keyboard.c rename : usr/src/psm/stand/boot/i386/common/keyboard_table.c => usr/src/uts/i86pc/boot/boot_keyboard_table.c rename : usr/src/psm/stand/boot/i386/common/keyboard_table.h => usr/src/uts/i86pc/boot/boot_keyboard_table.h rename : usr/src/psm/stand/boot/i386/common/serial.h => usr/src/uts/i86pc/boot/boot_serial.h rename : usr/src/psm/stand/boot/i386/common/vga.c => usr/src/uts/i86pc/boot/boot_vga.c rename : usr/src/psm/stand/boot/i386/common/vga.h => usr/src/uts/i86pc/boot/boot_vga.h rename : usr/src/uts/intel/consconfig_dacf/Makefile => usr/src/uts/i86pc/consconfig_dacf/Makefile rename : usr/src/uts/intel/io/consplat.c => usr/src/uts/i86pc/io/consplat.c rename : usr/src/uts/common/io/pit.c => usr/src/uts/i86pc/io/hardclk.c rename : usr/src/uts/common/io/hardclk.c => usr/src/uts/i86pc/io/todpc_subr.c rename : usr/src/uts/i86pc/io/pcplusmp/apic.h => usr/src/uts/i86pc/sys/apic.h rename : usr/src/psm/stand/boot/i386/common/console.h => usr/src/uts/i86pc/sys/boot_console.h rename : usr/src/uts/i86pc/vm/mach_i86mmu.c => usr/src/uts/i86pc/vm/i86_mmu.c rename : usr/src/uts/i86pc/acpica/Makefile => usr/src/uts/intel/acpica/Makefile rename : usr/src/uts/i86pc/agpgart/Makefile => usr/src/uts/intel/agpgart/Makefile rename : usr/src/uts/i86pc/agpmaster/Makefile => usr/src/uts/intel/agpmaster/Makefile rename : usr/src/uts/i86pc/agptarget/Makefile => usr/src/uts/intel/agptarget/Makefile rename : usr/src/uts/i86pc/amd64_gart/Makefile => usr/src/uts/intel/amd64_gart/Makefile rename : usr/src/uts/i86pc/ata/Makefile => usr/src/uts/intel/ata/Makefile rename : usr/src/uts/i86pc/audio810/Makefile => usr/src/uts/intel/audio810/Makefile rename : usr/src/uts/i86pc/audiohd/Makefile => usr/src/uts/intel/audiohd/Makefile rename : usr/src/uts/i86pc/audioixp/Makefile => usr/src/uts/intel/audioixp/Makefile rename : usr/src/uts/i86pc/bootdev/Makefile => usr/src/uts/intel/bootdev/Makefile rename : usr/src/uts/i86pc/dnet/Makefile => usr/src/uts/intel/dnet/Makefile rename : usr/src/uts/i86pc/drm/Makefile => usr/src/uts/intel/drm/Makefile rename : usr/src/uts/i86pc/fd/Makefile => usr/src/uts/intel/fd/Makefile rename : usr/src/uts/i86pc/fdc/Makefile => usr/src/uts/intel/fdc/Makefile rename : usr/src/uts/i86pc/i915/Makefile => usr/src/uts/intel/i915/Makefile rename : usr/src/uts/i86pc/io/acpica/README.txt => usr/src/uts/intel/io/acpica/README.txt rename : usr/src/uts/i86pc/io/acpica/acpi_enum.c => usr/src/uts/intel/io/acpica/acpi_enum.c rename : usr/src/uts/i86pc/io/acpica/acpica.c => usr/src/uts/intel/io/acpica/acpica.c rename : usr/src/uts/i86pc/io/acpica/acpica_ec.c => usr/src/uts/intel/io/acpica/acpica_ec.c rename : usr/src/uts/i86pc/io/acpica/changes.txt => usr/src/uts/intel/io/acpica/changes.txt rename : usr/src/uts/i86pc/io/acpica/cmp_ca.sh => usr/src/uts/intel/io/acpica/cmp_ca.sh rename : usr/src/uts/i86pc/io/acpica/debugger/dbcmds.c => usr/src/uts/intel/io/acpica/debugger/dbcmds.c rename : usr/src/uts/i86pc/io/acpica/debugger/dbdisply.c => usr/src/uts/intel/io/acpica/debugger/dbdisply.c rename : usr/src/uts/i86pc/io/acpica/debugger/dbexec.c => usr/src/uts/intel/io/acpica/debugger/dbexec.c rename : usr/src/uts/i86pc/io/acpica/debugger/dbfileio.c => usr/src/uts/intel/io/acpica/debugger/dbfileio.c rename : usr/src/uts/i86pc/io/acpica/debugger/dbhistry.c => usr/src/uts/intel/io/acpica/debugger/dbhistry.c rename : usr/src/uts/i86pc/io/acpica/debugger/dbinput.c => usr/src/uts/intel/io/acpica/debugger/dbinput.c rename : usr/src/uts/i86pc/io/acpica/debugger/dbstats.c => usr/src/uts/intel/io/acpica/debugger/dbstats.c rename : usr/src/uts/i86pc/io/acpica/debugger/dbutils.c => usr/src/uts/intel/io/acpica/debugger/dbutils.c rename : usr/src/uts/i86pc/io/acpica/debugger/dbxface.c => usr/src/uts/intel/io/acpica/debugger/dbxface.c rename : usr/src/uts/i86pc/io/acpica/disassembler/dmbuffer.c => usr/src/uts/intel/io/acpica/disassembler/dmbuffer.c rename : usr/src/uts/i86pc/io/acpica/disassembler/dmnames.c => usr/src/uts/intel/io/acpica/disassembler/dmnames.c rename : usr/src/uts/i86pc/io/acpica/disassembler/dmobject.c => usr/src/uts/intel/io/acpica/disassembler/dmobject.c rename : usr/src/uts/i86pc/io/acpica/disassembler/dmopcode.c => usr/src/uts/intel/io/acpica/disassembler/dmopcode.c rename : usr/src/uts/i86pc/io/acpica/disassembler/dmresrc.c => usr/src/uts/intel/io/acpica/disassembler/dmresrc.c rename : usr/src/uts/i86pc/io/acpica/disassembler/dmresrcl.c => usr/src/uts/intel/io/acpica/disassembler/dmresrcl.c rename : usr/src/uts/i86pc/io/acpica/disassembler/dmresrcs.c => usr/src/uts/intel/io/acpica/disassembler/dmresrcs.c rename : usr/src/uts/i86pc/io/acpica/disassembler/dmutils.c => usr/src/uts/intel/io/acpica/disassembler/dmutils.c rename : usr/src/uts/i86pc/io/acpica/disassembler/dmwalk.c => usr/src/uts/intel/io/acpica/disassembler/dmwalk.c rename : usr/src/uts/i86pc/io/acpica/events/evevent.c => usr/src/uts/intel/io/acpica/events/evevent.c rename : usr/src/uts/i86pc/io/acpica/events/evgpe.c => usr/src/uts/intel/io/acpica/events/evgpe.c rename : usr/src/uts/i86pc/io/acpica/events/evgpeblk.c => usr/src/uts/intel/io/acpica/events/evgpeblk.c rename : usr/src/uts/i86pc/io/acpica/events/evmisc.c => usr/src/uts/intel/io/acpica/events/evmisc.c rename : usr/src/uts/i86pc/io/acpica/events/evregion.c => usr/src/uts/intel/io/acpica/events/evregion.c rename : usr/src/uts/i86pc/io/acpica/events/evrgnini.c => usr/src/uts/intel/io/acpica/events/evrgnini.c rename : usr/src/uts/i86pc/io/acpica/events/evsci.c => usr/src/uts/intel/io/acpica/events/evsci.c rename : usr/src/uts/i86pc/io/acpica/events/evxface.c => usr/src/uts/intel/io/acpica/events/evxface.c rename : usr/src/uts/i86pc/io/acpica/events/evxfevnt.c => usr/src/uts/intel/io/acpica/events/evxfevnt.c rename : usr/src/uts/i86pc/io/acpica/events/evxfregn.c => usr/src/uts/intel/io/acpica/events/evxfregn.c rename : usr/src/uts/i86pc/io/acpica/hardware/hwacpi.c => usr/src/uts/intel/io/acpica/hardware/hwacpi.c rename : usr/src/uts/i86pc/io/acpica/hardware/hwgpe.c => usr/src/uts/intel/io/acpica/hardware/hwgpe.c rename : usr/src/uts/i86pc/io/acpica/hardware/hwregs.c => usr/src/uts/intel/io/acpica/hardware/hwregs.c rename : usr/src/uts/i86pc/io/acpica/hardware/hwsleep.c => usr/src/uts/intel/io/acpica/hardware/hwsleep.c rename : usr/src/uts/i86pc/io/acpica/hardware/hwtimer.c => usr/src/uts/intel/io/acpica/hardware/hwtimer.c rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsfield.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsfield.c rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsinit.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsinit.c rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsmethod.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsmethod.c rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsmthdat.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsmthdat.c rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsobject.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsobject.c rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsopcode.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsopcode.c rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsutils.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsutils.c rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswexec.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswexec.c rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswload.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswload.c rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswscope.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswscope.c rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswstate.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswstate.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exconfig.c => usr/src/uts/intel/io/acpica/interpreter/executer/exconfig.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exconvrt.c => usr/src/uts/intel/io/acpica/interpreter/executer/exconvrt.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/excreate.c => usr/src/uts/intel/io/acpica/interpreter/executer/excreate.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exdump.c => usr/src/uts/intel/io/acpica/interpreter/executer/exdump.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exfield.c => usr/src/uts/intel/io/acpica/interpreter/executer/exfield.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exfldio.c => usr/src/uts/intel/io/acpica/interpreter/executer/exfldio.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exmisc.c => usr/src/uts/intel/io/acpica/interpreter/executer/exmisc.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exmutex.c => usr/src/uts/intel/io/acpica/interpreter/executer/exmutex.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exnames.c => usr/src/uts/intel/io/acpica/interpreter/executer/exnames.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg1.c => usr/src/uts/intel/io/acpica/interpreter/executer/exoparg1.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg2.c => usr/src/uts/intel/io/acpica/interpreter/executer/exoparg2.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg3.c => usr/src/uts/intel/io/acpica/interpreter/executer/exoparg3.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg6.c => usr/src/uts/intel/io/acpica/interpreter/executer/exoparg6.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exprep.c => usr/src/uts/intel/io/acpica/interpreter/executer/exprep.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exregion.c => usr/src/uts/intel/io/acpica/interpreter/executer/exregion.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exresnte.c => usr/src/uts/intel/io/acpica/interpreter/executer/exresnte.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exresolv.c => usr/src/uts/intel/io/acpica/interpreter/executer/exresolv.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exresop.c => usr/src/uts/intel/io/acpica/interpreter/executer/exresop.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exstore.c => usr/src/uts/intel/io/acpica/interpreter/executer/exstore.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exstoren.c => usr/src/uts/intel/io/acpica/interpreter/executer/exstoren.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exstorob.c => usr/src/uts/intel/io/acpica/interpreter/executer/exstorob.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exsystem.c => usr/src/uts/intel/io/acpica/interpreter/executer/exsystem.c rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exutils.c => usr/src/uts/intel/io/acpica/interpreter/executer/exutils.c rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psargs.c => usr/src/uts/intel/io/acpica/interpreter/parser/psargs.c rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psloop.c => usr/src/uts/intel/io/acpica/interpreter/parser/psloop.c rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psopcode.c => usr/src/uts/intel/io/acpica/interpreter/parser/psopcode.c rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psparse.c => usr/src/uts/intel/io/acpica/interpreter/parser/psparse.c rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psscope.c => usr/src/uts/intel/io/acpica/interpreter/parser/psscope.c rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/pstree.c => usr/src/uts/intel/io/acpica/interpreter/parser/pstree.c rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psutils.c => usr/src/uts/intel/io/acpica/interpreter/parser/psutils.c rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/pswalk.c => usr/src/uts/intel/io/acpica/interpreter/parser/pswalk.c rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psxface.c => usr/src/uts/intel/io/acpica/interpreter/parser/psxface.c rename : usr/src/uts/i86pc/io/acpica/master_ops.c => usr/src/uts/intel/io/acpica/master_ops.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsaccess.c => usr/src/uts/intel/io/acpica/namespace/nsaccess.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsalloc.c => usr/src/uts/intel/io/acpica/namespace/nsalloc.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsdump.c => usr/src/uts/intel/io/acpica/namespace/nsdump.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsdumpdv.c => usr/src/uts/intel/io/acpica/namespace/nsdumpdv.c rename : usr/src/uts/i86pc/io/acpica/namespace/nseval.c => usr/src/uts/intel/io/acpica/namespace/nseval.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsinit.c => usr/src/uts/intel/io/acpica/namespace/nsinit.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsload.c => usr/src/uts/intel/io/acpica/namespace/nsload.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsnames.c => usr/src/uts/intel/io/acpica/namespace/nsnames.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsobject.c => usr/src/uts/intel/io/acpica/namespace/nsobject.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsparse.c => usr/src/uts/intel/io/acpica/namespace/nsparse.c rename : usr/src/uts/i86pc/io/acpica/namespace/nssearch.c => usr/src/uts/intel/io/acpica/namespace/nssearch.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsutils.c => usr/src/uts/intel/io/acpica/namespace/nsutils.c rename : usr/src/uts/i86pc/io/acpica/namespace/nswalk.c => usr/src/uts/intel/io/acpica/namespace/nswalk.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsxfeval.c => usr/src/uts/intel/io/acpica/namespace/nsxfeval.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsxfname.c => usr/src/uts/intel/io/acpica/namespace/nsxfname.c rename : usr/src/uts/i86pc/io/acpica/namespace/nsxfobj.c => usr/src/uts/intel/io/acpica/namespace/nsxfobj.c rename : usr/src/uts/i86pc/io/acpica/osl.c => usr/src/uts/intel/io/acpica/osl.c rename : usr/src/uts/i86pc/io/acpica/osl_ml.s => usr/src/uts/intel/io/acpica/osl_ml.s rename : usr/src/uts/i86pc/io/acpica/resources/rsaddr.c => usr/src/uts/intel/io/acpica/resources/rsaddr.c rename : usr/src/uts/i86pc/io/acpica/resources/rscalc.c => usr/src/uts/intel/io/acpica/resources/rscalc.c rename : usr/src/uts/i86pc/io/acpica/resources/rscreate.c => usr/src/uts/intel/io/acpica/resources/rscreate.c rename : usr/src/uts/i86pc/io/acpica/resources/rsdump.c => usr/src/uts/intel/io/acpica/resources/rsdump.c rename : usr/src/uts/i86pc/io/acpica/resources/rsinfo.c => usr/src/uts/intel/io/acpica/resources/rsinfo.c rename : usr/src/uts/i86pc/io/acpica/resources/rsio.c => usr/src/uts/intel/io/acpica/resources/rsio.c rename : usr/src/uts/i86pc/io/acpica/resources/rsirq.c => usr/src/uts/intel/io/acpica/resources/rsirq.c rename : usr/src/uts/i86pc/io/acpica/resources/rslist.c => usr/src/uts/intel/io/acpica/resources/rslist.c rename : usr/src/uts/i86pc/io/acpica/resources/rsmemory.c => usr/src/uts/intel/io/acpica/resources/rsmemory.c rename : usr/src/uts/i86pc/io/acpica/resources/rsmisc.c => usr/src/uts/intel/io/acpica/resources/rsmisc.c rename : usr/src/uts/i86pc/io/acpica/resources/rsutils.c => usr/src/uts/intel/io/acpica/resources/rsutils.c rename : usr/src/uts/i86pc/io/acpica/resources/rsxface.c => usr/src/uts/intel/io/acpica/resources/rsxface.c rename : usr/src/uts/i86pc/io/acpica/tables/tbconvrt.c => usr/src/uts/intel/io/acpica/tables/tbconvrt.c rename : usr/src/uts/i86pc/io/acpica/tables/tbget.c => usr/src/uts/intel/io/acpica/tables/tbget.c rename : usr/src/uts/i86pc/io/acpica/tables/tbgetall.c => usr/src/uts/intel/io/acpica/tables/tbgetall.c rename : usr/src/uts/i86pc/io/acpica/tables/tbinstal.c => usr/src/uts/intel/io/acpica/tables/tbinstal.c rename : usr/src/uts/i86pc/io/acpica/tables/tbrsdt.c => usr/src/uts/intel/io/acpica/tables/tbrsdt.c rename : usr/src/uts/i86pc/io/acpica/tables/tbutils.c => usr/src/uts/intel/io/acpica/tables/tbutils.c rename : usr/src/uts/i86pc/io/acpica/tables/tbxface.c => usr/src/uts/intel/io/acpica/tables/tbxface.c rename : usr/src/uts/i86pc/io/acpica/tables/tbxfroot.c => usr/src/uts/intel/io/acpica/tables/tbxfroot.c rename : usr/src/uts/i86pc/io/acpica/utilities/utalloc.c => usr/src/uts/intel/io/acpica/utilities/utalloc.c rename : usr/src/uts/i86pc/io/acpica/utilities/utcache.c => usr/src/uts/intel/io/acpica/utilities/utcache.c rename : usr/src/uts/i86pc/io/acpica/utilities/utclib.c => usr/src/uts/intel/io/acpica/utilities/utclib.c rename : usr/src/uts/i86pc/io/acpica/utilities/utcopy.c => usr/src/uts/intel/io/acpica/utilities/utcopy.c rename : usr/src/uts/i86pc/io/acpica/utilities/utdebug.c => usr/src/uts/intel/io/acpica/utilities/utdebug.c rename : usr/src/uts/i86pc/io/acpica/utilities/utdelete.c => usr/src/uts/intel/io/acpica/utilities/utdelete.c rename : usr/src/uts/i86pc/io/acpica/utilities/uteval.c => usr/src/uts/intel/io/acpica/utilities/uteval.c rename : usr/src/uts/i86pc/io/acpica/utilities/utglobal.c => usr/src/uts/intel/io/acpica/utilities/utglobal.c rename : usr/src/uts/i86pc/io/acpica/utilities/utinit.c => usr/src/uts/intel/io/acpica/utilities/utinit.c rename : usr/src/uts/i86pc/io/acpica/utilities/utmath.c => usr/src/uts/intel/io/acpica/utilities/utmath.c rename : usr/src/uts/i86pc/io/acpica/utilities/utmisc.c => usr/src/uts/intel/io/acpica/utilities/utmisc.c rename : usr/src/uts/i86pc/io/acpica/utilities/utmutex.c => usr/src/uts/intel/io/acpica/utilities/utmutex.c rename : usr/src/uts/i86pc/io/acpica/utilities/utobject.c => usr/src/uts/intel/io/acpica/utilities/utobject.c rename : usr/src/uts/i86pc/io/acpica/utilities/utresrc.c => usr/src/uts/intel/io/acpica/utilities/utresrc.c rename : usr/src/uts/i86pc/io/acpica/utilities/utstate.c => usr/src/uts/intel/io/acpica/utilities/utstate.c rename : usr/src/uts/i86pc/io/acpica/utilities/uttrack.c => usr/src/uts/intel/io/acpica/utilities/uttrack.c rename : usr/src/uts/i86pc/io/acpica/utilities/utxface.c => usr/src/uts/intel/io/acpica/utilities/utxface.c rename : usr/src/uts/i86pc/io/agpgart/agp_kstat.c => usr/src/uts/intel/io/agpgart/agp_kstat.c rename : usr/src/uts/i86pc/io/agpgart/agpgart.c => usr/src/uts/intel/io/agpgart/agpgart.c rename : usr/src/uts/i86pc/io/agpgart/agpgart.conf => usr/src/uts/intel/io/agpgart/agpgart.conf rename : usr/src/uts/i86pc/io/agpgart/agptarget.c => usr/src/uts/intel/io/agpgart/agptarget.c rename : usr/src/uts/i86pc/io/agpgart/amd64_gart.c => usr/src/uts/intel/io/agpgart/amd64_gart.c rename : usr/src/uts/i86pc/io/agpmaster/agpmaster.c => usr/src/uts/intel/io/agpmaster/agpmaster.c rename : usr/src/uts/i86pc/io/dnet.c => usr/src/uts/intel/io/dnet.c rename : usr/src/uts/i86pc/io/dnet.conf => usr/src/uts/intel/io/dnet.conf rename : usr/src/uts/i86pc/io/drm/drm_asm.s => usr/src/uts/intel/io/drm/drm_asm.s rename : usr/src/uts/i86pc/io/drm/i915_dma.c => usr/src/uts/intel/io/drm/i915_dma.c rename : usr/src/uts/i86pc/io/drm/i915_drm.h => usr/src/uts/intel/io/drm/i915_drm.h rename : usr/src/uts/i86pc/io/drm/i915_drv.c => usr/src/uts/intel/io/drm/i915_drv.c rename : usr/src/uts/i86pc/io/drm/i915_drv.h => usr/src/uts/intel/io/drm/i915_drv.h rename : usr/src/uts/i86pc/io/drm/i915_irq.c => usr/src/uts/intel/io/drm/i915_irq.c rename : usr/src/uts/i86pc/io/drm/i915_mem.c => usr/src/uts/intel/io/drm/i915_mem.c rename : usr/src/uts/i86pc/io/drm/i915_sundrv.c => usr/src/uts/intel/io/drm/i915_sundrv.c rename : usr/src/uts/i86pc/io/fd.conf => usr/src/uts/intel/io/fd.conf rename : usr/src/uts/common/io/i8254.c => usr/src/uts/intel/io/i8254.c rename : usr/src/uts/i86pc/io/logi.c => usr/src/uts/intel/io/logi.c rename : usr/src/uts/i86pc/io/mii.c => usr/src/uts/intel/io/mii.c rename : usr/src/uts/i86pc/io/mscsi.c => usr/src/uts/intel/io/mscsi.c rename : usr/src/uts/i86pc/io/mscsi.conf => usr/src/uts/intel/io/mscsi.conf rename : usr/src/uts/i86pc/io/msm.c => usr/src/uts/intel/io/msm.c rename : usr/src/uts/i86pc/io/pci/mps_table.h => usr/src/uts/intel/io/pci/mps_table.h rename : usr/src/uts/i86pc/io/pci/pci_autoconfig.c => usr/src/uts/intel/io/pci/pci_autoconfig.c rename : usr/src/uts/i86pc/io/pci/pci_boot.c => usr/src/uts/intel/io/pci/pci_boot.c rename : usr/src/uts/i86pc/io/pci/pci_memlist.c => usr/src/uts/intel/io/pci/pci_memlist.c rename : usr/src/uts/i86pc/io/pci/pci_pci.c => usr/src/uts/intel/io/pci/pci_pci.c rename : usr/src/uts/i86pc/io/pci/pci_resource.c => usr/src/uts/intel/io/pci/pci_resource.c rename : usr/src/uts/i86pc/io/pci/pcihrt.h => usr/src/uts/intel/io/pci/pcihrt.h rename : usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_acpi.c => usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_acpi.c rename : usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_acpi.h => usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_acpi.h rename : usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_nvidia.c => usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_nvidia.c rename : usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_nvidia.h => usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_nvidia.h rename : usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_x86.c => usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_x86.c rename : usr/src/uts/i86pc/io/pciex/pcie_error.c => usr/src/uts/intel/io/pciex/pcie_error.c rename : usr/src/uts/i86pc/io/pciex/pcie_error.h => usr/src/uts/intel/io/pciex/pcie_error.h rename : usr/src/uts/i86pc/io/pciex/pcie_nvidia.c => usr/src/uts/intel/io/pciex/pcie_nvidia.c rename : usr/src/uts/i86pc/io/pciex/pcie_nvidia.h => usr/src/uts/intel/io/pciex/pcie_nvidia.h rename : usr/src/uts/i86pc/io/pciex/pcie_pci.c => usr/src/uts/intel/io/pciex/pcie_pci.c rename : usr/src/uts/i86pc/io/pciex/pcie_pci.conf => usr/src/uts/intel/io/pciex/pcie_pci.conf rename : usr/src/uts/i86pc/io/smcp/smcp.c => usr/src/uts/intel/io/smcp/smcp.c rename : usr/src/uts/i86pc/io/smcp/smcp.h => usr/src/uts/intel/io/smcp/smcp.h rename : usr/src/uts/i86pc/kb8042/Makefile => usr/src/uts/intel/kb8042/Makefile rename : usr/src/cmd/mdb/intel/amd64/kmdb/kaif_startup.s => usr/src/uts/intel/kdi/amd64/kdi_asm.s rename : usr/src/cmd/mdb/intel/ia32/kmdb/kaif_startup.s => usr/src/uts/intel/kdi/ia32/kdi_asm.s rename : usr/src/cmd/mdb/intel/kmdb/kaif_idt.c => usr/src/uts/intel/kdi/kdi_idt.c rename : usr/src/cmd/mdb/intel/kmdb/kaif_idthdl.s => usr/src/uts/intel/kdi/kdi_idthdl.s rename : usr/src/cmd/mdb/intel/kmdb/kaif_off.in => usr/src/uts/intel/kdi/kdi_offsets.in rename : usr/src/uts/i86pc/logi/Makefile => usr/src/uts/intel/logi/Makefile rename : usr/src/uts/i86pc/mscsi/Makefile => usr/src/uts/intel/mscsi/Makefile rename : usr/src/uts/i86pc/msm/Makefile => usr/src/uts/intel/msm/Makefile rename : usr/src/uts/i86pc/pci_autoconfig/Makefile => usr/src/uts/intel/pci_autoconfig/Makefile rename : usr/src/uts/i86pc/pci_pci/Makefile => usr/src/uts/intel/pci_pci/Makefile rename : usr/src/uts/i86pc/pcic/Makefile => usr/src/uts/intel/pcic/Makefile rename : usr/src/uts/i86pc/pcie_pci/Makefile => usr/src/uts/intel/pcie_pci/Makefile rename : usr/src/uts/i86pc/pciehpc/Makefile => usr/src/uts/intel/pciehpc/Makefile rename : usr/src/uts/i86pc/power/Makefile => usr/src/uts/intel/power/Makefile rename : usr/src/cmd/mdb/intel/kmdb/kaif_regs.h => usr/src/uts/intel/sys/kdi_regs.h rename : usr/src/uts/i86pc/sys/pmem.h => usr/src/uts/intel/sys/pmem.h rename : usr/src/uts/i86pc/vuid2ps2/Makefile => usr/src/uts/intel/vuid2ps2/Makefile rename : usr/src/uts/i86pc/vuid3ps2/Makefile => usr/src/uts/intel/vuid3ps2/Makefile rename : usr/src/uts/i86pc/vuidm3p/Makefile => usr/src/uts/intel/vuidm3p/Makefile rename : usr/src/uts/i86pc/vuidm4p/Makefile => usr/src/uts/intel/vuidm4p/Makefile rename : usr/src/uts/i86pc/vuidm5p/Makefile => usr/src/uts/intel/vuidm5p/Makefile
Diffstat (limited to 'usr/src/uts/intel/io/dnet.c')
-rw-r--r--usr/src/uts/intel/io/dnet.c4856
1 files changed, 4856 insertions, 0 deletions
diff --git a/usr/src/uts/intel/io/dnet.c b/usr/src/uts/intel/io/dnet.c
new file mode 100644
index 0000000000..e3e4d87ae3
--- /dev/null
+++ b/usr/src/uts/intel/io/dnet.c
@@ -0,0 +1,4856 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * dnet -- DEC 21x4x
+ *
+ * Currently supports:
+ * 21040, 21041, 21140, 21142, 21143
+ * SROM versions 1, 3, 3.03, 4
+ * TP, AUI, BNC, 100BASETX, 100BASET4
+ *
+ * XXX NEEDSWORK
+ * All media SHOULD work, FX is untested
+ *
+ * Depends on the Generic LAN Driver utility functions in /kernel/misc/gld
+ */
+
+#define BUG_4010796 /* See 4007871, 4010796 */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/param.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#include <sys/kmem.h>
+#include <sys/conf.h>
+#include <sys/devops.h>
+#include <sys/ksynch.h>
+#include <sys/stat.h>
+#include <sys/modctl.h>
+#include <sys/debug.h>
+#include <sys/dlpi.h>
+#include <sys/ethernet.h>
+#include <sys/gld.h>
+#include <sys/pci.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+
+#include <sys/mii.h>
+#include <sys/dnet.h>
+
+#ifdef MII_IS_MODULE
+#define MII_DEPEND " misc/mii"
+#else
+#define MII_DEPEND
+#endif
+
+char _depends_on[] = "misc/gld" MII_DEPEND;
+
+/*
+ * Declarations and Module Linkage
+ */
+
+#define IDENT "DNET 21x4x"
+
+/*
+ * #define DNET_NOISY
+ * #define SROMDEBUG
+ * #define SROMDUMPSTRUCTURES
+ */
+
+#ifdef DNETDEBUG
+#ifdef DNET_NOISY
+int dnetdebug = -1;
+#else
+int dnetdebug = 0;
+#endif
+#endif
+
+/* used for message allocated using desballoc() */
+struct free_ptr {
+ struct free_rtn free_rtn;
+ caddr_t buf;
+};
+
+struct rbuf_list {
+ struct rbuf_list *rbuf_next; /* next in the list */
+ caddr_t rbuf_vaddr; /* virual addr of the buf */
+ caddr_t rbuf_paddr; /* physical addr of the buf */
+ caddr_t rbuf_endpaddr; /* physical addr at the end */
+ ddi_dma_handle_t rbuf_dmahdl; /* dma handle */
+ ddi_acc_handle_t rbuf_acchdl; /* handle for DDI functions */
+};
+
+/* Required system entry points */
+static int dnetdevinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
+static int dnetprobe(dev_info_t *);
+static int dnetattach(dev_info_t *, ddi_attach_cmd_t);
+static int dnetdetach(dev_info_t *, ddi_detach_cmd_t);
+
+/* Required driver entry points for GLD */
+static int dnet_reset(gld_mac_info_t *);
+static int dnet_start_board(gld_mac_info_t *);
+static int dnet_stop_board(gld_mac_info_t *);
+static int dnet_set_mac_addr(gld_mac_info_t *, uchar_t *);
+static int dnet_set_multicast(gld_mac_info_t *, uchar_t *, int);
+static int dnet_set_promiscuous(gld_mac_info_t *, int);
+static int dnet_get_stats(gld_mac_info_t *, struct gld_stats *);
+static int dnet_send(gld_mac_info_t *, mblk_t *);
+static uint_t dnetintr(gld_mac_info_t *);
+
+/* Internal functions used by the above entry points */
+static void write_gpr(struct dnetinstance *dnetp, uint32_t val);
+static void dnet_reset_board(gld_mac_info_t *);
+static void dnet_init_board(gld_mac_info_t *);
+static void dnet_chip_init(gld_mac_info_t *);
+static unsigned int hashindex(uchar_t *);
+static int dnet_start(gld_mac_info_t *);
+static int dnet_set_addr(gld_mac_info_t *, uchar_t *);
+
+static void dnet_getp(gld_mac_info_t *);
+static void update_rx_stats(gld_mac_info_t *, int);
+static void update_tx_stats(gld_mac_info_t *, int);
+
+/* Media Selection Setup Routines */
+static void set_gpr(gld_mac_info_t *macinfo);
+static void set_opr(gld_mac_info_t *macinfo);
+static void set_sia(gld_mac_info_t *macinfo);
+
+/* Buffer Management Routines */
+static int dnet_alloc_bufs(gld_mac_info_t *);
+static void dnet_free_bufs(gld_mac_info_t *);
+static void dnet_init_txrx_bufs(gld_mac_info_t *);
+static int alloc_descriptor(gld_mac_info_t *);
+static void dnet_reclaim_Tx_desc(gld_mac_info_t *);
+static int dnet_rbuf_init(dev_info_t *, int);
+static int dnet_rbuf_destroy();
+static struct rbuf_list *dnet_rbuf_alloc(dev_info_t *, int);
+static void dnet_rbuf_free(caddr_t);
+static void dnet_freemsg_buf(struct free_ptr *);
+
+static void setup_block(gld_mac_info_t *macinfo);
+
+/* SROM read functions */
+static int dnet_read_srom(dev_info_t *, int, ddi_acc_handle_t, int, uchar_t *,
+ int);
+static void dnet_read21040addr(dev_info_t *, ddi_acc_handle_t, int, uchar_t *,
+ int *);
+static void dnet_read21140srom(ddi_acc_handle_t, int, uchar_t *, int);
+static int get_alternative_srom_image(dev_info_t *, uchar_t *, int);
+static void dnet_print_srom(SROM_FORMAT *sr);
+static void dnet_dump_leaf(LEAF_FORMAT *leaf);
+static void dnet_dump_block(media_block_t *block);
+#ifdef BUG_4010796
+static void set_alternative_srom_image(dev_info_t *, uchar_t *, int);
+static int dnethack(dev_info_t *);
+#endif
+
+static int dnet_hack_interrupts(gld_mac_info_t *, int);
+static int dnet_detach_hacked_interrupt(dev_info_t *devinfo);
+static void enable_interrupts(struct dnetinstance *dnetp, int enable_xmit);
+
+/* SROM parsing functions */
+static void dnet_parse_srom(struct dnetinstance *dnetp, SROM_FORMAT *sr,
+ uchar_t *vi);
+static void parse_controller_leaf(struct dnetinstance *dnetp, LEAF_FORMAT *leaf,
+ uchar_t *vi);
+static uchar_t *parse_media_block(struct dnetinstance *dnetp,
+ media_block_t *block, uchar_t *vi);
+static int check_srom_valid(uchar_t *);
+static void dnet_dumpbin(char *msg, uchar_t *, int size, int len);
+static void setup_legacy_blocks();
+/* Active Media Determination Routines */
+static void find_active_media(gld_mac_info_t *);
+static int send_test_packet(gld_mac_info_t *);
+static int dnet_link_sense(gld_mac_info_t *macinfo);
+
+/* PHY MII Routines */
+static ushort_t dnet_mii_read(dev_info_t *dip, int phy_addr, int reg_num);
+static void dnet_mii_write(dev_info_t *dip, int phy_addr, int reg_num,
+ int reg_dat);
+static void write_mii(struct dnetinstance *, uint32_t, int);
+static void mii_tristate(struct dnetinstance *);
+static void do_phy(gld_mac_info_t *);
+static void dnet_mii_link_cb(dev_info_t *, int, enum mii_phy_state);
+static void set_leaf(SROM_FORMAT *sr, LEAF_FORMAT *leaf);
+
+#ifdef DNETDEBUG
+uint32_t dnet_usecelapsed(struct dnetinstance *dnetp);
+void dnet_timestamp(struct dnetinstance *, char *);
+void dnet_usectimeout(struct dnetinstance *, uint32_t, int, timercb_t);
+#endif
+static char *media_str[] = {
+ "10BaseT",
+ "10Base2",
+ "10Base5",
+ "100BaseTX",
+ "10BaseT FD",
+ "100BaseTX FD",
+ "100BaseT4",
+ "100BaseFX",
+ "100BaseFX FD",
+ "MII"
+};
+
+/* default SROM info for cards with no SROMs */
+static LEAF_FORMAT leaf_default_100;
+static LEAF_FORMAT leaf_asante;
+static LEAF_FORMAT leaf_phylegacy;
+static LEAF_FORMAT leaf_cogent_100;
+static LEAF_FORMAT leaf_21041;
+static LEAF_FORMAT leaf_21040;
+
+int rx_buf_size = (ETHERMAX + ETHERFCSL + 3) & ~3; /* roundup to 4 */
+
+int max_rx_desc_21040 = MAX_RX_DESC_21040;
+int max_rx_desc_21140 = MAX_RX_DESC_21140;
+int max_tx_desc = MAX_TX_DESC;
+int dnet_xmit_threshold = MAX_TX_DESC >> 2; /* XXX need tuning? */
+
+static kmutex_t dnet_rbuf_lock; /* mutex to protect rbuf_list data */
+
+/* used for buffers allocated by ddi_dma_mem_alloc() */
+static ddi_dma_attr_t dma_attr = {
+ DMA_ATTR_V0, /* dma_attr version */
+ 0, /* dma_attr_addr_lo */
+ (uint64_t)0xFFFFFFFF, /* dma_attr_addr_hi */
+ 0x7FFFFFFF, /* dma_attr_count_max */
+ 4, /* dma_attr_align */
+ 0x3F, /* dma_attr_burstsizes */
+ 1, /* dma_attr_minxfer */
+ (uint64_t)0xFFFFFFFF, /* dma_attr_maxxfer */
+ (uint64_t)0xFFFFFFFF, /* dma_attr_seg */
+ 1, /* dma_attr_sgllen */
+ 1, /* dma_attr_granular */
+ 0, /* dma_attr_flags */
+};
+
+/* used for buffers allocated for rbuf, allow 2 cookies */
+static ddi_dma_attr_t dma_attr_rb = {
+ DMA_ATTR_V0, /* dma_attr version */
+ 0, /* dma_attr_addr_lo */
+ (uint64_t)0xFFFFFFFF, /* dma_attr_addr_hi */
+ 0x7FFFFFFF, /* dma_attr_count_max */
+ 4, /* dma_attr_align */
+ 0x3F, /* dma_attr_burstsizes */
+ 1, /* dma_attr_minxfer */
+ (uint64_t)0xFFFFFFFF, /* dma_attr_maxxfer */
+ (uint64_t)0xFFFFFFFF, /* dma_attr_seg */
+ 2, /* dma_attr_sgllen */
+ 1, /* dma_attr_granular */
+ 0, /* dma_attr_flags */
+};
+/* used for buffers which are NOT from ddi_dma_mem_alloc() - xmit side */
+static ddi_dma_attr_t dma_attr_tx = {
+ DMA_ATTR_V0, /* dma_attr version */
+ 0, /* dma_attr_addr_lo */
+ (uint64_t)0xFFFFFFFF, /* dma_attr_addr_hi */
+ 0x7FFFFFFF, /* dma_attr_count_max */
+ 1, /* dma_attr_align */
+ 0x3F, /* dma_attr_burstsizes */
+ 1, /* dma_attr_minxfer */
+ (uint64_t)0xFFFFFFFF, /* dma_attr_maxxfer */
+ (uint64_t)0xFFFFFFFF, /* dma_attr_seg */
+ 0x7FFF, /* dma_attr_sgllen */
+ 1, /* dma_attr_granular */
+ 0, /* dma_attr_flags */
+};
+
+static ddi_device_acc_attr_t accattr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_NEVERSWAP_ACC,
+ DDI_STRICTORDER_ACC,
+};
+
+uchar_t dnet_broadcastaddr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+/* Standard Streams initialization */
+static struct module_info minfo = {
+ DNETIDNUM, "dnet", 0, INFPSZ, DNETHIWAT, DNETLOWAT
+};
+
+static struct qinit rinit = { /* read queues */
+ NULL, gld_rsrv, gld_open, gld_close, NULL, &minfo, NULL
+};
+
+static struct qinit winit = { /* write queues */
+ gld_wput, gld_wsrv, NULL, NULL, NULL, &minfo, NULL
+};
+
+static struct streamtab dnetinfo = {&rinit, &winit, NULL, NULL};
+
+/* Standard Module linkage initialization for a Streams driver */
+extern struct mod_ops mod_driverops;
+
+static struct cb_ops cb_dnetops = {
+ nulldev, /* cb_open */
+ nulldev, /* cb_close */
+ nodev, /* cb_strategy */
+ nodev, /* cb_print */
+ nodev, /* cb_dump */
+ nodev, /* cb_read */
+ nodev, /* cb_write */
+ nodev, /* cb_ioctl */
+ nodev, /* cb_devmap */
+ nodev, /* cb_mmap */
+ nodev, /* cb_segmap */
+ nochpoll, /* cb_chpoll */
+ ddi_prop_op, /* cb_prop_op */
+ &dnetinfo, /* cb_stream */
+ (int)(D_MP | D_HOTPLUG) /* cb_flag */
+};
+
+static struct dev_ops dnetops = {
+ DEVO_REV, /* devo_rev */
+ 0, /* devo_refcnt */
+ gld_getinfo, /* devo_getinfo */
+ nulldev, /* devo_identify */
+ dnetprobe, /* devo_probe */
+ dnetattach, /* devo_attach */
+ dnetdetach, /* devo_detach */
+ nodev, /* devo_reset */
+ &cb_dnetops, /* devo_cb_ops */
+ (struct bus_ops *)NULL /* devo_bus_ops */
+};
+
+static struct modldrv modldrv = {
+ &mod_driverops, /* Type of module. This one is a driver */
+ IDENT " %I%", /* short description */
+ &dnetops /* driver specific ops */
+};
+
+static struct modlinkage modlinkage = {
+ MODREV_1, (void *)&modldrv, NULL
+};
+
+
+/*
+ * Passed to the hacked interrupt for multiport Cogent and ZNYX cards with
+ * dodgy interrupt routing
+ */
+#define MAX_INST 8 /* Maximum instances on a multiport adapter. */
+struct hackintr_inf
+{
+ gld_mac_info_t *macinfos[MAX_INST]; /* macinfos for each port */
+ dev_info_t *devinfo; /* Devinfo of the primary device */
+ kmutex_t lock;
+ /* Ensures the interrupt doesn't get called while detaching */
+};
+static char hackintr_propname[] = "InterruptData";
+static char macoffset_propname[] = "MAC_offset";
+static char speed_propname[] = "speed";
+static char ofloprob_propname[] = "dmaworkaround";
+static char duplex_propname[] = "full-duplex"; /* Must agree with MII */
+static char printsrom_propname[] = "print-srom";
+
+static uint_t dnet_hack_intr(struct hackintr_inf *);
+
+/*
+ * ========== Module Loading Entry Points ==========
+ */
+
+int
+_init(void)
+{
+ int i;
+
+ /* Configure fake sroms for legacy cards */
+ mutex_init(&dnet_rbuf_lock, NULL, MUTEX_DRIVER, NULL);
+ setup_legacy_blocks();
+ if ((i = mod_install(&modlinkage)) != 0) {
+ mutex_destroy(&dnet_rbuf_lock);
+ }
+ return (i);
+}
+
+int
+_fini(void)
+{
+ int i;
+ if ((i = mod_remove(&modlinkage)) == 0) { /* module can be unloaded */
+ /* loop until all the receive buffers are freed */
+ while (dnet_rbuf_destroy() != 0) {
+ delay(drv_usectohz(100000));
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETDDI)
+ cmn_err(CE_WARN, "dnet _fini delay");
+#endif
+ }
+ mutex_destroy(&dnet_rbuf_lock);
+ }
+ return (i);
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+ return (mod_info(&modlinkage, modinfop));
+}
+
+/*
+ * ========== DDI Entry Points ==========
+ */
+
+/*
+ * probe(9E) -- Determine if a device is present
+ */
+static int
+dnetprobe(dev_info_t *devinfo)
+{
+ ddi_acc_handle_t handle;
+ uint16_t vendorid;
+ uint16_t deviceid;
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETDDI)
+ cmn_err(CE_NOTE, "dnetprobe(0x%p)", (void *) devinfo);
+#endif
+
+ if (pci_config_setup(devinfo, &handle) != DDI_SUCCESS)
+ return (DDI_PROBE_FAILURE);
+
+ vendorid = pci_config_get16(handle, PCI_CONF_VENID);
+
+ if (vendorid != DEC_VENDOR_ID) {
+ pci_config_teardown(&handle);
+ return (DDI_PROBE_FAILURE);
+ }
+
+ deviceid = pci_config_get16(handle, PCI_CONF_DEVID);
+ switch (deviceid) {
+ case DEVICE_ID_21040:
+ case DEVICE_ID_21041:
+ case DEVICE_ID_21140:
+ case DEVICE_ID_21143: /* And 142 */
+ break;
+ default:
+ pci_config_teardown(&handle);
+ return (DDI_PROBE_FAILURE);
+ }
+
+ pci_config_teardown(&handle);
+#ifndef BUG_4010796
+ return (DDI_PROBE_SUCCESS);
+#else
+ return (dnethack(devinfo));
+#endif
+}
+
+#ifdef BUG_4010796
+/*
+ * If we have a device, but we cannot presently access its SROM data,
+ * then we return DDI_PROBE_PARTIAL and hope that sometime later we
+ * will be able to get at the SROM data. This can only happen if we
+ * are a secondary port with no SROM, and the bootstrap failed to set
+ * our DNET_SROM property, and our primary sibling has not yet probed.
+ */
+static int
+dnethack(dev_info_t *devinfo)
+{
+ uchar_t vendor_info[SROM_SIZE];
+ uint32_t csr;
+ uint16_t deviceid;
+ ddi_acc_handle_t handle;
+ uint32_t retval;
+ int secondary;
+ ddi_acc_handle_t io_handle;
+ uint32_t io_reg;
+
+#define DNET_PCI_RNUMBER 1
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETDDI)
+ cmn_err(CE_NOTE, "dnethack(0x%p)", (void *) devinfo);
+#endif
+
+ if (pci_config_setup(devinfo, &handle) != DDI_SUCCESS)
+ return (DDI_PROBE_FAILURE);
+
+ deviceid = pci_config_get16(handle, PCI_CONF_DEVID);
+
+ /*
+ * Turn on Master Enable and IO Enable bits.
+ */
+ csr = pci_config_get32(handle, PCI_CONF_COMM);
+ pci_config_put32(handle, PCI_CONF_COMM, (csr |PCI_COMM_ME|PCI_COMM_IO));
+
+ pci_config_teardown(&handle);
+
+ /* Now map I/O register */
+ if (ddi_regs_map_setup(devinfo, DNET_PCI_RNUMBER,
+ (caddr_t *)&io_reg, (offset_t)0, (offset_t)0, &accattr,
+ &io_handle) != DDI_SUCCESS) {
+ return (DDI_PROBE_FAILURE);
+ }
+
+ /*
+ * Reset the chip
+ */
+ ddi_put32(io_handle, REG32(io_reg, BUS_MODE_REG), SW_RESET);
+ drv_usecwait(3);
+ ddi_put32(io_handle, REG32(io_reg, BUS_MODE_REG), 0);
+ drv_usecwait(8);
+
+ secondary = dnet_read_srom(devinfo, deviceid, io_handle,
+ io_reg, vendor_info, sizeof (vendor_info));
+
+ switch (secondary) {
+ case -1:
+ /* We can't access our SROM data! */
+ retval = DDI_PROBE_PARTIAL;
+ break;
+ case 0:
+ retval = DDI_PROBE_SUCCESS;
+ break;
+ default:
+ retval = DDI_PROBE_SUCCESS;
+ }
+
+ ddi_regs_map_free(&io_handle);
+ return (retval);
+}
+#endif /* BUG_4010796 */
+
+/*
+ * attach(9E) -- Attach a device to the system
+ *
+ * Called once for each board successfully probed.
+ */
+static int
+dnetattach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
+{
+ uint16_t revid;
+ struct dnetinstance *dnetp; /* Our private device info */
+ gld_mac_info_t *macinfo; /* GLD structure */
+ uchar_t vendor_info[SROM_SIZE];
+ uint32_t csr;
+ uint16_t deviceid;
+ ddi_acc_handle_t handle;
+ int secondary;
+
+#define DNET_PCI_RNUMBER 1
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETDDI)
+ cmn_err(CE_NOTE, "dnetattach(0x%p)", (void *) devinfo);
+#endif
+
+ if (cmd != DDI_ATTACH)
+ return (DDI_FAILURE);
+ if (pci_config_setup(devinfo, &handle) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ deviceid = pci_config_get16(handle, PCI_CONF_DEVID);
+ switch (deviceid) {
+ case DEVICE_ID_21040:
+ case DEVICE_ID_21041:
+ case DEVICE_ID_21140:
+ case DEVICE_ID_21143: /* And 142 */
+ break;
+ default:
+ pci_config_teardown(&handle);
+ return (DDI_FAILURE);
+ }
+
+ /*
+ * Turn on Master Enable and IO Enable bits.
+ */
+ csr = pci_config_get32(handle, PCI_CONF_COMM);
+ pci_config_put32(handle, PCI_CONF_COMM, (csr |PCI_COMM_ME|PCI_COMM_IO));
+
+ /* Make sure the device is not asleep */
+ csr = pci_config_get32(handle, PCI_DNET_CONF_CFDD);
+ pci_config_put32(handle, PCI_DNET_CONF_CFDD,
+ csr & ~(CFDD_SLEEP|CFDD_SNOOZE));
+
+ revid = pci_config_get8(handle, PCI_CONF_REVID);
+ pci_config_teardown(&handle);
+
+ /*
+ * Allocate gld_mac_info_t and dnetinstance structures
+ */
+ if ((macinfo = gld_mac_alloc(devinfo)) == NULL)
+ return (DDI_FAILURE);
+
+ if ((dnetp = (struct dnetinstance *)
+ kmem_zalloc(sizeof (struct dnetinstance), KM_SLEEP)) == NULL) {
+ gld_mac_free(macinfo);
+ return (DDI_FAILURE);
+ }
+
+ /* Now map I/O register */
+ if (ddi_regs_map_setup(devinfo, DNET_PCI_RNUMBER,
+ (caddr_t *)&dnetp->io_reg, (offset_t)0, (offset_t)0, &accattr,
+ &dnetp->io_handle) != DDI_SUCCESS) {
+ kmem_free(dnetp, sizeof (struct dnetinstance));
+ gld_mac_free(macinfo);
+ return (DDI_FAILURE);
+ }
+
+ dnetp->devinfo = devinfo;
+ dnetp->board_type = deviceid;
+
+ /*
+ * Initialize our private fields in macinfo and dnetinstance
+ */
+ macinfo->gldm_private = (caddr_t)dnetp;
+
+ /*
+ * Initialize pointers to device specific functions which will be
+ * used by the generic layer.
+ */
+ macinfo->gldm_reset = dnet_reset;
+ macinfo->gldm_start = dnet_start_board;
+ macinfo->gldm_stop = dnet_stop_board;
+ macinfo->gldm_set_mac_addr = dnet_set_mac_addr;
+ macinfo->gldm_set_multicast = dnet_set_multicast;
+ macinfo->gldm_set_promiscuous = dnet_set_promiscuous;
+ macinfo->gldm_get_stats = dnet_get_stats;
+ macinfo->gldm_send = dnet_send;
+ macinfo->gldm_intr = dnetintr;
+ macinfo->gldm_ioctl = NULL;
+
+ /*
+ * Initialize board characteristics needed by the generic layer.
+ */
+ macinfo->gldm_ident = IDENT;
+ macinfo->gldm_type = DL_ETHER;
+ macinfo->gldm_minpkt = 0; /* assumes we pad ourselves */
+ macinfo->gldm_maxpkt = DNETMAXPKT;
+ macinfo->gldm_addrlen = ETHERADDRL;
+ macinfo->gldm_saplen = -2;
+
+ /* Other required initialization */
+ macinfo->gldm_ppa = ddi_get_instance(devinfo);
+ macinfo->gldm_vendor_addr = dnetp->vendor_addr;
+ macinfo->gldm_broadcast_addr = dnet_broadcastaddr;
+ macinfo->gldm_devinfo = devinfo;
+
+
+ /*
+ * Get the iblock cookie with which to initialize the mutexes.
+ */
+ if (ddi_get_iblock_cookie(devinfo, 0, &macinfo->gldm_cookie)
+ != DDI_SUCCESS)
+ goto fail;
+
+ /*
+ * Initialize mutex's for this device.
+ * Do this before registering the interrupt handler to avoid
+ * condition where interrupt handler can try using uninitialized
+ * mutex.
+ * Lock ordering rules: always lock intrlock first before
+ * txlock if both are required.
+ */
+ mutex_init(&dnetp->txlock,
+ NULL, MUTEX_DRIVER, macinfo->gldm_cookie);
+ mutex_init(&dnetp->intrlock,
+ NULL, MUTEX_DRIVER, macinfo->gldm_cookie);
+
+ /*
+ * Get the BNC/TP indicator from the conf file for 21040
+ */
+ dnetp->bnc_indicator =
+ ddi_getprop(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS,
+ "bncaui", -1);
+
+ /*
+ * For 21140 check the data rate set in the conf file. Default is
+ * 100Mb/s. Disallow connections at settings that would conflict
+ * with what's in the conf file
+ */
+ dnetp->speed =
+ ddi_getprop(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS,
+ speed_propname, 0);
+ dnetp->full_duplex =
+ ddi_getprop(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS,
+ duplex_propname, -1);
+
+ if (dnetp->speed == 100) {
+ dnetp->disallowed_media |= (1UL<<MEDIA_TP) | (1UL<<MEDIA_TP_FD);
+ } else if (dnetp->speed == 10) {
+ dnetp->disallowed_media |=
+ (1UL<<MEDIA_SYM_SCR) | (1UL<<MEDIA_SYM_SCR_FD);
+ }
+
+ if (dnetp->full_duplex == 1) {
+ dnetp->disallowed_media |=
+ (1UL<<MEDIA_TP) | (1UL<<MEDIA_SYM_SCR);
+ } else if (dnetp->full_duplex == 0) {
+ dnetp->disallowed_media |=
+ (1UL<<MEDIA_TP_FD) | (1UL<<MEDIA_SYM_SCR_FD);
+ }
+
+ if (dnetp->bnc_indicator == 0) /* Disable BNC and AUI media */
+ dnetp->disallowed_media |= (1UL<<MEDIA_BNC) | (1UL<<MEDIA_AUI);
+ else if (dnetp->bnc_indicator == 1) /* Force BNC only */
+ dnetp->disallowed_media = (uint32_t)~(1U<<MEDIA_BNC);
+ else if (dnetp->bnc_indicator == 2) /* Force AUI only */
+ dnetp->disallowed_media = (uint32_t)~(1U<<MEDIA_AUI);
+
+ dnet_reset_board(macinfo);
+
+ secondary = dnet_read_srom(devinfo, dnetp->board_type, dnetp->io_handle,
+ dnetp->io_reg, vendor_info, sizeof (vendor_info));
+
+ if (secondary == -1) /* ASSERT (vendor_info not big enough) */
+ goto fail1;
+
+ dnet_parse_srom(dnetp, &dnetp->sr, vendor_info);
+
+ if (ddi_getprop(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS,
+ printsrom_propname, 0))
+ dnet_print_srom(&dnetp->sr);
+
+ dnetp->sr.netaddr[ETHERADDRL-1] += secondary; /* unique ether addr */
+
+ BCOPY((caddr_t)dnetp->sr.netaddr,
+ (caddr_t)dnetp->vendor_addr, ETHERADDRL);
+
+ BCOPY((caddr_t)dnetp->sr.netaddr,
+ (caddr_t)dnetp->curr_macaddr, ETHERADDRL);
+
+
+ /*
+ * determine whether to implement workaround from DEC
+ * for DMA overrun errata.
+ */
+ dnetp->overrun_workaround =
+ ((dnetp->board_type == DEVICE_ID_21140 && revid >= 0x20) ||
+ (dnetp->board_type == DEVICE_ID_21143 && revid <= 0x30)) ? 1 : 0;
+
+ dnetp->overrun_workaround =
+ ddi_getprop(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS,
+ ofloprob_propname, dnetp->overrun_workaround);
+
+ /*
+ * Add the interrupt handler if dnet_hack_interrupts() returns 0.
+ * Otherwise dnet_hack_interrupts() itself adds the handler.
+ */
+ if (!dnet_hack_interrupts(macinfo, secondary)) {
+ (void) ddi_add_intr(devinfo, 0, NULL,
+ NULL, gld_intr, (caddr_t)macinfo);
+ }
+
+ dnetp->max_tx_desc = max_tx_desc;
+ dnetp->max_rx_desc = max_rx_desc_21040;
+ if (dnetp->board_type != DEVICE_ID_21040 &&
+ dnetp->board_type != DEVICE_ID_21041 &&
+ dnetp->speed != 10)
+ dnetp->max_rx_desc = max_rx_desc_21140;
+
+ /* Allocate the TX and RX descriptors/buffers. */
+ if (dnet_alloc_bufs(macinfo) == FAILURE) {
+ cmn_err(CE_WARN, "DNET: Not enough DMA memory for buffers.");
+ goto fail2;
+ }
+
+ /*
+ * Register ourselves with the GLD interface
+ *
+ * gld_register will:
+ * link us with the GLD system;
+ * set our ddi_set_driver_private(9F) data to the macinfo pointer;
+ * save the devinfo pointer in macinfo->gldm_devinfo;
+ * map the registers, putting the kvaddr into macinfo->gldm_memp;
+ * add the interrupt, putting the cookie in gldm_cookie;
+ * init the gldm_intrlock mutex which will block that interrupt;
+ * create the minor node.
+ */
+
+ if (gld_register(devinfo, "dnet", macinfo) == DDI_SUCCESS) {
+ mutex_enter(&dnetp->intrlock);
+ dnetp->phyaddr = -1;
+ if (dnetp->board_type == DEVICE_ID_21140 ||
+ dnetp->board_type == DEVICE_ID_21143)
+ do_phy(macinfo); /* Initialize the PHY, if any */
+ find_active_media(macinfo);
+
+ /* if the chosen media is non-MII, stop the port monitor */
+ if (dnetp->selected_media_block->media_code != MEDIA_MII &&
+ dnetp->mii != NULL) {
+ mii_destroy(dnetp->mii);
+ dnetp->mii = NULL;
+ dnetp->phyaddr = -1;
+ }
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETSENSE)
+ cmn_err(CE_NOTE, "dnet: link configured : %s",
+ media_str[dnetp->selected_media_block->media_code]);
+#endif
+ bzero(dnetp->setup_buf_vaddr, SETUPBUF_SIZE);
+ dnet_reset_board(macinfo);
+ dnet_init_board(macinfo);
+ /* XXX function return value ignored */
+ mutex_exit(&dnetp->intrlock);
+ /* dropped intrlock as dnet_stop_board() grabs intrlock */
+ (void) dnet_stop_board(macinfo);
+ return (DDI_SUCCESS);
+ }
+fail2:
+ /* XXX function return value ignored */
+ /*
+ * dnet_detach_hacked_interrupt() will remove
+ * interrupt for the non-hacked case also.
+ */
+ (void) dnet_detach_hacked_interrupt(devinfo);
+ dnet_free_bufs(macinfo);
+fail1:
+ mutex_destroy(&dnetp->txlock);
+ mutex_destroy(&dnetp->intrlock);
+fail:
+ ddi_regs_map_free(&dnetp->io_handle);
+ kmem_free(dnetp, sizeof (struct dnetinstance));
+ gld_mac_free(macinfo);
+ return (DDI_FAILURE);
+}
+
+/*
+ * detach(9E) -- Detach a device from the system
+ */
+static int
+dnetdetach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
+{
+ int32_t rc;
+ gld_mac_info_t *macinfo; /* GLD structure */
+ struct dnetinstance *dnetp; /* Our private device info */
+ int32_t proplen;
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETDDI)
+ cmn_err(CE_NOTE, "dnetdetach(0x%p)", (void *) devinfo);
+#endif
+
+ if (cmd != DDI_DETACH) {
+ return (DDI_FAILURE);
+ }
+
+ /* Get the driver private (gld_mac_info_t) structure */
+ macinfo = ddi_get_driver_private(devinfo);
+ dnetp = (struct dnetinstance *)(macinfo->gldm_private);
+
+ /*
+ * Unregister ourselves from the GLD interface
+ *
+ * gld_unregister will:
+ * remove the minor node;
+ * unmap the registers;
+ * remove the interrupt;
+ * destroy the gldm_intrlock mutex;
+ * unlink us from the GLD system.
+ */
+ if (gld_unregister(macinfo) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ /* stop the board if it is running */
+ dnet_reset_board(macinfo);
+
+ if ((rc = dnet_detach_hacked_interrupt(devinfo)) != DDI_SUCCESS)
+ return (rc);
+
+ if (dnetp->mii != NULL)
+ mii_destroy(dnetp->mii);
+
+ /* Free leaf information */
+ set_leaf(&dnetp->sr, NULL);
+
+ ddi_regs_map_free(&dnetp->io_handle);
+ dnet_free_bufs(macinfo);
+ mutex_destroy(&dnetp->txlock);
+ mutex_destroy(&dnetp->intrlock);
+ kmem_free(dnetp, sizeof (struct dnetinstance));
+ gld_mac_free(macinfo);
+
+#ifdef BUG_4010796
+ if (ddi_getproplen(DDI_DEV_T_ANY, devinfo, 0,
+ "DNET_HACK", &proplen) != DDI_PROP_SUCCESS)
+ return (DDI_SUCCESS);
+
+ /*
+ * We must remove the properties we added, because if we leave
+ * them in the devinfo nodes and the driver is unloaded, when
+ * the driver is reloaded the info will still be there, causing
+ * nodes which had returned PROBE_PARTIAL the first time to
+ * instead return PROBE_SUCCESS, in turn causing the nodes to be
+ * attached in a different order, causing their PPA numbers to
+ * be different the second time around, which is undesirable.
+ */
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, devinfo, "DNET_HACK");
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, ddi_get_parent(devinfo),
+ "DNET_SROM");
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, ddi_get_parent(devinfo),
+ "DNET_DEVNUM");
+#endif
+
+ return (DDI_SUCCESS);
+}
+
+/*
+ * ========== GLD Entry Points ==========
+ */
+
+/*
+ * dnet_reset() -- reset the board to initial state;
+ */
+static int
+dnet_reset(gld_mac_info_t *macinfo)
+{
+ struct dnetinstance *dnetp = /* Our private device info */
+ (struct dnetinstance *)macinfo->gldm_private;
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_NOTE, "dnet_reset(0x%p)", (void *) macinfo);
+#endif
+
+ mutex_enter(&dnetp->intrlock);
+ /*
+ * Initialize internal data structures
+ */
+ bzero(dnetp->setup_buf_vaddr, SETUPBUF_SIZE);
+ bzero(dnetp->multicast_cnt, MCASTBUF_SIZE);
+ dnetp->promisc = 0;
+
+ mutex_enter(&dnetp->txlock);
+ dnetp->need_saddr = 0;
+ mutex_exit(&dnetp->txlock);
+
+ dnet_reset_board(macinfo);
+
+ if (ddi_getprop(DDI_DEV_T_ANY, dnetp->devinfo, DDI_PROP_DONTPASS,
+ "reset_do_find_active_media", 0)) {
+ find_active_media(macinfo); /* Redetermine active media */
+ /* Go back to a good state */
+ bzero(dnetp->setup_buf_vaddr, SETUPBUF_SIZE);
+ dnet_reset_board(macinfo);
+ }
+ dnet_init_board(macinfo);
+ mutex_exit(&dnetp->intrlock);
+ return (0);
+}
+
+static void
+dnet_reset_board(gld_mac_info_t *macinfo)
+{
+ struct dnetinstance *dnetp = /* Our private device info */
+ (struct dnetinstance *)macinfo->gldm_private;
+ uint32_t val;
+
+ /*
+ * before initializing the dnet should be in STOP state
+ */
+ /* XXX function return value ignored */
+ /* (void) dnet_stop_board(macinfo); */
+ val = ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG));
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, OPN_MODE_REG),
+ val & ~(START_TRANSMIT | START_RECEIVE));
+
+ /*
+ * Reset the chip
+ */
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, INT_MASK_REG), 0);
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, BUS_MODE_REG), SW_RESET);
+ drv_usecwait(5);
+}
+
+/*
+ * dnet_init_board() -- initialize the specified network board short of
+ * actually starting the board. Call after dnet_reset_board().
+ * called with intrlock held.
+ */
+static void
+dnet_init_board(gld_mac_info_t *macinfo)
+{
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_NOTE, "dnet_init_board(0x%p)", (void *) macinfo);
+#endif
+ set_opr(macinfo);
+ set_gpr(macinfo);
+ set_sia(macinfo);
+ dnet_chip_init(macinfo);
+}
+
+/* dnet_chip_init() - called with intrlock held */
+static void
+dnet_chip_init(gld_mac_info_t *macinfo)
+{
+ struct dnetinstance *dnetp = (struct dnetinstance *)
+ (macinfo->gldm_private);
+
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, BUS_MODE_REG),
+ CACHE_ALIGN | BURST_SIZE); /* CSR0 */
+
+ /*
+ * Initialize the TX and RX descriptors/buffers
+ */
+ dnet_init_txrx_bufs(macinfo);
+
+ /*
+ * Set the base address of the Rx descriptor list in CSR3
+ */
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, RX_BASE_ADDR_REG),
+ (uint32_t)(dnetp->rx_desc_paddr));
+
+ /*
+ * Set the base address of the Tx descrptor list in CSR4
+ */
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, TX_BASE_ADDR_REG),
+ (uint32_t)(dnetp->tx_desc_paddr));
+
+ dnetp->tx_current_desc = dnetp->rx_current_desc = 0;
+ dnetp->transmitted_desc = 0;
+ dnetp->free_desc = dnetp->max_tx_desc;
+ enable_interrupts(dnetp, 1);
+}
+
+/*
+ * dnet_start() -- start the board receiving and allow transmits.
+ * Called with intrlock held.
+ */
+static int
+dnet_start(gld_mac_info_t *macinfo)
+{
+ struct dnetinstance *dnetp = /* Our private device info */
+ (struct dnetinstance *)macinfo->gldm_private;
+ uint32_t val;
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_NOTE, "dnet_start(0x%p)", (void *) macinfo);
+#endif
+
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+ /*
+ * start the board and enable receiving
+ */
+ val = ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG));
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, OPN_MODE_REG),
+ val | START_TRANSMIT);
+ (void) dnet_set_addr(macinfo, dnetp->curr_macaddr);
+ val = ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG));
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, OPN_MODE_REG),
+ val | START_RECEIVE);
+ enable_interrupts(dnetp, 1);
+ return (0);
+}
+
+/*
+ * dnet_start_board() -- start the board receiving and allow transmits.
+ */
+static int
+dnet_start_board(gld_mac_info_t *macinfo)
+{
+ struct dnetinstance *dnetp = /* Our private device info */
+ (struct dnetinstance *)macinfo->gldm_private;
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_NOTE, "dnet_start_board(0x%p)", (void *) macinfo);
+#endif
+
+ mutex_enter(&dnetp->intrlock);
+ /*
+ * start the board and enable receiving
+ */
+ (void) dnet_start(macinfo);
+ mutex_exit(&dnetp->intrlock);
+ return (0);
+}
+
+/*
+ * dnet_stop_board() -- stop board receiving
+ */
+static int
+dnet_stop_board(gld_mac_info_t *macinfo)
+{
+ struct dnetinstance *dnetp = /* Our private device info */
+ (struct dnetinstance *)macinfo->gldm_private;
+ uint32_t val;
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_NOTE, "dnet_stop_board(0x%p)", (void *) macinfo);
+#endif
+ /*
+ * stop the board and disable transmit/receive
+ */
+ mutex_enter(&dnetp->intrlock);
+ val = ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG));
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, OPN_MODE_REG),
+ val & ~(START_TRANSMIT | START_RECEIVE));
+ mutex_exit(&dnetp->intrlock);
+ return (0);
+}
+
+/*
+ * dnet_set_addr() -- set the physical network address on the board
+ * Called with intrlock held.
+ */
+static int
+dnet_set_addr(gld_mac_info_t *macinfo, uchar_t *macaddr)
+{
+ struct dnetinstance *dnetp = /* Our private device info */
+ (struct dnetinstance *)macinfo->gldm_private;
+ struct tx_desc_type *desc;
+ int current_desc;
+ uint32_t index;
+ uint32_t *hashp;
+ uint32_t val;
+
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_NOTE, "dnet_set_addr(0x%p)", (void *) macinfo);
+#endif
+ bcopy(macaddr, dnetp->curr_macaddr, ETHERADDRL);
+ val = ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG));
+ if (!(val & START_TRANSMIT))
+ return (0);
+
+ current_desc = dnetp->tx_current_desc;
+ desc = &dnetp->tx_desc[current_desc];
+
+ mutex_enter(&dnetp->txlock);
+ dnetp->need_saddr = 0;
+ mutex_exit(&dnetp->txlock);
+
+ if ((alloc_descriptor(macinfo)) == FAILURE) {
+ mutex_enter(&dnetp->txlock);
+ dnetp->need_saddr = 1;
+ mutex_exit(&dnetp->txlock);
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_WARN, "DNET saddr:alloc descriptor failure");
+#endif
+ return (0);
+ }
+
+ desc->buffer1 = (uint32_t)(dnetp->setup_buf_paddr);
+ desc->buffer2 = (uint32_t)(0);
+ desc->desc1.buffer_size1 = SETUPBUF_SIZE;
+ desc->desc1.buffer_size2 = 0;
+ desc->desc1.setup_packet = 1;
+ desc->desc1.first_desc = 0;
+ desc->desc1.last_desc = 0;
+ desc->desc1.filter_type0 = 1;
+ desc->desc1.filter_type1 = 1;
+ desc->desc1.int_on_comp = 1;
+
+ /*
+ * As we are using Imperfect filtering, the broadcast address has to
+ * be set explicitly in the 512 bit hash table. Hence the index into
+ * the hash table is calculated and the bit set to enable reception
+ * of broadcast packets.
+ *
+ * We also use HASH_ONLY mode, without using the perfect filter for
+ * our station address, because there appears to be a bug in the
+ * 21140 where it fails to receive the specified perfect filter
+ * address.
+ *
+ * Since dlsdmult comes through here, it doesn't matter that the count
+ * is wrong for the two bits that correspond to the cases below. The
+ * worst that could happen is that we'd leave on a bit for an old
+ * macaddr, in the case where the macaddr gets changed, which is rare.
+ * Since filtering is imperfect, it is OK if that happens.
+ */
+ hashp = (uint32_t *)dnetp->setup_buf_vaddr;
+ index = hashindex((uchar_t *)dnet_broadcastaddr);
+ hashp[ index / 16 ] |= 1 << (index % 16);
+
+ index = hashindex((uchar_t *)dnetp->curr_macaddr);
+ hashp[ index / 16 ] |= 1 << (index % 16);
+
+ desc->desc0.own = 1;
+ ddi_put8(dnetp->io_handle, REG8(dnetp->io_reg, TX_POLL_REG),
+ TX_POLL_DEMAND);
+ return (0);
+}
+
+/*
+ * dnet_set_mac_addr() -- set the physical network address on the board
+ */
+static int
+dnet_set_mac_addr(gld_mac_info_t *macinfo, uchar_t *macaddr)
+{
+ struct dnetinstance *dnetp = /* Our private device info */
+ (struct dnetinstance *)macinfo->gldm_private;
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_NOTE, "dnet_set_mac_addr(0x%p)", (void *) macinfo);
+#endif
+ mutex_enter(&dnetp->intrlock);
+ (void) dnet_set_addr(macinfo, macaddr);
+ mutex_exit(&dnetp->intrlock);
+ return (0);
+}
+
+/*
+ * dnet_set_multicast() -- set (enable) or disable a multicast address
+ *
+ * Program the hardware to enable/disable the multicast address
+ * in "mcast". Enable if "op" is non-zero, disable if zero.
+ */
+static int
+dnet_set_multicast(gld_mac_info_t *macinfo, uchar_t *mcast, int op)
+{
+ struct dnetinstance *dnetp = /* Our private device info */
+ (struct dnetinstance *)macinfo->gldm_private;
+ uint32_t index;
+ uint32_t *hashp;
+ uint32_t retval;
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_NOTE, "dnet_set_multicast(0x%p, %s)",
+ (void *) macinfo, op ? "ON" : "OFF");
+#endif
+ mutex_enter(&dnetp->intrlock);
+ index = hashindex(mcast);
+ hashp = (uint32_t *)dnetp->setup_buf_vaddr;
+ if (op == GLD_MULTI_ENABLE) {
+ if (dnetp->multicast_cnt[index]++) {
+ mutex_exit(&dnetp->intrlock);
+ return (0);
+ }
+ hashp[ index / 16 ] |= 1 << (index % 16);
+ } else {
+ if (--dnetp->multicast_cnt[index]) {
+ mutex_exit(&dnetp->intrlock);
+ return (0);
+ }
+ hashp[ index / 16 ] &= ~ (1 << (index % 16));
+ }
+ retval = dnet_set_addr(macinfo, dnetp->curr_macaddr);
+ mutex_exit(&dnetp->intrlock);
+ return (retval);
+}
+
+/*
+ * A hashing function used for setting the
+ * node address or a multicast address
+ */
+static uint32_t
+hashindex(uchar_t *address)
+{
+ uint32_t crc = (uint32_t)HASH_CRC;
+ uint32_t const POLY = HASH_POLY;
+ uint32_t msb;
+ int32_t byteslength;
+ uint8_t currentbyte;
+ uint32_t index;
+ int32_t bit;
+ int32_t shift;
+
+ for (byteslength = 0; byteslength < ETHERADDRL; byteslength++) {
+ currentbyte = address[byteslength];
+ for (bit = 0; bit < 8; bit++) {
+ msb = crc >> 31;
+ crc <<= 1;
+ if (msb ^ (currentbyte & 1)) {
+ crc ^= POLY;
+ crc |= 0x00000001;
+ }
+ currentbyte >>= 1;
+ }
+ }
+
+ for (index = 0, bit = 23, shift = 8;
+ shift >= 0;
+ bit++, shift--) {
+ index |= (((crc >> bit) & 1) << shift);
+ }
+ return (index);
+}
+
+/*
+ * dnet_set_promiscuous() -- set or reset promiscuous mode on the board
+ *
+ * Program the hardware to enable/disable promiscuous mode.
+ * Enable if "on" is non-zero, disable if zero.
+ */
+
+static int
+dnet_set_promiscuous(gld_mac_info_t *macinfo, int on)
+{
+ struct dnetinstance *dnetp;
+ uint32_t val;
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_NOTE, "dnet_set_promiscuous(0x%p, %s)",
+ (void *) macinfo, on ? "ON" : "OFF");
+#endif
+
+ dnetp = (struct dnetinstance *)macinfo->gldm_private;
+ mutex_enter(&dnetp->intrlock);
+ if (dnetp->promisc == on) {
+ mutex_exit(&dnetp->intrlock);
+ return (SUCCESS);
+ }
+ dnetp->promisc = on;
+
+ val = ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG));
+ if (on != GLD_MAC_PROMISC_NONE)
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG),
+ val | PROM_MODE);
+ else
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG),
+ val & (~PROM_MODE));
+ mutex_exit(&dnetp->intrlock);
+ return (DDI_SUCCESS);
+}
+
+/*
+ * dnet_get_stats() -- update statistics
+ *
+ * GLD calls this routine just before it reads the driver's statistics
+ * structure. If your board maintains statistics, this is the time to
+ * read them in and update the values in the structure. If the driver
+ * maintains statistics continuously, this routine need do nothing.
+ */
+
+static int
+dnet_get_stats(gld_mac_info_t *macinfo, struct gld_stats *sp)
+{
+ struct dnetinstance *dnetp = /* Our private device info */
+ (struct dnetinstance *)macinfo->gldm_private;
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_NOTE, "dnet_get_stats(0x%p)", (void *) macinfo);
+#endif
+ sp->glds_errrcv = dnetp->stat_errrcv;
+ sp->glds_overflow = dnetp->stat_overflow;
+ sp->glds_intr = dnetp->stat_intr;
+ sp->glds_defer = dnetp->stat_defer;
+ sp->glds_missed = dnetp->stat_missed;
+ sp->glds_norcvbuf = dnetp->stat_norcvbuf;
+ sp->glds_crc = dnetp->stat_crc;
+ sp->glds_short = dnetp->stat_short;
+ sp->glds_frame = dnetp->stat_frame;
+ sp->glds_errxmt = dnetp->stat_errxmt;
+ sp->glds_collisions = dnetp->stat_collisions;
+ sp->glds_xmtlatecoll = dnetp->stat_xmtlatecoll;
+ sp->glds_excoll = dnetp->stat_excoll;
+ sp->glds_underflow = dnetp->stat_underflow;
+ sp->glds_nocarrier = dnetp->stat_nocarrier;
+
+ /* stats from instance structure */
+ sp->glds_speed = dnetp->speed * 1000000;
+ sp->glds_duplex =
+ dnetp->full_duplex ? GLD_DUPLEX_FULL : GLD_DUPLEX_HALF;
+
+ return (DDI_SUCCESS);
+}
+
+/*
+ * dnet_send() -- send a packet
+ *
+ * Called when a packet is ready to be transmitted. A pointer to an
+ * M_DATA message that contains the packet is passed to this routine.
+ * The complete LLC header is contained in the message's first message
+ * block, and the remainder of the packet is contained within
+ * additional M_DATA message blocks linked to the first message block.
+ */
+
+#define NextTXIndex(index) (((index)+1) % dnetp->max_tx_desc)
+#define PrevTXIndex(index) (((index)-1) < 0 ? dnetp->max_tx_desc - 1: (index)-1)
+
+static int
+dnet_send(gld_mac_info_t *macinfo, mblk_t *mp)
+{
+ struct dnetinstance *dnetp = /* Our private device info */
+ (struct dnetinstance *)macinfo->gldm_private;
+ struct tx_desc_type *ring = dnetp->tx_desc;
+ int mblen, totlen;
+ int index, end_index, start_index;
+ int avail;
+ int error;
+ int bufn;
+ int bp_count;
+ int retval;
+ mblk_t *bp;
+ uint32_t tx_interrupt_mask;
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETSEND)
+ cmn_err(CE_NOTE, "dnet_send(0x%p, 0x%p)",
+ (void *) macinfo, (void *) mp);
+#endif
+ mutex_enter(&dnetp->txlock);
+ if (dnetp->need_saddr) {
+ /* XXX function return value ignored */
+ mutex_exit(&dnetp->txlock);
+ mutex_enter(&dnetp->intrlock);
+ (void) dnet_set_addr(macinfo, dnetp->curr_macaddr);
+ mutex_exit(&dnetp->intrlock);
+ mutex_enter(&dnetp->txlock);
+ }
+
+ /* reclaim any xmit descriptors completed */
+ dnet_reclaim_Tx_desc(macinfo);
+
+ /*
+ * Use the data buffers from the message and construct the
+ * scatter/gather list by calling ddi_dma_addr_bind_handle().
+ */
+ error = bp_count = 0;
+ totlen = 0;
+ bp = mp;
+ bufn = 0;
+ index = start_index = dnetp->tx_current_desc;
+ avail = dnetp->free_desc;
+ while (bp != NULL) {
+ uint_t ncookies;
+ ddi_dma_cookie_t dma_cookie;
+
+ if (++bp_count > DNET_MAX_FRAG) {
+#ifndef DNET_NOISY
+ (void) pullupmsg(bp, -1);
+#else
+ if (pullupmsg(bp, -1))
+ cmn_err(CE_NOTE, "DNET: pulled up send msg");
+ else
+ cmn_err(CE_NOTE, "DNET: couldn't pullup send msg");
+#endif
+ }
+
+ mblen = (int)(bp->b_wptr - bp->b_rptr);
+
+ if (!mblen) { /* skip zero-length message blocks */
+ bp = bp->b_cont;
+ continue;
+ }
+
+ retval = ddi_dma_addr_bind_handle(dnetp->dma_handle_tx, NULL,
+ (caddr_t)bp->b_rptr, mblen,
+ DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, 0,
+ &dma_cookie, &ncookies);
+
+ switch (retval) {
+ case DDI_DMA_MAPPED:
+ break; /* everything's fine */
+
+ case DDI_DMA_NORESOURCES:
+ error = 1; /* allow retry by gld */
+ break;
+
+ case DDI_DMA_NOMAPPING:
+ case DDI_DMA_INUSE:
+ case DDI_DMA_TOOBIG:
+ default:
+ error = 2; /* error, no retry */
+ break;
+ }
+
+ /*
+ * we can use two cookies per descriptor (i.e buffer1 and
+ * buffer2) so we need at least (ncookies+1)/2 descriptors.
+ */
+ if (((ncookies + 1) >> 1) > dnetp->free_desc) {
+ (void) ddi_dma_unbind_handle(dnetp->dma_handle_tx);
+ error = 1;
+ break;
+ }
+
+ /* setup the descriptors for this data buffer */
+ while (ncookies) {
+ end_index = index;
+ if (bufn % 2) {
+ ring[index].buffer2 =
+ (uint32_t)dma_cookie.dmac_address;
+ ring[index].desc1.buffer_size2 =
+ dma_cookie.dmac_size;
+ index = NextTXIndex(index); /* goto next desc */
+ } else {
+ /* initialize the descriptor */
+ ASSERT(ring[index].desc0.own == 0);
+ *(uint32_t *)&ring[index].desc0 = 0;
+ *(uint32_t *)&ring[index].desc1 &=
+ DNET_END_OF_RING;
+ ring[index].buffer1 =
+ (uint32_t)dma_cookie.dmac_address;
+ ring[index].desc1.buffer_size1 =
+ dma_cookie.dmac_size;
+ ring[index].buffer2 = (uint32_t)(0);
+ dnetp->free_desc--;
+ ASSERT(dnetp->free_desc >= 0);
+ }
+ totlen += dma_cookie.dmac_size;
+ bufn++;
+ if (--ncookies)
+ ddi_dma_nextcookie(dnetp->dma_handle_tx,
+ &dma_cookie);
+ }
+ (void) ddi_dma_unbind_handle(dnetp->dma_handle_tx);
+ bp = bp->b_cont;
+ }
+
+ if (error == 1) {
+ dnetp->stat_defer++;
+ dnetp->free_desc = avail;
+ dnetp->need_gld_sched = 1;
+ mutex_exit(&dnetp->txlock);
+ return (GLD_TX_RESEND);
+ } else if (error) {
+ dnetp->free_desc = avail;
+ mutex_exit(&dnetp->txlock);
+ freemsg(mp);
+ return (0); /* Drop packet, don't retry */
+ }
+
+ if (totlen > ETHERMAX) {
+ cmn_err(CE_WARN, "DNET: tried to send large %d packet", totlen);
+ dnetp->free_desc = avail;
+ mutex_exit(&dnetp->txlock);
+ freemsg(mp);
+ return (0); /* We don't want to repeat this attempt */
+ }
+
+ /*
+ * Remeber the message buffer pointer to do freemsg() at xmit
+ * interrupt time.
+ */
+ dnetp->tx_msgbufp[end_index] = mp;
+
+ /*
+ * Now set the first/last buffer and own bits
+ * Since the 21040 looks for these bits set in the
+ * first buffer, work backwards in multiple buffers.
+ */
+ ring[end_index].desc1.last_desc = 1;
+ ring[end_index].desc1.int_on_comp = 1;
+ for (index = end_index; index != start_index;
+ index = PrevTXIndex(index))
+ ring[index].desc0.own = 1;
+ ring[start_index].desc1.first_desc = 1;
+ ring[start_index].desc0.own = 1;
+
+ dnetp->tx_current_desc = NextTXIndex(end_index);
+
+ /*
+ * Safety check: make sure end-of-ring is set in last desc.
+ */
+ ASSERT(ring[dnetp->max_tx_desc-1].desc1.end_of_ring != 0);
+
+ /*
+ * Enable xmit interrupt if we are running out of xmit descriptors
+ * or there are more packets on the queue waiting to be transmitted.
+ */
+#ifdef GLD_INTR_WAIT /* XXX This relies on new GLD changes */
+ if (dnetp->free_desc <= dnet_xmit_threshold)
+ tx_interrupt_mask = TX_INTERRUPT_MASK;
+ else
+ tx_interrupt_mask = (macinfo->gldm_GLD_flags & GLD_INTR_WAIT) ?
+ TX_INTERRUPT_MASK : 0;
+#else
+ tx_interrupt_mask = TX_INTERRUPT_MASK;
+#endif
+
+ mutex_exit(&dnetp->txlock);
+ mutex_enter(&dnetp->intrlock);
+ enable_interrupts(dnetp, tx_interrupt_mask);
+
+ /*
+ * Kick the transmitter
+ */
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, TX_POLL_REG),
+ TX_POLL_DEMAND);
+ mutex_exit(&dnetp->intrlock);
+ return (GLD_TX_OK); /* successful transmit attempt */
+}
+
+/*
+ * dnetintr() -- interrupt from board to inform us that a receive or
+ * transmit has completed.
+ */
+
+
+static uint_t
+dnetintr(gld_mac_info_t *macinfo)
+{
+ struct dnetinstance *dnetp = /* Our private device info */
+ (struct dnetinstance *)macinfo->gldm_private;
+ uint32_t int_status;
+ uint32_t tx_interrupt_mask;
+
+ mutex_enter(&dnetp->intrlock);
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETINT)
+ cmn_err(CE_NOTE, "dnetintr(0x%p)", (void *)macinfo);
+#endif
+ int_status = ddi_get32(dnetp->io_handle, REG32(dnetp->io_reg,
+ STATUS_REG));
+
+ /*
+ * If interrupt was not from this board
+ */
+ if (!(int_status & (NORMAL_INTR_SUMM | ABNORMAL_INTR_SUMM))) {
+ mutex_exit(&dnetp->intrlock);
+ return (DDI_INTR_UNCLAIMED);
+ }
+
+ dnetp->stat_intr++;
+
+ if (int_status & GPTIMER_INTR) {
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, STATUS_REG), GPTIMER_INTR);
+ if (dnetp->timer.cb)
+ dnetp->timer.cb(dnetp);
+ else
+ cmn_err(CE_WARN, "dnet: unhandled timer interrupt");
+ }
+
+ if (int_status & TX_INTR) {
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, STATUS_REG), TX_INTR);
+ mutex_enter(&dnetp->txlock);
+ if (dnetp->need_gld_sched) {
+ mutex_exit(&dnetp->txlock);
+ mutex_exit(&dnetp->intrlock);
+ gld_sched(macinfo);
+ mutex_enter(&dnetp->intrlock);
+ mutex_enter(&dnetp->txlock);
+ dnetp->need_gld_sched = 0;
+ }
+ /* reclaim any xmit descriptors that are completed */
+ dnet_reclaim_Tx_desc(macinfo);
+ mutex_exit(&dnetp->txlock);
+ }
+
+ /*
+ * Check if receive interrupt bit is set
+ */
+ if (int_status & RX_INTR) {
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, STATUS_REG), RX_INTR);
+ dnet_getp(macinfo);
+ }
+
+ if (int_status & ABNORMAL_INTR_SUMM) {
+ /*
+ * Check for system error
+ */
+ if (int_status & SYS_ERR) {
+ if ((int_status & SYS_ERR_BITS) == MASTER_ABORT)
+ cmn_err(CE_WARN, "DNET: Bus Master Abort");
+ if ((int_status & SYS_ERR_BITS) == TARGET_ABORT)
+ cmn_err(CE_WARN, "DNET: Bus Target Abort");
+ if ((int_status & SYS_ERR_BITS) == PARITY_ERROR)
+ cmn_err(CE_WARN, "DNET: Parity error");
+ }
+
+ /*
+ * If the jabber has timed out then reset the chip
+ */
+ if (int_status & TX_JABBER_TIMEOUT)
+ cmn_err(CE_WARN, "DNET: Jabber timeout.");
+
+ /*
+ * If an underflow has occurred, reset the chip
+ */
+ if (int_status & TX_UNDERFLOW)
+ cmn_err(CE_WARN, "DNET: Tx Underflow.");
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETINT)
+ cmn_err(CE_NOTE, "Trying to reset...");
+#endif
+ dnet_reset_board(macinfo);
+ dnet_init_board(macinfo);
+ /* XXX function return value ignored */
+ (void) dnet_start(macinfo);
+ }
+
+ /*
+ * Enable the interrupts. Enable xmit interrupt only if we are
+ * running out of free descriptors or if there are packets
+ * in the queue waiting to be transmitted.
+ */
+#ifdef GLD_INTR_WAIT /* XXX This relies on new GLD changes */
+ if (dnetp->free_desc <= dnet_xmit_threshold)
+ tx_interrupt_mask = TX_INTERRUPT_MASK;
+ else
+ tx_interrupt_mask = (macinfo->gldm_GLD_flags & GLD_INTR_WAIT) ?
+ TX_INTERRUPT_MASK : 0;
+#else
+ tx_interrupt_mask = TX_INTERRUPT_MASK;
+#endif
+ enable_interrupts(dnetp, tx_interrupt_mask);
+ mutex_exit(&dnetp->intrlock);
+ return (DDI_INTR_CLAIMED); /* Indicate it was our interrupt */
+}
+
+static void
+dnet_getp(gld_mac_info_t *macinfo)
+{
+ struct dnetinstance *dnetp =
+ (struct dnetinstance *)macinfo->gldm_private;
+ int packet_length, index;
+ mblk_t *mp;
+ caddr_t virtual_address;
+ struct rx_desc_type *desc = dnetp->rx_desc;
+ int marker = dnetp->rx_current_desc;
+ int misses;
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETRECV)
+ cmn_err(CE_NOTE, "dnet_getp(0x%p)", (void *)macinfo);
+#endif
+
+ if (!dnetp->overrun_workaround) {
+ /*
+ * If the workaround is not in place, we must still update
+ * the missed frame statistic from the on-chip counter.
+ */
+ misses = ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, MISSED_FRAME_REG));
+ dnetp->stat_missed += (misses & MISSED_FRAME_MASK);
+ }
+
+ /* While host owns the current descriptor */
+ while (!(desc[dnetp->rx_current_desc].desc0.own)) {
+ struct free_ptr *frp;
+ caddr_t newbuf;
+ struct rbuf_list *rp;
+
+ index = dnetp->rx_current_desc;
+ ASSERT(desc[index].desc0.first_desc != 0);
+
+ /*
+ * DMA overrun errata from DEC: avoid possible bus hangs
+ * and data corruption
+ */
+ if (dnetp->overrun_workaround &&
+ marker == dnetp->rx_current_desc) {
+ int opn;
+ do {
+ marker = (marker+1) % dnetp->max_rx_desc;
+ } while (!(dnetp->rx_desc[marker].desc0.own) &&
+ marker != index);
+
+ misses = ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, MISSED_FRAME_REG));
+ dnetp->stat_missed +=
+ (misses & MISSED_FRAME_MASK);
+ if (misses & OVERFLOW_COUNTER_MASK) {
+ /*
+ * Overflow(s) have occurred : stop receiver,
+ * and wait until in stopped state
+ */
+ opn = ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG));
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG),
+ opn & ~(START_RECEIVE));
+
+ do {
+ drv_usecwait(10);
+ } while ((ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, STATUS_REG)) &
+ RECEIVE_PROCESS_STATE) != 0);
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETRECV)
+ cmn_err(CE_CONT, "^*");
+#endif
+ /* Discard probably corrupt frames */
+ while (!(dnetp->rx_desc[index].desc0.own)) {
+ dnetp->rx_desc[index].desc0.own = 1;
+ index = (index+1) % dnetp->max_rx_desc;
+ dnetp->stat_missed++;
+ }
+
+ /* restart the receiver */
+ opn = ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG));
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG),
+ opn | START_RECEIVE);
+ marker = dnetp->rx_current_desc = index;
+ continue;
+ }
+ /*
+ * At this point, we know that all packets before
+ * "marker" were received before a dma overrun occurred
+ */
+ }
+
+ /*
+ * If we get an oversized packet it could span multiple
+ * descriptors. If this happens an error bit should be set.
+ */
+ while (desc[index].desc0.last_desc == 0) {
+ index = (index + 1) % dnetp->max_rx_desc;
+ if (desc[index].desc0.own)
+ return; /* not done receiving large packet */
+ }
+ while (dnetp->rx_current_desc != index) {
+ desc[dnetp->rx_current_desc].desc0.own = 1;
+ dnetp->rx_current_desc =
+ (dnetp->rx_current_desc + 1) % dnetp->max_rx_desc;
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETRECV)
+ cmn_err(CE_WARN, "dnet: received large packet");
+#endif
+ }
+
+ packet_length = desc[index].desc0.frame_len;
+
+ /*
+ * Remove CRC from received data. This is an artefact of the
+ * 21x4x chip and should not be passed higher up the network
+ * stack.
+ */
+ packet_length -= ETHERFCSL;
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETRECV) {
+ if (packet_length > ETHERMAX)
+ cmn_err(CE_WARN, "dnet: large packet size %d",
+ packet_length);
+ }
+#endif
+
+ /* get the virtual address of the packet received */
+ virtual_address =
+ dnetp->rx_buf_vaddr[index];
+
+ /*
+ * If no packet errors then do:
+ * 1. Allocate a new receive buffer so that we can
+ * use the current buffer as streams buffer to
+ * avoid bcopy.
+ * 2. If we got a new receive buffer then allocate
+ * an mblk using desballoc().
+ * 3. Otherwise use the mblk from allocb() and do
+ * the bcopy.
+ */
+ frp = NULL;
+ rp = NULL;
+ newbuf = NULL;
+ mp = NULL;
+ if (!desc[index].desc0.err_summary) {
+ ASSERT(packet_length < rx_buf_size);
+ /*
+ * Allocate another receive buffer for this descriptor.
+ * If we fail to allocate then we do the normal bcopy.
+ */
+ rp = dnet_rbuf_alloc(dnetp->devinfo, 0);
+ if (rp != NULL) {
+ newbuf = rp->rbuf_vaddr;
+ frp = kmem_zalloc(sizeof (*frp), KM_NOSLEEP);
+ if (frp != NULL) {
+ frp->free_rtn.free_func = dnet_freemsg_buf;
+ frp->free_rtn.free_arg = (char *)frp;
+ frp->buf = virtual_address;
+ mp = desballoc((uchar_t *)virtual_address,
+ packet_length, 0, &frp->free_rtn);
+ if (mp == NULL) {
+ kmem_free(frp, sizeof (*frp));
+ dnet_rbuf_free((caddr_t)newbuf);
+ frp = NULL;
+ newbuf = NULL;
+ }
+ }
+ }
+ if (mp == NULL) {
+ if (newbuf != NULL)
+ dnet_rbuf_free((caddr_t)newbuf);
+ mp = allocb(packet_length, 0);
+ }
+ }
+
+ if (desc[index].desc0.err_summary || (mp == NULL)) {
+
+ /* Update gld statistics */
+ if (desc[index].desc0.err_summary)
+ update_rx_stats(macinfo, index);
+ else
+ dnetp->stat_norcvbuf++;
+
+ /*
+ * Reset ownership of the descriptor.
+ */
+ desc[index].desc0.own = 1;
+ dnetp->rx_current_desc =
+ (dnetp->rx_current_desc+1) % dnetp->max_rx_desc;
+
+ /* Demand receive polling by the chip */
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, RX_POLL_REG), RX_POLL_DEMAND);
+
+ continue;
+ }
+
+ if (newbuf != NULL) {
+ uint32_t end_paddr;
+ /* attach the new buffer to the rx descriptor */
+ dnetp->rx_buf_vaddr[index] = newbuf;
+ desc[index].buffer1 = (uint32_t)rp->rbuf_paddr;
+ desc[index].desc1.buffer_size1 = rx_buf_size;
+ desc[index].desc1.buffer_size2 = 0;
+ end_paddr = (uint32_t)rp->rbuf_endpaddr;
+ if ((desc[index].buffer1 & ~dnetp->pgmask) !=
+ (end_paddr & ~dnetp->pgmask)) {
+ /* discontiguous */
+ desc[index].buffer2 = end_paddr&~dnetp->pgmask;
+ desc[index].desc1.buffer_size2 =
+ (end_paddr & dnetp->pgmask) + 1;
+ desc[index].desc1.buffer_size1 =
+ rx_buf_size-desc[index].desc1.buffer_size2;
+ }
+ } else {
+ /* couldn't allocate another buffer; copy the data */
+ BCOPY((caddr_t)virtual_address, (caddr_t)mp->b_wptr,
+ packet_length);
+ }
+
+ mp->b_wptr += packet_length;
+
+ desc[dnetp->rx_current_desc].desc0.own = 1;
+
+ /*
+ * Increment receive desc index. This is for the scan of
+ * next packet
+ */
+ dnetp->rx_current_desc =
+ (dnetp->rx_current_desc+1) % dnetp->max_rx_desc;
+
+ /* Demand polling by chip */
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, RX_POLL_REG), RX_POLL_DEMAND);
+
+ /* send the packet upstream */
+ mutex_exit(&dnetp->intrlock);
+ gld_recv(macinfo, mp);
+ mutex_enter(&dnetp->intrlock);
+ }
+}
+/*
+ * Function to update receive statistics
+ */
+static void
+update_rx_stats(gld_mac_info_t *macinfo, int index)
+{
+ struct dnetinstance *dnetp =
+ (struct dnetinstance *)macinfo->gldm_private;
+ struct rx_desc_type *descp = &(dnetp->rx_desc[index]);
+
+ /*
+ * Update gld statistics
+ */
+ dnetp->stat_errrcv++;
+
+ if (descp->desc0.overflow) {
+ /* FIFO Overrun */
+ dnetp->stat_overflow++;
+ }
+
+ if (descp->desc0.collision) {
+ /*EMPTY*/
+ /* Late Colllision on receive */
+ /* no appropriate counter */
+ }
+
+ if (descp->desc0.crc) {
+ /* CRC Error */
+ dnetp->stat_crc++;
+ }
+
+ if (descp->desc0.runt_frame) {
+ /* Runt Error */
+ dnetp->stat_short++;
+ }
+
+ if (descp->desc0.desc_err) {
+ /*EMPTY*/
+ /* Not enough receive descriptors */
+ /* This condition is accounted in dnetintr() */
+ /* macinfo->gldm_stats.glds_missed++; */
+ }
+
+ if (descp->desc0.frame2long) {
+ dnetp->stat_frame++;
+ }
+}
+
+/*
+ * Function to update transmit statistics
+ */
+static void
+update_tx_stats(gld_mac_info_t *macinfo, int index)
+{
+ struct dnetinstance *dnetp =
+ (struct dnetinstance *)macinfo->gldm_private;
+ struct tx_desc_type *descp = &(dnetp->tx_desc[index]);
+ int fd;
+ media_block_t *block = dnetp->selected_media_block;
+
+
+ /* Update gld statistics */
+ dnetp->stat_errxmt++;
+
+ /* If we're in full-duplex don't count collisions or carrier loss. */
+ if (dnetp->mii_up) {
+ fd = dnetp->mii_duplex;
+ } else {
+ /* Rely on media code */
+ fd =
+ block->media_code == MEDIA_TP_FD ||
+ block->media_code == MEDIA_SYM_SCR_FD;
+ }
+
+ if (descp->desc0.collision_count && !fd) {
+ dnetp->stat_collisions +=
+ descp->desc0.collision_count;
+ }
+
+ if (descp->desc0.late_collision && !fd) {
+ dnetp->stat_xmtlatecoll++;
+ }
+
+ if (descp->desc0.excess_collision && !fd) {
+ dnetp->stat_excoll++;
+ }
+
+ if (descp->desc0.underflow) {
+ dnetp->stat_underflow++;
+ }
+
+#if 0
+ if (descp->desc0.tx_jabber_to) {
+ /* no appropriate counter */
+ }
+#endif
+
+ if (descp->desc0.carrier_loss && !fd) {
+ dnetp->stat_nocarrier++;
+ }
+
+ if (descp->desc0.no_carrier && !fd) {
+ dnetp->stat_nocarrier++;
+ }
+}
+
+/*
+ * ========== Media Selection Setup Routines ==========
+ */
+
+
+static void
+write_gpr(struct dnetinstance *dnetp, uint32_t val)
+{
+#ifdef DEBUG
+ if (dnetdebug & DNETREGCFG)
+ cmn_err(CE_NOTE, "GPR: %x", val);
+#endif
+ switch (dnetp->board_type) {
+ case DEVICE_ID_21143:
+ /* Set the correct bit for a control write */
+ if (val & GPR_CONTROL_WRITE)
+ val |= CWE_21143, val &= ~GPR_CONTROL_WRITE;
+ /* Write to upper half of CSR15 */
+ dnetp->gprsia = (dnetp->gprsia & 0xffff) | (val << 16);
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, SIA_GENERAL_REG),
+ dnetp->gprsia);
+ break;
+ default:
+ /* Set the correct bit for a control write */
+ if (val & GPR_CONTROL_WRITE)
+ val |= CWE_21140, val &= ~GPR_CONTROL_WRITE;
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, GP_REG),
+ val);
+ break;
+ }
+}
+
+static uint32_t
+read_gpr(struct dnetinstance *dnetp)
+{
+ switch (dnetp->board_type) {
+ case DEVICE_ID_21143:
+ /* Read upper half of CSR15 */
+ return (ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, SIA_GENERAL_REG)) >> 16);
+ default:
+ return (ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, GP_REG)));
+ }
+}
+
+static void
+set_gpr(gld_mac_info_t *macinfo)
+{
+ uint32_t *sequence;
+ int len;
+ struct dnetinstance *dnetp = (struct dnetinstance *)
+ macinfo->gldm_private;
+ LEAF_FORMAT *leaf = &dnetp->sr.leaf[dnetp->leaf];
+ media_block_t *block = dnetp->selected_media_block;
+ int i;
+
+ if (ddi_getlongprop(DDI_DEV_T_ANY, dnetp->devinfo,
+ DDI_PROP_DONTPASS, "gpr-sequence", (caddr_t)&sequence,
+ &len) == DDI_PROP_SUCCESS) {
+ for (i = 0; i < len / sizeof (uint32_t); i++)
+ write_gpr(dnetp, sequence[i]);
+ kmem_free(sequence, len);
+ } else {
+ /*
+ * Write the reset sequence if this is the first time this
+ * block has been selected.
+ */
+ if (block->rstseqlen) {
+ for (i = 0; i < block->rstseqlen; i++)
+ write_gpr(dnetp, block->rstseq[i]);
+ /*
+ * XXX Legacy blocks do not have reset sequences, so the
+ * static blocks will never be modified by this
+ */
+ block->rstseqlen = 0;
+ }
+ if (leaf->gpr)
+ write_gpr(dnetp, leaf->gpr | GPR_CONTROL_WRITE);
+
+ /* write GPR sequence each time */
+ for (i = 0; i < block->gprseqlen; i++)
+ write_gpr(dnetp, block->gprseq[i]);
+ }
+
+ /* This has possibly caused a PHY to reset. Let MII know */
+ if (dnetp->phyaddr != -1)
+ /* XXX function return value ignored */
+ (void) mii_sync(dnetp->mii, dnetp->phyaddr);
+ drv_usecwait(5);
+}
+
+/* set_opr() - must be called with intrlock held */
+
+static void
+set_opr(gld_mac_info_t *macinfo)
+{
+ uint32_t fd, mb1, sf;
+
+ struct dnetinstance *dnetp =
+ (struct dnetinstance *)macinfo->gldm_private;
+ int opnmode_len;
+ uint32_t val;
+ media_block_t *block = dnetp->selected_media_block;
+
+ ASSERT(block);
+
+ /* Check for custom "opnmode_reg" property */
+ opnmode_len = sizeof (val);
+ if (ddi_prop_op(DDI_DEV_T_ANY, dnetp->devinfo,
+ PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, "opnmode_reg",
+ (caddr_t)&val, &opnmode_len) != DDI_PROP_SUCCESS)
+ opnmode_len = 0;
+
+ /* Some bits exist only on 21140 and greater */
+ if (dnetp->board_type != DEVICE_ID_21040 &&
+ dnetp->board_type != DEVICE_ID_21041) {
+ mb1 = OPN_REG_MB1;
+ sf = STORE_AND_FORWARD;
+ } else {
+ mb1 = sf = 0;
+ mb1 = OPN_REG_MB1; /* Needed for 21040? */
+ }
+
+ if (opnmode_len) {
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG), val);
+ dnet_reset_board(macinfo);
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, OPN_MODE_REG), val);
+ return;
+ }
+
+ /*
+ * Set each bit in CSR6 that we want
+ */
+
+ /* Always want these bits set */
+ val = HASH_FILTERING | HASH_ONLY | TX_THRESHOLD_160 | mb1 | sf;
+
+ /* Promiscuous mode */
+ val |= dnetp->promisc ? PROM_MODE : 0;
+
+ /* Scrambler for SYM style media */
+ val |= ((block->command & CMD_SCR) && !dnetp->disable_scrambler) ?
+ SCRAMBLER_MODE : 0;
+
+ /* Full duplex */
+ if (dnetp->mii_up) {
+ fd = dnetp->mii_duplex;
+ } else {
+ /* Rely on media code */
+ fd =
+ block->media_code == MEDIA_TP_FD ||
+ block->media_code == MEDIA_SYM_SCR_FD;
+ }
+
+ /* Port select (and therefore, heartbeat disable) */
+ val |= block->command & CMD_PS ? (PORT_SELECT | HEARTBEAT_DISABLE) : 0;
+
+ /* PCS function */
+ val |= (block->command) & CMD_PCS ? PCS_FUNCTION : 0;
+ val |= fd ? FULL_DUPLEX : 0;
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETREGCFG)
+ cmn_err(CE_NOTE, "OPN: %x", val);
+#endif
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, OPN_MODE_REG), val);
+ dnet_reset_board(macinfo);
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, OPN_MODE_REG), val);
+}
+
+static void
+set_sia(gld_mac_info_t *macinfo)
+{
+ struct dnetinstance *dnetp = (struct dnetinstance *)
+ (macinfo->gldm_private);
+ media_block_t *block = dnetp->selected_media_block;
+
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+ if (block->type == 2) {
+ int sia_delay;
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETREGCFG)
+ cmn_err(CE_NOTE,
+ "SIA: CSR13: %x, CSR14: %x, CSR15: %x",
+ block->un.sia.csr13,
+ block->un.sia.csr14,
+ block->un.sia.csr15);
+#endif
+ sia_delay = ddi_getprop(DDI_DEV_T_ANY, dnetp->devinfo,
+ DDI_PROP_DONTPASS, "sia-delay", 10000);
+
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, SIA_CONNECT_REG), 0);
+
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, SIA_TXRX_REG),
+ block->un.sia.csr14);
+
+ /*
+ * For '143, we need to write through a copy of the register
+ * to keep the GP half intact
+ */
+ dnetp->gprsia = (dnetp->gprsia&0xffff0000)|block->un.sia.csr15;
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, SIA_GENERAL_REG),
+ dnetp->gprsia);
+
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, SIA_CONNECT_REG),
+ block->un.sia.csr13);
+
+ drv_usecwait(sia_delay);
+
+ } else if (dnetp->board_type != DEVICE_ID_21140) {
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, SIA_CONNECT_REG), 0);
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, SIA_TXRX_REG), 0);
+ }
+}
+
+/*
+ * ========== Buffer Management Routines ==========
+ */
+
+/*
+ * This function (re)allocates the receive and transmit buffers and
+ * descriptors. It can be called more than once per instance, though
+ * currently it is only called from attach. It should only be called
+ * while the device is reset.
+ */
+static int
+dnet_alloc_bufs(gld_mac_info_t *macinfo)
+{
+ struct dnetinstance *dnetp = (struct dnetinstance *)
+ (macinfo->gldm_private);
+ int i;
+ size_t len;
+ int page_size;
+ int realloc = 0;
+ int nrecv_desc_old = 0;
+ ddi_dma_cookie_t cookie;
+ uint_t ncookies;
+
+ /*
+ * check if we are trying to reallocate with different xmit/recv
+ * descriptor ring sizes.
+ */
+ if ((dnetp->tx_desc != NULL) &&
+ (dnetp->nxmit_desc != dnetp->max_tx_desc))
+ realloc = 1;
+
+ if ((dnetp->rx_desc != NULL) &&
+ (dnetp->nrecv_desc != dnetp->max_rx_desc))
+ realloc = 1;
+
+ /* free up the old buffers if we are reallocating them */
+ if (realloc) {
+ nrecv_desc_old = dnetp->nrecv_desc;
+ dnet_free_bufs(macinfo); /* free the old buffers */
+ }
+
+ if (dnetp->dma_handle == NULL)
+ if (ddi_dma_alloc_handle(dnetp->devinfo, &dma_attr,
+ DDI_DMA_SLEEP, 0, &dnetp->dma_handle) != DDI_SUCCESS)
+ return (FAILURE);
+
+ if (dnetp->dma_handle_tx == NULL)
+ if (ddi_dma_alloc_handle(dnetp->devinfo, &dma_attr_tx,
+ DDI_DMA_SLEEP, 0, &dnetp->dma_handle_tx) != DDI_SUCCESS)
+ return (FAILURE);
+
+ if (dnetp->dma_handle_txdesc == NULL)
+ if (ddi_dma_alloc_handle(dnetp->devinfo, &dma_attr,
+ DDI_DMA_SLEEP, 0, &dnetp->dma_handle_txdesc) != DDI_SUCCESS)
+ return (FAILURE);
+
+ if (dnetp->dma_handle_setbuf == NULL)
+ if (ddi_dma_alloc_handle(dnetp->devinfo, &dma_attr,
+ DDI_DMA_SLEEP, 0, &dnetp->dma_handle_setbuf) != DDI_SUCCESS)
+ return (FAILURE);
+
+ page_size = ddi_ptob(dnetp->devinfo, 1);
+ for (i = page_size, len = 0; i > 1; len++)
+ i >>= 1;
+ dnetp->pgmask = page_size - 1;
+ dnetp->pgshft = len;
+
+ /* allocate setup buffer if necessary */
+ if (dnetp->setup_buf_vaddr == NULL) {
+ if (ddi_dma_mem_alloc(dnetp->dma_handle_setbuf,
+ SETUPBUF_SIZE, &accattr, DDI_DMA_STREAMING,
+ DDI_DMA_DONTWAIT, 0, (caddr_t *)&dnetp->setup_buf_vaddr,
+ &len, &dnetp->setup_buf_acchdl) != DDI_SUCCESS)
+ return (FAILURE);
+
+ if (ddi_dma_addr_bind_handle(dnetp->dma_handle_setbuf,
+ NULL, dnetp->setup_buf_vaddr, SETUPBUF_SIZE,
+ DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_SLEEP,
+ NULL, &cookie, &ncookies) != DDI_DMA_MAPPED)
+ return (FAILURE);
+
+ dnetp->setup_buf_paddr = (caddr_t)(uintptr_t)
+ cookie.dmac_laddress;
+ bzero(dnetp->setup_buf_vaddr, len);
+ }
+
+ /* allocate xmit descriptor array of size dnetp->max_tx_desc */
+ if (dnetp->tx_desc == NULL) {
+ if (ddi_dma_mem_alloc(dnetp->dma_handle_txdesc,
+ sizeof (struct tx_desc_type) * dnetp->max_tx_desc,
+ &accattr, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0,
+ (caddr_t *)&dnetp->tx_desc, &len,
+ &dnetp->tx_desc_acchdl) != DDI_SUCCESS)
+ return (FAILURE);
+
+ if (ddi_dma_addr_bind_handle(dnetp->dma_handle_txdesc,
+ NULL, (caddr_t)dnetp->tx_desc,
+ sizeof (struct tx_desc_type) * dnetp->max_tx_desc,
+ DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_SLEEP,
+ NULL, &cookie, &ncookies) != DDI_DMA_MAPPED)
+ return (FAILURE);
+ dnetp->tx_desc_paddr = (caddr_t)(uintptr_t)
+ cookie.dmac_laddress;
+ bzero(dnetp->tx_desc, len);
+ dnetp->nxmit_desc = dnetp->max_tx_desc;
+
+ dnetp->tx_msgbufp =
+ kmem_zalloc(dnetp->max_tx_desc * sizeof (mblk_t **),
+ KM_SLEEP);
+ }
+
+ /* allocate receive descriptor array of size dnetp->max_rx_desc */
+ if (dnetp->rx_desc == NULL) {
+ int ndesc;
+
+ if (ddi_dma_mem_alloc(dnetp->dma_handle,
+ sizeof (struct rx_desc_type) * dnetp->max_rx_desc,
+ &accattr, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0,
+ (caddr_t *)&dnetp->rx_desc, &len,
+ &dnetp->rx_desc_acchdl) != DDI_SUCCESS)
+ return (FAILURE);
+
+ if (ddi_dma_addr_bind_handle(dnetp->dma_handle,
+ NULL, (caddr_t)dnetp->rx_desc,
+ sizeof (struct rx_desc_type) * dnetp->max_rx_desc,
+ DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_SLEEP,
+ NULL, &cookie, &ncookies) != DDI_DMA_MAPPED)
+ return (FAILURE);
+
+ dnetp->rx_desc_paddr = (caddr_t)(uintptr_t)
+ cookie.dmac_laddress;
+ bzero(dnetp->rx_desc, len);
+ dnetp->nrecv_desc = dnetp->max_rx_desc;
+
+ dnetp->rx_buf_vaddr =
+ kmem_zalloc(dnetp->max_rx_desc * sizeof (caddr_t),
+ KM_SLEEP);
+ dnetp->rx_buf_paddr =
+ kmem_zalloc(dnetp->max_rx_desc * sizeof (caddr_t),
+ KM_SLEEP);
+ /*
+ * Allocate or add to the pool of receive buffers. The pool
+ * is shared among all instances of dnet.
+ *
+ * XXX NEEDSWORK
+ *
+ * We arbitrarily allocate twice as many receive buffers as
+ * receive descriptors because we use the buffers for streams
+ * messages to pass the packets up the stream. We should
+ * instead have initialized constants reflecting
+ * MAX_RX_BUF_2104x and MAX_RX_BUF_2114x, and we should also
+ * probably have a total maximum for the free pool, so that we
+ * don't get out of hand when someone puts in an 8-port board.
+ * The maximum for the entire pool should be the total number
+ * of descriptors for all attached instances together, plus the
+ * total maximum for the free pool. This maximum would only be
+ * reached after some number of instances allocate buffers:
+ * each instance would add (max_rx_buf-max_rx_desc) to the free
+ * pool.
+ */
+ ndesc = dnetp->max_rx_desc - nrecv_desc_old;
+ if ((ndesc > 0) &&
+ (dnet_rbuf_init(dnetp->devinfo, ndesc * 2) != 0))
+ return (FAILURE);
+
+ for (i = 0; i < dnetp->max_rx_desc; i++) {
+ struct rbuf_list *rp;
+
+ rp = dnet_rbuf_alloc(dnetp->devinfo, 1);
+ if (rp == NULL)
+ return (FAILURE);
+ dnetp->rx_buf_vaddr[i] = rp->rbuf_vaddr;
+ }
+ }
+
+ return (SUCCESS);
+}
+/*
+ * free descriptors/buffers allocated for this device instance. This routine
+ * should only be called while the device is reset.
+ */
+static void
+dnet_free_bufs(gld_mac_info_t *macinfo)
+{
+ int i;
+ struct dnetinstance *dnetp = (struct dnetinstance *)
+ (macinfo->gldm_private);
+ /* free up any xmit descriptors/buffers */
+ if (dnetp->tx_desc != NULL) {
+ ddi_dma_mem_free(&dnetp->tx_desc_acchdl);
+ dnetp->tx_desc = NULL;
+ /* we use streams buffers for DMA in xmit process */
+ if (dnetp->tx_msgbufp != NULL) {
+ /* free up any streams message buffers unclaimed */
+ for (i = 0; i < dnetp->nxmit_desc; i++) {
+ if (dnetp->tx_msgbufp[i] != NULL) {
+ freemsg(dnetp->tx_msgbufp[i]);
+ }
+ }
+ kmem_free(dnetp->tx_msgbufp,
+ dnetp->nxmit_desc * sizeof (mblk_t **));
+ dnetp->tx_msgbufp = NULL;
+ }
+ dnetp->nxmit_desc = 0;
+ }
+
+ /* free up any receive descriptors/buffers */
+ if (dnetp->rx_desc != NULL) {
+ ddi_dma_mem_free(&dnetp->rx_desc_acchdl);
+ dnetp->rx_desc = NULL;
+ if (dnetp->rx_buf_vaddr != NULL) {
+ /* free up the attached rbufs if any */
+ for (i = 0; i < dnetp->nrecv_desc; i++) {
+ if (dnetp->rx_buf_vaddr[i])
+ dnet_rbuf_free((caddr_t)dnetp->rx_buf_vaddr[i]);
+ }
+ kmem_free(dnetp->rx_buf_vaddr,
+ dnetp->nrecv_desc * sizeof (caddr_t));
+ kmem_free(dnetp->rx_buf_paddr,
+ dnetp->nrecv_desc * sizeof (caddr_t));
+ dnetp->rx_buf_vaddr = NULL;
+ dnetp->rx_buf_paddr = NULL;
+ }
+ dnetp->nrecv_desc = 0;
+ }
+
+ if (dnetp->setup_buf_vaddr != NULL) {
+ ddi_dma_mem_free(&dnetp->setup_buf_acchdl);
+ dnetp->setup_buf_vaddr = NULL;
+ }
+
+ if (dnetp->dma_handle != NULL) {
+ (void) ddi_dma_unbind_handle(dnetp->dma_handle);
+ ddi_dma_free_handle(&dnetp->dma_handle);
+ dnetp->dma_handle = NULL;
+ }
+
+ if (dnetp->dma_handle_tx != NULL) {
+ (void) ddi_dma_unbind_handle(dnetp->dma_handle_tx);
+ ddi_dma_free_handle(&dnetp->dma_handle_tx);
+ dnetp->dma_handle_tx = NULL;
+ }
+
+ if (dnetp->dma_handle_txdesc != NULL) {
+ (void) ddi_dma_unbind_handle(dnetp->dma_handle_txdesc);
+ ddi_dma_free_handle(&dnetp->dma_handle_txdesc);
+ dnetp->dma_handle_txdesc = NULL;
+ }
+
+ if (dnetp->dma_handle_setbuf != NULL) {
+ (void) ddi_dma_unbind_handle(dnetp->dma_handle_setbuf);
+ ddi_dma_free_handle(&dnetp->dma_handle_setbuf);
+ dnetp->dma_handle_setbuf = NULL;
+ }
+
+}
+
+/*
+ * Initialize transmit and receive descriptors.
+ */
+static void
+dnet_init_txrx_bufs(gld_mac_info_t *macinfo)
+{
+ int i;
+ struct dnetinstance *dnetp = (struct dnetinstance *)
+ (macinfo->gldm_private);
+
+ /*
+ * Initilize all the Tx descriptors
+ */
+ for (i = 0; i < dnetp->nxmit_desc; i++) {
+ /*
+ * We may be resetting the device due to errors,
+ * so free up any streams message buffer unclaimed.
+ */
+ if (dnetp->tx_msgbufp[i] != NULL) {
+ freemsg(dnetp->tx_msgbufp[i]);
+ dnetp->tx_msgbufp[i] = NULL;
+ }
+ *(uint32_t *)&dnetp->tx_desc[i].desc0 = 0;
+ *(uint32_t *)&dnetp->tx_desc[i].desc1 = 0;
+ dnetp->tx_desc[i].buffer1 = (uint32_t)(0);
+ dnetp->tx_desc[i].buffer2 = (uint32_t)(0);
+ }
+ dnetp->tx_desc[i - 1].desc1.end_of_ring = 1;
+
+ /*
+ * Initialize the Rx descriptors
+ */
+ for (i = 0; i < dnetp->nrecv_desc; i++) {
+ uint32_t end_paddr;
+ *(uint32_t *)&dnetp->rx_desc[i].desc0 = 0;
+ *(uint32_t *)&dnetp->rx_desc[i].desc1 = 0;
+ dnetp->rx_desc[i].desc0.own = 1;
+ dnetp->rx_desc[i].desc1.buffer_size1 = rx_buf_size;
+ dnetp->rx_desc[i].buffer1 =
+ (uint32_t)dnetp->rx_buf_paddr[i];
+ dnetp->rx_desc[i].buffer2 = (uint32_t)(0);
+ end_paddr =
+ (uint32_t)dnetp->rx_buf_paddr[i]+rx_buf_size-1;
+
+ if ((dnetp->rx_desc[i].buffer1 & ~dnetp->pgmask) !=
+ (end_paddr & ~dnetp->pgmask)) {
+ /* discontiguous */
+ dnetp->rx_desc[i].buffer2 = end_paddr&~dnetp->pgmask;
+ dnetp->rx_desc[i].desc1.buffer_size2 =
+ (end_paddr & dnetp->pgmask) + 1;
+ dnetp->rx_desc[i].desc1.buffer_size1 =
+ rx_buf_size-dnetp->rx_desc[i].desc1.buffer_size2;
+ }
+ }
+ dnetp->rx_desc[i - 1].desc1.end_of_ring = 1;
+}
+
+static int
+alloc_descriptor(gld_mac_info_t *macinfo)
+{
+ int index;
+ struct dnetinstance *dnetp = /* Our private device info */
+ (struct dnetinstance *)macinfo->gldm_private;
+ struct tx_desc_type *ring = dnetp->tx_desc;
+
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+alloctop:
+ mutex_enter(&dnetp->txlock);
+ index = dnetp->tx_current_desc;
+
+ dnet_reclaim_Tx_desc(macinfo);
+
+ /* we do have free descriptors, right? */
+ if (dnetp->free_desc <= 0) {
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETRECV)
+ cmn_err(CE_NOTE, "dnet: Ring buffer is full");
+#endif
+ mutex_exit(&dnetp->txlock);
+ return (FAILURE);
+ }
+
+ /* sanity, make sure the next descriptor is free for use (should be) */
+ if (ring[index].desc0.own) {
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETRECV)
+ cmn_err(CE_WARN,
+ "dnet: next descriptor is not free for use");
+#endif
+ mutex_exit(&dnetp->txlock);
+ return (FAILURE);
+ }
+ if (dnetp->need_saddr) {
+ mutex_exit(&dnetp->txlock);
+ /* XXX function return value ignored */
+ /* XXX function return value ignored */
+ (void) dnet_set_addr(macinfo, dnetp->curr_macaddr);
+ goto alloctop;
+ }
+
+ *(uint32_t *)&ring[index].desc0 = 0; /* init descs */
+ *(uint32_t *)&ring[index].desc1 &= DNET_END_OF_RING;
+
+ /* hardware will own this descriptor when poll activated */
+ dnetp->free_desc--;
+
+ /* point to next free descriptor to be used */
+ dnetp->tx_current_desc = NextTXIndex(index);
+
+#ifdef DNET_NOISY
+ cmn_err(CE_WARN, "sfree 0x%x, transmitted 0x%x, tx_current 0x%x",
+ dnetp->free_desc, dnetp->transmitted_desc, dnetp->tx_current_desc);
+#endif
+ mutex_exit(&dnetp->txlock);
+ return (SUCCESS);
+}
+
+/*
+ * dnet_reclaim_Tx_desc() - called with txlock held.
+ */
+static void
+dnet_reclaim_Tx_desc(gld_mac_info_t *macinfo)
+{
+ struct dnetinstance *dnetp = (struct dnetinstance *)
+ (macinfo->gldm_private);
+ struct tx_desc_type *desc = dnetp->tx_desc;
+ int index;
+
+ ASSERT(MUTEX_HELD(&dnetp->txlock));
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_NOTE, "dnet_reclaim_Tx_desc(0x%p)",
+ (void *) macinfo);
+#endif
+
+ index = dnetp->transmitted_desc;
+ while (((dnetp->free_desc == 0) || (index != dnetp->tx_current_desc)) &&
+ !(desc[index].desc0.own)) {
+ /*
+ * Check for Tx Error that gets set
+ * in the last desc.
+ */
+ if (desc[index].desc1.setup_packet == 0 &&
+ desc[index].desc1.last_desc &&
+ desc[index].desc0.err_summary)
+ update_tx_stats(macinfo, index);
+
+ /*
+ * If we have used the streams message buffer for this
+ * descriptor then free up the message now.
+ */
+ if (dnetp->tx_msgbufp[index] != NULL) {
+ freemsg(dnetp->tx_msgbufp[index]);
+ dnetp->tx_msgbufp[index] = NULL;
+ }
+ dnetp->free_desc++;
+ index = (index+1) % dnetp->max_tx_desc;
+ }
+
+ dnetp->transmitted_desc = index;
+}
+
+/*
+ * Receive buffer allocation/freeing routines.
+ *
+ * There is a common pool of receive buffers shared by all dnet instances.
+ *
+ * XXX NEEDSWORK
+ *
+ * We arbitrarily allocate twice as many receive buffers as
+ * receive descriptors because we use the buffers for streams
+ * messages to pass the packets up the stream. We should
+ * instead have initialized constants reflecting
+ * MAX_RX_BUF_2104x and MAX_RX_BUF_2114x, and we should also
+ * probably have a total maximum for the free pool, so that we
+ * don't get out of hand when someone puts in an 8-port board.
+ * The maximum for the entire pool should be the total number
+ * of descriptors for all attached instances together, plus the
+ * total maximum for the free pool. This maximum would only be
+ * reached after some number of instances allocate buffers:
+ * each instance would add (max_rx_buf-max_rx_desc) to the free
+ * pool.
+ */
+
+static struct rbuf_list *rbuf_usedlist_head;
+static struct rbuf_list *rbuf_freelist_head;
+static struct rbuf_list *rbuf_usedlist_end; /* last buffer allocated */
+
+static int rbuf_freebufs; /* no. of free buffers in the pool */
+static int rbuf_pool_size; /* total no. of buffers in the pool */
+
+/* initialize/add 'nbufs' buffers to the rbuf pool */
+/* ARGSUSED */
+static int
+dnet_rbuf_init(dev_info_t *dip, int nbufs)
+{
+ int i;
+ struct rbuf_list *rp;
+ ddi_dma_cookie_t cookie;
+ uint_t ncookies;
+ size_t len;
+
+ mutex_enter(&dnet_rbuf_lock);
+
+ /* allocate buffers and add them to the pool */
+ for (i = 0; i < nbufs; i++) {
+ /* allocate rbuf_list element */
+ rp = kmem_zalloc(sizeof (struct rbuf_list), KM_SLEEP);
+ if (ddi_dma_alloc_handle(dip, &dma_attr_rb, DDI_DMA_SLEEP,
+ 0, &rp->rbuf_dmahdl) != DDI_SUCCESS)
+ goto fail_kfree;
+
+ /* allocate dma memory for the buffer */
+ if (ddi_dma_mem_alloc(rp->rbuf_dmahdl, rx_buf_size, &accattr,
+ DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0,
+ &rp->rbuf_vaddr, &len,
+ &rp->rbuf_acchdl) != DDI_SUCCESS)
+ goto fail_freehdl;
+
+ if (ddi_dma_addr_bind_handle(rp->rbuf_dmahdl, NULL,
+ rp->rbuf_vaddr, len, DDI_DMA_RDWR | DDI_DMA_STREAMING,
+ DDI_DMA_SLEEP, NULL, &cookie,
+ &ncookies) != DDI_DMA_MAPPED)
+ goto fail_free;
+
+ if (ncookies > 2)
+ goto fail_unbind;
+ if (ncookies == 1) {
+ rp->rbuf_endpaddr = (caddr_t)(uintptr_t)
+ (cookie.dmac_laddress + rx_buf_size - 1);
+ } else {
+ ddi_dma_nextcookie(rp->rbuf_dmahdl, &cookie);
+ rp->rbuf_endpaddr = (caddr_t)(uintptr_t)
+ (cookie.dmac_laddress + cookie.dmac_size - 1);
+ }
+ rp->rbuf_paddr = (caddr_t)(uintptr_t)cookie.dmac_laddress;
+
+ rp->rbuf_next = rbuf_freelist_head;
+ rbuf_freelist_head = rp;
+ rbuf_pool_size++;
+ rbuf_freebufs++;
+ }
+
+ mutex_exit(&dnet_rbuf_lock);
+ return (0);
+fail_unbind:
+ (void) ddi_dma_unbind_handle(rp->rbuf_dmahdl);
+fail_free:
+ ddi_dma_mem_free(&rp->rbuf_acchdl);
+fail_freehdl:
+ ddi_dma_free_handle(&rp->rbuf_dmahdl);
+fail_kfree:
+ kmem_free(rp, sizeof (struct rbuf_list));
+
+ mutex_exit(&dnet_rbuf_lock);
+ return (-1);
+}
+
+/*
+ * Try to free up all the rbufs in the pool. Returns 0 if it frees up all
+ * buffers. The buffers in the used list are considered busy so these
+ * buffers are not freed.
+ */
+static int
+dnet_rbuf_destroy()
+{
+ struct rbuf_list *rp, *next;
+
+ mutex_enter(&dnet_rbuf_lock);
+
+ for (rp = rbuf_freelist_head; rp; rp = next) {
+ next = rp->rbuf_next;
+ ddi_dma_mem_free(&rp->rbuf_acchdl);
+ (void) ddi_dma_unbind_handle(rp->rbuf_dmahdl);
+ kmem_free(rp, sizeof (struct rbuf_list));
+ rbuf_pool_size--;
+ rbuf_freebufs--;
+ }
+ rbuf_freelist_head = NULL;
+
+ if (rbuf_pool_size) { /* pool is still not empty */
+ mutex_exit(&dnet_rbuf_lock);
+ return (-1);
+ }
+ mutex_exit(&dnet_rbuf_lock);
+ return (0);
+}
+static struct rbuf_list *
+dnet_rbuf_alloc(dev_info_t *dip, int cansleep)
+{
+ struct rbuf_list *rp;
+ size_t len;
+ ddi_dma_cookie_t cookie;
+ uint_t ncookies;
+
+ mutex_enter(&dnet_rbuf_lock);
+
+ if (rbuf_freelist_head == NULL) {
+
+ if (!cansleep) {
+ mutex_exit(&dnet_rbuf_lock);
+ return (NULL);
+ }
+
+ /* allocate rbuf_list element */
+ rp = kmem_zalloc(sizeof (struct rbuf_list), KM_SLEEP);
+ if (ddi_dma_alloc_handle(dip, &dma_attr_rb, DDI_DMA_SLEEP,
+ 0, &rp->rbuf_dmahdl) != DDI_SUCCESS)
+ goto fail_kfree;
+
+ /* allocate dma memory for the buffer */
+ if (ddi_dma_mem_alloc(rp->rbuf_dmahdl, rx_buf_size, &accattr,
+ DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0,
+ &rp->rbuf_vaddr, &len,
+ &rp->rbuf_acchdl) != DDI_SUCCESS)
+ goto fail_freehdl;
+
+ if (ddi_dma_addr_bind_handle(rp->rbuf_dmahdl, NULL,
+ rp->rbuf_vaddr, len, DDI_DMA_RDWR | DDI_DMA_STREAMING,
+ DDI_DMA_SLEEP, NULL, &cookie,
+ &ncookies) != DDI_DMA_MAPPED)
+ goto fail_free;
+
+ if (ncookies > 2)
+ goto fail_unbind;
+ if (ncookies == 1) {
+ rp->rbuf_endpaddr = (caddr_t)(uintptr_t)
+ (cookie.dmac_laddress + rx_buf_size - 1);
+ } else {
+ ddi_dma_nextcookie(rp->rbuf_dmahdl, &cookie);
+ rp->rbuf_endpaddr = (caddr_t)(uintptr_t)
+ (cookie.dmac_laddress + cookie.dmac_size - 1);
+ }
+ rp->rbuf_paddr = (caddr_t)(uintptr_t)cookie.dmac_laddress;
+
+ rbuf_freelist_head = rp;
+ rbuf_pool_size++;
+ rbuf_freebufs++;
+ }
+
+ /* take the buffer from the head of the free list */
+ rp = rbuf_freelist_head;
+ rbuf_freelist_head = rbuf_freelist_head->rbuf_next;
+
+ /* update the used list; put the entry at the end */
+ if (rbuf_usedlist_head == NULL)
+ rbuf_usedlist_head = rp;
+ else
+ rbuf_usedlist_end->rbuf_next = rp;
+ rp->rbuf_next = NULL;
+ rbuf_usedlist_end = rp;
+ rbuf_freebufs--;
+
+ mutex_exit(&dnet_rbuf_lock);
+
+ return (rp);
+fail_unbind:
+ (void) ddi_dma_unbind_handle(rp->rbuf_dmahdl);
+fail_free:
+ ddi_dma_mem_free(&rp->rbuf_acchdl);
+fail_freehdl:
+ ddi_dma_free_handle(&rp->rbuf_dmahdl);
+fail_kfree:
+ kmem_free(rp, sizeof (struct rbuf_list));
+ mutex_exit(&dnet_rbuf_lock);
+ return (NULL);
+}
+
+static void
+dnet_rbuf_free(caddr_t vaddr)
+{
+ struct rbuf_list *rp, *prev;
+
+ ASSERT(vaddr != NULL);
+ ASSERT(rbuf_usedlist_head != NULL);
+
+ mutex_enter(&dnet_rbuf_lock);
+
+ /* find the entry in the used list */
+ for (prev = rp = rbuf_usedlist_head; rp; rp = rp->rbuf_next) {
+ if (rp->rbuf_vaddr == vaddr)
+ break;
+ prev = rp;
+ }
+
+ if (rp == NULL) {
+ cmn_err(CE_WARN, "DNET: rbuf_free: bad addr 0x%p",
+ (void *)vaddr);
+ mutex_exit(&dnet_rbuf_lock);
+ return;
+ }
+
+ /* update the used list and put the buffer back in the free list */
+ if (rbuf_usedlist_head != rp) {
+ prev->rbuf_next = rp->rbuf_next;
+ if (rbuf_usedlist_end == rp)
+ rbuf_usedlist_end = prev;
+ } else {
+ rbuf_usedlist_head = rp->rbuf_next;
+ if (rbuf_usedlist_end == rp)
+ rbuf_usedlist_end = NULL;
+ }
+ rp->rbuf_next = rbuf_freelist_head;
+ rbuf_freelist_head = rp;
+ rbuf_freebufs++;
+
+ mutex_exit(&dnet_rbuf_lock);
+}
+
+/*
+ * Free the receive buffer used in a stream's message block allocated
+ * thru desballoc().
+ */
+static void
+dnet_freemsg_buf(struct free_ptr *frp)
+{
+ dnet_rbuf_free((caddr_t)frp->buf); /* buffer goes back to the pool */
+ kmem_free(frp, sizeof (*frp)); /* free up the free_rtn structure */
+}
+
+/*
+ * ========== SROM Read Routines ==========
+ */
+
+/*
+ * The following code gets the SROM information, either by reading it
+ * from the device or, failing that, by reading a property.
+ */
+static int
+dnet_read_srom(dev_info_t *devinfo, int board_type, ddi_acc_handle_t io_handle,
+ int io_reg, uchar_t *vi, int maxlen)
+{
+ int all_ones, zerocheck, i;
+
+ /*
+ * Load SROM into vendor_info
+ */
+ if (board_type == DEVICE_ID_21040)
+ dnet_read21040addr(devinfo, io_handle, io_reg, vi, &maxlen);
+ else
+ /* 21041/21140 serial rom */
+ dnet_read21140srom(io_handle, io_reg, vi, maxlen);
+ /*
+ * If the dumpsrom property is present in the conf file, print
+ * the contents of the SROM to the console
+ */
+ if (ddi_getprop(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS,
+ "dumpsrom", 0))
+ dnet_dumpbin("SROM", vi, 1, maxlen);
+
+ for (zerocheck = i = 0, all_ones = 0xff; i < maxlen; i++) {
+ zerocheck |= vi[i];
+ all_ones &= vi[i];
+ }
+ if (zerocheck == 0 || all_ones == 0xff) {
+ return (get_alternative_srom_image(devinfo, vi, maxlen));
+ } else {
+#ifdef BUG_4010796
+ set_alternative_srom_image(devinfo, vi, maxlen);
+#endif
+ return (0); /* Primary */
+ }
+}
+
+/*
+ * The function reads the ethernet address of the 21040 adapter
+ */
+static void
+dnet_read21040addr(dev_info_t *dip, ddi_acc_handle_t io_handle, int io_reg,
+ uchar_t *addr, int *len)
+{
+ uint32_t val;
+ int i;
+
+ /* No point reading more than the ethernet address */
+ *len = ddi_getprop(DDI_DEV_T_ANY, dip,
+ DDI_PROP_DONTPASS, macoffset_propname, 0) + ETHERADDRL;
+
+ /* Reset ROM pointer */
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG), 0);
+ for (i = 0; i < *len; i++) {
+ do {
+ val = ddi_get32(io_handle,
+ REG32(io_reg, ETHER_ROM_REG));
+ } while (val & 0x80000000);
+ addr[i] = val & 0xFF;
+ }
+}
+
+#define drv_nsecwait(x) drv_usecwait(((x)+999)/1000) /* XXX */
+
+/*
+ * The function reads the SROM of the 21140 adapter
+ */
+static void
+dnet_read21140srom(ddi_acc_handle_t io_handle, int io_reg, uchar_t *addr,
+ int maxlen)
+{
+ uint32_t i, j;
+ uint32_t dout;
+ uint16_t word;
+ uint8_t rom_addr;
+ uint8_t bit;
+
+
+ rom_addr = 0;
+ for (i = 0; i < maxlen; i += 2) {
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM);
+ drv_nsecwait(30);
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP);
+ drv_nsecwait(50);
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP | SEL_CLK);
+ drv_nsecwait(250);
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP);
+ drv_nsecwait(100);
+
+ /* command */
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP | DATA_IN);
+ drv_nsecwait(150);
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP | DATA_IN | SEL_CLK);
+ drv_nsecwait(250);
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP | DATA_IN);
+ drv_nsecwait(250);
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP | DATA_IN | SEL_CLK);
+ drv_nsecwait(250);
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP | DATA_IN);
+ drv_nsecwait(100);
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP);
+ drv_nsecwait(150);
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP | SEL_CLK);
+ drv_nsecwait(250);
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP);
+ drv_nsecwait(100);
+
+ /* Address */
+ for (j = HIGH_ADDRESS_BIT; j >= 1; j >>= 1) {
+ bit = (rom_addr & j) ? DATA_IN : 0;
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP | bit);
+ drv_nsecwait(150);
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP | bit | SEL_CLK);
+ drv_nsecwait(250);
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP | bit);
+ drv_nsecwait(100);
+ }
+ drv_nsecwait(150);
+
+ /* Data */
+ word = 0;
+ for (j = 0x8000; j >= 1; j >>= 1) {
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP | SEL_CLK);
+ drv_nsecwait(100);
+ dout = ddi_get32(io_handle,
+ REG32(io_reg, ETHER_ROM_REG));
+ drv_nsecwait(150);
+ if (dout & DATA_OUT)
+ word |= j;
+ ddi_put32(io_handle,
+ REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM | SEL_CHIP);
+ drv_nsecwait(250);
+ }
+ addr[i] = (word & 0x0000FF);
+ addr[i + 1] = (word >> 8);
+ rom_addr++;
+ ddi_put32(io_handle, REG32(io_reg, ETHER_ROM_REG),
+ READ_OP | SEL_ROM);
+ drv_nsecwait(100);
+ }
+}
+
+
+/*
+ * XXX NEEDSWORK
+ *
+ * Some lame multiport cards have only one SROM, which can be accessed
+ * only from the "first" 21x4x chip, whichever that one is. If we can't
+ * get at our SROM, we look for its contents in a property instead, which
+ * we rely on the bootstrap to have properly set.
+ * #ifdef BUG_4010796
+ * We also have a hack to try to set it ourselves, when the "first" port
+ * attaches, if it has not already been properly set. However, this method
+ * is not reliable, since it makes the unwarrented assumption that the
+ * "first" port will attach first.
+ * #endif
+ */
+
+static int
+get_alternative_srom_image(dev_info_t *devinfo, uchar_t *vi, int len)
+{
+ int l = len;
+
+ if (ddi_getlongprop_buf(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS,
+ "DNET_SROM", (caddr_t)vi, &len) != DDI_PROP_SUCCESS &&
+ (len = l) && ddi_getlongprop_buf(DDI_DEV_T_ANY,
+ ddi_get_parent(devinfo), DDI_PROP_DONTPASS, "DNET_SROM",
+ (caddr_t)vi, &len) != DDI_PROP_SUCCESS)
+ return (-1); /* Can't find it! */
+
+ /*
+ * The return value from this routine specifies which port number
+ * we are. The primary port is denoted port 0. On a QUAD card we
+ * should return 1, 2, and 3 from this routine. The return value
+ * is used to modify the ethernet address from the SROM data.
+ */
+
+#ifdef BUG_4010796
+ {
+ /*
+ * For the present, we remember the device number of our primary
+ * sibling and hope we and our other siblings are consecutively
+ * numbered up from there. In the future perhaps the bootstrap
+ * will pass us the necessary information telling us which physical
+ * port we really are.
+ */
+ pci_regspec_t *assignp;
+ int assign_len;
+ int devnum;
+ int primary_devnum;
+
+ primary_devnum = ddi_getprop(DDI_DEV_T_ANY, devinfo, 0,
+ "DNET_DEVNUM", -1);
+ if (primary_devnum == -1)
+ return (1); /* XXX NEEDSWORK -- We have no better idea */
+
+ if ((ddi_getlongprop(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS,
+ "assigned-addresses", (caddr_t)&assignp,
+ &assign_len)) != DDI_PROP_SUCCESS)
+ return (1); /* XXX NEEDSWORK -- We have no better idea */
+
+ devnum = PCI_REG_DEV_G(assignp->pci_phys_hi);
+ kmem_free(assignp, assign_len);
+ return (devnum - primary_devnum);
+ }
+#else
+ return (1); /* XXX NEEDSWORK -- We have no better idea */
+#endif
+}
+
+
+#ifdef BUG_4010796
+static void
+set_alternative_srom_image(dev_info_t *devinfo, uchar_t *vi, int len)
+{
+ int proplen;
+ pci_regspec_t *assignp;
+ int assign_len;
+ int devnum;
+
+ if (ddi_getproplen(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS,
+ "DNET_SROM", &proplen) == DDI_PROP_SUCCESS ||
+ ddi_getproplen(DDI_DEV_T_ANY, ddi_get_parent(devinfo),
+ DDI_PROP_DONTPASS, "DNET_SROM", &proplen) == DDI_PROP_SUCCESS)
+ return; /* Already done! */
+
+ /* function return value ignored */
+ (void) ddi_prop_update_byte_array(DDI_DEV_T_NONE,
+ ddi_get_parent(devinfo), "DNET_SROM", (uchar_t *)vi, len);
+ (void) ddi_prop_update_string(DDI_DEV_T_NONE, devinfo,
+ "DNET_HACK", "hack");
+
+ if ((ddi_getlongprop(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS,
+ "assigned-addresses", (caddr_t)&assignp,
+ &assign_len)) == DDI_PROP_SUCCESS) {
+ devnum = PCI_REG_DEV_G(assignp->pci_phys_hi);
+ kmem_free(assignp, assign_len);
+ /* function return value ignored */
+ (void) ddi_prop_update_int(DDI_DEV_T_NONE,
+ ddi_get_parent(devinfo), "DNET_DEVNUM", devnum);
+ }
+}
+#endif
+
+/*
+ * ========== SROM Parsing Routines ==========
+ */
+
+static int
+check_srom_valid(uchar_t *vi)
+{
+ int word, bit;
+ uint8_t crc;
+ uint16_t *wvi; /* word16 pointer to vendor info */
+ uint16_t bitval;
+
+ /* verify that the number of controllers on the card is within range */
+ if (vi[SROM_ADAPTER_CNT] < 1 || vi[SROM_ADAPTER_CNT] > MAX_ADAPTERS)
+ return (0);
+
+ /*
+ * version 1 and 3 of this card did not check the id block CRC value
+ * and this can't be changed without retesting every supported card
+ *
+ * however version 4 of the SROM can have this test applied
+ * without fear of breaking something that used to work.
+ * the CRC algorithm is taken from the Intel document
+ * "21x4 Serial ROM Format"
+ * version 4.09
+ * 3-Mar-1999
+ */
+
+ switch (vi[SROM_VERSION]) {
+ case 1:
+ /* fallthru */
+ case 3:
+ return (
+ vi[SROM_MBZ] == 0 && /* must be zero */
+ vi[SROM_MBZ2] == 0 && /* must be zero */
+ vi[SROM_MBZ3] == 0); /* must be zero */
+
+ case 4:
+ wvi = (uint16_t *)vi;
+ crc = 0xff;
+ for (word = 0; word < 9; word++)
+ for (bit = 15; bit >= 0; bit--) {
+ if (word == 8 && bit == 7)
+ return (crc == vi[16]);
+ bitval = ((wvi[word] >> bit) & 1) ^ ((crc >> 7) & 1);
+ crc <<= 1;
+ if (bitval == 1) {
+ crc ^= 7;
+ }
+ }
+
+ default:
+ return (0);
+ }
+}
+
+/*
+ * ========== Active Media Determination Routines ==========
+ */
+
+/* This routine is also called for V3 Compact and extended type 0 SROMs */
+static int
+is_fdmedia(int media)
+{
+ if (media == MEDIA_TP_FD || media == MEDIA_SYM_SCR_FD)
+ return (1);
+ else
+ return (0);
+}
+
+/*
+ * "Linkset" is used to merge media that use the same link test check. So,
+ * if the TP link is added to the linkset, so is the TP Full duplex link.
+ * Used to avoid checking the same link status twice.
+ */
+static void
+linkset_add(uint32_t *set, int media)
+{
+ if (media == MEDIA_TP_FD || media == MEDIA_TP)
+ *set |= (1UL<<MEDIA_TP_FD) | (1UL<<MEDIA_TP);
+ else if (media == MEDIA_SYM_SCR_FD || media == MEDIA_SYM_SCR)
+ *set |= (1UL<<MEDIA_SYM_SCR_FD) | (1UL<<MEDIA_SYM_SCR);
+ else *set |= 1UL<<media;
+}
+static int
+linkset_isset(uint32_t linkset, int media)
+{
+ return (((1UL<<media) & linkset) ? 1:0);
+}
+
+/*
+ * The following code detects which Media is connected for 21041/21140
+ * Expect to change this code to support new 21140 variants.
+ * find_active_media() - called with intrlock held.
+ */
+static void
+find_active_media(gld_mac_info_t *macinfo)
+{
+ int i;
+ media_block_t *block;
+ media_block_t *best_allowed = NULL;
+ media_block_t *hd_found = NULL;
+ media_block_t *fd_found = NULL;
+ struct dnetinstance *dnetp = (struct dnetinstance *)
+ (macinfo->gldm_private);
+ LEAF_FORMAT *leaf = &dnetp->sr.leaf[dnetp->leaf];
+ uint32_t checked = 0, links_up = 0;
+
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+#ifdef SROMDEBUG
+ cmn_err(CE_NOTE, "find_active_media 0x%x,0x%x", sr->version, macinfo);
+#endif
+ dnetp->selected_media_block = leaf->default_block;
+
+ if (dnetp->phyaddr != -1) {
+ dnetp->selected_media_block = leaf->mii_block;
+ setup_block(macinfo);
+
+ if (ddi_getprop(DDI_DEV_T_ANY, dnetp->devinfo,
+ DDI_PROP_DONTPASS, "portmon", 1)) {
+ /* XXX return value ignored */
+ (void) mii_start_portmon(dnetp->mii, dnet_mii_link_cb,
+ &dnetp->intrlock);
+ /*
+ * If the port monitor detects the link is already
+ * up, there is no point going through the rest of the
+ * link sense
+ */
+ if (dnetp->mii_up) {
+ return;
+ }
+ }
+ }
+
+ /*
+ * Media is searched for in order of Precedence. This DEC SROM spec
+ * tells us that the first media entry in the SROM is the lowest
+ * precedence and should be checked last. This is why we go to the last
+ * Media block and work back to the beginning.
+ *
+ * However, some older SROMs (Cogent EM110's etc.) have this the wrong
+ * way around. As a result, following the SROM spec would result in a
+ * 10 link being chosen over a 100 link if both media are available.
+ * So we continue trying the media until we have at least tried the
+ * DEFAULT media.
+ */
+
+ /* Search for an active medium, and select it */
+ for (block = leaf->block + leaf->block_count - 1;
+ block >= leaf->block; block--) {
+ int media = block->media_code;
+
+ /* User settings disallow selection of this block */
+ if (dnetp->disallowed_media & (1UL<<media))
+ continue;
+
+ /* We may not be able to pick the default */
+ if (best_allowed == NULL || block == leaf->default_block)
+ best_allowed = block;
+#ifdef DEBUG
+ if (dnetdebug & DNETSENSE)
+ cmn_err(CE_NOTE, "Testing %s medium (block type %d)",
+ media_str[media], block->type);
+#endif
+
+ dnetp->selected_media_block = block;
+ switch (block->type) {
+
+ case 2: /* SIA Media block: Best we can do is send a packet */
+ setup_block(macinfo);
+ if (send_test_packet(macinfo)) {
+ if (!is_fdmedia(media))
+ return;
+ if (!fd_found)
+ fd_found = block;
+ }
+ break;
+
+ /* SYM/SCR or TP block: Use the link-sense bits */
+ case 0:
+ if (!linkset_isset(checked, media)) {
+ linkset_add(&checked, media);
+ if (((media == MEDIA_BNC ||
+ media == MEDIA_AUI) &&
+ send_test_packet(macinfo)) ||
+ dnet_link_sense(macinfo))
+ linkset_add(&links_up, media);
+ }
+
+ if (linkset_isset(links_up, media)) {
+ /*
+ * Half Duplex is *always* the favoured media.
+ * Full Duplex can be set and forced via the
+ * conf file.
+ */
+ if (!is_fdmedia(media) &&
+ dnetp->selected_media_block ==
+ leaf->default_block) {
+ /*
+ * Cogent cards have the media in
+ * opposite order to the spec.,
+ * this code forces the media test to
+ * keep going until the default media
+ * is tested.
+ *
+ * In Cogent case, 10, 10FD, 100FD, 100
+ * 100 is the default but 10 could have
+ * been detected and would have been
+ * chosen but now we force it through to
+ * 100.
+ */
+ setup_block(macinfo);
+ return;
+ } else if (!is_fdmedia(media)) {
+ /*
+ * This allows all the others to work
+ * properly by remembering the media
+ * that works and not defaulting to
+ * a FD link.
+ */
+ if (hd_found == NULL)
+ hd_found = block;
+ } else if (fd_found == NULL) {
+ /*
+ * No media have already been found
+ * so far, this is FD, it works so
+ * remember it and if no others are
+ * detected, use it.
+ */
+ fd_found = block;
+ }
+ }
+ break;
+
+ /*
+ * MII block: May take up to a second or so to settle if
+ * setup causes a PHY reset
+ */
+ case 1: case 3:
+ setup_block(macinfo);
+ for (i = 0; ; i++) {
+ if (mii_linkup(dnetp->mii, dnetp->phyaddr)) {
+ /* XXX function return value ignored */
+ (void) mii_getspeed(dnetp->mii,
+ dnetp->phyaddr,
+ &dnetp->mii_speed,
+ &dnetp->mii_duplex);
+ dnetp->mii_up = 1;
+ leaf->mii_block = block;
+ return;
+ }
+ if (i == 10)
+ break;
+ delay(drv_usectohz(150000));
+ }
+ dnetp->mii_up = 0;
+ break;
+ }
+ } /* for loop */
+ if (hd_found) {
+ dnetp->selected_media_block = hd_found;
+ } else if (fd_found) {
+ dnetp->selected_media_block = fd_found;
+ } else {
+ if (best_allowed == NULL)
+ best_allowed = leaf->default_block;
+ dnetp->selected_media_block = best_allowed;
+ cmn_err(CE_WARN, "!dnet: Default media selected\n");
+ }
+ setup_block(macinfo);
+}
+
+/*
+ * Do anything neccessary to select the selected_media_block.
+ * setup_block() - called with intrlock held.
+ */
+static void
+setup_block(gld_mac_info_t *macinfo)
+{
+ dnet_reset_board(macinfo);
+ dnet_init_board(macinfo);
+ /* XXX function return value ignored */
+ (void) dnet_start(macinfo);
+}
+
+/* dnet_link_sense() - called with intrlock held */
+static int
+dnet_link_sense(gld_mac_info_t *macinfo)
+{
+ /*
+ * This routine makes use of the command word from the srom config.
+ * Details of the auto-sensing information contained in this can
+ * be found in the "Digital Semiconductor 21X4 Serial ROM Format v3.03"
+ * spec. Section 4.3.2.1, and 4.5.2.1.3
+ */
+ struct dnetinstance *dnetp = (struct dnetinstance *)
+ (macinfo->gldm_private);
+ media_block_t *block = dnetp->selected_media_block;
+ uint32_t link, status, mask, polarity;
+ int settletime, stabletime, waittime, upsamples;
+ int delay_100, delay_10;
+
+
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+ /* Don't autosense if the medium does not support it */
+ if (block->command & (1 << 15)) {
+ /* This should be the default block */
+ if (block->command & (1UL<<14))
+ dnetp->sr.leaf[dnetp->leaf].default_block = block;
+ return (0);
+ }
+
+ delay_100 = ddi_getprop(DDI_DEV_T_ANY, dnetp->devinfo,
+ DDI_PROP_DONTPASS, "autosense-delay-100", 2000);
+
+ delay_10 = ddi_getprop(DDI_DEV_T_ANY, dnetp->devinfo,
+ DDI_PROP_DONTPASS, "autosense-delay-10", 400);
+
+ /*
+ * Scrambler may need to be disabled for link sensing
+ * to work
+ */
+ dnetp->disable_scrambler = 1;
+ setup_block(macinfo);
+ dnetp->disable_scrambler = 0;
+
+ if (block->media_code == MEDIA_TP || block->media_code == MEDIA_TP_FD)
+ settletime = delay_10;
+ else
+ settletime = delay_100;
+ stabletime = settletime / 4;
+
+ mask = 1 << ((block->command & CMD_MEDIABIT_MASK) >> 1);
+ polarity = block->command & CMD_POL ? 0xffffffff : 0;
+
+ for (waittime = 0, upsamples = 0;
+ waittime <= settletime + stabletime && upsamples < 8;
+ waittime += stabletime/8) {
+ delay(drv_usectohz(stabletime*1000 / 8));
+ status = read_gpr(dnetp);
+ link = (status^polarity) & mask;
+ if (link)
+ upsamples++;
+ else
+ upsamples = 0;
+ }
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETSENSE)
+ cmn_err(CE_NOTE, "%s upsamples:%d stat:%x polarity:%x "
+ "mask:%x link:%x",
+ upsamples == 8 ? "UP":"DOWN",
+ upsamples, status, polarity, mask, link);
+#endif
+ if (upsamples == 8)
+ return (1);
+ return (0);
+}
+
+static int
+send_test_packet(gld_mac_info_t *macinfo)
+{
+ int packet_delay;
+ struct dnetinstance *dnetp = (struct dnetinstance *)
+ (macinfo->gldm_private);
+ struct tx_desc_type *desc;
+ int bufindex;
+ int media_code = dnetp->selected_media_block->media_code;
+ uint32_t del;
+
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+ /*
+ * For a successful test packet, the card must have settled into
+ * its current setting. Almost all cards we've tested manage to
+ * do this with all media within 50ms. However, the SMC 8432
+ * requires 300ms to settle into BNC mode. We now only do this
+ * from attach, and we do sleeping delay() instead of drv_usecwait()
+ * so we hope this .2 second delay won't cause too much suffering.
+ * ALSO: with an autonegotiating hub, an aditional 1 second delay is
+ * required. This is done if the media type is TP
+ */
+ if (media_code == MEDIA_TP || media_code == MEDIA_TP_FD) {
+ packet_delay = ddi_getprop(DDI_DEV_T_ANY, dnetp->devinfo,
+ DDI_PROP_DONTPASS, "test_packet_delay_tp", 1300000);
+ } else {
+ packet_delay = ddi_getprop(DDI_DEV_T_ANY, dnetp->devinfo,
+ DDI_PROP_DONTPASS, "test_packet_delay", 300000);
+ }
+ delay(drv_usectohz(packet_delay));
+
+ desc = dnetp->tx_desc;
+
+ bufindex = dnetp->tx_current_desc;
+ if (alloc_descriptor(macinfo) == FAILURE) {
+ cmn_err(CE_WARN, "DNET: send_test_packet: alloc_descriptor"
+ "failed");
+ return (0);
+ }
+
+ /*
+ * use setup buffer as the buffer for the test packet
+ * instead of allocating one.
+ */
+
+ ASSERT(dnetp->setup_buf_vaddr != NULL);
+ /* Put something decent in dest address so we don't annoy other cards */
+ BCOPY((caddr_t)dnetp->curr_macaddr,
+ (caddr_t)dnetp->setup_buf_vaddr, ETHERADDRL);
+ BCOPY((caddr_t)dnetp->curr_macaddr,
+ (caddr_t)dnetp->setup_buf_vaddr+ETHERADDRL, ETHERADDRL);
+
+ desc[bufindex].buffer1 = (uint32_t)(dnetp->setup_buf_paddr);
+ desc[bufindex].desc1.buffer_size1 = SETUPBUF_SIZE;
+ desc[bufindex].buffer2 = (uint32_t)(0);
+ desc[bufindex].desc1.first_desc = 1;
+ desc[bufindex].desc1.last_desc = 1;
+ desc[bufindex].desc1.int_on_comp = 1;
+ desc[bufindex].desc0.own = 1;
+
+ ddi_put8(dnetp->io_handle, REG8(dnetp->io_reg, TX_POLL_REG),
+ TX_POLL_DEMAND);
+
+ /*
+ * Give enough time for the chip to transmit the packet
+ */
+#if 1
+ del = 1000;
+ while (desc[bufindex].desc0.own && --del)
+ drv_usecwait(10); /* quickly wait up to 10ms */
+ if (desc[bufindex].desc0.own)
+ delay(drv_usectohz(200000)); /* nicely wait a longer time */
+#else
+ del = 0x10000;
+ while (desc[bufindex].desc0.own && --del)
+ drv_usecwait(10);
+#endif
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETSENSE)
+ cmn_err(CE_NOTE, "desc0 bits = %u, %u, %u, %u, %u, %u",
+ desc[bufindex].desc0.own,
+ desc[bufindex].desc0.err_summary,
+ desc[bufindex].desc0.carrier_loss,
+ desc[bufindex].desc0.no_carrier,
+ desc[bufindex].desc0.late_collision,
+ desc[bufindex].desc0.link_fail);
+#endif
+ if (desc[bufindex].desc0.own) /* it shouldn't take this long, error */
+ return (0);
+
+ return (!desc[bufindex].desc0.err_summary);
+}
+
+/* enable_interrupts - called with intrlock held */
+static void
+enable_interrupts(struct dnetinstance *dnetp, int enable_xmit)
+{
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+ /* Don't enable interrupts if they have been forced off */
+ if (dnetp->interrupts_disabled)
+ return;
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, INT_MASK_REG),
+ NORMAL_INTR_MASK | ABNORMAL_INTR_MASK | TX_UNDERFLOW_MASK |
+ (enable_xmit ? TX_INTERRUPT_MASK : 0) |
+ (dnetp->timer.cb ? GPTIMER_INTR : 0) |
+ RX_INTERRUPT_MASK | SYSTEM_ERROR_MASK | TX_JABBER_MASK);
+
+}
+
+/*
+ * Some older multiport cards are non-PCI compliant in their interrupt routing.
+ * Second and subsequent devices are incorrectly configured by the BIOS
+ * (either in their ILINE configuration or the MP Configuration Table for PC+MP
+ * systems).
+ * The hack stops gldregister() registering the interrupt routine for the
+ * FIRST device on the adapter, and registers its own. It builds up a table
+ * of macinfo structures for each device, and the new interrupt routine
+ * calls gldintr for each of them.
+ * Known cards that suffer from this problem are:
+ * All Cogent multiport cards;
+ * Znyx 314;
+ * Znyx 315.
+ *
+ * XXX NEEDSWORK -- see comments above get_alternative_srom_image(). This
+ * hack relies on the fact that the offending cards will have only one SROM.
+ * It uses this fact to identify devices that are on the same multiport
+ * adapter, as opposed to multiple devices from the same vendor (as
+ * indicated by "secondary")
+ */
+static int
+dnet_hack_interrupts(gld_mac_info_t *macinfo, int secondary)
+{
+ int i;
+ struct hackintr_inf *hackintr_inf;
+ struct dnetinstance *dnetp =
+ (struct dnetinstance *)macinfo->gldm_private;
+ dev_info_t *devinfo = dnetp->devinfo;
+ uint32_t oui = 0; /* Organizationally Unique ID */
+
+ if (ddi_getprop(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS,
+ "no_INTA_workaround", 0) != 0)
+ return (0);
+
+ for (i = 0; i < 3; i++)
+ oui = (oui << 8) | dnetp->vendor_addr[i];
+
+ /* Check wheather or not we need to implement the hack */
+
+ switch (oui) {
+ case ZNYX_ETHER:
+ /* Znyx multiport 21040 cards <<==>> ZX314 or ZX315 */
+ if (dnetp->board_type != DEVICE_ID_21040)
+ return (0);
+ break;
+
+ case COGENT_ETHER:
+ /* All known Cogent multiport cards */
+ break;
+
+ case ADAPTEC_ETHER:
+ /* Adaptec multiport cards */
+ break;
+
+ default:
+ /* Other cards work correctly */
+ return (0);
+ }
+
+ /* card is (probably) non-PCI compliant in its interrupt routing */
+
+
+ if (!secondary) {
+
+ /*
+ * If we have already registered a hacked interrupt, and
+ * this is also a 'primary' adapter, then this is NOT part of
+ * a multiport card, but a second card on the same PCI bus.
+ * BUGID: 4057747
+ */
+ if (ddi_getprop(DDI_DEV_T_ANY, ddi_get_parent(devinfo),
+ DDI_PROP_DONTPASS, hackintr_propname, 0) != 0)
+ return (0);
+ /* ... Primary not part of a multiport device */
+
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_NOTE, "dnet: Implementing hardware "
+ "interrupt flaw workaround");
+#endif
+ dnetp->hackintr_inf = hackintr_inf =
+ kmem_zalloc(sizeof (struct hackintr_inf), KM_SLEEP);
+ if (hackintr_inf == NULL)
+ goto fail;
+
+ hackintr_inf->macinfos[0] = macinfo;
+ hackintr_inf->devinfo = devinfo;
+
+ /*
+ * Add a property to allow successive attaches to find the
+ * table
+ */
+
+ if (ddi_prop_update_byte_array(DDI_DEV_T_NONE,
+ ddi_get_parent(devinfo), hackintr_propname,
+ (uchar_t *)&dnetp->hackintr_inf,
+ sizeof (void *)) != DDI_PROP_SUCCESS)
+ goto fail;
+
+
+ /* Register our hacked interrupt routine */
+ if (ddi_add_intr(devinfo, 0, &macinfo->gldm_cookie, NULL,
+ (uint_t (*)(char *))dnet_hack_intr,
+ (caddr_t)hackintr_inf) != DDI_SUCCESS) {
+ /* XXX function return value ignored */
+ (void) ddi_prop_remove(DDI_DEV_T_NONE,
+ ddi_get_parent(devinfo),
+ hackintr_propname);
+ goto fail;
+ }
+
+ /*
+ * Mutex required to ensure interrupt routine has completed
+ * when detaching devices
+ */
+ mutex_init(&hackintr_inf->lock, NULL, MUTEX_DRIVER,
+ macinfo->gldm_cookie);
+
+ /* Stop GLD registering an interrupt */
+ return (-1);
+ } else {
+
+ /* Add the macinfo for this secondary device to the table */
+
+ hackintr_inf = (struct hackintr_inf *)(uintptr_t)
+ ddi_getprop(DDI_DEV_T_ANY, ddi_get_parent(devinfo),
+ DDI_PROP_DONTPASS, hackintr_propname, 0);
+
+ if (hackintr_inf == NULL)
+ goto fail;
+
+ /* Find an empty slot */
+ for (i = 0; i < MAX_INST; i++)
+ if (hackintr_inf->macinfos[i] == NULL)
+ break;
+
+ /* More than 8 ports on adapter ?! */
+ if (i == MAX_INST)
+ goto fail;
+
+ hackintr_inf->macinfos[i] = macinfo;
+
+ /*
+ * Allow GLD to register a handler for this
+ * device. If the card is actually broken, as we suspect, this
+ * handler will never get called. However, by registering the
+ * interrupt handler, we can copy gracefully with new multiport
+ * Cogent cards that decide to fix the hardware problem
+ */
+ return (0);
+ }
+
+fail:
+ cmn_err(CE_WARN, "dnet: Could not work around hardware interrupt"
+ " routing problem");
+ return (0);
+}
+
+/*
+ * Call gld_intr for all adapters on a multiport card
+ */
+
+static uint_t
+dnet_hack_intr(struct hackintr_inf *hackintr_inf)
+{
+ int i;
+ int claimed = DDI_INTR_UNCLAIMED;
+
+ /* Stop detaches while processing interrupts */
+ mutex_enter(&hackintr_inf->lock);
+
+ for (i = 0; i < MAX_INST; i++) {
+ if (hackintr_inf->macinfos[i] &&
+ gld_intr(hackintr_inf->macinfos[i]) == DDI_INTR_CLAIMED)
+ claimed = DDI_INTR_CLAIMED;
+ }
+ mutex_exit(&hackintr_inf->lock);
+ return (claimed);
+}
+
+/*
+ * This removes the detaching device from the table procesed by the hacked
+ * interrupt routine. Because the interrupts from all devices come in to the
+ * same interrupt handler, ALL devices must stop interrupting once the
+ * primary device detaches. This isn't a problem at present, because all
+ * instances of a device are detached when the driver is unloaded.
+ */
+static int
+dnet_detach_hacked_interrupt(dev_info_t *devinfo)
+{
+ int i;
+ struct hackintr_inf *hackintr_inf;
+ gld_mac_info_t *mac, *macinfo = ddi_get_driver_private(devinfo);
+
+ hackintr_inf = (struct hackintr_inf *)(uintptr_t)
+ ddi_getprop(DDI_DEV_T_ANY, ddi_get_parent(devinfo),
+ DDI_PROP_DONTPASS, hackintr_propname, 0);
+
+ /*
+ * No hackintr_inf implies hack was not required or the primary has
+ * detached, and our interrupts are already disabled
+ */
+ if (!hackintr_inf) {
+ /* remove the interrupt for the non-hacked case */
+ ddi_remove_intr(devinfo, 0, macinfo->gldm_cookie);
+ return (DDI_SUCCESS);
+ }
+
+ /* Remove this device from the handled table */
+ mutex_enter(&hackintr_inf->lock);
+ for (i = 0; i < MAX_INST; i++) {
+ if (hackintr_inf->macinfos[i] == macinfo) {
+ hackintr_inf->macinfos[i] = NULL;
+ break;
+ }
+ }
+
+ mutex_exit(&hackintr_inf->lock);
+
+ /* Not the primary card, we are done */
+ if (devinfo != hackintr_inf->devinfo)
+ return (DDI_SUCCESS);
+
+ /*
+ * This is the primary card. All remaining adapters on this device
+ * must have their interrupts disabled before we remove the handler
+ */
+ for (i = 0; i < MAX_INST; i++) {
+ if ((mac = hackintr_inf->macinfos[i]) != NULL) {
+ struct dnetinstance *altdnetp =
+ (struct dnetinstance *)mac->gldm_private;
+ altdnetp->interrupts_disabled = 1;
+ ddi_put32(altdnetp->io_handle,
+ REG32(altdnetp->io_reg, INT_MASK_REG), 0);
+ }
+ }
+
+ /* It should now be safe to remove the interrupt handler */
+
+ ddi_remove_intr(devinfo, 0, macinfo->gldm_cookie);
+ mutex_destroy(&hackintr_inf->lock);
+ /* XXX function return value ignored */
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, ddi_get_parent(devinfo),
+ hackintr_propname);
+ kmem_free(hackintr_inf, sizeof (struct hackintr_inf));
+ return (DDI_SUCCESS);
+}
+
+/*
+ * ========== PHY MII Routines ==========
+ */
+
+/* do_phy() - called with intrlock held */
+static void
+do_phy(gld_mac_info_t *macinfo)
+{
+ dev_info_t *dip;
+ struct dnetinstance
+ *dnetp = (struct dnetinstance *)macinfo->gldm_private;
+ LEAF_FORMAT *leaf = dnetp->sr.leaf + dnetp->leaf;
+ media_block_t *block;
+ int phy;
+
+ dip = dnetp->devinfo;
+
+ /*
+ * Find and configure the PHY media block. If NO PHY blocks are
+ * found on the SROM, but a PHY device is present, we assume the card
+ * is a legacy device, and that there is ONLY a PHY interface on the
+ * card (ie, no BNC or AUI, and 10BaseT is implemented by the PHY
+ */
+
+ for (block = leaf->block + leaf->block_count -1;
+ block >= leaf->block; block --) {
+ if (block->type == 3 || block->type == 1) {
+ leaf->mii_block = block;
+ break;
+ }
+ }
+
+ /*
+ * If no MII block, select default, and hope this configuration will
+ * allow the phy to be read/written if it is present
+ */
+ dnetp->selected_media_block = leaf->mii_block ?
+ leaf->mii_block : leaf->default_block;
+
+ setup_block(macinfo);
+ /* XXX function return value ignored */
+ (void) mii_create(dip, dnet_mii_write, dnet_mii_read, &dnetp->mii);
+
+ /*
+ * We try PHY 0 LAST because it is less likely to be connected
+ */
+ for (phy = 1; phy < 33; phy++)
+ if (mii_probe_phy(dnetp->mii, phy % 32) == MII_SUCCESS &&
+ mii_init_phy(dnetp->mii, phy % 32) == MII_SUCCESS) {
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETSENSE)
+ cmn_err(CE_NOTE, "dnet: "
+ "PHY at address %d", phy % 32);
+#endif
+ dnetp->phyaddr = phy % 32;
+ if (!leaf->mii_block) {
+ /* Legacy card, change the leaf node */
+ set_leaf(&dnetp->sr, &leaf_phylegacy);
+ }
+ return;
+ }
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETSENSE)
+ cmn_err(CE_NOTE, "dnet: No PHY found");
+#endif
+}
+
+static ushort_t
+dnet_mii_read(dev_info_t *dip, int phy_addr, int reg_num)
+{
+ gld_mac_info_t *macinfo;
+ struct dnetinstance *dnetp;
+
+ uint32_t command_word;
+ uint32_t tmp;
+ uint32_t data = 0;
+ int i;
+ int bits_in_ushort = ((sizeof (ushort_t))*8);
+ int turned_around = 0;
+
+ macinfo = ddi_get_driver_private(dip);
+ dnetp = (struct dnetinstance *)macinfo->gldm_private;
+
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+ /* Write Preamble */
+ write_mii(dnetp, MII_PRE, 2*bits_in_ushort);
+
+ /* Prepare command word */
+ command_word = (uint32_t)phy_addr << MII_PHY_ADDR_ALIGN;
+ command_word |= (uint32_t)reg_num << MII_REG_ADDR_ALIGN;
+ command_word |= MII_READ_FRAME;
+
+ write_mii(dnetp, command_word, bits_in_ushort-2);
+
+ mii_tristate(dnetp);
+
+ /* Check that the PHY generated a zero bit the 2nd clock */
+ tmp = ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, ETHER_ROM_REG));
+
+ turned_around = (tmp & MII_DATA_IN) ? 0 : 1;
+
+ /* read data WORD */
+ for (i = 0; i < bits_in_ushort; i++) {
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, ETHER_ROM_REG), MII_READ);
+ drv_usecwait(MII_DELAY);
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, ETHER_ROM_REG), MII_READ | MII_CLOCK);
+ drv_usecwait(MII_DELAY);
+ tmp = ddi_get32(dnetp->io_handle,
+ REG32(dnetp->io_reg, ETHER_ROM_REG));
+ drv_usecwait(MII_DELAY);
+ data = (data << 1) | (tmp >> MII_DATA_IN_POSITION) & 0x0001;
+ }
+
+ mii_tristate(dnetp);
+ return (turned_around ? data: -1);
+}
+
+static void
+dnet_mii_write(dev_info_t *dip, int phy_addr, int reg_num, int reg_dat)
+{
+ gld_mac_info_t *macinfo;
+ struct dnetinstance *dnetp;
+ uint32_t command_word;
+ int bits_in_ushort = ((sizeof (ushort_t))*8);
+
+ macinfo = ddi_get_driver_private(dip);
+ dnetp = (struct dnetinstance *)macinfo->gldm_private;
+
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+ write_mii(dnetp, MII_PRE, 2*bits_in_ushort);
+
+ /* Prepare command word */
+ command_word = ((uint32_t)phy_addr << MII_PHY_ADDR_ALIGN);
+ command_word |= ((uint32_t)reg_num << MII_REG_ADDR_ALIGN);
+ command_word |= (MII_WRITE_FRAME | (uint32_t)reg_dat);
+
+ write_mii(dnetp, command_word, 2*bits_in_ushort);
+ mii_tristate(dnetp);
+}
+
+/*
+ * Write data size bits from mii_data to the MII control lines.
+ */
+static void
+write_mii(struct dnetinstance *dnetp, uint32_t mii_data, int data_size)
+{
+ int i;
+ uint32_t dbit;
+
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+ for (i = data_size; i > 0; i--) {
+ dbit = ((mii_data >>
+ (31 - MII_WRITE_DATA_POSITION)) & MII_WRITE_DATA);
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, ETHER_ROM_REG),
+ MII_WRITE | dbit);
+ drv_usecwait(MII_DELAY);
+ ddi_put32(dnetp->io_handle,
+ REG32(dnetp->io_reg, ETHER_ROM_REG),
+ MII_WRITE | MII_CLOCK | dbit);
+ drv_usecwait(MII_DELAY);
+ mii_data <<= 1;
+ }
+}
+
+/*
+ * Put the MDIO port in tri-state for the turn around bits
+ * in MII read and at end of MII management sequence.
+ */
+static void
+mii_tristate(struct dnetinstance *dnetp)
+{
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, ETHER_ROM_REG),
+ MII_WRITE_TS);
+ drv_usecwait(MII_DELAY);
+ ddi_put32(dnetp->io_handle, REG32(dnetp->io_reg, ETHER_ROM_REG),
+ MII_WRITE_TS | MII_CLOCK);
+ drv_usecwait(MII_DELAY);
+}
+
+
+static void
+set_leaf(SROM_FORMAT *sr, LEAF_FORMAT *leaf)
+{
+ if (sr->leaf && !sr->leaf->is_static)
+ kmem_free(sr->leaf, sr->adapters * sizeof (LEAF_FORMAT));
+ sr->leaf = leaf;
+}
+
+/*
+ * Callback from MII module. Makes sure that the CSR registers are
+ * configured properly if the PHY changes mode.
+ */
+/* ARGSUSED */
+/* dnet_mii_link_cb - called with intrlock held */
+static void
+dnet_mii_link_cb(dev_info_t *dip, int phy, enum mii_phy_state state)
+{
+ gld_mac_info_t *macinfo = ddi_get_driver_private(dip);
+ struct dnetinstance *dnetp =
+ (struct dnetinstance *)macinfo->gldm_private;
+ LEAF_FORMAT *leaf;
+
+ ASSERT(MUTEX_HELD(&dnetp->intrlock));
+ leaf = dnetp->sr.leaf + dnetp->leaf;
+ if (state == phy_state_linkup) {
+ dnetp->mii_up = 1;
+ /* XXX function return value ignored */
+ (void) mii_getspeed(dnetp->mii,
+ dnetp->phyaddr, &dnetp->mii_speed,
+ &dnetp->mii_duplex);
+ dnetp->selected_media_block = leaf->mii_block;
+ setup_block(macinfo);
+ } else {
+ /* NEEDSWORK: Probably can call find_active_media here */
+ dnetp->mii_up = 0;
+ if (leaf->default_block->media_code == MEDIA_MII)
+ dnetp->selected_media_block = leaf->default_block;
+ setup_block(macinfo);
+ }
+}
+
+/*
+ * SROM parsing routines.
+ * Refer to the Digital 3.03 SROM spec while reading this! (references refer
+ * to this document)
+ * Where possible ALL vendor specific changes should be localised here. The
+ * SROM data should be capable of describing any programmatic irregularities
+ * of DNET cards (via SIA or GP registers, in particular), so vendor specific
+ * code elsewhere should not be required
+ */
+static void
+dnet_parse_srom(struct dnetinstance *dnetp, SROM_FORMAT *sr, uchar_t *vi)
+{
+ uint32_t ether_mfg = 0;
+ int i;
+ uchar_t *p;
+
+ if (!ddi_getprop(DDI_DEV_T_ANY, dnetp->devinfo,
+ DDI_PROP_DONTPASS, "no_sromconfig", 0))
+ dnetp->sr.init_from_srom = check_srom_valid(vi);
+
+ if (dnetp->sr.init_from_srom && dnetp->board_type != DEVICE_ID_21040) {
+ /* Section 2/3: General SROM Format/ ID Block */
+ p = vi+18;
+ sr->version = *p++;
+ sr->adapters = *p++;
+
+ sr->leaf =
+ kmem_zalloc(sr->adapters * sizeof (LEAF_FORMAT), KM_SLEEP);
+ for (i = 0; i < 6; i++)
+ sr->netaddr[i] = *p++;
+
+ for (i = 0; i < sr->adapters; i++) {
+ uchar_t devno = *p++;
+ uint16_t offset = *p++;
+ offset |= *p++ << 8;
+ sr->leaf[i].device_number = devno;
+ parse_controller_leaf(dnetp, sr->leaf+i, vi+offset);
+ }
+ /*
+ * 'Orrible hack for cogent cards. The 6911A board seems to
+ * have an incorrect SROM. (From the OEMDEMO program
+ * supplied by cogent, it seems that the ROM matches a setup
+ * or a board with a QSI or ICS PHY.
+ */
+ for (i = 0; i < 3; i++)
+ ether_mfg = (ether_mfg << 8) | sr->netaddr[i];
+
+ if (ether_mfg == ADAPTEC_ETHER) {
+ static uint16_t cogent_gprseq[] = {0x821, 0};
+ switch (vi[COGENT_SROM_ID]) {
+ case COGENT_ANA6911A_C:
+ case COGENT_ANA6911AC_C:
+#ifdef DNETDEBUG
+ if (dnetdebug & DNETTRACE)
+ cmn_err(CE_WARN,
+ "Suspected bad GPR sequence."
+ " Making a guess (821,0)");
+#endif
+
+ /* XXX function return value ignored */
+ (void) ddi_prop_update_byte_array(
+ DDI_DEV_T_NONE, dnetp->devinfo,
+ "gpr-sequence", (uchar_t *)cogent_gprseq,
+ sizeof (cogent_gprseq));
+ break;
+ }
+ }
+ } else {
+ /*
+ * Adhoc SROM, check for some cards which need special handling
+ * Assume vendor info contains ether address in first six bytes
+ */
+
+ uchar_t *mac = vi + ddi_getprop(DDI_DEV_T_ANY, dnetp->devinfo,
+ DDI_PROP_DONTPASS, macoffset_propname, 0);
+
+ for (i = 0; i < 6; i++)
+ sr->netaddr[i] = mac[i];
+
+ if (dnetp->board_type == DEVICE_ID_21140) {
+ for (i = 0; i < 3; i++)
+ ether_mfg = (ether_mfg << 8) | mac[i];
+
+ switch (ether_mfg) {
+ case ASANTE_ETHER:
+ dnetp->vendor_21140 = ASANTE_TYPE;
+ dnetp->vendor_revision = 0;
+ set_leaf(sr, &leaf_asante);
+ sr->adapters = 1;
+ break;
+
+ case COGENT_ETHER:
+ case ADAPTEC_ETHER:
+ dnetp->vendor_21140 = COGENT_EM_TYPE;
+ dnetp->vendor_revision =
+ vi[VENDOR_REVISION_OFFSET];
+ set_leaf(sr, &leaf_cogent_100);
+ sr->adapters = 1;
+ break;
+
+ default:
+ dnetp->vendor_21140 = DEFAULT_TYPE;
+ dnetp->vendor_revision = 0;
+ set_leaf(sr, &leaf_default_100);
+ sr->adapters = 1;
+ break;
+ }
+ } else if (dnetp->board_type == DEVICE_ID_21041) {
+ set_leaf(sr, &leaf_21041);
+ } else if (dnetp->board_type == DEVICE_ID_21040) {
+ set_leaf(sr, &leaf_21040);
+ }
+ }
+}
+
+/* Section 4.2, 4.3, 4.4, 4.5 */
+static void
+parse_controller_leaf(struct dnetinstance *dnetp, LEAF_FORMAT *leaf,
+ uchar_t *vi)
+{
+ int i;
+
+ leaf->selected_contype = *vi++;
+ leaf->selected_contype |= *vi++ << 8;
+
+ if (dnetp->board_type == DEVICE_ID_21140) /* Sect. 4.3 */
+ leaf->gpr = *vi++;
+
+ leaf->block_count = *vi++;
+
+ if (leaf->block_count > MAX_MEDIA) {
+ cmn_err(CE_WARN, "dnet: Too many media in SROM!");
+ leaf->block_count = 1;
+ }
+ for (i = 0; i <= leaf->block_count; i++) {
+ vi = parse_media_block(dnetp, leaf->block + i, vi);
+ if (leaf->block[i].command & CMD_DEFAULT_MEDIUM)
+ leaf->default_block = leaf->block+i;
+ }
+ /* No explicit default block: use last in the ROM */
+ if (leaf->default_block == NULL)
+ leaf->default_block = leaf->block + leaf->block_count -1;
+
+}
+
+static uchar_t *
+parse_media_block(struct dnetinstance *dnetp, media_block_t *block, uchar_t *vi)
+{
+ int i;
+
+ /*
+ * There are three kinds of media block we need to worry about:
+ * The 21041 blocks.
+ * 21140 blocks from a version 1 SROM
+ * 2114[023] block from a version 3 SROM
+ */
+
+ if (dnetp->board_type == DEVICE_ID_21041) {
+ /* Section 4.2 */
+ block->media_code = *vi & 0x3f;
+ block->type = 2;
+ if (*vi++ & 0x40) {
+ block->un.sia.csr13 = *vi++;
+ block->un.sia.csr13 |= *vi++ << 8;
+ block->un.sia.csr14 = *vi++;
+ block->un.sia.csr14 |= *vi++ << 8;
+ block->un.sia.csr15 = *vi++;
+ block->un.sia.csr15 |= *vi++ << 8;
+ } else {
+ /* No media data (csrs 13,14,15). Insert defaults */
+ switch (block->media_code) {
+ case MEDIA_TP:
+ block->un.sia.csr13 = 0xef01;
+ block->un.sia.csr14 = 0x7f3f;
+ block->un.sia.csr15 = 0x0008;
+ break;
+ case MEDIA_TP_FD:
+ block->un.sia.csr13 = 0xef01;
+ block->un.sia.csr14 = 0x7f3d;
+ block->un.sia.csr15 = 0x0008;
+ break;
+ case MEDIA_BNC:
+ block->un.sia.csr13 = 0xef09;
+ block->un.sia.csr14 = 0x0705;
+ block->un.sia.csr15 = 0x0006;
+ break;
+ case MEDIA_AUI:
+ block->un.sia.csr13 = 0xef09;
+ block->un.sia.csr14 = 0x0705;
+ block->un.sia.csr15 = 0x000e;
+ break;
+ }
+ }
+ } else if (*vi & 0x80) { /* Extended format: Section 4.3.2.2 */
+ int blocklen = *vi++ & 0x7f;
+ block->type = *vi++;
+ switch (block->type) {
+ case 0: /* "non-MII": Section 4.3.2.2.1 */
+ block->media_code = (*vi++) & 0x3f;
+ block->gprseqlen = 1;
+ block->gprseq[0] = *vi++;
+ block->command = *vi++;
+ block->command |= *vi++ << 8;
+ break;
+
+ case 1: /* MII/PHY: Section 4.3.2.2.2 */
+ block->command = CMD_PS;
+ block->media_code = MEDIA_MII;
+ /* This is whats needed in CSR6 */
+
+ block->un.mii.phy_num = *vi++;
+ block->gprseqlen = *vi++;
+
+ for (i = 0; i < block->gprseqlen; i++)
+ block->gprseq[i] = *vi++;
+ block->rstseqlen = *vi++;
+ for (i = 0; i < block->rstseqlen; i++)
+ block->rstseq[i] = *vi++;
+
+ block->un.mii.mediacaps = *vi++;
+ block->un.mii.mediacaps |= *vi++ << 8;
+ block->un.mii.nwayadvert = *vi++;
+ block->un.mii.nwayadvert |= *vi++ << 8;
+ block->un.mii.fdxmask = *vi++;
+ block->un.mii.fdxmask |= *vi++ << 8;
+ block->un.mii.ttmmask = *vi++;
+ block->un.mii.ttmmask |= *vi++ << 8;
+ break;
+
+ case 2: /* SIA Media: Section 4.4.2.1.1 */
+ block->media_code = *vi & 0x3f;
+ if (*vi++ & 0x40) {
+ block->un.sia.csr13 = *vi++;
+ block->un.sia.csr13 |= *vi++ << 8;
+ block->un.sia.csr14 = *vi++;
+ block->un.sia.csr14 |= *vi++ << 8;
+ block->un.sia.csr15 = *vi++;
+ block->un.sia.csr15 |= *vi++ << 8;
+ } else {
+ /*
+ * SIA values not provided by SROM; provide
+ * defaults. See appendix D of 2114[23] manuals.
+ */
+ switch (block->media_code) {
+ case MEDIA_BNC:
+ block->un.sia.csr13 = 0x0009;
+ block->un.sia.csr14 = 0x0705;
+ block->un.sia.csr15 = 0x0000;
+ break;
+ case MEDIA_AUI:
+ block->un.sia.csr13 = 0x0009;
+ block->un.sia.csr14 = 0x0705;
+ block->un.sia.csr15 = 0x0008;
+ break;
+ case MEDIA_TP:
+ block->un.sia.csr13 = 0x0001;
+ block->un.sia.csr14 = 0x7f3f;
+ block->un.sia.csr15 = 0x0000;
+ break;
+ case MEDIA_TP_FD:
+ block->un.sia.csr13 = 0x0001;
+ block->un.sia.csr14 = 0x7f3d;
+ block->un.sia.csr15 = 0x0000;
+ break;
+ default:
+ block->un.sia.csr13 = 0x0000;
+ block->un.sia.csr14 = 0x0000;
+ block->un.sia.csr15 = 0x0000;
+ }
+ }
+
+ /* Treat GP control/data as a GPR sequence */
+ block->gprseqlen = 2;
+ block->gprseq[0] = *vi++;
+ block->gprseq[0] |= *vi++ << 8;
+ block->gprseq[0] |= GPR_CONTROL_WRITE;
+ block->gprseq[1] = *vi++;
+ block->gprseq[1] |= *vi++ << 8;
+ break;
+
+ case 3: /* MII/PHY : Section 4.4.2.1.2 */
+ block->command = CMD_PS;
+ block->media_code = MEDIA_MII;
+ block->un.mii.phy_num = *vi++;
+
+ block->gprseqlen = *vi++;
+ for (i = 0; i < block->gprseqlen; i++) {
+ block->gprseq[i] = *vi++;
+ block->gprseq[i] |= *vi++ << 8;
+ }
+
+ block->rstseqlen = *vi++;
+ for (i = 0; i < block->rstseqlen; i++) {
+ block->rstseq[i] = *vi++;
+ block->rstseq[i] |= *vi++ << 8;
+ }
+ block->un.mii.mediacaps = *vi++;
+ block->un.mii.mediacaps |= *vi++ << 8;
+ block->un.mii.nwayadvert = *vi++;
+ block->un.mii.nwayadvert |= *vi++ << 8;
+ block->un.mii.fdxmask = *vi++;
+ block->un.mii.fdxmask |= *vi++ << 8;
+ block->un.mii.ttmmask = *vi++;
+ block->un.mii.ttmmask |= *vi++ << 8;
+ block->un.mii.miiintr |= *vi++;
+ break;
+
+ case 4: /* SYM Media: 4.5.2.1.3 */
+ block->media_code = *vi++ & 0x3f;
+ /* Treat GP control and data as a GPR sequence */
+ block->gprseqlen = 2;
+ block->gprseq[0] = *vi++;
+ block->gprseq[0] |= *vi++ << 8;
+ block->gprseq[0] |= GPR_CONTROL_WRITE;
+ block->gprseq[1] = *vi++;
+ block->gprseq[1] |= *vi++ << 8;
+ block->command = *vi++;
+ block->command = *vi++ << 8;
+ break;
+
+ case 5: /* GPR reset sequence: Section 4.5.2.1.4 */
+ block->rstseqlen = *vi++;
+ for (i = 0; i < block->rstseqlen; i++)
+ block->rstseq[i] = *vi++;
+ break;
+
+ default: /* Unknown media block. Skip it. */
+ cmn_err(CE_WARN, "dnet: Unsupported SROM block.");
+ vi += blocklen;
+ break;
+ }
+ } else { /* Compact format (or V1 SROM): Section 4.3.2.1 */
+ block->type = 0;
+ block->media_code = *vi++ & 0x3f;
+ block->gprseqlen = 1;
+ block->gprseq[0] = *vi++;
+ block->command = *vi++;
+ block->command |= (*vi++) << 8;
+ }
+ return (vi);
+}
+
+
+/*
+ * An alternative to doing this would be to store the legacy ROMs in binary
+ * format in the conf file, and in read_srom, pick out the data. This would
+ * then allow the parser to continue on as normal. This makes it a little
+ * easier to read.
+ */
+static void
+setup_legacy_blocks()
+{
+ LEAF_FORMAT *leaf;
+ media_block_t *block;
+
+ /* Default FAKE SROM */
+ leaf = &leaf_default_100;
+ leaf->is_static = 1;
+ leaf->default_block = &leaf->block[3];
+ leaf->block_count = 4; /* 100 cards are highly unlikely to have BNC */
+ block = leaf->block;
+ block->media_code = MEDIA_TP_FD;
+ block->type = 0;
+ block->command = 0x8e; /* PCS, PS off, media sense: bit7, pol=1 */
+ block++;
+ block->media_code = MEDIA_TP;
+ block->type = 0;
+ block->command = 0x8e; /* PCS, PS off, media sense: bit7, pol=1 */
+ block++;
+ block->media_code = MEDIA_SYM_SCR_FD;
+ block->type = 0;
+ block->command = 0x6d; /* PCS, PS, SCR on, media sense: bit6, pol=0 */
+ block++;
+ block->media_code = MEDIA_SYM_SCR;
+ block->type = 0;
+ block->command = 0x406d; /* PCS, PS, SCR on, media sense: bit6, pol=0 */
+
+ /* COGENT FAKE SROM */
+ leaf = &leaf_cogent_100;
+ leaf->is_static = 1;
+ leaf->default_block = &leaf->block[4];
+ leaf->block_count = 5; /* 100TX, 100TX-FD, 10T 10T-FD, BNC */
+ block = leaf->block; /* BNC */
+ block->media_code = MEDIA_BNC;
+ block->type = 0;
+ block->command = 0x8000; /* No media sense, PCS, SCR, PS all off */
+ block->gprseqlen = 2;
+ block->rstseqlen = 0;
+ block->gprseq[0] = 0x13f;
+ block->gprseq[1] = 1;
+
+ block++;
+ block->media_code = MEDIA_TP_FD;
+ block->type = 0;
+ block->command = 0x8e; /* PCS, PS off, media sense: bit7, pol=1 */
+ block->gprseqlen = 2;
+ block->rstseqlen = 0;
+ block->gprseq[0] = 0x13f;
+ block->gprseq[1] = 0x26;
+
+ block++; /* 10BaseT */
+ block->media_code = MEDIA_TP;
+ block->type = 0;
+ block->command = 0x8e; /* PCS, PS off, media sense: bit7, pol=1 */
+ block->gprseqlen = 2;
+ block->rstseqlen = 0;
+ block->gprseq[0] = 0x13f;
+ block->gprseq[1] = 0x3e;
+
+ block++; /* 100BaseTX-FD */
+ block->media_code = MEDIA_SYM_SCR_FD;
+ block->type = 0;
+ block->command = 0x6d; /* PCS, PS, SCR on, media sense: bit6, pol=0 */
+ block->gprseqlen = 2;
+ block->rstseqlen = 0;
+ block->gprseq[0] = 0x13f;
+ block->gprseq[1] = 1;
+
+ block++; /* 100BaseTX */
+ block->media_code = MEDIA_SYM_SCR;
+ block->type = 0;
+ block->command = 0x406d; /* PCS, PS, SCR on, media sense: bit6, pol=0 */
+ block->gprseqlen = 2;
+ block->rstseqlen = 0;
+ block->gprseq[0] = 0x13f;
+ block->gprseq[1] = 1;
+
+ /* Generic legacy card with a PHY. */
+ leaf = &leaf_phylegacy;
+ leaf->block_count = 1;
+ leaf->mii_block = leaf->block;
+ leaf->default_block = &leaf->block[0];
+ leaf->is_static = 1;
+ block = leaf->block;
+ block->media_code = MEDIA_MII;
+ block->type = 1; /* MII Block type 1 */
+ block->command = 1; /* Port select */
+ block->gprseqlen = 0;
+ block->rstseqlen = 0;
+
+ /* ASANTE FAKE SROM */
+ leaf = &leaf_asante;
+ leaf->is_static = 1;
+ leaf->default_block = &leaf->block[0];
+ leaf->block_count = 1;
+ block = leaf->block;
+ block->media_code = MEDIA_MII;
+ block->type = 1; /* MII Block type 1 */
+ block->command = 1; /* Port select */
+ block->gprseqlen = 3;
+ block->rstseqlen = 0;
+ block->gprseq[0] = 0x180;
+ block->gprseq[1] = 0x80;
+ block->gprseq[2] = 0x0;
+
+ /* LEGACY 21041 card FAKE SROM */
+ leaf = &leaf_21041;
+ leaf->is_static = 1;
+ leaf->block_count = 4; /* SIA Blocks for TP, TPfd, BNC, AUI */
+ leaf->default_block = &leaf->block[3];
+
+ block = leaf->block;
+ block->media_code = MEDIA_AUI;
+ block->type = 2;
+ block->un.sia.csr13 = 0xef09;
+ block->un.sia.csr14 = 0x0705;
+ block->un.sia.csr15 = 0x000e;
+
+ block++;
+ block->media_code = MEDIA_TP_FD;
+ block->type = 2;
+ block->un.sia.csr13 = 0xef01;
+ block->un.sia.csr14 = 0x7f3d;
+ block->un.sia.csr15 = 0x0008;
+
+ block++;
+ block->media_code = MEDIA_BNC;
+ block->type = 2;
+ block->un.sia.csr13 = 0xef09;
+ block->un.sia.csr14 = 0x0705;
+ block->un.sia.csr15 = 0x0006;
+
+ block++;
+ block->media_code = MEDIA_TP;
+ block->type = 2;
+ block->un.sia.csr13 = 0xef01;
+ block->un.sia.csr14 = 0x7f3f;
+ block->un.sia.csr15 = 0x0008;
+
+ /* LEGACY 21040 card FAKE SROM */
+ leaf = &leaf_21040;
+ leaf->is_static = 1;
+ leaf->block_count = 4; /* SIA Blocks for TP, TPfd, BNC, AUI */
+ block = leaf->block;
+ block->media_code = MEDIA_AUI;
+ block->type = 2;
+ block->un.sia.csr13 = 0x8f09;
+ block->un.sia.csr14 = 0x0705;
+ block->un.sia.csr15 = 0x000e;
+ block++;
+ block->media_code = MEDIA_TP_FD;
+ block->type = 2;
+ block->un.sia.csr13 = 0x0f01;
+ block->un.sia.csr14 = 0x7f3d;
+ block->un.sia.csr15 = 0x0008;
+ block++;
+ block->media_code = MEDIA_BNC;
+ block->type = 2;
+ block->un.sia.csr13 = 0xef09;
+ block->un.sia.csr14 = 0x0705;
+ block->un.sia.csr15 = 0x0006;
+ block++;
+ block->media_code = MEDIA_TP;
+ block->type = 2;
+ block->un.sia.csr13 = 0x8f01;
+ block->un.sia.csr14 = 0x7f3f;
+ block->un.sia.csr15 = 0x0008;
+}
+
+static void
+dnet_print_srom(SROM_FORMAT *sr)
+{
+ int i;
+ uchar_t *a = sr->netaddr;
+ cmn_err(CE_NOTE, "SROM Dump: %d. ver %d, Num adapters %d,"
+ "Addr:%x:%x:%x:%x:%x:%x",
+ sr->init_from_srom, sr->version, sr->adapters,
+ a[0], a[1], a[2], a[3], a[4], a[5]);
+
+ for (i = 0; i < sr->adapters; i++)
+ dnet_dump_leaf(sr->leaf+i);
+}
+
+static void
+dnet_dump_leaf(LEAF_FORMAT *leaf)
+{
+ int i;
+ cmn_err(CE_NOTE, "Leaf: Device %d, block_count %d, gpr: %x",
+ leaf->device_number, leaf->block_count, leaf->gpr);
+ for (i = 0; i < leaf->block_count; i++)
+ dnet_dump_block(leaf->block+i);
+}
+
+static void
+dnet_dump_block(media_block_t *block)
+{
+ cmn_err(CE_NOTE, "Block(%p): type %x, media %s, command: %x ",
+ (void *)block,
+ block->type, media_str[block->media_code], block->command);
+ dnet_dumpbin("\tGPR Seq", (uchar_t *)block->gprseq, 2,
+ block->gprseqlen *2);
+ dnet_dumpbin("\tGPR Reset", (uchar_t *)block->rstseq, 2,
+ block->rstseqlen *2);
+ switch (block->type) {
+ case 1: case 3:
+ cmn_err(CE_NOTE, "\tMII Info: phy %d, nway %x, fdx"
+ "%x, ttm %x, mediacap %x",
+ block->un.mii.phy_num, block->un.mii.nwayadvert,
+ block->un.mii.fdxmask, block->un.mii.ttmmask,
+ block->un.mii.mediacaps);
+ break;
+ case 2:
+ cmn_err(CE_NOTE, "\tSIA Regs: CSR13:%x, CSR14:%x, CSR15:%x",
+ block->un.sia.csr13, block->un.sia.csr14,
+ block->un.sia.csr15);
+ break;
+ }
+}
+
+
+/* Utility to print out binary info dumps. Handy for SROMs, etc */
+
+static int
+hexcode(unsigned val)
+{
+ if (val <= 9)
+ return (val +'0');
+ if (val <= 15)
+ return (val + 'a' - 10);
+ return (-1);
+}
+
+static void
+dnet_dumpbin(char *msg, unsigned char *data, int size, int len)
+{
+ char hex[128], *p = hex;
+ char ascii[128], *q = ascii;
+ int i, j;
+
+ if (!len)
+ return;
+
+ for (i = 0; i < len; i += size) {
+ for (j = size - 1; j >= 0; j--) { /* PORTABILITY: byte order */
+ *p++ = hexcode(data[i+j] >> 4);
+ *p++ = hexcode(data[i+j] & 0xf);
+ *q++ = (data[i+j] < 32 || data[i+j] > 127) ?
+ '.' : data[i];
+ }
+ *p++ = ' ';
+ if (q-ascii >= 8) {
+ *p = *q = 0;
+ cmn_err(CE_NOTE, "%s: %s\t%s", msg, hex, ascii);
+ p = hex;
+ q = ascii;
+ }
+ }
+ if (p != hex) {
+ while ((p - hex) < 8*3)
+ *p++ = ' ';
+ *p = *q = 0;
+ cmn_err(CE_NOTE, "%s: %s\t%s", msg, hex, ascii);
+ }
+}
+
+#ifdef DNETDEBUG
+void
+dnet_usectimeout(struct dnetinstance *dnetp, uint32_t usecs, int contin,
+ timercb_t cback)
+{
+ mutex_enter(&dnetp->intrlock);
+ dnetp->timer.start_ticks = (usecs * 100) / 8192;
+ dnetp->timer.cb = cback;
+ outl(dnetp->io_reg + GP_TIMER_REG, dnetp->timer.start_ticks |
+ (contin ? GPTIMER_CONT : 0));
+ if (dnetp->timer.cb)
+ enable_interrupts(dnetp, 1);
+ mutex_exit(&dnetp->intrlock);
+}
+
+uint32_t
+dnet_usecelapsed(struct dnetinstance *dnetp)
+{
+ uint32_t ticks = dnetp->timer.start_ticks -
+ (inl(dnetp->io_reg + GP_TIMER_REG) & 0xffff);
+ return ((ticks * 8192) / 100);
+}
+
+/* ARGSUSED */
+void
+dnet_timestamp(struct dnetinstance *dnetp, char *buf)
+{
+ uint32_t elapsed = dnet_usecelapsed(dnetp);
+ char loc[32], *p = loc;
+ int firstdigit = 1;
+ uint32_t divisor;
+
+ while (*p++ = *buf++)
+ ;
+ p--;
+
+ for (divisor = 1000000000; divisor /= 10; ) {
+ int digit = (elapsed / divisor);
+ elapsed -= digit * divisor;
+ if (!firstdigit || digit) {
+ *p++ = digit + '0';
+ firstdigit = 0;
+ }
+
+ }
+
+ /* Actual zero, output it */
+ if (firstdigit)
+ *p++ = '0';
+
+ *p++ = '-';
+ *p++ = '>';
+ *p++ = 0;
+
+ printf(loc);
+ dnet_usectimeout(dnetp, 1000000, 0, 0);
+}
+
+#endif