xref: /linux/drivers/misc/ibmasm/lowlevel.c (revision 4dc0c899b14c3ea2c9b5f42b523301040d1c8100)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * IBM ASM Service Processor Device Driver
4  *
5  * Copyright (C) IBM Corporation, 2004
6  *
7  * Author: Max Asböck <amax@us.ibm.com>
8  */
9 
10 #include "ibmasm.h"
11 #include "lowlevel.h"
12 #include "i2o.h"
13 #include "dot_command.h"
14 #include "remote.h"
15 
16 static struct i2o_header header = I2O_HEADER_TEMPLATE;
17 
18 
19 int ibmasm_send_i2o_message(struct service_processor *sp)
20 {
21 	u32 mfa;
22 	size_t command_size;
23 	struct i2o_message *message;
24 	struct command *command = sp->current_command;
25 
26 	command_size = get_dot_command_size(command->buffer);
27 	if (command_size > command->buffer_size)
28 		return 1;
29 	if (command_size > I2O_COMMAND_SIZE)
30 		command_size = I2O_COMMAND_SIZE;
31 
32 	mfa = get_mfa_inbound(sp->base_address);
33 	if (!mfa)
34 		return 1;
35 
36 	header.message_size = outgoing_message_size((unsigned int)command_size);
37 	message = get_i2o_message(sp->base_address, mfa);
38 
39 	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
40 	memcpy_toio(&message->data, command->buffer, command_size);
41 
42 	set_mfa_inbound(sp->base_address, mfa);
43 
44 	return 0;
45 }
46 
47 irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id)
48 {
49 	u32	mfa;
50 	struct service_processor *sp = (struct service_processor *)dev_id;
51 	void __iomem *base_address = sp->base_address;
52 	char tsbuf[32];
53 
54 	if (!sp_interrupt_pending(base_address))
55 		return IRQ_NONE;
56 
57 	dbg("respond to interrupt at %s\n", get_timestamp(tsbuf));
58 
59 	if (mouse_interrupt_pending(sp)) {
60 		ibmasm_handle_mouse_interrupt(sp);
61 		clear_mouse_interrupt(sp);
62 	}
63 
64 	mfa = get_mfa_outbound(base_address);
65 	if (valid_mfa(mfa)) {
66 		struct i2o_message *msg = get_i2o_message(base_address, mfa);
67 		ibmasm_receive_message(sp, &msg->data, incoming_data_size(msg));
68 	} else
69 		dbg("didn't get a valid MFA\n");
70 
71 	set_mfa_outbound(base_address, mfa);
72 	dbg("finished interrupt at   %s\n", get_timestamp(tsbuf));
73 
74 	return IRQ_HANDLED;
75 }
76