summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/hp_ipc.cpp
blob: 024a0dbc41e2e6b0a2b4a8d9b8be3ba7becd3f26 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/******************************************************************************

Integral Personal Computer (HP9807A)
Hewlett-Packard, 1985

Driver to-do list
=================

- softlist: merge dumps from coho.org and classiccmp.org
- keyboard: NMI generation, autorepeat
- RTC chip: proper month, day (possibly a different chip, 82167)
- HP-IL printer
- sound (needs dump of COP452)

QA
+ diagnstc.td0: display test
- diagnstc.td0: complete keyboard test [second connector not implemented]
- diagnstc.td0: speaker test
- diagnstc.td0: printer test
+ diagnstc.td0: auto: floppy disc test
+ diagnstc.td0: auto: ram test
- diagnstc.td0: auto: rtc test [cannot execute]
+ diagnstc.td0: auto: short keyboard test

maybe
- drive AP line of MLC from a timer
- RTC standby interrupt?
- what does _desktop do except setting 640x400 mode?
- non-HLE keyboard and mouse? (need dumps of COP4xx)

slot devices
- 82915A -- 300/1200 bps modem; http://www.hpmuseum.net/display_item.php?hw=920
- 82919A -- serial; http://www.hpmuseum.net/display_item.php?hw=445
- 82920A -- current loop; http://www.hpmuseum.net/display_item.php?hw=975
- 82922A -- BCD interface; http://www.hpmuseum.net/display_item.php?hw=921
- 82923A -- GPIO; http://www.hpmuseum.net/display_item.php?hw=976
- 82924A -- HP-IL; http://www.hpmuseum.net/display_item.php?hw=922
- 82968A -- up to 256 KB of ROM on top of operating system PCA
- 82971A -- up to 1 MB of EPROM or 2 MB or masked ROM
- 82998A -- HP-IB; http://www.hpmuseum.net/display_item.php?hw=933
- 98071A -- 640x400 composite Video + Serial; http://www.hpmuseum.net/display_item.php?hw=935


This is a portable mains-powered UNIX workstation computer system produced by Hewlett-Packard and launched in 1985
Basic hardware specs are....
- 68000 CPU at 7.96MHz
- 9" amber electro-luminescent display with a resolution of 255*512 pixels or up to 85 characters x 31 lines (default=80*24) with
  dedicated 32Kb display memory
- Internal 3.5" floppy disk drive with the following specification....
  Encoding: Double Density HP MFM Format
  Rotational speed: 600 RPM
  Transfer speed: 62.5kB/second
  Capacity: 709Kb (709632 bytes)
  Bytes per sector: 512
  Sectors per track: 9
  Total tracks per surface: 80, Available: 77, Spare: 2, Wear: 1
  Surfaces: 2
  Interleave: 1
- HP ThinkJet ink-jet printer integrated into the top of the case. This is a modified HP2225B Thinkjet printer
- 90-key detachable keyboard
- ROM: up to 512Kb standard and an additional 512Kb of option ROM
- RAM: 512Kb, arranged as 256Kbx16. RAM is expandable externally to 7Mb
- Real Time Clock
- Speaker
- External I/O bus with two I/O ports for interfaces and memory modules. Expandable to maximum 10 ports with two 5-port Bus Expander Modules
- HP-IB (IEEE-488) bus
- Runs the HP-UX Operating System III or System V (in ROM)


PCB Layouts
===========

CPU/Memory Board (LOGIC A PCA)
----------------

HP Part# 00095-60953
                     |---------------------------------------------------------------------------------|
                     |  15.92MHz     J1        J2                                                      |
                     |LS74                                                                             |
                     |     |---|                                                                       |
                     |     |T  |                                                                       |
                     |     |M  |                                                                       |
                     |     |S  |                                                                       |
                     |     |4  |         |-------------------------|                                   |
|--------------------|     |5  |         |          68000          |                                   |
|                          |0  |         |                         |                                   |
| MB81256   MB81256        |0  |         |-------------------------|                                   |
|                          |A  |                                                                       |
| MB81256   MB81256        |---|                                                                       |
|                      |----------------J3-----------------|                                           |
| MB81256   MB81256    |                                   |                                           |
|                      |                                   |                                           |
| MB81256   MB81256    |                                   |                                           |
|                      |                                   |                                           |
| MB81256   MB81256    |                                   |                                           |
|                      |                                   |                                           |
| MB81256   MB81256    |                                   |                                           |
|                      |----------------J4-----------------|                                           |
| MB81256   MB81256                                                                                    |
|                                                                                U58            U60    |
| MB81256   MB81256                                                                      555           |
|                                                                                                      |
|                                                                                                      |
|                                                                                                      |
|      J5                                                           J6                         J7      |
|------------------------------------------------------------------------------------------------------|
Notes:
        68000 - 68000 CPU at U7. Clock input 7.96MHz [15.92/2] (DIP64)
         LS74 - 74LS74 at U2 provides system clock dividers /4 /2
      MB81256 - Fujitsu MB81256 256Kx1 DRAM. Total RAM 512Kx8/256Kx16. HP part# 1818-3308. U20-U35 (DIP16)
      TMS4500 - Texas Instruments TMS4500A DRAM Controller at U4. Clock input 3.98MHz [15.92/4] (DIP40)
          U58 - 1RD2-6001, HP-HIL Master Link Controller 'Cerberus'. Clock input on pin 24 is unknown (DIP24)
          U60 - Unknown IC used as an interrupt encoder. Possibly a logic chip? (DIP20)
          555 - 555 Timer
        J1/J2 - Connectors joining to LOGIC B PCA (logic A to logic B bus)
        J3/J4 - Connectors for ROM board
           J5 - Power input connector from power supply PCB
           J6 - 64-pin external I/O bus. This is connected to the I/O backplane PCB mounted at the rear of the case using a ribbon cable
           J7 - 10 pin connector. Labelled on schematics as LOOP0 In/Out and LOOP1 In/Out. Connected to 'Cerberus' IC. Possibly for more input devices?


Interface & Control Board (LOGIC B PCA)
-------------------------

HP Part# 00095-60952
00095-60107 BD REV A
00095-60149 ASSY LOGIC B
|---------------------------------------------------------------------------------|
|SPEAKER                        NS58167A               J11       J10              |
|            LM358   32.768kHz                                                    |
|                                                                                 |
|                                                      16Kx4  16Kx4  16Kx4  16Kx4 |
|                 ROM                                                             |
|                                                                                 |
|   BT1                       HP-IL(2)       GPU                                  |
|                                                                                 |--------------------|
|                 1Kb                                                                                  |
|  COP452                                                                                              |
|                                                                                                      |
|                                                                                                      |
|                                                                              WD2797                  |
| LM393          HP-IL(1)                                                                              |
|                                                                                                      |
|                                           LS193                                                      |
|                                                                                                      |
|                                                                                                      |
|                                                                                                      |
|                                                  LS74    24MHz      LS161                            |
|                                                                                                    J2|
|                                                                                                      |
|                                                            TMS9914                                   |
|                                                                                                      |
|                                                                                                      |
|                                                              75162   75160                           |
|                                                                                                      |
|  J14  J6     J5     J4     J3                  J7             J1         J8        J9        J12     |
|------------------------------------------------------------------------------------------------------|
Notes:
         GPU - 1LL3-0005 GPU (Graphics Processor) at U1. Clock input 3MHz [24/8]. VSync on pin 45, HSync on pin 46 (DIP48)
       16Kx4 - 16Kx4 DRAM, organised as 32Kx8bit/16Kx16bit at U3, U4, U5 & U6. Chip type unknown, likely Fujitsu MB81416 (DIP18)
      WD2797 - Western Digital WD2797 Floppy Disk Controller at U18. Clock input 2MHz [24/2/3/2] (DIP40)
    HP-IL(1) - HP-IL 1LJ7-0015 'Saturn' Thinkjet Printer Controller IC at U28. Clock input 3MHz on pin 9 [24/8] (DIP48)
    HP-IL(2) - HP-IL 1LB3 Interface IC at U31. Clock input 2MHz on pin 22 [24/2/3/2] (DIP28)
         1Kb - 1Kb RAM at U27 for printer buffer (DIP28, type unknown, very old, with only DATA0,1,2,3, C/D and DIN,DOUT)
         ROM - 16Kb (32Kx4) Some kind of very early DIP28 PROM/ROM? Same pinout as 1Kb RAM above. Holds the character font table for the printer
               Four versions of this ROM exist, one each for Japan/Arabic/Hebrew and one for all other regions
    NS58167A - National Semiconductor NS58167A Clock Controller RTC at U44. Clock input 32.768kHz (DIP24)
               (Tony Duell's schematics show a 82167 instead)
       LM358 - National Semiconductor LM358 Operational Amplifier at U40 (DIP8)
       LM393 - Texas Instruments LM393 Dual Comparator at U34 (DIP8)
         BT1 - 3v lithium battery
      COP452 - National Semiconductor COP452 Speaker Controller at U39. Clock input 2MHz [24/2/3/2]. This IC provides programmable square wave output from 100Hz to 5000Hz (DIP14)
     TMS9914 - Texas Instruments TMS9914 General Purpose Interface Bus Adapter at U41. Clock input 4MHz [24/2/3] (DIP40)
       75160 - National Semiconductor DS75160A IEEE-488 General Purpose Interface Bus Transceiver at U42 (DIP20)
       75162 - National Semiconductor DS75162A IEEE-488 General Purpose Interface Bus Transceiver at U43 (DIP22)
       LS193 - 74LS193 at U9 provides the main system clock dividers /8 /4 /2 (24MHz -> 12MHz, 6MHz, 3MHz). This is also the source of the 6MHz video clock on connector J1
       LS161 - 74LS161 at U46. Takes 12MHz clock input on pin 2 and outputs 4MHz on pin 13 (i.e. /3). This is the clock source for the TMS9914
        LS74 - LS74 at U16. Takes output of 4MHz from LS161 at U46 and outputs 2MHz on pin 5 (i.e. /2). This is the source of the 2MHz clocks
          J1 - Connector joining to video display assembly
          J2 - Connector joining to floppy drive
          J3 - Connector joining to printer front switch panel assembly (ADV/CONT/FF/ATTN)
          J4 - Connector joining to printer out of paper switch connected to ATTN
          J5 - Connector joining to printer carriage motor
          J6 - Connector joining to printer mechanism assembly including paper motor
          J7 - Connector joining to printer printhead
          J8 - Connector joining to HO?E switch (? ~ M, text unreadable on schems)
          J9 - Connector for ?
     J10/J11 - Connectors joining to LOGIC A PCA (logic A to logic B bus)
         J12 - Power input connector from power supply PCB
         J14 - Fan connector


ROM board (Operating System ROM PCA. Assembly# HP82991A or HP82995A)
---------

|----------------J3-----------------|
|                                   |
|                                   |
|                                   |
|J1  U1      U2      U3     U4    J2|
|                                   |
|                                   |
|                                   |
|----------------J4-----------------|
Notes:
      J1/J2 - 20 pin connector joining to 'Option ROM PCA'
      J3/J4 - 20 pin connector joining to 'LOGIC A PCA'
      U1-U4 - 28 pin EPROM/mask ROM 0L/1L/0H/1H (note 1Mbit: 128Kx8 28 pin)


ROM board (Option ROM PCA)
---------
Note this PCB plugs in upside-down on top of the Operating System ROM PCB

|----------------J4-----------------|
|                                   |
|                                   |
|                                   |
|J1  U1      U2      U3     U4    J2|
|                                   |
|                                   |
|                                   |
|----------------J3-----------------|
Notes:
      J1/J2 - 20 pin connector joining to 'Operating System ROM PCA'
      J3/J4 - 20 pin connector joining to 'LOGIC A PCA'
      U1-U4 - 28 pin EPROM/mask ROM 0L/1L/0H/1H (note 1Mbit: 128Kx8 28 pin)


Physical Memory Map
===================
000000-07FFFF - Internal ROM (Operating System PCA 512Kb)
080000-0FFFFF - Internal ROM (Option ROM PCA 512Kb)
100000-4FFFFF - External ROM modules (up to 4Mb)
500000-5FFFFF - Reserved 1Mb
600000-6FFFFF - Internal I/O 1Mb

                Address        Port  Use
                -------------------------
                600000-60FFFF   0    MMU
                610000-61FFFF   1    Disk Drive
                620000-62FFFF   2    Display
                630000-63FFFF   3    HP-IB
                640000-64FFFF   4    RTC
                650000-65FFFF   5    Printer
                660000-66FFFF   6    Keyboard
                670000-67FFFF   7    Speaker
                680000-68FFFF   8    Reserved
                690000-69FFFF   9    Reserved
                6A0000-6AFFFF   10   Reserved
                6B0000-6BFFFF   11   Reserved
                6C0000-6CFFFF   12   Reserved
                6D0000-6DFFFF   13   Reserved
                6E0000-6EFFFF   14   Reserved
                6F0000-6FFFFF   15   Reserved

700000-7FFFFF - External I/O 1Mb

                Address        Port  Use
                -------------------------
                700000-70FFFF   16   Mainframe Port A
                710000-71FFFF   17   Mainframe Port B
                720000-72FFFF   18   Bus Expander Port A1
                730000-73FFFF   19   Bus Expander Port A2
                740000-74FFFF   20   Bus Expander Port A3
                750000-75FFFF   21   Bus Expander Port A4
                760000-76FFFF   22   Bus Expander Port A5
                770000-77FFFF   23   Reserved
                780000-78FFFF   24   Reserved
                790000-79FFFF   25   Reserved
                7A0000-7AFFFF   26   Bus Expander Port B1
                7B0000-7BFFFF   27   Bus Expander Port B2
                7C0000-7CFFFF   28   Bus Expander Port B3
                7D0000-7DFFFF   29   Bus Expander Port B4
                7E0000-7EFFFF   30   Bus Expander Port B5
                7F0000-7FFFFF   31   Reserved

800000-EFFFFF - External RAM modules (up to 7Mb)
F00000-F7FFFF - Internal RAM 512Kb
F80000-FFFFFF - Reserved 512Kb

Access to 800000-FFFFFF can be remapped by the MMU registers.


Interrupts (all autovectored)
----------
High Priority 7 - Soft reset from keyboard (NMI)
     /\       6 - RTC or NBIR3 (external I/O)
     ||       5 - Disc Drive or NBIR2 (external I/O)
     ||       4 - GPU or NBIR1 (external I/O)
     ||       3 - HP-IB, printer or NBIR0 (external I/O)
     \/       2 - HP-HIL devices (keyboard/mouse)
Low Priority  1 - RTC

Note external interrupt lines NBIR0 to NBIR3 can be asserted by an interface connected to the external I/O port


Useful links etc.
-----------------

bitsavers://pdf/hp/integral/00095-90126_Integral_Personal_Computer_Service_Jan86.pdf

bitsavers://pdf/hp/hp-hil/45918A-90001_HP-HIL_Technical_Reference_Manual_Jan86.pdf
    HP-HIL MLC, SLC datasheets

bitsavers://pdf/sony/floppy/Sony_OA-D32_Microfloppy_Service_Nov83.pdf
    OA-D32W

http://www.hpl.hp.com/hpjournal/pdfs/IssuePDFs/1983-01.pdf
    HP-IL issue

http://www.hpl.hp.com/hpjournal/pdfs/IssuePDFs/1985-10.pdf
    IPC issue

http://www.hpl.hp.com/hpjournal/pdfs/IssuePDFs/1987-06.pdf
    HP-HIL article

http://www.hpmuseum.net/pdf/ComputerNews_1985_Jan15_37pages_OCR.pdf
    introducing the IPC

http://www.hpmuseum.net/pdf/ComputerFocus_1985_Nov_25pages_OCR.pdf
    SysV upgrade

http://www.hpmuseum.net/pdf/InformationSystemsAndManufacturingNews_81pages_Jun1-86_OCR.pdf
    EPROM/ROM modules

http://www.hpmuseum.net/pdf/HPChannels_1986_11_37pages_Nov86_OCR.pdf
    SW Eng ROM and serial option for it

http://www.coho.org/~pete/downloads/IPC/burst/Freeware/IPC_Driver_Writers_Disc/hp-ux.5.0.0
    kernel namelist

http://www.hpmuseum.net/display_item.php?hw=122
    overview, manuals, software

http://www.ambry.com/hp-computer-model/9807A.html
    replacement parts

http://www.brouhaha.com/~eric/hpcalc/chips/
    chip part numbers


Software to look for
--------------------

00095-60978 "Service ROM - Used in trobleshooting the integral PC" via ambry
00095-60925 "Service ROM" via service manual
00095-60969 "Service Diagnostic Disc" via service manual
00095-60950 "I/O Component-Level Diagnostic Disc" via serial interface service manual

00095-60006 (original System III-based HP-UX 1.0 ROM)
82995A (same bits as 82991A; the latter is an upgrade kit, former was pre-installed)
82989J Technical Basic ROM (Jan'1986)
82987A Software Engineering ROM (Nov'1986) (possibly can be rebuilt from floppy images on coho?)

******************************************************************************/

#include "emu.h"

#include "bus/hp_hil/hp_hil.h"
#include "bus/hp_hil/hil_devices.h"
#include "cpu/m68000/m68000.h"
#include "formats/hp_ipc_dsk.h"
#include "imagedev/floppy.h"
#include "machine/bankdev.h"
#include "machine/mm58167.h"
#include "machine/ram.h"
#include "machine/wd_fdc.h"
#include "video/hp1ll3.h"
#include "machine/tms9914.h"
#include "bus/ieee488/ieee488.h"

#include "emupal.h"
#include "screen.h"


class hp_ipc_state : public driver_device
{
public:
	hp_ipc_state(const machine_config &mconfig, device_type type, const char *tag)
		: driver_device(mconfig, type, tag)
		, m_maincpu(*this, "maincpu")
		, m_bankdev(*this, "bankdev")
		, m_fdc(*this, "fdc")
		, m_ram(*this, RAM_TAG)
		, m_gpu(*this , "gpu")
		, m_screen(*this, "screen")
	{ }

	void hp_ipc_base(machine_config &config);
	void hp_ipc(machine_config &config);
	void hp9808a(machine_config &config);

private:
	virtual void machine_start() override;
	virtual void machine_reset() override;

	uint16_t mem_r(offs_t offset, uint16_t mem_mask);
	void mem_w(offs_t offset, uint16_t data, uint16_t mem_mask);
	uint16_t mmu_r(offs_t offset);
	void mmu_w(offs_t offset, uint16_t data);
	uint16_t ram_r(offs_t offset, uint16_t mem_mask);
	void ram_w(offs_t offset, uint16_t data, uint16_t mem_mask);
	uint16_t trap_r(offs_t offset, uint16_t mem_mask);
	void trap_w(offs_t offset, uint16_t data, uint16_t mem_mask);

	uint8_t floppy_id_r();
	void floppy_id_w(uint8_t data);
	DECLARE_FLOPPY_FORMATS(floppy_formats);

	DECLARE_WRITE_LINE_MEMBER(irq_1);
	DECLARE_WRITE_LINE_MEMBER(irq_2);
	DECLARE_WRITE_LINE_MEMBER(irq_3);
	DECLARE_WRITE_LINE_MEMBER(irq_4);
	DECLARE_WRITE_LINE_MEMBER(irq_5);
	DECLARE_WRITE_LINE_MEMBER(irq_6);
	DECLARE_WRITE_LINE_MEMBER(irq_7);

	emu_timer *m_bus_error_timer;

	void hp_ipc_mem_inner_base(address_map &map);
	void hp_ipc_mem_inner_9807a(address_map &map);
	void hp_ipc_mem_outer(address_map &map);

	void hp_ipc_mem_inner_9808a(address_map &map);

	required_device<m68000_device> m_maincpu;
	required_device<address_map_bank_device> m_bankdev;
	required_device<wd2797_device> m_fdc;
	required_device<ram_device> m_ram;
	required_device<hp1ll3_device> m_gpu;
	required_device<screen_device> m_screen;

	uint32_t m_mmu[4], m_lowest_ram_addr;
	uint16_t *m_internal_ram;
	int m_fc;

	floppy_image_device *m_floppy;

	inline uint32_t get_ram_address(offs_t offset)
	{
		return (m_mmu[(m_maincpu->get_fc() >> 1) & 3] + offset) & 0x3FFFFF;
	}

	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
	void set_bus_error(uint32_t address, bool write, uint16_t mem_mask);
	bool m_bus_error;
};


void hp_ipc_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	m_bus_error = false;
}

void hp_ipc_state::set_bus_error(uint32_t address, bool rw, uint16_t mem_mask)
{
	if (m_bus_error)
	{
		return;
	}
	if (!ACCESSING_BITS_8_15)
	{
		address++;
	}
	m_bus_error = true;
	m_maincpu->set_buserror_details(address, rw, m_maincpu->get_fc());
	m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
	m_bus_error_timer->adjust(m_maincpu->cycles_to_attotime(16)); // let rmw cycles complete
}

void hp_ipc_state::hp_ipc_mem_outer(address_map &map)
{
	map(0x000000, 0xFFFFFF).rw(FUNC(hp_ipc_state::mem_r), FUNC(hp_ipc_state::mem_w));
}

void hp_ipc_state::hp_ipc_mem_inner_base(address_map &map)
{
// bus error handler
	map(0x0000000, 0x1FFFFFF).rw(FUNC(hp_ipc_state::trap_r), FUNC(hp_ipc_state::trap_w));

// user mode
	map(0x1000000, 0x17FFFFF).rw(FUNC(hp_ipc_state::ram_r), FUNC(hp_ipc_state::ram_w));
	map(0x1800000, 0x187FFFF).rom().region("maincpu", 0);
	map(0x1E00000, 0x1E0FFFF).rw(FUNC(hp_ipc_state::mmu_r), FUNC(hp_ipc_state::mmu_w));
	map(0x1E20000, 0x1E2000F).rw(m_gpu, FUNC(hp1ll3_device::read), FUNC(hp1ll3_device::write)).umask16(0x00ff);
	map(0x1E40000, 0x1E4002F).rw("rtc", FUNC(mm58167_device::read), FUNC(mm58167_device::write)).umask16(0x00ff);

// supervisor mode
	map(0x0000000, 0x007FFFF).rom().region("maincpu", 0);       // Internal ROM (operating system PCA)
	map(0x0080000, 0x00FFFFF).unmaprw();     // Internal ROM (option ROM PCA)
	map(0x0100000, 0x04FFFFF).unmaprw();     // External ROM modules
	map(0x0600000, 0x060FFFF).rw(FUNC(hp_ipc_state::mmu_r), FUNC(hp_ipc_state::mmu_w));
	map(0x0610000, 0x0610007).rw(FUNC(hp_ipc_state::floppy_id_r), FUNC(hp_ipc_state::floppy_id_w)).umask16(0x00ff);
	map(0x0610008, 0x061000F).rw(m_fdc, FUNC(wd2797_device::read), FUNC(wd2797_device::write)).umask16(0x00ff);
	map(0x0620000, 0x0620007).rw(m_gpu, FUNC(hp1ll3_device::read), FUNC(hp1ll3_device::write)).umask16(0x00ff);
	map(0x0630000, 0x063FFFF).mask(0xf).rw("hpib" , FUNC(tms9914_device::read) , FUNC(tms9914_device::write)).umask16(0x00ff);
	map(0x0640000, 0x064002F).rw("rtc", FUNC(mm58167_device::read), FUNC(mm58167_device::write)).umask16(0x00ff);
	map(0x0660000, 0x06600FF).rw("mlc", FUNC(hp_hil_mlc_device::read), FUNC(hp_hil_mlc_device::write)).umask16(0x00ff);  // 'caravan', scrn/caravan.h
	map(0x0670000, 0x067FFFF).noprw();       // Speaker (NatSemi COP 452)
	map(0x0680000, 0x068FFFF).noprw();       // 'SIMON (98628) fast HP-IB card' -- sys/simon.h
	map(0x0700000, 0x07FFFFF).unmaprw();     // External I/O
	map(0x0800000, 0x0FFFFFF).rw(FUNC(hp_ipc_state::ram_r), FUNC(hp_ipc_state::ram_w));
}

void hp_ipc_state::hp_ipc_mem_inner_9807a(address_map &map)
{
	hp_ipc_mem_inner_base(map);
	map(0x0650000, 0x065FFFF).noprw();       // HP-IL Printer (optional; ROM sets _desktop to 0 if not mapped) -- sys/lpint.h
}

void hp_ipc_state::hp_ipc_mem_inner_9808a(address_map &map)
{
	hp_ipc_mem_inner_base(map);
}

static INPUT_PORTS_START(hp_ipc)
INPUT_PORTS_END


uint16_t hp_ipc_state::mmu_r(offs_t offset)
{
	uint16_t data = (m_mmu[offset & 3] >> 10);

	return data;
}

void hp_ipc_state::mmu_w(offs_t offset, uint16_t data)
{
	m_mmu[offset & 3] = (data & 0xFFF) << 10;
}

uint16_t hp_ipc_state::mem_r(offs_t offset, uint16_t mem_mask)
{
	int fc = m_maincpu->get_fc() & 4;

	if (fc != m_fc)
	{
		m_fc = fc;
		m_bankdev->set_bank(m_fc ? 0 : 1);
	}

	return m_bankdev->read16(offset, mem_mask);
}

void hp_ipc_state::mem_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
	int fc = m_maincpu->get_fc() & 4;

	if (fc != m_fc)
	{
		m_fc = fc;
		m_bankdev->set_bank(m_fc ? 0 : 1);
	}

	m_bankdev->write16(offset, data, mem_mask);
}

uint16_t hp_ipc_state::trap_r(offs_t offset, uint16_t mem_mask)
{
	if (!machine().side_effects_disabled()) set_bus_error((offset << 1) & 0xFFFFFF, true, mem_mask);

	return 0xffff;
}

void hp_ipc_state::trap_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
	if (!machine().side_effects_disabled()) set_bus_error((offset << 1) & 0xFFFFFF, false, mem_mask);
}


uint16_t hp_ipc_state::ram_r(offs_t offset, uint16_t mem_mask)
{
	uint32_t ram_address = get_ram_address(offset);
	uint16_t data = 0xffff;

	if (ram_address < m_lowest_ram_addr)
	{
		if (!machine().side_effects_disabled()) set_bus_error((offset << 1) + 0x800000, 0, mem_mask);
	}
	else if (ram_address < 0x3c0000)
	{
		// Internal RAM
		data = m_internal_ram[ram_address - m_lowest_ram_addr];
	}

	return data;
}

void hp_ipc_state::ram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
	uint32_t ram_address = get_ram_address(offset);

	if (ram_address < m_lowest_ram_addr)
	{
		if (!machine().side_effects_disabled()) set_bus_error((offset << 1) + 0x800000, 1, mem_mask);
	}
	else if (ram_address < 0x3c0000)
	{
		// Internal RAM
		COMBINE_DATA(&m_internal_ram[ram_address - m_lowest_ram_addr]);
	}
}


/*
 * bit 6 -- INTRQ
 * bit 1 -- disk changed (from drive)
 * bit 0 -- write protect (from drive)
 */
uint8_t hp_ipc_state::floppy_id_r()
{
	uint8_t data = 0;

	// TODO: fix sys controller switch
	data = (m_fdc->intrq_r() << 6) | 0x80;

	if (m_floppy)
	{
		data |= (m_fdc->intrq_r() << 6) | (m_floppy->dskchg_r() << 1) | m_floppy->wpt_r();
	}

	return data;
}

/*
 * bit 7 -- 1: motor on (via inverter to drive's /MTorOn)
 * bit 3 -- 1: head 0, 0: head 1 (via inverter to drive's /SSO)
 * bit 1 -- 1: drive select (via inverter to drive's /DRIVE SEL 1)
 * bit 0 -- 1: reset disc_changed (via inverter to drive's /DSKRST)
 */
void hp_ipc_state::floppy_id_w(uint8_t data)
{
	floppy_image_device *floppy0 = m_fdc->subdevice<floppy_connector>("0")->get_device();

	if (!BIT(data, 1))
	{
		if (m_floppy == nullptr)
		{
			m_floppy = floppy0;
			m_fdc->set_floppy(m_floppy);
		}
	}
	else
	{
		m_floppy = nullptr;
	}

	if (m_floppy)
	{
		m_floppy->ss_w(BIT(data, 3));
		m_floppy->mon_w(!BIT(data, 7));
		if (BIT(data, 0))
			m_floppy->dskchg_w(0);
	}
	else
	{
		floppy0->mon_w(1);
	}
}


WRITE_LINE_MEMBER(hp_ipc_state::irq_1)
{
	m_maincpu->set_input_line(M68K_IRQ_1, state);
}

WRITE_LINE_MEMBER(hp_ipc_state::irq_2)
{
	m_maincpu->set_input_line(M68K_IRQ_2, state);
}

WRITE_LINE_MEMBER(hp_ipc_state::irq_3)
{
	m_maincpu->set_input_line(M68K_IRQ_3, state);
}

WRITE_LINE_MEMBER(hp_ipc_state::irq_4)
{
	m_maincpu->set_input_line(M68K_IRQ_4, state);
}

WRITE_LINE_MEMBER(hp_ipc_state::irq_5)
{
	m_maincpu->set_input_line(M68K_IRQ_5, state);
}

WRITE_LINE_MEMBER(hp_ipc_state::irq_6)
{
	m_maincpu->set_input_line(M68K_IRQ_6, state);
}

WRITE_LINE_MEMBER(hp_ipc_state::irq_7)
{
	m_maincpu->set_input_line(M68K_IRQ_7, state);
}


void hp_ipc_state::machine_start()
{
	m_bus_error_timer = timer_alloc(0);

	m_bankdev->set_bank(1);

	m_lowest_ram_addr = 0x3c0000 - (m_ram->size() >> 1);
	m_internal_ram = (uint16_t *)m_ram->pointer();
}

void hp_ipc_state::machine_reset()
{
	m_floppy = nullptr;
}


FLOPPY_FORMATS_MEMBER( hp_ipc_state::floppy_formats )
	FLOPPY_HP_IPC_FORMAT
FLOPPY_FORMATS_END

static void hp_ipc_floppies(device_slot_interface &device)
{
	device.option_add("35dd", SONY_OA_D32W);
}

/*
 *  IRQ levels (page 5-4)
 *
 *  7   Soft reset from keyboard, non-maskable
 *  6   Real-time clock or NBIR3 (ext. I/O)
 *  5   Disc Drive or NBIR2
 *  4   GPU or NBIR1
 *  3   HP-IB, printer, or NBIR0
 *  2   HP-HIL devices (keyboard, mouse)
 *  1   Real-time clock
 */
void hp_ipc_state::hp_ipc_base(machine_config &config)
{
	M68000(config, m_maincpu, 15.92_MHz_XTAL / 2);
	m_maincpu->set_addrmap(AS_PROGRAM, &hp_ipc_state::hp_ipc_mem_outer);

	HP1LL3(config , m_gpu , 24_MHz_XTAL / 8).set_screen("screen");

	// XXX actual clock is 1MHz; remove this workaround (and change 2000 to 100 in hp_ipc_dsk.cpp)
	// XXX when floppy code correctly handles 600 rpm drives.
	WD2797(config, m_fdc, 2_MHz_XTAL);
	m_fdc->intrq_wr_callback().set(FUNC(hp_ipc_state::irq_5));
	FLOPPY_CONNECTOR(config, "fdc:0", hp_ipc_floppies, "35dd", hp_ipc_state::floppy_formats);

	SOFTWARE_LIST(config, "flop_list").set_original("hp_ipc");

	mm58167_device &rtc(MM58167(config, "rtc", 32.768_kHz_XTAL));
	rtc.irq().set(FUNC(hp_ipc_state::irq_1));
//  rtc.standby_irq().set(FUNC(hp_ipc_state::irq_6));

	hp_hil_mlc_device &mlc(HP_HIL_MLC(config, "mlc", XTAL(15'920'000)/2));
	mlc.int_callback().set(FUNC(hp_ipc_state::irq_2));
	mlc.nmi_callback().set(FUNC(hp_ipc_state::irq_7));

	HP_HIL_SLOT(config, "hil1", "mlc", hp_hil_devices, "hp_ipc_kbd");
	HP_HIL_SLOT(config, "hil2", "mlc", hp_hil_devices, "hp_46060b");

	tms9914_device &hpib(TMS9914(config, "hpib", 4_MHz_XTAL));
	hpib.int_write_cb().set(FUNC(hp_ipc_state::irq_3));
	hpib.dio_read_cb().set(IEEE488_TAG, FUNC(ieee488_device::dio_r));
	hpib.dio_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_dio_w));
	hpib.eoi_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_eoi_w));
	hpib.dav_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_dav_w));
	hpib.nrfd_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_nrfd_w));
	hpib.ndac_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ndac_w));
	hpib.ifc_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ifc_w));
	hpib.srq_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_srq_w));
	hpib.atn_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_atn_w));
	hpib.ren_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ren_w));

	ieee488_device &ieee(IEEE488(config, IEEE488_TAG));
	ieee.eoi_callback().set("hpib" , FUNC(tms9914_device::eoi_w));
	ieee.dav_callback().set("hpib" , FUNC(tms9914_device::dav_w));
	ieee.nrfd_callback().set("hpib" , FUNC(tms9914_device::nrfd_w));
	ieee.ndac_callback().set("hpib" , FUNC(tms9914_device::ndac_w));
	ieee.ifc_callback().set("hpib" , FUNC(tms9914_device::ifc_w));
	ieee.srq_callback().set("hpib" , FUNC(tms9914_device::srq_w));
	ieee.atn_callback().set("hpib" , FUNC(tms9914_device::atn_w));
	ieee.ren_callback().set("hpib" , FUNC(tms9914_device::ren_w));
	IEEE488_SLOT(config , "ieee_rem" , 0 , remote488_devices , nullptr);

	RAM(config, RAM_TAG).set_default_size("512K").set_extra_options("768K,1M,1576K,2M,3M,4M,5M,6M,7M,7680K");
}

void hp_ipc_state::hp_ipc(machine_config &config)
{
	hp_ipc_base(config);

	ADDRESS_MAP_BANK(config, "bankdev").set_map(&hp_ipc_state::hp_ipc_mem_inner_9807a).set_options(ENDIANNESS_BIG, 16, 25, 0x1000000);

	// 16kw/32kb video RAM
	m_gpu->set_vram_size(16);

	// horizontal time = 60 us (min)
	// ver.refresh period = ~300 us
	// ver.period = 16.7ms (~60 hz)
	SCREEN(config , m_screen , SCREEN_TYPE_LCD);
	m_screen->set_color(rgb_t::amber()); // actually a kind of EL display
	m_screen->set_screen_update("gpu" , FUNC(hp1ll3_device::screen_update));
	m_screen->set_raw(6_MHz_XTAL * 2 , 720 , 0 , 512 , 261 , 0 , 255);
	m_screen->screen_vblank().set("mlc", FUNC(hp_hil_mlc_device::ap_w)); // XXX actually it's driven by 555 (U59)
	m_screen->set_palette("palette");

	PALETTE(config, "palette", palette_device::MONOCHROME);
}

void hp_ipc_state::hp9808a(machine_config &config)
{
	hp_ipc_base(config);

	ADDRESS_MAP_BANK(config, "bankdev").set_map(&hp_ipc_state::hp_ipc_mem_inner_9808a).set_options(ENDIANNESS_BIG, 16, 25, 0x1000000);

	// 64kw/128kb video RAM
	m_gpu->set_vram_size(64);

	SCREEN(config , m_screen , SCREEN_TYPE_LCD);
	m_screen->set_color(rgb_t::amber()); // actually a kind of EL display
	m_screen->set_screen_update("gpu" , FUNC(hp1ll3_device::screen_update));
	m_screen->set_raw(6_MHz_XTAL * 2 , 880 , 0 , 640 , 425 , 0 , 400);
	m_screen->screen_vblank().set("mlc", FUNC(hp_hil_mlc_device::ap_w)); // XXX actually it's driven by 555 (U59)
	m_screen->set_palette("palette");

	PALETTE(config, "palette", palette_device::MONOCHROME);
}


ROM_START(hp_ipc)
	ROM_REGION(0x80000, "maincpu", 0)
	ROM_DEFAULT_BIOS("v50")

	ROM_SYSTEM_BIOS(0, "v10", "HP-UX 1.0")
	ROMX_LOAD("00095-60006.bin", 0x00000, 0x80000, NO_DUMP, ROM_BIOS(0))

	ROM_SYSTEM_BIOS(1, "v50", "HP-UX 5.0")
	// Should be spread across 4 x 128K ROMs
	ROMX_LOAD("hp ipc os 82991a.bin", 0x00000, 0x80000, BAD_DUMP CRC(df45a37b) SHA1(476af9923bca0d2d0f40aeb81be5145ca76fddf5), ROM_BIOS(1))

	ROM_SYSTEM_BIOS(2, "diaga", "Diag ROM A")
	ROMX_LOAD("boarda_u1.bin", 0x00001, 0x4000, CRC(f40e1434) SHA1(a4f633f3e0971ba3ff218c6d6f777b8253bade8c), ROM_BIOS(2) | ROM_SKIP(1))
	ROMX_LOAD("boarda_u2.bin", 0x00000, 0x4000, CRC(80f6eb08) SHA1(ea943f72d37b43b5ba06b8e6f11824601109497c), ROM_BIOS(2) | ROM_SKIP(1))
	ROMX_LOAD("boarda_u3.bin", 0x40001, 0x4000, CRC(0f2fd4d5) SHA1(9ed41fca947d58d7f4159336421601963e3cae17), ROM_BIOS(2) | ROM_SKIP(1))
	ROMX_LOAD("boarda_u4.bin", 0x40000, 0x4000, CRC(d6741772) SHA1(1574a52d6658f9a7beace6572bea11ee923fc1bf), ROM_BIOS(2) | ROM_SKIP(1))

	ROM_SYSTEM_BIOS(3, "diagb", "Diag ROM B")
	ROMX_LOAD("boardb_u1.bin", 0x00001, 0x4000, CRC(597777d9) SHA1(24671499e4685f306b1b37a071adc0634f9f1e4e), ROM_BIOS(3) | ROM_SKIP(1))
	ROMX_LOAD("boardb_u2.bin", 0x00000, 0x4000, CRC(bc2ada19) SHA1(efebab335ca8a57e77b1076050e861a3a0eb09fc), ROM_BIOS(3) | ROM_SKIP(1))
	ROMX_LOAD("boardb_u3.bin", 0x40001, 0x2000, CRC(c227622a) SHA1(99747945dc6efaa45ce8d7d3c58830dbe46b651a), ROM_BIOS(3) | ROM_SKIP(1))
	ROMX_LOAD("boardb_u4.bin", 0x40000, 0x2000, CRC(d99efe90) SHA1(345437007f8d728ceafc5cd97414ef94ce38e363), ROM_BIOS(3) | ROM_SKIP(1))
ROM_END

#define rom_hp9808a rom_hp_ipc

//    YEAR  NAME     PARENT  COMPAT  MACHINE  INPUT   CLASS         INIT        COMPANY            FULLNAME                            FLAGS
COMP( 1985, hp_ipc,  0,      0,      hp_ipc,  hp_ipc, hp_ipc_state, empty_init, "Hewlett-Packard", "Integral Personal Computer 9807A", MACHINE_NO_SOUND)
COMP( 1985, hp9808a, 0,      0,      hp9808a, hp_ipc, hp_ipc_state, empty_init, "Hewlett-Packard", "Integral Personal Computer 9808A", MACHINE_NOT_WORKING)