1c3a7c13e97b8db3dc509de2f4d3d658bf204ce9
[tpg/acess2.git] / KernelLand / Modules / Interfaces / UDI / trans / bus_pci.c
1 /*
2  * Acess2 UDI Layer
3  * - By John Hodge (thePowersGang)
4  *
5  * trans/bus_pci.c
6  * - PCI Bus Driver
7  */
8 #include <udi.h>
9 #include <udi_physio.h>
10 #include <udi_pci.h>
11 #include <acess.h>
12 #include <drv_pci.h>    // acess
13 #include "../udi_internal.h"
14
15 // === MACROS ===
16 /* Copied from http://projectudi.cvs.sourceforge.net/viewvc/projectudi/udiref/driver/udi_dpt/udi_dpt.h */
17 #define DPT_SET_ATTR_BOOLEAN(attr, name, val)   \
18                 udi_strcpy((attr)->attr_name, (name)); \
19                 (attr)->attr_type = UDI_ATTR_BOOLEAN; \
20                 (attr)->attr_length = sizeof(udi_boolean_t); \
21                 UDI_ATTR32_SET((attr)->attr_value, (val))
22
23 #define DPT_SET_ATTR32(attr, name, val) \
24                 udi_strcpy((attr)->attr_name, (name)); \
25                 (attr)->attr_type = UDI_ATTR_UBIT32; \
26                 (attr)->attr_length = sizeof(udi_ubit32_t); \
27                 UDI_ATTR32_SET((attr)->attr_value, (val))
28
29 #define DPT_SET_ATTR_ARRAY8(attr, name, val, len) \
30                 udi_strcpy((attr)->attr_name, (name)); \
31                 (attr)->attr_type = UDI_ATTR_ARRAY8; \
32                 (attr)->attr_length = (len); \
33                 udi_memcpy((attr)->attr_value, (val), (len))
34
35 #define DPT_SET_ATTR_STRING(attr, name, val, len) \
36                 udi_strcpy((attr)->attr_name, (name)); \
37                 (attr)->attr_type = UDI_ATTR_STRING; \
38                 (attr)->attr_length = (len); \
39                 udi_strncpy_rtrim((char *)(attr)->attr_value, (val), (len))
40
41
42 // === TYPES ===
43 typedef struct
44 {
45         udi_init_context_t      init_context;
46         
47         tPCIDev cur_iter;
48 } pci_rdata_t;
49
50 // === PROTOTYPES ===
51 void    pci_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level);
52 void    pci_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level);
53 void    pci_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID);
54 void    pci_final_cleanup_req(udi_mgmt_cb_t *cb);
55
56 void    pci_bridge_ch_event_ind(udi_channel_event_cb_t *cb);
57 void    pci_unbind_req(udi_bus_bind_cb_t *cb);
58 void    pci_bind_req_op(udi_bus_bind_cb_t *cb);
59 void    pci_intr_attach_req(udi_intr_attach_cb_t *cb);
60 void    pci_intr_detach_req(udi_intr_detach_cb_t *cb);
61
62 // - Hook to physio (UDI doesn't define these)
63  int    pci_pio_get_regset(udi_cb_t *gcb, udi_ubit32_t regset_idx, void **baseptr, size_t *lenptr);
64
65 // === CODE ===
66 void pci_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level)
67 {
68         pci_rdata_t     *rdata = UDI_GCB(cb)->context;
69         
70         switch(cb->meta_idx)
71         {
72         case 1: // mgmt
73                 break;
74         }
75
76         switch(resource_level)
77         {
78         case UDI_RESOURCES_CRITICAL:
79         case UDI_RESOURCES_LOW:
80         case UDI_RESOURCES_NORMAL:
81         case UDI_RESOURCES_PLENTIFUL:
82                 break;
83         }
84
85         // TODO: Initialise rdata
86         rdata->cur_iter = -1;
87
88         udi_usage_res(cb);
89 }
90 void pci_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level)
91 {
92         pci_rdata_t     *rdata = UDI_GCB(cb)->context;
93         switch(enumeration_level)
94         {
95         case UDI_ENUMERATE_START:
96         case UDI_ENUMERATE_START_RESCAN:
97                 rdata->cur_iter = -1;
98         case UDI_ENUMERATE_NEXT:
99                 // TODO: Filters
100                 if( (rdata->cur_iter = PCI_GetDeviceByClass(0,0, rdata->cur_iter)) == -1 )
101                 {
102                         udi_enumerate_ack(cb, UDI_ENUMERATE_DONE, 0);
103                 }
104                 else
105                 {
106                         udi_instance_attr_list_t *attr_list = cb->attr_list;
107                         Uint16  ven, dev;
108                         Uint32  class;
109                         PCI_GetDeviceInfo(rdata->cur_iter, &ven, &dev, &class);
110                         Uint8   revision;
111                         PCI_GetDeviceVersion(rdata->cur_iter, &revision);
112                         Uint16  sven, sdev;
113                         PCI_GetDeviceSubsys(rdata->cur_iter, &sven, &sdev);
114
115                         udi_strcpy(attr_list->attr_name, "identifier");
116                         attr_list->attr_length = sprintf((char*)attr_list->attr_value,
117                                 "%04x%04x%02x%04x%04x",
118                                 ven, dev, revision, sven, sdev);
119                         attr_list ++;
120                         DPT_SET_ATTR_STRING(attr_list, "bus_type", "pci", 3);
121                         attr_list ++;
122                         DPT_SET_ATTR32(attr_list, "pci_vendor_id", ven);
123                         attr_list ++;
124                         DPT_SET_ATTR32(attr_list, "pci_device_id", dev);
125                         attr_list ++;
126
127                         cb->attr_valid_length = attr_list - cb->attr_list;
128                         cb->child_ID = rdata->cur_iter;
129                         udi_enumerate_ack(cb, UDI_ENUMERATE_OK, 1);
130                 }
131                 break;
132         }
133 }
134 void pci_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID)
135 {
136         UNIMPLEMENTED();
137 }
138 void pci_final_cleanup_req(udi_mgmt_cb_t *cb)
139 {
140         UNIMPLEMENTED();
141 }
142
143 void pci_bridge_ch_event_ind(udi_channel_event_cb_t *cb)
144 {
145         UNIMPLEMENTED();
146 }
147 void pci_bind_req(udi_bus_bind_cb_t *cb)
148 {
149         // TODO: "Lock" PCI device
150
151         // TODO: DMA constraints
152         udi_bus_bind_ack(cb, 0, UDI_DMA_LITTLE_ENDIAN, UDI_OK);
153 }
154 void pci_unbind_req(udi_bus_bind_cb_t *cb)
155 {
156         UNIMPLEMENTED();
157 }
158 void pci_intr_attach_req(udi_intr_attach_cb_t *cb)
159 {
160         // Create a channel
161         //udi_channel_spawn(, UCI_GCB(cb), cb->gcb.channel, 0, PCI_OPS_IRQ, NULL);
162         UNIMPLEMENTED();
163 }
164 void pci_intr_detach_req(udi_intr_detach_cb_t *cb)
165 {
166         UNIMPLEMENTED();
167 }
168
169 // - physio hooks
170 udi_status_t pci_pio_do_io(uint32_t child_ID, udi_ubit32_t regset_idx, udi_ubit32_t ofs, udi_ubit8_t len,
171         void *data, bool isOutput)
172 {
173         tPCIDev pciid = child_ID;
174         // TODO: Cache child mappings   
175
176         switch(regset_idx)
177         {
178         case UDI_PCI_CONFIG_SPACE:
179                 // TODO:
180                 return UDI_STAT_NOT_SUPPORTED;
181         case UDI_PCI_BAR_0 ... UDI_PCI_BAR_5: {
182                 Uint64 bar = PCI_GetBAR(pciid, regset_idx);
183                 if(bar & 1)
184                 {
185                         // IO BAR
186                         bar &= ~3;
187                         #define _IO(fc, type) do {\
188                                 if( isOutput )  out##fc(bar+ofs, *(type*)data); \
189                                 else    *(type*)data = in##fc(bar+ofs); \
190                                 } while(0)
191                         switch(len)
192                         {
193                         case UDI_PIO_1BYTE:     _IO(b, udi_ubit8_t);    return UDI_OK;
194                         case UDI_PIO_2BYTE:     _IO(w, udi_ubit16_t);   return UDI_OK;
195                         case UDI_PIO_4BYTE:     _IO(d, udi_ubit32_t);   return UDI_OK;
196                         //case UDI_PIO_8BYTE:   _IO(q, uint64_t);       return UDI_OK;
197                         default:
198                                 return UDI_STAT_NOT_SUPPORTED;
199                         }
200                         #undef _IO
201                 }
202                 else
203                 {
204                         // Memory BAR
205                         bar = PCI_GetValidBAR(pciid, regset_idx, PCI_BARTYPE_MEM);
206                         return UDI_STAT_NOT_SUPPORTED;
207                 }
208                 break; }
209         default:
210                 return UDI_STAT_NOT_UNDERSTOOD;
211         }
212 }
213
214 // === UDI Functions ===
215 udi_mgmt_ops_t  pci_mgmt_ops = {
216         pci_usage_ind,
217         pci_enumerate_req,
218         pci_devmgmt_req,
219         pci_final_cleanup_req
220 };
221 udi_ubit8_t     pci_mgmt_op_flags[4] = {0,0,0,0};
222 udi_bus_bridge_ops_t    pci_bridge_ops = {
223         pci_bridge_ch_event_ind,
224         pci_bind_req,
225         pci_unbind_req,
226         pci_intr_attach_req,
227         pci_intr_detach_req
228 };
229 udi_ubit8_t     pci_bridge_op_flags[5] = {0,0,0,0,0};
230 udi_primary_init_t      pci_pri_init = {
231         .mgmt_ops = &pci_mgmt_ops,
232         .mgmt_op_flags = pci_mgmt_op_flags,
233         .mgmt_scratch_requirement = 0,
234         .enumeration_attr_list_length = 4,
235         .rdata_size = sizeof(pci_rdata_t),
236         .child_data_size = 0,
237         .per_parent_paths = 0
238 };
239 udi_ops_init_t  pci_ops_list[] = {
240         {
241                 1, 1, UDI_BUS_BRIDGE_OPS_NUM,
242                 sizeof(udi_child_chan_context_t),
243                 (udi_ops_vector_t*)&pci_bridge_ops,
244                 pci_bridge_op_flags
245         },
246         {0}
247 };
248 udi_init_t      pci_init = {
249         .primary_init_info = &pci_pri_init,
250         .ops_init_list = pci_ops_list
251 };
252 const char      pci_udiprops[] =
253         "properties_version 0x101\0"
254         "message 1 Acess2 Kernel\0"
255         "message 2 John Hodge ([email protected])\0"
256         "message 3 Acess2 PCI Bus\0"
257         "supplier 1\0"
258         "contact 2\0"
259         "name 3\0"
260         "module acess_pci\0"
261         "shortname acesspci\0"
262         "requires udi 0x101\0"
263         "provides udi_bridge 0x101\0"
264         "meta 1 udi_bridge\0"
265         "enumerates 4 0 100 1 bus_name string pci\0"
266         "region 0\0"
267         "child_bind_ops 1 0 1\0"
268         "";
269 size_t  pci_udiprops_size = sizeof(pci_udiprops);

UCC git Repository :: git.ucc.asn.au