/* * An example device driver for Syllable. See the included text for an * explanation. * * Released under the terms of the MIT License * Copyright (c) 2006 Kristian Van Der Vliet * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE */ #include #include #include #include #include static PCI_bus_s* g_psBus; static int g_nHandle; /* The driver will need to keep track of the handle of the device it creates */ static int g_nNode; /* We'll also need to track the handle of the device node we create */ /* Device interface */ static status_t example_open( void* pNode, uint32 nFlags, void **pCookie ) { kerndbg( KERN_INFO, "This is example_open( %p, %d, %p )\n", pNode, nFlags, pCookie ); return 0; } static status_t example_close( void* pNode, void* pCookie ) { kerndbg( KERN_INFO, "This is example_close( %p, %p )\n", pNode, pCookie ); return 0; } static status_t example_ioctl( void* pNode, void* pCookie, uint32 nCommand, void* pArgs, bool bFromKernel ) { return ENOSYS; } static int example_read( void* pNode, void* pCookie, off_t nPosition, void* pBuffer, size_t nSize ) { kerndbg( KERN_INFO, "This is example_read( %p, %p, %Ld, %p, %d )\n", pNode, pCookie, (uint64)nPosition, pBuffer, nSize ); return 0; } static int example_write( void* pNode, void* pCookie, off_t nPosition, const void* pBuffer, size_t nSize ) { kerndbg( KERN_INFO, "This is example_write( %p, %p, %Ld, %p, %d )\n", pNode, pCookie, (uint64)nPosition, pBuffer, nSize ); return nSize; } static DeviceOperations_s g_sDevOps = { example_open, example_close, example_ioctl, example_read, example_write, NULL, /* dop_readv */ NULL, /* dop_writev */ NULL, /* dop_add_select_req */ NULL /* dop_rem_select_req */ }; /* Driver management */ status_t device_init( int nDeviceID ) { kerndbg( KERN_INFO, "This is the example driver device_init() function. The device ID is %d.\n", nDeviceID ); /* Get PCI bus */ g_psBus = get_busmanager( PCI_BUS_NAME, PCI_BUS_VERSION ); if( g_psBus == NULL ) return -ENODEV; /* Register a fake device */ g_nHandle = register_device( "fake", "none" ); /* Claim the fake device */ claim_device( nDeviceID, g_nHandle, "Example device", DEVICE_SYSTEM ); /* Create a device node under /dev */ g_nNode = create_device_node( nDeviceID, g_nHandle, "misc/example", &g_sDevOps, NULL ); if( g_nNode < 0 ) kerndbg( KERN_WARNING, "Failed to create the example device node /dev/example! create_device_node() returned %d.\n", g_nNode ); return 0; } status_t device_uninit( int nDeviceID ) { kerndbg( KERN_INFO, "This is the example driver device_uninit() function. The device ID is %d.\n", nDeviceID ); /* Remove the device node from /dev */ if( g_nNode >= 0 ) delete_device_node( g_nNode ); /* Release the fake device */ release_device( g_nHandle ); /* Remove the fake device from the system */ unregister_device( g_nHandle ); return 0; }