aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/rar
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2009-08-06 15:44:18 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-15 15:02:11 -0400
commit542385ee6da337529c1087dd3d8c7af3e4269602 (patch)
tree2926ee4dd362ff01cff8964282b3948e13c9ca29 /drivers/staging/rar
parentcd1bb431d8b183e2d063267419984cc9bbe22b0b (diff)
Staging: sep: Move the RAR support into staging where it is supposed to be
Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/rar')
-rw-r--r--drivers/staging/rar/Kconfig17
-rw-r--r--drivers/staging/rar/Makefile2
-rw-r--r--drivers/staging/rar/rar_driver.c450
-rw-r--r--drivers/staging/rar/rar_driver.h99
4 files changed, 568 insertions, 0 deletions
diff --git a/drivers/staging/rar/Kconfig b/drivers/staging/rar/Kconfig
new file mode 100644
index 00000000000..17f8bf3bb41
--- /dev/null
+++ b/drivers/staging/rar/Kconfig
@@ -0,0 +1,17 @@
1#
2# RAR device configuration
3#
4
5menu "RAR Register Driver"
6#
7# Restricted Access Register Manager
8#
9config RAR_REGISTER
10 tristate "Restricted Access Region Register Driver"
11 default n
12 ---help---
13 This driver allows other kernel drivers access to the
14 contents of the restricted access region control
15 registers.
16
17endmenu
diff --git a/drivers/staging/rar/Makefile b/drivers/staging/rar/Makefile
new file mode 100644
index 00000000000..5422ed04ccf
--- /dev/null
+++ b/drivers/staging/rar/Makefile
@@ -0,0 +1,2 @@
1EXTRA_CFLAGS += -DLITTLE__ENDIAN
2obj-$(CONFIG_RAR_REGISTER) += rar_driver.o
diff --git a/drivers/staging/rar/rar_driver.c b/drivers/staging/rar/rar_driver.c
new file mode 100644
index 00000000000..8c4463e2f62
--- /dev/null
+++ b/drivers/staging/rar/rar_driver.c
@@ -0,0 +1,450 @@
1#include <linux/init.h>
2#include <linux/module.h>
3#include <linux/fs.h>
4#include <linux/cdev.h>
5#include <linux/kdev_t.h>
6#include <linux/semaphore.h>
7#include <linux/mm.h>
8#include <linux/poll.h>
9#include <linux/wait.h>
10#include <linux/ioctl.h>
11#include <linux/ioport.h>
12#include <linux/io.h>
13#include <linux/interrupt.h>
14#include <linux/pagemap.h>
15#include <linux/pci.h>
16#include <linux/firmware.h>
17#include <linux/sched.h>
18#include "rar_driver.h"
19
20/* PCI vendor id for controler */
21#define VENDOR_ID 0x8086
22
23/* PCI device id for controler */
24#define DEVICE_ID 0x4110
25
26/* The following defines are for the IPC process to retrieve RAR in */
27
28/* === Lincroft Message Bus Interface === */
29/* Message Control Register */
30#define LNC_MCR_OFFSET 0xD0
31
32/* Message Data Register */
33#define LNC_MDR_OFFSET 0xD4
34
35/* Message Opcodes */
36#define LNC_MESSAGE_READ_OPCODE 0xD0
37#define LNC_MESSAGE_WRITE_OPCODE 0xE0
38
39/* Message Write Byte Enables */
40#define LNC_MESSAGE_BYTE_WRITE_ENABLES 0xF
41
42/* B-unit Port */
43#define LNC_BUNIT_PORT 0x3
44
45/* === Lincroft B-Unit Registers - Programmed by IA32 firmware === */
46#define LNC_BRAR0L 0x10
47#define LNC_BRAR0H 0x11
48#define LNC_BRAR1L 0x12
49#define LNC_BRAR1H 0x13
50
51/* Reserved for SeP */
52#define LNC_BRAR2L 0x14
53#define LNC_BRAR2H 0x15
54
55
56/* This structure is only used during module initialization. */
57struct RAR_offsets {
58 int low; /* Register offset for low RAR physical address. */
59 int high; /* Register offset for high RAR physical address. */
60};
61
62struct pci_dev *rar_dev;
63static uint32_t registered;
64
65/* Moorestown supports three restricted access regions. */
66#define MRST_NUM_RAR 3
67
68struct RAR_address_struct rar_addr[MRST_NUM_RAR];
69
70/* prototype for init */
71static int __init rar_init_handler(void);
72static void __exit rar_exit_handler(void);
73
74/*
75 function that is activated on the succesfull probe of the RAR device
76*/
77static int __devinit rar_probe(struct pci_dev *pdev, struct pci_device_id *ent);
78
79static struct pci_device_id rar_pci_id_tbl[] = {
80 { PCI_DEVICE(VENDOR_ID, DEVICE_ID) },
81 { 0 }
82};
83
84MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl);
85
86/* field for registering driver to PCI device */
87static struct pci_driver rar_pci_driver = {
88 .name = "rar_driver",
89 .id_table = rar_pci_id_tbl,
90 .probe = rar_probe
91};
92
93/* This function is used to retrieved RAR info using the IPC message
94 bus interface */
95static int memrar_get_rar_addr(struct pci_dev* pdev,
96 int offset,
97 u32 *addr)
98{
99 /*
100 * ======== The Lincroft Message Bus Interface ========
101 * Lincroft registers may be obtained from the PCI
102 * (the Host Bridge) using the Lincroft Message Bus
103 * Interface. That message bus interface is generally
104 * comprised of two registers: a control register (MCR, 0xDO)
105 * and a data register (MDR, 0xD4).
106 *
107 * The MCR (message control register) format is the following:
108 * 1. [31:24]: Opcode
109 * 2. [23:16]: Port
110 * 3. [15:8]: Register Offset
111 * 4. [7:4]: Byte Enables (use 0xF to set all of these bits
112 * to 1)
113 * 5. [3:0]: reserved
114 *
115 * Read (0xD0) and write (0xE0) opcodes are written to the
116 * control register when reading and writing to Lincroft
117 * registers, respectively.
118 *
119 * We're interested in registers found in the Lincroft
120 * B-unit. The B-unit port is 0x3.
121 *
122 * The six B-unit RAR register offsets we use are listed
123 * earlier in this file.
124 *
125 * Lastly writing to the MCR register requires the "Byte
126 * enables" bits to be set to 1. This may be achieved by
127 * writing 0xF at bit 4.
128 *
129 * The MDR (message data register) format is the following:
130 * 1. [31:0]: Read/Write Data
131 *
132 * Data being read from this register is only available after
133 * writing the appropriate control message to the MCR
134 * register.
135 *
136 * Data being written to this register must be written before
137 * writing the appropriate control message to the MCR
138 * register.
139 */
140
141 int result = 0; /* result */
142 /* Construct control message */
143 u32 const message =
144 (LNC_MESSAGE_READ_OPCODE << 24)
145 | (LNC_BUNIT_PORT << 16)
146 | (offset << 8)
147 | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4);
148
149 printk(KERN_WARNING "rar- offset to LNC MSG is %x\n",offset);
150
151 if (addr == 0)
152 return -EINVAL;
153
154 /* Send the control message */
155 result = pci_write_config_dword(pdev,
156 LNC_MCR_OFFSET,
157 message);
158
159 printk(KERN_WARNING "rar- result from send ctl register is %x\n"
160 ,result);
161
162 if (!result)
163 result = pci_read_config_dword(pdev,
164 LNC_MDR_OFFSET,
165 addr);
166
167 printk(KERN_WARNING "rar- result from read data register is %x\n",
168 result);
169
170 printk(KERN_WARNING "rar- value read from data register is %x\n",
171 *addr);
172
173 if (result)
174 return -1;
175 else
176 return 0;
177}
178
179static int memrar_set_rar_addr(struct pci_dev* pdev,
180 int offset,
181 u32 addr)
182{
183 /*
184 * ======== The Lincroft Message Bus Interface ========
185 * Lincroft registers may be obtained from the PCI
186 * (the Host Bridge) using the Lincroft Message Bus
187 * Interface. That message bus interface is generally
188 * comprised of two registers: a control register (MCR, 0xDO)
189 * and a data register (MDR, 0xD4).
190 *
191 * The MCR (message control register) format is the following:
192 * 1. [31:24]: Opcode
193 * 2. [23:16]: Port
194 * 3. [15:8]: Register Offset
195 * 4. [7:4]: Byte Enables (use 0xF to set all of these bits
196 * to 1)
197 * 5. [3:0]: reserved
198 *
199 * Read (0xD0) and write (0xE0) opcodes are written to the
200 * control register when reading and writing to Lincroft
201 * registers, respectively.
202 *
203 * We're interested in registers found in the Lincroft
204 * B-unit. The B-unit port is 0x3.
205 *
206 * The six B-unit RAR register offsets we use are listed
207 * earlier in this file.
208 *
209 * Lastly writing to the MCR register requires the "Byte
210 * enables" bits to be set to 1. This may be achieved by
211 * writing 0xF at bit 4.
212 *
213 * The MDR (message data register) format is the following:
214 * 1. [31:0]: Read/Write Data
215 *
216 * Data being read from this register is only available after
217 * writing the appropriate control message to the MCR
218 * register.
219 *
220 * Data being written to this register must be written before
221 * writing the appropriate control message to the MCR
222 * register.
223 */
224
225 int result = 0; /* result */
226
227 /* Construct control message */
228 u32 const message =
229 (LNC_MESSAGE_WRITE_OPCODE << 24)
230 | (LNC_BUNIT_PORT << 16)
231 | (offset << 8)
232 | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4);
233
234 printk(KERN_WARNING "rar- offset to LNC MSG is %x\n",offset);
235
236 if (addr == 0)
237 return -EINVAL;
238
239 /* Send the control message */
240 result = pci_write_config_dword(pdev,
241 LNC_MDR_OFFSET,
242 addr);
243
244 printk(KERN_WARNING "rar- result from send ctl register is %x\n"
245 ,result);
246
247 if (!result)
248 result = pci_write_config_dword(pdev,
249 LNC_MCR_OFFSET,
250 message);
251
252 printk(KERN_WARNING "rar- result from write data register is %x\n",
253 result);
254
255 printk(KERN_WARNING "rar- value read to data register is %x\n",
256 addr);
257
258 if (result)
259 return -1;
260 else
261 return 0;
262}
263
264/*
265
266 * Initialize RAR parameters, such as physical addresses, etc.
267
268 */
269static int memrar_init_rar_params(struct pci_dev *pdev)
270{
271 struct RAR_offsets const offsets[] = {
272 { LNC_BRAR0L, LNC_BRAR0H },
273 { LNC_BRAR1L, LNC_BRAR1H },
274 { LNC_BRAR2L, LNC_BRAR2H }
275 };
276
277 size_t const num_offsets = sizeof(offsets) / sizeof(offsets[0]);
278 struct RAR_offsets const *end = offsets + num_offsets;
279 struct RAR_offsets const *i;
280 unsigned int n = 0;
281 int result = 0;
282
283 /* Retrieve RAR start and end physical addresses. */
284
285 /*
286 * Access the RAR registers through the Lincroft Message Bus
287 * Interface on PCI device: 00:00.0 Host bridge.
288 */
289
290 /* struct pci_dev *pdev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); */
291
292 if (pdev == NULL)
293 return -ENODEV;
294
295 for (i = offsets; i != end; ++i, ++n) {
296 if (memrar_get_rar_addr (pdev,
297 (*i).low,
298 &(rar_addr[n].low)) != 0
299 || memrar_get_rar_addr (pdev,
300 (*i).high,
301 &(rar_addr[n].high)) != 0) {
302 result = -1;
303 break;
304 }
305 }
306
307 /* Done accessing the device. */
308 /* pci_dev_put(pdev); */
309
310 if (result == 0) {
311 if(1) {
312 size_t z;
313 for (z = 0; z != MRST_NUM_RAR; ++z) {
314 printk(KERN_WARNING "rar - BRAR[%u] physical address low\n"
315 "\tlow: 0x%08x\n"
316 "\thigh: 0x%08x\n",
317 z,
318 rar_addr[z].low,
319 rar_addr[z].high);
320 }
321 }
322 }
323
324 return result;
325}
326
327/*
328 function that is activaed on the succesfull probe of the RAR device
329*/
330static int __devinit rar_probe(struct pci_dev *pdev, struct pci_device_id *ent)
331{
332 /* error */
333 int error;
334
335 /*------------------------
336 CODE
337 ---------------------------*/
338
339 DEBUG_PRINT_0(RAR_DEBUG_LEVEL_EXTENDED,
340 "Rar pci probe starting\n");
341 error = 0;
342
343 /* enable the device */
344 error = pci_enable_device(pdev);
345 if (error) {
346 DEBUG_PRINT_0(RAR_DEBUG_LEVEL_EXTENDED,
347 "error enabling pci device\n");
348 goto end_function;
349 }
350
351 rar_dev = pdev;
352 registered = 1;
353
354 /* Initialize the RAR parameters, which have to be retrieved */
355 /* via the message bus service */
356 error=memrar_init_rar_params(rar_dev);
357
358 if (error) {
359 DEBUG_PRINT_0(RAR_DEBUG_LEVEL_EXTENDED,
360 "error getting RAR addresses device\n");
361 registered = 0;
362 goto end_function;
363 }
364
365end_function:
366
367 return error;
368}
369
370/*
371 this function registers th driver to
372 the device subsystem( either PCI, USB, etc)
373*/
374static int __init rar_init_handler(void)
375{
376 return pci_register_driver(&rar_pci_driver);
377}
378
379static void __exit rar_exit_handler(void)
380{
381 pci_unregister_driver(&rar_pci_driver);
382}
383
384module_init(rar_init_handler);
385module_exit(rar_exit_handler);
386
387MODULE_LICENSE("GPL");
388
389
390/* The get_rar_address function is used by other device drivers
391 * to obtain RAR address information on a RAR. It takes two
392 * parameter:
393 *
394 * int rar_index
395 * The rar_index is an index to the rar for which you wish to retrieve
396 * the address information.
397 * Values can be 0,1, or 2.
398 *
399 * struct RAR_address_struct is a pointer to a place to which the function
400 * can return the address structure for the RAR.
401 *
402 * The function returns a 0 upon success or a -1 if there is no RAR
403 * facility on this system.
404 */
405int get_rar_address(int rar_index,struct RAR_address_struct *addresses)
406{
407 if (registered && (rar_index < 3) && (rar_index >= 0)) {
408 *addresses=rar_addr[rar_index];
409 /* strip off lock bit information */
410 addresses->low = addresses->low & 0xfffffff0;
411 addresses->high = addresses->high & 0xfffffff0;
412 return 0;
413 }
414
415 else {
416 return -ENODEV;
417 }
418}
419
420
421EXPORT_SYMBOL(get_rar_address);
422
423/* The lock_rar function is ued by other device drivers to lock an RAR.
424 * once an RAR is locked, it stays locked until the next system reboot.
425 * The function takes one parameter:
426 *
427 * int rar_index
428 * The rar_index is an index to the rar that you want to lock.
429 * Values can be 0,1, or 2.
430 *
431 * The function returns a 0 upon success or a -1 if there is no RAR
432 * facility on this system.
433 */
434int lock_rar(int rar_index)
435{
436 u32 working_addr;
437 int result;
438if (registered && (rar_index < 3) && (rar_index >= 0)) {
439 /* first make sure that lock bits are clear (this does lock) */
440 working_addr=rar_addr[rar_index].low & 0xfffffff0;
441
442 /* now send that value to the register using the IPC */
443 result=memrar_set_rar_addr(rar_dev,rar_index,working_addr);
444 return result;
445 }
446
447else {
448 return -ENODEV;
449 }
450}
diff --git a/drivers/staging/rar/rar_driver.h b/drivers/staging/rar/rar_driver.h
new file mode 100644
index 00000000000..3690f984ff5
--- /dev/null
+++ b/drivers/staging/rar/rar_driver.h
@@ -0,0 +1,99 @@
1/* === RAR Physical Addresses === */
2struct RAR_address_struct {
3 u32 low;
4 u32 high;
5};
6
7/* The get_rar_address function is used by other device drivers
8 * to obtain RAR address information on a RAR. It takes two
9 * parameter:
10 *
11 * int rar_index
12 * The rar_index is an index to the rar for which you wish to retrieve
13 * the address information.
14 * Values can be 0,1, or 2.
15 *
16 * struct RAR_address_struct is a pointer to a place to which the function
17 * can return the address structure for the RAR.
18 *
19 * The function returns a 0 upon success or a -1 if there is no RAR
20 * facility on this system.
21 */
22int get_rar_address(int rar_index,struct RAR_address_struct *addresses);
23
24
25/* The lock_rar function is ued by other device drivers to lock an RAR.
26 * once an RAR is locked, it stays locked until the next system reboot.
27 * The function takes one parameter:
28 *
29 * int rar_index
30 * The rar_index is an index to the rar that you want to lock.
31 * Values can be 0,1, or 2.
32 *
33 * The function returns a 0 upon success or a -1 if there is no RAR
34 * facility on this system.
35 */
36int lock_rar(int rar_index);
37
38
39/* DEBUG LEVEL MASKS */
40#define RAR_DEBUG_LEVEL_BASIC 0x1
41
42#define RAR_DEBUG_LEVEL_REGISTERS 0x2
43
44#define RAR_DEBUG_LEVEL_EXTENDED 0x4
45
46#define DEBUG_LEVEL 0x7
47
48/* FUNCTIONAL MACROS */
49
50/* debug macro without paramaters */
51#define DEBUG_PRINT_0(DEBUG_LEVEL , info) \
52do \
53{ \
54 if(DEBUG_LEVEL) \
55 { \
56 printk(KERN_WARNING info); \
57 } \
58}while(0)
59
60/* debug macro with 1 paramater */
61#define DEBUG_PRINT_1(DEBUG_LEVEL , info , param1) \
62do \
63{ \
64 if(DEBUG_LEVEL) \
65 { \
66 printk(KERN_WARNING info , param1); \
67 } \
68}while(0)
69
70/* debug macro with 2 paramaters */
71#define DEBUG_PRINT_2(DEBUG_LEVEL , info , param1, param2) \
72do \
73{ \
74 if(DEBUG_LEVEL) \
75 { \
76 printk(KERN_WARNING info , param1, param2); \
77 } \
78}while(0)
79
80/* debug macro with 3 paramaters */
81#define DEBUG_PRINT_3(DEBUG_LEVEL , info , param1, param2 , param3) \
82do \
83{ \
84 if(DEBUG_LEVEL) \
85 { \
86 printk(KERN_WARNING info , param1, param2 , param3); \
87 } \
88}while(0)
89
90/* debug macro with 4 paramaters */
91#define DEBUG_PRINT_4(DEBUG_LEVEL , info , param1, param2 , param3 , param4) \
92do \
93{ \
94 if(DEBUG_LEVEL) \
95 { \
96 printk(KERN_WARNING info , param1, param2 , param3 , param4); \
97 } \
98}while(0)
99