source: bootcd/isolinux/syslinux-6.03/gpxe/src/drivers/infiniband/hermon.h

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 16.6 KB
RevLine 
[e16e8f2]1#ifndef _HERMON_H
2#define _HERMON_H
3
4/** @file
5 *
6 * Mellanox Hermon Infiniband HCA driver
7 *
8 */
9
10FILE_LICENCE ( GPL2_OR_LATER );
11
12#include <stdint.h>
13#include <gpxe/uaccess.h>
14#include <gpxe/ib_packet.h>
15#include "mlx_bitops.h"
16#include "MT25408_PRM.h"
17
18/*
19 * Hardware constants
20 *
21 */
22
23/* Ports in existence */
24#define HERMON_MAX_PORTS                2
25#define HERMON_PORT_BASE                1
26
27/* PCI BARs */
28#define HERMON_PCI_CONFIG_BAR           PCI_BASE_ADDRESS_0
29#define HERMON_PCI_CONFIG_BAR_SIZE      0x100000
30#define HERMON_PCI_UAR_BAR              PCI_BASE_ADDRESS_2
31
32/* Device reset */
33#define HERMON_RESET_OFFSET             0x0f0010
34#define HERMON_RESET_MAGIC              0x01000000UL
35#define HERMON_RESET_WAIT_TIME_MS       1000
36
37/* Work queue entry and completion queue entry opcodes */
38#define HERMON_OPCODE_NOP               0x00
39#define HERMON_OPCODE_SEND              0x0a
40#define HERMON_OPCODE_RECV_ERROR        0xfe
41#define HERMON_OPCODE_SEND_ERROR        0xff
42
43/* HCA command register opcodes */
44#define HERMON_HCR_QUERY_DEV_CAP        0x0003
45#define HERMON_HCR_QUERY_FW             0x0004
46#define HERMON_HCR_INIT_HCA             0x0007
47#define HERMON_HCR_CLOSE_HCA            0x0008
48#define HERMON_HCR_INIT_PORT            0x0009
49#define HERMON_HCR_CLOSE_PORT           0x000a
50#define HERMON_HCR_SW2HW_MPT            0x000d
51#define HERMON_HCR_WRITE_MTT            0x0011
52#define HERMON_HCR_MAP_EQ               0x0012
53#define HERMON_HCR_SW2HW_EQ             0x0013
54#define HERMON_HCR_HW2SW_EQ             0x0014
55#define HERMON_HCR_QUERY_EQ             0x0015
56#define HERMON_HCR_SW2HW_CQ             0x0016
57#define HERMON_HCR_HW2SW_CQ             0x0017
58#define HERMON_HCR_RST2INIT_QP          0x0019
59#define HERMON_HCR_INIT2RTR_QP          0x001a
60#define HERMON_HCR_RTR2RTS_QP           0x001b
61#define HERMON_HCR_RTS2RTS_QP           0x001c
62#define HERMON_HCR_2RST_QP              0x0021
63#define HERMON_HCR_QUERY_QP             0x0022
64#define HERMON_HCR_CONF_SPECIAL_QP      0x0023
65#define HERMON_HCR_MAD_IFC              0x0024
66#define HERMON_HCR_READ_MCG             0x0025
67#define HERMON_HCR_WRITE_MCG            0x0026
68#define HERMON_HCR_MGID_HASH            0x0027
69#define HERMON_HCR_SENSE_PORT           0x004d
70#define HERMON_HCR_RUN_FW               0x0ff6
71#define HERMON_HCR_DISABLE_LAM          0x0ff7
72#define HERMON_HCR_ENABLE_LAM           0x0ff8
73#define HERMON_HCR_UNMAP_ICM            0x0ff9
74#define HERMON_HCR_MAP_ICM              0x0ffa
75#define HERMON_HCR_UNMAP_ICM_AUX        0x0ffb
76#define HERMON_HCR_MAP_ICM_AUX          0x0ffc
77#define HERMON_HCR_SET_ICM_SIZE         0x0ffd
78#define HERMON_HCR_UNMAP_FA             0x0ffe
79#define HERMON_HCR_MAP_FA               0x0fff
80
81/* Service types */
82#define HERMON_ST_RC                    0x00
83#define HERMON_ST_UD                    0x03
84#define HERMON_ST_MLX                   0x07
85
86/* MTUs */
87#define HERMON_MTU_2048                 0x04
88
89#define HERMON_INVALID_LKEY             0x00000100UL
90
91#define HERMON_PAGE_SIZE                4096
92
93#define HERMON_DB_POST_SND_OFFSET       0x14
94#define HERMON_DB_EQ_OFFSET(_eqn)       \
95        ( 0x800 + HERMON_PAGE_SIZE * ( (_eqn) / 4 ) + 0x08 * ( (_eqn) % 4 ) )
96
97#define HERMON_QP_OPT_PARAM_PM_STATE    0x00000400UL
98#define HERMON_QP_OPT_PARAM_QKEY        0x00000020UL
99#define HERMON_QP_OPT_PARAM_ALT_PATH    0x00000001UL
100
101#define HERMON_MAP_EQ                   ( 0UL << 31 )
102#define HERMON_UNMAP_EQ                 ( 1UL << 31 )
103
104#define HERMON_EV_PORT_STATE_CHANGE     0x09
105
106#define HERMON_SCHED_QP0                0x3f
107#define HERMON_SCHED_DEFAULT            0x83
108
109#define HERMON_PM_STATE_ARMED           0x00
110#define HERMON_PM_STATE_REARM           0x01
111#define HERMON_PM_STATE_MIGRATED        0x03
112
113#define HERMON_RETRY_MAX                0x07
114
115/*
116 * Datatypes that seem to be missing from the autogenerated documentation
117 *
118 */
119struct hermonprm_mgm_hash_st {
120        pseudo_bit_t reserved0[0x00020];
121/* -------------- */
122        pseudo_bit_t hash[0x00010];
123        pseudo_bit_t reserved1[0x00010];
124} __attribute__ (( packed ));
125
126struct hermonprm_mcg_entry_st {
127        struct hermonprm_mcg_hdr_st hdr;
128        struct hermonprm_mcg_qp_dw_st qp[8];
129} __attribute__ (( packed ));
130
131struct hermonprm_cq_db_record_st {
132        pseudo_bit_t update_ci[0x00018];
133        pseudo_bit_t reserved0[0x00008];
134/* -------------- */
135        pseudo_bit_t arm_ci[0x00018];
136        pseudo_bit_t cmd[0x00003];
137        pseudo_bit_t reserved1[0x00001];
138        pseudo_bit_t cmd_sn[0x00002];
139        pseudo_bit_t reserved2[0x00002];
140} __attribute__ (( packed ));
141
142struct hermonprm_send_db_register_st {
143        pseudo_bit_t reserved[0x00008];
144        pseudo_bit_t qn[0x00018];
145} __attribute__ (( packed ));
146
147struct hermonprm_event_db_register_st {
148        pseudo_bit_t ci[0x00018];
149        pseudo_bit_t reserver[0x00007];
150        pseudo_bit_t a[0x00001];
151} __attribute__ (( packed ));
152
153struct hermonprm_scalar_parameter_st {
154        pseudo_bit_t value_hi[0x00020];
155/* -------------- */
156        pseudo_bit_t value[0x00020];
157} __attribute__ (( packed ));
158
159struct hermonprm_event_mask_st {
160        pseudo_bit_t reserved0[0x00020];
161/* -------------- */
162        pseudo_bit_t completion[0x00001];
163        pseudo_bit_t reserved1[0x0008];
164        pseudo_bit_t port_state_change[0x00001];
165        pseudo_bit_t reserved2[0x00016];
166} __attribute__ (( packed ));
167
168struct hermonprm_port_state_change_event_st {
169        pseudo_bit_t reserved[0x00020];
170        struct hermonprm_port_state_change_st data;
171} __attribute__ (( packed ));
172
173/** Hermon sense port */
174struct hermonprm_sense_port_st {
175        pseudo_bit_t port_type[0x00020];
176/* -------------- */
177        pseudo_bit_t reserved[0x00020];
178};
179#define HERMON_PORT_TYPE_IB             1
180
181/*
182 * Wrapper structures for hardware datatypes
183 *
184 */
185
186struct MLX_DECLARE_STRUCT ( hermonprm_completion_queue_context );
187struct MLX_DECLARE_STRUCT ( hermonprm_completion_queue_entry );
188struct MLX_DECLARE_STRUCT ( hermonprm_completion_with_error );
189struct MLX_DECLARE_STRUCT ( hermonprm_cq_db_record );
190struct MLX_DECLARE_STRUCT ( hermonprm_eqc );
191struct MLX_DECLARE_STRUCT ( hermonprm_event_db_register );
192struct MLX_DECLARE_STRUCT ( hermonprm_event_mask );
193struct MLX_DECLARE_STRUCT ( hermonprm_event_queue_entry );
194struct MLX_DECLARE_STRUCT ( hermonprm_hca_command_register );
195struct MLX_DECLARE_STRUCT ( hermonprm_init_hca );
196struct MLX_DECLARE_STRUCT ( hermonprm_init_port );
197struct MLX_DECLARE_STRUCT ( hermonprm_mad_ifc );
198struct MLX_DECLARE_STRUCT ( hermonprm_mcg_entry );
199struct MLX_DECLARE_STRUCT ( hermonprm_mgm_hash );
200struct MLX_DECLARE_STRUCT ( hermonprm_mpt );
201struct MLX_DECLARE_STRUCT ( hermonprm_mtt );
202struct MLX_DECLARE_STRUCT ( hermonprm_port_state_change_event );
203struct MLX_DECLARE_STRUCT ( hermonprm_qp_db_record );
204struct MLX_DECLARE_STRUCT ( hermonprm_qp_ee_state_transitions );
205struct MLX_DECLARE_STRUCT ( hermonprm_query_dev_cap );
206struct MLX_DECLARE_STRUCT ( hermonprm_query_fw );
207struct MLX_DECLARE_STRUCT ( hermonprm_queue_pair_ee_context_entry );
208struct MLX_DECLARE_STRUCT ( hermonprm_scalar_parameter );
209struct MLX_DECLARE_STRUCT ( hermonprm_sense_port );
210struct MLX_DECLARE_STRUCT ( hermonprm_send_db_register );
211struct MLX_DECLARE_STRUCT ( hermonprm_ud_address_vector );
212struct MLX_DECLARE_STRUCT ( hermonprm_virtual_physical_mapping );
213struct MLX_DECLARE_STRUCT ( hermonprm_wqe_segment_ctrl_mlx );
214struct MLX_DECLARE_STRUCT ( hermonprm_wqe_segment_ctrl_send );
215struct MLX_DECLARE_STRUCT ( hermonprm_wqe_segment_data_ptr );
216struct MLX_DECLARE_STRUCT ( hermonprm_wqe_segment_ud );
217
218/*
219 * Composite hardware datatypes
220 *
221 */
222
223struct hermonprm_write_mtt {
224        struct hermonprm_scalar_parameter mtt_base_addr;
225        struct hermonprm_scalar_parameter reserved;
226        struct hermonprm_mtt mtt;
227} __attribute__ (( packed ));
228
229#define HERMON_MAX_GATHER 2
230
231struct hermonprm_ud_send_wqe {
232        struct hermonprm_wqe_segment_ctrl_send ctrl;
233        struct hermonprm_wqe_segment_ud ud;
234        struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_GATHER];
235} __attribute__ (( packed ));
236
237struct hermonprm_mlx_send_wqe {
238        struct hermonprm_wqe_segment_ctrl_mlx ctrl;
239        struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_GATHER];
240        uint8_t headers[IB_MAX_HEADER_SIZE];
241} __attribute__ (( packed ));
242
243struct hermonprm_rc_send_wqe {
244        struct hermonprm_wqe_segment_ctrl_send ctrl;
245        struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_GATHER];
246} __attribute__ (( packed ));
247
248#define HERMON_MAX_SCATTER 1
249
250struct hermonprm_recv_wqe {
251        struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_SCATTER];
252} __attribute__ (( packed ));
253
254union hermonprm_completion_entry {
255        struct hermonprm_completion_queue_entry normal;
256        struct hermonprm_completion_with_error error;
257} __attribute__ (( packed ));
258
259union hermonprm_event_entry {
260        struct hermonprm_event_queue_entry generic;
261        struct hermonprm_port_state_change_event port_state_change;
262} __attribute__ (( packed ));
263
264union hermonprm_doorbell_register {
265        struct hermonprm_send_db_register send;
266        struct hermonprm_event_db_register event;
267        uint32_t dword[1];
268} __attribute__ (( packed ));
269
270union hermonprm_mad {
271        struct hermonprm_mad_ifc ifc;
272        union ib_mad mad;
273} __attribute__ (( packed ));
274
275/*
276 * gPXE-specific definitions
277 *
278 */
279
280/** Hermon device capabilitiess */
281struct hermon_dev_cap {
282        /** CMPT entry size */
283        size_t cmpt_entry_size;
284        /** Number of reserved QPs */
285        unsigned int reserved_qps;
286        /** QP context entry size */
287        size_t qpc_entry_size;
288        /** Alternate path context entry size */
289        size_t altc_entry_size;
290        /** Auxiliary context entry size */
291        size_t auxc_entry_size;
292        /** Number of reserved SRQs */
293        unsigned int reserved_srqs;
294        /** SRQ context entry size */
295        size_t srqc_entry_size;
296        /** Number of reserved CQs */
297        unsigned int reserved_cqs;
298        /** CQ context entry size */
299        size_t cqc_entry_size;
300        /** Number of reserved EQs */
301        unsigned int reserved_eqs;
302        /** EQ context entry size */
303        size_t eqc_entry_size;
304        /** Number of reserved MTTs */
305        unsigned int reserved_mtts;
306        /** MTT entry size */
307        size_t mtt_entry_size;
308        /** Number of reserved MRWs */
309        unsigned int reserved_mrws;
310        /** DMPT entry size */
311        size_t dmpt_entry_size;
312        /** Number of reserved UARs */
313        unsigned int reserved_uars;
314        /** Number of ports */
315        unsigned int num_ports;
316        /** Dual-port different protocol */
317        int dpdp;
318};
319
320/** Number of cMPT entries of each type */
321#define HERMON_CMPT_MAX_ENTRIES ( 1 << 24 )
322
323/** Hermon ICM memory map entry */
324struct hermon_icm_map {
325        /** Offset (virtual address within ICM) */
326        uint64_t offset;
327        /** Length */
328        size_t len;
329};
330
331/** Discontiguous regions within Hermon ICM */
332enum hermon_icm_map_regions {
333        HERMON_ICM_QP_CMPT = 0,
334        HERMON_ICM_SRQ_CMPT,
335        HERMON_ICM_CQ_CMPT,
336        HERMON_ICM_EQ_CMPT,
337        HERMON_ICM_OTHER,
338        HERMON_ICM_NUM_REGIONS
339};
340
341/** UAR page for doorbell accesses
342 *
343 * Pages 0-127 are reserved for event queue doorbells only, so we use
344 * page 128.
345 */
346#define HERMON_UAR_NON_EQ_PAGE  128
347
348/** Maximum number of allocatable MTT entries
349 *
350 * This is a policy decision, not a device limit.
351 */
352#define HERMON_MAX_MTTS         64
353
354/** A Hermon MTT descriptor */
355struct hermon_mtt {
356        /** MTT offset */
357        unsigned int mtt_offset;
358        /** Number of pages */
359        unsigned int num_pages;
360        /** MTT base address */
361        unsigned int mtt_base_addr;
362        /** Offset within page */
363        unsigned int page_offset;
364};
365
366/** Alignment of Hermon send work queue entries */
367#define HERMON_SEND_WQE_ALIGN 128
368
369/** A Hermon send work queue entry */
370union hermon_send_wqe {
371        struct hermonprm_wqe_segment_ctrl_send ctrl;
372        struct hermonprm_ud_send_wqe ud;
373        struct hermonprm_mlx_send_wqe mlx;
374        struct hermonprm_rc_send_wqe rc;
375        uint8_t force_align[HERMON_SEND_WQE_ALIGN];
376} __attribute__ (( packed ));
377
378/** A Hermon send work queue */
379struct hermon_send_work_queue {
380        /** Number of work queue entries, including headroom
381         *
382         * Hermon requires us to leave unused space within the send
383         * WQ, so we create a send WQ with more entries than are
384         * requested in the create_qp() call.
385         */
386        unsigned int num_wqes;
387        /** Work queue entries */
388        union hermon_send_wqe *wqe;
389        /** Size of work queue */
390        size_t wqe_size;
391        /** Doorbell register */
392        void *doorbell;
393};
394
395/** Alignment of Hermon receive work queue entries */
396#define HERMON_RECV_WQE_ALIGN 16
397
398/** A Hermon receive work queue entry */
399union hermon_recv_wqe {
400        struct hermonprm_recv_wqe recv;
401        uint8_t force_align[HERMON_RECV_WQE_ALIGN];
402} __attribute__ (( packed ));
403
404/** A Hermon receive work queue */
405struct hermon_recv_work_queue {
406        /** Work queue entries */
407        union hermon_recv_wqe *wqe;
408        /** Size of work queue */
409        size_t wqe_size;
410        /** Doorbell */
411        struct hermonprm_qp_db_record doorbell __attribute__ (( aligned (4) ));
412};
413
414/** Number of special queue pairs */
415#define HERMON_NUM_SPECIAL_QPS 8
416
417/** Number of queue pairs reserved for the "special QP" block
418 *
419 * The special QPs must be within a contiguous block aligned on its
420 * own size.
421 */
422#define HERMON_RSVD_SPECIAL_QPS ( ( HERMON_NUM_SPECIAL_QPS << 1 ) - 1 )
423
424/** Maximum number of allocatable queue pairs
425 *
426 * This is a policy decision, not a device limit.
427 */
428#define HERMON_MAX_QPS          8
429
430/** Queue pair number randomisation mask */
431#define HERMON_QPN_RANDOM_MASK 0xfff000
432
433/** Hermon queue pair state */
434enum hermon_queue_pair_state {
435        HERMON_QP_ST_RST = 0,
436        HERMON_QP_ST_INIT,
437        HERMON_QP_ST_RTR,
438        HERMON_QP_ST_RTS,
439};
440
441/** A Hermon queue pair */
442struct hermon_queue_pair {
443        /** Work queue buffer */
444        void *wqe;
445        /** Size of work queue buffer */
446        size_t wqe_size;
447        /** MTT descriptor */
448        struct hermon_mtt mtt;
449        /** Send work queue */
450        struct hermon_send_work_queue send;
451        /** Receive work queue */
452        struct hermon_recv_work_queue recv;
453        /** Queue state */
454        enum hermon_queue_pair_state state;
455};
456
457/** Maximum number of allocatable completion queues
458 *
459 * This is a policy decision, not a device limit.
460 */
461#define HERMON_MAX_CQS          8
462
463/** A Hermon completion queue */
464struct hermon_completion_queue {
465        /** Completion queue entries */
466        union hermonprm_completion_entry *cqe;
467        /** Size of completion queue */
468        size_t cqe_size;
469        /** MTT descriptor */
470        struct hermon_mtt mtt;
471        /** Doorbell */
472        struct hermonprm_cq_db_record doorbell __attribute__ (( aligned (8) ));
473};
474
475/** Maximum number of allocatable event queues
476 *
477 * This is a policy decision, not a device limit.
478 */
479#define HERMON_MAX_EQS          8
480
481/** A Hermon event queue */
482struct hermon_event_queue {
483        /** Event queue entries */
484        union hermonprm_event_entry *eqe;
485        /** Size of event queue */
486        size_t eqe_size;
487        /** MTT descriptor */
488        struct hermon_mtt mtt;
489        /** Event queue number */
490        unsigned long eqn;
491        /** Next event queue entry index */
492        unsigned long next_idx;
493        /** Doorbell register */
494        void *doorbell;
495};
496
497/** Number of event queue entries
498 *
499 * This is a policy decision.
500 */
501#define HERMON_NUM_EQES         4
502
503/** A Hermon resource bitmask */
504typedef uint32_t hermon_bitmask_t;
505
506/** Size of a hermon resource bitmask */
507#define HERMON_BITMASK_SIZE(max_entries)                                     \
508        ( ( (max_entries) + ( 8 * sizeof ( hermon_bitmask_t ) ) - 1 ) /      \
509          ( 8 * sizeof ( hermon_bitmask_t ) ) )
510
511/** A Hermon device */
512struct hermon {
513        /** PCI configuration registers */
514        void *config;
515        /** PCI user Access Region */
516        void *uar;
517
518        /** Command toggle */
519        unsigned int toggle;
520        /** Command input mailbox */
521        void *mailbox_in;
522        /** Command output mailbox */
523        void *mailbox_out;
524
525        /** Firmware area in external memory */
526        userptr_t firmware_area;
527        /** ICM map */
528        struct hermon_icm_map icm_map[HERMON_ICM_NUM_REGIONS];
529        /** ICM area */
530        userptr_t icm;
531
532        /** Event queue */
533        struct hermon_event_queue eq;
534        /** Unrestricted LKey
535         *
536         * Used to get unrestricted memory access.
537         */
538        unsigned long lkey;
539
540        /** Completion queue in-use bitmask */
541        hermon_bitmask_t cq_inuse[ HERMON_BITMASK_SIZE ( HERMON_MAX_CQS ) ];
542        /** Queue pair in-use bitmask */
543        hermon_bitmask_t qp_inuse[ HERMON_BITMASK_SIZE ( HERMON_MAX_QPS ) ];
544        /** MTT entry in-use bitmask */
545        hermon_bitmask_t mtt_inuse[ HERMON_BITMASK_SIZE ( HERMON_MAX_MTTS ) ];
546
547        /** Device capabilities */
548        struct hermon_dev_cap cap;
549        /** Special QPN base */
550        unsigned long special_qpn_base;
551        /** QPN base */
552        unsigned long qpn_base;
553
554        /** Infiniband devices */
555        struct ib_device *ibdev[HERMON_MAX_PORTS];
556};
557
558/** Global protection domain */
559#define HERMON_GLOBAL_PD                0x123456
560
561/** Memory key prefix */
562#define HERMON_MKEY_PREFIX              0x77000000UL
563
564/*
565 * HCA commands
566 *
567 */
568
569#define HERMON_HCR_BASE                 0x80680
570#define HERMON_HCR_REG(x)               ( HERMON_HCR_BASE + 4 * (x) )
571#define HERMON_HCR_MAX_WAIT_MS          2000
572#define HERMON_MBOX_ALIGN               4096
573#define HERMON_MBOX_SIZE                512
574
575/* HCA command is split into
576 *
577 * bits  11:0   Opcode
578 * bit     12   Input uses mailbox
579 * bit     13   Output uses mailbox
580 * bits 22:14   Input parameter length (in dwords)
581 * bits 31:23   Output parameter length (in dwords)
582 *
583 * Encoding the information in this way allows us to cut out several
584 * parameters to the hermon_command() call.
585 */
586#define HERMON_HCR_IN_MBOX              0x00001000UL
587#define HERMON_HCR_OUT_MBOX             0x00002000UL
588#define HERMON_HCR_OPCODE( _command )   ( (_command) & 0xfff )
589#define HERMON_HCR_IN_LEN( _command )   ( ( (_command) >> 12 ) & 0x7fc )
590#define HERMON_HCR_OUT_LEN( _command )  ( ( (_command) >> 21 ) & 0x7fc )
591
592/** Build HCR command from component parts */
593#define HERMON_HCR_INOUT_CMD( _opcode, _in_mbox, _in_len,                    \
594                             _out_mbox, _out_len )                           \
595        ( (_opcode) |                                                        \
596          ( (_in_mbox) ? HERMON_HCR_IN_MBOX : 0 ) |                          \
597          ( ( (_in_len) / 4 ) << 14 ) |                                      \
598          ( (_out_mbox) ? HERMON_HCR_OUT_MBOX : 0 ) |                        \
599          ( ( (_out_len) / 4 ) << 23 ) )
600
601#define HERMON_HCR_IN_CMD( _opcode, _in_mbox, _in_len )                      \
602        HERMON_HCR_INOUT_CMD ( _opcode, _in_mbox, _in_len, 0, 0 )
603
604#define HERMON_HCR_OUT_CMD( _opcode, _out_mbox, _out_len )                   \
605        HERMON_HCR_INOUT_CMD ( _opcode, 0, 0, _out_mbox, _out_len )
606
607#define HERMON_HCR_VOID_CMD( _opcode )                                       \
608        HERMON_HCR_INOUT_CMD ( _opcode, 0, 0, 0, 0 )
609
610#endif /* _HERMON_H */
Note: See TracBrowser for help on using the repository browser.