From 4eee111127d8ec2bdd77c0da46739e2b42323187 Mon Sep 17 00:00:00 2001 From: haya Date: Fri, 15 Oct 1999 06:07:17 +0000 Subject: [PATCH] This is the first check-in of CardBus driver. CardBus driver contains CardBus bus stub, YENTA PCI-CardBus bridge (cbb), 3Com 3C575TX driver (ex) and Intel fxp driver. TODO: o Conform to the KNF more strictly. o Be unified with pcmcia code as much as possible. o Add more drivers for CardBus card, such as APA-1480 or USB card. The affected files are listed below. sys/arch/i386/conf/files.i386 sys/arch/macppc/conf/files.macppc sys/conf/files sys/dev/ic/elinkxl.c sys/dev/ic/elinkxlvar.h sys/dev/ic/i82365.c sys/dev/ic/i82365var.h sys/dev/isa/i82365_isasubr.c sys/dev/pci/files.pci sys/dev/pcmcia/pcmcia.c sys/dev/pcmcia/pcmciachip.h The added files are listed below. sys/arch/i386/conf/CARDBUS sys/arch/i386/include/rbus_machdep.h sys/arch/i386/i386/rbus_machdep.c sys/arch/macppc/include/rbus_machdep.h sys/arch/macppc/macppc/rbus_machdep.c sys/dev/cardbus/if_ex_cardbus.c sys/dev/cardbus/Makefile.cardbusdevs sys/dev/cardbus/cardbus.c sys/dev/cardbus/cardbus_map.c sys/dev/cardbus/cardbusdevs sys/dev/cardbus/cardbusdevs.h sys/dev/cardbus/cardbusdevs_data.h sys/dev/cardbus/cardbusvar.h sys/dev/cardbus/cardslot.c sys/dev/cardbus/cardslotvar.h sys/dev/cardbus/devlist2h.awk sys/dev/cardbus/files.cardbus sys/dev/cardbus/if_fxp_cardbus.c sys/dev/cardbus/pccardcis.h sys/dev/cardbus/rbus.c sys/dev/cardbus/rbus.h sys/dev/pci/pccbb.c sys/dev/pci/pccbbreg.h sys/dev/pci/pccbbvar.h --- sys/arch/i386/conf/CARDBUS | 652 +++++ sys/arch/i386/conf/files.i386 | 8 +- sys/arch/i386/i386/rbus_machdep.c | 160 ++ sys/arch/i386/include/rbus_machdep.h | 51 + sys/arch/macppc/conf/files.macppc | 9 +- sys/arch/macppc/include/rbus_machdep.h | 42 + sys/arch/macppc/macppc/rbus_machdep.c | 153 ++ sys/conf/files | 4 +- sys/dev/cardbus/Makefile.cardbusdevs | 7 + sys/dev/cardbus/cardbus.c | 609 +++++ sys/dev/cardbus/cardbus_map.c | 373 +++ sys/dev/cardbus/cardbusdevs | 69 + sys/dev/cardbus/cardbusvar.h | 365 +++ sys/dev/cardbus/cardslot.c | 426 ++++ sys/dev/cardbus/cardslotvar.h | 121 + sys/dev/cardbus/devlist2h.awk | 221 ++ sys/dev/cardbus/files.cardbus | 33 + sys/dev/cardbus/if_ex_cardbus.c | 415 ++++ sys/dev/cardbus/if_fxp_cardbus.c | 281 +++ sys/dev/cardbus/pccardcis.h | 92 + sys/dev/cardbus/rbus.c | 394 +++ sys/dev/cardbus/rbus.h | 165 ++ sys/dev/ic/elinkxl.c | 15 +- sys/dev/ic/elinkxlvar.h | 4 +- sys/dev/ic/i82365.c | 138 +- sys/dev/ic/i82365var.h | 23 +- sys/dev/isa/i82365_isasubr.c | 8 +- sys/dev/pci/files.pci | 8 +- sys/dev/pci/pccbb.c | 3041 ++++++++++++++++++++++++ sys/dev/pci/pccbbreg.h | 220 ++ sys/dev/pci/pccbbvar.h | 174 ++ sys/dev/pcmcia/pcmcia.c | 7 +- sys/dev/pcmcia/pcmciachip.h | 6 +- 33 files changed, 8240 insertions(+), 54 deletions(-) create mode 100644 sys/arch/i386/conf/CARDBUS create mode 100644 sys/arch/i386/i386/rbus_machdep.c create mode 100644 sys/arch/i386/include/rbus_machdep.h create mode 100644 sys/arch/macppc/include/rbus_machdep.h create mode 100644 sys/arch/macppc/macppc/rbus_machdep.c create mode 100644 sys/dev/cardbus/Makefile.cardbusdevs create mode 100644 sys/dev/cardbus/cardbus.c create mode 100644 sys/dev/cardbus/cardbus_map.c create mode 100644 sys/dev/cardbus/cardbusdevs create mode 100644 sys/dev/cardbus/cardbusvar.h create mode 100644 sys/dev/cardbus/cardslot.c create mode 100644 sys/dev/cardbus/cardslotvar.h create mode 100644 sys/dev/cardbus/devlist2h.awk create mode 100644 sys/dev/cardbus/files.cardbus create mode 100644 sys/dev/cardbus/if_ex_cardbus.c create mode 100644 sys/dev/cardbus/if_fxp_cardbus.c create mode 100644 sys/dev/cardbus/pccardcis.h create mode 100644 sys/dev/cardbus/rbus.c create mode 100644 sys/dev/cardbus/rbus.h create mode 100644 sys/dev/pci/pccbb.c create mode 100644 sys/dev/pci/pccbbreg.h create mode 100644 sys/dev/pci/pccbbvar.h diff --git a/sys/arch/i386/conf/CARDBUS b/sys/arch/i386/conf/CARDBUS new file mode 100644 index 000000000000..eacc7b75e8fe --- /dev/null +++ b/sys/arch/i386/conf/CARDBUS @@ -0,0 +1,652 @@ +# $NetBSD: CARDBUS,v 1.1 1999/10/15 06:10:38 haya Exp $ +# +# CARDBUS -- GENERIC + CardBus support +# + +include "arch/i386/conf/std.i386" + +maxusers 32 # estimated number of users + +# CPU support. At least one is REQUIRED. +options I386_CPU +options I486_CPU +options I586_CPU +options I686_CPU + +# CPU-related options. +options MATH_EMULATE # floating point emulation +#options VM86 # virtual 8086 emulation +options USER_LDT # user-settable LDT; used by WINE +# eliminate delay no-ops in I/O; recommended on all but very old machines +#options DUMMY_NOPS + +# delay between "rebooting ..." message and hardware reset, in milliseconds +#options CPURESET_DELAY=2000 + +# Misc. i386-specific options +options XSERVER # X server support in console drivers +#options XSERVER_DDB # PF12 gets you into DDB when X is running + +# This option allows you to force a serial console at the specified +# I/O address. see console(4) for details. +#options "CONSDEVNAME=\"com\"",CONADDR=0x2f8,CONSPEED=57600 +# you don't want the option below ON iff you are using the +# serial console option of the new boot strap code. +#options CONS_OVERRIDE # Always use above! independent of boot info + +# The following options override the memory sizes passed in from the boot +# block. Use them *only* if the boot block is unable to determine the correct +# values. Note that the BIOS may *correctly* report less than 640k of base +# memory if the extended BIOS data area is located at the top of base memory +# (as is the case on most recent systems). +#options REALBASEMEM=639 # size of base memory (in KB) +#options REALEXTMEM=15360 # size of extended memory (in KB) + +# Standard system options + +options UCONSOLE # users can use TIOCCONS (for xconsole) +options INSECURE # disable kernel security levels + +options RTC_OFFSET=0 # hardware clock is this many mins. west of GMT +options NTP # NTP phase/frequency locked loop + +options KTRACE # system call tracing via ktrace(1) + +options SYSVMSG # System V-like message queues +options SYSVSEM # System V-like semaphores +options SYSVSHM # System V-like memory sharing +#options SHMMAXPGS=1024 # 1024 pages is the default + +options LKM # loadable kernel modules + +# Diagnostic/debugging support options +options DIAGNOSTIC # cheap kernel consistency checks +#options DEBUG # expensive debugging checks/support +#options KMEMSTATS # kernel memory statistics (vmstat -m) +options DDB # in-kernel debugger +#options DDB_HISTORY_SIZE=100 # enable history editing in DDB +#options KGDB # remote debugger +#options "KGDB_DEVNAME=\"com\"",KGDBADDR=0x3f8,KGDBRATE=9600 +#makeoptions DEBUG="-g" # compile full symbol table + +# Compatibility options +options COMPAT_NOMID # compatibility with 386BSD, BSDI, NetBSD 0.8, +options COMPAT_09 # NetBSD 0.9, +options COMPAT_10 # NetBSD 1.0, +options COMPAT_11 # NetBSD 1.1, +options COMPAT_12 # NetBSD 1.2, +options COMPAT_13 # NetBSD 1.3, +options COMPAT_43 # and 4.3BSD +options COMPAT_386BSD_MBRPART # recognize old partition ID + +options COMPAT_SVR4 # binary compatibility with SVR4 +options COMPAT_IBCS2 # binary compatibility with SCO and ISC +options COMPAT_LINUX # binary compatibility with Linux +options COMPAT_FREEBSD # binary compatibility with FreeBSD + +# Executable format options +options EXEC_ELF32 # 32-bit ELF executables (SVR4, Linux) + +# File systems +file-system FFS # UFS +file-system EXT2FS # second extended file system (linux) +file-system LFS # log-structured file system +file-system MFS # memory file system +file-system NFS # Network File System client +file-system CD9660 # ISO 9660 + Rock Ridge file system +file-system MSDOSFS # MS-DOS file system +file-system FDESC # /dev/fd +file-system KERNFS # /kern +file-system NULLFS # loopback file system +file-system PORTAL # portal filesystem (still experimental) +file-system PROCFS # /proc +file-system UMAPFS # NULLFS + uid and gid remapping +file-system UNION # union file system +file-system CODA # Coda File System; also needs vcoda (below) + +# File system options +options QUOTA # UFS quotas +#options FFS_EI # FFS Endian Independant support +options NFSSERVER # Network File System server +#options EXT2FS_SYSTEM_FLAGS # makes ext2fs file flags (append and + # immutable) behave as system flags. + +# Networking options +#options GATEWAY # packet forwarding +options INET # IP + ICMP + TCP + UDP +#options MROUTING # IP multicast routing +options NS # XNS +#options NSIP # XNS tunneling over IP +options ISO,TPIP # OSI +options EON # OSI tunneling over IP +options CCITT,LLC,HDLC # X.25 +options NETATALK # AppleTalk networking protocols +#options PPP_BSDCOMP # BSD-Compress compression support for PPP +#options PPP_DEFLATE # Deflate compression support for PPP +#options PPP_FILTER # Active filter support for PPP (requires bpf) +#options PFIL_HOOKS # pfil(9) packet filter hooks +#options IPFILTER_LOG # ipmon(8) log support + +# Compatibility with 4.2BSD implementation of TCP/IP. Not recommended. +#options TCP_COMPAT_42 + +# These options enable verbose messages for several subsystems. +# Warning, these may compile large string tables into the kernel! +options EISAVERBOSE # verbose EISA device autoconfig messages +options PCIVERBOSE # verbose PCI device autoconfig messages +#options PCMCIAVERBOSE # verbose PCMCIA configuration messages +options SCSIVERBOSE # human readable SCSI error messages +options USBVERBOSE # verbose USB device autoconfig messages + +options NFS_BOOT_BOOTP,NFS_BOOT_BOOTPARAM + +# +# wscons options +# +# builtin terminal emulations +#options WSEMUL_SUN # sun terminal emulation +options WSEMUL_VT100 # VT100 / VT220 emulation +# different kernel output - see dev/wscons/wsdisplayvar.h +options WS_KERNEL_FG=WSCOL_GREEN +#options WS_KERNEL_BG=WSCOL_BLACK +# compatibility to other console drivers +options WSDISPLAY_COMPAT_PCVT # emulate some ioctls +options WSDISPLAY_COMPAT_SYSCONS # emulate some ioctls +options WSDISPLAY_COMPAT_USL # VT handling +options WSDISPLAY_COMPAT_RAWKBD # can get raw scancodes +# see dev/pckbc/wskbdmap_mfii.c for implemented layouts +#options PCKBD_LAYOUT="(KB_DE | KB_NODEAD)" +# allocate a number of virtual screens at autoconfiguration time +#options WSDISPLAY_DEFAULTSCREENS=4 + +# Kernel root file system and dump configuration. +config netbsd root on ? type ? +#config netbsd root on sd0a type ffs +#config netbsd root on ? type nfs + +# +# Device configuration +# + +mainbus0 at root + +#apm0 at mainbus0 # Advanced power management + + +# Basic Bus Support + +# PCI bus support +pci* at mainbus? bus ? +pci* at pchb? bus ? +pci* at ppb? bus ? + +# PCI bridges +pchb* at pci? dev ? function ? # PCI-Host bridges +pceb* at pci? dev ? function ? # PCI-EISA bridges +pcib* at pci? dev ? function ? # PCI-ISA bridges +ppb* at pci? dev ? function ? # PCI-PCI bridges +# XXX 'puc's aren't really bridges, but there's no better place for them here +puc* at pci? dev ? function ? # PCI "universal" comm. cards + +# EISA bus support +eisa* at mainbus? +eisa* at pceb? + +# ISA bus support +isa* at mainbus? +isa* at pceb? +isa* at pcib? + +# PCMCIA bus support +pcmcia* at pcic? controller ? socket ? +pcmcia* at tcic? controller ? socket ? + +# ISA PCMCIA controllers +pcic0 at isa? port 0x3e0 iomem 0xd0000 iosiz 0x4000 +pcic1 at isa? port 0x3e2 iomem 0xd4000 iosiz 0x4000 +tcic0 at isa? port 0x240 iomem 0xd0000 iosiz 0x4000 + +# PCI PCMCIA controllers +pcic0 at pci? dev? function ? + +# ISA Plug-and-Play bus support +isapnp0 at isa? + +# ISA Plug-and-Play PCMCIA controllers +pcic* at isapnp? + +# CardBus bus support +cardbus* at cardslot? +pcmcia* at cardslot? + +cbb* at pci? dev? function ? + +cardslot* at cbb? + +# Coprocessor Support + +# Math Coprocessor support +npx0 at isa? port 0xf0 irq 13 # x86 math coprocessor + + +# Console Devices + +# ISA console. You can only configure one of these! +#pc0 at isa? port 0x60 irq 1 # pccons generic PC console driver +#vt0 at isa? port 0x60 irq 1 # PCVT console driver + +# Keyboard layout configuration for pccons +#options FRENCH_KBD +#options FINNISH_KBD +#options GERMAN_KBD +#options NORWEGIAN_KBD + +# wscons +pckbc0 at isa? # pc keyboard controller +pckbd* at pckbc? # PC keyboard +# "opms" should not be enabled together with "pms" or "pmsi" +#pms* at pckbc? # PS/2 mouse for wsmouse +#pmsi* at pckbc? # PS/2 "Intelli"mouse for wsmouse +opms* at pckbc? # backwards compatible PS/2 mouse +vga0 at isa? +vga* at pci? +pcdisplay0 at isa? # CGA, MDA, EGA, HGA +wsdisplay* at vga? console ? +wsdisplay* at pcdisplay? console ? +wskbd* at pckbd? console ? +#wsmouse* at pms? +#wsmouse* at pmsi? + +pcppi0 at isa? +sysbeep0 at pcppi? + +# Serial Devices + +# PCI serial interfaces +com* at puc? port ? # 16x450s on "universal" comm boards +cy* at pci? dev ? function ? # Cyclades Cyclom-Y serial boards + +# ISA Plug-and-Play serial interfaces +com* at isapnp? # Modems and serial boards + +# PCMCIA serial interfaces +com* at pcmcia? function ? # Modems and serial cards + +pcmcom* at pcmcia? function ? # PCMCIA multi-port serial cards +com* at pcmcom? slave ? # ...and the slave devices + +# ISA serial interfaces +#options COM_HAYESP # adds Hayes ESP serial board support +com0 at isa? port 0x3f8 irq 4 # Standard PC serial ports +com1 at isa? port 0x2f8 irq 3 +com2 at isa? port 0x3e8 irq 5 +#com3 at isa? port 0x2e8 irq 9 +#ast0 at isa? port 0x1a0 irq 5 # AST 4-port serial cards +#com* at ast? slave ? +#boca0 at isa? port 0x100 irq 5 # BOCA 8-port serial cards +#com* at boca? slave ? +#tcom0 at isa? port 0x100 irq 7 # TC-800 8-port serial cards +#com* at tcom? slave ? +#rtfps0 at isa? port 0x1230 irq 10 # RT 4-port serial cards +#com* at rtfps? slave ? +#cy0 at isa? iomem 0xd4000 irq 12 # Cyclades serial cards + + +# Parallel Printer Interfaces + +# PCI parallel printer interfaces +lpt* at puc? port ? # || ports on "universal" comm boards + +# ISA parallel printer interfaces +lpt0 at isa? port 0x378 irq 7 # standard PC parallel ports +lpt1 at isa? port 0x278 +lpt2 at isa? port 0x3bc + + +# SCSI Controllers and Devices + +# PCI SCSI controllers +adv* at pci? dev ? function ? # AdvanSys 1200[A,B], 9xx[U,UA] SCSI +adw* at pci? dev ? function ? # AdvanSys 9xxUW SCSI +ahc* at pci? dev ? function ? # Adaptec [23]94x, aic78x0 SCSI +bha* at pci? dev ? function ? # BusLogic 9xx SCSI +isp* at pci? dev ? function ? # Qlogic ISP [12]0x0 SCSI/FibreChannel +ncr* at pci? dev ? function ? # NCR 53c8xx SCSI +pcscp* at pci? dev ? function ? # AMD 53c974 PCscsi-PCI SCSI + +# EISA SCSI controllers +ahb* at eisa? slot ? # Adaptec 174[02] SCSI +ahc* at eisa? slot ? # Adaptec 274x, aic7770 SCSI +bha* at eisa? slot ? # BusLogic 7xx SCSI +uha* at eisa? slot ? # UltraStor 24f SCSI + +# PCMCIA SCSI controllers +aic* at pcmcia? function ? # Adaptec APA-1460 SCSI + +# ISA Plug-and-Play SCSI controllers +aha* at isapnp? # Adaptec AHA-154[02 +aic* at isapnp? # Adaptec AHA-1520B + +# ISA SCSI controllers +aha0 at isa? port 0x330 irq ? drq ? # Adaptec 154[02] SCSI +aha1 at isa? port 0x334 irq ? drq ? +ahc0 at isa? port ? irq ? # Adaptec 284x SCSI +aic0 at isa? port 0x340 irq 11 # Adaptec 152[02] SCSI +bha0 at isa? port 0x330 irq ? drq ? # BusLogic [457]4X SCSI +bha1 at isa? port 0x334 irq ? drq ? +nca0 at isa? port 0x360 irq 15 # Port-mapped NCR 53C80 contoller +nca1 at isa? iomem 0xd8000 irq 5 # Memory-mapped controller (T128, etc.) +sea0 at isa? iomem 0xc8000 irq 5 # Seagate/Future Domain SCSI +uha0 at isa? port 0x330 irq ? drq ? # UltraStor [13]4f SCSI +uha1 at isa? port 0x340 irq ? drq ? +wds0 at isa? port 0x350 irq 15 drq 6 # WD7000 and TMC-7000 controllers +wds1 at isa? port 0x358 irq 11 drq 5 + +# SCSI bus support +scsibus* at adv? +scsibus* at adw? +scsibus* at aha? +scsibus* at ahb? +scsibus* at ahc? +scsibus* at aic? +scsibus* at bha? +scsibus* at isp? +scsibus* at nca? +scsibus* at ncr? +scsibus* at pcscp? +scsibus* at sea? +scsibus* at uha? +scsibus* at wds? + +# SCSI devices +sd* at scsibus? target ? lun ? # SCSI disk drives +st* at scsibus? target ? lun ? # SCSI tape drives +cd* at scsibus? target ? lun ? # SCSI CD-ROM drives +ch* at scsibus? target ? lun ? # SCSI autochangers +ss* at scsibus? target ? lun ? # SCSI scanners +uk* at scsibus? target ? lun ? # SCSI unknown + + +# IDE and related devices +# PCI IDE controllers - see pciide(4) for supported hardware. +# The 0x0001 flag force the driver to use DMA, even if the driver doesn't know +# how to set up DMA modes for this chip. This may work, or may cause +# a machine hang with some controllers. +pciide* at pci ? dev ? function ? flags 0x0000 + +# ISA Plug-and-Play IDE controllers +wdc* at isapnp? + +# PCMCIA IDE controllers +wdc* at pcmcia? function ? + +# ISA ST506, ESDI, and IDE controllers +wdc0 at isa? port 0x1f0 irq 14 +wdc1 at isa? port 0x170 irq 15 + +# IDE drives +# Flags are used only with controllers that support DMA operations +# and mode settings (e.g. some pciide controllers) +# The lowest order four bits (rightmost digit) of the flags define the PIO +# mode to use, the next set of four bits the DMA mode and the third set the +# UltraDMA mode. For each set of four bits, the 3 lower bits define the mode +# to use, and the last bit must be 1 for this setting to be used. +# For DMA and UDMA, 0xf (1111) means 'disable'. +# 0x0fac means 'use PIO mode 4, DMA mode 2, disable UltraDMA'. +# (0xc=1100, 0xa=1010, 0xf=1111) +# 0x0000 means "use whatever the drive claims to support". +wd* at wdc? channel ? drive ? flags 0x0000 +wd* at pciide? channel ? drive ? flags 0x0000 + +# ATAPI bus support +atapibus* at wdc? channel ? +atapibus* at pciide? channel ? + +# ATAPI devices +# flags have the same meaning as for IDE drives. +cd* at atapibus? drive ? flags 0x0000 # ATAPI CD-ROM drives +sd* at atapibus? drive ? flags 0x0000 # ATAPI disk drives +uk* at atapibus? drive ? flags 0x0000 # ATAPI unknown + + +# Miscellaneous mass storage devices + +# ISA floppy +fdc0 at isa? port 0x3f0 irq 6 drq 2 # standard PC floppy controllers +#fdc1 at isa? port 0x370 irq ? drq ? +fd* at fdc? drive ? # the drives themselves +# some machines need you to do this instead of fd* +#fd0 at fdc0 drive 0 + +# ISA CD-ROM devices +#mcd0 at isa? port 0x300 irq 10 # Mitsumi CD-ROM drives + +# ISA tape devices +# note: the wt driver conflicts unpleasantly with SMC boards at the +# same I/O address. The probe reprograms their EEPROMs. Don't +# uncomment it unless you are actually using it. +#wt0 at isa? port 0x308 irq 5 drq 1 # Archive and Wangtek QIC tape drives + + +# Network Interfaces + +# PCI network interfaces +de* at pci? dev ? function ? # DEC 21x4x-based Ethernet +en* at pci? dev ? function ? # ENI/Adaptec ATM +ep* at pci? dev ? function ? # 3Com 3c59x +ex* at pci? dev ? function ? # 3Com 90x[B] +epic* at pci? dev ? function ? # SMC EPIC/100 Ethernet +esh* at pci? dev ? function ? # Essential HIPPI card +fpa* at pci? dev ? function ? # DEC DEFPA FDDI +fxp* at pci? dev ? function ? # Intel EtherExpress PRO 10+/100B +le* at pci? dev ? function ? # PCnet-PCI Ethernet +ne* at pci? dev ? function ? # NE2000-compatible Ethernet +tl* at pci? dev ? function ? # ThunderLAN-based Ethernet +vr* at pci? dev ? function ? # VIA Rhine Fast Ethernet +lmc* at pci? dev ? function ? # Lan Media Corp SSI/HSSI/DS3 + +# EISA network interfaces +ep* at eisa? slot ? # 3Com 3c579 Ethernet +fea* at eisa? slot ? # DEC DEFEA FDDI + +# ISA Plug-and-Play network interfaces +ep* at isapnp? # 3Com 3c509 Ethernet +ne* at isapnp? # NE2000-compatible Ethernet +tr* at isapnp? # IBM/3COM TROPIC Token-Ring + +# PCMCIA network interfaces +ep* at pcmcia? function ? # 3Com 3c589 and 3c562 Ethernet +mbe* at pcmcia? function ? # MB8696x based Ethernet +ne* at pcmcia? function ? # NE2000-compatible Ethernet +sm* at pcmcia? function ? # Megahertz Ethernet + +# ISA network interfaces +ate0 at isa? port 0x2a0 irq ? # AT1700 +cs0 at isa? port 0x300 iomem ? irq ? drq ? # CS8900 Ethernet +ec0 at isa? port 0x250 iomem 0xd8000 irq 9 # 3Com 3c503 Ethernet +eg0 at isa? port 0x280 irq 9 # 3C505 ethernet cards +el0 at isa? port 0x300 irq 9 # 3C501 ethernet cards +ep0 at isa? port ? irq ? # 3C509 ethernet cards +ef0 at isa? port 0x360 iomem 0xd0000 irq 7 # 3C507 +ai0 at isa? port 0x360 iomem 0xd0000 irq 7 # StarLAN +fmv0 at isa? port 0x2a0 irq ? # FMV-180 series +ix0 at isa? port 0x300 irq 10 # EtherExpress/16 +iy0 at isa? port 0x360 irq ? # EtherExpress PRO 10 ISA +lc0 at isa? port 0x320 iomem ? irq ? # DEC EtherWORKS III (LEMAC) +#depca0 at isa? port 0x300 iomem 0xc8000 iosiz 0x8000 irq 5 # DEPCA +#le* at depca? +nele0 at isa? port 0x320 irq 9 drq 7 # NE2100 +le* at nele? +bicc0 at isa? port 0x320 irq 10 drq 7 # BICC IsoLan +le* at bicc? +ne0 at isa? port 0x280 irq 9 # NE[12]000 ethernet cards +ne1 at isa? port 0x300 irq 10 +sm0 at isa? port 0x300 irq 10 # SMC91C9x Ethernet +tr0 at isa? port 0xa20 iomem 0xd8000 irq ? # IBM TROPIC based Token-Ring +tr1 at isa? port 0xa24 iomem 0xd0000 irq ? # IBM TROPIC based Token-Ring +tr* at isa? port ? irq ? # 3COM TROPIC based Token-Ring +we0 at isa? port 0x280 iomem 0xd0000 irq 9 # WD/SMC Ethernet +we1 at isa? port 0x300 iomem 0xcc000 irq 10 + +# CardBus network card +ex* at cardbus? # 3Com 3C575TX + +# MII/PHY support +exphy* at mii? phy ? # 3Com internal PHYs +icsphy* at mii? phy ? # Integrated Circuit Systems ICS1890 +inphy* at mii? phy ? # Intel 82555 PHYs +lxtphy* at mii? phy ? # Level One LXT-970 PHYs +nsphy* at mii? phy ? # NS83840 PHYs +qsphy* at mii? phy ? # Quality Semiconductor QS6612 PHYs +sqphy* at mii? phy ? # Seeq 80220/80221/80223 PHYs +tlphy* at mii? phy ? # ThunderLAN PHYs +ukphy* at mii? phy ? # generic unknown PHYs + +# USB Controller and Devices + +# PCI USB controllers +uhci* at pci? # Universal Host Controller (Intel) +ohci* at pci? # Open Host Controller + +# USB bus support +usb* at uhci? +usb* at ohci? + +# USB Hubs +uhub* at usb? +uhub* at uhub? port ? configuration ? interface ? + +# USB Mice +ums* at uhub? port ? configuration ? interface ? +wsmouse* at ums? + +# USB Keyboards +ukbd* at uhub? port ? configuration ? interface ? +wskbd* at ukbd? console ? + +# USB Generic HID devices +uhid* at uhub? port ? configuration ? interface ? + +# USB Printer +ulpt* at uhub? port ? configuration ? interface ? + +# USB Generic driver +ugen* at uhub? port ? configuration ? interface ? + +# Audio Devices + +# PCI audio devices +eap* at pci? dev ? function ? # Ensoniq AudioPCI +sv* at pci? dev ? function ? # S3 SonicVibes + +# ISA Plug-and-Play audio devices +ess* at isapnp? # ESS Tech ES1887, ES1888, ES888 audio +guspnp* at isapnp? # Gravis Ultra Sound PnP audio +sb* at isapnp? # SoundBlaster-compatible audio +wss* at isapnp? # Windows Sound System +ym* at isapnp? # Yamaha OPL3-SA3 audio + +# ISA audio devices +# the "aria" probe might give false hits +#aria0 at isa? port 0x290 irq 10 # Aria +gus0 at isa? port 0x220 irq 7 drq 1 drq2 6 # Gravis Ultra Sound +pas0 at isa? port 0x220 irq 7 drq 1 # ProAudio Spectrum +pss0 at isa? port 0x220 irq 7 drq 6 # Personal Sound System +sp0 at pss0 port 0x530 irq 10 drq 0 # sound port driver +sb0 at isa? port 0x220 irq 5 drq 1 drq2 5 # SoundBlaster +wss0 at isa? port 0x530 irq 10 drq 0 drq2 1 # Windows Sound System + +# OPL[23] FM syntheziers +#opl0 at isa? port 0x388 # use only if not attached to sound card +opl* at ess? +opl* at sb? +opl* at sv? + +# Audio support +#audio* at aria? +audio* at eap? +audio* at ess? +audio* at gus? +audio* at guspnp? +audio* at pas? +audio* at sb? +audio* at sp? +audio* at sv? +audio* at wss? +audio* at ym? + +# MIDI support +midi* at pcppi? # MIDI interface to the PC speaker +midi* at sb? # SB MPU401 port +midi* at opl? # OPL FM synth + +# The spkr driver provides a simple tone interface to the built in speaker. +#spkr0 at pcppi? # PC speaker + + +# Mice + +# ISA busmice +#lms0 at isa? port 0x23c irq 5 # Logitech bus mouse +#lms1 at isa? port 0x238 irq 5 +#mms0 at isa? port 0x23c irq 5 # Microsoft InPort mouse +#mms1 at isa? port 0x238 irq 5 +#wsmouse* at lms? +#wsmouse* at mms? +# backwards compatible versions +olms0 at isa? port 0x23c irq 5 # Logitech bus mouse +olms1 at isa? port 0x238 irq 5 +omms0 at isa? port 0x23c irq 5 # Microsoft InPort mouse +omms1 at isa? port 0x238 irq 5 +#opms0 at pc? irq 12 # PS/2 auxiliary port mouse +#opms0 at vt? irq 12 # PS/2 auxiliary port mouse + + +# Joysticks + +# ISA Plug-and-Play joysticks +joy* at isapnp? # Game ports (usually on audio cards) + +# ISA joysticks. Probe is a little strange; add only if you have one. +#joy0 at isa? port 0x201 + + +# Miscellaneous Devices + +# Planetconnect Satellite receiver driver. +#satlink0 at isa? port 0x300 drq 1 + + +# Pull in optional local configuration +include "arch/i386/conf/GENERIC.local" + + +# Pseudo-Devices + +# disk/mass storage pseudo-devices +pseudo-device ccd 4 # concatenated/striped disk devices +#pseudo-device raid 4 # RAIDframe disk driver +pseudo-device md 1 # memory disk device (ramdisk) +pseudo-device vnd 4 # disk-like interface to files + +# network pseudo-devices +pseudo-device bpfilter 8 # Berkeley packet filter +pseudo-device ipfilter # IP filter (firewall) and NAT +pseudo-device loop # network loopback +pseudo-device ppp 2 # Point-to-Point Protocol +pseudo-device sl 2 # Serial Line IP +pseudo-device strip 2 # Starmode Radio IP (Metricom) +pseudo-device tun 2 # network tunneling over tty +pseudo-device gre 2 # generic L3 over IP tunnel +pseudo-device ipip 2 # IP Encapsulation within IP (RFC 2003) + +# miscellaneous pseudo-devices +pseudo-device pty 64 # pseudo-terminals +pseudo-device tb 1 # tablet line discipline +pseudo-device sequencer 1 # MIDI sequencer +# rnd works; RND_COM does not on port i386 yet. +pseudo-device rnd # /dev/random and in-kernel generator +#options RND_COM # use "com" randomness as well (BROKEN) + +# a pseudo device needed for Coda # also needs CODA (above) +pseudo-device vcoda 4 # coda minicache <-> venus comm. diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386 index 27fc3af38bc2..9d0e46f97981 100644 --- a/sys/arch/i386/conf/files.i386 +++ b/sys/arch/i386/conf/files.i386 @@ -1,4 +1,4 @@ -# $NetBSD: files.i386,v 1.138 1999/09/09 03:52:21 itohy Exp $ +# $NetBSD: files.i386,v 1.139 1999/10/15 06:10:38 haya Exp $ # # new style config file for i386 architecture # @@ -275,6 +275,12 @@ include "compat/ossaudio/files.ossaudio" # network devices MII bus include "dev/mii/files.mii" +# +# CARDBUS +# +include "dev/cardbus/files.cardbus" +file arch/i386/i386/rbus_machdep.c cardbus + # XXXX pcic here because it needs to be late. The catch: pcic needs # to be late, so devices which attach to it are attached late. But it # needs to be before its isa and pci attachments. This answer is diff --git a/sys/arch/i386/i386/rbus_machdep.c b/sys/arch/i386/i386/rbus_machdep.c new file mode 100644 index 000000000000..7e9b62993813 --- /dev/null +++ b/sys/arch/i386/i386/rbus_machdep.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by HAYAKAWA Koichi. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id: rbus_machdep.c,v 1.1 1999/10/15 06:11:30 haya Exp $ */ + +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +#include +#include +#include + +#include + + + +/********************************************************************** + * void _i386_memio_unmap(bus_space_tag bst, bus_space_handle bsh, + * bus_size_t size, bus_addr_t *adrp) + * + * This function unmaps memory- or io-space mapped by the function + * _i386_memio_map(). This function works nearly as same as + * i386_memio_unmap(), but this function does not ask kernel + * built-in extents and returns physical address of the bus space, + * for the convenience of the extra extent manager. + * + * I suppose this function should be in arch/i386/i386/machdep.c, + * but it is not. + **********************************************************************/ +void +_i386_memio_unmap(t, bsh, size, adrp) + bus_space_tag_t t; + bus_space_handle_t bsh; + bus_size_t size; + bus_addr_t *adrp; +{ + u_long va, endva; + bus_addr_t bpa; + + /* + * Find the correct extent and bus physical address. + */ + if (t == I386_BUS_SPACE_IO) { + bpa = bsh; + } else if (t == I386_BUS_SPACE_MEM) { + if (bsh >= atdevbase && (bsh + size) <= (atdevbase + IOM_SIZE)) { + bpa = (bus_addr_t)ISA_PHYSADDR(bsh); + } else { + + va = i386_trunc_page(bsh); + endva = i386_round_page(bsh + size); + +#ifdef DIAGNOSTIC + if (endva <= va) { + panic("_i386_memio_unmap: overflow"); + } +#endif + +#if __NetBSD_Version__ > 104050000 + if (pmap_extract(pmap_kernel(), va, &bpa) == FALSE) { + panic("_i386_memio_unmap:i386/rbus_machdep.c wrong virtual address"); + } + bpa += (bsh & PGOFSET); +#else + bpa = pmap_extract(pmap_kernel(), va) + (bsh & PGOFSET); +#endif + + /* + * Free the kernel virtual mapping. + */ + uvm_km_free(kernel_map, va, endva - va); + } + } else { + panic("_i386_memio_unmap: bad bus space tag"); + } + + if (adrp != NULL) { + *adrp = bpa; + } +} + + + + +/********************************************************************** + * rbus_tag_t rbus_fakeparent_mem(struct pci_attach_args *pa) + * + * This function allocates a memory space from 1 GB to 1.25 GB. + **********************************************************************/ +rbus_tag_t +rbus_pccbb_parent_mem(pa) + struct pci_attach_args *pa; +{ + bus_addr_t start = 0x40000000; /* 1 GB */ + bus_size_t size = 0x08000000; /* 128 MB */ + bus_space_handle_t memh; /* fake */ + + start += pa->pa_function * size; + + bus_space_map(pa->pa_memt, start, size, 0, &memh); + + return rbus_new_root_delegate(pa->pa_memt, start, size, 0); +} + + +/********************************************************************** + * rbus_tag_t rbus_pccbb_parent_io(struct pci_attach_args *pa) + **********************************************************************/ +rbus_tag_t +rbus_pccbb_parent_io(pa) + struct pci_attach_args *pa; +{ + bus_addr_t start = 0x2000; + bus_size_t size = 0x0800; + bus_space_handle_t ioh; + + start += pa->pa_function * size; + + bus_space_map(pa->pa_iot, start, size, 0, &ioh); + + return rbus_new_root_delegate(pa->pa_iot, start, size, 0); +} diff --git a/sys/arch/i386/include/rbus_machdep.h b/sys/arch/i386/include/rbus_machdep.h new file mode 100644 index 000000000000..da1a9ad8f16d --- /dev/null +++ b/sys/arch/i386/include/rbus_machdep.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by HAYAKAWA Koichi. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id: rbus_machdep.h,v 1.1 1999/10/15 06:11:17 haya Exp $ */ + +#if !defined _ARCH_I386_I386_RBUS_MACHDEP_H_ +#define _ARCH_I386_I386_RBUS_MACHDEP_H_ + +struct pci_attach_args; /* XXX */ + +void _i386_memio_unmap __P((bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_addr_t *)); + +#define md_space_map(bt, physaddr, size, flags, bshp) \ + _i386_memio_map((bt), (physaddr), (size), (flags), (bshp)) + +#define md_space_unmap(bt, bsh, size, adrp) \ + _i386_memio_unmap((bt), (bsh), (size), (adrp)) + + +rbus_tag_t rbus_pccbb_parent_io __P((struct pci_attach_args *pa)); +rbus_tag_t rbus_pccbb_parent_mem __P((struct pci_attach_args *pa)); + +#endif /* _ARCH_I386_I386_RBUS_MACHDEP_H_ */ diff --git a/sys/arch/macppc/conf/files.macppc b/sys/arch/macppc/conf/files.macppc index 5fbc1aa8c37e..689033542235 100644 --- a/sys/arch/macppc/conf/files.macppc +++ b/sys/arch/macppc/conf/files.macppc @@ -1,4 +1,4 @@ -# $NetBSD: files.macppc,v 1.22 1999/07/21 19:20:04 tsubai Exp $ +# $NetBSD: files.macppc,v 1.23 1999/10/15 06:12:15 haya Exp $ # # macppc-specific configuration info @@ -162,3 +162,10 @@ attach macofcons at pci file arch/macppc/dev/ofcons.c macofcons needs-flag include "dev/usb/files.usb" + +# +# Machine-independent CardBus drivers +# +include "dev/files.cardbus" +include "dev/pcmcia/files.pcmcia" +file arch/macppc/macppc/rbus_machdep.c cardbus diff --git a/sys/arch/macppc/include/rbus_machdep.h b/sys/arch/macppc/include/rbus_machdep.h new file mode 100644 index 000000000000..0992487c5fdb --- /dev/null +++ b/sys/arch/macppc/include/rbus_machdep.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1999 + * TSUBAI Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id: rbus_machdep.h,v 1.1 1999/10/15 06:12:16 haya Exp $ */ + +#ifndef _MACHINE_RBUS_MACHDEP_H_ +#define _MACHINE_RBUS_MACHDEP_H_ + +struct pci_attach_args; +rbus_tag_t rbus_pccbb_parent_io __P((struct pci_attach_args *)); +rbus_tag_t rbus_pccbb_parent_mem __P((struct pci_attach_args *)); + +int md_space_map __P((bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *)); +void md_space_unmap __P((bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_addr_t *)); + +#endif /* _MACHINE_RBUS_MACHDEP_H_ */ diff --git a/sys/arch/macppc/macppc/rbus_machdep.c b/sys/arch/macppc/macppc/rbus_machdep.c new file mode 100644 index 000000000000..332349b899f4 --- /dev/null +++ b/sys/arch/macppc/macppc/rbus_machdep.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1999 + * TSUBAI Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id: rbus_machdep.c,v 1.1 1999/10/15 06:12:17 haya Exp $ */ + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include + +static void macppc_cardbus_init __P((pci_chipset_tag_t, pcitag_t)); + +#define DEBUG_ALLOC + +#ifdef DEBUG_ALLOC +# define DPRINTF printf +#else +# define DPRINTF while (0) printf +#endif + +int +md_space_map(t, bpa, size, flags, bshp) + bus_space_tag_t t; + bus_addr_t bpa; + bus_size_t size; + int flags; + bus_space_handle_t *bshp; +{ + DPRINTF("md_space_map: 0x%x, 0x%x, 0x%x\n", t, bpa, size); + + /* XXX */ + *bshp = t + bpa; + return 0; +} + +void +md_space_unmap(t, bsh, size, adrp) + bus_space_tag_t t; + bus_space_handle_t bsh; + bus_size_t size; + bus_addr_t *adrp; +{ + DPRINTF("md_space_unmap: 0x%x 0x%x\n", t, bsh); + + /* XXX */ + if (adrp) + *adrp = bsh - t; +} + +rbus_tag_t +rbus_pccbb_parent_mem(pa) + struct pci_attach_args *pa; +{ + bus_addr_t start; + bus_size_t size; + int node, reg[5]; + + macppc_cardbus_init(pa->pa_pc, pa->pa_tag); + + node = pcidev_to_ofdev(pa->pa_pc, pa->pa_tag); + OF_getprop(node, "assigned-addresses", reg, sizeof(reg)); + + start = reg[2]; + size = reg[4]; + + /* XXX PowerBook G3 */ + if (size < 0x10000) { + start = 0x90000000; + size = 0x10000000; + } + + battable[start >> 28].batl = BATL(start, BAT_I); + battable[start >> 28].batu = BATU(start); + + return rbus_new_root_delegate(pa->pa_memt, start, size, 0); +} + +rbus_tag_t +rbus_pccbb_parent_io(pa) + struct pci_attach_args *pa; +{ + bus_addr_t start = 0x2000; + bus_size_t size = 0x0800; + + start += pa->pa_function * size; + return rbus_new_root_delegate(pa->pa_iot, start, size, 0); + + /* XXX we should use ``offset''? */ +} + +void +macppc_cardbus_init(pc, tag) + pci_chipset_tag_t pc; + pcitag_t tag; +{ + u_int x; + static int initted = 0; + + if (initted) + return; + initted = 1; + + if (pc == PCI_CHIPSET_MPC106) { + /* For CardBus card. */ + pci_conf_write(pc, tag, 0x18, 0x10010100); + + /* Route INTA to MFUNC0 */ + x = pci_conf_read(pc, tag, 0x8c); + x |= 0x02; + pci_conf_write(pc, tag, 0x8c, x); + + /* Set Subordinate bus number to 1 */ + tag = pci_make_tag(pc, 0, 0, 0); + x = pci_conf_read(pc, tag, 0x40); + x |= 1 << 8; + pci_conf_write(pc, tag, 0x40, x); + } +} diff --git a/sys/conf/files b/sys/conf/files index aca084a40bc1..a82a8c21f87c 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $NetBSD: files,v 1.323 1999/10/14 18:42:15 jdolecek Exp $ +# $NetBSD: files,v 1.324 1999/10/15 06:09:29 haya Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -409,6 +409,8 @@ define tcbus { } # TurboChannel attachment define usbus { } # USB attachment define vmebus { } # VME bus attachment define pcmciabus { [controller = -1], [socket = -1]} # PCMCIA bus attachment +define cbbus {[slot = -1]} # CardBus attachment +define pcmciaslot {[slot = -1]} # PCMCIA slot itself: # We need the USB bus controllers here so different busses can # use them in an 'attach-with'. diff --git a/sys/dev/cardbus/Makefile.cardbusdevs b/sys/dev/cardbus/Makefile.cardbusdevs new file mode 100644 index 000000000000..361f6d091430 --- /dev/null +++ b/sys/dev/cardbus/Makefile.cardbusdevs @@ -0,0 +1,7 @@ +# $Id: Makefile.cardbusdevs,v 1.1 1999/10/15 06:07:17 haya Exp $ + +AWK= awk + +cardbusdevs.h cardbusdevs_data.h: cardbusdevs devlist2h.awk + /bin/rm -f cardbusdevs.h cardbusdevs_data.h + ${AWK} -f devlist2h.awk cardbusdevs diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c new file mode 100644 index 000000000000..ff39f0fe05d9 --- /dev/null +++ b/sys/dev/cardbus/cardbus.c @@ -0,0 +1,609 @@ +/* $Id: cardbus.c,v 1.1 1999/10/15 06:07:17 haya Exp $ */ + +/* + * Copyright (c) 1997 and 1998 HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by HAYAKAWA Koichi. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* #define CARDBUS_DEBUG */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#if pccard +#include +#include +#else +#include +#include +#endif + +#include /* XXX */ +#include /* XXX */ + +#if defined CARDBUS_DEBUG +#define STATIC +#define DPRINTF(a) printf a +#define DDELAY(x) delay((x)*1000*1000) +#else +#define STATIC static +#define DPRINTF(a) +#endif + + + +STATIC void cardbusattach __P((struct device *, struct device *, void *)); +/* STATIC int cardbusprint __P((void *, const char *)); */ +int cardbus_attach_card __P((struct cardbus_softc *)); + +#if !defined __BROKEN_INDIRECT_CONFIG +STATIC int cardbusmatch __P((struct device *, struct cfdata *, void *)); +static int cardbussubmatch __P((struct device *, struct cfdata *, void *)); +#else +STATIC int cardbusmatch __P((struct device *, void *, void *)); +static int cardbussubmatch __P((struct device *, void *, void *)); +#endif +static int cardbusprint __P((void *, const char *)); + +static int decode_tuples __P((u_int8_t *, int)); + + +struct cfattach cardbus_ca = { + sizeof(struct cardbus_softc), cardbusmatch, cardbusattach +}; + +#ifndef __NetBSD_Version__ +struct cfdriver cardbus_cd = { + NULL, "cardbus", DV_DULL +}; +#endif + + +STATIC int +#if defined __BROKEN_INDIRECT_CONFIG +cardbusmatch(parent, match, aux) + struct device *parent; + void *match; + void *aux; +#else +cardbusmatch(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +#endif +{ +#if defined __BROKEN_INDIRECT_CONFIG + struct cfdata *cf = match; +#endif + struct cbslot_attach_args *cba = aux; + + if (strcmp(cba->cba_busname, cf->cf_driver->cd_name)) { + DPRINTF(("cardbusmatch: busname differs %s <=> %s\n", + cba->cba_busname, cf->cf_driver->cd_name)); + return 0; + } + + /* which function? */ + if (cf->cbslotcf_func != CBSLOT_UNK_FUNC && + cf->cbslotcf_func != cba->cba_function) { + DPRINTF(("pccardmatch: function differs %d <=> %d\n", + cf->cbslotcf_func, cba->cba_function)); + return 0; + } + + if (cba->cba_function < 0 || cba->cba_function > 255) { + return 0; + } + + return 1; +} + + + +STATIC void +cardbusattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct cardbus_softc *sc = (void *)self; + struct cbslot_attach_args *cba = aux; + int cdstatus; + + sc->sc_bus = cba->cba_bus; + sc->sc_device = cba->cba_function; + sc->sc_intrline = cba->cba_intrline; + sc->sc_cacheline = cba->cba_cacheline; + sc->sc_lattimer = cba->cba_lattimer; + + printf(" bus %d device %d\n", sc->sc_bus, sc->sc_device); + printf("cacheline 0x%x, lattimer 0x%x", sc->sc_cacheline,sc->sc_lattimer); + + sc->sc_iot = cba->cba_iot; /* CardBus I/O space tag */ + sc->sc_memt = cba->cba_memt; /* CardBus MEM space tag */ + sc->sc_dmat = cba->cba_dmat; /* DMA tag */ + sc->sc_cc = cba->cba_cc; + sc->sc_cf = cba->cba_cf; + +#if rbus + sc->sc_rbus_iot = cba->cba_rbus_iot; + sc->sc_rbus_memt = cba->cba_rbus_memt; +#endif + + sc->sc_funcs = NULL; + + cdstatus = 0; +} + + + + +/* + * int cardbus_attach_card(struct cardbus_softc *sc) + * + * This function attaches the card on the slot: turns on power, + * reads and analyses tuple, sets consifuration index. + * + * This function returns the number of recognised device functions. + * If no functions are recognised, return 0. + */ +int +cardbus_attach_card(sc) + struct cardbus_softc *sc; +{ + cardbus_chipset_tag_t cc; + cardbus_function_tag_t cf; + int cdstatus; + cardbustag_t tag; + cardbusreg_t id, class, cis_ptr; + cardbusreg_t bhlc; + u_int8_t tuple[2048]; + int function, nfunction; + struct cardbus_devfunc **previous_next = &(sc->sc_funcs); + struct device *csc; + int no_work_funcs = 0; + cardbus_devfunc_t ct; + + cc = sc->sc_cc; + cf = sc->sc_cf; + + DPRINTF(("cardbus_attach_card: cb%d start\n", sc->sc_dev.dv_unit)); + + /* inspect initial voltage */ + if (0 == (cdstatus = (cf->cardbus_ctrl)(cc, CARDBUS_CD))) { + DPRINTF(("cardbusattach: no CardBus card on cb%d\n", sc->sc_dev.dv_unit)); + return 0; + } + + if (cdstatus & CARDBUS_3V_CARD) { + cf->cardbus_power(cc, CARDBUS_VCC_3V); + sc->sc_poweron_func = 1; /* function 0 on */ + } + + (cf->cardbus_ctrl)(cc, CARDBUS_RESET); + + function = 0; + + tag = cardbus_make_tag(cc, cf, sc->sc_bus, sc->sc_device, function); + + /* + * Wait until power comes up. Maxmum 500 ms. + */ + { + int i; + for (i = 0; i < 5; ++i) { + id = cardbus_conf_read(cc, cf, tag, CARDBUS_ID_REG); + if (id != 0xffffffff && id != 0) { + break; + } + delay(100*1000); /* or tsleep */ + } + if (i == 5) { + return 0; + } + } + + bhlc = cardbus_conf_read(cc, cf, tag, CARDBUS_BHLC_REG); + if (CARDBUS_LATTIMER(bhlc) < 0x10) { + bhlc &= (CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT); + bhlc |= (0x10 << CARDBUS_LATTIMER_SHIFT); + cardbus_conf_write(cc, cf, tag, CARDBUS_BHLC_REG, bhlc); + } + + nfunction = CARDBUS_HDRTYPE_MULTIFN(bhlc) ? 8 : 1; + + /* + * XXX multi-function card + * + * I don't know how to process CIS information for + * multi-function cards. + */ + + id = cardbus_conf_read(cc, cf, tag, CARDBUS_ID_REG); + class = cardbus_conf_read(cc, cf, tag, CARDBUS_CLASS_REG); + cis_ptr = cardbus_conf_read(cc, cf, tag, CARDBUS_CIS_REG); + + DPRINTF(("cardbus_attach_card: Vendor 0x%x, Product 0x%x, CIS 0x%x\n", + CARDBUS_VENDOR(id), CARDBUS_PRODUCT(id), cis_ptr)); + + bzero(tuple, 2048); + + if (CARDBUS_CIS_ASI_TUPLE == (CARDBUS_CIS_ASI(cis_ptr))) { + /* Tuple is in Cardbus config space */ + int i = cis_ptr & CARDBUS_CIS_ADDRMASK; + int j = 0; + + for (; i < 0xff; i += 4) { + u_int32_t e = (cf->cardbus_conf_read)(cc, tag, i); + tuple[j] = 0xff & e; + e >>= 8; + tuple[j + 1] = 0xff & e; + e >>= 8; + tuple[j + 2] = 0xff & e; + e >>= 8; + tuple[j + 3] = 0xff & e; + j += 4; + } + } else if (CARDBUS_CIS_ASI(cis_ptr) <= CARDBUS_CIS_ASI_BAR5) { + /* int bar = CARDBUS_CIS_ASI_BAR(cis_ptr);*/ + } + + + decode_tuples(tuple, 2048); + + { + struct cardbus_attach_args ca; + + if (NULL == (ct = (cardbus_devfunc_t)malloc(sizeof(struct cardbus_devfunc), + M_DEVBUF, M_NOWAIT))) { + panic("no room for cardbus_tag"); + } + + ct->ct_cc = sc->sc_cc; + ct->ct_cf = sc->sc_cf; + ct->ct_bus = sc->sc_bus; + ct->ct_dev = sc->sc_device; + ct->ct_func = function; + ct->ct_sc = sc; + ct->ct_next = NULL; + *previous_next = ct; + + ca.ca_unit = sc->sc_dev.dv_unit; + ca.ca_ct = ct; + + ca.ca_iot = sc->sc_iot; + ca.ca_memt = sc->sc_memt; + ca.ca_dmat = sc->sc_dmat; + + ca.ca_tag = tag; + ca.ca_device = sc->sc_device; + ca.ca_function = function; + ca.ca_id = id; + ca.ca_class = class; + + ca.ca_intrline = sc->sc_intrline; + + if (NULL == (csc = config_found_sm((void *)sc, &ca, cardbusprint, cardbussubmatch))) { + /* do not match */ + cf->cardbus_power(cc, CARDBUS_VCC_0V); + sc->sc_poweron_func = 0; /* no functions on */ + free(cc, M_DEVBUF); + } else { + /* found */ + previous_next = &(ct->ct_next); + ct->ct_device = csc; + ++no_work_funcs; + } + } + + return no_work_funcs; +} + + +static int +#ifdef __BROKEN_INDIRECT_CONFIG +cardbussubmatch(parent, match, aux) +#else +cardbussubmatch(parent, cf, aux) +#endif + struct device *parent; +#ifdef __BROKEN_INDIRECT_CONFIG + void *match; +#else + struct cfdata *cf; +#endif + void *aux; +{ +#ifdef __BROKEN_INDIRECT_CONFIG + struct cfdata *cf = match; +#endif + struct cardbus_attach_args *ca = aux; + + if (cf->cardbuscf_dev != CARDBUS_UNK_DEV && + cf->cardbuscf_dev != ca->ca_unit) { + return 0; + } + if (cf->cardbuscf_function != CARDBUS_UNK_FUNCTION && + cf->cardbuscf_function != ca->ca_function) { + return 0; + } + + return ((*cf->cf_attach->ca_match)(parent, cf, aux)); +} + + + +static int +cardbusprint(aux, pnp) + void *aux; + const char *pnp; +{ + register struct cardbus_attach_args *ca = aux; + char devinfo[256]; + + if (pnp) { + pci_devinfo(ca->ca_id, ca->ca_class, 1, devinfo); + printf("%s at %s", devinfo, pnp); + } + printf(" dev %d function %d", ca->ca_device, ca->ca_function); + + return UNCONF; +} + + + + + + +/* + * void *cardbus_intr_establish(cc, cf, irq, level, func, arg) + * Interrupt handler of pccard. + * args: + * cardbus_chipset_tag_t *cc + * int irq: + */ +void * +cardbus_intr_establish(cc, cf, irq, level, func, arg) + cardbus_chipset_tag_t cc; + cardbus_function_tag_t cf; + cardbus_intr_handle_t irq; + int level; + int (*func) __P((void *)); + void *arg; +{ + DPRINTF(("- cardbus_intr_establish: irq %d\n", irq)); + + return (*cf->cardbus_intr_establish)(cc, irq, level, func, arg); +} + + + +/* + * void cardbus_intr_disestablish(cc, cf, handler) + * Interrupt handler of pccard. + * args: + * cardbus_chipset_tag_t *cc + */ +void +cardbus_intr_disestablish(cc, cf, handler) + cardbus_chipset_tag_t cc; + cardbus_function_tag_t cf; + void *handler; +{ + DPRINTF(("- pccard_intr_disestablish\n")); + + (*cf->cardbus_intr_disestablish)(cc, handler); + return; +} + + + +/* + * int cardbus_function_enable(cardbus_devfunc_t ct) + * + * This function enables a function on a card. When no power is + * applied on the card, power will be applied on it. + */ +int +cardbus_function_enable(ct) + cardbus_devfunc_t ct; +{ + struct cardbus_softc *sc = ct->ct_sc; + int func = ct->ct_func; + cardbus_chipset_tag_t cc = sc->sc_cc; + cardbus_function_tag_t cf = sc->sc_cf; + cardbusreg_t command; + cardbustag_t tag; + + DPRINTF(("entering cardbus_function_enable... ")); + + /* entering critical area */ + + if (sc->sc_poweron_func == 0) { + /* no functions are enabled */ + (*cf->cardbus_power)(cc, CARDBUS_VCC_3V); /* XXX: sc_vold should be used */ + (*cf->cardbus_ctrl)(cc, CARDBUS_RESET); + } + + sc->sc_poweron_func |= (1 << func); + + /* exiting critical area */ + + tag = Cardbus_make_tag(ct); + command = cardbus_conf_read(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG); + command |= (CARDBUS_COMMAND_MEM_ENABLE | CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE); /* XXX: good guess needed */ + cardbus_conf_write(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG, command); + Cardbus_free_tag(ct, tag); + + + DPRINTF(("%x\n", sc->sc_poweron_func)); + + return 0; +} + + +/* + * int cardbus_function_disable(cardbus_devfunc_t ct) + * + * This function disable a function on a card. When no functions are + * enabled, it turns off the power. + */ +int +cardbus_function_disable(ct) + cardbus_devfunc_t ct; +{ + struct cardbus_softc *sc = ct->ct_sc; + int func = ct->ct_func; + cardbus_chipset_tag_t cc = sc->sc_cc; + cardbus_function_tag_t cf = sc->sc_cf; + + DPRINTF(("entering cardbus_enable_disable... ")); + + sc->sc_poweron_func &= ~(1 << func); + + DPRINTF(("%x\n", sc->sc_poweron_func)); + + if (sc->sc_poweron_func == 0) { + /* power-off because no functions are enabled */ + (*cf->cardbus_power)(cc, CARDBUS_VCC_0V); + } + + return 0; +} + + + + + + + +/* + * below this line, there are some functions for decoding tuples. + * They should go out from this file. + */ + +static u_int8_t *decode_tuple __P((u_int8_t *)); +static char *tuple_name __P((int)); + +static int +decode_tuples(tuple, buflen) + u_int8_t *tuple; + int buflen; +{ + u_int8_t *tp = tuple; + + if (CISTPL_LINKTARGET != *tuple) { + DPRINTF(("WRONG TUPLE: 0x%x\n", *tuple)); + return 0; + } + + while (NULL != (tp = decode_tuple(tp))) { + if (tuple + buflen < tp) { + break; + } + } + + return 1; +} + + +static u_int8_t * +decode_tuple(tuple) + u_int8_t *tuple; +{ + u_int8_t type; + u_int8_t len; + int i; + + type = tuple[0]; + len = tuple[1] + 2; + + printf("tuple: %s len %d\n", tuple_name(type), len); + if (CISTPL_END == type) { + return NULL; + } + + for (i = 0; i < len; ++i) { + if (i % 16 == 0) { + printf(" 0x%2x:", i); + } + printf(" %x",tuple[i]); + if (i % 16 == 15) { + printf("\n"); + } + } + if (i % 16 != 0) { + printf("\n"); + } + + return tuple + len; +} + + +static char * +tuple_name(type) + int type; +{ + static char *tuple_name_s [] = { + "TPL_NULL", "TPL_DEVICE", "Reserved", "Reserved", /* 0-3 */ + "CONFIG_CB", "CFTABLE_ENTRY_CB", "Reserved", "BAR", /* 4-7 */ + "Reserved", "Reserved", "Reserved", "Reserved", /* 8-B */ + "Reserved", "Reserved", "Reserved", "Reserved", /* C-F */ + "CHECKSUM", "LONGLINK_A", "LONGLINK_C", "LINKTARGET", /* 10-13 */ + "NO_LINK", "VERS_1", "ALTSTR", "DEVICE_A", + "JEDEC_C", "JEDEC_A", "CONFIG", "CFTABLE_ENTRY", + "DEVICE_OC", "DEVICE_OA", "DEVICE_GEO", "DEVICE_GEO_A", + "MANFID", "FUNCID", "FUNCE", "SWIL", /* 20-23 */ + "Reserved", "Reserved", "Reserved", "Reserved", /* 24-27 */ + "Reserved", "Reserved", "Reserved", "Reserved", /* 28-2B */ + "Reserved", "Reserved", "Reserved", "Reserved", /* 2C-2F */ + "Reserved", "Reserved", "Reserved", "Reserved", /* 30-33 */ + "Reserved", "Reserved", "Reserved", "Reserved", /* 34-37 */ + "Reserved", "Reserved", "Reserved", "Reserved", /* 38-3B */ + "Reserved", "Reserved", "Reserved", "Reserved", /* 3C-3F */ + "VERS_2", "FORMAT", "GEOMETRY", "BYTEORDER", + "DATE", "BATTERY", "ORG" + }; +#define NAME_LEN(x) (sizeof x / sizeof(x[0])) + + if (type > 0 && type < NAME_LEN(tuple_name_s)) { + return tuple_name_s[type]; + } else if (0xff == type) { + return "END"; + } else { + return "Reserved"; + } +} diff --git a/sys/dev/cardbus/cardbus_map.c b/sys/dev/cardbus/cardbus_map.c new file mode 100644 index 000000000000..34e2c894d831 --- /dev/null +++ b/sys/dev/cardbus/cardbus_map.c @@ -0,0 +1,373 @@ +/* $Id: cardbus_map.c,v 1.1 1999/10/15 06:07:18 haya Exp $ */ + +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by HAYAKAWA Koichi. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#define CARDBUS_MAP_DEBUG 1 + +#include +#include +#include +#include + +#include + +#include + +#include /* XXX */ + +#if defined DEBUG && !defined CARDBUS_MAP_DEBUG +#define CARDBUS_MAP_DEBUG +#endif + +#if defined CARDBUS_MAP_DEBUG +#define STATIC +#define DPRINTF(a) printf a +#else +#define STATIC static +#define DPRINTF(a) +#endif + + +static int cardbus_io_find __P((cardbus_chipset_tag_t, cardbus_function_tag_t, + cardbustag_t, int, cardbusreg_t, + bus_addr_t *, bus_size_t *, int *)); +static int cardbus_mem_find __P((cardbus_chipset_tag_t, cardbus_function_tag_t, + cardbustag_t, int, cardbusreg_t, + bus_addr_t *, bus_size_t *, int *)); + +/* + * static int cardbus_io_find(cardbus_chipset_tag_t cc, + * cardbus_function_tag_t cf, cardbustag_t tag, + * int reg, cardbusreg_t type, bus_addr_t *basep, + * bus_size_t *sizep, int *flagsp) + * This code is stallen from sys/dev/pci_map.c. + */ +static int +cardbus_io_find(cc, cf, tag, reg, type, basep, sizep, flagsp) + cardbus_chipset_tag_t cc; + cardbus_function_tag_t cf; + cardbustag_t tag; + int reg; + cardbusreg_t type; + bus_addr_t *basep; + bus_size_t *sizep; + int *flagsp; +{ + cardbusreg_t address, mask; + int s; + + if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) { + panic("cardbus_io_find: bad request"); + } + + /* + * Section 6.2.5.1, `Address Maps', tells us that: + * + * 1) The builtin software should have already mapped the device in a + * reasonable way. + * + * 2) A device which wants 2^n bytes of memory will hardwire the bottom + * n bits of the address to 0. As recommended, we write all 1s and see + * what we get back. + */ + s = splhigh(); + address = cardbus_conf_read(cc, cf, tag, reg); + cardbus_conf_write(cc, cf, tag, reg, 0xffffffff); + mask = cardbus_conf_read(cc, cf, tag, reg); + cardbus_conf_write(cc, cf, tag, reg, address); + splx(s); + + if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) { + printf("pci_io_find: expected type i/o, found mem\n"); + return 1; + } + + if (PCI_MAPREG_IO_SIZE(mask) == 0) { + printf("pci_io_find: void region\n"); + return (1); + } + + if (basep != 0) { + *basep = PCI_MAPREG_IO_ADDR(address); + } + if (sizep != 0) { + *sizep = PCI_MAPREG_IO_SIZE(mask); + } + if (flagsp != 0) { + *flagsp = 0; + } + + return 0; +} + + + +/* + * static int cardbus_mem_find(cardbus_chipset_tag_t cc, + * cardbus_function_tag_t cf, cardbustag_t tag, + * int reg, cardbusreg_t type, bus_addr_t *basep, + * bus_size_t *sizep, int *flagsp) + * This code is stallen from sys/dev/pci_map.c. + */ +static int +cardbus_mem_find(cc, cf, tag, reg, type, basep, sizep, flagsp) + cardbus_chipset_tag_t cc; + cardbus_function_tag_t cf; + cardbustag_t tag; + int reg; + cardbusreg_t type; + bus_addr_t *basep; + bus_size_t *sizep; + int *flagsp; +{ + cardbusreg_t address, mask; + int s; + + if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) { + panic("cardbus_find_mem: bad request"); + } + + /* + * Section 6.2.5.1, `Address Maps', tells us that: + * + * 1) The builtin software should have already mapped the device in a + * reasonable way. + * + * 2) A device which wants 2^n bytes of memory will hardwire the bottom + * n bits of the address to 0. As recommended, we write all 1s and see + * what we get back. + */ + s = splhigh(); + address = cardbus_conf_read(cc, cf, tag, reg); + cardbus_conf_write(cc, cf, tag, reg, 0xffffffff); + mask = cardbus_conf_read(cc, cf, tag, reg); + cardbus_conf_write(cc, cf, tag, reg, address); + splx(s); + + if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) { + printf("cardbus_mem_find: expected type mem, found i/o\n"); + return 1; + } + if (PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE(type)) { + printf("cardbus_mem_find: expected mem type %08x, found %08x\n", + PCI_MAPREG_MEM_TYPE(type), + PCI_MAPREG_MEM_TYPE(address)); + return 1; + } + + if (PCI_MAPREG_MEM_SIZE(mask) == 0) { + printf("cardbus_mem_find: void region\n"); + return 1; + } + + switch (PCI_MAPREG_MEM_TYPE(address)) { + case PCI_MAPREG_MEM_TYPE_32BIT: + case PCI_MAPREG_MEM_TYPE_32BIT_1M: + break; + case PCI_MAPREG_MEM_TYPE_64BIT: + printf("pci_mem_find: 64-bit memory mapping register\n"); + return 1; + default: + printf("cardbus_mem_find: reserved mapping register type\n"); + return 1; + } + + if (basep != 0) { + *basep = PCI_MAPREG_MEM_ADDR(address); + } + if (sizep != 0) { + *sizep = PCI_MAPREG_MEM_SIZE(mask); + } + if (flagsp != 0) { + *flagsp = PCI_MAPREG_MEM_CACHEABLE(address) ? BUS_SPACE_MAP_CACHEABLE : 0; + } + + return 0; +} + + + + +/* + * int cardbus_mapreg_map(cardbus_devfunc_t, int, cardbusreg_t, + * int bus_space_tag_t *, bus_space_handle_t *, + * bus_addr_t *, bus_size_t *) + * This function maps bus-space on the value of Base Address + * Register (BAR) indexed by the argument `reg' (the second argument). + * When the value of the BAR is not valid, such as 0x00000000, a new + * address should be allocated for the BAR and new address values is + * written on the BAR. + */ +int +cardbus_mapreg_map(ct, reg, type, busflags, tagp, handlep, basep, sizep) + cardbus_devfunc_t ct; + int reg, busflags; + cardbusreg_t type; + bus_space_tag_t *tagp; + bus_space_handle_t *handlep; + bus_addr_t *basep; + bus_size_t *sizep; +{ + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; + bus_space_tag_t bustag; +#if rbus + rbus_tag_t rbustag; +#endif + bus_space_handle_t handle; + bus_addr_t base; + bus_size_t size; + int flags; + int status = 0; + + cardbustag_t tag = cardbus_make_tag(cc, cf, ct->ct_bus, ct->ct_dev, ct->ct_func); + + DPRINTF(("cardbus_mapreg_map called: %s %x\n", ct->ct_sc->sc_dev.dv_xname, + type)); + + if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) { + if (cardbus_io_find(cc, cf, tag, reg, type, &base, &size, &flags)) { + status = 1; + } + bustag = ct->ct_sc->sc_iot; +#if rbus + rbustag = ct->ct_sc->sc_rbus_iot; +#endif + } else { + if (cardbus_mem_find(cc, cf, tag, reg, type, &base, &size, &flags)){ + status = 1; + } + bustag = ct->ct_sc->sc_memt; +#if rbus + rbustag = ct->ct_sc->sc_rbus_memt; +#endif + } + if (status == 0) { +#if rbus + bus_addr_t mask = size - 1; + if (base != 0) { + mask = 0xffffffff; + } + if ((*cf->cardbus_space_alloc)(cc, rbustag, base, size, mask, size, + busflags | flags, &base, &handle)) { + panic("io alloc"); + } +#else + bus_addr_t start = 0x8300; + bus_addr_t end = 0x8400; + if (base != 0) { + bus_addr_t start = base; + bus_addr_t end = base + size; + } + if (bus_space_alloc(bustag, start, end, size, size, 0, 0, &base, &handle)) { + panic("io alloc"); + } +#endif + } + cardbus_conf_write(cc, cf, tag, reg, base); + + DPRINTF(("cardbus_mapreg_map: physaddr %lx\n", base)); + + if (tagp != 0) { + *tagp = bustag; + } + if (handlep != 0) { + *handlep = handle; + } + if (basep != 0) { + *basep = base; + } + if (sizep != 0) { + *sizep = size; + } + return 0; +} + + + + + + +/* + * int cardbus_save_bar(cardbus_devfunc_t); + * + * This function saves the Base Address Registers at the CardBus + * function denoted by the argument. + */ +int cardbus_save_bar(ct) + cardbus_devfunc_t ct; +{ + cardbustag_t tag = Cardbus_make_tag(ct); + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; + + ct->ct_bar[0] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE0_REG); + ct->ct_bar[1] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE1_REG); + ct->ct_bar[2] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE2_REG); + ct->ct_bar[3] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE3_REG); + ct->ct_bar[4] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE4_REG); + ct->ct_bar[5] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE5_REG); + + DPRINTF(("cardbus_save_bar: %x %x\n", ct->ct_bar[0], ct->ct_bar[1])); + + Cardbus_free_tag(ct, tag); + + return 0; +} + + + +/* + * int cardbus_restore_bar(cardbus_devfunc_t); + * + * This function saves the Base Address Registers at the CardBus + * function denoted by the argument. + */ +int cardbus_restore_bar(ct) + cardbus_devfunc_t ct; +{ + cardbustag_t tag = Cardbus_make_tag(ct); + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; + + cardbus_conf_write(cc, cf, tag, CARDBUS_BASE0_REG, ct->ct_bar[0]); + cardbus_conf_write(cc, cf, tag, CARDBUS_BASE1_REG, ct->ct_bar[1]); + cardbus_conf_write(cc, cf, tag, CARDBUS_BASE2_REG, ct->ct_bar[2]); + cardbus_conf_write(cc, cf, tag, CARDBUS_BASE3_REG, ct->ct_bar[3]); + cardbus_conf_write(cc, cf, tag, CARDBUS_BASE4_REG, ct->ct_bar[4]); + cardbus_conf_write(cc, cf, tag, CARDBUS_BASE5_REG, ct->ct_bar[5]); + + Cardbus_free_tag(ct, tag); + return 0; +} diff --git a/sys/dev/cardbus/cardbusdevs b/sys/dev/cardbus/cardbusdevs new file mode 100644 index 000000000000..8e75f5a0f361 --- /dev/null +++ b/sys/dev/cardbus/cardbusdevs @@ -0,0 +1,69 @@ +$Id: cardbusdevs,v 1.1 1999/10/15 06:07:18 haya Exp $ + +/* + * Copyright (C) 1999 Hayakawa Koichi. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the author + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This code is stollen from sys/dev/pci/pcidevs + */ + + +/* + * List of known CardBus vendors + */ + +vendor DEC 0x1011 Digital Equipment +vendor 3COM 0x10B7 3Com +vendor ADP 0x9004 Adaptec +vendor ADP2 0x9005 Adaptec (2nd PCI Vendor ID) +vendor OPTI 0x1045 Opti +vendor INTEL 0x8086 Intel + +/* + * List of known products. Grouped by vendor. + */ + +/* 3COM Products */ + +product 3COM 3C575TX 0x5057 3c575 100Base-TX +product 3COM 3C575BTX 0x5157 3c575B 100Base-TX + +/* Adaptec products */ +product ADP 1480 0x6075 APA-1480 + +/* DEC products */ +product DEC 21142 0x0019 DECchip 21142/3 + +/* Intel products */ +product INTEL 82557 0x1229 82557 Fast Ethernet LAN Controller + +/* Opti products */ +product OPTI 82C861 0xc861 82C861 USB Host Controller (OHCI) diff --git a/sys/dev/cardbus/cardbusvar.h b/sys/dev/cardbus/cardbusvar.h new file mode 100644 index 000000000000..e386ffaff62f --- /dev/null +++ b/sys/dev/cardbus/cardbusvar.h @@ -0,0 +1,365 @@ +/* $Id: cardbusvar.h,v 1.1 1999/10/15 06:07:19 haya Exp $ */ + +/* + * Copyright (c) 1998 and 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the author. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined SYS_DEV_CARDBUS_CARDBUSVAR_H +#define SYS_DEV_CARDBUS_CARDBUSVAR_H + +#include /* for pcitag_t */ + +#if 1 +#include +#endif + + + +typedef void *cardbus_chipset_tag_t; +typedef int cardbus_intr_handle_t; + + +/* XXX they must be in cardbusreg.h */ +typedef u_int32_t cardbusreg_t; +typedef pcitag_t cardbustag_t; +typedef int cardbus_intr_line_t; + +#define CARDBUS_ID_REG 0x00 + +typedef u_int16_t cardbus_vendor_id_t; +typedef u_int16_t cardbus_product_id_t; + +# define CARDBUS_VENDOR_SHIFT 0 +# define CARDBUS_VENDOR_MASK 0xffff +# define CARDBUS_VENDOR(id) \ + (((id) >> CARDBUS_VENDOR_SHIFT) & CARDBUS_VENDOR_MASK) + +# define CARDBUS_PRODUCT_SHIFT 16 +# define CARDBUS_PRODUCT_MASK 0xffff +# define CARDBUS_PRODUCT(id) \ + (((id) >> CARDBUS_PRODUCT_SHIFT) & CARDBUS_PRODUCT_MASK) + + +#define CARDBUS_COMMAND_STATUS_REG 0x04 + +# define CARDBUS_COMMAND_IO_ENABLE 0x00000001 +# define CARDBUS_COMMAND_MEM_ENABLE 0x00000002 +# define CARDBUS_COMMAND_MASTER_ENABLE 0x00000004 + + +#define CARDBUS_CLASS_REG 0x08 + +/* BIST, Header Type, Latency Timer, Cache Line Size */ +#define CARDBUS_BHLC_REG 0x0c + +#define CARDBUS_BIST_SHIFT 24 +#define CARDBUS_BIST_MASK 0xff +#define CARDBUS_BIST(bhlcr) \ + (((bhlcr) >> CARDBUS_BIST_SHIFT) & CARDBUS_BIST_MASK) + +#define CARDBUS_HDRTYPE_SHIFT 16 +#define CARDBUS_HDRTYPE_MASK 0xff +#define CARDBUS_HDRTYPE(bhlcr) \ + (((bhlcr) >> CARDBUS_HDRTYPE_SHIFT) & CARDBUS_HDRTYPE_MASK) + +#define CARDBUS_HDRTYPE_TYPE(bhlcr) \ + (CARDBUS_HDRTYPE(bhlcr) & 0x7f) +#define CARDBUS_HDRTYPE_MULTIFN(bhlcr) \ + ((CARDBUS_HDRTYPE(bhlcr) & 0x80) != 0) + +#define CARDBUS_LATTIMER_SHIFT 8 +#define CARDBUS_LATTIMER_MASK 0xff +#define CARDBUS_LATTIMER(bhlcr) \ + (((bhlcr) >> CARDBUS_LATTIMER_SHIFT) & CARDBUS_LATTIMER_MASK) + +#define CARDBUS_CACHELINE_SHIFT 0 +#define CARDBUS_CACHELINE_MASK 0xff +#define CARDBUS_CACHELINE(bhlcr) \ + (((bhlcr) >> CARDBUS_CACHELINE_SHIFT) & CARDBUS_CACHELINE_MASK) + + +/* Base Resisters */ +#define CARDBUS_BASE0_REG 0x10 +#define CARDBUS_BASE1_REG 0x14 +#define CARDBUS_BASE2_REG 0x18 +#define CARDBUS_BASE3_REG 0x1C +#define CARDBUS_BASE4_REG 0x20 +#define CARDBUS_BASE5_REG 0x24 +#define CARDBUS_CIS_REG 0x28 +# define CARDBUS_CIS_ASIMASK 0x07 +# define CARDBUS_CIS_ASI(x) (CARDBUS_CIS_ASIMASK & (x)) +# define CARDBUS_CIS_ASI_TUPLE 0x00 +# define CARDBUS_CIS_ASI_BAR0 0x01 +# define CARDBUS_CIS_ASI_BAR1 0x02 +# define CARDBUS_CIS_ASI_BAR2 0x03 +# define CARDBUS_CIS_ASI_BAR3 0x04 +# define CARDBUS_CIS_ASI_BAR4 0x05 +# define CARDBUS_CIS_ASI_BAR5 0x06 +# define CARDBUS_CIS_ASI_ROM 0x07 +# define CARDBUS_CIS_ADDRMASK 0x0ffffff8 +# define CARDBUS_CIS_ADDR(x) (CARDBUS_CIS_ADDRMASK & (x)) +# define CARDBUS_CIS_ASI_BAR(x) (((CARDBUS_CIS_ASIMASK & (x))-1)*4+0x10) + +#define CARDBUS_INTERRUPT_REG 0x3c + +#define CARDBUS_MAPREG_TYPE_MEM 0x00000000 +#define CARDBUS_MAPREG_TYPE_IO 0x00000001 + +/* XXX end */ + +#if rbus + +typedef struct cardbus_functions { + int (*cardbus_space_alloc) __P((cardbus_chipset_tag_t, rbus_tag_t, + bus_addr_t addr, bus_size_t size, + bus_addr_t mask, bus_size_t align, + int flags, bus_addr_t *addrp, + bus_space_handle_t *bshp)); + int (*cardbus_space_free) __P((cardbus_chipset_tag_t, rbus_tag_t, + bus_space_handle_t, bus_size_t)); + void *(*cardbus_intr_establish) __P((cardbus_chipset_tag_t, int irq, int level, int (*ih)(void *), void *sc)); + void (*cardbus_intr_disestablish) __P((cardbus_chipset_tag_t ct, void *ih)); + int (*cardbus_ctrl) __P((cardbus_chipset_tag_t, int)); + int (*cardbus_power) __P((cardbus_chipset_tag_t, int)); + + cardbustag_t (*cardbus_make_tag) __P((cardbus_chipset_tag_t, int, int, int)); + void (*cardbus_free_tag) __P((cardbus_chipset_tag_t, cardbustag_t)); + cardbusreg_t (*cardbus_conf_read) __P((cardbus_chipset_tag_t, cardbustag_t, int)); + void (*cardbus_conf_write) __P((cardbus_chipset_tag_t, cardbustag_t, int, cardbusreg_t)); +} cardbus_function_t, *cardbus_function_tag_t; + +#else + +typedef struct cardbus_functions { + int (*cardbus_ctrl) __P((cardbus_chipset_tag_t, int)); + int (*cardbus_power) __P((cardbus_chipset_tag_t, int)); + int (*cardbus_mem_open) __P((cardbus_chipset_tag_t, int, u_int32_t, u_int32_t)); + int (*cardbus_mem_close) __P((cardbus_chipset_tag_t, int)); + int (*cardbus_io_open) __P((cardbus_chipset_tag_t, int, u_int32_t, u_int32_t)); + int (*cardbus_io_close) __P((cardbus_chipset_tag_t, int)); + void *(*cardbus_intr_establish) __P((cardbus_chipset_tag_t, int irq, int level, int (*ih)(void *), void *sc)); + void (*cardbus_intr_disestablish) __P((cardbus_chipset_tag_t ct, void *ih)); + + cardbustag_t (*cardbus_make_tag) __P((cardbus_chipset_tag_t, int, int, int)); cardbusreg_t (*cardbus_conf_read) __P((cardbus_chipset_tag_t, cardbustag_t, int)); + void (*cardbus_conf_write) __P((cardbus_chipset_tag_t, cardbustag_t, int, cardbusreg_t)); +} cardbus_function_t, *cardbus_function_tag_t; +#endif /* rbus */ + +/********************************************************************** +* struct cbslot_attach_args is the attach argument for cardbus card. +**********************************************************************/ +struct cbslot_attach_args { + char *cba_busname; + bus_space_tag_t cba_iot; /* cardbus i/o space tag */ + bus_space_tag_t cba_memt; /* cardbus mem space tag */ + bus_dma_tag_t cba_dmat; /* DMA tag */ + + int cba_bus; /* cardbus bus number */ + int cba_function; /* slot number on this Host Bus Adaptor */ + + cardbus_chipset_tag_t cba_cc; /* cardbus chipset */ + cardbus_function_tag_t cba_cf; /* cardbus functions */ + int cba_intrline; /* interrupt line */ + +#if rbus + rbus_tag_t cba_rbus_iot; /* CardBus i/o rbus tag */ + rbus_tag_t cba_rbus_memt; /* CardBus mem rbus tag */ +#endif + + int cba_cacheline; /* cache line size */ + int cba_lattimer; /* latency timer */ +}; + + +#define cbslotcf_dev cf_loc[0] +#define cbslotcf_func cf_loc[1] +#define CBSLOT_UNK_DEV -1 +#define CBSLOT_UNK_FUNC -1 + + +struct cardbus_devfunc; + +/********************************************************************** +* struct cardbus_softc is the softc for cardbus card. +**********************************************************************/ +struct cardbus_softc { + struct device sc_dev; /* fundamental device structure */ + + int sc_bus; /* cardbus bus number */ + int sc_device; /* cardbus device number */ + int sc_intrline; /* CardBus intrline */ + + bus_space_tag_t sc_iot; /* CardBus I/O space tag */ + bus_space_tag_t sc_memt; /* CardBus MEM space tag */ + bus_dma_tag_t sc_dmat; /* DMA tag */ + + cardbus_chipset_tag_t sc_cc; /* CardBus chipset */ + cardbus_function_tag_t sc_cf; /* CardBus function */ + +#if rbus + rbus_tag_t sc_rbus_iot; /* CardBus i/o rbus tag */ + rbus_tag_t sc_rbus_memt; /* CardBus mem rbus tag */ +#endif + + int sc_cacheline; /* cache line size */ + int sc_lattimer; /* latency timer */ + int sc_volt; /* applied Vcc voltage */ +#define PCCARD_33V 0x02 +#define PCCARD_XXV 0x04 +#define PCCARD_YYV 0x08 + int sc_poweron_func; + struct cardbus_devfunc *sc_funcs; /* list of cardbus device functions */ +}; + + +/********************************************************************** + * struct cardbus_devfunc: + * + * This is the data deposit for each function of a CardBus device. + * This structure is used for memory or i/o space allocation and + * disallocation. + **********************************************************************/ +typedef struct cardbus_devfunc { + cardbus_chipset_tag_t ct_cc; + cardbus_function_tag_t ct_cf; + struct cardbus_softc *ct_sc; /* pointer to the parent */ + int ct_bus; /* bus number */ + int ct_dev; /* device number */ + int ct_func; /* function number */ + +#if rbus + rbus_tag_t ct_rbus_iot; /* CardBus i/o rbus tag */ + rbus_tag_t ct_rbus_memt; /* CardBus mem rbus tag */ +#endif + + u_int32_t ct_bar[6]; /* Base Address Regs 0 to 6 */ + u_int32_t ct_lc; /* Latency timer and cache line size */ + /* u_int32_t ct_cisreg; */ /* CIS reg: is it needed??? */ + + struct device *ct_device; /* pointer to the device */ + + struct cardbus_devfunc *ct_next; + + /* some data structure needed for tuple??? */ +} *cardbus_devfunc_t; + + +struct cardbus_attach_args { + int ca_unit; + cardbus_devfunc_t ca_ct; + + bus_space_tag_t ca_iot; /* CardBus I/O space tag */ + bus_space_tag_t ca_memt; /* CardBus MEM space tag */ + bus_dma_tag_t ca_dmat; /* DMA tag */ + + u_int ca_device; + u_int ca_function; + cardbustag_t ca_tag; + cardbusreg_t ca_id; + cardbusreg_t ca_class; + + /* interrupt information */ + cardbus_intr_line_t ca_intrline; + +#if rbus + rbus_tag_t ca_rbus_iot; /* CardBus i/o rbus tag */ + rbus_tag_t ca_rbus_memt; /* CardBus mem rbus tag */ +#endif +}; + + +#define CARDBUS_ENABLE 1 /* enable the channel */ +#define CARDBUS_DISABLE 2 /* disable the channel */ +#define CARDBUS_RESET 4 +#define CARDBUS_CD 7 +# define CARDBUS_NOCARD 0 +# define CARDBUS_5V_CARD 0x01 /* XXX: It must not exist */ +# define CARDBUS_3V_CARD 0x02 +# define CARDBUS_XV_CARD 0x04 +# define CARDBUS_YV_CARD 0x08 +#define CARDBUS_IO_ENABLE 100 +#define CARDBUS_IO_DISABLE 101 +#define CARDBUS_MEM_ENABLE 102 +#define CARDBUS_MEM_DISABLE 103 +#define CARDBUS_BM_ENABLE 104 /* bus master */ +#define CARDBUS_BM_DISABLE 105 + +#define CARDBUS_VCC_UC 0x0000 +#define CARDBUS_VCC_3V 0x0001 +#define CARDBUS_VCC_XV 0x0002 +#define CARDBUS_VCC_YV 0x0003 +#define CARDBUS_VCC_0V 0x0004 +#define CARDBUS_VCC_5V 0x0005 /* ??? */ +#define CARDBUS_VCCMASK 0x000f +#define CARDBUS_VPP_UC 0x0000 +#define CARDBUS_VPP_VCC 0x0010 +#define CARDBUS_VPP_12V 0x0030 +#define CARDBUS_VPP_0V 0x0040 +#define CARDBUS_VPPMASK 0x00f0 + + +#include "locators.h" + +/* + * Locators devies that attach to 'cardbus', as specified to config. + */ +#define cardbuscf_dev cf_loc[CARDBUSCF_DEV] +#define CARDBUS_UNK_DEV CARDBUSCF_DEV_DEFAULT + +#define cardbuscf_function cf_loc[CARDBUSCF_FUNCTION] +#define CARDBUS_UNK_FUNCTION CARDBUSCF_FUNCTION_DEFAULT + +int cardbus_attach_card __P((struct cardbus_softc *)); +void *cardbus_intr_establish __P((cardbus_chipset_tag_t, cardbus_function_tag_t, cardbus_intr_handle_t irq, int level, int (*func) (void *), void *arg)); +void cardbus_intr_disestablish __P((cardbus_chipset_tag_t, cardbus_function_tag_t, void *handler)); + +int cardbus_mapreg_map __P((cardbus_devfunc_t, int, cardbusreg_t, + int, bus_space_tag_t *, bus_space_handle_t *, + bus_addr_t *, bus_size_t *)); + +int cardbus_save_bar __P((cardbus_devfunc_t)); +int cardbus_restore_bar __P((cardbus_devfunc_t)); + +int cardbus_function_enable __P((cardbus_devfunc_t)); +int cardbus_function_disable __P((cardbus_devfunc_t)); + +#define Cardbus_make_tag(ct) (*(ct)->ct_cf->cardbus_make_tag)((ct)->ct_cc, (ct)->ct_bus, (ct)->ct_dev, (ct)->ct_func) +#define cardbus_make_tag(cc, cf, bus, device, function) ((cf)->cardbus_make_tag)((cc), (bus), (device), (function)) + +#define Cardbus_free_tag(ct, tag) (*(ct)->ct_cf->cardbus_free_tag)((ct)->ct_cc, (tag)) + +#define Cardbus_conf_read(ct, tag, offs) (*(ct)->ct_cf->cardbus_conf_read)((ct)->ct_cf, (tag), (offs)) +#define cardbus_conf_read(cc, cf, tag, offs) ((cf)->cardbus_conf_read)((cc), (tag), (offs)) +#define Cardbus_conf_write(ct, tag, offs, val) (*(cc)->ct_cf->cardbus_conf_write)((ct)->ct_cf, (tag), (offs), (val)) +#define cardbus_conf_write(cc, cf, tag, offs, val) ((cf)->cardbus_conf_write)((cc), (tag), (offs), (val)) + +#endif /* SYS_DEV_CARDBUS_CARDBUSVAR_H */ + diff --git a/sys/dev/cardbus/cardslot.c b/sys/dev/cardbus/cardslot.c new file mode 100644 index 000000000000..b1c19b3756f3 --- /dev/null +++ b/sys/dev/cardbus/cardslot.c @@ -0,0 +1,426 @@ +/* $Id: cardslot.c,v 1.1 1999/10/15 06:07:19 haya Exp $ */ + +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by HAYAKAWA Koichi. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* #define CARDSLOT_DEBUG */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + + +#if defined CARDSLOT_DEBUG +#define STATIC +#define DPRINTF(a) printf a +#define DDELAY(x) delay((x)*1000*1000) +#else +#define STATIC static +#define DPRINTF(a) +#endif + + + +STATIC void cardslotattach __P((struct device *, struct device *, void *)); + +#if !defined __BROKEN_INDIRECT_CONFIG +STATIC int cardslotmatch __P((struct device *, struct cfdata *, void *)); +#else +STATIC int cardslotmatch __P((struct device *, void *, void *)); +#endif +static void create_slot_manager __P((void *)); +static void cardslot_event_thread __P((void *arg)); + +STATIC int cardslot_cb_print __P((void *aux, const char *pcic)); +static int cardslot_16_print __P((void *, const char *)); +static int cardslot_16_submatch __P((struct device *, struct cfdata *,void *)); + +struct cfattach cardslot_ca = { + sizeof(struct cardslot_softc), cardslotmatch, cardslotattach +}; + +#ifndef __NetBSD_Version__ +struct cfdriver cardslot_cd = { + NULL, "cardslot", DV_DULL +}; +#endif + + +STATIC int +#if defined __BROKEN_INDIRECT_CONFIG +cardslotmatch(parent, match, aux) + struct device *parent; + void *match; + void *aux; +#else +cardslotmatch(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +#endif +{ +#if defined __BROKEN_INDIRECT_CONFIG + struct cfdata *cf = match; +#endif + struct cardslot_attach_args *caa = aux; + + if (caa->caa_cb_attach == NULL && caa->caa_16_attach == NULL) { + /* Neither CardBus nor 16-bit PCMCIA are defined. */ + return 0; + } + + return 1; +} + + + +STATIC void +cardslotattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct cardslot_softc *sc = (struct cardslot_softc *)self; + struct cardslot_attach_args *caa = aux; + + struct cbslot_attach_args *cba = caa->caa_cb_attach; + struct pcmciabus_attach_args *pa = caa->caa_16_attach; + + struct cardbus_softc *csc; + struct pcmcia_softc *psc; + + int card_attach_now; + + sc->sc_slot = sc->sc_dev.dv_unit; + sc->sc_cb_softc = NULL; + sc->sc_16_softc = NULL; + SIMPLEQ_INIT(&sc->sc_events); + sc->sc_th_enable = 0; + + printf(" slot %d flags %x\n", sc->sc_slot, sc->sc_dev.dv_cfdata->cf_flags); + + DPRINTF(("%s attaching CardBus bus...\n", sc->sc_dev.dv_xname)); + if (cba != NULL) { + if (NULL != (csc = (void *)config_found(self, cba, cardslot_cb_print))) { + /* cardbus found */ + DPRINTF(("cardslotattach: found cardbus on %s\n", sc->sc_dev.dv_xname)); + sc->sc_cb_softc = csc; + } + } + + if (pa != NULL) { + if (NULL != (psc = (void *)config_found_sm(self, pa, cardslot_16_print, + cardslot_16_submatch))) { + /* pcmcia 16-bit bus found */ + DPRINTF(("cardslotattach: found 16-bit pcmcia bus\n")); + sc->sc_16_softc = psc; + /* XXX: dirty. This code should be removed to achieve MI */ + caa->caa_ph->pcmcia = (struct device *)psc; + } + } + + if (csc != NULL || psc != NULL) { +#if __NetBSD_Version__ > 104060000 + kthread_create(create_slot_manager, (void *)sc); +#else + kthread_create_deferred(create_slot_manager, (void *)sc); +#endif + } + + card_attach_now = sc->sc_dev.dv_cfdata->cf_flags & 0x01; + + if (csc && (csc->sc_cf->cardbus_ctrl)(csc->sc_cc, CARDBUS_CD)) { + DPRINTF(("cardslotattach: CardBus card found\n")); + if (card_attach_now) { + /* attach now */ + cardbus_attach_card(sc->sc_cb_softc); + CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_CB); + } else { + /* attach deffered */ + cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_CB); + } + } + + if (psc && (psc->pct->card_detect)(psc->pch)) { + DPRINTF(("cardbusattach: 16-bit card found\n")); + if (card_attach_now) { + /* attach now */ + pcmcia_card_attach((struct device *)sc->sc_16_softc); + CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_16); + } else { + /* attach deffered */ + cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_16); + } + } +} + + + +STATIC int +cardslot_cb_print(aux, pcic) + void *aux; + const char *pcic; +{ + return UNCONF; +} + + +static int +cardslot_16_submatch(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] != PCMCIABUSCF_CONTROLLER_DEFAULT + && cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 0) { + return 0; + } + + if ((cf->cf_loc[PCMCIABUSCF_CONTROLLER] == PCMCIABUSCF_CONTROLLER_DEFAULT)) { + return ((*cf->cf_attach->ca_match)(parent, cf, aux)); + } + + return 0; +} + + + +static int +cardslot_16_print(arg, pnp) + void *arg; + const char *pnp; +{ + if (pnp) { + printf("pcmcia at %s", pnp); + } + + return UNCONF; +} + + + + +static void +create_slot_manager(arg) + void *arg; +{ + struct cardslot_softc *sc = (struct cardslot_softc *)arg; + + sc->sc_th_enable = 1; + +#if __NetBSD_Version__ > 104060000 + if (kthread_create1(cardslot_event_thread, sc, &sc->sc_event_thread, "%s", + sc->sc_dev.dv_xname)) { +#else + if (kthread_create(cardslot_event_thread, sc, &sc->sc_event_thread, "%s", + sc->sc_dev.dv_xname)) { +#endif + printf("%s: unable to create event thread for slot %d\n", + sc->sc_dev.dv_xname, sc->sc_slot); + panic("create_slot_manager"); + } +} + + + + +/* + * void cardslot_event_throw(struct cardslot_softc *sc, int ev) + * + * This function throws an event to the event handler. If the state + * of a slot is changed, it should be noticed using this function. + */ +void +cardslot_event_throw(sc, ev) + struct cardslot_softc *sc; + int ev; +{ + struct cardslot_event *ce; + + DPRINTF(("cardslot_event_throw: an event %s comes\n", + ev == CARDSLOT_EVENT_INSERTION_CB ? "CardBus Card inserted" : + ev == CARDSLOT_EVENT_INSERTION_16 ? "16-bit Card inserted" : + ev == CARDSLOT_EVENT_REMOVAL_CB ? "CardBus Card removed" : + ev == CARDSLOT_EVENT_REMOVAL_16 ? "16-bit Card removed" : "???")); + + if (NULL == (ce = (struct cardslot_event *)malloc(sizeof (struct cardslot_event), M_TEMP, M_NOWAIT))) { + panic("cardslot_enevt"); + } + + ce->ce_type = ev; + + { + int s = spltty(); + SIMPLEQ_INSERT_TAIL(&sc->sc_events, ce, ce_q); + splx(s); + } + + wakeup(&sc->sc_events); + + return; +} + + +/* + * static void cardslot_event_thread(void *arg) + * + * This function is the main routine handing cardslot events such as + * insertions and removals. + * + */ +static void +cardslot_event_thread(arg) + void *arg; +{ + struct cardslot_softc *sc = arg; + struct cardslot_event *ce; + int s; + static int antonym_ev[4] = { + CARDSLOT_EVENT_REMOVAL_16, CARDSLOT_EVENT_INSERTION_16, + CARDSLOT_EVENT_REMOVAL_CB, CARDSLOT_EVENT_INSERTION_CB + }; + + while (sc->sc_th_enable) { + s = spltty(); + if ((ce = SIMPLEQ_FIRST(&sc->sc_events)) == NULL) { + splx(s); + (void) tsleep(&sc->sc_events, PWAIT, "cardslotev", 0); + continue; + } + SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce, ce_q); + splx(s); + + if (IS_CARDSLOT_INSERT_REMOVE_EV(ce->ce_type)) { + /* Chattering supression */ + s = spltty(); + while (1) { + struct cardslot_event *ce1, *ce2; + + if ((ce1 = SIMPLEQ_FIRST(&sc->sc_events)) == NULL) { + break; + } + if (ce1->ce_type != antonym_ev[ce->ce_type]) { + break; + } + if ((ce2 = SIMPLEQ_NEXT(ce1, ce_q)) == NULL) { + break; + } + if (ce2->ce_type == ce->ce_type) { + SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce1, ce_q); + free(ce1, M_TEMP); + SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce2, ce_q); + free(ce2, M_TEMP); + } + } + splx(s); + } + + switch (ce->ce_type) { + case CARDSLOT_EVENT_INSERTION_CB: + if (CARDSLOT_CARDTYPE(sc->sc_status) != CARDSLOT_STATUS_CARD_NONE) { + /* A card has already been inserted. */ + break; + } + if (sc->sc_cb_softc) { + cardbus_attach_card(sc->sc_cb_softc); + CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_CB); + } else { + panic("no cardbus on %s", sc->sc_dev.dv_xname); + } + + break; + + case CARDSLOT_EVENT_INSERTION_16: + if (CARDSLOT_CARDTYPE(sc->sc_status) != CARDSLOT_STATUS_CARD_NONE) { + /* A card has already been inserted. */ + break; + } + if (sc->sc_16_softc) { + pcmcia_card_attach((struct device *)sc->sc_16_softc); + CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_16); + } else { + panic("no 16-bit pcmcia on %s", sc->sc_dev.dv_xname); + } + + break; + + case CARDSLOT_EVENT_REMOVAL_CB: + if (CARDSLOT_CARDTYPE(sc->sc_status) != CARDSLOT_STATUS_CARD_CB) { + /* CardBus card has not been inserted. */ + break; + } + /* not yet */ + CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_NONE); + break; + + case CARDSLOT_EVENT_REMOVAL_16: + DPRINTF(("%s: removal event\n", sc->sc_dev.dv_xname)); + if (CARDSLOT_CARDTYPE(sc->sc_status) != CARDSLOT_STATUS_CARD_16) { + /* 16-bit card has not been inserted. */ + break; + } + if (sc->sc_16_softc) { + struct pcmcia_softc *psc = sc->sc_16_softc; + + pcmcia_card_deactivate((struct device *)psc); + pcmcia_chip_socket_disable(psc->pct, psc->pch); + pcmcia_card_detach((struct device *)psc, DETACH_FORCE); + CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_NONE); + } + break; + + default: + panic("cardslot_event_thread: unknown event %d", ce->ce_type); + } + free(ce, M_TEMP); + } + + sc->sc_event_thread = NULL; + + /* In case parent is waiting for us to exit. */ + wakeup(sc); + + kthread_exit(0); +} diff --git a/sys/dev/cardbus/cardslotvar.h b/sys/dev/cardbus/cardslotvar.h new file mode 100644 index 000000000000..1242edbc2ee2 --- /dev/null +++ b/sys/dev/cardbus/cardslotvar.h @@ -0,0 +1,121 @@ +/* $Id: cardslotvar.h,v 1.1 1999/10/15 06:07:22 haya Exp $ */ + +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the author. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined SYS_DEV_CARDBUS_CARDSLOTVAR_H +#define SYS_DEV_CARDBUS_CARDSLOTVAR_H + +/* require sys/device.h */ +/* require sys/queue.h */ + +struct cardslot_event; + +/* + * The data structure cardslot_attach_args is the attach argument for + * PCMCIA (including CardBus and 16-bit card) slot. + */ +struct cardslot_attach_args { + char *caa_busname; + + int caa_slot; + + /* for cardbus... */ + struct cbslot_attach_args *caa_cb_attach; + + /* for 16-bit pcmcia */ + struct pcmciabus_attach_args *caa_16_attach; + + /* XXX: for 16-bit pcmcia. dirty! This should be removed to achieve MI. */ + struct pcic_handle *caa_ph; +}; + + +/* + * The data structure cardslot_attach_args is the attach argument for + * PCMCIA (including CardBus and 16-bit card) slot. + */ +struct cardslot_softc { + struct device sc_dev; + + int sc_slot; /* slot number */ + int sc_status; /* the status of slot */ + + struct cardbus_softc *sc_cb_softc; + struct pcmcia_softc *sc_16_softc; + + struct proc *sc_event_thread; + int sc_th_enable; /* true if the thread is enabled */ + + /* An event queue for the thead which processes slot state events. */ + + SIMPLEQ_HEAD(, cardslot_event) sc_events; +}; + +#define CARDSLOT_STATUS_CARD_MASK 0x07 +#define CARDSLOT_STATUS_CARD_NONE 0x00 /* NO card inserted */ +#define CARDSLOT_STATUS_CARD_16 0x01 /* 16-bit pcmcia card inserted */ +#define CARDSLOT_STATUS_CARD_CB 0x02 /* CardBus pcmcia card inserted */ +#define CARDSLOT_STATUS_UNKNOWN 0x07 /* Unknown card inserted */ + +#define CARDSLOT_CARDTYPE(x) ((x) & CARDSLOT_STATUS_CARD_MASK) +#define CARDSLOT_SET_CARDTYPE(x, type) \ + do {(x) &= ~CARDSLOT_STATUS_CARD_MASK;\ + (x) |= (CARDSLOT_STATUS_CARD_MASK & (type));} while(0) + +#define CARDSLOT_STATUS_WORK_MASK 0x08 +#define CARDSLOT_STATUS_WORKING 0x08 /* at least one function works */ +#define CARDSLOT_STATUS_NOTWORK 0x00 /* no functions are working */ + + +struct cardslot_event { + SIMPLEQ_ENTRY(cardslot_event) ce_q; + + int ce_type; +}; + +typedef struct cardslot_softc *cardslot_t; + +/* ce_type */ +#define CARDSLOT_EVENT_INSERTION_16 0 +#define CARDSLOT_EVENT_REMOVAL_16 1 + +#define CARDSLOT_EVENT_INSERTION_CB 2 +#define CARDSLOT_EVENT_REMOVAL_CB 3 + +#define IS_CARDSLOT_INSERT_REMOVE_EV(x) (0 <= (x) && (x) <= 3) + +#include "locators.h" + +void cardslot_event_throw __P((cardslot_t cs, int ev)); + +#endif /* SYS_DEV_CARDBUS_CARDSLOTVAR_H */ diff --git a/sys/dev/cardbus/devlist2h.awk b/sys/dev/cardbus/devlist2h.awk new file mode 100644 index 000000000000..b54f45de1698 --- /dev/null +++ b/sys/dev/cardbus/devlist2h.awk @@ -0,0 +1,221 @@ +#! /usr/bin/awk -f +# $NetBSD: devlist2h.awk,v 1.1 1999/10/15 06:07:22 haya Exp $ +# +# Copyright (c) 1995, 1996 Christopher G. Demetriou +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by Christopher G. Demetriou. +# 4. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +BEGIN { + nproducts = nvendors = 0 + dfile="cardbusdevs_data.h" + hfile="cardbusdevs.h" +} +NR == 1 { + VERSION = $0 + gsub("\\$", "", VERSION) + + printf("/*\t\$NetBSD\$\t*/\n\n") > dfile + printf("/*\n") > dfile + printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \ + > dfile + printf(" *\n") > dfile + printf(" * generated from:\n") > dfile + printf(" *\t%s\n", VERSION) > dfile + printf(" */\n") > dfile + + printf("/*\t\$NetBSD\$\t*/\n\n") > hfile + printf("/*\n") > hfile + printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \ + > hfile + printf(" *\n") > hfile + printf(" * generated from:\n") > hfile + printf(" *\t%s\n", VERSION) > hfile + printf(" */\n") > hfile + + next +} +$1 == "vendor" { + nvendors++ + + vendorindex[$2] = nvendors; # record index for this name, for later. + vendors[nvendors, 1] = $2; # name + vendors[nvendors, 2] = $3; # id + printf("#define\tCARDBUS_VENDOR_%s\t%s\t", vendors[nvendors, 1], + vendors[nvendors, 2]) > hfile + + i = 3; f = 4; + + # comments + ocomment = oparen = 0 + if (f <= NF) { + printf("\t/* ") > hfile + ocomment = 1; + } + while (f <= NF) { + if ($f == "#") { + printf("(") > hfile + oparen = 1 + f++ + continue + } + if (oparen) { + printf("%s", $f) > hfile + if (f < NF) + printf(" ") > hfile + f++ + continue + } + vendors[nvendors, i] = $f + printf("%s", vendors[nvendors, i]) > hfile + if (f < NF) + printf(" ") > hfile + i++; f++; + } + if (oparen) + printf(")") > hfile + if (ocomment) + printf(" */") > hfile + printf("\n") > hfile + + next +} +$1 == "product" { + nproducts++ + + products[nproducts, 1] = $2; # vendor name + products[nproducts, 2] = $3; # product id + products[nproducts, 3] = $4; # id + printf("#define\tCARDBUS_PRODUCT_%s_%s\t%s\t", products[nproducts, 1], + products[nproducts, 2], products[nproducts, 3]) > hfile + + i=4; f = 5; + + # comments + ocomment = oparen = 0 + if (f <= NF) { + printf("\t/* ") > hfile + ocomment = 1; + } + while (f <= NF) { + if ($f == "#") { + printf("(") > hfile + oparen = 1 + f++ + continue + } + if (oparen) { + printf("%s", $f) > hfile + if (f < NF) + printf(" ") > hfile + f++ + continue + } + products[nproducts, i] = $f + printf("%s", products[nproducts, i]) > hfile + if (f < NF) + printf(" ") > hfile + i++; f++; + } + if (oparen) + printf(")") > hfile + if (ocomment) + printf(" */") > hfile + printf("\n") > hfile + + next +} +{ + if ($0 == "") + blanklines++ + print $0 > hfile + if (blanklines < 2) + print $0 > dfile +} +END { + # print out the match tables + + printf("\n") > dfile + + printf("struct cardbus_knowndev cardbus_knowndevs[] = {\n") > dfile + for (i = 1; i <= nproducts; i++) { + printf("\t{\n") > dfile + printf("\t CARDBUS_VENDOR_%s, CARDBUS_PRODUCT_%s_%s,\n", + products[i, 1], products[i, 1], products[i, 2]) \ + > dfile + printf("\t ") > dfile + printf("0") > dfile + printf(",\n") > dfile + + vendi = vendorindex[products[i, 1]]; + printf("\t \"") > dfile + j = 3; + needspace = 0; + while (vendors[vendi, j] != "") { + if (needspace) + printf(" ") > dfile + printf("%s", vendors[vendi, j]) > dfile + needspace = 1 + j++ + } + printf("\",\n") > dfile + + printf("\t \"") > dfile + j = 4; + needspace = 0; + while (products[i, j] != "") { + if (needspace) + printf(" ") > dfile + printf("%s", products[i, j]) > dfile + needspace = 1 + j++ + } + printf("\",\n") > dfile + printf("\t},\n") > dfile + } + for (i = 1; i <= nvendors; i++) { + printf("\t{\n") > dfile + printf("\t CARDBUS_VENDOR_%s, 0,\n", vendors[i, 1]) \ + > dfile + printf("\t CARDBUS_KNOWNDEV_NOPROD,\n") \ + > dfile + printf("\t \"") > dfile + j = 3; + needspace = 0; + while (vendors[i, j] != "") { + if (needspace) + printf(" ") > dfile + printf("%s", vendors[i, j]) > dfile + needspace = 1 + j++ + } + printf("\",\n") > dfile + printf("\t NULL,\n") > dfile + printf("\t},\n") > dfile + } + printf("\t{ 0, 0, 0, NULL, NULL, }\n") > dfile + printf("};\n") > dfile +} diff --git a/sys/dev/cardbus/files.cardbus b/sys/dev/cardbus/files.cardbus new file mode 100644 index 000000000000..b889f8b1a808 --- /dev/null +++ b/sys/dev/cardbus/files.cardbus @@ -0,0 +1,33 @@ +# $Id: files.cardbus,v 1.1 1999/10/15 06:07:23 haya Exp $ +# +# files.cardbus +# + +device cardslot: cbbus, pcmciabus +attach cardslot at pcmciaslot +file dev/cardbus/cardslot.c cardslot needs-flag + +device cardbus {[dev = -1], [function = -1]} +attach cardbus at cbbus +file dev/cardbus/cardbus.c cardbus needs-flag +file dev/cardbus/cardbus_map.c cardbus +file dev/cardbus/rbus.c cardbus + + +# +# 3Com 3C575TX and 3C575BTX +# +attach ex at cardbus with ex_cardbus +file dev/cardbus/if_ex_cardbus.c ex_cardbus + +# +# Intel PRO/100 8255x based CardBus cards. +# +# +# +#attach fxp at cardbus with fxp_cardbus +#file dev/cardbus/if_fxp_cardbus.c fxp_cardbus + + +#attach com at cardbus with com_cardbus +#file dev/cardbus/com_cardbus.c com_cardbus diff --git a/sys/dev/cardbus/if_ex_cardbus.c b/sys/dev/cardbus/if_ex_cardbus.c new file mode 100644 index 000000000000..cde8dfae52d6 --- /dev/null +++ b/sys/dev/cardbus/if_ex_cardbus.c @@ -0,0 +1,415 @@ +/* $Id: if_ex_cardbus.c,v 1.1 1999/10/15 06:07:23 haya Exp $ */ + +/* + * CardBus specific routines for 3Com 3C575-family CardBus ethernet adapter + * + * Copyright (c) 1998 and 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the author. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY HAYAKAWA KOICHI ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL TAKESHI OHASHI OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + */ + + +#define EX_DEBUG 4 /* define to report infomation for debugging */ + +#define EX_POWER_STATIC /* do not use enable/disable functions */ + /* I'm waiting elinkxl.c uses + sc->enable and sc->disable + functions. */ + +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if defined INET +#include +#include +#include +#include +#endif + +#ifdef NS +#include +#include +#endif + +#if NBPFILTER > 0 +#include +#include +#endif + +#include +#include +#include +#if defined pciinc +#include +#endif +#if pccard +#include +#include +#else +#include +#include +#endif + +#include + +#include +#include +#include +#include + +#if defined DEBUG && !defined EX_DEBUG +#define EX_DEBUG +#endif + +#if defined EX_DEBUG +#define STATIC +#define DPRINTF(a) printf a +#else +#define STATIC static +#define DPRINTF(a) +#endif + +#define CARDBUS_3C575BTX_FUNCSTAT_PCIREG CARDBUS_BASE2_REG /* means 0x18 */ +#define EX_CB_INTR 4 /* intr acknowledge reg. CardBus only */ +#define EX_CB_INTR_ACK 0x8000 /* intr acknowledge bit */ + + +/* Definitions, most of them has turned out to be unneccesary, but here they + * are anyway. + */ + + +STATIC int ex_cardbus_match __P((struct device *, struct cfdata *, void *)); +STATIC void ex_cardbus_attach __P((struct device *, struct device *,void *)); +STATIC int ex_cardbus_detach __P((struct device *, int)); +STATIC void ex_cardbus_intr_ack __P((struct ex_softc *)); + +#if 0 +static void expoll __P((void *arg)); +#endif + +#if !defined EX_POWER_STATIC +STATIC int ex_cardbus_enable __P((struct ex_softc *sc)); +STATIC void ex_cardbus_disable __P((struct ex_softc *sc)); +#endif /* !defined EX_POWER_STATIC */ + + +struct ex_cardbus_softc { + struct ex_softc sc_softc; + + cardbus_devfunc_t sc_ct; + int sc_intrline; + u_int8_t sc_cardbus_flags; +#define EX_REATTACH 0x01 +#define EX_ABSENT 0x02 + u_int8_t sc_cardtype; +#define EX_3C575 1 +#define EX_3C575B 2 + + /* CardBus function status space. 575B requests it. */ + bus_space_tag_t sc_funct; + bus_space_handle_t sc_funch; +}; + +struct cfattach ex_cardbus_ca = { + sizeof(struct ex_cardbus_softc), ex_cardbus_match, + ex_cardbus_attach, ex_cardbus_detach +}; + + + +STATIC int +ex_cardbus_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct cardbus_attach_args *ca = aux; + + if ((CARDBUS_VENDOR(ca->ca_id) == CARDBUS_VENDOR_3COM)) { + if (CARDBUS_PRODUCT(ca->ca_id) == CARDBUS_PRODUCT_3COM_3C575TX + || CARDBUS_PRODUCT(ca->ca_id) == CARDBUS_PRODUCT_3COM_3C575BTX) { + return 1; + } + } + return 0; +} + + + + + + +STATIC void +ex_cardbus_attach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct ex_cardbus_softc *psc = (void *)self; + struct ex_softc *sc = &psc->sc_softc; + struct cardbus_attach_args *ca = aux; + cardbus_devfunc_t ct = ca->ca_ct; + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; + cardbusreg_t iob, command, bhlc; + bus_space_handle_t ioh; + bus_addr_t adr; + + + if (cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO, 0, + &(sc->sc_iot), &ioh, &adr, NULL)) { + panic("io alloc in ex_attach_cardbus\n"); + } + iob = adr; + sc->sc_ioh = ioh; + +#if rbus +#else + (ct->ct_cf->cardbus_io_open)(cc, 0, iob, iob + 0x40); +#endif + (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE); + + /* enable the card */ + command = cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_COMMAND_STATUS_REG); + + /* Card specific configuration */ + switch (CARDBUS_PRODUCT(ca->ca_id)) { + case CARDBUS_PRODUCT_3COM_3C575TX: + psc->sc_cardtype = EX_3C575; + command |= (CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE); + printf("\n 3Com 3C575TX (boomerang)"); + break; + case CARDBUS_PRODUCT_3COM_3C575BTX: + psc->sc_cardtype = EX_3C575B; + command |= (CARDBUS_COMMAND_IO_ENABLE | + CARDBUS_COMMAND_MEM_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE); + + /* Cardbus function status window */ + if (cardbus_mapreg_map(ct, CARDBUS_3C575BTX_FUNCSTAT_PCIREG, + CARDBUS_MAPREG_TYPE_MEM, 0, + &psc->sc_funct, &psc->sc_funch, 0, NULL)) { + panic("mem alloc in ex_attach_cardbus\n"); + } + + /* + * Make sure CardBus brigde can access memory space. Usually + * memory access is enabled by BIOS, but some BIOSes do not enable + * it. + */ + (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE); + + /* Setup interrupt acknowledge hook */ + sc->intr_ack = ex_cardbus_intr_ack; + + printf("\n 3Com 3C575BTX (cyclone)"); + break; + } + + cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_COMMAND_STATUS_REG, command); + + /* + * set latency timmer + */ + bhlc = cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG); + if (CARDBUS_LATTIMER(bhlc) < 0x20) { + /* at least the value of latency timer should 0x20. */ + DPRINTF(("if_ex_cardbus: lattimer %x -> 0x20\n", CARDBUS_LATTIMER(bhlc))); + bhlc &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT); + bhlc |= (0x20 << CARDBUS_LATTIMER_SHIFT); + cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG, bhlc); + } + + sc->sc_dmat = ca->ca_dmat; + sc->ex_bustype = EX_BUS_CARDBUS; + psc->sc_ct = ca->ca_ct; + psc->sc_intrline = ca->ca_intrline; + + switch (psc->sc_cardtype) { + case EX_3C575: + sc->ex_conf = EX_CONF_MII|EX_CONF_INTPHY; + break; + case EX_3C575B: + sc->ex_conf = EX_CONF_90XB|EX_CONF_MII|EX_CONF_INTPHY; + break; + } + +#if !defined EX_POWER_STATIC + sc->enable = ex_cardbus_enable; + sc->disable = ex_cardbus_disable; +#else + sc->enable = NULL; + sc->disable = NULL; +#endif + sc->enabled = 1; + + +#if defined EX_POWER_STATIC + /* Map and establish the interrupt. */ + + sc->sc_ih = cardbus_intr_establish(cc, cf, ca->ca_intrline, IPL_NET, + ex_intr, psc); + if (sc->sc_ih == NULL) { + printf("%s: couldn't establish interrupt", + sc->sc_dev.dv_xname); + printf(" at %d", ca->ca_intrline); + printf("\n"); + return; + } + printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname, ca->ca_intrline); +#endif + +#if 0 + timeout(expoll, sc, hz/20); /* XXX */ +#endif + + bus_space_write_2(sc->sc_iot, sc->sc_ioh, ELINK_COMMAND, GLOBAL_RESET); + delay(400); + { + int i = 0; + while (bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, ELINK_STATUS) \ + & S_COMMAND_IN_PROGRESS) { + if (++i > 10000) { + printf("ex: timeout %x\n", bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, ELINK_STATUS)); + printf("ex: addr %x\n", cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_BASE0_REG)); + return; /* emargency exit */ + } + } + } + + ex_config(sc); /* I'm BOOMERANG or CYCLONE */ + + if (psc->sc_cardtype == EX_3C575B) { + bus_space_write_4(psc->sc_funct, psc->sc_funch, EX_CB_INTR, EX_CB_INTR_ACK); + } + +#if !defined EX_POWER_STATIC + cardbus_function_disable(psc->sc_ct); + sc->enabled = 0; +#endif + return; +} + + + +STATIC void +ex_cardbus_intr_ack(sc) + struct ex_softc *sc; +{ + struct ex_cardbus_softc *psc = (struct ex_cardbus_softc *)sc; + bus_space_write_4 (psc->sc_funct, psc->sc_funch, EX_CB_INTR, EX_CB_INTR_ACK); +} + + +STATIC int +ex_cardbus_detach(self, arg) + struct device *self; + int arg; +{ + struct ex_cardbus_softc *psc = (void *)self; + struct ex_softc *sc = &psc->sc_softc; + cardbus_function_tag_t cf = psc->sc_ct->ct_cf; + cardbus_chipset_tag_t cc = psc->sc_ct->ct_cc; + + /* + * XXX Currently, no detach. + */ + printf("- ex_cardbus_detach\n"); + + cardbus_intr_disestablish(cc, cf, sc->sc_ih); + + sc->enabled = 0; + + return EBUSY; +} + + + +#if !defined EX_POWER_STATIC +STATIC int +ex_cardbus_enable(sc) + struct ex_softc *sc; +{ + struct ex_cardbus_softc *csc = (struct ex_cardbus_softc *)sc; + cardbus_function_tag_t cf = csc->sc_ct->ct_cf; + cardbus_chipset_tag_t cc = csc->sc_ct->ct_cc; + + cardbus_function_enable(csc->sc_ct); + cardbus_restore_bar(csc->sc_ct); + + sc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET, ex_intr, sc); + if (NULL == sc->sc_ih) { + printf("%s: couldn't establish interrupt\n", sc->sc_dev.dv_xname); + return 1; + } + +/* printf("ex_pccard_enable: %s turned on\n", sc->sc_dev.dv_xname); */ + return 0; +} + + + + +STATIC void +ex_cardbus_disable(sc) + struct ex_softc *sc; +{ + struct ex_cardbus_softc *csc = (struct ex_cardbus_softc *)sc; + cardbus_function_tag_t cf = csc->sc_ct->ct_cf; + cardbus_chipset_tag_t cc = csc->sc_ct->ct_cc; + + cardbus_save_bar(csc->sc_ct); + + cardbus_function_disable(csc->sc_ct); + + cardbus_intr_disestablish(cc, cf, sc->sc_ih); +} + +#endif /* EX_POWER_STATIC */ diff --git a/sys/dev/cardbus/if_fxp_cardbus.c b/sys/dev/cardbus/if_fxp_cardbus.c new file mode 100644 index 000000000000..c1aeb021128c --- /dev/null +++ b/sys/dev/cardbus/if_fxp_cardbus.c @@ -0,0 +1,281 @@ +/* $Id: if_fxp_cardbus.c,v 1.1 1999/10/15 06:07:24 haya Exp $ */ + +/* + * Copyright (c) 1999 + * Johan Danielsson . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the author. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "opt_inet.h" +#include "opt_ns.h" +#include "bpfilter.h" +#include "rnd.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if NRND > 0 +#include +#endif + +#include +#include +#include +#include + +#if NBPFILTER > 0 +#include +#endif + +#ifdef INET +#include +#include +#endif + +#ifdef NS +#include +#include +#endif + +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include + +static int fxp_cardbus_match __P((struct device *, struct cfdata *, void *)); +static void fxp_cardbus_attach __P((struct device *, struct device *, void *)); + +struct fxp_cardbus_softc { + struct fxp_softc sc; + cardbustag_t tag; + pcireg_t base1_reg; +}; + +struct cfattach fxp_cardbus_ca = { + sizeof(struct fxp_cardbus_softc), fxp_cardbus_match, fxp_cardbus_attach +}; + +#ifdef CBB_DEBUG +#define DPRINTF(X) printf X +#else +#define DPRINTF(X) +#endif + +/* + * Check if a device is an 82557. + */ +static int +fxp_cardbus_match(parent, match, aux) + struct device *parent; + struct cfdata *match; + void *aux; +{ + /* should check CIS */ + struct cardbus_attach_args *ca = aux; + + if (CARDBUS_VENDOR(ca->ca_id) != CARDBUS_VENDOR_INTEL) + return (0); + + switch (CARDBUS_PRODUCT(ca->ca_id)) { + case CARDBUS_PRODUCT_INTEL_82557: + return (1); + } + + return (0); +} + +int +fxp_enable(struct fxp_softc *sc); + +static int +fxp_cardbus_enable(struct fxp_softc *sc); +static void +fxp_cardbus_disable(struct fxp_softc *sc); + +static void +fxp_cardbus_setup(struct fxp_softc *sc); + +static void +fxp_cardbus_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct fxp_softc *sc = (struct fxp_softc*)self; + struct fxp_cardbus_softc *csc = (struct fxp_cardbus_softc*)self; + struct cardbus_attach_args *ca = aux; + cardbus_function_tag_t cf = ca->ca_cf; + bus_space_handle_t ioh, memh; + + bus_addr_t adr; + + /* + * Map control/status registers. + */ +#if rbus + cardbus_function_tag_t cf = ct->ct_cf; + + if (cardbus_mapreg_map(ct, CARDBUS_BASE1_REG, CARDBUS_MAPREG_TYPE_IO, 0, + &(sc->sc_iot), &ioh, &adr, NULL)) { + panic("io alloc in ex_attach_cardbus\n"); + } + csc->base1_reg = adr | 1; + sc->sc_sh = ioh; + +#elif unibus + printf("fxp_cardbus_attach: uni %p\n", ca->ca_uni); + if ((*cf->cf_ub.unibus_space_alloc)(ca->ca_uni, ca->bar_info[1].tag, 0, + ca->bar_info[1].size, + ca->bar_info[1].size - 1, + ca->bar_info[1].size, + 0, 0, &adr, &ioh)) + panic("io alloc"); + + + csc->base1_reg = adr | 1; + sc->sc_st = ca->bar_info[1].tag; + sc->sc_sh = ioh; + + if (0) { + /* + * Map control/status registers. + */ + if ((*cf->cf_ub.unibus_space_alloc)(ca->ca_uni, ca->bar_info[0].tag, 0, + ca->bar_info[0].size, + ca->bar_info[0].size - 1, + ca->bar_info[0].size, + 0, 0, &adr, &memh)) + panic("mem alloc"); + + + sc->sc_st = ca->bar_info[0].tag; + sc->sc_sh = memh; + } +#endif + + csc->tag = ca->ca_tag; + + sc->sc_dmat = ca->ca_dmat; + sc->enable = fxp_cardbus_enable; + sc->disable = fxp_cardbus_disable; + sc->enabled = 0; + + fxp_cardbus_setup(sc); + printf(": Intel EtherExpress Pro 10+/100B Ethernet\n"); + + fxp_attach_common(sc); +} + + +static void +fxp_cardbus_setup(struct fxp_softc *sc) +{ + struct fxp_cardbus_softc *csc = (struct fxp_cardbus_softc*)sc; + struct cardbus_softc *psc = (struct cardbus_softc *)sc->sc_dev.dv_parent; + cardbus_chipset_tag_t cc = psc->sc_cc; + cardbus_function_tag_t cf = psc->sc_cf; + pcireg_t command; + + printf("fxp_cardbus_setup\n"); + + cardbus_conf_write(cc, cf, csc->tag, CARDBUS_BASE1_REG, csc->base1_reg); + + (cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE); + + /* enable the card */ + command = cardbus_conf_read(cc, cf, csc->tag, CARDBUS_COMMAND_STATUS_REG); + command |= (CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE); + cardbus_conf_write(cc, cf, csc->tag, CARDBUS_COMMAND_STATUS_REG, command); +#if 0 + cardbus_conf_write(cc, cf, ca->tag, CARDBUS_BASE0_REG, adr); + + (ca->ca_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE); + + /* enable card mem */ + command = cardbus_conf_read(cc, cf, ca->tag, CARDBUS_COMMAND_STATUS_REG); + command |= CARDBUS_COMMAND_MEM_ENABLE; + cardbus_conf_write(cc, cf, ca->tag, CARDBUS_COMMAND_STATUS_REG, command); +#endif +} + +static int +fxp_cardbus_enable(struct fxp_softc *sc) +{ + struct fxp_cardbus_softc *csc = (struct fxp_cardbus_softc*)sc; + struct cardbus_softc *psc = (struct cardbus_softc *)sc->sc_dev.dv_parent; + cardbus_chipset_tag_t cc = psc->sc_cc; + cardbus_function_tag_t cf = psc->sc_cf; + + cardbus_function_enable(psc, csc->tag); + + fxp_cardbus_setup(sc); + + /* Map and establish the interrupt. */ + + sc->sc_ih = cardbus_intr_establish(cc, cf, psc->sc_intrline, IPL_NET, + fxp_intr, sc); + if (NULL == sc->sc_ih) { + printf("%s: couldn't establish interrupt\n", sc->sc_dev.dv_xname); + return 1; + } + + printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname, psc->sc_intrline); + + return 0; +} + +static void +fxp_cardbus_disable(struct fxp_softc *sc) +{ + struct cardbus_softc *psc = (struct cardbus_softc *)sc->sc_dev.dv_parent; + cardbus_chipset_tag_t cc = psc->sc_cc; + cardbus_function_tag_t cf = psc->sc_cf; + + fxp_stop(sc); + cardbus_intr_disestablish(cc, cf, sc->sc_ih); /* remove intr handler */ + + cardbus_function_disable(psc); +} diff --git a/sys/dev/cardbus/pccardcis.h b/sys/dev/cardbus/pccardcis.h new file mode 100644 index 000000000000..aa87095a5a6c --- /dev/null +++ b/sys/dev/cardbus/pccardcis.h @@ -0,0 +1,92 @@ +/* $Id: pccardcis.h,v 1.1 1999/10/15 06:07:24 haya Exp $ */ + +/* + * Copyright (c) 1997 and 1998 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the author. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#if !defined SYS_DEV_PCCARD_PCCARDCIS_H +#define SYS_DEV_PCCARD_PCCARDCIS_H 1 + +#define CISTPL_NULL 0x00 +#define CISTPL_DEVICE 0x01 +#define CISTPL_CONFIG_CB 0x04 +#define CISTPL_CFTABLE_ENTRY_CB 0x05 +#define CISTPL_BAR 0x07 +#define CISTPL_CHECKSUM 0x10 +#define CISTPL_LONGLINK_A 0x11 +#define CISTPL_LONGLINK_C 0x12 +#define CISTPL_LINKTARGET 0x13 +#define CISTPL_NO_LINK 0x14 +#define CISTPL_VERS_1 0x15 +#define CISTPL_ALTSTR 0x16 +#define CISTPL_DEVICE_A 0x17 +#define CISTPL_JEDEC_C 0x18 +#define CISTPL_JEDEC_A 0x19 +#define CISTPL_CONFIG 0x1A +#define CISTPL_CFTABLE_ENTRY 0x1B +#define CISTPL_DEVICE_OC 0x1C +#define CISTPL_DEVICE_OA 0x1D +#define CISTPL_DEVICE_GEO 0x1E +#define CISTPL_DEVICE_GEO_A 0x1F +#define CISTPL_MANFID 0x20 +#define CISTPL_FUNCID 0x21 +#define CISTPL_FUNCE 0x22 +#define CISTPL_SWIL 0x23 +#define CISTPL_VERS_2 0x40 +#define CISTPL_FORMAT 0x41 +#define CISTPL_GEOMETRY 0x42 +#define CISTPL_BYTEORDER 0x43 +#define CISTPL_DATE 0x44 +#define CISTPL_BATTERY 0x45 +#define CISTPL_ORG 0x46 +#define CISTPL_END 0xFF + + +/* CISTPL_FUNC */ +#define TPL_FUNC_MF 0 /* multi function tuple */ +#define TPL_FUNC_MEM 1 /* memory */ +#define TPL_FUNC_SERIAL 2 /* serial, including modem and fax */ +#define TPL_FUNC_PARALLEL 3 /* parallel, including printer and SCSI */ +#define TPL_FUNC_DISK 4 /* Disk */ +#define TPL_FUNC_VIDEO 5 /* Video Adaptor */ +#define TPL_FUNC_LAN 6 /* LAN Adaptor */ +#define TPL_FUNC_AIMS 7 /* Auto Inclement Mass Strages */ + +/* TPL_FUNC_LAN */ +#define TPL_FUNCE_LAN_TECH 1 /* technology */ +#define TPL_FUNCE_LAN_SPEED 2 /* speed */ +#define TPL_FUNCE_LAN_MEDIA 2 /* which media do you use? */ +#define TPL_FUNCE_LAN_NID 4 /* node id (address) */ +#define TPL_FUNCE_LAN_CONN 5 /* connector type (shape) */ + + +#endif /* SYS_DEV_PCCARD_PCCARDCIS_H */ diff --git a/sys/dev/cardbus/rbus.c b/sys/dev/cardbus/rbus.c new file mode 100644 index 000000000000..97fd89ecccdf --- /dev/null +++ b/sys/dev/cardbus/rbus.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by HAYAKAWA Koichi. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id: rbus.c,v 1.1 1999/10/15 06:07:24 haya Exp $ */ + + +#include +#include +#include +#include +#include +#include + +#include + +#include + +/* #define RBUS_DEBUG */ + +#if defined RBUS_DEBUG +#define STATIC +#define DPRINTF(a) printf a +#define DDELAY(x) delay((x)*1000*1000) +#else +#define STATIC static +#define DPRINTF(a) +#endif + + + +static rbus_tag_t rbus_new_body __P((bus_space_tag_t bt, rbus_tag_t parent, + struct extent *ex, bus_addr_t start, + bus_addr_t end, bus_addr_t offset, + int flags)); + + +int +rbus_space_alloc(rbt, addr, size, mask, align, flags, addrp, bshp) + rbus_tag_t rbt; + bus_addr_t addr; + bus_size_t size; + bus_addr_t mask, align; + int flags; + bus_addr_t *addrp; + bus_space_handle_t *bshp; +{ + return rbus_space_alloc_subregion(rbt, rbt->rb_start, rbt->rb_end, addr, + size, mask, align, flags, addrp, bshp); +} + + + + +int +rbus_space_alloc_subregion(rbt, substart, subend, addr, size, mask, align, flags, addrp, bshp) + rbus_tag_t rbt; + bus_addr_t addr; + bus_addr_t substart; + bus_addr_t subend; + bus_size_t size; + bus_addr_t mask, align; + int flags; + bus_addr_t *addrp; + bus_space_handle_t *bshp; +{ + bus_addr_t decodesize = mask + 1; + bus_addr_t boundary, search_addr; + int val = 0; + bus_addr_t result; + int exflags = EX_FAST | EX_NOWAIT; + + DPRINTF(("rbus_space_alloc: addr %lx, size %lx, mask %lx, align %lx\n", + addr, size, mask, align)); + + if (size > align) { + return 1; /* ??? size should be smaller than align */ + } + + addr += rbt->rb_offset; + + if (mask == 0) { + /* FULL Decode */ + decodesize = 0; + } + + if (size > align) { + return 1; /* ??? size should be smaller than align */ + } + + if (rbt->rb_flags == RBUS_SPACE_ASK_PARENT) { + return rbus_space_alloc(rbt->rb_parent, addr, size, mask, align, flags, + addrp, bshp); + } else if (rbt->rb_flags == RBUS_SPACE_SHARE || + rbt->rb_flags == RBUS_SPACE_DEDICATE) { + /* rbt has its own sh_extent */ + + /* sanity check: the subregion [substart, subend] should be + smaller than the region included in sh_extent */ + if (substart < rbt->rb_ext->ex_start || subend > rbt->rb_ext->ex_end) { + return 1; + } + + if (decodesize == align) { + if(extent_alloc_subregion(rbt->rb_ext, substart, subend, size, align, 0, + exflags, (u_long *)&result)) { + return 1; + } + } else if (decodesize == 0) { + /* maybe, the resister is overflowed. */ + + if (extent_alloc_subregion(rbt->rb_ext, addr, addr + size, size, + 0, 0, exflags, (u_long *)&result)) { + return 1; + } + } else { + + boundary = decodesize > align ? decodesize : align; + + search_addr = (substart & ~(boundary - 1)) + addr; + + if (search_addr < substart) { + search_addr += boundary; + } + + for (; search_addr + size <= subend; search_addr += boundary) { + val = extent_alloc_subregion(rbt->rb_ext,search_addr, search_addr+size, + size, align, 0, exflags, (u_long *)&result); + if (val == 0) { + break; + } + } + if (val) { + return 1; + } + } + + if(md_space_map(rbt->rb_bt, result, size, flags, bshp)) { + /* map failed */ + extent_free(rbt->rb_ext, result, size, exflags); + return 1; + } + + if (addrp != NULL) { + *addrp = result + rbt->rb_offset; + } + return 0; + + } else { + /* error!! */ + return 1; + } + return 1; +} + + + + + +int +rbus_space_free(rbt, bsh, size, addrp) + rbus_tag_t rbt; + bus_space_handle_t bsh; + bus_size_t size; + bus_addr_t *addrp; +{ + int exflags = EX_FAST | EX_NOWAIT; + bus_addr_t addr; + int status = 1; + + if (rbt->rb_flags == RBUS_SPACE_ASK_PARENT) { + status = rbus_space_free(rbt->rb_parent, bsh, size, &addr); + } else if (rbt->rb_flags == RBUS_SPACE_SHARE || + rbt->rb_flags == RBUS_SPACE_DEDICATE) { + md_space_unmap(rbt->rb_bt, bsh, size, &addr); + + extent_free(rbt->rb_ext, addr, size, exflags); + + status = 0; + } else { + /* error. INVALID rbustag */ + status = 1; + } + if (addrp != NULL) { + *addrp = addr; + } + return status; +} + + + +/* + * static rbus_tag_t + * rbus_new_body(bus_space_tag_t bt, rbus_tag_t parent, + * struct extent *ex, bus_addr_t start, bus_size_t end, + * bus_addr_t offset, int flags) + * + */ +static rbus_tag_t +rbus_new_body(bt, parent, ex, start, end, offset, flags) + bus_space_tag_t bt; + rbus_tag_t parent; + struct extent *ex; + bus_addr_t start, end, offset; + int flags; +{ + rbus_tag_t rb; + + /* sanity check */ + if (parent != NULL) { + if (start < parent->rb_start || end > parent->rb_end) { + /* out of range: [start, size] should be containd in parent space */ + return 0; + /* Should I invoke panic? */ + } + } + + if (NULL == (rb = (rbus_tag_t)malloc(sizeof(struct rbustag), M_DEVBUF, + M_NOWAIT))) { + panic("no memory for rbus instance"); + } + + rb->rb_bt = bt; + rb->rb_parent = parent; + rb->rb_start = start; + rb->rb_end = end; + rb->rb_offset = offset; + rb->rb_flags = flags; + rb->rb_ext = ex; + + DPRINTF(("rbus_new_body: [%lx, %lx] type %s name [%s]\n", start, end, + flags == RBUS_SPACE_SHARE ? "share" : + flags == RBUS_SPACE_DEDICATE ? "dedicated" : + flags == RBUS_SPACE_ASK_PARENT ? "parent" : "invalid", + ex != NULL ? ex->ex_name : "noname")); + + return rb; +} + + + +/* + * rbus_tag_t rbus_new(rbus_tag_t parent, bus_addr_t start, bus_size_t + * size, bus_addr_t offset, int flags) + * + * This function makes a new child rbus instance. + */ +rbus_tag_t +rbus_new(parent, start, size, offset, flags) + rbus_tag_t parent; + bus_addr_t start; + bus_size_t size; + bus_addr_t offset; + int flags; +{ + rbus_tag_t rb; + struct extent *ex = NULL; + bus_addr_t end = start + size; + + if (flags == RBUS_SPACE_SHARE) { + ex = parent->rb_ext; + } else if (flags == RBUS_SPACE_DEDICATE) { + if (NULL == (ex = extent_create("rbus", start, end, M_DEVBUF, NULL, 0, + EX_NOCOALESCE|EX_NOWAIT))) { + free(rb, M_DEVBUF); + return NULL; + } + } else if (flags == RBUS_SPACE_ASK_PARENT) { + ex = NULL; + } else { + /* Invalid flag */ + return 0; + } + + rb = rbus_new_body(parent->rb_bt, parent, ex, start, start + size, + offset, flags); + + if ((rb == NULL) && (flags == RBUS_SPACE_DEDICATE)) { + extent_destroy(ex); + } + + return rb; +} + + + + +/* + * rbus_tag_t rbus_new_root_delegate(bus_space_tag, bus_addr_t, + * bus_size_t, bus_addr_t offset) + * + * This function makes a root rbus instance. + */ +rbus_tag_t +rbus_new_root_delegate(bt, start, size, offset) + bus_space_tag_t bt; + bus_addr_t start; + bus_size_t size; + bus_addr_t offset; +{ + rbus_tag_t rb; + struct extent *ex; + + if (NULL == (ex = extent_create("rbus root", start, start + size, M_DEVBUF, + NULL, 0, EX_NOCOALESCE|EX_NOWAIT))) { + return NULL; + } + + rb = rbus_new_body(bt, NULL, ex, start, start + size, offset, + RBUS_SPACE_DEDICATE); + + if (rb == NULL) { + extent_destroy(ex); + } + + return rb; +} + + + +/* + * rbus_tag_t rbus_new_root_share(bus_space_tag, struct extent *, + * bus_addr_t, bus_size_t, bus_addr_t offset) + * + * This function makes a root rbus instance. + */ +rbus_tag_t +rbus_new_root_share(bt, ex, start, size, offset) + bus_space_tag_t bt; + struct extent *ex; + bus_addr_t start; + bus_size_t size; + bus_addr_t offset; +{ + /* sanity check */ + if (start < ex->ex_start || start + size > ex->ex_end) { + /* out of range: [start, size] should be containd in parent space */ + return 0; + /* Should I invoke panic? */ + } + + return rbus_new_body(bt, NULL, ex, start, start + size, offset, + RBUS_SPACE_SHARE); +} + + + + + +/* + * int rbus_delete (rbus_tag_t rb) + * + * This function deletes the rbus structure pointed in the argument. + */ +int +rbus_delete(rb) + rbus_tag_t rb; +{ + DPRINTF(("rbus_delete called [%s]\n", + rb->rb_ext != NULL ? rb->rb_ext->ex_name : "noname")); + if (rb->rb_flags == RBUS_SPACE_DEDICATE) { + extent_destroy(rb->rb_ext); + } + + free(rb, M_DEVBUF); + + return 0; +} diff --git a/sys/dev/cardbus/rbus.h b/sys/dev/cardbus/rbus.h new file mode 100644 index 000000000000..6c6cfc51f0ea --- /dev/null +++ b/sys/dev/cardbus/rbus.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the author. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* $Id: rbus.h,v 1.1 1999/10/15 06:07:25 haya Exp $ */ + +/* + * This file defines rbus (pseudo) class + * + * What is rbus? + * + * Ths rbus is a recursive bus-space administrator. This means a + * parent bus-space administrator, which usually belongs to a bus + * bridge, makes some child bus-space administorators and gives + * (restricted) bus-space for children. There are a root bus-space + * administrator which maintains whole bus-space. + * + * Why recursive? + * + * The recursive bus-space administration has two virtues. The + * former is this modelling matches the actual memory and io space + * management of bridge devices well. The latter is the rbus is + * distributed management system, so it matches well with + * multi-thread kernel. + * + * Abstraction + * + * The rbus models bus-to-bus bridge into three way: dedicate, share + * and slave. Dedicate means that the bridge has dedicate bus space. + * Share means that the bridge has bus space, but this bus space is + * shared with other bus bridges. Slave means the bus bridge which + * does not have it own bus space and ask a parent bus bridge for bus + * space when a client requests bus space to the bridge. + */ + + +#if !defined SYS_DEV_CARDBUS_RBUS_H +#define SYS_DEV_CARDBUS_RBUS_H + +/* require sys/extent.h */ +/* require machine/bus.h */ + +#define rbus 1 + + +struct extent; + + +/* + * General rule + * + * 1) When a rbustag has no space for child (it means rb_extent is + * NULL), ask bus-space for parent through rb_parent. + * + * 2) When a rbustag has its own space (whether shared or dedicated), + * allocate from rb_ext. + */ +struct rbustag { + bus_space_tag_t rb_bt; + struct rbustag *rb_parent; + struct extent *rb_ext; + bus_addr_t rb_start; + bus_addr_t rb_end; + bus_addr_t rb_offset; +#if notyet + int (*rb_space_alloc) __P((struct rbustag *, + bus_addr_t start, bus_addr_t end, + bus_addr_t addr, bus_size_t size, + bus_addr_t mask, bus_addr_t align, + int flags, + bus_addr_t *addrp, bus_space_handle_t *bshp)); + int (*rbus_space_free) __P((struct rbustag *, bus_space_handle_t, + bus_size_t size, bus_addr_t *addrp)); +#endif + int rb_flags; +#define RBUS_SPACE_INVALID 0x00 +#define RBUS_SPACE_SHARE 0x01 +#define RBUS_SPACE_DEDICATE 0x02 +#define RBUS_SPACE_MASK 0x03 +#define RBUS_SPACE_ASK_PARENT 0x04 + /* your own data below */ + void *rb_md; +}; + +typedef struct rbustag *rbus_tag_t; + + + + +/* + * These functions sugarcoat rbus interface to make rbus being used + * easier. These functions should be member functions of rbus + * `class'. + */ +int rbus_space_alloc __P((rbus_tag_t, + bus_addr_t addr, bus_size_t size, bus_addr_t mask, + bus_addr_t align, int flags, + bus_addr_t *addrp, bus_space_handle_t *bshp)); + +int rbus_space_alloc_subregion __P((rbus_tag_t, + bus_addr_t start, bus_addr_t end, + bus_addr_t addr, bus_size_t size, + bus_addr_t mask, bus_addr_t align, + int flags, + bus_addr_t *addrp, bus_space_handle_t *bshp)); + +int rbus_space_free __P((rbus_tag_t, bus_space_handle_t, bus_size_t size, + bus_addr_t *addrp)); + + +/* + * These functions create rbus instance. These functions are + * so-called-as a constructor of rbus. + * + * rbus_new is a constructor which make an rbus instance from a parent + * rbus. + */ +rbus_tag_t rbus_new __P((rbus_tag_t parent, bus_addr_t start, bus_size_t size, + bus_addr_t offset, int flags)); + +rbus_tag_t rbus_new_root_delegate __P((bus_space_tag_t, bus_addr_t, bus_size_t, + bus_addr_t offset)); +rbus_tag_t rbus_new_root_share __P((bus_space_tag_t, struct extent *, + bus_addr_t, bus_size_t,bus_addr_t offset)); + +/* + * This function release bus-space used by the argument. This + * function is so-called-as a destructor. + */ +int rbus_delete __P((rbus_tag_t)); + + +/* + * Machine-dependent definitions. + */ +#include + +#endif /* SYS_DEV_CARDBUS_RBUS_H */ diff --git a/sys/dev/ic/elinkxl.c b/sys/dev/ic/elinkxl.c index f2f32d77094d..6dd5d0828ca0 100644 --- a/sys/dev/ic/elinkxl.c +++ b/sys/dev/ic/elinkxl.c @@ -1,4 +1,4 @@ -/* $NetBSD: elinkxl.c,v 1.14 1999/09/01 21:03:02 fvdl Exp $ */ +/* $NetBSD: elinkxl.c,v 1.15 1999/10/15 06:07:26 haya Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -210,6 +210,11 @@ ex_config(sc) printf("%s: MAC address %s\n", sc->sc_dev.dv_xname, ether_sprintf(macaddr)); + if (sc->intr_ack) { /* 3C575BTX specific */ + GO_WINDOW(2); + bus_space_write_2(sc->sc_iot, ioh, 12, 0x10|bus_space_read_2(sc->sc_iot, ioh, 12)); + } + attach_stage = 0; /* @@ -630,7 +635,8 @@ ex_init(sc) bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_INTR_MASK | S_MASK); bus_space_write_2(iot, ioh, ELINK_COMMAND, ACK_INTR | 0xff); - + if (sc->intr_ack) + (* sc->intr_ack)(sc); ex_set_media(sc); ex_set_mc(sc); @@ -1082,6 +1088,9 @@ ex_intr(arg) int ret = 0; struct ifnet *ifp = &sc->sc_ethercom.ec_if; + if (sc->enabled == 0) { + return ret; + } for (;;) { stat = bus_space_read_2(iot, ioh, ELINK_STATUS); if (!(stat & S_MASK)) @@ -1091,6 +1100,8 @@ ex_intr(arg) */ bus_space_write_2(iot, ioh, ELINK_COMMAND, ACK_INTR | (stat & S_MASK)); + if (sc->intr_ack) + (*sc->intr_ack)(sc); ret = 1; if (stat & S_HOST_ERROR) { printf("%s: adapter failure (%x)\n", diff --git a/sys/dev/ic/elinkxlvar.h b/sys/dev/ic/elinkxlvar.h index 7094ddbcfcd4..c20f6a595047 100644 --- a/sys/dev/ic/elinkxlvar.h +++ b/sys/dev/ic/elinkxlvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: elinkxlvar.h,v 1.2 1999/04/13 23:07:26 jonathan Exp $ */ +/* $NetBSD: elinkxlvar.h,v 1.3 1999/10/15 06:07:27 haya Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -116,6 +116,8 @@ struct ex_softc { int (*enable) __P((struct ex_softc *)); void (*disable) __P((struct ex_softc *)); int enabled; + /* interrupt acknowledge hook */ + void (*intr_ack) __P((struct ex_softc *)); }; #define ex_waitcmd(sc) \ diff --git a/sys/dev/ic/i82365.c b/sys/dev/ic/i82365.c index 0fa22ff3dd64..d9f1880a5bde 100644 --- a/sys/dev/ic/i82365.c +++ b/sys/dev/ic/i82365.c @@ -1,4 +1,4 @@ -/* $NetBSD: i82365.c,v 1.24 1999/07/06 21:44:10 thorpej Exp $ */ +/* $NetBSD: i82365.c,v 1.25 1999/10/15 06:07:27 haya Exp $ */ #define PCICDEBUG @@ -94,6 +94,9 @@ void pcic_queue_event __P((struct pcic_handle *, int)); static void pcic_wait_ready __P((struct pcic_handle *)); +static u_int8_t st_pcic_read __P((struct pcic_handle *, int)); +static void st_pcic_write __P((struct pcic_handle *, int, u_int8_t)); + int pcic_ident_ok(ident) int ident; @@ -183,8 +186,13 @@ pcic_attach(sc) DPRINTF(("pcic ident regs:")); - sc->handle[0].sc = sc; + sc->handle[0].ph_parent = (struct device *)sc; sc->handle[0].sock = C0SA; + /* initialise pcic_read and pcic_write functions */ + sc->handle[0].ph_read = st_pcic_read; + sc->handle[0].ph_write = st_pcic_write; + sc->handle[0].ph_bus_t = sc->iot; + sc->handle[0].ph_bus_h = sc->ioh; if (pcic_ident_ok(reg = pcic_read(&sc->handle[0], PCIC_IDENT))) { sc->handle[0].flags = PCIC_FLAG_SOCKETP; count++; @@ -195,8 +203,13 @@ pcic_attach(sc) DPRINTF((" 0x%02x", reg)); - sc->handle[1].sc = sc; + sc->handle[1].ph_parent = (struct device *)sc; sc->handle[1].sock = C0SB; + /* initialise pcic_read and pcic_write functions */ + sc->handle[1].ph_read = st_pcic_read; + sc->handle[1].ph_write = st_pcic_write; + sc->handle[1].ph_bus_t = sc->iot; + sc->handle[1].ph_bus_h = sc->ioh; if (pcic_ident_ok(reg = pcic_read(&sc->handle[1], PCIC_IDENT))) { sc->handle[1].flags = PCIC_FLAG_SOCKETP; count++; @@ -212,8 +225,13 @@ pcic_attach(sc) * if you try to read from the second one. Maybe pcic_ident_ok * shouldn't accept 0? */ - sc->handle[2].sc = sc; + sc->handle[2].ph_parent = (struct device *)sc; sc->handle[2].sock = C1SA; + /* initialise pcic_read and pcic_write functions */ + sc->handle[2].ph_read = st_pcic_read; + sc->handle[2].ph_write = st_pcic_write; + sc->handle[2].ph_bus_t = sc->iot; + sc->handle[2].ph_bus_h = sc->ioh; if (pcic_vendor(&sc->handle[0]) != PCIC_VENDOR_CIRRUS_PD672X || pcic_read(&sc->handle[2], PCIC_IDENT) != 0) { if (pcic_ident_ok(reg = pcic_read(&sc->handle[2], @@ -227,8 +245,13 @@ pcic_attach(sc) DPRINTF((" 0x%02x", reg)); - sc->handle[3].sc = sc; + sc->handle[3].ph_parent = (struct device *)sc; sc->handle[3].sock = C1SB; + /* initialise pcic_read and pcic_write functions */ + sc->handle[3].ph_read = st_pcic_read; + sc->handle[3].ph_write = st_pcic_write; + sc->handle[3].ph_bus_t = sc->iot; + sc->handle[3].ph_bus_h = sc->ioh; if (pcic_ident_ok(reg = pcic_read(&sc->handle[3], PCIC_IDENT))) { sc->handle[3].flags = PCIC_FLAG_SOCKETP; @@ -322,6 +345,7 @@ pcic_attach_socket(h) struct pcic_handle *h; { struct pcmciabus_attach_args paa; + struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent); /* initialize the rest of the handle */ @@ -332,12 +356,13 @@ pcic_attach_socket(h) /* now, config one pcmcia device per socket */ - paa.pct = (pcmcia_chipset_tag_t) h->sc->pct; + paa.paa_busname = "pcmcia"; + paa.pct = (pcmcia_chipset_tag_t) sc->pct; paa.pch = (pcmcia_chipset_handle_t) h; - paa.iobase = h->sc->iobase; - paa.iosize = h->sc->iosize; + paa.iobase = sc->iobase; + paa.iosize = sc->iosize; - h->pcmcia = config_found_sm(&h->sc->dev, &paa, pcic_print, + h->pcmcia = config_found_sm(&sc->dev, &paa, pcic_print, pcic_submatch); /* if there's actually a pcmcia device attached, initialize the slot */ @@ -371,9 +396,9 @@ pcic_create_event_thread(arg) } if (kthread_create1(pcic_event_thread, h, &h->event_thread, - "%s,%s", h->sc->dev.dv_xname, cs)) { + "%s,%s", h->ph_parent->dv_xname, cs)) { printf("%s: unable to create event thread for sock 0x%02x\n", - h->sc->dev.dv_xname, h->sock); + h->ph_parent->dv_xname, h->sock); panic("pcic_create_event_thread"); } } @@ -385,6 +410,7 @@ pcic_event_thread(arg) struct pcic_handle *h = arg; struct pcic_event *pe; int s; + struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent); while (h->shutdown == 0) { s = splhigh(); @@ -422,7 +448,7 @@ pcic_event_thread(arg) } splx(s); - DPRINTF(("%s: insertion event\n", h->sc->dev.dv_xname)); + DPRINTF(("%s: insertion event\n", h->ph_parent->dv_xname)); pcic_attach_card(h); break; @@ -446,7 +472,7 @@ pcic_event_thread(arg) } splx(s); - DPRINTF(("%s: removal event\n", h->sc->dev.dv_xname)); + DPRINTF(("%s: removal event\n", h->ph_parent->dv_xname)); pcic_detach_card(h, DETACH_FORCE); break; @@ -460,7 +486,7 @@ pcic_event_thread(arg) h->event_thread = NULL; /* In case parent is waiting for us to exit. */ - wakeup(h->sc); + wakeup(sc); kthread_exit(0); } @@ -470,6 +496,7 @@ pcic_init_socket(h) struct pcic_handle *h; { int reg; + struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent); /* * queue creation of a kernel thread to handle insert/removal events. @@ -482,7 +509,7 @@ pcic_init_socket(h) /* set up the card to interrupt on card detect */ - pcic_write(h, PCIC_CSC_INTR, (h->sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) | + pcic_write(h, PCIC_CSC_INTR, (sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) | PCIC_CSC_INTR_CD_ENABLE); pcic_write(h, PCIC_INTR, 0); pcic_read(h, PCIC_CSC); @@ -494,7 +521,7 @@ pcic_init_socket(h) reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2); if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) { DPRINTF(("%s: socket %02x was suspended\n", - h->sc->dev.dv_xname, h->sock)); + h->ph_parent->dv_xname, h->sock)); reg &= ~PCIC_CIRRUS_MISC_CTL_2_SUSPEND; pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg); } @@ -637,21 +664,21 @@ pcic_intr_socket(h) PCIC_CSC_BATTDEAD); if (cscreg & PCIC_CSC_GPI) { - DPRINTF(("%s: %02x GPI\n", h->sc->dev.dv_xname, h->sock)); + DPRINTF(("%s: %02x GPI\n", h->ph_parent->dv_xname, h->sock)); } if (cscreg & PCIC_CSC_CD) { int statreg; statreg = pcic_read(h, PCIC_IF_STATUS); - DPRINTF(("%s: %02x CD %x\n", h->sc->dev.dv_xname, h->sock, + DPRINTF(("%s: %02x CD %x\n", h->ph_parent->dv_xname, h->sock, statreg)); if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == PCIC_IF_STATUS_CARDDETECT_PRESENT) { if (h->laststate != PCIC_LASTSTATE_PRESENT) { DPRINTF(("%s: enqueing INSERTION event\n", - h->sc->dev.dv_xname)); + h->ph_parent->dv_xname)); pcic_queue_event(h, PCIC_EVENT_INSERTION); } h->laststate = PCIC_LASTSTATE_PRESENT; @@ -659,11 +686,11 @@ pcic_intr_socket(h) if (h->laststate == PCIC_LASTSTATE_PRESENT) { /* Deactivate the card now. */ DPRINTF(("%s: deactivating card\n", - h->sc->dev.dv_xname)); + h->ph_parent->dv_xname)); pcic_deactivate_card(h); DPRINTF(("%s: enqueing REMOVAL event\n", - h->sc->dev.dv_xname)); + h->ph_parent->dv_xname)); pcic_queue_event(h, PCIC_EVENT_REMOVAL); } h->laststate = ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == 0) @@ -671,14 +698,14 @@ pcic_intr_socket(h) } } if (cscreg & PCIC_CSC_READY) { - DPRINTF(("%s: %02x READY\n", h->sc->dev.dv_xname, h->sock)); + DPRINTF(("%s: %02x READY\n", h->ph_parent->dv_xname, h->sock)); /* shouldn't happen */ } if (cscreg & PCIC_CSC_BATTWARN) { - DPRINTF(("%s: %02x BATTWARN\n", h->sc->dev.dv_xname, h->sock)); + DPRINTF(("%s: %02x BATTWARN\n", h->ph_parent->dv_xname, h->sock)); } if (cscreg & PCIC_CSC_BATTDEAD) { - DPRINTF(("%s: %02x BATTDEAD\n", h->sc->dev.dv_xname, h->sock)); + DPRINTF(("%s: %02x BATTDEAD\n", h->ph_parent->dv_xname, h->sock)); } return (cscreg ? 1 : 0); } @@ -759,6 +786,7 @@ pcic_chip_mem_alloc(pch, size, pcmhp) bus_addr_t addr; bus_size_t sizepg; int i, mask, mhandle; + struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent); /* out of sc->memh, allocate as many pages as necessary */ @@ -773,15 +801,15 @@ pcic_chip_mem_alloc(pch, size, pcmhp) mhandle = 0; /* XXX gcc -Wuninitialized */ for (i = 0; i <= PCIC_MAX_MEM_PAGES - sizepg; i++) { - if ((h->sc->subregionmask & (mask << i)) == (mask << i)) { - if (bus_space_subregion(h->sc->memt, h->sc->memh, + if ((sc->subregionmask & (mask << i)) == (mask << i)) { + if (bus_space_subregion(sc->memt, sc->memh, i * PCIC_MEM_PAGESIZE, sizepg * PCIC_MEM_PAGESIZE, &memh)) return (1); mhandle = mask << i; - addr = h->sc->membase + (i * PCIC_MEM_PAGESIZE); - h->sc->subregionmask &= ~(mhandle); - pcmhp->memt = h->sc->memt; + addr = sc->membase + (i * PCIC_MEM_PAGESIZE); + sc->subregionmask &= ~(mhandle); + pcmhp->memt = sc->memt; pcmhp->memh = memh; pcmhp->addr = addr; pcmhp->size = size; @@ -800,8 +828,9 @@ pcic_chip_mem_free(pch, pcmhp) struct pcmcia_mem_handle *pcmhp; { struct pcic_handle *h = (struct pcic_handle *) pch; + struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent); - h->sc->subregionmask |= pcmhp->mhandle; + sc->subregionmask |= pcmhp->mhandle; } static struct mem_map_index_st { @@ -932,6 +961,7 @@ pcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp) bus_addr_t busaddr; long card_offset; int i, win; + struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent); win = -1; for (i = 0; i < (sizeof(mem_map_index) / sizeof(mem_map_index[0])); @@ -950,7 +980,7 @@ pcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp) /* XXX this is pretty gross */ - if (h->sc->memt != pcmhp->memt) + if (sc->memt != pcmhp->memt) panic("pcic_chip_mem_map memt is bogus"); busaddr = pcmhp->addr; @@ -1018,12 +1048,13 @@ pcic_chip_io_alloc(pch, start, size, align, pcihp) bus_space_handle_t ioh; bus_addr_t ioaddr; int flags = 0; + struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent); /* * Allocate some arbitrary I/O space. */ - iot = h->sc->iot; + iot = sc->iot; if (start) { ioaddr = start; @@ -1033,8 +1064,8 @@ pcic_chip_io_alloc(pch, start, size, align, pcihp) (u_long) ioaddr, (u_long) size)); } else { flags |= PCMCIA_IO_ALLOCATED; - if (bus_space_alloc(iot, h->sc->iobase, - h->sc->iobase + h->sc->iosize, size, align, 0, 0, + if (bus_space_alloc(iot, sc->iobase, + sc->iobase + sc->iosize, size, align, 0, 0, &ioaddr, &ioh)) return (1); DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n", @@ -1154,6 +1185,7 @@ pcic_chip_io_map(pch, width, offset, size, pcihp, windowp) #ifdef PCICDEBUG static char *width_names[] = { "auto", "io8", "io16" }; #endif + struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent); /* XXX Sanity check offset/size. */ @@ -1173,7 +1205,7 @@ pcic_chip_io_map(pch, width, offset, size, pcihp, windowp) /* XXX this is pretty gross */ - if (h->sc->iot != pcihp->iot) + if (sc->iot != pcihp->iot) panic("pcic_chip_io_map iot is bogus"); DPRINTF(("pcic_chip_io_map window %d %s port %lx+%lx\n", @@ -1256,8 +1288,8 @@ pcic_chip_socket_enable(pch) delay((300 + 100) * 1000); #ifdef VADEM_POWER_HACK - bus_space_write_1(h->sc->iot, h->sc->ioh, PCIC_REG_INDEX, 0x0e); - bus_space_write_1(h->sc->iot, h->sc->ioh, PCIC_REG_INDEX, 0x37); + bus_space_write_1(sc->iot, sc->ioh, PCIC_REG_INDEX, 0x0e); + bus_space_write_1(sc->iot, sc->ioh, PCIC_REG_INDEX, 0x37); printf("prcr = %02x\n", pcic_read(h, 0x02)); printf("cvsr = %02x\n", pcic_read(h, 0x2f)); printf("DANGER WILL ROBINSON! Changing voltage select!\n"); @@ -1324,8 +1356,8 @@ pcic_chip_socket_enable(pch) pcic_write(h, PCIC_INTR, reg); DPRINTF(("%s: pcic_chip_socket_enable %02x cardtype %s %02x\n", - h->sc->dev.dv_xname, h->sock, - ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), reg)); + h->ph_parent->dv_xname, h->sock, + ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), reg)); /* reinstall all the memory and io mappings */ @@ -1355,3 +1387,31 @@ pcic_chip_socket_disable(pch) */ delay(300 * 1000); } + + + + +static u_int8_t +st_pcic_read(h, idx) + struct pcic_handle *h; + int idx; +{ + if (idx != -1) { + bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_INDEX, h->sock + idx); + } + + return bus_space_read_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_DATA); +} + +static void +st_pcic_write(h, idx, data) + struct pcic_handle *h; + int idx; + u_int8_t data; +{ + if (idx != -1) { + bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_INDEX, h->sock + idx); + } + + bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_DATA, data); +} diff --git a/sys/dev/ic/i82365var.h b/sys/dev/ic/i82365var.h index 1db4728367b2..21f4d6f571c7 100644 --- a/sys/dev/ic/i82365var.h +++ b/sys/dev/ic/i82365var.h @@ -1,4 +1,4 @@ -/* $NetBSD: i82365var.h,v 1.7 1999/01/21 07:43:33 msaitoh Exp $ */ +/* $NetBSD: i82365var.h,v 1.8 1999/10/15 06:07:27 haya Exp $ */ /* * Copyright (c) 1997 Marc Horowitz. All rights reserved. @@ -48,7 +48,12 @@ struct pcic_event { #define PCIC_EVENT_REMOVAL 1 struct pcic_handle { - struct pcic_softc *sc; + struct device *ph_parent; + bus_space_tag_t ph_bus_t; /* I/O or MEM? I don't mind */ + bus_space_handle_t ph_bus_h; + u_int8_t (* ph_read) __P((struct pcic_handle*, int)); + void (* ph_write) __P((struct pcic_handle *, int, u_int8_t)); + int vendor; int sock; int flags; @@ -141,8 +146,10 @@ void pcic_attach __P((struct pcic_softc *)); void pcic_attach_sockets __P((struct pcic_softc *)); int pcic_intr __P((void *arg)); +/* static inline int pcic_read __P((struct pcic_handle *, int)); -static inline void pcic_write __P((struct pcic_handle *, int, int)); +static inline void pcic_write __P((struct pcic_handle *, int, u_int8_t)); +*/ int pcic_chip_mem_alloc __P((pcmcia_chipset_handle_t, bus_size_t, struct pcmcia_mem_handle *)); @@ -163,6 +170,8 @@ void pcic_chip_io_unmap __P((pcmcia_chipset_handle_t, int)); void pcic_chip_socket_enable __P((pcmcia_chipset_handle_t)); void pcic_chip_socket_disable __P((pcmcia_chipset_handle_t)); +#if 0 + static __inline int pcic_read __P((struct pcic_handle *, int)); static __inline int pcic_read(h, idx) @@ -187,3 +196,11 @@ pcic_write(h, idx, data) h->sock + idx); bus_space_write_1(h->sc->iot, h->sc->ioh, PCIC_REG_DATA, (data)); } +#else +#define pcic_read(h, idx) \ + (*(h)->ph_read)((h), (idx)) + +#define pcic_write(h, idx, data) \ + (*(h)->ph_write)((h), (idx), (data)) + +#endif diff --git a/sys/dev/isa/i82365_isasubr.c b/sys/dev/isa/i82365_isasubr.c index b8782209d444..c2dbe9801c51 100644 --- a/sys/dev/isa/i82365_isasubr.c +++ b/sys/dev/isa/i82365_isasubr.c @@ -1,4 +1,4 @@ -/* $NetBSD: i82365_isasubr.c,v 1.3 1999/02/19 03:14:01 mycroft Exp $ */ +/* $NetBSD: i82365_isasubr.c,v 1.4 1999/10/15 06:07:27 haya Exp $ */ #define PCICISADEBUG @@ -217,7 +217,8 @@ pcic_isa_chip_intr_establish(pch, pf, ipl, fct, arg) void *arg; { struct pcic_handle *h = (struct pcic_handle *) pch; - isa_chipset_tag_t ic = h->sc->intr_est; + struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent); + isa_chipset_tag_t ic = sc->intr_est; int irq, ist; void *ih; int reg; @@ -254,7 +255,8 @@ pcic_isa_chip_intr_disestablish(pch, ih) void *ih; { struct pcic_handle *h = (struct pcic_handle *) pch; - isa_chipset_tag_t ic = h->sc->intr_est; + struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent); + isa_chipset_tag_t ic = sc->intr_est; int reg; h->ih_irq = 0; diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index a6f59bcf86d1..3099567b0c89 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $NetBSD: files.pci,v 1.64 1999/10/13 18:37:13 thorpej Exp $ +# $NetBSD: files.pci,v 1.65 1999/10/15 06:07:28 haya Exp $ # # Config file and device description for machine-independent PCI code. # Included by ports that need it. Requires that the SCSI files be @@ -232,3 +232,9 @@ file dev/pci/if_ti.c ti # Adaptec AIC-6915 Ethernet interface attach sf at pci with sf_pci file dev/pci/if_sf_pci.c sf_pci + +# YENTA PCI-Cardbus bridge +#device cbb: cbbus, pcmciabus +device cbb: pcmciaslot +attach cbb at pci with cbb_pci +file dev/pci/pccbb.c cbb diff --git a/sys/dev/pci/pccbb.c b/sys/dev/pci/pccbb.c new file mode 100644 index 000000000000..2a09b51e832c --- /dev/null +++ b/sys/dev/pci/pccbb.c @@ -0,0 +1,3041 @@ +/* + * Copyright (c) 1998 and 1999 HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by HAYAKAWA Koichi. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id: pccbb.c,v 1.1 1999/10/15 06:07:28 haya Exp $ */ + +/* +#define CBB_DEBUG +#define SHOW_REGS +#define PCCBB_PCMCIA_POLL +*/ +/* #define CBB_DEBUG */ + +/* +#define CB_PCMCIA_POLL +#define CB_PCMCIA_POLL_ONLY +#define LEVEL2 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +#include +#include +#include + +#include "locators.h" + + +#ifndef __NetBSD_Version__ +struct cfdriver cbb_cd = { + NULL, "cbb", DV_DULL +}; +#endif + +#if defined CBB_DEBUG +#define DPRINTF(x) printf x +#define STATIC +#else +#define DPRINTF(x) +#define STATIC static +#endif + + +#ifdef __BROKEN_INDIRECT_CONFIG +int pcicbbmatch __P((struct device *, void *, void *)); +#else +int pcicbbmatch __P((struct device *, struct cfdata *, void *)); +#endif +void pccbbattach __P((struct device *, struct device *, void *)); +int pccbbintr __P((void *)); +static void pci113x_insert __P((void *)); + +static int pccbb_detect_card __P((struct pccbb_softc *)); + +static void pccbb_pcmcia_write __P((struct pcic_handle *, int, u_int8_t)); +static u_int8_t pccbb_pcmcia_read __P((struct pcic_handle *, int)); +#define Pcic_read(ph, reg) ((ph)->ph_read((ph), (reg))) +#define Pcic_write(ph, reg, val) ((ph)->ph_write((ph), (reg), (val))) + + +STATIC int cb_reset __P((struct pccbb_softc *)); +STATIC int cb_detect_voltage __P((struct pccbb_softc *)); +STATIC int cbbprint __P((void *, const char *)); + +static int cb_chipset __P((u_int32_t, char const **, int *)); +STATIC void pccbb_pcmcia_attach_setup __P((struct pccbb_softc *, struct pcmciabus_attach_args *)); +#if 0 +STATIC void pccbb_pcmcia_attach_card __P((struct pcic_handle *)); +STATIC void pccbb_pcmcia_detach_card __P((struct pcic_handle *, int)); +STATIC void pccbb_pcmcia_deactivate_card __P((struct pcic_handle *)); +#endif + +STATIC int pccbb_ctrl __P((cardbus_chipset_tag_t, int)); +STATIC int pccbb_power __P((cardbus_chipset_tag_t, int)); +STATIC int pccbb_cardenable __P((struct pccbb_softc *sc, int function)); +#if !rbus +static int pccbb_io_open __P((cardbus_chipset_tag_t, int, u_int32_t, u_int32_t)); +static int pccbb_io_close __P((cardbus_chipset_tag_t, int)); +static int pccbb_mem_open __P((cardbus_chipset_tag_t, int, u_int32_t, u_int32_t)); +static int pccbb_mem_close __P((cardbus_chipset_tag_t, int)); +#endif /* !rbus */ +static void *pccbb_intr_establish __P((cardbus_chipset_tag_t, int irq, int level, int (* ih)(void *), void *sc)); +static void pccbb_intr_disestablish __P((cardbus_chipset_tag_t ct, void *ih)); + +static cardbustag_t pccbb_make_tag __P((cardbus_chipset_tag_t, int, int, int)); +static void pccbb_free_tag __P((cardbus_chipset_tag_t, cardbustag_t)); +static cardbusreg_t pccbb_conf_read __P((cardbus_chipset_tag_t, cardbustag_t, int)); +static void pccbb_conf_write __P((cardbus_chipset_tag_t, cardbustag_t, int, cardbusreg_t)); +static void pccbb_chipinit __P((struct pccbb_softc *)); + + +STATIC int pccbb_pcmcia_mem_alloc __P((pcmcia_chipset_handle_t, bus_size_t, + struct pcmcia_mem_handle *)); +STATIC void pccbb_pcmcia_mem_free __P((pcmcia_chipset_handle_t, + struct pcmcia_mem_handle *)); +STATIC int pccbb_pcmcia_mem_map __P((pcmcia_chipset_handle_t, int, bus_addr_t, + bus_size_t, struct pcmcia_mem_handle *, bus_addr_t *, int *)); +STATIC void pccbb_pcmcia_mem_unmap __P((pcmcia_chipset_handle_t, int)); +STATIC int pccbb_pcmcia_io_alloc __P((pcmcia_chipset_handle_t, bus_addr_t, + bus_size_t, bus_size_t, struct pcmcia_io_handle *)); +STATIC void pccbb_pcmcia_io_free __P((pcmcia_chipset_handle_t, + struct pcmcia_io_handle *)); +STATIC int pccbb_pcmcia_io_map __P((pcmcia_chipset_handle_t, int, bus_addr_t, + bus_size_t, struct pcmcia_io_handle *, int *)); +STATIC void pccbb_pcmcia_io_unmap __P((pcmcia_chipset_handle_t, int)); +STATIC void *pccbb_pcmcia_intr_establish __P((pcmcia_chipset_handle_t, + struct pcmcia_function *, int, int (*) (void *), void *)); +STATIC void pccbb_pcmcia_intr_disestablish __P((pcmcia_chipset_handle_t, void *)); +STATIC void pccbb_pcmcia_socket_enable __P((pcmcia_chipset_handle_t)); +STATIC void pccbb_pcmcia_socket_disable __P((pcmcia_chipset_handle_t)); +STATIC int pccbb_pcmcia_card_detect __P((pcmcia_chipset_handle_t pch)); + +static void pccbb_pcmcia_do_io_map __P((struct pcic_handle *, int)); +static void pccbb_pcmcia_wait_ready __P((struct pcic_handle *)); +static void pccbb_pcmcia_do_mem_map __P((struct pcic_handle *, int)); + +/* bus-space allocation and disallocation functions */ +#if rbus + +static int pccbb_rbus_cb_space_alloc __P((cardbus_chipset_tag_t, rbus_tag_t, + bus_addr_t addr, bus_size_t size, + bus_addr_t mask, bus_size_t align, + int flags, bus_addr_t *addrp, + bus_space_handle_t *bshp)); +static int pccbb_rbus_cb_space_free __P((cardbus_chipset_tag_t, rbus_tag_t, + bus_space_handle_t, bus_size_t)); + +#endif /* rbus */ + +#if rbus + +static int pccbb_open_win __P((struct pccbb_softc *, bus_space_tag_t, bus_addr_t, bus_size_t, bus_space_handle_t, int flags)); +static int pccbb_close_win __P((struct pccbb_softc *, bus_space_tag_t, bus_space_handle_t, bus_size_t)); +static int pccbb_winlist_insert __P((struct pccbb_win_chain **, bus_addr_t, + bus_size_t, bus_space_handle_t, int)); +static int pccbb_winlist_delete __P((struct pccbb_win_chain **, + bus_space_handle_t, bus_size_t)); +static void pccbb_winset __P((bus_addr_t align, struct pccbb_softc *, + bus_space_tag_t)); +void pccbb_winlist_show(struct pccbb_win_chain *); + +#endif /* rbus */ + +/* for config_defer */ +static void pccbb_pci_callback __P((struct device *)); + + +#if defined SHOW_REGS +static void cb_show_regs __P((pci_chipset_tag_t pc, pcitag_t tag, bus_space_tag_t memt, bus_space_handle_t memh)); +#endif + + + +struct cfattach cbb_pci_ca = { + sizeof(struct pccbb_softc), pcicbbmatch, pccbbattach +}; + + +static struct pcmcia_chip_functions pccbb_pcmcia_funcs = { + pccbb_pcmcia_mem_alloc, + pccbb_pcmcia_mem_free, + pccbb_pcmcia_mem_map, + pccbb_pcmcia_mem_unmap, + pccbb_pcmcia_io_alloc, + pccbb_pcmcia_io_free, + pccbb_pcmcia_io_map, + pccbb_pcmcia_io_unmap, + pccbb_pcmcia_intr_establish, + pccbb_pcmcia_intr_disestablish, + pccbb_pcmcia_socket_enable, + pccbb_pcmcia_socket_disable, + pccbb_pcmcia_card_detect +}; + +#if rbus +static struct cardbus_functions pccbb_funcs = { + pccbb_rbus_cb_space_alloc, + pccbb_rbus_cb_space_free, + pccbb_intr_establish, + pccbb_intr_disestablish, + pccbb_ctrl, + pccbb_power, + pccbb_make_tag, + pccbb_free_tag, + pccbb_conf_read, + pccbb_conf_write, +}; +#else +static struct cardbus_functions pccbb_funcs = { + pccbb_ctrl, + pccbb_power, + pccbb_mem_open, + pccbb_mem_close, + pccbb_io_open, + pccbb_io_close, + pccbb_intr_establish, + pccbb_intr_disestablish, + pccbb_make_tag, + pccbb_conf_read, + pccbb_conf_write, +}; +#endif + + + + +int +pcicbbmatch(parent, match, aux) + struct device *parent; +#ifdef __BROKEN_INDIRECT_CONFIG + void *match; +#else + struct cfdata *match; +#endif + void *aux; +{ + struct pci_attach_args *pa = (struct pci_attach_args *)aux; + + if ((pa->pa_class & PCI_CLASS_INTERFACE_MASK) == PCI_CLASS_INTERFACE_YENTA) { + /* OK, It must be YENTA PCI-CardBus bridge */ + +#if 0 + if (cb_chipset(pa->pa_id, 0, 0) > 0) { + return 1; + } +#endif + return 1; + } + + return 0; +} + + +#define MAKEID(vendor, prod) (((vendor) << PCI_VENDOR_SHIFT) \ + | ((prod) << PCI_PRODUCT_SHIFT)) + + +struct yenta_chipinfo { + pcireg_t yc_id; /* vendor tag | product tag */ + const char *yc_name; + int yc_chiptype; + int yc_flags; +} yc_chipsets[] = { + /* Texas Instruments chips */ + {MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1130), "TI1130", CB_TI113X, + PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1131), "TI1131", CB_TI113X, + PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, + + {MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1250), "TI1250", CB_TI12XX, + PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1220), "TI1220", CB_TI12XX, + PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1221), "TI1221", CB_TI12XX, + PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1225), "TI1225", CB_TI12XX, + PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1251), "TI1251", CB_TI12XX, + PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1251B), "TI1251B", CB_TI12XX, + PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1211), "TI1211", CB_TI12XX, + PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1420), "TI1420", CB_TI12XX, + PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1450), "TI1450", CB_TI12XX, + PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI2030), "TI2030", CB_UNKNOWN, + PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, + + /* Ricoh chips */ + {MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C475), "RF5C475", + CB_RF5C47X, PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C476), "RF5C476", + CB_RF5C47X, PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C477), "RF5C477", + CB_RF5C47X, PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C478), "RF5C478", + CB_RF5C47X, PCCBB_PCMCIA_MEM_32}, + + {MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C465), "RF5C465", + CB_RF5C46X, PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C466), "RF5C466", + CB_RF5C46X, PCCBB_PCMCIA_MEM_32}, + + /* Toshiba products */ + {MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC95), "ToPIC95", + CB_TOPIC95, PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC95B), "ToPIC95B", + CB_TOPIC95B, PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC97), "ToPIC97", + CB_TOPIC97, PCCBB_PCMCIA_MEM_32}, + + /* Cirrus Logic products */ + {MAKEID(PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_PD6832), "CL-PD683X", + CB_CIRRUS, PCCBB_PCMCIA_MEM_32}, + {MAKEID(PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_PD6833), "CL-PD683X", + CB_CIRRUS, PCCBB_PCMCIA_MEM_32}, + + /* sentinel, or Generic chip */ + {0 /* null id */, "unknown", CB_UNKNOWN, PCCBB_PCMCIA_MEM_32}, +}; + + + +static int +cb_chipset(pci_id, namep, flagp) + u_int32_t pci_id; + char const **namep; + int *flagp; +{ + int loopend = sizeof(yc_chipsets)/sizeof(yc_chipsets[0]); + struct yenta_chipinfo *ycp, *ycend; + + ycend = yc_chipsets + loopend; + + for (ycp =yc_chipsets; ycp < ycend && pci_id != ycp->yc_id; ++ycp); + + if (ycp == ycend) { + /* not found */ + ycp = yc_chipsets + loopend - 1; /* to point the sentinel */ + } + + if (namep != NULL) { + *namep = ycp->yc_name; + } + + if (flagp != NULL) { + *flagp = ycp->yc_flags; + } + + return ycp->yc_chiptype; +} + + + + + +void +pccbbattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct pccbb_softc *sc = (void *)self; + struct pci_attach_args *pa = aux; + pci_chipset_tag_t pc = pa->pa_pc; + pcireg_t sock_base; + bus_addr_t sockbase; + char const *name; + int flags; + + sc->sc_chipset = cb_chipset(pa->pa_id, &name, &flags); + printf(" (%s), flags %d\n", name, flags); + +#if rbus + sc->sc_rbus_iot = rbus_pccbb_parent_io(pa); + sc->sc_rbus_memt = rbus_pccbb_parent_mem(pa); + /* + sc->sc_rbus_iot = pa->pa_rbus_iot; + sc->sc_rbus_memt = pa->pa_rbus_memt; + */ +#if 0 + sc->sc_rbus_iot->rb_space_alloc = + pccbb_rb_space_alloc_io(sc->sc_rbus_iot); + sc->sc_rbus_iot->rb_space_alloc = + pccbb_rb_space_alloc_mem(sc->sc_rbus_memt); +#endif /* 0 */ +#endif /* rbus */ + + sc->sc_base_memh = 0; + + /* MAP socket registers and ExCA registers on memory-space + When no valid address is set on socket base registers (on pci + config space), get it not polite way */ + sock_base = pci_conf_read(pc, pa->pa_tag, PCI_SOCKBASE); + + if (PCI_MAPREG_MEM_ADDR(sock_base) >= 0x100000 && + PCI_MAPREG_MEM_ADDR(sock_base) != 0xfffffff0) { + /* The address must be valid. */ + if (pci_mapreg_map(pa, PCI_SOCKBASE, PCI_MAPREG_TYPE_MEM, 0, + &sc->sc_base_memt, &sc->sc_base_memh, &sockbase, + NULL)) { + printf("%s: can't map socket base address 0x%x\n", sc->sc_dev.dv_xname, + sock_base); + /* I think it's funny: socket base registers must be mapped on + memory space, but ... */ + if (pci_mapreg_map(pa, PCI_SOCKBASE, PCI_MAPREG_TYPE_IO, 0, + &sc->sc_base_memt, &sc->sc_base_memh, + &sockbase, NULL)) { + printf("%s: can't map socket base address 0x%lx: io mode\n", + sc->sc_dev.dv_xname, sockbase); + return; + } + } else { + DPRINTF(("%s: socket base address 0x%lx",sc->sc_dev.dv_xname, sockbase)); + } + } + + + +#if 1 + sc->sc_mem_start = 0; /* XXX */ +#else + sc->sc_mem_start = CBB_PCI_BASE; /* XXX */ +#endif + sc->sc_mem_end = 0xffffffff; /* XXX */ + + /****** modify Interrupt line ******/ + if ((0 == pa->pa_intrline) || (255 == pa->pa_intrline)) { + printf("changing intrline %d to 10\n", pa->pa_intrline); + /* We must ask PCI BIOS for the proper interrupt. */ + pa->pa_intrline = 10; /* XXX: no good guess */ + } + + /* pccbb_machdep.c end */ + + +#if defined CBB_DEBUG + { + static char *intrname[5] = {"NON", "A", "B", "C", "D"}; + printf(" intrpin %s, intrtag %d\n", intrname[pa->pa_intrpin], + pa->pa_intrline); + } +#endif + + + /****** setup softc ******/ + sc->sc_pc = pc; + sc->sc_iot = pa->pa_iot; + sc->sc_memt = pa->pa_memt; + sc->sc_dmat = pa->pa_dmat; + sc->sc_tag = pa->pa_tag; + sc->sc_function = pa->pa_function; + + sc->sc_intrline = pa->pa_intrline; + sc->sc_intrtag = pa->pa_intrtag; + sc->sc_intrpin = pa->pa_intrpin; + + sc->sc_pcmcia_flags = flags; /* set PCMCIA facility */ + +#if __NetBSD_Version__ > 103060000 + config_defer(self, pccbb_pci_callback); +#else + pccbb_pci_callback(self); +#endif +} + + + + +static void +pccbb_pci_callback(self) + struct device *self; +{ + struct pccbb_softc *sc = (void *)self; + pci_chipset_tag_t pc = sc->sc_pc; + bus_space_tag_t base_memt; + bus_space_handle_t base_memh; + u_int32_t maskreg; + pci_intr_handle_t ih; + const char *intrstr = NULL; + bus_addr_t sockbase; + struct cbslot_attach_args cba; + struct pcmciabus_attach_args paa; + struct cardslot_attach_args caa; + struct cardslot_softc *csc; + + if (0 == sc->sc_base_memh) { + /* The socket registers aren't mapped correctly. */ +#if rbus + if (rbus_space_alloc(sc->sc_rbus_memt, + 0, /* address: I don't mind where it is mapped */ + 0x1000, /* size */ + 0x0fff, /* mask */ + 0x1000, /* align */ + 0, /* flags */ + &sockbase, &sc->sc_base_memh)) { + return; + } + sc->sc_base_memt = sc->sc_memt; + pci_conf_write(pc, sc->sc_tag, PCI_SOCKBASE, sockbase); + DPRINTF(("%s: CardBus resister address 0x%lx -> 0x%x\n", + sc->sc_dev.dv_xname, sockbase, pci_conf_read(pc, sc->sc_tag, PCI_SOCKBASE))); +#else + sc->sc_base_memt = sc->sc_memt; +#if !defined CBB_PCI_BASE +#define CBB_PCI_BASE 0x20000000 +#endif + if (bus_space_alloc(sc->sc_base_memt, CBB_PCI_BASE, 0xffffffff, + 0x1000, /* size */ + 0x1000, /* alignment */ + 0, /* boundary */ + 0, /* flags */ + &sockbase, &sc->sc_base_memh)) { + /* cannot allocate memory space */ + return; + } + pci_conf_write(pc, sc->sc_tag, PCI_SOCKBASE, sockbase); + DPRINTF(("%s: CardBus resister address 0x%x -> 0x%x\n",sc->sc_dev.dv_xname, + sock_base, pci_conf_read(pc, sc->sc_tag, PCI_SOCKBASE))); +#endif + } + + pccbb_chipinit(sc); + + base_memt = sc->sc_base_memt; /* socket regs memory tag */ + base_memh = sc->sc_base_memh; /* socket regs memory handle */ + + + /* CSC Interrupt: Card detect interrupt on */ + maskreg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_MASK); + maskreg |= CB_SOCKET_MASK_CD; /* Card detect intr is turned on. */ + bus_space_write_4(base_memt, base_memh, CB_SOCKET_MASK, maskreg); + /* reset interrupt */ + bus_space_write_4(base_memt, base_memh, CB_SOCKET_EVENT, + bus_space_read_4(base_memt, base_memh, CB_SOCKET_EVENT)); + + + /* Map and establish the interrupt. */ + if (pci_intr_map(pc, sc->sc_intrtag, sc->sc_intrpin, + sc->sc_intrline, &ih)) { + printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); + return; + } + intrstr = pci_intr_string(pc, ih); + sc->sc_ih = pci_intr_establish(pc, ih, IPL_BIO, pccbbintr, sc); + + if (sc->sc_ih == NULL) { + printf("%s: couldn't establish interrupt", sc->sc_dev.dv_xname); + if (intrstr != NULL) { + printf(" at %s", intrstr); + } + printf("\n"); + return; + } + + printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); + + { + u_int32_t sockstat = bus_space_read_4(base_memt,base_memh, CB_SOCKET_STAT); + if (0 == (sockstat & CB_SOCKET_STAT_CD)) { /* card exist */ + sc->sc_flags |= CBB_CARDEXIST; + } + } + + /****** attach cardbus ******/ + { + pcireg_t busreg = pci_conf_read(pc, sc->sc_tag, PCI_BUSNUM); + pcireg_t bhlc = pci_conf_read(pc, sc->sc_tag, PCI_BHLC_REG); + pcireg_t pci_lscp = pci_conf_read(pc, sc->sc_tag, PCI_CB_LSCP_REG); + + /* initialise cbslot_attach */ + cba.cba_busname = "cardbus"; + cba.cba_iot = sc->sc_iot; + cba.cba_memt = sc->sc_memt; + cba.cba_dmat = sc->sc_dmat; +#if 0 + cba.cba_function = sc->sc_function; +#else + cba.cba_function = 0; +#endif + cba.cba_bus = (busreg >> 8) & 0x0ff; + cba.cba_cc = (void *)sc; + cba.cba_cf = &pccbb_funcs; + cba.cba_intrline = sc->sc_intrline; + +#if rbus + cba.cba_rbus_iot = sc->sc_rbus_iot; + cba.cba_rbus_memt = sc->sc_rbus_memt; +#endif + + cba.cba_cacheline = PCI_CACHELINE(bhlc); + cba.cba_lattimer = PCI_CB_LATENCY(pci_lscp); + + printf("%s: cacheline 0x%x lattimer 0x%x\n", sc->sc_dev.dv_xname, + cba.cba_cacheline, cba.cba_lattimer); + printf("%s: bhlc 0x%x lscp 0x%x\n", sc->sc_dev.dv_xname, + bhlc, pci_lscp); +#if defined SHOW_REGS + cb_show_regs(sc->sc_pc, sc->sc_tag, sc->sc_base_memt, sc->sc_base_memh); +#endif + } + + pccbb_pcmcia_attach_setup(sc, &paa); + caa.caa_cb_attach = &cba; + caa.caa_16_attach = &paa; + caa.caa_ph = &sc->sc_pcmcia_h; + + if (NULL != (csc = (void *)config_found(self, &caa, cbbprint))) { + DPRINTF(("pccbbattach: found cardslot\n")); + sc->sc_csc = csc; + } + + return; +} + + + +static void +pccbb_chipinit(sc) + struct pccbb_softc *sc; +{ + pci_chipset_tag_t pc = sc->sc_pc; + pcitag_t tag = sc->sc_tag; + bus_space_tag_t base_memt = sc->sc_base_memt; /* socket regs memory tag */ + bus_space_handle_t base_memh = sc->sc_base_memh; /* socket regs memory handle */ + pcireg_t cbctrl; + + /* + Set PCI command reg. + Some laptop's BIOSes (i.e. TICO) do not enable CardBus chip. + */ + { + pcireg_t command = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); + + /* I believe it is harmless. */ + command |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | + PCI_COMMAND_MASTER_ENABLE); +/* + pa->pa_flags |= (PCI_FLAGS_MEM_ENABLED | PCI_FLAGS_IO_ENABLED); +*/ + pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, command); + } + + /* + Set CardBus latency timer + */ + { + pcireg_t pci_lscp = pci_conf_read(pc, tag, PCI_CB_LSCP_REG); + if (PCI_CB_LATENCY(pci_lscp) < 0x20) { + pci_lscp &= ~(PCI_CB_LATENCY_MASK << PCI_CB_LATENCY_SHIFT); + pci_lscp |= (0x20 << PCI_CB_LATENCY_SHIFT); + pci_conf_write(pc, tag, PCI_CB_LSCP_REG, pci_lscp); + } + DPRINTF(("CardBus latency time 0x%x\n", PCI_CB_LATENCY(pci_lscp))); + printf("CardBus latency timer 0x%x (%x)\n", PCI_CB_LATENCY(pci_lscp), + pci_conf_read(pc, tag, PCI_CB_LSCP_REG)); + } + + /* + Set PCI latency timer + */ + { + pcireg_t pci_bhlc = pci_conf_read(pc, tag, PCI_BHLC_REG); + if (PCI_LATTIMER(pci_bhlc) < 0x10) { + pci_bhlc &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT); + pci_bhlc |= (0x10 << PCI_LATTIMER_SHIFT); + pci_conf_write(pc, tag, PCI_BHLC_REG, pci_bhlc); + } + DPRINTF(("PCI latency time 0x%x\n", PCI_LATTIMER(pci_bhlc))); + printf("PCI latency timer 0x%x (%x)\n", PCI_LATTIMER(pci_bhlc), + pci_conf_read(pc, tag, PCI_BHLC_REG)); + } + + /* disable Legacy IO */ + + switch (sc->sc_chipset) { + case CB_RF5C46X: /* fallthrogh */ + case CB_RF5C47X: + { + pcireg_t bcri = pci_conf_read(pc, tag, PCI_BCR_INTR); + bcri &= ~(CB_BCRI_RL_3E0_ENA | CB_BCRI_RL_3E2_ENA); + pci_conf_write(pc, tag, PCI_BCR_INTR, bcri); + } + break; + default: + /* XXX: I don't know proper way to kill Legacy IO properly. */ + pci_conf_write(pc, tag, PCI_LEGACY, 0x0); + break; + } + + + + /****** Interrupt routing ******/ + + /* use PCI interrupt */ + { + u_int32_t bcr = pci_conf_read(pc, tag, PCI_BCR_INTR); + bcr &= ~CB_BCR_INTR_IREQ_ENABLE; /* use PCI Intr */ + bcr |= CB_BCR_WRITE_POST_ENABLE; /* enable write post */ + pci_conf_write(pc, tag, PCI_BCR_INTR, bcr); + } + + if (CB_TI113X == sc->sc_chipset) { + cbctrl = pci_conf_read(pc, tag, PCI_CBCTRL); + if (0 == sc->sc_function) { + cbctrl |= PCI113X_CBCTRL_PCI_IRQ_ENA; + } + cbctrl |= PCI113X_CBCTRL_PCI_IRQ_ENA; /* XXX: bug in PCI113X */ + cbctrl |= PCI113X_CBCTRL_PCI_CSC; /* CSC intr enable */ + cbctrl &= ~PCI113X_CBCTRL_PCI_INTR; /* functional intr prohibit */ + cbctrl &= ~PCI113X_CBCTRL_INT_MASK; /* prohibit ISA routing */ + pci_conf_write(pc, tag, PCI_CBCTRL, cbctrl); + + /* set ExCA regs: PCI113X required to be set bit 4 at Interrupt + and General Register, which is IRQ Enable Register, and clear + bit 3:0 to zero in order to route CSC interrupt to PCI + interrupt pin. */ + bus_space_write_1(base_memt, base_memh, 0x0803, 0x10); + /* set ExCA regs: prohibit all pcmcia-style CSC intr. */ + bus_space_write_1(base_memt, base_memh, 0x0805, 0x00); +#if 1 + DPRINTF(("ExCA regs:")); + DPRINTF((" 0x803: %02x", bus_space_read_1(base_memt, base_memh, 0x803))); + DPRINTF((" 0x805: %02x", bus_space_read_1(base_memt, base_memh, 0x805))); + DPRINTF((" 0x81e: %02x\n", bus_space_read_1(base_memt,base_memh,0x81e))); +#endif + } else if (sc->sc_chipset == CB_TI12XX) { + cbctrl = pci_conf_read(pc, tag, PCI_CBCTRL); + cbctrl &= ~PCI12XX_CBCTRL_INT_MASK; /* intr routing reset */ + pci_conf_write(pc, tag, PCI_CBCTRL, cbctrl); + /* set ExCA regs: PCI12XX required to be set bit 4 at Interrupt + and General Register, which is IRQ Enable Register, and clear + bit 3:0 to zero in order to route CSC interrupt to PCI + interrupt pin. */ + bus_space_write_1(base_memt, base_memh, 0x0803, 0x10); + /* set ExCA regs: prohibit all pcmcia-style CSC intr. */ + bus_space_write_1(base_memt, base_memh, 0x0805, 0x00); + } else if (sc->sc_chipset == CB_TOPIC95B) { + cardbusreg_t sock_ctrl, slot_ctrl; + + sock_ctrl = pci_conf_read(pc, tag, TOPIC_SOCKET_CTRL); + pci_conf_write(pc, tag, TOPIC_SOCKET_CTRL, + sock_ctrl | TOPIC_SOCKET_CTRL_SCR_IRQSEL); + + slot_ctrl = pci_conf_read(pc, tag, TOPIC_SLOT_CTRL); + DPRINTF(("%s: topic slot ctrl reg 0x%x -> ", sc->sc_dev.dv_xname, + slot_ctrl)); +// slot_ctrl &= ~TOPIC_SLOT_CTRL_CLOCK_MASK; + slot_ctrl |= (TOPIC_SLOT_CTRL_SLOTON | TOPIC_SLOT_CTRL_SLOTEN | + TOPIC_SLOT_CTRL_ID_LOCK); + slot_ctrl |= TOPIC_SLOT_CTRL_CARDBUS; + slot_ctrl &= ~TOPIC_SLOT_CTRL_SWDETECT; + pci_conf_write(pc, tag, TOPIC_SLOT_CTRL, slot_ctrl); + DPRINTF(("0x%x\n", slot_ctrl)); + } + + /* close all memory and io windows */ + pci_conf_write(pc, tag, PCI_CB_MEMBASE0, 0xffffffff); + pci_conf_write(pc, tag, PCI_CB_MEMLIMIT0, 0); + pci_conf_write(pc, tag, PCI_CB_MEMBASE1, 0xffffffff); + pci_conf_write(pc, tag, PCI_CB_MEMLIMIT1, 0); + pci_conf_write(pc, tag, PCI_CB_IOBASE0, 0xffffffff); + pci_conf_write(pc, tag, PCI_CB_IOLIMIT0, 0); + pci_conf_write(pc, tag, PCI_CB_IOBASE1, 0xffffffff); + pci_conf_write(pc, tag, PCI_CB_IOLIMIT1, 0); + + return; +} + + + +/****** attach pccard bus ******/ +STATIC void +pccbb_pcmcia_attach_setup(sc, paa) + struct pccbb_softc *sc; + struct pcmciabus_attach_args *paa; +{ + struct pcic_handle *ph = &sc->sc_pcmcia_h; + + /* initialise pcmcia part in pccbb_softc */ + ph->ph_parent = (struct device *)sc; + ph->sock = sc->sc_function; + ph->flags = 0; + ph->shutdown = 0; + ph->ih_irq = sc->sc_intrline; + ph->ph_bus_t = sc->sc_base_memt; + ph->ph_bus_h = sc->sc_base_memh; + ph->ph_read = pccbb_pcmcia_read; + ph->ph_write = pccbb_pcmcia_write; + sc->sc_pct = &pccbb_pcmcia_funcs; + + Pcic_write(ph, PCIC_CSC_INTR, 0); + Pcic_read(ph, PCIC_CSC); + + /* initialise pcmcia bus attachment */ + paa->paa_busname = "pcmcia"; + paa->pct = sc->sc_pct; + paa->pch = ph; + paa->iobase = 0; /* I don't use them */ + paa->iosize = 0; + + return; +} + + +#if 0 +STATIC void +pccbb_pcmcia_attach_card(ph) + struct pcic_handle *ph; +{ + if (ph->flags & PCIC_FLAG_CARDP) { + panic("pccbb_pcmcia_attach_card: already attached"); + } + + /* call the MI attach function */ + pcmcia_card_attach(ph->pcmcia); + + ph->flags |= PCIC_FLAG_CARDP; +} + + +STATIC void +pccbb_pcmcia_detach_card(ph, flags) + struct pcic_handle *ph; + int flags; +{ + if (!(ph->flags & PCIC_FLAG_CARDP)) { + panic("pccbb_pcmcia_detach_card: already detached"); + } + + ph->flags &= ~PCIC_FLAG_CARDP; + + /* call the MI detach function */ + pcmcia_card_detach(ph->pcmcia, flags); +} +#endif + + + + +/********************************************************************** +* int pccbbintr(arg) +* void *arg; +* This routine handles the interrupt from Yenta PCI-CardBus bridge +* itself. +**********************************************************************/ +int +pccbbintr(arg) + void *arg; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)arg; + u_int32_t sockevent; + bus_space_tag_t memt = sc->sc_base_memt; + bus_space_handle_t memh = sc->sc_base_memh; + u_int32_t sockstate; + + sockevent = bus_space_read_4(memt, memh, CB_SOCKET_EVENT); + if (0 == sockevent) { /* not for me */ + return 0; + } else { + bus_space_write_4(memt, memh, CB_SOCKET_EVENT, sockevent); /* reset bit */ + } + sockstate = bus_space_read_4(memt, memh, CB_SOCKET_STAT); + + if (sockevent & CB_SOCKET_EVENT_CD) { + if (CB_SOCKET_STAT_CD == (sockstate & CB_SOCKET_STAT_CD)) { + /* A card should be removed. */ + if (sc->sc_flags & CBB_CARDEXIST) { + DPRINTF(("%s: 0x%08x", sc->sc_dev.dv_xname, sockevent)); + DPRINTF((" card removed, 0x%08x\n", sockstate)); + sc->sc_flags &= ~CBB_CARDEXIST; + if (sc->sc_csc->sc_status & CARDSLOT_STATUS_CARD_16) { +#if 0 + struct pcic_handle *ph = &sc->sc_pcmcia_h; + + pcmcia_card_deactivate(ph->pcmcia); + pccbb_pcmcia_socket_disable(ph); + pccbb_pcmcia_detach_card(ph, DETACH_FORCE); +#endif + cardslot_event_throw(sc->sc_csc, CARDSLOT_EVENT_REMOVAL_16); + } else if (sc->sc_csc->sc_status & CARDSLOT_STATUS_CARD_CB) { + /* Cardbus intr removed */ + cardslot_event_throw(sc->sc_csc, CARDSLOT_EVENT_REMOVAL_CB); + } + } + } else if (0x00 == (sockstate & CB_SOCKET_STAT_CD)) { + if (sc->sc_flags & CBB_INSERTING) { + untimeout(pci113x_insert, sc); + } + timeout(pci113x_insert, sc, hz/10); + sc->sc_flags |= CBB_INSERTING; + } + } else { + DPRINTF(("%s: 0x%08x", sc->sc_dev.dv_xname, sockevent)); + if (sockevent & CB_SOCKET_EVENT_CSTS) { + DPRINTF((" cstsevent occures, 0x%08x\n", sockstate)); + } + if (sockevent & CB_SOCKET_EVENT_POWER) { + DPRINTF((" pwrevent occures, 0x%08x\n", sockstate)); + } + } + + return 1; +} + + + +static void +pci113x_insert(arg) + void *arg; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)arg; + u_int32_t sockevent, sockstate; + + sockevent = bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh, + CB_SOCKET_EVENT); + sockstate = bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh, + CB_SOCKET_STAT); + + if (0 == (sockstate & CB_SOCKET_STAT_CD)) { /* card exist */ + DPRINTF(("%s: 0x%08x", sc->sc_dev.dv_xname, sockevent)); + DPRINTF((" card inserted, 0x%08x\n", sockstate)); + sc->sc_flags |= CBB_CARDEXIST; + /* call pccard intterupt handler here */ + if (sockstate & CB_SOCKET_STAT_16BIT) { + /* 16-bit card found */ +/* pccbb_pcmcia_attach_card(&sc->sc_pcmcia_h); */ + cardslot_event_throw(sc->sc_csc, CARDSLOT_EVENT_INSERTION_16); + } else if (sockstate & CB_SOCKET_STAT_CB) { + /* cardbus card fuond */ +/* cardbus_attach_card(sc->sc_csc); */ + cardslot_event_throw(sc->sc_csc, CARDSLOT_EVENT_INSERTION_CB); + } else { + /* who are you? */ + } + } else { + timeout(pci113x_insert, sc, hz/10); + } +} + + + + +#define PCCBB_PCMCIA_OFFSET 0x800 +static u_int8_t +pccbb_pcmcia_read(ph, reg) + struct pcic_handle *ph; + int reg; +{ + return bus_space_read_1(ph->ph_bus_t, ph->ph_bus_h, PCCBB_PCMCIA_OFFSET + reg); +} + + + +static void +pccbb_pcmcia_write(ph, reg, val) + struct pcic_handle *ph; + int reg; + u_int8_t val; +{ + bus_space_write_1(ph->ph_bus_t, ph->ph_bus_h, PCCBB_PCMCIA_OFFSET + reg, val); + + return; +} + + + + +/********************************************************************** +* STATIC int pccbb_ctrl(cardbus_chipset_tag_t, int) +**********************************************************************/ +STATIC int +pccbb_ctrl(ct, command) + cardbus_chipset_tag_t ct; + int command; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)ct; + + switch(command) { + case CARDBUS_CD: + if (2 == pccbb_detect_card(sc)) { + int retval = 0; + int status = cb_detect_voltage(sc); + if (PCCARD_VCC_5V & status) { + retval |= CARDBUS_5V_CARD; + } + if (PCCARD_VCC_3V & status) { + retval |= CARDBUS_3V_CARD; + } + if (PCCARD_VCC_XV & status) { + retval |= CARDBUS_XV_CARD; + } + if (PCCARD_VCC_YV & status) { + retval |= CARDBUS_YV_CARD; + } + return retval; + } else { + return 0; + } + break; + case CARDBUS_RESET: + return cb_reset(sc); + break; + case CARDBUS_IO_ENABLE: /* fallthrough */ + case CARDBUS_IO_DISABLE: /* fallthrough */ + case CARDBUS_MEM_ENABLE: /* fallthrough */ + case CARDBUS_MEM_DISABLE: /* fallthrough */ + case CARDBUS_BM_ENABLE: /* fallthrough */ + case CARDBUS_BM_DISABLE: /* fallthrough */ + return pccbb_cardenable(sc, command); + break; + } + + return 0; +} + + + +/********************************************************************** +* STATIC int pccbb_power(cardbus_chipset_tag_t, int) +* This function returns true when it succeeds and returns false when +* it fails. +**********************************************************************/ +STATIC int +pccbb_power(ct, command) + cardbus_chipset_tag_t ct; + int command; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)ct; + + u_int32_t status, sock_ctrl; + bus_space_tag_t memt = sc->sc_base_memt; + bus_space_handle_t memh = sc->sc_base_memh; + + DPRINTF(("pccbb_power: %s and %s [%x]\n", + (command & CARDBUS_VCCMASK) == CARDBUS_VCC_UC ? "CARDBUS_VCC_UC" : + (command & CARDBUS_VCCMASK) == CARDBUS_VCC_5V ? "CARDBUS_VCC_5V" : + (command & CARDBUS_VCCMASK) == CARDBUS_VCC_3V ? "CARDBUS_VCC_3V" : + (command & CARDBUS_VCCMASK) == CARDBUS_VCC_XV ? "CARDBUS_VCC_XV" : + (command & CARDBUS_VCCMASK) == CARDBUS_VCC_YV ? "CARDBUS_VCC_YV" : + (command & CARDBUS_VCCMASK) == CARDBUS_VCC_0V ? "CARDBUS_VCC_0V" : + "UNKNOWN", + (command & CARDBUS_VPPMASK) == CARDBUS_VPP_UC ? "CARDBUS_VPP_UC" : + (command & CARDBUS_VPPMASK) == CARDBUS_VPP_12V ? "CARDBUS_VPP_12V" : + (command & CARDBUS_VPPMASK) == CARDBUS_VPP_VCC ? "CARDBUS_VPP_VCC" : + (command & CARDBUS_VPPMASK) == CARDBUS_VPP_0V ? "CARDBUS_VPP_0V" : + "UNKNOWN", + command)); + + status = bus_space_read_4(memt, memh, CB_SOCKET_STAT); + sock_ctrl = bus_space_read_4(memt, memh, CB_SOCKET_CTRL); + + switch (command & CARDBUS_VCCMASK) { + case CARDBUS_VCC_UC: + break; + case CARDBUS_VCC_5V: + if (CB_SOCKET_STAT_5VCARD & status) { /* check 5 V card */ + sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK; + sock_ctrl |= CB_SOCKET_CTRL_VCC_5V; + } else { + printf("%s: BAD voltage request: no 5 V card\n", sc->sc_dev.dv_xname); + } + break; + case CARDBUS_VCC_3V: + if (CB_SOCKET_STAT_3VCARD & status) { + sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK; + sock_ctrl |= CB_SOCKET_CTRL_VCC_3V; + } else { + printf("%s: BAD voltage request: no 3.3 V card\n", sc->sc_dev.dv_xname); + } + break; + case CARDBUS_VCC_0V: + sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK; + break; + default: + return 0; /* power NEVER changed */ + break; + } + + switch (command & CARDBUS_VPPMASK) { + case CARDBUS_VPP_UC: + break; + case CARDBUS_VPP_0V: + sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK; + break; + case CARDBUS_VPP_VCC: + sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK; + sock_ctrl |= ((sock_ctrl >> 4) & 0x07); + break; + case CARDBUS_VPP_12V: + sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK; + sock_ctrl |= CB_SOCKET_CTRL_VPP_12V; + break; + } + +#if 0 + DPRINTF(("sock_ctrl: %x\n", sock_ctrl)); +#endif + bus_space_write_4(memt, memh, CB_SOCKET_CTRL, sock_ctrl); + status = bus_space_read_4(memt, memh, CB_SOCKET_STAT); + + delay(20*1000); /* wait 20 ms: Vcc setup time */ + /* XXX + delay 200 ms: though the standard defines that the Vcc set-up time + is 20 ms, some PC-Card bridge requires longer duration. + */ + delay(200*1000); + + + if (status & CB_SOCKET_STAT_BADVCC) { /* bad Vcc request */ + printf("%s: bad Vcc request. sock_ctrl 0x%x, sock_status 0x%x\n", + sc->sc_dev.dv_xname, sock_ctrl ,status); + DPRINTF(("pccbb_power: %s and %s [%x]\n", + (command & CARDBUS_VCCMASK) == CARDBUS_VCC_UC ? "CARDBUS_VCC_UC" : + (command & CARDBUS_VCCMASK) == CARDBUS_VCC_5V ? "CARDBUS_VCC_5V": + (command & CARDBUS_VCCMASK) == CARDBUS_VCC_3V ? "CARDBUS_VCC_3V": + (command & CARDBUS_VCCMASK) == CARDBUS_VCC_XV ? "CARDBUS_VCC_XV": + (command & CARDBUS_VCCMASK) == CARDBUS_VCC_YV ? "CARDBUS_VCC_YV": + (command & CARDBUS_VCCMASK) == CARDBUS_VCC_0V ? "CARDBUS_VCC_0V": + "UNKNOWN", + (command & CARDBUS_VPPMASK) == CARDBUS_VPP_UC ? "CARDBUS_VPP_UC": + (command & CARDBUS_VPPMASK) == CARDBUS_VPP_12V ?"CARDBUS_VPP_12V": + (command & CARDBUS_VPPMASK) == CARDBUS_VPP_VCC ?"CARDBUS_VPP_VCC": + (command & CARDBUS_VPPMASK) == CARDBUS_VPP_0V ? "CARDBUS_VPP_0V" : + "UNKNOWN", + command)); +#if 0 + if (command == (CARDBUS_VCC_0V | CARDBUS_VPP_0V)) { + u_int32_t force = bus_space_read_4(memt, memh, CB_SOCKET_FORCE); + /* Reset Bad Vcc request */ + force &= ~CB_SOCKET_FORCE_BADVCC; + bus_space_write_4(memt, memh, CB_SOCKET_FORCE, force); + printf("new status 0x%x\n", bus_space_read_4(memt, memh,CB_SOCKET_STAT)); + return 1; + } +#endif + return 0; + } + return 1; /* power changed correctly */ +} + + + + + + +#if defined CB_PCMCIA_POLL +struct cb_poll_str { + void *arg; + int (* func) __P((void *)); + int level; + pccard_chipset_tag_t ct; + int count; +}; + +static struct cb_poll_str cb_poll[10]; +static int cb_poll_n = 0; + +static void cb_pcmcia_poll __P((void *arg)); + +static void +cb_pcmcia_poll(arg) + void *arg; +{ + struct cb_poll_str *poll = arg; + struct cbb_pcmcia_softc *psc = (void *)poll->ct->v; + struct pccbb_softc *sc = psc->cpc_parent; + int s; + u_int32_t spsr; /* socket present-state reg */ + + timeout(cb_pcmcia_poll, arg, hz/10); + switch (poll->level) { + case IPL_NET: + s = splnet(); + break; + case IPL_BIO: + s = splbio(); + break; + case IPL_TTY: /* fallthrough */ + default: + s = spltty(); + break; + } + + spsr = bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh, CB_SOCKET_STAT); + +#if defined CB_PCMCIA_POLL_ONLY && defined LEVEL2 + if (!(spsr & 0x40)) { /* CINT low */ +#else + if (1) { +#endif + if ((*poll->func)(poll->arg) == 1) { + ++poll->count; + printf("intr: reported from poller, 0x%x\n", spsr); +#if defined LEVEL2 + } else { + printf("intr: miss! 0x%x\n", spsr); +#endif + } + } + splx(s); +} +#endif /* defined CB_PCMCIA_POLL */ + + + + +/********************************************************************** +* static int pccbb_detect_card(struct pccbb_softc *sc) +* return value: 0 if no card exists. +* 1 if 16-bit card exists. +* 2 if cardbus card exists. +**********************************************************************/ +static int +pccbb_detect_card(sc) + struct pccbb_softc *sc; +{ + bus_space_handle_t base_memh = sc->sc_base_memh; + bus_space_tag_t base_memt = sc->sc_base_memt; + u_int32_t sockstat = bus_space_read_4(base_memt,base_memh, CB_SOCKET_STAT); + int retval = 0; + + if (0x00 == (sockstat & CB_SOCKET_STAT_CD)) { /* CD1 and CD2 asserted */ + /* card must be present */ + if (!(CB_SOCKET_STAT_NOTCARD & sockstat)) { /* NOTACARD DEASSERTED */ + if (CB_SOCKET_STAT_CB & sockstat) { /* CardBus mode */ + retval = 2; + } else if (CB_SOCKET_STAT_16BIT & sockstat) { /* 16-bit mode */ + retval = 1; + } + } + } + return retval; +} + + + + +/********************************************************************** +* STATIC int cb_reset(struct pccbb_softc *sc) +* This function resets CardBus card. +**********************************************************************/ +STATIC int +cb_reset(sc) + struct pccbb_softc *sc; +{ + u_int32_t bcr = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR); + bcr |= (0x40 << 16); /* Reset bit Assert (bit 6 at 0x3E) */ + pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, bcr); + /* Reset Assert at least 20 ms */ + delay(20*1000); + + if (CBB_CARDEXIST & sc->sc_flags) { /* A card exists. Reset it! */ + bcr &= ~(0x40 << 16); /* Reset bit Deassert (bit 6 at 0x3E) */ + pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, bcr); + delay(20*1000); + } + /* No card found on the slot. Keep Reset. */ + return 1; +} + + + + +/********************************************************************** +* STATIC int cb_detect_voltage(struct pccbb_softc *sc) +* This function detect card Voltage. +**********************************************************************/ +STATIC int +cb_detect_voltage(sc) + struct pccbb_softc *sc; +{ + u_int32_t psr; /* socket present-state reg */ + bus_space_tag_t iot = sc->sc_base_memt; + bus_space_handle_t ioh = sc->sc_base_memh; + int vol = PCCARD_VCC_UKN; /* set 0 */ + + psr = bus_space_read_4(iot, ioh, CB_SOCKET_STAT); + + if (0x400u & psr) { + vol |= PCCARD_VCC_5V; + } + if (0x800u & psr) { + vol |= PCCARD_VCC_3V; + } + + return vol; +} + + + + + + +STATIC int +cbbprint(aux, pcic) + void *aux; + const char *pcic; +{ +/* + struct cbslot_attach_args *cba = aux; + + if (cba->cba_slot >= 0) { + printf(" slot %d", cba->cba_slot); + } +*/ + return UNCONF; +} + + + + +/********************************************************************** +* STATIC int pccbb_cardenable(struct pccbb_softc *sc, int function) +* This function enables and disables the card +**********************************************************************/ +STATIC int +pccbb_cardenable(sc, function) + struct pccbb_softc *sc; + int function; +{ + u_int32_t command = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG); + + DPRINTF(("pccbb_cardenable:")); + switch (function) { + case CARDBUS_IO_ENABLE: + command |= PCI_COMMAND_IO_ENABLE; + break; + case CARDBUS_IO_DISABLE: + command &= ~PCI_COMMAND_IO_ENABLE; + break; + case CARDBUS_MEM_ENABLE: + command |= PCI_COMMAND_MEM_ENABLE; + break; + case CARDBUS_MEM_DISABLE: + command &= ~PCI_COMMAND_MEM_ENABLE; + break; + case CARDBUS_BM_ENABLE: + command |= PCI_COMMAND_MASTER_ENABLE; + break; + case CARDBUS_BM_DISABLE: + command &= ~PCI_COMMAND_MASTER_ENABLE; + break; + default: + return 0; + } + + pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG, command); + DPRINTF((" command reg 0x%x\n", command)); + return 1; +} + + + + + + +#if !rbus +/********************************************************************** +* int pccbb_io_open(cardbus_chipset_tag_t, int, u_int32_t, u_int32_t) +**********************************************************************/ +static int +pccbb_io_open(ct, win, start, end) + cardbus_chipset_tag_t ct; + int win; + u_int32_t start, end; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)ct; + int basereg; + int limitreg; + + if ((win < 0) || (win > 2)) { +#if defined DIAGNOSTIC + printf("cardbus_io_open: window out of range %d\n", win); +#endif + return 0; + } + + basereg = win*8 + 0x2c; + limitreg = win*8 + 0x30; + + DPRINTF(("pccbb_io_open: 0x%x[0x%x] - 0x%x[0x%x]\n", + start, basereg, end, limitreg)); + + pci_conf_write(sc->sc_pc, sc->sc_tag, basereg, start); + pci_conf_write(sc->sc_pc, sc->sc_tag, limitreg, end); + return 1; +} + +/********************************************************************** +* int pccbb_io_close(cardbus_chipset_tag_t, int) +**********************************************************************/ +static int +pccbb_io_close(ct, win) + cardbus_chipset_tag_t ct; + int win; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)ct; + int basereg; + int limitreg; + + if ((win < 0) || (win > 2)) { +#if defined DIAGNOSTIC + printf("cardbus_io_close: window out of range %d\n", win); +#endif + return 0; + } + + basereg = win*8 + 0x2c; + limitreg = win*8 + 0x30; + + pci_conf_write(sc->sc_pc, sc->sc_tag, basereg, 0); + pci_conf_write(sc->sc_pc, sc->sc_tag, limitreg, 0); + return 1; +} + +/********************************************************************** +* int pccbb_mem_open(cardbus_chipset_tag_t, int, u_int32_t, u_int32_t) +**********************************************************************/ +static int +pccbb_mem_open(ct, win, start, end) + cardbus_chipset_tag_t ct; + int win; + u_int32_t start, end; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)ct; + int basereg; + int limitreg; + + if ((win < 0) || (win > 2)) { +#if defined DIAGNOSTIC + printf("cardbus_mem_open: window out of range %d\n", win); +#endif + return 0; + } + + basereg = win*8 + 0x1c; + limitreg = win*8 + 0x20; + + pci_conf_write(sc->sc_pc, sc->sc_tag, basereg, start); + pci_conf_write(sc->sc_pc, sc->sc_tag, limitreg, end); + return 1; +} + + +/********************************************************************** +* int pccbb_mem_close(cardbus_chipset_tag_t, int); +**********************************************************************/ +static int +pccbb_mem_close(ct, win) + cardbus_chipset_tag_t ct; + int win; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)ct; + int basereg; + int limitreg; + + if ((win < 0) || (win > 2)) { +#if defined DIAGNOSTIC + printf("cardbus_mem_close: window out of range %d\n", win); +#endif + return 0; + } + + basereg = win*8 + 0x1c; + limitreg = win*8 + 0x20; + + pci_conf_write(sc->sc_pc, sc->sc_tag, basereg, 0); + pci_conf_write(sc->sc_pc, sc->sc_tag, limitreg, 0); + return 1; +} +#endif + + + +static void * +pccbb_intr_establish(ct, irq, level, func, arg) + cardbus_chipset_tag_t ct; + int irq, level; + int (* func) __P((void *)); + void *arg; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)ct; + + switch (sc->sc_chipset) { + case CB_TI113X: + { + pcireg_t cbctrl = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL); + cbctrl |= PCI113X_CBCTRL_PCI_INTR; /* functional intr enabled */ + pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, cbctrl); + } + break; + default: + break; + } + + return pci_intr_establish(sc->sc_pc, irq, level, func, arg); +} + + + + +static void +pccbb_intr_disestablish(ct, ih) + cardbus_chipset_tag_t ct; + void *ih; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)ct; + + switch (sc->sc_chipset) { + case CB_TI113X: + { + pcireg_t cbctrl = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL); + cbctrl &= ~PCI113X_CBCTRL_PCI_INTR; /* functional intr disabled */ + pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, cbctrl); + } + break; + default: + break; + } + + pci_intr_disestablish(sc->sc_pc, ih); +} + + + + + +#if defined SHOW_REGS +static void +cb_show_regs(pc, tag, memt, memh) + pci_chipset_tag_t pc; + pcitag_t tag; + bus_space_tag_t memt; + bus_space_handle_t memh; +{ + int i; + printf("PCI config regs:"); + for (i = 0; i < 0x50; i += 4) { + if (i % 16 == 0) { + printf("\n 0x%02x:", i); + } + printf(" %08x", pci_conf_read(pc, tag, i)); + } + for (i = 0x80; i < 0xb0; i += 4) { + if (i % 16 == 0) { + printf("\n 0x%02x:", i); + } + printf(" %08x", pci_conf_read(pc, tag, i)); + } + + if (memh == 0) { + printf("\n"); + return; + } + + printf("\nsocket regs:"); + for (i = 0; i <= 0x10; i += 0x04) { + printf(" %08x", bus_space_read_4(memt, memh, i)); + } + printf("\nExCA regs:"); + for (i = 0; i < 0x08; ++i) { + printf(" %02x", bus_space_read_1(memt, memh, 0x800 + i)); + } + printf("\n"); + return; +} +#endif + + + +/********************************************************************** +* static cardbustag_t pccbb_make_tag(cardbus_chipset_tag_t cc, +* int busno, int devno, int function); +* This is the function to make a tag to access config space of +* a CardBus Card. It works same as pci_conf_read. +**********************************************************************/ +static cardbustag_t +pccbb_make_tag(cc, busno, devno, function) + cardbus_chipset_tag_t cc; + int busno, devno, function; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)cc; + + return pci_make_tag(sc->sc_pc, busno, devno, function); +} + + +static void +pccbb_free_tag(cc, tag) + cardbus_chipset_tag_t cc; + cardbustag_t tag; +{ +} + + +/********************************************************************** +* static cardbusreg_t pccbb_conf_read(cardbus_chipset_tag_t cc, +* cardbustag_t tag, int offset) +* This is the function to read the config space of a CardBus Card. +* It works same as pci_conf_read. +**********************************************************************/ +static cardbusreg_t +pccbb_conf_read(cc, tag, offset) + cardbus_chipset_tag_t cc; + cardbustag_t tag; + int offset; /* register offset */ +{ + struct pccbb_softc *sc = (struct pccbb_softc *)cc; + + return pci_conf_read(sc->sc_pc, tag, offset); +} + + + +/********************************************************************** +* static void pccbb_conf_write(cardbus_chipset_tag_t cc, cardbustag_t tag, +* int offs, cardbusreg_t val) +* This is the function to write the config space of a CardBus Card. +* It works same as pci_conf_write. +**********************************************************************/ +static void +pccbb_conf_write(cc, tag, reg, val) + cardbus_chipset_tag_t cc; + cardbustag_t tag; + int reg; /* register offset */ + cardbusreg_t val; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)cc; + + pci_conf_write(sc->sc_pc, tag, reg, val); +} + + + + + +#if 0 +STATIC int +pccbb_new_pcmcia_io_alloc(pcmcia_chipset_handle_t pch, + bus_addr_t start, bus_size_t size, + bus_size_t align, bus_addr_t mask, /* address line width */ + int speed, int flags, /* bus width */ + bus_space_handle_t *iohp) +#endif + + +/********************************************************************** +* STATIC int pccbb_pcmcia_io_alloc(pcmcia_chipset_handle_t pch, +* bus_addr_t start, bus_size_t size, +* bus_size_t align, +* struct pcmcia_io_handle *pcihp +* +* This function only allocates I/O region for pccard. This function +* never maps the allcated region to pccard I/O area. +* +* XXX: The interface of this function is not very good, I believe. +**********************************************************************/ +STATIC int +pccbb_pcmcia_io_alloc(pch, start, size, align, pcihp) + pcmcia_chipset_handle_t pch; + bus_addr_t start; /* start address */ + bus_size_t size; + bus_size_t align; + struct pcmcia_io_handle *pcihp; +{ + struct pcic_handle *ph = (struct pcic_handle *)pch; + bus_addr_t ioaddr; + int flags = 0; + bus_space_tag_t iot; + bus_space_handle_t ioh; +#if rbus + rbus_tag_t rb; +#endif + if (align == 0) { + align = size; /* XXX: funny??? */ + } + + + /* + * Allocate some arbitrary I/O space. + */ + + iot = ((struct pccbb_softc *)(ph->ph_parent))->sc_iot; + +#if rbus + rb = ((struct pccbb_softc *)(ph->ph_parent))->sc_rbus_iot; + if (rbus_space_alloc(rb, start, size, 0x3ff /* XXX: I assume all card decode lower 10 bits by its hardware */, + align, 0, &ioaddr, &ioh)) { + return 1; + } +#else + if (start) { + ioaddr = start; + if (bus_space_map(iot, start, size, 0, &ioh)) { + return 1; + } + DPRINTF(("pccbb_pcmcia_io_alloc map port %lx+%lx\n", + (u_long) ioaddr, (u_long) size)); + } else { + flags |= PCMCIA_IO_ALLOCATED; + if (bus_space_alloc(iot, 0x700/* ph->sc->sc_iobase */, + 0x800/* ph->sc->sc_iobase + ph->sc->sc_iosize*/, + size, align, 0, 0, &ioaddr, &ioh)) { + /* No room be able to be get. */ + return 1; + } + DPRINTF(("pccbb_pcmmcia_io_alloc alloc port 0x%lx+0x%lx\n", + (u_long) ioaddr, (u_long) size)); + } +#endif + + pcihp->iot = iot; + pcihp->ioh = ioh; + pcihp->addr = ioaddr; + pcihp->size = size; + pcihp->flags = flags; + + return 0; +} + + + + + +/********************************************************************** +* STATIC int pccbb_pcmcia_io_free(pcmcia_chipset_handle_t pch, +* struct pcmcia_io_handle *pcihp) +* +* This function only frees I/O region for pccard. +* +* XXX: The interface of this function is not very good, I believe. +**********************************************************************/ +void +pccbb_pcmcia_io_free(pch, pcihp) + pcmcia_chipset_handle_t pch; + struct pcmcia_io_handle *pcihp; +{ +#if !rbus + bus_space_tag_t iot = pcihp->iot; +#endif + bus_space_handle_t ioh = pcihp->ioh; + bus_size_t size = pcihp->size; + +#if rbus + struct pccbb_softc *sc = (struct pccbb_softc *)((struct pcic_handle *)pch)->ph_parent; + rbus_tag_t rb = sc->sc_rbus_iot; + + rbus_space_free(rb, ioh, size, NULL); +#else + if (pcihp->flags & PCMCIA_IO_ALLOCATED) + bus_space_free(iot, ioh, size); + else + bus_space_unmap(iot, ioh, size); +#endif +} + + + +/********************************************************************** +* STATIC int pccbb_pcmcia_io_map(pcmcia_chipset_handle_t pch, int width, +* bus_addr_t offset, bus_size_t size, +* struct pcmcia_io_handle *pcihp, +* int *windowp) +* +* This function maps the allocated I/O region to pccard. This function +* never allocates any I/O region for pccard I/O area. I don't +* understand why the original authors of pcmciabus separated alloc and +* map. I believe the two must be unite. +* +* XXX: no wait timing control? +**********************************************************************/ +int +pccbb_pcmcia_io_map(pch, width, offset, size, pcihp, windowp) + pcmcia_chipset_handle_t pch; + int width; + bus_addr_t offset; + bus_size_t size; + struct pcmcia_io_handle *pcihp; + int *windowp; +{ + struct pcic_handle *ph = (struct pcic_handle *) pch; + bus_addr_t ioaddr = pcihp->addr + offset; + int i, win; +#if defined CBB_DEBUG + static char *width_names[] = { "dynamic", "io8", "io16" }; +#endif + + /* Sanity check I/O handle. */ + + if (((struct pccbb_softc *)ph->ph_parent)->sc_iot != pcihp->iot) { + panic("pccbb_pcmcia_io_map iot is bogus"); + } + + /* XXX Sanity check offset/size. */ + + win = -1; + for (i = 0; i < PCIC_IO_WINS; i++) { + if ((ph->ioalloc & (1 << i)) == 0) { + win = i; + ph->ioalloc |= (1 << i); + break; + } + } + + if (win == -1) { + return 1; + } + + *windowp = win; + + /* XXX this is pretty gross */ + + DPRINTF(("pccbb_pcmcia_io_map window %d %s port %lx+%lx\n", + win, width_names[width], (u_long) ioaddr, (u_long) size)); + + /* XXX wtf is this doing here? */ + +#if 0 + printf(" port 0x%lx", (u_long) ioaddr); + if (size > 1) { + printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1); + } +#endif + + ph->io[win].addr = ioaddr; + ph->io[win].size = size; + ph->io[win].width = width; + + /* actual dirty register-value changing in the function below. */ + pccbb_pcmcia_do_io_map(ph, win); + + return 0; +} + + + +/********************************************************************** +* STATIC void pccbb_pcmcia_do_io_map(struct pcic_handle *h, int win) +* +* This function changes register-value to map I/O region for pccard. +**********************************************************************/ +static void +pccbb_pcmcia_do_io_map(ph, win) + struct pcic_handle *ph; + int win; +{ + static u_int8_t pcic_iowidth[3] = { + PCIC_IOCTL_IO0_IOCS16SRC_CARD, + PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | PCIC_IOCTL_IO0_DATASIZE_8BIT, + PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | PCIC_IOCTL_IO0_DATASIZE_16BIT, + }; + +#define PCIC_SIA_START_LOW 0 +#define PCIC_SIA_START_HIGH 1 +#define PCIC_SIA_STOP_LOW 2 +#define PCIC_SIA_STOP_HIGH 3 + + int regbase_win = 0x8 + win*0x04; + u_int8_t ioctl, enable; + + DPRINTF(("pccbb_pcmcia_do_io_map win %d addr 0x%lx size 0x%lx width %d\n", + win, (long) ph->io[win].addr, (long) ph->io[win].size, + ph->io[win].width * 8)); + + Pcic_write(ph, regbase_win + PCIC_SIA_START_LOW, + ph->io[win].addr & 0xff); + Pcic_write(ph, regbase_win + PCIC_SIA_START_HIGH, + (ph->io[win].addr >> 8) & 0xff); + + Pcic_write(ph, regbase_win + PCIC_SIA_STOP_LOW, + (ph->io[win].addr + ph->io[win].size - 1) & 0xff); + Pcic_write(ph, regbase_win + PCIC_SIA_STOP_HIGH, + ((ph->io[win].addr + ph->io[win].size - 1) >> 8) & 0xff); + + ioctl = Pcic_read(ph, PCIC_IOCTL); + enable = Pcic_read(ph, PCIC_ADDRWIN_ENABLE); + switch (win) { + case 0: + ioctl &= ~(PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT | + PCIC_IOCTL_IO0_IOCS16SRC_MASK | PCIC_IOCTL_IO0_DATASIZE_MASK); + ioctl |= pcic_iowidth[ph->io[win].width]; + enable |= PCIC_ADDRWIN_ENABLE_IO0; + break; + case 1: + ioctl &= ~(PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT | + PCIC_IOCTL_IO1_IOCS16SRC_MASK | PCIC_IOCTL_IO1_DATASIZE_MASK); + ioctl |= (pcic_iowidth[ph->io[win].width] << 4); + enable |= PCIC_ADDRWIN_ENABLE_IO1; + break; + } + Pcic_write(ph, PCIC_IOCTL, ioctl); + Pcic_write(ph, PCIC_ADDRWIN_ENABLE, enable); +#if defined CBB_DEBUG + { + u_int8_t start_low = Pcic_read(ph, regbase_win + PCIC_SIA_START_LOW); + u_int8_t start_high = Pcic_read(ph, regbase_win + PCIC_SIA_START_HIGH); + u_int8_t stop_low = Pcic_read(ph, regbase_win + PCIC_SIA_STOP_LOW); + u_int8_t stop_high = Pcic_read(ph, regbase_win + PCIC_SIA_STOP_HIGH); + printf(" start %02x %02x, stop %02x %02x, ioctl %02x enable %02x\n", + start_low, start_high, stop_low, stop_high, ioctl, enable); + } +#endif +} + + + +/********************************************************************** +* STATIC void pccbb_pcmcia_io_unmap(pcmcia_chipset_handle_t *h, int win) +* +* This function unmapss I/O region. No return value. +**********************************************************************/ +STATIC void +pccbb_pcmcia_io_unmap(pch, win) + pcmcia_chipset_handle_t pch; + int win; +{ + struct pcic_handle *ph = (struct pcic_handle *)pch; + int reg; + + if (win >= PCIC_IO_WINS || win < 0) { + panic("pccbb_pcmcia_io_unmap: window out of range"); + } + + reg = Pcic_read(ph, PCIC_ADDRWIN_ENABLE); + switch (win) { + case 0: + reg &= ~PCIC_ADDRWIN_ENABLE_IO0; + break; + case 1: + reg &= ~PCIC_ADDRWIN_ENABLE_IO1; + break; + } + Pcic_write(ph, PCIC_ADDRWIN_ENABLE, reg); + + ph->ioalloc &= ~(1 << win); +} + + + + + +/********************************************************************** +* static void pccbb_pcmcia_wait_ready(struct pcic_handle *ph) +* +* This function enables the card. All information is stored in +* the first argument, pcmcia_chipset_handle_t. +**********************************************************************/ +static void +pccbb_pcmcia_wait_ready(ph) + struct pcic_handle *ph; +{ + int i; + + DPRINTF(("pccbb_pcmcia_wait_ready: status 0x%02x\n", + Pcic_read(ph, PCIC_IF_STATUS))); + + for (i = 0; i < 10000; i++) { + if (Pcic_read(ph, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY) { + return; + } + delay(500); +#ifdef CBB_DEBUG + if ((i > 5000) && (i%100 == 99)) + printf("."); +#endif + } + +#ifdef DIAGNOSTIC + printf("pcic_wait_ready: ready never happened, status = %02x\n", + Pcic_read(ph, PCIC_IF_STATUS)); +#endif +} + + + +/********************************************************************** +* STATIC void pccbb_pcmcia_socket_enable(pcmcia_chipset_handle_t pch) +* +* This function enables the card. All information is stored in +* the first argument, pcmcia_chipset_handle_t. +**********************************************************************/ +STATIC void +pccbb_pcmcia_socket_enable(pch) + pcmcia_chipset_handle_t pch; +{ + struct pcic_handle *ph = (struct pcic_handle *)pch; + struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent; + int cardtype, win; + u_int8_t power, intr; + pcireg_t spsr; + int voltage; +#define PCIC_INTR_PCI PCIC_INTR_ENABLE + + /* this bit is mostly stolen from pcic_attach_card */ + + DPRINTF(("pccbb_pcmcia_socket_enable:\n")); + + /* get card Vcc info */ + + spsr = bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh, CB_SOCKET_STAT); + if (spsr & CB_SOCKET_STAT_5VCARD) { + printf("5V card\n"); /* XXX */ + voltage = CARDBUS_VCC_5V | CARDBUS_VPP_VCC; + } else if (spsr & CB_SOCKET_STAT_3VCARD) { + printf("3V card\n"); /* XXX */ + voltage = CARDBUS_VCC_3V | CARDBUS_VPP_VCC; + } else { + printf("?V card, 0x%x\n", spsr); /* XXX */ + return; + } + + /* assert reset bit */ + + intr = Pcic_read(ph, PCIC_INTR); + intr &= ~PCIC_INTR_RESET; + intr |= PCIC_INTR_PCI; /* XXX */ + Pcic_write(ph, PCIC_INTR, intr); + + /* disable socket i/o: negate output enable bit */ + + power = Pcic_read(ph, PCIC_PWRCTL); + power &= ~PCIC_PWRCTL_OE; + Pcic_write(ph, PCIC_PWRCTL, power); + + /* power down the socket to reset it, clear the card reset pin */ + + pccbb_power(sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V); + + /* + * wait 200ms until power fails (Tpf). Then, wait 100ms since + * we are changing Vcc (Toff). + */ + /* delay(300*1000); too much */ + + /* power up the socket */ + pccbb_power(sc, voltage); + + /* + * wait 100ms until power raise (Tpr) and 20ms to become + * stable (Tsu(Vcc)). + * + * some machines require some more time to be settled + * (another 200ms is added here). + */ + /* delay((100 + 20 + 200)*1000); too much */ + + power = Pcic_read(ph, PCIC_PWRCTL); + Pcic_write(ph, PCIC_PWRCTL, power | PCIC_PWRCTL_OE); + + /* + * hold RESET at least 10us. + */ + delay(10); + delay(2*1000); /* XXX: TI1130 requires it. */ + delay(20*1000); /* XXX: TI1130 requires it. */ + + /* clear the reset flag */ + + intr = Pcic_read(ph, PCIC_INTR); + Pcic_write(ph, PCIC_INTR, intr | PCIC_INTR_RESET); + + /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */ + + delay(20000); + + /* wait for the chip to finish initializing */ + + pccbb_pcmcia_wait_ready(ph); + + /* zero out the address windows */ + + Pcic_write(ph, PCIC_ADDRWIN_ENABLE, 0); + + /* set the card type */ + + cardtype = pcmcia_card_gettype(ph->pcmcia); + + intr = Pcic_read(ph, PCIC_INTR); + intr &= ~PCIC_INTR_CARDTYPE_MASK; + intr |= ((cardtype == PCMCIA_IFTYPE_IO) ? + PCIC_INTR_CARDTYPE_IO : + PCIC_INTR_CARDTYPE_MEM); + Pcic_write(ph, PCIC_INTR, intr); + + DPRINTF(("%s: pccbb_pcmcia_socket_enable %02x cardtype %s %02x\n", + ph->ph_parent->dv_xname, ph->sock, + ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), intr)); + + /* reinstall all the memory and io mappings */ + + for (win = 0; win < PCIC_MEM_WINS; ++win) { + if (ph->memalloc & (1 << win)) { + pccbb_pcmcia_do_mem_map(ph, win); + } + } + + for (win = 0; win < PCIC_IO_WINS; ++win) { + if (ph->ioalloc & (1 << win)) { + pccbb_pcmcia_do_io_map(ph, win); + } + } +} + + + +/********************************************************************** +* STATIC void pccbb_pcmcia_socket_disable(pcmcia_chipset_handle_t *ph) +* +* This function disables the card. All information is stored in +* the first argument, pcmcia_chipset_handle_t. +**********************************************************************/ +STATIC void +pccbb_pcmcia_socket_disable(pch) + pcmcia_chipset_handle_t pch; +{ + struct pcic_handle *ph = (struct pcic_handle *)pch; + struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent; + u_int8_t power, intr; + + DPRINTF(("pccbb_pcmcia_socket_disable\n")); + + /* reset signal asserting... */ + + intr = Pcic_read(ph, PCIC_INTR); + intr &= ~PCIC_INTR_RESET; + Pcic_write(ph, PCIC_INTR, intr); + delay(2*1000); + + /* power down the socket */ + power = Pcic_read(ph, PCIC_PWRCTL); + power &= ~PCIC_PWRCTL_OE; + Pcic_write(ph, PCIC_PWRCTL, power); + pccbb_power(sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V); + + /* + * wait 300ms until power fails (Tpf). + */ + delay(300 * 1000); +} + + + +/********************************************************************** + * STATIC int pccbb_pcmcia_card_detect(pcmcia_chipset_handle_t *ph) + * + * This function detects whether a card is in the slot or not. + * If a card is inserted, return 1. Otherwise, return 0. + **********************************************************************/ +STATIC int +pccbb_pcmcia_card_detect(pch) + pcmcia_chipset_handle_t pch; +{ + struct pcic_handle *ph = (struct pcic_handle *)pch; + struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent; + + DPRINTF(("pccbb_pcmcia_card_detect\n")); + return pccbb_detect_card(sc) == 1 ? 1 : 0; +} + + + +#if 0 +STATIC int +pccbb_new_pcmcia_mem_alloc(pcmcia_chipset_handle_t pch, + bus_addr_t start, bus_size_t size, + bus_size_t align, + int speed, int flags, /* bus width */ + bus_space_tag_t *memtp + bus_space_handle_t *memhp) +#endif + + +/********************************************************************** +* STATIC int pccbb_pcmcia_mem_alloc(pcmcia_chipset_handle_t pch, +* bus_size_t size, +* struct pcmcia_mem_handle *pcmhp) +* +* This function only allocates memory region for pccard. This +* function never maps the allcated region to pccard memory area. +* +* XXX: Why the argument of start address is not in? +**********************************************************************/ +STATIC int +pccbb_pcmcia_mem_alloc(pch, size, pcmhp) + pcmcia_chipset_handle_t pch; + bus_size_t size; + struct pcmcia_mem_handle *pcmhp; +{ + struct pcic_handle *ph = (struct pcic_handle *)pch; + bus_space_handle_t memh; + bus_addr_t addr; + bus_size_t sizepg; + struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent; +#if rbus + rbus_tag_t rb; +#endif + + /* out of sc->memh, allocate as many pages as necessary */ + + /* convert size to PCIC pages */ + /* + This is not enough; when the requested region is on the + page boundaries, this may calculate wrong result. + */ + sizepg = (size + (PCIC_MEM_PAGESIZE - 1)) / PCIC_MEM_PAGESIZE; +#if 0 + if (sizepg > PCIC_MAX_MEM_PAGES) { + return 1; + } +#endif + + if (!(sc->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32)) { + return 1; + } + + addr = 0; /* XXX gcc -Wuninitialized */ + +#if rbus + rb = sc->sc_rbus_memt; + if (rbus_space_alloc(rb, 0, sizepg*PCIC_MEM_PAGESIZE, + sizepg*PCIC_MEM_PAGESIZE - 1, PCIC_MEM_PAGESIZE, + 0, &addr, &memh)) { + return 1; + } + +#else + if (bus_space_alloc(sc->sc_memt, sc->sc_mem_start, sc->sc_mem_end, + sizepg*PCIC_MEM_PAGESIZE, PCIC_MEM_PAGESIZE, + 0 /* boundary */, 0 /* flags */, + &addr, &memh)) { + return 1; + } +#endif + + DPRINTF(("pccbb_pcmcia_alloc_mem: addr 0x%lx size 0x%lx, realsize 0x%lx\n", + addr, size, sizepg*PCIC_MEM_PAGESIZE)); + + pcmhp->memt = sc->sc_memt; + pcmhp->memh = memh; + pcmhp->addr = addr; + pcmhp->size = size; + pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE; + /* What is mhandle? I feel it is very dirty and it must go trush. */ + pcmhp->mhandle = 0; + /* No offset??? Funny. */ + + return 0; +} + + + + +/********************************************************************** +* STATIC void pccbb_pcmcia_mem_free(pcmcia_chipset_handle_t pch, +* struct pcmcia_mem_handle *pcmhp) +* +* This function release the memory space allocated by the fuction +* pccbb_pcmcia_mem_alloc(). +**********************************************************************/ +STATIC void +pccbb_pcmcia_mem_free(pch, pcmhp) + pcmcia_chipset_handle_t pch; + struct pcmcia_mem_handle *pcmhp; +{ +#if rbus + struct pcic_handle *ph = (struct pcic_handle *)pch; + struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent; + + rbus_space_free(sc->sc_rbus_memt, pcmhp->memh, pcmhp->realsize, NULL); +#else + bus_space_free(pcmhp->memt, pcmhp->memh, pcmhp->realsize); +#endif +} + + + + +/********************************************************************** +* STATIC void pccbb_pcmcia_do_mem_map(struct pcic_handle *ph, int win) +* +* This function release the memory space allocated by the fuction +* pccbb_pcmcia_mem_alloc(). +**********************************************************************/ +STATIC void +pccbb_pcmcia_do_mem_map(ph, win) + struct pcic_handle *ph; + int win; +{ + int regbase_win; + bus_addr_t phys_addr; + bus_addr_t phys_end; + +#define PCIC_SMM_START_LOW 0 +#define PCIC_SMM_START_HIGH 1 +#define PCIC_SMM_STOP_LOW 2 +#define PCIC_SMM_STOP_HIGH 3 +#define PCIC_CMA_LOW 4 +#define PCIC_CMA_HIGH 5 + + u_int8_t start_low, start_high = 0; + u_int8_t stop_low, stop_high; + u_int8_t off_low, off_high; + u_int8_t mem_window; + int reg; + + regbase_win = 0x10 + win*0x08; + + phys_addr = ph->mem[win].addr; + phys_end = phys_addr + ph->mem[win].size; + + DPRINTF(("pccbb_pcmcia_do_mem_map: start 0x%lx end 0x%lx off 0x%lx\n", + phys_addr, phys_end, ph->mem[win].offset)); + +#define PCIC_MEMREG_LSB_SHIFT PCIC_SYSMEM_ADDRX_SHIFT +#define PCIC_MEMREG_MSB_SHIFT (PCIC_SYSMEM_ADDRX_SHIFT + 8) +#define PCIC_MEMREG_WIN_SHIFT (PCIC_SYSMEM_ADDRX_SHIFT + 12) + + start_low = (phys_addr >> PCIC_MEMREG_LSB_SHIFT) & 0xff; /* bit 19:12 */ + start_high = ((phys_addr >> PCIC_MEMREG_MSB_SHIFT) & 0x0f) /* bit 23:20 */ + | PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT; /* bit 7 on */ + /* bit 31:24, for 32-bit address */ + mem_window = (phys_addr >> PCIC_MEMREG_WIN_SHIFT) & 0xff; /* bit 31:24 */ + + Pcic_write(ph, regbase_win + PCIC_SMM_START_LOW, start_low); + Pcic_write(ph, regbase_win + PCIC_SMM_START_HIGH, start_high); + + if (((struct pccbb_softc *)ph->ph_parent)->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32) { + Pcic_write(ph, 0x40 + win, mem_window); + } + + +#if 0 + /* XXX do I want 16 bit all the time? */ + PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT; +#endif + + + stop_low = (phys_end >> PCIC_MEMREG_LSB_SHIFT) & 0xff; + stop_high = ((phys_end >> PCIC_MEMREG_MSB_SHIFT) & 0x0f) + | PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2; /* wait 2 cycles */ + /* XXX Geee, WAIT2!! Crazy!! I must rewrite this routine. */ + + Pcic_write(ph, regbase_win + PCIC_SMM_STOP_LOW, stop_low); + Pcic_write(ph, regbase_win + PCIC_SMM_STOP_HIGH, stop_high); + + off_low = (ph->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff; + off_high = ((ph->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) + & PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) + | ((ph->mem[win].kind == PCMCIA_MEM_ATTR) ? + PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0); + + Pcic_write(ph, regbase_win + PCIC_CMA_LOW, off_low); + Pcic_write(ph, regbase_win + PCIC_CMA_HIGH, off_high); + + reg = Pcic_read(ph, PCIC_ADDRWIN_ENABLE); + reg |= ((1 << win) | PCIC_ADDRWIN_ENABLE_MEMCS16); + Pcic_write(ph, PCIC_ADDRWIN_ENABLE, reg); + +#if defined CBB_DEBUG + { + int r1, r2, r3, r4, r5, r6, r7 = 0; + + r1 = Pcic_read(ph, regbase_win + PCIC_SMM_START_LOW); + r2 = Pcic_read(ph, regbase_win + PCIC_SMM_START_HIGH); + r3 = Pcic_read(ph, regbase_win + PCIC_SMM_STOP_LOW); + r4 = Pcic_read(ph, regbase_win + PCIC_SMM_STOP_HIGH); + r5 = Pcic_read(ph, regbase_win + PCIC_CMA_LOW); + r6 = Pcic_read(ph, regbase_win + PCIC_CMA_HIGH); + if (((struct pccbb_softc *)(ph->ph_parent))->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32) { + r7 = Pcic_read(ph, 0x40 + win); + } + + DPRINTF(("pccbb_pcmcia_do_mem_map window %d: %02x%02x %02x%02x " + "%02x%02x", win, r1, r2, r3, r4, r5, r6)); + if (((struct pccbb_softc *)(ph->ph_parent))->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32) { + DPRINTF((" %02x",r7)); + } + DPRINTF(("\n")); + } +#endif +} + + + + +/********************************************************************** +* STATIC int pccbb_pcmcia_mem_map(pcmcia_chipset_handle_t pch, int kind, +* bus_addr_t card_addr, bus_size_t size, +* struct pcmcia_mem_handle *pcmhp, +* bus_addr_t *offsetp, int *windowp) +* +* This function maps memory space allocated by the fuction +* pccbb_pcmcia_mem_alloc(). +**********************************************************************/ +STATIC int +pccbb_pcmcia_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp) + pcmcia_chipset_handle_t pch; + int kind; + bus_addr_t card_addr; + bus_size_t size; + struct pcmcia_mem_handle *pcmhp; + bus_addr_t *offsetp; + int *windowp; +{ + struct pcic_handle *ph = (struct pcic_handle *)pch; + bus_addr_t busaddr; + long card_offset; + int win; + + for (win = 0; win < PCIC_MEM_WINS; ++win) { + if ((ph->memalloc & (1 << win)) == 0) { + ph->memalloc |= (1 << win); + break; + } + } + + if (win == PCIC_MEM_WINS) { + return 1; + } + + *windowp = win; + + /* XXX this is pretty gross */ + + if (((struct pccbb_softc *)ph->ph_parent)->sc_memt != pcmhp->memt) { + panic("pccbb_pcmcia_mem_map memt is bogus"); + } + + busaddr = pcmhp->addr; + + /* + * compute the address offset to the pcmcia address space for the + * pcic. this is intentionally signed. The masks and shifts below + * will cause TRT to happen in the pcic registers. Deal with making + * sure the address is aligned, and return the alignment offset. + */ + + *offsetp = card_addr % PCIC_MEM_PAGESIZE; + card_addr -= *offsetp; + + DPRINTF(("pccbb_pcmcia_mem_map window %d bus %lx+%lx+%lx at card addr " + "%lx\n", win, (u_long)busaddr, (u_long)*offsetp, (u_long)size, + (u_long)card_addr)); + + /* + * include the offset in the size, and decrement size by one, since + * the hw wants start/stop + */ + size += *offsetp - 1; + + card_offset = (((long) card_addr) - ((long) busaddr)); + + ph->mem[win].addr = busaddr; + ph->mem[win].size = size; + ph->mem[win].offset = card_offset; + ph->mem[win].kind = kind; + + pccbb_pcmcia_do_mem_map(ph, win); + + return 0; +} + + + +/********************************************************************** +* STATIC int pccbb_pcmcia_mem_unmap(pcmcia_chipset_handle_t pch, +* int window) +* +* This function unmaps memory space which mapped by the fuction +* pccbb_pcmcia_mem_map(). +**********************************************************************/ +STATIC void +pccbb_pcmcia_mem_unmap(pch, window) + pcmcia_chipset_handle_t pch; + int window; +{ + struct pcic_handle *ph = (struct pcic_handle *)pch; + int reg; + + if (window >= PCIC_MEM_WINS) { + panic("pccbb_pcmcia_mem_unmap: window out of range"); + } + + reg = Pcic_read(ph, PCIC_ADDRWIN_ENABLE); + reg &= ~(1 << window); + Pcic_write(ph, PCIC_ADDRWIN_ENABLE, reg); + + ph->memalloc &= ~(1 << window); +} + + + +#if defined PCCBB_PCMCIA_POLL +struct pccbb_poll_str { + void *arg; + int (* func) __P((void *)); + int level; + struct pcic_handle *ph; + int count; + int num; +}; + +static struct pccbb_poll_str pccbb_poll[10]; +static int pccbb_poll_n = 0; + +static void pccbb_pcmcia_poll __P((void *arg)); + +static void +pccbb_pcmcia_poll(arg) + void *arg; +{ + struct pccbb_poll_str *poll = arg; + struct pcic_handle *ph = poll->ph; + struct pccbb_softc *sc = ph->sc; + int s; + u_int32_t spsr; /* socket present-state reg */ + + timeout(pccbb_pcmcia_poll, arg, hz*2); + switch (poll->level) { + case IPL_NET: + s = splnet(); + break; + case IPL_BIO: + s = splbio(); + break; + case IPL_TTY: /* fallthrough */ + default: + s = spltty(); + break; + } + + spsr = bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh, CB_SOCKET_STAT); +// printf("pccbb_pcmcia_poll: socket 0x%08x\n", spsr); + +#if defined PCCBB_PCMCIA_POLL_ONLY && defined LEVEL2 + if (!(spsr & 0x40)) /* CINT low */ +#else + if (1) +#endif + { + if ((*poll->func)(poll->arg) > 0) { + ++poll->count; +// printf("intr: reported from poller, 0x%x\n", spsr); +#if defined LEVEL2 + } else { + printf("intr: miss! 0x%x\n", spsr); +#endif + } + } + splx(s); +} +#endif /* defined CB_PCMCIA_POLL */ + + + +/********************************************************************** +* STATIC void *pccbb_pcmcia_intr_establish(pcmcia_chipset_handle_t pch, +* struct pcmcia_function *pf, +* int ipl, +* int (*func)(void *), +* void *arg); +* +* This function enables PC-Card interrupt. PCCBB uses PCI interrupt line. +**********************************************************************/ +STATIC void * +pccbb_pcmcia_intr_establish(pch, pf, ipl, func, arg) + pcmcia_chipset_handle_t pch; + struct pcmcia_function *pf; + int ipl; + int (*func) __P((void *)); + void *arg; +{ + struct pcic_handle *ph = (struct pcic_handle *)pch; + struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent; + pci_intr_handle_t handle; + void *ih; + + if (!(pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)) { + /* what should I do? */ + if ((pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)) { + DPRINTF(("%s does not provide edge nor pulse interrupt\n", + sc->sc_dev.dv_xname)); + return NULL; + } + /* XXX Noooooo! The interrupt flag must set properly!! */ + /* dumb pcmcia driver!! */ + } + + if (pci_intr_map(sc->sc_pc, sc->sc_intrtag, sc->sc_intrpin, + sc->sc_intrline, &handle)) { + printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); + return NULL; + } + DPRINTF(("pccbb_pcmcia_intr_establish: line %d, handle %d\n", + sc->sc_intrline, handle)); + + if (NULL != (ih = pci_intr_establish(sc->sc_pc, handle, ipl, func, arg))) + { + u_int32_t cbctrl; + + if ((CB_TI113X == sc->sc_chipset)) { + cbctrl = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL); + cbctrl |= PCI113X_CBCTRL_PCI_INTR; /* PCI functional intr req */ + pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, cbctrl); + } + } +#if defined PCCBB_PCMCIA_POLL + if (pccbb_poll_n < 10) { + pccbb_poll[pccbb_poll_n].arg = arg; + pccbb_poll[pccbb_poll_n].func = func; + pccbb_poll[pccbb_poll_n].level = ipl; + pccbb_poll[pccbb_poll_n].count = 0; + pccbb_poll[pccbb_poll_n].num = pccbb_poll_n; + pccbb_poll[pccbb_poll_n].ph = ph; + timeout(pccbb_pcmcia_poll, &pccbb_poll[pccbb_poll_n++], hz*2); + printf("polling set\n"); + } +#endif +#if defined SHOW_REGS + cb_show_regs(sc->sc_pc, sc->sc_tag, sc->sc_base_memt, sc->sc_base_memh); +#endif + + return ih; +} + + + + +/********************************************************************** +* STATIC void pccbb_pcmcia_intr_disestablish(pcmcia_chipset_handle_t pch, +* void *ih) +* +* This function disables PC-Card interrupt. +**********************************************************************/ +STATIC void +pccbb_pcmcia_intr_disestablish(pch, ih) + pcmcia_chipset_handle_t pch; + void *ih; +{ + struct pcic_handle *ph = (struct pcic_handle *)pch; + struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent; + + pci_intr_disestablish(sc->sc_pc, ih); +} + + + + +#if rbus +/********************************************************************** +* static int +* pccbb_rbus_cb_space_alloc(cardbus_chipset_tag_t ct, rbus_tag_t rb, +* bus_addr_t addr, bus_size_t size, +* bus_addr_t mask, bus_size_t align, +* int flags, bus_addr_t *addrp; +* bus_space_handle_t *bshp) +* +* This function allocates a portion of memory or io space for +* clients. This function is called from CardBus card drivers. +**********************************************************************/ +static int +pccbb_rbus_cb_space_alloc(ct, rb, addr, size, mask, align, flags, addrp, bshp) + cardbus_chipset_tag_t ct; + rbus_tag_t rb; + bus_addr_t addr; + bus_size_t size; + bus_addr_t mask; + bus_size_t align; + int flags; + bus_addr_t *addrp; + bus_space_handle_t *bshp; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)ct; + + DPRINTF(("pccbb_rbus_cb_space_alloc: adr %lx, size %lx, mask %lx, align %lx\n", addr, size, mask, align)); + + if (align == 0) { + align = size; + } + + if (rb->rb_bt == sc->sc_memt) { + if (align < 16) { + return 1; + } + } else if (rb->rb_bt == sc->sc_iot) { + if (align < 4) { + return 1; + } + } else { + DPRINTF(("pccbb_rbus_cb_space_alloc: Bus space tag %x is NOT used.\n", + rb->rb_bt)); + return 1; + /* XXX: panic here? */ + } + + /* XXX: hack for avoiding ISA image */ + if (mask < 0x3ff) { + mask = 0x3ff; + addr = 0x300; + } + + if (rbus_space_alloc(rb, addr, size, mask, align, flags, addrp, bshp)) { + printf("%s: no bus space\n", sc->sc_dev.dv_xname); + return 1; + } + + pccbb_open_win(sc, rb->rb_bt, *addrp, size, *bshp, 0); + + return 0; +} + + + + + +/********************************************************************** +* static int +* pccbb_rbus_cb_space_free(cardbus_chipset_tag_t *ct, rbus_tag_t rb, +* bus_space_handle_t *bshp, bus_size_t size); +* +* This function is called from CardBus card drivers. +**********************************************************************/ +static int +pccbb_rbus_cb_space_free(ct, rb, bsh, size) + cardbus_chipset_tag_t ct; + rbus_tag_t rb; + bus_space_handle_t bsh; + bus_size_t size; +{ + struct pccbb_softc *sc = (struct pccbb_softc *)ct; + bus_space_tag_t bt = rb->rb_bt; + + pccbb_close_win(sc, bt, bsh, size); + + if (bt == sc->sc_memt) { + } else if (bt == sc->sc_iot) { + } else { + return 1; + /* XXX: panic here? */ + } + + return rbus_space_free(rb, bsh, size, NULL); +} +#endif /* rbus */ + + +#if rbus + +static int +pccbb_open_win(sc, bst, addr, size, bsh, flags) + struct pccbb_softc *sc; + bus_space_tag_t bst; + bus_addr_t addr; + bus_size_t size; + bus_space_handle_t bsh; + int flags; +{ + struct pccbb_win_chain **top; + bus_addr_t align; + + top = &sc->sc_iowindow; + align = 0x04; + if (sc->sc_memt == bst) { + top = &sc->sc_memwindow; + align = 0x1000; + printf("using memory window, %x %x %x\n\n", + sc->sc_iot, sc->sc_memt, bst); + } + + if (pccbb_winlist_insert(top, addr, size, bsh, flags)) { + printf("winlist insert fails:\n"); + } + pccbb_winset(align, sc, bst); + + return 0; +} + + + +static int +pccbb_close_win(sc, bst, bsh, size) + struct pccbb_softc *sc; + bus_space_tag_t bst; + bus_space_handle_t bsh; + bus_size_t size; +{ + struct pccbb_win_chain **top; + bus_addr_t align; + + top = &sc->sc_iowindow; + align = 0x04; + if (sc->sc_memt == bst) { + top = &sc->sc_memwindow; + align = 0x1000; + } + + if (pccbb_winlist_delete(top, bsh, size)) { + printf("winlist delete fails:\n"); + } + pccbb_winset(align, sc, bst); + + return 0; +} + + +static int +pccbb_winlist_insert(top, start, size, bsh, flags) + struct pccbb_win_chain **top; + bus_addr_t start; + bus_size_t size; + bus_space_handle_t bsh; + int flags; +{ + struct pccbb_win_chain *chainp = *top; + struct pccbb_win_chain *before = *top; + struct pccbb_win_chain *elem; + + if (*top == NULL) { + if (NULL == (elem = (struct pccbb_win_chain *)malloc(sizeof(struct pccbb_win_chain), M_DEVBUF, M_NOWAIT))) { + return 1; /* fail */ + } + + elem->wc_start = start; + elem->wc_end = start + size - 1; + elem->wc_handle = bsh; + elem->wc_flags = flags; + + *top = elem; + elem->wc_next = NULL; + return 0; + } + + for(; chainp && chainp->wc_start <= start; chainp = chainp->wc_next) { + before = chainp; + } + + if (chainp != NULL) { + if (chainp->wc_start < start + size) { + printf("fatal! 0x%lx 0x%lx\n", chainp->wc_start, start+size); + return 1; + } + } + if ((before != *top) && (before->wc_end >= start)) { + printf("fatal!! 0x%lx 0x%lx\n", before->wc_end, start); + return 1; + } + + if (NULL == (elem = (struct pccbb_win_chain *)malloc(sizeof(struct pccbb_win_chain), M_DEVBUF, M_NOWAIT))) { + return 1; /* fail */ + } + + elem->wc_start = start; + elem->wc_end = start + size - 1; + elem->wc_handle = bsh; + elem->wc_flags = flags; + + elem->wc_next = chainp; + if (chainp == *top) { + *top = elem; + } else { + before->wc_next = elem; + } + return 0; +} + + + + +static int +pccbb_winlist_delete(top, bsh, size) + struct pccbb_win_chain **top; + bus_space_handle_t bsh; + bus_size_t size; +{ + struct pccbb_win_chain *chainp = *top; + struct pccbb_win_chain **before = top; + + for (; chainp && chainp->wc_handle != bsh; chainp = chainp->wc_next) { + before = &chainp->wc_next; + } + + if (chainp == NULL) { + return 1; /* fail: no candidate to remove */ + } + + if (chainp->wc_end - chainp->wc_start != size - 1) { + printf("fatal!!! 0x%lx\n", chainp->wc_start); + return 1; /* fail: no candidate to remove */ + } + + *before = chainp->wc_next; + free(chainp, M_DEVBUF); + + return 0; +} + + + +static void +pccbb_winset(align, sc, bst) + bus_addr_t align; + struct pccbb_softc *sc; + bus_space_tag_t bst; +{ + pci_chipset_tag_t pc; + pcitag_t tag; + bus_addr_t mask = ~(align - 1); + struct { + cardbusreg_t win_start; + cardbusreg_t win_limit; + int win_flags; + } win[2]; + struct pccbb_win_chain *chainp; + int offs; + + win[0].win_start = 0xffffffff; + win[0].win_limit = 0; + win[1].win_start = 0xffffffff; + win[1].win_limit = 0; + + chainp = sc->sc_iowindow; + offs = 0x2c; + if (sc->sc_memt == bst) { + chainp = sc->sc_memwindow; + offs = 0x1c; + } + + if (chainp) { + win[0].win_start = chainp->wc_start & mask; + win[0].win_limit = chainp->wc_end & mask; + win[0].win_flags = chainp->wc_flags; + chainp = chainp->wc_next; + } + + for(; chainp; chainp = chainp->wc_next) { + if (win[1].win_start == 0xffffffff) { + /* window 1 is not used */ + if ((win[0].win_flags == chainp->wc_flags) && + (win[0].win_limit + align >= (chainp->wc_start & mask))) { + /* concatinate */ + win[0].win_limit = chainp->wc_end & mask; + } else { + /* make new window */ + win[1].win_start = chainp->wc_start & mask; + win[1].win_limit = chainp->wc_end & mask; + win[1].win_flags = chainp->wc_flags; + } + continue; + } + + /* Both windows are engagad. */ + if (win[0].win_flags == win[1].win_flags) { + /* same flags */ + if (win[0].win_flags == chainp->wc_flags) { + + win[1].win_limit = chainp->wc_end & mask; + + if (win[1].win_start - (win[0].win_limit + align) + < (chainp->wc_start & mask) - (win[1].win_limit + align)) { + win[0].win_limit = win[1].win_limit; + win[1].win_start = chainp->wc_start & mask; + } + } else { + /* different flags */ + + /* concatinate win0 and win1 */ + win[0].win_limit = win[1].win_limit; + /* allocate win[1] to new space */ + win[1].win_start = chainp->wc_start & mask; + win[1].win_limit = chainp->wc_end & mask; + win[1].win_flags = chainp->wc_flags; + } + } else { + /* the flags of win[0] and win[1] is different */ + if (win[0].win_flags == chainp->wc_flags) { + win[0].win_limit = chainp->wc_end & mask; + } else { + win[1].win_limit = chainp->wc_end & mask; + } + } + } + + pc = sc->sc_pc; + tag = sc->sc_tag; + pci_conf_write(pc, tag, offs, win[0].win_start); + pci_conf_write(pc, tag, offs+4, win[0].win_limit); + pci_conf_write(pc, tag, offs+8, win[1].win_start); + pci_conf_write(pc, tag, offs+12, win[1].win_limit); + DPRINTF(("--pccbb_winset: win0 [%x, %lx), win1 [%x, %lx)\n", + pci_conf_read(pc, tag, offs), + pci_conf_read(pc, tag, offs+4) + align, + pci_conf_read(pc, tag, offs+8), + pci_conf_read(pc, tag, offs+12) + align)); + + if (bst == sc->sc_memt) { + if (win[0].win_start & PCCBB_MEM_CACHABLE) { + pcireg_t bcr = pci_conf_read(pc, tag, PCI_BCR_INTR); + bcr |= CB_BCR_PREFETCH_MEMWIN0; + pci_conf_write(pc,tag, PCI_BCR_INTR, bcr); + } + if (win[1].win_start & PCCBB_MEM_CACHABLE) { + pcireg_t bcr = pci_conf_read(pc, tag, PCI_BCR_INTR); + bcr |= CB_BCR_PREFETCH_MEMWIN1; + pci_conf_write(pc,tag, PCI_BCR_INTR, bcr); + } + } +} + +#endif /* rbus */ diff --git a/sys/dev/pci/pccbbreg.h b/sys/dev/pci/pccbbreg.h new file mode 100644 index 000000000000..a6f00d3d0afa --- /dev/null +++ b/sys/dev/pci/pccbbreg.h @@ -0,0 +1,220 @@ +/* + * Copyright (c) 1999 HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by HAYAKAWA Koichi. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id: pccbbreg.h,v 1.1 1999/10/15 06:07:30 haya Exp $ */ + +#ifndef _DEV_PCI_PCCBBREG_H_ +#define _DEV_PCI_PCCBBREG_H_ + + + + +#define PCI_SOCKBASE 0x10 /* Socket Base Address Register */ +#define PCI_BUSNUM 0x18 /* latency timer, Subordinate bus number */ +#define PCI_BCR_INTR 0x3C /* intr line, intr pin, bridge control regs */ +#define PCI_LEGACY 0x44 /* legacy IO register address (32 bits) */ +#define PCI_CBCTRL 0x90 /* Retry status, Card ctrl, Device ctrl */ + +#define PCI_CLASS_INTERFACE_MASK 0xffffff00 +#define PCI_CLASS_INTERFACE_YENTA 0x06070000 + +#define CB_SOCKET_EVENT 0x00 /* offset of cardbus socket event reg */ +#define CB_SOCKET_MASK 0x04 /* offset of cardbus socket mask register */ +#define CB_SOCKET_STAT 0x08 /* offset of cardbus socket present-state */ +#define CB_SOCKET_FORCE 0x0c /* offset of cardbus socket force event */ +#define CB_SOCKET_CTRL 0x10 /* offset of cardbus socket control reg */ + + +/* CardBus latency timer, Subordinate bus no, CardBus bus no and PCI bus no */ +#define PCI_CB_LSCP_REG 0x18 +/* CardBus memory and io windows */ +#define PCI_CB_MEMBASE0 0x1c +#define PCI_CB_MEMLIMIT0 0x20 +#define PCI_CB_MEMBASE1 0x24 +#define PCI_CB_MEMLIMIT1 0x28 +#define PCI_CB_IOBASE0 0x2c +#define PCI_CB_IOLIMIT0 0x30 +#define PCI_CB_IOBASE1 0x34 +#define PCI_CB_IOLIMIT1 0x38 + +/* PCI_CB_LSCP_REG */ +#define PCI_CB_LATENCY_SHIFT 24 +#define PCI_CB_LATENCY_MASK 0xff +#define PCI_CB_LATENCY(x) (((x) >> PCI_CB_LATENCY_SHIFT) & PCI_CB_LATENCY_MASK) + + + +/* PCI_BCR_INTR bits for generic PCI-CardBus bridge */ +#define CB_BCR_INTR_IREQ_ENABLE 0x00800000 +#define CB_BCR_PREFETCH_MEMWIN0 0x01000000 +#define CB_BCR_PREFETCH_MEMWIN1 0x02000000 +#define CB_BCR_WRITE_POST_ENABLE 0x04000000 + +/* PCI_CBCTRL bits for TI PCI113X */ +#define PCI113X_CBCTRL_INT_SERIAL 0x040000 +#define PCI113X_CBCTRL_INT_ISA 0x020000 +#define PCI113X_CBCTRL_INT_MASK 0x060000 +#define PCI113X_CBCTRL_RIENB 0x8000 /* Ring indicate output enable */ +#define PCI113X_CBCTRL_ZVENAB 0x4000 /* ZV mode enable */ +#define PCI113X_CBCTRL_PCI_IRQ_ENA 0x2000 /* PCI intr enable (funct and CSC) */ +#define PCI113X_CBCTRL_PCI_INTR 0x1000 /* PCI functional intr req */ +#define PCI113X_CBCTRL_PCI_CSC 0x0800 /* CSC intr route to PCI */ +#define PCI113X_CBCTRL_PCI_CSC_D 0x0400 /* unknown */ +#define PCI113X_CBCTRL_SPK_ENA 0x0200 /* Speaker enable */ +#define PCI113X_CBCTRL_INTR_DET 0x0100 /* functional interrupt detect */ + +/* PCI_CBCTRL bits for TI PCI12XX */ +#define PCI12XX_CBCTRL_INT_SERIAL 0x040000 +#define PCI12XX_CBCTRL_INT_ISA 0x020000 +#define PCI12XX_CBCTRL_INT_PCI 0x000000 +#define PCI12XX_CBCTRL_INT_MASK 0x060000 +#define PCI12XX_CBCTRL_RIENB 0x8000 /* Ring indicate output enable */ +#define PCI12XX_CBCTRL_ZVENAB 0x4000 /* ZV mode enable */ +#define PCI12XX_CBCTRL_AUD2MUX 0x0400 /* unknown */ +#define PCI12XX_CBCTRL_SPK_ENA 0x0200 /* Speaker enable */ +#define PCI12XX_CBCTRL_INTR_DET 0x0100 /* functional interrupt detect */ + + +/* PCI_BCR_INTR additional bit for RF5C46[567] */ +#define CB_BCRI_RL_3E0_ENA 0x08000000 +#define CB_BCRI_RL_3E2_ENA 0x10000000 + +/* + * Special resister definition for Toshiba ToPIC95/97 + * These values are borrowed from pcmcia-cs/Linux. + */ +#define TOPIC_SOCKET_CTRL 0x90 +# define TOPIC_SOCKET_CTRL_SCR_IRQSEL 0x00000001 /* PCI intr */ + +#define TOPIC_SLOT_CTRL 0xa0 +# define TOPIC_SLOT_CTRL_SLOTON 0x00000080 +# define TOPIC_SLOT_CTRL_SLOTEN 0x00000040 +# define TOPIC_SLOT_CTRL_ID_LOCK 0x00000020 +# define TOPIC_SLOT_CTRL_ID_WP 0x00000010 +# define TOPIC_SLOT_CTRL_PORT_MASK 0x0000000c +# define TOPIC_SLOT_CTRL_PORT_SHIFT 2 +# define TOPIC_SLOT_CTRL_OSF_MASK 0x00000003 +# define TOPIC_SLOT_CTRL_OSF_SHIFT 0 + +# define TOPIC_SLOT_CTRL_INTB 0x00002000 +# define TOPIC_SLOT_CTRL_INTA 0x00001000 +# define TOPIC_SLOT_CTRL_INT_MASK 0x00003000 +# define TOPIC_SLOT_CTRL_CLOCK_MASK 0x00000c00 +# define TOPIC_SLOT_CTRL_CLOCK_2 0x00000800 /* PCI Clock/2 */ +# define TOPIC_SLOT_CTRL_CLOCK_1 0x00000400 /* PCI Clock */ +# define TOPIC_SLOT_CTRL_CLOCK_0 0x00000000 /* no clock */ + +# define TOPIC_SLOT_CTRL_CARDBUS 0x80000000 +# define TOPIC_SLOT_CTRL_VS1 0x04000000 +# define TOPIC_SLOT_CTRL_VS2 0x02000000 +# define TOPIC_SLOT_CTRL_SWDETECT 0x01000000 + +#define TOPIC_REG_CTRL 0x00a4 +# define TOPIC_REG_CTRL_RESUME_RESET 0x80000000 +# define TOPIC_REG_CTRL_REMOVE_RESET 0x40000000 +# define TOPIC97_REG_CTRL_CLKRUN_ENA 0x20000000 +# define TOPIC97_REG_CTRL_TESTMODE 0x10000000 +# define TOPIC97_REG_CTRL_IOPLUP 0x08000000 +# define TOPIC_REG_CTRL_BUFOFF_PWROFF 0x02000000 +# define TOPIC_REG_CTRL_BUFOFF_SIGOFF 0x01000000 +# define TOPIC97_REG_CTRL_CB_DEV_MASK 0x0000f800 +# define TOPIC97_REG_CTRL_CB_DEV_SHIFT 11 +# define TOPIC97_REG_CTRL_RI_DISABLE 0x00000004 +# define TOPIC97_REG_CTRL_CAUDIO_OFF 0x00000002 +# define TOPIC_REG_CTRL_CAUDIO_INVERT 0x00000001 + + + +/* socket event register (CB_SOCKET_EVENT) elements */ +#define CB_SOCKET_EVENT_CSTS 0x01 /* CARDSTS event occurs */ +#define CB_SOCKET_EVENT_CD 0x06 /* CD event occurs */ +#define CB_SOCKET_EVENT_CD1 0x02 /* CD1 event occurs */ +#define CB_SOCKET_EVENT_CD2 0x04 /* CD2 event occurs */ +#define CB_SOCKET_EVENT_POWER 0x08 /* Power cycle event occurs */ + + +/* socket mask register (CB_SOCKET_MASK) elements */ +#define CB_SOCKET_MASK_CSTS 0x01 /* CARDSTS event mask */ +#define CB_SOCKET_MASK_CD 0x06 /* CD event mask */ +#define CB_SOCKET_MASK_POWER 0x08 /* Power cycle event mask */ + +/* socket present-state register (CB_SOCKET_STAT) elements */ +#define CB_SOCKET_STAT_CARDSTS 0x01 /* card status change bit */ +#define CB_SOCKET_STAT_CD1 0x02 /* card detect 1 */ +#define CB_SOCKET_STAT_CD2 0x04 /* card detect 2 */ +#define CB_SOCKET_STAT_CD 0x06 /* card detect 1 and 2 */ +#define CB_SOCKET_STAT_PWRCYCLE 0x08 /* power cycle */ +#define CB_SOCKET_STAT_16BIT 0x010 /* 16-bit card */ +#define CB_SOCKET_STAT_CB 0x020 /* cardbus card */ +#define CB_SOCKET_STAT_IREQ 0x040 /* READY(~IREQ)//(~CINT) bit */ +#define CB_SOCKET_STAT_NOTCARD 0x080 /* Inserted card is unrecognisable */ +#define CB_SOCKET_STAT_DATALOST 0x0100 /* data lost */ +#define CB_SOCKET_STAT_BADVCC 0x0200 /* Bad Vcc Request */ +#define CB_SOCKET_STAT_5VCARD 0x0400 /* 5 V Card */ +#define CB_SOCKET_STAT_3VCARD 0x0800 /* 3.3 V Card */ +#define CB_SOCKET_STAT_XVCARD 0x01000 /* X.X V Card */ +#define CB_SOCKET_STAT_YVCARD 0x02000 /* Y.Y V Card */ +#define CB_SOCKET_STAT_5VSOCK 0x10000000 /* 5 V Socket */ +#define CB_SOCKET_STAT_3VSOCK 0x20000000 /* 3.3 V Socket */ +#define CB_SOCKET_STAT_XVSOCK 0x20000000 /* X.X V Socket */ +#define CB_SOCKET_STAT_YVSOCK 0x20000000 /* Y.Y V Socket */ + +/* socket force event register (CB_SOCKET_FORCE) elements */ +#define CB_SOCKET_FORCE_BADVCC 0x0200 /* Bad Vcc Request */ + + +/* socket control register (CB_SOCKET_CTRL) elements */ +#define CB_SOCKET_CTRL_VPPMASK 0x07 +#define CB_SOCKET_CTRL_VPP_OFF 0x00 +#define CB_SOCKET_CTRL_VPP_12V 0x01 +#define CB_SOCKET_CTRL_VPP_5V 0x02 +#define CB_SOCKET_CTRL_VPP_3V 0x03 +#define CB_SOCKET_CTRL_VPP_XV 0x04 +#define CB_SOCKET_CTRL_VPP_YV 0x05 + +#define CB_SOCKET_CTRL_VCCMASK 0x070 +#define CB_SOCKET_CTRL_VCC_OFF 0x000 +#define CB_SOCKET_CTRL_VCC_5V 0x020 +#define CB_SOCKET_CTRL_VCC_3V 0x030 +#define CB_SOCKET_CTRL_VCC_XV 0x040 +#define CB_SOCKET_CTRL_VCC_YV 0x050 + +#define CB_SOCKET_CTRL_STOPCLK 0x080 + + + +/* PCCARD VOLTAGE */ +#define PCCARD_VCC_UKN 0x00 /* unknown */ +#define PCCARD_VCC_5V 0x01 +#define PCCARD_VCC_3V 0x02 +#define PCCARD_VCC_XV 0x04 +#define PCCARD_VCC_YV 0x08 + + +#endif /* _DEV_PCI_PCCBBREG_H_ */ diff --git a/sys/dev/pci/pccbbvar.h b/sys/dev/pci/pccbbvar.h new file mode 100644 index 000000000000..896977ea0007 --- /dev/null +++ b/sys/dev/pci/pccbbvar.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 1999 HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by HAYAKAWA Koichi. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id:*/ + +/* require sys/device.h */ +/* require sys/queue.h */ +/* require dev/ic/i82365reg.h */ +/* require dev/ic/i82365var.h */ + +#ifndef _DEV_PCI_PCCBBVAR_H_ +#define _DEV_PCI_PCCBBVAR_H_ + + +#define PCIC_FLAG_SOCKETP 0x0001 +#define PCIC_FLAG_CARDP 0x0002 + + + +/* Chipset ID */ +#define CB_UNKNOWN 0 /* NOT Cardbus-PCI bridge */ +#define CB_TI113X 1 /* TI PCI1130/1131 */ +#define CB_TI12XX 2 /* TI PCI1250/1220 */ +#define CB_RF5C47X 3 /* RICOH RF5C475/476/477 */ +#define CB_RF5C46X 4 /* RICOH RF5C465/466/467 */ +#define CB_TOPIC95 5 /* Toshiba ToPIC95 */ +#define CB_TOPIC95B 6 /* Toshiba ToPIC95B */ +#define CB_TOPIC97 7 /* Toshiba ToPIC97 */ +#define CB_CIRRUS 8 /* Cirrus Logic CL-PD683X */ +#define CB_CHIPS_LAST 9 /* Sentinel */ + +#if 0 +static char *cb_chipset_name[CB_CHIPS_LAST] = { + "unknown", "TI 113X", "TI 12XX", "RF5C47X", "RF5C46X", "ToPIC95", + "ToPIC95B", "ToPIC97", "CL-PD 683X", +}; +#endif + +struct pccbb_softc; + +#if pccard +struct cbb_pcmcia_softc { + pccard_chipset_t cpc_ct; + struct pccard_softc *cpc_csc; + struct pccbb_softc *cpc_parent; + u_int8_t cpc_statreg; /* status register */ + u_int32_t cpc_regbase; /* base index of the slot */ + u_int16_t cpc_flags; + bus_space_tag_t cpc_iot; + bus_space_handle_t cpc_ioh; +}; +#endif /* pccard */ + +struct cbb_pcic_handle { + struct device *ph_parent; + bus_space_tag_t ph_base_t; + bus_space_handle_t ph_base_h; + u_int8_t (* ph_read) __P((struct cbb_pcic_handle *, int)); + void (* ph_write) __P((struct cbb_pcic_handle *, int, u_int8_t)); + int sock; + + int vendor; + int flags; + int memalloc; + struct { + bus_addr_t addr; + bus_size_t size; + long offset; + int kind; + } mem[PCIC_MEM_WINS]; + int ioalloc; + struct { + bus_addr_t addr; + bus_size_t size; + int width; + } io[PCIC_IO_WINS]; + int ih_irq; + struct device *pcmcia; + + int shutdown; +}; + + +struct pccbb_win_chain { + bus_addr_t wc_start; /* Caution: region [start, end], */ + bus_addr_t wc_end; /* instead of [start, end). */ + int wc_flags; +#define PCCBB_MEM_CACHABLE 1 + bus_space_handle_t wc_handle; + struct pccbb_win_chain *wc_next; +}; + + +struct pccbb_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_tag_t sc_memt; + bus_dma_tag_t sc_dmat; + +#if rbus + rbus_tag_t sc_rbus_iot; /* rbus for i/o donated from parent */ + rbus_tag_t sc_rbus_memt; /* rbus for mem donated from parent */ +#endif + + bus_space_tag_t sc_base_memt; + bus_space_handle_t sc_base_memh; + + void *sc_ih; /* interrupt handler */ + int sc_intrline; /* interrupt line */ + pcitag_t sc_intrtag; /* copy of pa->pa_intrtag */ + pci_intr_pin_t sc_intrpin; /* copy of pa->pa_intrpin */ + int sc_function; + u_int32_t sc_flags; +#define CBB_CARDEXIST 0x01 +#define CBB_INSERTING 0x01000000 +#define CBB_16BITCARD 0x04 +#define CBB_32BITCARD 0x08 + +#if pccard + struct cbb_pcmcia_softc sc_pcmcia; +#endif /* pccard */ + pci_chipset_tag_t sc_pc; + pcitag_t sc_tag; + int sc_chipset; /* chipset id */ + + bus_addr_t sc_mem_start; /* CardBus/PCMCIA memory start */ + bus_addr_t sc_mem_end; /* CardBus/PCMCIA memory end */ + bus_addr_t sc_io_start; /* CardBus/PCMCIA io start */ + bus_addr_t sc_io_end; /* CardBus/PCMCIA io end */ + + /* CardBus stuff */ + struct cardslot_softc *sc_csc; + + struct pccbb_win_chain *sc_memwindow; + struct pccbb_win_chain *sc_iowindow; + + /* pcmcia stuff */ + struct pcic_handle sc_pcmcia_h; + pcmcia_chipset_tag_t sc_pct; + int sc_pcmcia_flags; +#define PCCBB_PCMCIA_IO_RELOC 0x01 /* IO address relocatable stuff exists */ +#define PCCBB_PCMCIA_MEM_32 0x02 /* 32-bit memory address ready */ + + struct proc *sc_event_thread; + SIMPLEQ_HEAD(, pcic_event) sc_events; +}; + +#endif /* _DEV_PCI_PCCBBREG_H_ */ diff --git a/sys/dev/pcmcia/pcmcia.c b/sys/dev/pcmcia/pcmcia.c index 252a79d1e4da..141670222652 100644 --- a/sys/dev/pcmcia/pcmcia.c +++ b/sys/dev/pcmcia/pcmcia.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcmcia.c,v 1.13 1998/12/24 04:51:59 marc Exp $ */ +/* $NetBSD: pcmcia.c,v 1.14 1999/10/15 06:07:31 haya Exp $ */ #define PCMCIADEBUG @@ -111,6 +111,11 @@ pcmcia_match(parent, match, aux) struct cfdata *match; void *aux; { + struct pcmciabus_attach_args *paa = aux; + + if (strcmp(paa->paa_busname, match->cf_driver->cd_name)) { + return 0; + } /* if the autoconfiguration got this far, there's a socket here */ return (1); } diff --git a/sys/dev/pcmcia/pcmciachip.h b/sys/dev/pcmcia/pcmciachip.h index 898d67f0b4bd..139c3f05349c 100644 --- a/sys/dev/pcmcia/pcmciachip.h +++ b/sys/dev/pcmcia/pcmciachip.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcmciachip.h,v 1.3 1998/11/17 08:49:12 thorpej Exp $ */ +/* $NetBSD: pcmciachip.h,v 1.4 1999/10/15 06:07:32 haya Exp $ */ /* * Copyright (c) 1997 Marc Horowitz. All rights reserved. @@ -83,6 +83,9 @@ struct pcmcia_chip_functions { /* card enable/disable */ void (*socket_enable) __P((pcmcia_chipset_handle_t)); void (*socket_disable) __P((pcmcia_chipset_handle_t)); + + /* card detection */ + int (*card_detect) __P((pcmcia_chipset_handle_t)); }; /* Memory space functions. */ @@ -129,6 +132,7 @@ struct pcmcia_chip_functions { ((*(tag)->socket_disable)((handle))) struct pcmciabus_attach_args { + char *paa_busname; /* Bus name */ pcmcia_chipset_tag_t pct; pcmcia_chipset_handle_t pch; bus_addr_t iobase; /* start i/o space allocation here */