现在的位置: 首页 > 综合 > 正文

Solaris Source Insight: PCI bus driver moduls – pci_pci driver module

2013年02月09日 ⁄ 综合 ⁄ 共 4409字 ⁄ 字号 评论关闭

<!--
@page { margin: 0.79in }
P { margin-bottom: 0.08in }
-->

This time we will look into pci_pci
driver module. It's PCI to PCI bus bridge nexus driver. As usual, we
can find the source files which implement this module. I tried to
type Chinese in OpenOffice, but the font looks so ugly.

 

[allen@blu-xvm-osol:uts]find . -name
Makefile/* | xargs grep PCI_PCINEXUS_OBJS

./intel/Makefile.files:PCI_PCINEXUS_OBJS
+= pci_pci.o

./intel/pci_pci/Makefile:OBJECTS =
$(PCI_PCINEXUS_OBJS:%=$(OBJS_DIR)/%)

./intel/pci_pci/Makefile:LINTS =
$(PCI_PCINEXUS_OBJS:%.o=$(LINTS_DIR)/%.ln)

[allen@blu-xvm-osol:uts]find . -name
pci_pci.c

./sun4u/io/pci/pci_pci.c

./intel/io/pci/pci_pci.c

 

As usual, if no further notification,
all source code is from intel/io/pci/pci_pci.c. Module linkage
information:

 

175 /*

176 * Module linkage information for
the kernel.

177 */

178

179 static struct modldrv modldrv = {

180 |_______&mod_driverops, /*
Type of module */

181 |_______"Standard PCI to PCI
bridge nexus driver",

182 |_______&ppb_ops,|______/*
driver ops */

183 };

184

185 static struct modlinkage
modlinkage = {

186 |_______MODREV_1,

187 |_______(void *)&modldrv,

188 |_______NULL

189 };

 

Soft state structure is created in
_init() and will be allocated attach(). The state structure is
defined as below.

 

191 /*

192 * soft state pointer and
structure template:

193 */

194 static void *ppb_state;

195

196 typedef struct {

197 |_______dev_info_t *dip;

198 |_______int ppb_fmcap;

199 |_______ddi_iblock_cookie_t
ppb_fm_ibc;

200 |_______kmutex_t ppb_mutex;

201 |_______kmutex_t
ppb_peek_poke_mutex;

202 |_______kmutex_t ppb_err_mutex;

203

204 |_______/*

205 |_______ * cpr support:

206 |_______ */

207 |_______uint_t
config_state_index;

208 |_______struct {

209 |_______|_______dev_info_t *dip;

210 |_______|_______ushort_t command;

211 |_______|_______uchar_t
cache_line_size;

212 |_______|_______uchar_t
latency_timer;

213 |_______|_______uchar_t
header_type;

214 |_______|_______uchar_t
sec_latency_timer;

215 |_______|_______ushort_t
bridge_control;

216 |_______}
config_state[PCI_MAX_CHILDREN];

217

218 |_______uint16_t parent_bus;

219 } ppb_devstate_t;

 

attach() interface first and ignore the
DDI_RESUME command.

  1. Set property of "device_type"
    to "pci".

  2. Allocate and get soft state
    structure.

  3. FM setup, don't enable ereports if
    immediate child of npe.

  4. Initialize the mutex locks in soft
    state structure.

  5. Check all the ancestor of the
    bridge, if there is a PCIe device, set parent_bus of soft state to
    PCIE_PCIECAP_DEV_TYPE_PCIE_DEV; otherwise, it is set to
    PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO.

  6. Initialize hotplug support on this
    bus. If itś a PCI-E Endpont Device, pcie_init() is called;
    otherwise, pcihp_init() is called.

  7. Report the bridge device.

Question: What is the differnce between
“PCI-E to PCI bus bridge” and “PCI to PCI bus bridge”? Why
bus_parent set to PCIE_PCIECAP_DEV_TYPE_PCIE_DEV when the ancestor
of a PCI_PCI bridge is PCI-E device?

 

Answer: with bus_parent set to
PCIE_PCIECAP_DEV_TYPE_PCIE_DEV, the platform is a PCI-E platform;
otherwise, it is a lagecy PCI platform.

 

 

Picture 1 Tylersburg IOH
block diagram

 

 

Dirver Operations:

  • ppb_open()

  • ppb_close()

  • ppb_ioctl()

  • ppb_prop_op()

Call pcie
framework interface if it is a PCIe platform; otherwise, call
interfaces in misc/pcihp. All hotplug, power management, fault
management interfaces of a PCI-e device are exported via misc/pcie,
which is called PCI Express framework. For a legacy PCI platform,
hotplug is supported by misc/pcihp.

 

972 |_______/*

973 |_______ *
Ioctls will be handled by PCI Express framework for all

974 |_______ *
PCIe platforms

975 |_______ */

976 |_______if
(ppb_p->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)

977
|_______|_______return (pcie_ioctl(ppb_p->dip, dev, cmd, arg,
mode, credp,

978
|_______|_______ rvalp));

979

980
|_______return ((pcihp_get_cb_ops())->cb_ioctl(dev, cmd, arg,
mode, credp,

981 |_______
rvalp));

 

Bus Operation:

  • ppb_bus_map()

Escalate this
request to parent.

  • ppb_ctlops()

ppb_initchild()/ppb_removechild()
are used to initialize a child node under this pci-pci bridge. It
first merges the pseudo .conf node property. This kind of pseudo
nodes are created in init_node() when DDI implementation tries to put
the devinfo node at DS_INITIALIZED state. Initialize the PCI-e
private data if this bridge is on a PCIE platform. PCIe Bus Private
Data contains commonly used PCI/PCIe information and offsets to key
registers. Create parent private data and the interrupt vectore data
if the node contains “interrupt” property. The last step of
initchild() is the support for the "command-preserve"
property. ppb_removechild() will be called in init_node() if
initchild() returns error.

Device suspend and
resume support is implemented via DDI_CTLOPS_ATTACH/DDI_CTLOPS_DETACH
bus ctl operations.

Device configure
space peek/poke is supported via DDI_CTLOPS_PEEK/DDI_CTLOPS_POKE bus
ctl operations.

  • ppb_fm_init()

  • ppb_intr_ops()

This function is
defined to intercept certain interrupt services to handle special
cases, such as check for hypertransport msi mapping capability.

 

抱歉!评论已关闭.