]>
Commit | Line | Data |
---|---|---|
e2a67c78 | 1 | /* |
2 | * GDB operations to send and recieve RPC requests and replies. | |
3 | */ | |
4 | ||
5 | sms_start_call(op, hcon, arg) | |
6 | OPERATION op; | |
7 | HALF_CONNECTION hcon; | |
8 | register struct param *arg; | |
9 | { | |
10 | /* | |
11 | * This should probably be split into several routines. | |
12 | * It could also probably be made more efficient (punting most | |
13 | * of the argument marshalling stuff by doing I/O directly | |
14 | * from the strings. Anyone for a scatter/gather sms_send_data? | |
15 | * | |
16 | * that would look a lot like the uio stuff in the kernel.. hmm. | |
17 | */ | |
18 | ||
19 | /* | |
20 | * Marshall the entire data right now.. | |
21 | * We are sending the version number, | |
22 | * total request size, request number, | |
23 | * argument count, and then each argument. | |
24 | * At least for now, each argument is a string, which is | |
25 | * sent as a count of bytes followed by the bytes | |
26 | * (including the trailing '\0'), padded | |
27 | * to a longword boundary. | |
28 | */ | |
29 | ||
30 | sms_size = 4 * sizeof(long); | |
31 | ||
32 | argl = (int *)malloc(sizeof(int) * arg->argc); | |
33 | ||
34 | /* | |
35 | * For each argument, figure out how much space is needed. | |
36 | */ | |
37 | ||
38 | for (i = arg->argc; i; --i) { | |
39 | argl[i] = len = strlen(arg->argv[i]) + 1; | |
40 | sms_size += sizeof(long) + len; | |
41 | sms_size = sizeof(long) * howmany(sms_size, sizeof(long)); | |
42 | } | |
43 | ||
44 | arg->flattened = buf = db_alloc(sms_size); | |
45 | ||
46 | bzero(arg->flattened, sms_size); | |
47 | ||
48 | arg->size = sms_size; | |
49 | ||
50 | /* | |
51 | * This is gross. Any better suggestions, anyone? | |
52 | * It should work on the RT's, since malloc is guaranteed to | |
53 | * return a pointer which is aligned correctly for any data. | |
54 | */ | |
55 | ||
56 | ((long *)buf)[0] = htonl(SMS_VERSION_1); | |
57 | ((long *)buf)[1] = htonl(sms_size); | |
58 | ((long *)buf)[2] = htonl(arg->procno); | |
59 | ((long *)buf)[3] = htonl(arg->argc); | |
60 | ||
61 | /* | |
62 | * bp is a pointer into the point in the buffer to put | |
63 | * the next argument. | |
64 | */ | |
65 | ||
66 | bp = (char *)(&(long *)buf[4]) | |
67 | for (i = arg->argc; i; --i) { | |
68 | len = argl[i]; | |
69 | *((long *)bp) = htonl(len); | |
70 | bp += sizeof(long); | |
71 | bcopy(arg->argv[i], bp, len); | |
72 | bp += sizeof(long) * howmany(len, sizeof(long)); | |
73 | } | |
74 | op->fcn.cont = sms_cont_call; | |
75 | arg->size = sms_size; | |
76 | ||
77 | if (gdb_send_data(hcon, arg->flattened, sms_size) == OP_COMPLETE) | |
78 | return sms_cont_call(op, hcon, arg); | |
79 | else return OP_RUNNING; | |
80 | } | |
81 | ||
82 | /* | |
83 | * This doesn't get called until after the actual buffered write completes. | |
84 | * In a non-preflattening version of this, this would then queue the | |
85 | * write of the next bunch of data. | |
86 | */ | |
87 | ||
88 | sms_cont_call(op, hcon, arg) | |
89 | OPERATION op; | |
90 | HALF_CONNECTION hcon; | |
91 | struct params *arg; | |
92 | { | |
93 | op->result = OP_SUCCESS; | |
94 | db_free(arg->flattened, arg->size); | |
95 | db_free(arg, sizeof(struct params)); | |
96 | return OP_COMPLETE; | |
97 | } | |
98 | ||
99 | ||
100 | /* Need routines to decode all that... */ |