revert 213 commits (to 56092) from the last month. 10 still need work to resolve...
[AROS.git] / workbench / devs / networks / prism2 / pccard.c
blobf4525e57739df230f55437ba2797f311cca33b1e
1 /*
3 Copyright (C) 2000-2014 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
23 #include <exec/types.h>
24 #include <utility/tagitem.h>
25 #include <libraries/pccard.h>
27 #include <proto/exec.h>
28 #include <proto/utility.h>
29 #include <proto/cardres.h>
30 #include <proto/pccard.h>
32 #include "device.h"
34 #include "pccard_protos.h"
35 #include "device_protos.h"
36 #include "unit_protos.h"
38 #define MAX_TUPLE_SIZE 0xff
39 #define TUPLE_BUFFER_SIZE (MAX_TUPLE_SIZE + 8)
40 #define HANDLE_PRIORITY 10
43 struct BusContext
45 struct DevUnit *unit;
46 struct CardHandle *card_handle;
47 UBYTE *tuple_buffer;
48 UPINT config_base;
49 UPINT io_base;
50 UWORD resource_version;
51 BOOL have_card;
55 /* Private prototypes */
57 static struct DevUnit *FindPCCardUnit(ULONG index, struct DevBase *base);
58 static struct DevUnit *CreatePCCardUnit(ULONG index,
59 struct DevBase *base);
60 static struct BusContext *AllocCard(struct DevBase *base);
61 static VOID FreeCard(struct BusContext *context, struct DevBase *base);
62 static BOOL IsCardCompatible(struct BusContext *context,
63 struct DevBase *base);
64 static BOOL InitialiseCard(struct BusContext *context,
65 struct DevBase *base);
66 static VOID CardRemovedHook(struct BusContext *context,
67 struct DevBase *base);
68 static BOOL CardInsertedHook(struct BusContext *context,
69 struct DevBase *base);
70 static VOID CardRemovedInt(REG(a1, struct BusContext *context),
71 REG(a6, APTR int_code));
72 static VOID CardInsertedInt(REG(a1, struct BusContext *context),
73 REG(a6, APTR int_code));
74 static UBYTE CardStatusInt(REG(a1, struct BusContext *context),
75 REG(a6, APTR int_code), REG(d0, UBYTE mask));
76 static VOID WordsInHook(struct BusContext *context,
77 ULONG offset, UWORD *buffer, ULONG count);
78 static VOID WordsOutHook(struct BusContext *context, ULONG offset,
79 const UWORD *buffer, ULONG count);
80 static VOID BEWordOutHook(struct BusContext *context, ULONG offset,
81 UWORD value);
82 static UWORD LEWordInHook(struct BusContext *context, ULONG offset);
83 static VOID LEWordOutHook(struct BusContext *context, ULONG offset,
84 UWORD value);
87 static const ULONG product_codes[] =
89 0x000b7300,
90 0x00890001,
91 0x01010001,
92 0x01050000,
93 0x01380002,
94 0x014d0801,
95 0x01560002,
96 0x01560003,
97 0x016b0001,
98 0x016c0001,
99 0x01eb080a,
100 0x02500002,
101 0x02610002,
102 0x026f0305,
103 0x026f030b,
104 0x02741612,
105 0x02741613,
106 0x02743301,
107 0x028a0002,
108 0x02ac0002,
109 0x02d20001,
110 0x16680101,
111 0xc0010008,
112 0xc00f0000,
113 0xc2500002,
114 0xd6010002,
115 0xd6010004,
116 0xd6010005,
117 0xd6010010,
122 static const struct TagItem unit_tags[] =
124 {IOTAG_WordsIn, (UPINT)WordsInHook},
125 {IOTAG_WordsOut, (UPINT)WordsOutHook},
126 {IOTAG_BEWordOut, (UPINT)BEWordOutHook},
127 {IOTAG_LEWordIn, (UPINT)LEWordInHook},
128 {IOTAG_LEWordOut, (UPINT)LEWordOutHook},
129 {TAG_END, 0}
133 /****i* prism2.device/GetPCCardCount ***************************************
135 * NAME
136 * GetPCCardCount -- Get the number of compatible PC Cards.
138 * SYNOPSIS
139 * count = GetPCCardCount()
141 * ULONG GetPCCardCount();
143 ****************************************************************************
147 ULONG GetPCCardCount(struct DevBase *base)
149 ULONG count = 0;
150 struct BusContext *context;
152 if(CardResource != NULL)
154 if(FindPCCardUnit(0, base) != NULL)
155 count = 1;
156 else
158 context = AllocCard(base);
159 if(context != NULL)
161 count = 1;
162 FreeCard(context, base);
167 return count;
172 /****i* prism2.device/GetPCCardUnit ****************************************
174 * NAME
175 * GetPCCardUnit -- Get a unit by number.
177 * SYNOPSIS
178 * unit = GetPCCardUnit(index)
180 * struct DevUnit *GetPCCardUnit(ULONG);
182 ****************************************************************************
186 struct DevUnit *GetPCCardUnit(ULONG index, struct DevBase *base)
188 struct DevUnit *unit;
190 unit = FindPCCardUnit(index, base);
192 if(unit == NULL)
194 unit = CreatePCCardUnit(index, base);
195 if(unit != NULL)
196 AddTail((APTR)&base->pccard_units, (APTR)unit);
199 return unit;
204 /****i* prism2.device/FindPCCardUnit ***************************************
206 * NAME
207 * FindPCCardUnit -- Find a unit by number.
209 * SYNOPSIS
210 * unit = FindPCCardUnit(index)
212 * struct DevUnit *FindPCCardUnit(ULONG);
214 ****************************************************************************
218 static struct DevUnit *FindPCCardUnit(ULONG index, struct DevBase *base)
220 struct DevUnit *unit, *tail;
222 unit = (APTR)base->pccard_units.mlh_Head;
223 tail = (APTR)&base->pccard_units.mlh_Tail;
224 if(unit == tail)
225 unit = NULL;
227 return unit;
232 /****i* prism2.device/CreatePCCardUnit *************************************
234 * NAME
235 * CreatePCCardUnit -- Create a unit.
237 * SYNOPSIS
238 * unit = CreatePCCardUnit(index)
240 * struct DevUnit *CreatePCCardUnit(ULONG);
242 * FUNCTION
243 * Creates a new unit.
245 ****************************************************************************
249 static struct DevUnit *CreatePCCardUnit(ULONG index,
250 struct DevBase *base)
252 BOOL success = TRUE;
253 struct BusContext *context;
254 struct DevUnit *unit;
256 /* Get card from system */
258 context = AllocCard(base);
259 if(context == NULL)
260 success = FALSE;
262 /* Prepare card for use */
264 if(success)
266 if(!InitialiseCard(context, base))
267 success = FALSE;
270 /* Create device driver unit */
272 if(success)
274 context->unit = unit =
275 CreateUnit(index, context, unit_tags, PCCARD_BUS, base);
276 if(unit == NULL)
277 success = FALSE;
280 if(success)
282 if(!(WrapInt(&unit->status_int, base)
283 && WrapInt(&unit->rx_int, base)
284 && WrapInt(&unit->tx_int, base)
285 && WrapInt(&unit->info_int, base)))
286 success = FALSE;
288 unit->insertion_function = (APTR)CardInsertedHook;
289 unit->removal_function = (APTR)CardRemovedHook;
292 if(!success)
294 if(context != NULL)
296 DeleteUnit(context->unit, base);
297 FreeCard(context, base);
299 unit = NULL;
302 return unit;
307 /****i* prism2.device/DeletePCCardUnit *************************************
309 * NAME
310 * DeletePCCardUnit -- Delete a unit.
312 * SYNOPSIS
313 * DeletePCCardUnit(unit)
315 * VOID DeletePCCardUnit(struct DevUnit *);
317 * FUNCTION
318 * Deletes a unit.
320 * INPUTS
321 * unit - Device unit (may be NULL).
323 * RESULT
324 * None.
326 ****************************************************************************
330 VOID DeletePCCardUnit(struct DevUnit *unit, struct DevBase *base)
332 struct BusContext *context;
334 if(unit != NULL)
336 UnwrapInt(&unit->info_int, base);
337 UnwrapInt(&unit->tx_int, base);
338 UnwrapInt(&unit->rx_int, base);
339 UnwrapInt(&unit->status_int, base);
340 context = unit->card;
341 DeleteUnit(unit, base);
342 FreeCard(context, base);
345 return;
350 /****i* prism2.device/AllocCard ********************************************
352 * NAME
353 * AllocCard -- Get card from system.
355 * SYNOPSIS
356 * unit = AllocCard()
358 * struct BusContext *AllocCard();
360 ****************************************************************************
364 static struct BusContext *AllocCard(struct DevBase *base)
366 BOOL success = TRUE;
367 struct BusContext *context;
368 struct CardHandle *card_handle;
369 struct Interrupt *card_removed_int, *card_inserted_int, *card_status_int;
371 context = AllocMem(sizeof(struct BusContext), MEMF_PUBLIC | MEMF_CLEAR);
372 if(context == NULL)
373 success = FALSE;
375 if(success)
377 context->resource_version =
378 ((struct Library *)base->card_base)->lib_Version;
379 context->card_handle = card_handle =
380 AllocMem(sizeof(struct CardHandle), MEMF_PUBLIC | MEMF_CLEAR);
381 context->tuple_buffer =
382 AllocVec(TUPLE_BUFFER_SIZE, MEMF_PUBLIC);
384 if(card_handle == NULL || context->tuple_buffer == NULL)
385 success = FALSE;
388 if(success)
390 /* Set up card handle */
392 card_handle->cah_CardNode.ln_Pri = HANDLE_PRIORITY;
393 card_handle->cah_CardNode.ln_Name =
394 base->device.dd_Library.lib_Node.ln_Name;
395 card_handle->cah_CardFlags = CARDF_POSTSTATUS;
397 card_handle->cah_CardRemoved = card_removed_int =
398 AllocVec(sizeof(struct Interrupt), MEMF_PUBLIC | MEMF_CLEAR);
400 card_handle->cah_CardInserted = card_inserted_int =
401 AllocVec(sizeof(struct Interrupt), MEMF_PUBLIC | MEMF_CLEAR);
403 card_handle->cah_CardStatus = card_status_int =
404 AllocVec(sizeof(struct Interrupt), MEMF_PUBLIC | MEMF_CLEAR);
406 if(card_removed_int == NULL || card_inserted_int == NULL
407 || card_status_int == NULL)
408 success = FALSE;
411 if(success)
413 /* Try to gain access to card */
415 card_removed_int->is_Code = CardRemovedInt;
416 card_removed_int->is_Data = context;
417 card_inserted_int->is_Code = CardInsertedInt;
418 card_inserted_int->is_Data = context;
419 card_status_int->is_Code = (APTR)CardStatusInt;
420 card_status_int->is_Data = context;
422 if(!(WrapCardInt(card_removed_int, base)
423 && WrapCardInt(card_inserted_int, base)
424 && WrapCardInt(card_status_int, base)))
425 success = FALSE;
428 if(success)
430 if(OwnCard(card_handle) != 0)
431 success = FALSE;
434 if(success)
436 if(!IsCardCompatible(context, base))
437 success = FALSE;
440 if(!success)
442 FreeCard(context, base);
443 context = NULL;
445 return context;
450 /****i* prism2.device/FreeCard *********************************************
452 * NAME
453 * FreeCard
455 * SYNOPSIS
456 * FreeCard(context)
458 * VOID FreeCard(struct BusContext *);
460 ****************************************************************************
464 static VOID FreeCard(struct BusContext *context, struct DevBase *base)
466 struct CardHandle *card_handle;
468 if(context != NULL)
470 card_handle = context->card_handle;
472 if(context->have_card)
474 CardMiscControl(card_handle, 0);
475 CardResetCard(card_handle);
477 ReleaseCard(card_handle, CARDF_REMOVEHANDLE);
478 UnwrapCardInt(card_handle->cah_CardStatus, base);
479 UnwrapCardInt(card_handle->cah_CardInserted, base);
480 UnwrapCardInt(card_handle->cah_CardRemoved, base);
482 FreeVec(card_handle->cah_CardStatus);
483 FreeVec(card_handle->cah_CardInserted);
484 FreeVec(card_handle->cah_CardRemoved);
485 FreeVec(context->tuple_buffer);
486 FreeMem(card_handle, sizeof(struct CardHandle));
488 FreeMem(context, sizeof(struct BusContext));
491 return;
496 /****i* prism2.device/IsCardCompatible *************************************
498 * NAME
499 * IsCardCompatible
501 * SYNOPSIS
502 * compatible = IsCardCompatible(context)
504 * BOOL IsCardCompatible(struct BusContext *);
506 ****************************************************************************
510 static BOOL IsCardCompatible(struct BusContext *context,
511 struct DevBase *base)
513 BOOL success = TRUE;
514 struct CardHandle *card_handle;
515 UBYTE *tuple_buffer;
516 const struct TagItem *tuple_tags = NULL;
517 ULONG code;
518 const ULONG *p;
519 UWORD maker = 0, product = 0;
521 card_handle = context->card_handle;
522 tuple_buffer = context->tuple_buffer;
524 /* Get card's make and model */
526 if(CopyTuple(card_handle, tuple_buffer, PCCARD_TPL_MANFID,
527 MAX_TUPLE_SIZE))
529 tuple_tags = PCCard_GetTupleInfo(tuple_buffer);
530 if(tuple_tags != NULL)
532 maker = GetTagData(PCCARD_Maker, 0, tuple_tags);
533 product = GetTagData(PCCARD_Product, 0, tuple_tags);
537 /* Check this is a card we can use */
539 code = maker << 16 | product;
540 for(success = FALSE, p = product_codes; *p != 0; p++)
541 if(*p == code)
542 success = TRUE;
543 PCCard_FreeTupleInfo(tuple_tags);
545 return success;
550 /****i* prism2.device/InitialiseCard ***************************************
552 * NAME
553 * InitialiseCard
555 * SYNOPSIS
556 * success = InitialiseCard(context)
558 * BOOL InitialiseCard(struct BusContext *);
560 ****************************************************************************
564 static BOOL InitialiseCard(struct BusContext *context,
565 struct DevBase *base)
567 BOOL success = TRUE;
568 struct CardHandle *card_handle;
569 struct CardMemoryMap *card_map;
570 UBYTE config_value, i, window_count, *tuple_buffer;
571 const struct TagItem *tuple_tags = NULL;
572 ULONG *io_bases, *io_lengths, io_base_offset = 0, config_base_offset;
574 /* Wake up card's I/O functionality */
576 card_handle = context->card_handle;
577 tuple_buffer = context->tuple_buffer;
578 CardMiscControl(card_handle,
579 CARD_ENABLEF_DIGAUDIO | CARD_DISABLEF_WP);
581 /* Get configuration data */
583 if(!CopyTuple(card_handle, tuple_buffer, PCCARD_TPL_CONFIG,
584 MAX_TUPLE_SIZE))
585 success = FALSE;
587 if(success)
589 PCCard_FreeTupleInfo(tuple_tags);
590 tuple_tags = PCCard_GetTupleInfo(tuple_buffer);
591 if(tuple_tags == NULL)
592 success = FALSE;
595 if(success)
597 config_base_offset = GetTagData(PCCARD_RegisterBase, 0, tuple_tags);
599 PCCard_FreeTupleInfo(tuple_tags);
600 tuple_tags = NULL;
602 /* Get IO base */
604 if(!CopyTuple(card_handle, tuple_buffer, PCCARD_TPL_CFTABLEENTRY,
605 MAX_TUPLE_SIZE))
606 success = FALSE;
609 if(success)
611 tuple_tags = PCCard_GetTupleInfo(tuple_buffer);
612 if(tuple_tags == NULL)
613 success = FALSE;
616 if(success)
618 config_value = GetTagData(PCCARD_ModeNo, 0, tuple_tags);
620 io_bases =
621 (APTR)GetTagData(PCCARD_IOWinBases, (UPINT)NULL, tuple_tags);
622 if(io_bases == NULL)
623 success = FALSE;
626 /* Find the appropriate IO window */
628 if(success)
630 io_lengths =
631 (APTR)GetTagData(PCCARD_IOWinLengths, (UPINT)NULL, tuple_tags);
633 window_count = GetTagData(PCCARD_IOWinCount, 0, tuple_tags);
635 for(i = 0; i < window_count && io_base_offset == 0; i++)
636 if(io_lengths[i] == IO_WINDOW_SIZE)
637 io_base_offset = io_bases[i];
640 PCCard_FreeTupleInfo(tuple_tags);
642 /* Configure card */
644 if(success)
646 card_map = GetCardMap();
647 context->config_base =
648 (UPINT)card_map->cmm_AttributeMemory + config_base_offset;
650 context->io_base = (UPINT)card_map->cmm_IOMemory + io_base_offset;
651 BYTEOUT(context->config_base + PCCARD_REG_COR, config_value);
652 BYTEOUT(context->config_base + PCCARD_REG_CCSR,
653 BYTEIN(context->config_base + PCCARD_REG_CCSR)
654 | PCCARD_REG_CCSRF_AUDIOENABLE);
657 return success;
662 /****i* prism2.device/CardRemovedHook **************************************
664 * NAME
665 * CardRemovedHook
667 * SYNOPSIS
668 * CardRemovedHook(context)
670 * VOID CardRemovedHook(struct BusContext *);
672 ****************************************************************************
676 static VOID CardRemovedHook(struct BusContext *context,
677 struct DevBase *base)
679 ReleaseCard(context->card_handle, 0);
681 return;
686 /****i* prism2.device/CardInsertedHook *************************************
688 * NAME
689 * CardInsertedHook
691 * SYNOPSIS
692 * success = CardInsertedHook(context)
694 * BOOL CardInsertedHook(struct BusContext *);
696 ****************************************************************************
700 static BOOL CardInsertedHook(struct BusContext *context,
701 struct DevBase *base)
703 BOOL success = TRUE;
705 success = IsCardCompatible(context, base);
707 if(success)
708 success = InitialiseCard(context, base);
710 if(success)
711 success = InitialiseAdapter(context->unit, TRUE, base);
713 if(!success)
714 ReleaseCard(context->card_handle, 0);
716 return success;
721 /****i* prism2.device/CardRemovedInt ***************************************
723 * NAME
724 * CardRemovedInt
726 * SYNOPSIS
727 * CardRemovedInt(context)
729 * VOID CardRemovedInt(struct BusContext *);
731 ****************************************************************************
735 static VOID CardRemovedInt(REG(a1, struct BusContext *context),
736 REG(a6, APTR int_code))
738 struct DevBase *base;
739 struct DevUnit *unit;
741 /* Record loss of card and get our task to call ReleaseCard() */
743 unit = context->unit;
744 if (unit != NULL)
746 base = unit->device;
747 if((unit->flags & UNITF_ONLINE) != 0)
748 unit->flags |= UNITF_WASONLINE;
749 unit->flags &= ~(UNITF_HAVEADAPTER | UNITF_ONLINE);
751 context->have_card = FALSE;
752 if (unit != NULL)
753 Signal(unit->task, unit->card_removed_signal);
755 return;
760 /****i* prism2.device/CardInsertedInt **************************************
762 * NAME
763 * CardInsertedInt
765 * SYNOPSIS
766 * CardInsertedInt(context)
768 * VOID CardInsertedInt(struct BusContext *);
770 ****************************************************************************
774 static VOID CardInsertedInt(REG(a1, struct BusContext *context),
775 REG(a6, APTR int_code))
777 struct DevBase *base;
778 struct DevUnit *unit;
780 unit = context->unit;
781 if (unit != NULL) {
782 base = unit->device;
783 context->have_card = TRUE;
784 Signal(unit->task, unit->card_inserted_signal);
787 return;
792 /****i* prism2.device/CardStatusInt ****************************************
794 * NAME
795 * CardStatusInt
797 * SYNOPSIS
798 * mask = CardStatusInt(context, int_code, mask)
800 * UBYTE CardStatusInt(struct BusContext *, APTR, UBYTE);
802 ****************************************************************************
804 * int_code is really in A5, but GCC 2.95.3 doesn't seem able to handle that.
805 * Since we don't use this parameter, we can lie.
809 static UBYTE CardStatusInt(REG(a1, struct BusContext *context),
810 REG(a6, APTR int_code), REG(d0, UBYTE mask))
812 if(context->resource_version < 39)
814 /* Work around gayle interrupt bug */
816 *((volatile UBYTE *)0xda9000) = (mask ^ 0x2c) | 0xc0;
817 mask = 0;
820 if(context->unit != NULL)
821 StatusInt(context->unit, StatusInt);
823 return mask;
828 /****i* prism2.device/WordsInHook ******************************************
830 * NAME
831 * WordsInHook
833 * SYNOPSIS
834 * WordsInHook(context, offset, buffer, count)
836 * VOID WordsInHook(struct BusContext *, ULONG, UWORD *, ULONG);
838 ****************************************************************************
842 static VOID WordsInHook(struct BusContext *context, ULONG offset,
843 UWORD *buffer, ULONG count)
845 WORDSIN(context->io_base + offset, buffer, count);
847 return;
852 /****i* prism2.device/WordsOutHook *****************************************
854 * NAME
855 * WordsOutHook
857 * SYNOPSIS
858 * WordsOutHook(context, offset, buffer, count)
860 * VOID WordsOutHook(struct BusContext *, ULONG, const UWORD *, ULONG);
862 ****************************************************************************
866 static VOID WordsOutHook(struct BusContext *context, ULONG offset,
867 const UWORD *buffer, ULONG count)
869 WORDSOUT(context->io_base + offset, buffer, count);
871 return;
876 /****i* prism2.device/BEWordOutHook ****************************************
878 * NAME
879 * BEWordOutHook
881 * SYNOPSIS
882 * BEWordOutHook(context, offset, value)
884 * VOID BEWordOutHook(struct BusContext *, ULONG, UWORD);
886 ****************************************************************************
890 static VOID BEWordOutHook(struct BusContext *context, ULONG offset,
891 UWORD value)
893 BEWORDOUT(context->io_base + offset, value);
895 return;
900 /****i* prism2.device/LEWordInHook *****************************************
902 * NAME
903 * LEWordInHook
905 * SYNOPSIS
906 * value = LEWordInHook(context, offset)
908 * UWORD LEWordInHook(struct BusContext *, ULONG);
910 ****************************************************************************
914 static UWORD LEWordInHook(struct BusContext *context, ULONG offset)
916 return LEWORDIN(context->io_base + offset);
921 /****i* prism2.device/LEWordOutHook ****************************************
923 * NAME
924 * LEWordOutHook
926 * SYNOPSIS
927 * LEWordOutHook(context, offset, value)
929 * VOID LEWordOutHook(struct BusContext *, ULONG, UWORD);
931 ****************************************************************************
935 static VOID LEWordOutHook(struct BusContext *context, ULONG offset,
936 UWORD value)
938 LEWORDOUT(context->io_base + offset, value);
940 return;