131158Sminshall /* 231158Sminshall * This file implements the API used in the PC version. 331158Sminshall */ 431158Sminshall 531158Sminshall #include <stdio.h> 631158Sminshall 731158Sminshall #include "api.h" 831183Sminshall #include "../general/general.h" 931158Sminshall 1031168Sminshall #include "../ctlr/screen.h" 1131193Sminshall #include "../ctlr/oia.h" 1231193Sminshall 1331183Sminshall #include "../general/globals.h" 1431158Sminshall 1531158Sminshall /* 1631193Sminshall * General utility routines. 1731193Sminshall */ 1831193Sminshall 1931193Sminshall #if defined(MSDOS) 2031193Sminshall 21*31211Sminshall #if defined(LINT_ARGS) 22*31211Sminshall static void movetous(char *, int, int, int); 23*31211Sminshall static void movetothem(int, int, char *, int); 24*31211Sminshall #endif /* defined(LINT_ARGS) */ 25*31211Sminshall 2631193Sminshall static void 2731193Sminshall movetous(parms, es, di, length) 2831193Sminshall char *parms; 29*31211Sminshall int es, di, length; 3031193Sminshall { 31*31211Sminshall char far *farparms = parms; 3231193Sminshall 33*31211Sminshall movedata(es, di, (int) FP_SEG(farparms), (int) FP_OFF(farparms), length); 3431193Sminshall } 3531193Sminshall 3631193Sminshall static void 37*31211Sminshall movetothem(es, di, parms, length) 38*31211Sminshall int es, di; 39*31211Sminshall char *parms; 40*31211Sminshall int length; 4131193Sminshall { 42*31211Sminshall char far *farparms = parms; 4331193Sminshall 44*31211Sminshall movedata((int) FP_SEG(farparms), (int) FP_OFF(farparms), es, di, length); 4531193Sminshall } 4631193Sminshall #endif /* defined(MSDOS) */ 4731193Sminshall 4831193Sminshall /* No Unix version yet... */ 4931193Sminshall 5031193Sminshall 5131193Sminshall /* 5231158Sminshall * Supervisor Services. 5331158Sminshall */ 5431158Sminshall 5531158Sminshall static void 5631193Sminshall name_resolution(regs, sregs) 5731158Sminshall union REGS *regs; 5831158Sminshall struct SREGS *sregs; 5931158Sminshall { 6031167Sminshall NameResolveParms parms; 6131161Sminshall 6231167Sminshall movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms); 6331161Sminshall 6431161Sminshall regs->h.cl = 0; 6531193Sminshall if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) { 6631161Sminshall regs->x.dx = GATE_SESSMGR; 6731193Sminshall } else if (memcmp((char *)&parms, NAME_KEYBOARD, 6831193Sminshall sizeof parms.gate_name) == 0) { 6931161Sminshall regs->x.dx = GATE_KEYBOARD; 7031193Sminshall } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) { 7131161Sminshall regs->x.dx = GATE_COPY; 7231193Sminshall } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) { 7331161Sminshall regs->x.dx = GATE_OIAM; 7431161Sminshall } else { 7531161Sminshall regs->h.cl = 0x2e; /* Name not found */ 7631161Sminshall } 7731161Sminshall regs->h.ch = 0x12; 7831161Sminshall regs->h.bh = 7; 7931158Sminshall } 8031158Sminshall 8131158Sminshall /* 8231158Sminshall * Session Information Services. 8331158Sminshall */ 8431158Sminshall 8531158Sminshall static void 8631158Sminshall query_session_id(regs, sregs) 8731158Sminshall union REGS *regs; 8831158Sminshall struct SREGS *sregs; 8931158Sminshall { 9031167Sminshall QuerySessionIdParms parms; 9131161Sminshall 9231167Sminshall movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 9331161Sminshall 94*31211Sminshall if ((parms.rc != 0) || (parms.function_id != 0)) { 95*31211Sminshall parms.rc = 0x0c; 96*31211Sminshall } else if (parms.option_code != 0x01) { 97*31211Sminshall parms.rc = 0x0d; /* Invalid option code */ 9831167Sminshall } else if (parms.data_code != 0x45) { 99*31211Sminshall parms.rc = 0x0b; 10031161Sminshall } else { 10131168Sminshall NameArray list; 10231167Sminshall NameArrayElement element; 10331167Sminshall 10431167Sminshall movetous((char *)&list, FP_SEG(parms.name_array), 10531193Sminshall FP_OFF(parms.name_array), sizeof list); 10631168Sminshall if ((list.length < 14) || (list.length > 170)) { 10731167Sminshall parms.rc = 0x12; 10831161Sminshall } else { 10931167Sminshall list.number_matching_session = 1; 11031167Sminshall list.name_array_element.short_name = parms.data_code; 11131167Sminshall list.name_array_element.type = TYPE_DFT; 11231167Sminshall list.name_array_element.session_id = 23; 11331167Sminshall memcpy(list.name_array_element.long_name, "ONLYSESS", 11431167Sminshall sizeof list.name_array_element.long_name); 11531167Sminshall movetothem(FP_SEG(parms.name_array), 11631193Sminshall FP_OFF(parms.name_array), (char *)&list, sizeof list); 11731167Sminshall parms.rc = 0; 11831161Sminshall } 11931161Sminshall } 120*31211Sminshall parms.function_id = 0x6b; 12131167Sminshall movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 12231158Sminshall } 12331158Sminshall 12431158Sminshall static void 12531158Sminshall query_session_parameters(regs, sregs) 12631158Sminshall union REGS *regs; 12731158Sminshall struct SREGS *sregs; 12831158Sminshall { 12931167Sminshall QuerySessionParametersParms parms; 13031167Sminshall 13131167Sminshall movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 13231167Sminshall 13331168Sminshall if ((parms.rc !=0) || (parms.function_id != 0)) { 134*31211Sminshall parms.rc = 0x0c; 135*31211Sminshall } else if (parms.session_id != 23) { 136*31211Sminshall parms.rc = 0x02; 13731167Sminshall } else { 138*31211Sminshall parms.rc = 0; 13931167Sminshall parms.session_type = TYPE_DFT; 14031167Sminshall parms.session_characteristics = 0; /* Neither EAB nor PSS */ 14131167Sminshall parms.rows = MaxNumberLines; 14231167Sminshall parms.columns = MaxNumberColumns; 14331167Sminshall parms.presentation_space = 0; 14431167Sminshall } 145*31211Sminshall parms.function_id = 0x6b; 14631168Sminshall movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 14731158Sminshall } 14831158Sminshall 14931158Sminshall static void 15031158Sminshall query_session_cursor(regs, sregs) 15131158Sminshall union REGS *regs; 15231158Sminshall struct SREGS *sregs; 15331158Sminshall { 15431167Sminshall QuerySessionCursorParms parms; 15531167Sminshall 15631167Sminshall movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 15731167Sminshall 15831167Sminshall if ((parms.rc != 0) || (parms.function_id != 0)) { 15931167Sminshall parms.rc = 0x0c; 16031167Sminshall } else if (parms.session_id != 23) { 16131167Sminshall parms.rc = 0x02; 16231167Sminshall } else { 16331167Sminshall parms.rc = 0; 16431167Sminshall parms.cursor_type = CURSOR_BLINKING; /* XXX what is inhibited? */ 16531167Sminshall parms.row_address = ScreenLine(CursorAddress); 16631167Sminshall parms.column_address = ScreenLineOffset(CursorAddress); 16731167Sminshall } 16831167Sminshall 169*31211Sminshall parms.function_id = 0x6b; 170*31211Sminshall movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms); 17131158Sminshall } 17231158Sminshall 17331158Sminshall /* 17431158Sminshall * Keyboard Services. 17531158Sminshall */ 17631158Sminshall 17731158Sminshall 17831158Sminshall static void 17931158Sminshall connect_to_keyboard(regs, sregs) 18031158Sminshall union REGS *regs; 18131158Sminshall struct SREGS *sregs; 18231158Sminshall { 18331167Sminshall ConnectToKeyboardParms parms; 18431167Sminshall 18531183Sminshall movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 18631167Sminshall 18731167Sminshall if ((parms.rc != 0) || (parms.function_id != 0)) { 18831167Sminshall parms.rc = 0x0c; 18931167Sminshall } else if (parms.session_id != 23) { 19031167Sminshall parms.rc = 0x02; 19131167Sminshall } else if (parms.intercept_options != 0) { 19231167Sminshall parms.rc = 0x01; 19331167Sminshall } else { 19431167Sminshall parms.rc = 0; 19531167Sminshall parms.first_connection_identifier = 0; 19631167Sminshall } 19731167Sminshall parms.function_id = 0x62; 19831167Sminshall 19931167Sminshall movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 20031158Sminshall } 20131158Sminshall 20231158Sminshall static void 20331167Sminshall disconnect_from_keyboard(regs, sregs) 20431158Sminshall union REGS *regs; 20531158Sminshall struct SREGS *sregs; 20631158Sminshall { 20731167Sminshall DisconnectFromKeyboardParms parms; 20831167Sminshall 20931167Sminshall movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 21031167Sminshall 21131167Sminshall if ((parms.rc != 0) || (parms.function_id != 0)) { 21231167Sminshall parms.rc = 0x0c; 21331167Sminshall } else if (parms.session_id != 23) { 21431167Sminshall parms.rc = 0x02; 21531167Sminshall } else if (parms.connectors_task_id != 0) { 21631167Sminshall parms.rc = 04; /* XXX */ 21731167Sminshall } else { 21831167Sminshall parms.rc = 0; 21931167Sminshall } 22031167Sminshall parms.function_id = 0x62; 22131167Sminshall 22231167Sminshall movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 22331158Sminshall } 22431158Sminshall 22531158Sminshall static void 22631158Sminshall write_keystroke(regs, sregs) 22731158Sminshall union REGS *regs; 22831158Sminshall struct SREGS *sregs; 22931158Sminshall { 23031198Sminshall WriteKeystrokeParms parms; 23131198Sminshall 23231198Sminshall movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 23331198Sminshall 23431198Sminshall if ((parms.rc != 0) || (parms.function_id != 0)) { 23531198Sminshall parms.rc = 0x0c; 23631198Sminshall } else if (parms.session_id != 23) { 23731198Sminshall parms.rc = 0x02; 23831198Sminshall } else if (parms.connectors_task_id != 0) { 23931198Sminshall parms.rc = 0x04; 24031198Sminshall } else { 24131198Sminshall parms.number_of_keys_sent = 0; 24231198Sminshall parms.rc = 0; 24331198Sminshall if (parms.options == OPTION_SINGLE_KEYSTROKE) { 24431198Sminshall KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry; 24531198Sminshall 24631198Sminshall if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) { 24731198Sminshall parms.rc = 0x10; /* XXX needs 0x12 too! */ 24831198Sminshall } 24931198Sminshall parms.number_of_keys_sent++; 25031198Sminshall } else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) { 25131198Sminshall KeystrokeList 25231198Sminshall list, 25331198Sminshall far *atlist = parms.keystroke_specifier.keystroke_list; 25431198Sminshall KeystrokeEntry 25531198Sminshall entry[10], /* 10 at a time */ 25631198Sminshall *ourentry, 25731198Sminshall far *theirentry; 25831198Sminshall int 25931198Sminshall todo; 26031198Sminshall 26131198Sminshall movetous((char *)&list, FP_SEG(atlist), 26231198Sminshall FP_OFF(atlist), sizeof *atlist); 26331198Sminshall todo = list.length/2; 26431198Sminshall ourentry = entry+(highestof(entry)+1); 26531198Sminshall 26631198Sminshall while (todo) { 26731198Sminshall if (ourentry > &entry[highestof(entry)]) { 26831198Sminshall int thistime; 26931198Sminshall 27031198Sminshall thistime = todo; 27131198Sminshall if (thistime > numberof(entry)) { 27231198Sminshall thistime = numberof(entry); 27331198Sminshall } 27431198Sminshall movetous((char *)entry, FP_SEG(theirentry), 27531198Sminshall FP_OFF(theirentry), thistime*sizeof *theirentry); 27631198Sminshall theirentry += thistime; 27731198Sminshall ourentry = entry; 27831198Sminshall } 27931198Sminshall if (AcceptKeystroke(ourentry->scancode, 28031198Sminshall ourentry->shift_state) == 0) { 28131198Sminshall parms.rc = 0x10; /* XXX needs 0x12 too! */ 28231198Sminshall break; 28331198Sminshall } 28431198Sminshall parms.number_of_keys_sent++; 28531198Sminshall ourentry++; 28631198Sminshall todo--; 28731198Sminshall } 28831198Sminshall } else { 28931198Sminshall parms.rc = 0x01; 29031198Sminshall } 29131198Sminshall } 29231198Sminshall parms.function_id = 0x62; 29331198Sminshall 29431198Sminshall movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 29531167Sminshall /* XXX */ 29631158Sminshall } 29731158Sminshall 29831167Sminshall 29931158Sminshall static void 30031167Sminshall disable_input(regs, sregs) 30131167Sminshall union REGS *regs; 30231167Sminshall struct SREGS *sregs; 30331167Sminshall { 30431167Sminshall DisableInputParms parms; 30531167Sminshall 30631167Sminshall movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 30731167Sminshall 30831167Sminshall if ((parms.rc != 0) || (parms.function_id != 0)) { 30931167Sminshall parms.rc = 0x0c; 31031167Sminshall } else if (parms.session_id != 23) { 31131167Sminshall parms.rc = 0x02; 31231167Sminshall } else if (parms.connectors_task_id != 0) { 31331167Sminshall parms.rc = 0x04; 31431167Sminshall } else { 315*31211Sminshall SetOiaApiInhibit(&OperatorInformationArea); 31631167Sminshall parms.rc = 0; 31731167Sminshall } 31831167Sminshall parms.function_id = 0x62; 31931167Sminshall 32031167Sminshall movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 32131167Sminshall } 32231167Sminshall 32331167Sminshall static void 32431158Sminshall enable_input(regs, sregs) 32531158Sminshall union REGS *regs; 32631158Sminshall struct SREGS *sregs; 32731158Sminshall { 32831167Sminshall EnableInputParms parms; 32931167Sminshall 33031167Sminshall movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 33131167Sminshall 33231167Sminshall if ((parms.rc != 0) || (parms.function_id != 0)) { 33331167Sminshall parms.rc = 0x0c; 33431167Sminshall } else if (parms.session_id != 23) { 33531167Sminshall parms.rc = 0x02; 33631167Sminshall } else if (parms.connectors_task_id != 0) { 33731167Sminshall parms.rc = 0x04; 33831167Sminshall } else { 339*31211Sminshall ResetOiaApiInhibit(&OperatorInformationArea); 34031167Sminshall parms.rc = 0; 34131167Sminshall } 34231167Sminshall parms.function_id = 0x62; 34331167Sminshall 34431167Sminshall movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 34531158Sminshall } 34631158Sminshall 34731158Sminshall /* 34831158Sminshall * Copy Services. 34931158Sminshall */ 35031158Sminshall 35131158Sminshall static void 35231167Sminshall copy_string(regs, sregs) 35331158Sminshall union REGS *regs; 35431158Sminshall struct SREGS *sregs; 35531158Sminshall { 35631167Sminshall CopyStringParms parms; 35731167Sminshall BufferDescriptor *target, *source; 35831167Sminshall 35931167Sminshall movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 36031167Sminshall 36131167Sminshall if ((parms.rc != 0) || (parms.function_id !=0)) { 36231167Sminshall parms.rc = 0x0c; 36331167Sminshall } 36431167Sminshall /* XXX do something! */ 36531183Sminshall movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 36631158Sminshall } 36731158Sminshall /* 36831158Sminshall * Operator Information Area Services. 36931158Sminshall */ 37031158Sminshall 37131158Sminshall static void 37231158Sminshall read_oia_group(regs, sregs) 37331158Sminshall union REGS *regs; 37431158Sminshall struct SREGS *sregs; 37531158Sminshall { 37631167Sminshall ReadOiaGroupParms parms; 37731167Sminshall 37831167Sminshall movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 37931167Sminshall 38031167Sminshall if ((parms.rc != 0) || (parms.function_id != 0)) { 38131167Sminshall parms.rc = 0x0c; 38231167Sminshall } else if (parms.session_id != 23) { 38331167Sminshall parms.rc = 0x02; 38431167Sminshall } else { 38531167Sminshall int group = parms.oia_group_number; 38631193Sminshall char *from; 38731193Sminshall int size; 38831167Sminshall 389*31211Sminshall if ((group != API_OIA_ALL_GROUPS) && 390*31211Sminshall ((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) { 39131193Sminshall } else { 39231193Sminshall if (group == API_OIA_ALL_GROUPS) { 39331193Sminshall size = API_OIA_BYTES_ALL_GROUPS; 39431193Sminshall from = (char *)&OperatorInformationArea; 39531193Sminshall } else if (group == API_OIA_INPUT_INHIBITED) { 39631193Sminshall size = sizeof OperatorInformationArea.input_inhibited; 39731193Sminshall from = (char *)&OperatorInformationArea.input_inhibited[0]; 39831193Sminshall } else { 39931193Sminshall size = 1; 40031193Sminshall from = ((char *)&OperatorInformationArea)+group; 40131193Sminshall } 40231193Sminshall movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer), 40331193Sminshall from, size); 40431168Sminshall } 40531167Sminshall } 40631168Sminshall parms.function_id = 0x6d; 40731167Sminshall movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 40831158Sminshall } 40931158Sminshall 41031158Sminshall static void 41131158Sminshall unknown_op(regs, sregs) 41231158Sminshall union REGS *regs; 41331158Sminshall struct SREGS *sregs; 41431158Sminshall { 41531158Sminshall regs->h.ch = 0x12; 41631158Sminshall regs->h.cl = 0x05; 41731158Sminshall } 41831158Sminshall 41931158Sminshall 42031158Sminshall handle_api(regs, sregs) 42131158Sminshall union REGS *regs; 42231158Sminshall struct SREGS *sregs; 42331158Sminshall { 42431158Sminshall if (regs->h.ah == NAME_RESOLUTION) { 42531158Sminshall name_resolution(regs, sregs); 42631168Sminshall } else if (regs->h.ah != 0x09) { 42731168Sminshall regs->h.ch = 0x12; 42831168Sminshall regs->h.cl = 0x0f; /* XXX Invalid environmental access */ 42931168Sminshall } else if (regs->x.bx != 0x8020) { 43031168Sminshall regs->h.ch = 0x12; 43131168Sminshall regs->h.cl = 0x08; /* XXX Invalid wait specified */ 43231168Sminshall } else if (regs->h.ch != 0) { 433*31211Sminshall regs->x.cx = 0x1206; /* XXX Invalid priority */ 43431158Sminshall } else { 43531158Sminshall switch (regs->x.dx) { 43631158Sminshall case GATE_SESSMGR: 43731158Sminshall switch (regs->h.al) { 43831158Sminshall case QUERY_SESSION_ID: 43931168Sminshall if (regs->h.cl != 0) { 440*31211Sminshall regs->x.cx = 0x1206; 44131168Sminshall } else { 442*31211Sminshall regs->x.cx = 0x1200; 44331168Sminshall query_session_id(regs, sregs); 44431168Sminshall } 44531158Sminshall break; 446*31211Sminshall case QUERY_SESSION_PARAMETERS: 44731168Sminshall if (regs->h.cl != 0) { 448*31211Sminshall regs->x.cx = 0x1206; 44931168Sminshall } else { 450*31211Sminshall regs->x.cx = 0x1200; 45131193Sminshall query_session_parameters(regs, sregs); 45231168Sminshall } 45331158Sminshall break; 45431158Sminshall case QUERY_SESSION_CURSOR: 45531168Sminshall if (regs->h.cl != 0xff) { 456*31211Sminshall regs->x.cx = 0x1206; 45731168Sminshall } else { 458*31211Sminshall regs->x.cx = 0x1200; 45931168Sminshall query_session_cursor(regs, sregs); 46031168Sminshall } 46131158Sminshall break; 46231158Sminshall default: 46331158Sminshall unknown_op(regs, sregs); 46431158Sminshall break; 46531158Sminshall } 46631158Sminshall break; 46731158Sminshall case GATE_KEYBOARD: 46831168Sminshall if (regs->h.cl != 00) { 469*31211Sminshall regs->x.cx = 0x1206; 47031168Sminshall } else { 471*31211Sminshall regs->x.cx = 0x1200; 47231168Sminshall switch (regs->h.al) { 47331168Sminshall case CONNECT_TO_KEYBOARD: 47431168Sminshall connect_to_keyboard(regs, sregs); 47531168Sminshall break; 47631168Sminshall case DISABLE_INPUT: 47731168Sminshall disable_input(regs, sregs); 47831168Sminshall break; 47931168Sminshall case WRITE_KEYSTROKE: 48031168Sminshall write_keystroke(regs, sregs); 48131168Sminshall break; 48231168Sminshall case ENABLE_INPUT: 48331168Sminshall enable_input(regs, sregs); 48431168Sminshall break; 48531168Sminshall case DISCONNECT_FROM_KEYBOARD: 48631168Sminshall disconnect_from_keyboard(regs, sregs); 48731168Sminshall break; 48831168Sminshall default: 48931168Sminshall unknown_op(regs, sregs); 49031168Sminshall break; 49131168Sminshall } 49231158Sminshall } 49331158Sminshall break; 49431158Sminshall case GATE_COPY: 49531168Sminshall if (regs->h.cl != 0xff) { 496*31211Sminshall regs->x.cx = 0x1206; 49731168Sminshall } else { 498*31211Sminshall regs->x.cx = 0x1200; 49931168Sminshall switch (regs->h.al) { 50031168Sminshall case COPY_STRING: 50131168Sminshall copy_string(regs, sregs); 50231168Sminshall break; 50331168Sminshall default: 50431168Sminshall unknown_op(regs, sregs); 50531168Sminshall break; 50631168Sminshall } 50731158Sminshall } 50831158Sminshall break; 50931158Sminshall case GATE_OIAM: 51031168Sminshall if (regs->h.cl != 0xff) { 511*31211Sminshall regs->x.cx = 0x1206; 51231168Sminshall } else { 513*31211Sminshall regs->x.cx = 0x1200; 51431168Sminshall switch (regs->h.al) { 51531168Sminshall case READ_OIA_GROUP: 51631168Sminshall read_oia_group(regs, sregs); 51731168Sminshall break; 51831168Sminshall default: 51931168Sminshall unknown_op(regs, sregs); 52031168Sminshall break; 52131168Sminshall } 52231158Sminshall } 52331158Sminshall break; 52431158Sminshall default: 52531168Sminshall regs->h.ch = 0x12; 52631168Sminshall regs->h.cl = 0x34; /* Invalid GATE entry */ 52731158Sminshall break; 52831158Sminshall } 52931158Sminshall } 53031158Sminshall } 531