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