1/*
2 * BeOS Driver for Intel ICH AC'97 Link interface
3 *
4 * Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
5 *
6 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without modification,
8 * are permitted provided that the following conditions are met:
9 *
10 * - Redistributions of source code must retain the above copyright notice,
11 *   this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright notice,
13 *   this list of conditions and the following disclaimer in the documentation
14 *   and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28#include <KernelExport.h>
29#include <OS.h>
30#include <PCI.h>
31#include "debug.h"
32#include "io.h"
33#include "ich.h"
34#include "config.h"
35
36extern pci_module_info *pci;
37
38status_t ich_codec_wait(void);
39
40uint8
41ich_reg_read_8(int regno)
42{
43	ASSERT(regno >= 0);
44	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
45	if (config->type & TYPE_ICH4)
46		return *(uint8 *)(((char *)config->log_mbbar) + regno);
47	else
48		return pci->read_io_8(config->nabmbar + regno);
49}
50
51uint16
52ich_reg_read_16(int regno)
53{
54	ASSERT(regno >= 0);
55	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
56	if (config->type & TYPE_ICH4)
57		return *(uint16 *)(((char *)config->log_mbbar) + regno);
58	else
59		return pci->read_io_16(config->nabmbar + regno);
60}
61
62uint32
63ich_reg_read_32(int regno)
64{
65	ASSERT(regno >= 0);
66	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
67	if (config->type & TYPE_ICH4)
68		return *(uint32 *)(((char *)config->log_mbbar) + regno);
69	else
70		return pci->read_io_32(config->nabmbar + regno);
71}
72
73void
74ich_reg_write_8(int regno, uint8 value)
75{
76	ASSERT(regno >= 0);
77	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
78	if (config->type & TYPE_ICH4)
79		*(uint8 *)(((char *)config->log_mbbar) + regno) = value;
80	else
81		pci->write_io_8(config->nabmbar + regno, value);
82}
83
84void
85ich_reg_write_16(int regno, uint16 value)
86{
87	ASSERT(regno >= 0);
88	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
89	if (config->type & TYPE_ICH4)
90		*(uint16 *)(((char *)config->log_mbbar) + regno) = value;
91	else
92		pci->write_io_16(config->nabmbar + regno, value);
93}
94
95void
96ich_reg_write_32(int regno, uint32 value)
97{
98	ASSERT(regno >= 0);
99	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
100	if (config->type & TYPE_ICH4)
101		*(uint32 *)(((char *)config->log_mbbar) + regno) = value;
102	else
103		pci->write_io_32(config->nabmbar + regno, value);
104}
105
106status_t
107ich_codec_wait(void)
108{
109	int i;
110	for (i = 0; i < 1100; i++) {
111		if ((ich_reg_read_8(ICH_REG_ACC_SEMA) & 0x01) == 0)
112			return B_OK;
113		if (i > 100)
114			snooze(1);
115	}
116	return B_TIMED_OUT;
117}
118
119uint16
120ich_codec_read(int regno)
121{
122	status_t rv;
123	ASSERT(regno >= 0);
124	ASSERT((regno & 1) == 0);
125	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 511) || regno <= 255);
126	if (regno == 0x54) // intel uses 0x54 for GPIO access, we filter it!
127		return 0;
128	rv = ich_codec_wait();
129	if (rv != B_OK)
130		PRINT(("semaphore timeout reading register %#x\n",regno));
131	if (config->type & TYPE_ICH4)
132		return *(uint16 *)(((char *)config->log_mmbar) + regno);
133	else
134		return pci->read_io_16(config->nambar + regno);
135}
136
137void
138ich_codec_write(int regno, uint16 value)
139{
140	status_t rv;
141	ASSERT(regno >= 0);
142	ASSERT((regno & 1) == 0);
143	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 511) || regno <= 255);
144	if (regno == 0x54) // intel uses 0x54 for GPIO access, we filter it!
145		return;
146	rv = ich_codec_wait();
147	if (rv != B_OK)
148		PRINT(("semaphore timeout writing register %#x\n",regno));
149	if (config->type & TYPE_ICH4)
150		*(uint16 *)(((char *)config->log_mmbar) + regno) = value;
151	else
152		pci->write_io_16(config->nambar + regno, value);
153}
154