ipmi_kcs.c revision 281941
1240116Smarcel/*-
2240116Smarcel * Copyright (c) 2006 IronPort Systems Inc. <ambrisko@ironport.com>
3240116Smarcel * All rights reserved.
4240116Smarcel *
5240116Smarcel * Redistribution and use in source and binary forms, with or without
6240116Smarcel * modification, are permitted provided that the following conditions
7240116Smarcel * are met:
8240116Smarcel * 1. Redistributions of source code must retain the above copyright
9240116Smarcel *    notice, this list of conditions and the following disclaimer.
10240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright
11240116Smarcel *    notice, this list of conditions and the following disclaimer in the
12240116Smarcel *    documentation and/or other materials provided with the distribution.
13240116Smarcel *
14240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15240116Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16240116Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17240116Smarcel * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18240116Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20240116Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21240116Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22240116Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23240116Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24240116Smarcel * SUCH DAMAGE.
25240116Smarcel */
26240116Smarcel
27240116Smarcel#include <sys/cdefs.h>
28240116Smarcel__FBSDID("$FreeBSD: head/sys/dev/ipmi/ipmi_kcs.c 281941 2015-04-24 16:56:23Z jhb $");
29240116Smarcel
30240116Smarcel#include <sys/param.h>
31240116Smarcel#include <sys/systm.h>
32240116Smarcel#include <sys/bus.h>
33240116Smarcel#include <sys/condvar.h>
34240116Smarcel#include <sys/eventhandler.h>
35240116Smarcel#include <sys/kernel.h>
36240116Smarcel#include <sys/kthread.h>
37240116Smarcel#include <sys/rman.h>
38240116Smarcel#include <sys/selinfo.h>
39240116Smarcel#include <machine/bus.h>
40240116Smarcel
41240116Smarcel#ifdef LOCAL_MODULE
42240116Smarcel#include <ipmi.h>
43240116Smarcel#include <ipmivars.h>
44240116Smarcel#else
45240116Smarcel#include <sys/ipmi.h>
46240116Smarcel#include <dev/ipmi/ipmivars.h>
47240116Smarcel#endif
48240116Smarcel
49240116Smarcelstatic void	kcs_clear_obf(struct ipmi_softc *, int);
50240116Smarcelstatic void	kcs_error(struct ipmi_softc *);
51240116Smarcelstatic int	kcs_wait_for_ibf(struct ipmi_softc *, int);
52240116Smarcelstatic int	kcs_wait_for_obf(struct ipmi_softc *, int);
53240116Smarcel
54240116Smarcelstatic int
55240116Smarcelkcs_wait_for_ibf(struct ipmi_softc *sc, int state)
56240116Smarcel{
57240116Smarcel	int status, start = ticks;
58240116Smarcel
59240116Smarcel	status = INB(sc, KCS_CTL_STS);
60240116Smarcel	if (state == 0) {
61240116Smarcel		/* WAIT FOR IBF = 0 */
62240116Smarcel		while (ticks - start < MAX_TIMEOUT && status & KCS_STATUS_IBF) {
63240116Smarcel			DELAY(100);
64240116Smarcel			status = INB(sc, KCS_CTL_STS);
65240116Smarcel		}
66240116Smarcel	} else {
67240116Smarcel		/* WAIT FOR IBF = 1 */
68240116Smarcel		while (ticks - start < MAX_TIMEOUT &&
69240116Smarcel		    !(status & KCS_STATUS_IBF)) {
70240116Smarcel			DELAY(100);
71240116Smarcel			status = INB(sc, KCS_CTL_STS);
72240116Smarcel		}
73240116Smarcel	}
74240116Smarcel	return (status);
75240116Smarcel}
76240116Smarcel
77240116Smarcelstatic int
78240116Smarcelkcs_wait_for_obf(struct ipmi_softc *sc, int state)
79240116Smarcel{
80240116Smarcel	int status, start = ticks;
81240116Smarcel
82240116Smarcel	status = INB(sc, KCS_CTL_STS);
83240116Smarcel	if (state == 0) {
84240116Smarcel		/* WAIT FOR OBF = 0 */
85240116Smarcel		while (ticks - start < MAX_TIMEOUT && status & KCS_STATUS_OBF) {
86240116Smarcel			DELAY(100);
87240116Smarcel			status = INB(sc, KCS_CTL_STS);
88240116Smarcel		}
89240116Smarcel	} else {
90240116Smarcel		/* WAIT FOR OBF = 1 */
91240116Smarcel		while (ticks - start < MAX_TIMEOUT &&
92240116Smarcel		    !(status & KCS_STATUS_OBF)) {
93240116Smarcel			DELAY(100);
94240116Smarcel			status = INB(sc, KCS_CTL_STS);
95240116Smarcel		}
96240116Smarcel	}
97240116Smarcel	return (status);
98240116Smarcel}
99240116Smarcel
100240116Smarcelstatic void
101240116Smarcelkcs_clear_obf(struct ipmi_softc *sc, int status)
102240116Smarcel{
103240116Smarcel	int data;
104240116Smarcel
105240116Smarcel	/* Clear OBF */
106240116Smarcel	if (status & KCS_STATUS_OBF) {
107240116Smarcel		data = INB(sc, KCS_DATA);
108240116Smarcel	}
109240116Smarcel}
110240116Smarcel
111240116Smarcelstatic void
112240116Smarcelkcs_error(struct ipmi_softc *sc)
113240116Smarcel{
114240116Smarcel	int retry, status;
115240116Smarcel	u_char data;
116240116Smarcel
117240116Smarcel	for (retry = 0; retry < 2; retry++) {
118240116Smarcel
119240116Smarcel		/* Wait for IBF = 0 */
120240116Smarcel		status = kcs_wait_for_ibf(sc, 0);
121240116Smarcel
122240116Smarcel		/* ABORT */
123240116Smarcel		OUTB(sc, KCS_CTL_STS, KCS_CONTROL_GET_STATUS_ABORT);
124240116Smarcel
125240116Smarcel		/* Wait for IBF = 0 */
126240116Smarcel		status = kcs_wait_for_ibf(sc, 0);
127240116Smarcel
128240116Smarcel		/* Clear OBF */
129240116Smarcel		kcs_clear_obf(sc, status);
130240116Smarcel
131240116Smarcel		if (status & KCS_STATUS_OBF) {
132240116Smarcel			data = INB(sc, KCS_DATA);
133240116Smarcel			if (data != 0)
134240116Smarcel				device_printf(sc->ipmi_dev,
135240116Smarcel				    "KCS Error Data %02x\n", data);
136240116Smarcel		}
137240116Smarcel
138240116Smarcel		/* 0x00 to DATA_IN */
139240116Smarcel		OUTB(sc, KCS_DATA, 0x00);
140240116Smarcel
141240116Smarcel		/* Wait for IBF = 0 */
142240116Smarcel		status = kcs_wait_for_ibf(sc, 0);
143240116Smarcel
144240116Smarcel		if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) {
145240116Smarcel
146240116Smarcel			/* Wait for OBF = 1 */
147240116Smarcel			status = kcs_wait_for_obf(sc, 1);
148240116Smarcel
149240116Smarcel			/* Read error status */
150240116Smarcel			data = INB(sc, KCS_DATA);
151240116Smarcel			if (data != 0)
152240116Smarcel				device_printf(sc->ipmi_dev, "KCS error: %02x\n",
153240116Smarcel				    data);
154240116Smarcel
155240116Smarcel			/* Write READ into Data_in */
156240116Smarcel			OUTB(sc, KCS_DATA, KCS_DATA_IN_READ);
157240116Smarcel
158240116Smarcel			/* Wait for IBF = 0 */
159240116Smarcel			status = kcs_wait_for_ibf(sc, 0);
160240116Smarcel		}
161240116Smarcel
162240116Smarcel		/* IDLE STATE */
163240116Smarcel		if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) {
164240116Smarcel			/* Wait for OBF = 1 */
165240116Smarcel			status = kcs_wait_for_obf(sc, 1);
166240116Smarcel
167240116Smarcel			/* Clear OBF */
168240116Smarcel			kcs_clear_obf(sc, status);
169240116Smarcel			return;
170240116Smarcel		}
171240116Smarcel	}
172240116Smarcel	device_printf(sc->ipmi_dev, "KCS: Error retry exhausted\n");
173240116Smarcel}
174240116Smarcel
175240116Smarcel/*
176240116Smarcel * Start to write a request.  Waits for IBF to clear and then sends the
177240116Smarcel * WR_START command.
178240116Smarcel */
179240116Smarcelstatic int
180240116Smarcelkcs_start_write(struct ipmi_softc *sc)
181240116Smarcel{
182240116Smarcel	int retry, status;
183240116Smarcel
184240116Smarcel	for (retry = 0; retry < 10; retry++) {
185240116Smarcel		/* Wait for IBF = 0 */
186240116Smarcel		status = kcs_wait_for_ibf(sc, 0);
187240116Smarcel		if (status & KCS_STATUS_IBF)
188240116Smarcel			return (0);
189240116Smarcel
190240116Smarcel		/* Clear OBF */
191240116Smarcel		kcs_clear_obf(sc, status);
192240116Smarcel
193240116Smarcel		/* Write start to command */
194240116Smarcel		OUTB(sc, KCS_CTL_STS, KCS_CONTROL_WRITE_START);
195240116Smarcel
196240116Smarcel		/* Wait for IBF = 0 */
197240116Smarcel		status = kcs_wait_for_ibf(sc, 0);
198240116Smarcel		if (status & KCS_STATUS_IBF)
199240116Smarcel			return (0);
200240116Smarcel
201240116Smarcel		if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_WRITE)
202240116Smarcel			break;
203240116Smarcel		DELAY(1000000);
204240116Smarcel	}
205240116Smarcel
206240116Smarcel	if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE)
207240116Smarcel		/* error state */
208240116Smarcel		return (0);
209240116Smarcel
210240116Smarcel	/* Clear OBF */
211240116Smarcel	kcs_clear_obf(sc, status);
212240116Smarcel
213240116Smarcel	return (1);
214240116Smarcel}
215240116Smarcel
216240116Smarcel/*
217240116Smarcel * Write a byte of the request message, excluding the last byte of the
218240116Smarcel * message which requires special handling.
219240116Smarcel */
220240116Smarcelstatic int
221240116Smarcelkcs_write_byte(struct ipmi_softc *sc, u_char data)
222240116Smarcel{
223240116Smarcel	int status;
224240116Smarcel
225240116Smarcel	/* Data to Data */
226240116Smarcel	OUTB(sc, KCS_DATA, data);
227240116Smarcel
228240116Smarcel	/* Wait for IBF = 0 */
229240116Smarcel	status = kcs_wait_for_ibf(sc, 0);
230240116Smarcel	if (status & KCS_STATUS_IBF)
231240116Smarcel		return (0);
232240116Smarcel
233240116Smarcel	if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE)
234240116Smarcel		return (0);
235240116Smarcel
236240116Smarcel	/* Clear OBF */
237240116Smarcel	kcs_clear_obf(sc, status);
238240116Smarcel	return (1);
239240116Smarcel}
240240116Smarcel
241240116Smarcel/*
242240116Smarcel * Write the last byte of a request message.
243240116Smarcel */
244240116Smarcelstatic int
245240116Smarcelkcs_write_last_byte(struct ipmi_softc *sc, u_char data)
246240116Smarcel{
247240116Smarcel	int status;
248240116Smarcel
249240116Smarcel	/* Write end to command */
250240116Smarcel	OUTB(sc, KCS_CTL_STS, KCS_CONTROL_WRITE_END);
251240116Smarcel
252240116Smarcel	/* Wait for IBF = 0 */
253240116Smarcel	status = kcs_wait_for_ibf(sc, 0);
254240116Smarcel	if (status & KCS_STATUS_IBF)
255240116Smarcel		return (0);
256240116Smarcel
257240116Smarcel	if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE)
258240116Smarcel		/* error state */
259240116Smarcel		return (0);
260240116Smarcel
261240116Smarcel	/* Clear OBF */
262240116Smarcel	kcs_clear_obf(sc, status);
263240116Smarcel
264240116Smarcel	/* Send data byte to DATA. */
265240116Smarcel	OUTB(sc, KCS_DATA, data);
266240116Smarcel	return (1);
267240116Smarcel}
268240116Smarcel
269240116Smarcel/*
270240116Smarcel * Read one byte of the reply message.
271240116Smarcel */
272240116Smarcelstatic int
273240116Smarcelkcs_read_byte(struct ipmi_softc *sc, u_char *data)
274240116Smarcel{
275240116Smarcel	int status;
276240116Smarcel	u_char dummy;
277240116Smarcel
278240116Smarcel	/* Wait for IBF = 0 */
279240116Smarcel	status = kcs_wait_for_ibf(sc, 0);
280240116Smarcel
281240116Smarcel	/* Read State */
282240116Smarcel	if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) {
283240116Smarcel
284240116Smarcel		/* Wait for OBF = 1 */
285240116Smarcel		status = kcs_wait_for_obf(sc, 1);
286240116Smarcel		if ((status & KCS_STATUS_OBF) == 0)
287240116Smarcel			return (0);
288240116Smarcel
289240116Smarcel		/* Read Data_out */
290240116Smarcel		*data = INB(sc, KCS_DATA);
291240116Smarcel
292240116Smarcel		/* Write READ into Data_in */
293240116Smarcel		OUTB(sc, KCS_DATA, KCS_DATA_IN_READ);
294240116Smarcel		return (1);
295240116Smarcel	}
296240116Smarcel
297240116Smarcel	/* Idle State */
298240116Smarcel	if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) {
299240116Smarcel
300240116Smarcel		/* Wait for OBF = 1*/
301240116Smarcel		status = kcs_wait_for_obf(sc, 1);
302240116Smarcel		if ((status & KCS_STATUS_OBF) == 0)
303240116Smarcel			return (0);
304240116Smarcel
305240116Smarcel		/* Read Dummy */
306240116Smarcel		dummy = INB(sc, KCS_DATA);
307240116Smarcel		return (2);
308240116Smarcel	}
309240116Smarcel
310240116Smarcel	/* Error State */
311240116Smarcel	return (0);
312240116Smarcel}
313240116Smarcel
314240116Smarcel/*
315240116Smarcel * Send a request message and collect the reply.  Returns true if we
316240116Smarcel * succeed.
317240116Smarcel */
318240116Smarcelstatic int
319240116Smarcelkcs_polled_request(struct ipmi_softc *sc, struct ipmi_request *req)
320240116Smarcel{
321240116Smarcel	u_char *cp, data;
322240116Smarcel	int i, state;
323240116Smarcel
324240116Smarcel	IPMI_IO_LOCK(sc);
325240116Smarcel
326240116Smarcel	/* Send the request. */
327240116Smarcel	if (!kcs_start_write(sc)) {
328240116Smarcel		device_printf(sc->ipmi_dev, "KCS: Failed to start write\n");
329240116Smarcel		goto fail;
330240116Smarcel	}
331240116Smarcel#ifdef KCS_DEBUG
332240116Smarcel	device_printf(sc->ipmi_dev, "KCS: WRITE_START... ok\n");
333240116Smarcel#endif
334240116Smarcel
335240116Smarcel	if (!kcs_write_byte(sc, req->ir_addr)) {
336240116Smarcel		device_printf(sc->ipmi_dev, "KCS: Failed to write address\n");
337240116Smarcel		goto fail;
338240116Smarcel	}
339240116Smarcel#ifdef KCS_DEBUG
340240116Smarcel	device_printf(sc->ipmi_dev, "KCS: Wrote address: %02x\n", req->ir_addr);
341240116Smarcel#endif
342240116Smarcel
343240116Smarcel	if (req->ir_requestlen == 0) {
344240116Smarcel		if (!kcs_write_last_byte(sc, req->ir_command)) {
345240116Smarcel			device_printf(sc->ipmi_dev,
346240116Smarcel			    "KCS: Failed to write command\n");
347240116Smarcel			goto fail;
348240116Smarcel		}
349240116Smarcel#ifdef KCS_DEBUG
350240116Smarcel		device_printf(sc->ipmi_dev, "KCS: Wrote command: %02x\n",
351240116Smarcel		    req->ir_command);
352240116Smarcel#endif
353240116Smarcel	} else {
354240116Smarcel		if (!kcs_write_byte(sc, req->ir_command)) {
355240116Smarcel			device_printf(sc->ipmi_dev,
356240116Smarcel			    "KCS: Failed to write command\n");
357240116Smarcel			goto fail;
358240116Smarcel		}
359240116Smarcel#ifdef KCS_DEBUG
360240116Smarcel		device_printf(sc->ipmi_dev, "KCS: Wrote command: %02x\n",
361240116Smarcel		    req->ir_command);
362240116Smarcel#endif
363240116Smarcel
364240116Smarcel		cp = req->ir_request;
365240116Smarcel		for (i = 0; i < req->ir_requestlen - 1; i++) {
366240116Smarcel			if (!kcs_write_byte(sc, *cp++)) {
367240116Smarcel				device_printf(sc->ipmi_dev,
368240116Smarcel				    "KCS: Failed to write data byte %d\n",
369240116Smarcel				    i + 1);
370240116Smarcel				goto fail;
371240116Smarcel			}
372240116Smarcel#ifdef KCS_DEBUG
373240116Smarcel			device_printf(sc->ipmi_dev, "KCS: Wrote data: %02x\n",
374240116Smarcel			    cp[-1]);
375240116Smarcel#endif
376240116Smarcel		}
377240116Smarcel
378240116Smarcel		if (!kcs_write_last_byte(sc, *cp)) {
379240116Smarcel			device_printf(sc->ipmi_dev,
380240116Smarcel			    "KCS: Failed to write last dta byte\n");
381240116Smarcel			goto fail;
382240116Smarcel		}
383240116Smarcel#ifdef KCS_DEBUG
384240116Smarcel		device_printf(sc->ipmi_dev, "KCS: Wrote last data: %02x\n",
385240116Smarcel		    *cp);
386240116Smarcel#endif
387240116Smarcel	}
388240116Smarcel
389240116Smarcel	/* Read the reply.  First, read the NetFn/LUN. */
390240116Smarcel	if (kcs_read_byte(sc, &data) != 1) {
391240116Smarcel		device_printf(sc->ipmi_dev, "KCS: Failed to read address\n");
392240116Smarcel		goto fail;
393	}
394#ifdef KCS_DEBUG
395	device_printf(sc->ipmi_dev, "KCS: Read address: %02x\n", data);
396#endif
397	if (data != IPMI_REPLY_ADDR(req->ir_addr)) {
398		device_printf(sc->ipmi_dev, "KCS: Reply address mismatch\n");
399		goto fail;
400	}
401
402	/* Next we read the command. */
403	if (kcs_read_byte(sc, &data) != 1) {
404		device_printf(sc->ipmi_dev, "KCS: Failed to read command\n");
405		goto fail;
406	}
407#ifdef KCS_DEBUG
408	device_printf(sc->ipmi_dev, "KCS: Read command: %02x\n", data);
409#endif
410	if (data != req->ir_command) {
411		device_printf(sc->ipmi_dev, "KCS: Command mismatch\n");
412		goto fail;
413	}
414
415	/* Next we read the completion code. */
416	if (kcs_read_byte(sc, &req->ir_compcode) != 1) {
417		device_printf(sc->ipmi_dev,
418		    "KCS: Failed to read completion code\n");
419		goto fail;
420	}
421#ifdef KCS_DEBUG
422	device_printf(sc->ipmi_dev, "KCS: Read completion code: %02x\n",
423	    req->ir_compcode);
424#endif
425
426	/* Finally, read the reply from the BMC. */
427	i = 0;
428	for (;;) {
429		state = kcs_read_byte(sc, &data);
430		if (state == 0) {
431			device_printf(sc->ipmi_dev,
432			    "KCS: Read failed on byte %d\n", i + 1);
433			goto fail;
434		}
435		if (state == 2)
436			break;
437		if (i < req->ir_replybuflen) {
438			req->ir_reply[i] = data;
439#ifdef KCS_DEBUG
440			device_printf(sc->ipmi_dev, "KCS: Read data %02x\n",
441			    data);
442		} else {
443			device_printf(sc->ipmi_dev,
444			    "KCS: Read short %02x byte %d\n", data, i + 1);
445#endif
446		}
447		i++;
448	}
449	IPMI_IO_UNLOCK(sc);
450	req->ir_replylen = i;
451#ifdef KCS_DEBUG
452	device_printf(sc->ipmi_dev, "KCS: READ finished (%d bytes)\n", i);
453	if (req->ir_replybuflen < i)
454#else
455	if (req->ir_replybuflen < i && req->ir_replybuflen != 0)
456#endif
457		device_printf(sc->ipmi_dev,
458		    "KCS: Read short: %zd buffer, %d actual\n",
459		    req->ir_replybuflen, i);
460	return (1);
461fail:
462	kcs_error(sc);
463	IPMI_IO_UNLOCK(sc);
464	return (0);
465}
466
467static void
468kcs_loop(void *arg)
469{
470	struct ipmi_softc *sc = arg;
471	struct ipmi_request *req;
472	int i, ok;
473
474	IPMI_LOCK(sc);
475	while ((req = ipmi_dequeue_request(sc)) != NULL) {
476		IPMI_UNLOCK(sc);
477		ok = 0;
478		for (i = 0; i < 3 && !ok; i++)
479			ok = kcs_polled_request(sc, req);
480		if (ok)
481			req->ir_error = 0;
482		else
483			req->ir_error = EIO;
484		IPMI_LOCK(sc);
485		ipmi_complete_request(sc, req);
486	}
487	IPMI_UNLOCK(sc);
488	kproc_exit(0);
489}
490
491static int
492kcs_startup(struct ipmi_softc *sc)
493{
494
495	return (kproc_create(kcs_loop, sc, &sc->ipmi_kthread, 0, 0, "%s: kcs",
496	    device_get_nameunit(sc->ipmi_dev)));
497}
498
499static int
500kcs_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo)
501{
502	int i, ok;
503
504	ok = 0;
505	for (i = 0; i < 3 && !ok; i++)
506		ok = kcs_polled_request(sc, req);
507	if (ok)
508		req->ir_error = 0;
509	else
510		req->ir_error = EIO;
511	return (req->ir_error);
512}
513
514int
515ipmi_kcs_attach(struct ipmi_softc *sc)
516{
517	int status;
518
519	/* Setup function pointers. */
520	sc->ipmi_startup = kcs_startup;
521	sc->ipmi_enqueue_request = ipmi_polled_enqueue_request;
522	sc->ipmi_driver_request = kcs_driver_request;
523	sc->ipmi_driver_requests_polled = 1;
524
525	/* See if we can talk to the controller. */
526	status = INB(sc, KCS_CTL_STS);
527	if (status == 0xff) {
528		device_printf(sc->ipmi_dev, "couldn't find it\n");
529		return (ENXIO);
530	}
531
532#ifdef KCS_DEBUG
533	device_printf(sc->ipmi_dev, "KCS: initial state: %02x\n", status);
534#endif
535	if (status & KCS_STATUS_OBF ||
536	    KCS_STATUS_STATE(status) != KCS_STATUS_STATE_IDLE)
537		kcs_error(sc);
538
539	return (0);
540}
541
542/*
543 * Determine the alignment automatically for a PCI attachment.  In this case,
544 * any unused bytes will return 0x00 when read.  We make use of the C/D bit
545 * in the CTL_STS register to try to start a GET_STATUS transaction.  When
546 * we write the command, that bit should be set, so we should get a non-zero
547 * value back when we read CTL_STS if the offset we are testing is the CTL_STS
548 * register.
549 */
550int
551ipmi_kcs_probe_align(struct ipmi_softc *sc)
552{
553	int data, status;
554
555	sc->ipmi_io_spacing = 1;
556retry:
557#ifdef KCS_DEBUG
558	device_printf(sc->ipmi_dev, "Trying KCS align %d... ", sc->ipmi_io_spacing);
559#endif
560
561	/* Wait for IBF = 0 */
562	status = INB(sc, KCS_CTL_STS);
563	while (status & KCS_STATUS_IBF) {
564		DELAY(100);
565		status = INB(sc, KCS_CTL_STS);
566	}
567
568	OUTB(sc, KCS_CTL_STS, KCS_CONTROL_GET_STATUS_ABORT);
569
570	/* Wait for IBF = 0 */
571	status = INB(sc, KCS_CTL_STS);
572	while (status & KCS_STATUS_IBF) {
573		DELAY(100);
574		status = INB(sc, KCS_CTL_STS);
575	}
576
577	/* If we got 0x00 back, then this must not be the CTL_STS register. */
578	if (status == 0) {
579#ifdef KCS_DEBUG
580		printf("failed\n");
581#endif
582		sc->ipmi_io_spacing <<= 1;
583		if (sc->ipmi_io_spacing > 4)
584			return (0);
585		goto retry;
586	}
587#ifdef KCS_DEBUG
588	printf("ok\n");
589#endif
590
591	/* Finish out the transaction. */
592
593	/* Clear OBF */
594	if (status & KCS_STATUS_OBF)
595		data = INB(sc, KCS_DATA);
596
597	/* 0x00 to DATA_IN */
598	OUTB(sc, KCS_DATA, 0);
599
600	/* Wait for IBF = 0 */
601	status = INB(sc, KCS_CTL_STS);
602	while (status & KCS_STATUS_IBF) {
603		DELAY(100);
604		status = INB(sc, KCS_CTL_STS);
605	}
606
607	if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) {
608		/* Wait for IBF = 1 */
609		while (!(status & KCS_STATUS_OBF)) {
610			DELAY(100);
611			status = INB(sc, KCS_CTL_STS);
612		}
613
614		/* Read error status. */
615		data = INB(sc, KCS_DATA);
616
617		/* Write dummy READ to DATA_IN. */
618		OUTB(sc, KCS_DATA, KCS_DATA_IN_READ);
619
620		/* Wait for IBF = 0 */
621		status = INB(sc, KCS_CTL_STS);
622		while (status & KCS_STATUS_IBF) {
623			DELAY(100);
624			status = INB(sc, KCS_CTL_STS);
625		}
626	}
627
628	if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) {
629		/* Wait for IBF = 1 */
630		while (!(status & KCS_STATUS_OBF)) {
631			DELAY(100);
632			status = INB(sc, KCS_CTL_STS);
633		}
634
635		/* Clear OBF */
636		if (status & KCS_STATUS_OBF)
637			data = INB(sc, KCS_DATA);
638	} else
639		device_printf(sc->ipmi_dev, "KCS probe: end state %x\n",
640		    KCS_STATUS_STATE(status));
641
642	return (1);
643}
644