1806c35f5SAlan Cox /*
2806c35f5SAlan Cox * AMD 76x Memory Controller kernel module
3806c35f5SAlan Cox * (C) 2003 Linux Networx (http://lnxi.com)
4806c35f5SAlan Cox * This file may be distributed under the terms of the
5806c35f5SAlan Cox * GNU General Public License.
6806c35f5SAlan Cox *
7806c35f5SAlan Cox * Written by Thayne Harbaugh
8806c35f5SAlan Cox * Based on work by Dan Hollis <goemon at anime dot net> and others.
9806c35f5SAlan Cox * http://www.anime.net/~goemon/linux-ecc/
10806c35f5SAlan Cox *
11806c35f5SAlan Cox * $Id: edac_amd76x.c,v 1.4.2.5 2005/10/05 00:43:44 dsp_llnl Exp $
12806c35f5SAlan Cox *
13806c35f5SAlan Cox */
14806c35f5SAlan Cox
15806c35f5SAlan Cox #include <linux/module.h>
16806c35f5SAlan Cox #include <linux/init.h>
17806c35f5SAlan Cox #include <linux/pci.h>
18806c35f5SAlan Cox #include <linux/pci_ids.h>
19c3c52bceSHitoshi Mitake #include <linux/edac.h>
20*78d88e8aSMauro Carvalho Chehab #include "edac_module.h"
21806c35f5SAlan Cox
22929a40ecSDoug Thompson #define EDAC_MOD_STR "amd76x_edac"
2337f04581SDoug Thompson
24537fba28SDave Peterson #define amd76x_printk(level, fmt, arg...) \
25537fba28SDave Peterson edac_printk(level, "amd76x", fmt, ##arg)
26537fba28SDave Peterson
27537fba28SDave Peterson #define amd76x_mc_printk(mci, level, fmt, arg...) \
28537fba28SDave Peterson edac_mc_chipset_printk(mci, level, "amd76x", fmt, ##arg)
29537fba28SDave Peterson
30806c35f5SAlan Cox #define AMD76X_NR_CSROWS 8
31806c35f5SAlan Cox #define AMD76X_NR_DIMMS 4
32806c35f5SAlan Cox
33806c35f5SAlan Cox /* AMD 76x register addresses - device 0 function 0 - PCI bridge */
34e7ecd891SDave Peterson
35806c35f5SAlan Cox #define AMD76X_ECC_MODE_STATUS 0x48 /* Mode and status of ECC (32b)
36806c35f5SAlan Cox *
37806c35f5SAlan Cox * 31:16 reserved
38806c35f5SAlan Cox * 15:14 SERR enabled: x1=ue 1x=ce
39806c35f5SAlan Cox * 13 reserved
40806c35f5SAlan Cox * 12 diag: disabled, enabled
41806c35f5SAlan Cox * 11:10 mode: dis, EC, ECC, ECC+scrub
42806c35f5SAlan Cox * 9:8 status: x1=ue 1x=ce
43806c35f5SAlan Cox * 7:4 UE cs row
44806c35f5SAlan Cox * 3:0 CE cs row
45806c35f5SAlan Cox */
46e7ecd891SDave Peterson
47806c35f5SAlan Cox #define AMD76X_DRAM_MODE_STATUS 0x58 /* DRAM Mode and status (32b)
48806c35f5SAlan Cox *
49806c35f5SAlan Cox * 31:26 clock disable 5 - 0
50806c35f5SAlan Cox * 25 SDRAM init
51806c35f5SAlan Cox * 24 reserved
52806c35f5SAlan Cox * 23 mode register service
53806c35f5SAlan Cox * 22:21 suspend to RAM
54806c35f5SAlan Cox * 20 burst refresh enable
55806c35f5SAlan Cox * 19 refresh disable
56806c35f5SAlan Cox * 18 reserved
57806c35f5SAlan Cox * 17:16 cycles-per-refresh
58806c35f5SAlan Cox * 15:8 reserved
59806c35f5SAlan Cox * 7:0 x4 mode enable 7 - 0
60806c35f5SAlan Cox */
61e7ecd891SDave Peterson
62806c35f5SAlan Cox #define AMD76X_MEM_BASE_ADDR 0xC0 /* Memory base address (8 x 32b)
63806c35f5SAlan Cox *
64806c35f5SAlan Cox * 31:23 chip-select base
65806c35f5SAlan Cox * 22:16 reserved
66806c35f5SAlan Cox * 15:7 chip-select mask
67806c35f5SAlan Cox * 6:3 reserved
68806c35f5SAlan Cox * 2:1 address mode
69806c35f5SAlan Cox * 0 chip-select enable
70806c35f5SAlan Cox */
71806c35f5SAlan Cox
72806c35f5SAlan Cox struct amd76x_error_info {
73806c35f5SAlan Cox u32 ecc_mode_status;
74806c35f5SAlan Cox };
75806c35f5SAlan Cox
76806c35f5SAlan Cox enum amd76x_chips {
77806c35f5SAlan Cox AMD761 = 0,
78806c35f5SAlan Cox AMD762
79806c35f5SAlan Cox };
80806c35f5SAlan Cox
81806c35f5SAlan Cox struct amd76x_dev_info {
82806c35f5SAlan Cox const char *ctl_name;
83806c35f5SAlan Cox };
84806c35f5SAlan Cox
85806c35f5SAlan Cox static const struct amd76x_dev_info amd76x_devs[] = {
86e7ecd891SDave Peterson [AMD761] = {
8767cb2b61SDouglas Thompson .ctl_name = "AMD761"},
88e7ecd891SDave Peterson [AMD762] = {
8967cb2b61SDouglas Thompson .ctl_name = "AMD762"},
90806c35f5SAlan Cox };
91806c35f5SAlan Cox
92456a2f95SDave Jiang static struct edac_pci_ctl_info *amd76x_pci;
93456a2f95SDave Jiang
94806c35f5SAlan Cox /**
95806c35f5SAlan Cox * amd76x_get_error_info - fetch error information
96806c35f5SAlan Cox * @mci: Memory controller
97806c35f5SAlan Cox * @info: Info to fill in
98806c35f5SAlan Cox *
99806c35f5SAlan Cox * Fetch and store the AMD76x ECC status. Clear pending status
100806c35f5SAlan Cox * on the chip so that further errors will be reported
101806c35f5SAlan Cox */
amd76x_get_error_info(struct mem_ctl_info * mci,struct amd76x_error_info * info)102806c35f5SAlan Cox static void amd76x_get_error_info(struct mem_ctl_info *mci,
103806c35f5SAlan Cox struct amd76x_error_info *info)
104806c35f5SAlan Cox {
10537f04581SDoug Thompson struct pci_dev *pdev;
10637f04581SDoug Thompson
107fd687502SMauro Carvalho Chehab pdev = to_pci_dev(mci->pdev);
10837f04581SDoug Thompson pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS,
109806c35f5SAlan Cox &info->ecc_mode_status);
110806c35f5SAlan Cox
111806c35f5SAlan Cox if (info->ecc_mode_status & BIT(8))
11237f04581SDoug Thompson pci_write_bits32(pdev, AMD76X_ECC_MODE_STATUS,
113806c35f5SAlan Cox (u32) BIT(8), (u32) BIT(8));
114806c35f5SAlan Cox
115806c35f5SAlan Cox if (info->ecc_mode_status & BIT(9))
11637f04581SDoug Thompson pci_write_bits32(pdev, AMD76X_ECC_MODE_STATUS,
117806c35f5SAlan Cox (u32) BIT(9), (u32) BIT(9));
118806c35f5SAlan Cox }
119806c35f5SAlan Cox
120806c35f5SAlan Cox /**
121806c35f5SAlan Cox * amd76x_process_error_info - Error check
122806c35f5SAlan Cox * @mci: Memory controller
123806c35f5SAlan Cox * @info: Previously fetched information from chip
124806c35f5SAlan Cox * @handle_errors: 1 if we should do recovery
125806c35f5SAlan Cox *
126806c35f5SAlan Cox * Process the chip state and decide if an error has occurred.
127806c35f5SAlan Cox * A return of 1 indicates an error. Also if handle_errors is true
128806c35f5SAlan Cox * then attempt to handle and clean up after the error
129806c35f5SAlan Cox */
amd76x_process_error_info(struct mem_ctl_info * mci,struct amd76x_error_info * info,int handle_errors)130806c35f5SAlan Cox static int amd76x_process_error_info(struct mem_ctl_info *mci,
13167cb2b61SDouglas Thompson struct amd76x_error_info *info,
13267cb2b61SDouglas Thompson int handle_errors)
133806c35f5SAlan Cox {
134806c35f5SAlan Cox int error_found;
135806c35f5SAlan Cox u32 row;
136806c35f5SAlan Cox
137806c35f5SAlan Cox error_found = 0;
138806c35f5SAlan Cox
139806c35f5SAlan Cox /*
140806c35f5SAlan Cox * Check for an uncorrectable error
141806c35f5SAlan Cox */
142806c35f5SAlan Cox if (info->ecc_mode_status & BIT(8)) {
143806c35f5SAlan Cox error_found = 1;
144806c35f5SAlan Cox
145806c35f5SAlan Cox if (handle_errors) {
146806c35f5SAlan Cox row = (info->ecc_mode_status >> 4) & 0xf;
1479eb07a7fSMauro Carvalho Chehab edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
148de3910ebSMauro Carvalho Chehab mci->csrows[row]->first_page, 0, 0,
149d8c34af4SMauro Carvalho Chehab row, 0, -1,
15003f7eae8SMauro Carvalho Chehab mci->ctl_name, "");
151806c35f5SAlan Cox }
152806c35f5SAlan Cox }
153806c35f5SAlan Cox
154806c35f5SAlan Cox /*
155806c35f5SAlan Cox * Check for a correctable error
156806c35f5SAlan Cox */
157806c35f5SAlan Cox if (info->ecc_mode_status & BIT(9)) {
158806c35f5SAlan Cox error_found = 1;
159806c35f5SAlan Cox
160806c35f5SAlan Cox if (handle_errors) {
161806c35f5SAlan Cox row = info->ecc_mode_status & 0xf;
1629eb07a7fSMauro Carvalho Chehab edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
163de3910ebSMauro Carvalho Chehab mci->csrows[row]->first_page, 0, 0,
164d8c34af4SMauro Carvalho Chehab row, 0, -1,
16503f7eae8SMauro Carvalho Chehab mci->ctl_name, "");
166806c35f5SAlan Cox }
167806c35f5SAlan Cox }
168e7ecd891SDave Peterson
169806c35f5SAlan Cox return error_found;
170806c35f5SAlan Cox }
171806c35f5SAlan Cox
172806c35f5SAlan Cox /**
173806c35f5SAlan Cox * amd76x_check - Poll the controller
174806c35f5SAlan Cox * @mci: Memory controller
175806c35f5SAlan Cox *
176806c35f5SAlan Cox * Called by the poll handlers this function reads the status
177806c35f5SAlan Cox * from the controller and checks for errors.
178806c35f5SAlan Cox */
amd76x_check(struct mem_ctl_info * mci)179806c35f5SAlan Cox static void amd76x_check(struct mem_ctl_info *mci)
180806c35f5SAlan Cox {
181806c35f5SAlan Cox struct amd76x_error_info info;
182806c35f5SAlan Cox amd76x_get_error_info(mci, &info);
183806c35f5SAlan Cox amd76x_process_error_info(mci, &info, 1);
184806c35f5SAlan Cox }
185806c35f5SAlan Cox
amd76x_init_csrows(struct mem_ctl_info * mci,struct pci_dev * pdev,enum edac_type edac_mode)18613189525SDoug Thompson static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
18713189525SDoug Thompson enum edac_type edac_mode)
188806c35f5SAlan Cox {
18913189525SDoug Thompson struct csrow_info *csrow;
190084a4fccSMauro Carvalho Chehab struct dimm_info *dimm;
19113189525SDoug Thompson u32 mba, mba_base, mba_mask, dms;
192806c35f5SAlan Cox int index;
193806c35f5SAlan Cox
194806c35f5SAlan Cox for (index = 0; index < mci->nr_csrows; index++) {
195de3910ebSMauro Carvalho Chehab csrow = mci->csrows[index];
196de3910ebSMauro Carvalho Chehab dimm = csrow->channels[0]->dimm;
197806c35f5SAlan Cox
198806c35f5SAlan Cox /* find the DRAM Chip Select Base address and mask */
19937f04581SDoug Thompson pci_read_config_dword(pdev,
20067cb2b61SDouglas Thompson AMD76X_MEM_BASE_ADDR + (index * 4), &mba);
201806c35f5SAlan Cox
202806c35f5SAlan Cox if (!(mba & BIT(0)))
203806c35f5SAlan Cox continue;
204806c35f5SAlan Cox
205806c35f5SAlan Cox mba_base = mba & 0xff800000UL;
206806c35f5SAlan Cox mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL;
20737f04581SDoug Thompson pci_read_config_dword(pdev, AMD76X_DRAM_MODE_STATUS, &dms);
208806c35f5SAlan Cox csrow->first_page = mba_base >> PAGE_SHIFT;
209a895bf8bSMauro Carvalho Chehab dimm->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
210a895bf8bSMauro Carvalho Chehab csrow->last_page = csrow->first_page + dimm->nr_pages - 1;
211806c35f5SAlan Cox csrow->page_mask = mba_mask >> PAGE_SHIFT;
212a895bf8bSMauro Carvalho Chehab dimm->grain = dimm->nr_pages << PAGE_SHIFT;
213084a4fccSMauro Carvalho Chehab dimm->mtype = MEM_RDDR;
214084a4fccSMauro Carvalho Chehab dimm->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
215084a4fccSMauro Carvalho Chehab dimm->edac_mode = edac_mode;
21613189525SDoug Thompson }
217806c35f5SAlan Cox }
218806c35f5SAlan Cox
21913189525SDoug Thompson /**
22013189525SDoug Thompson * amd76x_probe1 - Perform set up for detected device
22113189525SDoug Thompson * @pdev; PCI device detected
22213189525SDoug Thompson * @dev_idx: Device type index
22313189525SDoug Thompson *
22413189525SDoug Thompson * We have found an AMD76x and now need to set up the memory
22513189525SDoug Thompson * controller status reporting. We configure and set up the
22613189525SDoug Thompson * memory controller reporting and claim the device.
22713189525SDoug Thompson */
amd76x_probe1(struct pci_dev * pdev,int dev_idx)22813189525SDoug Thompson static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
22913189525SDoug Thompson {
23013189525SDoug Thompson static const enum edac_type ems_modes[] = {
23113189525SDoug Thompson EDAC_NONE,
23213189525SDoug Thompson EDAC_EC,
23313189525SDoug Thompson EDAC_SECDED,
23413189525SDoug Thompson EDAC_SECDED
23513189525SDoug Thompson };
236d8c34af4SMauro Carvalho Chehab struct mem_ctl_info *mci;
237d8c34af4SMauro Carvalho Chehab struct edac_mc_layer layers[2];
23813189525SDoug Thompson u32 ems;
23913189525SDoug Thompson u32 ems_mode;
24013189525SDoug Thompson struct amd76x_error_info discard;
24113189525SDoug Thompson
242956b9ba1SJoe Perches edac_dbg(0, "\n");
24313189525SDoug Thompson pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems);
24413189525SDoug Thompson ems_mode = (ems >> 10) & 0x3;
24513189525SDoug Thompson
246d8c34af4SMauro Carvalho Chehab layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
247d8c34af4SMauro Carvalho Chehab layers[0].size = AMD76X_NR_CSROWS;
248d8c34af4SMauro Carvalho Chehab layers[0].is_virt_csrow = true;
249d8c34af4SMauro Carvalho Chehab layers[1].type = EDAC_MC_LAYER_CHANNEL;
250d8c34af4SMauro Carvalho Chehab layers[1].size = 1;
251d8c34af4SMauro Carvalho Chehab layers[1].is_virt_csrow = false;
252ca0907b9SMauro Carvalho Chehab mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0);
253d8c34af4SMauro Carvalho Chehab
254d8c34af4SMauro Carvalho Chehab if (mci == NULL)
25513189525SDoug Thompson return -ENOMEM;
25613189525SDoug Thompson
257956b9ba1SJoe Perches edac_dbg(0, "mci = %p\n", mci);
258fd687502SMauro Carvalho Chehab mci->pdev = &pdev->dev;
25913189525SDoug Thompson mci->mtype_cap = MEM_FLAG_RDDR;
26013189525SDoug Thompson mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
26113189525SDoug Thompson mci->edac_cap = ems_mode ?
26213189525SDoug Thompson (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE;
26313189525SDoug Thompson mci->mod_name = EDAC_MOD_STR;
26413189525SDoug Thompson mci->ctl_name = amd76x_devs[dev_idx].ctl_name;
265c4192705SDave Jiang mci->dev_name = pci_name(pdev);
26613189525SDoug Thompson mci->edac_check = amd76x_check;
26713189525SDoug Thompson mci->ctl_page_to_phys = NULL;
26813189525SDoug Thompson
26913189525SDoug Thompson amd76x_init_csrows(mci, pdev, ems_modes[ems_mode]);
270749ede57SDave Peterson amd76x_get_error_info(mci, &discard); /* clear counters */
271806c35f5SAlan Cox
2722d7bbb91SDoug Thompson /* Here we assume that we will never see multiple instances of this
2732d7bbb91SDoug Thompson * type of memory controller. The ID is therefore hardcoded to 0.
2742d7bbb91SDoug Thompson */
275b8f6f975SDoug Thompson if (edac_mc_add_mc(mci)) {
276956b9ba1SJoe Perches edac_dbg(3, "failed edac_mc_add_mc()\n");
277806c35f5SAlan Cox goto fail;
278806c35f5SAlan Cox }
279806c35f5SAlan Cox
280456a2f95SDave Jiang /* allocating generic PCI control info */
281456a2f95SDave Jiang amd76x_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
282456a2f95SDave Jiang if (!amd76x_pci) {
283456a2f95SDave Jiang printk(KERN_WARNING
284456a2f95SDave Jiang "%s(): Unable to create PCI control\n",
285456a2f95SDave Jiang __func__);
286456a2f95SDave Jiang printk(KERN_WARNING
287456a2f95SDave Jiang "%s(): PCI error report via EDAC not setup\n",
288456a2f95SDave Jiang __func__);
289456a2f95SDave Jiang }
290456a2f95SDave Jiang
291806c35f5SAlan Cox /* get this far and it's successful */
292956b9ba1SJoe Perches edac_dbg(3, "success\n");
293806c35f5SAlan Cox return 0;
294806c35f5SAlan Cox
295806c35f5SAlan Cox fail:
296806c35f5SAlan Cox edac_mc_free(mci);
29713189525SDoug Thompson return -ENODEV;
298806c35f5SAlan Cox }
299806c35f5SAlan Cox
300806c35f5SAlan Cox /* returns count (>= 0), or negative on error */
amd76x_init_one(struct pci_dev * pdev,const struct pci_device_id * ent)3019b3c6e85SGreg Kroah-Hartman static int amd76x_init_one(struct pci_dev *pdev,
302806c35f5SAlan Cox const struct pci_device_id *ent)
303806c35f5SAlan Cox {
304956b9ba1SJoe Perches edac_dbg(0, "\n");
305806c35f5SAlan Cox
306ee6583f6SRoman Fietze /* don't need to call pci_enable_device() */
307806c35f5SAlan Cox return amd76x_probe1(pdev, ent->driver_data);
308806c35f5SAlan Cox }
309806c35f5SAlan Cox
310806c35f5SAlan Cox /**
311806c35f5SAlan Cox * amd76x_remove_one - driver shutdown
312806c35f5SAlan Cox * @pdev: PCI device being handed back
313806c35f5SAlan Cox *
314806c35f5SAlan Cox * Called when the driver is unloaded. Find the matching mci
315806c35f5SAlan Cox * structure for the device then delete the mci and free the
316806c35f5SAlan Cox * resources.
317806c35f5SAlan Cox */
amd76x_remove_one(struct pci_dev * pdev)3189b3c6e85SGreg Kroah-Hartman static void amd76x_remove_one(struct pci_dev *pdev)
319806c35f5SAlan Cox {
320806c35f5SAlan Cox struct mem_ctl_info *mci;
321806c35f5SAlan Cox
322956b9ba1SJoe Perches edac_dbg(0, "\n");
323806c35f5SAlan Cox
324456a2f95SDave Jiang if (amd76x_pci)
325456a2f95SDave Jiang edac_pci_release_generic_ctl(amd76x_pci);
326456a2f95SDave Jiang
32737f04581SDoug Thompson if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
328806c35f5SAlan Cox return;
32918dbc337SDave Peterson
330806c35f5SAlan Cox edac_mc_free(mci);
331806c35f5SAlan Cox }
332806c35f5SAlan Cox
333ba935f40SJingoo Han static const struct pci_device_id amd76x_pci_tbl[] = {
334e7ecd891SDave Peterson {
335e7ecd891SDave Peterson PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
33667cb2b61SDouglas Thompson AMD762},
337e7ecd891SDave Peterson {
338e7ecd891SDave Peterson PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
33967cb2b61SDouglas Thompson AMD761},
340e7ecd891SDave Peterson {
341e7ecd891SDave Peterson 0,
342e7ecd891SDave Peterson } /* 0 terminated list. */
343806c35f5SAlan Cox };
344806c35f5SAlan Cox
345806c35f5SAlan Cox MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl);
346806c35f5SAlan Cox
347806c35f5SAlan Cox static struct pci_driver amd76x_driver = {
348680cbbbbSDave Peterson .name = EDAC_MOD_STR,
349806c35f5SAlan Cox .probe = amd76x_init_one,
3509b3c6e85SGreg Kroah-Hartman .remove = amd76x_remove_one,
351806c35f5SAlan Cox .id_table = amd76x_pci_tbl,
352806c35f5SAlan Cox };
353806c35f5SAlan Cox
amd76x_init(void)354da9bb1d2SAlan Cox static int __init amd76x_init(void)
355806c35f5SAlan Cox {
356c3c52bceSHitoshi Mitake /* Ensure that the OPSTATE is set correctly for POLL or NMI */
357c3c52bceSHitoshi Mitake opstate_init();
358c3c52bceSHitoshi Mitake
359806c35f5SAlan Cox return pci_register_driver(&amd76x_driver);
360806c35f5SAlan Cox }
361806c35f5SAlan Cox
amd76x_exit(void)362806c35f5SAlan Cox static void __exit amd76x_exit(void)
363806c35f5SAlan Cox {
364806c35f5SAlan Cox pci_unregister_driver(&amd76x_driver);
365806c35f5SAlan Cox }
366806c35f5SAlan Cox
367806c35f5SAlan Cox module_init(amd76x_init);
368806c35f5SAlan Cox module_exit(amd76x_exit);
369806c35f5SAlan Cox
370806c35f5SAlan Cox MODULE_LICENSE("GPL");
371806c35f5SAlan Cox MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
372806c35f5SAlan Cox MODULE_DESCRIPTION("MC support for AMD 76x memory controllers");
373c3c52bceSHitoshi Mitake
374c3c52bceSHitoshi Mitake module_param(edac_op_state, int, 0444);
375c3c52bceSHitoshi Mitake MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
376