2 * Copyright (c) 2017 Broadcom. All rights reserved.
3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
34 * Implementation of common BSD OS abstraction functions
39 static MALLOC_DEFINE(M_OCS, "OCS", "OneCore Storage data");
41 #include <dev/pci/pcireg.h>
42 #include <dev/pci/pcivar.h>
44 #include <machine/bus.h>
46 callout_func_t __ocs_callout;
49 ocs_config_read32(ocs_os_handle_t os, uint32_t reg)
51 return pci_read_config(os->dev, reg, 4);
55 ocs_config_read16(ocs_os_handle_t os, uint32_t reg)
57 return pci_read_config(os->dev, reg, 2);
61 ocs_config_read8(ocs_os_handle_t os, uint32_t reg)
63 return pci_read_config(os->dev, reg, 1);
67 ocs_config_write8(ocs_os_handle_t os, uint32_t reg, uint8_t val)
69 return pci_write_config(os->dev, reg, val, 1);
73 ocs_config_write16(ocs_os_handle_t os, uint32_t reg, uint16_t val)
75 return pci_write_config(os->dev, reg, val, 2);
79 ocs_config_write32(ocs_os_handle_t os, uint32_t reg, uint32_t val)
81 return pci_write_config(os->dev, reg, val, 4);
86 * @brief Read a 32bit PCI register
88 * The SLI documentation uses the term "register set" to describe one or more
89 * PCI BARs which form a logical address. For example, a 64-bit address uses
90 * two BARs, and thus constitute a register set.
92 * @param ocs Pointer to the driver's context
93 * @param rset Register Set to use
94 * @param off Offset from the base address of the Register Set
96 * @return register value
99 ocs_reg_read32(ocs_t *ocs, uint32_t rset, uint32_t off)
101 ocs_pci_reg_t *reg = NULL;
103 reg = &ocs->reg[rset];
105 return bus_space_read_4(reg->btag, reg->bhandle, off);
110 * @brief Read a 16bit PCI register
112 * The SLI documentation uses the term "register set" to describe one or more
113 * PCI BARs which form a logical address. For example, a 64-bit address uses
114 * two BARs, and thus constitute a register set.
116 * @param ocs Pointer to the driver's context
117 * @param rset Register Set to use
118 * @param off Offset from the base address of the Register Set
120 * @return register value
123 ocs_reg_read16(ocs_t *ocs, uint32_t rset, uint32_t off)
125 ocs_pci_reg_t *reg = NULL;
127 reg = &ocs->reg[rset];
129 return bus_space_read_2(reg->btag, reg->bhandle, off);
134 * @brief Read a 8bit PCI register
136 * The SLI documentation uses the term "register set" to describe one or more
137 * PCI BARs which form a logical address. For example, a 64-bit address uses
138 * two BARs, and thus constitute a register set.
140 * @param ocs Pointer to the driver's context
141 * @param rset Register Set to use
142 * @param off Offset from the base address of the Register Set
144 * @return register value
147 ocs_reg_read8(ocs_t *ocs, uint32_t rset, uint32_t off)
149 ocs_pci_reg_t *reg = NULL;
151 reg = &ocs->reg[rset];
153 return bus_space_read_1(reg->btag, reg->bhandle, off);
158 * @brief Write a 32bit PCI register
160 * The SLI documentation uses the term "register set" to describe one or more
161 * PCI BARs which form a logical address. For example, a 64-bit address uses
162 * two BARs, and thus constitute a register set.
164 * @param ocs Pointer to the driver's context
165 * @param rset Register Set to use
166 * @param off Offset from the base address of the Register Set
167 * @param val Value to write
172 ocs_reg_write32(ocs_t *ocs, uint32_t rset, uint32_t off, uint32_t val)
174 ocs_pci_reg_t *reg = NULL;
176 reg = &ocs->reg[rset];
178 return bus_space_write_4(reg->btag, reg->bhandle, off, val);
183 * @brief Write a 16-bit PCI register
185 * The SLI documentation uses the term "register set" to describe one or more
186 * PCI BARs which form a logical address. For example, a 64-bit address uses
187 * two BARs, and thus constitute a register set.
189 * @param ocs Pointer to the driver's context
190 * @param rset Register Set to use
191 * @param off Offset from the base address of the Register Set
192 * @param val Value to write
197 ocs_reg_write16(ocs_t *ocs, uint32_t rset, uint32_t off, uint16_t val)
199 ocs_pci_reg_t *reg = NULL;
201 reg = &ocs->reg[rset];
203 return bus_space_write_2(reg->btag, reg->bhandle, off, val);
208 * @brief Write a 8-bit PCI register
210 * The SLI documentation uses the term "register set" to describe one or more
211 * PCI BARs which form a logical address. For example, a 64-bit address uses
212 * two BARs, and thus constitute a register set.
214 * @param ocs Pointer to the driver's context
215 * @param rset Register Set to use
216 * @param off Offset from the base address of the Register Set
217 * @param val Value to write
222 ocs_reg_write8(ocs_t *ocs, uint32_t rset, uint32_t off, uint8_t val)
224 ocs_pci_reg_t *reg = NULL;
226 reg = &ocs->reg[rset];
228 return bus_space_write_1(reg->btag, reg->bhandle, off, val);
233 * @brief Allocate host memory
235 * @param os OS handle
236 * @param size number of bytes to allocate
237 * @param flags additional options
239 * @return pointer to allocated memory, NULL otherwise
242 ocs_malloc(ocs_os_handle_t os, size_t size, int32_t flags)
244 if ((flags & OCS_M_NOWAIT) == 0) {
248 #ifndef OCS_DEBUG_MEMORY
249 return malloc(size, M_OCS, flags);
253 void *addr = malloc(size, M_OCS, flags);
255 linker_ddb_search_symbol_name(__builtin_return_address(1), nameb, sizeof(nameb), &offset);
256 printf("A: %p %ld @ %s+%#lx\n", addr, size, nameb, offset);
264 * @brief Free host memory
266 * @param os OS handle
267 * @param addr pointer to memory
268 * @param size bytes to free
270 * @note size ignored in BSD
273 ocs_free(ocs_os_handle_t os, void *addr, size_t size)
275 #ifndef OCS_DEBUG_MEMORY
278 printf("F: %p %ld\n", addr, size);
284 * @brief Callback function provided to bus_dmamap_load
286 * Function loads the physical / bus address into the DMA descriptor. The caller
287 * can detect a mapping failure if a descriptor's phys element is zero.
289 * @param arg Argument provided to bus_dmamap_load is a ocs_dma_t
290 * @param seg Array of DMA segment(s), each describing segment's address and length
291 * @param nseg Number of elements in array
292 * @param error Indicates success (0) or failure of mapping
295 ocs_dma_load(void *arg, bus_dma_segment_t *seg, int nseg, int error)
297 ocs_dma_t *dma = arg;
300 printf("%s: error=%d\n", __func__, error);
303 dma->phys = seg->ds_addr;
309 * @brief Free a DMA capable block of memory
311 * @param os Device abstraction
312 * @param dma DMA descriptor for memory to be freed
314 * @return 0 if memory is de-allocated, -1 otherwise
317 ocs_dma_free(ocs_os_handle_t os, ocs_dma_t *dma)
319 struct ocs_softc *ocs = os;
322 device_printf(ocs->dev, "%s: bad parameter(s) dma=%p\n", __func__, dma);
326 if (dma->size == 0) {
331 bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_POSTREAD |
332 BUS_DMASYNC_POSTWRITE);
333 bus_dmamap_unload(dma->tag, dma->map);
337 bus_dmamem_free(dma->tag, dma->virt, dma->map);
338 bus_dmamap_destroy(dma->tag, dma->map);
340 bus_dma_tag_destroy(dma->tag);
342 bzero(dma, sizeof(ocs_dma_t));
349 * @brief Allocate a DMA capable block of memory
351 * @param os Device abstraction
352 * @param dma DMA descriptor containing results of memory allocation
353 * @param size Size in bytes of desired allocation
354 * @param align Alignment in bytes
356 * @return 0 on success, ENOMEM otherwise
359 ocs_dma_alloc(ocs_os_handle_t os, ocs_dma_t *dma, size_t size, size_t align)
361 struct ocs_softc *ocs = os;
364 device_printf(ocs->dev, "%s bad parameter(s) dma=%p size=%zd\n",
365 __func__, dma, size);
369 bzero(dma, sizeof(ocs_dma_t));
371 /* create a "tag" that describes the desired memory allocation */
372 if (bus_dma_tag_create(ocs->dmat, align, 0, BUS_SPACE_MAXADDR,
373 BUS_SPACE_MAXADDR, NULL, NULL,
374 size, 1, size, 0, NULL, NULL, &dma->tag)) {
375 device_printf(ocs->dev, "DMA tag allocation failed\n");
381 /* allocate the memory */
382 if (bus_dmamem_alloc(dma->tag, &dma->virt, BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
384 device_printf(ocs->dev, "DMA memory allocation failed s=%zd a=%zd\n", size, align);
385 ocs_dma_free(ocs, dma);
389 dma->alloc = dma->virt;
391 /* map virtual address to device visible address */
392 if (bus_dmamap_load(dma->tag, dma->map, dma->virt, dma->size, ocs_dma_load,
394 device_printf(ocs->dev, "DMA memory load failed\n");
395 ocs_dma_free(ocs, dma);
399 /* if the DMA map load callback fails, it sets the physical address to zero */
400 if (0 == dma->phys) {
401 device_printf(ocs->dev, "ocs_dma_load failed\n");
402 ocs_dma_free(ocs, dma);
411 * @brief Synchronize the DMA buffer memory
413 * Ensures memory coherency between the CPU and device
415 * @param dma DMA descriptor of memory to synchronize
416 * @param flags Describes direction of synchronization
417 * See BUS_DMA(9) for details
418 * - BUS_DMASYNC_PREWRITE
419 * - BUS_DMASYNC_POSTREAD
422 ocs_dma_sync(ocs_dma_t *dma, uint32_t flags)
424 bus_dmamap_sync(dma->tag, dma->map, flags);
428 ocs_dma_copy_in(ocs_dma_t *dma, void *buffer, uint32_t buffer_length)
434 if (buffer_length == 0)
436 if (buffer_length > dma->size)
437 buffer_length = dma->size;
438 ocs_memcpy(dma->virt, buffer, buffer_length);
439 dma->len = buffer_length;
440 return buffer_length;
444 ocs_dma_copy_out(ocs_dma_t *dma, void *buffer, uint32_t buffer_length)
450 if (buffer_length == 0)
452 if (buffer_length > dma->len)
453 buffer_length = dma->len;
454 ocs_memcpy(buffer, dma->virt, buffer_length);
455 return buffer_length;
460 * @brief Initialize a lock
462 * @param lock lock to initialize
463 * @param name string identifier for the lock
466 ocs_lock_init(void *os, ocs_lock_t *lock, const char *name, ...)
471 ocs_vsnprintf(lock->name, MAX_LOCK_DESC_LEN, name, ap);
474 mtx_init(&lock->lock, lock->name, NULL, MTX_DEF);
478 * @brief Allocate a bit map
480 * For BSD, this is a simple character string
482 * @param n_bits number of bits in bit map
484 * @return pointer to the bit map, NULL on error
487 ocs_bitmap_alloc(uint32_t n_bits)
490 return malloc(bitstr_size(n_bits), M_OCS, M_ZERO | M_NOWAIT);
494 * @brief Free a bit map
496 * @param bitmap pointer to previously allocated bit map
499 ocs_bitmap_free(ocs_bitmap_t *bitmap)
506 * @brief find next unset bit and set it
508 * @param bitmap bit map to search
509 * @param n_bits number of bits in map
511 * @return bit position or -1 if map is full
514 ocs_bitmap_find(ocs_bitmap_t *bitmap, uint32_t n_bits)
516 int32_t position = -1;
518 bit_ffc(bitmap, n_bits, &position);
520 if (-1 != position) {
521 bit_set(bitmap, position);
528 * @brief search for next (un)set bit
530 * @param bitmap bit map to search
531 * @param set search for a set or unset bit
532 * @param n_bits number of bits in map
534 * @return bit position or -1
537 ocs_bitmap_search(ocs_bitmap_t *bitmap, uint8_t set, uint32_t n_bits)
546 bit_ffs(bitmap, n_bits, &position);
548 bit_ffc(bitmap, n_bits, &position);
555 * @brief clear the specified bit
557 * @param bitmap pointer to bit map
558 * @param bit bit number to clear
561 ocs_bitmap_clear(ocs_bitmap_t *bitmap, uint32_t bit)
563 bit_clear(bitmap, bit);
566 void _ocs_log(ocs_t *ocs, const char *func_name, int line, const char *fmt, ...)
574 /* TODO: Add Current PID info here. */
576 p += snprintf(p, sizeof(buf) - (p - buf), "%s: ", DRV_NAME);
577 p += snprintf(p, sizeof(buf) - (p - buf), "%s:", func_name);
578 p += snprintf(p, sizeof(buf) - (p - buf), "%i:", line);
579 p += snprintf(p, sizeof(buf) - (p - buf), "%s:", (ocs != NULL) ? device_get_nameunit(ocs->dev) : "");
580 p += vsnprintf(p, sizeof(buf) - (p - buf), fmt, ap);
588 * @brief Common thread call function
590 * This is the common function called whenever a thread instantiated by ocs_thread_create() is started.
591 * It captures the return value from the actual thread function and stashes it in the thread object, to
592 * be later retrieved by ocs_thread_get_retval(), and calls kthread_exit(), the proscribed method to terminate
595 * @param arg a pointer to the thread object
601 ocs_thread_call_fctn(void *arg)
603 ocs_thread_t *thread = arg;
604 thread->retval = (*thread->fctn)(thread->arg);
605 ocs_free(NULL, thread->name, ocs_strlen(thread->name+1));
610 * @brief Create a kernel thread
612 * Creates a kernel thread and optionally starts it. If the thread is not immediately
613 * started, ocs_thread_start() should be called at some later point.
615 * @param os OS handle
616 * @param thread pointer to thread object
617 * @param fctn function for thread to be begin executing
618 * @param name text name to identify thread
619 * @param arg application specific argument passed to thread function
620 * @param start start option, OCS_THREAD_RUN will start the thread immediately,
621 * OCS_THREAD_CREATE will create but not start the thread
623 * @return returns 0 for success, a negative error code value for failure.
627 ocs_thread_create(ocs_os_handle_t os, ocs_thread_t *thread, ocs_thread_fctn fctn, const char *name, void *arg, ocs_thread_start_e start)
631 ocs_memset(thread, 0, sizeof(*thread));
634 thread->name = ocs_strdup(name);
635 if (thread->name == NULL) {
636 thread->name = "unknown";
640 ocs_atomic_set(&thread->terminate, 0);
642 rc = kthread_add(ocs_thread_call_fctn, thread, NULL, &thread->tcb, (start == OCS_THREAD_CREATE) ? RFSTOPPED : 0,
643 OCS_THREAD_DEFAULT_STACK_SIZE_PAGES, "%s", name);
649 * @brief Start a thread
651 * Starts a thread that was created with OCS_THREAD_CREATE rather than OCS_THREAD_RUN
653 * @param thread pointer to thread object
655 * @return returns 0 for success, a negative error code value for failure.
658 int32_t ocs_thread_start(ocs_thread_t *thread)
661 thread_lock(thread->tcb);
662 sched_add(thread->tcb, SRQ_BORING);
667 * @brief return thread argument
669 * Returns a pointer to the thread's application specific argument
671 * @param mythread pointer to the thread object
673 * @return pointer to application specific argument
676 void *ocs_thread_get_arg(ocs_thread_t *mythread)
678 return mythread->arg;
682 * @brief Request thread stop
684 * A stop request is made to the thread. This is a voluntary call, the thread needs
685 * to periodically query its terminate request using ocs_thread_terminate_requested()
687 * @param thread pointer to thread object
689 * @return returns 0 for success, a negative error code value for failure.
693 ocs_thread_terminate(ocs_thread_t *thread)
695 ocs_atomic_set(&thread->terminate, 1);
700 * @brief See if a terminate request has been made
702 * Check to see if a stop request has been made to the current thread. This
703 * function would be used by a thread to see if it should terminate.
705 * @return returns non-zero if a stop has been requested
708 int32_t ocs_thread_terminate_requested(ocs_thread_t *thread)
710 return ocs_atomic_read(&thread->terminate);
714 * @brief Retrieve threads return value
716 * After a thread has terminated, it's return value may be retrieved with this function.
718 * @param thread pointer to thread object
720 * @return return value from thread function
724 ocs_thread_get_retval(ocs_thread_t *thread)
726 return thread->retval;
730 * @brief Request that the currently running thread yield
732 * The currently running thread yields to the scheduler
734 * @param thread pointer to thread (ignored)
740 ocs_thread_yield(ocs_thread_t *thread) {
741 pause("thread yield", 1);
745 ocs_thread_self(void)
747 ocs_printf(">>> %s not implemented\n", __func__);
752 ocs_thread_setcpu(ocs_thread_t *thread, uint32_t cpu)
754 ocs_printf(">>> %s not implemented\n", __func__);
759 ocs_thread_getcpu(void)
765 ocs_sem_init(ocs_sem_t *sem, int val, const char *name, ...)
770 ocs_vsnprintf(sem->name, sizeof(sem->name), name, ap);
773 sema_init(&sem->sem, val, sem->name);
779 * @brief Copy user arguments in to kernel space for an ioctl
781 * This function is called at the beginning of an ioctl function
782 * to copy the ioctl argument from user space to kernel space.
784 * BSD handles this for us - arg is already in kernel space,
785 * so we just return it.
787 * @param os OS handle
788 * @param arg The argument passed to the ioctl function
789 * @param size The size of the structure pointed to by arg
791 * @return A pointer to a kernel space copy of the argument on
792 * success; NULL on failure
794 void *ocs_ioctl_preprocess(ocs_os_handle_t os, void *arg, size_t size)
801 * @brief Copy results of an ioctl back to user space
803 * This function is called at the end of ioctl processing to
804 * copy the argument back to user space.
806 * BSD handles this for us.
808 * @param os OS handle
809 * @param arg The argument passed to the ioctl function
810 * @param kern_ptr A pointer to the kernel space copy of the
812 * @param size The size of the structure pointed to by arg.
816 int32_t ocs_ioctl_postprocess(ocs_os_handle_t os, void *arg, void *kern_ptr, size_t size)
823 * @brief Free memory allocated by ocs_ioctl_preprocess
825 * This function is called in the event of an error in ioctl
826 * processing. For operating environments where ocs_ioctlpreprocess
827 * allocates memory, this call frees the memory without copying
828 * results back to user space.
830 * For BSD, because no memory was allocated in ocs_ioctl_preprocess,
831 * nothing needs to be done here.
833 * @param os OS handle
834 * @param kern_ptr A pointer to the kernel space copy of the
836 * @param size The size of the structure pointed to by arg.
838 * @return Returns nothing.
840 void ocs_ioctl_free(ocs_os_handle_t os, void *kern_ptr, size_t size)
845 void ocs_intr_disable(ocs_os_handle_t os)
849 void ocs_intr_enable(ocs_os_handle_t os)
853 void ocs_print_stack(void)
865 panic(">>> abort/panic\n");
869 ocs_pci_model(uint16_t vendor, uint16_t device)
872 case PCI_PRODUCT_EMULEX_OCE16002: return "OCE16002";
873 case PCI_PRODUCT_EMULEX_OCE1600_VF: return "OCE1600_VF";
874 case PCI_PRODUCT_EMULEX_OCE50102: return "OCE50102";
875 case PCI_PRODUCT_EMULEX_OCE50102_VF: return "OCE50102_VR";
884 ocs_get_bus_dev_func(ocs_t *ocs, uint8_t* bus, uint8_t* dev, uint8_t* func)
886 *bus = pci_get_bus(ocs->dev);
887 *dev = pci_get_slot(ocs->dev);
888 *func= pci_get_function(ocs->dev);
892 * @brief return CPU information
894 * This function populates the ocs_cpuinfo_t buffer with CPU information
896 * @param cpuinfo pointer to ocs_cpuinfo_t buffer
898 * @return returns 0 for success, a negative error code value for failure.
902 ocs_get_cpuinfo(ocs_cpuinfo_t *cpuinfo)
904 cpuinfo->num_cpus = mp_ncpus;
909 ocs_get_num_cpus(void)
911 static ocs_cpuinfo_t cpuinfo;
913 if (cpuinfo.num_cpus == 0) {
914 ocs_get_cpuinfo(&cpuinfo);
916 return cpuinfo.num_cpus;
920 __ocs_callout(void *t)
922 ocs_timer_t *timer = t;
924 if (callout_pending(&timer->callout)) {
925 /* Callout was reset */
929 if (!callout_active(&timer->callout)) {
930 /* Callout was stopped */
934 callout_deactivate(&timer->callout);
937 timer->func(timer->data);
942 ocs_setup_timer(ocs_os_handle_t os, ocs_timer_t *timer, void(*func)(void *arg), void *data, uint32_t timeout_ms)
948 ocs_log_err(NULL, "bad parameter\n");
952 if (!mtx_initialized(&timer->lock)) {
953 mtx_init(&timer->lock, "ocs_timer", NULL, MTX_DEF);
956 callout_init_mtx(&timer->callout, &timer->lock, 0);
961 tv.tv_sec = timeout_ms / 1000;
962 tv.tv_usec = (timeout_ms % 1000) * 1000;
970 mtx_lock(&timer->lock);
971 callout_reset(&timer->callout, hz, __ocs_callout, timer);
972 mtx_unlock(&timer->lock);
978 ocs_mod_timer(ocs_timer_t *timer, uint32_t timeout_ms)
984 ocs_log_err(NULL, "bad parameter\n");
988 tv.tv_sec = timeout_ms / 1000;
989 tv.tv_usec = (timeout_ms % 1000) * 1000;
997 mtx_lock(&timer->lock);
998 callout_reset(&timer->callout, hz, __ocs_callout, timer);
999 mtx_unlock(&timer->lock);
1005 ocs_timer_pending(ocs_timer_t *timer)
1007 return callout_active(&timer->callout);
1011 ocs_del_timer(ocs_timer_t *timer)
1014 mtx_lock(&timer->lock);
1015 callout_stop(&timer->callout);
1016 mtx_unlock(&timer->lock);
1022 ocs_strdup(const char *s)
1024 uint32_t l = strlen(s);
1027 d = ocs_malloc(NULL, l+1, OCS_M_NOWAIT);
1035 _ocs_assert(const char *cond, const char *filename, int linenum)
1037 const char *fn = strrchr(__FILE__, '/');
1039 ocs_log_err(NULL, "%s(%d) assertion (%s) failed\n", (fn ? fn + 1 : filename), linenum, cond);
1041 ocs_save_ddump_all(OCS_DDUMP_FLAGS_WQES|OCS_DDUMP_FLAGS_CQES|OCS_DDUMP_FLAGS_MQES, -1, TRUE);