|
|
1.1 root 1: /* This is a total crock of shit. */
2:
3: #include "ds_oskit.h"
4:
5: #include <oskit/error.h>
6: #include <oskit/dev/bus.h>
7:
8: #include <vm/vm_map.h>
9: #include <vm/vm_kern.h>
10: #include <vm/vm_page.h>
11:
12: #include <string.h>
13:
14:
15: oskit_error_t
16: populate_bus (device_t dev, oskit_bus_t *bus)
17: {
18: kern_return_t kr;
19: oskit_error_t rc;
20: unsigned int i;
21: char *p;
22:
23: /* First, we probe the bus so it knows what devices are on it. */
24: rc = oskit_bus_probe (bus);
25: if (OSKIT_FAILED (rc) && rc != OSKIT_E_NOTIMPL)
26: return rc;
27:
28: /* Next, we will get a page of kernel memory to hold our ridiculous
29: text representation of the bus's device list. */
30:
31: kr = kmem_alloc_pageable (kernel_map, (vm_offset_t *) &dev->com.bus.contents,
32: PAGE_SIZE);
33: if (kr)
34: return OSKIT_E_OUTOFMEMORY;
35:
36: p = dev->com.bus.contents;
37: i = 0;
38: do
39: {
40: inline void append (char sep, const char *str)
41: {
42: extern char *stpcpy (char *, const char *);
43: if (str)
44: {
45: *p++ = sep;
46: p = stpcpy (p, str);
47: }
48: }
49:
50: char pos[OSKIT_BUS_POS_MAX];
51: oskit_device_t *child;
52: oskit_devinfo_t info;
53:
54: rc = oskit_bus_getchild (bus, i++, &child, pos);
55: if (rc == OSKIT_E_DEV_NOMORE_CHILDREN)
56: break;
57: if (OSKIT_SUCCEEDED (rc))
58: {
59: rc = oskit_device_getinfo (child, &info);
60: oskit_device_release (child);
61: }
62: if (OSKIT_FAILED (rc))
63: {
64: kmem_free (kernel_map,
65: (vm_offset_t) dev->com.bus.contents, PAGE_SIZE);
66: return rc;
67: }
68:
69: append ('@', pos);
70: append (':', info.name);
71: append ('=', info.description);
72: append (';', info.author);
73: append ('/', info.version);
74: *p++ = '\n';
75:
76: assert (p < dev->com.bus.contents + PAGE_SIZE);
77: } while (rc == 0);
78:
79: dev->com.bus.size = p - dev->com.bus.contents;
80: memset (p, 0, PAGE_SIZE - dev->com.bus.size);
81:
82: return 0;
83: }
84:
85: void
86: ds_bus_close (device_t dev)
87: {
88: kmem_free (kernel_map, (vm_offset_t) dev->com.bus.contents, PAGE_SIZE);
89: }
90:
91: io_return_t
92: ds_bus_read (device_t dev, ipc_port_t reply_port,
93: mach_msg_type_name_t reply_port_type, dev_mode_t mode,
94: recnum_t recnum, int count, io_buf_ptr_t *data,
95: unsigned *bytes_read)
96: {
97: if (recnum % PAGE_SIZE != 0)
98: return D_INVALID_OPERATION; /* let generic code use inband read */
99:
100: if (recnum + count > dev->com.bus.size)
101: INVALREC;
102:
103: if (count == 0)
104: {
105: *bytes_read = 0;
106: return D_SUCCESS;
107: }
108:
109: *bytes_read = count;
110: return vm_map_copyin_page_list (kernel_map,
111: (vm_offset_t) dev->com.bus.contents + recnum,
112: round_page (count),
113: FALSE, FALSE, (vm_map_copy_t *) data,
114: FALSE);
115: }
116:
117: io_return_t
118: ds_bus_read_inband (device_t dev, ipc_port_t reply_port,
119: mach_msg_type_name_t reply_port_type, dev_mode_t mode,
120: recnum_t recnum, int count, char *data,
121: unsigned *bytes_read)
122: {
123: if (recnum + count > dev->com.bus.size)
124: INVALREC;
125: memcpy (data, dev->com.bus.contents + recnum, count);
126: *bytes_read = count;
127: return D_SUCCESS;
128: }
129:
130: io_return_t
131: ds_bus_get_status (device_t dev, dev_flavor_t flavor, dev_status_t status,
132: mach_msg_type_number_t *status_count)
133: {
134: switch (flavor)
135: {
136: case DEV_GET_SIZE:
137: status[DEV_GET_SIZE_RECORD_SIZE] = 1;
138: status[DEV_GET_SIZE_DEVICE_SIZE] = dev->com.bus.size;
139: *status_count = 2;
140: return D_SUCCESS;
141: }
142: INVALOP;
143: }
144:
145:
146: const struct device_ops bus_device_ops =
147: {
148: read_inband: ds_bus_read_inband,
149: read: ds_bus_read,
150: get_status: ds_bus_get_status,
151: close: ds_bus_close
152: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.