Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /******************************************************************************* |
| 2 | * |
| 3 | * (c) 1998 by Computone Corporation |
| 4 | * |
| 5 | ******************************************************************************** |
| 6 | * |
| 7 | * |
| 8 | * PACKAGE: Linux tty Device Driver for IntelliPort family of multiport |
| 9 | * serial I/O controllers. |
| 10 | * |
| 11 | * DESCRIPTION: Low-level interface code for the device driver |
| 12 | * (This is included source code, not a separate compilation |
| 13 | * module.) |
| 14 | * |
| 15 | *******************************************************************************/ |
| 16 | //--------------------------------------------- |
| 17 | // Function declarations private to this module |
| 18 | //--------------------------------------------- |
| 19 | // Functions called only indirectly through i2eBordStr entries. |
| 20 | |
| 21 | static int iiWriteBuf16(i2eBordStrPtr, unsigned char *, int); |
| 22 | static int iiWriteBuf8(i2eBordStrPtr, unsigned char *, int); |
| 23 | static int iiReadBuf16(i2eBordStrPtr, unsigned char *, int); |
| 24 | static int iiReadBuf8(i2eBordStrPtr, unsigned char *, int); |
| 25 | |
| 26 | static unsigned short iiReadWord16(i2eBordStrPtr); |
| 27 | static unsigned short iiReadWord8(i2eBordStrPtr); |
| 28 | static void iiWriteWord16(i2eBordStrPtr, unsigned short); |
| 29 | static void iiWriteWord8(i2eBordStrPtr, unsigned short); |
| 30 | |
| 31 | static int iiWaitForTxEmptyII(i2eBordStrPtr, int); |
| 32 | static int iiWaitForTxEmptyIIEX(i2eBordStrPtr, int); |
| 33 | static int iiTxMailEmptyII(i2eBordStrPtr); |
| 34 | static int iiTxMailEmptyIIEX(i2eBordStrPtr); |
| 35 | static int iiTrySendMailII(i2eBordStrPtr, unsigned char); |
| 36 | static int iiTrySendMailIIEX(i2eBordStrPtr, unsigned char); |
| 37 | |
| 38 | static unsigned short iiGetMailII(i2eBordStrPtr); |
| 39 | static unsigned short iiGetMailIIEX(i2eBordStrPtr); |
| 40 | |
| 41 | static void iiEnableMailIrqII(i2eBordStrPtr); |
| 42 | static void iiEnableMailIrqIIEX(i2eBordStrPtr); |
| 43 | static void iiWriteMaskII(i2eBordStrPtr, unsigned char); |
| 44 | static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char); |
| 45 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 46 | static void ii2Nop(void); |
| 47 | |
| 48 | //*************** |
| 49 | //* Static Data * |
| 50 | //*************** |
| 51 | |
| 52 | static int ii2Safe; // Safe I/O address for delay routine |
| 53 | |
| 54 | static int iiDelayed; // Set when the iiResetDelay function is |
| 55 | // called. Cleared when ANY board is reset. |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 56 | static DEFINE_RWLOCK(Dl_spinlock); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 57 | |
| 58 | //******** |
| 59 | //* Code * |
| 60 | //******** |
| 61 | |
| 62 | //======================================================= |
| 63 | // Initialization Routines |
| 64 | // |
| 65 | // iiSetAddress |
| 66 | // iiReset |
| 67 | // iiResetDelay |
| 68 | // iiInitialize |
| 69 | //======================================================= |
| 70 | |
| 71 | //****************************************************************************** |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 72 | // Function: iiSetAddress(pB, address, delay) |
| 73 | // Parameters: pB - pointer to the board structure |
| 74 | // address - the purported I/O address of the board |
| 75 | // delay - pointer to the 1-ms delay function to use |
| 76 | // in this and any future operations to this board |
| 77 | // |
| 78 | // Returns: True if everything appears copacetic. |
| 79 | // False if there is any error: the pB->i2eError field has the error |
| 80 | // |
| 81 | // Description: |
| 82 | // |
| 83 | // This routine (roughly) checks for address validity, sets the i2eValid OK and |
| 84 | // sets the state to II_STATE_COLD which means that we haven't even sent a reset |
| 85 | // yet. |
| 86 | // |
| 87 | //****************************************************************************** |
| 88 | static int |
| 89 | iiSetAddress( i2eBordStrPtr pB, int address, delayFunc_t delay ) |
| 90 | { |
| 91 | // Should any failure occur before init is finished... |
| 92 | pB->i2eValid = I2E_INCOMPLETE; |
| 93 | |
| 94 | // Cannot check upper limit except extremely: Might be microchannel |
| 95 | // Address must be on an 8-byte boundary |
| 96 | |
| 97 | if ((unsigned int)address <= 0x100 |
| 98 | || (unsigned int)address >= 0xfff8 |
| 99 | || (address & 0x7) |
| 100 | ) |
| 101 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 102 | I2_COMPLETE(pB, I2EE_BADADDR); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | // Initialize accelerators |
| 106 | pB->i2eBase = address; |
| 107 | pB->i2eData = address + FIFO_DATA; |
| 108 | pB->i2eStatus = address + FIFO_STATUS; |
| 109 | pB->i2ePointer = address + FIFO_PTR; |
| 110 | pB->i2eXMail = address + FIFO_MAIL; |
| 111 | pB->i2eXMask = address + FIFO_MASK; |
| 112 | |
| 113 | // Initialize i/o address for ii2DelayIO |
| 114 | ii2Safe = address + FIFO_NOP; |
| 115 | |
| 116 | // Initialize the delay routine |
| 117 | pB->i2eDelay = ((delay != (delayFunc_t)NULL) ? delay : (delayFunc_t)ii2Nop); |
| 118 | |
| 119 | pB->i2eValid = I2E_MAGIC; |
| 120 | pB->i2eState = II_STATE_COLD; |
| 121 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 122 | I2_COMPLETE(pB, I2EE_GOOD); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 123 | } |
| 124 | |
| 125 | //****************************************************************************** |
| 126 | // Function: iiReset(pB) |
| 127 | // Parameters: pB - pointer to the board structure |
| 128 | // |
| 129 | // Returns: True if everything appears copacetic. |
| 130 | // False if there is any error: the pB->i2eError field has the error |
| 131 | // |
| 132 | // Description: |
| 133 | // |
| 134 | // Attempts to reset the board (see also i2hw.h). Normally, we would use this to |
| 135 | // reset a board immediately after iiSetAddress(), but it is valid to reset a |
| 136 | // board from any state, say, in order to change or re-load loadware. (Under |
| 137 | // such circumstances, no reason to re-run iiSetAddress(), which is why it is a |
| 138 | // separate routine and not included in this routine. |
| 139 | // |
| 140 | //****************************************************************************** |
| 141 | static int |
| 142 | iiReset(i2eBordStrPtr pB) |
| 143 | { |
| 144 | // Magic number should be set, else even the address is suspect |
| 145 | if (pB->i2eValid != I2E_MAGIC) |
| 146 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 147 | I2_COMPLETE(pB, I2EE_BADMAGIC); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 148 | } |
| 149 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 150 | outb(0, pB->i2eBase + FIFO_RESET); /* Any data will do */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 151 | iiDelay(pB, 50); // Pause between resets |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 152 | outb(0, pB->i2eBase + FIFO_RESET); /* Second reset */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 153 | |
| 154 | // We must wait before even attempting to read anything from the FIFO: the |
| 155 | // board's P.O.S.T may actually attempt to read and write its end of the |
| 156 | // FIFO in order to check flags, loop back (where supported), etc. On |
| 157 | // completion of this testing it would reset the FIFO, and on completion |
| 158 | // of all // P.O.S.T., write the message. We must not mistake data which |
| 159 | // might have been sent for testing as part of the reset message. To |
| 160 | // better utilize time, say, when resetting several boards, we allow the |
| 161 | // delay to be performed externally; in this way the caller can reset |
| 162 | // several boards, delay a single time, then call the initialization |
| 163 | // routine for all. |
| 164 | |
| 165 | pB->i2eState = II_STATE_RESET; |
| 166 | |
| 167 | iiDelayed = 0; // i.e., the delay routine hasn't been called since the most |
| 168 | // recent reset. |
| 169 | |
| 170 | // Ensure anything which would have been of use to standard loadware is |
| 171 | // blanked out, since board has now forgotten everything!. |
| 172 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 173 | pB->i2eUsingIrq = I2_IRQ_UNDEFINED; /* to not use an interrupt so far */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 174 | pB->i2eWaitingForEmptyFifo = 0; |
| 175 | pB->i2eOutMailWaiting = 0; |
| 176 | pB->i2eChannelPtr = NULL; |
| 177 | pB->i2eChannelCnt = 0; |
| 178 | |
| 179 | pB->i2eLeadoffWord[0] = 0; |
| 180 | pB->i2eFifoInInts = 0; |
| 181 | pB->i2eFifoOutInts = 0; |
| 182 | pB->i2eFatalTrap = NULL; |
| 183 | pB->i2eFatal = 0; |
| 184 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 185 | I2_COMPLETE(pB, I2EE_GOOD); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 186 | } |
| 187 | |
| 188 | //****************************************************************************** |
| 189 | // Function: iiResetDelay(pB) |
| 190 | // Parameters: pB - pointer to the board structure |
| 191 | // |
| 192 | // Returns: True if everything appears copacetic. |
| 193 | // False if there is any error: the pB->i2eError field has the error |
| 194 | // |
| 195 | // Description: |
| 196 | // |
| 197 | // Using the delay defined in board structure, waits two seconds (for board to |
| 198 | // reset). |
| 199 | // |
| 200 | //****************************************************************************** |
| 201 | static int |
| 202 | iiResetDelay(i2eBordStrPtr pB) |
| 203 | { |
| 204 | if (pB->i2eValid != I2E_MAGIC) { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 205 | I2_COMPLETE(pB, I2EE_BADMAGIC); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 206 | } |
| 207 | if (pB->i2eState != II_STATE_RESET) { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 208 | I2_COMPLETE(pB, I2EE_BADSTATE); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 209 | } |
| 210 | iiDelay(pB,2000); /* Now we wait for two seconds. */ |
| 211 | iiDelayed = 1; /* Delay has been called: ok to initialize */ |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 212 | I2_COMPLETE(pB, I2EE_GOOD); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 213 | } |
| 214 | |
| 215 | //****************************************************************************** |
| 216 | // Function: iiInitialize(pB) |
| 217 | // Parameters: pB - pointer to the board structure |
| 218 | // |
| 219 | // Returns: True if everything appears copacetic. |
| 220 | // False if there is any error: the pB->i2eError field has the error |
| 221 | // |
| 222 | // Description: |
| 223 | // |
| 224 | // Attempts to read the Power-on reset message. Initializes any remaining fields |
| 225 | // in the pB structure. |
| 226 | // |
| 227 | // This should be called as the third step of a process beginning with |
| 228 | // iiReset(), then iiResetDelay(). This routine checks to see that the structure |
| 229 | // is "valid" and in the reset state, also confirms that the delay routine has |
| 230 | // been called since the latest reset (to any board! overly strong!). |
| 231 | // |
| 232 | //****************************************************************************** |
| 233 | static int |
| 234 | iiInitialize(i2eBordStrPtr pB) |
| 235 | { |
| 236 | int itemp; |
| 237 | unsigned char c; |
| 238 | unsigned short utemp; |
| 239 | unsigned int ilimit; |
| 240 | |
| 241 | if (pB->i2eValid != I2E_MAGIC) |
| 242 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 243 | I2_COMPLETE(pB, I2EE_BADMAGIC); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 244 | } |
| 245 | |
| 246 | if (pB->i2eState != II_STATE_RESET || !iiDelayed) |
| 247 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 248 | I2_COMPLETE(pB, I2EE_BADSTATE); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 249 | } |
| 250 | |
| 251 | // In case there is a failure short of our completely reading the power-up |
| 252 | // message. |
| 253 | pB->i2eValid = I2E_INCOMPLETE; |
| 254 | |
| 255 | |
| 256 | // Now attempt to read the message. |
| 257 | |
| 258 | for (itemp = 0; itemp < sizeof(porStr); itemp++) |
| 259 | { |
| 260 | // We expect the entire message is ready. |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 261 | if (!I2_HAS_INPUT(pB)) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 262 | pB->i2ePomSize = itemp; |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 263 | I2_COMPLETE(pB, I2EE_PORM_SHORT); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 264 | } |
| 265 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 266 | pB->i2ePom.c[itemp] = c = inb(pB->i2eData); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 267 | |
| 268 | // We check the magic numbers as soon as they are supposed to be read |
| 269 | // (rather than after) to minimize effect of reading something we |
| 270 | // already suspect can't be "us". |
| 271 | if ( (itemp == POR_1_INDEX && c != POR_MAGIC_1) || |
| 272 | (itemp == POR_2_INDEX && c != POR_MAGIC_2)) |
| 273 | { |
| 274 | pB->i2ePomSize = itemp+1; |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 275 | I2_COMPLETE(pB, I2EE_BADMAGIC); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 276 | } |
| 277 | } |
| 278 | |
| 279 | pB->i2ePomSize = itemp; |
| 280 | |
| 281 | // Ensure that this was all the data... |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 282 | if (I2_HAS_INPUT(pB)) |
| 283 | I2_COMPLETE(pB, I2EE_PORM_LONG); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 284 | |
| 285 | // For now, we'll fail to initialize if P.O.S.T reports bad chip mapper: |
| 286 | // Implying we will not be able to download any code either: That's ok: the |
| 287 | // condition is pretty explicit. |
| 288 | if (pB->i2ePom.e.porDiag1 & POR_BAD_MAPPER) |
| 289 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 290 | I2_COMPLETE(pB, I2EE_POSTERR); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 291 | } |
| 292 | |
| 293 | // Determine anything which must be done differently depending on the family |
| 294 | // of boards! |
| 295 | switch (pB->i2ePom.e.porID & POR_ID_FAMILY) |
| 296 | { |
| 297 | case POR_ID_FII: // IntelliPort-II |
| 298 | |
| 299 | pB->i2eFifoStyle = FIFO_II; |
| 300 | pB->i2eFifoSize = 512; // 512 bytes, always |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 301 | pB->i2eDataWidth16 = false; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 302 | |
| 303 | pB->i2eMaxIrq = 15; // Because board cannot tell us it is in an 8-bit |
| 304 | // slot, we do allow it to be done (documentation!) |
| 305 | |
| 306 | pB->i2eGoodMap[1] = |
| 307 | pB->i2eGoodMap[2] = |
| 308 | pB->i2eGoodMap[3] = |
| 309 | pB->i2eChannelMap[1] = |
| 310 | pB->i2eChannelMap[2] = |
| 311 | pB->i2eChannelMap[3] = 0; |
| 312 | |
| 313 | switch (pB->i2ePom.e.porID & POR_ID_SIZE) |
| 314 | { |
| 315 | case POR_ID_II_4: |
| 316 | pB->i2eGoodMap[0] = |
| 317 | pB->i2eChannelMap[0] = 0x0f; // four-port |
| 318 | |
| 319 | // Since porPorts1 is based on the Hardware ID register, the numbers |
| 320 | // should always be consistent for IntelliPort-II. Ditto below... |
| 321 | if (pB->i2ePom.e.porPorts1 != 4) |
| 322 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 323 | I2_COMPLETE(pB, I2EE_INCONSIST); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 324 | } |
| 325 | break; |
| 326 | |
| 327 | case POR_ID_II_8: |
| 328 | case POR_ID_II_8R: |
| 329 | pB->i2eGoodMap[0] = |
| 330 | pB->i2eChannelMap[0] = 0xff; // Eight port |
| 331 | if (pB->i2ePom.e.porPorts1 != 8) |
| 332 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 333 | I2_COMPLETE(pB, I2EE_INCONSIST); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 334 | } |
| 335 | break; |
| 336 | |
| 337 | case POR_ID_II_6: |
| 338 | pB->i2eGoodMap[0] = |
| 339 | pB->i2eChannelMap[0] = 0x3f; // Six Port |
| 340 | if (pB->i2ePom.e.porPorts1 != 6) |
| 341 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 342 | I2_COMPLETE(pB, I2EE_INCONSIST); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 343 | } |
| 344 | break; |
| 345 | } |
| 346 | |
| 347 | // Fix up the "good channel list based on any errors reported. |
| 348 | if (pB->i2ePom.e.porDiag1 & POR_BAD_UART1) |
| 349 | { |
| 350 | pB->i2eGoodMap[0] &= ~0x0f; |
| 351 | } |
| 352 | |
| 353 | if (pB->i2ePom.e.porDiag1 & POR_BAD_UART2) |
| 354 | { |
| 355 | pB->i2eGoodMap[0] &= ~0xf0; |
| 356 | } |
| 357 | |
| 358 | break; // POR_ID_FII case |
| 359 | |
| 360 | case POR_ID_FIIEX: // IntelliPort-IIEX |
| 361 | |
| 362 | pB->i2eFifoStyle = FIFO_IIEX; |
| 363 | |
| 364 | itemp = pB->i2ePom.e.porFifoSize; |
| 365 | |
| 366 | // Implicit assumption that fifo would not grow beyond 32k, |
| 367 | // nor would ever be less than 256. |
| 368 | |
| 369 | if (itemp < 8 || itemp > 15) |
| 370 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 371 | I2_COMPLETE(pB, I2EE_INCONSIST); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 372 | } |
| 373 | pB->i2eFifoSize = (1 << itemp); |
| 374 | |
| 375 | // These are based on what P.O.S.T thinks should be there, based on |
| 376 | // box ID registers |
| 377 | ilimit = pB->i2ePom.e.porNumBoxes; |
| 378 | if (ilimit > ABS_MAX_BOXES) |
| 379 | { |
| 380 | ilimit = ABS_MAX_BOXES; |
| 381 | } |
| 382 | |
| 383 | // For as many boxes as EXIST, gives the type of box. |
| 384 | // Added 8/6/93: check for the ISA-4 (asic) which looks like an |
| 385 | // expandable but for whom "8 or 16?" is not the right question. |
| 386 | |
| 387 | utemp = pB->i2ePom.e.porFlags; |
| 388 | if (utemp & POR_CEX4) |
| 389 | { |
| 390 | pB->i2eChannelMap[0] = 0x000f; |
| 391 | } else { |
| 392 | utemp &= POR_BOXES; |
| 393 | for (itemp = 0; itemp < ilimit; itemp++) |
| 394 | { |
| 395 | pB->i2eChannelMap[itemp] = |
| 396 | ((utemp & POR_BOX_16) ? 0xffff : 0x00ff); |
| 397 | utemp >>= 1; |
| 398 | } |
| 399 | } |
| 400 | |
| 401 | // These are based on what P.O.S.T actually found. |
| 402 | |
| 403 | utemp = (pB->i2ePom.e.porPorts2 << 8) + pB->i2ePom.e.porPorts1; |
| 404 | |
| 405 | for (itemp = 0; itemp < ilimit; itemp++) |
| 406 | { |
| 407 | pB->i2eGoodMap[itemp] = 0; |
| 408 | if (utemp & 1) pB->i2eGoodMap[itemp] |= 0x000f; |
| 409 | if (utemp & 2) pB->i2eGoodMap[itemp] |= 0x00f0; |
| 410 | if (utemp & 4) pB->i2eGoodMap[itemp] |= 0x0f00; |
| 411 | if (utemp & 8) pB->i2eGoodMap[itemp] |= 0xf000; |
| 412 | utemp >>= 4; |
| 413 | } |
| 414 | |
| 415 | // Now determine whether we should transfer in 8 or 16-bit mode. |
| 416 | switch (pB->i2ePom.e.porBus & (POR_BUS_SLOT16 | POR_BUS_DIP16) ) |
| 417 | { |
| 418 | case POR_BUS_SLOT16 | POR_BUS_DIP16: |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 419 | pB->i2eDataWidth16 = true; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 420 | pB->i2eMaxIrq = 15; |
| 421 | break; |
| 422 | |
| 423 | case POR_BUS_SLOT16: |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 424 | pB->i2eDataWidth16 = false; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 425 | pB->i2eMaxIrq = 15; |
| 426 | break; |
| 427 | |
| 428 | case 0: |
| 429 | case POR_BUS_DIP16: // In an 8-bit slot, DIP switch don't care. |
| 430 | default: |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 431 | pB->i2eDataWidth16 = false; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 432 | pB->i2eMaxIrq = 7; |
| 433 | break; |
| 434 | } |
| 435 | break; // POR_ID_FIIEX case |
| 436 | |
| 437 | default: // Unknown type of board |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 438 | I2_COMPLETE(pB, I2EE_BAD_FAMILY); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 439 | break; |
| 440 | } // End the switch based on family |
| 441 | |
| 442 | // Temporarily, claim there is no room in the outbound fifo. |
| 443 | // We will maintain this whenever we check for an empty outbound FIFO. |
| 444 | pB->i2eFifoRemains = 0; |
| 445 | |
| 446 | // Now, based on the bus type, should we expect to be able to re-configure |
| 447 | // interrupts (say, for testing purposes). |
| 448 | switch (pB->i2ePom.e.porBus & POR_BUS_TYPE) |
| 449 | { |
| 450 | case POR_BUS_T_ISA: |
| 451 | case POR_BUS_T_UNK: // If the type of bus is undeclared, assume ok. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 452 | case POR_BUS_T_MCA: |
| 453 | case POR_BUS_T_EISA: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 454 | break; |
| 455 | default: |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 456 | I2_COMPLETE(pB, I2EE_BADBUS); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 457 | } |
| 458 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 459 | if (pB->i2eDataWidth16) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 460 | { |
| 461 | pB->i2eWriteBuf = iiWriteBuf16; |
| 462 | pB->i2eReadBuf = iiReadBuf16; |
| 463 | pB->i2eWriteWord = iiWriteWord16; |
| 464 | pB->i2eReadWord = iiReadWord16; |
| 465 | } else { |
| 466 | pB->i2eWriteBuf = iiWriteBuf8; |
| 467 | pB->i2eReadBuf = iiReadBuf8; |
| 468 | pB->i2eWriteWord = iiWriteWord8; |
| 469 | pB->i2eReadWord = iiReadWord8; |
| 470 | } |
| 471 | |
| 472 | switch(pB->i2eFifoStyle) |
| 473 | { |
| 474 | case FIFO_II: |
| 475 | pB->i2eWaitForTxEmpty = iiWaitForTxEmptyII; |
| 476 | pB->i2eTxMailEmpty = iiTxMailEmptyII; |
| 477 | pB->i2eTrySendMail = iiTrySendMailII; |
| 478 | pB->i2eGetMail = iiGetMailII; |
| 479 | pB->i2eEnableMailIrq = iiEnableMailIrqII; |
| 480 | pB->i2eWriteMask = iiWriteMaskII; |
| 481 | |
| 482 | break; |
| 483 | |
| 484 | case FIFO_IIEX: |
| 485 | pB->i2eWaitForTxEmpty = iiWaitForTxEmptyIIEX; |
| 486 | pB->i2eTxMailEmpty = iiTxMailEmptyIIEX; |
| 487 | pB->i2eTrySendMail = iiTrySendMailIIEX; |
| 488 | pB->i2eGetMail = iiGetMailIIEX; |
| 489 | pB->i2eEnableMailIrq = iiEnableMailIrqIIEX; |
| 490 | pB->i2eWriteMask = iiWriteMaskIIEX; |
| 491 | |
| 492 | break; |
| 493 | |
| 494 | default: |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 495 | I2_COMPLETE(pB, I2EE_INCONSIST); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 496 | } |
| 497 | |
| 498 | // Initialize state information. |
| 499 | pB->i2eState = II_STATE_READY; // Ready to load loadware. |
| 500 | |
| 501 | // Some Final cleanup: |
| 502 | // For some boards, the bootstrap firmware may perform some sort of test |
| 503 | // resulting in a stray character pending in the incoming mailbox. If one is |
| 504 | // there, it should be read and discarded, especially since for the standard |
| 505 | // firmware, it's the mailbox that interrupts the host. |
| 506 | |
| 507 | pB->i2eStartMail = iiGetMail(pB); |
| 508 | |
| 509 | // Throw it away and clear the mailbox structure element |
| 510 | pB->i2eStartMail = NO_MAIL_HERE; |
| 511 | |
| 512 | // Everything is ok now, return with good status/ |
| 513 | |
| 514 | pB->i2eValid = I2E_MAGIC; |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 515 | I2_COMPLETE(pB, I2EE_GOOD); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 516 | } |
| 517 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 518 | //****************************************************************************** |
| 519 | // Function: ii2DelayTimer(mseconds) |
| 520 | // Parameters: mseconds - number of milliseconds to delay |
| 521 | // |
| 522 | // Returns: Nothing |
| 523 | // |
| 524 | // Description: |
| 525 | // |
| 526 | // This routine delays for approximately mseconds milliseconds and is intended |
| 527 | // to be called indirectly through i2Delay field in i2eBordStr. It uses the |
| 528 | // Linux timer_list mechanism. |
| 529 | // |
| 530 | // The Linux timers use a unit called "jiffies" which are 10mS in the Intel |
| 531 | // architecture. This function rounds the delay period up to the next "jiffy". |
| 532 | // In the Alpha architecture the "jiffy" is 1mS, but this driver is not intended |
| 533 | // for Alpha platforms at this time. |
| 534 | // |
| 535 | //****************************************************************************** |
| 536 | static void |
| 537 | ii2DelayTimer(unsigned int mseconds) |
| 538 | { |
Jiri Slaby | 7126dd0 | 2007-07-15 23:40:20 -0700 | [diff] [blame] | 539 | msleep_interruptible(mseconds); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 540 | } |
| 541 | |
| 542 | #if 0 |
| 543 | //static void ii2DelayIO(unsigned int); |
| 544 | //****************************************************************************** |
| 545 | // !!! Not Used, this is DOS crap, some of you young folks may be interested in |
| 546 | // in how things were done in the stone age of caculating machines !!! |
| 547 | // Function: ii2DelayIO(mseconds) |
| 548 | // Parameters: mseconds - number of milliseconds to delay |
| 549 | // |
| 550 | // Returns: Nothing |
| 551 | // |
| 552 | // Description: |
| 553 | // |
| 554 | // This routine delays for approximately mseconds milliseconds and is intended |
| 555 | // to be called indirectly through i2Delay field in i2eBordStr. It is intended |
| 556 | // for use where a clock-based function is impossible: for example, DOS drivers. |
| 557 | // |
| 558 | // This function uses the IN instruction to place bounds on the timing and |
| 559 | // assumes that ii2Safe has been set. This is because I/O instructions are not |
| 560 | // subject to caching and will therefore take a certain minimum time. To ensure |
| 561 | // the delay is at least long enough on fast machines, it is based on some |
| 562 | // fastest-case calculations. On slower machines this may cause VERY long |
| 563 | // delays. (3 x fastest case). In the fastest case, everything is cached except |
| 564 | // the I/O instruction itself. |
| 565 | // |
| 566 | // Timing calculations: |
| 567 | // The fastest bus speed for I/O operations is likely to be 10 MHz. The I/O |
| 568 | // operation in question is a byte operation to an odd address. For 8-bit |
| 569 | // operations, the architecture generally enforces two wait states. At 10 MHz, a |
| 570 | // single cycle time is 100nS. A read operation at two wait states takes 6 |
| 571 | // cycles for a total time of 600nS. Therefore approximately 1666 iterations |
| 572 | // would be required to generate a single millisecond delay. The worst |
| 573 | // (reasonable) case would be an 8MHz system with no cacheing. In this case, the |
| 574 | // I/O instruction would take 125nS x 6 cyles = 750 nS. More importantly, code |
| 575 | // fetch of other instructions in the loop would take time (zero wait states, |
| 576 | // however) and would be hard to estimate. This is minimized by using in-line |
| 577 | // assembler for the in inner loop of IN instructions. This consists of just a |
| 578 | // few bytes. So we'll guess about four code fetches per loop. Each code fetch |
| 579 | // should take four cycles, so we have 125nS * 8 = 1000nS. Worst case then is |
| 580 | // that what should have taken 1 mS takes instead 1666 * (1750) = 2.9 mS. |
| 581 | // |
| 582 | // So much for theoretical timings: results using 1666 value on some actual |
| 583 | // machines: |
| 584 | // IBM 286 6MHz 3.15 mS |
| 585 | // Zenith 386 33MHz 2.45 mS |
| 586 | // (brandX) 386 33MHz 1.90 mS (has cache) |
| 587 | // (brandY) 486 33MHz 2.35 mS |
| 588 | // NCR 486 ?? 1.65 mS (microchannel) |
| 589 | // |
| 590 | // For most machines, it is probably safe to scale this number back (remember, |
| 591 | // for robust operation use an actual timed delay if possible), so we are using |
| 592 | // a value of 1190. This yields 1.17 mS for the fastest machine in our sample, |
| 593 | // 1.75 mS for typical 386 machines, and 2.25 mS the absolute slowest machine. |
| 594 | // |
| 595 | // 1/29/93: |
| 596 | // The above timings are too slow. Actual cycle times might be faster. ISA cycle |
| 597 | // times could approach 500 nS, and ... |
| 598 | // The IBM model 77 being microchannel has no wait states for 8-bit reads and |
| 599 | // seems to be accessing the I/O at 440 nS per access (from start of one to |
| 600 | // start of next). This would imply we need 1000/.440 = 2272 iterations to |
| 601 | // guarantee we are fast enough. In actual testing, we see that 2 * 1190 are in |
| 602 | // fact enough. For diagnostics, we keep the level at 1190, but developers note |
| 603 | // this needs tuning. |
| 604 | // |
| 605 | // Safe assumption: 2270 i/o reads = 1 millisecond |
| 606 | // |
| 607 | //****************************************************************************** |
| 608 | |
| 609 | |
| 610 | static int ii2DelValue = 1190; // See timing calculations below |
| 611 | // 1666 for fastest theoretical machine |
| 612 | // 1190 safe for most fast 386 machines |
| 613 | // 1000 for fastest machine tested here |
| 614 | // 540 (sic) for AT286/6Mhz |
| 615 | static void |
| 616 | ii2DelayIO(unsigned int mseconds) |
| 617 | { |
| 618 | if (!ii2Safe) |
| 619 | return; /* Do nothing if this variable uninitialized */ |
| 620 | |
| 621 | while(mseconds--) { |
| 622 | int i = ii2DelValue; |
| 623 | while ( i-- ) { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 624 | inb(ii2Safe); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 625 | } |
| 626 | } |
| 627 | } |
| 628 | #endif |
| 629 | |
| 630 | //****************************************************************************** |
| 631 | // Function: ii2Nop() |
| 632 | // Parameters: None |
| 633 | // |
| 634 | // Returns: Nothing |
| 635 | // |
| 636 | // Description: |
| 637 | // |
| 638 | // iiInitialize will set i2eDelay to this if the delay parameter is NULL. This |
| 639 | // saves checking for a NULL pointer at every call. |
| 640 | //****************************************************************************** |
| 641 | static void |
| 642 | ii2Nop(void) |
| 643 | { |
| 644 | return; // no mystery here |
| 645 | } |
| 646 | |
| 647 | //======================================================= |
| 648 | // Routines which are available in 8/16-bit versions, or |
| 649 | // in different fifo styles. These are ALL called |
| 650 | // indirectly through the board structure. |
| 651 | //======================================================= |
| 652 | |
| 653 | //****************************************************************************** |
| 654 | // Function: iiWriteBuf16(pB, address, count) |
| 655 | // Parameters: pB - pointer to board structure |
| 656 | // address - address of data to write |
| 657 | // count - number of data bytes to write |
| 658 | // |
| 659 | // Returns: True if everything appears copacetic. |
| 660 | // False if there is any error: the pB->i2eError field has the error |
| 661 | // |
| 662 | // Description: |
| 663 | // |
| 664 | // Writes 'count' bytes from 'address' to the data fifo specified by the board |
| 665 | // structure pointer pB. Should count happen to be odd, an extra pad byte is |
| 666 | // sent (identity unknown...). Uses 16-bit (word) operations. Is called |
| 667 | // indirectly through pB->i2eWriteBuf. |
| 668 | // |
| 669 | //****************************************************************************** |
| 670 | static int |
| 671 | iiWriteBuf16(i2eBordStrPtr pB, unsigned char *address, int count) |
| 672 | { |
| 673 | // Rudimentary sanity checking here. |
| 674 | if (pB->i2eValid != I2E_MAGIC) |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 675 | I2_COMPLETE(pB, I2EE_INVALID); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 676 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 677 | I2_OUTSW(pB->i2eData, address, count); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 678 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 679 | I2_COMPLETE(pB, I2EE_GOOD); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 680 | } |
| 681 | |
| 682 | //****************************************************************************** |
| 683 | // Function: iiWriteBuf8(pB, address, count) |
| 684 | // Parameters: pB - pointer to board structure |
| 685 | // address - address of data to write |
| 686 | // count - number of data bytes to write |
| 687 | // |
| 688 | // Returns: True if everything appears copacetic. |
| 689 | // False if there is any error: the pB->i2eError field has the error |
| 690 | // |
| 691 | // Description: |
| 692 | // |
| 693 | // Writes 'count' bytes from 'address' to the data fifo specified by the board |
| 694 | // structure pointer pB. Should count happen to be odd, an extra pad byte is |
| 695 | // sent (identity unknown...). This is to be consistent with the 16-bit version. |
| 696 | // Uses 8-bit (byte) operations. Is called indirectly through pB->i2eWriteBuf. |
| 697 | // |
| 698 | //****************************************************************************** |
| 699 | static int |
| 700 | iiWriteBuf8(i2eBordStrPtr pB, unsigned char *address, int count) |
| 701 | { |
| 702 | /* Rudimentary sanity checking here */ |
| 703 | if (pB->i2eValid != I2E_MAGIC) |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 704 | I2_COMPLETE(pB, I2EE_INVALID); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 705 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 706 | I2_OUTSB(pB->i2eData, address, count); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 707 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 708 | I2_COMPLETE(pB, I2EE_GOOD); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 709 | } |
| 710 | |
| 711 | //****************************************************************************** |
| 712 | // Function: iiReadBuf16(pB, address, count) |
| 713 | // Parameters: pB - pointer to board structure |
| 714 | // address - address to put data read |
| 715 | // count - number of data bytes to read |
| 716 | // |
| 717 | // Returns: True if everything appears copacetic. |
| 718 | // False if there is any error: the pB->i2eError field has the error |
| 719 | // |
| 720 | // Description: |
| 721 | // |
| 722 | // Reads 'count' bytes into 'address' from the data fifo specified by the board |
| 723 | // structure pointer pB. Should count happen to be odd, an extra pad byte is |
| 724 | // received (identity unknown...). Uses 16-bit (word) operations. Is called |
| 725 | // indirectly through pB->i2eReadBuf. |
| 726 | // |
| 727 | //****************************************************************************** |
| 728 | static int |
| 729 | iiReadBuf16(i2eBordStrPtr pB, unsigned char *address, int count) |
| 730 | { |
| 731 | // Rudimentary sanity checking here. |
| 732 | if (pB->i2eValid != I2E_MAGIC) |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 733 | I2_COMPLETE(pB, I2EE_INVALID); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 734 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 735 | I2_INSW(pB->i2eData, address, count); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 736 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 737 | I2_COMPLETE(pB, I2EE_GOOD); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 738 | } |
| 739 | |
| 740 | //****************************************************************************** |
| 741 | // Function: iiReadBuf8(pB, address, count) |
| 742 | // Parameters: pB - pointer to board structure |
| 743 | // address - address to put data read |
| 744 | // count - number of data bytes to read |
| 745 | // |
| 746 | // Returns: True if everything appears copacetic. |
| 747 | // False if there is any error: the pB->i2eError field has the error |
| 748 | // |
| 749 | // Description: |
| 750 | // |
| 751 | // Reads 'count' bytes into 'address' from the data fifo specified by the board |
| 752 | // structure pointer pB. Should count happen to be odd, an extra pad byte is |
| 753 | // received (identity unknown...). This to match the 16-bit behaviour. Uses |
| 754 | // 8-bit (byte) operations. Is called indirectly through pB->i2eReadBuf. |
| 755 | // |
| 756 | //****************************************************************************** |
| 757 | static int |
| 758 | iiReadBuf8(i2eBordStrPtr pB, unsigned char *address, int count) |
| 759 | { |
| 760 | // Rudimentary sanity checking here. |
| 761 | if (pB->i2eValid != I2E_MAGIC) |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 762 | I2_COMPLETE(pB, I2EE_INVALID); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 763 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 764 | I2_INSB(pB->i2eData, address, count); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 765 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 766 | I2_COMPLETE(pB, I2EE_GOOD); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 767 | } |
| 768 | |
| 769 | //****************************************************************************** |
| 770 | // Function: iiReadWord16(pB) |
| 771 | // Parameters: pB - pointer to board structure |
| 772 | // |
| 773 | // Returns: True if everything appears copacetic. |
| 774 | // False if there is any error: the pB->i2eError field has the error |
| 775 | // |
| 776 | // Description: |
| 777 | // |
| 778 | // Returns the word read from the data fifo specified by the board-structure |
| 779 | // pointer pB. Uses a 16-bit operation. Is called indirectly through |
| 780 | // pB->i2eReadWord. |
| 781 | // |
| 782 | //****************************************************************************** |
| 783 | static unsigned short |
| 784 | iiReadWord16(i2eBordStrPtr pB) |
| 785 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 786 | return inw(pB->i2eData); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 787 | } |
| 788 | |
| 789 | //****************************************************************************** |
| 790 | // Function: iiReadWord8(pB) |
| 791 | // Parameters: pB - pointer to board structure |
| 792 | // |
| 793 | // Returns: True if everything appears copacetic. |
| 794 | // False if there is any error: the pB->i2eError field has the error |
| 795 | // |
| 796 | // Description: |
| 797 | // |
| 798 | // Returns the word read from the data fifo specified by the board-structure |
| 799 | // pointer pB. Uses two 8-bit operations. Bytes are assumed to be LSB first. Is |
| 800 | // called indirectly through pB->i2eReadWord. |
| 801 | // |
| 802 | //****************************************************************************** |
| 803 | static unsigned short |
| 804 | iiReadWord8(i2eBordStrPtr pB) |
| 805 | { |
| 806 | unsigned short urs; |
| 807 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 808 | urs = inb(pB->i2eData); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 809 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 810 | return (inb(pB->i2eData) << 8) | urs; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 811 | } |
| 812 | |
| 813 | //****************************************************************************** |
| 814 | // Function: iiWriteWord16(pB, value) |
| 815 | // Parameters: pB - pointer to board structure |
| 816 | // value - data to write |
| 817 | // |
| 818 | // Returns: True if everything appears copacetic. |
| 819 | // False if there is any error: the pB->i2eError field has the error |
| 820 | // |
| 821 | // Description: |
| 822 | // |
| 823 | // Writes the word 'value' to the data fifo specified by the board-structure |
| 824 | // pointer pB. Uses 16-bit operation. Is called indirectly through |
| 825 | // pB->i2eWriteWord. |
| 826 | // |
| 827 | //****************************************************************************** |
| 828 | static void |
| 829 | iiWriteWord16(i2eBordStrPtr pB, unsigned short value) |
| 830 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 831 | outw((int)value, pB->i2eData); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 832 | } |
| 833 | |
| 834 | //****************************************************************************** |
| 835 | // Function: iiWriteWord8(pB, value) |
| 836 | // Parameters: pB - pointer to board structure |
| 837 | // value - data to write |
| 838 | // |
| 839 | // Returns: True if everything appears copacetic. |
| 840 | // False if there is any error: the pB->i2eError field has the error |
| 841 | // |
| 842 | // Description: |
| 843 | // |
| 844 | // Writes the word 'value' to the data fifo specified by the board-structure |
| 845 | // pointer pB. Uses two 8-bit operations (writes LSB first). Is called |
| 846 | // indirectly through pB->i2eWriteWord. |
| 847 | // |
| 848 | //****************************************************************************** |
| 849 | static void |
| 850 | iiWriteWord8(i2eBordStrPtr pB, unsigned short value) |
| 851 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 852 | outb((char)value, pB->i2eData); |
| 853 | outb((char)(value >> 8), pB->i2eData); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 854 | } |
| 855 | |
| 856 | //****************************************************************************** |
| 857 | // Function: iiWaitForTxEmptyII(pB, mSdelay) |
| 858 | // Parameters: pB - pointer to board structure |
| 859 | // mSdelay - period to wait before returning |
| 860 | // |
| 861 | // Returns: True if the FIFO is empty. |
| 862 | // False if it not empty in the required time: the pB->i2eError |
| 863 | // field has the error. |
| 864 | // |
| 865 | // Description: |
| 866 | // |
| 867 | // Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if |
| 868 | // not empty by the required time, returns false and error in pB->i2eError, |
| 869 | // otherwise returns true. |
| 870 | // |
| 871 | // mSdelay == 0 is taken to mean must be empty on the first test. |
| 872 | // |
| 873 | // This version operates on IntelliPort-II - style FIFO's |
| 874 | // |
| 875 | // Note this routine is organized so that if status is ok there is no delay at |
| 876 | // all called either before or after the test. Is called indirectly through |
| 877 | // pB->i2eWaitForTxEmpty. |
| 878 | // |
| 879 | //****************************************************************************** |
| 880 | static int |
| 881 | iiWaitForTxEmptyII(i2eBordStrPtr pB, int mSdelay) |
| 882 | { |
| 883 | unsigned long flags; |
| 884 | int itemp; |
| 885 | |
| 886 | for (;;) |
| 887 | { |
| 888 | // This routine hinges on being able to see the "other" status register |
| 889 | // (as seen by the local processor). His incoming fifo is our outgoing |
| 890 | // FIFO. |
| 891 | // |
| 892 | // By the nature of this routine, you would be using this as part of a |
| 893 | // larger atomic context: i.e., you would use this routine to ensure the |
| 894 | // fifo empty, then act on this information. Between these two halves, |
| 895 | // you will generally not want to service interrupts or in any way |
| 896 | // disrupt the assumptions implicit in the larger context. |
| 897 | // |
| 898 | // Even worse, however, this routine "shifts" the status register to |
| 899 | // point to the local status register which is not the usual situation. |
| 900 | // Therefore for extra safety, we force the critical section to be |
| 901 | // completely atomic, and pick up after ourselves before allowing any |
| 902 | // interrupts of any kind. |
| 903 | |
| 904 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 905 | write_lock_irqsave(&Dl_spinlock, flags); |
| 906 | outb(SEL_COMMAND, pB->i2ePointer); |
| 907 | outb(SEL_CMD_SH, pB->i2ePointer); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 908 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 909 | itemp = inb(pB->i2eStatus); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 910 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 911 | outb(SEL_COMMAND, pB->i2ePointer); |
| 912 | outb(SEL_CMD_UNSH, pB->i2ePointer); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 913 | |
| 914 | if (itemp & ST_IN_EMPTY) |
| 915 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 916 | I2_UPDATE_FIFO_ROOM(pB); |
| 917 | write_unlock_irqrestore(&Dl_spinlock, flags); |
| 918 | I2_COMPLETE(pB, I2EE_GOOD); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 919 | } |
| 920 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 921 | write_unlock_irqrestore(&Dl_spinlock, flags); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 922 | |
| 923 | if (mSdelay-- == 0) |
| 924 | break; |
| 925 | |
| 926 | iiDelay(pB, 1); /* 1 mS granularity on checking condition */ |
| 927 | } |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 928 | I2_COMPLETE(pB, I2EE_TXE_TIME); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 929 | } |
| 930 | |
| 931 | //****************************************************************************** |
| 932 | // Function: iiWaitForTxEmptyIIEX(pB, mSdelay) |
| 933 | // Parameters: pB - pointer to board structure |
| 934 | // mSdelay - period to wait before returning |
| 935 | // |
| 936 | // Returns: True if the FIFO is empty. |
| 937 | // False if it not empty in the required time: the pB->i2eError |
| 938 | // field has the error. |
| 939 | // |
| 940 | // Description: |
| 941 | // |
| 942 | // Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if |
| 943 | // not empty by the required time, returns false and error in pB->i2eError, |
| 944 | // otherwise returns true. |
| 945 | // |
| 946 | // mSdelay == 0 is taken to mean must be empty on the first test. |
| 947 | // |
| 948 | // This version operates on IntelliPort-IIEX - style FIFO's |
| 949 | // |
| 950 | // Note this routine is organized so that if status is ok there is no delay at |
| 951 | // all called either before or after the test. Is called indirectly through |
| 952 | // pB->i2eWaitForTxEmpty. |
| 953 | // |
| 954 | //****************************************************************************** |
| 955 | static int |
| 956 | iiWaitForTxEmptyIIEX(i2eBordStrPtr pB, int mSdelay) |
| 957 | { |
| 958 | unsigned long flags; |
| 959 | |
| 960 | for (;;) |
| 961 | { |
| 962 | // By the nature of this routine, you would be using this as part of a |
| 963 | // larger atomic context: i.e., you would use this routine to ensure the |
| 964 | // fifo empty, then act on this information. Between these two halves, |
| 965 | // you will generally not want to service interrupts or in any way |
| 966 | // disrupt the assumptions implicit in the larger context. |
| 967 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 968 | write_lock_irqsave(&Dl_spinlock, flags); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 969 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 970 | if (inb(pB->i2eStatus) & STE_OUT_MT) { |
| 971 | I2_UPDATE_FIFO_ROOM(pB); |
| 972 | write_unlock_irqrestore(&Dl_spinlock, flags); |
| 973 | I2_COMPLETE(pB, I2EE_GOOD); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 974 | } |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 975 | write_unlock_irqrestore(&Dl_spinlock, flags); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 976 | |
| 977 | if (mSdelay-- == 0) |
| 978 | break; |
| 979 | |
| 980 | iiDelay(pB, 1); // 1 mS granularity on checking condition |
| 981 | } |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 982 | I2_COMPLETE(pB, I2EE_TXE_TIME); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 983 | } |
| 984 | |
| 985 | //****************************************************************************** |
| 986 | // Function: iiTxMailEmptyII(pB) |
| 987 | // Parameters: pB - pointer to board structure |
| 988 | // |
| 989 | // Returns: True if the transmit mailbox is empty. |
| 990 | // False if it not empty. |
| 991 | // |
| 992 | // Description: |
| 993 | // |
| 994 | // Returns true or false according to whether the transmit mailbox is empty (and |
| 995 | // therefore able to accept more mail) |
| 996 | // |
| 997 | // This version operates on IntelliPort-II - style FIFO's |
| 998 | // |
| 999 | //****************************************************************************** |
| 1000 | static int |
| 1001 | iiTxMailEmptyII(i2eBordStrPtr pB) |
| 1002 | { |
| 1003 | int port = pB->i2ePointer; |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 1004 | outb(SEL_OUTMAIL, port); |
| 1005 | return inb(port) == 0; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1006 | } |
| 1007 | |
| 1008 | //****************************************************************************** |
| 1009 | // Function: iiTxMailEmptyIIEX(pB) |
| 1010 | // Parameters: pB - pointer to board structure |
| 1011 | // |
| 1012 | // Returns: True if the transmit mailbox is empty. |
| 1013 | // False if it not empty. |
| 1014 | // |
| 1015 | // Description: |
| 1016 | // |
| 1017 | // Returns true or false according to whether the transmit mailbox is empty (and |
| 1018 | // therefore able to accept more mail) |
| 1019 | // |
| 1020 | // This version operates on IntelliPort-IIEX - style FIFO's |
| 1021 | // |
| 1022 | //****************************************************************************** |
| 1023 | static int |
| 1024 | iiTxMailEmptyIIEX(i2eBordStrPtr pB) |
| 1025 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 1026 | return !(inb(pB->i2eStatus) & STE_OUT_MAIL); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1027 | } |
| 1028 | |
| 1029 | //****************************************************************************** |
| 1030 | // Function: iiTrySendMailII(pB,mail) |
| 1031 | // Parameters: pB - pointer to board structure |
| 1032 | // mail - value to write to mailbox |
| 1033 | // |
| 1034 | // Returns: True if the transmit mailbox is empty, and mail is sent. |
| 1035 | // False if it not empty. |
| 1036 | // |
| 1037 | // Description: |
| 1038 | // |
| 1039 | // If outgoing mailbox is empty, sends mail and returns true. If outgoing |
| 1040 | // mailbox is not empty, returns false. |
| 1041 | // |
| 1042 | // This version operates on IntelliPort-II - style FIFO's |
| 1043 | // |
| 1044 | //****************************************************************************** |
| 1045 | static int |
| 1046 | iiTrySendMailII(i2eBordStrPtr pB, unsigned char mail) |
| 1047 | { |
| 1048 | int port = pB->i2ePointer; |
| 1049 | |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 1050 | outb(SEL_OUTMAIL, port); |
| 1051 | if (inb(port) == 0) { |
| 1052 | outb(SEL_OUTMAIL, port); |
| 1053 | outb(mail, port); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1054 | return 1; |
| 1055 | } |
| 1056 | return 0; |
| 1057 | } |
| 1058 | |
| 1059 | //****************************************************************************** |
| 1060 | // Function: iiTrySendMailIIEX(pB,mail) |
| 1061 | // Parameters: pB - pointer to board structure |
| 1062 | // mail - value to write to mailbox |
| 1063 | // |
| 1064 | // Returns: True if the transmit mailbox is empty, and mail is sent. |
| 1065 | // False if it not empty. |
| 1066 | // |
| 1067 | // Description: |
| 1068 | // |
| 1069 | // If outgoing mailbox is empty, sends mail and returns true. If outgoing |
| 1070 | // mailbox is not empty, returns false. |
| 1071 | // |
| 1072 | // This version operates on IntelliPort-IIEX - style FIFO's |
| 1073 | // |
| 1074 | //****************************************************************************** |
| 1075 | static int |
| 1076 | iiTrySendMailIIEX(i2eBordStrPtr pB, unsigned char mail) |
| 1077 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 1078 | if (inb(pB->i2eStatus) & STE_OUT_MAIL) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1079 | return 0; |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 1080 | outb(mail, pB->i2eXMail); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1081 | return 1; |
| 1082 | } |
| 1083 | |
| 1084 | //****************************************************************************** |
| 1085 | // Function: iiGetMailII(pB,mail) |
| 1086 | // Parameters: pB - pointer to board structure |
| 1087 | // |
| 1088 | // Returns: Mailbox data or NO_MAIL_HERE. |
| 1089 | // |
| 1090 | // Description: |
| 1091 | // |
| 1092 | // If no mail available, returns NO_MAIL_HERE otherwise returns the data from |
| 1093 | // the mailbox, which is guaranteed != NO_MAIL_HERE. |
| 1094 | // |
| 1095 | // This version operates on IntelliPort-II - style FIFO's |
| 1096 | // |
| 1097 | //****************************************************************************** |
| 1098 | static unsigned short |
| 1099 | iiGetMailII(i2eBordStrPtr pB) |
| 1100 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 1101 | if (I2_HAS_MAIL(pB)) { |
| 1102 | outb(SEL_INMAIL, pB->i2ePointer); |
| 1103 | return inb(pB->i2ePointer); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1104 | } else { |
| 1105 | return NO_MAIL_HERE; |
| 1106 | } |
| 1107 | } |
| 1108 | |
| 1109 | //****************************************************************************** |
| 1110 | // Function: iiGetMailIIEX(pB,mail) |
| 1111 | // Parameters: pB - pointer to board structure |
| 1112 | // |
| 1113 | // Returns: Mailbox data or NO_MAIL_HERE. |
| 1114 | // |
| 1115 | // Description: |
| 1116 | // |
| 1117 | // If no mail available, returns NO_MAIL_HERE otherwise returns the data from |
| 1118 | // the mailbox, which is guaranteed != NO_MAIL_HERE. |
| 1119 | // |
| 1120 | // This version operates on IntelliPort-IIEX - style FIFO's |
| 1121 | // |
| 1122 | //****************************************************************************** |
| 1123 | static unsigned short |
| 1124 | iiGetMailIIEX(i2eBordStrPtr pB) |
| 1125 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 1126 | if (I2_HAS_MAIL(pB)) |
| 1127 | return inb(pB->i2eXMail); |
| 1128 | else |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1129 | return NO_MAIL_HERE; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1130 | } |
| 1131 | |
| 1132 | //****************************************************************************** |
| 1133 | // Function: iiEnableMailIrqII(pB) |
| 1134 | // Parameters: pB - pointer to board structure |
| 1135 | // |
| 1136 | // Returns: Nothing |
| 1137 | // |
| 1138 | // Description: |
| 1139 | // |
| 1140 | // Enables board to interrupt host (only) by writing to host's in-bound mailbox. |
| 1141 | // |
| 1142 | // This version operates on IntelliPort-II - style FIFO's |
| 1143 | // |
| 1144 | //****************************************************************************** |
| 1145 | static void |
| 1146 | iiEnableMailIrqII(i2eBordStrPtr pB) |
| 1147 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 1148 | outb(SEL_MASK, pB->i2ePointer); |
| 1149 | outb(ST_IN_MAIL, pB->i2ePointer); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1150 | } |
| 1151 | |
| 1152 | //****************************************************************************** |
| 1153 | // Function: iiEnableMailIrqIIEX(pB) |
| 1154 | // Parameters: pB - pointer to board structure |
| 1155 | // |
| 1156 | // Returns: Nothing |
| 1157 | // |
| 1158 | // Description: |
| 1159 | // |
| 1160 | // Enables board to interrupt host (only) by writing to host's in-bound mailbox. |
| 1161 | // |
| 1162 | // This version operates on IntelliPort-IIEX - style FIFO's |
| 1163 | // |
| 1164 | //****************************************************************************** |
| 1165 | static void |
| 1166 | iiEnableMailIrqIIEX(i2eBordStrPtr pB) |
| 1167 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 1168 | outb(MX_IN_MAIL, pB->i2eXMask); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1169 | } |
| 1170 | |
| 1171 | //****************************************************************************** |
| 1172 | // Function: iiWriteMaskII(pB) |
| 1173 | // Parameters: pB - pointer to board structure |
| 1174 | // |
| 1175 | // Returns: Nothing |
| 1176 | // |
| 1177 | // Description: |
| 1178 | // |
| 1179 | // Writes arbitrary value to the mask register. |
| 1180 | // |
| 1181 | // This version operates on IntelliPort-II - style FIFO's |
| 1182 | // |
| 1183 | //****************************************************************************** |
| 1184 | static void |
| 1185 | iiWriteMaskII(i2eBordStrPtr pB, unsigned char value) |
| 1186 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 1187 | outb(SEL_MASK, pB->i2ePointer); |
| 1188 | outb(value, pB->i2ePointer); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1189 | } |
| 1190 | |
| 1191 | //****************************************************************************** |
| 1192 | // Function: iiWriteMaskIIEX(pB) |
| 1193 | // Parameters: pB - pointer to board structure |
| 1194 | // |
| 1195 | // Returns: Nothing |
| 1196 | // |
| 1197 | // Description: |
| 1198 | // |
| 1199 | // Writes arbitrary value to the mask register. |
| 1200 | // |
| 1201 | // This version operates on IntelliPort-IIEX - style FIFO's |
| 1202 | // |
| 1203 | //****************************************************************************** |
| 1204 | static void |
| 1205 | iiWriteMaskIIEX(i2eBordStrPtr pB, unsigned char value) |
| 1206 | { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 1207 | outb(value, pB->i2eXMask); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1208 | } |
| 1209 | |
| 1210 | //****************************************************************************** |
| 1211 | // Function: iiDownloadBlock(pB, pSource, isStandard) |
| 1212 | // Parameters: pB - pointer to board structure |
| 1213 | // pSource - loadware block to download |
| 1214 | // isStandard - True if "standard" loadware, else false. |
| 1215 | // |
| 1216 | // Returns: Success or Failure |
| 1217 | // |
| 1218 | // Description: |
| 1219 | // |
| 1220 | // Downloads a single block (at pSource)to the board referenced by pB. Caller |
| 1221 | // sets isStandard to true/false according to whether the "standard" loadware is |
| 1222 | // what's being loaded. The normal process, then, is to perform an iiInitialize |
| 1223 | // to the board, then perform some number of iiDownloadBlocks using the returned |
| 1224 | // state to determine when download is complete. |
| 1225 | // |
| 1226 | // Possible return values: (see I2ELLIS.H) |
| 1227 | // II_DOWN_BADVALID |
| 1228 | // II_DOWN_BADFILE |
| 1229 | // II_DOWN_CONTINUING |
| 1230 | // II_DOWN_GOOD |
| 1231 | // II_DOWN_BAD |
| 1232 | // II_DOWN_BADSTATE |
| 1233 | // II_DOWN_TIMEOUT |
| 1234 | // |
| 1235 | // Uses the i2eState and i2eToLoad fields (initialized at iiInitialize) to |
| 1236 | // determine whether this is the first block, whether to check for magic |
| 1237 | // numbers, how many blocks there are to go... |
| 1238 | // |
| 1239 | //****************************************************************************** |
| 1240 | static int |
| 1241 | iiDownloadBlock ( i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard) |
| 1242 | { |
| 1243 | int itemp; |
| 1244 | int loadedFirst; |
| 1245 | |
| 1246 | if (pB->i2eValid != I2E_MAGIC) return II_DOWN_BADVALID; |
| 1247 | |
| 1248 | switch(pB->i2eState) |
| 1249 | { |
| 1250 | case II_STATE_READY: |
| 1251 | |
| 1252 | // Loading the first block after reset. Must check the magic number of the |
| 1253 | // loadfile, store the number of blocks we expect to load. |
| 1254 | if (pSource->e.loadMagic != MAGIC_LOADFILE) |
| 1255 | { |
| 1256 | return II_DOWN_BADFILE; |
| 1257 | } |
| 1258 | |
| 1259 | // Next we store the total number of blocks to load, including this one. |
| 1260 | pB->i2eToLoad = 1 + pSource->e.loadBlocksMore; |
| 1261 | |
| 1262 | // Set the state, store the version numbers. ('Cause this may have come |
| 1263 | // from a file - we might want to report these versions and revisions in |
| 1264 | // case of an error! |
| 1265 | pB->i2eState = II_STATE_LOADING; |
| 1266 | pB->i2eLVersion = pSource->e.loadVersion; |
| 1267 | pB->i2eLRevision = pSource->e.loadRevision; |
| 1268 | pB->i2eLSub = pSource->e.loadSubRevision; |
| 1269 | |
| 1270 | // The time and date of compilation is also available but don't bother |
| 1271 | // storing it for normal purposes. |
| 1272 | loadedFirst = 1; |
| 1273 | break; |
| 1274 | |
| 1275 | case II_STATE_LOADING: |
| 1276 | loadedFirst = 0; |
| 1277 | break; |
| 1278 | |
| 1279 | default: |
| 1280 | return II_DOWN_BADSTATE; |
| 1281 | } |
| 1282 | |
| 1283 | // Now we must be in the II_STATE_LOADING state, and we assume i2eToLoad |
| 1284 | // must be positive still, because otherwise we would have cleaned up last |
| 1285 | // time and set the state to II_STATE_LOADED. |
| 1286 | if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) { |
| 1287 | return II_DOWN_TIMEOUT; |
| 1288 | } |
| 1289 | |
| 1290 | if (!iiWriteBuf(pB, pSource->c, LOADWARE_BLOCK_SIZE)) { |
| 1291 | return II_DOWN_BADVALID; |
| 1292 | } |
| 1293 | |
| 1294 | // If we just loaded the first block, wait for the fifo to empty an extra |
| 1295 | // long time to allow for any special startup code in the firmware, like |
| 1296 | // sending status messages to the LCD's. |
| 1297 | |
| 1298 | if (loadedFirst) { |
| 1299 | if (!iiWaitForTxEmpty(pB, MAX_DLOAD_START_TIME)) { |
| 1300 | return II_DOWN_TIMEOUT; |
| 1301 | } |
| 1302 | } |
| 1303 | |
| 1304 | // Determine whether this was our last block! |
| 1305 | if (--(pB->i2eToLoad)) { |
| 1306 | return II_DOWN_CONTINUING; // more to come... |
| 1307 | } |
| 1308 | |
| 1309 | // It WAS our last block: Clean up operations... |
| 1310 | // ...Wait for last buffer to drain from the board... |
| 1311 | if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) { |
| 1312 | return II_DOWN_TIMEOUT; |
| 1313 | } |
| 1314 | // If there were only a single block written, this would come back |
| 1315 | // immediately and be harmless, though not strictly necessary. |
| 1316 | itemp = MAX_DLOAD_ACK_TIME/10; |
| 1317 | while (--itemp) { |
Jiri Slaby | cf1c63c | 2008-04-30 00:53:54 -0700 | [diff] [blame] | 1318 | if (I2_HAS_INPUT(pB)) { |
| 1319 | switch (inb(pB->i2eData)) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1320 | case LOADWARE_OK: |
| 1321 | pB->i2eState = |
| 1322 | isStandard ? II_STATE_STDLOADED :II_STATE_LOADED; |
| 1323 | |
| 1324 | // Some revisions of the bootstrap firmware (e.g. ISA-8 1.0.2) |
| 1325 | // will, // if there is a debug port attached, require some |
| 1326 | // time to send information to the debug port now. It will do |
| 1327 | // this before // executing any of the code we just downloaded. |
| 1328 | // It may take up to 700 milliseconds. |
| 1329 | if (pB->i2ePom.e.porDiag2 & POR_DEBUG_PORT) { |
| 1330 | iiDelay(pB, 700); |
| 1331 | } |
| 1332 | |
| 1333 | return II_DOWN_GOOD; |
| 1334 | |
| 1335 | case LOADWARE_BAD: |
| 1336 | default: |
| 1337 | return II_DOWN_BAD; |
| 1338 | } |
| 1339 | } |
| 1340 | |
| 1341 | iiDelay(pB, 10); // 10 mS granularity on checking condition |
| 1342 | } |
| 1343 | |
| 1344 | // Drop-through --> timed out waiting for firmware confirmation |
| 1345 | |
| 1346 | pB->i2eState = II_STATE_BADLOAD; |
| 1347 | return II_DOWN_TIMEOUT; |
| 1348 | } |
| 1349 | |
| 1350 | //****************************************************************************** |
| 1351 | // Function: iiDownloadAll(pB, pSource, isStandard, size) |
| 1352 | // Parameters: pB - pointer to board structure |
| 1353 | // pSource - loadware block to download |
| 1354 | // isStandard - True if "standard" loadware, else false. |
| 1355 | // size - size of data to download (in bytes) |
| 1356 | // |
| 1357 | // Returns: Success or Failure |
| 1358 | // |
| 1359 | // Description: |
| 1360 | // |
| 1361 | // Given a pointer to a board structure, a pointer to the beginning of some |
| 1362 | // loadware, whether it is considered the "standard loadware", and the size of |
| 1363 | // the array in bytes loads the entire array to the board as loadware. |
| 1364 | // |
| 1365 | // Assumes the board has been freshly reset and the power-up reset message read. |
| 1366 | // (i.e., in II_STATE_READY). Complains if state is bad, or if there seems to be |
| 1367 | // too much or too little data to load, or if iiDownloadBlock complains. |
| 1368 | //****************************************************************************** |
| 1369 | static int |
| 1370 | iiDownloadAll(i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard, int size) |
| 1371 | { |
| 1372 | int status; |
| 1373 | |
| 1374 | // We know (from context) board should be ready for the first block of |
| 1375 | // download. Complain if not. |
| 1376 | if (pB->i2eState != II_STATE_READY) return II_DOWN_BADSTATE; |
| 1377 | |
| 1378 | while (size > 0) { |
| 1379 | size -= LOADWARE_BLOCK_SIZE; // How much data should there be left to |
| 1380 | // load after the following operation ? |
| 1381 | |
| 1382 | // Note we just bump pSource by "one", because its size is actually that |
| 1383 | // of an entire block, same as LOADWARE_BLOCK_SIZE. |
| 1384 | status = iiDownloadBlock(pB, pSource++, isStandard); |
| 1385 | |
| 1386 | switch(status) |
| 1387 | { |
| 1388 | case II_DOWN_GOOD: |
| 1389 | return ( (size > 0) ? II_DOWN_OVER : II_DOWN_GOOD); |
| 1390 | |
| 1391 | case II_DOWN_CONTINUING: |
| 1392 | break; |
| 1393 | |
| 1394 | default: |
| 1395 | return status; |
| 1396 | } |
| 1397 | } |
| 1398 | |
| 1399 | // We shouldn't drop out: it means "while" caught us with nothing left to |
| 1400 | // download, yet the previous DownloadBlock did not return complete. Ergo, |
| 1401 | // not enough data to match the size byte in the header. |
| 1402 | return II_DOWN_UNDER; |
| 1403 | } |