瀏覽代碼

Extraced from 3c509.c

tags/v0.9.3
Michael Brown 19 年之前
父節點
當前提交
200b39a645
共有 2 個檔案被更改,包括 212 行新增0 行删除
  1. 136
    0
      src/drivers/bus/eisa.c
  2. 76
    0
      src/include/eisa.h

+ 136
- 0
src/drivers/bus/eisa.c 查看文件

@@ -0,0 +1,136 @@
1
+#include "etherboot.h"
2
+#include "dev.h"
3
+#include "io.h"
4
+#include "timer.h"
5
+#include "eisa.h"
6
+
7
+#define DEBUG_EISA
8
+
9
+#undef DBG
10
+#ifdef DEBUG_EISA
11
+#define DBG(...) printf ( __VA_ARGS__ )
12
+#else
13
+#define DBG(...)
14
+#endif
15
+
16
+/*
17
+ * Fill in parameters for an EISA device based on slot number
18
+ *
19
+ * Return 1 if device present, 0 otherwise
20
+ *
21
+ */
22
+static int fill_eisa_device ( struct eisa_device *eisa ) {
23
+	uint8_t present;
24
+
25
+	/* Set ioaddr */
26
+	eisa->ioaddr = EISA_SLOT_BASE ( eisa->slot );
27
+
28
+	/* Test for board present */
29
+	outb ( 0xff, eisa->ioaddr + EISA_MFG_ID_HI );
30
+	present = inb ( eisa->ioaddr + EISA_MFG_ID_HI );
31
+	if ( present & 0x80 ) {
32
+		/* No board present */
33
+		return 0;
34
+	}
35
+
36
+	/* Read mfg and product IDs.  Yes, the resulting uint16_ts
37
+	 * will be upside-down.  This appears to be by design.
38
+	 */
39
+	eisa->mfg_id = ( inb ( eisa->ioaddr + EISA_MFG_ID_LO ) << 8 )
40
+		+ present;
41
+	eisa->prod_id = ( inb ( eisa->ioaddr + EISA_PROD_ID_LO ) << 8 )
42
+		+ inb ( eisa->ioaddr + EISA_PROD_ID_HI );
43
+
44
+	DBG ( "EISA slot %d (base %#hx) ID %hx:%hx (\"%s\")\n",
45
+	      eisa->slot, eisa->ioaddr, eisa->mfg_id, eisa->prod_id,
46
+	      isa_id_string ( eisa->mfg_id, eisa->prod_id ) );
47
+
48
+	return 1;
49
+}
50
+
51
+/*
52
+ * Obtain a struct eisa * from a struct dev *
53
+ *
54
+ * If dev has not previously been used for an EISA device scan, blank
55
+ * out dev.eisa
56
+ */
57
+struct eisa_device * eisa_device ( struct dev *dev ) {
58
+	struct eisa_device *eisa = &dev->eisa;
59
+
60
+	if ( dev->devid.bus_type != EISA_BUS_TYPE ) {
61
+		memset ( eisa, 0, sizeof ( *eisa ) );
62
+		dev->devid.bus_type = EISA_BUS_TYPE;
63
+		eisa->slot = EISA_MIN_SLOT;
64
+	}
65
+	eisa->dev = dev;
66
+	return eisa;
67
+}
68
+
69
+/*
70
+ * Find an EISA device matching the specified driver
71
+ *
72
+ */
73
+int find_eisa_device ( struct eisa_device *eisa, struct eisa_driver *driver ) {
74
+	unsigned int i;
75
+
76
+	/* Iterate through all possible EISA slots, starting where we
77
+	 * left off/
78
+	 */
79
+	for ( ; eisa->slot <= EISA_MAX_SLOT ; eisa->slot++ ) {
80
+		/* If we've already used this device, skip it */
81
+		if ( eisa->already_tried ) {
82
+			eisa->already_tried = 0;
83
+			continue;
84
+		}
85
+
86
+		/* Fill in device parameters */
87
+		if ( ! fill_eisa_device ( eisa ) ) {
88
+			continue;
89
+		}
90
+
91
+		/* Compare against driver's ID list */
92
+		for ( i = 0 ; i < driver->id_count ; i++ ) {
93
+			struct eisa_id *id = &driver->ids[i];
94
+			
95
+			if ( ( eisa->mfg_id == id->mfg_id ) &&
96
+			     ( ISA_PROD_ID ( eisa->prod_id ) ==
97
+			       ISA_PROD_ID ( id->prod_id ) ) ) {
98
+				DBG ( "Device %s (driver %s) matches ID %s\n",
99
+				      id->name, driver->name,
100
+				      isa_id_string ( eisa->mfg_id,
101
+						      eisa->prod_id ) );
102
+				if ( eisa->dev ) {
103
+					eisa->dev->name = driver->name;
104
+					eisa->dev->devid.vendor_id
105
+						= eisa->mfg_id;
106
+					eisa->dev->devid.device_id
107
+						= eisa->prod_id;
108
+				}
109
+				eisa->already_tried = 1;
110
+				return 1;
111
+			}
112
+		}
113
+	}
114
+
115
+	/* No device found */
116
+	eisa->slot = EISA_MIN_SLOT;
117
+	return 0;
118
+}
119
+
120
+/*
121
+ * Reset and enable an EISA device
122
+ *
123
+ */
124
+void enable_eisa_device ( struct eisa_device *eisa ) {
125
+	/* Set reset line high for 1000 µs.  Spec says 500 µs, but
126
+	 * this doesn't work for all cards, so we are conservative.
127
+	 */
128
+	outb ( EISA_CMD_RESET, eisa->ioaddr + EISA_GLOBAL_CONFIG );
129
+	udelay ( 1000 ); /* Must wait 800 */
130
+
131
+	/* Set reset low and write a 1 to ENABLE.  Delay again, in
132
+	 * case the card takes a while to wake up.
133
+	 */
134
+	outb ( EISA_CMD_ENABLE, eisa->ioaddr + EISA_GLOBAL_CONFIG );
135
+	udelay ( 1000 ); /* Must wait 800 */
136
+}

+ 76
- 0
src/include/eisa.h 查看文件

@@ -0,0 +1,76 @@
1
+#ifndef EISA_H
2
+#define EISA_H
3
+
4
+#include "isa_ids.h"
5
+
6
+/*
7
+ * EISA constants
8
+ *
9
+ */
10
+
11
+#define EISA_MIN_SLOT (0x1)
12
+#define EISA_MAX_SLOT (0xf)
13
+#define EISA_SLOT_BASE( n ) ( 0x1000 * (n) )
14
+
15
+#define EISA_MFG_ID_HI ( 0xc80 )
16
+#define EISA_MFG_ID_LO ( 0xc81 )
17
+#define EISA_PROD_ID_HI ( 0xc82 )
18
+#define EISA_PROD_ID_LO ( 0xc83 )
19
+#define EISA_GLOBAL_CONFIG ( 0xc84 )
20
+
21
+#define EISA_CMD_RESET ( 1 << 2 )
22
+#define EISA_CMD_ENABLE ( 1 << 0 )
23
+
24
+/*
25
+ * A physical EISA device
26
+ *
27
+ */
28
+struct dev;
29
+struct eisa_device {
30
+	struct dev *dev;
31
+	unsigned int slot;
32
+	uint16_t ioaddr;
33
+	uint16_t mfg_id;
34
+	uint16_t prod_id;
35
+	int already_tried;
36
+};
37
+
38
+/*
39
+ * An individual EISA device identified by ID
40
+ *
41
+ */
42
+struct eisa_id {
43
+        const char *name;
44
+	uint16_t mfg_id, prod_id;
45
+};
46
+
47
+/*
48
+ * An EISA driver, with a device ID (struct eisa_id) table.
49
+ *
50
+ */
51
+struct eisa_driver {
52
+	const char *name;
53
+	struct eisa_id *ids;
54
+	unsigned int id_count;
55
+};
56
+
57
+/*
58
+ * Define an EISA driver
59
+ *
60
+ */
61
+#define EISA_DRIVER( driver_name, eisa_ids ) {				\
62
+	.name = driver_name,						\
63
+	.ids = eisa_ids,						\
64
+	.id_count = sizeof ( eisa_ids ) / sizeof ( eisa_ids[0] ),	\
65
+}
66
+
67
+/*
68
+ * Functions in eisa.c
69
+ *
70
+ */
71
+extern struct eisa_device * eisa_device ( struct dev *dev );
72
+extern int find_eisa_device ( struct eisa_device *eisa,
73
+			      struct eisa_driver *driver );
74
+extern void enable_eisa_device ( struct eisa_device *eisa );
75
+
76
+#endif /* EISA_H */

Loading…
取消
儲存