d8f33821a94dee67468344d1d6bc76e3e0a47f2f
[people/sha0/winvblock.git] / src / winvblock / device.c
1 /**
2  * Copyright (C) 2009-2010, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
3  * Copyright 2006-2008, V.
4  * For WinAoE contact information, see http://winaoe.org/
5  *
6  * This file is part of WinVBlock, derived from WinAoE.
7  *
8  * WinVBlock is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * WinVBlock is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with WinVBlock.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /**
23  * @file
24  *
25  * Device specifics.
26  */
27
28 #include <ntddk.h>
29
30 #include "winvblock.h"
31 #include "wv_stdlib.h"
32 #include "portable.h"
33 #include "irp.h"
34 #include "driver.h"
35 #include "device.h"
36 #include "debug.h"
37
38 /* Forward declarations. */
39 static device__free_func device__free_dev_;
40 static device__create_pdo_func make_dev_pdo;
41
42 /**
43  * Create a new device.
44  *
45  * @ret dev             The address of a new device, or NULL for failure.
46  *
47  * This function should not be confused with a PDO creation routine, which is
48  * actually implemented for each device type.  This routine will allocate a
49  * device__type, track it in a global list, as well as populate the device
50  * with default values.
51  */
52 winvblock__lib_func struct device__type * device__create(void) {
53     struct device__type * dev;
54
55     /*
56      * Devices might be used for booting and should
57      * not be allocated from a paged memory pool.
58      */
59     dev = wv_mallocz(sizeof *dev);
60     if (dev == NULL)
61       return NULL;
62     /* Populate non-zero device defaults. */
63     dev->dispatch = driver__default_dispatch;
64     dev->DriverObject = driver__obj_ptr;
65     dev->ops.create_pdo = make_dev_pdo;
66     dev->ops.free = device__free_dev_;
67
68     return dev;
69   }
70
71 /**
72  * Create a device PDO.
73  *
74  * @v dev               Points to the device that needs a PDO.
75  */
76 winvblock__lib_func PDEVICE_OBJECT STDCALL device__create_pdo(
77     IN struct device__type * dev
78   ) {
79     return dev->ops.create_pdo(dev);
80   }
81
82 /**
83  * Default PDO creation operation.
84  *
85  * @v dev               Points to the device that needs a PDO.
86  * @ret NULL            Reports failure, no matter what.
87  *
88  * This function does nothing, since it doesn't make sense to create a PDO
89  * for an unknown type of device.
90  */
91 static PDEVICE_OBJECT STDCALL make_dev_pdo(IN struct device__type * dev) {
92     DBG("No specific PDO creation operation for this device!\n");
93     return NULL;
94   }
95
96 /**
97  * Close a device.
98  *
99  * @v dev               Points to the device to close.
100  */
101 winvblock__lib_func void STDCALL device__close(
102     IN struct device__type * dev
103   ) {
104     /* Call the device's close routine. */
105     dev->ops.close(dev);
106     return;
107   }
108
109 /**
110  * Delete a device.
111  *
112  * @v dev               Points to the device to delete.
113  */
114 winvblock__lib_func void STDCALL device__free(IN struct device__type * dev) {
115     /* Call the device's free routine. */
116     dev->ops.free(dev);
117   }
118
119 /**
120  * Default device deletion operation.
121  *
122  * @v dev               Points to the device to delete.
123  */
124 static void STDCALL device__free_dev_(IN struct device__type * dev) {
125     wv_free(dev);
126   }
127
128 /**
129  * Get a device from a DEVICE_OBJECT.
130  *
131  * @v dev_obj           Points to the DEVICE_OBJECT to get the device from.
132  * @ret                 Returns a pointer to the device on success, else NULL.
133  */
134 winvblock__lib_func struct device__type * device__get(PDEVICE_OBJECT dev_obj) {
135     driver__dev_ext_ptr dev_ext = dev_obj->DeviceExtension;
136     return dev_ext->device;
137   }
138
139 /**
140  * Set the device for a DEVICE_OBJECT.
141  *
142  * @v dev_obj           Points to the DEVICE_OBJECT to set the device for.
143  * @v dev               Points to the device to associate with.
144  */
145 winvblock__lib_func void device__set(
146     PDEVICE_OBJECT dev_obj,
147     struct device__type * dev
148   ) {
149     driver__dev_ext_ptr dev_ext = dev_obj->DeviceExtension;
150     dev_ext->device = dev;
151     return;
152   }