summaryrefslogblamecommitdiffstats
path: root/drivers/char/ip2/i2ellis.h
blob: 5eabe47b0bc842f4abc60599b561dfa7229fbcdf (plain) (tree)
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
















































                                                                                




















































































































































































































































































































































































































































































































































































                                                                                                           
/*******************************************************************************
*
*   (c) 1999 by Computone Corporation
*
********************************************************************************
*
*
*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
*                serial I/O controllers.
*
*   DESCRIPTION: Mainline code for the device driver
*
*******************************************************************************/
//------------------------------------------------------------------------------
// i2ellis.h
//
// IntelliPort-II and IntelliPort-IIEX
//
// Extremely
// Low
// Level
// Interface
// Services
//
// Structure Definitions and declarations for "ELLIS" service routines found in
// i2ellis.c
//
// These routines are based on properties of the IntelliPort-II and -IIEX
// hardware and bootstrap firmware, and are not sensitive to particular
// conventions of any particular loadware.
//
// Unlike i2hw.h, which provides IRONCLAD hardware definitions, the material
// here and in i2ellis.c is intended to provice a useful, but not required,
// layer of insulation from the hardware specifics.
//------------------------------------------------------------------------------
#ifndef  I2ELLIS_H   /* To prevent multiple includes */
#define  I2ELLIS_H   1
//------------------------------------------------
// Revision History:
//
// 30 September 1991 MAG First Draft Started
// 12 October   1991 ...continued...
//
// 20 December  1996 AKM Linux version
//-------------------------------------------------

//----------------------
// Mandatory Includes:
//----------------------
#include "ip2types.h"
#include "i2hw.h"       // The hardware definitions

//------------------------------------------
// STAT_BOXIDS packets
//------------------------------------------
#define MAX_BOX		4

typedef struct _bidStat
{
	unsigned char bid_value[MAX_BOX];
} bidStat, *bidStatPtr;

// This packet is sent in response to a CMD_GET_BOXIDS bypass command. For -IIEX
// boards, reports the hardware-specific "asynchronous resource register" on
// each expansion box. Boxes not present report 0xff. For -II boards, the first
// element contains 0x80 for 8-port, 0x40 for 4-port boards.

// Box IDs aka ARR or Async Resource Register (more than you want to know)
//   7   6   5   4   3   2   1   0
//   F   F   N   N   L   S   S   S
//   =============================
//   F   F   -  Product Family Designator
//   =====+++++++++++++++++++++++++++++++
//   0   0   -  Intelliport II EX / ISA-8
//   1   0   -  IntelliServer
//   0   1   -  SAC - Port Device (Intelliport III ??? )
//           =====+++++++++++++++++++++++++++++++++++++++
//           N   N   -  Number of Ports
//           0   0   -  8  (eight)
//           0   1   -  4  (four)
//           1   0   -  12 (twelve)
//           1   1   -  16 (sixteen)
//                   =++++++++++++++++++++++++++++++++++
//                   L  -   LCD Display Module Present
//                   0  -   No
//                   1  -   LCD module present
//                   =========+++++++++++++++++++++++++++++++++++++
//                      S   S   S - Async Signals Supported Designator
//                      0   0   0 - 8dss, Mod DCE DB25 Female
//                      0   0   1 - 6dss, RJ-45
//                      0   1   0 - RS-232/422 dss, DB25 Female
//                      0   1   1 - RS-232/422 dss, separate 232/422 DB25 Female
//                      1   0   0 - 6dss, 921.6 I/F with ST654's
//                      1   0   1 - RS-423/232 8dss, RJ-45 10Pin
//                      1   1   0 - 6dss, Mod DCE DB25 Female
//                      1   1   1 - NO BOX PRESENT

#define FF(c)	((c & 0xC0) >> 6)
#define NN(c)	((c & 0x30) >> 4)
#define L(c)	((c & 0x08) >> 3)
#define SSS(c)	 (c & 0x07)

#define BID_HAS_654(x)	(SSS(x) == 0x04)
#define BID_NO_BOX	0xff /* no box */
#define BID_8PORT  	0x80 /* IP2-8 port */
#define BID_4PORT   	0x81 /* IP2-4 port */
#define BID_EXP_MASK   	0x30 /* IP2-EX  */
#define BID_EXP_8PORT	0x00 /*     8, */
#define BID_EXP_4PORT	0x10 /*     4, */
#define BID_EXP_UNDEF	0x20 /*     UNDEF, */
#define BID_EXP_16PORT	0x30 /*    16, */
#define BID_LCD_CTRL   	0x08 /* LCD Controller */
#define BID_LCD_NONE	0x00 /* - no controller present */
#define BID_LCD_PRES   	0x08 /* - controller present */
#define BID_CON_MASK	0x07 /* - connector pinouts */
#define BID_CON_DB25	0x00 /* - DB-25 F */
#define BID_CON_RJ45	0x01 /* - rj45 */

//------------------------------------------------------------------------------
// i2eBordStr
//
// This structure contains all the information the ELLIS routines require in
// dealing with a particular board.
//------------------------------------------------------------------------------
// There are some queues here which are guaranteed to never contain the entry
// for a single channel twice. So they must be slightly larger to allow
// unambiguous full/empty management
//
#define CH_QUEUE_SIZE ABS_MOST_PORTS+2

typedef struct _i2eBordStr
{
	porStr         i2ePom;	// Structure containing the power-on message.

	unsigned short i2ePomSize;
						// The number of bytes actually read if
						// different from sizeof i2ePom, indicates
						// there is an error!

	unsigned short i2eStartMail;
						// Contains whatever inbound mailbox data
						// present at startup. NO_MAIL_HERE indicates
						// nothing was present. No special
						// significance as of this writing, but may be
						// useful for diagnostic reasons.

	unsigned short i2eValid;
						// Indicates validity of the structure; if
						// i2eValid == I2E_MAGIC, then we can trust
						// the other fields. Some (especially
						// initialization) functions are good about
						// checking for validity.  Many functions do
						// not, it being assumed that the larger
						// context assures we are using a valid
						// i2eBordStrPtr.

	unsigned short i2eError;
						// Used for returning an error condition from
						// several functions which use i2eBordStrPtr
						// as an argument.

	// Accelerators to characterize separate features of a board, derived from a
	// number of sources.

	unsigned short i2eFifoSize;
						// Always, the size of the FIFO. For
						// IntelliPort-II, always the same, for -IIEX
						// taken from the Power-On reset message.

	volatile 
	unsigned short i2eFifoRemains;
						// Used during normal operation to indicate a
						// lower bound on the amount of data which
						// might be in the outbound fifo.

	unsigned char  i2eFifoStyle;
						// Accelerator which tells which style (-II or
						// -IIEX) FIFO we are using.

	unsigned char  i2eDataWidth16;
						// Accelerator which tells whether we should
						// do 8 or 16-bit data transfers.

	unsigned char  i2eMaxIrq;
						// The highest allowable IRQ, based on the
						// slot size.

	unsigned char  i2eChangeIrq;
						// Whether tis valid to change IRQ's
						// ISA = ok, EISA, MicroChannel, no

	// Accelerators for various addresses on the board
	int            i2eBase;        // I/O Address of the Board
	int            i2eData;        // From here data transfers happen
	int            i2eStatus;      // From here status reads happen
	int            i2ePointer;     // (IntelliPort-II: pointer/commands)
	int            i2eXMail;       // (IntelliPOrt-IIEX: mailboxes
	int            i2eXMask;       // (IntelliPort-IIEX: mask write

	//-------------------------------------------------------
	// Information presented in a common format across boards
	// For each box, bit map of the channels present.  Box closest to 
	// the host is box 0. LSB is channel 0. IntelliPort-II (non-expandable)
	// is taken to be box 0. These are derived from product i.d. registers.

	unsigned short i2eChannelMap[ABS_MAX_BOXES];

	// Same as above, except each is derived from firmware attempting to detect
	// the uart presence (by reading a valid GFRCR register). If bits are set in
	// i2eChannelMap and not in i2eGoodMap, there is a potential problem.

	unsigned short i2eGoodMap[ABS_MAX_BOXES];

	// ---------------------------
	// For indirect function calls

	// Routine to cause an N-millisecond delay: Patched by the ii2Initialize
	// function.

	void  (*i2eDelay)(unsigned int);

	// Routine to write N bytes to the board through the FIFO. Returns true if
	// all copacetic, otherwise returns false and error is in i2eError field.
	// IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER.

	int   (*i2eWriteBuf)(struct _i2eBordStr *, unsigned char *, int);

	// Routine to read N bytes from the board through the FIFO. Returns true if
	// copacetic, otherwise returns false and error in i2eError.
	// IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER.

	int   (*i2eReadBuf)(struct _i2eBordStr *, unsigned char *, int);

	// Returns a word from FIFO. Will use 2 byte operations if needed.

	unsigned short (*i2eReadWord)(struct _i2eBordStr *);

	// Writes a word to FIFO. Will use 2 byte operations if needed.

	void  (*i2eWriteWord)(struct _i2eBordStr *, unsigned short);

	// Waits specified time for the Transmit FIFO to go empty. Returns true if
	//  ok, otherwise returns false and error in i2eError.

	int   (*i2eWaitForTxEmpty)(struct _i2eBordStr *, int);

	// Returns true or false according to whether the outgoing mailbox is empty.

	int   (*i2eTxMailEmpty)(struct _i2eBordStr *);

	// Checks whether outgoing mailbox is empty.  If so, sends mail and returns
	// true.  Otherwise returns false.

	int   (*i2eTrySendMail)(struct _i2eBordStr *, unsigned char);

	// If no mail available, returns NO_MAIL_HERE, else returns the value in the
	// mailbox (guaranteed can't be NO_MAIL_HERE).

	unsigned short (*i2eGetMail)(struct _i2eBordStr *);

	// Enables the board to interrupt the host when it writes to the mailbox.
	// Irqs will not occur, however, until the loadware separately enables
	// interrupt generation to the host.  The standard loadware does this in
	// response to a command packet sent by the host. (Also, disables
	// any other potential interrupt sources from the board -- other than the
	// inbound mailbox).

	void  (*i2eEnableMailIrq)(struct _i2eBordStr *);

	// Writes an arbitrary value to the mask register.

	void  (*i2eWriteMask)(struct _i2eBordStr *, unsigned char);


	// State information

	// During downloading, indicates the number of blocks remaining to download
	// to the board.

	short i2eToLoad;

	// State of board (see manifests below) (e.g., whether in reset condition,
	// whether standard loadware is installed, etc.

	unsigned char  i2eState;

	// These three fields are only valid when there is loadware running on the
	// board. (i2eState == II_STATE_LOADED or i2eState == II_STATE_STDLOADED )

	unsigned char  i2eLVersion;  // Loadware version
	unsigned char  i2eLRevision; // Loadware revision
	unsigned char  i2eLSub;      // Loadware subrevision

	// Flags which only have meaning in the context of the standard loadware.
	// Somewhat violates the layering concept, but there is so little additional
	// needed at the board level (while much additional at the channel level),
	// that this beats maintaining two different per-board structures.

	// Indicates which IRQ the board has been initialized (from software) to use
	// For MicroChannel boards, any value different from IRQ_UNDEFINED means
	// that the software command has been sent to enable interrupts (or specify
	// they are disabled). Special value: IRQ_UNDEFINED indicates that the
	// software command to select the interrupt has not yet been sent, therefore
	// (since the standard loadware insists that it be sent before any other
	// packets are sent) no other packets should be sent yet.

	unsigned short i2eUsingIrq;

	// This is set when we hit the MB_OUT_STUFFED mailbox, which prevents us
	// putting more in the mailbox until an appropriate mailbox message is
	// received.

	unsigned char  i2eWaitingForEmptyFifo;

	// Any mailbox bits waiting to be sent to the board are OR'ed in here.

	unsigned char  i2eOutMailWaiting;

	// The head of any incoming packet is read into here, is then examined and 
	// we dispatch accordingly.

	unsigned short i2eLeadoffWord[1];

	// Running counter of interrupts where the mailbox indicated incoming data.

	unsigned short i2eFifoInInts;

	// Running counter of interrupts where the mailbox indicated outgoing data
	// had been stripped.

	unsigned short i2eFifoOutInts;

	// If not void, gives the address of a routine to call if fatal board error
	// is found (only applies to standard l/w).

	void  (*i2eFatalTrap)(struct _i2eBordStr *);

	// Will point to an array of some sort of channel structures (whose format
	// is unknown at this level, being a function of what loadware is
	// installed and the code configuration (max sizes of buffers, etc.)).

	void  *i2eChannelPtr;

	// Set indicates that the board has gone fatal.

	unsigned short i2eFatal;

	// The number of elements pointed to by i2eChannelPtr.

	unsigned short i2eChannelCnt;

	// Ring-buffers of channel structures whose channels have particular needs.

	rwlock_t	Fbuf_spinlock;
	volatile
	unsigned short i2Fbuf_strip;	// Strip index
	volatile 
	unsigned short i2Fbuf_stuff;	// Stuff index
	void  *i2Fbuf[CH_QUEUE_SIZE];	// An array of channel pointers
									// of channels who need to send
									// flow control packets.
	rwlock_t	Dbuf_spinlock;
	volatile
	unsigned short i2Dbuf_strip;	// Strip index
	volatile
	unsigned short i2Dbuf_stuff;	// Stuff index
	void  *i2Dbuf[CH_QUEUE_SIZE];	// An array of channel pointers
									// of channels who need to send
									// data or in-line command packets.
	rwlock_t	Bbuf_spinlock;
	volatile
	unsigned short i2Bbuf_strip;	// Strip index
	volatile
	unsigned short i2Bbuf_stuff;	// Stuff index
	void  *i2Bbuf[CH_QUEUE_SIZE];	// An array of channel pointers
									// of channels who need to send
									// bypass command packets.

	/*
	 * A set of flags to indicate that certain events have occurred on at least
	 * one of the ports on this board. We use this to decide whether to spin
	 * through the channels looking for breaks, etc.
	 */
	int		got_input;
	int		status_change;
	bidStat	channelBtypes;

	/*
	 * Debugging counters, etc.
	 */
	unsigned long debugFlowQueued;
	unsigned long debugInlineQueued;
	unsigned long debugDataQueued;
	unsigned long debugBypassQueued;
	unsigned long debugFlowCount;
	unsigned long debugInlineCount;
	unsigned long debugBypassCount;
	
	rwlock_t	read_fifo_spinlock;
	rwlock_t	write_fifo_spinlock;

//	For queuing interrupt bottom half handlers.	/\/\|=mhw=|\/\/
	struct work_struct	tqueue_interrupt;

	struct timer_list  SendPendingTimer;   // Used by iiSendPending
	unsigned int	SendPendingRetry;
} i2eBordStr, *i2eBordStrPtr;

//-------------------------------------------------------------------
// Macro Definitions for the indirect calls defined in the i2eBordStr
//-------------------------------------------------------------------
//
#define iiDelay(a,b)          (*(a)->i2eDelay)(b)
#define iiWriteBuf(a,b,c)     (*(a)->i2eWriteBuf)(a,b,c)
#define iiReadBuf(a,b,c)      (*(a)->i2eReadBuf)(a,b,c)

#define iiWriteWord(a,b)      (*(a)->i2eWriteWord)(a,b)
#define iiReadWord(a)         (*(a)->i2eReadWord)(a)

#define iiWaitForTxEmpty(a,b) (*(a)->i2eWaitForTxEmpty)(a,b)

#define iiTxMailEmpty(a)      (*(a)->i2eTxMailEmpty)(a)
#define iiTrySendMail(a,b)    (*(a)->i2eTrySendMail)(a,b)

#define iiGetMail(a)          (*(a)->i2eGetMail)(a)
#define iiEnableMailIrq(a)    (*(a)->i2eEnableMailIrq)(a)
#define iiDisableMailIrq(a)   (*(a)->i2eWriteMask)(a,0)
#define iiWriteMask(a,b)      (*(a)->i2eWriteMask)(a,b)

//-------------------------------------------
// Manifests for i2eBordStr:
//-------------------------------------------

#define YES 1
#define NO  0

#define NULLFUNC (void (*)(void))0
#define NULLPTR (void *)0

typedef void (*delayFunc_t)(unsigned int);

// i2eValid
//
#define I2E_MAGIC       0x4251   // Structure is valid.
#define I2E_INCOMPLETE  0x1122   // Structure failed during init.


// i2eError
//
#define I2EE_GOOD       0	// Operation successful
#define I2EE_BADADDR    1	// Address out of range
#define I2EE_BADSTATE   2	// Attempt to perform a function when the board
							// structure was in the incorrect state
#define I2EE_BADMAGIC   3	// Bad magic number from Power On test (i2ePomSize
							// reflects what was read
#define I2EE_PORM_SHORT 4	// Power On message too short
#define I2EE_PORM_LONG  5	// Power On message too long
#define I2EE_BAD_FAMILY 6	// Un-supported board family type
#define I2EE_INCONSIST  7	// Firmware reports something impossible,
							// e.g. unexpected number of ports... Almost no
							// excuse other than bad FIFO...
#define I2EE_POSTERR    8	// Power-On self test reported a bad error
#define I2EE_BADBUS     9	// Unknown Bus type declared in message
#define I2EE_TXE_TIME   10	// Timed out waiting for TX Fifo to empty
#define I2EE_INVALID    11	// i2eValid field does not indicate a valid and
							// complete board structure (for functions which
							// require this be so.)
#define I2EE_BAD_PORT   12	// Discrepancy between channels actually found and
							// what the product is supposed to have. Check
							// i2eGoodMap vs i2eChannelMap for details.
#define I2EE_BAD_IRQ    13	// Someone specified an unsupported IRQ
#define I2EE_NOCHANNELS 14	// No channel structures have been defined (for
							// functions requiring this).

// i2eFifoStyle
//
#define FIFO_II   0  /* IntelliPort-II style: see also i2hw.h */
#define FIFO_IIEX 1  /* IntelliPort-IIEX style */

// i2eGetMail
//
#define NO_MAIL_HERE    0x1111	// Since mail is unsigned char, cannot possibly
								// promote to 0x1111.
// i2eState
//
#define II_STATE_COLD      0  // Addresses have been defined, but board not even
							  // reset yet.
#define II_STATE_RESET     1  // Board,if it exists, has just been reset
#define II_STATE_READY     2  // Board ready for its first block
#define II_STATE_LOADING   3  // Board continuing load
#define II_STATE_LOADED    4  // Board has finished load: status ok
#define II_STATE_BADLOAD   5  // Board has finished load: failed!
#define II_STATE_STDLOADED 6  // Board has finished load: standard firmware

// i2eUsingIrq
//
#define IRQ_UNDEFINED   0x1352  // No valid irq (or polling = 0) can ever
								// promote to this!
//------------------------------------------
// Handy Macros for i2ellis.c and others
// Note these are common to -II and -IIEX
//------------------------------------------

// Given a pointer to the board structure, does the input FIFO have any data or
// not?
//
#define HAS_INPUT(pB)      !(INB(pB->i2eStatus) & ST_IN_EMPTY)
#define HAS_NO_INPUT(pB)   (INB(pB->i2eStatus) & ST_IN_EMPTY)

// Given a pointer to board structure, read a byte or word from the fifo
//
#define BYTE_FROM(pB)      (unsigned char)INB(pB->i2eData)
#define WORD_FROM(pB)      (unsigned short)INW(pB->i2eData)

// Given a pointer to board structure, is there room for any data to be written
// to the data fifo?
//
#define HAS_OUTROOM(pB)    !(INB(pB->i2eStatus) & ST_OUT_FULL)
#define HAS_NO_OUTROOM(pB) (INB(pB->i2eStatus) & ST_OUT_FULL)

// Given a pointer to board structure, write a single byte to the fifo
// structure. Note that for 16-bit interfaces, the high order byte is undefined
// and unknown.
//
#define BYTE_TO(pB, c)     OUTB(pB->i2eData,(c))

// Write a word to the fifo structure. For 8-bit interfaces, this may have
// unknown results.
//
#define WORD_TO(pB, c)     OUTW(pB->i2eData,(c))

// Given a pointer to the board structure, is there anything in the incoming
// mailbox?
//
#define HAS_MAIL(pB)       (INB(pB->i2eStatus) & ST_IN_MAIL)

#define UPDATE_FIFO_ROOM(pB)  (pB)->i2eFifoRemains=(pB)->i2eFifoSize

// Handy macro to round up a number (like the buffer write and read routines do)
// 
#define ROUNDUP(number)    (((number)+1) & (~1))

//------------------------------------------
// Function Declarations for i2ellis.c
//------------------------------------------
//
// Functions called directly
//
// Initialization of a board & structure is in four (five!) parts:
//
// 0) iiEllisInit()  - Initialize iiEllis subsystem.
// 1) iiSetAddress() - Define the board address & delay function for a board.
// 2) iiReset()      - Reset the board   (provided it exists)
//       -- Note you may do this to several boards --
// 3) iiResetDelay() - Delay for 2 seconds (once for all boards)
// 4) iiInitialize() - Attempt to read Power-up message; further initialize
//                     accelerators
//
// Then you may use iiDownloadAll() or iiDownloadFile() (in i2file.c) to write
// loadware.  To change loadware, you must begin again with step 2, resetting
// the board again (step 1 not needed).

static void iiEllisInit(void);
static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t );
static int iiReset(i2eBordStrPtr);
static int iiResetDelay(i2eBordStrPtr);
static int iiInitialize(i2eBordStrPtr);

// Routine to validate that all channels expected are there.
//
extern int iiValidateChannels(i2eBordStrPtr);

// Routine used to download a block of loadware.
//
static int iiDownloadBlock(i2eBordStrPtr, loadHdrStrPtr, int);

// Return values given by iiDownloadBlock, iiDownloadAll, iiDownloadFile:
//
#define II_DOWN_BADVALID   0	// board structure is invalid
#define II_DOWN_CONTINUING 1	// So far, so good, firmware expects more
#define II_DOWN_GOOD       2	// Download complete, CRC good
#define II_DOWN_BAD        3	// Download complete, but CRC bad
#define II_DOWN_BADFILE    4	// Bad magic number in loadware file
#define II_DOWN_BADSTATE   5	// Board is in an inappropriate state for
								// downloading loadware. (see i2eState)
#define II_DOWN_TIMEOUT    6	// Timeout waiting for firmware
#define II_DOWN_OVER       7	// Too much data
#define II_DOWN_UNDER      8	// Not enough data
#define II_DOWN_NOFILE     9	// Loadware file not found

// Routine to download an entire loadware module: Return values are a subset of
// iiDownloadBlock's, excluding, of course, II_DOWN_CONTINUING
//
static int iiDownloadAll(i2eBordStrPtr, loadHdrStrPtr, int, int);

// Called indirectly always.  Needed externally so the routine might be
// SPECIFIED as an argument to iiReset()
//
//static void ii2DelayIO(unsigned int);		// N-millisecond delay using
											//hardware spin
//static void ii2DelayTimer(unsigned int);	// N-millisecond delay using Linux
											//timer

// Many functions defined here return True if good, False otherwise, with an
// error code in i2eError field. Here is a handy macro for setting the error
// code and returning.
//
#define COMPLETE(pB,code) \
	if(1){ \
		 pB->i2eError = code; \
		 return (code == I2EE_GOOD);\
	}

#endif   // I2ELLIS_H