Solaris Source Insight: PCI bus driver moduls - npe Part 5

本文介绍了DDI中断处理机制,包括支持的中断操作类型、中断处理结构体定义、以及如何分配和管理中断资源等内容。

  • Fri Nov 13 14:19:32 CST 2009

  • DDI_INTROP_NAVAIL/DDI_INTROP_NINTRS

Return the number of supported interrupt number. If MSI/X supported, the responding capability registers will tell the number. Otherwise, the interrupt number was saved in parent private data of devinfo node.

 

[i86pc/os/ddi_impl.c]

925 int

926 i_ddi_get_intx_nintrs(dev_info_t *dip)

927 {

928 |_______struct ddi_parent_private_data *pdp;

929

930 |_______if ((pdp = ddi_get_parent_data(dip)) == NULL)

931 |_______|_______return (0);

932

933 |_______return (pdp->par_nintr);

934 }

 

Let's roll back to check what kind of things passed to npe_intr_ops().

 

[i86pc/io/pciex/npe.c]

829 /*

830 * npe_intr_ops

831 */

832 static int

833 npe_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,

834 ddi_intr_handle_impl_t *hdlp, void *result)

835 {

836 |_______return (pci_common_intr_ops(pdip, rdip, intr_op, hdlp, result));

837 }

 

pdip – the bus devinfo node

rdip – the leaf devinfo node which issued the request

intr_op – interrupt ops, following operations supported

 

[common/sys/ddi_intr_impl.h]

42 /*

43 * Typedef for interrupt ops

44 */

45 typedef enum {

46 |_______DDI_INTROP_SUPPORTED_TYPES = 1,|/* 1 get supported interrupts types */

47 |_______DDI_INTROP_NINTRS,|_____|_______/* 2 get num of interrupts supported */

48 |_______DDI_INTROP_ALLOC,|______|_______/* 3 allocate interrupt handle */

49 |_______DDI_INTROP_GETPRI,|_____|_______/* 4 get priority */

50 |_______DDI_INTROP_SETPRI,|_____|_______/* 5 set priority */

51 |_______DDI_INTROP_ADDISR,|_____|_______/* 6 add interrupt handler */

52 |_______DDI_INTROP_DUPVEC,|_____|_______/* 7 duplicate interrupt handler */

53 |_______DDI_INTROP_ENABLE,|_____|_______/* 8 enable interrupt */

54 |_______DDI_INTROP_BLOCKENABLE,||_______/* 9 block enable interrupts */

55 |_______DDI_INTROP_BLOCKDISABLE,|_______/* 10 block disable interrupts */

56 |_______DDI_INTROP_DISABLE,|____|_______/* 11 disable interrupt */

57 |_______DDI_INTROP_REMISR,|_____|_______/* 12 remove interrupt handler */

58 |_______DDI_INTROP_FREE,|_______|_______/* 13 free interrupt handle */

59 |_______DDI_INTROP_GETCAP,|_____|_______/* 14 get capacity */

60 |_______DDI_INTROP_SETCAP,|_____|_______/* 15 set capacity */

61 |_______DDI_INTROP_SETMASK,|____|_______/* 16 set mask */

62 |_______DDI_INTROP_CLRMASK,|____|_______/* 17 clear mask */

63 |_______DDI_INTROP_GETPENDING,|_|_______/* 18 get pending interrupt */

64 |_______DDI_INTROP_NAVAIL,|_____|_______/* 19 get num of available interrupts */

65 |_______DDI_INTROP_GETPOOL,|____|_______/* 20 get resource management pool */

66 |_______DDI_INTROP_GETTARGET,|__|_______/* 21 get target for a given intr(s) */

67 |_______DDI_INTROP_SETTARGET|___|_______/* 22 set target for a given intr(s) */

68 } ddi_intr_op_t;

 

hdlp – the implementation structure for DDI interrupt handling

result – the returned result data

 

[common/sys/ddi_intr_impl.h]

74 /*

75 * One such data structure is allocated per ddi_intr_handle_t

76 * This is the incore copy of the regular interrupt info.

77 */

78 typedef struct ddi_intr_handle_impl {

79 |_______dev_info_t|_____|_______*ih_dip;|_______/* dip associated with handle */

80 |_______uint16_t|_______|_______ih_type;|_______/* interrupt type being used */

81 |_______ushort_t|_______|_______ih_inum;|_______/* interrupt number */

82 |_______uint32_t|_______|_______ih_vector;|_____/* vector number */

83 |_______uint16_t|_______|_______ih_ver;||_______/* Version */

84 |_______uint_t|_|_______|_______ih_state;|______/* interrupt handle state */

85 |_______uint_t|_|_______|_______ih_cap;||_______/* interrupt capabilities */

86 |_______uint_t|_|_______|_______ih_pri;||_______/* priority - bus dependent */

87 |_______krwlock_t|______|_______ih_rwlock;|_____/* read/write lock per handle */

… …

125 } ddi_intr_handle_impl_t;

 

This structure will be passed through different functions for DDI interrupt handling. Type, inum, vector are basic to understand the implementation. Specific interrupts are always specified by the combination of interrupt type and inum. For legacy devices, inum refers to the nth interrupt, typically as defined by the devices interrupts property. For PCI fixed interrupts, inum refers to the interrupt number. The inum is the relative interrupt vector number, from 0 to 31 for MSI, from 0 to 2047 for MSI-X. The first interrupt vector is 0. The last relative vector is 31 for MSI or 2047 for MSI-X. Three interrupt types are defined in Solaris DDI.

 

[common/sys/ddi_intr.h]

61 /* Hardware interrupt types */

62 #define|DDI_INTR_TYPE_FIXED|____0x1

63 #define|DDI_INTR_TYPE_MSI|______0x2

64 #define|DDI_INTR_TYPE_MSIX|_____0x4

 

The second piece of interrupt data is stored as ddi parent private data. It's created for both fixed interrupt and MSI/X interrupt types.

 

[i86pc/io/pci/pci_common.c]

134 /*

135 * Create the ddi_parent_private_data for a pseudo child.

136 */

137 void

138 pci_common_set_parent_private_data(dev_info_t *dip)

139 {

140 |_______struct ddi_parent_private_data *pdptr;

141

142 |_______pdptr = (struct ddi_parent_private_data *)kmem_zalloc(

143 |_______ (sizeof (struct ddi_parent_private_data) +

144 |_______ sizeof (struct intrspec)), KM_SLEEP);

145 |_______pdptr->par_intr = (struct intrspec *)(pdptr + 1);

146 |_______pdptr->par_nintr = 1;

147 |_______ddi_set_parent_data(dip, pdptr);

148 }

 

[common/sys/ddi_impldefs.h]

735 /*

736 * parent private data structure contains register, interrupt, property

737 * and range information.

738 */

739 struct ddi_parent_private_data {

740 |_______int par_nreg;|__|_______|_______/* number of regs */

741 |_______struct regspec *par_reg;|_______/* array of regs */

742 |_______int par_nintr;|_|_______|_______/* number of interrupts */

743 |_______struct intrspec *par_intr;|_____/* array of possible interrupts */

744 |_______int par_nrng;|__|_______|_______/* number of ranges */

745 |_______struct rangespec *par_rng;|_____/* array of ranges */

746 };

747 #define|DEVI_PD(d)|_____/

748 |_______((struct ddi_parent_private_data *)DEVI((d))->devi_parent_data)

 

[common/sys/ddi_intr_impl.h]

390 /*

391 * This structure represents one interrupt possible from the given

392 * device. It is used in an array for devices with multiple interrupts.

393 */

394 struct intrspec {

395 |_______uint_t intrspec_pri;|___|_______/* interrupt priority */

396 |_______uint_t intrspec_vec;|___|_______/* vector # (0 if none) */

397 |_______uint_t (*intrspec_func)();|_____/* function to call for interrupt, */

398 |_______|_______|_______|_______|_______/* If (uint_t (*)()) 0, none. */

399 |_______|_______|_______|_______|_______/* If (uint_t (*)()) 1, then */

400 };

 

The third piece of data related to ddi interrupt is stored in devinfo structure.

 

126 struct dev_info {

...

237 |_______/* Owned by DDI interrupt framework */

238 |_______devinfo_intr_t|_*devi_intr_p;

… …

276 };

 

[common/sys/ddi_intr_impl.h]

273 /*

274 * One such data structure is allocated for each dip.

275 * It has interrupt related information that can be

276 * stored/retrieved for convenience.

277 */

278 typedef struct devinfo_intr {

279 |_______/* These three fields show what the device is capable of */

280 |_______uint_t|_|_______devi_intr_sup_types;|___/* Intrs supported by device */

281

282 |_______ddi_intr_msix_t|*devi_msix_p;|__|_______/* MSI-X info, if supported */

283

284 |_______/* Next three fields show current status for the device */

285 |_______uint_t|_|_______devi_intr_curr_type;|___/* Interrupt type being used */

286 |_______uint_t|_|_______devi_intr_sup_nintrs;|__/* #intr supported */

287 |_______uint_t|_|_______devi_intr_curr_nintrs;|_/* #intr currently being used */

288 |_______/*

289 |_______ * #intr currently being enabled

290 |_______ * (for MSI block enable, the valuse is either 1 or 0.)

291 |_______ */

292 |_______uint_t|_|_______devi_intr_curr_nenables;

293

294 |_______ddi_intr_handle_t *devi_intr_handle_p;|_/* Hdl for legacy intr APIs */

295

296 #if defined(__i386) || defined(__amd64)

297 |_______/* Save the PCI config space handle */

298 |_______ddi_acc_handle_t devi_cfg_handle;

299 |_______int|____|_______ devi_cap_ptr;|_|_______/* MSI or MSI-X cap pointer */

300 #endif

301

302 |_______ddi_irm_req_t|__*devi_irm_req_p;|_______/* IRM request information */

303 } devinfo_intr_t;

 

  • DDI_INTROP_ALLOC/DDI_INTROP_FREE

Allocate and free the interrupt vectors. Allocate interrupts of the interrupt type beginning at the interrupt number inum. ddi_intr_alloc(9F) will call this function for purpose. If MSI/X is supported, the actual operation is accomplished through psm_intr_ops() which is specified in psm module.

 

[i86pc/io/pci/pci_common.c]

359 |_______|_______|_______/*

360 |_______|_______|_______ * Allocate interrupt vectors

361 |_______|_______|_______ */

362 |_______|_______|_______(void) (*psm_intr_ops)(rdip, hdlp,

363 |_______|_______|_______ PSM_INTR_OP_ALLOC_VECTORS, result);

 

  • DDI_INTROP_GETPRI/DDI_INTROP_SETPRI

Interrupt priority is stored at DEVI(dip)->devi_parent_data->par_intr->intrspec_pri. To set/change the interrupt priority, platform level psm_intr_ops() must be called. Two broad classes of interrupt: High-level and normal interrupts are defined. Most interrupts on the system are normal interrupts. Seldom must a device be configured to a high-level interrupt .

 

[i86pc/io/pci/pci_common.c]

459 |_______case DDI_INTROP_SETPRI:

460 |_______|_______/* Validate the interrupt priority passed */

461 |_______|_______if (*(int *)result > LOCK_LEVEL)

462 |_______|_______|_______return (DDI_FAILURE);

 

High-level interrupts are handled much like traditional UNIX interrupts . A high-level interrupt has no process or thread context of its own . A high-level interrupt may not block for any reason . A high-level ISR may only call mutex_enter(9F), the associated mutex_exit(9F), and ddi_trigger_softintr(9F)

  • DDI_INTROP_ADDISR/DDI_INTROP_REMISR

    Add and remove ispec.

  • DDI_INTROP_GETCAP/DDI_INTROP_SETCAP

  • DDI_INTROP_ENABLE/DDI_INTROP_DISABLE

  • DDI_INTROP_BLOCKDISABLE/DDI_INTROP_BLOCKENABLE

    Rely on pcplusmp psm_intr_ops().

 

To be continued …

潮汐研究作为海洋科学的关键分支,融合了物理海洋学、地理信息系统及水利工程等多领域知识。TMD2.05.zip是一套基于MATLAB环境开发的潮汐专用分析工具集,为科研人员与工程实践者提供系统化的潮汐建模与计算支持。该工具箱通过模块化设计实现了两大核心功能: 在交互界面设计方面,工具箱构建了图形化操作环境,有效降低了非专业用户的操作门槛。通过预设参数输入模块(涵盖地理坐标、时间序列、测站数据等),用户可自主配置模型运行条件。界面集成数据加载、参数调整、可视化呈现及流程控制等标准化组件,将复杂的数值运算过程转化为可交互的操作流程。 在潮汐预测模块中,工具箱整合了谐波分解法与潮流要素解析法等数学模型。这些算法能够解构潮汐观测数据,识别关键影响要素(包括K1、O1、M2等核心分潮),并生成不同时间尺度的潮汐预报。基于这些模型,研究者可精准推算特定海域的潮位变化周期与振幅特征,为海洋工程建设、港湾规划设计及海洋生态研究提供定量依据。 该工具集在实践中的应用方向包括: - **潮汐动力解析**:通过多站点观测数据比对,揭示区域主导潮汐成分的时空分布规律 - **数值模型构建**:基于历史观测序列建立潮汐动力学模型,实现潮汐现象的数字化重构与预测 - **工程影响量化**:在海岸开发项目中评估人工构筑物对自然潮汐节律的扰动效应 - **极端事件模拟**:建立风暴潮与天文潮耦合模型,提升海洋灾害预警的时空精度 工具箱以"TMD"为主程序包,内含完整的函数库与示例脚本。用户部署后可通过MATLAB平台调用相关模块,参照技术文档完成全流程操作。这套工具集将专业计算能力与人性化操作界面有机结合,形成了从数据输入到成果输出的完整研究链条,显著提升了潮汐研究的工程适用性与科研效率。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值