xref: /haiku/src/add-ons/kernel/drivers/misc/poke.cpp (revision f866c78257f5911c7487c48773eec7d4ac3ebf31)
15ae6f34bSAugustin Cavalier /*
25ae6f34bSAugustin Cavalier  * Copyright 2005, Oscar Lesta. All rights reserved.
38d13e725SAugustin Cavalier  * Copyright 2018, Haiku, Inc. All rights reserved.
45ae6f34bSAugustin Cavalier  * Distributed under the terms of the MIT License.
55ae6f34bSAugustin Cavalier  */
65ae6f34bSAugustin Cavalier 
75ae6f34bSAugustin Cavalier 
85ae6f34bSAugustin Cavalier #include <Drivers.h>
95ae6f34bSAugustin Cavalier #include <KernelExport.h>
105ae6f34bSAugustin Cavalier #include <ISA.h>
115ae6f34bSAugustin Cavalier #include <PCI.h>
125ae6f34bSAugustin Cavalier 
1308d7c6e8SFrançois Revol #if defined(__i386__) || defined(__x86_64__)
1408d7c6e8SFrançois Revol #include <thread.h>
1508d7c6e8SFrançois Revol #endif
1608d7c6e8SFrançois Revol 
175ae6f34bSAugustin Cavalier #include "poke.h"
185ae6f34bSAugustin Cavalier 
1908d7c6e8SFrançois Revol /*
2008d7c6e8SFrançois Revol  TODO: maintain a list of mapped areas in the cookie
2108d7c6e8SFrançois Revol  and only allow unmapping them, and clean them up on free.
2208d7c6e8SFrançois Revol  */
235ae6f34bSAugustin Cavalier 
245ae6f34bSAugustin Cavalier static status_t poke_open(const char*, uint32, void**);
255ae6f34bSAugustin Cavalier static status_t poke_close(void*);
265ae6f34bSAugustin Cavalier static status_t poke_free(void*);
275ae6f34bSAugustin Cavalier static status_t poke_control(void*, uint32, void*, size_t);
285ae6f34bSAugustin Cavalier static status_t poke_read(void*, off_t, void*, size_t*);
295ae6f34bSAugustin Cavalier static status_t poke_write(void*, off_t, const void*, size_t*);
305ae6f34bSAugustin Cavalier 
315ae6f34bSAugustin Cavalier 
325ae6f34bSAugustin Cavalier static const char* poke_name[] = {
335ae6f34bSAugustin Cavalier     "misc/" POKE_DEVICE_NAME,
345ae6f34bSAugustin Cavalier     NULL
355ae6f34bSAugustin Cavalier };
365ae6f34bSAugustin Cavalier 
375ae6f34bSAugustin Cavalier 
385ae6f34bSAugustin Cavalier device_hooks poke_hooks = {
395ae6f34bSAugustin Cavalier 	poke_open,
405ae6f34bSAugustin Cavalier 	poke_close,
415ae6f34bSAugustin Cavalier 	poke_free,
425ae6f34bSAugustin Cavalier 	poke_control,
435ae6f34bSAugustin Cavalier 	poke_read,
445ae6f34bSAugustin Cavalier 	poke_write,
455ae6f34bSAugustin Cavalier };
465ae6f34bSAugustin Cavalier 
475ae6f34bSAugustin Cavalier int32 api_version = B_CUR_DRIVER_API_VERSION;
485ae6f34bSAugustin Cavalier 
495ae6f34bSAugustin Cavalier isa_module_info* isa;
505ae6f34bSAugustin Cavalier pci_module_info* pci;
515ae6f34bSAugustin Cavalier 
525ae6f34bSAugustin Cavalier 
535ae6f34bSAugustin Cavalier status_t
545ae6f34bSAugustin Cavalier init_hardware(void)
555ae6f34bSAugustin Cavalier {
565ae6f34bSAugustin Cavalier 	return B_OK;
575ae6f34bSAugustin Cavalier }
585ae6f34bSAugustin Cavalier 
595ae6f34bSAugustin Cavalier 
605ae6f34bSAugustin Cavalier status_t
615ae6f34bSAugustin Cavalier init_driver(void)
625ae6f34bSAugustin Cavalier {
635ae6f34bSAugustin Cavalier 	if (get_module(B_ISA_MODULE_NAME, (module_info**)&isa) < B_OK)
645ae6f34bSAugustin Cavalier 		return ENOSYS;
655ae6f34bSAugustin Cavalier 
665ae6f34bSAugustin Cavalier 	if (get_module(B_PCI_MODULE_NAME, (module_info**)&pci) < B_OK) {
675ae6f34bSAugustin Cavalier 		put_module(B_ISA_MODULE_NAME);
685ae6f34bSAugustin Cavalier 		return ENOSYS;
695ae6f34bSAugustin Cavalier 	}
705ae6f34bSAugustin Cavalier 
715ae6f34bSAugustin Cavalier 	return B_OK;
725ae6f34bSAugustin Cavalier }
735ae6f34bSAugustin Cavalier 
745ae6f34bSAugustin Cavalier 
755ae6f34bSAugustin Cavalier void
765ae6f34bSAugustin Cavalier uninit_driver(void)
775ae6f34bSAugustin Cavalier {
785ae6f34bSAugustin Cavalier 	put_module(B_ISA_MODULE_NAME);
795ae6f34bSAugustin Cavalier 	put_module(B_PCI_MODULE_NAME);
805ae6f34bSAugustin Cavalier }
815ae6f34bSAugustin Cavalier 
825ae6f34bSAugustin Cavalier 
835ae6f34bSAugustin Cavalier const char**
845ae6f34bSAugustin Cavalier publish_devices(void)
855ae6f34bSAugustin Cavalier {
865ae6f34bSAugustin Cavalier 	return poke_name;
875ae6f34bSAugustin Cavalier }
885ae6f34bSAugustin Cavalier 
895ae6f34bSAugustin Cavalier 
905ae6f34bSAugustin Cavalier device_hooks*
915ae6f34bSAugustin Cavalier find_device(const char* name)
925ae6f34bSAugustin Cavalier {
935ae6f34bSAugustin Cavalier 	return &poke_hooks;
945ae6f34bSAugustin Cavalier }
955ae6f34bSAugustin Cavalier 
965ae6f34bSAugustin Cavalier 
975ae6f34bSAugustin Cavalier //	#pragma mark -
985ae6f34bSAugustin Cavalier 
995ae6f34bSAugustin Cavalier 
1005ae6f34bSAugustin Cavalier status_t
1015ae6f34bSAugustin Cavalier poke_open(const char* name, uint32 flags, void** cookie)
1025ae6f34bSAugustin Cavalier {
1035ae6f34bSAugustin Cavalier 	*cookie = NULL;
1045ae6f34bSAugustin Cavalier 
1051e3f0626SAugustin Cavalier 	if (getuid() != 0 && geteuid() != 0)
1061e3f0626SAugustin Cavalier 		return EPERM;
1071e3f0626SAugustin Cavalier 
10808d7c6e8SFrançois Revol #if defined(__i386__) || defined(__x86_64__)
10908d7c6e8SFrançois Revol 	/* on x86, raise the IOPL so that outb/inb will work */
11008d7c6e8SFrançois Revol 	iframe* frame = x86_get_user_iframe();
11108d7c6e8SFrançois Revol 	int iopl = 3;
11208d7c6e8SFrançois Revol 	frame->flags &= ~X86_EFLAGS_IO_PRIVILEG_LEVEL;
11308d7c6e8SFrançois Revol 	frame->flags |= (iopl << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT)
11408d7c6e8SFrançois Revol 		& X86_EFLAGS_IO_PRIVILEG_LEVEL;
11508d7c6e8SFrançois Revol #endif
11608d7c6e8SFrançois Revol 
1175ae6f34bSAugustin Cavalier 	return B_OK;
1185ae6f34bSAugustin Cavalier }
1195ae6f34bSAugustin Cavalier 
1205ae6f34bSAugustin Cavalier 
1215ae6f34bSAugustin Cavalier status_t
1225ae6f34bSAugustin Cavalier poke_close(void* cookie)
1235ae6f34bSAugustin Cavalier {
1245ae6f34bSAugustin Cavalier 	return B_OK;
1255ae6f34bSAugustin Cavalier }
1265ae6f34bSAugustin Cavalier 
1275ae6f34bSAugustin Cavalier 
1285ae6f34bSAugustin Cavalier status_t
1295ae6f34bSAugustin Cavalier poke_free(void* cookie)
1305ae6f34bSAugustin Cavalier {
13108d7c6e8SFrançois Revol #if defined(__i386__) || defined(__x86_64__)
13208d7c6e8SFrançois Revol 	iframe* frame = x86_get_user_iframe();
13308d7c6e8SFrançois Revol 	int iopl = 0;
13408d7c6e8SFrançois Revol 	frame->flags &= ~X86_EFLAGS_IO_PRIVILEG_LEVEL;
13508d7c6e8SFrançois Revol 	frame->flags |= (iopl << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT)
13608d7c6e8SFrançois Revol 		& X86_EFLAGS_IO_PRIVILEG_LEVEL;
13708d7c6e8SFrançois Revol #endif
13808d7c6e8SFrançois Revol 
1395ae6f34bSAugustin Cavalier 	return B_OK;
1405ae6f34bSAugustin Cavalier }
1415ae6f34bSAugustin Cavalier 
1425ae6f34bSAugustin Cavalier 
1435ae6f34bSAugustin Cavalier status_t
1445ae6f34bSAugustin Cavalier poke_control(void* cookie, uint32 op, void* arg, size_t length)
1455ae6f34bSAugustin Cavalier {
1465ae6f34bSAugustin Cavalier 	switch (op) {
1475ae6f34bSAugustin Cavalier 		case POKE_PORT_READ:
1485ae6f34bSAugustin Cavalier 		{
1498d13e725SAugustin Cavalier 			status_t result = B_OK;
1508d13e725SAugustin Cavalier 			port_io_args ioctl;
1518d13e725SAugustin Cavalier 			if (user_memcpy(&ioctl, arg, sizeof(port_io_args)) != B_OK)
1528d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
1538d13e725SAugustin Cavalier 			if (ioctl.signature != POKE_SIGNATURE)
1545ae6f34bSAugustin Cavalier 				return B_BAD_VALUE;
1555ae6f34bSAugustin Cavalier 
1568d13e725SAugustin Cavalier 			switch (ioctl.size) {
1575ae6f34bSAugustin Cavalier 				case 1:
1588d13e725SAugustin Cavalier 					ioctl.value = isa->read_io_8(ioctl.port);
1595ae6f34bSAugustin Cavalier 				break;
1605ae6f34bSAugustin Cavalier 				case 2:
1618d13e725SAugustin Cavalier 					ioctl.value = isa->read_io_16(ioctl.port);
1625ae6f34bSAugustin Cavalier 				break;
1635ae6f34bSAugustin Cavalier 				case 4:
1648d13e725SAugustin Cavalier 					ioctl.value = isa->read_io_32(ioctl.port);
1655ae6f34bSAugustin Cavalier 				break;
1665ae6f34bSAugustin Cavalier 				default:
1675ae6f34bSAugustin Cavalier 					result = B_BAD_VALUE;
1685ae6f34bSAugustin Cavalier 			}
1695ae6f34bSAugustin Cavalier 
1708d13e725SAugustin Cavalier 			if (user_memcpy(arg, &ioctl, sizeof(port_io_args)) != B_OK)
1718d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
1725ae6f34bSAugustin Cavalier 			return result;
1735ae6f34bSAugustin Cavalier 		}
1745ae6f34bSAugustin Cavalier 
1755ae6f34bSAugustin Cavalier 		case POKE_PORT_WRITE:
1765ae6f34bSAugustin Cavalier 		{
1778d13e725SAugustin Cavalier 			status_t result = B_OK;
1788d13e725SAugustin Cavalier 			port_io_args ioctl;
1798d13e725SAugustin Cavalier 			if (user_memcpy(&ioctl, arg, sizeof(port_io_args)) != B_OK)
1808d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
1818d13e725SAugustin Cavalier 			if (ioctl.signature != POKE_SIGNATURE)
1825ae6f34bSAugustin Cavalier 				return B_BAD_VALUE;
1835ae6f34bSAugustin Cavalier 
1848d13e725SAugustin Cavalier 			switch (ioctl.size) {
1855ae6f34bSAugustin Cavalier 				case 1:
1868d13e725SAugustin Cavalier 					isa->write_io_8(ioctl.port, ioctl.value);
1875ae6f34bSAugustin Cavalier 					break;
1885ae6f34bSAugustin Cavalier 				case 2:
1898d13e725SAugustin Cavalier 					isa->write_io_16(ioctl.port, ioctl.value);
1905ae6f34bSAugustin Cavalier 					break;
1915ae6f34bSAugustin Cavalier 				case 4:
1928d13e725SAugustin Cavalier 					isa->write_io_32(ioctl.port, ioctl.value);
1935ae6f34bSAugustin Cavalier 					break;
1945ae6f34bSAugustin Cavalier 				default:
1955ae6f34bSAugustin Cavalier 					result = B_BAD_VALUE;
1965ae6f34bSAugustin Cavalier 			}
1975ae6f34bSAugustin Cavalier 
1985ae6f34bSAugustin Cavalier 			return result;
1995ae6f34bSAugustin Cavalier 		}
2005ae6f34bSAugustin Cavalier 
2015ae6f34bSAugustin Cavalier 		case POKE_PORT_INDEXED_READ:
2025ae6f34bSAugustin Cavalier 		{
2038d13e725SAugustin Cavalier 			port_io_args ioctl;
2048d13e725SAugustin Cavalier 			if (user_memcpy(&ioctl, arg, sizeof(port_io_args)) != B_OK)
2058d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
2068d13e725SAugustin Cavalier 			if (ioctl.signature != POKE_SIGNATURE)
2075ae6f34bSAugustin Cavalier 				return B_BAD_VALUE;
2085ae6f34bSAugustin Cavalier 
2098d13e725SAugustin Cavalier 			isa->write_io_8(ioctl.port, ioctl.size);
2108d13e725SAugustin Cavalier 			ioctl.value = isa->read_io_8(ioctl.port + 1);
2118d13e725SAugustin Cavalier 
2128d13e725SAugustin Cavalier 			if (user_memcpy(arg, &ioctl, sizeof(port_io_args)) != B_OK)
2138d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
2145ae6f34bSAugustin Cavalier 			return B_OK;
2155ae6f34bSAugustin Cavalier 		}
2165ae6f34bSAugustin Cavalier 
2175ae6f34bSAugustin Cavalier 		case POKE_PORT_INDEXED_WRITE:
2185ae6f34bSAugustin Cavalier 		{
2198d13e725SAugustin Cavalier 			port_io_args ioctl;
2208d13e725SAugustin Cavalier 			if (user_memcpy(&ioctl, arg, sizeof(port_io_args)) != B_OK)
2218d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
2228d13e725SAugustin Cavalier 			if (ioctl.signature != POKE_SIGNATURE)
2235ae6f34bSAugustin Cavalier 				return B_BAD_VALUE;
2245ae6f34bSAugustin Cavalier 
2258d13e725SAugustin Cavalier 			isa->write_io_8(ioctl.port, ioctl.size);
2268d13e725SAugustin Cavalier 			isa->write_io_8(ioctl.port + 1, ioctl.value);
2275ae6f34bSAugustin Cavalier 			return B_OK;
2285ae6f34bSAugustin Cavalier 		}
2295ae6f34bSAugustin Cavalier 
2305ae6f34bSAugustin Cavalier 		case POKE_PCI_READ_CONFIG:
2315ae6f34bSAugustin Cavalier 		{
2328d13e725SAugustin Cavalier 			pci_io_args ioctl;
2338d13e725SAugustin Cavalier 			if (user_memcpy(&ioctl, arg, sizeof(pci_io_args)) != B_OK)
2348d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
2358d13e725SAugustin Cavalier 			if (ioctl.signature != POKE_SIGNATURE)
2365ae6f34bSAugustin Cavalier 				return B_BAD_VALUE;
2375ae6f34bSAugustin Cavalier 
2388d13e725SAugustin Cavalier 			ioctl.value = pci->read_pci_config(ioctl.bus, ioctl.device,
2398d13e725SAugustin Cavalier 				ioctl.function, ioctl.offset, ioctl.size);
2408d13e725SAugustin Cavalier 			if (user_memcpy(arg, &ioctl, sizeof(pci_io_args)) != B_OK)
2418d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
2425ae6f34bSAugustin Cavalier 			return B_OK;
2435ae6f34bSAugustin Cavalier 		}
2445ae6f34bSAugustin Cavalier 
2455ae6f34bSAugustin Cavalier 		case POKE_PCI_WRITE_CONFIG:
2465ae6f34bSAugustin Cavalier 		{
2478d13e725SAugustin Cavalier 			pci_io_args ioctl;
2488d13e725SAugustin Cavalier 			if (user_memcpy(&ioctl, arg, sizeof(pci_io_args)) != B_OK)
2498d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
2508d13e725SAugustin Cavalier 			if (ioctl.signature != POKE_SIGNATURE)
2515ae6f34bSAugustin Cavalier 				return B_BAD_VALUE;
2525ae6f34bSAugustin Cavalier 
2538d13e725SAugustin Cavalier 			pci->write_pci_config(ioctl.bus, ioctl.device, ioctl.function,
2548d13e725SAugustin Cavalier 				ioctl.offset, ioctl.size, ioctl.value);
2555ae6f34bSAugustin Cavalier 			return B_OK;
2565ae6f34bSAugustin Cavalier 		}
2575ae6f34bSAugustin Cavalier 
2585ae6f34bSAugustin Cavalier 		case POKE_GET_NTH_PCI_INFO:
2595ae6f34bSAugustin Cavalier 		{
2608d13e725SAugustin Cavalier 			pci_info_args ioctl;
2618d13e725SAugustin Cavalier 			if (user_memcpy(&ioctl, arg, sizeof(pci_info_args)) != B_OK)
2628d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
2638d13e725SAugustin Cavalier 			if (ioctl.signature != POKE_SIGNATURE)
2645ae6f34bSAugustin Cavalier 				return B_BAD_VALUE;
2655ae6f34bSAugustin Cavalier 
2668d13e725SAugustin Cavalier 			pci_info info;
2678d13e725SAugustin Cavalier 			ioctl.status = pci->get_nth_pci_info(ioctl.index, &info);
2688d13e725SAugustin Cavalier 
2698d13e725SAugustin Cavalier 			if (user_memcpy(ioctl.info, &info, sizeof(pci_info)) != B_OK)
2708d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
2718d13e725SAugustin Cavalier 			if (user_memcpy(arg, &ioctl, sizeof(pci_info_args)) != B_OK)
2728d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
2735ae6f34bSAugustin Cavalier 			return B_OK;
2745ae6f34bSAugustin Cavalier 		}
2755ae6f34bSAugustin Cavalier 
2765ae6f34bSAugustin Cavalier 		case POKE_GET_PHYSICAL_ADDRESS:
2775ae6f34bSAugustin Cavalier 		{
2788d13e725SAugustin Cavalier 			mem_map_args ioctl;
2798d13e725SAugustin Cavalier 			if (user_memcpy(&ioctl, arg, sizeof(mem_map_args)) != B_OK)
2808d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
2815ae6f34bSAugustin Cavalier 			physical_entry table;
2825ae6f34bSAugustin Cavalier 			status_t result;
2835ae6f34bSAugustin Cavalier 
2848d13e725SAugustin Cavalier 			if (ioctl.signature != POKE_SIGNATURE)
2855ae6f34bSAugustin Cavalier 				return B_BAD_VALUE;
2865ae6f34bSAugustin Cavalier 
2878d13e725SAugustin Cavalier 			result = get_memory_map(ioctl.address, ioctl.size, &table, 1);
28859b54f38SOscar Lesta 			ioctl.physical_address = table.address;
2898d13e725SAugustin Cavalier 			ioctl.size = table.size;
2908d13e725SAugustin Cavalier 			if (user_memcpy(arg, &ioctl, sizeof(mem_map_args)) != B_OK)
2918d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
2925ae6f34bSAugustin Cavalier 			return result;
2935ae6f34bSAugustin Cavalier 		}
2945ae6f34bSAugustin Cavalier 
2955ae6f34bSAugustin Cavalier 		case POKE_MAP_MEMORY:
2965ae6f34bSAugustin Cavalier 		{
2978d13e725SAugustin Cavalier 			mem_map_args ioctl;
2988d13e725SAugustin Cavalier 			if (user_memcpy(&ioctl, arg, sizeof(mem_map_args)) != B_OK)
2998d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
3008d13e725SAugustin Cavalier 			if (ioctl.signature != POKE_SIGNATURE)
3015ae6f34bSAugustin Cavalier 				return B_BAD_VALUE;
3025ae6f34bSAugustin Cavalier 
3038d13e725SAugustin Cavalier 			char name[B_OS_NAME_LENGTH];
304*f866c782SX512 			if (user_strlcpy(name, ioctl.name, B_OS_NAME_LENGTH) < B_OK)
3058d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
3068d13e725SAugustin Cavalier 
3078d13e725SAugustin Cavalier 			ioctl.area = map_physical_memory(name,
3088d13e725SAugustin Cavalier 				(addr_t)ioctl.physical_address, ioctl.size, ioctl.flags,
3098d13e725SAugustin Cavalier 				ioctl.protection, (void**)&ioctl.address);
3108d13e725SAugustin Cavalier 
3118d13e725SAugustin Cavalier 			if (user_memcpy(arg, &ioctl, sizeof(mem_map_args)) != B_OK)
3128d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
3138d13e725SAugustin Cavalier 			return ioctl.area;
3145ae6f34bSAugustin Cavalier 		}
3155ae6f34bSAugustin Cavalier 
3165ae6f34bSAugustin Cavalier 		case POKE_UNMAP_MEMORY:
3175ae6f34bSAugustin Cavalier 		{
3188d13e725SAugustin Cavalier 			mem_map_args ioctl;
3198d13e725SAugustin Cavalier 			if (user_memcpy(&ioctl, arg, sizeof(mem_map_args)) != B_OK)
3208d13e725SAugustin Cavalier 				return B_BAD_ADDRESS;
3218d13e725SAugustin Cavalier 			if (ioctl.signature != POKE_SIGNATURE)
3225ae6f34bSAugustin Cavalier 				return B_BAD_VALUE;
3235ae6f34bSAugustin Cavalier 
3248d13e725SAugustin Cavalier 			return delete_area(ioctl.area);
3255ae6f34bSAugustin Cavalier 		}
3265ae6f34bSAugustin Cavalier 	}
3275ae6f34bSAugustin Cavalier 
3285ae6f34bSAugustin Cavalier 	return B_BAD_VALUE;
3295ae6f34bSAugustin Cavalier }
3305ae6f34bSAugustin Cavalier 
3315ae6f34bSAugustin Cavalier 
3325ae6f34bSAugustin Cavalier status_t
3335ae6f34bSAugustin Cavalier poke_read(void* cookie, off_t position, void* buffer, size_t* numBytes)
3345ae6f34bSAugustin Cavalier {
3355ae6f34bSAugustin Cavalier 	*numBytes = 0;
3365ae6f34bSAugustin Cavalier 	return B_NOT_ALLOWED;
3375ae6f34bSAugustin Cavalier }
3385ae6f34bSAugustin Cavalier 
3395ae6f34bSAugustin Cavalier 
3405ae6f34bSAugustin Cavalier status_t
3415ae6f34bSAugustin Cavalier poke_write(void* cookie, off_t position, const void* buffer, size_t* numBytes)
3425ae6f34bSAugustin Cavalier {
3435ae6f34bSAugustin Cavalier 	*numBytes = 0;
3445ae6f34bSAugustin Cavalier 	return B_NOT_ALLOWED;
3455ae6f34bSAugustin Cavalier }
346