revert between 56095 -> 55830 in arch
[AROS.git] / rom / hidds / pci / doc / pci.en
bloba296252f3e7d15c96d93c7928c74cc014b20be7f
1 ===================
2 PCI class subsystem
3 ===================
5 :Author:    Michal Schulz
6 :Copyright: Copyright © 2004, The AROS Development Team
7 :Version:   $Revision$
8 :Date:      $Date$
10 .. Note::
12    This draft documentation shouldn't be actually here, but instead somewhere
13    within the doc tree.
16 The pci.hidd is a collection of classes used to maintain all PCI devices
17 available in the system. All device properties are available through
18 appropriate OOP_Object properties and should not be changed manually
19 (although this is still available through six public methods of the pcidriver
20 class).
22 How to find a PCI device?
23 ============================
24 In order to find a specified PCI device, the moHidd_PCI_EnumDevices method
25 of the main PCI class (IID_Hidd_PCI) is to be used.
26 It expects two parameters. The first one is a pointer to struct Hook,
27 which is defining a callback function that is called for every PCI device
28 and is trying to match the given requirements.
29 The second parameter (might be NULL) is a pointer to struct TagItem[].
30 This TagItem list is defining the search criteria that have to be met.
31 Any combination of VendorID, ProductID, RevisionID, Interface,
32 Class, Subclass, SubsystemVendorID, SubsystemID may be used (see
33 include/hidd/pci.h for details). If NULL is given instead, the callback
34 function will be called for every single PCI device seen by the pci class.
35 The following code may be used to find the PCI device:
37 /* This hook will be called for every PCI device that matches the given
38  * requirements */
40 AROS_UFH3(void, Callback,
41     AROS_UFHA(struct Hook *,    hook,   A0),
42     AROS_UFHA(OOP_Object *,     obj,    A2),
43     AROS_UFHA(APTR,             msg,    A1))
45     AROS_USERFUNC_INIT
47     /* Do whatever here with the PCIDevice object stored in obj pointer */
49     AROS_USERFUNC_EXIT
52 /* Hook defining our callback */
53 static const struct Hook PCIHook = {
54     h_Entry : (APTR)Callback
57 void Query()
59     OOP_Object *o;  /* Keep PCI class object */
61     /* Get only VGA compatible video cards */
62     struct TagItem tags[] = {
63         { tHidd_PCI_Class,      3 },
64         { tHidd_PCI_SubClass,   0 },
65         { tHidd_PCI_Interface,  0 },
66         { TAG_DONE, 0UL }
67     };
69     /* Create instance of pci class */
70     o = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
71     if (o)
72     {
73         /* Enumerate through all PCI devices */
74         HIDD_PCI_EnumDevices(o, &PCIHook, NULL);
75         /* Enumerate through devices who meet the requirements */
76         HIDD_PCI_EnumDevices(o, &PCIHook, &tags);
78         [do whatever you want with the PCI devices]
80         /* PCI object isn't needed anymore */
81         OOP_DisposeObject(o);
82     }
85 Simple, efficient, nice :)
87 What to do with PCI device object?
88 ==================================
89 Once the pointer to a pci device object is known, the PCI device may be asked
90 for its properties, and as well some of the device properties might be changed.
91 The Bus, Dev and Sub properties define the physical address of the PCI device,
92 as its seen by the bus driver who is handling the device (available as driver
93 property).
94 In case of PCI-to-PCI bridges (see isBridge property) some additional
95 properties are available. On the other hand some others, like base addresses
96 2 to 5 are not. The most commonly used are probably:
98     aHidd_PCIDevice_Base[0..5] - PCI base addresses of given device
99     aHidd_PCIDevice_Size[0..5] - sizes of PCI memory/IO areas
100     aHidd_PCIDevice_Type[0..5] - type of given area.
102 If bit ADDRB_IO in property Type is set to 1, the address region is an IO space
103 region. Otherwise it is a memory space region, which may be prefetchable memory.
104 The ADDRB_PREFETCH bit is set to 1 then (see includes/hidd/pci.h).
106 Additionally the driver may check if IO or memory space is decoded by a given
107 PCI device at all (isIO, isMEM properties), if the BusMaster flag has been
108 enabled (isMaster property) or if the device does snoop the PCI bus for VGA
109 palette changes (paletteSnoop property).
110 Finally, it is possible to check if the device supports 66MHz PCI (is66MHz).
112 Note that depending on driver requirements the isIO, isMEM, isMaster and
113 paletteSnoop properties may also be set.
115 All properties are obtainable through the OOP_GetAttr call (sigh, we are really
116 missing the OOP_GetAttrs(obj, struct TagItem
117 **attributes_to_get_with_one_call)!!!). Some of them are setable through the
118 OOP_SetAttrs call (see includes/hidd/pci.h for details). Please also remember
119 that before work with attributes is done, the IID_Hidd_PCIDevice AttrBase has
120 to be obtained (don't forget to release it when it's not needed anymore!).
122 PCIDriver class (user side)
123 ===========================
124 One of the read-only attributes of the PCIDevice class, is the PCIDriver class
125 pointer. It points to the hardware driver which handles the given PCI device
126 object. As you will see later, there might be more then one driver working in
127 the system at the same time.
129 The driver class has one important attribute - aHidd_PCIDriver_DirectBus. It
130 is read-only and if it is set to TRUE, the driver handles a PCI bus which is
131 directly mapped within the CPU space. A DirectBus device for example is a
132 typical PCI bus in a i386 PC handled by native AROS. A typical indirect PCI bus
133 is a PCI bus handled under Linux (there is no physical *direct* access to the
134 PCI devices with hosted AROS on Linux). Depending on the DirectBus property,
135 some methods may or must be used.
137 While working with a indirect PCI bus driver, the HIDD_PCIDriver_MapPCI and
138 HIDD_PCIDriver_UnmapPCI methods shall be used to access memory ranges of PCI
139 a device.
140 The first method tries to map PCI memory space to CPU memory space
141 (using for example mmap on /dev/mem in case of Linux) so that the given PCI
142 memory range can be accessed. The UnmapPCI method frees the mapping that was
143 created previously with this method.
145 Additionally AllocPCIMem and FreePCIMem can be used in order to allocate or
146 free memory that is accessible by PCI devices and is aligned to the memory page
147 boundary. If these methods are not implemented or there is
148 no memory available for PCI devices, AllocPCIMem will return (APTR)-1.
150 In case of DirectBus devices, the above called methods are still usable. The
151 MapPCI is then equivalent to the HIDD_PCIDriver_PCItoCPU call and simply
152 translates the address seen by the PCI device to an address seen by CPU.
153 HIDD_PCIDriver_CPUtoPCI is used for the other direction.
155 Driver creation
156 ===============
157 In order to write PCI hardware drivers one has to create a class derivateing
158 from the CLID_Hidd_PCIDriver class. That simplifies the work on a driver, as
159 only a few methods have to be implemented:
161 PCIDriver::New()
162 ----------------
163 This method should add some attributes to the msg->attrList and pass the ::New
164 message to the superclass. The aHidd_Name and aHidd_HardwareName are welcomed
165 here. If the driver only works with an indirect access bus, it must set the
166 aHidd_PCIDriver_DirectBus to FALSE (otherwise it will be set to TRUE by
167 the superclass).
169 Please note that in worst case (author doesn't want to provide aHidd_Name and
170 aHidd_HardwareName), the implementation of ::New can be skipped.
172 PCIDriver::ReadConfigLong() and PCIDriver::WriteConfigLong()
173 ------------------------------------------------------------
174 These two methods *HAVE TO* be defined in the driver class. Otherwise the
175 superclass will complain with error messages. All other methods who are used
176 to access the PCI config space (Read/Write of Word/Byte) can be implemented by
177 the driver class but don't have to.
178 As all methods are virtual, the superclass will do the magic (it will use
179 ReadConfigLong and WriteConfigLong methods to access words and bytes
180 in both read and write mode).
182 The MapPCI/UnmapPCI and CPUtoPCI/PCItoCPU calls may require rewriting (the
183 default is, that in case of indirect bus access they always return 0xffffffff
184 and in case of direct bus access they return the same address as they were
185 given).
187 Adding a driver class to the system
188 ---------------------------------
189 When the driver class was created successfully, it's pointer can be passed to
190 the main pci class. You may implement this like in the following example
191 (assume, that cl is a pointer to a freshly created driver class):
193 [...]
194     struct pHidd_PCI_AddHardwareDriver msg;
195     OOP_Object *pci;
196     
197     msg.driverClass = cl;
198     msg.mID = OOP_GetMethodID(IID_Hidd_PCI, moHidd_PCI_AddHardwareDriver);
200     pci = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
201     if (pci)
202     {
203         OOP_DoMethod(pci, (OOP_Msg)&msg);
204         OOP_DisposeObject(pci);
205     }
206 [...]
208 Done. The pci subsystem will then use the passed class pointer (note: thanks
209 to passing the class pointer directly, driver classes do not have to be public)
210 to scan the PCI bus handled by this hardware driver.
211 From this point PCI devices handled by the added driver are available for
212 any use.
214 Removing a driver class from the system
215 -------------------------------------
216 The driver may ask the PCI subsystem to get removed using the RemHardwareDriver 
217 call. The query may be, but doesn't have to be fulfilled. The driver will
218 not be removed if there are any other users of the PCI subsystem expect the
219 driver itself wanting to be removed. If the RemHardwareDriver call succeeds,
220 the driver class may be deleted.
222 Why do I need this plugable driver?
223 ------------------------------------
224 Imagine a PCI device (of any kind) which brings it's own PCI bus with it.
225 The device driver knows about this bus and wants to share it with other drivers
226 (system user). Unfortunately only this specific device driver knows how to
227 handle this additional PCI bus. When it creates a driver class which knows how
228 to talk to it and adds this driver class to the pci subsystem, this PCI bus
229 becomes part of whole system and from now on it is accessible for anyone.