Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 1 | ================ |
| 2 | EISA bus support |
| 3 | ================ |
| 4 | |
| 5 | :Author: Marc Zyngier <maz@wild-wind.fr.eu.org> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6 | |
| 7 | This document groups random notes about porting EISA drivers to the |
| 8 | new EISA/sysfs API. |
| 9 | |
| 10 | Starting from version 2.5.59, the EISA bus is almost given the same |
| 11 | status as other much more mainstream busses such as PCI or USB. This |
| 12 | has been possible through sysfs, which defines a nice enough set of |
| 13 | abstractions to manage busses, devices and drivers. |
| 14 | |
| 15 | Although the new API is quite simple to use, converting existing |
| 16 | drivers to the new infrastructure is not an easy task (mostly because |
| 17 | detection code is generally also used to probe ISA cards). Moreover, |
| 18 | most EISA drivers are among the oldest Linux drivers so, as you can |
| 19 | imagine, some dust has settled here over the years. |
| 20 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 21 | The EISA infrastructure is made up of three parts: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 22 | |
| 23 | - The bus code implements most of the generic code. It is shared |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 24 | among all the architectures that the EISA code runs on. It |
| 25 | implements bus probing (detecting EISA cards available on the bus), |
| 26 | allocates I/O resources, allows fancy naming through sysfs, and |
| 27 | offers interfaces for driver to register. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 28 | |
| 29 | - The bus root driver implements the glue between the bus hardware |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 30 | and the generic bus code. It is responsible for discovering the |
| 31 | device implementing the bus, and setting it up to be latter probed |
| 32 | by the bus code. This can go from something as simple as reserving |
| 33 | an I/O region on x86, to the rather more complex, like the hppa |
| 34 | EISA code. This is the part to implement in order to have EISA |
| 35 | running on an "new" platform. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 36 | |
| 37 | - The driver offers the bus a list of devices that it manages, and |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 38 | implements the necessary callbacks to probe and release devices |
| 39 | whenever told to. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 40 | |
| 41 | Every function/structure below lives in <linux/eisa.h>, which depends |
| 42 | heavily on <linux/device.h>. |
| 43 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 44 | Bus root driver |
| 45 | =============== |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 46 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 47 | :: |
| 48 | |
| 49 | int eisa_root_register (struct eisa_root_device *root); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 50 | |
| 51 | The eisa_root_register function is used to declare a device as the |
| 52 | root of an EISA bus. The eisa_root_device structure holds a reference |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 53 | to this device, as well as some parameters for probing purposes:: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 54 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 55 | struct eisa_root_device { |
| 56 | struct device *dev; /* Pointer to bridge device */ |
| 57 | struct resource *res; |
| 58 | unsigned long bus_base_addr; |
| 59 | int slots; /* Max slot number */ |
| 60 | int force_probe; /* Probe even when no slot 0 */ |
| 61 | u64 dma_mask; /* from bridge device */ |
| 62 | int bus_nr; /* Set by eisa_root_register */ |
| 63 | struct resource eisa_root_res; /* ditto */ |
| 64 | }; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 65 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 66 | ============= ====================================================== |
| 67 | node used for eisa_root_register internal purpose |
| 68 | dev pointer to the root device |
| 69 | res root device I/O resource |
| 70 | bus_base_addr slot 0 address on this bus |
| 71 | slots max slot number to probe |
| 72 | force_probe Probe even when slot 0 is empty (no EISA mainboard) |
| 73 | dma_mask Default DMA mask. Usually the bridge device dma_mask. |
| 74 | bus_nr unique bus id, set by eisa_root_register |
| 75 | ============= ====================================================== |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 76 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 77 | Driver |
| 78 | ====== |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 79 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 80 | :: |
| 81 | |
| 82 | int eisa_driver_register (struct eisa_driver *edrv); |
| 83 | void eisa_driver_unregister (struct eisa_driver *edrv); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 84 | |
| 85 | Clear enough ? |
| 86 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 87 | :: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 88 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 89 | struct eisa_device_id { |
| 90 | char sig[EISA_SIG_LEN]; |
| 91 | unsigned long driver_data; |
| 92 | }; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 93 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 94 | struct eisa_driver { |
| 95 | const struct eisa_device_id *id_table; |
| 96 | struct device_driver driver; |
| 97 | }; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 98 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 99 | =============== ==================================================== |
| 100 | id_table an array of NULL terminated EISA id strings, |
| 101 | followed by an empty string. Each string can |
| 102 | optionally be paired with a driver-dependent value |
| 103 | (driver_data). |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 104 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 105 | driver a generic driver, such as described in |
| 106 | Documentation/driver-model/driver.txt. Only .name, |
| 107 | .probe and .remove members are mandatory. |
| 108 | =============== ==================================================== |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 109 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 110 | An example is the 3c59x driver:: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 111 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 112 | static struct eisa_device_id vortex_eisa_ids[] = { |
| 113 | { "TCM5920", EISA_3C592_OFFSET }, |
| 114 | { "TCM5970", EISA_3C597_OFFSET }, |
| 115 | { "" } |
| 116 | }; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 117 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 118 | static struct eisa_driver vortex_eisa_driver = { |
| 119 | .id_table = vortex_eisa_ids, |
| 120 | .driver = { |
| 121 | .name = "3c59x", |
| 122 | .probe = vortex_eisa_probe, |
| 123 | .remove = vortex_eisa_remove |
| 124 | } |
| 125 | }; |
| 126 | |
| 127 | Device |
| 128 | ====== |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 129 | |
| 130 | The sysfs framework calls .probe and .remove functions upon device |
| 131 | discovery and removal (note that the .remove function is only called |
| 132 | when driver is built as a module). |
| 133 | |
| 134 | Both functions are passed a pointer to a 'struct device', which is |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 135 | encapsulated in a 'struct eisa_device' described as follows:: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 136 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 137 | struct eisa_device { |
| 138 | struct eisa_device_id id; |
| 139 | int slot; |
| 140 | int state; |
| 141 | unsigned long base_addr; |
| 142 | struct resource res[EISA_MAX_RESOURCES]; |
| 143 | u64 dma_mask; |
| 144 | struct device dev; /* generic device */ |
| 145 | }; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 146 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 147 | ======== ============================================================ |
| 148 | id EISA id, as read from device. id.driver_data is set from the |
| 149 | matching driver EISA id. |
| 150 | slot slot number which the device was detected on |
| 151 | state set of flags indicating the state of the device. Current |
| 152 | flags are EISA_CONFIG_ENABLED and EISA_CONFIG_FORCED. |
| 153 | res set of four 256 bytes I/O regions allocated to this device |
| 154 | dma_mask DMA mask set from the parent device. |
| 155 | dev generic device (see Documentation/driver-model/device.txt) |
| 156 | ======== ============================================================ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 157 | |
| 158 | You can get the 'struct eisa_device' from 'struct device' using the |
| 159 | 'to_eisa_device' macro. |
| 160 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 161 | Misc stuff |
| 162 | ========== |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 163 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 164 | :: |
| 165 | |
| 166 | void eisa_set_drvdata (struct eisa_device *edev, void *data); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 167 | |
| 168 | Stores data into the device's driver_data area. |
| 169 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 170 | :: |
| 171 | |
| 172 | void *eisa_get_drvdata (struct eisa_device *edev): |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 173 | |
| 174 | Gets the pointer previously stored into the device's driver_data area. |
| 175 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 176 | :: |
| 177 | |
| 178 | int eisa_get_region_index (void *addr); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 179 | |
| 180 | Returns the region number (0 <= x < EISA_MAX_RESOURCES) of a given |
| 181 | address. |
| 182 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 183 | Kernel parameters |
| 184 | ================= |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 185 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 186 | eisa_bus.enable_dev |
| 187 | A comma-separated list of slots to be enabled, even if the firmware |
| 188 | set the card as disabled. The driver must be able to properly |
| 189 | initialize the device in such conditions. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 190 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 191 | eisa_bus.disable_dev |
| 192 | A comma-separated list of slots to be enabled, even if the firmware |
| 193 | set the card as enabled. The driver won't be called to handle this |
| 194 | device. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 195 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 196 | virtual_root.force_probe |
| 197 | Force the probing code to probe EISA slots even when it cannot find an |
| 198 | EISA compliant mainboard (nothing appears on slot 0). Defaults to 0 |
| 199 | (don't force), and set to 1 (force probing) when either |
| 200 | CONFIG_ALPHA_JENSEN or CONFIG_EISA_VLB_PRIMING are set. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 201 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 202 | Random notes |
| 203 | ============ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 204 | |
| 205 | Converting an EISA driver to the new API mostly involves *deleting* |
| 206 | code (since probing is now in the core EISA code). Unfortunately, most |
Paul Gortmaker | bb8187d | 2012-05-17 19:06:13 -0400 | [diff] [blame] | 207 | drivers share their probing routine between ISA, and EISA. Special |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 208 | care must be taken when ripping out the EISA code, so other busses |
| 209 | won't suffer from these surgical strikes... |
| 210 | |
| 211 | You *must not* expect any EISA device to be detected when returning |
| 212 | from eisa_driver_register, since the chances are that the bus has not |
| 213 | yet been probed. In fact, that's what happens most of the time (the |
| 214 | bus root driver usually kicks in rather late in the boot process). |
| 215 | Unfortunately, most drivers are doing the probing by themselves, and |
| 216 | expect to have explored the whole machine when they exit their probe |
| 217 | routine. |
| 218 | |
| 219 | For example, switching your favorite EISA SCSI card to the "hotplug" |
| 220 | model is "the right thing"(tm). |
| 221 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 222 | Thanks |
| 223 | ====== |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 224 | |
Mauro Carvalho Chehab | 72fd15c | 2017-05-14 13:27:55 -0300 | [diff] [blame] | 225 | I'd like to thank the following people for their help: |
| 226 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 227 | - Xavier Benigni for lending me a wonderful Alpha Jensen, |
| 228 | - James Bottomley, Jeff Garzik for getting this stuff into the kernel, |
| 229 | - Andries Brouwer for contributing numerous EISA ids, |
| 230 | - Catrin Jones for coping with far too many machines at home. |